Compare commits
87 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 00bd028d8b | |||
| 273dc41559 | |||
| 61bc74148f | |||
| e181a1cfb1 | |||
| fdbe3a1f6a | |||
| 5b15ed6f15 | |||
| 57703af642 | |||
| 9dd4c5d871 | |||
| 4813cf6c18 | |||
| 83b76c6b37 | |||
| 4120234155 | |||
| 42b444ddf8 | |||
| acd832d8e5 | |||
| 75a726ebbe | |||
| b9fbab6024 | |||
| 06ed8716a1 | |||
| beddd3dcee | |||
| 4d02dfb899 | |||
| 80d6cb5c12 | |||
| 7422ab69ba | |||
| 60c8185bea | |||
| 9d3c7c0be8 | |||
| d6048fae52 | |||
| ddb7b0e872 | |||
| 4995dde705 | |||
| 63bfe4246f | |||
| 4654b360e0 | |||
| 7c5c19986a | |||
| 46edca0bd4 | |||
| b03a1f922d | |||
| 9616c90433 | |||
| ea49f0a265 | |||
| 2470c8b9b5 | |||
| 7d001965ec | |||
| 11b1089d83 | |||
| 52699d7598 | |||
| 87443dd624 | |||
| e0f2fa6705 | |||
| 7949b07213 | |||
| bd20fd0b1f | |||
| 57d3d6fd0f | |||
| 06eff652dd | |||
| 246decac4a | |||
| a14ae298ae | |||
| 43188051d3 | |||
| 8aa15fa467 | |||
| f77b037ef7 | |||
| 75dbc5d790 | |||
| e6bcd706ff | |||
| 9a077a0928 | |||
| 11fd42e187 | |||
| 6e499e5996 | |||
| f98cc73a1f | |||
| db9bf4d3fa | |||
| b30628529d | |||
| 3be615f74f | |||
| a8ccd2ec17 | |||
| 2d71caf50a | |||
| 4d08d62fc2 | |||
| 40e5595d65 | |||
| 6780d58a98 | |||
| ccbf06f179 | |||
| e6ecf71cc3 | |||
| c66312ee96 | |||
| 808802aeb4 | |||
| fb38f24e5c | |||
| 65f148a5ad | |||
| 2bcdc5d11e | |||
| 5ecb03ffe9 | |||
| 8505989dad | |||
| ed5e865db7 | |||
| ea3194e0c3 | |||
| 190bff4ffe | |||
| c509555d15 | |||
| f0d66fdd88 | |||
| 14847d01b7 | |||
| f4711902bd | |||
| d92d6877a4 | |||
| ce676c2bb5 | |||
| a096f9d54e | |||
| d9b6823106 | |||
| 89bcb5649b | |||
| a74a99d81d | |||
| c09d3af92f | |||
| 76773c58d7 | |||
| fd90175e87 | |||
| 0eb859467e |
+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-Country
|
||||
GEOIPUPDATE_EDITION_IDS=GeoLite2-City
|
||||
# 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
|
||||
|
||||
+10
-14
@@ -6,23 +6,19 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
|
||||
|
||||
### Added
|
||||
|
||||
- socks5: send status message for service ready, and network-requester error response
|
||||
- socks5: send status message for service ready, and network-requester error response in https://github.com/nymtech/nym/pull/2715
|
||||
|
||||
### Changed
|
||||
|
||||
- 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
|
||||
- all-binaries: improved error logging in https://github.com/nymtech/nym/pull/2686
|
||||
- native client: bring shutdown logic up to the same level as socks5-client in https://github.com/nymtech/nym/pull/2695
|
||||
- nym-api, coconut-dkg contract: automatic, time-based dkg epoch state advancement in https://github.com/nymtech/nym/pull/2670
|
||||
- DKG resharing unit test by @neacsu in https://github.com/nymtech/nym/pull/2668
|
||||
- Renaming validator-api to nym-api by @futurechimp in https://github.com/nymtech/nym/pull/1863
|
||||
- Modify wasm specific make targets by @neacsu in https://github.com/nymtech/nym/pull/2693
|
||||
- client: create websocket handler builder by @octol in https://github.com/nymtech/nym/pull/2700
|
||||
- Outfox and Lion by @durch in https://github.com/nymtech/nym/pull/2730
|
||||
- Feature/multi surb transmission lanes by @jstuczyn in https://github.com/nymtech/nym/pull/2723
|
||||
|
||||
## [v1.1.4] (2022-12-20)
|
||||
|
||||
|
||||
Generated
+93
-145
@@ -426,13 +426,6 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "build-information"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"vergen 7.2.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.9.1"
|
||||
@@ -605,51 +598,41 @@ version = "3.2.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "190814073e85d238f31ff738fcb0bf6910cedeb73376c87cd69291028966fd83"
|
||||
dependencies = [
|
||||
"atty",
|
||||
"bitflags",
|
||||
"clap_lex 0.2.4",
|
||||
"clap_derive",
|
||||
"clap_lex",
|
||||
"indexmap",
|
||||
"once_cell",
|
||||
"strsim",
|
||||
"termcolor",
|
||||
"textwrap 0.15.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.0.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2148adefda54e14492fb9bddcc600b4344c5d1a3123bd666dcb939c6f0e0e57e"
|
||||
dependencies = [
|
||||
"atty",
|
||||
"bitflags",
|
||||
"clap_derive",
|
||||
"clap_lex 0.3.0",
|
||||
"once_cell",
|
||||
"strsim",
|
||||
"termcolor",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_complete"
|
||||
version = "4.0.7"
|
||||
version = "3.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "10861370d2ba66b0f5989f83ebf35db6421713fd92351790e7fdd6c36774c56b"
|
||||
checksum = "e4179da71abd56c26b54dd0c248cc081c1f43b0a1a7e8448e28e57a29baa993d"
|
||||
dependencies = [
|
||||
"clap 4.0.26",
|
||||
"clap 3.2.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_complete_fig"
|
||||
version = "4.0.2"
|
||||
version = "3.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "46b30e010e669cd021e5004f3be26cff6b7c08d2a8a0d65b48d43a8cc0efd6c3"
|
||||
checksum = "ed37b4c0c1214673eba6ad8ea31666626bf72be98ffb323067d973c48b4964b9"
|
||||
dependencies = [
|
||||
"clap 4.0.26",
|
||||
"clap 3.2.8",
|
||||
"clap_complete",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "4.0.21"
|
||||
version = "3.2.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0177313f9f02afc995627906bbd8967e2be069f5261954222dac78290c2b9014"
|
||||
checksum = "759bf187376e1afa7b85b959e6a664a3e7a95203415dba952ad19139e798f902"
|
||||
dependencies = [
|
||||
"heck 0.4.0",
|
||||
"proc-macro-error",
|
||||
@@ -667,15 +650,6 @@ 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"
|
||||
@@ -792,7 +766,7 @@ dependencies = [
|
||||
name = "completions"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"clap 4.0.26",
|
||||
"clap 3.2.8",
|
||||
"clap_complete",
|
||||
"clap_complete_fig",
|
||||
]
|
||||
@@ -1031,7 +1005,7 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"bip39",
|
||||
"cfg-if 0.1.10",
|
||||
"clap 4.0.26",
|
||||
"clap 3.2.8",
|
||||
"coconut-interface",
|
||||
"completions",
|
||||
"config",
|
||||
@@ -1791,7 +1765,7 @@ name = "explorer-api"
|
||||
version = "1.1.1"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"clap 4.0.26",
|
||||
"clap 3.2.8",
|
||||
"contracts-common",
|
||||
"dotenv",
|
||||
"humantime-serde",
|
||||
@@ -1804,9 +1778,6 @@ dependencies = [
|
||||
"network-defaults",
|
||||
"okapi",
|
||||
"pretty_env_logger",
|
||||
"rand 0.8.5",
|
||||
"rand_pcg 0.3.1",
|
||||
"rand_seeder",
|
||||
"reqwest",
|
||||
"rocket",
|
||||
"rocket_cors",
|
||||
@@ -3231,72 +3202,6 @@ 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"
|
||||
@@ -3335,7 +3240,7 @@ dependencies = [
|
||||
"base64",
|
||||
"bip39",
|
||||
"bs58",
|
||||
"clap 4.0.26",
|
||||
"clap 3.2.8",
|
||||
"clap_complete",
|
||||
"clap_complete_fig",
|
||||
"dotenv",
|
||||
@@ -3359,7 +3264,7 @@ dependencies = [
|
||||
"bip39",
|
||||
"bs58",
|
||||
"cfg-if 1.0.0",
|
||||
"clap 4.0.26",
|
||||
"clap 3.2.8",
|
||||
"comfy-table",
|
||||
"cosmrs",
|
||||
"cosmwasm-std",
|
||||
@@ -3385,8 +3290,7 @@ dependencies = [
|
||||
name = "nym-client"
|
||||
version = "1.1.4"
|
||||
dependencies = [
|
||||
"build-information",
|
||||
"clap 4.0.26",
|
||||
"clap 3.2.8",
|
||||
"client-connections",
|
||||
"client-core",
|
||||
"coconut-interface",
|
||||
@@ -3399,7 +3303,6 @@ dependencies = [
|
||||
"futures",
|
||||
"gateway-client",
|
||||
"gateway-requests",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"logging",
|
||||
"network-defaults",
|
||||
@@ -3417,6 +3320,7 @@ dependencies = [
|
||||
"topology",
|
||||
"url",
|
||||
"validator-client",
|
||||
"vergen 5.1.17",
|
||||
"version-checker",
|
||||
"websocket-requests",
|
||||
]
|
||||
@@ -3429,8 +3333,7 @@ dependencies = [
|
||||
"async-trait",
|
||||
"bip39",
|
||||
"bs58",
|
||||
"build-information",
|
||||
"clap 4.0.26",
|
||||
"clap 3.2.8",
|
||||
"coconut-interface",
|
||||
"colored",
|
||||
"completions",
|
||||
@@ -3443,7 +3346,6 @@ dependencies = [
|
||||
"futures",
|
||||
"gateway-requests",
|
||||
"humantime-serde",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"logging",
|
||||
"mixnet-client",
|
||||
@@ -3466,6 +3368,7 @@ dependencies = [
|
||||
"tokio-util 0.7.3",
|
||||
"url",
|
||||
"validator-client",
|
||||
"vergen 5.1.17",
|
||||
"version-checker",
|
||||
]
|
||||
|
||||
@@ -3475,8 +3378,7 @@ version = "1.1.4"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bs58",
|
||||
"build-information",
|
||||
"clap 4.0.26",
|
||||
"clap 3.2.8",
|
||||
"colored",
|
||||
"completions",
|
||||
"config",
|
||||
@@ -3508,6 +3410,7 @@ dependencies = [
|
||||
"topology",
|
||||
"url",
|
||||
"validator-client",
|
||||
"vergen 5.1.17",
|
||||
"version-checker",
|
||||
]
|
||||
|
||||
@@ -3516,7 +3419,7 @@ name = "nym-network-requester"
|
||||
version = "1.1.4"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"clap 4.0.26",
|
||||
"clap 3.2.8",
|
||||
"client-connections",
|
||||
"completions",
|
||||
"dirs",
|
||||
@@ -3579,8 +3482,7 @@ dependencies = [
|
||||
name = "nym-socks5-client"
|
||||
version = "1.1.4"
|
||||
dependencies = [
|
||||
"build-information",
|
||||
"clap 4.0.26",
|
||||
"clap 3.2.8",
|
||||
"client-connections",
|
||||
"client-core",
|
||||
"coconut-interface",
|
||||
@@ -3593,7 +3495,6 @@ dependencies = [
|
||||
"futures",
|
||||
"gateway-client",
|
||||
"gateway-requests",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"logging",
|
||||
"network-defaults",
|
||||
@@ -3614,6 +3515,7 @@ dependencies = [
|
||||
"topology",
|
||||
"url",
|
||||
"validator-client",
|
||||
"vergen 5.1.17",
|
||||
"version-checker",
|
||||
]
|
||||
|
||||
@@ -3643,6 +3545,70 @@ 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"
|
||||
@@ -4424,7 +4390,7 @@ dependencies = [
|
||||
"rand_isaac",
|
||||
"rand_jitter",
|
||||
"rand_os",
|
||||
"rand_pcg 0.1.2",
|
||||
"rand_pcg",
|
||||
"rand_xorshift",
|
||||
"winapi",
|
||||
]
|
||||
@@ -4588,24 +4554,6 @@ 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,7 +30,6 @@ 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.4"
|
||||
version = "1.1.5"
|
||||
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> {
|
||||
) -> Result<GatewayClient, ClientCoreError<B>> {
|
||||
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> {
|
||||
) -> Result<(), ClientCoreError<B>> {
|
||||
let topology_refresher_config = TopologyRefresherConfig::new(
|
||||
nym_api_urls,
|
||||
refresh_rate,
|
||||
@@ -328,17 +328,12 @@ where
|
||||
async fn setup_persistent_reply_storage(
|
||||
backend: B,
|
||||
shutdown: TaskClient,
|
||||
) -> Result<CombinedReplyStorage, ClientCoreError>
|
||||
where
|
||||
<B as ReplyStorageBackend>::StorageError: Sync + Send,
|
||||
{
|
||||
) -> Result<CombinedReplyStorage, ClientCoreError<B>> {
|
||||
let persistent_storage = PersistentReplyStorage::new(backend);
|
||||
let mem_store = persistent_storage
|
||||
.load_state_from_backend()
|
||||
.await
|
||||
.map_err(|err| ClientCoreError::SurbStorageError {
|
||||
source: Box::new(err),
|
||||
})?;
|
||||
.map_err(|err| ClientCoreError::SurbStorageError { source: err })?;
|
||||
|
||||
let store_clone = mem_store.clone();
|
||||
spawn_future(async move {
|
||||
@@ -350,10 +345,7 @@ where
|
||||
Ok(mem_store)
|
||||
}
|
||||
|
||||
pub async fn start_base(mut self) -> Result<BaseClient, ClientCoreError>
|
||||
where
|
||||
<B as ReplyStorageBackend>::StorageError: Sync + Send,
|
||||
{
|
||||
pub async fn start_base(mut self) -> Result<BaseClient, ClientCoreError<B>> {
|
||||
info!("Starting nym client");
|
||||
// channels for inter-component communication
|
||||
// TODO: make the channels be internally created by the relevant components
|
||||
|
||||
@@ -14,15 +14,13 @@ use time::OffsetDateTime;
|
||||
async fn setup_fresh_backend<P: AsRef<Path>>(
|
||||
db_path: P,
|
||||
debug_config: &DebugConfig,
|
||||
) -> Result<fs_backend::Backend, ClientCoreError> {
|
||||
) -> Result<fs_backend::Backend, ClientCoreError<fs_backend::Backend>> {
|
||||
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: Box::new(err),
|
||||
});
|
||||
return Err(ClientCoreError::SurbStorageError { source: err });
|
||||
}
|
||||
};
|
||||
|
||||
@@ -36,9 +34,7 @@ async fn setup_fresh_backend<P: AsRef<Path>>(
|
||||
storage_backend
|
||||
.init_fresh(&mem_store)
|
||||
.await
|
||||
.map_err(|err| ClientCoreError::SurbStorageError {
|
||||
source: Box::new(err),
|
||||
})?;
|
||||
.map_err(|err| ClientCoreError::SurbStorageError { source: err })?;
|
||||
|
||||
Ok(storage_backend)
|
||||
}
|
||||
@@ -67,7 +63,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> {
|
||||
) -> Result<fs_backend::Backend, ClientCoreError<fs_backend::Backend>> {
|
||||
// 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,13 +1,14 @@
|
||||
// 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 {
|
||||
pub enum ClientCoreError<B: ReplyStorageBackend> {
|
||||
#[error("I/O error: {0}")]
|
||||
IoError(#[from] std::io::Error),
|
||||
|
||||
@@ -39,9 +40,7 @@ pub enum ClientCoreError {
|
||||
InsufficientNetworkTopology(#[from] NymTopologyError),
|
||||
|
||||
#[error("experienced a failure with our reply surb persistent storage: {source}")]
|
||||
SurbStorageError {
|
||||
source: Box<dyn std::error::Error + Send + Sync>,
|
||||
},
|
||||
SurbStorageError { source: B::StorageError },
|
||||
|
||||
#[error("The gateway id is invalid - {0}")]
|
||||
UnableToCreatePublicKeyFromGatewayId(Ed25519RecoveryError),
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// 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},
|
||||
@@ -16,10 +17,13 @@ use tap::TapFallible;
|
||||
use topology::{filter::VersionFilterable, gateway};
|
||||
use url::Url;
|
||||
|
||||
pub(super) async fn query_gateway_details(
|
||||
pub(super) async fn query_gateway_details<B>(
|
||||
validator_servers: Vec<Url>,
|
||||
chosen_gateway_id: Option<String>,
|
||||
) -> Result<gateway::Node, ClientCoreError> {
|
||||
) -> Result<gateway::Node, ClientCoreError<B>>
|
||||
where
|
||||
B: ReplyStorageBackend,
|
||||
{
|
||||
let nym_api = validator_servers
|
||||
.choose(&mut thread_rng())
|
||||
.ok_or(ClientCoreError::ListOfNymApisIsEmpty)?;
|
||||
@@ -51,10 +55,13 @@ pub(super) async fn query_gateway_details(
|
||||
}
|
||||
}
|
||||
|
||||
async fn register_with_gateway(
|
||||
async fn register_with_gateway<B>(
|
||||
gateway: &gateway::Node,
|
||||
our_identity: Arc<identity::KeyPair>,
|
||||
) -> Result<Arc<SharedKeys>, ClientCoreError> {
|
||||
) -> Result<Arc<SharedKeys>, ClientCoreError<B>>
|
||||
where
|
||||
B: ReplyStorageBackend,
|
||||
{
|
||||
let timeout = Duration::from_millis(1500);
|
||||
let mut gateway_client = GatewayClient::new_init(
|
||||
gateway.clients_address(),
|
||||
@@ -74,12 +81,13 @@ async fn register_with_gateway(
|
||||
Ok(shared_keys)
|
||||
}
|
||||
|
||||
pub(super) async fn register_with_gateway_and_store_keys<T>(
|
||||
pub(super) async fn register_with_gateway_and_store_keys<T, B>(
|
||||
gateway_details: gateway::Node,
|
||||
config: &Config<T>,
|
||||
) -> Result<(), ClientCoreError>
|
||||
) -> Result<(), ClientCoreError<B>>
|
||||
where
|
||||
T: NymConfig,
|
||||
B: ReplyStorageBackend,
|
||||
{
|
||||
let mut rng = OsRng;
|
||||
let mut key_manager = KeyManager::new(&mut rng);
|
||||
|
||||
@@ -12,6 +12,7 @@ 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,
|
||||
@@ -62,13 +63,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<C, T>(
|
||||
pub async fn setup_gateway<B, 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>
|
||||
) -> Result<GatewayEndpointConfig, ClientCoreError<B>>
|
||||
where
|
||||
B: ReplyStorageBackend,
|
||||
C: NymConfig + ClientCoreConfigTrait,
|
||||
T: NymConfig,
|
||||
{
|
||||
@@ -78,18 +79,19 @@ 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::<C>(&id)
|
||||
reuse_existing_gateway_config::<B, 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<T>(
|
||||
pub async fn register_with_gateway<B, T>(
|
||||
user_chosen_gateway_id: Option<String>,
|
||||
config: &Config<T>,
|
||||
) -> Result<GatewayEndpointConfig, ClientCoreError>
|
||||
) -> Result<GatewayEndpointConfig, ClientCoreError<B>>
|
||||
where
|
||||
B: ReplyStorageBackend,
|
||||
T: NymConfig,
|
||||
{
|
||||
println!("Configuring gateway");
|
||||
@@ -109,11 +111,12 @@ 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<T>(
|
||||
pub async fn config_gateway_with_existing_keys<B, T>(
|
||||
user_chosen_gateway_id: String,
|
||||
config: &Config<T>,
|
||||
) -> Result<GatewayEndpointConfig, ClientCoreError>
|
||||
) -> Result<GatewayEndpointConfig, ClientCoreError<B>>
|
||||
where
|
||||
B: ReplyStorageBackend,
|
||||
T: NymConfig,
|
||||
{
|
||||
println!("Using gateway provided by user, keeping existing keys");
|
||||
@@ -124,8 +127,11 @@ where
|
||||
}
|
||||
|
||||
/// Read and reuse the existing gateway configuration from a file that was generate earlier.
|
||||
pub fn reuse_existing_gateway_config<T>(id: &str) -> Result<GatewayEndpointConfig, ClientCoreError>
|
||||
pub fn reuse_existing_gateway_config<B, T>(
|
||||
id: &str,
|
||||
) -> Result<GatewayEndpointConfig, ClientCoreError<B>>
|
||||
where
|
||||
B: ReplyStorageBackend,
|
||||
T: NymConfig + ClientCoreConfigTrait,
|
||||
{
|
||||
println!("Not registering gateway, will reuse existing config and keys");
|
||||
@@ -144,15 +150,19 @@ where
|
||||
}
|
||||
|
||||
/// Get the client address by loading the keys from stored files.
|
||||
pub fn get_client_address_from_stored_keys<T>(
|
||||
pub fn get_client_address_from_stored_keys<B, T>(
|
||||
config: &Config<T>,
|
||||
) -> Result<Recipient, ClientCoreError>
|
||||
) -> Result<Recipient, ClientCoreError<B>>
|
||||
where
|
||||
T: config::NymConfig,
|
||||
B: ReplyStorageBackend,
|
||||
{
|
||||
fn load_identity_keys(
|
||||
fn load_identity_keys<B>(
|
||||
pathfinder: &ClientKeyPathfinder,
|
||||
) -> Result<identity::KeyPair, ClientCoreError> {
|
||||
) -> Result<identity::KeyPair, ClientCoreError<B>>
|
||||
where
|
||||
B: ReplyStorageBackend,
|
||||
{
|
||||
let identity_keypair: identity::KeyPair =
|
||||
pemstore::load_keypair(&pemstore::KeyPairPath::new(
|
||||
pathfinder.private_identity_key().to_owned(),
|
||||
@@ -162,9 +172,12 @@ where
|
||||
Ok(identity_keypair)
|
||||
}
|
||||
|
||||
fn load_sphinx_keys(
|
||||
fn load_sphinx_keys<B>(
|
||||
pathfinder: &ClientKeyPathfinder,
|
||||
) -> Result<encryption::KeyPair, ClientCoreError> {
|
||||
) -> Result<encryption::KeyPair, ClientCoreError<B>>
|
||||
where
|
||||
B: ReplyStorageBackend,
|
||||
{
|
||||
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 = "4.0", features = ["cargo", "derive"] }
|
||||
clap = { version = "3.2", 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.as_ref());
|
||||
setup_env(args.config_env_file.clone());
|
||||
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::command(), bin_name),
|
||||
Command::GenerateFigSpec => fig_generate(&mut crate::Cli::command(), bin_name)
|
||||
Command::Completions(c) => c.generate(&mut crate::Cli::into_app(), bin_name),
|
||||
Command::GenerateFigSpec => fig_generate(&mut crate::Cli::into_app(), bin_name)
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "nym-client"
|
||||
version = "1.1.4"
|
||||
version = "1.1.5"
|
||||
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jędrzej Stuczyński <andrew@nymtech.net>"]
|
||||
description = "Implementation of the Nym Client"
|
||||
edition = "2021"
|
||||
@@ -20,9 +20,8 @@ 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 = "4.0", features = ["cargo", "derive"] }
|
||||
clap = { version = "3.2", 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
|
||||
@@ -34,7 +33,6 @@ 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 }
|
||||
@@ -60,3 +58,6 @@ 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"] }
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use vergen::{vergen, Config};
|
||||
+256
-400
File diff suppressed because it is too large
Load Diff
@@ -8,7 +8,6 @@ use crate::{
|
||||
};
|
||||
use clap::Args;
|
||||
use config::NymConfig;
|
||||
use crypto::asymmetric::identity;
|
||||
use nymsphinx::addressing::clients::Recipient;
|
||||
use serde::Serialize;
|
||||
use std::fmt::Display;
|
||||
@@ -22,7 +21,7 @@ pub(crate) struct Init {
|
||||
|
||||
/// Id of the gateway we are going to connect to.
|
||||
#[clap(long)]
|
||||
gateway: Option<identity::PublicKey>,
|
||||
gateway: Option<String>,
|
||||
|
||||
/// Force register gateway. WARNING: this will overwrite any existing keys for the given id,
|
||||
/// potentially causing loss of access.
|
||||
@@ -30,14 +29,12 @@ pub(crate) struct Init {
|
||||
force_register_gateway: bool,
|
||||
|
||||
/// Comma separated list of rest endpoints of the nymd validators
|
||||
#[cfg(feature = "coconut")]
|
||||
#[clap(long, value_delimiter = ',')]
|
||||
nymd_validators: Option<Vec<url::Url>>,
|
||||
#[clap(long)]
|
||||
nymd_validators: Option<String>,
|
||||
|
||||
/// Comma separated list of rest endpoints of the API validators
|
||||
#[clap(long, alias = "api_validators", value_delimiter = ',')]
|
||||
// the alias here is included for backwards compatibility (1.1.4 and before)
|
||||
nym_apis: Option<Vec<url::Url>>,
|
||||
#[clap(long)]
|
||||
api_validators: Option<String>,
|
||||
|
||||
/// Whether to not start the websocket
|
||||
#[clap(long)]
|
||||
@@ -49,11 +46,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, hide = true)]
|
||||
#[clap(long, hidden = true)]
|
||||
fastmode: bool,
|
||||
|
||||
/// Disable loop cover traffic and the Poisson rate limiter (for debugging only)
|
||||
#[clap(long, hide = true)]
|
||||
#[clap(long, hidden = true)]
|
||||
no_cover: bool,
|
||||
|
||||
/// Set this client to work in a enabled credentials mode that would attempt to use gateway
|
||||
@@ -70,14 +67,13 @@ pub(crate) struct Init {
|
||||
impl From<Init> for OverrideConfig {
|
||||
fn from(init_config: Init) -> Self {
|
||||
OverrideConfig {
|
||||
nym_apis: init_config.nym_apis,
|
||||
nymd_validators: init_config.nymd_validators,
|
||||
api_validators: init_config.api_validators,
|
||||
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,
|
||||
}
|
||||
@@ -131,16 +127,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;
|
||||
let user_chosen_gateway_id = args.gateway.clone();
|
||||
|
||||
// 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.map(|id| id.to_base58_string()),
|
||||
user_chosen_gateway_id,
|
||||
config.get_base(),
|
||||
)
|
||||
.await
|
||||
@@ -156,14 +152,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: {address}\n");
|
||||
println!("\nThe address of this client is: {}\n", address);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@@ -1,30 +1,54 @@
|
||||
// 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;
|
||||
|
||||
lazy_static! {
|
||||
pub static ref PRETTY_BUILD_INFORMATION: String =
|
||||
BinaryBuildInformation::new(env!("CARGO_PKG_VERSION")).pretty_print();
|
||||
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"),
|
||||
)
|
||||
}
|
||||
|
||||
// Helper for passing LONG_VERSION to clap
|
||||
fn pretty_build_info_static() -> &'static str {
|
||||
&PRETTY_BUILD_INFORMATION
|
||||
fn long_version_static() -> &'static str {
|
||||
Box::leak(long_version().into_boxed_str())
|
||||
}
|
||||
|
||||
#[derive(Parser)]
|
||||
#[clap(author = "Nymtech", version, long_version = pretty_build_info_static(), about)]
|
||||
#[clap(author = "Nymtech", version, long_version = long_version_static(), about)]
|
||||
pub(crate) struct Cli {
|
||||
/// Path pointing to an env file that configures the client.
|
||||
#[clap(short, long)]
|
||||
@@ -52,14 +76,13 @@ pub(crate) enum Commands {
|
||||
|
||||
// Configuration that can be overridden.
|
||||
pub(crate) struct OverrideConfig {
|
||||
nym_apis: Option<Vec<url::Url>>,
|
||||
nymd_validators: Option<String>,
|
||||
api_validators: Option<String>,
|
||||
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,
|
||||
}
|
||||
@@ -71,21 +94,34 @@ 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::command(), bin_name),
|
||||
Commands::GenerateFigSpec => fig_generate(&mut Cli::command(), bin_name),
|
||||
Commands::Completions(s) => s.generate(&mut Cli::into_app(), bin_name),
|
||||
Commands::GenerateFigSpec => fig_generate(&mut Cli::into_app(), bin_name),
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn override_config(mut config: Config, args: OverrideConfig) -> Config {
|
||||
if let Some(nym_apis) = args.nym_apis {
|
||||
config.get_base_mut().set_custom_nym_apis(nym_apis);
|
||||
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));
|
||||
} 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_urls(&raw_validators));
|
||||
.set_custom_nym_apis(config::parse_validators(&raw_validators));
|
||||
}
|
||||
|
||||
if args.disable_socket {
|
||||
@@ -98,15 +134,6 @@ 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-2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use std::error::Error;
|
||||
@@ -11,7 +11,6 @@ use crate::{
|
||||
|
||||
use clap::Args;
|
||||
use config::NymConfig;
|
||||
use crypto::asymmetric::identity;
|
||||
use log::*;
|
||||
use version_checker::is_minor_version_compatible;
|
||||
|
||||
@@ -22,19 +21,17 @@ pub(crate) struct Run {
|
||||
id: String,
|
||||
|
||||
/// Comma separated list of rest endpoints of the nymd validators
|
||||
#[cfg(feature = "coconut")]
|
||||
#[clap(long, value_delimiter = ',')]
|
||||
nymd_validators: Option<Vec<url::Url>>,
|
||||
#[clap(long)]
|
||||
nymd_validators: Option<String>,
|
||||
|
||||
/// Comma separated list of rest endpoints of the API validators
|
||||
#[clap(long, alias = "api_validators", value_delimiter = ',')]
|
||||
// the alias here is included for backwards compatibility (1.1.4 and before)
|
||||
nym_apis: Option<Vec<url::Url>>,
|
||||
#[clap(long)]
|
||||
api_validators: Option<String>,
|
||||
|
||||
/// 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<identity::PublicKey>,
|
||||
gateway: Option<String>,
|
||||
|
||||
/// Whether to not start the websocket
|
||||
#[clap(long)]
|
||||
@@ -46,11 +43,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, hide = true)]
|
||||
#[clap(long, hidden = true)]
|
||||
fastmode: bool,
|
||||
|
||||
/// Disable loop cover traffic and the Poisson rate limiter (for debugging only)
|
||||
#[clap(long, hide = true)]
|
||||
#[clap(long, hidden = true)]
|
||||
no_cover: bool,
|
||||
|
||||
/// Set this client to work in a enabled credentials mode that would attempt to use gateway
|
||||
@@ -63,14 +60,12 @@ pub(crate) struct Run {
|
||||
impl From<Run> for OverrideConfig {
|
||||
fn from(run_config: Run) -> Self {
|
||||
OverrideConfig {
|
||||
nym_apis: run_config.nym_apis,
|
||||
nymd_validators: run_config.nymd_validators,
|
||||
api_validators: run_config.api_validators,
|
||||
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,3 +1,4 @@
|
||||
use client_core::client::replies::reply_storage::fs_backend;
|
||||
use client_core::error::ClientCoreError;
|
||||
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
@@ -6,7 +7,7 @@ pub enum ClientError {
|
||||
IoError(#[from] std::io::Error),
|
||||
|
||||
#[error("client-core error: {0}")]
|
||||
ClientCoreError(#[from] ClientCoreError),
|
||||
ClientCoreError(#[from] ClientCoreError<fs_backend::Backend>),
|
||||
|
||||
#[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.as_ref());
|
||||
setup_env(args.config_env_file.clone());
|
||||
commands::execute(&args).await
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "nym-socks5-client"
|
||||
version = "1.1.4"
|
||||
version = "1.1.5"
|
||||
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,10 +11,9 @@ name = "nym_socks5"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[dependencies]
|
||||
clap = { version = "4.0", features = ["cargo", "derive"] }
|
||||
clap = { version = "3.2", 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"
|
||||
@@ -27,7 +26,6 @@ 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 }
|
||||
@@ -53,3 +51,6 @@ 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"] }
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
// 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,7 +8,6 @@ use crate::{
|
||||
};
|
||||
use clap::Args;
|
||||
use config::NymConfig;
|
||||
use crypto::asymmetric::identity;
|
||||
use nymsphinx::addressing::clients::Recipient;
|
||||
use serde::Serialize;
|
||||
use std::fmt::Display;
|
||||
@@ -22,20 +21,19 @@ pub(crate) struct Init {
|
||||
|
||||
/// Address of the socks5 provider to send messages to.
|
||||
#[clap(long)]
|
||||
provider: Recipient,
|
||||
provider: String,
|
||||
|
||||
/// 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.
|
||||
// the alias here is included for backwards compatibility (1.1.4 and before)
|
||||
#[clap(long, alias = "use_anonymous_sender_tag")]
|
||||
use_reply_surbs: bool,
|
||||
#[clap(long)]
|
||||
use_anonymous_sender_tag: bool,
|
||||
|
||||
/// Id of the gateway we are going to connect to.
|
||||
#[clap(long)]
|
||||
gateway: Option<identity::PublicKey>,
|
||||
gateway: Option<String>,
|
||||
|
||||
/// Force register gateway. WARNING: this will overwrite any existing keys for the given id,
|
||||
/// potentially causing loss of access.
|
||||
@@ -43,14 +41,12 @@ pub(crate) struct Init {
|
||||
force_register_gateway: bool,
|
||||
|
||||
/// Comma separated list of rest endpoints of the nymd validators
|
||||
#[cfg(feature = "coconut")]
|
||||
#[clap(long, value_delimiter = ',')]
|
||||
nymd_validators: Option<Vec<url::Url>>,
|
||||
#[clap(long)]
|
||||
nymd_validators: Option<String>,
|
||||
|
||||
/// Comma separated list of rest endpoints of the API validators
|
||||
#[clap(long, alias = "api_validators", value_delimiter = ',')]
|
||||
// the alias here is included for backwards compatibility (1.1.4 and before)
|
||||
nym_apis: Option<Vec<url::Url>>,
|
||||
#[clap(long)]
|
||||
api_validators: Option<String>,
|
||||
|
||||
/// Port for the socket to listen on in all subsequent runs
|
||||
#[clap(short, long)]
|
||||
@@ -58,11 +54,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, hide = true)]
|
||||
#[clap(long, hidden = true)]
|
||||
fastmode: bool,
|
||||
|
||||
/// Disable loop cover traffic and the Poisson rate limiter (for debugging only)
|
||||
#[clap(long, hide = true)]
|
||||
#[clap(long, hidden = true)]
|
||||
no_cover: bool,
|
||||
|
||||
/// Set this client to work in a enabled credentials mode that would attempt to use gateway
|
||||
@@ -79,14 +75,12 @@ pub(crate) struct Init {
|
||||
impl From<Init> for OverrideConfig {
|
||||
fn from(init_config: Init) -> Self {
|
||||
OverrideConfig {
|
||||
nym_apis: init_config.nym_apis,
|
||||
nymd_validators: init_config.nymd_validators,
|
||||
api_validators: init_config.api_validators,
|
||||
port: init_config.port,
|
||||
use_anonymous_replies: init_config.use_reply_surbs,
|
||||
use_anonymous_sender_tag: init_config.use_anonymous_sender_tag,
|
||||
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,
|
||||
}
|
||||
@@ -141,19 +135,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;
|
||||
let user_chosen_gateway_id = args.gateway.clone();
|
||||
|
||||
// Load and potentially override config
|
||||
let mut config = override_config(
|
||||
Config::new(id, &provider_address.to_string()),
|
||||
Config::new(id, provider_address),
|
||||
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.map(|id| id.to_base58_string()),
|
||||
user_chosen_gateway_id,
|
||||
config.get_base(),
|
||||
)
|
||||
.await
|
||||
|
||||
@@ -1,31 +1,55 @@
|
||||
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use std::error::Error;
|
||||
|
||||
use crate::client::config::Config;
|
||||
use build_information::BinaryBuildInformation;
|
||||
use clap::CommandFactory;
|
||||
use clap::{Parser, Subcommand};
|
||||
use completions::{fig_generate, ArgShell};
|
||||
use config::parse_urls;
|
||||
use lazy_static::lazy_static;
|
||||
use std::error::Error;
|
||||
use config::parse_validators;
|
||||
|
||||
pub mod init;
|
||||
pub(crate) mod run;
|
||||
pub(crate) mod upgrade;
|
||||
|
||||
lazy_static! {
|
||||
pub static ref PRETTY_BUILD_INFORMATION: String =
|
||||
BinaryBuildInformation::new(env!("CARGO_PKG_VERSION")).pretty_print();
|
||||
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"),
|
||||
)
|
||||
}
|
||||
|
||||
// Helper for passing LONG_VERSION to clap
|
||||
fn pretty_build_info_static() -> &'static str {
|
||||
&PRETTY_BUILD_INFORMATION
|
||||
fn long_version_static() -> &'static str {
|
||||
Box::leak(long_version().into_boxed_str())
|
||||
}
|
||||
|
||||
#[derive(Parser)]
|
||||
#[clap(author = "Nymtech", version, long_version = pretty_build_info_static(), about)]
|
||||
#[clap(author = "Nymtech", version, long_version = long_version_static(), about)]
|
||||
pub(crate) struct Cli {
|
||||
/// Path pointing to an env file that configures the client.
|
||||
#[clap(short, long)]
|
||||
@@ -55,14 +79,13 @@ pub(crate) enum Commands {
|
||||
|
||||
// Configuration that can be overridden.
|
||||
pub(crate) struct OverrideConfig {
|
||||
nym_apis: Option<Vec<url::Url>>,
|
||||
nymd_validators: Option<String>,
|
||||
api_validators: Option<String>,
|
||||
port: Option<u16>,
|
||||
use_anonymous_replies: bool,
|
||||
use_anonymous_sender_tag: bool,
|
||||
fastmode: bool,
|
||||
no_cover: bool,
|
||||
|
||||
#[cfg(feature = "coconut")]
|
||||
nymd_validators: Option<Vec<url::Url>>,
|
||||
#[cfg(feature = "coconut")]
|
||||
enabled_credentials_mode: bool,
|
||||
}
|
||||
@@ -74,22 +97,33 @@ 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::command(), bin_name),
|
||||
Commands::GenerateFigSpec => fig_generate(&mut Cli::command(), bin_name),
|
||||
Commands::Completions(s) => s.generate(&mut Cli::into_app(), bin_name),
|
||||
Commands::GenerateFigSpec => fig_generate(&mut Cli::into_app(), bin_name),
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn override_config(mut config: Config, args: OverrideConfig) -> Config {
|
||||
if let Some(nym_apis) = args.nym_apis {
|
||||
config.get_base_mut().set_custom_nym_apis(nym_apis);
|
||||
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));
|
||||
} else if let Ok(raw_validators) = std::env::var(network_defaults::var_names::API_VALIDATOR) {
|
||||
config
|
||||
.get_base_mut()
|
||||
.set_custom_nym_apis(parse_urls(&raw_validators));
|
||||
.set_custom_nym_apis(parse_validators(&raw_validators));
|
||||
}
|
||||
|
||||
if args.use_anonymous_replies {
|
||||
if args.use_anonymous_sender_tag {
|
||||
config = config.with_anonymous_replies(true)
|
||||
}
|
||||
|
||||
@@ -99,15 +133,6 @@ 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,9 +9,7 @@ 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)]
|
||||
@@ -29,27 +27,25 @@ 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.
|
||||
// the alias here is included for backwards compatibility (1.1.4 and before)
|
||||
#[clap(long, alias = "use_anonymous_sender_tag")]
|
||||
use_anonymous_replies: bool,
|
||||
#[clap(long)]
|
||||
use_anonymous_sender_tag: bool,
|
||||
|
||||
/// Address of the socks5 provider to send messages to.
|
||||
#[clap(long)]
|
||||
provider: Option<Recipient>,
|
||||
provider: Option<String>,
|
||||
|
||||
/// 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<identity::PublicKey>,
|
||||
gateway: Option<String>,
|
||||
|
||||
/// Comma separated list of rest endpoints of the nymd validators
|
||||
#[cfg(feature = "coconut")]
|
||||
#[clap(long, value_delimiter = ',')]
|
||||
nymd_validators: Option<Vec<url::Url>>,
|
||||
#[clap(long)]
|
||||
nymd_validators: Option<String>,
|
||||
|
||||
/// Comma separated list of rest endpoints of the Nym APIs
|
||||
#[clap(long, value_delimiter = ',')]
|
||||
nym_apis: Option<Vec<url::Url>>,
|
||||
#[clap(long)]
|
||||
nym_apis: Option<String>,
|
||||
|
||||
/// Port for the socket to listen on
|
||||
#[clap(short, long)]
|
||||
@@ -57,11 +53,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, hide = true)]
|
||||
#[clap(long, hidden = true)]
|
||||
fastmode: bool,
|
||||
|
||||
/// Disable loop cover traffic and the Poisson rate limiter (for debugging only)
|
||||
#[clap(long, hide = true)]
|
||||
#[clap(long, hidden = true)]
|
||||
no_cover: bool,
|
||||
|
||||
/// Set this client to work in a enabled credentials mode that would attempt to use gateway
|
||||
@@ -74,14 +70,12 @@ pub(crate) struct Run {
|
||||
impl From<Run> for OverrideConfig {
|
||||
fn from(run_config: Run) -> Self {
|
||||
OverrideConfig {
|
||||
nym_apis: run_config.nym_apis,
|
||||
nymd_validators: run_config.nymd_validators,
|
||||
api_validators: run_config.nym_apis,
|
||||
port: run_config.port,
|
||||
use_anonymous_replies: run_config.use_anonymous_replies,
|
||||
use_anonymous_sender_tag: run_config.use_anonymous_sender_tag,
|
||||
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,5 @@
|
||||
use crate::socks::types::SocksProxyError;
|
||||
use client_core::client::replies::reply_storage::fs_backend;
|
||||
use client_core::error::ClientCoreError;
|
||||
use socks5_requests::ConnectionId;
|
||||
|
||||
@@ -8,7 +9,7 @@ pub enum Socks5ClientError {
|
||||
IoError(#[from] std::io::Error),
|
||||
|
||||
#[error("client-core error: {0}")]
|
||||
ClientCoreError(#[from] ClientCoreError),
|
||||
ClientCoreError(#[from] ClientCoreError<fs_backend::Backend>),
|
||||
|
||||
#[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.as_ref());
|
||||
setup_env(args.config_env_file.clone());
|
||||
commands::execute(&args).await
|
||||
}
|
||||
|
||||
|
||||
+165
-433
File diff suppressed because it is too large
Load Diff
@@ -1,11 +0,0 @@
|
||||
[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,86 +0,0 @@
|
||||
// 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 = "4.0", features = ["derive"] }
|
||||
clap = { version = "3.2", 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.as_ref());
|
||||
setup_env(args.config_env_file.clone());
|
||||
|
||||
// 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 = "4.0", features = ["derive"] }
|
||||
clap_complete = "4.0"
|
||||
clap_complete_fig = "4.0"
|
||||
clap = { version = "3.2", features = ["derive"] }
|
||||
clap_complete = "3.2"
|
||||
clap_complete_fig = "3.2"
|
||||
@@ -1,5 +1,5 @@
|
||||
use clap::builder::Command;
|
||||
use clap::clap_derive::ValueEnum;
|
||||
use clap::clap_derive::ArgEnum;
|
||||
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(ValueEnum, Copy, Clone)]
|
||||
#[derive(ArgEnum, Copy, Clone)]
|
||||
pub enum Shell {
|
||||
Bash,
|
||||
Elvish,
|
||||
@@ -25,7 +25,7 @@ pub enum Shell {
|
||||
|
||||
#[derive(Args, Copy, Clone)]
|
||||
pub struct ArgShell {
|
||||
#[clap(value_enum, value_name = "SHELL")]
|
||||
#[clap(arg_enum, value_name = "SHELL")]
|
||||
shell: Shell,
|
||||
}
|
||||
|
||||
|
||||
@@ -118,14 +118,13 @@ pub trait NymConfig: Default + Serialize + DeserializeOwned {
|
||||
}
|
||||
}
|
||||
|
||||
// this function is only used for parsing values from the network defaults and thus the "expect" there are fine
|
||||
pub fn parse_urls(raw: &str) -> Vec<url::Url> {
|
||||
pub fn parse_validators(raw: &str) -> Vec<url::Url> {
|
||||
raw.split(',')
|
||||
.map(|raw_url| {
|
||||
raw_url
|
||||
.map(|raw_validator| {
|
||||
raw_validator
|
||||
.trim()
|
||||
.parse()
|
||||
.expect("one of the provided nym api urls is invalid")
|
||||
.expect("one of the provided validator api urls is invalid")
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
@@ -56,6 +56,7 @@ impl Family {
|
||||
self.proxy.as_ref()
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn label(&self) -> &str {
|
||||
&self.label
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ 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")]
|
||||
@@ -142,14 +141,6 @@ 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,7 +10,6 @@ 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
|
||||
@@ -226,14 +225,6 @@ 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::*;
|
||||
|
||||
+1180
-1647
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.1.0",
|
||||
"@nomiclabs/hardhat-etherscan": "^3.0.3",
|
||||
"@nomiclabs/hardhat-waffle": "^2.0.3",
|
||||
"chai": "^4.3.6",
|
||||
"ethereum-waffle": "^3.4.4",
|
||||
"ethers": "^5.6.1",
|
||||
"hardhat": "^2.11.2",
|
||||
"hardhat": "^2.9.2",
|
||||
"solidity-coverage": "^0.7.20"
|
||||
},
|
||||
"dependencies": {
|
||||
|
||||
+1522
-65
File diff suppressed because it is too large
Load Diff
@@ -16,7 +16,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/node": "^14.14.22",
|
||||
"nodemon": "^2.0.20",
|
||||
"nodemon": "^2.0.7",
|
||||
"@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-Country.mmdb
|
||||
GEOIP_DB_PATH=./geo_ip/GeoLite2-City.mmdb
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
[package]
|
||||
name = "explorer-api"
|
||||
version = "1.1.1"
|
||||
version = "1.1.2"
|
||||
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 = "4.0", features = ["cargo", "derive"] }
|
||||
clap = { version = "3.2", features = ["cargo", "derive"] }
|
||||
humantime-serde = "1.0"
|
||||
isocountry = "0.3.2"
|
||||
itertools = "0.10.3"
|
||||
@@ -25,9 +25,6 @@ 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-Country.mmdb cargo run
|
||||
GEOIP_DB_PATH=./geo_ip/GeoLite2-City.mmdb cargo run
|
||||
```
|
||||
|
||||
Note: explorer-api binary reads the provided `.env` file.
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
// 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()))
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
pub(crate) mod http;
|
||||
@@ -3,14 +3,14 @@
|
||||
|
||||
use isocountry::CountryCode;
|
||||
use log::warn;
|
||||
use maxminddb::{geoip2::Country, MaxMindDBError, Reader};
|
||||
use maxminddb::{geoip2::City, MaxMindDBError, Reader};
|
||||
use std::{
|
||||
net::{IpAddr, ToSocketAddrs},
|
||||
str::FromStr,
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
const DEFAULT_DATABASE_PATH: &str = "./geo_ip/GeoLite2-Country.mmdb";
|
||||
const DEFAULT_DATABASE_PATH: &str = "./geo_ip/GeoLite2-City.mmdb";
|
||||
const FAKE_PORT: u16 = 1234;
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -38,6 +38,8 @@ 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 {
|
||||
@@ -86,7 +88,7 @@ impl GeoIp {
|
||||
error!("No registered GeoIP database");
|
||||
GeoIpError::InternalError
|
||||
})?
|
||||
.lookup::<Country>(ip);
|
||||
.lookup::<City>(ip);
|
||||
match &result {
|
||||
Ok(v) => Ok(Some(
|
||||
Location::try_from(v).map_err(|_| GeoIpError::InternalError)?,
|
||||
@@ -99,11 +101,11 @@ impl GeoIp {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> TryFrom<&Country<'a>> for Location {
|
||||
impl<'a> TryFrom<&City<'a>> for Location {
|
||||
type Error = String;
|
||||
|
||||
fn try_from(country: &Country) -> Result<Self, Self::Error> {
|
||||
let data = country.country.as_ref().ok_or_else(|| {
|
||||
fn try_from(city: &City) -> Result<Self, Self::Error> {
|
||||
let data = city.country.as_ref().ok_or_else(|| {
|
||||
warn!("No Country data found");
|
||||
"No Country data found"
|
||||
})?;
|
||||
@@ -119,10 +121,13 @@ impl<'a> TryFrom<&Country<'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,7 +5,6 @@ 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;
|
||||
@@ -57,7 +56,6 @@ 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,9 +8,8 @@ use dotenv::dotenv;
|
||||
use log::info;
|
||||
use logging::setup_logging;
|
||||
use network_defaults::setup_env;
|
||||
use task::{wait_for_signal, TaskManager};
|
||||
use task::TaskManager;
|
||||
|
||||
mod buy_terms;
|
||||
pub(crate) mod cache;
|
||||
mod client;
|
||||
pub(crate) mod commands;
|
||||
@@ -35,7 +34,7 @@ async fn main() {
|
||||
dotenv().ok();
|
||||
setup_logging();
|
||||
let args = commands::Cli::parse();
|
||||
setup_env(args.config_env_file.as_ref());
|
||||
setup_env(args.config_env_file);
|
||||
let mut explorer_api = ExplorerApi::new();
|
||||
explorer_api.run().await;
|
||||
}
|
||||
@@ -88,3 +87,31 @@ 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,7 +40,6 @@ 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,6 +36,8 @@ 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 {
|
||||
@@ -44,6 +46,8 @@ 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,7 +6,6 @@ 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,7 +13,6 @@ 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;
|
||||
@@ -141,8 +140,6 @@ 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()),
|
||||
@@ -160,7 +157,6 @@ 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,15 +1,9 @@
|
||||
// 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(),
|
||||
@@ -22,10 +16,3 @@ 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()
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
## UNRELEASED
|
||||
|
||||
## [nym-explorer-v1.0.1](https://github.com/nymtech/nym/tree/nym-explorer-v1.0.1) (2023-01-10)
|
||||
|
||||
- Feat/2161 ne gate version by @gala1234 in https://github.com/nymtech/nym/pull/2743
|
||||
- fix(explorer): set gateway bond 6 decimals by @doums in https://github.com/nymtech/nym/pull/2741
|
||||
- Feat/2130 tables update rebase by @gala1234 in https://github.com/nymtech/nym/pull/2742
|
||||
- fix(explorer,explorer-api): mixnode location by @doums in https://github.com/nymtech/nym-api
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nym/network-explorer",
|
||||
"version": "1.0.0",
|
||||
"version": "1.0.1",
|
||||
"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 { currencyToString } from '../utils/currency';
|
||||
import { unymToNym } 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 currencyToString(val.toString());
|
||||
return unymToNym(val, 6);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ export type GatewayRowType = {
|
||||
bond: number;
|
||||
host: string;
|
||||
location: string;
|
||||
version: string;
|
||||
};
|
||||
|
||||
export type GatewayEnrichedRowType = GatewayRowType & {
|
||||
@@ -26,6 +27,7 @@ export function gatewayToGridRow(arrayOfGateways: GatewayResponse): GatewayRowTy
|
||||
location: gw?.gateway?.location || '',
|
||||
bond: gw.pledge_amount.amount || 0,
|
||||
host: gw.gateway.host || '',
|
||||
version: gw.gateway.version || '',
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -40,6 +42,7 @@ 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}%`,
|
||||
|
||||
@@ -58,6 +58,12 @@ 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 { currencyToString } from '../../utils/currency';
|
||||
import { unymToNym } 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"
|
||||
>
|
||||
{currencyToString(params.value)}
|
||||
{unymToNym(params.value, 6)}
|
||||
</MuiLink>
|
||||
),
|
||||
},
|
||||
@@ -128,7 +128,7 @@ export const PageGateways: React.FC = () => {
|
||||
field: 'owner',
|
||||
headerName: 'Owner',
|
||||
renderHeader: () => <CustomColumnHeading headingTitle="Owner" />,
|
||||
width: 380,
|
||||
width: 180,
|
||||
headerAlign: 'left',
|
||||
headerClassName: 'MuiDataGrid-header-override',
|
||||
renderCell: (params: GridRenderCellParams) => (
|
||||
@@ -142,6 +142,24 @@ 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 && mixNode?.data?.location && (
|
||||
{mixNode?.data?.location?.latitude && mixNode?.data?.location?.longitude && (
|
||||
<WorldMap
|
||||
loading={mixNode.isLoading}
|
||||
userLocation={[mixNode?.data?.location?.lng, mixNode?.data?.location?.lat]}
|
||||
userLocation={[mixNode.data.location.longitude, mixNode.data.location.latitude]}
|
||||
/>
|
||||
)}
|
||||
</ContentCard>
|
||||
|
||||
@@ -77,8 +77,8 @@ export interface MixNodeResponseItem {
|
||||
status: MixnodeStatus;
|
||||
location: {
|
||||
country_name: string;
|
||||
lat: number;
|
||||
lng: number;
|
||||
latitude?: number;
|
||||
longitude?: number;
|
||||
three_letter_iso_country_code: string;
|
||||
two_letter_iso_country_code: string;
|
||||
};
|
||||
|
||||
+9
-5
@@ -3,7 +3,7 @@
|
||||
|
||||
[package]
|
||||
name = "nym-gateway"
|
||||
version = "1.1.4"
|
||||
version = "1.1.5"
|
||||
authors = [
|
||||
"Dave Hrycyszyn <futurechimp@users.noreply.github.com>",
|
||||
"Jędrzej Stuczyński <andrew@nymtech.net>",
|
||||
@@ -19,14 +19,13 @@ anyhow = "1.0.53"
|
||||
async-trait = { version = "0.1.51" }
|
||||
bip39 = "1.0.1"
|
||||
bs58 = "0.4.0"
|
||||
clap = { version = "4.0", features = ["cargo", "derive"] }
|
||||
clap = { version = "3.2", 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"
|
||||
@@ -52,7 +51,6 @@ 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" }
|
||||
@@ -87,4 +85,10 @@ sqlx = { version = "0.5", features = [
|
||||
"sqlite",
|
||||
"macros",
|
||||
"migrate",
|
||||
] }
|
||||
] }
|
||||
vergen = { version = "5", default-features = false, features = [
|
||||
"build",
|
||||
"git",
|
||||
"rustc",
|
||||
"cargo",
|
||||
] }
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use sqlx::{Connection, SqliteConnection};
|
||||
use std::env;
|
||||
use vergen::{vergen, Config};
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
@@ -22,4 +23,6 @@ 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-2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// Copyright 2020 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::{
|
||||
@@ -8,9 +8,6 @@ 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 {
|
||||
@@ -20,11 +17,11 @@ pub struct Init {
|
||||
|
||||
/// The custom host on which the gateway will be running for receiving sphinx packets
|
||||
#[clap(long)]
|
||||
host: IpAddr,
|
||||
host: String,
|
||||
|
||||
/// The wallet address you will use to bond this gateway, e.g. nymt1z9egw0knv47nmur0p8vk4rcx59h9gg4zuxrrr9
|
||||
#[clap(long)]
|
||||
wallet_address: nymd::AccountId,
|
||||
wallet_address: String,
|
||||
|
||||
/// The port on which the gateway will be listening for sphinx packets
|
||||
#[clap(long)]
|
||||
@@ -36,27 +33,23 @@ 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<PathBuf>,
|
||||
datastore: 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>>,
|
||||
#[clap(long)]
|
||||
nym_apis: Option<String>,
|
||||
|
||||
/// Comma separated list of endpoints of the validator
|
||||
#[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>>,
|
||||
#[clap(long)]
|
||||
validators: Option<String>,
|
||||
|
||||
/// Cosmos wallet mnemonic needed for double spending protection
|
||||
#[clap(long)]
|
||||
mnemonic: Option<bip39::Mnemonic>,
|
||||
mnemonic: Option<String>,
|
||||
|
||||
/// Set this gateway to work only with coconut credentials; that would disallow clients to
|
||||
/// bypass bandwidth credential requirement
|
||||
@@ -70,7 +63,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<url::Url>,
|
||||
statistics_service_url: Option<String>,
|
||||
}
|
||||
|
||||
impl From<Init> for OverrideConfig {
|
||||
@@ -83,15 +76,14 @@ 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,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -167,19 +159,18 @@ mod tests {
|
||||
async fn create_gateway_with_in_mem_storage() {
|
||||
let args = Init {
|
||||
id: "foo-id".to_string(),
|
||||
host: "1.1.1.1".parse().unwrap(),
|
||||
wallet_address: "n1z9egw0knv47nmur0p8vk4rcx59h9gg4zjx9ede".parse().unwrap(),
|
||||
host: "foo-host".to_string(),
|
||||
wallet_address: "n1z9egw0knv47nmur0p8vk4rcx59h9gg4zjx9ede".to_string(),
|
||||
mix_port: Some(42),
|
||||
clients_port: Some(43),
|
||||
announce_host: Some("foo-announce-host".to_string()),
|
||||
datastore: Some("/foo-datastore".parse().unwrap()),
|
||||
datastore: Some("foo-datastore".to_string()),
|
||||
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");
|
||||
|
||||
+37
-34
@@ -1,20 +1,19 @@
|
||||
// Copyright 2020-2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// Copyright 2020 - 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, STATISTICS_SERVICE_DOMAIN_ADDRESS,
|
||||
API_VALIDATOR, BECH32_PREFIX, CONFIGURED, NYMD_VALIDATOR, 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;
|
||||
@@ -48,19 +47,18 @@ pub(crate) enum Commands {
|
||||
|
||||
// Configuration that can be overridden.
|
||||
pub(crate) struct OverrideConfig {
|
||||
host: Option<IpAddr>,
|
||||
wallet_address: Option<nymd::AccountId>,
|
||||
host: Option<String>,
|
||||
wallet_address: Option<String>,
|
||||
mix_port: Option<u16>,
|
||||
clients_port: Option<u16>,
|
||||
datastore: Option<PathBuf>,
|
||||
datastore: Option<String>,
|
||||
announce_host: Option<String>,
|
||||
enabled_statistics: Option<bool>,
|
||||
statistics_service_url: Option<url::Url>,
|
||||
nym_apis: Option<Vec<url::Url>>,
|
||||
mnemonic: Option<bip39::Mnemonic>,
|
||||
statistics_service_url: Option<String>,
|
||||
nym_apis: Option<String>,
|
||||
validators: Option<String>,
|
||||
mnemonic: Option<String>,
|
||||
|
||||
#[cfg(feature = "coconut")]
|
||||
nymd_validators: Option<Vec<url::Url>>,
|
||||
#[cfg(feature = "coconut")]
|
||||
only_coconut_credentials: bool,
|
||||
}
|
||||
@@ -74,8 +72,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::command(), bin_name),
|
||||
Commands::GenerateFigSpec => fig_generate(&mut crate::Cli::command(), bin_name),
|
||||
Commands::Completions(s) => s.generate(&mut crate::Cli::into_app(), bin_name),
|
||||
Commands::GenerateFigSpec => fig_generate(&mut crate::Cli::into_app(), bin_name),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,8 +103,12 @@ pub(crate) fn override_config(mut config: Config, args: OverrideConfig) -> Confi
|
||||
config = config.with_enabled_statistics(enabled_statistics);
|
||||
}
|
||||
|
||||
if let Some(url) = args.statistics_service_url {
|
||||
config = config.with_custom_statistics_service_url(url);
|
||||
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!"),
|
||||
);
|
||||
} 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(
|
||||
@@ -117,18 +119,26 @@ pub(crate) fn override_config(mut config: Config, args: OverrideConfig) -> Confi
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(nym_apis) = args.nym_apis {
|
||||
config = config.with_custom_nym_apis(nym_apis);
|
||||
if let Some(raw_validators) = args.nym_apis {
|
||||
config = config.with_custom_nym_apis(parse_validators(&raw_validators));
|
||||
} else if std::env::var(CONFIGURED).is_ok() {
|
||||
if let Some(raw_validators) = read_var_if_not_default(API_VALIDATOR) {
|
||||
config = config.with_custom_nym_apis(::config::parse_urls(&raw_validators))
|
||||
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))
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
let trimmed = wallet_address.trim();
|
||||
validate_bech32_address_or_exit(trimmed);
|
||||
config = config.with_wallet_address(trimmed);
|
||||
}
|
||||
|
||||
if let Some(datastore_path) = args.datastore {
|
||||
@@ -136,20 +146,13 @@ pub(crate) fn override_config(mut config: Config, args: OverrideConfig) -> Confi
|
||||
}
|
||||
|
||||
if let Some(cosmos_mnemonic) = args.mnemonic {
|
||||
config = config.with_cosmos_mnemonic(cosmos_mnemonic);
|
||||
config = config.with_cosmos_mnemonic(
|
||||
bip39::Mnemonic::from_str(&cosmos_mnemonic).expect("Provided mnemonic is invalid"),
|
||||
);
|
||||
}
|
||||
|
||||
#[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);
|
||||
}
|
||||
|
||||
|
||||
+15
-23
@@ -1,4 +1,4 @@
|
||||
// Copyright 2020-2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// Copyright 2020 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::{
|
||||
@@ -8,9 +8,6 @@ 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 {
|
||||
@@ -20,11 +17,11 @@ pub struct Run {
|
||||
|
||||
/// The custom host on which the gateway will be running for receiving sphinx packets
|
||||
#[clap(long)]
|
||||
host: Option<IpAddr>,
|
||||
host: Option<String>,
|
||||
|
||||
/// The wallet address you will use to bond this gateway, e.g. nymt1z9egw0knv47nmur0p8vk4rcx59h9gg4zuxrrr9
|
||||
#[clap(long)]
|
||||
wallet_address: Option<nymd::AccountId>,
|
||||
wallet_address: Option<String>,
|
||||
|
||||
/// The port on which the gateway will be listening for sphinx packets
|
||||
#[clap(long)]
|
||||
@@ -36,27 +33,23 @@ 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<PathBuf>,
|
||||
datastore: 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 nym APIs
|
||||
#[clap(long)]
|
||||
nym_apis: Option<String>,
|
||||
|
||||
/// Comma separated list of endpoints of the validator
|
||||
#[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>>,
|
||||
#[clap(long)]
|
||||
validators: Option<String>,
|
||||
|
||||
/// Cosmos wallet mnemonic
|
||||
#[clap(long)]
|
||||
mnemonic: Option<bip39::Mnemonic>,
|
||||
mnemonic: Option<String>,
|
||||
|
||||
/// Set this gateway to work only with coconut credentials; that would disallow clients to
|
||||
/// bypass bandwidth credential requirement
|
||||
@@ -70,7 +63,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<url::Url>,
|
||||
statistics_service_url: Option<String>,
|
||||
}
|
||||
|
||||
impl From<Run> for OverrideConfig {
|
||||
@@ -83,15 +76,14 @@ 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,9 +1,8 @@
|
||||
// Copyright 2020-2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// Copyright 2020 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::commands::validate_bech32_address_or_exit;
|
||||
use crate::{
|
||||
commands::version_check,
|
||||
commands::{validate_bech32_address_or_exit, version_check},
|
||||
config::{persistence::pathfinder::GatewayPathfinder, Config},
|
||||
};
|
||||
use anyhow::{anyhow, Result};
|
||||
@@ -11,10 +10,9 @@ use clap::{ArgGroup, Args};
|
||||
use config::NymConfig;
|
||||
use crypto::asymmetric::identity;
|
||||
use log::error;
|
||||
use validator_client::nymd;
|
||||
|
||||
#[derive(Args, Clone)]
|
||||
#[clap(group(ArgGroup::new("sign").required(true).args(&["wallet_address", "text"])))]
|
||||
#[clap(group(ArgGroup::new("sign").required(true).args(&["address", "text"])))]
|
||||
pub struct Sign {
|
||||
/// The id of the mixnode you want to sign with
|
||||
#[clap(long)]
|
||||
@@ -22,7 +20,7 @@ pub struct Sign {
|
||||
|
||||
/// Signs your blockchain address with your identity key
|
||||
#[clap(long)]
|
||||
wallet_address: Option<nymd::AccountId>,
|
||||
address: Option<String>,
|
||||
|
||||
/// Signs an arbitrary piece of text with your identity key
|
||||
#[clap(long)]
|
||||
@@ -31,7 +29,7 @@ pub struct Sign {
|
||||
|
||||
enum SignedTarget {
|
||||
Text(String),
|
||||
Address(nymd::AccountId),
|
||||
Address(String),
|
||||
}
|
||||
|
||||
impl TryFrom<Sign> for SignedTarget {
|
||||
@@ -40,7 +38,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.wallet_address {
|
||||
} else if let Some(address) = args.address {
|
||||
Ok(SignedTarget::Address(address))
|
||||
} else {
|
||||
// This is unreachable, and hopefully clap will support it explicitly by outputting an
|
||||
@@ -60,12 +58,15 @@ pub fn load_identity_keys(pathfinder: &GatewayPathfinder) -> identity::KeyPair {
|
||||
identity_keypair
|
||||
}
|
||||
|
||||
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());
|
||||
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);
|
||||
|
||||
let signature = private_key.sign_text(wallet_address.as_ref());
|
||||
println!("The base58-encoded signature on '{wallet_address}' is: {signature}",);
|
||||
println!(
|
||||
"The base58-encoded signature on '{}' is: {}",
|
||||
trimmed, signature
|
||||
);
|
||||
}
|
||||
|
||||
fn print_signed_text(private_key: &identity::PrivateKey, text: &str) {
|
||||
@@ -112,6 +113,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());
|
||||
let upgraded_config = config.with_custom_version(to_version.to_string().as_ref());
|
||||
|
||||
upgraded_config.save_to_file(None).unwrap_or_else(|err| {
|
||||
eprintln!("failed to overwrite config file! - {err}");
|
||||
|
||||
+21
-15
@@ -4,6 +4,7 @@
|
||||
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;
|
||||
@@ -11,7 +12,6 @@ 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,7 +149,6 @@ 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
|
||||
@@ -160,8 +159,16 @@ impl Config {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_listening_address(mut self, listening_address: IpAddr) -> Self {
|
||||
self.gateway.listening_address = listening_address;
|
||||
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
|
||||
);
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
@@ -185,18 +192,18 @@ impl Config {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_custom_persistent_store(mut self, store_dir: PathBuf) -> Self {
|
||||
self.gateway.persistent_storage = store_dir;
|
||||
pub fn with_custom_persistent_store<S: Into<String>>(mut self, store_dir: S) -> Self {
|
||||
self.gateway.persistent_storage = PathBuf::from(store_dir.into());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_custom_version<S: Into<String>>(mut self, version: S) -> Self {
|
||||
self.gateway.version = version.into();
|
||||
pub fn with_custom_version(mut self, version: &str) -> Self {
|
||||
self.gateway.version = version.to_string();
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_wallet_address(mut self, wallet_address: nymd::AccountId) -> Self {
|
||||
self.gateway.wallet_address = Some(wallet_address);
|
||||
pub fn with_wallet_address(mut self, wallet_address: &str) -> Self {
|
||||
self.gateway.wallet_address = wallet_address.to_string();
|
||||
self
|
||||
}
|
||||
|
||||
@@ -295,8 +302,8 @@ impl Config {
|
||||
&self.gateway.version
|
||||
}
|
||||
|
||||
pub fn get_wallet_address(&self) -> Option<nymd::AccountId> {
|
||||
self.gateway.wallet_address.clone()
|
||||
pub fn get_wallet_address(&self) -> &str {
|
||||
&self.gateway.wallet_address
|
||||
}
|
||||
}
|
||||
|
||||
@@ -370,8 +377,7 @@ pub struct Gateway {
|
||||
persistent_storage: PathBuf,
|
||||
|
||||
/// The Cosmos wallet address that will control this gateway
|
||||
// the only reason this is an Option is because of the lack of existence of a sane default value
|
||||
wallet_address: Option<nymd::AccountId>,
|
||||
wallet_address: String,
|
||||
}
|
||||
|
||||
impl Gateway {
|
||||
@@ -417,7 +423,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: None,
|
||||
wallet_address: "nymXXXXXXXX".to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+44
-11
@@ -1,28 +1,24 @@
|
||||
// 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;
|
||||
|
||||
lazy_static! {
|
||||
pub static ref PRETTY_BUILD_INFORMATION: String =
|
||||
BinaryBuildInformation::new(env!("CARGO_PKG_VERSION")).pretty_print();
|
||||
}
|
||||
static LONG_VERSION: OnceCell<String> = OnceCell::new();
|
||||
|
||||
// Helper for passing LONG_VERSION to clap
|
||||
fn pretty_build_info_static() -> &'static str {
|
||||
&PRETTY_BUILD_INFORMATION
|
||||
// Helper for passing LONG_ABOUT to clap
|
||||
fn long_version_static() -> &'static str {
|
||||
LONG_VERSION.get().expect("Failed to get long about text")
|
||||
}
|
||||
|
||||
#[derive(Parser)]
|
||||
#[clap(author = "Nymtech", version, about, long_version = pretty_build_info_static())]
|
||||
#[clap(author = "Nymtech", version, about, long_version = long_version_static())]
|
||||
struct Cli {
|
||||
/// Path pointing to an env file that configures the gateway.
|
||||
#[clap(short, long)]
|
||||
@@ -36,9 +32,12 @@ 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.as_ref());
|
||||
setup_env(args.config_env_file.clone());
|
||||
commands::execute(args).await;
|
||||
}
|
||||
|
||||
@@ -59,6 +58,37 @@ 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::*;
|
||||
@@ -66,6 +96,9 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn verify_cli() {
|
||||
LONG_VERSION
|
||||
.set(long_version())
|
||||
.expect("Failed to set long about text");
|
||||
Cli::command().debug_assert();
|
||||
}
|
||||
}
|
||||
|
||||
+9
-15
@@ -1,20 +1,19 @@
|
||||
// Copyright 2020-2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// Copyright 2020 - 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;
|
||||
@@ -22,15 +21,16 @@ 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,15 +117,9 @@ where
|
||||
fn generate_owner_signature(&self) -> String {
|
||||
let pathfinder = GatewayPathfinder::new_from_config(&self.config);
|
||||
let identity_keypair = load_identity_keys(&pathfinder);
|
||||
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());
|
||||
let address = self.config.get_wallet_address();
|
||||
validate_bech32_address_or_exit(address);
|
||||
let verification_code = identity_keypair.private_key().sign_text(address);
|
||||
verification_code
|
||||
}
|
||||
|
||||
|
||||
+5
-3
@@ -3,7 +3,7 @@
|
||||
|
||||
[package]
|
||||
name = "nym-mixnode"
|
||||
version = "1.1.4"
|
||||
version = "1.1.5"
|
||||
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 = "4.0", features = ["cargo", "derive"] }
|
||||
clap = { version = "3.2", features = ["cargo", "derive"] }
|
||||
colored = "2.0"
|
||||
cupid = "0.6.1"
|
||||
dirs = "4.0"
|
||||
@@ -38,7 +38,6 @@ 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" }
|
||||
@@ -58,3 +57,6 @@ 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"] }
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
// 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,6 +1,3 @@
|
||||
// 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;
|
||||
@@ -14,32 +11,9 @@ 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>,
|
||||
}
|
||||
|
||||
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) {
|
||||
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,
|
||||
@@ -49,29 +23,33 @@ 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";
|
||||
|
||||
// get input from the user if not provided via the arguments
|
||||
let name = args.name.unwrap_or_else(|| {
|
||||
print!("name: ");
|
||||
read_user_input()
|
||||
});
|
||||
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();
|
||||
|
||||
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()
|
||||
});
|
||||
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 node_description = NodeDescription {
|
||||
name,
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
// Copyright 2020-2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// Copyright 2020 - 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 std::net::IpAddr;
|
||||
use validator_client::nymd;
|
||||
|
||||
use super::OverrideConfig;
|
||||
|
||||
#[derive(Args, Clone)]
|
||||
pub(crate) struct Init {
|
||||
@@ -19,11 +18,11 @@ pub(crate) struct Init {
|
||||
|
||||
/// The host on which the mixnode will be running
|
||||
#[clap(long)]
|
||||
host: IpAddr,
|
||||
host: String,
|
||||
|
||||
/// The wallet address you will use to bond this mixnode, e.g. nymt1z9egw0knv47nmur0p8vk4rcx59h9gg4zuxrrr9
|
||||
#[clap(long)]
|
||||
wallet_address: nymd::AccountId,
|
||||
wallet_address: String,
|
||||
|
||||
/// The port on which the mixnode will be listening for mix packets
|
||||
#[clap(long)]
|
||||
@@ -41,10 +40,9 @@ pub(crate) struct Init {
|
||||
#[clap(long)]
|
||||
announce_host: 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>>,
|
||||
/// Comma separated list of rest endpoints of the validators
|
||||
#[clap(long)]
|
||||
validators: Option<String>,
|
||||
}
|
||||
|
||||
impl From<Init> for OverrideConfig {
|
||||
@@ -57,7 +55,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,
|
||||
nym_apis: init_config.nym_apis,
|
||||
validators: init_config.validators,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+24
-22
@@ -1,17 +1,19 @@
|
||||
// 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};
|
||||
use config::{
|
||||
defaults::var_names::{API_VALIDATOR, BECH32_PREFIX, CONFIGURED},
|
||||
parse_validators,
|
||||
};
|
||||
use crypto::bech32_address_validation;
|
||||
use std::net::IpAddr;
|
||||
use std::process;
|
||||
use validator_client::nymd;
|
||||
|
||||
mod describe;
|
||||
mod init;
|
||||
@@ -50,27 +52,27 @@ pub(crate) enum Commands {
|
||||
// Configuration that can be overridden.
|
||||
struct OverrideConfig {
|
||||
id: String,
|
||||
host: Option<IpAddr>,
|
||||
wallet_address: Option<nymd::AccountId>,
|
||||
host: Option<String>,
|
||||
wallet_address: Option<String>,
|
||||
mix_port: Option<u16>,
|
||||
verloc_port: Option<u16>,
|
||||
http_api_port: Option<u16>,
|
||||
announce_host: Option<String>,
|
||||
nym_apis: Option<Vec<url::Url>>,
|
||||
validators: Option<String>,
|
||||
}
|
||||
|
||||
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::command(), bin_name),
|
||||
Commands::GenerateFigSpec => fig_generate(&mut crate::Cli::command(), 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::into_app(), bin_name),
|
||||
Commands::GenerateFigSpec => fig_generate(&mut crate::Cli::into_app(), bin_name),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,11 +95,11 @@ fn override_config(mut config: Config, args: OverrideConfig) -> Config {
|
||||
config = config.with_http_api_port(port);
|
||||
}
|
||||
|
||||
if let Some(nym_apis) = args.nym_apis {
|
||||
config = config.with_custom_nym_apis(nym_apis);
|
||||
if let Some(ref raw_validators) = args.validators {
|
||||
config = config.with_custom_nym_apis(parse_validators(raw_validators));
|
||||
} else if std::env::var(CONFIGURED).is_ok() {
|
||||
if let Some(raw_validators) = read_var_if_not_default(API_VALIDATOR) {
|
||||
config = config.with_custom_nym_apis(::config::parse_urls(&raw_validators))
|
||||
config = config.with_custom_nym_apis(::config::parse_validators(&raw_validators))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,10 +110,10 @@ fn override_config(mut config: Config, args: OverrideConfig) -> Config {
|
||||
config = config.announce_address_from_listening_address()
|
||||
}
|
||||
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
config
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
// 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 std::net::IpAddr;
|
||||
use validator_client::nymd;
|
||||
|
||||
use super::OverrideConfig;
|
||||
|
||||
#[derive(Args, Clone)]
|
||||
pub(crate) struct Run {
|
||||
@@ -18,11 +17,11 @@ pub(crate) struct Run {
|
||||
|
||||
/// The custom host on which the mixnode will be running
|
||||
#[clap(long)]
|
||||
host: Option<IpAddr>,
|
||||
host: Option<String>,
|
||||
|
||||
/// The wallet address you will use to bond this mixnode, e.g. nymt1z9egw0knv47nmur0p8vk4rcx59h9gg4zuxrrr9
|
||||
#[clap(long)]
|
||||
wallet_address: Option<nymd::AccountId>,
|
||||
wallet_address: Option<String>,
|
||||
|
||||
/// The port on which the mixnode will be listening for mix packets
|
||||
#[clap(long)]
|
||||
@@ -40,10 +39,9 @@ pub(crate) struct Run {
|
||||
#[clap(long)]
|
||||
announce_host: 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>>,
|
||||
/// Comma separated list of rest endpoints of the validators
|
||||
#[clap(long)]
|
||||
validators: Option<String>,
|
||||
}
|
||||
|
||||
impl From<Run> for OverrideConfig {
|
||||
@@ -56,7 +54,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,
|
||||
nym_apis: run_config.nym_apis,
|
||||
validators: run_config.validators,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2020-2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// Copyright 2020 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use std::convert::TryFrom;
|
||||
@@ -11,21 +11,19 @@ use clap::{ArgGroup, Args};
|
||||
use config::NymConfig;
|
||||
use crypto::asymmetric::identity;
|
||||
use log::error;
|
||||
use validator_client::nymd;
|
||||
|
||||
use super::version_check;
|
||||
|
||||
#[derive(Args, Clone)]
|
||||
#[clap(group(ArgGroup::new("sign").required(true).args(&["wallet_address", "text"])))]
|
||||
#[clap(group(ArgGroup::new("sign").required(true).args(&["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
|
||||
// the alias here is included for backwards compatibility (1.1.4 and before)
|
||||
#[clap(long, alias = "address")]
|
||||
wallet_address: Option<nymd::AccountId>,
|
||||
#[clap(long)]
|
||||
address: Option<String>,
|
||||
|
||||
/// Signs an arbitrary piece of text with your identity key
|
||||
#[clap(long)]
|
||||
@@ -34,7 +32,7 @@ pub(crate) struct Sign {
|
||||
|
||||
enum SignedTarget {
|
||||
Text(String),
|
||||
Address(nymd::AccountId),
|
||||
Address(String),
|
||||
}
|
||||
|
||||
impl TryFrom<Sign> for SignedTarget {
|
||||
@@ -43,7 +41,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.wallet_address {
|
||||
} else if let Some(address) = args.address {
|
||||
Ok(SignedTarget::Address(address))
|
||||
} else {
|
||||
// This is unreachable, and hopefully clap will support it explicitly by outputting an
|
||||
@@ -54,12 +52,15 @@ impl TryFrom<Sign> for SignedTarget {
|
||||
}
|
||||
}
|
||||
|
||||
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());
|
||||
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);
|
||||
|
||||
let signature = private_key.sign_text(wallet_address.as_ref());
|
||||
println!("The base58-encoded signature on '{wallet_address}' is: {signature}",);
|
||||
println!(
|
||||
"The base58-encoded signature on '{}' is: {}",
|
||||
trimmed, signature
|
||||
);
|
||||
}
|
||||
|
||||
fn print_signed_text(private_key: &identity::PrivateKey, text: &str) {
|
||||
@@ -106,6 +107,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),
|
||||
}
|
||||
}
|
||||
|
||||
+16
-10
@@ -13,7 +13,6 @@ use std::path::PathBuf;
|
||||
use std::str::FromStr;
|
||||
use std::time::Duration;
|
||||
use url::Url;
|
||||
use validator_client::nymd;
|
||||
|
||||
pub mod persistence;
|
||||
mod template;
|
||||
@@ -161,8 +160,16 @@ impl Config {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_listening_address(mut self, listening_address: IpAddr) -> Self {
|
||||
self.mixnode.listening_address = listening_address;
|
||||
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
|
||||
)
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
@@ -196,8 +203,8 @@ impl Config {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_wallet_address(mut self, wallet_address: nymd::AccountId) -> Self {
|
||||
self.mixnode.wallet_address = Some(wallet_address);
|
||||
pub fn with_wallet_address(mut self, wallet_address: &str) -> Self {
|
||||
self.mixnode.wallet_address = wallet_address.to_string();
|
||||
self
|
||||
}
|
||||
|
||||
@@ -310,8 +317,8 @@ impl Config {
|
||||
self.verloc.retry_timeout
|
||||
}
|
||||
|
||||
pub fn get_wallet_address(&self) -> Option<nymd::AccountId> {
|
||||
self.mixnode.wallet_address.clone()
|
||||
pub fn get_wallet_address(&self) -> &str {
|
||||
&self.mixnode.wallet_address
|
||||
}
|
||||
}
|
||||
|
||||
@@ -370,8 +377,7 @@ struct MixNode {
|
||||
nym_root_directory: PathBuf,
|
||||
|
||||
/// The Cosmos wallet address that will control this mixnode
|
||||
// the only reason this is an Option is because of the lack of existence of a sane default value
|
||||
wallet_address: Option<nymd::AccountId>,
|
||||
wallet_address: String,
|
||||
}
|
||||
|
||||
impl MixNode {
|
||||
@@ -408,7 +414,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: None,
|
||||
wallet_address: "nymXXXXXXXX".to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+39
-10
@@ -1,11 +1,10 @@
|
||||
// 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;
|
||||
@@ -15,17 +14,16 @@ mod config;
|
||||
mod node;
|
||||
|
||||
lazy_static! {
|
||||
pub static ref PRETTY_BUILD_INFORMATION: String =
|
||||
BinaryBuildInformation::new(env!("CARGO_PKG_VERSION")).pretty_print();
|
||||
pub static ref LONG_VERSION: String = long_version();
|
||||
}
|
||||
|
||||
// Helper for passing LONG_VERSION to clap
|
||||
fn pretty_build_info_static() -> &'static str {
|
||||
&PRETTY_BUILD_INFORMATION
|
||||
fn long_version_static() -> &'static str {
|
||||
&LONG_VERSION
|
||||
}
|
||||
|
||||
#[derive(Parser)]
|
||||
#[clap(author = "Nymtech", version, about, long_version = pretty_build_info_static())]
|
||||
#[clap(author = "Nymtech", version, about, long_version = long_version_static())]
|
||||
struct Cli {
|
||||
/// Path pointing to an env file that configures the mixnode.
|
||||
#[clap(short, long)]
|
||||
@@ -41,7 +39,7 @@ async fn main() {
|
||||
println!("{}", banner());
|
||||
|
||||
let args = Cli::parse();
|
||||
setup_env(args.config_env_file.as_ref());
|
||||
setup_env(args.config_env_file.clone());
|
||||
commands::execute(args).await;
|
||||
}
|
||||
|
||||
@@ -62,6 +60,37 @@ 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::*;
|
||||
|
||||
+4
-14
@@ -18,7 +18,6 @@ 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};
|
||||
@@ -88,15 +87,9 @@ 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 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());
|
||||
let address = self.config.get_wallet_address();
|
||||
validate_bech32_address_or_exit(address);
|
||||
let verification_code = identity_keypair.private_key().sign_text(address);
|
||||
verification_code
|
||||
}
|
||||
|
||||
@@ -125,10 +118,7 @@ impl MixNode {
|
||||
);
|
||||
println!(
|
||||
"You are bonding to wallet address: {}\n\n",
|
||||
self.config
|
||||
.get_wallet_address()
|
||||
.map(|addr| addr.to_string())
|
||||
.unwrap_or_else(|| "UNSPECIFIED".to_string())
|
||||
self.config.get_wallet_address()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
+9
-6
@@ -2,8 +2,8 @@
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
[package]
|
||||
name = "nym-api"
|
||||
version = "1.1.4"
|
||||
name = "nym-validator-api"
|
||||
version = "1.1.5"
|
||||
authors = [
|
||||
"Dave Hrycyszyn <futurechimp@users.noreply.github.com>",
|
||||
"Jędrzej Stuczyński <andrew@nymtech.net>",
|
||||
@@ -17,15 +17,13 @@ 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 = "4.0", features = ["cargo", "derive"] }
|
||||
clap = { version = "3.2", features = ["cargo"] }
|
||||
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"
|
||||
@@ -65,7 +63,6 @@ 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 }
|
||||
@@ -118,6 +115,12 @@ 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,5 +1,6 @@
|
||||
use sqlx::{Connection, SqliteConnection};
|
||||
use std::env;
|
||||
use vergen::{vergen, Config};
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
@@ -22,4 +23,6 @@ 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,6 +446,8 @@ 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
|
||||
}
|
||||
|
||||
+262
-141
@@ -1,4 +1,4 @@
|
||||
// Copyright 2020-2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// Copyright 2020 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
#[macro_use]
|
||||
@@ -6,7 +6,6 @@ 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;
|
||||
@@ -16,12 +15,9 @@ use ::config::defaults::setup_env;
|
||||
use ::config::defaults::var_names::{CONFIGURED, MIXNET_CONTRACT_ADDRESS, MIX_DENOM};
|
||||
use ::config::NymConfig;
|
||||
use anyhow::Result;
|
||||
use build_information::BinaryBuildInformation;
|
||||
use clap::Parser;
|
||||
use clap::{crate_version, App, Arg, ArgMatches};
|
||||
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;
|
||||
@@ -30,21 +26,27 @@ 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::{wait_for_signal, TaskManager};
|
||||
use task::TaskManager;
|
||||
use tokio::sync::Notify;
|
||||
use validator_client::nymd::{self, SigningNymdClient};
|
||||
#[cfg(feature = "coconut")]
|
||||
use url::Url;
|
||||
use validator_client::nymd::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 rand::rngs::OsRng;
|
||||
use validator_client::nymd::bip32::secp256k1::elliptic_curve::rand_core::OsRng;
|
||||
|
||||
pub(crate) mod config;
|
||||
pub(crate) mod contract_cache;
|
||||
@@ -58,92 +60,150 @@ mod swagger;
|
||||
#[cfg(feature = "coconut")]
|
||||
mod coconut;
|
||||
|
||||
lazy_static! {
|
||||
pub static ref PRETTY_BUILD_INFORMATION: String =
|
||||
BinaryBuildInformation::new(env!("CARGO_PKG_VERSION")).pretty_print();
|
||||
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")
|
||||
)
|
||||
}
|
||||
|
||||
// Helper for passing LONG_VERSION to clap
|
||||
fn pretty_build_info_static() -> &'static str {
|
||||
&PRETTY_BUILD_INFORMATION
|
||||
}
|
||||
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")
|
||||
);
|
||||
|
||||
// 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")]
|
||||
#[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,
|
||||
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()
|
||||
}
|
||||
|
||||
async fn wait_for_interrupt(mut shutdown: TaskManager) {
|
||||
@@ -158,55 +218,122 @@ async fn wait_for_interrupt(mut shutdown: TaskManager) {
|
||||
log::info!("Stopping nym API");
|
||||
}
|
||||
|
||||
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)))
|
||||
#[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)))
|
||||
.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);
|
||||
}
|
||||
|
||||
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(MONITORING_ENABLED) {
|
||||
config = config.with_network_monitor_enabled(true)
|
||||
}
|
||||
|
||||
if let Some(mixnet_contract) = args.mixnet_contract {
|
||||
config = config.with_custom_mixnet_contract(mixnet_contract.to_string())
|
||||
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)
|
||||
} 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) = args.mnemonic {
|
||||
config = config.with_mnemonic(mnemonic.to_string())
|
||||
|
||||
if let Some(mnemonic) = matches.value_of(MNEMONIC_ARG) {
|
||||
config = config.with_mnemonic(mnemonic)
|
||||
}
|
||||
|
||||
if let Some(monitor_threshold) = args.monitor_threshold {
|
||||
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!"
|
||||
);
|
||||
config = config.with_minimum_interval_monitor_threshold(monitor_threshold)
|
||||
}
|
||||
|
||||
if let Some(reliability) = args.min_mixnode_reliability {
|
||||
config = config.with_min_mixnode_reliability(reliability)
|
||||
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_gateway_reliability {
|
||||
config = config.with_min_gateway_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!"),
|
||||
)
|
||||
}
|
||||
|
||||
#[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(ENABLED_CREDENTIALS_MODE_ARG_NAME) {
|
||||
config = config.with_disabled_credentials_mode(false)
|
||||
}
|
||||
|
||||
if args.save_config {
|
||||
if matches.is_present(WRITE_CONFIG_ARG) {
|
||||
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}");
|
||||
@@ -363,11 +490,11 @@ fn get_servers() -> Vec<rocket_okapi::okapi::openapi3::Server> {
|
||||
}]
|
||||
}
|
||||
|
||||
async fn run_nym_api(args: ApiArgs) -> Result<()> {
|
||||
async fn run_nym_api(matches: ArgMatches) -> 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 = args.id.as_deref();
|
||||
let id = matches.value_of(ID);
|
||||
let (config, _already_inited) = match Config::load_from_file(id) {
|
||||
Ok(cfg) => (cfg, true),
|
||||
Err(_) => {
|
||||
@@ -376,14 +503,14 @@ async fn run_nym_api(args: ApiArgs) -> Result<()> {
|
||||
.into_string()
|
||||
.unwrap();
|
||||
warn!(
|
||||
"Could not load the configuration file from {config_path}. Either the file did not exist or was malformed. Using the default values instead",
|
||||
"Could not load the configuration file from {}. Either the file did not exist or was malformed. Using the default values instead",
|
||||
config_path
|
||||
);
|
||||
(Config::new(), false)
|
||||
}
|
||||
};
|
||||
|
||||
let save_to_file = args.save_config;
|
||||
let config = override_config(config, args);
|
||||
let config = override_config(config, &matches);
|
||||
|
||||
#[cfg(feature = "coconut")]
|
||||
if !_already_inited {
|
||||
@@ -391,16 +518,9 @@ async fn run_nym_api(args: ApiArgs) -> Result<()> {
|
||||
}
|
||||
|
||||
// if we just wanted to write data to the config, exit
|
||||
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(());
|
||||
}
|
||||
if matches.is_present(WRITE_CONFIG_ARG) {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let mix_denom = std::env::var(MIX_DENOM).expect("mix denom not set");
|
||||
|
||||
let signing_nymd_client = Client::new_signing(&config);
|
||||
@@ -464,13 +584,11 @@ async fn run_nym_api(args: ApiArgs) -> Result<()> {
|
||||
tokio::spawn(async move { validator_cache_refresher.run(shutdown_listener).await });
|
||||
|
||||
// spawn rewarded set updater
|
||||
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() });
|
||||
}
|
||||
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.
|
||||
@@ -540,7 +658,10 @@ async fn main() -> Result<()> {
|
||||
}}
|
||||
|
||||
setup_logging();
|
||||
let args = ApiArgs::parse();
|
||||
setup_env(args.config_env_file.as_ref());
|
||||
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);
|
||||
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.3"
|
||||
resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283"
|
||||
integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==
|
||||
version "2.2.1"
|
||||
resolved "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz"
|
||||
integrity sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==
|
||||
|
||||
kleur@^3.0.3:
|
||||
version "3.0.3"
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
## UNRELEASED
|
||||
|
||||
## [nym-connect-v1.1.5](https://github.com/nymtech/nym/tree/nym-connect-v1.1.5) (2023-01-10)
|
||||
|
||||
- get version number from tauri and display by @fmtabbara in https://github.com/nymtech/nym/pull/2684
|
||||
- Feature/nym connect experimental software text by @fmtabbara in https://github.com/nymtech/nym/pull/2692
|
||||
- NymConnect - Display service info in tooltip **1.1.5 Release** by @fmtabbara in https://github.com/nymtech/nym/pull/2704
|
||||
- Feat/2130 tables update rebase by @gala1234 in https://github.com/nymtech/nym/pull/2742
|
||||
|
||||
## [nym-connect-v1.1.4](https://github.com/nymtech/nym/tree/nym-connect-v1.1.4) (2022-12-20)
|
||||
|
||||
This release contains the new opt-in Test & Earn program, and it uses a stress-tested directory of network requesters to improve reliability. It also has some bugfixes, performance improvements, and better error handling.
|
||||
|
||||
Generated
+22
-59
@@ -407,13 +407,6 @@ dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "build-information"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"vergen 7.4.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.11.0"
|
||||
@@ -573,33 +566,35 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.0.26"
|
||||
version = "3.2.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2148adefda54e14492fb9bddcc600b4344c5d1a3123bd666dcb939c6f0e0e57e"
|
||||
checksum = "86447ad904c7fb335a790c9d7fe3d0d971dc523b8ccd1561a520de9a85302750"
|
||||
dependencies = [
|
||||
"atty",
|
||||
"bitflags",
|
||||
"clap_derive",
|
||||
"clap_lex",
|
||||
"indexmap",
|
||||
"once_cell",
|
||||
"strsim",
|
||||
"termcolor",
|
||||
"textwrap",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_complete"
|
||||
version = "4.0.7"
|
||||
version = "3.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "10861370d2ba66b0f5989f83ebf35db6421713fd92351790e7fdd6c36774c56b"
|
||||
checksum = "3f7a2e0a962c45ce25afce14220bc24f9dade0a1787f185cecf96bfba7847cd8"
|
||||
dependencies = [
|
||||
"clap",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_complete_fig"
|
||||
version = "4.0.2"
|
||||
version = "3.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "46b30e010e669cd021e5004f3be26cff6b7c08d2a8a0d65b48d43a8cc0efd6c3"
|
||||
checksum = "ed37b4c0c1214673eba6ad8ea31666626bf72be98ffb323067d973c48b4964b9"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"clap_complete",
|
||||
@@ -607,9 +602,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "4.0.21"
|
||||
version = "3.2.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0177313f9f02afc995627906bbd8967e2be069f5261954222dac78290c2b9014"
|
||||
checksum = "ea0c8bce528c4be4da13ea6fead8965e95b6073585a2f05204bd8f4119f82a65"
|
||||
dependencies = [
|
||||
"heck 0.4.0",
|
||||
"proc-macro-error",
|
||||
@@ -620,9 +615,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap_lex"
|
||||
version = "0.3.0"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0d4198f73e42b4936b35b5bb248d81d2b595ecb170da0bac7655c54eedfa8da8"
|
||||
checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5"
|
||||
dependencies = [
|
||||
"os_str_bytes",
|
||||
]
|
||||
@@ -1588,16 +1583,7 @@ version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2953d1df47ac0eb70086ccabf0275aa8da8591a28bd358ee2b52bd9f9e3ff9e9"
|
||||
dependencies = [
|
||||
"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",
|
||||
"enum-iterator-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1611,17 +1597,6 @@ 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"
|
||||
@@ -3465,7 +3440,6 @@ dependencies = [
|
||||
name = "nym-socks5-client"
|
||||
version = "1.1.4"
|
||||
dependencies = [
|
||||
"build-information",
|
||||
"clap",
|
||||
"client-connections",
|
||||
"client-core",
|
||||
@@ -3477,7 +3451,6 @@ dependencies = [
|
||||
"futures",
|
||||
"gateway-client",
|
||||
"gateway-requests",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"logging",
|
||||
"network-defaults",
|
||||
@@ -3498,6 +3471,7 @@ dependencies = [
|
||||
"topology",
|
||||
"url",
|
||||
"validator-client",
|
||||
"vergen",
|
||||
"version-checker",
|
||||
]
|
||||
|
||||
@@ -6054,6 +6028,12 @@ 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"
|
||||
@@ -6558,7 +6538,7 @@ dependencies = [
|
||||
"anyhow",
|
||||
"cfg-if",
|
||||
"chrono",
|
||||
"enum-iterator 0.8.1",
|
||||
"enum-iterator",
|
||||
"getset",
|
||||
"git2",
|
||||
"rustc_version 0.4.0",
|
||||
@@ -6566,23 +6546,6 @@ 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"
|
||||
@@ -6619,7 +6582,7 @@ dependencies = [
|
||||
"schemars",
|
||||
"serde",
|
||||
"thiserror",
|
||||
"vergen 5.1.17",
|
||||
"vergen",
|
||||
"vesting-contract-common",
|
||||
]
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nym/nym-connect",
|
||||
"version": "1.1.4",
|
||||
"version": "1.1.5",
|
||||
"main": "index.js",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "nym-connect"
|
||||
version = "1.1.4"
|
||||
version = "1.1.5"
|
||||
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_urls(&raw_validators));
|
||||
.set_custom_nym_apis(config_common::parse_validators(&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,3 +1,4 @@
|
||||
use client_core::client::replies::reply_storage::fs_backend;
|
||||
use client_core::error::ClientCoreError;
|
||||
use serde::{Serialize, Serializer};
|
||||
use thiserror::Error;
|
||||
@@ -38,7 +39,7 @@ pub enum BackendError {
|
||||
#[error("{source}")]
|
||||
ClientCoreError {
|
||||
#[from]
|
||||
source: ClientCoreError,
|
||||
source: ClientCoreError<fs_backend::Backend>,
|
||||
},
|
||||
#[error("{source}")]
|
||||
ApiClientError {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"package": {
|
||||
"productName": "nym-connect",
|
||||
"version": "1.1.4"
|
||||
"version": "1.1.5"
|
||||
},
|
||||
"build": {
|
||||
"distDir": "../dist",
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import React from 'react';
|
||||
import { Box, CircularProgress, Typography } from '@mui/material';
|
||||
import { Box, CircularProgress, Divider, Stack, Tooltip, 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';
|
||||
@@ -14,8 +15,8 @@ const ConnectionStatusContent: React.FC<{
|
||||
switch (status) {
|
||||
case ConnectionStatusKind.connected:
|
||||
return (
|
||||
<Typography fontWeight={FONT_WEIGHT} fontStyle={FONT_STYLE} textAlign="center">
|
||||
Connected
|
||||
<Typography fontWeight={FONT_WEIGHT} fontStyle={FONT_STYLE} fontSize="14px">
|
||||
Connected to
|
||||
</Typography>
|
||||
);
|
||||
case ConnectionStatusKind.disconnecting:
|
||||
@@ -44,7 +45,7 @@ const ConnectionStatusContent: React.FC<{
|
||||
ml={1}
|
||||
textTransform="uppercase"
|
||||
textAlign="center"
|
||||
fontSize="10px"
|
||||
fontSize={FONT_SIZE}
|
||||
sx={{ wordSpacing: 3, letterSpacing: 2 }}
|
||||
>
|
||||
You are not protected
|
||||
@@ -59,7 +60,7 @@ export const ConnectionStatus: React.FC<{
|
||||
status: ConnectionStatusKind;
|
||||
connectedSince?: DateTime;
|
||||
serviceProvider?: ServiceProvider;
|
||||
}> = ({ status, connectedSince, serviceProvider }) => {
|
||||
}> = ({ status, serviceProvider }) => {
|
||||
const color =
|
||||
status === ConnectionStatusKind.connected || status === ConnectionStatusKind.disconnecting
|
||||
? '#21D072'
|
||||
@@ -70,13 +71,13 @@ export const ConnectionStatus: React.FC<{
|
||||
<Box color={color} fontSize={FONT_SIZE} sx={{ mb: 1 }}>
|
||||
<ConnectionStatusContent status={status} />
|
||||
</Box>
|
||||
<Box>
|
||||
{serviceProvider && (
|
||||
<Typography fontSize={12} textAlign="center">
|
||||
To {serviceProvider.description}
|
||||
</Typography>
|
||||
)}
|
||||
</Box>
|
||||
{serviceProvider ? (
|
||||
<Tooltip title={<ServiceProviderInfo serviceProvider={serviceProvider} />}>
|
||||
<Box sx={{ cursor: 'pointer' }}>
|
||||
{serviceProvider && <Typography>{serviceProvider.description}</Typography>}
|
||||
</Box>
|
||||
</Tooltip>
|
||||
) : null}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
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,6 +86,8 @@ 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,11 +37,13 @@ export const ConnectedLayout: React.FC<{
|
||||
}) => (
|
||||
<>
|
||||
<IpAddressAndPortModal show={showInfoModal} onClose={handleCloseInfoModal} ipAddress={ipAddress} port={port} />
|
||||
<Box pb={4}>
|
||||
<Box>
|
||||
<ConnectionStatus status={ConnectionStatusKind.connected} serviceProvider={serviceProvider} />
|
||||
</Box>
|
||||
<IpAddressAndPort label="Socks5 address" ipAddress={ipAddress} port={port} />
|
||||
<Divider sx={{ my: 3 }} />
|
||||
<Divider sx={{ my: 2 }} />
|
||||
<Box sx={{ mb: 3 }}>
|
||||
<IpAddressAndPort label="Socks5 address" ipAddress={ipAddress} port={port} />
|
||||
</Box>
|
||||
{/* <ConnectionStats stats={stats} /> */}
|
||||
<ConnectionTimer connectedSince={connectedSince} />
|
||||
<ConnectionButton status={status} busy={busy} onClick={onConnectClick} isError={isError} />
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user