feature: use clap derive for nym-api + use stricter validation for other binaries (#2772)

* fixed all uses of deprecated clap methods

* updated all uses of clap to 4.0

* unified obtaining build information

* moved around the imports

* Moved all nym-api arguments to ApiArgs and simplified parsing

* Using common shutdown signal code

* Using clap for parsing Vec<Url>

* stricter validation of socks5-client arguments

* ibid for the native client

* ibid for the gateway

* ibid for the mixnode

* clippy
This commit is contained in:
Jędrzej Stuczyński
2023-01-05 10:32:57 +00:00
committed by GitHub
parent 1f132a4eaa
commit 5f4926dd49
57 changed files with 814 additions and 801 deletions
Generated
+62 -31
View File
@@ -426,6 +426,13 @@ dependencies = [
"serde",
]
[[package]]
name = "build-information"
version = "0.1.0"
dependencies = [
"vergen 7.2.1",
]
[[package]]
name = "bumpalo"
version = "3.9.1"
@@ -598,41 +605,51 @@ version = "3.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "190814073e85d238f31ff738fcb0bf6910cedeb73376c87cd69291028966fd83"
dependencies = [
"atty",
"bitflags",
"clap_derive",
"clap_lex",
"clap_lex 0.2.4",
"indexmap",
"once_cell",
"strsim",
"termcolor",
"textwrap 0.15.0",
]
[[package]]
name = "clap_complete"
version = "3.2.4"
name = "clap"
version = "4.0.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e4179da71abd56c26b54dd0c248cc081c1f43b0a1a7e8448e28e57a29baa993d"
checksum = "2148adefda54e14492fb9bddcc600b4344c5d1a3123bd666dcb939c6f0e0e57e"
dependencies = [
"clap 3.2.8",
"atty",
"bitflags",
"clap_derive",
"clap_lex 0.3.0",
"once_cell",
"strsim",
"termcolor",
]
[[package]]
name = "clap_complete"
version = "4.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10861370d2ba66b0f5989f83ebf35db6421713fd92351790e7fdd6c36774c56b"
dependencies = [
"clap 4.0.26",
]
[[package]]
name = "clap_complete_fig"
version = "3.2.4"
version = "4.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed37b4c0c1214673eba6ad8ea31666626bf72be98ffb323067d973c48b4964b9"
checksum = "46b30e010e669cd021e5004f3be26cff6b7c08d2a8a0d65b48d43a8cc0efd6c3"
dependencies = [
"clap 3.2.8",
"clap 4.0.26",
"clap_complete",
]
[[package]]
name = "clap_derive"
version = "3.2.7"
version = "4.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "759bf187376e1afa7b85b959e6a664a3e7a95203415dba952ad19139e798f902"
checksum = "0177313f9f02afc995627906bbd8967e2be069f5261954222dac78290c2b9014"
dependencies = [
"heck 0.4.0",
"proc-macro-error",
@@ -650,6 +667,15 @@ dependencies = [
"os_str_bytes",
]
[[package]]
name = "clap_lex"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d4198f73e42b4936b35b5bb248d81d2b595ecb170da0bac7655c54eedfa8da8"
dependencies = [
"os_str_bytes",
]
[[package]]
name = "client-connections"
version = "0.1.0"
@@ -766,7 +792,7 @@ dependencies = [
name = "completions"
version = "0.1.0"
dependencies = [
"clap 3.2.8",
"clap 4.0.26",
"clap_complete",
"clap_complete_fig",
]
@@ -1005,7 +1031,7 @@ version = "0.1.0"
dependencies = [
"bip39",
"cfg-if 0.1.10",
"clap 3.2.8",
"clap 4.0.26",
"coconut-interface",
"completions",
"config",
@@ -1765,7 +1791,7 @@ name = "explorer-api"
version = "1.1.1"
dependencies = [
"chrono",
"clap 3.2.8",
"clap 4.0.26",
"contracts-common",
"dotenv",
"humantime-serde",
@@ -3211,9 +3237,11 @@ version = "1.1.4"
dependencies = [
"anyhow",
"async-trait",
"bip39",
"bs58",
"build-information",
"cfg-if 1.0.0",
"clap 3.2.8",
"clap 4.0.26",
"coconut-bandwidth-contract-common",
"coconut-dkg-common",
"coconut-interface",
@@ -3234,6 +3262,7 @@ dependencies = [
"getset",
"humantime-serde",
"inclusion-probability",
"lazy_static",
"log",
"logging",
"mixnet-contract-common",
@@ -3265,7 +3294,6 @@ dependencies = [
"ts-rs",
"url",
"validator-client",
"vergen 7.2.1",
"version-checker",
]
@@ -3307,7 +3335,7 @@ dependencies = [
"base64",
"bip39",
"bs58",
"clap 3.2.8",
"clap 4.0.26",
"clap_complete",
"clap_complete_fig",
"dotenv",
@@ -3331,7 +3359,7 @@ dependencies = [
"bip39",
"bs58",
"cfg-if 1.0.0",
"clap 3.2.8",
"clap 4.0.26",
"comfy-table",
"cosmrs",
"cosmwasm-std",
@@ -3357,7 +3385,8 @@ dependencies = [
name = "nym-client"
version = "1.1.4"
dependencies = [
"clap 3.2.8",
"build-information",
"clap 4.0.26",
"client-connections",
"client-core",
"coconut-interface",
@@ -3370,6 +3399,7 @@ dependencies = [
"futures",
"gateway-client",
"gateway-requests",
"lazy_static",
"log",
"logging",
"network-defaults",
@@ -3387,7 +3417,6 @@ dependencies = [
"topology",
"url",
"validator-client",
"vergen 5.1.17",
"version-checker",
"websocket-requests",
]
@@ -3400,7 +3429,8 @@ dependencies = [
"async-trait",
"bip39",
"bs58",
"clap 3.2.8",
"build-information",
"clap 4.0.26",
"coconut-interface",
"colored",
"completions",
@@ -3413,6 +3443,7 @@ dependencies = [
"futures",
"gateway-requests",
"humantime-serde",
"lazy_static",
"log",
"logging",
"mixnet-client",
@@ -3435,7 +3466,6 @@ dependencies = [
"tokio-util 0.7.3",
"url",
"validator-client",
"vergen 5.1.17",
"version-checker",
]
@@ -3445,7 +3475,8 @@ version = "1.1.4"
dependencies = [
"anyhow",
"bs58",
"clap 3.2.8",
"build-information",
"clap 4.0.26",
"colored",
"completions",
"config",
@@ -3477,7 +3508,6 @@ dependencies = [
"topology",
"url",
"validator-client",
"vergen 5.1.17",
"version-checker",
]
@@ -3486,7 +3516,7 @@ name = "nym-network-requester"
version = "1.1.4"
dependencies = [
"async-trait",
"clap 3.2.8",
"clap 4.0.26",
"client-connections",
"completions",
"dirs",
@@ -3549,7 +3579,8 @@ dependencies = [
name = "nym-socks5-client"
version = "1.1.4"
dependencies = [
"clap 3.2.8",
"build-information",
"clap 4.0.26",
"client-connections",
"client-core",
"coconut-interface",
@@ -3562,6 +3593,7 @@ dependencies = [
"futures",
"gateway-client",
"gateway-requests",
"lazy_static",
"log",
"logging",
"network-defaults",
@@ -3582,7 +3614,6 @@ dependencies = [
"topology",
"url",
"validator-client",
"vergen 5.1.17",
"version-checker",
]
+1
View File
@@ -30,6 +30,7 @@ members = [
"common/coconut-interface",
"common/commands",
"common/config",
"common/build-information",
"common/cosmwasm-smart-contracts/coconut-bandwidth-contract",
"common/cosmwasm-smart-contracts/coconut-dkg",
"common/cosmwasm-smart-contracts/contracts-common",
+1
View File
@@ -64,6 +64,7 @@ impl Display for InitResults {
/// it will do the sensible thing.
pub async fn setup_gateway<C, T>(
register_gateway: bool,
// TODO: this should get refactored to instead take Option<identity::PublicKey>
user_chosen_gateway_id: Option<String>,
config: &Config<T>,
) -> Result<GatewayEndpointConfig, ClientCoreError>
+1 -1
View File
@@ -8,7 +8,7 @@ edition = "2021"
[dependencies]
bip39 = "1.0.1"
cfg-if = "0.1"
clap = { version = "3.2", features = ["cargo", "derive"] }
clap = { version = "4.0", features = ["cargo", "derive"] }
rand = "0.7.3"
serde = { version = "1.0", features = ["derive"] }
thiserror = "1.0"
+3 -3
View File
@@ -31,7 +31,7 @@ cfg_if::cfg_if! {
#[tokio::main]
async fn main() -> Result<()> {
let args = Cli::parse();
setup_env(args.config_env_file.clone());
setup_env(args.config_env_file.as_ref());
let bin_name = "nym-credential-client";
match args.command {
@@ -42,8 +42,8 @@ cfg_if::cfg_if! {
let state = deposit(&r.nymd_url, &r.mnemonic, r.amount).await?;
get_credential(&state, shared_storage).await?;
}
Command::Completions(c) => c.generate(&mut crate::Cli::into_app(), bin_name),
Command::GenerateFigSpec => fig_generate(&mut crate::Cli::into_app(), bin_name)
Command::Completions(c) => c.generate(&mut crate::Cli::command(), bin_name),
Command::GenerateFigSpec => fig_generate(&mut crate::Cli::command(), bin_name)
}
Ok(())
+3 -4
View File
@@ -20,8 +20,9 @@ futures = "0.3" # bunch of futures stuff, however, now that I think about it, it
# and the single instance of abortable we have should really be refactored anyway
url = "2.2"
clap = { version = "3.2", features = ["cargo", "derive"] }
clap = { version = "4.0", features = ["cargo", "derive"] }
dirs = "4.0"
lazy_static = "1.4.0"
log = "0.4" # self explanatory
pretty_env_logger = "0.4" # for formatting log messages
rand = { version = "0.7.3", features = ["wasm-bindgen"] } # rng-related traits + some rng implementation to use
@@ -33,6 +34,7 @@ tokio = { version = "1.21.2", features = ["rt-multi-thread", "net", "signal"] }
tokio-tungstenite = "0.14" # websocket
## internal
build-information = { path = "../../common/build-information" }
client-core = { path = "../client-core", features = ["fs-surb-storage"] }
client-connections = { path = "../../common/client-connections" }
coconut-interface = { path = "../../common/coconut-interface", optional = true }
@@ -58,6 +60,3 @@ coconut = ["coconut-interface", "credentials", "credentials/coconut", "gateway-r
[dev-dependencies]
serde_json = "1.0" # for the "textsend" example
[build-dependencies]
vergen = { version = "5", default-features = false, features = ["build", "git", "rustc", "cargo"] }
+10 -9
View File
@@ -8,6 +8,7 @@ use crate::{
};
use clap::Args;
use config::NymConfig;
use crypto::asymmetric::identity;
use nymsphinx::addressing::clients::Recipient;
use serde::Serialize;
use std::fmt::Display;
@@ -21,7 +22,7 @@ pub(crate) struct Init {
/// Id of the gateway we are going to connect to.
#[clap(long)]
gateway: Option<String>,
gateway: Option<identity::PublicKey>,
/// Force register gateway. WARNING: this will overwrite any existing keys for the given id,
/// potentially causing loss of access.
@@ -29,14 +30,14 @@ pub(crate) struct Init {
force_register_gateway: bool,
/// Comma separated list of rest endpoints of the nymd validators
#[clap(long)]
#[cfg(feature = "coconut")]
nymd_validators: Option<String>,
#[clap(long, value_delimiter = ',')]
nymd_validators: Option<Vec<url::Url>>,
/// Comma separated list of rest endpoints of the API validators
#[clap(long, alias = "api_validators")]
#[clap(long, alias = "api_validators", value_delimiter = ',')]
// the alias here is included for backwards compatibility (1.1.4 and before)
nym_apis: Option<String>,
nym_apis: Option<Vec<url::Url>>,
/// Whether to not start the websocket
#[clap(long)]
@@ -48,11 +49,11 @@ pub(crate) struct Init {
/// Mostly debug-related option to increase default traffic rate so that you would not need to
/// modify config post init
#[clap(long, hidden = true)]
#[clap(long, hide = true)]
fastmode: bool,
/// Disable loop cover traffic and the Poisson rate limiter (for debugging only)
#[clap(long, hidden = true)]
#[clap(long, hide = true)]
no_cover: bool,
/// Set this client to work in a enabled credentials mode that would attempt to use gateway
@@ -130,7 +131,7 @@ pub(crate) async fn execute(args: &Init) -> Result<(), ClientError> {
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.clone();
let user_chosen_gateway_id = args.gateway;
// Load and potentially override config
let mut config = override_config(Config::new(id), OverrideConfig::from(args.clone()));
@@ -139,7 +140,7 @@ pub(crate) async fn execute(args: &Init) -> Result<(), ClientError> {
// one but with keys kept, or reusing the gateway configuration.
let gateway = client_core::init::setup_gateway::<Config, _>(
register_gateway,
user_chosen_gateway_id,
user_chosen_gateway_id.map(|id| id.to_base58_string()),
config.get_base(),
)
.await
+18 -46
View File
@@ -1,54 +1,30 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use std::error::Error;
use crate::client::config::{Config, SocketType};
use build_information::BinaryBuildInformation;
use clap::CommandFactory;
use clap::{Parser, Subcommand};
use completions::{fig_generate, ArgShell};
use lazy_static::lazy_static;
use std::error::Error;
pub(crate) mod init;
pub(crate) mod run;
pub(crate) mod upgrade;
fn long_version() -> String {
format!(
r#"
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
"#,
"Build Timestamp:",
env!("VERGEN_BUILD_TIMESTAMP"),
"Build Version:",
env!("VERGEN_BUILD_SEMVER"),
"Commit SHA:",
env!("VERGEN_GIT_SHA"),
"Commit Date:",
env!("VERGEN_GIT_COMMIT_TIMESTAMP"),
"Commit Branch:",
env!("VERGEN_GIT_BRANCH"),
"rustc Version:",
env!("VERGEN_RUSTC_SEMVER"),
"rustc Channel:",
env!("VERGEN_RUSTC_CHANNEL"),
"cargo Profile:",
env!("VERGEN_CARGO_PROFILE"),
)
lazy_static! {
pub static ref PRETTY_BUILD_INFORMATION: String =
BinaryBuildInformation::new(env!("CARGO_PKG_VERSION")).pretty_print();
}
fn long_version_static() -> &'static str {
Box::leak(long_version().into_boxed_str())
// Helper for passing LONG_VERSION to clap
fn pretty_build_info_static() -> &'static str {
&PRETTY_BUILD_INFORMATION
}
#[derive(Parser)]
#[clap(author = "Nymtech", version, long_version = long_version_static(), about)]
#[clap(author = "Nymtech", version, long_version = pretty_build_info_static(), about)]
pub(crate) struct Cli {
/// Path pointing to an env file that configures the client.
#[clap(short, long)]
@@ -76,14 +52,14 @@ pub(crate) enum Commands {
// Configuration that can be overridden.
pub(crate) struct OverrideConfig {
nym_apis: Option<String>,
nym_apis: Option<Vec<url::Url>>,
disable_socket: bool,
port: Option<u16>,
fastmode: bool,
no_cover: bool,
#[cfg(feature = "coconut")]
nymd_validators: Option<String>,
nymd_validators: Option<Vec<url::Url>>,
#[cfg(feature = "coconut")]
enabled_credentials_mode: bool,
}
@@ -95,17 +71,15 @@ pub(crate) async fn execute(args: &Cli) -> Result<(), Box<dyn Error + Send + Syn
Commands::Init(m) => init::execute(m).await?,
Commands::Run(m) => run::execute(m).await?,
Commands::Upgrade(m) => upgrade::execute(m),
Commands::Completions(s) => s.generate(&mut Cli::into_app(), bin_name),
Commands::GenerateFigSpec => fig_generate(&mut Cli::into_app(), bin_name),
Commands::Completions(s) => s.generate(&mut Cli::command(), bin_name),
Commands::GenerateFigSpec => fig_generate(&mut Cli::command(), bin_name),
}
Ok(())
}
pub(crate) fn override_config(mut config: Config, args: OverrideConfig) -> Config {
if let Some(raw_validators) = args.nym_apis {
config
.get_base_mut()
.set_custom_nym_apis(config::parse_urls(&raw_validators));
if let Some(nym_apis) = args.nym_apis {
config.get_base_mut().set_custom_nym_apis(nym_apis);
} else if std::env::var(network_defaults::var_names::CONFIGURED).is_ok() {
let raw_validators = std::env::var(network_defaults::var_names::API_VALIDATOR)
.expect("api validator not set");
@@ -124,10 +98,8 @@ pub(crate) fn override_config(mut config: Config, args: OverrideConfig) -> Confi
#[cfg(feature = "coconut")]
{
if let Some(raw_validators) = args.nymd_validators {
config
.get_base_mut()
.set_custom_validators(config::parse_urls(&raw_validators));
if let Some(nymd_validators) = args.nymd_validators {
config.get_base_mut().set_custom_validators(nymd_validators);
} else if std::env::var(network_defaults::var_names::CONFIGURED).is_ok() {
let raw_validators = std::env::var(network_defaults::var_names::NYMD_VALIDATOR)
.expect("nymd validator not set");
+8 -7
View File
@@ -11,6 +11,7 @@ use crate::{
use clap::Args;
use config::NymConfig;
use crypto::asymmetric::identity;
use log::*;
use version_checker::is_minor_version_compatible;
@@ -21,19 +22,19 @@ pub(crate) struct Run {
id: String,
/// Comma separated list of rest endpoints of the nymd validators
#[clap(long)]
#[cfg(feature = "coconut")]
nymd_validators: Option<String>,
#[clap(long, value_delimiter = ',')]
nymd_validators: Option<Vec<url::Url>>,
/// Comma separated list of rest endpoints of the API validators
#[clap(long, alias = "api_validators")]
#[clap(long, alias = "api_validators", value_delimiter = ',')]
// the alias here is included for backwards compatibility (1.1.4 and before)
nym_apis: Option<String>,
nym_apis: Option<Vec<url::Url>>,
/// Id of the gateway we want to connect to. If overridden, it is user's responsibility to
/// ensure prior registration happened
#[clap(long)]
gateway: Option<String>,
gateway: Option<identity::PublicKey>,
/// Whether to not start the websocket
#[clap(long)]
@@ -45,11 +46,11 @@ pub(crate) struct Run {
/// Mostly debug-related option to increase default traffic rate so that you would not need to
/// modify config post init
#[clap(long, hidden = true)]
#[clap(long, hide = true)]
fastmode: bool,
/// Disable loop cover traffic and the Poisson rate limiter (for debugging only)
#[clap(long, hidden = true)]
#[clap(long, hide = true)]
no_cover: bool,
/// Set this client to work in a enabled credentials mode that would attempt to use gateway
+1 -1
View File
@@ -18,7 +18,7 @@ async fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
println!("{}", banner());
let args = commands::Cli::parse();
setup_env(args.config_env_file.clone());
setup_env(args.config_env_file.as_ref());
commands::execute(&args).await
}
+3 -4
View File
@@ -11,9 +11,10 @@ name = "nym_socks5"
path = "src/lib.rs"
[dependencies]
clap = { version = "3.2", features = ["cargo", "derive"] }
clap = { version = "4.0", features = ["cargo", "derive"] }
dirs = "4.0"
futures = "0.3"
lazy_static = "1.4.0"
log = "0.4"
pin-project = "1.0"
pretty_env_logger = "0.4"
@@ -26,6 +27,7 @@ tokio = { version = "1.21.2", features = ["rt-multi-thread", "net", "signal"] }
url = "2.2"
# internal
build-information = { path = "../../common/build-information" }
client-core = { path = "../client-core", features = ["fs-surb-storage"] }
client-connections = { path = "../../common/client-connections" }
coconut-interface = { path = "../../common/coconut-interface", optional = true }
@@ -51,6 +53,3 @@ version-checker = { path = "../../common/version-checker" }
[features]
coconut = ["coconut-interface", "credentials", "gateway-requests/coconut", "gateway-client/coconut", "credentials/coconut", "client-core/coconut"]
eth = []
[build-dependencies]
vergen = { version = "5", default-features = false, features = ["build", "git", "rustc", "cargo"] }
-8
View File
@@ -1,8 +0,0 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use vergen::{vergen, Config};
fn main() {
vergen(Config::default()).expect("failed to extract build metadata")
}
+12 -11
View File
@@ -8,6 +8,7 @@ use crate::{
};
use clap::Args;
use config::NymConfig;
use crypto::asymmetric::identity;
use nymsphinx::addressing::clients::Recipient;
use serde::Serialize;
use std::fmt::Display;
@@ -21,7 +22,7 @@ pub(crate) struct Init {
/// Address of the socks5 provider to send messages to.
#[clap(long)]
provider: String,
provider: Recipient,
/// Specifies whether this client is going to use an anonymous sender tag for communication with the service provider.
/// While this is going to hide its actual address information, it will make the actual communication
@@ -34,7 +35,7 @@ pub(crate) struct Init {
/// Id of the gateway we are going to connect to.
#[clap(long)]
gateway: Option<String>,
gateway: Option<identity::PublicKey>,
/// Force register gateway. WARNING: this will overwrite any existing keys for the given id,
/// potentially causing loss of access.
@@ -43,13 +44,13 @@ pub(crate) struct Init {
/// Comma separated list of rest endpoints of the nymd validators
#[cfg(feature = "coconut")]
#[clap(long)]
nymd_validators: Option<String>,
#[clap(long, value_delimiter = ',')]
nymd_validators: Option<Vec<url::Url>>,
/// Comma separated list of rest endpoints of the API validators
#[clap(long, alias = "api_validators")]
#[clap(long, alias = "api_validators", value_delimiter = ',')]
// the alias here is included for backwards compatibility (1.1.4 and before)
nym_apis: Option<String>,
nym_apis: Option<Vec<url::Url>>,
/// Port for the socket to listen on in all subsequent runs
#[clap(short, long)]
@@ -57,11 +58,11 @@ pub(crate) struct Init {
/// Mostly debug-related option to increase default traffic rate so that you would not need to
/// modify config post init
#[clap(long, hidden = true)]
#[clap(long, hide = true)]
fastmode: bool,
/// Disable loop cover traffic and the Poisson rate limiter (for debugging only)
#[clap(long, hidden = true)]
#[clap(long, hide = true)]
no_cover: bool,
/// Set this client to work in a enabled credentials mode that would attempt to use gateway
@@ -140,11 +141,11 @@ pub(crate) async fn execute(args: &Init) -> Result<(), Socks5ClientError> {
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.clone();
let user_chosen_gateway_id = args.gateway;
// Load and potentially override config
let mut config = override_config(
Config::new(id, provider_address),
Config::new(id, &provider_address.to_string()),
OverrideConfig::from(args.clone()),
);
@@ -152,7 +153,7 @@ pub(crate) async fn execute(args: &Init) -> Result<(), Socks5ClientError> {
// one but with keys kept, or reusing the gateway configuration.
let gateway = client_core::init::setup_gateway::<Config, _>(
register_gateway,
user_chosen_gateway_id,
user_chosen_gateway_id.map(|id| id.to_base58_string()),
config.get_base(),
)
.await
+19 -47
View File
@@ -1,55 +1,31 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use std::error::Error;
use crate::client::config::Config;
use build_information::BinaryBuildInformation;
use clap::CommandFactory;
use clap::{Parser, Subcommand};
use completions::{fig_generate, ArgShell};
use config::parse_urls;
use lazy_static::lazy_static;
use std::error::Error;
pub mod init;
pub(crate) mod run;
pub(crate) mod upgrade;
fn long_version() -> String {
format!(
r#"
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
"#,
"Build Timestamp:",
env!("VERGEN_BUILD_TIMESTAMP"),
"Build Version:",
env!("VERGEN_BUILD_SEMVER"),
"Commit SHA:",
env!("VERGEN_GIT_SHA"),
"Commit Date:",
env!("VERGEN_GIT_COMMIT_TIMESTAMP"),
"Commit Branch:",
env!("VERGEN_GIT_BRANCH"),
"rustc Version:",
env!("VERGEN_RUSTC_SEMVER"),
"rustc Channel:",
env!("VERGEN_RUSTC_CHANNEL"),
"cargo Profile:",
env!("VERGEN_CARGO_PROFILE"),
)
lazy_static! {
pub static ref PRETTY_BUILD_INFORMATION: String =
BinaryBuildInformation::new(env!("CARGO_PKG_VERSION")).pretty_print();
}
fn long_version_static() -> &'static str {
Box::leak(long_version().into_boxed_str())
// Helper for passing LONG_VERSION to clap
fn pretty_build_info_static() -> &'static str {
&PRETTY_BUILD_INFORMATION
}
#[derive(Parser)]
#[clap(author = "Nymtech", version, long_version = long_version_static(), about)]
#[clap(author = "Nymtech", version, long_version = pretty_build_info_static(), about)]
pub(crate) struct Cli {
/// Path pointing to an env file that configures the client.
#[clap(short, long)]
@@ -79,14 +55,14 @@ pub(crate) enum Commands {
// Configuration that can be overridden.
pub(crate) struct OverrideConfig {
nym_apis: Option<String>,
nym_apis: Option<Vec<url::Url>>,
port: Option<u16>,
use_anonymous_replies: bool,
fastmode: bool,
no_cover: bool,
#[cfg(feature = "coconut")]
nymd_validators: Option<String>,
nymd_validators: Option<Vec<url::Url>>,
#[cfg(feature = "coconut")]
enabled_credentials_mode: bool,
}
@@ -98,17 +74,15 @@ pub(crate) async fn execute(args: &Cli) -> Result<(), Box<dyn Error + Send + Syn
Commands::Init(m) => init::execute(m).await?,
Commands::Run(m) => run::execute(m).await?,
Commands::Upgrade(m) => upgrade::execute(m),
Commands::Completions(s) => s.generate(&mut Cli::into_app(), bin_name),
Commands::GenerateFigSpec => fig_generate(&mut Cli::into_app(), bin_name),
Commands::Completions(s) => s.generate(&mut Cli::command(), bin_name),
Commands::GenerateFigSpec => fig_generate(&mut Cli::command(), bin_name),
}
Ok(())
}
pub(crate) fn override_config(mut config: Config, args: OverrideConfig) -> Config {
if let Some(raw_validators) = args.nym_apis {
config
.get_base_mut()
.set_custom_nym_apis(parse_urls(&raw_validators));
if let Some(nym_apis) = args.nym_apis {
config.get_base_mut().set_custom_nym_apis(nym_apis);
} else if let Ok(raw_validators) = std::env::var(network_defaults::var_names::API_VALIDATOR) {
config
.get_base_mut()
@@ -125,10 +99,8 @@ pub(crate) fn override_config(mut config: Config, args: OverrideConfig) -> Confi
#[cfg(feature = "coconut")]
{
if let Some(raw_validators) = args.nymd_validators {
config
.get_base_mut()
.set_custom_validators(parse_urls(&raw_validators));
if let Some(nymd_validators) = args.nymd_validators {
config.get_base_mut().set_custom_validators(nymd_validators);
} else if let Ok(raw_validators) =
std::env::var(network_defaults::var_names::NYMD_VALIDATOR)
{
+10 -8
View File
@@ -9,7 +9,9 @@ use crate::{
use clap::Args;
use config::NymConfig;
use crypto::asymmetric::identity;
use log::*;
use nymsphinx::addressing::clients::Recipient;
use version_checker::is_minor_version_compatible;
#[derive(Args, Clone)]
@@ -33,21 +35,21 @@ pub(crate) struct Run {
/// Address of the socks5 provider to send messages to.
#[clap(long)]
provider: Option<String>,
provider: Option<Recipient>,
/// Id of the gateway we want to connect to. If overridden, it is user's responsibility to
/// ensure prior registration happened
#[clap(long)]
gateway: Option<String>,
gateway: Option<identity::PublicKey>,
/// Comma separated list of rest endpoints of the nymd validators
#[cfg(feature = "coconut")]
#[clap(long)]
nymd_validators: Option<String>,
#[clap(long, value_delimiter = ',')]
nymd_validators: Option<Vec<url::Url>>,
/// Comma separated list of rest endpoints of the Nym APIs
#[clap(long)]
nym_apis: Option<String>,
#[clap(long, value_delimiter = ',')]
nym_apis: Option<Vec<url::Url>>,
/// Port for the socket to listen on
#[clap(short, long)]
@@ -55,11 +57,11 @@ pub(crate) struct Run {
/// Mostly debug-related option to increase default traffic rate so that you would not need to
/// modify config post init
#[clap(long, hidden = true)]
#[clap(long, hide = true)]
fastmode: bool,
/// Disable loop cover traffic and the Poisson rate limiter (for debugging only)
#[clap(long, hidden = true)]
#[clap(long, hide = true)]
no_cover: bool,
/// Set this client to work in a enabled credentials mode that would attempt to use gateway
+1 -1
View File
@@ -18,7 +18,7 @@ async fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
println!("{}", banner());
let args = commands::Cli::parse();
setup_env(args.config_env_file.clone());
setup_env(args.config_env_file.as_ref());
commands::execute(&args).await
}
+11
View File
@@ -0,0 +1,11 @@
[package]
name = "build-information"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
[build-dependencies]
vergen = { version = "7", default-features = false, features = ["build", "git", "rustc", "cargo"] }
@@ -1,4 +1,4 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use vergen::{vergen, Config};
+86
View File
@@ -0,0 +1,86 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
// TODO: at a later date this crate should probably also expose `ContractBuildInformation`
// and be used by our smart contracts
pub struct BinaryBuildInformation {
// VERGEN_BUILD_TIMESTAMP
/// Provides the build timestamp, for example `2021-02-23T20:14:46.558472672+00:00`.
pub build_timestamp: &'static str,
// VERGEN_BUILD_SEMVER
/// Provides the build version, for example `0.1.0-9-g46f83e1`.
pub build_version: &'static str,
// VERGEN_GIT_SHA
/// Provides the hash of the commit that was used for the build, for example `46f83e112520533338245862d366f6a02cef07d4`.
pub commit_sha: &'static str,
// VERGEN_GIT_COMMIT_TIMESTAMP
/// Provides the timestamp of the commit that was used for the build, for example `2021-02-23T08:08:02-05:00`.
pub commit_timestamp: &'static str,
// VERGEN_GIT_BRANCH
/// Provides the name of the git branch that was used for the build, for example `master`.
pub commit_branch: &'static str,
// VERGEN_RUSTC_SEMVER
/// Provides the rustc version that was used for the build, for example `1.52.0-nightly`.
pub rustc_version: &'static str,
// VERGEN_RUSTC_CHANNEL
/// Provides the rustc channel that was used for the build, for example `nightly`.
pub rustc_channel: &'static str,
// VERGEN_CARGO_PROFILE
/// Provides the cargo profile that was used for the build, for example `debug`.
pub cargo_profile: &'static str,
}
impl BinaryBuildInformation {
// explicitly require the build_version to be passed as it's binary specific
pub const fn new(build_version: &'static str) -> Self {
BinaryBuildInformation {
build_timestamp: env!("VERGEN_BUILD_TIMESTAMP"),
build_version,
commit_sha: env!("VERGEN_GIT_SHA"),
commit_timestamp: env!("VERGEN_GIT_COMMIT_TIMESTAMP"),
commit_branch: env!("VERGEN_GIT_BRANCH"),
rustc_version: env!("VERGEN_RUSTC_SEMVER"),
rustc_channel: env!("VERGEN_RUSTC_CHANNEL"),
cargo_profile: env!("VERGEN_CARGO_PROFILE"),
}
}
pub fn pretty_print(&self) -> String {
format!(
r#"
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
"#,
"Build Timestamp:",
self.build_timestamp,
"Build Version:",
self.build_version,
"Commit SHA:",
self.commit_sha,
"Commit Date:",
self.commit_timestamp,
"Commit Branch:",
self.commit_branch,
"rustc Version:",
self.rustc_version,
"rustc Channel:",
self.rustc_channel,
"cargo Profile:",
self.cargo_profile,
)
}
}
+1 -1
View File
@@ -10,7 +10,7 @@ bip39 = "1.0.1"
bs58 = "0.4"
comfy-table = "6.0.0"
cfg-if = "1.0.0"
clap = { version = "3.2", features = ["derive"] }
clap = { version = "4.0", features = ["derive"] }
handlebars = "3.0.1"
humantime-serde = "1.0"
k256 = { version = "0.10", features = ["ecdsa", "sha256"] }
+1 -1
View File
@@ -32,7 +32,7 @@ pub struct ClientArgs {
pub fn get_network_details(args: &ClientArgs) -> Result<NymNetworkDetails, ContextError> {
// let the network defaults crate handle setting up the env vars if the file arg is set, otherwise
// it will default to what is already in env vars, falling back to mainnet
setup_env(args.config_env_file.clone());
setup_env(args.config_env_file.as_ref());
// override the env vars with user supplied arguments, if set
if let Some(nymd_url) = args.nymd_url.as_ref() {
+3 -3
View File
@@ -6,6 +6,6 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
clap = { version = "3.2", features = ["derive"] }
clap_complete = "3.2"
clap_complete_fig = "3.2"
clap = { version = "4.0", features = ["derive"] }
clap_complete = "4.0"
clap_complete_fig = "4.0"
+3 -3
View File
@@ -1,5 +1,5 @@
use clap::builder::Command;
use clap::clap_derive::ArgEnum;
use clap::clap_derive::ValueEnum;
use clap::Args;
use clap_complete::generator::generate;
use clap_complete::Shell as ClapShell;
@@ -14,7 +14,7 @@ pub fn fig_generate(command: &mut Command, name: &str) {
)
}
#[derive(ArgEnum, Copy, Clone)]
#[derive(ValueEnum, Copy, Clone)]
pub enum Shell {
Bash,
Elvish,
@@ -25,7 +25,7 @@ pub enum Shell {
#[derive(Args, Copy, Clone)]
pub struct ArgShell {
#[clap(arg_enum, value_name = "SHELL")]
#[clap(value_enum, value_name = "SHELL")]
shell: Shell,
}
+1
View File
@@ -118,6 +118,7 @@ pub trait NymConfig: Default + Serialize + DeserializeOwned {
}
}
// this function is only used for parsing values from the network defaults and thus the "expect" there are fine
pub fn parse_urls(raw: &str) -> Vec<url::Url> {
raw.split(',')
.map(|raw_url| {
@@ -7,6 +7,7 @@ pub use ed25519_dalek::{Verifier, PUBLIC_KEY_LENGTH, SECRET_KEY_LENGTH, SIGNATUR
use nymsphinx_types::{DestinationAddressBytes, DESTINATION_ADDRESS_LENGTH};
use pemstore::traits::{PemStorableKey, PemStorableKeyPair};
use std::fmt::{self, Display, Formatter};
use std::str::FromStr;
use thiserror::Error;
#[cfg(feature = "rand")]
@@ -141,6 +142,14 @@ impl PublicKey {
}
}
impl FromStr for PublicKey {
type Err = Ed25519RecoveryError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
PublicKey::from_base58_string(s)
}
}
#[cfg(feature = "serde")]
impl Serialize for PublicKey {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+1 -1
View File
@@ -289,7 +289,7 @@ impl ValidatorDetails {
}
}
pub fn setup_env(config_env_file: Option<PathBuf>) {
pub fn setup_env(config_env_file: Option<&PathBuf>) {
match std::env::var(var_names::CONFIGURED) {
// if the configuration is not already set in the env vars
Err(std::env::VarError::NotPresent) => {
@@ -10,6 +10,7 @@ use nymsphinx_types::Destination;
use serde::de::{Error as SerdeError, Unexpected, Visitor};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::fmt::{self, Formatter};
use std::str::FromStr;
use thiserror::Error;
// Not entirely sure whether this is the correct place for those, but let's see how it's going
@@ -225,6 +226,14 @@ impl std::fmt::Display for Recipient {
}
}
impl FromStr for Recipient {
type Err = RecipientFormattingError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Recipient::try_from_base58_string(s)
}
}
#[cfg(test)]
mod tests {
use super::*;
+1 -1
View File
@@ -7,7 +7,7 @@ edition = "2021"
[dependencies]
chrono = { version = "0.4.19", features = ["serde"] }
clap = { version = "3.2", features = ["cargo", "derive"] }
clap = { version = "4.0", features = ["cargo", "derive"] }
humantime-serde = "1.0"
isocountry = "0.3.2"
itertools = "0.10.3"
+2 -30
View File
@@ -8,7 +8,7 @@ use dotenv::dotenv;
use log::info;
use logging::setup_logging;
use network_defaults::setup_env;
use task::TaskManager;
use task::{wait_for_signal, TaskManager};
mod buy_terms;
pub(crate) mod cache;
@@ -35,7 +35,7 @@ async fn main() {
dotenv().ok();
setup_logging();
let args = commands::Cli::parse();
setup_env(args.config_env_file);
setup_env(args.config_env_file.as_ref());
let mut explorer_api = ExplorerApi::new();
explorer_api.run().await;
}
@@ -88,31 +88,3 @@ impl ExplorerApi {
log::info!("Stopping explorer API");
}
}
#[cfg(unix)]
async fn wait_for_signal() {
use tokio::signal::unix::{signal, SignalKind};
let mut sigterm = signal(SignalKind::terminate()).expect("Failed to setup SIGTERM channel");
let mut sigquit = signal(SignalKind::quit()).expect("Failed to setup SIGQUIT channel");
tokio::select! {
_ = tokio::signal::ctrl_c() => {
log::info!("Received SIGINT");
},
_ = sigterm.recv() => {
log::info!("Received SIGTERM");
}
_ = sigquit.recv() => {
log::info!("Received SIGQUIT");
}
}
}
#[cfg(not(unix))]
async fn wait_for_signal() {
tokio::select! {
_ = tokio::signal::ctrl_c() => {
log::info!("Received SIGINT");
},
}
}
+3 -7
View File
@@ -19,13 +19,14 @@ anyhow = "1.0.53"
async-trait = { version = "0.1.51" }
bip39 = "1.0.1"
bs58 = "0.4.0"
clap = { version = "3.2", features = ["cargo", "derive"] }
clap = { version = "4.0", features = ["cargo", "derive"] }
colored = "2.0"
dashmap = "4.0"
dirs = "4.0"
dotenv = "0.15.0"
futures = "0.3"
humantime-serde = "1.0.1"
lazy_static = "1.4.0"
log = "0.4"
once_cell = "1.7.2"
pretty_env_logger = "0.4"
@@ -51,6 +52,7 @@ tokio-util = { version = "0.7.3", features = ["codec"] }
url = { version = "2.2", features = ["serde"] }
# internal
build-information = { path = "../common/build-information" }
coconut-interface = { path = "../common/coconut-interface", optional = true }
credentials = { path = "../common/credentials" }
config = { path = "../common/config" }
@@ -86,9 +88,3 @@ sqlx = { version = "0.5", features = [
"macros",
"migrate",
] }
vergen = { version = "5", default-features = false, features = [
"build",
"git",
"rustc",
"cargo",
] }
-3
View File
@@ -1,6 +1,5 @@
use sqlx::{Connection, SqliteConnection};
use std::env;
use vergen::{vergen, Config};
#[tokio::main]
async fn main() {
@@ -23,6 +22,4 @@ async fn main() {
// for some strange reason we need to add a leading `/` to the windows path even though it's
// not a valid windows path... but hey, it works...
println!("cargo:rustc-env=DATABASE_URL=sqlite:///{}", &database_path);
vergen(Config::default()).expect("failed to extract build metadata")
}
+17 -13
View File
@@ -1,4 +1,4 @@
// Copyright 2020 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2020-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::{
@@ -8,6 +8,9 @@ use crate::{
use clap::Args;
use config::NymConfig;
use crypto::asymmetric::{encryption, identity};
use std::net::IpAddr;
use std::path::PathBuf;
use validator_client::nymd;
#[derive(Args, Clone)]
pub struct Init {
@@ -17,11 +20,11 @@ pub struct Init {
/// The custom host on which the gateway will be running for receiving sphinx packets
#[clap(long)]
host: String,
host: IpAddr,
/// The wallet address you will use to bond this gateway, e.g. nymt1z9egw0knv47nmur0p8vk4rcx59h9gg4zuxrrr9
#[clap(long)]
wallet_address: String,
wallet_address: nymd::AccountId,
/// The port on which the gateway will be listening for sphinx packets
#[clap(long)]
@@ -33,26 +36,27 @@ pub struct Init {
/// The host that will be reported to the directory server
#[clap(long)]
// TODO: could this be changed to `Option<url::Url>`?
announce_host: Option<String>,
/// Path to sqlite database containing all gateway persistent data
#[clap(long)]
datastore: Option<String>,
datastore: Option<PathBuf>,
/// Comma separated list of endpoints of nym APIs
#[clap(long, alias = "validator_apis")]
#[clap(long, alias = "validator_apis", value_delimiter = ',')]
// the alias here is included for backwards compatibility (1.1.4 and before)
nym_apis: Option<String>,
nym_apis: Option<Vec<url::Url>>,
/// Comma separated list of endpoints of the validator
#[cfg(feature = "coconut")]
#[clap(long, alias = "validators")]
#[clap(long, alias = "validators", value_delimiter = ',')]
// the alias here is included for backwards compatibility (1.1.4 and before)
nymd_validators: Option<String>,
nymd_validators: Option<Vec<url::Url>>,
/// Cosmos wallet mnemonic needed for double spending protection
#[clap(long)]
mnemonic: Option<String>,
mnemonic: Option<bip39::Mnemonic>,
/// Set this gateway to work only with coconut credentials; that would disallow clients to
/// bypass bandwidth credential requirement
@@ -66,7 +70,7 @@ pub struct Init {
/// URL where a statistics aggregator is running. The default value is a Nym aggregator server
#[clap(long)]
statistics_service_url: Option<String>,
statistics_service_url: Option<url::Url>,
}
impl From<Init> for OverrideConfig {
@@ -163,12 +167,12 @@ mod tests {
async fn create_gateway_with_in_mem_storage() {
let args = Init {
id: "foo-id".to_string(),
host: "foo-host".to_string(),
wallet_address: "n1z9egw0knv47nmur0p8vk4rcx59h9gg4zjx9ede".to_string(),
host: "1.1.1.1".parse().unwrap(),
wallet_address: "n1z9egw0knv47nmur0p8vk4rcx59h9gg4zjx9ede".parse().unwrap(),
mix_port: Some(42),
clients_port: Some(43),
announce_host: Some("foo-announce-host".to_string()),
datastore: Some("foo-datastore".to_string()),
datastore: Some("/foo-datastore".parse().unwrap()),
nym_apis: None,
mnemonic: None,
statistics_service_url: None,
+24 -29
View File
@@ -1,19 +1,20 @@
// Copyright 2020 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2020-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use std::{process, str::FromStr};
use crate::{config::Config, Cli};
use clap::CommandFactory;
use clap::Subcommand;
use colored::Colorize;
use completions::{fig_generate, ArgShell};
use config::parse_urls;
use crypto::bech32_address_validation;
use network_defaults::mainnet::read_var_if_not_default;
use network_defaults::var_names::{
API_VALIDATOR, BECH32_PREFIX, CONFIGURED, STATISTICS_SERVICE_DOMAIN_ADDRESS,
};
use std::net::IpAddr;
use std::path::PathBuf;
use std::process;
use validator_client::nymd::{self};
pub(crate) mod init;
pub(crate) mod node_details;
@@ -47,19 +48,19 @@ pub(crate) enum Commands {
// Configuration that can be overridden.
pub(crate) struct OverrideConfig {
host: Option<String>,
wallet_address: Option<String>,
host: Option<IpAddr>,
wallet_address: Option<nymd::AccountId>,
mix_port: Option<u16>,
clients_port: Option<u16>,
datastore: Option<String>,
datastore: Option<PathBuf>,
announce_host: Option<String>,
enabled_statistics: Option<bool>,
statistics_service_url: Option<String>,
nym_apis: Option<String>,
mnemonic: Option<String>,
statistics_service_url: Option<url::Url>,
nym_apis: Option<Vec<url::Url>>,
mnemonic: Option<bip39::Mnemonic>,
#[cfg(feature = "coconut")]
nymd_validators: Option<String>,
nymd_validators: Option<Vec<url::Url>>,
#[cfg(feature = "coconut")]
only_coconut_credentials: bool,
}
@@ -73,8 +74,8 @@ pub(crate) async fn execute(args: Cli) {
Commands::Run(m) => run::execute(m).await,
Commands::Sign(m) => sign::execute(m),
Commands::Upgrade(m) => upgrade::execute(m).await,
Commands::Completions(s) => s.generate(&mut crate::Cli::into_app(), bin_name),
Commands::GenerateFigSpec => fig_generate(&mut crate::Cli::into_app(), bin_name),
Commands::Completions(s) => s.generate(&mut crate::Cli::command(), bin_name),
Commands::GenerateFigSpec => fig_generate(&mut crate::Cli::command(), bin_name),
}
}
@@ -104,12 +105,8 @@ pub(crate) fn override_config(mut config: Config, args: OverrideConfig) -> Confi
config = config.with_enabled_statistics(enabled_statistics);
}
if let Some(raw_url) = args.statistics_service_url {
config = config.with_custom_statistics_service_url(
raw_url
.parse()
.expect("the provided statistics service url is invalid!"),
);
if let Some(url) = args.statistics_service_url {
config = config.with_custom_statistics_service_url(url);
} else if std::env::var(CONFIGURED).is_ok() {
if let Some(raw_url) = read_var_if_not_default(STATISTICS_SERVICE_DOMAIN_ADDRESS) {
config = config.with_custom_statistics_service_url(
@@ -120,8 +117,8 @@ pub(crate) fn override_config(mut config: Config, args: OverrideConfig) -> Confi
}
}
if let Some(raw_validators) = args.nym_apis {
config = config.with_custom_nym_apis(parse_urls(&raw_validators));
if let Some(nym_apis) = args.nym_apis {
config = config.with_custom_nym_apis(nym_apis);
} else if std::env::var(CONFIGURED).is_ok() {
if let Some(raw_validators) = read_var_if_not_default(API_VALIDATOR) {
config = config.with_custom_nym_apis(::config::parse_urls(&raw_validators))
@@ -129,9 +126,9 @@ pub(crate) fn override_config(mut config: Config, args: OverrideConfig) -> Confi
}
if let Some(wallet_address) = args.wallet_address {
let trimmed = wallet_address.trim();
validate_bech32_address_or_exit(trimmed);
config = config.with_wallet_address(trimmed);
// perform extra validation to ensure we have correct prefix
validate_bech32_address_or_exit(wallet_address.as_ref());
config = config.with_wallet_address(wallet_address);
}
if let Some(datastore_path) = args.datastore {
@@ -139,17 +136,15 @@ pub(crate) fn override_config(mut config: Config, args: OverrideConfig) -> Confi
}
if let Some(cosmos_mnemonic) = args.mnemonic {
config = config.with_cosmos_mnemonic(
bip39::Mnemonic::from_str(&cosmos_mnemonic).expect("Provided mnemonic is invalid"),
);
config = config.with_cosmos_mnemonic(cosmos_mnemonic);
}
#[cfg(feature = "coconut")]
{
use network_defaults::var_names::NYMD_VALIDATOR;
if let Some(ref raw_validators) = args.nymd_validators {
config = config.with_custom_validator_nymd(parse_urls(raw_validators));
if let Some(nymd_validators) = args.nymd_validators {
config = config.with_custom_validator_nymd(nymd_validators);
} else if std::env::var(CONFIGURED).is_ok() {
if let Some(raw_validators) = read_var_if_not_default(NYMD_VALIDATOR) {
config = config.with_custom_validator_nymd(::config::parse_urls(&raw_validators))
+14 -10
View File
@@ -1,4 +1,4 @@
// Copyright 2020 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2020-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::{
@@ -8,6 +8,9 @@ use crate::{
use clap::Args;
use config::NymConfig;
use log::*;
use std::net::IpAddr;
use std::path::PathBuf;
use validator_client::nymd;
#[derive(Args, Clone)]
pub struct Run {
@@ -17,11 +20,11 @@ pub struct Run {
/// The custom host on which the gateway will be running for receiving sphinx packets
#[clap(long)]
host: Option<String>,
host: Option<IpAddr>,
/// The wallet address you will use to bond this gateway, e.g. nymt1z9egw0knv47nmur0p8vk4rcx59h9gg4zuxrrr9
#[clap(long)]
wallet_address: Option<String>,
wallet_address: Option<nymd::AccountId>,
/// The port on which the gateway will be listening for sphinx packets
#[clap(long)]
@@ -33,26 +36,27 @@ pub struct Run {
/// The host that will be reported to the directory server
#[clap(long)]
// TODO: could this be changed to `Option<url::Url>`?
announce_host: Option<String>,
/// Path to sqlite database containing all gateway persistent data
#[clap(long)]
datastore: Option<String>,
datastore: Option<PathBuf>,
/// Comma separated list of endpoints of nym APIs
#[clap(long, alias = "validator_apis")]
#[clap(long, alias = "validator_apis", value_delimiter = ',')]
// the alias here is included for backwards compatibility (1.1.4 and before)
nym_apis: Option<String>,
nym_apis: Option<Vec<url::Url>>,
/// Comma separated list of endpoints of the validator
#[cfg(feature = "coconut")]
#[clap(long, alias = "validators")]
#[clap(long, alias = "validators", value_delimiter = ',')]
// the alias here is included for backwards compatibility (1.1.4 and before)
nymd_validators: Option<String>,
nymd_validators: Option<Vec<url::Url>>,
/// Cosmos wallet mnemonic
#[clap(long)]
mnemonic: Option<String>,
mnemonic: Option<bip39::Mnemonic>,
/// Set this gateway to work only with coconut credentials; that would disallow clients to
/// bypass bandwidth credential requirement
@@ -66,7 +70,7 @@ pub struct Run {
/// URL where a statistics aggregator is running. The default value is a Nym aggregator server
#[clap(long)]
statistics_service_url: Option<String>,
statistics_service_url: Option<url::Url>,
}
impl From<Run> for OverrideConfig {
+12 -13
View File
@@ -1,8 +1,9 @@
// Copyright 2020-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::commands::validate_bech32_address_or_exit;
use crate::{
commands::{validate_bech32_address_or_exit, version_check},
commands::version_check,
config::{persistence::pathfinder::GatewayPathfinder, Config},
};
use anyhow::{anyhow, Result};
@@ -10,9 +11,10 @@ use clap::{ArgGroup, Args};
use config::NymConfig;
use crypto::asymmetric::identity;
use log::error;
use validator_client::nymd;
#[derive(Args, Clone)]
#[clap(group(ArgGroup::new("sign").required(true).args(&["wallet-address", "text"])))]
#[clap(group(ArgGroup::new("sign").required(true).args(&["wallet_address", "text"])))]
pub struct Sign {
/// The id of the mixnode you want to sign with
#[clap(long)]
@@ -20,7 +22,7 @@ pub struct Sign {
/// Signs your blockchain address with your identity key
#[clap(long)]
wallet_address: Option<String>,
wallet_address: Option<nymd::AccountId>,
/// Signs an arbitrary piece of text with your identity key
#[clap(long)]
@@ -29,7 +31,7 @@ pub struct Sign {
enum SignedTarget {
Text(String),
Address(String),
Address(nymd::AccountId),
}
impl TryFrom<Sign> for SignedTarget {
@@ -58,15 +60,12 @@ pub fn load_identity_keys(pathfinder: &GatewayPathfinder) -> identity::KeyPair {
identity_keypair
}
fn print_signed_address(private_key: &identity::PrivateKey, raw_address: &str) {
let trimmed = raw_address.trim();
validate_bech32_address_or_exit(trimmed);
let signature = private_key.sign_text(trimmed);
fn print_signed_address(private_key: &identity::PrivateKey, wallet_address: nymd::AccountId) {
// perform extra validation to ensure we have correct prefix
validate_bech32_address_or_exit(wallet_address.as_ref());
println!(
"The base58-encoded signature on '{}' is: {}",
trimmed, signature
);
let signature = private_key.sign_text(wallet_address.as_ref());
println!("The base58-encoded signature on '{wallet_address}' is: {signature}",);
}
fn print_signed_text(private_key: &identity::PrivateKey, text: &str) {
@@ -113,6 +112,6 @@ pub fn execute(args: &Sign) {
match signed_target {
SignedTarget::Text(text) => print_signed_text(identity_keypair.private_key(), &text),
SignedTarget::Address(addr) => print_signed_address(identity_keypair.private_key(), &addr),
SignedTarget::Address(addr) => print_signed_address(identity_keypair.private_key(), addr),
}
}
+1 -1
View File
@@ -103,7 +103,7 @@ fn minor_0_12_upgrade(
print_start_upgrade(config_version, &to_version);
let upgraded_config = config.with_custom_version(to_version.to_string().as_ref());
let upgraded_config = config.with_custom_version(to_version.to_string());
upgraded_config.save_to_file(None).unwrap_or_else(|err| {
eprintln!("failed to overwrite config file! - {err}");
+14 -21
View File
@@ -4,7 +4,6 @@
use crate::config::template::config_template;
use config::defaults::{DEFAULT_CLIENT_LISTENING_PORT, DEFAULT_MIX_LISTENING_PORT};
use config::NymConfig;
use log::error;
use network_defaults::mainnet::{API_VALIDATOR, NYMD_VALIDATOR, STATISTICS_SERVICE_DOMAIN_ADDRESS};
use serde::{Deserialize, Serialize};
use std::net::IpAddr;
@@ -12,6 +11,7 @@ use std::path::PathBuf;
use std::str::FromStr;
use std::time::Duration;
use url::Url;
use validator_client::nymd;
pub mod persistence;
mod template;
@@ -160,16 +160,8 @@ impl Config {
self
}
pub fn with_listening_address<S: Into<String>>(mut self, listening_address: S) -> Self {
let listening_address_string = listening_address.into();
if let Ok(ip_addr) = listening_address_string.parse() {
self.gateway.listening_address = ip_addr;
} else {
error!(
"failed to change listening address. the provided value ({}) was invalid",
listening_address_string
);
}
pub fn with_listening_address(mut self, listening_address: IpAddr) -> Self {
self.gateway.listening_address = listening_address;
self
}
@@ -193,18 +185,18 @@ impl Config {
self
}
pub fn with_custom_persistent_store<S: Into<String>>(mut self, store_dir: S) -> Self {
self.gateway.persistent_storage = PathBuf::from(store_dir.into());
pub fn with_custom_persistent_store(mut self, store_dir: PathBuf) -> Self {
self.gateway.persistent_storage = store_dir;
self
}
pub fn with_custom_version(mut self, version: &str) -> Self {
self.gateway.version = version.to_string();
pub fn with_custom_version<S: Into<String>>(mut self, version: S) -> Self {
self.gateway.version = version.into();
self
}
pub fn with_wallet_address(mut self, wallet_address: &str) -> Self {
self.gateway.wallet_address = wallet_address.to_string();
pub fn with_wallet_address(mut self, wallet_address: nymd::AccountId) -> Self {
self.gateway.wallet_address = Some(wallet_address);
self
}
@@ -303,8 +295,8 @@ impl Config {
&self.gateway.version
}
pub fn get_wallet_address(&self) -> &str {
&self.gateway.wallet_address
pub fn get_wallet_address(&self) -> Option<nymd::AccountId> {
self.gateway.wallet_address.clone()
}
}
@@ -378,7 +370,8 @@ pub struct Gateway {
persistent_storage: PathBuf,
/// The Cosmos wallet address that will control this gateway
wallet_address: String,
// the only reason this is an Option is because of the lack of existence of a sane default value
wallet_address: Option<nymd::AccountId>,
}
impl Gateway {
@@ -424,7 +417,7 @@ impl Default for Gateway {
cosmos_mnemonic: bip39::Mnemonic::from_str("exact antique hybrid width raise anchor puzzle degree fee quit long crack net vague hip despair write put useless civil mechanic broom music day").unwrap(),
nym_root_directory: Config::default_root_directory(),
persistent_storage: Default::default(),
wallet_address: "nymXXXXXXXX".to_string(),
wallet_address: None,
}
}
}
+11 -44
View File
@@ -1,24 +1,28 @@
// Copyright 2020 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use build_information::BinaryBuildInformation;
use clap::{crate_version, Parser};
use lazy_static::lazy_static;
use logging::setup_logging;
use network_defaults::setup_env;
use once_cell::sync::OnceCell;
mod commands;
mod config;
mod node;
static LONG_VERSION: OnceCell<String> = OnceCell::new();
lazy_static! {
pub static ref PRETTY_BUILD_INFORMATION: String =
BinaryBuildInformation::new(env!("CARGO_PKG_VERSION")).pretty_print();
}
// Helper for passing LONG_ABOUT to clap
fn long_version_static() -> &'static str {
LONG_VERSION.get().expect("Failed to get long about text")
// Helper for passing LONG_VERSION to clap
fn pretty_build_info_static() -> &'static str {
&PRETTY_BUILD_INFORMATION
}
#[derive(Parser)]
#[clap(author = "Nymtech", version, about, long_version = long_version_static())]
#[clap(author = "Nymtech", version, about, long_version = pretty_build_info_static())]
struct Cli {
/// Path pointing to an env file that configures the gateway.
#[clap(short, long)]
@@ -32,12 +36,9 @@ struct Cli {
async fn main() {
setup_logging();
println!("{}", banner());
LONG_VERSION
.set(long_version())
.expect("Failed to set long about text");
let args = Cli::parse();
setup_env(args.config_env_file.clone());
setup_env(args.config_env_file.as_ref());
commands::execute(args).await;
}
@@ -58,37 +59,6 @@ fn banner() -> String {
)
}
fn long_version() -> String {
format!(
r#"
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
"#,
"Build Timestamp:",
env!("VERGEN_BUILD_TIMESTAMP"),
"Build Version:",
env!("VERGEN_BUILD_SEMVER"),
"Commit SHA:",
env!("VERGEN_GIT_SHA"),
"Commit Date:",
env!("VERGEN_GIT_COMMIT_TIMESTAMP"),
"Commit Branch:",
env!("VERGEN_GIT_BRANCH"),
"rustc Version:",
env!("VERGEN_RUSTC_SEMVER"),
"rustc Channel:",
env!("VERGEN_RUSTC_CHANNEL"),
"cargo Profile:",
env!("VERGEN_CARGO_PROFILE")
)
}
#[cfg(test)]
mod tests {
use super::*;
@@ -96,9 +66,6 @@ mod tests {
#[test]
fn verify_cli() {
LONG_VERSION
.set(long_version())
.expect("Failed to set long about text");
Cli::command().debug_assert();
}
}
+15 -9
View File
@@ -1,19 +1,20 @@
// Copyright 2020 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2020-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use self::storage::PersistentStorage;
use crate::commands::sign::load_identity_keys;
use crate::commands::validate_bech32_address_or_exit;
use crate::config::persistence::pathfinder::GatewayPathfinder;
use crate::config::Config;
use crate::node::client_handling::active_clients::ActiveClientsStore;
use crate::node::client_handling::websocket;
use crate::node::mixnet_handling::receiver::connection_handler::ConnectionHandler;
use crate::node::statistics::collector::GatewayStatisticsCollector;
use crate::node::storage::Storage;
use colored::Colorize;
use crypto::asymmetric::{encryption, identity};
use log::*;
use mixnet_client::forwarder::{MixForwardingSender, PacketForwarder};
#[cfg(feature = "coconut")]
use network_defaults::NymNetworkDetails;
use rand::seq::SliceRandom;
use rand::thread_rng;
use statistics_common::collector::StatisticsSender;
@@ -21,16 +22,15 @@ use std::net::SocketAddr;
use std::process;
use std::sync::Arc;
use crate::config::persistence::pathfinder::GatewayPathfinder;
#[cfg(feature = "coconut")]
use crate::node::client_handling::websocket::connection_handler::coconut::CoconutVerifier;
#[cfg(feature = "coconut")]
use credentials::coconut::utils::obtain_aggregate_verification_key;
#[cfg(feature = "coconut")]
use network_defaults::NymNetworkDetails;
#[cfg(feature = "coconut")]
use validator_client::{Client, CoconutApiClient};
use self::storage::PersistentStorage;
pub(crate) mod client_handling;
pub(crate) mod mixnet_handling;
pub(crate) mod statistics;
@@ -117,9 +117,15 @@ where
fn generate_owner_signature(&self) -> String {
let pathfinder = GatewayPathfinder::new_from_config(&self.config);
let identity_keypair = load_identity_keys(&pathfinder);
let address = self.config.get_wallet_address();
validate_bech32_address_or_exit(address);
let verification_code = identity_keypair.private_key().sign_text(address);
let Some(address) = self.config.get_wallet_address() else {
let error_message = "Error: gateway hasn't set its wallet address".red();
println!("{error_message}");
println!("Exiting...");
process::exit(1);
};
// perform extra validation to ensure we have correct prefix
validate_bech32_address_or_exit(address.as_ref());
let verification_code = identity_keypair.private_key().sign_text(address.as_ref());
verification_code
}
+2 -4
View File
@@ -18,7 +18,7 @@ rust-version = "1.58.1"
[dependencies]
anyhow = "1.0.40"
bs58 = "0.4.0"
clap = { version = "3.2", features = ["cargo", "derive"] }
clap = { version = "4.0", features = ["cargo", "derive"] }
colored = "2.0"
cupid = "0.6.1"
dirs = "4.0"
@@ -38,6 +38,7 @@ toml = "0.5.8"
url = { version = "2.2", features = ["serde"] }
## internal
build-information = { path = "../common/build-information" }
config = { path="../common/config" }
crypto = { path="../common/crypto" }
completions = { path="../common/completions" }
@@ -57,6 +58,3 @@ tokio = { version="1.21.2", features = ["rt-multi-thread", "net", "signal", "tes
nymsphinx-types = { path = "../common/nymsphinx/types" }
nymsphinx-params = { path = "../common/nymsphinx/params" }
[build-dependencies]
vergen = { version = "5", default-features = false, features = ["build", "git", "rustc", "cargo"] }
-8
View File
@@ -1,8 +0,0 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use vergen::{vergen, Config};
fn main() {
vergen(Config::default()).expect("failed to extract build metadata")
}
+7 -6
View File
@@ -1,14 +1,15 @@
// Copyright 2020-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use super::OverrideConfig;
use crate::config::Config;
use crate::node::MixNode;
use crate::{commands::override_config, config::persistence::pathfinder::MixNodePathfinder};
use clap::Args;
use config::NymConfig;
use crypto::asymmetric::{encryption, identity};
use super::OverrideConfig;
use std::net::IpAddr;
use validator_client::nymd;
#[derive(Args, Clone)]
pub(crate) struct Init {
@@ -18,11 +19,11 @@ pub(crate) struct Init {
/// The host on which the mixnode will be running
#[clap(long)]
host: String,
host: IpAddr,
/// The wallet address you will use to bond this mixnode, e.g. nymt1z9egw0knv47nmur0p8vk4rcx59h9gg4zuxrrr9
#[clap(long)]
wallet_address: String,
wallet_address: nymd::AccountId,
/// The port on which the mixnode will be listening for mix packets
#[clap(long)]
@@ -42,8 +43,8 @@ pub(crate) struct Init {
/// Comma separated list of nym-api endpoints of the validators
// the alias here is included for backwards compatibility (1.1.4 and before)
#[clap(long, alias = "validators")]
nym_apis: Option<String>,
#[clap(long, alias = "validators", value_delimiter = ',')]
nym_apis: Option<Vec<url::Url>>,
}
impl From<Init> for OverrideConfig {
+15 -17
View File
@@ -1,19 +1,17 @@
// Copyright 2020 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use std::process;
use crate::{config::Config, Cli};
use clap::CommandFactory;
use clap::Subcommand;
use colored::Colorize;
use completions::{fig_generate, ArgShell};
use config::defaults::mainnet::read_var_if_not_default;
use config::{
defaults::var_names::{API_VALIDATOR, BECH32_PREFIX, CONFIGURED},
parse_urls,
};
use config::defaults::var_names::{API_VALIDATOR, BECH32_PREFIX, CONFIGURED};
use crypto::bech32_address_validation;
use std::net::IpAddr;
use std::process;
use validator_client::nymd;
mod describe;
mod init;
@@ -52,13 +50,13 @@ pub(crate) enum Commands {
// Configuration that can be overridden.
struct OverrideConfig {
id: String,
host: Option<String>,
wallet_address: Option<String>,
host: Option<IpAddr>,
wallet_address: Option<nymd::AccountId>,
mix_port: Option<u16>,
verloc_port: Option<u16>,
http_api_port: Option<u16>,
announce_host: Option<String>,
nym_apis: Option<String>,
nym_apis: Option<Vec<url::Url>>,
}
pub(crate) async fn execute(args: Cli) {
@@ -71,8 +69,8 @@ pub(crate) async fn execute(args: Cli) {
Commands::Sign(m) => sign::execute(&m),
Commands::Upgrade(m) => upgrade::execute(&m),
Commands::NodeDetails(m) => node_details::execute(&m),
Commands::Completions(s) => s.generate(&mut crate::Cli::into_app(), bin_name),
Commands::GenerateFigSpec => fig_generate(&mut crate::Cli::into_app(), bin_name),
Commands::Completions(s) => s.generate(&mut crate::Cli::command(), bin_name),
Commands::GenerateFigSpec => fig_generate(&mut crate::Cli::command(), bin_name),
}
}
@@ -95,8 +93,8 @@ fn override_config(mut config: Config, args: OverrideConfig) -> Config {
config = config.with_http_api_port(port);
}
if let Some(ref raw_validators) = args.nym_apis {
config = config.with_custom_nym_apis(parse_urls(raw_validators));
if let Some(nym_apis) = args.nym_apis {
config = config.with_custom_nym_apis(nym_apis);
} else if std::env::var(CONFIGURED).is_ok() {
if let Some(raw_validators) = read_var_if_not_default(API_VALIDATOR) {
config = config.with_custom_nym_apis(::config::parse_urls(&raw_validators))
@@ -110,10 +108,10 @@ fn override_config(mut config: Config, args: OverrideConfig) -> Config {
config = config.announce_address_from_listening_address()
}
if let Some(ref wallet_address) = args.wallet_address {
let trimmed = wallet_address.trim();
validate_bech32_address_or_exit(trimmed);
config = config.with_wallet_address(trimmed);
if let Some(wallet_address) = args.wallet_address {
// perform extra validation to ensure we have correct prefix
validate_bech32_address_or_exit(wallet_address.as_ref());
config = config.with_wallet_address(wallet_address);
}
config
+7 -6
View File
@@ -1,13 +1,14 @@
// Copyright 2020 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use super::OverrideConfig;
use crate::commands::{override_config, version_check};
use crate::config::Config;
use crate::node::MixNode;
use clap::Args;
use config::NymConfig;
use super::OverrideConfig;
use std::net::IpAddr;
use validator_client::nymd;
#[derive(Args, Clone)]
pub(crate) struct Run {
@@ -17,11 +18,11 @@ pub(crate) struct Run {
/// The custom host on which the mixnode will be running
#[clap(long)]
host: Option<String>,
host: Option<IpAddr>,
/// The wallet address you will use to bond this mixnode, e.g. nymt1z9egw0knv47nmur0p8vk4rcx59h9gg4zuxrrr9
#[clap(long)]
wallet_address: Option<String>,
wallet_address: Option<nymd::AccountId>,
/// The port on which the mixnode will be listening for mix packets
#[clap(long)]
@@ -41,8 +42,8 @@ pub(crate) struct Run {
/// Comma separated list of nym-api endpoints of the validators
// the alias here is included for backwards compatibility (1.1.4 and before)
#[clap(long, alias = "validators")]
nym_apis: Option<String>,
#[clap(long, alias = "validators", value_delimiter = ',')]
nym_apis: Option<Vec<url::Url>>,
}
impl From<Run> for OverrideConfig {
+10 -12
View File
@@ -11,11 +11,12 @@ use clap::{ArgGroup, Args};
use config::NymConfig;
use crypto::asymmetric::identity;
use log::error;
use validator_client::nymd;
use super::version_check;
#[derive(Args, Clone)]
#[clap(group(ArgGroup::new("sign").required(true).args(&["wallet-address", "text"])))]
#[clap(group(ArgGroup::new("sign").required(true).args(&["wallet_address", "text"])))]
pub(crate) struct Sign {
/// The id of the mixnode you want to sign with
#[clap(long)]
@@ -24,7 +25,7 @@ pub(crate) struct Sign {
/// Signs your blockchain address with your identity key
// the alias here is included for backwards compatibility (1.1.4 and before)
#[clap(long, alias = "address")]
wallet_address: Option<String>,
wallet_address: Option<nymd::AccountId>,
/// Signs an arbitrary piece of text with your identity key
#[clap(long)]
@@ -33,7 +34,7 @@ pub(crate) struct Sign {
enum SignedTarget {
Text(String),
Address(String),
Address(nymd::AccountId),
}
impl TryFrom<Sign> for SignedTarget {
@@ -53,15 +54,12 @@ impl TryFrom<Sign> for SignedTarget {
}
}
fn print_signed_address(private_key: &identity::PrivateKey, raw_address: &str) {
let trimmed = raw_address.trim();
validate_bech32_address_or_exit(trimmed);
let signature = private_key.sign_text(trimmed);
fn print_signed_address(private_key: &identity::PrivateKey, wallet_address: nymd::AccountId) {
// perform extra validation to ensure we have correct prefix
validate_bech32_address_or_exit(wallet_address.as_ref());
println!(
"The base58-encoded signature on '{}' is: {}",
trimmed, signature
);
let signature = private_key.sign_text(wallet_address.as_ref());
println!("The base58-encoded signature on '{wallet_address}' is: {signature}",);
}
fn print_signed_text(private_key: &identity::PrivateKey, text: &str) {
@@ -108,6 +106,6 @@ pub(crate) fn execute(args: &Sign) {
match signed_target {
SignedTarget::Text(text) => print_signed_text(identity_keypair.private_key(), &text),
SignedTarget::Address(addr) => print_signed_address(identity_keypair.private_key(), &addr),
SignedTarget::Address(addr) => print_signed_address(identity_keypair.private_key(), addr),
}
}
+10 -16
View File
@@ -13,6 +13,7 @@ use std::path::PathBuf;
use std::str::FromStr;
use std::time::Duration;
use url::Url;
use validator_client::nymd;
pub mod persistence;
mod template;
@@ -160,16 +161,8 @@ impl Config {
self
}
pub fn with_listening_address<S: Into<String>>(mut self, listening_address: S) -> Self {
let listening_address_string = listening_address.into();
if let Ok(ip_addr) = listening_address_string.parse() {
self.mixnode.listening_address = ip_addr
} else {
error!(
"failed to change listening address. the provided value ({}) was invalid",
listening_address_string
)
}
pub fn with_listening_address(mut self, listening_address: IpAddr) -> Self {
self.mixnode.listening_address = listening_address;
self
}
@@ -203,8 +196,8 @@ impl Config {
self
}
pub fn with_wallet_address(mut self, wallet_address: &str) -> Self {
self.mixnode.wallet_address = wallet_address.to_string();
pub fn with_wallet_address(mut self, wallet_address: nymd::AccountId) -> Self {
self.mixnode.wallet_address = Some(wallet_address);
self
}
@@ -317,8 +310,8 @@ impl Config {
self.verloc.retry_timeout
}
pub fn get_wallet_address(&self) -> &str {
&self.mixnode.wallet_address
pub fn get_wallet_address(&self) -> Option<nymd::AccountId> {
self.mixnode.wallet_address.clone()
}
}
@@ -377,7 +370,8 @@ struct MixNode {
nym_root_directory: PathBuf,
/// The Cosmos wallet address that will control this mixnode
wallet_address: String,
// the only reason this is an Option is because of the lack of existence of a sane default value
wallet_address: Option<nymd::AccountId>,
}
impl MixNode {
@@ -414,7 +408,7 @@ impl Default for MixNode {
public_sphinx_key_file: Default::default(),
nym_api_urls: vec![Url::from_str(API_VALIDATOR).expect("Invalid default API URL")],
nym_root_directory: Config::default_root_directory(),
wallet_address: "nymXXXXXXXX".to_string(),
wallet_address: None,
}
}
}
+10 -39
View File
@@ -1,10 +1,11 @@
// Copyright 2020-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
#[macro_use]
extern crate rocket;
// Copyright 2020 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use ::config::defaults::setup_env;
use build_information::BinaryBuildInformation;
use clap::{crate_version, Parser};
use lazy_static::lazy_static;
use logging::setup_logging;
@@ -14,16 +15,17 @@ mod config;
mod node;
lazy_static! {
pub static ref LONG_VERSION: String = long_version();
pub static ref PRETTY_BUILD_INFORMATION: String =
BinaryBuildInformation::new(env!("CARGO_PKG_VERSION")).pretty_print();
}
// Helper for passing LONG_VERSION to clap
fn long_version_static() -> &'static str {
&LONG_VERSION
fn pretty_build_info_static() -> &'static str {
&PRETTY_BUILD_INFORMATION
}
#[derive(Parser)]
#[clap(author = "Nymtech", version, about, long_version = long_version_static())]
#[clap(author = "Nymtech", version, about, long_version = pretty_build_info_static())]
struct Cli {
/// Path pointing to an env file that configures the mixnode.
#[clap(short, long)]
@@ -39,7 +41,7 @@ async fn main() {
println!("{}", banner());
let args = Cli::parse();
setup_env(args.config_env_file.clone());
setup_env(args.config_env_file.as_ref());
commands::execute(args).await;
}
@@ -60,37 +62,6 @@ fn banner() -> String {
)
}
fn long_version() -> String {
format!(
r#"
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
"#,
"Build Timestamp:",
env!("VERGEN_BUILD_TIMESTAMP"),
"Build Version:",
env!("VERGEN_BUILD_SEMVER"),
"Commit SHA:",
env!("VERGEN_GIT_SHA"),
"Commit Date:",
env!("VERGEN_GIT_COMMIT_TIMESTAMP"),
"Commit Branch:",
env!("VERGEN_GIT_BRANCH"),
"rustc Version:",
env!("VERGEN_RUSTC_SEMVER"),
"rustc Channel:",
env!("VERGEN_RUSTC_CHANNEL"),
"cargo Profile:",
env!("VERGEN_CARGO_PROFILE")
)
}
#[cfg(test)]
mod tests {
use super::*;
+14 -4
View File
@@ -18,6 +18,7 @@ use crate::node::node_description::NodeDescription;
use crate::node::node_statistics::SharedNodeStats;
use crate::node::packet_delayforwarder::{DelayForwarder, PacketDelayForwardSender};
use ::crypto::asymmetric::{encryption, identity};
use colored::Colorize;
use config::NymConfig;
use log::{error, info, warn};
use mixnode_common::verloc::{self, AtomicVerlocResult, VerlocMeasurer};
@@ -87,9 +88,15 @@ impl MixNode {
fn generate_owner_signature(&self) -> String {
let pathfinder = MixNodePathfinder::new_from_config(&self.config);
let identity_keypair = Self::load_identity_keys(&pathfinder);
let address = self.config.get_wallet_address();
validate_bech32_address_or_exit(address);
let verification_code = identity_keypair.private_key().sign_text(address);
let Some(address) = self.config.get_wallet_address() else {
let error_message = "Error: mixnode hasn't set its wallet address".red();
println!("{error_message}");
println!("Exiting...");
process::exit(1);
};
// perform extra validation to ensure we have correct prefix
validate_bech32_address_or_exit(address.as_ref());
let verification_code = identity_keypair.private_key().sign_text(address.as_ref());
verification_code
}
@@ -118,7 +125,10 @@ impl MixNode {
);
println!(
"You are bonding to wallet address: {}\n\n",
self.config.get_wallet_address()
self.config
.get_wallet_address()
.map(|addr| addr.to_string())
.unwrap_or_else(|| "UNSPECIFIED".to_string())
);
}
+4 -7
View File
@@ -17,13 +17,15 @@ rust-version = "1.56"
[dependencies]
async-trait = "0.1.52"
bs58 = {version = "0.4.0", optional = true }
bip39 = "1"
cfg-if = "1.0"
clap = { version = "3.2", features = ["cargo"] }
clap = { version = "4.0", 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"
dotenv = "0.15.0"
futures = "0.3.24"
humantime-serde = "1.0"
lazy_static = "1.4.0"
log = "0.4.17"
pin-project = "1.0"
pretty_env_logger = "0.4.0"
@@ -63,6 +65,7 @@ rocket_okapi = { version = "0.8.0-rc.2", features = ["swagger"] }
schemars = { version = "0.8", features = ["preserve_order"] }
## internal
build-information = { path = "../common/build-information" }
coconut-bandwidth-contract-common = { path = "../common/cosmwasm-smart-contracts/coconut-bandwidth-contract" }
coconut-dkg-common = { path = "../common/cosmwasm-smart-contracts/coconut-dkg", optional = true }
coconut-interface = { path = "../common/coconut-interface", optional = true }
@@ -115,12 +118,6 @@ sqlx = { version = "0.6.2", features = [
"macros",
"migrate",
] }
vergen = { version = "7", default-features = false, features = [
"build",
"git",
"rustc",
"cargo",
] }
[dev-dependencies]
cw3 = "0.13.4"
-3
View File
@@ -1,6 +1,5 @@
use sqlx::{Connection, SqliteConnection};
use std::env;
use vergen::{vergen, Config};
#[tokio::main]
async fn main() {
@@ -23,6 +22,4 @@ async fn main() {
// for some strange reason we need to add a leading `/` to the windows path even though it's
// not a valid windows path... but hey, it works...
println!("cargo:rustc-env=DATABASE_URL=sqlite:///{}", &database_path);
vergen(Config::default()).expect("failed to extract build metadata")
}
+133 -256
View File
@@ -1,4 +1,4 @@
// Copyright 2020 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2020-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
#[macro_use]
@@ -6,6 +6,7 @@ extern crate rocket;
use crate::config::Config;
use crate::contract_cache::ValidatorCacheRefresher;
use crate::epoch_operations::RewardedSetUpdater;
use crate::network_monitor::NetworkMonitorBuilder;
use crate::node_status_api::uptime_updater::HistoricalUptimeUpdater;
use crate::nymd_client::Client;
@@ -15,9 +16,12 @@ use ::config::defaults::setup_env;
use ::config::defaults::var_names::{CONFIGURED, MIXNET_CONTRACT_ADDRESS, MIX_DENOM};
use ::config::NymConfig;
use anyhow::Result;
use clap::{crate_version, App, Arg, ArgMatches};
use build_information::BinaryBuildInformation;
use clap::Parser;
use contract_cache::ValidatorCache;
use lazy_static::lazy_static;
use log::{info, warn};
use logging::setup_logging;
use node_status_api::NodeStatusCache;
use okapi::openapi3::OpenApi;
use rocket::fairing::AdHoc;
@@ -26,27 +30,21 @@ use rocket::{Ignite, Rocket};
use rocket_cors::{AllowedHeaders, AllowedOrigins, Cors};
use rocket_okapi::mount_endpoints_and_merged_docs;
use rocket_okapi::swagger_ui::make_swagger_ui;
use std::path::PathBuf;
use std::str::FromStr;
use std::sync::Arc;
use std::time::Duration;
use std::{fs, process};
use task::TaskManager;
use task::{wait_for_signal, TaskManager};
use tokio::sync::Notify;
#[cfg(feature = "coconut")]
use url::Url;
use validator_client::nymd::SigningNymdClient;
use validator_client::nymd::{self, SigningNymdClient};
use crate::epoch_operations::RewardedSetUpdater;
#[cfg(feature = "coconut")]
use coconut::{
comm::QueryCommunicationChannel,
dkg::controller::{init_keypair, DkgController},
InternalSignRequest,
};
use logging::setup_logging;
#[cfg(feature = "coconut")]
use validator_client::nymd::bip32::secp256k1::elliptic_curve::rand_core::OsRng;
use rand::rngs::OsRng;
pub(crate) mod config;
pub(crate) mod contract_cache;
@@ -60,150 +58,92 @@ mod swagger;
#[cfg(feature = "coconut")]
mod coconut;
const ID: &str = "id";
const CONFIG_ENV_FILE: &str = "config-env-file";
const MONITORING_ENABLED: &str = "enable-monitor";
const REWARDING_ENABLED: &str = "enable-rewarding";
const MIXNET_CONTRACT_ARG: &str = "mixnet-contract";
const MNEMONIC_ARG: &str = "mnemonic";
const WRITE_CONFIG_ARG: &str = "save-config";
const NYMD_VALIDATOR_ARG: &str = "nymd-validator";
const ENABLED_CREDENTIALS_MODE_ARG_NAME: &str = "enabled-credentials-mode";
#[cfg(feature = "coconut")]
const ANNOUNCE_ADDRESS: &str = "announce-address";
#[cfg(feature = "coconut")]
const COCONUT_ENABLED: &str = "enable-coconut";
const REWARDING_MONITOR_THRESHOLD_ARG: &str = "monitor-threshold";
const MIN_MIXNODE_RELIABILITY_ARG: &str = "min_mixnode_reliability";
const MIN_GATEWAY_RELIABILITY_ARG: &str = "min_gateway_reliability";
fn long_version() -> String {
format!(
r#"
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
"#,
"Build Timestamp:",
env!("VERGEN_BUILD_TIMESTAMP"),
"Build Version:",
env!("VERGEN_BUILD_SEMVER"),
"Commit SHA:",
env!("VERGEN_GIT_SHA"),
"Commit Date:",
env!("VERGEN_GIT_COMMIT_TIMESTAMP"),
"Commit Branch:",
env!("VERGEN_GIT_BRANCH"),
"rustc Version:",
env!("VERGEN_RUSTC_SEMVER"),
"rustc Channel:",
env!("VERGEN_RUSTC_CHANNEL"),
"cargo Profile:",
env!("VERGEN_CARGO_PROFILE")
)
lazy_static! {
pub static ref PRETTY_BUILD_INFORMATION: String =
BinaryBuildInformation::new(env!("CARGO_PKG_VERSION")).pretty_print();
}
fn parse_args() -> ArgMatches {
let build_details = long_version();
let base_app = App::new("Nym API")
.version(crate_version!())
.long_version(&*build_details)
.author("Nymtech")
.arg(
Arg::with_name(CONFIG_ENV_FILE)
.help("Path pointing to an env file that configures the Nym API")
.long(CONFIG_ENV_FILE)
.short('c')
.takes_value(true)
)
.arg(
Arg::with_name(ID)
.help("Id of the nym-api we want to run")
.long(ID)
.takes_value(true)
)
.arg(
Arg::with_name(MONITORING_ENABLED)
.help("specifies whether a network monitoring is enabled on this API")
.long(MONITORING_ENABLED)
.short('m')
)
.arg(
Arg::with_name(REWARDING_ENABLED)
.help("specifies whether a network rewarding is enabled on this API")
.long(REWARDING_ENABLED)
.short('r')
.requires_all(&[MONITORING_ENABLED, MNEMONIC_ARG])
)
.arg(
Arg::with_name(NYMD_VALIDATOR_ARG)
.help("Endpoint to nymd instance from which the monitor will grab nodes to test")
.long(NYMD_VALIDATOR_ARG)
.takes_value(true)
)
.arg(Arg::with_name(MIXNET_CONTRACT_ARG)
.long(MIXNET_CONTRACT_ARG)
.help("Address of the mixnet contract managing the network")
.takes_value(true),
)
.arg(Arg::with_name(MNEMONIC_ARG)
.long(MNEMONIC_ARG)
.help("Mnemonic of the network monitor used for rewarding operators")
.takes_value(true)
)
.arg(
Arg::with_name(WRITE_CONFIG_ARG)
.help("specifies whether a config file based on provided arguments should be saved to a file")
.long(WRITE_CONFIG_ARG)
.short('w')
)
.arg(
Arg::with_name(REWARDING_MONITOR_THRESHOLD_ARG)
.help("Specifies the minimum percentage of monitor test run data present in order to distribute rewards for given interval.")
.takes_value(true)
.long(REWARDING_MONITOR_THRESHOLD_ARG)
)
.arg(
Arg::with_name(MIN_MIXNODE_RELIABILITY_ARG)
.long(MIN_MIXNODE_RELIABILITY_ARG)
.help("Mixnodes with reliability lower the this get blacklisted by network monitor, get no traffic and cannot be selected into a rewarded set.")
.takes_value(true)
)
.arg(
Arg::with_name(MIN_GATEWAY_RELIABILITY_ARG)
.long(MIN_GATEWAY_RELIABILITY_ARG)
.help("Gateways with reliability lower the this get blacklisted by network monitor, get no traffic and cannot be selected into a rewarded set.")
.takes_value(true)
)
.arg(
Arg::with_name(ENABLED_CREDENTIALS_MODE_ARG_NAME)
.long(ENABLED_CREDENTIALS_MODE_ARG_NAME)
.help("Set this nym api to work in a enabled credentials that would attempt to use gateway with the bandwidth credential requirement")
);
// Helper for passing LONG_VERSION to clap
fn pretty_build_info_static() -> &'static str {
&PRETTY_BUILD_INFORMATION
}
// explicitly defined custom parser (as opposed to just using
// #[arg(value_parser = clap::value_parser!(u8).range(0..100))]
// for better error message
fn threshold_in_range(s: &str) -> Result<u8, String> {
let threshold: usize = s
.parse()
.map_err(|_| format!("`{s}` isn't a valid threshold number"))?;
if threshold > 100 {
Err(format!("{threshold} is not within the range 0-100"))
} else {
Ok(threshold as u8)
}
}
#[derive(Parser)]
#[clap(author = "Nymtech", version, long_version = pretty_build_info_static(), about)]
struct ApiArgs {
/// Path pointing to an env file that configures the Nym API.
#[clap(short, long)]
config_env_file: Option<std::path::PathBuf>,
/// Id of the nym-api we want to run
#[clap(long)]
id: Option<String>,
/// Specifies whether network monitoring is enabled on this API
#[clap(short = 'm', long)]
enable_monitor: bool,
/// Specifies whether network rewarding is enabled on this API
#[clap(short = 'r', long, requires = "enable_monitor", requires = "mnemonic")]
enable_rewarding: bool,
/// Endpoint to nymd instance from which the monitor will grab nodes to test
#[clap(long)]
nymd_validator: Option<url::Url>,
/// Address of the mixnet contract managing the network
#[clap(long)]
mixnet_contract: Option<nymd::AccountId>,
/// Mnemonic of the network monitor used for rewarding operators
// even though we're currently converting the mnemonic to string (and then back to the concrete type)
// at least we're getting immediate validation when passing the arguments
#[clap(long)]
mnemonic: Option<bip39::Mnemonic>,
/// Specifies whether a config file based on provided arguments should be saved to a file
#[clap(short = 'w', long)]
save_config: bool,
/// Specifies the minimum percentage of monitor test run data present in order to distribute rewards for given interval.
#[clap(long, value_parser = threshold_in_range)]
monitor_threshold: Option<u8>,
/// Mixnodes with reliability lower the this get blacklisted by network monitor, get no traffic and cannot be selected into a rewarded set.
#[clap(long, value_parser = threshold_in_range)]
min_mixnode_reliability: Option<u8>,
/// Gateways with reliability lower the this get blacklisted by network monitor, get no traffic and cannot be selected into a rewarded set.
#[clap(long, value_parser = threshold_in_range)]
min_gateway_reliability: Option<u8>,
/// Set this nym api to work in a enabled credentials that would attempt to use gateway with the bandwidth credential requirement
#[clap(long)]
enabled_credentials_mode: bool,
/// Announced address where coconut clients will connect.
#[cfg(feature = "coconut")]
let base_app = base_app
.arg(
Arg::with_name(ANNOUNCE_ADDRESS)
.help("Announced address where coconut clients will connect.")
.long(ANNOUNCE_ADDRESS)
.takes_value(true),
)
.arg(
Arg::with_name(COCONUT_ENABLED)
.help("Flag to indicate whether coconut signer authority is enabled on this API")
.requires_all(&[MNEMONIC_ARG, ANNOUNCE_ADDRESS])
.long(COCONUT_ENABLED),
);
base_app.get_matches()
#[clap(long)]
announce_address: Option<url::Url>,
/// Flag to indicate whether coconut signer authority is enabled on this API
#[cfg(feature = "coconut")]
#[clap(long, requires = "mnemonic", requires = "announce-address")]
enable_coconut: bool,
}
async fn wait_for_interrupt(mut shutdown: TaskManager) {
@@ -218,122 +158,55 @@ async fn wait_for_interrupt(mut shutdown: TaskManager) {
log::info!("Stopping nym API");
}
#[cfg(unix)]
async fn wait_for_signal() {
use tokio::signal::unix::{signal, SignalKind};
let mut sigterm = signal(SignalKind::terminate()).expect("Failed to setup SIGTERM channel");
let mut sigquit = signal(SignalKind::quit()).expect("Failed to setup SIGQUIT channel");
tokio::select! {
_ = tokio::signal::ctrl_c() => {
log::info!("Received SIGINT");
},
_ = sigterm.recv() => {
log::info!("Received SIGTERM");
}
_ = sigquit.recv() => {
log::info!("Received SIGQUIT");
}
}
}
#[cfg(not(unix))]
async fn wait_for_signal() {
tokio::select! {
_ = tokio::signal::ctrl_c() => {
log::info!("Received SIGINT");
},
}
}
fn override_config(mut config: Config, matches: &ArgMatches) -> Config {
if let Some(id) = matches.value_of(ID) {
fs::create_dir_all(Config::default_config_directory(Some(id)))
fn override_config(mut config: Config, args: ApiArgs) -> Config {
if let Some(id) = args.id {
fs::create_dir_all(Config::default_config_directory(Some(&id)))
.expect("Could not create config directory");
fs::create_dir_all(Config::default_data_directory(Some(id)))
fs::create_dir_all(Config::default_data_directory(Some(&id)))
.expect("Could not create data directory");
config = config.with_id(id);
config = config.with_id(&id);
}
if matches.is_present(MONITORING_ENABLED) {
config = config.with_network_monitor_enabled(true)
config = config
.with_network_monitor_enabled(args.enable_monitor)
.with_rewarding_enabled(args.enable_rewarding)
.with_disabled_credentials_mode(!args.enabled_credentials_mode);
if let Some(nymd_validator) = args.nymd_validator {
config = config.with_custom_nymd_validator(nymd_validator);
}
if matches.is_present(REWARDING_ENABLED) {
config = config.with_rewarding_enabled(true)
}
#[cfg(feature = "coconut")]
if matches.is_present(COCONUT_ENABLED) {
config = config.with_coconut_signer_enabled(true)
}
#[cfg(feature = "coconut")]
if let Some(announce_address) = matches.value_of(ANNOUNCE_ADDRESS) {
config = config.with_announce_address(
Url::parse(announce_address).expect("Could not parse announce address"),
);
}
if let Some(raw_validator) = matches.value_of(NYMD_VALIDATOR_ARG) {
let parsed = match raw_validator.parse() {
Err(err) => {
error!("Passed validator argument is invalid - {err}");
process::exit(1)
}
Ok(url) => url,
};
config = config.with_custom_nymd_validator(parsed);
}
if let Some(mixnet_contract) = matches.value_of(MIXNET_CONTRACT_ARG) {
config = config.with_custom_mixnet_contract(mixnet_contract)
if let Some(mixnet_contract) = args.mixnet_contract {
config = config.with_custom_mixnet_contract(mixnet_contract.to_string())
} else if std::env::var(CONFIGURED).is_ok() {
if let Some(mixnet_contract) = read_var_if_not_default(MIXNET_CONTRACT_ADDRESS) {
config = config.with_custom_mixnet_contract(mixnet_contract)
}
}
if let Some(mnemonic) = matches.value_of(MNEMONIC_ARG) {
config = config.with_mnemonic(mnemonic)
if let Some(mnemonic) = args.mnemonic {
config = config.with_mnemonic(mnemonic.to_string())
}
if let Some(monitor_threshold) = matches
.value_of(REWARDING_MONITOR_THRESHOLD_ARG)
.map(|t| t.parse::<u8>())
{
let monitor_threshold =
monitor_threshold.expect("Provided monitor threshold is not a number!");
assert!(
monitor_threshold <= 100,
"Provided monitor threshold is greater than 100!"
);
if let Some(monitor_threshold) = args.monitor_threshold {
config = config.with_minimum_interval_monitor_threshold(monitor_threshold)
}
if let Some(reliability) = matches
.value_of(MIN_MIXNODE_RELIABILITY_ARG)
.map(|t| t.parse::<u8>())
{
config = config.with_min_mixnode_reliability(
reliability.expect("Provided reliability is not a u8 number!"),
)
if let Some(reliability) = args.min_mixnode_reliability {
config = config.with_min_mixnode_reliability(reliability)
}
if let Some(reliability) = matches
.value_of(MIN_GATEWAY_RELIABILITY_ARG)
.map(|t| t.parse::<u8>())
{
config = config.with_min_gateway_reliability(
reliability.expect("Provided reliability is not a u8 number!"),
)
if let Some(reliability) = args.min_gateway_reliability {
config = config.with_min_gateway_reliability(reliability)
}
if matches.is_present(ENABLED_CREDENTIALS_MODE_ARG_NAME) {
config = config.with_disabled_credentials_mode(false)
#[cfg(feature = "coconut")]
if let Some(announce_address) = args.announce_address {
config = config
.with_announce_address(announce_address)
.with_coconut_signer_enabled(args.enable_coconut);
}
if matches.is_present(WRITE_CONFIG_ARG) {
if args.save_config {
info!("Saving the configuration to a file");
if let Err(err) = config.save_to_file(None) {
error!("Failed to write config to a file - {err}");
@@ -490,11 +363,11 @@ fn get_servers() -> Vec<rocket_okapi::okapi::openapi3::Server> {
}]
}
async fn run_nym_api(matches: ArgMatches) -> Result<()> {
async fn run_nym_api(args: ApiArgs) -> Result<()> {
let system_version = env!("CARGO_PKG_VERSION");
// try to load config from the file, if it doesn't exist, use default values
let id = matches.value_of(ID);
let id = args.id.as_deref();
let (config, _already_inited) = match Config::load_from_file(id) {
Ok(cfg) => (cfg, true),
Err(_) => {
@@ -503,14 +376,14 @@ async fn run_nym_api(matches: ArgMatches) -> Result<()> {
.into_string()
.unwrap();
warn!(
"Could not load the configuration file from {}. Either the file did not exist or was malformed. Using the default values instead",
config_path
"Could not load the configuration file from {config_path}. Either the file did not exist or was malformed. Using the default values instead",
);
(Config::new(), false)
}
};
let config = override_config(config, &matches);
let save_to_file = args.save_config;
let config = override_config(config, args);
#[cfg(feature = "coconut")]
if !_already_inited {
@@ -518,9 +391,16 @@ async fn run_nym_api(matches: ArgMatches) -> Result<()> {
}
// if we just wanted to write data to the config, exit
if matches.is_present(WRITE_CONFIG_ARG) {
if save_to_file {
info!("Saving the configuration to a file");
if let Err(err) = config.save_to_file(None) {
error!("Failed to write config to a file - {err}");
process::exit(1)
} else {
return Ok(());
}
}
let mix_denom = std::env::var(MIX_DENOM).expect("mix denom not set");
let signing_nymd_client = Client::new_signing(&config);
@@ -660,10 +540,7 @@ async fn main() -> Result<()> {
}}
setup_logging();
let args = parse_args();
let config_env_file = args
.value_of(CONFIG_ENV_FILE)
.map(|s| PathBuf::from_str(s).expect("invalid env config file"));
setup_env(config_env_file);
let args = ApiArgs::parse();
setup_env(args.config_env_file.as_ref());
run_nym_api(args).await
}
+59 -22
View File
@@ -407,6 +407,13 @@ dependencies = [
"memchr",
]
[[package]]
name = "build-information"
version = "0.1.0"
dependencies = [
"vergen 7.4.4",
]
[[package]]
name = "bumpalo"
version = "3.11.0"
@@ -566,35 +573,33 @@ dependencies = [
[[package]]
name = "clap"
version = "3.2.22"
version = "4.0.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "86447ad904c7fb335a790c9d7fe3d0d971dc523b8ccd1561a520de9a85302750"
checksum = "2148adefda54e14492fb9bddcc600b4344c5d1a3123bd666dcb939c6f0e0e57e"
dependencies = [
"atty",
"bitflags",
"clap_derive",
"clap_lex",
"indexmap",
"once_cell",
"strsim",
"termcolor",
"textwrap",
]
[[package]]
name = "clap_complete"
version = "3.2.5"
version = "4.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f7a2e0a962c45ce25afce14220bc24f9dade0a1787f185cecf96bfba7847cd8"
checksum = "10861370d2ba66b0f5989f83ebf35db6421713fd92351790e7fdd6c36774c56b"
dependencies = [
"clap",
]
[[package]]
name = "clap_complete_fig"
version = "3.2.4"
version = "4.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed37b4c0c1214673eba6ad8ea31666626bf72be98ffb323067d973c48b4964b9"
checksum = "46b30e010e669cd021e5004f3be26cff6b7c08d2a8a0d65b48d43a8cc0efd6c3"
dependencies = [
"clap",
"clap_complete",
@@ -602,9 +607,9 @@ dependencies = [
[[package]]
name = "clap_derive"
version = "3.2.18"
version = "4.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea0c8bce528c4be4da13ea6fead8965e95b6073585a2f05204bd8f4119f82a65"
checksum = "0177313f9f02afc995627906bbd8967e2be069f5261954222dac78290c2b9014"
dependencies = [
"heck 0.4.0",
"proc-macro-error",
@@ -615,9 +620,9 @@ dependencies = [
[[package]]
name = "clap_lex"
version = "0.2.4"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5"
checksum = "0d4198f73e42b4936b35b5bb248d81d2b595ecb170da0bac7655c54eedfa8da8"
dependencies = [
"os_str_bytes",
]
@@ -1583,7 +1588,16 @@ version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2953d1df47ac0eb70086ccabf0275aa8da8591a28bd358ee2b52bd9f9e3ff9e9"
dependencies = [
"enum-iterator-derive",
"enum-iterator-derive 0.8.1",
]
[[package]]
name = "enum-iterator"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "45a0ac4aeb3a18f92eaf09c6bb9b3ac30ff61ca95514fc58cbead1c9a6bf5401"
dependencies = [
"enum-iterator-derive 1.1.0",
]
[[package]]
@@ -1597,6 +1611,17 @@ dependencies = [
"syn",
]
[[package]]
name = "enum-iterator-derive"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "828de45d0ca18782232dfb8f3ea9cc428e8ced380eb26a520baaacfc70de39ce"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "env_logger"
version = "0.7.1"
@@ -3440,6 +3465,7 @@ dependencies = [
name = "nym-socks5-client"
version = "1.1.4"
dependencies = [
"build-information",
"clap",
"client-connections",
"client-core",
@@ -3451,6 +3477,7 @@ dependencies = [
"futures",
"gateway-client",
"gateway-requests",
"lazy_static",
"log",
"logging",
"network-defaults",
@@ -3471,7 +3498,6 @@ dependencies = [
"topology",
"url",
"validator-client",
"vergen",
"version-checker",
]
@@ -6028,12 +6054,6 @@ dependencies = [
"winapi-util",
]
[[package]]
name = "textwrap"
version = "0.15.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7b3e525a49ec206798b40326a44121291b530c963cfb01018f63e135bac543d"
[[package]]
name = "thin-slice"
version = "0.1.1"
@@ -6538,7 +6558,7 @@ dependencies = [
"anyhow",
"cfg-if",
"chrono",
"enum-iterator",
"enum-iterator 0.8.1",
"getset",
"git2",
"rustc_version 0.4.0",
@@ -6546,6 +6566,23 @@ dependencies = [
"thiserror",
]
[[package]]
name = "vergen"
version = "7.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "efadd36bc6fde40c6048443897d69511a19161c0756cb704ed403f8dfd2b7d1c"
dependencies = [
"anyhow",
"cfg-if",
"enum-iterator 1.1.3",
"getset",
"git2",
"rustc_version 0.4.0",
"rustversion",
"thiserror",
"time 0.3.17",
]
[[package]]
name = "version-checker"
version = "0.1.0"
@@ -6582,7 +6619,7 @@ dependencies = [
"schemars",
"serde",
"thiserror",
"vergen",
"vergen 5.1.17",
"vesting-contract-common",
]
+141 -20
View File
@@ -167,7 +167,7 @@ version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
dependencies = [
"hermit-abi",
"hermit-abi 0.1.19",
"libc",
"winapi",
]
@@ -511,26 +511,24 @@ dependencies = [
[[package]]
name = "clap"
version = "3.2.20"
version = "4.0.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23b71c3ce99b7611011217b366d923f1d0a7e07a92bb2dbf1e84508c673ca3bd"
checksum = "a7db700bc935f9e43e88d00b0850dae18a63773cfbec6d8e070fccf7fef89a39"
dependencies = [
"atty",
"bitflags",
"clap_derive",
"clap_lex",
"indexmap",
"is-terminal",
"once_cell",
"strsim",
"termcolor",
"textwrap",
]
[[package]]
name = "clap_derive"
version = "3.2.18"
version = "4.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea0c8bce528c4be4da13ea6fead8965e95b6073585a2f05204bd8f4119f82a65"
checksum = "0177313f9f02afc995627906bbd8967e2be069f5261954222dac78290c2b9014"
dependencies = [
"heck 0.4.0",
"proc-macro-error",
@@ -541,9 +539,9 @@ dependencies = [
[[package]]
name = "clap_lex"
version = "0.2.4"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5"
checksum = "0d4198f73e42b4936b35b5bb248d81d2b595ecb170da0bac7655c54eedfa8da8"
dependencies = [
"os_str_bytes",
]
@@ -1339,6 +1337,27 @@ dependencies = [
"termcolor",
]
[[package]]
name = "errno"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1"
dependencies = [
"errno-dragonfly",
"libc",
"winapi",
]
[[package]]
name = "errno-dragonfly"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
dependencies = [
"cc",
"libc",
]
[[package]]
name = "execute"
version = "0.1.0"
@@ -2016,6 +2035,15 @@ dependencies = [
"libc",
]
[[package]]
name = "hermit-abi"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7"
dependencies = [
"libc",
]
[[package]]
name = "hex"
version = "0.4.3"
@@ -2284,12 +2312,34 @@ dependencies = [
"cfg-if",
]
[[package]]
name = "io-lifetimes"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46112a93252b123d31a119a8d1a1ac19deac4fac6e0e8b0df58f0d4e5870e63c"
dependencies = [
"libc",
"windows-sys 0.42.0",
]
[[package]]
name = "ipnet"
version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68f2d64f2edebec4ce84ad108148e67e1064789bee435edc5b60ad398714a3a9"
[[package]]
name = "is-terminal"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28dfb6c8100ccc63462345b67d1bbc3679177c75ee4bf59bf29c8b1d110b8189"
dependencies = [
"hermit-abi 0.2.6",
"io-lifetimes",
"rustix",
"windows-sys 0.42.0",
]
[[package]]
name = "itertools"
version = "0.10.3"
@@ -2460,6 +2510,12 @@ dependencies = [
"safemem",
]
[[package]]
name = "linux-raw-sys"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4"
[[package]]
name = "lock_api"
version = "0.4.6"
@@ -2613,7 +2669,7 @@ dependencies = [
"libc",
"log",
"wasi 0.11.0+wasi-snapshot-preview1",
"windows-sys",
"windows-sys 0.36.1",
]
[[package]]
@@ -2765,7 +2821,7 @@ version = "1.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1"
dependencies = [
"hermit-abi",
"hermit-abi 0.1.19",
"libc",
]
@@ -3009,7 +3065,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f23a407004a1033f53e93f9b45580d14de23928faad187384f891507c9b0c045"
dependencies = [
"pathdiff",
"windows-sys",
"windows-sys 0.36.1",
]
[[package]]
@@ -3130,7 +3186,7 @@ dependencies = [
"libc",
"redox_syscall",
"smallvec 1.8.0",
"windows-sys",
"windows-sys 0.36.1",
]
[[package]]
@@ -3960,6 +4016,20 @@ dependencies = [
"semver 1.0.6",
]
[[package]]
name = "rustix"
version = "0.36.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4feacf7db682c6c329c4ede12649cd36ecab0f3be5b7d74e6a20304725db4549"
dependencies = [
"bitflags",
"errno",
"io-lifetimes",
"libc",
"linux-raw-sys",
"windows-sys 0.42.0",
]
[[package]]
name = "rustls"
version = "0.19.1"
@@ -4967,12 +5037,6 @@ dependencies = [
"winapi-util",
]
[[package]]
name = "textwrap"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb"
[[package]]
name = "thin-slice"
version = "0.1.1"
@@ -5749,12 +5813,33 @@ dependencies = [
"windows_x86_64_msvc 0.36.1",
]
[[package]]
name = "windows-sys"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc 0.42.0",
"windows_i686_gnu 0.42.0",
"windows_i686_msvc 0.42.0",
"windows_x86_64_gnu 0.42.0",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc 0.42.0",
]
[[package]]
name = "windows-tokens"
version = "0.39.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f838de2fe15fe6bac988e74b798f26499a8b21a9d97edec321e79b28d1d7f597"
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e"
[[package]]
name = "windows_aarch64_msvc"
version = "0.36.1"
@@ -5773,6 +5858,12 @@ version = "0.39.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec7711666096bd4096ffa835238905bb33fb87267910e154b18b44eaabb340f2"
[[package]]
name = "windows_aarch64_msvc"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4"
[[package]]
name = "windows_i686_gnu"
version = "0.36.1"
@@ -5791,6 +5882,12 @@ version = "0.39.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "763fc57100a5f7042e3057e7e8d9bdd7860d330070251a73d003563a3bb49e1b"
[[package]]
name = "windows_i686_gnu"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7"
[[package]]
name = "windows_i686_msvc"
version = "0.36.1"
@@ -5809,6 +5906,12 @@ version = "0.39.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7bc7cbfe58828921e10a9f446fcaaf649204dcfe6c1ddd712c5eebae6bda1106"
[[package]]
name = "windows_i686_msvc"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246"
[[package]]
name = "windows_x86_64_gnu"
version = "0.36.1"
@@ -5827,6 +5930,18 @@ version = "0.39.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6868c165637d653ae1e8dc4d82c25d4f97dd6605eaa8d784b5c6e0ab2a252b65"
[[package]]
name = "windows_x86_64_gnu"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028"
[[package]]
name = "windows_x86_64_msvc"
version = "0.36.1"
@@ -5845,6 +5960,12 @@ version = "0.39.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e4d40883ae9cae962787ca76ba76390ffa29214667a111db9e0a1ad8377e809"
[[package]]
name = "windows_x86_64_msvc"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5"
[[package]]
name = "winreg"
version = "0.7.0"
@@ -11,7 +11,7 @@ anyhow = "1.0"
argon2 = "0.4"
base64 = "0.13"
bip39 = "1.0"
clap = { version = "3.2", features = ["derive"] }
clap = { version = "4.0", features = ["derive"] }
log = "0.4"
pretty_env_logger = "0.4"
serde_json = "1.0.0"
@@ -12,7 +12,7 @@ rust-version = "1.65"
[dependencies]
async-trait = { version = "0.1.51" }
clap = {version = "3.2", features = ["derive"]}
clap = {version = "4.0", features = ["derive"]}
dirs = "4.0"
futures = "0.3.24"
ipnetwork = "0.20.0"
@@ -98,8 +98,8 @@ pub(crate) async fn execute(args: Cli) -> Result<(), NetworkRequesterError> {
match &args.command {
Commands::Run(r) => r.execute().await?,
Commands::Completions(s) => s.generate(&mut crate::Cli::into_app(), bin_name),
Commands::GenerateFigSpec => fig_generate(&mut crate::Cli::into_app(), bin_name),
Commands::Completions(s) => s.generate(&mut crate::Cli::command(), bin_name),
Commands::GenerateFigSpec => fig_generate(&mut crate::Cli::command(), bin_name),
}
Ok(())
}
+3 -3
View File
@@ -7,9 +7,9 @@ edition = "2021"
[dependencies]
base64 = "0.13.0"
bs58 = "0.4"
clap = { version = "3.2", features = ["derive"] }
clap_complete = "3.2"
clap_complete_fig = "3.2"
clap = { version = "4.0", features = ["derive"] }
clap_complete = "4.0"
clap_complete_fig = "4.0"
dotenv = "0.15.0"
log = "0.4"
pretty_env_logger = "0.4"