Compare commits
27 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1060888945 | |||
| 5f4926dd49 | |||
| 1f132a4eaa | |||
| 097d2d51cc | |||
| a2078d997b | |||
| 558d4b899d | |||
| 4fcb98e839 | |||
| 702bb202a3 | |||
| 71ff2c04a0 | |||
| cb30384eaf | |||
| e911c2fbc0 | |||
| bb005a39f5 | |||
| ea72c37083 | |||
| a24dd8b9bc | |||
| b006c01397 | |||
| f7f2a51458 | |||
| 408396c900 | |||
| a97c913bb1 | |||
| dba5a9caef | |||
| 3e39573feb | |||
| ac312e9109 | |||
| 8a2a7dc0ce | |||
| 9684b7ffbd | |||
| 29f48efe49 | |||
| bdc285dbbb | |||
| a02a1b0385 | |||
| a746738d48 |
+1
-1
@@ -14,7 +14,7 @@ GEOIPUPDATE_LICENSE_KEY=xxx
|
||||
# List of space-separated database edition IDs. Edition IDs may
|
||||
# consist of letters, digits, and dashes. For example, GeoIP2-City
|
||||
# would download the GeoIP2 City database (GeoIP2-City).
|
||||
GEOIPUPDATE_EDITION_IDS=GeoLite2-City
|
||||
GEOIPUPDATE_EDITION_IDS=GeoLite2-Country
|
||||
# The number of hours between geoipupdate runs. If this is not set
|
||||
# or is set to 0, geoipupdate will run once and exit.
|
||||
GEOIPUPDATE_FREQUENCY=72
|
||||
|
||||
@@ -13,9 +13,16 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
|
||||
- all-binaries: improved error logging ([#2686])
|
||||
- native client: bring shutdown logic up to the same level as socks5-client
|
||||
- nym-api, coconut-dkg contract: automatic, time-based dkg epoch state advancement ([#2670])
|
||||
- all-binaries: standarised argument names (note: old names should still be accepted) ([#2762]
|
||||
|
||||
### Fixed
|
||||
|
||||
- nym-api: should now correctly use `rewarding.enabled` config flag ([#2753])
|
||||
|
||||
[#2686]: https://github.com/nymtech/nym/pull/2686
|
||||
[#2670]: https://github.com/nymtech/nym/pull/2670
|
||||
[#2753]: https://github.com/nymtech/nym/pull/2753
|
||||
[#2762]: https://github.com/nymtech/nym/pull/2762
|
||||
|
||||
## [v1.1.4] (2022-12-20)
|
||||
|
||||
|
||||
Generated
+146
-94
@@ -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",
|
||||
@@ -1778,6 +1804,9 @@ dependencies = [
|
||||
"network-defaults",
|
||||
"okapi",
|
||||
"pretty_env_logger",
|
||||
"rand 0.8.5",
|
||||
"rand_pcg 0.3.1",
|
||||
"rand_seeder",
|
||||
"reqwest",
|
||||
"rocket",
|
||||
"rocket_cors",
|
||||
@@ -3202,6 +3231,72 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nym-api"
|
||||
version = "1.1.4"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
"bip39",
|
||||
"bs58",
|
||||
"build-information",
|
||||
"cfg-if 1.0.0",
|
||||
"clap 4.0.26",
|
||||
"coconut-bandwidth-contract-common",
|
||||
"coconut-dkg-common",
|
||||
"coconut-interface",
|
||||
"config",
|
||||
"console-subscriber",
|
||||
"contracts-common",
|
||||
"cosmwasm-std",
|
||||
"credential-storage",
|
||||
"credentials",
|
||||
"crypto",
|
||||
"cw-utils",
|
||||
"cw3",
|
||||
"dirs",
|
||||
"dkg",
|
||||
"dotenv",
|
||||
"futures",
|
||||
"gateway-client",
|
||||
"getset",
|
||||
"humantime-serde",
|
||||
"inclusion-probability",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"logging",
|
||||
"mixnet-contract-common",
|
||||
"multisig-contract-common",
|
||||
"nym-api-requests",
|
||||
"nymcoconut",
|
||||
"nymsphinx",
|
||||
"okapi",
|
||||
"pemstore",
|
||||
"pin-project",
|
||||
"pretty_env_logger",
|
||||
"rand 0.7.3",
|
||||
"rand 0.8.5",
|
||||
"reqwest",
|
||||
"rocket",
|
||||
"rocket_cors",
|
||||
"rocket_okapi",
|
||||
"schemars",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sqlx 0.6.2",
|
||||
"tap",
|
||||
"task",
|
||||
"thiserror",
|
||||
"time 0.3.17",
|
||||
"tokio",
|
||||
"tokio-stream",
|
||||
"topology",
|
||||
"ts-rs",
|
||||
"url",
|
||||
"validator-client",
|
||||
"version-checker",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nym-api-requests"
|
||||
version = "0.1.0"
|
||||
@@ -3240,7 +3335,7 @@ dependencies = [
|
||||
"base64",
|
||||
"bip39",
|
||||
"bs58",
|
||||
"clap 3.2.8",
|
||||
"clap 4.0.26",
|
||||
"clap_complete",
|
||||
"clap_complete_fig",
|
||||
"dotenv",
|
||||
@@ -3264,7 +3359,7 @@ dependencies = [
|
||||
"bip39",
|
||||
"bs58",
|
||||
"cfg-if 1.0.0",
|
||||
"clap 3.2.8",
|
||||
"clap 4.0.26",
|
||||
"comfy-table",
|
||||
"cosmrs",
|
||||
"cosmwasm-std",
|
||||
@@ -3290,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",
|
||||
@@ -3303,6 +3399,7 @@ dependencies = [
|
||||
"futures",
|
||||
"gateway-client",
|
||||
"gateway-requests",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"logging",
|
||||
"network-defaults",
|
||||
@@ -3320,7 +3417,6 @@ dependencies = [
|
||||
"topology",
|
||||
"url",
|
||||
"validator-client",
|
||||
"vergen 5.1.17",
|
||||
"version-checker",
|
||||
"websocket-requests",
|
||||
]
|
||||
@@ -3333,7 +3429,8 @@ dependencies = [
|
||||
"async-trait",
|
||||
"bip39",
|
||||
"bs58",
|
||||
"clap 3.2.8",
|
||||
"build-information",
|
||||
"clap 4.0.26",
|
||||
"coconut-interface",
|
||||
"colored",
|
||||
"completions",
|
||||
@@ -3346,6 +3443,7 @@ dependencies = [
|
||||
"futures",
|
||||
"gateway-requests",
|
||||
"humantime-serde",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"logging",
|
||||
"mixnet-client",
|
||||
@@ -3368,7 +3466,6 @@ dependencies = [
|
||||
"tokio-util 0.7.3",
|
||||
"url",
|
||||
"validator-client",
|
||||
"vergen 5.1.17",
|
||||
"version-checker",
|
||||
]
|
||||
|
||||
@@ -3378,7 +3475,8 @@ version = "1.1.4"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bs58",
|
||||
"clap 3.2.8",
|
||||
"build-information",
|
||||
"clap 4.0.26",
|
||||
"colored",
|
||||
"completions",
|
||||
"config",
|
||||
@@ -3410,7 +3508,6 @@ dependencies = [
|
||||
"topology",
|
||||
"url",
|
||||
"validator-client",
|
||||
"vergen 5.1.17",
|
||||
"version-checker",
|
||||
]
|
||||
|
||||
@@ -3419,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",
|
||||
@@ -3482,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",
|
||||
@@ -3495,6 +3593,7 @@ dependencies = [
|
||||
"futures",
|
||||
"gateway-client",
|
||||
"gateway-requests",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"logging",
|
||||
"network-defaults",
|
||||
@@ -3515,7 +3614,6 @@ dependencies = [
|
||||
"topology",
|
||||
"url",
|
||||
"validator-client",
|
||||
"vergen 5.1.17",
|
||||
"version-checker",
|
||||
]
|
||||
|
||||
@@ -3545,70 +3643,6 @@ dependencies = [
|
||||
"vesting-contract-common",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nym-validator-api"
|
||||
version = "1.1.4"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
"bs58",
|
||||
"cfg-if 1.0.0",
|
||||
"clap 3.2.8",
|
||||
"coconut-bandwidth-contract-common",
|
||||
"coconut-dkg-common",
|
||||
"coconut-interface",
|
||||
"config",
|
||||
"console-subscriber",
|
||||
"contracts-common",
|
||||
"cosmwasm-std",
|
||||
"credential-storage",
|
||||
"credentials",
|
||||
"crypto",
|
||||
"cw-utils",
|
||||
"cw3",
|
||||
"dirs",
|
||||
"dkg",
|
||||
"dotenv",
|
||||
"futures",
|
||||
"gateway-client",
|
||||
"getset",
|
||||
"humantime-serde",
|
||||
"inclusion-probability",
|
||||
"log",
|
||||
"logging",
|
||||
"mixnet-contract-common",
|
||||
"multisig-contract-common",
|
||||
"nym-api-requests",
|
||||
"nymcoconut",
|
||||
"nymsphinx",
|
||||
"okapi",
|
||||
"pemstore",
|
||||
"pin-project",
|
||||
"pretty_env_logger",
|
||||
"rand 0.7.3",
|
||||
"rand 0.8.5",
|
||||
"reqwest",
|
||||
"rocket",
|
||||
"rocket_cors",
|
||||
"rocket_okapi",
|
||||
"schemars",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sqlx 0.6.2",
|
||||
"tap",
|
||||
"task",
|
||||
"thiserror",
|
||||
"time 0.3.17",
|
||||
"tokio",
|
||||
"tokio-stream",
|
||||
"topology",
|
||||
"ts-rs",
|
||||
"url",
|
||||
"validator-client",
|
||||
"vergen 7.2.1",
|
||||
"version-checker",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nym-wallet-types"
|
||||
version = "1.0.0"
|
||||
@@ -4390,7 +4424,7 @@ dependencies = [
|
||||
"rand_isaac",
|
||||
"rand_jitter",
|
||||
"rand_os",
|
||||
"rand_pcg",
|
||||
"rand_pcg 0.1.2",
|
||||
"rand_xorshift",
|
||||
"winapi",
|
||||
]
|
||||
@@ -4554,6 +4588,24 @@ dependencies = [
|
||||
"rand_core 0.4.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_pcg"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "59cad018caf63deb318e5a4586d99a24424a364f40f1e5778c29aca23f4fc73e"
|
||||
dependencies = [
|
||||
"rand_core 0.6.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_seeder"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf2890aaef0aa82719a50e808de264f9484b74b442e1a3a0e5ee38243ac40bdb"
|
||||
dependencies = [
|
||||
"rand_core 0.6.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_xorshift"
|
||||
version = "0.1.1"
|
||||
|
||||
@@ -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,6 +1,6 @@
|
||||
[package]
|
||||
name = "client-core"
|
||||
version = "1.1.5"
|
||||
version = "1.1.4"
|
||||
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"]
|
||||
edition = "2021"
|
||||
rust-version = "1.66"
|
||||
|
||||
@@ -230,7 +230,7 @@ where
|
||||
mixnet_message_sender: MixnetMessageSender,
|
||||
ack_sender: AcknowledgementSender,
|
||||
shutdown: TaskClient,
|
||||
) -> Result<GatewayClient, ClientCoreError<B>> {
|
||||
) -> Result<GatewayClient, ClientCoreError> {
|
||||
let gateway_id = self.gateway_config.gateway_id.clone();
|
||||
if gateway_id.is_empty() {
|
||||
return Err(ClientCoreError::GatewayIdUnknown);
|
||||
@@ -285,7 +285,7 @@ where
|
||||
refresh_rate: Duration,
|
||||
topology_accessor: TopologyAccessor,
|
||||
shutdown: TaskClient,
|
||||
) -> Result<(), ClientCoreError<B>> {
|
||||
) -> Result<(), ClientCoreError> {
|
||||
let topology_refresher_config = TopologyRefresherConfig::new(
|
||||
nym_api_urls,
|
||||
refresh_rate,
|
||||
@@ -328,12 +328,17 @@ where
|
||||
async fn setup_persistent_reply_storage(
|
||||
backend: B,
|
||||
shutdown: TaskClient,
|
||||
) -> Result<CombinedReplyStorage, ClientCoreError<B>> {
|
||||
) -> Result<CombinedReplyStorage, ClientCoreError>
|
||||
where
|
||||
<B as ReplyStorageBackend>::StorageError: Sync + Send,
|
||||
{
|
||||
let persistent_storage = PersistentReplyStorage::new(backend);
|
||||
let mem_store = persistent_storage
|
||||
.load_state_from_backend()
|
||||
.await
|
||||
.map_err(|err| ClientCoreError::SurbStorageError { source: err })?;
|
||||
.map_err(|err| ClientCoreError::SurbStorageError {
|
||||
source: Box::new(err),
|
||||
})?;
|
||||
|
||||
let store_clone = mem_store.clone();
|
||||
spawn_future(async move {
|
||||
@@ -345,7 +350,10 @@ where
|
||||
Ok(mem_store)
|
||||
}
|
||||
|
||||
pub async fn start_base(mut self) -> Result<BaseClient, ClientCoreError<B>> {
|
||||
pub async fn start_base(mut self) -> Result<BaseClient, ClientCoreError>
|
||||
where
|
||||
<B as ReplyStorageBackend>::StorageError: Sync + Send,
|
||||
{
|
||||
info!("Starting nym client");
|
||||
// channels for inter-component communication
|
||||
// TODO: make the channels be internally created by the relevant components
|
||||
|
||||
@@ -14,13 +14,15 @@ use time::OffsetDateTime;
|
||||
async fn setup_fresh_backend<P: AsRef<Path>>(
|
||||
db_path: P,
|
||||
debug_config: &DebugConfig,
|
||||
) -> Result<fs_backend::Backend, ClientCoreError<fs_backend::Backend>> {
|
||||
) -> Result<fs_backend::Backend, ClientCoreError> {
|
||||
info!("creating fresh surb database");
|
||||
let mut storage_backend = match fs_backend::Backend::init(db_path).await {
|
||||
Ok(backend) => backend,
|
||||
Err(err) => {
|
||||
error!("failed to setup persistent storage backend for our reply needs: {err}");
|
||||
return Err(ClientCoreError::SurbStorageError { source: err });
|
||||
return Err(ClientCoreError::SurbStorageError {
|
||||
source: Box::new(err),
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -34,7 +36,9 @@ async fn setup_fresh_backend<P: AsRef<Path>>(
|
||||
storage_backend
|
||||
.init_fresh(&mem_store)
|
||||
.await
|
||||
.map_err(|err| ClientCoreError::SurbStorageError { source: err })?;
|
||||
.map_err(|err| ClientCoreError::SurbStorageError {
|
||||
source: Box::new(err),
|
||||
})?;
|
||||
|
||||
Ok(storage_backend)
|
||||
}
|
||||
@@ -63,7 +67,7 @@ fn archive_corrupted_database<P: AsRef<Path>>(db_path: P) -> io::Result<()> {
|
||||
pub async fn setup_fs_reply_surb_backend<P: AsRef<Path>>(
|
||||
db_path: P,
|
||||
debug_config: &DebugConfig,
|
||||
) -> Result<fs_backend::Backend, ClientCoreError<fs_backend::Backend>> {
|
||||
) -> Result<fs_backend::Backend, ClientCoreError> {
|
||||
// if the database file doesnt exist, initialise fresh storage, otherwise attempt to load the existing one
|
||||
let db_path = db_path.as_ref();
|
||||
if db_path.exists() {
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::client::replies::reply_storage::ReplyStorageBackend;
|
||||
use crypto::asymmetric::identity::Ed25519RecoveryError;
|
||||
use gateway_client::error::GatewayClientError;
|
||||
use topology::NymTopologyError;
|
||||
use validator_client::ValidatorClientError;
|
||||
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
pub enum ClientCoreError<B: ReplyStorageBackend> {
|
||||
pub enum ClientCoreError {
|
||||
#[error("I/O error: {0}")]
|
||||
IoError(#[from] std::io::Error),
|
||||
|
||||
@@ -40,7 +39,9 @@ pub enum ClientCoreError<B: ReplyStorageBackend> {
|
||||
InsufficientNetworkTopology(#[from] NymTopologyError),
|
||||
|
||||
#[error("experienced a failure with our reply surb persistent storage: {source}")]
|
||||
SurbStorageError { source: B::StorageError },
|
||||
SurbStorageError {
|
||||
source: Box<dyn std::error::Error + Send + Sync>,
|
||||
},
|
||||
|
||||
#[error("The gateway id is invalid - {0}")]
|
||||
UnableToCreatePublicKeyFromGatewayId(Ed25519RecoveryError),
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::client::replies::reply_storage::ReplyStorageBackend;
|
||||
use crate::{
|
||||
client::key_manager::KeyManager,
|
||||
config::{persistence::key_pathfinder::ClientKeyPathfinder, Config},
|
||||
@@ -17,13 +16,10 @@ use tap::TapFallible;
|
||||
use topology::{filter::VersionFilterable, gateway};
|
||||
use url::Url;
|
||||
|
||||
pub(super) async fn query_gateway_details<B>(
|
||||
pub(super) async fn query_gateway_details(
|
||||
validator_servers: Vec<Url>,
|
||||
chosen_gateway_id: Option<String>,
|
||||
) -> Result<gateway::Node, ClientCoreError<B>>
|
||||
where
|
||||
B: ReplyStorageBackend,
|
||||
{
|
||||
) -> Result<gateway::Node, ClientCoreError> {
|
||||
let nym_api = validator_servers
|
||||
.choose(&mut thread_rng())
|
||||
.ok_or(ClientCoreError::ListOfNymApisIsEmpty)?;
|
||||
@@ -55,13 +51,10 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
async fn register_with_gateway<B>(
|
||||
async fn register_with_gateway(
|
||||
gateway: &gateway::Node,
|
||||
our_identity: Arc<identity::KeyPair>,
|
||||
) -> Result<Arc<SharedKeys>, ClientCoreError<B>>
|
||||
where
|
||||
B: ReplyStorageBackend,
|
||||
{
|
||||
) -> Result<Arc<SharedKeys>, ClientCoreError> {
|
||||
let timeout = Duration::from_millis(1500);
|
||||
let mut gateway_client = GatewayClient::new_init(
|
||||
gateway.clients_address(),
|
||||
@@ -81,13 +74,12 @@ where
|
||||
Ok(shared_keys)
|
||||
}
|
||||
|
||||
pub(super) async fn register_with_gateway_and_store_keys<T, B>(
|
||||
pub(super) async fn register_with_gateway_and_store_keys<T>(
|
||||
gateway_details: gateway::Node,
|
||||
config: &Config<T>,
|
||||
) -> Result<(), ClientCoreError<B>>
|
||||
) -> Result<(), ClientCoreError>
|
||||
where
|
||||
T: NymConfig,
|
||||
B: ReplyStorageBackend,
|
||||
{
|
||||
let mut rng = OsRng;
|
||||
let mut key_manager = KeyManager::new(&mut rng);
|
||||
|
||||
@@ -12,7 +12,6 @@ use tap::TapFallible;
|
||||
use config::NymConfig;
|
||||
use crypto::asymmetric::{encryption, identity};
|
||||
|
||||
use crate::client::replies::reply_storage::ReplyStorageBackend;
|
||||
use crate::{
|
||||
config::{
|
||||
persistence::key_pathfinder::ClientKeyPathfinder, ClientCoreConfigTrait, Config,
|
||||
@@ -63,13 +62,13 @@ impl Display for InitResults {
|
||||
|
||||
/// Convenience function for setting up the gateway for a client. Depending on the arguments given
|
||||
/// it will do the sensible thing.
|
||||
pub async fn setup_gateway<B, C, T>(
|
||||
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<B>>
|
||||
) -> Result<GatewayEndpointConfig, ClientCoreError>
|
||||
where
|
||||
B: ReplyStorageBackend,
|
||||
C: NymConfig + ClientCoreConfigTrait,
|
||||
T: NymConfig,
|
||||
{
|
||||
@@ -79,19 +78,18 @@ where
|
||||
} else if let Some(user_chosen_gateway_id) = user_chosen_gateway_id {
|
||||
config_gateway_with_existing_keys(user_chosen_gateway_id, config).await
|
||||
} else {
|
||||
reuse_existing_gateway_config::<B, C>(&id)
|
||||
reuse_existing_gateway_config::<C>(&id)
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the gateway details by querying the validator-api. Either pick one at random or use
|
||||
/// the chosen one if it's among the available ones.
|
||||
/// Saves keys to disk, specified by the paths in `config`.
|
||||
pub async fn register_with_gateway<B, T>(
|
||||
pub async fn register_with_gateway<T>(
|
||||
user_chosen_gateway_id: Option<String>,
|
||||
config: &Config<T>,
|
||||
) -> Result<GatewayEndpointConfig, ClientCoreError<B>>
|
||||
) -> Result<GatewayEndpointConfig, ClientCoreError>
|
||||
where
|
||||
B: ReplyStorageBackend,
|
||||
T: NymConfig,
|
||||
{
|
||||
println!("Configuring gateway");
|
||||
@@ -111,12 +109,11 @@ where
|
||||
/// create any keys.
|
||||
/// This assumes that the user knows what they are doing, and that the existing keys are valid for
|
||||
/// the gateway being used
|
||||
pub async fn config_gateway_with_existing_keys<B, T>(
|
||||
pub async fn config_gateway_with_existing_keys<T>(
|
||||
user_chosen_gateway_id: String,
|
||||
config: &Config<T>,
|
||||
) -> Result<GatewayEndpointConfig, ClientCoreError<B>>
|
||||
) -> Result<GatewayEndpointConfig, ClientCoreError>
|
||||
where
|
||||
B: ReplyStorageBackend,
|
||||
T: NymConfig,
|
||||
{
|
||||
println!("Using gateway provided by user, keeping existing keys");
|
||||
@@ -127,11 +124,8 @@ where
|
||||
}
|
||||
|
||||
/// Read and reuse the existing gateway configuration from a file that was generate earlier.
|
||||
pub fn reuse_existing_gateway_config<B, T>(
|
||||
id: &str,
|
||||
) -> Result<GatewayEndpointConfig, ClientCoreError<B>>
|
||||
pub fn reuse_existing_gateway_config<T>(id: &str) -> Result<GatewayEndpointConfig, ClientCoreError>
|
||||
where
|
||||
B: ReplyStorageBackend,
|
||||
T: NymConfig + ClientCoreConfigTrait,
|
||||
{
|
||||
println!("Not registering gateway, will reuse existing config and keys");
|
||||
@@ -150,19 +144,15 @@ where
|
||||
}
|
||||
|
||||
/// Get the client address by loading the keys from stored files.
|
||||
pub fn get_client_address_from_stored_keys<B, T>(
|
||||
pub fn get_client_address_from_stored_keys<T>(
|
||||
config: &Config<T>,
|
||||
) -> Result<Recipient, ClientCoreError<B>>
|
||||
) -> Result<Recipient, ClientCoreError>
|
||||
where
|
||||
T: config::NymConfig,
|
||||
B: ReplyStorageBackend,
|
||||
{
|
||||
fn load_identity_keys<B>(
|
||||
fn load_identity_keys(
|
||||
pathfinder: &ClientKeyPathfinder,
|
||||
) -> Result<identity::KeyPair, ClientCoreError<B>>
|
||||
where
|
||||
B: ReplyStorageBackend,
|
||||
{
|
||||
) -> Result<identity::KeyPair, ClientCoreError> {
|
||||
let identity_keypair: identity::KeyPair =
|
||||
pemstore::load_keypair(&pemstore::KeyPairPath::new(
|
||||
pathfinder.private_identity_key().to_owned(),
|
||||
@@ -172,12 +162,9 @@ where
|
||||
Ok(identity_keypair)
|
||||
}
|
||||
|
||||
fn load_sphinx_keys<B>(
|
||||
fn load_sphinx_keys(
|
||||
pathfinder: &ClientKeyPathfinder,
|
||||
) -> Result<encryption::KeyPair, ClientCoreError<B>>
|
||||
where
|
||||
B: ReplyStorageBackend,
|
||||
{
|
||||
) -> Result<encryption::KeyPair, ClientCoreError> {
|
||||
let sphinx_keypair: encryption::KeyPair =
|
||||
pemstore::load_keypair(&pemstore::KeyPairPath::new(
|
||||
pathfinder.private_encryption_key().to_owned(),
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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(())
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "nym-client"
|
||||
version = "1.1.5"
|
||||
version = "1.1.4"
|
||||
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jędrzej Stuczyński <andrew@nymtech.net>"]
|
||||
description = "Implementation of the Nym Client"
|
||||
edition = "2021"
|
||||
@@ -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"] }
|
||||
|
||||
+400
-256
File diff suppressed because it is too large
Load Diff
@@ -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,12 +30,14 @@ pub(crate) struct Init {
|
||||
force_register_gateway: bool,
|
||||
|
||||
/// Comma separated list of rest endpoints of the nymd validators
|
||||
#[clap(long)]
|
||||
nymd_validators: Option<String>,
|
||||
#[cfg(feature = "coconut")]
|
||||
#[clap(long, value_delimiter = ',')]
|
||||
nymd_validators: Option<Vec<url::Url>>,
|
||||
|
||||
/// Comma separated list of rest endpoints of the API validators
|
||||
#[clap(long)]
|
||||
api_validators: Option<String>,
|
||||
#[clap(long, alias = "api_validators", value_delimiter = ',')]
|
||||
// the alias here is included for backwards compatibility (1.1.4 and before)
|
||||
nym_apis: Option<Vec<url::Url>>,
|
||||
|
||||
/// Whether to not start the websocket
|
||||
#[clap(long)]
|
||||
@@ -46,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
|
||||
@@ -67,13 +70,14 @@ pub(crate) struct Init {
|
||||
impl From<Init> for OverrideConfig {
|
||||
fn from(init_config: Init) -> Self {
|
||||
OverrideConfig {
|
||||
nymd_validators: init_config.nymd_validators,
|
||||
api_validators: init_config.api_validators,
|
||||
nym_apis: init_config.nym_apis,
|
||||
disable_socket: init_config.disable_socket,
|
||||
port: init_config.port,
|
||||
fastmode: init_config.fastmode,
|
||||
no_cover: init_config.no_cover,
|
||||
|
||||
#[cfg(feature = "coconut")]
|
||||
nymd_validators: init_config.nymd_validators,
|
||||
#[cfg(feature = "coconut")]
|
||||
enabled_credentials_mode: init_config.enabled_credentials_mode,
|
||||
}
|
||||
@@ -127,16 +131,16 @@ 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()));
|
||||
|
||||
// Setup gateway by either registering a new one, or creating a new config from the selected
|
||||
// one but with keys kept, or reusing the gateway configuration.
|
||||
let gateway = client_core::init::setup_gateway::<_, Config, _>(
|
||||
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
|
||||
@@ -152,14 +156,14 @@ pub(crate) async fn execute(args: &Init) -> Result<(), ClientError> {
|
||||
|
||||
let address = client_core::init::get_client_address_from_stored_keys(config.get_base())?;
|
||||
let init_results = InitResults::new(&config, &address);
|
||||
println!("{}", init_results);
|
||||
println!("{init_results}");
|
||||
|
||||
// Output summary to a json file, if specified
|
||||
if args.output_json {
|
||||
client_core::init::output_to_json(&init_results, "client_init_results.json");
|
||||
}
|
||||
|
||||
println!("\nThe address of this client is: {}\n", address);
|
||||
println!("\nThe address of this client is: {address}\n");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@@ -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,13 +52,14 @@ pub(crate) enum Commands {
|
||||
|
||||
// Configuration that can be overridden.
|
||||
pub(crate) struct OverrideConfig {
|
||||
nymd_validators: Option<String>,
|
||||
api_validators: 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<Vec<url::Url>>,
|
||||
#[cfg(feature = "coconut")]
|
||||
enabled_credentials_mode: bool,
|
||||
}
|
||||
@@ -94,34 +71,21 @@ 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.nymd_validators {
|
||||
config
|
||||
.get_base_mut()
|
||||
.set_custom_validators(config::parse_validators(&raw_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");
|
||||
config
|
||||
.get_base_mut()
|
||||
.set_custom_validators(config::parse_validators(&raw_validators));
|
||||
}
|
||||
if let Some(raw_validators) = args.api_validators {
|
||||
config
|
||||
.get_base_mut()
|
||||
.set_custom_nym_apis(config::parse_validators(&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");
|
||||
config
|
||||
.get_base_mut()
|
||||
.set_custom_nym_apis(config::parse_validators(&raw_validators));
|
||||
.set_custom_nym_apis(config::parse_urls(&raw_validators));
|
||||
}
|
||||
|
||||
if args.disable_socket {
|
||||
@@ -134,6 +98,15 @@ pub(crate) fn override_config(mut config: Config, args: OverrideConfig) -> Confi
|
||||
|
||||
#[cfg(feature = "coconut")]
|
||||
{
|
||||
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");
|
||||
config
|
||||
.get_base_mut()
|
||||
.set_custom_validators(config::parse_urls(&raw_validators));
|
||||
}
|
||||
if args.enabled_credentials_mode {
|
||||
config.get_base_mut().with_disabled_credentials(false)
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// 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;
|
||||
@@ -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,17 +22,19 @@ pub(crate) struct Run {
|
||||
id: String,
|
||||
|
||||
/// Comma separated list of rest endpoints of the nymd validators
|
||||
#[clap(long)]
|
||||
nymd_validators: Option<String>,
|
||||
#[cfg(feature = "coconut")]
|
||||
#[clap(long, value_delimiter = ',')]
|
||||
nymd_validators: Option<Vec<url::Url>>,
|
||||
|
||||
/// Comma separated list of rest endpoints of the API validators
|
||||
#[clap(long)]
|
||||
api_validators: Option<String>,
|
||||
#[clap(long, alias = "api_validators", value_delimiter = ',')]
|
||||
// the alias here is included for backwards compatibility (1.1.4 and before)
|
||||
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)]
|
||||
@@ -43,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
|
||||
@@ -60,12 +63,14 @@ pub(crate) struct Run {
|
||||
impl From<Run> for OverrideConfig {
|
||||
fn from(run_config: Run) -> Self {
|
||||
OverrideConfig {
|
||||
nymd_validators: run_config.nymd_validators,
|
||||
api_validators: run_config.api_validators,
|
||||
nym_apis: run_config.nym_apis,
|
||||
disable_socket: run_config.disable_socket,
|
||||
port: run_config.port,
|
||||
fastmode: run_config.fastmode,
|
||||
no_cover: run_config.no_cover,
|
||||
|
||||
#[cfg(feature = "coconut")]
|
||||
nymd_validators: run_config.nymd_validators,
|
||||
#[cfg(feature = "coconut")]
|
||||
enabled_credentials_mode: run_config.enabled_credentials_mode,
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
use client_core::client::replies::reply_storage::fs_backend;
|
||||
use client_core::error::ClientCoreError;
|
||||
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
@@ -7,7 +6,7 @@ pub enum ClientError {
|
||||
IoError(#[from] std::io::Error),
|
||||
|
||||
#[error("client-core error: {0}")]
|
||||
ClientCoreError(#[from] ClientCoreError<fs_backend::Backend>),
|
||||
ClientCoreError(#[from] ClientCoreError),
|
||||
|
||||
#[error("Failed to load config for: {0}")]
|
||||
FailedToLoadConfig(String),
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "nym-socks5-client"
|
||||
version = "1.1.5"
|
||||
version = "1.1.4"
|
||||
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"]
|
||||
description = "A SOCKS5 localhost proxy that converts incoming messages to Sphinx and sends them to a Nym address"
|
||||
edition = "2021"
|
||||
@@ -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"] }
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
@@ -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,19 +22,20 @@ 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
|
||||
/// slower and consume nearly double the bandwidth as it will require sending reply SURBs.
|
||||
///
|
||||
/// Note that some service providers might not support this.
|
||||
#[clap(long)]
|
||||
use_anonymous_sender_tag: bool,
|
||||
// the alias here is included for backwards compatibility (1.1.4 and before)
|
||||
#[clap(long, alias = "use_anonymous_sender_tag")]
|
||||
use_reply_surbs: bool,
|
||||
|
||||
/// 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.
|
||||
@@ -41,12 +43,14 @@ pub(crate) struct Init {
|
||||
force_register_gateway: bool,
|
||||
|
||||
/// Comma separated list of rest endpoints of the nymd validators
|
||||
#[clap(long)]
|
||||
nymd_validators: Option<String>,
|
||||
#[cfg(feature = "coconut")]
|
||||
#[clap(long, value_delimiter = ',')]
|
||||
nymd_validators: Option<Vec<url::Url>>,
|
||||
|
||||
/// Comma separated list of rest endpoints of the API validators
|
||||
#[clap(long)]
|
||||
api_validators: Option<String>,
|
||||
#[clap(long, alias = "api_validators", value_delimiter = ',')]
|
||||
// the alias here is included for backwards compatibility (1.1.4 and before)
|
||||
nym_apis: Option<Vec<url::Url>>,
|
||||
|
||||
/// Port for the socket to listen on in all subsequent runs
|
||||
#[clap(short, long)]
|
||||
@@ -54,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
|
||||
@@ -75,12 +79,14 @@ pub(crate) struct Init {
|
||||
impl From<Init> for OverrideConfig {
|
||||
fn from(init_config: Init) -> Self {
|
||||
OverrideConfig {
|
||||
nymd_validators: init_config.nymd_validators,
|
||||
api_validators: init_config.api_validators,
|
||||
nym_apis: init_config.nym_apis,
|
||||
port: init_config.port,
|
||||
use_anonymous_sender_tag: init_config.use_anonymous_sender_tag,
|
||||
use_anonymous_replies: init_config.use_reply_surbs,
|
||||
fastmode: init_config.fastmode,
|
||||
no_cover: init_config.no_cover,
|
||||
|
||||
#[cfg(feature = "coconut")]
|
||||
nymd_validators: init_config.nymd_validators,
|
||||
#[cfg(feature = "coconut")]
|
||||
enabled_credentials_mode: init_config.enabled_credentials_mode,
|
||||
}
|
||||
@@ -135,19 +141,19 @@ 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()),
|
||||
);
|
||||
|
||||
// Setup gateway by either registering a new one, or creating a new config from the selected
|
||||
// one but with keys kept, or reusing the gateway configuration.
|
||||
let gateway = client_core::init::setup_gateway::<_, Config, _>(
|
||||
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
|
||||
|
||||
@@ -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_validators;
|
||||
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,13 +55,14 @@ pub(crate) enum Commands {
|
||||
|
||||
// Configuration that can be overridden.
|
||||
pub(crate) struct OverrideConfig {
|
||||
nymd_validators: Option<String>,
|
||||
api_validators: Option<String>,
|
||||
nym_apis: Option<Vec<url::Url>>,
|
||||
port: Option<u16>,
|
||||
use_anonymous_sender_tag: bool,
|
||||
use_anonymous_replies: bool,
|
||||
fastmode: bool,
|
||||
no_cover: bool,
|
||||
|
||||
#[cfg(feature = "coconut")]
|
||||
nymd_validators: Option<Vec<url::Url>>,
|
||||
#[cfg(feature = "coconut")]
|
||||
enabled_credentials_mode: bool,
|
||||
}
|
||||
@@ -97,33 +74,22 @@ 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.nymd_validators {
|
||||
config
|
||||
.get_base_mut()
|
||||
.set_custom_validators(parse_validators(&raw_validators));
|
||||
} else if let Ok(raw_validators) = std::env::var(network_defaults::var_names::NYMD_VALIDATOR) {
|
||||
config
|
||||
.get_base_mut()
|
||||
.set_custom_validators(parse_validators(&raw_validators));
|
||||
}
|
||||
if let Some(raw_validators) = args.api_validators {
|
||||
config
|
||||
.get_base_mut()
|
||||
.set_custom_nym_apis(parse_validators(&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()
|
||||
.set_custom_nym_apis(parse_validators(&raw_validators));
|
||||
.set_custom_nym_apis(parse_urls(&raw_validators));
|
||||
}
|
||||
|
||||
if args.use_anonymous_sender_tag {
|
||||
if args.use_anonymous_replies {
|
||||
config = config.with_anonymous_replies(true)
|
||||
}
|
||||
|
||||
@@ -133,6 +99,15 @@ pub(crate) fn override_config(mut config: Config, args: OverrideConfig) -> Confi
|
||||
|
||||
#[cfg(feature = "coconut")]
|
||||
{
|
||||
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)
|
||||
{
|
||||
config
|
||||
.get_base_mut()
|
||||
.set_custom_validators(parse_urls(&raw_validators));
|
||||
}
|
||||
if args.enabled_credentials_mode {
|
||||
config.get_base_mut().with_disabled_credentials(false)
|
||||
}
|
||||
|
||||
@@ -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)]
|
||||
@@ -27,25 +29,27 @@ pub(crate) struct Run {
|
||||
/// slower and consume nearly double the bandwidth as it will require sending reply SURBs.
|
||||
///
|
||||
/// Note that some service providers might not support this.
|
||||
#[clap(long)]
|
||||
use_anonymous_sender_tag: bool,
|
||||
// the alias here is included for backwards compatibility (1.1.4 and before)
|
||||
#[clap(long, alias = "use_anonymous_sender_tag")]
|
||||
use_anonymous_replies: bool,
|
||||
|
||||
/// 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
|
||||
#[clap(long)]
|
||||
nymd_validators: Option<String>,
|
||||
#[cfg(feature = "coconut")]
|
||||
#[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)]
|
||||
@@ -53,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
|
||||
@@ -70,12 +74,14 @@ pub(crate) struct Run {
|
||||
impl From<Run> for OverrideConfig {
|
||||
fn from(run_config: Run) -> Self {
|
||||
OverrideConfig {
|
||||
nymd_validators: run_config.nymd_validators,
|
||||
api_validators: run_config.nym_apis,
|
||||
nym_apis: run_config.nym_apis,
|
||||
port: run_config.port,
|
||||
use_anonymous_sender_tag: run_config.use_anonymous_sender_tag,
|
||||
use_anonymous_replies: run_config.use_anonymous_replies,
|
||||
fastmode: run_config.fastmode,
|
||||
no_cover: run_config.no_cover,
|
||||
|
||||
#[cfg(feature = "coconut")]
|
||||
nymd_validators: run_config.nymd_validators,
|
||||
#[cfg(feature = "coconut")]
|
||||
enabled_credentials_mode: run_config.enabled_credentials_mode,
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
use crate::socks::types::SocksProxyError;
|
||||
use client_core::client::replies::reply_storage::fs_backend;
|
||||
use client_core::error::ClientCoreError;
|
||||
use socks5_requests::ConnectionId;
|
||||
|
||||
@@ -9,7 +8,7 @@ pub enum Socks5ClientError {
|
||||
IoError(#[from] std::io::Error),
|
||||
|
||||
#[error("client-core error: {0}")]
|
||||
ClientCoreError(#[from] ClientCoreError<fs_backend::Backend>),
|
||||
ClientCoreError(#[from] ClientCoreError),
|
||||
|
||||
#[error("SOCKS proxy error")]
|
||||
SocksProxyError(SocksProxyError),
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
+434
-166
File diff suppressed because it is too large
Load Diff
@@ -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};
|
||||
@@ -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,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -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"] }
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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"
|
||||
@@ -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,
|
||||
}
|
||||
|
||||
|
||||
@@ -118,13 +118,14 @@ pub trait NymConfig: Default + Serialize + DeserializeOwned {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_validators(raw: &str) -> Vec<url::Url> {
|
||||
// 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_validator| {
|
||||
raw_validator
|
||||
.map(|raw_url| {
|
||||
raw_url
|
||||
.trim()
|
||||
.parse()
|
||||
.expect("one of the provided validator api urls is invalid")
|
||||
.expect("one of the provided nym api urls is invalid")
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
@@ -56,7 +56,6 @@ impl Family {
|
||||
self.proxy.as_ref()
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn label(&self) -> &str {
|
||||
&self.label
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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::*;
|
||||
|
||||
+1647
-1180
File diff suppressed because it is too large
Load Diff
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"devDependencies": {
|
||||
"@nomiclabs/hardhat-ethers": "^2.0.5",
|
||||
"@nomiclabs/hardhat-etherscan": "^3.0.3",
|
||||
"@nomiclabs/hardhat-etherscan": "^3.1.0",
|
||||
"@nomiclabs/hardhat-waffle": "^2.0.3",
|
||||
"chai": "^4.3.6",
|
||||
"ethereum-waffle": "^3.4.4",
|
||||
"ethers": "^5.6.1",
|
||||
"hardhat": "^2.9.2",
|
||||
"hardhat": "^2.11.2",
|
||||
"solidity-coverage": "^0.7.20"
|
||||
},
|
||||
"dependencies": {
|
||||
|
||||
+65
-1522
File diff suppressed because it is too large
Load Diff
@@ -16,7 +16,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/node": "^14.14.22",
|
||||
"nodemon": "^2.0.7",
|
||||
"nodemon": "^2.0.20",
|
||||
"@nymproject/nym-validator-client" : "0.18.0",
|
||||
"save-dev": "0.0.1-security",
|
||||
"tasktimer": "^3.0.0",
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
# The path to the geoip database file
|
||||
GEOIP_DB_PATH=./geo_ip/GeoLite2-City.mmdb
|
||||
GEOIP_DB_PATH=./geo_ip/GeoLite2-Country.mmdb
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
[package]
|
||||
name = "explorer-api"
|
||||
version = "1.1.2"
|
||||
version = "1.1.1"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[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"
|
||||
@@ -25,6 +25,9 @@ thiserror = "1.0.29"
|
||||
tokio = {version = "1.21.2", features = ["full"] }
|
||||
maxminddb = "0.23.0"
|
||||
dotenv = "0.15.0"
|
||||
rand = "0.8.5"
|
||||
rand_seeder = "0.2.3"
|
||||
rand_pcg = "0.3.1"
|
||||
|
||||
mixnet-contract-common = { path = "../common/cosmwasm-smart-contracts/mixnet-contract" }
|
||||
contracts-common = { path = "../common/cosmwasm-smart-contracts/contracts-common" }
|
||||
|
||||
@@ -40,7 +40,7 @@ It should be previously installed thanks to `geoipupdate` service.
|
||||
For example:
|
||||
|
||||
```shell
|
||||
GEOIP_DB_PATH=./geo_ip/GeoLite2-City.mmdb cargo run
|
||||
GEOIP_DB_PATH=./geo_ip/GeoLite2-Country.mmdb cargo run
|
||||
```
|
||||
|
||||
Note: explorer-api binary reads the provided `.env` file.
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::geo_ip::location::Location;
|
||||
use crate::state::ExplorerApiStateContext;
|
||||
use rocket::response::status;
|
||||
use rocket::serde::json::Json;
|
||||
use rocket::{Route, State};
|
||||
use rocket_okapi::okapi::openapi3::OpenApi;
|
||||
use rocket_okapi::settings::OpenApiSettings;
|
||||
|
||||
pub fn nym_terms_make_default_routes(settings: &OpenApiSettings) -> (Vec<Route>, OpenApi) {
|
||||
openapi_get_routes_spec![settings: terms]
|
||||
}
|
||||
|
||||
#[openapi(tag = "terms")]
|
||||
#[get("/")]
|
||||
pub(crate) async fn terms(
|
||||
_state: &State<ExplorerApiStateContext>,
|
||||
location: Location,
|
||||
) -> Result<Json<String>, status::Forbidden<String>> {
|
||||
if location.iso_alpha2 == "US" {
|
||||
return Err(status::Forbidden(Some("US government sucks".to_string())));
|
||||
}
|
||||
Ok(Json("Nym Terms & Conditions: Welcome".to_string()))
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
pub(crate) mod http;
|
||||
@@ -3,14 +3,14 @@
|
||||
|
||||
use isocountry::CountryCode;
|
||||
use log::warn;
|
||||
use maxminddb::{geoip2::City, MaxMindDBError, Reader};
|
||||
use maxminddb::{geoip2::Country, MaxMindDBError, Reader};
|
||||
use std::{
|
||||
net::{IpAddr, ToSocketAddrs},
|
||||
str::FromStr,
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
const DEFAULT_DATABASE_PATH: &str = "./geo_ip/GeoLite2-City.mmdb";
|
||||
const DEFAULT_DATABASE_PATH: &str = "./geo_ip/GeoLite2-Country.mmdb";
|
||||
const FAKE_PORT: u16 = 1234;
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -38,8 +38,6 @@ pub(crate) struct Location {
|
||||
pub(crate) iso_alpha3: String,
|
||||
/// English country short name (ISO 3166-1)
|
||||
pub(crate) name: String,
|
||||
pub(crate) latitude: Option<f64>,
|
||||
pub(crate) longitude: Option<f64>,
|
||||
}
|
||||
|
||||
impl GeoIp {
|
||||
@@ -88,7 +86,7 @@ impl GeoIp {
|
||||
error!("No registered GeoIP database");
|
||||
GeoIpError::InternalError
|
||||
})?
|
||||
.lookup::<City>(ip);
|
||||
.lookup::<Country>(ip);
|
||||
match &result {
|
||||
Ok(v) => Ok(Some(
|
||||
Location::try_from(v).map_err(|_| GeoIpError::InternalError)?,
|
||||
@@ -101,11 +99,11 @@ impl GeoIp {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> TryFrom<&City<'a>> for Location {
|
||||
impl<'a> TryFrom<&Country<'a>> for Location {
|
||||
type Error = String;
|
||||
|
||||
fn try_from(city: &City) -> Result<Self, Self::Error> {
|
||||
let data = city.country.as_ref().ok_or_else(|| {
|
||||
fn try_from(country: &Country) -> Result<Self, Self::Error> {
|
||||
let data = country.country.as_ref().ok_or_else(|| {
|
||||
warn!("No Country data found");
|
||||
"No Country data found"
|
||||
})?;
|
||||
@@ -121,13 +119,10 @@ impl<'a> TryFrom<&City<'a>> for Location {
|
||||
warn!("{}", &message);
|
||||
message
|
||||
})?;
|
||||
|
||||
Ok(Location {
|
||||
iso_alpha2,
|
||||
iso_alpha3: String::from(iso_codes.alpha3()),
|
||||
name: String::from(iso_codes.name()),
|
||||
latitude: city.location.as_ref().and_then(|l| l.latitude),
|
||||
longitude: city.location.as_ref().and_then(|l| l.longitude),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ use rocket::{Build, Request, Rocket};
|
||||
use rocket_cors::{AllowedHeaders, AllowedOrigins};
|
||||
use rocket_okapi::swagger_ui::make_swagger_ui;
|
||||
|
||||
use crate::buy_terms::http::nym_terms_make_default_routes;
|
||||
use crate::country_statistics::http::country_statistics_make_default_routes;
|
||||
use crate::gateways::http::gateways_make_default_routes;
|
||||
use crate::http::swagger::get_docs;
|
||||
@@ -56,6 +57,7 @@ fn configure_rocket(state: ExplorerApiStateContext) -> Rocket<Build> {
|
||||
"/overview" => overview_make_default_routes(&openapi_settings),
|
||||
"/ping" => ping_make_default_routes(&openapi_settings),
|
||||
"/validators" => validators_make_default_routes(&openapi_settings),
|
||||
"/terms" => nym_terms_make_default_routes(&openapi_settings),
|
||||
};
|
||||
|
||||
building_rocket
|
||||
|
||||
@@ -8,8 +8,9 @@ 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;
|
||||
mod client;
|
||||
pub(crate) mod commands;
|
||||
@@ -34,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;
|
||||
}
|
||||
@@ -87,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");
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@ pub(crate) struct PrettyDetailedMixNodeBond {
|
||||
pub estimated_delegators_apy: f64,
|
||||
pub operating_cost: Coin,
|
||||
pub profit_margin_percent: Percent,
|
||||
pub family_id: Option<u16>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, JsonSchema)]
|
||||
|
||||
@@ -36,8 +36,6 @@ pub(crate) struct Location {
|
||||
pub(crate) two_letter_iso_country_code: String,
|
||||
pub(crate) three_letter_iso_country_code: String,
|
||||
pub(crate) country_name: String,
|
||||
pub(crate) latitude: Option<f64>,
|
||||
pub(crate) longitude: Option<f64>,
|
||||
}
|
||||
|
||||
impl Location {
|
||||
@@ -46,8 +44,6 @@ impl Location {
|
||||
country_name: location.name,
|
||||
two_letter_iso_country_code: location.iso_alpha2,
|
||||
three_letter_iso_country_code: location.iso_alpha3,
|
||||
latitude: location.latitude,
|
||||
longitude: location.longitude,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ use std::time::Duration;
|
||||
pub(crate) mod http;
|
||||
pub(crate) mod location;
|
||||
pub(crate) mod models;
|
||||
pub(crate) mod utils;
|
||||
|
||||
pub(crate) const CACHE_REFRESH_RATE: Duration = Duration::from_secs(30);
|
||||
pub(crate) const CACHE_ENTRY_TTL: Duration = Duration::from_secs(60);
|
||||
|
||||
@@ -13,6 +13,7 @@ use tokio::sync::{RwLock, RwLockReadGuard};
|
||||
use crate::helpers::best_effort_small_dec_to_f64;
|
||||
use validator_client::models::MixNodeBondAnnotated;
|
||||
|
||||
use super::utils::family_numerical_id;
|
||||
use crate::mix_node::models::{MixnodeStatus, PrettyDetailedMixNodeBond};
|
||||
use crate::mix_nodes::location::{Location, LocationCache, LocationCacheItem};
|
||||
use crate::mix_nodes::CACHE_ENTRY_TTL;
|
||||
@@ -140,6 +141,8 @@ impl ThreadsafeMixNodesCache {
|
||||
let denom = &node.mixnode_details.original_pledge().denom;
|
||||
let rewarding_info = &node.mixnode_details.rewarding_details;
|
||||
|
||||
let family_id = node.family.as_ref().map(family_numerical_id);
|
||||
|
||||
PrettyDetailedMixNodeBond {
|
||||
mix_id,
|
||||
location: location.and_then(|l| l.location.clone()),
|
||||
@@ -157,6 +160,7 @@ impl ThreadsafeMixNodesCache {
|
||||
estimated_delegators_apy: best_effort_small_dec_to_f64(node.estimated_delegators_apy),
|
||||
operating_cost: rewarding_info.cost_params.interval_operating_cost.clone(),
|
||||
profit_margin_percent: rewarding_info.cost_params.profit_margin_percent,
|
||||
family_id,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,15 @@
|
||||
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use mixnet_contract_common::families::FamilyHead;
|
||||
use rand::Rng;
|
||||
use rand_pcg::Pcg64;
|
||||
use rand_seeder::Seeder;
|
||||
|
||||
use crate::mix_nodes::location::GeoLocation;
|
||||
use isocountry::CountryCode;
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn map_2_letter_to_3_letter_country_code(geo: &GeoLocation) -> String {
|
||||
match CountryCode::for_alpha2(&geo.country_code) {
|
||||
Ok(three_letter_country_code) => three_letter_country_code.alpha3().to_string(),
|
||||
@@ -16,3 +22,10 @@ pub(crate) fn map_2_letter_to_3_letter_country_code(geo: &GeoLocation) -> String
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We don't need numerical IDs anywhere, so to avoid modifying the contract storage again and
|
||||
// since this is for explorer ergonomics, it will generate a deterministic random u16 based on the family Identity.
|
||||
pub(crate) fn family_numerical_id(fh: &FamilyHead) -> u16 {
|
||||
let mut rng: Pcg64 = Seeder::from(fh.identity()).make_rng();
|
||||
rng.gen()
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nym/network-explorer",
|
||||
"version": "1.0.1",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
|
||||
@@ -5,7 +5,7 @@ import { Tooltip } from '@nymproject/react/tooltip/Tooltip';
|
||||
import { CopyToClipboard } from '@nymproject/react/clipboard/CopyToClipboard';
|
||||
import { Box } from '@mui/system';
|
||||
import { cellStyles } from './Universal-DataGrid';
|
||||
import { unymToNym } from '../utils/currency';
|
||||
import { currencyToString } from '../utils/currency';
|
||||
import { GatewayEnrichedRowType } from './Gateways';
|
||||
import { MixnodeRowType } from './MixNodes';
|
||||
|
||||
@@ -38,7 +38,7 @@ function formatCellValues(val: string | number, field: string) {
|
||||
);
|
||||
}
|
||||
if (field === 'bond') {
|
||||
return unymToNym(val, 6);
|
||||
return currencyToString(val.toString());
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ export type GatewayRowType = {
|
||||
bond: number;
|
||||
host: string;
|
||||
location: string;
|
||||
version: string;
|
||||
};
|
||||
|
||||
export type GatewayEnrichedRowType = GatewayRowType & {
|
||||
@@ -27,7 +26,6 @@ export function gatewayToGridRow(arrayOfGateways: GatewayResponse): GatewayRowTy
|
||||
location: gw?.gateway?.location || '',
|
||||
bond: gw.pledge_amount.amount || 0,
|
||||
host: gw.gateway.host || '',
|
||||
version: gw.gateway.version || '',
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -42,7 +40,6 @@ export function gatewayEnrichedToGridRow(
|
||||
location: gateway?.gateway?.location || '',
|
||||
bond: gateway.pledge_amount.amount || 0,
|
||||
host: gateway.gateway.host || '',
|
||||
version: gateway.gateway.version || '',
|
||||
clientsPort: gateway.gateway.clients_port || 0,
|
||||
mixPort: gateway.gateway.mix_port || 0,
|
||||
routingScore: `${report.most_recent}%`,
|
||||
|
||||
@@ -4,6 +4,8 @@ import Select, { SelectChangeEvent } from '@mui/material/Select';
|
||||
import { Filters } from './Filters/Filters';
|
||||
import { useIsMobile } from '../hooks/useIsMobile';
|
||||
|
||||
const fieldsHeight = '42.25px';
|
||||
|
||||
type TableToolBarProps = {
|
||||
onChangeSearch: (arg: string) => void;
|
||||
onChangePageSize: (event: SelectChangeEvent<string>) => void;
|
||||
@@ -35,7 +37,7 @@ export const TableToolbar: React.FC<TableToolBarProps> = ({
|
||||
}}
|
||||
>
|
||||
<Box sx={{ display: 'flex', flexDirection: isMobile ? 'column-reverse' : 'row', alignItems: 'middle' }}>
|
||||
<Box sx={{ display: 'flex', justifyContent: 'space-between' }}>
|
||||
<Box sx={{ display: 'flex', justifyContent: 'space-between', height: fieldsHeight }}>
|
||||
{childrenBefore}
|
||||
<Select
|
||||
labelId="simple-select-label"
|
||||
@@ -65,6 +67,9 @@ export const TableToolbar: React.FC<TableToolBarProps> = ({
|
||||
sx={{
|
||||
width: isMobile ? '100%' : 200,
|
||||
marginBottom: isMobile ? 2 : 0,
|
||||
'& > :not(style)': {
|
||||
height: fieldsHeight,
|
||||
},
|
||||
}}
|
||||
value={searchTerm}
|
||||
data-testid="search-box"
|
||||
|
||||
@@ -58,12 +58,6 @@ const columns: ColumnsType[] = [
|
||||
headerAlign: 'left',
|
||||
flex: 1,
|
||||
},
|
||||
{
|
||||
field: 'version',
|
||||
title: 'Version',
|
||||
headerAlign: 'left',
|
||||
flex: 1,
|
||||
},
|
||||
];
|
||||
|
||||
/**
|
||||
|
||||
@@ -10,7 +10,7 @@ import { TableToolbar } from '../../components/TableToolbar';
|
||||
import { CustomColumnHeading } from '../../components/CustomColumnHeading';
|
||||
import { Title } from '../../components/Title';
|
||||
import { cellStyles, UniversalDataGrid } from '../../components/Universal-DataGrid';
|
||||
import { unymToNym } from '../../utils/currency';
|
||||
import { currencyToString } from '../../utils/currency';
|
||||
import { Tooltip } from '../../components/Tooltip';
|
||||
import { BIG_DIPPER } from '../../api/constants';
|
||||
import { splice } from '../../utils';
|
||||
@@ -77,7 +77,7 @@ export const PageGateways: React.FC = () => {
|
||||
to={`/network-components/gateway/${params.row.identityKey}`}
|
||||
data-testid="pledge-amount"
|
||||
>
|
||||
{unymToNym(params.value, 6)}
|
||||
{currencyToString(params.value)}
|
||||
</MuiLink>
|
||||
),
|
||||
},
|
||||
@@ -128,7 +128,7 @@ export const PageGateways: React.FC = () => {
|
||||
field: 'owner',
|
||||
headerName: 'Owner',
|
||||
renderHeader: () => <CustomColumnHeading headingTitle="Owner" />,
|
||||
width: 180,
|
||||
width: 380,
|
||||
headerAlign: 'left',
|
||||
headerClassName: 'MuiDataGrid-header-override',
|
||||
renderCell: (params: GridRenderCellParams) => (
|
||||
@@ -142,24 +142,6 @@ export const PageGateways: React.FC = () => {
|
||||
</MuiLink>
|
||||
),
|
||||
},
|
||||
{
|
||||
field: 'version',
|
||||
headerName: 'Version',
|
||||
renderHeader: () => <CustomColumnHeading headingTitle="Version" />,
|
||||
width: 150,
|
||||
headerAlign: 'left',
|
||||
headerClassName: 'MuiDataGrid-header-override',
|
||||
renderCell: (params: GridRenderCellParams) => (
|
||||
<MuiLink
|
||||
sx={{ ...cellStyles }}
|
||||
href={`${BIG_DIPPER}/account/${params.value}`}
|
||||
target="_blank"
|
||||
data-testid="owner"
|
||||
>
|
||||
{params.value}
|
||||
</MuiLink>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
const handlePageSize = (event: SelectChangeEvent<string>) => {
|
||||
|
||||
@@ -164,10 +164,10 @@ const PageMixnodeDetailWithState: React.FC = () => {
|
||||
{mixNode && (
|
||||
<ContentCard title="Location">
|
||||
{mixNode?.error && <ComponentError text="There was a problem retrieving this mixnode location" />}
|
||||
{mixNode?.data?.location?.latitude && mixNode?.data?.location?.longitude && (
|
||||
{mixNode.data && mixNode?.data?.location && (
|
||||
<WorldMap
|
||||
loading={mixNode.isLoading}
|
||||
userLocation={[mixNode.data.location.longitude, mixNode.data.location.latitude]}
|
||||
userLocation={[mixNode?.data?.location?.lng, mixNode?.data?.location?.lat]}
|
||||
/>
|
||||
)}
|
||||
</ContentCard>
|
||||
|
||||
@@ -77,8 +77,8 @@ export interface MixNodeResponseItem {
|
||||
status: MixnodeStatus;
|
||||
location: {
|
||||
country_name: string;
|
||||
latitude?: number;
|
||||
longitude?: number;
|
||||
lat: number;
|
||||
lng: number;
|
||||
three_letter_iso_country_code: string;
|
||||
two_letter_iso_country_code: string;
|
||||
};
|
||||
|
||||
+5
-9
@@ -3,7 +3,7 @@
|
||||
|
||||
[package]
|
||||
name = "nym-gateway"
|
||||
version = "1.1.5"
|
||||
version = "1.1.4"
|
||||
authors = [
|
||||
"Dave Hrycyszyn <futurechimp@users.noreply.github.com>",
|
||||
"Jędrzej Stuczyński <andrew@nymtech.net>",
|
||||
@@ -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" }
|
||||
@@ -85,10 +87,4 @@ sqlx = { version = "0.5", features = [
|
||||
"sqlite",
|
||||
"macros",
|
||||
"migrate",
|
||||
] }
|
||||
vergen = { version = "5", default-features = false, features = [
|
||||
"build",
|
||||
"git",
|
||||
"rustc",
|
||||
"cargo",
|
||||
] }
|
||||
] }
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
@@ -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,23 +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)]
|
||||
nym_apis: Option<String>,
|
||||
#[clap(long, alias = "validator_apis", value_delimiter = ',')]
|
||||
// the alias here is included for backwards compatibility (1.1.4 and before)
|
||||
nym_apis: Option<Vec<url::Url>>,
|
||||
|
||||
/// Comma separated list of endpoints of the validator
|
||||
#[clap(long)]
|
||||
validators: Option<String>,
|
||||
#[cfg(feature = "coconut")]
|
||||
#[clap(long, alias = "validators", value_delimiter = ',')]
|
||||
// the alias here is included for backwards compatibility (1.1.4 and before)
|
||||
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
|
||||
@@ -63,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 {
|
||||
@@ -76,14 +83,15 @@ impl From<Init> for OverrideConfig {
|
||||
datastore: init_config.datastore,
|
||||
announce_host: init_config.announce_host,
|
||||
nym_apis: init_config.nym_apis,
|
||||
validators: init_config.validators,
|
||||
mnemonic: init_config.mnemonic,
|
||||
|
||||
#[cfg(feature = "coconut")]
|
||||
only_coconut_credentials: init_config.only_coconut_credentials,
|
||||
|
||||
enabled_statistics: init_config.enabled_statistics,
|
||||
statistics_service_url: init_config.statistics_service_url,
|
||||
|
||||
#[cfg(feature = "coconut")]
|
||||
nymd_validators: init_config.nymd_validators,
|
||||
#[cfg(feature = "coconut")]
|
||||
only_coconut_credentials: init_config.only_coconut_credentials,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -159,18 +167,19 @@ 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,
|
||||
validators: None,
|
||||
mnemonic: None,
|
||||
statistics_service_url: None,
|
||||
enabled_statistics: None,
|
||||
#[cfg(feature = "coconut")]
|
||||
nymd_validators: None,
|
||||
#[cfg(feature = "coconut")]
|
||||
only_coconut_credentials: false,
|
||||
};
|
||||
std::env::set_var(BECH32_PREFIX, "n");
|
||||
|
||||
+34
-37
@@ -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_validators;
|
||||
use crypto::bech32_address_validation;
|
||||
use network_defaults::mainnet::read_var_if_not_default;
|
||||
use network_defaults::var_names::{
|
||||
API_VALIDATOR, BECH32_PREFIX, CONFIGURED, NYMD_VALIDATOR, STATISTICS_SERVICE_DOMAIN_ADDRESS,
|
||||
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,18 +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>,
|
||||
validators: 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<Vec<url::Url>>,
|
||||
#[cfg(feature = "coconut")]
|
||||
only_coconut_credentials: bool,
|
||||
}
|
||||
@@ -72,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),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,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(
|
||||
@@ -119,26 +117,18 @@ 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_validators(&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_validators(&raw_validators))
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(ref raw_validators) = args.validators {
|
||||
config = config.with_custom_validator_nymd(parse_validators(raw_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_validators(&raw_validators))
|
||||
config = config.with_custom_nym_apis(::config::parse_urls(&raw_validators))
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
@@ -146,13 +136,20 @@ 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(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))
|
||||
}
|
||||
}
|
||||
config = config.with_only_coconut_credentials(args.only_coconut_credentials);
|
||||
}
|
||||
|
||||
|
||||
+23
-15
@@ -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,23 +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 the nym APIs
|
||||
#[clap(long)]
|
||||
nym_apis: Option<String>,
|
||||
/// Comma separated list of endpoints of nym APIs
|
||||
#[clap(long, alias = "validator_apis", value_delimiter = ',')]
|
||||
// the alias here is included for backwards compatibility (1.1.4 and before)
|
||||
nym_apis: Option<Vec<url::Url>>,
|
||||
|
||||
/// Comma separated list of endpoints of the validator
|
||||
#[clap(long)]
|
||||
validators: Option<String>,
|
||||
#[cfg(feature = "coconut")]
|
||||
#[clap(long, alias = "validators", value_delimiter = ',')]
|
||||
// the alias here is included for backwards compatibility (1.1.4 and before)
|
||||
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
|
||||
@@ -63,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 {
|
||||
@@ -76,14 +83,15 @@ impl From<Run> for OverrideConfig {
|
||||
datastore: run_config.datastore,
|
||||
announce_host: run_config.announce_host,
|
||||
nym_apis: run_config.nym_apis,
|
||||
validators: run_config.validators,
|
||||
mnemonic: run_config.mnemonic,
|
||||
|
||||
#[cfg(feature = "coconut")]
|
||||
only_coconut_credentials: run_config.only_coconut_credentials,
|
||||
|
||||
enabled_statistics: run_config.enabled_statistics,
|
||||
statistics_service_url: run_config.statistics_service_url,
|
||||
|
||||
#[cfg(feature = "coconut")]
|
||||
nymd_validators: run_config.nymd_validators,
|
||||
#[cfg(feature = "coconut")]
|
||||
only_coconut_credentials: run_config.only_coconut_credentials,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
// 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::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(&["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)]
|
||||
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 {
|
||||
@@ -38,7 +40,7 @@ impl TryFrom<Sign> for SignedTarget {
|
||||
fn try_from(args: Sign) -> Result<Self, Self::Error> {
|
||||
if let Some(text) = args.text {
|
||||
Ok(SignedTarget::Text(text))
|
||||
} else if let Some(address) = args.address {
|
||||
} else if let Some(address) = args.wallet_address {
|
||||
Ok(SignedTarget::Address(address))
|
||||
} else {
|
||||
// This is unreachable, and hopefully clap will support it explicitly by outputting an
|
||||
@@ -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),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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}");
|
||||
|
||||
+15
-21
@@ -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;
|
||||
@@ -149,6 +149,7 @@ impl Config {
|
||||
self
|
||||
}
|
||||
|
||||
#[cfg(feature = "coconut")]
|
||||
pub fn with_custom_validator_nymd(mut self, validator_nymd_urls: Vec<Url>) -> Self {
|
||||
self.gateway.validator_nymd_urls = validator_nymd_urls;
|
||||
self
|
||||
@@ -159,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
|
||||
}
|
||||
|
||||
@@ -192,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
|
||||
}
|
||||
|
||||
@@ -302,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()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -377,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 {
|
||||
@@ -423,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
@@ -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
@@ -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
|
||||
}
|
||||
|
||||
|
||||
+3
-5
@@ -3,7 +3,7 @@
|
||||
|
||||
[package]
|
||||
name = "nym-mixnode"
|
||||
version = "1.1.5"
|
||||
version = "1.1.4"
|
||||
authors = [
|
||||
"Dave Hrycyszyn <futurechimp@users.noreply.github.com>",
|
||||
"Jędrzej Stuczyński <andrew@nymtech.net>",
|
||||
@@ -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"] }
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
@@ -1,3 +1,6 @@
|
||||
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::config::Config;
|
||||
use crate::node::node_description::NodeDescription;
|
||||
use clap::Args;
|
||||
@@ -11,9 +14,32 @@ pub(crate) struct Describe {
|
||||
/// The id of the mixnode you want to describe
|
||||
#[clap(long)]
|
||||
id: String,
|
||||
|
||||
/// Human readable name of this node
|
||||
#[clap(long)]
|
||||
name: Option<String>,
|
||||
|
||||
/// Description of this node
|
||||
#[clap(long)]
|
||||
description: Option<String>,
|
||||
|
||||
/// Link associated with this node, for example `https://mixnode.yourdomain.com`
|
||||
#[clap(long)]
|
||||
link: Option<String>,
|
||||
|
||||
/// Physical location of this node, for example `City: London, Country: UK`
|
||||
#[clap(long)]
|
||||
location: Option<String>,
|
||||
}
|
||||
|
||||
pub(crate) fn execute(args: &Describe) {
|
||||
fn read_user_input() -> String {
|
||||
io::stdout().flush().unwrap();
|
||||
let mut buf = String::new();
|
||||
io::stdin().read_line(&mut buf).unwrap();
|
||||
buf.trim().to_string()
|
||||
}
|
||||
|
||||
pub(crate) fn execute(args: Describe) {
|
||||
// ensure that the mixnode has in fact been initialized
|
||||
match Config::load_from_file(Some(&args.id)) {
|
||||
Ok(cfg) => cfg,
|
||||
@@ -23,33 +49,29 @@ pub(crate) fn execute(args: &Describe) {
|
||||
}
|
||||
};
|
||||
|
||||
// get input from the user
|
||||
print!("name: ");
|
||||
io::stdout().flush().unwrap();
|
||||
let mut name_buf = String::new();
|
||||
io::stdin().read_line(&mut name_buf).unwrap();
|
||||
let name = name_buf.trim().to_string();
|
||||
|
||||
print!("description: ");
|
||||
io::stdout().flush().unwrap();
|
||||
let mut desc_buf = String::new();
|
||||
io::stdin().read_line(&mut desc_buf).unwrap();
|
||||
let description = desc_buf.trim().to_string();
|
||||
|
||||
let example_url = "https://mixnode.yourdomain.com".bright_cyan();
|
||||
let example_location = "City: London, Country: UK";
|
||||
|
||||
print!("link, e.g. {}: ", example_url);
|
||||
io::stdout().flush().unwrap();
|
||||
let mut link_buf = String::new();
|
||||
io::stdin().read_line(&mut link_buf).unwrap();
|
||||
let link = link_buf.trim().to_string();
|
||||
// get input from the user if not provided via the arguments
|
||||
let name = args.name.unwrap_or_else(|| {
|
||||
print!("name: ");
|
||||
read_user_input()
|
||||
});
|
||||
|
||||
print!("location, e.g. {}: ", example_location);
|
||||
io::stdout().flush().unwrap();
|
||||
let mut location_buf = String::new();
|
||||
io::stdin().read_line(&mut location_buf).unwrap();
|
||||
let location = location_buf.trim().to_string();
|
||||
let description = args.description.unwrap_or_else(|| {
|
||||
print!("description: ");
|
||||
read_user_input()
|
||||
});
|
||||
|
||||
let link = args.link.unwrap_or_else(|| {
|
||||
print!("link, e.g. {example_url}: ");
|
||||
read_user_input()
|
||||
});
|
||||
|
||||
let location = args.location.unwrap_or_else(|| {
|
||||
print!("location, e.g. {example_location}: ");
|
||||
read_user_input()
|
||||
});
|
||||
|
||||
let node_description = NodeDescription {
|
||||
name,
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
// Copyright 2020 - Nym Technologies SA <contact@nymtech.net>
|
||||
// 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)]
|
||||
@@ -40,9 +41,10 @@ pub(crate) struct Init {
|
||||
#[clap(long)]
|
||||
announce_host: Option<String>,
|
||||
|
||||
/// Comma separated list of rest endpoints of the validators
|
||||
#[clap(long)]
|
||||
validators: Option<String>,
|
||||
/// 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", value_delimiter = ',')]
|
||||
nym_apis: Option<Vec<url::Url>>,
|
||||
}
|
||||
|
||||
impl From<Init> for OverrideConfig {
|
||||
@@ -55,7 +57,7 @@ impl From<Init> for OverrideConfig {
|
||||
verloc_port: init_config.verloc_port,
|
||||
http_api_port: init_config.http_api_port,
|
||||
announce_host: init_config.announce_host,
|
||||
validators: init_config.validators,
|
||||
nym_apis: init_config.nym_apis,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+22
-24
@@ -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_validators,
|
||||
};
|
||||
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,27 +50,27 @@ 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>,
|
||||
validators: Option<String>,
|
||||
nym_apis: Option<Vec<url::Url>>,
|
||||
}
|
||||
|
||||
pub(crate) async fn execute(args: Cli) {
|
||||
let bin_name = "nym-mixnode";
|
||||
|
||||
match &args.command {
|
||||
match args.command {
|
||||
Commands::Describe(m) => describe::execute(m),
|
||||
Commands::Init(m) => init::execute(m),
|
||||
Commands::Run(m) => run::execute(m).await,
|
||||
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::Init(m) => init::execute(&m),
|
||||
Commands::Run(m) => run::execute(&m).await,
|
||||
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::command(), bin_name),
|
||||
Commands::GenerateFigSpec => fig_generate(&mut crate::Cli::command(), bin_name),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,11 +93,11 @@ fn override_config(mut config: Config, args: OverrideConfig) -> Config {
|
||||
config = config.with_http_api_port(port);
|
||||
}
|
||||
|
||||
if let Some(ref raw_validators) = args.validators {
|
||||
config = config.with_custom_nym_apis(parse_validators(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_validators(&raw_validators))
|
||||
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
|
||||
|
||||
@@ -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)]
|
||||
@@ -39,9 +40,10 @@ pub(crate) struct Run {
|
||||
#[clap(long)]
|
||||
announce_host: Option<String>,
|
||||
|
||||
/// Comma separated list of rest endpoints of the validators
|
||||
#[clap(long)]
|
||||
validators: Option<String>,
|
||||
/// 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", value_delimiter = ',')]
|
||||
nym_apis: Option<Vec<url::Url>>,
|
||||
}
|
||||
|
||||
impl From<Run> for OverrideConfig {
|
||||
@@ -54,7 +56,7 @@ impl From<Run> for OverrideConfig {
|
||||
verloc_port: run_config.verloc_port,
|
||||
http_api_port: run_config.http_api_port,
|
||||
announce_host: run_config.announce_host,
|
||||
validators: run_config.validators,
|
||||
nym_apis: run_config.nym_apis,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 std::convert::TryFrom;
|
||||
@@ -11,19 +11,21 @@ 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(&["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)]
|
||||
id: String,
|
||||
|
||||
/// Signs your blockchain address with your identity key
|
||||
#[clap(long)]
|
||||
address: Option<String>,
|
||||
// the alias here is included for backwards compatibility (1.1.4 and before)
|
||||
#[clap(long, alias = "address")]
|
||||
wallet_address: Option<nymd::AccountId>,
|
||||
|
||||
/// Signs an arbitrary piece of text with your identity key
|
||||
#[clap(long)]
|
||||
@@ -32,7 +34,7 @@ pub(crate) struct Sign {
|
||||
|
||||
enum SignedTarget {
|
||||
Text(String),
|
||||
Address(String),
|
||||
Address(nymd::AccountId),
|
||||
}
|
||||
|
||||
impl TryFrom<Sign> for SignedTarget {
|
||||
@@ -41,7 +43,7 @@ impl TryFrom<Sign> for SignedTarget {
|
||||
fn try_from(args: Sign) -> Result<Self, Self::Error> {
|
||||
if let Some(text) = args.text {
|
||||
Ok(SignedTarget::Text(text))
|
||||
} else if let Some(address) = args.address {
|
||||
} else if let Some(address) = args.wallet_address {
|
||||
Ok(SignedTarget::Address(address))
|
||||
} else {
|
||||
// This is unreachable, and hopefully clap will support it explicitly by outputting an
|
||||
@@ -52,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) {
|
||||
@@ -107,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
@@ -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
@@ -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
@@ -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())
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
+6
-9
@@ -2,8 +2,8 @@
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
[package]
|
||||
name = "nym-validator-api"
|
||||
version = "1.1.5"
|
||||
name = "nym-api"
|
||||
version = "1.1.4"
|
||||
authors = [
|
||||
"Dave Hrycyszyn <futurechimp@users.noreply.github.com>",
|
||||
"Jędrzej Stuczyński <andrew@nymtech.net>",
|
||||
@@ -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"
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
@@ -446,8 +446,6 @@ impl Config {
|
||||
self.network_monitor.credentials_database_path.clone()
|
||||
}
|
||||
|
||||
// TODO: Remove if still unused
|
||||
#[allow(dead_code)]
|
||||
pub fn get_rewarding_enabled(&self) -> bool {
|
||||
self.rewarding.enabled
|
||||
}
|
||||
|
||||
+141
-262
@@ -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) {
|
||||
return Ok(());
|
||||
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);
|
||||
@@ -584,11 +464,13 @@ async fn run_nym_api(matches: ArgMatches) -> Result<()> {
|
||||
tokio::spawn(async move { validator_cache_refresher.run(shutdown_listener).await });
|
||||
|
||||
// spawn rewarded set updater
|
||||
let mut rewarded_set_updater =
|
||||
RewardedSetUpdater::new(signing_nymd_client, validator_cache.clone(), storage).await?;
|
||||
let shutdown_listener = shutdown.subscribe();
|
||||
tokio::spawn(async move { rewarded_set_updater.run(shutdown_listener).await.unwrap() });
|
||||
|
||||
if config.get_rewarding_enabled() {
|
||||
let mut rewarded_set_updater =
|
||||
RewardedSetUpdater::new(signing_nymd_client, validator_cache.clone(), storage)
|
||||
.await?;
|
||||
let shutdown_listener = shutdown.subscribe();
|
||||
tokio::spawn(async move { rewarded_set_updater.run(shutdown_listener).await.unwrap() });
|
||||
}
|
||||
validator_cache_listener
|
||||
} else {
|
||||
// Spawn the validator cache refresher.
|
||||
@@ -658,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
|
||||
}
|
||||
|
||||
@@ -2161,9 +2161,9 @@ json-stringify-safe@5.0.1:
|
||||
integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==
|
||||
|
||||
json5@^2.2.1:
|
||||
version "2.2.1"
|
||||
resolved "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz"
|
||||
integrity sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==
|
||||
version "2.2.3"
|
||||
resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283"
|
||||
integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==
|
||||
|
||||
kleur@^3.0.3:
|
||||
version "3.0.3"
|
||||
|
||||
Generated
+59
-22
@@ -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",
|
||||
]
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nym/nym-connect",
|
||||
"version": "1.1.5",
|
||||
"version": "1.1.4",
|
||||
"main": "index.js",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "nym-connect"
|
||||
version = "1.1.5"
|
||||
version = "1.1.4"
|
||||
description = "nym-connect"
|
||||
authors = ["Nym Technologies SA"]
|
||||
license = ""
|
||||
|
||||
@@ -130,11 +130,11 @@ pub async fn init_socks5_config(provider_address: String, chosen_gateway_id: Str
|
||||
if let Ok(raw_validators) = std::env::var(config_common::defaults::var_names::API_VALIDATOR) {
|
||||
config
|
||||
.get_base_mut()
|
||||
.set_custom_nym_apis(config_common::parse_validators(&raw_validators));
|
||||
.set_custom_nym_apis(config_common::parse_urls(&raw_validators));
|
||||
}
|
||||
|
||||
// Setup gateway by either registering a new one, or reusing exiting keys
|
||||
let gateway = client_core::init::setup_gateway::<_, Socks5Config, _>(
|
||||
let gateway = client_core::init::setup_gateway::<Socks5Config, _>(
|
||||
register_gateway,
|
||||
Some(chosen_gateway_id),
|
||||
config.get_base(),
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
use client_core::client::replies::reply_storage::fs_backend;
|
||||
use client_core::error::ClientCoreError;
|
||||
use serde::{Serialize, Serializer};
|
||||
use thiserror::Error;
|
||||
@@ -39,7 +38,7 @@ pub enum BackendError {
|
||||
#[error("{source}")]
|
||||
ClientCoreError {
|
||||
#[from]
|
||||
source: ClientCoreError<fs_backend::Backend>,
|
||||
source: ClientCoreError,
|
||||
},
|
||||
#[error("{source}")]
|
||||
ApiClientError {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"package": {
|
||||
"productName": "nym-connect",
|
||||
"version": "1.1.5"
|
||||
"version": "1.1.4"
|
||||
},
|
||||
"build": {
|
||||
"distDir": "../dist",
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
import React from 'react';
|
||||
import { Box, CircularProgress, Divider, Stack, Tooltip, Typography } from '@mui/material';
|
||||
import { Box, CircularProgress, Typography } from '@mui/material';
|
||||
import { DateTime } from 'luxon';
|
||||
import { ConnectionStatusKind } from '../types';
|
||||
import { ServiceProvider } from '../types/directory';
|
||||
import { ServiceProviderInfo } from './ServiceProviderInfo';
|
||||
|
||||
const FONT_SIZE = '10px';
|
||||
const FONT_WEIGHT = '600';
|
||||
@@ -15,8 +14,8 @@ const ConnectionStatusContent: React.FC<{
|
||||
switch (status) {
|
||||
case ConnectionStatusKind.connected:
|
||||
return (
|
||||
<Typography fontWeight={FONT_WEIGHT} fontStyle={FONT_STYLE} fontSize="14px">
|
||||
Connected to
|
||||
<Typography fontWeight={FONT_WEIGHT} fontStyle={FONT_STYLE} textAlign="center">
|
||||
Connected
|
||||
</Typography>
|
||||
);
|
||||
case ConnectionStatusKind.disconnecting:
|
||||
@@ -45,7 +44,7 @@ const ConnectionStatusContent: React.FC<{
|
||||
ml={1}
|
||||
textTransform="uppercase"
|
||||
textAlign="center"
|
||||
fontSize={FONT_SIZE}
|
||||
fontSize="10px"
|
||||
sx={{ wordSpacing: 3, letterSpacing: 2 }}
|
||||
>
|
||||
You are not protected
|
||||
@@ -60,7 +59,7 @@ export const ConnectionStatus: React.FC<{
|
||||
status: ConnectionStatusKind;
|
||||
connectedSince?: DateTime;
|
||||
serviceProvider?: ServiceProvider;
|
||||
}> = ({ status, serviceProvider }) => {
|
||||
}> = ({ status, connectedSince, serviceProvider }) => {
|
||||
const color =
|
||||
status === ConnectionStatusKind.connected || status === ConnectionStatusKind.disconnecting
|
||||
? '#21D072'
|
||||
@@ -71,13 +70,13 @@ export const ConnectionStatus: React.FC<{
|
||||
<Box color={color} fontSize={FONT_SIZE} sx={{ mb: 1 }}>
|
||||
<ConnectionStatusContent status={status} />
|
||||
</Box>
|
||||
{serviceProvider ? (
|
||||
<Tooltip title={<ServiceProviderInfo serviceProvider={serviceProvider} />}>
|
||||
<Box sx={{ cursor: 'pointer' }}>
|
||||
{serviceProvider && <Typography>{serviceProvider.description}</Typography>}
|
||||
</Box>
|
||||
</Tooltip>
|
||||
) : null}
|
||||
<Box>
|
||||
{serviceProvider && (
|
||||
<Typography fontSize={12} textAlign="center">
|
||||
To {serviceProvider.description}
|
||||
</Typography>
|
||||
)}
|
||||
</Box>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
import React from 'react';
|
||||
import { Divider, Stack, Typography } from '@mui/material';
|
||||
import { ServiceProvider } from 'src/types/directory';
|
||||
|
||||
export const ServiceProviderInfo = ({ serviceProvider }: { serviceProvider: ServiceProvider }) => (
|
||||
<Stack gap={1} sx={{ wordWrap: 'break-word', maxWidth: 150, p: 1 }}>
|
||||
<Typography variant="body2" fontWeight="bold">
|
||||
Connection info
|
||||
</Typography>
|
||||
<Typography variant="caption">{serviceProvider.description}</Typography>
|
||||
<Divider />
|
||||
<Typography variant="caption" fontWeight="bold">
|
||||
Gateway <Typography variant="caption">{serviceProvider.gateway}</Typography>
|
||||
</Typography>
|
||||
<Divider />
|
||||
<Typography variant="caption" fontWeight="bold">
|
||||
Provider <Typography variant="caption">{serviceProvider.address.slice(0, 35)}...</Typography>
|
||||
</Typography>
|
||||
</Stack>
|
||||
);
|
||||
@@ -86,8 +86,6 @@ export const ClientContextProvider = ({ children }: { children: React.ReactNode
|
||||
.catch((e) => console.log(e));
|
||||
|
||||
listen('socks5-event', (e: TauriEvent) => {
|
||||
console.log(e);
|
||||
|
||||
setError(e.payload);
|
||||
}).then((result) => {
|
||||
unlisten.push(result);
|
||||
|
||||
@@ -37,13 +37,11 @@ export const ConnectedLayout: React.FC<{
|
||||
}) => (
|
||||
<>
|
||||
<IpAddressAndPortModal show={showInfoModal} onClose={handleCloseInfoModal} ipAddress={ipAddress} port={port} />
|
||||
<Box>
|
||||
<Box pb={4}>
|
||||
<ConnectionStatus status={ConnectionStatusKind.connected} serviceProvider={serviceProvider} />
|
||||
</Box>
|
||||
<Divider sx={{ my: 2 }} />
|
||||
<Box sx={{ mb: 3 }}>
|
||||
<IpAddressAndPort label="Socks5 address" ipAddress={ipAddress} port={port} />
|
||||
</Box>
|
||||
<IpAddressAndPort label="Socks5 address" ipAddress={ipAddress} port={port} />
|
||||
<Divider sx={{ my: 3 }} />
|
||||
{/* <ConnectionStats stats={stats} /> */}
|
||||
<ConnectionTimer connectedSince={connectedSince} />
|
||||
<ConnectionButton status={status} busy={busy} onClick={onConnectClick} isError={isError} />
|
||||
|
||||
Generated
+2092
-712
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user