Compare commits

..

27 Commits

Author SHA1 Message Date
Tommy Verrall 8c5f264cbf Update build-and-upload-binaries-ci.yml
change rust version due to wasm-opt issue
2023-06-07 10:50:18 +02:00
Jędrzej Stuczyński 73b74ad4d2 removed explicit packet_type argument when starting base client
it's known implicitly from the previously passed config struct
2023-06-05 10:07:15 +01:00
Jędrzej Stuczyński 4b4f211cba fixed wasm client build 2023-06-05 09:54:14 +01:00
Jędrzej Stuczyński 7a26e2ef57 clippy 2023-06-02 17:48:56 +01:00
Jędrzej Stuczyński 9782945c92 defined socks5 lib config 2023-06-02 17:32:46 +01:00
Jędrzej Stuczyński 573a91e015 outfox fixes 2023-06-02 16:32:50 +01:00
Jędrzej Stuczyński eb06285653 nym-connect config updates 2023-06-02 16:20:30 +01:00
Jędrzej Stuczyński 728542181e nym-connect clippy 2023-06-02 16:20:30 +01:00
Jędrzej Stuczyński 8f52c2a229 removed deprecations (that will be resolved in the following PRs) + fixed clippy 2023-06-02 16:20:30 +01:00
Jędrzej Stuczyński 3916bbf632 NR config migration 2023-06-02 16:20:30 +01:00
Jędrzej Stuczyński f8ce87a205 socks5 client config migration 2023-06-02 16:20:30 +01:00
Jędrzej Stuczyński c9b5ac2abf native client config migration 2023-06-02 16:20:30 +01:00
Jędrzej Stuczyński bd5577c0a4 nym-api config migration 2023-06-02 16:20:30 +01:00
Jędrzej Stuczyński 3e9178a664 gateway config migration 2023-06-02 16:20:30 +01:00
Jędrzej Stuczyński ac822164af mixnode config migration 2023-06-02 16:20:30 +01:00
Jędrzej Stuczyński edc404d6d7 renamed paths to storage_paths and fixed mixnode template 2023-06-02 16:20:30 +01:00
Jędrzej Stuczyński e0e5317b44 creating full directory structure on init 2023-06-02 16:20:30 +01:00
Jędrzej Stuczyński 6711a3bb3c everything compiling once more
but definitely not compatible with CI and older versions (yet)
2023-06-02 16:20:28 +01:00
Jędrzej Stuczyński 20130fb2a2 nym-sdk 2023-06-02 16:19:18 +01:00
Jędrzej Stuczyński 59560ac125 nym-api 2023-06-02 16:18:42 +01:00
Jędrzej Stuczyński 893648cad0 compiling updated gateway 2023-06-02 16:17:57 +01:00
Jędrzej Stuczyński 27502b9c75 using const for mixnnode config template 2023-06-02 16:17:57 +01:00
Jędrzej Stuczyński 2ab4a445b7 building socks5 2023-06-02 16:17:55 +01:00
Jędrzej Stuczyński 7f5e2f2909 wip 2023-06-02 16:16:18 +01:00
Jędrzej Stuczyński d5bc26d2e3 native client config revamping 2023-06-02 16:13:25 +01:00
Jędrzej Stuczyński aaa965937b wip 2023-06-02 16:12:49 +01:00
Jędrzej Stuczyński b3f883e82b revamping mixnode connfig 2023-06-02 16:09:01 +01:00
238 changed files with 7258 additions and 7692 deletions
@@ -107,8 +107,6 @@ jobs:
cp contracts/target/wasm32-unknown-unknown/release/nym_coconut_dkg.wasm $OUTPUT_DIR cp contracts/target/wasm32-unknown-unknown/release/nym_coconut_dkg.wasm $OUTPUT_DIR
cp contracts/target/wasm32-unknown-unknown/release/cw3_flex_multisig.wasm $OUTPUT_DIR cp contracts/target/wasm32-unknown-unknown/release/cw3_flex_multisig.wasm $OUTPUT_DIR
cp contracts/target/wasm32-unknown-unknown/release/cw4_group.wasm $OUTPUT_DIR cp contracts/target/wasm32-unknown-unknown/release/cw4_group.wasm $OUTPUT_DIR
cp contracts/target/wasm32-unknown-unknown/release/nym_service_provider_directory.wasm $OUTPUT_DIR
cp contracts/target/wasm32-unknown-unknown/release/nym_name_service.wasm $OUTPUT_DIR
- name: Deploy branch to CI www - name: Deploy branch to CI www
continue-on-error: true continue-on-error: true
-30
View File
@@ -4,36 +4,6 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
## [Unreleased] ## [Unreleased]
## [v1.1.20] (2023-06-06)
- Explorer - Fix SP supported apps list ([#3458])
- Investigate if we need to lower `SHUTDOWN_TIMEOUT` in socks5 to zero (or almost zero) ([#3438])
- Explorer - show all gateways in the default view regardless of the version number ([#3427])
- service-provider-directory: add signature check when announcing ([#3360])
- Support functionality for nym-name-service (nym-api, nym-cli, etc) ([#3355])
- Edit the nym-network-requester to support the enabled-credentials-mode flag ([#3101])
- [BUG] network requester documentation update ([#3493])
- removing hardcoded version numbers ([#3485])
- [BUG] network requester documentation update ([#3481])
- [BUG] network requester documentation update ([#3469])
- Sign when announcing service providers to the directory contract ([#3459])
- mixnode documentation update ([#3435])
- updated readme with new developer chat links + new docs links ([#3141])
[#3458]: https://github.com/nymtech/nym/issues/3458
[#3438]: https://github.com/nymtech/nym/issues/3438
[#3427]: https://github.com/nymtech/nym/issues/3427
[#3360]: https://github.com/nymtech/nym/issues/3360
[#3355]: https://github.com/nymtech/nym/issues/3355
[#3101]: https://github.com/nymtech/nym/issues/3101
[#3493]: https://github.com/nymtech/nym/pull/3493
[#3485]: https://github.com/nymtech/nym/pull/3485
[#3481]: https://github.com/nymtech/nym/pull/3481
[#3469]: https://github.com/nymtech/nym/pull/3469
[#3459]: https://github.com/nymtech/nym/pull/3459
[#3435]: https://github.com/nymtech/nym/pull/3435
[#3141]: https://github.com/nymtech/nym/pull/3141
## [v1.1.19] (2023-05-16) ## [v1.1.19] (2023-05-16)
- nym-name-service endpoint in nym-api ([#3403]) - nym-name-service endpoint in nym-api ([#3403])
Generated
+112 -52
View File
@@ -1243,20 +1243,6 @@ dependencies = [
"zeroize", "zeroize",
] ]
[[package]]
name = "cw-controllers"
version = "0.13.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4f0bc6019b4d3d81e11f5c384bcce7173e2210bd654d75c6c9668e12cca05dfa"
dependencies = [
"cosmwasm-std",
"cw-storage-plus",
"cw-utils",
"schemars",
"serde",
"thiserror",
]
[[package]] [[package]]
name = "cw-storage-plus" name = "cw-storage-plus"
version = "0.13.4" version = "0.13.4"
@@ -1451,7 +1437,16 @@ version = "4.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059"
dependencies = [ dependencies = [
"dirs-sys", "dirs-sys 0.3.7",
]
[[package]]
name = "dirs"
version = "5.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225"
dependencies = [
"dirs-sys 0.4.1",
] ]
[[package]] [[package]]
@@ -1465,6 +1460,18 @@ dependencies = [
"winapi", "winapi",
] ]
[[package]]
name = "dirs-sys"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c"
dependencies = [
"libc",
"option-ext",
"redox_users",
"windows-sys 0.48.0",
]
[[package]] [[package]]
name = "doc-comment" name = "doc-comment"
version = "0.3.3" version = "0.3.3"
@@ -1646,7 +1653,7 @@ checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0"
[[package]] [[package]]
name = "explorer-api" name = "explorer-api"
version = "1.1.20" version = "1.1.19"
dependencies = [ dependencies = [
"chrono", "chrono",
"clap 4.2.7", "clap 4.2.7",
@@ -1755,7 +1762,7 @@ dependencies = [
"atomic", "atomic",
"pear", "pear",
"serde", "serde",
"toml", "toml 0.5.11",
"uncased", "uncased",
"version_check", "version_check",
] ]
@@ -3190,7 +3197,7 @@ dependencies = [
[[package]] [[package]]
name = "nym-api" name = "nym-api"
version = "1.1.21" version = "1.1.20"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"async-trait", "async-trait",
@@ -3203,7 +3210,7 @@ dependencies = [
"cw-utils", "cw-utils",
"cw3", "cw3",
"cw4", "cw4",
"dirs", "dirs 4.0.0",
"futures", "futures",
"getset", "getset",
"humantime-serde", "humantime-serde",
@@ -3255,6 +3262,7 @@ dependencies = [
"tokio-stream", "tokio-stream",
"ts-rs", "ts-rs",
"url", "url",
"zeroize",
] ]
[[package]] [[package]]
@@ -3324,7 +3332,7 @@ dependencies = [
[[package]] [[package]]
name = "nym-cli" name = "nym-cli"
version = "1.1.20" version = "1.1.19"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"base64 0.13.1", "base64 0.13.1",
@@ -3373,7 +3381,6 @@ dependencies = [
"nym-name-service-common", "nym-name-service-common",
"nym-network-defaults", "nym-network-defaults",
"nym-service-provider-directory-common", "nym-service-provider-directory-common",
"nym-sphinx",
"nym-validator-client", "nym-validator-client",
"nym-vesting-contract-common", "nym-vesting-contract-common",
"rand 0.6.5", "rand 0.6.5",
@@ -3382,16 +3389,16 @@ dependencies = [
"tap", "tap",
"thiserror", "thiserror",
"time 0.3.21", "time 0.3.21",
"toml", "toml 0.5.11",
"url", "url",
] ]
[[package]] [[package]]
name = "nym-client" name = "nym-client"
version = "1.1.20" version = "1.1.19"
dependencies = [ dependencies = [
"clap 4.2.7", "clap 4.2.7",
"dirs", "dirs 4.0.0",
"futures", "futures",
"lazy_static", "lazy_static",
"log", "log",
@@ -3428,7 +3435,7 @@ version = "1.1.14"
dependencies = [ dependencies = [
"async-trait", "async-trait",
"dashmap 5.4.0", "dashmap 5.4.0",
"dirs", "dirs 4.0.0",
"futures", "futures",
"gloo-timers", "gloo-timers",
"humantime-serde", "humantime-serde",
@@ -3535,18 +3542,18 @@ dependencies = [
name = "nym-config" name = "nym-config"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"cfg-if", "dirs 5.0.1",
"handlebars", "handlebars",
"log", "log",
"nym-network-defaults", "nym-network-defaults",
"serde", "serde",
"toml", "toml 0.7.4",
"url", "url",
] ]
[[package]] [[package]]
name = "nym-contracts-common" name = "nym-contracts-common"
version = "0.5.0" version = "0.4.0"
dependencies = [ dependencies = [
"bs58", "bs58",
"cosmwasm-std", "cosmwasm-std",
@@ -3564,6 +3571,7 @@ dependencies = [
"log", "log",
"nym-bandwidth-controller", "nym-bandwidth-controller",
"nym-bin-common", "nym-bin-common",
"nym-client-core",
"nym-config", "nym-config",
"nym-credential-storage", "nym-credential-storage",
"nym-credentials", "nym-credentials",
@@ -3602,7 +3610,7 @@ dependencies = [
[[package]] [[package]]
name = "nym-crypto" name = "nym-crypto"
version = "0.4.0" version = "0.3.0"
dependencies = [ dependencies = [
"aes 0.8.2", "aes 0.8.2",
"blake3", "blake3",
@@ -3659,7 +3667,7 @@ dependencies = [
[[package]] [[package]]
name = "nym-gateway" name = "nym-gateway"
version = "1.1.20" version = "1.1.19"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"async-trait", "async-trait",
@@ -3669,7 +3677,7 @@ dependencies = [
"clap 4.2.7", "clap 4.2.7",
"colored", "colored",
"dashmap 4.0.2", "dashmap 4.0.2",
"dirs", "dirs 4.0.0",
"dotenvy", "dotenvy",
"futures", "futures",
"humantime-serde", "humantime-serde",
@@ -3791,7 +3799,7 @@ dependencies = [
[[package]] [[package]]
name = "nym-mixnet-contract-common" name = "nym-mixnet-contract-common"
version = "0.6.0" version = "0.5.0"
dependencies = [ dependencies = [
"bs58", "bs58",
"cosmwasm-std", "cosmwasm-std",
@@ -3810,7 +3818,7 @@ dependencies = [
[[package]] [[package]]
name = "nym-mixnode" name = "nym-mixnode"
version = "1.1.21" version = "1.1.20"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"bs58", "bs58",
@@ -3819,7 +3827,7 @@ dependencies = [
"colored", "colored",
"cpu-cycles", "cpu-cycles",
"cupid", "cupid",
"dirs", "dirs 4.0.0",
"futures", "futures",
"humantime-serde", "humantime-serde",
"lazy_static", "lazy_static",
@@ -3848,7 +3856,7 @@ dependencies = [
"sysinfo", "sysinfo",
"tokio", "tokio",
"tokio-util", "tokio-util",
"toml", "toml 0.5.11",
"tracing", "tracing",
"url", "url",
] ]
@@ -3920,13 +3928,12 @@ dependencies = [
[[package]] [[package]]
name = "nym-network-requester" name = "nym-network-requester"
version = "1.1.20" version = "1.1.19"
dependencies = [ dependencies = [
"async-file-watcher", "async-file-watcher",
"async-trait", "async-trait",
"bs58",
"clap 4.2.7", "clap 4.2.7",
"dirs", "dirs 4.0.0",
"futures", "futures",
"humantime-serde", "humantime-serde",
"ipnetwork 0.20.0", "ipnetwork 0.20.0",
@@ -3947,13 +3954,11 @@ dependencies = [
"nym-sphinx", "nym-sphinx",
"nym-statistics-common", "nym-statistics-common",
"nym-task", "nym-task",
"nym-types",
"pretty_env_logger", "pretty_env_logger",
"publicsuffix", "publicsuffix",
"rand 0.7.3", "rand 0.7.3",
"reqwest", "reqwest",
"serde", "serde",
"serde_json",
"sqlx 0.6.3", "sqlx 0.6.3",
"tap", "tap",
"tempfile", "tempfile",
@@ -3965,9 +3970,9 @@ dependencies = [
[[package]] [[package]]
name = "nym-network-statistics" name = "nym-network-statistics"
version = "1.1.20" version = "1.1.19"
dependencies = [ dependencies = [
"dirs", "dirs 4.0.0",
"log", "log",
"nym-bin-common", "nym-bin-common",
"nym-statistics-common", "nym-statistics-common",
@@ -4040,7 +4045,7 @@ dependencies = [
[[package]] [[package]]
name = "nym-pemstore" name = "nym-pemstore"
version = "0.3.0" version = "0.2.0"
dependencies = [ dependencies = [
"pem", "pem",
] ]
@@ -4072,7 +4077,7 @@ dependencies = [
"tap", "tap",
"thiserror", "thiserror",
"tokio", "tokio",
"toml", "toml 0.5.11",
"url", "url",
] ]
@@ -4081,12 +4086,8 @@ name = "nym-service-provider-directory-common"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"cosmwasm-std", "cosmwasm-std",
"cw-controllers",
"cw-utils",
"nym-contracts-common",
"schemars", "schemars",
"serde", "serde",
"thiserror",
] ]
[[package]] [[package]]
@@ -4107,7 +4108,7 @@ dependencies = [
[[package]] [[package]]
name = "nym-socks5-client" name = "nym-socks5-client"
version = "1.1.20" version = "1.1.19"
dependencies = [ dependencies = [
"clap 4.2.7", "clap 4.2.7",
"lazy_static", "lazy_static",
@@ -4139,7 +4140,7 @@ dependencies = [
name = "nym-socks5-client-core" name = "nym-socks5-client-core"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"dirs", "dirs 4.0.0",
"futures", "futures",
"log", "log",
"nym-bandwidth-controller", "nym-bandwidth-controller",
@@ -4180,6 +4181,7 @@ dependencies = [
"openssl", "openssl",
"rand 0.7.3", "rand 0.7.3",
"safer-ffi", "safer-ffi",
"serde",
"tokio", "tokio",
] ]
@@ -4503,7 +4505,7 @@ dependencies = [
[[package]] [[package]]
name = "nym-vesting-contract-common" name = "nym-vesting-contract-common"
version = "0.7.0" version = "0.6.0"
dependencies = [ dependencies = [
"cosmwasm-std", "cosmwasm-std",
"nym-contracts-common", "nym-contracts-common",
@@ -4666,6 +4668,12 @@ dependencies = [
"thiserror", "thiserror",
] ]
[[package]]
name = "option-ext"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
[[package]] [[package]]
name = "os_str_bytes" name = "os_str_bytes"
version = "6.5.0" version = "6.5.0"
@@ -6039,6 +6047,15 @@ dependencies = [
"syn 2.0.16", "syn 2.0.16",
] ]
[[package]]
name = "serde_spanned"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93107647184f6027e3b7dcb2e11034cf95ffa1e3a682c67951963ac69c1c007d"
dependencies = [
"serde",
]
[[package]] [[package]]
name = "serde_urlencoded" name = "serde_urlencoded"
version = "0.7.1" version = "0.7.1"
@@ -6667,7 +6684,7 @@ dependencies = [
"serde", "serde",
"serde_json", "serde_json",
"tendermint", "tendermint",
"toml", "toml 0.5.11",
"url", "url",
] ]
@@ -6990,6 +7007,40 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "toml"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d6135d499e69981f9ff0ef2167955a5333c35e36f6937d382974566b3d5b94ec"
dependencies = [
"serde",
"serde_spanned",
"toml_datetime",
"toml_edit",
]
[[package]]
name = "toml_datetime"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a76a9312f5ba4c2dec6b9161fdf25d87ad8a09256ccea5a556fef03c706a10f"
dependencies = [
"serde",
]
[[package]]
name = "toml_edit"
version = "0.19.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2380d56e8670370eee6566b0bfd4265f65b3f432e8c6d85623f728d4fa31f739"
dependencies = [
"indexmap",
"serde",
"serde_spanned",
"toml_datetime",
"winnow",
]
[[package]] [[package]]
name = "tonic" name = "tonic"
version = "0.9.2" version = "0.9.2"
@@ -7809,6 +7860,15 @@ version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
[[package]]
name = "winnow"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61de7bac303dc551fe038e2b3cef0f571087a47571ea6e79a87692ac99b99699"
dependencies = [
"memchr",
]
[[package]] [[package]]
name = "winreg" name = "winreg"
version = "0.10.1" version = "0.10.1"
+1 -2
View File
@@ -120,9 +120,8 @@ cosmwasm-derive = "=1.0.0"
cosmwasm-schema = "=1.0.0" cosmwasm-schema = "=1.0.0"
cosmwasm-std = "=1.0.0" cosmwasm-std = "=1.0.0"
cosmwasm-storage = "=1.0.0" cosmwasm-storage = "=1.0.0"
cw-controllers = "=0.13.4"
cw-storage-plus = "=0.13.4"
cw-utils = "=0.13.4" cw-utils = "=0.13.4"
cw-storage-plus = "=0.13.4"
cw2 = { version = "=0.13.4" } cw2 = { version = "=0.13.4" }
cw3 = { version = "=0.13.4" } cw3 = { version = "=0.13.4" }
cw3-fixed-multisig = { version = "=0.13.4" } cw3-fixed-multisig = { version = "=0.13.4" }
+2 -6
View File
@@ -22,7 +22,7 @@ The platform is composed of multiple Rust crates. Top-level executable binary cr
### Building ### Building
Platform build instructions are available on [our docs site](https://nymtech.net/docs/binaries/building-nym.html). Platform build instructions are available on [our docs site](https://nymtech.net/docs/binaries/building-nym.html).
Wallet build instructions are also available on [our docs site](https://nymtech.net/docs/wallet/desktop-wallet.html). Wallet build instructions are also available on [our docs site](https://nymtech.net/docs/stable/nym-apps/wallet#for-developers).
### Developing ### Developing
@@ -32,11 +32,7 @@ For Typescript components, please see [ts-packages](./ts-packages).
### Developer chat ### Developer chat
> We used to use Keybase for developer chats, but we have since migrated to Matrix and Discord. We no longer check the old **nymtech.friends** Keybase team. You can chat with us in [Keybase](https://keybase.io). Download their chat app, then click **Teams -> Join a team**. Type **nymtech.friends** into the team name and hit **continue**. For general chat, hang out in the **#general** channel. Our development takes place in the **#dev** channel. Node operators should be in the **#node-operators** channel.
You can chat to us in two places:
* The #dev channel on [Matrix](https://matrix.to/#/#dev:nymtech.chat)
* The various developer channels on [Discord](https://discord.gg/nym)
### Rewards ### Rewards
+2
View File
@@ -12,7 +12,9 @@ serde = { workspace = true, features = ["derive"] }
thiserror = "1.0" thiserror = "1.0"
tokio = { version = "1.24.1", features = ["rt-multi-thread", "net", "signal", "macros"] } # async runtime tokio = { version = "1.24.1", features = ["rt-multi-thread", "net", "signal", "macros"] } # async runtime
nym-bandwidth-controller = { path = "../../common/bandwidth-controller" } nym-bandwidth-controller = { path = "../../common/bandwidth-controller" }
nym-client-core = { path = "../../common/client-core" }
nym-config = { path = "../../common/config" } nym-config = { path = "../../common/config" }
nym-credentials = { path = "../../common/credentials" } nym-credentials = { path = "../../common/credentials" }
nym-credential-storage = { path = "../../common/credential-storage" } nym-credential-storage = { path = "../../common/credential-storage" }
+8 -6
View File
@@ -1,4 +1,4 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net> // Copyright 2022-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
mod commands; mod commands;
@@ -9,13 +9,14 @@ use commands::*;
use error::Result; use error::Result;
use log::*; use log::*;
use nym_bin_common::completions::fig_generate; use nym_bin_common::completions::fig_generate;
use nym_config::{CRED_DB_FILE_NAME, DATA_DIR}; use nym_config::DEFAULT_DATA_DIR;
use nym_network_defaults::{setup_env, NymNetworkDetails}; use nym_network_defaults::{setup_env, NymNetworkDetails};
use std::process::exit; use std::process::exit;
use std::time::{Duration, SystemTime}; use std::time::{Duration, SystemTime};
use clap::{CommandFactory, Parser}; use clap::{CommandFactory, Parser};
use nym_bin_common::logging::setup_logging; use nym_bin_common::logging::setup_logging;
use nym_client_core::config::disk_persistence::CommonClientPaths;
use nym_validator_client::nyxd::traits::DkgQueryClient; use nym_validator_client::nyxd::traits::DkgQueryClient;
use nym_validator_client::nyxd::{Coin, CosmWasmClient}; use nym_validator_client::nyxd::{Coin, CosmWasmClient};
use nym_validator_client::Config; use nym_validator_client::Config;
@@ -71,10 +72,11 @@ async fn main() -> Result<()> {
match args.command { match args.command {
Command::Run(r) => { Command::Run(r) => {
let db_path = r // we assume the structure of <home-dir>/data
.client_home_directory let data_dir = r.client_home_directory.join(DEFAULT_DATA_DIR);
.join(DATA_DIR) let paths = CommonClientPaths::new_default(data_dir);
.join(CRED_DB_FILE_NAME); let db_path = paths.credentials_database;
let shared_storage = let shared_storage =
nym_credential_storage::initialise_persistent_storage(db_path).await; nym_credential_storage::initialise_persistent_storage(db_path).await;
let recovery_storage = recovery_storage::RecoveryStorage::new(r.recovery_dir)?; let recovery_storage = recovery_storage::RecoveryStorage::new(r.recovery_dir)?;
+1 -1
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "nym-client" name = "nym-client"
version = "1.1.20" version = "1.1.19"
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jędrzej Stuczyński <andrew@nymtech.net>"] authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jędrzej Stuczyński <andrew@nymtech.net>"]
description = "Implementation of the Nym Client" description = "Implementation of the Nym Client"
edition = "2021" edition = "2021"
+82 -92
View File
@@ -1,23 +1,57 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net> // Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use crate::client::config::template::config_template; use crate::client::config::persistence::ClientPaths;
use nym_client_core::config::ClientCoreConfigTrait; use crate::client::config::template::CONFIG_TEMPLATE;
use nym_bin_common::logging::LoggingSettings;
use nym_config::defaults::DEFAULT_WEBSOCKET_LISTENING_PORT; use nym_config::defaults::DEFAULT_WEBSOCKET_LISTENING_PORT;
use nym_config::{NymConfig, OptionalSet}; use nym_config::{
must_get_home, read_config_from_toml_file, save_formatted_config_to_file, NymConfigTemplate,
OptionalSet, DEFAULT_CONFIG_DIR, DEFAULT_CONFIG_FILENAME, DEFAULT_DATA_DIR, NYM_DIR,
};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::fmt::Debug; use std::fmt::Debug;
use std::io;
use std::net::{IpAddr, Ipv4Addr}; use std::net::{IpAddr, Ipv4Addr};
use std::path::PathBuf; use std::path::{Path, PathBuf};
use std::str::FromStr; use std::str::FromStr;
pub use nym_client_core::config::Config as BaseConfig; pub use nym_client_core::config::Config as BaseClientConfig;
pub use nym_client_core::config::MISSING_VALUE;
pub use nym_client_core::config::{DebugConfig, GatewayEndpointConfig}; pub use nym_client_core::config::{DebugConfig, GatewayEndpointConfig};
pub mod old_config_v1_1_13; pub mod old_config_v1_1_13;
pub mod old_config_v1_1_19;
mod persistence;
mod template; mod template;
const DEFAULT_CLIENTS_DIR: &str = "clients";
/// Derive default path to clients's config directory.
/// It should get resolved to `$HOME/.nym/mixnodes/<id>/config`
pub fn default_config_directory<P: AsRef<Path>>(id: P) -> PathBuf {
must_get_home()
.join(NYM_DIR)
.join(DEFAULT_CLIENTS_DIR)
.join(id)
.join(DEFAULT_CONFIG_DIR)
}
/// Derive default path to client's config file.
/// It should get resolved to `$HOME/.nym/clients/<id>/config/config.toml`
pub fn default_config_filepath<P: AsRef<Path>>(id: P) -> PathBuf {
default_config_directory(id).join(DEFAULT_CONFIG_FILENAME)
}
/// Derive default path to client's data directory where files, such as keys, are stored.
/// It should get resolved to `$HOME/.nym/clients/<id>/data`
pub fn default_data_directory<P: AsRef<Path>>(id: P) -> PathBuf {
must_get_home()
.join(NYM_DIR)
.join(DEFAULT_CLIENTS_DIR)
.join(id)
.join(DEFAULT_DATA_DIR)
}
#[derive(Debug, Deserialize, PartialEq, Eq, Serialize, Clone, Copy)] #[derive(Debug, Deserialize, PartialEq, Eq, Serialize, Clone, Copy)]
#[serde(deny_unknown_fields)] #[serde(deny_unknown_fields)]
pub enum SocketType { pub enum SocketType {
@@ -26,74 +60,57 @@ pub enum SocketType {
} }
impl SocketType { impl SocketType {
pub fn from_string<S: Into<String>>(val: S) -> Self {
let mut upper = val.into();
upper.make_ascii_uppercase();
match upper.as_ref() {
"WEBSOCKET" | "WS" => SocketType::WebSocket,
_ => SocketType::None,
}
}
pub fn is_websocket(&self) -> bool { pub fn is_websocket(&self) -> bool {
matches!(self, SocketType::WebSocket) matches!(self, SocketType::WebSocket)
} }
} }
#[derive(Debug, Default, Deserialize, PartialEq, Serialize)] #[derive(Debug, Deserialize, PartialEq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct Config { pub struct Config {
#[serde(flatten)] #[serde(flatten)]
base: BaseConfig<Config>, pub base: BaseClientConfig,
socket: Socket, pub socket: Socket,
// pub paths: CommonClientPathfinder,
pub storage_paths: ClientPaths,
pub logging: LoggingSettings,
} }
impl NymConfig for Config { impl NymConfigTemplate for Config {
fn template() -> &'static str { fn template() -> &'static str {
config_template() CONFIG_TEMPLATE
}
fn default_root_directory() -> PathBuf {
dirs::home_dir()
.expect("Failed to evaluate $HOME value")
.join(".nym")
.join("clients")
}
fn try_default_root_directory() -> Option<PathBuf> {
dirs::home_dir().map(|path| path.join(".nym").join("clients"))
}
fn root_directory(&self) -> PathBuf {
self.base.get_nym_root_directory()
}
fn config_directory(&self) -> PathBuf {
self.root_directory()
.join(self.base.get_id())
.join("config")
}
fn data_directory(&self) -> PathBuf {
self.root_directory().join(self.base.get_id()).join("data")
}
}
impl ClientCoreConfigTrait for Config {
fn get_gateway_endpoint(&self) -> &nym_client_core::config::GatewayEndpointConfig {
self.base.get_gateway_endpoint()
} }
} }
impl Config { impl Config {
pub fn new<S: Into<String>>(id: S) -> Self { pub fn new<S: AsRef<str>>(id: S) -> Self {
Config { Config {
base: BaseConfig::new(id), base: BaseClientConfig::new(id.as_ref()),
storage_paths: ClientPaths::new_default(default_data_directory(id.as_ref())),
logging: Default::default(),
socket: Default::default(), socket: Default::default(),
} }
} }
pub fn read_from_toml_file<P: AsRef<Path>>(path: P) -> io::Result<Self> {
read_config_from_toml_file(path)
}
pub fn read_from_default_path<P: AsRef<Path>>(id: P) -> io::Result<Self> {
Self::read_from_toml_file(default_config_filepath(id))
}
pub fn default_location(&self) -> PathBuf {
default_config_filepath(&self.base.client.id)
}
pub fn save_to_default_location(&self) -> io::Result<()> {
let config_save_location: PathBuf = self.default_location();
save_formatted_config_to_file(self, config_save_location)
}
pub fn validate(&self) -> bool { pub fn validate(&self) -> bool {
// no other sections have explicit requirements (yet) // no other sections have explicit requirements (yet)
self.base.validate() self.base.validate()
@@ -123,39 +140,10 @@ impl Config {
self self
} }
// getters
pub fn get_config_file_save_location(&self) -> PathBuf {
self.config_directory().join(Self::config_file_name())
}
pub fn get_base(&self) -> &BaseConfig<Self> {
&self.base
}
pub fn get_base_mut(&mut self) -> &mut BaseConfig<Self> {
&mut self.base
}
pub fn get_debug_settings(&self) -> &DebugConfig {
self.get_base().get_debug_config()
}
pub fn get_socket_type(&self) -> SocketType {
self.socket.socket_type
}
pub fn get_listening_ip(&self) -> IpAddr {
self.socket.host
}
pub fn get_listening_port(&self) -> u16 {
self.socket.listening_port
}
// poor man's 'builder' method // poor man's 'builder' method
pub fn with_base<F, T>(mut self, f: F, val: T) -> Self pub fn with_base<F, T>(mut self, f: F, val: T) -> Self
where where
F: Fn(BaseConfig<Self>, T) -> BaseConfig<Self>, F: Fn(BaseClientConfig, T) -> BaseClientConfig,
{ {
self.base = f(self.base, val); self.base = f(self.base, val);
self self
@@ -165,7 +153,7 @@ impl Config {
// (plz, lets refactor it) // (plz, lets refactor it)
pub fn with_optional_ext<F, T>(mut self, f: F, val: Option<T>) -> Self pub fn with_optional_ext<F, T>(mut self, f: F, val: Option<T>) -> Self
where where
F: Fn(BaseConfig<Self>, T) -> BaseConfig<Self>, F: Fn(BaseClientConfig, T) -> BaseClientConfig,
{ {
self.base = self.base.with_optional(f, val); self.base = self.base.with_optional(f, val);
self self
@@ -173,7 +161,7 @@ impl Config {
pub fn with_optional_env_ext<F, T>(mut self, f: F, val: Option<T>, env_var: &str) -> Self pub fn with_optional_env_ext<F, T>(mut self, f: F, val: Option<T>, env_var: &str) -> Self
where where
F: Fn(BaseConfig<Self>, T) -> BaseConfig<Self>, F: Fn(BaseClientConfig, T) -> BaseClientConfig,
T: FromStr, T: FromStr,
<T as FromStr>::Err: Debug, <T as FromStr>::Err: Debug,
{ {
@@ -189,7 +177,7 @@ impl Config {
parser: G, parser: G,
) -> Self ) -> Self
where where
F: Fn(BaseConfig<Self>, T) -> BaseConfig<Self>, F: Fn(BaseClientConfig, T) -> BaseClientConfig,
G: Fn(&str) -> T, G: Fn(&str) -> T,
{ {
self.base = self.base.with_optional_custom_env(f, val, env_var, parser); self.base = self.base.with_optional_custom_env(f, val, env_var, parser);
@@ -197,19 +185,21 @@ impl Config {
} }
} }
// define_optional_set_inner!(Config, base, BaseClientConfig);
#[derive(Debug, Deserialize, PartialEq, Eq, Serialize)] #[derive(Debug, Deserialize, PartialEq, Eq, Serialize)]
#[serde(default, deny_unknown_fields)] #[serde(default, deny_unknown_fields)]
pub struct Socket { pub struct Socket {
socket_type: SocketType, pub socket_type: SocketType,
host: IpAddr, pub host: IpAddr,
listening_port: u16, pub listening_port: u16,
} }
impl Default for Socket { impl Default for Socket {
fn default() -> Self { fn default() -> Self {
Socket { Socket {
socket_type: SocketType::WebSocket, socket_type: SocketType::WebSocket,
host: IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), host: IpAddr::V4(Ipv4Addr::LOCALHOST),
listening_port: DEFAULT_WEBSOCKET_LISTENING_PORT, listening_port: DEFAULT_WEBSOCKET_LISTENING_PORT,
} }
} }
@@ -1,58 +1,33 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net> // Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use crate::client::config::{Config, Socket}; use crate::client::config::old_config_v1_1_19::{ConfigV1_1_19, SocketV1_1_19};
use nym_client_core::config::old_config_v1_1_13::OldConfigV1_1_13 as OldBaseConfigV1_1_13; use nym_client_core::config::old_config_v1_1_13::OldConfigV1_1_13 as OldBaseConfigV1_1_13;
use nym_config::NymConfig; use nym_config::legacy_helpers::nym_config::MigrationNymConfig;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::path::PathBuf; use std::path::PathBuf;
#[derive(Debug, Default, Deserialize, PartialEq, Serialize)] #[derive(Debug, Deserialize, PartialEq, Serialize)]
#[serde(deny_unknown_fields)] #[serde(deny_unknown_fields)]
pub struct OldConfigV1_1_13 { pub struct OldConfigV1_1_13 {
#[serde(flatten)] #[serde(flatten)]
base: OldBaseConfigV1_1_13<OldConfigV1_1_13>, pub base: OldBaseConfigV1_1_13<OldConfigV1_1_13>,
socket: Socket, pub socket: SocketV1_1_19,
} }
impl NymConfig for OldConfigV1_1_13 { impl MigrationNymConfig for OldConfigV1_1_13 {
fn template() -> &'static str {
// not intended to be used
unimplemented!()
}
fn default_root_directory() -> PathBuf { fn default_root_directory() -> PathBuf {
dirs::home_dir() dirs::home_dir()
.expect("Failed to evaluate $HOME value") .expect("Failed to evaluate $HOME value")
.join(".nym") .join(".nym")
.join("clients") .join("clients")
} }
fn try_default_root_directory() -> Option<PathBuf> {
dirs::home_dir().map(|path| path.join(".nym").join("clients"))
}
fn root_directory(&self) -> PathBuf {
self.base.client.nym_root_directory.clone()
}
fn config_directory(&self) -> PathBuf {
self.root_directory()
.join(&self.base.client.id)
.join("config")
}
fn data_directory(&self) -> PathBuf {
self.root_directory()
.join(&self.base.client.id)
.join("data")
}
} }
impl From<OldConfigV1_1_13> for Config { impl From<OldConfigV1_1_13> for ConfigV1_1_19 {
fn from(value: OldConfigV1_1_13) -> Self { fn from(value: OldConfigV1_1_13) -> Self {
Config { ConfigV1_1_19 {
base: value.base.into(), base: value.base.into(),
socket: value.socket, socket: value.socket,
} }
@@ -0,0 +1,112 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::client::config::persistence::ClientPaths;
use crate::client::config::{Config, Socket, SocketType};
use nym_bin_common::logging::LoggingSettings;
use nym_client_core::config::disk_persistence::keys_paths::ClientKeysPaths;
use nym_client_core::config::disk_persistence::CommonClientPaths;
use nym_client_core::config::old_config_v1_1_19::ConfigV1_1_19 as BaseConfigV1_1_19;
use nym_client_core::config::{Client, Config as BaseConfig};
use nym_config::defaults::DEFAULT_WEBSOCKET_LISTENING_PORT;
use nym_config::legacy_helpers::nym_config::MigrationNymConfig;
use serde::{Deserialize, Serialize};
use std::fmt::Debug;
use std::net::{IpAddr, Ipv4Addr};
use std::path::PathBuf;
#[derive(Debug, Deserialize, PartialEq, Eq, Serialize, Clone, Copy)]
#[serde(deny_unknown_fields)]
pub enum SocketTypeV1_1_19 {
WebSocket,
None,
}
impl From<SocketTypeV1_1_19> for SocketType {
fn from(value: SocketTypeV1_1_19) -> Self {
match value {
SocketTypeV1_1_19::WebSocket => SocketType::WebSocket,
SocketTypeV1_1_19::None => SocketType::None,
}
}
}
#[derive(Debug, Deserialize, PartialEq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct ConfigV1_1_19 {
#[serde(flatten)]
pub base: BaseConfigV1_1_19<ConfigV1_1_19>,
pub socket: SocketV1_1_19,
}
impl From<ConfigV1_1_19> for Config {
fn from(value: ConfigV1_1_19) -> Self {
Config {
base: BaseConfig {
client: Client {
version: value.base.client.version,
id: value.base.client.id,
disabled_credentials_mode: value.base.client.disabled_credentials_mode,
nyxd_urls: value.base.client.nyxd_urls,
nym_api_urls: value.base.client.nym_api_urls,
gateway_endpoint: value.base.client.gateway_endpoint.into(),
},
debug: value.base.debug.into(),
},
socket: value.socket.into(),
storage_paths: ClientPaths {
common_paths: CommonClientPaths {
keys: ClientKeysPaths {
private_identity_key_file: value.base.client.private_identity_key_file,
public_identity_key_file: value.base.client.public_identity_key_file,
private_encryption_key_file: value.base.client.private_encryption_key_file,
public_encryption_key_file: value.base.client.public_encryption_key_file,
gateway_shared_key_file: value.base.client.gateway_shared_key_file,
ack_key_file: value.base.client.ack_key_file,
},
credentials_database: value.base.client.database_path,
reply_surb_database: value.base.client.reply_surb_database_path,
},
},
logging: LoggingSettings::default(),
}
}
}
impl MigrationNymConfig for ConfigV1_1_19 {
fn default_root_directory() -> PathBuf {
dirs::home_dir()
.expect("Failed to evaluate $HOME value")
.join(".nym")
.join("clients")
}
}
#[derive(Debug, Deserialize, PartialEq, Eq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct SocketV1_1_19 {
socket_type: SocketTypeV1_1_19,
host: IpAddr,
listening_port: u16,
}
impl From<SocketV1_1_19> for Socket {
fn from(value: SocketV1_1_19) -> Self {
Socket {
socket_type: value.socket_type.into(),
host: value.host,
listening_port: value.listening_port,
}
}
}
impl Default for SocketV1_1_19 {
fn default() -> Self {
SocketV1_1_19 {
socket_type: SocketTypeV1_1_19::WebSocket,
host: IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)),
listening_port: DEFAULT_WEBSOCKET_LISTENING_PORT,
}
}
}
@@ -0,0 +1,20 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use nym_client_core::config::disk_persistence::CommonClientPaths;
use serde::{Deserialize, Serialize};
use std::path::Path;
#[derive(Debug, Deserialize, PartialEq, Eq, Serialize, Clone)]
pub struct ClientPaths {
#[serde(flatten)]
pub common_paths: CommonClientPaths,
}
impl ClientPaths {
pub fn new_default<P: AsRef<Path>>(base_data_directory: P) -> Self {
ClientPaths {
common_paths: CommonClientPaths::new_default(base_data_directory),
}
}
}
+21 -26
View File
@@ -1,12 +1,11 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net> // Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
pub(crate) fn config_template() -> &'static str { // While using normal toml marshalling would have been way simpler with less overhead,
// While using normal toml marshalling would have been way simpler with less overhead, // I think it's useful to have comments attached to the saved config file to explain behaviour of
// I think it's useful to have comments attached to the saved config file to explain behaviour of // particular fields.
// particular fields. // Note: any changes to the template must be reflected in the appropriate structs.
// Note: any changes to the template must be reflected in the appropriate structs. pub(crate) const CONFIG_TEMPLATE: &str = r#"
r#"
# This is a TOML config file. # This is a TOML config file.
# For more information, see https://github.com/toml-lang/toml # For more information, see https://github.com/toml-lang/toml
@@ -37,39 +36,35 @@ nym_api_urls = [
{{/each}} {{/each}}
] ]
[storage_paths]
# Path to file containing private identity key. # Path to file containing private identity key.
private_identity_key_file = '{{ client.private_identity_key_file }}' keys.private_identity_key_file = '{{ storage_paths.keys.private_identity_key_file }}'
# Path to file containing public identity key. # Path to file containing public identity key.
public_identity_key_file = '{{ client.public_identity_key_file }}' keys.public_identity_key_file = '{{ storage_paths.keys.public_identity_key_file }}'
# Path to file containing private encryption key. # Path to file containing private encryption key.
private_encryption_key_file = '{{ client.private_encryption_key_file }}' keys.private_encryption_key_file = '{{ storage_paths.keys.private_encryption_key_file }}'
# Path to file containing public encryption key. # Path to file containing public encryption key.
public_encryption_key_file = '{{ client.public_encryption_key_file }}' keys.public_encryption_key_file = '{{ storage_paths.keys.public_encryption_key_file }}'
# Path to the database containing bandwidth credentials
database_path = '{{ client.database_path }}'
# Path to the persistent store for received reply surbs, unused encryption keys and used sender tags.
reply_surb_database_path = '{{ client.reply_surb_database_path }}'
##### additional client config options #####
# A gateway specific, optional, base58 stringified shared key used for # A gateway specific, optional, base58 stringified shared key used for
# communication with particular gateway. # communication with particular gateway.
gateway_shared_key_file = '{{ client.gateway_shared_key_file }}' keys.gateway_shared_key_file = '{{ storage_paths.keys.gateway_shared_key_file }}'
# Path to file containing key used for encrypting and decrypting the content of an # Path to file containing key used for encrypting and decrypting the content of an
# acknowledgement so that nobody besides the client knows which packet it refers to. # acknowledgement so that nobody besides the client knows which packet it refers to.
ack_key_file = '{{ client.ack_key_file }}' keys.ack_key_file = '{{ storage_paths.keys.ack_key_file }}'
##### advanced configuration options #####
# Absolute path to the home Nym Clients directory. # Path to the database containing bandwidth credentials
nym_root_directory = '{{ client.nym_root_directory }}' credentials_database = '{{ storage_paths.credentials_database }}'
# Path to the persistent store for received reply surbs, unused encryption keys and used sender tags.
reply_surb_database = '{{ storage_paths.reply_surb_database }}'
# DEPRECATED
[client.gateway_endpoint] [client.gateway_endpoint]
# ID of the gateway from which the client should be fetching messages. # ID of the gateway from which the client should be fetching messages.
gateway_id = '{{ client.gateway_endpoint.gateway_id }}' gateway_id = '{{ client.gateway_endpoint.gateway_id }}'
@@ -120,5 +115,5 @@ average_ack_delay = '{{ debug.acknowledgements.average_ack_delay }}'
[debug.cover_traffic] [debug.cover_traffic]
loop_cover_traffic_average_delay = '{{ debug.cover_traffic.loop_cover_traffic_average_delay }}' loop_cover_traffic_average_delay = '{{ debug.cover_traffic.loop_cover_traffic_average_delay }}'
"#
} "#;
+15 -17
View File
@@ -1,4 +1,4 @@
// Copyright 2021-2022 - Nym Technologies SA <contact@nymtech.net> // Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use crate::client::config::Config; use crate::client::config::Config;
@@ -17,7 +17,6 @@ use nym_client_core::client::key_manager::persistence::OnDiskKeys;
use nym_client_core::client::received_buffer::{ use nym_client_core::client::received_buffer::{
ReceivedBufferMessage, ReceivedBufferRequestSender, ReconstructedMessagesReceiver, ReceivedBufferMessage, ReceivedBufferRequestSender, ReconstructedMessagesReceiver,
}; };
use nym_client_core::config::persistence::key_pathfinder::ClientKeyPathfinder;
use nym_credential_storage::persistent_storage::PersistentStorage; use nym_credential_storage::persistent_storage::PersistentStorage;
use nym_sphinx::anonymous_replies::requests::AnonymousSenderTag; use nym_sphinx::anonymous_replies::requests::AnonymousSenderTag;
use nym_sphinx::params::PacketType; use nym_sphinx::params::PacketType;
@@ -50,11 +49,11 @@ impl SocketClient {
config: &Config, config: &Config,
) -> BandwidthController<Client<QueryNyxdClient>, PersistentStorage> { ) -> BandwidthController<Client<QueryNyxdClient>, PersistentStorage> {
let storage = nym_credential_storage::initialise_persistent_storage( let storage = nym_credential_storage::initialise_persistent_storage(
config.get_base().get_database_path(), &config.storage_paths.common_paths.credentials_database,
) )
.await; .await;
create_bandwidth_controller(config.get_base(), storage) create_bandwidth_controller(&config.base, storage)
} }
fn start_websocket_listener( fn start_websocket_listener(
@@ -93,7 +92,7 @@ impl SocketClient {
Some(packet_type), Some(packet_type),
); );
websocket::Listener::new(config.get_listening_ip(), config.get_listening_port()) websocket::Listener::new(config.socket.host, config.socket.listening_port)
.start(websocket_handler, shutdown); .start(websocket_handler, shutdown);
} }
@@ -107,26 +106,25 @@ impl SocketClient {
} }
fn key_store(&self) -> OnDiskKeys { fn key_store(&self) -> OnDiskKeys {
let pathfinder = ClientKeyPathfinder::new_from_config(self.config.get_base()); OnDiskKeys::new(self.config.storage_paths.common_paths.keys.clone())
OnDiskKeys::new(pathfinder)
} }
// TODO: see if this could also be shared with socks5 client / nym-sdk maybe // TODO: see if this could also be shared with socks5 client / nym-sdk maybe
async fn create_base_client_builder(&self) -> Result<NativeClientBuilder, ClientError> { async fn create_base_client_builder(&self) -> Result<NativeClientBuilder, ClientError> {
// don't create bandwidth controller if credentials are disabled // don't create bandwidth controller if credentials are disabled
let bandwidth_controller = if self.config.get_base().get_disabled_credentials_mode() { let bandwidth_controller = if self.config.base.client.disabled_credentials_mode {
None None
} else { } else {
Some(Self::create_bandwidth_controller(&self.config).await) Some(Self::create_bandwidth_controller(&self.config).await)
}; };
let base_client = BaseClientBuilder::new_from_base_config( let base_client = BaseClientBuilder::new_from_base_config(
self.config.get_base(), &self.config.base,
self.key_store(), self.key_store(),
bandwidth_controller, bandwidth_controller,
non_wasm_helpers::setup_fs_reply_surb_backend( non_wasm_helpers::setup_fs_reply_surb_backend(
self.config.get_base().get_reply_surb_database_path(), &self.config.storage_paths.common_paths.reply_surb_database,
&self.config.get_debug_settings().reply_surbs, &self.config.base.debug.reply_surbs,
) )
.await?, .await?,
); );
@@ -135,13 +133,13 @@ impl SocketClient {
} }
pub async fn start_socket(self) -> Result<TaskManager, ClientError> { pub async fn start_socket(self) -> Result<TaskManager, ClientError> {
if !self.config.get_socket_type().is_websocket() { if !self.config.socket.socket_type.is_websocket() {
return Err(ClientError::InvalidSocketMode); return Err(ClientError::InvalidSocketMode);
} }
let base_builder = self.create_base_client_builder().await?; let base_builder = self.create_base_client_builder().await?;
let packet_type = self.config.get_base().get_packet_type(); let packet_type = self.config.base.debug.traffic.packet_type;
let mut started_client = base_builder.start_base(packet_type).await?; let mut started_client = base_builder.start_base().await?;
let self_address = started_client.address; let self_address = started_client.address;
let client_input = started_client.client_input.register_producer(); let client_input = started_client.client_input.register_producer();
let client_output = started_client.client_output.register_consumer(); let client_output = started_client.client_output.register_consumer();
@@ -164,13 +162,13 @@ impl SocketClient {
} }
pub async fn start_direct(self) -> Result<DirectClient, ClientError> { pub async fn start_direct(self) -> Result<DirectClient, ClientError> {
if self.config.get_socket_type().is_websocket() { if self.config.socket.socket_type.is_websocket() {
return Err(ClientError::InvalidSocketMode); return Err(ClientError::InvalidSocketMode);
} }
let base_builder = self.create_base_client_builder().await?; let base_builder = self.create_base_client_builder().await?;
let packet_type = self.config.get_base().get_packet_type(); let packet_type = self.config.base.debug.traffic.packet_type;
let mut started_client = base_builder.start_base(packet_type).await?; let mut started_client = base_builder.start_base().await?;
let address = started_client.address; let address = started_client.address;
let client_input = started_client.client_input.register_producer(); let client_input = started_client.client_input.register_producer();
let client_output = started_client.client_output.register_consumer(); let client_output = started_client.client_output.register_consumer();
+37 -31
View File
@@ -1,7 +1,10 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net> // Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use crate::commands::try_upgrade_v1_1_13_config; use crate::client::config::{
default_config_directory, default_config_filepath, default_data_directory,
};
use crate::commands::try_upgrade_config;
use crate::{ use crate::{
client::config::Config, client::config::Config,
commands::{override_config, OverrideConfig}, commands::{override_config, OverrideConfig},
@@ -10,12 +13,12 @@ use crate::{
use clap::Args; use clap::Args;
use nym_bin_common::output_format::OutputFormat; use nym_bin_common::output_format::OutputFormat;
use nym_client_core::client::key_manager::persistence::OnDiskKeys; use nym_client_core::client::key_manager::persistence::OnDiskKeys;
use nym_config::NymConfig;
use nym_crypto::asymmetric::identity; use nym_crypto::asymmetric::identity;
use nym_sphinx::addressing::clients::Recipient; use nym_sphinx::addressing::clients::Recipient;
use serde::Serialize; use serde::Serialize;
use std::fmt::Display; use std::fmt::Display;
use std::net::IpAddr; use std::net::IpAddr;
use std::{fs, io};
use tap::TapFallible; use tap::TapFallible;
#[derive(Args, Clone)] #[derive(Args, Clone)]
@@ -97,15 +100,15 @@ impl From<Init> for OverrideConfig {
pub struct InitResults { pub struct InitResults {
#[serde(flatten)] #[serde(flatten)]
client_core: nym_client_core::init::InitResults, client_core: nym_client_core::init::InitResults,
client_listening_port: String, client_listening_port: u16,
client_address: String, client_address: String,
} }
impl InitResults { impl InitResults {
fn new(config: &Config, address: &Recipient) -> Self { fn new(config: &Config, address: &Recipient) -> Self {
Self { Self {
client_core: nym_client_core::init::InitResults::new(config.get_base(), address), client_core: nym_client_core::init::InitResults::new(&config.base, address),
client_listening_port: config.get_listening_port().to_string(), client_listening_port: config.socket.listening_port,
client_address: address.to_string(), client_address: address.to_string(),
} }
} }
@@ -119,18 +122,26 @@ impl Display for InitResults {
} }
} }
fn init_paths(id: &str) -> io::Result<()> {
fs::create_dir_all(default_data_directory(id))?;
fs::create_dir_all(default_config_directory(id))
}
pub(crate) async fn execute(args: &Init) -> Result<(), ClientError> { pub(crate) async fn execute(args: &Init) -> Result<(), ClientError> {
eprintln!("Initialising client..."); eprintln!("Initialising client...");
let id = &args.id; let id = &args.id;
let already_init = Config::default_config_file_path(id).exists(); let already_init = if default_config_filepath(id).exists() {
if already_init {
// in case we're using old config, try to upgrade it // in case we're using old config, try to upgrade it
// (if we're using the current version, it's a no-op) // (if we're using the current version, it's a no-op)
try_upgrade_v1_1_13_config(id)?; try_upgrade_config(id)?;
eprintln!("Client \"{id}\" was already initialised before"); eprintln!("Client \"{id}\" was already initialised before");
} true
} else {
init_paths(id)?;
false
};
// Usually you only register with the gateway on the first init, however you can force // Usually you only register with the gateway on the first init, however you can force
// re-registering if wanted. // re-registering if wanted.
@@ -152,42 +163,37 @@ pub(crate) async fn execute(args: &Init) -> Result<(), ClientError> {
// Setup gateway by either registering a new one, or creating a new config from the selected // 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. // one but with keys kept, or reusing the gateway configuration.
let key_store = OnDiskKeys::from_config(config.get_base()); let key_store = OnDiskKeys::new(config.storage_paths.common_paths.keys.clone());
let gateway = nym_client_core::init::setup_gateway_from_config::<Config, _, _>( let gateway = nym_client_core::init::setup_gateway_from_config::<_>(
&key_store, &key_store,
register_gateway, register_gateway,
user_chosen_gateway_id, user_chosen_gateway_id,
config.get_base(), &config.base,
args.latency_based_selection, args.latency_based_selection,
) )
.await .await
.tap_err(|err| eprintln!("Failed to setup gateway\nError: {err}"))?; .tap_err(|err| eprintln!("Failed to setup gateway\nError: {err}"))?;
config.get_base_mut().set_gateway_endpoint(gateway); config.base.set_gateway_endpoint(gateway);
config.save_to_file(None).tap_err(|_| { let config_save_location = config.default_location();
config.save_to_default_location().tap_err(|_| {
log::error!("Failed to save the config file"); log::error!("Failed to save the config file");
})?; })?;
eprintln!(
"Saved configuration file to {}",
config_save_location.display()
);
print_saved_config(&config); let address = nym_client_core::init::get_client_address_from_stored_ondisk_keys(
&config.storage_paths.common_paths.keys,
&config.base.client.gateway_endpoint,
)?;
eprintln!("Client configuration completed.\n");
let address =
nym_client_core::init::get_client_address_from_stored_ondisk_keys(config.get_base())?;
let init_results = InitResults::new(&config, &address); let init_results = InitResults::new(&config, &address);
println!("{}", args.output.format(&init_results)); println!("{}", args.output.format(&init_results));
Ok(()) Ok(())
} }
fn print_saved_config(config: &Config) {
let config_save_location = config.get_config_file_save_location();
eprintln!("Saved configuration file to {config_save_location:?}");
eprintln!("Using gateway: {}", config.get_base().get_gateway_id());
log::debug!("Gateway id: {}", config.get_base().get_gateway_id());
log::debug!("Gateway owner: {}", config.get_base().get_gateway_owner());
log::debug!(
"Gateway listener: {}",
config.get_base().get_gateway_listener()
);
eprintln!("Client configuration completed.\n");
}
+66 -12
View File
@@ -2,14 +2,16 @@
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use crate::client::config::old_config_v1_1_13::OldConfigV1_1_13; use crate::client::config::old_config_v1_1_13::OldConfigV1_1_13;
use crate::client::config::{BaseConfig, Config}; use crate::client::config::old_config_v1_1_19::ConfigV1_1_19;
use crate::client::config::{BaseClientConfig, Config};
use crate::error::ClientError;
use clap::CommandFactory; use clap::CommandFactory;
use clap::{Parser, Subcommand}; use clap::{Parser, Subcommand};
use lazy_static::lazy_static; use lazy_static::lazy_static;
use log::info; use log::{error, info};
use nym_bin_common::build_information::BinaryBuildInformation; use nym_bin_common::build_information::BinaryBuildInformation;
use nym_bin_common::completions::{fig_generate, ArgShell}; use nym_bin_common::completions::{fig_generate, ArgShell};
use nym_config::{NymConfig, OptionalSet}; use nym_config::OptionalSet;
use std::error::Error; use std::error::Error;
use std::net::IpAddr; use std::net::IpAddr;
@@ -82,40 +84,92 @@ pub(crate) async fn execute(args: &Cli) -> Result<(), Box<dyn Error + Send + Syn
pub(crate) fn override_config(config: Config, args: OverrideConfig) -> Config { pub(crate) fn override_config(config: Config, args: OverrideConfig) -> Config {
config config
.with_optional(Config::with_disabled_socket, args.disable_socket) .with_optional(Config::with_disabled_socket, args.disable_socket)
.with_base(BaseConfig::with_high_default_traffic_volume, args.fastmode) .with_base(
.with_base(BaseConfig::with_disabled_cover_traffic, args.no_cover) BaseClientConfig::with_high_default_traffic_volume,
args.fastmode,
)
.with_base(BaseClientConfig::with_disabled_cover_traffic, args.no_cover)
.with_optional(Config::with_port, args.port) .with_optional(Config::with_port, args.port)
.with_optional(Config::with_host, args.host) .with_optional(Config::with_host, args.host)
.with_optional_custom_env_ext( .with_optional_custom_env_ext(
BaseConfig::with_custom_nym_apis, BaseClientConfig::with_custom_nym_apis,
args.nym_apis, args.nym_apis,
nym_network_defaults::var_names::NYM_API, nym_network_defaults::var_names::NYM_API,
nym_config::parse_urls, nym_config::parse_urls,
) )
.with_optional_custom_env_ext( .with_optional_custom_env_ext(
BaseConfig::with_custom_nyxd, BaseClientConfig::with_custom_nyxd,
args.nyxd_urls, args.nyxd_urls,
nym_network_defaults::var_names::NYXD, nym_network_defaults::var_names::NYXD,
nym_config::parse_urls, nym_config::parse_urls,
) )
.with_optional_ext( .with_optional_ext(
BaseConfig::with_disabled_credentials, BaseClientConfig::with_disabled_credentials,
args.enabled_credentials_mode.map(|b| !b), args.enabled_credentials_mode.map(|b| !b),
) )
} }
fn try_upgrade_v1_1_13_config(id: &str) -> std::io::Result<()> { fn try_upgrade_v1_1_13_config(id: &str) -> Result<bool, ClientError> {
// explicitly load it as v1.1.13 (which is incompatible with the current, i.e. 1.1.14+) use nym_config::legacy_helpers::nym_config::MigrationNymConfig;
// explicitly load it as v1.1.13 (which is incompatible with the next step, i.e. 1.1.19)
let Ok(old_config) = OldConfigV1_1_13::load_from_file(id) else { let Ok(old_config) = OldConfigV1_1_13::load_from_file(id) else {
// if we failed to load it, there might have been nothing to upgrade // if we failed to load it, there might have been nothing to upgrade
// or maybe it was an even older file. in either way. just ignore it and carry on with our day // or maybe it was an even older file. in either way. just ignore it and carry on with our day
return Ok(()); return Ok(false);
}; };
info!("It seems the client is using <= v1.1.13 config template."); info!("It seems the client is using <= v1.1.13 config template.");
info!("It is going to get updated to the current specification."); info!("It is going to get updated to the current specification.");
let updated_step1: ConfigV1_1_19 = old_config.into();
let updated: Config = updated_step1.into();
updated.save_to_default_location()?;
Ok(true)
}
fn try_upgrade_v1_1_19_config(id: &str) -> Result<bool, ClientError> {
use nym_config::legacy_helpers::nym_config::MigrationNymConfig;
// explicitly load it as v1.1.19 (which is incompatible with the current one, i.e. +1.1.20)
let Ok(old_config) = ConfigV1_1_19::load_from_file(id) else {
// if we failed to load it, there might have been nothing to upgrade
// or maybe it was an even older file. in either way. just ignore it and carry on with our day
return Ok(false);
};
info!("It seems the client is using <= v1.1.19 config template.");
info!("It is going to get updated to the current specification.");
let updated: Config = old_config.into(); let updated: Config = old_config.into();
updated.save_to_file(None) updated.save_to_default_location()?;
Ok(true)
}
fn try_upgrade_config(id: &str) -> Result<(), ClientError> {
let upgraded = try_upgrade_v1_1_13_config(id)?;
if !upgraded {
try_upgrade_v1_1_19_config(id)?;
}
Ok(())
}
fn try_load_current_config(id: &str) -> Result<Config, ClientError> {
try_upgrade_config(id)?;
let config = match Config::read_from_default_path(id) {
Ok(cfg) => cfg,
Err(err) => {
error!("Failed to load config for {id}. Are you sure you have run `init` before? (Error was: {err})");
return Err(ClientError::FailedToLoadConfig(id.to_string()));
}
};
if !config.validate() {
return Err(ClientError::ConfigValidationFailure);
}
Ok(config)
} }
#[cfg(test)] #[cfg(test)]
+7 -29
View File
@@ -1,10 +1,7 @@
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net> // Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use std::error::Error; use crate::commands::try_load_current_config;
use std::net::IpAddr;
use crate::commands::try_upgrade_v1_1_13_config;
use crate::{ use crate::{
client::{config::Config, SocketClient}, client::{config::Config, SocketClient},
commands::{override_config, OverrideConfig}, commands::{override_config, OverrideConfig},
@@ -13,8 +10,9 @@ use crate::{
use clap::Args; use clap::Args;
use log::*; use log::*;
use nym_bin_common::version_checker::is_minor_version_compatible; use nym_bin_common::version_checker::is_minor_version_compatible;
use nym_config::NymConfig;
use nym_crypto::asymmetric::identity; use nym_crypto::asymmetric::identity;
use std::error::Error;
use std::net::IpAddr;
#[derive(Args, Clone)] #[derive(Args, Clone)]
pub(crate) struct Run { pub(crate) struct Run {
@@ -82,7 +80,7 @@ impl From<Run> for OverrideConfig {
// network version. It might do so in the future. // network version. It might do so in the future.
fn version_check(cfg: &Config) -> bool { fn version_check(cfg: &Config) -> bool {
let binary_version = env!("CARGO_PKG_VERSION"); let binary_version = env!("CARGO_PKG_VERSION");
let config_version = cfg.get_base().get_version(); let config_version = &cfg.base.client.version;
if binary_version == config_version { if binary_version == config_version {
true true
} else { } else {
@@ -98,30 +96,10 @@ fn version_check(cfg: &Config) -> bool {
} }
pub(crate) async fn execute(args: &Run) -> Result<(), Box<dyn Error + Send + Sync>> { pub(crate) async fn execute(args: &Run) -> Result<(), Box<dyn Error + Send + Sync>> {
let id = &args.id; eprintln!("Starting client {}...", args.id);
// in case we're using old config, try to upgrade it let mut config = try_load_current_config(&args.id)?;
// (if we're using the current version, it's a no-op) config = override_config(config, OverrideConfig::from(args.clone()));
try_upgrade_v1_1_13_config(id)?;
let mut config = match Config::load_from_file(id) {
Ok(cfg) => cfg,
Err(err) => {
error!("Failed to load config for {}. Are you sure you have run `init` before? (Error was: {err})", id);
return Err(Box::new(ClientError::FailedToLoadConfig(id.to_string())));
}
};
if !config.validate() {
return Err(Box::new(ClientError::ConfigValidationFailure));
}
let override_config_fields = OverrideConfig::from(args.clone());
config = override_config(config, override_config_fields);
if config.get_base_mut().set_empty_fields_to_defaults() {
warn!("some of the core config options were left unset. the default values are going to get used instead.");
}
if !version_check(&config) { if !version_check(&config) {
error!("failed the local version check"); error!("failed the local version check");
+16 -84
View File
@@ -1,42 +1,14 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net> // Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use crate::client::config::{Config, MISSING_VALUE}; use crate::client::config::Config;
use crate::commands::try_load_current_config;
use nym_bin_common::version_checker::Version;
use nym_config::NymConfig;
use clap::Args; use clap::Args;
use std::fmt::Display; use nym_bin_common::version_checker::Version;
use std::process; use std::process;
#[allow(dead_code)] fn unimplemented_upgrade(current_version: &Version, config_version: &Version) -> ! {
fn fail_upgrade<D1: Display, D2: Display>(from_version: D1, to_version: D2) -> ! { eprintln!("Cannot perform upgrade from {config_version} to {current_version} as it hasn't been implemented yet");
print_failed_upgrade(from_version, to_version);
process::exit(1)
}
fn print_start_upgrade<D1: Display, D2: Display>(from: D1, to: D2) {
println!("\n==================\nTrying to upgrade client from {from} to {to} ...");
}
fn print_failed_upgrade<D1: Display, D2: Display>(from: D1, to: D2) {
eprintln!("Upgrade from {from} to {to} failed!\n==================\n");
}
fn print_successful_upgrade<D1: Display, D2: Display>(from: D1, to: D2) {
println!("Upgrade from {from} to {to} was successful!\n==================\n");
}
fn outdated_upgrade(config_version: &Version, package_version: &Version) -> ! {
eprintln!(
"Cannot perform upgrade from {config_version} to {package_version}. Your version is too old to perform the upgrade.!"
);
process::exit(1)
}
fn unsupported_upgrade(current_version: &Version, config_version: &Version) -> ! {
eprintln!("Cannot perform upgrade from {config_version} to {current_version}. Please let the developers know about this issue if you expected it to work!");
process::exit(1) process::exit(1)
} }
@@ -48,7 +20,7 @@ pub(crate) struct Upgrade {
} }
fn parse_config_version(config: &Config) -> Version { fn parse_config_version(config: &Config) -> Version {
let version = Version::parse(config.get_base().get_version()).unwrap_or_else(|err| { let version = Version::parse(&config.base.client.version).unwrap_or_else(|err| {
eprintln!("failed to parse client version! - {err}"); eprintln!("failed to parse client version! - {err}");
process::exit(1) process::exit(1)
}); });
@@ -77,53 +49,14 @@ fn parse_package_version() -> Version {
version version
} }
fn minor_0_12_upgrade( fn do_upgrade(config: Config, _args: &Upgrade, package_version: &Version) {
mut config: Config, let config_version = parse_config_version(&config);
_matches: &Upgrade, if &config_version == package_version {
config_version: &Version, println!("You're using the most recent version!");
package_version: &Version, return;
) -> Config {
let to_version = if package_version.major == 0 && package_version.minor == 12 {
package_version.clone()
} else {
Version::new(0, 12, 0)
};
print_start_upgrade(config_version, &to_version);
config
.get_base_mut()
.set_custom_version(to_version.to_string().as_ref());
config.save_to_file(None).unwrap_or_else(|err| {
eprintln!("failed to overwrite config file! - {err}");
print_failed_upgrade(config_version, &to_version);
process::exit(1);
});
print_successful_upgrade(config_version, to_version);
config
}
fn do_upgrade(mut config: Config, args: &Upgrade, package_version: &Version) {
loop {
let config_version = parse_config_version(&config);
if &config_version == package_version {
println!("You're using the most recent version!");
return;
}
config = match config_version.major {
0 => match config_version.minor {
9 | 10 => outdated_upgrade(&config_version, package_version),
11 => minor_0_12_upgrade(config, args, &config_version, package_version),
_ => unsupported_upgrade(&config_version, package_version),
},
_ => unsupported_upgrade(&config_version, package_version),
}
} }
unimplemented_upgrade(package_version, &config_version)
} }
pub(crate) fn execute(args: &Upgrade) { pub(crate) fn execute(args: &Upgrade) {
@@ -131,16 +64,15 @@ pub(crate) fn execute(args: &Upgrade) {
let id = &args.id; let id = &args.id;
let existing_config = Config::load_from_file(id).unwrap_or_else(|err| { let existing_config = try_load_current_config(id).unwrap_or_else(|err| {
eprintln!("failed to load existing config file! - {err}"); eprintln!("failed to load existing config file! - {err}");
process::exit(1) process::exit(1)
}); });
if existing_config.get_base().get_version() == MISSING_VALUE { if existing_config.base.client.version.is_empty() {
eprintln!("the existing configuration file does not seem to contain version number."); eprintln!("the existing configuration file does not seem to contain version number.");
process::exit(1); process::exit(1);
} }
// here be upgrade path to 0.9.X and beyond based on version number from config
do_upgrade(existing_config, args, &package_version) do_upgrade(existing_config, args, &package_version)
} }
+1 -1
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "nym-socks5-client" name = "nym-socks5-client"
version = "1.1.20" version = "1.1.19"
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"] 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" description = "A SOCKS5 localhost proxy that converts incoming messages to Sphinx and sends them to a Nym address"
edition = "2021" edition = "2021"
+34 -32
View File
@@ -1,7 +1,10 @@
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net> // Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use crate::commands::try_upgrade_v1_1_13_config; use crate::commands::try_upgrade_config;
use crate::config::{
default_config_directory, default_config_filepath, default_data_directory, Config,
};
use crate::{ use crate::{
commands::{override_config, OverrideConfig}, commands::{override_config, OverrideConfig},
error::Socks5ClientError, error::Socks5ClientError,
@@ -9,12 +12,11 @@ use crate::{
use clap::Args; use clap::Args;
use nym_bin_common::output_format::OutputFormat; use nym_bin_common::output_format::OutputFormat;
use nym_client_core::client::key_manager::persistence::OnDiskKeys; use nym_client_core::client::key_manager::persistence::OnDiskKeys;
use nym_config::NymConfig;
use nym_crypto::asymmetric::identity; use nym_crypto::asymmetric::identity;
use nym_socks5_client_core::config::Config;
use nym_sphinx::addressing::clients::Recipient; use nym_sphinx::addressing::clients::Recipient;
use serde::Serialize; use serde::Serialize;
use std::fmt::Display; use std::fmt::Display;
use std::{fs, io};
use tap::TapFallible; use tap::TapFallible;
#[derive(Args, Clone)] #[derive(Args, Clone)]
@@ -100,15 +102,15 @@ impl From<Init> for OverrideConfig {
pub struct InitResults { pub struct InitResults {
#[serde(flatten)] #[serde(flatten)]
client_core: nym_client_core::init::InitResults, client_core: nym_client_core::init::InitResults,
socks5_listening_port: String, socks5_listening_port: u16,
client_address: String, client_address: String,
} }
impl InitResults { impl InitResults {
fn new(config: &Config, address: &Recipient) -> Self { fn new(config: &Config, address: &Recipient) -> Self {
Self { Self {
client_core: nym_client_core::init::InitResults::new(config.get_base(), address), client_core: nym_client_core::init::InitResults::new(&config.core.base, address),
socks5_listening_port: config.get_socks5().get_listening_port().to_string(), socks5_listening_port: config.core.socks5.listening_port,
client_address: address.to_string(), client_address: address.to_string(),
} }
} }
@@ -122,19 +124,27 @@ impl Display for InitResults {
} }
} }
fn init_paths(id: &str) -> io::Result<()> {
fs::create_dir_all(default_data_directory(id))?;
fs::create_dir_all(default_config_directory(id))
}
pub(crate) async fn execute(args: &Init) -> Result<(), Socks5ClientError> { pub(crate) async fn execute(args: &Init) -> Result<(), Socks5ClientError> {
eprintln!("Initialising client..."); eprintln!("Initialising client...");
let id = &args.id; let id = &args.id;
let provider_address = &args.provider; let provider_address = &args.provider;
let already_init = Config::default_config_file_path(id).exists(); let already_init = if default_config_filepath(id).exists() {
if already_init {
// in case we're using old config, try to upgrade it // in case we're using old config, try to upgrade it
// (if we're using the current version, it's a no-op) // (if we're using the current version, it's a no-op)
try_upgrade_v1_1_13_config(id)?; try_upgrade_config(id)?;
eprintln!("SOCKS5 client \"{id}\" was already initialised before"); eprintln!("SOCKS5 client \"{id}\" was already initialised before");
} true
} else {
init_paths(id)?;
false
};
// Usually you only register with the gateway on the first init, however you can force // Usually you only register with the gateway on the first init, however you can force
// re-registering if wanted. // re-registering if wanted.
@@ -159,44 +169,36 @@ pub(crate) async fn execute(args: &Init) -> Result<(), Socks5ClientError> {
// Setup gateway by either registering a new one, or creating a new config from the selected // 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. // one but with keys kept, or reusing the gateway configuration.
let key_store = OnDiskKeys::from_config(config.get_base()); let key_store = OnDiskKeys::new(config.storage_paths.common_paths.keys.clone());
let gateway = nym_client_core::init::setup_gateway_from_config::<Config, _, _>( let gateway = nym_client_core::init::setup_gateway_from_config::<_>(
&key_store, &key_store,
register_gateway, register_gateway,
user_chosen_gateway_id, user_chosen_gateway_id,
config.get_base(), &config.core.base,
args.latency_based_selection, args.latency_based_selection,
) )
.await .await
.tap_err(|err| eprintln!("Failed to setup gateway\nError: {err}"))?; .tap_err(|err| eprintln!("Failed to setup gateway\nError: {err}"))?;
config.get_base_mut().set_gateway_endpoint(gateway); config.core.base.set_gateway_endpoint(gateway);
// TODO: ask the service provider we specified for its interface version and set it in the config // TODO: ask the service provider we specified for its interface version and set it in the config
config.save_to_file(None).tap_err(|_| { let config_save_location = config.default_location();
config.save_to_default_location().tap_err(|_| {
log::error!("Failed to save the config file"); log::error!("Failed to save the config file");
})?; })?;
eprintln!(
"Saved configuration file to {}",
config_save_location.display()
);
print_saved_config(&config); let address = nym_client_core::init::get_client_address_from_stored_ondisk_keys(
&config.storage_paths.common_paths.keys,
let address = &config.core.base.client.gateway_endpoint,
nym_client_core::init::get_client_address_from_stored_ondisk_keys(config.get_base())?; )?;
let init_results = InitResults::new(&config, &address); let init_results = InitResults::new(&config, &address);
println!("{}", args.output.format(&init_results)); println!("{}", args.output.format(&init_results));
Ok(()) Ok(())
} }
fn print_saved_config(config: &Config) {
let config_save_location = config.get_config_file_save_location();
eprintln!("Saved configuration file to {:?}", config_save_location);
eprintln!("Using gateway: {}", config.get_base().get_gateway_id());
log::debug!("Gateway id: {}", config.get_base().get_gateway_id());
log::debug!("Gateway owner: {}", config.get_base().get_gateway_owner());
log::debug!(
"Gateway listener: {}",
config.get_base().get_gateway_listener()
);
eprintln!("Client configuration completed.\n");
}
+71 -17
View File
@@ -1,15 +1,17 @@
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net> // Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use crate::config::old_config_v1_1_13::OldConfigV1_1_13;
use crate::config::old_config_v1_1_19::ConfigV1_1_19;
use crate::config::{BaseClientConfig, Config};
use crate::error::Socks5ClientError;
use clap::CommandFactory; use clap::CommandFactory;
use clap::{Parser, Subcommand}; use clap::{Parser, Subcommand};
use lazy_static::lazy_static; use lazy_static::lazy_static;
use log::info; use log::{error, info};
use nym_bin_common::build_information::BinaryBuildInformation; use nym_bin_common::build_information::BinaryBuildInformation;
use nym_bin_common::completions::{fig_generate, ArgShell}; use nym_bin_common::completions::{fig_generate, ArgShell};
use nym_config::{NymConfig, OptionalSet}; use nym_config::OptionalSet;
use nym_socks5_client_core::config::old_config_v1_1_13::OldConfigV1_1_13;
use nym_socks5_client_core::config::{BaseConfig, Config};
use nym_sphinx::params::PacketType; use nym_sphinx::params::PacketType;
use std::error::Error; use std::error::Error;
@@ -88,41 +90,93 @@ pub(crate) fn override_config(config: Config, args: OverrideConfig) -> Config {
PacketType::Mix PacketType::Mix
}; };
config config
.with_base(BaseConfig::with_high_default_traffic_volume, args.fastmode) .with_base(
.with_base(BaseConfig::with_disabled_cover_traffic, args.no_cover) BaseClientConfig::with_high_default_traffic_volume,
.with_base(BaseConfig::with_packet_type, packet_type) args.fastmode,
)
.with_base(BaseClientConfig::with_disabled_cover_traffic, args.no_cover)
.with_base(BaseClientConfig::with_packet_type, packet_type)
.with_optional(Config::with_anonymous_replies, args.use_anonymous_replies) .with_optional(Config::with_anonymous_replies, args.use_anonymous_replies)
.with_optional(Config::with_port, args.port) .with_optional(Config::with_port, args.port)
.with_optional_custom_env_ext( .with_optional_base_custom_env(
BaseConfig::with_custom_nym_apis, BaseClientConfig::with_custom_nym_apis,
args.nym_apis, args.nym_apis,
nym_network_defaults::var_names::NYM_API, nym_network_defaults::var_names::NYM_API,
nym_config::parse_urls, nym_config::parse_urls,
) )
.with_optional_custom_env_ext( .with_optional_base_custom_env(
BaseConfig::with_custom_nyxd, BaseClientConfig::with_custom_nyxd,
args.nyxd_urls, args.nyxd_urls,
nym_network_defaults::var_names::NYXD, nym_network_defaults::var_names::NYXD,
nym_config::parse_urls, nym_config::parse_urls,
) )
.with_optional_ext( .with_optional_base(
BaseConfig::with_disabled_credentials, BaseClientConfig::with_disabled_credentials,
args.enabled_credentials_mode.map(|b| !b), args.enabled_credentials_mode.map(|b| !b),
) )
} }
fn try_upgrade_v1_1_13_config(id: &str) -> std::io::Result<()> { fn try_upgrade_v1_1_13_config(id: &str) -> Result<bool, Socks5ClientError> {
// explicitly load it as v1.1.13 (which is incompatible with the current, i.e. 1.1.14+) use nym_config::legacy_helpers::nym_config::MigrationNymConfig;
// explicitly load it as v1.1.13 (which is incompatible with the next step, i.e. 1.1.19)
let Ok(old_config) = OldConfigV1_1_13::load_from_file(id) else { let Ok(old_config) = OldConfigV1_1_13::load_from_file(id) else {
// if we failed to load it, there might have been nothing to upgrade // if we failed to load it, there might have been nothing to upgrade
// or maybe it was an even older file. in either way. just ignore it and carry on with our day // or maybe it was an even older file. in either way. just ignore it and carry on with our day
return Ok(()); return Ok(false);
}; };
info!("It seems the client is using <= v1.1.13 config template."); info!("It seems the client is using <= v1.1.13 config template.");
info!("It is going to get updated to the current specification."); info!("It is going to get updated to the current specification.");
let updated_step1: ConfigV1_1_19 = old_config.into();
let updated: Config = updated_step1.into();
updated.save_to_default_location()?;
Ok(true)
}
fn try_upgrade_v1_1_19_config(id: &str) -> Result<bool, Socks5ClientError> {
use nym_config::legacy_helpers::nym_config::MigrationNymConfig;
// explicitly load it as v1.1.19 (which is incompatible with the current one, i.e. +1.1.20)
let Ok(old_config) = ConfigV1_1_19::load_from_file(id) else {
// if we failed to load it, there might have been nothing to upgrade
// or maybe it was an even older file. in either way. just ignore it and carry on with our day
return Ok(false);
};
info!("It seems the client is using <= v1.1.19 config template.");
info!("It is going to get updated to the current specification.");
let updated: Config = old_config.into(); let updated: Config = old_config.into();
updated.save_to_file(None) updated.save_to_default_location()?;
Ok(true)
}
fn try_upgrade_config(id: &str) -> Result<(), Socks5ClientError> {
let upgraded = try_upgrade_v1_1_13_config(id)?;
if !upgraded {
try_upgrade_v1_1_19_config(id)?;
}
Ok(())
}
fn try_load_current_config(id: &str) -> Result<Config, Socks5ClientError> {
try_upgrade_config(id)?;
let config = match Config::read_from_default_path(id) {
Ok(cfg) => cfg,
Err(err) => {
error!("Failed to load config for {id}. Are you sure you have run `init` before? (Error was: {err})");
return Err(Socks5ClientError::FailedToLoadConfig(id.to_string()));
}
};
if !config.validate() {
return Err(Socks5ClientError::ConfigValidationFailure);
}
Ok(config)
} }
#[cfg(test)] #[cfg(test)]
+13 -38
View File
@@ -1,7 +1,8 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net> // Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use crate::commands::try_upgrade_v1_1_13_config; use crate::commands::try_load_current_config;
use crate::config::Config;
use crate::{ use crate::{
commands::{override_config, OverrideConfig}, commands::{override_config, OverrideConfig},
error::Socks5ClientError, error::Socks5ClientError,
@@ -10,9 +11,8 @@ use clap::Args;
use log::*; use log::*;
use nym_bin_common::version_checker::is_minor_version_compatible; use nym_bin_common::version_checker::is_minor_version_compatible;
use nym_client_core::client::base_client::storage::OnDiskPersistent; use nym_client_core::client::base_client::storage::OnDiskPersistent;
use nym_config::NymConfig;
use nym_crypto::asymmetric::identity; use nym_crypto::asymmetric::identity;
use nym_socks5_client_core::{config::Config, NymClient}; use nym_socks5_client_core::NymClient;
use nym_sphinx::addressing::clients::Recipient; use nym_sphinx::addressing::clients::Recipient;
#[derive(Args, Clone)] #[derive(Args, Clone)]
@@ -21,10 +21,6 @@ pub(crate) struct Run {
#[clap(long)] #[clap(long)]
id: String, id: String,
/// Custom path to the nym-mixnet-client configuration file
#[clap(long)]
config: Option<String>,
/// Specifies whether this client is going to use an anonymous sender tag for communication with the service provider. /// 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 /// 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. /// slower and consume nearly double the bandwidth as it will require sending reply SURBs.
@@ -92,13 +88,12 @@ impl From<Run> for OverrideConfig {
// network version. It might do so in the future. // network version. It might do so in the future.
fn version_check(cfg: &Config) -> bool { fn version_check(cfg: &Config) -> bool {
let binary_version = env!("CARGO_PKG_VERSION"); let binary_version = env!("CARGO_PKG_VERSION");
let config_version = cfg.get_base().get_version(); let config_version = &cfg.core.base.client.version;
if binary_version == config_version { if binary_version == config_version {
true true
} else { } else {
warn!( warn!(
"The mixnode binary has different version than what is specified in config file! {} and {}", "The socks5-client binary has different version than what is specified in config file! {binary_version} and {config_version}",
binary_version, config_version
); );
if is_minor_version_compatible(binary_version, config_version) { if is_minor_version_compatible(binary_version, config_version) {
info!("but they are still semver compatible. However, consider running the `upgrade` command"); info!("but they are still semver compatible. However, consider running the `upgrade` command");
@@ -111,38 +106,18 @@ fn version_check(cfg: &Config) -> bool {
} }
pub(crate) async fn execute(args: &Run) -> Result<(), Box<dyn std::error::Error + Send + Sync>> { pub(crate) async fn execute(args: &Run) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
let id = &args.id; eprintln!("Starting client {}...", args.id);
// in case we're using old config, try to upgrade it let mut config = try_load_current_config(&args.id)?;
// (if we're using the current version, it's a no-op) config = override_config(config, OverrideConfig::from(args.clone()));
try_upgrade_v1_1_13_config(id)?;
let mut config = match Config::load_from_file(id) {
Ok(cfg) => cfg,
Err(err) => {
error!("Failed to load config for {}. Are you sure you have run `init` before? (Error was: {err})", id);
return Err(Box::new(Socks5ClientError::FailedToLoadConfig(
id.to_string(),
)));
}
};
if !config.validate() {
return Err(Box::new(Socks5ClientError::ConfigValidationFailure));
}
let override_config_fields = OverrideConfig::from(args.clone());
config = override_config(config, override_config_fields);
if config.get_base_mut().set_empty_fields_to_defaults() {
warn!("some of the core config options were left unset. the default values are going to get used instead.");
}
if !version_check(&config) { if !version_check(&config) {
error!("failed the local version check"); error!("failed the local version check");
return Err(Box::new(Socks5ClientError::FailedLocalVersionCheck)); return Err(Box::new(Socks5ClientError::FailedLocalVersionCheck));
} }
let storage = OnDiskPersistent::from_config(config.get_base()).await?; let storage =
NymClient::new(config, storage).run_forever().await OnDiskPersistent::from_paths(config.storage_paths.common_paths, &config.core.base.debug)
.await?;
NymClient::new(config.core, storage).run_forever().await
} }
+19 -99
View File
@@ -1,50 +1,14 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net> // Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use nym_bin_common::version_checker::Version; use crate::commands::try_load_current_config;
use nym_config::NymConfig; use crate::config::Config;
use nym_socks5_client_core::config::{Config, MISSING_VALUE};
use clap::Args; use clap::Args;
use std::{fmt::Display, process}; use nym_bin_common::version_checker::Version;
use std::process;
#[allow(dead_code)] fn unimplemented_upgrade(current_version: &Version, config_version: &Version) -> ! {
fn fail_upgrade<D1: Display, D2: Display>(from_version: D1, to_version: D2) -> ! { eprintln!("Cannot perform upgrade from {config_version} to {current_version} as it hasn't been implemented yet");
print_failed_upgrade(from_version, to_version);
process::exit(1)
}
fn print_start_upgrade<D1: Display, D2: Display>(from: D1, to: D2) {
println!(
"\n==================\nTrying to upgrade client from {} to {} ...",
from, to
);
}
fn print_failed_upgrade<D1: Display, D2: Display>(from: D1, to: D2) {
eprintln!(
"Upgrade from {} to {} failed!\n==================\n",
from, to
);
}
fn print_successful_upgrade<D1: Display, D2: Display>(from: D1, to: D2) {
println!(
"Upgrade from {} to {} was successful!\n==================\n",
from, to
);
}
fn outdated_upgrade(config_version: &Version, package_version: &Version) -> ! {
eprintln!(
"Cannot perform upgrade from {} to {}. Your version is too old to perform the upgrade.!",
config_version, package_version
);
process::exit(1)
}
fn unsupported_upgrade(current_version: &Version, config_version: &Version) -> ! {
eprintln!("Cannot perform upgrade from {} to {}. Please let the developers know about this issue if you expected it to work!", config_version, current_version);
process::exit(1) process::exit(1)
} }
@@ -56,15 +20,14 @@ pub(crate) struct Upgrade {
} }
fn parse_config_version(config: &Config) -> Version { fn parse_config_version(config: &Config) -> Version {
let version = Version::parse(config.get_base().get_version()).unwrap_or_else(|err| { let version = Version::parse(&config.core.base.client.version).unwrap_or_else(|err| {
eprintln!("failed to parse client version! - {err}"); eprintln!("failed to parse client version! - {err}");
process::exit(1) process::exit(1)
}); });
if version.is_prerelease() || !version.build.is_empty() { if version.is_prerelease() || !version.build.is_empty() {
eprintln!( eprintln!(
"Trying to upgrade from a non-released version {}. This is not supported!", "Trying to upgrade from a non-released version {version}. This is not supported!"
version
); );
process::exit(1) process::exit(1)
} }
@@ -79,63 +42,21 @@ fn parse_package_version() -> Version {
// however, we are not using them ourselves at the moment and hence it should be fine. // however, we are not using them ourselves at the moment and hence it should be fine.
// if we change our mind, we could easily tweak this code // if we change our mind, we could easily tweak this code
if version.is_prerelease() || !version.build.is_empty() { if version.is_prerelease() || !version.build.is_empty() {
eprintln!( eprintln!("Trying to upgrade to a non-released version {version}. This is not supported!");
"Trying to upgrade to a non-released version {}. This is not supported!",
version
);
process::exit(1) process::exit(1)
} }
version version
} }
fn minor_0_12_upgrade( fn do_upgrade(config: Config, _args: &Upgrade, package_version: &Version) {
mut config: Config, let config_version = parse_config_version(&config);
_args: &Upgrade, if &config_version == package_version {
config_version: &Version, println!("You're using the most recent version!");
package_version: &Version, return;
) -> Config {
let to_version = if package_version.major == 0 && package_version.minor == 12 {
package_version.clone()
} else {
Version::new(0, 12, 0)
};
print_start_upgrade(config_version, &to_version);
config
.get_base_mut()
.set_custom_version(to_version.to_string().as_ref());
config.save_to_file(None).unwrap_or_else(|err| {
eprintln!("failed to overwrite config file! - {err}");
print_failed_upgrade(config_version, &to_version);
process::exit(1);
});
print_successful_upgrade(config_version, to_version);
config
}
fn do_upgrade(mut config: Config, args: &Upgrade, package_version: &Version) {
loop {
let config_version = parse_config_version(&config);
if &config_version == package_version {
println!("You're using the most recent version!");
return;
}
config = match config_version.major {
0 => match config_version.minor {
9 | 10 => outdated_upgrade(&config_version, package_version),
11 => minor_0_12_upgrade(config, args, &config_version, package_version),
_ => unsupported_upgrade(&config_version, package_version),
},
_ => unsupported_upgrade(&config_version, package_version),
}
} }
unimplemented_upgrade(package_version, &config_version)
} }
pub(crate) fn execute(args: &Upgrade) { pub(crate) fn execute(args: &Upgrade) {
@@ -143,16 +64,15 @@ pub(crate) fn execute(args: &Upgrade) {
let id = &args.id; let id = &args.id;
let existing_config = Config::load_from_file(id).unwrap_or_else(|err| { let existing_config = try_load_current_config(id).unwrap_or_else(|err| {
eprintln!("failed to load existing config file! - {err}"); eprintln!("failed to load existing config file! - {err}");
process::exit(1) process::exit(1)
}); });
if existing_config.get_base().get_version() == MISSING_VALUE { if existing_config.core.base.client.version.is_empty() {
eprintln!("the existing configuration file does not seem to contain version number."); eprintln!("the existing configuration file does not seem to contain version number.");
process::exit(1); process::exit(1);
} }
// here be upgrade path to 0.9.X and beyond based on version number from config
do_upgrade(existing_config, args, &package_version) do_upgrade(existing_config, args, &package_version)
} }
+155
View File
@@ -0,0 +1,155 @@
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::config::persistence::SocksClientPaths;
use crate::config::template::CONFIG_TEMPLATE;
use nym_bin_common::logging::LoggingSettings;
use nym_config::{
must_get_home, read_config_from_toml_file, save_formatted_config_to_file, NymConfigTemplate,
DEFAULT_CONFIG_DIR, DEFAULT_CONFIG_FILENAME, DEFAULT_DATA_DIR, NYM_DIR,
};
use serde::{Deserialize, Serialize};
use std::fmt::Debug;
use std::io;
use std::path::{Path, PathBuf};
use std::str::FromStr;
pub use nym_client_core::config::Config as BaseClientConfig;
pub use nym_socks5_client_core::config::Config as CoreConfig;
pub mod old_config_v1_1_13;
pub mod old_config_v1_1_19;
mod persistence;
mod template;
const DEFAULT_SOCKS5_CLIENTS_DIR: &str = "socks5-clients";
/// Derive default path to clients's config directory.
/// It should get resolved to `$HOME/.nym/socks5-clients/<id>/config`
pub fn default_config_directory<P: AsRef<Path>>(id: P) -> PathBuf {
must_get_home()
.join(NYM_DIR)
.join(DEFAULT_SOCKS5_CLIENTS_DIR)
.join(id)
.join(DEFAULT_CONFIG_DIR)
}
/// Derive default path to client's config file.
/// It should get resolved to `$HOME/.nym/socks5-clients/<id>/config/config.toml`
pub fn default_config_filepath<P: AsRef<Path>>(id: P) -> PathBuf {
default_config_directory(id).join(DEFAULT_CONFIG_FILENAME)
}
/// Derive default path to client's data directory where files, such as keys, are stored.
/// It should get resolved to `$HOME/.nym/socks5-clients/<id>/data`
pub fn default_data_directory<P: AsRef<Path>>(id: P) -> PathBuf {
must_get_home()
.join(NYM_DIR)
.join(DEFAULT_SOCKS5_CLIENTS_DIR)
.join(id)
.join(DEFAULT_DATA_DIR)
}
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct Config {
pub core: CoreConfig,
pub storage_paths: SocksClientPaths,
pub logging: LoggingSettings,
}
impl NymConfigTemplate for Config {
fn template() -> &'static str {
CONFIG_TEMPLATE
}
}
impl Config {
pub fn new<S: AsRef<str>>(id: S, provider_mix_address: S) -> Self {
Config {
core: CoreConfig::new(id.as_ref(), provider_mix_address.as_ref()),
storage_paths: SocksClientPaths::new_default(default_data_directory(id.as_ref())),
logging: Default::default(),
}
}
pub fn read_from_toml_file<P: AsRef<Path>>(path: P) -> io::Result<Self> {
read_config_from_toml_file(path)
}
pub fn read_from_default_path<P: AsRef<Path>>(id: P) -> io::Result<Self> {
Self::read_from_toml_file(default_config_filepath(id))
}
pub fn default_location(&self) -> PathBuf {
default_config_filepath(&self.core.base.client.id)
}
pub fn save_to_default_location(&self) -> io::Result<()> {
let config_save_location: PathBuf = self.default_location();
save_formatted_config_to_file(self, config_save_location)
}
pub fn validate(&self) -> bool {
// no other sections have explicit requirements (yet)
self.core.validate()
}
pub fn with_port(mut self, port: u16) -> Self {
self.core.socks5.listening_port = port;
self
}
pub fn with_anonymous_replies(mut self, anonymous_replies: bool) -> Self {
self.core.socks5.send_anonymously = anonymous_replies;
self
}
// poor man's 'builder' method
pub fn with_base<F, T>(mut self, f: F, val: T) -> Self
where
F: Fn(BaseClientConfig, T) -> BaseClientConfig,
{
self.core = self.core.with_base(f, val);
self
}
pub fn with_optional_base<F, T>(mut self, f: F, val: Option<T>) -> Self
where
F: Fn(BaseClientConfig, T) -> BaseClientConfig,
{
self.core = self.core.with_optional_base(f, val);
self
}
#[allow(unused)]
pub fn with_optional_base_env<F, T>(mut self, f: F, val: Option<T>, env_var: &str) -> Self
where
F: Fn(BaseClientConfig, T) -> BaseClientConfig,
T: FromStr,
<T as FromStr>::Err: Debug,
{
self.core = self.core.with_optional_base_env(f, val, env_var);
self
}
pub fn with_optional_base_custom_env<F, T, G>(
mut self,
f: F,
val: Option<T>,
env_var: &str,
parser: G,
) -> Self
where
F: Fn(BaseClientConfig, T) -> BaseClientConfig,
G: Fn(&str) -> T,
{
self.core = self
.core
.with_optional_base_custom_env(f, val, env_var, parser);
self
}
}
@@ -0,0 +1,38 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::config::old_config_v1_1_19::{ConfigV1_1_19, Socks5V1_1_19};
use nym_client_core::config::old_config_v1_1_13::OldConfigV1_1_13 as OldBaseConfigV1_1_13;
use nym_config::legacy_helpers::nym_config::MigrationNymConfig;
use nym_config::must_get_home;
use serde::{Deserialize, Serialize};
use std::path::PathBuf;
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct OldConfigV1_1_13 {
#[serde(flatten)]
pub base: OldBaseConfigV1_1_13<OldConfigV1_1_13>,
pub socks5: Socks5V1_1_19,
}
impl MigrationNymConfig for OldConfigV1_1_13 {
fn default_root_directory() -> PathBuf {
#[cfg(not(any(target_os = "android", target_os = "ios")))]
let base_dir = must_get_home();
#[cfg(any(target_os = "android", target_os = "ios"))]
let base_dir = PathBuf::from("/tmp");
base_dir.join(".nym").join("socks5-clients")
}
}
impl From<OldConfigV1_1_13> for ConfigV1_1_19 {
fn from(value: OldConfigV1_1_13) -> Self {
ConfigV1_1_19 {
base: value.base.into(),
socks5: value.socks5,
}
}
}
@@ -0,0 +1,135 @@
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::config::persistence::SocksClientPaths;
use crate::config::{BaseClientConfig, Config, CoreConfig};
use nym_bin_common::logging::LoggingSettings;
use nym_client_core::config::disk_persistence::keys_paths::ClientKeysPaths;
use nym_client_core::config::disk_persistence::CommonClientPaths;
use nym_client_core::config::old_config_v1_1_19::ConfigV1_1_19 as BaseConfigV1_1_19;
use nym_client_core::config::Client;
use nym_config::legacy_helpers::nym_config::MigrationNymConfig;
use nym_config::must_get_home;
use nym_socks5_client_core::config::{
ProviderInterfaceVersion, Socks5, Socks5Debug, Socks5ProtocolVersion,
};
use serde::{Deserialize, Serialize};
use std::fmt::Debug;
use std::path::PathBuf;
const DEFAULT_CONNECTION_START_SURBS: u32 = 20;
const DEFAULT_PER_REQUEST_SURBS: u32 = 3;
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct ConfigV1_1_19 {
#[serde(flatten)]
pub base: BaseConfigV1_1_19<ConfigV1_1_19>,
pub socks5: Socks5V1_1_19,
}
impl From<ConfigV1_1_19> for Config {
fn from(value: ConfigV1_1_19) -> Self {
Config {
core: CoreConfig {
base: BaseClientConfig {
client: Client {
version: value.base.client.version,
id: value.base.client.id,
disabled_credentials_mode: value.base.client.disabled_credentials_mode,
nyxd_urls: value.base.client.nyxd_urls,
nym_api_urls: value.base.client.nym_api_urls,
gateway_endpoint: value.base.client.gateway_endpoint.into(),
},
debug: value.base.debug.into(),
},
socks5: value.socks5.into(),
},
storage_paths: SocksClientPaths {
common_paths: CommonClientPaths {
keys: ClientKeysPaths {
private_identity_key_file: value.base.client.private_identity_key_file,
public_identity_key_file: value.base.client.public_identity_key_file,
private_encryption_key_file: value.base.client.private_encryption_key_file,
public_encryption_key_file: value.base.client.public_encryption_key_file,
gateway_shared_key_file: value.base.client.gateway_shared_key_file,
ack_key_file: value.base.client.ack_key_file,
},
credentials_database: value.base.client.database_path,
reply_surb_database: value.base.client.reply_surb_database_path,
},
},
logging: LoggingSettings::default(),
}
}
}
impl MigrationNymConfig for ConfigV1_1_19 {
fn default_root_directory() -> PathBuf {
#[cfg(not(any(target_os = "android", target_os = "ios")))]
let base_dir = must_get_home();
#[cfg(any(target_os = "android", target_os = "ios"))]
let base_dir = PathBuf::from("/tmp");
base_dir.join(".nym").join("socks5-clients")
}
}
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct Socks5V1_1_19 {
pub listening_port: u16,
pub provider_mix_address: String,
#[serde(default = "ProviderInterfaceVersion::new_legacy")]
pub provider_interface_version: ProviderInterfaceVersion,
#[serde(default = "Socks5ProtocolVersion::new_legacy")]
pub socks5_protocol_version: Socks5ProtocolVersion,
#[serde(default)]
pub send_anonymously: bool,
#[serde(default)]
pub socks5_debug: Socks5DebugV1_1_19,
}
impl From<Socks5V1_1_19> for Socks5 {
fn from(value: Socks5V1_1_19) -> Self {
Socks5 {
listening_port: value.listening_port,
provider_mix_address: value.provider_mix_address,
provider_interface_version: value.provider_interface_version,
socks5_protocol_version: value.socks5_protocol_version,
send_anonymously: value.send_anonymously,
socks5_debug: value.socks5_debug.into(),
}
}
}
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct Socks5DebugV1_1_19 {
connection_start_surbs: u32,
per_request_surbs: u32,
}
impl From<Socks5DebugV1_1_19> for Socks5Debug {
fn from(value: Socks5DebugV1_1_19) -> Self {
Socks5Debug {
connection_start_surbs: value.connection_start_surbs,
per_request_surbs: value.per_request_surbs,
}
}
}
impl Default for Socks5DebugV1_1_19 {
fn default() -> Self {
Socks5DebugV1_1_19 {
connection_start_surbs: DEFAULT_CONNECTION_START_SURBS,
per_request_surbs: DEFAULT_PER_REQUEST_SURBS,
}
}
}
+20
View File
@@ -0,0 +1,20 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use nym_client_core::config::disk_persistence::CommonClientPaths;
use serde::{Deserialize, Serialize};
use std::path::Path;
#[derive(Debug, Deserialize, PartialEq, Eq, Serialize, Clone)]
pub struct SocksClientPaths {
#[serde(flatten)]
pub common_paths: CommonClientPaths,
}
impl SocksClientPaths {
pub fn new_default<P: AsRef<Path>>(base_data_directory: P) -> Self {
SocksClientPaths {
common_paths: CommonClientPaths::new_default(base_data_directory),
}
}
}
@@ -1,102 +1,97 @@
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net> // Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
pub(crate) fn config_template() -> &'static str { // While using normal toml marshalling would have been way simpler with less overhead,
// While using normal toml marshalling would have been way simpler with less overhead, // I think it's useful to have comments attached to the saved config file to explain behaviour of
// I think it's useful to have comments attached to the saved config file to explain behaviour of // particular fields.
// particular fields. // Note: any changes to the template must be reflected in the appropriate structs.
// Note: any changes to the template must be reflected in the appropriate structs. pub(crate) const CONFIG_TEMPLATE: &str = r#"
r#"
# This is a TOML config file. # This is a TOML config file.
# For more information, see https://github.com/toml-lang/toml # For more information, see https://github.com/toml-lang/toml
##### main base client config options ##### ##### main base client config options #####
[client] [core.client]
# Version of the client for which this configuration was created. # Version of the client for which this configuration was created.
version = '{{ client.version }}' version = '{{ core.client.version }}'
# Human readable ID of this particular client. # Human readable ID of this particular client.
id = '{{ client.id }}' id = '{{ core.client.id }}'
# Indicates whether this client is running in a disabled credentials mode, thus attempting # Indicates whether this client is running in a disabled credentials mode, thus attempting
# to claim bandwidth without presenting bandwidth credentials. # to claim bandwidth without presenting bandwidth credentials.
disabled_credentials_mode = {{ client.disabled_credentials_mode }} disabled_credentials_mode = {{ core.client.disabled_credentials_mode }}
# Addresses to nyxd validators via which the client can communicate with the chain. # Addresses to nyxd validators via which the client can communicate with the chain.
nyxd_urls = [ nyxd_urls = [
{{#each client.nyxd_urls }} {{#each core.client.nyxd_urls }}
'{{this}}', '{{this}}',
{{/each}} {{/each}}
] ]
# Addresses to APIs running on validator from which the client gets the view of the network. # Addresses to APIs running on validator from which the client gets the view of the network.
nym_api_urls = [ nym_api_urls = [
{{#each client.nym_api_urls }} {{#each core.client.nym_api_urls }}
'{{this}}', '{{this}}',
{{/each}} {{/each}}
] ]
[storage_paths]
# Path to file containing private identity key. # Path to file containing private identity key.
private_identity_key_file = '{{ client.private_identity_key_file }}' keys.private_identity_key_file = '{{ storage_paths.keys.private_identity_key_file }}'
# Path to file containing public identity key. # Path to file containing public identity key.
public_identity_key_file = '{{ client.public_identity_key_file }}' keys.public_identity_key_file = '{{ storage_paths.keys.public_identity_key_file }}'
# Path to file containing private encryption key. # Path to file containing private encryption key.
private_encryption_key_file = '{{ client.private_encryption_key_file }}' keys.private_encryption_key_file = '{{ storage_paths.keys.private_encryption_key_file }}'
# Path to file containing public encryption key. # Path to file containing public encryption key.
public_encryption_key_file = '{{ client.public_encryption_key_file }}' keys.public_encryption_key_file = '{{ storage_paths.keys.public_encryption_key_file }}'
# Path to the database containing bandwidth credentials
database_path = '{{ client.database_path }}'
# Path to the persistent store for received reply surbs, unused encryption keys and used sender tags.
reply_surb_database_path = '{{ client.reply_surb_database_path }}'
##### additional client config options #####
# A gateway specific, optional, base58 stringified shared key used for # A gateway specific, optional, base58 stringified shared key used for
# communication with particular gateway. # communication with particular gateway.
gateway_shared_key_file = '{{ client.gateway_shared_key_file }}' keys.gateway_shared_key_file = '{{ storage_paths.keys.gateway_shared_key_file }}'
# Path to file containing key used for encrypting and decrypting the content of an # Path to file containing key used for encrypting and decrypting the content of an
# acknowledgement so that nobody besides the client knows which packet it refers to. # acknowledgement so that nobody besides the client knows which packet it refers to.
ack_key_file = '{{ client.ack_key_file }}' keys.ack_key_file = '{{ storage_paths.keys.ack_key_file }}'
##### advanced configuration options ##### # Path to the database containing bandwidth credentials
credentials_database = '{{ storage_paths.credentials_database }}'
# Absolute path to the home Nym Clients directory. # Path to the persistent store for received reply surbs, unused encryption keys and used sender tags.
nym_root_directory = '{{ client.nym_root_directory }}' reply_surb_database = '{{ storage_paths.reply_surb_database }}'
[client.gateway_endpoint] # DEPRECATED
[core.client.gateway_endpoint]
# ID of the gateway from which the client should be fetching messages. # ID of the gateway from which the client should be fetching messages.
gateway_id = '{{ client.gateway_endpoint.gateway_id }}' gateway_id = '{{ core.client.gateway_endpoint.gateway_id }}'
# Address of the gateway owner to which the client should send messages. # Address of the gateway owner to which the client should send messages.
gateway_owner = '{{ client.gateway_endpoint.gateway_owner }}' gateway_owner = '{{ core.client.gateway_endpoint.gateway_owner }}'
# Address of the gateway listener to which all client requests should be sent. # Address of the gateway listener to which all client requests should be sent.
gateway_listener = '{{ client.gateway_endpoint.gateway_listener }}' gateway_listener = '{{ core.client.gateway_endpoint.gateway_listener }}'
##### socket config options ##### ##### socket config options #####
[socks5] [core.socks5]
# The mix address of the provider to which all requests are going to be sent. # The mix address of the provider to which all requests are going to be sent.
provider_mix_address = '{{ socks5.provider_mix_address }}' provider_mix_address = '{{ core.socks5.provider_mix_address }}'
# The port on which the client will be listening for incoming requests # The port on which the client will be listening for incoming requests
listening_port = {{ socks5.listening_port }} listening_port = {{ core.socks5.listening_port }}
# Specifies whether this client is going to use an anonymous sender tag for communication with the service provider. # 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 # 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. # slower and consume nearly double the bandwidth as it will require sending reply SURBs.
# #
# Note that some service providers might not support this. # Note that some service providers might not support this.
send_anonymously = {{ socks5.send_anonymously }} send_anonymously = {{ core.socks5.send_anonymously }}
##### logging configuration options ##### ##### logging configuration options #####
@@ -109,20 +104,19 @@ send_anonymously = {{ socks5.send_anonymously }}
# The following options should not be modified unless you know EXACTLY what you are doing # The following options should not be modified unless you know EXACTLY what you are doing
# as if set incorrectly, they may impact your anonymity. # as if set incorrectly, they may impact your anonymity.
# [socks5.socks5_debug] # [core.socks5.socks5_debug]
[debug] [core.debug]
[debug.traffic] [core.debug.traffic]
average_packet_delay = '{{ debug.traffic.average_packet_delay }}' average_packet_delay = '{{ core.debug.traffic.average_packet_delay }}'
message_sending_average_delay = '{{ debug.traffic.message_sending_average_delay }}' message_sending_average_delay = '{{ core.debug.traffic.message_sending_average_delay }}'
[debug.acknowledgements] [core.debug.acknowledgements]
average_ack_delay = '{{ debug.acknowledgements.average_ack_delay }}' average_ack_delay = '{{ core.debug.acknowledgements.average_ack_delay }}'
[debug.cover_traffic] [core.debug.cover_traffic]
loop_cover_traffic_average_delay = '{{ debug.cover_traffic.loop_cover_traffic_average_delay }}' loop_cover_traffic_average_delay = '{{ core.debug.cover_traffic.loop_cover_traffic_average_delay }}'
"# "#;
}
+1
View File
@@ -8,6 +8,7 @@ use nym_bin_common::logging::{maybe_print_banner, setup_logging};
use nym_network_defaults::setup_env; use nym_network_defaults::setup_env;
mod commands; mod commands;
mod config;
pub mod error; pub mod error;
#[tokio::main] #[tokio::main]
+90 -28
View File
@@ -865,20 +865,6 @@ dependencies = [
"zeroize", "zeroize",
] ]
[[package]]
name = "cw-controllers"
version = "0.13.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4f0bc6019b4d3d81e11f5c384bcce7173e2210bd654d75c6c9668e12cca05dfa"
dependencies = [
"cosmwasm-std",
"cw-storage-plus",
"cw-utils",
"schemars",
"serde",
"thiserror",
]
[[package]] [[package]]
name = "cw-storage-plus" name = "cw-storage-plus"
version = "0.13.4" version = "0.13.4"
@@ -995,7 +981,16 @@ version = "4.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059"
dependencies = [ dependencies = [
"dirs-sys", "dirs-sys 0.3.7",
]
[[package]]
name = "dirs"
version = "5.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225"
dependencies = [
"dirs-sys 0.4.1",
] ]
[[package]] [[package]]
@@ -1009,6 +1004,18 @@ dependencies = [
"winapi", "winapi",
] ]
[[package]]
name = "dirs-sys"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c"
dependencies = [
"libc",
"option-ext",
"redox_users",
"windows-sys 0.48.0",
]
[[package]] [[package]]
name = "dotenv" name = "dotenv"
version = "0.15.0" version = "0.15.0"
@@ -2228,6 +2235,7 @@ dependencies = [
"log", "log",
"pretty_env_logger", "pretty_env_logger",
"semver 0.11.0", "semver 0.11.0",
"serde",
"vergen", "vergen",
] ]
@@ -2237,7 +2245,7 @@ version = "1.1.14"
dependencies = [ dependencies = [
"async-trait", "async-trait",
"dashmap", "dashmap",
"dirs", "dirs 4.0.0",
"futures", "futures",
"gloo-timers", "gloo-timers",
"humantime-serde", "humantime-serde",
@@ -2370,18 +2378,18 @@ dependencies = [
name = "nym-config" name = "nym-config"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"cfg-if 1.0.0", "dirs 5.0.1",
"handlebars", "handlebars",
"log", "log",
"nym-network-defaults", "nym-network-defaults",
"serde", "serde",
"toml", "toml 0.7.4",
"url", "url",
] ]
[[package]] [[package]]
name = "nym-contracts-common" name = "nym-contracts-common"
version = "0.5.0" version = "0.4.0"
dependencies = [ dependencies = [
"bs58", "bs58",
"cosmwasm-std", "cosmwasm-std",
@@ -2416,7 +2424,7 @@ dependencies = [
[[package]] [[package]]
name = "nym-crypto" name = "nym-crypto"
version = "0.4.0" version = "0.3.0"
dependencies = [ dependencies = [
"aes 0.8.2", "aes 0.8.2",
"blake3", "blake3",
@@ -2523,7 +2531,7 @@ dependencies = [
[[package]] [[package]]
name = "nym-mixnet-contract-common" name = "nym-mixnet-contract-common"
version = "0.6.0" version = "0.5.0"
dependencies = [ dependencies = [
"bs58", "bs58",
"cosmwasm-std", "cosmwasm-std",
@@ -2623,7 +2631,7 @@ dependencies = [
[[package]] [[package]]
name = "nym-pemstore" name = "nym-pemstore"
version = "0.3.0" version = "0.2.0"
dependencies = [ dependencies = [
"pem", "pem",
] ]
@@ -2633,12 +2641,8 @@ name = "nym-service-provider-directory-common"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"cosmwasm-std", "cosmwasm-std",
"cw-controllers",
"cw-utils",
"nym-contracts-common",
"schemars", "schemars",
"serde", "serde",
"thiserror",
] ]
[[package]] [[package]]
@@ -2891,7 +2895,7 @@ dependencies = [
[[package]] [[package]]
name = "nym-vesting-contract-common" name = "nym-vesting-contract-common"
version = "0.7.0" version = "0.6.0"
dependencies = [ dependencies = [
"cosmwasm-std", "cosmwasm-std",
"nym-contracts-common", "nym-contracts-common",
@@ -2962,6 +2966,12 @@ dependencies = [
"vcpkg", "vcpkg",
] ]
[[package]]
name = "option-ext"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
[[package]] [[package]]
name = "pairing" name = "pairing"
version = "0.20.0" version = "0.20.0"
@@ -3834,6 +3844,15 @@ dependencies = [
"syn 2.0.16", "syn 2.0.16",
] ]
[[package]]
name = "serde_spanned"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93107647184f6027e3b7dcb2e11034cf95ffa1e3a682c67951963ac69c1c007d"
dependencies = [
"serde",
]
[[package]] [[package]]
name = "serde_urlencoded" name = "serde_urlencoded"
version = "0.7.1" version = "0.7.1"
@@ -4317,7 +4336,7 @@ dependencies = [
"serde", "serde",
"serde_json", "serde_json",
"tendermint", "tendermint",
"toml", "toml 0.5.11",
"url", "url",
] ]
@@ -4554,6 +4573,40 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "toml"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d6135d499e69981f9ff0ef2167955a5333c35e36f6937d382974566b3d5b94ec"
dependencies = [
"serde",
"serde_spanned",
"toml_datetime",
"toml_edit",
]
[[package]]
name = "toml_datetime"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a76a9312f5ba4c2dec6b9161fdf25d87ad8a09256ccea5a556fef03c706a10f"
dependencies = [
"serde",
]
[[package]]
name = "toml_edit"
version = "0.19.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2380d56e8670370eee6566b0bfd4265f65b3f432e8c6d85623f728d4fa31f739"
dependencies = [
"indexmap",
"serde",
"serde_spanned",
"toml_datetime",
"winnow",
]
[[package]] [[package]]
name = "tower-service" name = "tower-service"
version = "0.3.2" version = "0.3.2"
@@ -5142,6 +5195,15 @@ version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
[[package]]
name = "winnow"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61de7bac303dc551fe038e2b3cef0f571087a47571ea6e79a87692ac99b99699"
dependencies = [
"memchr",
]
[[package]] [[package]]
name = "winreg" name = "winreg"
version = "0.10.1" version = "0.10.1"
+8 -8
View File
@@ -107,20 +107,20 @@ function printAndDisplayTestResult(result) {
} }
async function testWithTester() { async function testWithTester() {
const dummyGateway = "336yuXAeGEgedRfqTJZsG2YV7P13QH1bHv1SjCZYarc9"; const preferredGateway = "336yuXAeGEgedRfqTJZsG2YV7P13QH1bHv1SjCZYarc9";
// A) construct with hardcoded topology // A) construct with hardcoded topology
const topology = dummyTopology() const topology = dummyTopology()
const nodeTester = await new NymNodeTester(topology, dummyGateway); const nodeTester = await new NymNodeTester(topology, preferredGateway);
// B) first get topology directly from nym-api // B) first get topology directly from nym-api
// const validator = 'https://qwerty-validator-api.qa.nymte.ch/api'; // const validator = 'https://qwerty-validator-api.qa.nymte.ch/api';
// const topology = await current_network_topology(validator) // const topology = await current_network_topology(validator)
// const nodeTester = await new NymNodeTester(topology, dummyGateway); // const nodeTester = await new NymNodeTester(topology, preferredGateway);
// //
// C) use nym-api in the constructor (note: it does no filtering for 'good' nodes on other layers) // C) use nym-api in the constructor (note: it does no filtering for 'good' nodes on other layers)
// const validator = 'https://qwerty-validator-api.qa.nymte.ch/api'; // const validator = 'https://qwerty-validator-api.qa.nymte.ch/api';
// const nodeTester = await NymNodeTester.new_with_api(validator, dummyGateway) // const nodeTester = await NymNodeTester.new_with_api(validator, preferredGateway)
// D, E, F) you also don't have to specify the gateway. if you don't, a random one (from your topology) will be used // D, E, F) you also don't have to specify the gateway. if you don't, a random one (from your topology) will be used
// const topology = dummyTopology() // const topology = dummyTopology()
@@ -142,7 +142,7 @@ async function testWithTester() {
} }
async function testWithNymClient() { async function testWithNymClient() {
const dummyGateway = "336yuXAeGEgedRfqTJZsG2YV7P13QH1bHv1SjCZYarc9"; const preferredGateway = "336yuXAeGEgedRfqTJZsG2YV7P13QH1bHv1SjCZYarc9";
const topology = dummyTopology() const topology = dummyTopology()
let received = 0 let received = 0
@@ -164,7 +164,7 @@ async function testWithNymClient() {
console.log('Instantiating WASM client...'); console.log('Instantiating WASM client...');
let clientBuilder = NymClientBuilder.new_tester(topology, onMessageHandler, dummyGateway) let clientBuilder = NymClientBuilder.new_tester(topology, onMessageHandler, preferredGateway)
console.log('Web worker creating WASM client...'); console.log('Web worker creating WASM client...');
let local_client = await clientBuilder.start_client(); let local_client = await clientBuilder.start_client();
console.log('WASM client running!'); console.log('WASM client running!');
@@ -222,10 +222,10 @@ async function normalNymClientUsage() {
debug.topology_refresh_rate_ms = BigInt(60000) debug.topology_refresh_rate_ms = BigInt(60000)
const dummyGateway = "336yuXAeGEgedRfqTJZsG2YV7P13QH1bHv1SjCZYarc9"; const preferredGateway = "336yuXAeGEgedRfqTJZsG2YV7P13QH1bHv1SjCZYarc9";
const validator = 'https://qwerty-validator-api.qa.nymte.ch/api'; const validator = 'https://qwerty-validator-api.qa.nymte.ch/api';
const config = new Config('my-awesome-wasm-client', validator, dummyGateway, debug); const config = new Config('my-awesome-wasm-client', validator, debug);
const onMessageHandler = (message) => { const onMessageHandler = (message) => {
console.log(message); console.log(message);
+72 -86
View File
@@ -7,73 +7,49 @@
#![allow(clippy::drop_copy)] #![allow(clippy::drop_copy)]
use nym_client_core::config::{ use nym_client_core::config::{
Acknowledgements as ConfigAcknowledgements, CoverTraffic as ConfigCoverTraffic, Acknowledgements as ConfigAcknowledgements, Config as BaseClientConfig,
DebugConfig as ConfigDebug, GatewayConnection as ConfigGatewayConnection, CoverTraffic as ConfigCoverTraffic, DebugConfig as ConfigDebug,
ReplySurbs as ConfigReplySurbs, Topology as ConfigTopology, Traffic as ConfigTraffic, GatewayConnection as ConfigGatewayConnection, ReplySurbs as ConfigReplySurbs,
Topology as ConfigTopology, Traffic as ConfigTraffic,
}; };
use nym_sphinx::params::{PacketSize, PacketType}; use nym_sphinx::params::{PacketSize, PacketType};
use nym_validator_client::client::IdentityKey;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::time::Duration; use std::time::Duration;
use url::Url;
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;
#[wasm_bindgen] #[wasm_bindgen]
#[derive(Debug, Deserialize, PartialEq, Serialize)] #[derive(Debug, Deserialize, PartialEq, Serialize)]
#[serde(deny_unknown_fields)] #[serde(deny_unknown_fields)]
pub struct Config { pub struct Config {
/// ID specifies the human readable ID of this particular client. pub(crate) base: BaseClientConfig,
pub(crate) id: String,
pub(crate) nym_api_url: Option<Url>,
pub(crate) disabled_credentials_mode: bool,
/// Information regarding how the client should choose gateway.
/// If unspecified, the client will attempt to load the config from the storage.
pub(crate) gateway: Option<IdentityKey>,
pub(crate) debug: ConfigDebug,
pub(crate) packet_type: PacketType,
} }
#[wasm_bindgen] #[wasm_bindgen]
impl Config { impl Config {
#[wasm_bindgen(constructor)] #[wasm_bindgen(constructor)]
pub fn new( pub fn new(id: String, validator_server: String, debug: Option<DebugWasm>) -> Self {
id: String,
validator_server: String,
packet_type: Option<String>,
gateway: Option<IdentityKey>,
debug: Option<Debug>,
) -> Self {
let packet_type = if let Some(packet_type) = packet_type {
match packet_type.as_str() {
"outfox" => PacketType::Outfox,
_ => PacketType::Mix,
}
} else {
PacketType::Mix
};
Config { Config {
id, base: BaseClientConfig::new(id)
nym_api_url: Some( .with_custom_nyxd(vec![validator_server
validator_server
.parse() .parse()
.expect("provided url was malformed"), .expect("provided url was malformed")])
), .with_debug_config(debug.map(Into::into).unwrap_or_default()),
disabled_credentials_mode: true, }
gateway, }
debug: debug.map(Into::into).unwrap_or_default(),
packet_type, pub(crate) fn new_tester_config<S: Into<String>>(id: S) -> Self {
Config {
base: BaseClientConfig::new(id)
.with_disabled_credentials(true)
.with_disabled_cover_traffic(true)
.with_disabled_topology_refresh(true),
} }
} }
} }
#[wasm_bindgen] #[wasm_bindgen]
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
pub struct Traffic { pub struct TrafficWasm {
/// The parameter of Poisson distribution determining how long, on average, /// The parameter of Poisson distribution determining how long, on average,
/// sent packet is going to be delayed at any given mix node. /// sent packet is going to be delayed at any given mix node.
/// So for a packet going through three mix nodes, on average, it will take three times this value /// So for a packet going through three mix nodes, on average, it will take three times this value
@@ -92,14 +68,23 @@ pub struct Traffic {
/// Controls whether the sent sphinx packet use the NON-DEFAULT bigger size. /// Controls whether the sent sphinx packet use the NON-DEFAULT bigger size.
pub use_extended_packet_size: bool, pub use_extended_packet_size: bool,
/// Controls whether the sent packets should use outfox as opposed to the default sphinx.
pub use_outfox: bool,
} }
impl From<Traffic> for ConfigTraffic { impl From<TrafficWasm> for ConfigTraffic {
fn from(traffic: Traffic) -> Self { fn from(traffic: TrafficWasm) -> Self {
let use_extended_packet_size = traffic let use_extended_packet_size = traffic
.use_extended_packet_size .use_extended_packet_size
.then(|| PacketSize::ExtendedPacket32); .then(|| PacketSize::ExtendedPacket32);
let packet_type = if traffic.use_outfox {
PacketType::Outfox
} else {
PacketType::Mix
};
ConfigTraffic { ConfigTraffic {
average_packet_delay: Duration::from_millis(traffic.average_packet_delay_ms), average_packet_delay: Duration::from_millis(traffic.average_packet_delay_ms),
message_sending_average_delay: Duration::from_millis( message_sending_average_delay: Duration::from_millis(
@@ -109,27 +94,28 @@ impl From<Traffic> for ConfigTraffic {
.disable_main_poisson_packet_distribution, .disable_main_poisson_packet_distribution,
primary_packet_size: PacketSize::RegularPacket, primary_packet_size: PacketSize::RegularPacket,
secondary_packet_size: use_extended_packet_size, secondary_packet_size: use_extended_packet_size,
packet_type: None, packet_type,
} }
} }
} }
impl From<ConfigTraffic> for Traffic { impl From<ConfigTraffic> for TrafficWasm {
fn from(traffic: ConfigTraffic) -> Self { fn from(traffic: ConfigTraffic) -> Self {
Traffic { TrafficWasm {
average_packet_delay_ms: traffic.average_packet_delay.as_millis() as u64, average_packet_delay_ms: traffic.average_packet_delay.as_millis() as u64,
message_sending_average_delay_ms: traffic.message_sending_average_delay.as_millis() message_sending_average_delay_ms: traffic.message_sending_average_delay.as_millis()
as u64, as u64,
disable_main_poisson_packet_distribution: traffic disable_main_poisson_packet_distribution: traffic
.disable_main_poisson_packet_distribution, .disable_main_poisson_packet_distribution,
use_extended_packet_size: traffic.secondary_packet_size.is_some(), use_extended_packet_size: traffic.secondary_packet_size.is_some(),
use_outfox: traffic.packet_type == PacketType::Outfox,
} }
} }
} }
#[wasm_bindgen] #[wasm_bindgen]
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
pub struct CoverTraffic { pub struct CoverTrafficWasm {
/// The parameter of Poisson distribution determining how long, on average, /// The parameter of Poisson distribution determining how long, on average,
/// it is going to take for another loop cover traffic message to be sent. /// it is going to take for another loop cover traffic message to be sent.
pub loop_cover_traffic_average_delay_ms: u64, pub loop_cover_traffic_average_delay_ms: u64,
@@ -143,8 +129,8 @@ pub struct CoverTraffic {
pub disable_loop_cover_traffic_stream: bool, pub disable_loop_cover_traffic_stream: bool,
} }
impl From<CoverTraffic> for ConfigCoverTraffic { impl From<CoverTrafficWasm> for ConfigCoverTraffic {
fn from(cover_traffic: CoverTraffic) -> Self { fn from(cover_traffic: CoverTrafficWasm) -> Self {
ConfigCoverTraffic { ConfigCoverTraffic {
loop_cover_traffic_average_delay: Duration::from_millis( loop_cover_traffic_average_delay: Duration::from_millis(
cover_traffic.loop_cover_traffic_average_delay_ms, cover_traffic.loop_cover_traffic_average_delay_ms,
@@ -155,9 +141,9 @@ impl From<CoverTraffic> for ConfigCoverTraffic {
} }
} }
impl From<ConfigCoverTraffic> for CoverTraffic { impl From<ConfigCoverTraffic> for CoverTrafficWasm {
fn from(cover_traffic: ConfigCoverTraffic) -> Self { fn from(cover_traffic: ConfigCoverTraffic) -> Self {
CoverTraffic { CoverTrafficWasm {
loop_cover_traffic_average_delay_ms: cover_traffic loop_cover_traffic_average_delay_ms: cover_traffic
.loop_cover_traffic_average_delay .loop_cover_traffic_average_delay
.as_millis() as u64, .as_millis() as u64,
@@ -169,14 +155,14 @@ impl From<ConfigCoverTraffic> for CoverTraffic {
#[wasm_bindgen] #[wasm_bindgen]
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
pub struct GatewayConnection { pub struct GatewayConnectionWasm {
/// How long we're willing to wait for a response to a message sent to the gateway, /// How long we're willing to wait for a response to a message sent to the gateway,
/// before giving up on it. /// before giving up on it.
pub gateway_response_timeout_ms: u64, pub gateway_response_timeout_ms: u64,
} }
impl From<GatewayConnection> for ConfigGatewayConnection { impl From<GatewayConnectionWasm> for ConfigGatewayConnection {
fn from(gateway_connection: GatewayConnection) -> Self { fn from(gateway_connection: GatewayConnectionWasm) -> Self {
ConfigGatewayConnection { ConfigGatewayConnection {
gateway_response_timeout: Duration::from_millis( gateway_response_timeout: Duration::from_millis(
gateway_connection.gateway_response_timeout_ms, gateway_connection.gateway_response_timeout_ms,
@@ -185,9 +171,9 @@ impl From<GatewayConnection> for ConfigGatewayConnection {
} }
} }
impl From<ConfigGatewayConnection> for GatewayConnection { impl From<ConfigGatewayConnection> for GatewayConnectionWasm {
fn from(gateway_connection: ConfigGatewayConnection) -> Self { fn from(gateway_connection: ConfigGatewayConnection) -> Self {
GatewayConnection { GatewayConnectionWasm {
gateway_response_timeout_ms: gateway_connection.gateway_response_timeout.as_millis() gateway_response_timeout_ms: gateway_connection.gateway_response_timeout.as_millis()
as u64, as u64,
} }
@@ -196,7 +182,7 @@ impl From<ConfigGatewayConnection> for GatewayConnection {
#[wasm_bindgen] #[wasm_bindgen]
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
pub struct Acknowledgements { pub struct AcknowledgementsWasm {
/// The parameter of Poisson distribution determining how long, on average, /// The parameter of Poisson distribution determining how long, on average,
/// sent acknowledgement is going to be delayed at any given mix node. /// sent acknowledgement is going to be delayed at any given mix node.
/// So for an ack going through three mix nodes, on average, it will take three times this value /// So for an ack going through three mix nodes, on average, it will take three times this value
@@ -214,8 +200,8 @@ pub struct Acknowledgements {
pub ack_wait_addition_ms: u64, pub ack_wait_addition_ms: u64,
} }
impl From<Acknowledgements> for ConfigAcknowledgements { impl From<AcknowledgementsWasm> for ConfigAcknowledgements {
fn from(acknowledgements: Acknowledgements) -> Self { fn from(acknowledgements: AcknowledgementsWasm) -> Self {
ConfigAcknowledgements { ConfigAcknowledgements {
average_ack_delay: Duration::from_millis(acknowledgements.average_ack_delay_ms), average_ack_delay: Duration::from_millis(acknowledgements.average_ack_delay_ms),
ack_wait_multiplier: acknowledgements.ack_wait_multiplier, ack_wait_multiplier: acknowledgements.ack_wait_multiplier,
@@ -224,9 +210,9 @@ impl From<Acknowledgements> for ConfigAcknowledgements {
} }
} }
impl From<ConfigAcknowledgements> for Acknowledgements { impl From<ConfigAcknowledgements> for AcknowledgementsWasm {
fn from(acknowledgements: ConfigAcknowledgements) -> Self { fn from(acknowledgements: ConfigAcknowledgements) -> Self {
Acknowledgements { AcknowledgementsWasm {
average_ack_delay_ms: acknowledgements.average_ack_delay.as_millis() as u64, average_ack_delay_ms: acknowledgements.average_ack_delay.as_millis() as u64,
ack_wait_multiplier: acknowledgements.ack_wait_multiplier, ack_wait_multiplier: acknowledgements.ack_wait_multiplier,
ack_wait_addition_ms: acknowledgements.ack_wait_addition.as_millis() as u64, ack_wait_addition_ms: acknowledgements.ack_wait_addition.as_millis() as u64,
@@ -236,7 +222,7 @@ impl From<ConfigAcknowledgements> for Acknowledgements {
#[wasm_bindgen] #[wasm_bindgen]
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
pub struct Topology { pub struct TopologyWasm {
/// The uniform delay every which clients are querying the directory server /// The uniform delay every which clients are querying the directory server
/// to try to obtain a compatible network topology to send sphinx packets through. /// to try to obtain a compatible network topology to send sphinx packets through.
pub topology_refresh_rate_ms: u64, pub topology_refresh_rate_ms: u64,
@@ -252,8 +238,8 @@ pub struct Topology {
pub disable_refreshing: bool, pub disable_refreshing: bool,
} }
impl From<Topology> for ConfigTopology { impl From<TopologyWasm> for ConfigTopology {
fn from(topology: Topology) -> Self { fn from(topology: TopologyWasm) -> Self {
ConfigTopology { ConfigTopology {
topology_refresh_rate: Duration::from_millis(topology.topology_refresh_rate_ms), topology_refresh_rate: Duration::from_millis(topology.topology_refresh_rate_ms),
topology_resolution_timeout: Duration::from_millis( topology_resolution_timeout: Duration::from_millis(
@@ -264,9 +250,9 @@ impl From<Topology> for ConfigTopology {
} }
} }
impl From<ConfigTopology> for Topology { impl From<ConfigTopology> for TopologyWasm {
fn from(topology: ConfigTopology) -> Self { fn from(topology: ConfigTopology) -> Self {
Topology { TopologyWasm {
topology_refresh_rate_ms: topology.topology_refresh_rate.as_millis() as u64, topology_refresh_rate_ms: topology.topology_refresh_rate.as_millis() as u64,
topology_resolution_timeout_ms: topology.topology_resolution_timeout.as_millis() as u64, topology_resolution_timeout_ms: topology.topology_resolution_timeout.as_millis() as u64,
disable_refreshing: topology.disable_refreshing, disable_refreshing: topology.disable_refreshing,
@@ -276,7 +262,7 @@ impl From<ConfigTopology> for Topology {
#[wasm_bindgen] #[wasm_bindgen]
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
pub struct ReplySurbs { pub struct ReplySurbsWasm {
/// Defines the minimum number of reply surbs the client wants to keep in its storage at all times. /// Defines the minimum number of reply surbs the client wants to keep in its storage at all times.
/// It can only allow to go below that value if its to request additional reply surbs. /// It can only allow to go below that value if its to request additional reply surbs.
pub minimum_reply_surb_storage_threshold: usize, pub minimum_reply_surb_storage_threshold: usize,
@@ -310,8 +296,8 @@ pub struct ReplySurbs {
pub maximum_reply_key_age_ms: u64, pub maximum_reply_key_age_ms: u64,
} }
impl From<ReplySurbs> for ConfigReplySurbs { impl From<ReplySurbsWasm> for ConfigReplySurbs {
fn from(reply_surbs: ReplySurbs) -> Self { fn from(reply_surbs: ReplySurbsWasm) -> Self {
ConfigReplySurbs { ConfigReplySurbs {
minimum_reply_surb_storage_threshold: reply_surbs.minimum_reply_surb_storage_threshold, minimum_reply_surb_storage_threshold: reply_surbs.minimum_reply_surb_storage_threshold,
maximum_reply_surb_storage_threshold: reply_surbs.maximum_reply_surb_storage_threshold, maximum_reply_surb_storage_threshold: reply_surbs.maximum_reply_surb_storage_threshold,
@@ -331,9 +317,9 @@ impl From<ReplySurbs> for ConfigReplySurbs {
} }
} }
impl From<ConfigReplySurbs> for ReplySurbs { impl From<ConfigReplySurbs> for ReplySurbsWasm {
fn from(reply_surbs: ConfigReplySurbs) -> Self { fn from(reply_surbs: ConfigReplySurbs) -> Self {
ReplySurbs { ReplySurbsWasm {
minimum_reply_surb_storage_threshold: reply_surbs.minimum_reply_surb_storage_threshold, minimum_reply_surb_storage_threshold: reply_surbs.minimum_reply_surb_storage_threshold,
maximum_reply_surb_storage_threshold: reply_surbs.maximum_reply_surb_storage_threshold, maximum_reply_surb_storage_threshold: reply_surbs.maximum_reply_surb_storage_threshold,
minimum_reply_surb_request_size: reply_surbs.minimum_reply_surb_request_size, minimum_reply_surb_request_size: reply_surbs.minimum_reply_surb_request_size,
@@ -355,28 +341,28 @@ impl From<ConfigReplySurbs> for ReplySurbs {
// just a helper structure to more easily pass through the JS boundary // just a helper structure to more easily pass through the JS boundary
#[wasm_bindgen] #[wasm_bindgen]
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
pub struct Debug { pub struct DebugWasm {
/// Defines all configuration options related to traffic streams. /// Defines all configuration options related to traffic streams.
pub traffic: Traffic, pub traffic: TrafficWasm,
/// Defines all configuration options related to cover traffic stream(s). /// Defines all configuration options related to cover traffic stream(s).
pub cover_traffic: CoverTraffic, pub cover_traffic: CoverTrafficWasm,
/// Defines all configuration options related to the gateway connection. /// Defines all configuration options related to the gateway connection.
pub gateway_connection: GatewayConnection, pub gateway_connection: GatewayConnectionWasm,
/// Defines all configuration options related to acknowledgements, such as delays or wait timeouts. /// Defines all configuration options related to acknowledgements, such as delays or wait timeouts.
pub acknowledgements: Acknowledgements, pub acknowledgements: AcknowledgementsWasm,
/// Defines all configuration options related topology, such as refresh rates or timeouts. /// Defines all configuration options related topology, such as refresh rates or timeouts.
pub topology: Topology, pub topology: TopologyWasm,
/// Defines all configuration options related to reply SURBs. /// Defines all configuration options related to reply SURBs.
pub reply_surbs: ReplySurbs, pub reply_surbs: ReplySurbsWasm,
} }
impl From<Debug> for ConfigDebug { impl From<DebugWasm> for ConfigDebug {
fn from(debug: Debug) -> Self { fn from(debug: DebugWasm) -> Self {
ConfigDebug { ConfigDebug {
traffic: debug.traffic.into(), traffic: debug.traffic.into(),
cover_traffic: debug.cover_traffic.into(), cover_traffic: debug.cover_traffic.into(),
@@ -388,9 +374,9 @@ impl From<Debug> for ConfigDebug {
} }
} }
impl From<ConfigDebug> for Debug { impl From<ConfigDebug> for DebugWasm {
fn from(debug: ConfigDebug) -> Self { fn from(debug: ConfigDebug) -> Self {
Debug { DebugWasm {
traffic: debug.traffic.into(), traffic: debug.traffic.into(),
cover_traffic: debug.cover_traffic.into(), cover_traffic: debug.cover_traffic.into(),
gateway_connection: debug.gateway_connection.into(), gateway_connection: debug.gateway_connection.into(),
@@ -402,6 +388,6 @@ impl From<ConfigDebug> for Debug {
} }
#[wasm_bindgen] #[wasm_bindgen]
pub fn default_debug() -> Debug { pub fn default_debug() -> DebugWasm {
ConfigDebug::default().into() ConfigDebug::default().into()
} }
+32 -46
View File
@@ -21,7 +21,6 @@ use nym_client_core::client::base_client::{
}; };
use nym_client_core::client::inbound_messages::InputMessage; use nym_client_core::client::inbound_messages::InputMessage;
use nym_client_core::client::replies::reply_storage::browser_backend; use nym_client_core::client::replies::reply_storage::browser_backend;
use nym_client_core::config::{CoverTraffic, DebugConfig, Topology, Traffic};
use nym_credential_storage::ephemeral_storage::EphemeralStorage; use nym_credential_storage::ephemeral_storage::EphemeralStorage;
use nym_sphinx::params::PacketType; use nym_sphinx::params::PacketType;
use nym_task::connections::TransmissionLane; use nym_task::connections::TransmissionLane;
@@ -53,13 +52,15 @@ pub struct NymClient {
// even though we don't use graceful shutdowns, other components rely on existence of this struct // even though we don't use graceful shutdowns, other components rely on existence of this struct
// and if it's dropped, everything will start going offline // and if it's dropped, everything will start going offline
_task_manager: TaskManager, _task_manager: TaskManager,
packet_type: Option<PacketType>,
packet_type: PacketType,
} }
#[wasm_bindgen] #[wasm_bindgen]
pub struct NymClientBuilder { pub struct NymClientBuilder {
config: Config, config: Config,
custom_topology: Option<NymTopology>, custom_topology: Option<NymTopology>,
preferred_gateway: Option<IdentityKey>,
storage_passphrase: Option<String>, storage_passphrase: Option<String>,
reply_surb_storage_backend: browser_backend::Backend, reply_surb_storage_backend: browser_backend::Backend,
@@ -70,7 +71,6 @@ pub struct NymClientBuilder {
bandwidth_controller: bandwidth_controller:
Option<BandwidthController<FakeClient<DirectSigningNyxdClient>, EphemeralStorage>>, Option<BandwidthController<FakeClient<DirectSigningNyxdClient>, EphemeralStorage>>,
disabled_credentials: bool, disabled_credentials: bool,
packet_type: Option<PacketType>,
} }
#[wasm_bindgen] #[wasm_bindgen]
@@ -79,17 +79,20 @@ impl NymClientBuilder {
pub fn new( pub fn new(
config: Config, config: Config,
on_message: js_sys::Function, on_message: js_sys::Function,
preferred_gateway: Option<IdentityKey>,
storage_passphrase: Option<String>, storage_passphrase: Option<String>,
) -> Self { ) -> Self {
NymClientBuilder { NymClientBuilder {
reply_surb_storage_backend: setup_reply_surb_storage_backend(config.debug.reply_surbs), reply_surb_storage_backend: setup_reply_surb_storage_backend(
config.base.debug.reply_surbs,
),
config, config,
custom_topology: None, custom_topology: None,
storage_passphrase, storage_passphrase,
on_message, on_message,
bandwidth_controller: None, bandwidth_controller: None,
disabled_credentials: true, disabled_credentials: true,
packet_type: None, preferred_gateway,
} }
} }
@@ -108,32 +111,11 @@ impl NymClientBuilder {
} }
} }
let full_config = Config { let full_config = Config::new_tester_config(NODE_TESTER_CLIENT_ID);
id: NODE_TESTER_CLIENT_ID.to_string(),
nym_api_url: None,
disabled_credentials_mode: true,
gateway,
debug: DebugConfig {
traffic: Traffic {
disable_main_poisson_packet_distribution: true,
..Default::default()
},
cover_traffic: CoverTraffic {
disable_loop_cover_traffic_stream: true,
..Default::default()
},
topology: Topology {
disable_refreshing: true,
..Default::default()
},
..Default::default()
},
packet_type: PacketType::Mix,
};
NymClientBuilder { NymClientBuilder {
reply_surb_storage_backend: setup_reply_surb_storage_backend( reply_surb_storage_backend: setup_reply_surb_storage_backend(
full_config.debug.reply_surbs, full_config.base.debug.reply_surbs,
), ),
config: full_config, config: full_config,
custom_topology: Some(topology.into()), custom_topology: Some(topology.into()),
@@ -141,7 +123,7 @@ impl NymClientBuilder {
bandwidth_controller: None, bandwidth_controller: None,
disabled_credentials: true, disabled_credentials: true,
storage_passphrase: None, storage_passphrase: None,
packet_type: None, preferred_gateway: gateway,
} }
} }
@@ -166,20 +148,18 @@ impl NymClientBuilder {
CredentialsToggle::Enabled CredentialsToggle::Enabled
}; };
let nym_api_endpoints = match &self.config.nym_api_url { let nym_api_endpoints = self.config.base.client.nym_api_urls.clone();
Some(endpoint) => vec![endpoint.clone()],
None => Vec::new(),
};
// TODO: this will have to be re-used for surbs. but this is a problem for another PR. // TODO: this will have to be re-used for surbs. but this is a problem for another PR.
let client_store = let client_store =
ClientStorage::new_async(&self.config.id, self.storage_passphrase.take()).await?; ClientStorage::new_async(&self.config.base.client.id, self.storage_passphrase.take())
.await?;
// if we provided hardcoded topology, get gateway from it, otherwise get it the 'standard' way // if we provided hardcoded topology, get gateway from it, otherwise get it the 'standard' way
let gateway_endpoint = if let Some(topology) = &self.custom_topology { let gateway_endpoint = if let Some(topology) = &self.custom_topology {
gateway_from_topology( gateway_from_topology(
&mut thread_rng(), &mut thread_rng(),
self.config.gateway.as_deref(), self.preferred_gateway.as_deref(),
topology, topology,
&client_store, &client_store,
) )
@@ -187,7 +167,7 @@ impl NymClientBuilder {
} else { } else {
choose_gateway( choose_gateway(
&client_store, &client_store,
self.config.gateway.clone(), self.preferred_gateway.clone(),
&nym_api_endpoints, &nym_api_endpoints,
) )
.await? .await?
@@ -197,7 +177,7 @@ impl NymClientBuilder {
let mut base_builder: BaseClientBuilder<_, FullWasmClientStorage> = BaseClientBuilder::new( let mut base_builder: BaseClientBuilder<_, FullWasmClientStorage> = BaseClientBuilder::new(
&gateway_endpoint, &gateway_endpoint,
&self.config.debug, &self.config.base.debug,
client_store, client_store,
self.bandwidth_controller, self.bandwidth_controller,
self.reply_surb_storage_backend, self.reply_surb_storage_backend,
@@ -208,8 +188,7 @@ impl NymClientBuilder {
base_builder = base_builder.with_topology_provider(topology_provider); base_builder = base_builder.with_topology_provider(topology_provider);
} }
let packet_type = self.config.packet_type; let mut started_client = base_builder.start_base().await?;
let mut started_client = base_builder.start_base(packet_type).await?;
let self_address = started_client.address.to_string(); let self_address = started_client.address.to_string();
let client_input = started_client.client_input.register_producer(); let client_input = started_client.client_input.register_producer();
@@ -223,7 +202,7 @@ impl NymClientBuilder {
client_state: Arc::new(started_client.client_state), client_state: Arc::new(started_client.client_state),
_full_topology: None, _full_topology: None,
_task_manager: started_client.task_manager, _task_manager: started_client.task_manager,
packet_type: self.packet_type, packet_type: self.config.base.debug.traffic.packet_type,
}) })
} }
@@ -237,9 +216,10 @@ impl NymClient {
async fn _new( async fn _new(
config: Config, config: Config,
on_message: js_sys::Function, on_message: js_sys::Function,
preferred_gateway: Option<IdentityKey>,
storage_passphrase: Option<String>, storage_passphrase: Option<String>,
) -> Result<NymClient, WasmClientError> { ) -> Result<NymClient, WasmClientError> {
NymClientBuilder::new(config, on_message, storage_passphrase) NymClientBuilder::new(config, on_message, preferred_gateway, storage_passphrase)
.start_client_async() .start_client_async()
.await .await
} }
@@ -249,10 +229,11 @@ impl NymClient {
pub fn new( pub fn new(
config: Config, config: Config,
on_message: js_sys::Function, on_message: js_sys::Function,
preferred_gateway: Option<IdentityKey>,
storage_passphrase: Option<String>, storage_passphrase: Option<String>,
) -> Promise { ) -> Promise {
future_to_promise(async move { future_to_promise(async move {
Self::_new(config, on_message, storage_passphrase) Self::_new(config, on_message, preferred_gateway, storage_passphrase)
.await .await
.into_promise_result() .into_promise_result()
}) })
@@ -319,7 +300,7 @@ impl NymClient {
let lane = TransmissionLane::General; let lane = TransmissionLane::General;
let input_msg = InputMessage::new_regular(recipient, message, lane, self.packet_type); let input_msg = InputMessage::new_regular(recipient, message, lane, Some(self.packet_type));
self.client_input.send_message(input_msg) self.client_input.send_message(input_msg)
} }
@@ -346,8 +327,13 @@ impl NymClient {
let lane = TransmissionLane::General; let lane = TransmissionLane::General;
let input_msg = let input_msg = InputMessage::new_anonymous(
InputMessage::new_anonymous(recipient, message, reply_surbs, lane, self.packet_type); recipient,
message,
reply_surbs,
lane,
Some(self.packet_type),
);
self.client_input.send_message(input_msg) self.client_input.send_message(input_msg)
} }
@@ -365,7 +351,7 @@ impl NymClient {
let lane = TransmissionLane::General; let lane = TransmissionLane::General;
let input_msg = InputMessage::new_reply(sender_tag, message, lane, self.packet_type); let input_msg = InputMessage::new_reply(sender_tag, message, lane, Some(self.packet_type));
self.client_input.send_message(input_msg) self.client_input.send_message(input_msg)
} }
} }
+1 -1
View File
@@ -22,7 +22,7 @@ use wasm_bindgen_futures::future_to_promise;
use wasm_utils::{console_log, PromisableResult}; use wasm_utils::{console_log, PromisableResult};
// don't get too excited about the name, under the hood it's just a big fat placeholder // don't get too excited about the name, under the hood it's just a big fat placeholder
// with no persistence // with no disk_persistence
pub(crate) fn setup_reply_surb_storage_backend( pub(crate) fn setup_reply_surb_storage_backend(
config: config::ReplySurbs, config: config::ReplySurbs,
) -> browser_backend::Backend { ) -> browser_backend::Backend {
+2 -2
View File
@@ -15,7 +15,7 @@ clap_complete_fig = "4.0"
log = { workspace = true } log = { workspace = true }
pretty_env_logger = "0.4.0" pretty_env_logger = "0.4.0"
semver = "0.11" semver = "0.11"
serde = { workspace = true, features = ["derive"], optional = true } serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true, optional = true } serde_json = { workspace = true, optional = true }
## tracing ## tracing
@@ -36,5 +36,5 @@ vergen = { version = "=7.4.3", default-features = false, features = [
[features] [features]
default = [] default = []
output_format = ["serde", "serde_json"] output_format = ["serde_json"]
tracing = ["tracing-appender", "tracing-subscriber", "tracing-tree"] tracing = ["tracing-appender", "tracing-subscriber", "tracing-tree"]
@@ -4,6 +4,8 @@
// TODO: at a later date this crate should probably also expose `ContractBuildInformation` // TODO: at a later date this crate should probably also expose `ContractBuildInformation`
// and be used by our smart contracts // and be used by our smart contracts
use serde::{Deserialize, Serialize};
#[derive(Debug)] #[derive(Debug)]
pub struct BinaryBuildInformation { pub struct BinaryBuildInformation {
// VERGEN_BUILD_TIMESTAMP // VERGEN_BUILD_TIMESTAMP
@@ -99,8 +101,7 @@ impl BinaryBuildInformation {
} }
} }
#[derive(Debug)] #[derive(Debug, Serialize, Deserialize)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct BinaryBuildInformationOwned { pub struct BinaryBuildInformationOwned {
// VERGEN_BUILD_TIMESTAMP // VERGEN_BUILD_TIMESTAMP
/// Provides the build timestamp, for example `2021-02-23T20:14:46.558472672+00:00`. /// Provides the build timestamp, for example `2021-02-23T20:14:46.558472672+00:00`.
+3 -1
View File
@@ -4,5 +4,7 @@
pub mod build_information; pub mod build_information;
pub mod completions; pub mod completions;
pub mod logging; pub mod logging;
pub mod output_format;
pub mod version_checker; pub mod version_checker;
#[cfg(feature = "output_format")]
pub mod output_format;
+9 -5
View File
@@ -1,9 +1,7 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net> // Copyright 2022-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
// use tracing_subscriber::{
// fmt::Layer, layer::SubscriberExt, util::SubscriberInitExt, EnvFilter, Registry, use serde::{Deserialize, Serialize};
// };
// use tracing_tree::HierarchicalLayer;
#[cfg(feature = "tracing")] #[cfg(feature = "tracing")]
pub use tracing_appender; pub use tracing_appender;
@@ -12,6 +10,12 @@ pub use tracing_subscriber;
#[cfg(feature = "tracing")] #[cfg(feature = "tracing")]
pub use tracing_tree; pub use tracing_tree;
#[derive(Debug, Default, Clone, Deserialize, PartialEq, Eq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct LoggingSettings {
// well, we need to implement something here at some point...
}
// I'd argue we should start transitioning from `log` to `tracing` // I'd argue we should start transitioning from `log` to `tracing`
pub fn setup_logging() { pub fn setup_logging() {
let mut log_builder = pretty_env_logger::formatted_timed_builder(); let mut log_builder = pretty_env_logger::formatted_timed_builder();
@@ -176,15 +176,15 @@ where
C: DkgQueryClient + Send + Sync + 'static, C: DkgQueryClient + Send + Sync + 'static,
{ {
// TODO: combine all storages // TODO: combine all storages
pub fn new_from_base_config<T>( pub fn new_from_base_config(
base_config: &'a Config<T>, base_config: &'a Config,
key_store: S::KeyStore, key_store: S::KeyStore,
bandwidth_controller: Option<BandwidthController<C, S::CredentialStore>>, bandwidth_controller: Option<BandwidthController<C, S::CredentialStore>>,
reply_storage_backend: S::ReplyStore, reply_storage_backend: S::ReplyStore,
) -> BaseClientBuilder<'a, C, S> { ) -> BaseClientBuilder<'a, C, S> {
BaseClientBuilder { BaseClientBuilder {
gateway_config: base_config.get_gateway_endpoint_config(), gateway_config: base_config.get_gateway_endpoint_config(),
debug_config: base_config.get_debug_config(), debug_config: &base_config.debug,
disabled_credentials: base_config.get_disabled_credentials_mode(), disabled_credentials: base_config.get_disabled_credentials_mode(),
nym_api_endpoints: base_config.get_nym_api_endpoints(), nym_api_endpoints: base_config.get_nym_api_endpoints(),
bandwidth_controller, bandwidth_controller,
@@ -479,10 +479,7 @@ where
self.managed_keys = ManagedKeys::load_or_generate(&mut rng, &self.key_store).await; self.managed_keys = ManagedKeys::load_or_generate(&mut rng, &self.key_store).await;
} }
pub async fn start_base( pub async fn start_base(mut self) -> Result<BaseClient, ClientCoreError>
mut self,
packet_type: PacketType,
) -> Result<BaseClient, ClientCoreError>
where where
<S::ReplyStore as ReplyStorageBackend>::StorageError: Sync + Send, <S::ReplyStore as ReplyStorageBackend>::StorageError: Sync + Send,
S::ReplyStore: Send + Sync, S::ReplyStore: Send + Sync,
@@ -586,7 +583,7 @@ where
shared_lane_queue_lengths.clone(), shared_lane_queue_lengths.clone(),
client_connection_rx, client_connection_rx,
task_manager.subscribe(), task_manager.subscribe(),
packet_type, self.debug_config.traffic.packet_type,
); );
if !self if !self
@@ -101,8 +101,8 @@ pub async fn setup_fs_reply_surb_backend<P: AsRef<Path>>(
} }
} }
pub fn create_bandwidth_controller<T, St: CredentialStorage>( pub fn create_bandwidth_controller<St: CredentialStorage>(
config: &Config<T>, config: &Config,
storage: St, storage: St,
) -> BandwidthController<Client<QueryNyxdClient>, St> { ) -> BandwidthController<Client<QueryNyxdClient>, St> {
let nyxd_url = config let nyxd_url = config
@@ -17,15 +17,14 @@ use crate::client::base_client::non_wasm_helpers;
#[cfg(all(not(target_arch = "wasm32"), feature = "fs-surb-storage"))] #[cfg(all(not(target_arch = "wasm32"), feature = "fs-surb-storage"))]
use crate::client::key_manager::persistence::OnDiskKeys; use crate::client::key_manager::persistence::OnDiskKeys;
#[cfg(all(not(target_arch = "wasm32"), feature = "fs-surb-storage"))] #[cfg(all(not(target_arch = "wasm32"), feature = "fs-surb-storage"))]
use crate::config::{persistence::key_pathfinder::ClientKeyPathfinder, Config}; use crate::client::replies::reply_storage::fs_backend;
#[cfg(all(not(target_arch = "wasm32"), feature = "fs-surb-storage"))]
use crate::config::{self, disk_persistence::CommonClientPaths};
#[cfg(all(not(target_arch = "wasm32"), feature = "fs-surb-storage"))] #[cfg(all(not(target_arch = "wasm32"), feature = "fs-surb-storage"))]
use crate::error::ClientCoreError; use crate::error::ClientCoreError;
#[cfg(all(not(target_arch = "wasm32"), feature = "fs-surb-storage"))] #[cfg(all(not(target_arch = "wasm32"), feature = "fs-surb-storage"))]
use nym_credential_storage::persistent_storage::PersistentStorage as PersistentCredentialStorage; use nym_credential_storage::persistent_storage::PersistentStorage as PersistentCredentialStorage;
#[cfg(all(not(target_arch = "wasm32"), feature = "fs-surb-storage"))]
use crate::client::replies::reply_storage::fs_backend;
pub trait MixnetClientStorage { pub trait MixnetClientStorage {
type KeyStore: KeyStore; type KeyStore: KeyStore;
type ReplyStore: ReplyStorageBackend; type ReplyStore: ReplyStorageBackend;
@@ -95,18 +94,20 @@ impl OnDiskPersistent {
} }
} }
pub async fn from_config<T>(config: &Config<T>) -> Result<Self, ClientCoreError> { pub async fn from_paths(
let pathfinder = ClientKeyPathfinder::new_from_config(config); paths: CommonClientPaths,
let key_store = OnDiskKeys::new(pathfinder); debug_config: &config::DebugConfig,
) -> Result<Self, ClientCoreError> {
let key_store = OnDiskKeys::new(paths.keys);
let reply_store = non_wasm_helpers::setup_fs_reply_surb_backend( let reply_store = non_wasm_helpers::setup_fs_reply_surb_backend(
config.get_reply_surb_database_path(), paths.reply_surb_database,
&config.get_debug_config().reply_surbs, &debug_config.reply_surbs,
) )
.await?; .await?;
let credential_store = let credential_store =
nym_credential_storage::initialise_persistent_storage(config.get_database_path()).await; nym_credential_storage::initialise_persistent_storage(paths.credentials_database).await;
Ok(OnDiskPersistent { Ok(OnDiskPersistent {
key_store, key_store,
@@ -6,9 +6,7 @@ use async_trait::async_trait;
use std::error::Error; use std::error::Error;
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
use crate::config::persistence::key_pathfinder::ClientKeyPathfinder; use crate::config::disk_persistence::keys_paths::ClientKeysPaths;
#[cfg(not(target_arch = "wasm32"))]
use crate::config::Config;
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
use nym_crypto::asymmetric::{encryption, identity}; use nym_crypto::asymmetric::{encryption, identity};
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
@@ -65,24 +63,20 @@ pub enum OnDiskKeysError {
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
pub struct OnDiskKeys { pub struct OnDiskKeys {
pathfinder: ClientKeyPathfinder, paths: ClientKeysPaths,
} }
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
impl From<ClientKeyPathfinder> for OnDiskKeys { impl From<ClientKeysPaths> for OnDiskKeys {
fn from(pathfinder: ClientKeyPathfinder) -> Self { fn from(paths: ClientKeysPaths) -> Self {
OnDiskKeys { pathfinder } OnDiskKeys { paths }
} }
} }
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
impl OnDiskKeys { impl OnDiskKeys {
pub fn new(pathfinder: ClientKeyPathfinder) -> Self { pub fn new(paths: ClientKeysPaths) -> Self {
OnDiskKeys { pathfinder } OnDiskKeys { paths }
}
pub fn from_config<T>(config: &Config<T>) -> Self {
OnDiskKeys::new(ClientKeyPathfinder::new_from_config(config))
} }
fn load_key<T: PemStorableKey>( fn load_key<T: PemStorableKey>(
@@ -138,17 +132,17 @@ impl OnDiskKeys {
} }
fn load_keys(&self) -> Result<KeyManager, OnDiskKeysError> { fn load_keys(&self) -> Result<KeyManager, OnDiskKeysError> {
let identity_paths = self.pathfinder.identity_key_pair_path(); let identity_paths = self.paths.identity_key_pair_path();
let encryption_paths = self.pathfinder.encryption_key_pair_path(); let encryption_paths = self.paths.encryption_key_pair_path();
let identity_keypair: identity::KeyPair = let identity_keypair: identity::KeyPair =
self.load_keypair(identity_paths, "identity keys")?; self.load_keypair(identity_paths, "identity keys")?;
let encryption_keypair: encryption::KeyPair = let encryption_keypair: encryption::KeyPair =
self.load_keypair(encryption_paths, "encryption keys")?; self.load_keypair(encryption_paths, "encryption keys")?;
let ack_key: AckKey = self.load_key(self.pathfinder.ack_key(), "ack key")?; let ack_key: AckKey = self.load_key(self.paths.ack_key(), "ack key")?;
let gateway_shared_key: SharedKeys = let gateway_shared_key: SharedKeys =
self.load_key(self.pathfinder.gateway_shared_key(), "gateway shared keys")?; self.load_key(self.paths.gateway_shared_key(), "gateway shared keys")?;
Ok(KeyManager::from_keys( Ok(KeyManager::from_keys(
identity_keypair, identity_keypair,
@@ -159,8 +153,8 @@ impl OnDiskKeys {
} }
fn store_keys(&self, keys: &KeyManager) -> Result<(), OnDiskKeysError> { fn store_keys(&self, keys: &KeyManager) -> Result<(), OnDiskKeysError> {
let identity_paths = self.pathfinder.identity_key_pair_path(); let identity_paths = self.paths.identity_key_pair_path();
let encryption_paths = self.pathfinder.encryption_key_pair_path(); let encryption_paths = self.paths.encryption_key_pair_path();
self.store_keypair( self.store_keypair(
keys.identity_keypair.as_ref(), keys.identity_keypair.as_ref(),
@@ -173,10 +167,10 @@ impl OnDiskKeys {
"encryption keys", "encryption keys",
)?; )?;
self.store_key(keys.ack_key.as_ref(), self.pathfinder.ack_key(), "ack key")?; self.store_key(keys.ack_key.as_ref(), self.paths.ack_key(), "ack key")?;
self.store_key( self.store_key(
keys.gateway_shared_key.as_ref(), keys.gateway_shared_key.as_ref(),
self.pathfinder.gateway_shared_key(), self.paths.gateway_shared_key(),
"gateway shared keys", "gateway shared keys",
)?; )?;
@@ -565,7 +565,7 @@ where
fragments: Vec<Fragment>, fragments: Vec<Fragment>,
reply_surbs: Vec<ReplySurb>, reply_surbs: Vec<ReplySurb>,
) -> Result<Vec<PreparedFragment>, SurbWrappedPreparationError> { ) -> Result<Vec<PreparedFragment>, SurbWrappedPreparationError> {
debug_assert_eq!( debug_assert_ne!(
fragments.len(), fragments.len(),
reply_surbs.len(), reply_surbs.len(),
"attempted to send {} fragments with {} reply surbs", "attempted to send {} fragments with {} reply surbs",
@@ -1,4 +1,4 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net> // Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use self::sending_delay_controller::SendingDelayController; use self::sending_delay_controller::SendingDelayController;
@@ -247,7 +247,7 @@ where
self.config.average_ack_delay, self.config.average_ack_delay,
self.config.traffic.average_packet_delay, self.config.traffic.average_packet_delay,
cover_traffic_packet_size, cover_traffic_packet_size,
self.config.traffic.packet_type.unwrap_or_default(), self.config.traffic.packet_type,
) )
.expect( .expect(
"Somehow failed to generate a loop cover message with a valid topology", "Somehow failed to generate a loop cover message with a valid topology",
@@ -0,0 +1,117 @@
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use serde::{Deserialize, Serialize};
use std::path::{Path, PathBuf};
pub const DEFAULT_PRIVATE_IDENTITY_KEY_FILENAME: &str = "private_identity.pem";
pub const DEFAULT_PUBLIC_IDENTITY_KEY_FILENAME: &str = "public_identity.pem";
pub const DEFAULT_PRIVATE_ENCRYPTION_KEY_FILENAME: &str = "private_encryption.pem";
pub const DEFAULT_PUBLIC_ENCRYPTION_KEY_FILENAME: &str = "public_encryption.pem";
pub const DEFAULT_GATEWAY_SHARED_KEY_FILENAME: &str = "gateway_shared.pem";
pub const DEFAULT_ACK_KEY_FILENAME: &str = "ack_key.pem";
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
pub struct ClientKeysPaths {
/// Path to file containing private identity key.
pub private_identity_key_file: PathBuf,
/// Path to file containing public identity key.
pub public_identity_key_file: PathBuf,
/// Path to file containing private encryption key.
pub private_encryption_key_file: PathBuf,
/// Path to file containing public encryption key.
pub public_encryption_key_file: PathBuf,
/// Path to file containing shared key derived with the specified gateway that is used
/// for all communication with it.
pub gateway_shared_key_file: PathBuf,
/// Path to file containing key used for encrypting and decrypting the content of an
/// acknowledgement so that nobody besides the client knows which packet it refers to.
pub ack_key_file: PathBuf,
}
impl ClientKeysPaths {
pub fn new_default<P: AsRef<Path>>(base_data_directory: P) -> Self {
let base_dir = base_data_directory.as_ref();
ClientKeysPaths {
private_identity_key_file: base_dir.join(DEFAULT_PRIVATE_IDENTITY_KEY_FILENAME),
public_identity_key_file: base_dir.join(DEFAULT_PUBLIC_IDENTITY_KEY_FILENAME),
private_encryption_key_file: base_dir.join(DEFAULT_PRIVATE_ENCRYPTION_KEY_FILENAME),
public_encryption_key_file: base_dir.join(DEFAULT_PUBLIC_ENCRYPTION_KEY_FILENAME),
gateway_shared_key_file: base_dir.join(DEFAULT_GATEWAY_SHARED_KEY_FILENAME),
ack_key_file: base_dir.join(DEFAULT_ACK_KEY_FILENAME),
}
}
pub fn identity_key_pair_path(&self) -> nym_pemstore::KeyPairPath {
nym_pemstore::KeyPairPath::new(
self.private_identity_key().to_path_buf(),
self.public_identity_key().to_path_buf(),
)
}
pub fn encryption_key_pair_path(&self) -> nym_pemstore::KeyPairPath {
nym_pemstore::KeyPairPath::new(
self.private_encryption_key().to_path_buf(),
self.public_encryption_key().to_path_buf(),
)
}
pub fn any_file_exists(&self) -> bool {
matches!(self.public_identity_key_file.try_exists(), Ok(true))
|| matches!(self.private_identity_key_file.try_exists(), Ok(true))
|| matches!(self.public_encryption_key_file.try_exists(), Ok(true))
|| matches!(self.private_encryption_key_file.try_exists(), Ok(true))
|| matches!(self.gateway_shared_key_file.try_exists(), Ok(true))
|| matches!(self.ack_key_file.try_exists(), Ok(true))
}
pub fn any_file_exists_and_return(&self) -> Option<PathBuf> {
file_exists(&self.public_identity_key_file)
.or_else(|| file_exists(&self.private_identity_key_file))
.or_else(|| file_exists(&self.public_encryption_key_file))
.or_else(|| file_exists(&self.private_encryption_key_file))
.or_else(|| file_exists(&self.gateway_shared_key_file))
.or_else(|| file_exists(&self.ack_key_file))
}
pub fn gateway_key_file_exists(&self) -> bool {
matches!(self.gateway_shared_key_file.try_exists(), Ok(true))
}
pub fn private_identity_key(&self) -> &Path {
&self.private_identity_key_file
}
pub fn public_identity_key(&self) -> &Path {
&self.public_identity_key_file
}
pub fn private_encryption_key(&self) -> &Path {
&self.private_encryption_key_file
}
pub fn public_encryption_key(&self) -> &Path {
&self.public_encryption_key_file
}
pub fn gateway_shared_key(&self) -> &Path {
&self.gateway_shared_key_file
}
pub fn ack_key(&self) -> &Path {
&self.ack_key_file
}
}
fn file_exists(path: &Path) -> Option<PathBuf> {
if matches!(path.try_exists(), Ok(true)) {
return Some(path.to_path_buf());
}
None
}
@@ -0,0 +1,36 @@
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::config::disk_persistence::keys_paths::ClientKeysPaths;
use serde::{Deserialize, Serialize};
use std::path::{Path, PathBuf};
pub mod keys_paths;
pub const DEFAULT_REPLY_SURB_DB_FILENAME: &str = "persistent_reply_store.sqlite";
pub const DEFAULT_CREDENTIALS_DB_FILENAME: &str = "credentials_database.db";
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
pub struct CommonClientPaths {
pub keys: ClientKeysPaths,
// TODO:
// pub gateway_config_pathfinder: (),
/// Path to the database containing bandwidth credentials of this client.
pub credentials_database: PathBuf,
/// Path to the persistent store for received reply surbs, unused encryption keys and used sender tags.
pub reply_surb_database: PathBuf,
}
impl CommonClientPaths {
pub fn new_default<P: AsRef<Path>>(base_data_directory: P) -> Self {
let base_dir = base_data_directory.as_ref();
CommonClientPaths {
credentials_database: base_dir.join(DEFAULT_CREDENTIALS_DB_FILENAME),
reply_surb_database: base_dir.join(DEFAULT_REPLY_SURB_DB_FILENAME),
keys: ClientKeysPaths::new_default(base_data_directory),
}
}
}
+33 -394
View File
@@ -1,13 +1,10 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net> // Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use nym_config::defaults::NymNetworkDetails; use nym_config::defaults::NymNetworkDetails;
use nym_config::{NymConfig, OptionalSet, CRED_DB_FILE_NAME};
use nym_crypto::asymmetric::identity; use nym_crypto::asymmetric::identity;
use nym_sphinx::params::{PacketSize, PacketType}; use nym_sphinx::params::{PacketSize, PacketType};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::marker::PhantomData;
use std::path::{Path, PathBuf};
use std::time::Duration; use std::time::Duration;
use url::Url; use url::Url;
@@ -15,19 +12,9 @@ use crate::error::ClientCoreError;
#[cfg(target_arch = "wasm32")] #[cfg(target_arch = "wasm32")]
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;
pub mod disk_persistence;
pub mod old_config_v1_1_13; pub mod old_config_v1_1_13;
pub mod persistence; pub mod old_config_v1_1_19;
pub const DEFAULT_PRIVATE_IDENTITY_KEY_FILENAME: &str = "private_identity.pem";
pub const DEFAULT_PUBLIC_IDENTITY_KEY_FILENAME: &str = "public_identity.pem";
pub const DEFAULT_PRIVATE_ENCRYPTION_KEY_FILENAME: &str = "private_encryption.pem";
pub const DEFAULT_PUBLIC_ENCRYPTION_KEY_FILENAME: &str = "public_encryption.pem";
pub const DEFAULT_GATEWAY_KEYS_FILENAME: &str = "gateway_shared.pem";
pub const DEFAULT_ACK_KEY_FILENAME: &str = "ack_key.pem";
pub const DEFAULT_REPLY_STORE_FILENAME: &str = "persistent_reply_store.sqlite";
pub const DEFAULT_CREDENTIAL_STORE_FILENAME: &str = CRED_DB_FILE_NAME;
pub const MISSING_VALUE: &str = "MISSING VALUE";
// 'DEBUG' // 'DEBUG'
const DEFAULT_ACK_WAIT_MULTIPLIER: f64 = 1.5; const DEFAULT_ACK_WAIT_MULTIPLIER: f64 = 1.5;
@@ -68,154 +55,32 @@ const DEFAULT_MAXIMUM_REPLY_SURB_AGE: Duration = Duration::from_secs(12 * 60 * 6
// 24 hours // 24 hours
const DEFAULT_MAXIMUM_REPLY_KEY_AGE: Duration = Duration::from_secs(24 * 60 * 60); const DEFAULT_MAXIMUM_REPLY_KEY_AGE: Duration = Duration::from_secs(24 * 60 * 60);
pub fn missing_string_value() -> String {
MISSING_VALUE.to_string()
}
pub trait ClientCoreConfigTrait {
fn get_gateway_endpoint(&self) -> &GatewayEndpointConfig;
}
#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)] #[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
#[serde(deny_unknown_fields)] #[serde(deny_unknown_fields)]
pub struct Config<T> { pub struct Config {
client: Client<T>, pub client: Client,
#[serde(default)] #[serde(default)]
logging: Logging, pub debug: DebugConfig,
#[serde(default)]
debug: DebugConfig,
} }
impl<T> ClientCoreConfigTrait for Config<T> { impl Config {
fn get_gateway_endpoint(&self) -> &GatewayEndpointConfig { pub fn new<S: Into<String>>(id: S) -> Self {
&self.client.gateway_endpoint Config {
} client: Client::new_default(id),
} debug: Default::default(),
}
impl<T> OptionalSet for Config<T> where T: NymConfig {}
impl<T> Config<T> {
pub fn new<S: Into<String>>(id: S) -> Self
where
T: NymConfig,
{
Config::default().with_id(id)
} }
pub fn validate(&self) -> bool { pub fn validate(&self) -> bool {
// no other sections have explicit requirements (yet) self.client.validate() && self.debug.validate()
self.debug.validate()
} }
#[must_use] pub fn with_debug_config(mut self, debug: DebugConfig) -> Self {
pub fn with_id<S: Into<String>>(mut self, id: S) -> Self self.debug = debug;
where
T: NymConfig,
{
self.client.id = id.into();
self.set_empty_fields_to_defaults();
self self
} }
#[must_use]
#[doc(hidden)]
// TODO: this totally contradicts our trait... we REALLY have to refactor it...
pub fn reset_data_directory<P: AsRef<Path>>(mut self, dir: P) -> Self {
self.client.private_identity_key_file =
dir.as_ref().join(DEFAULT_PRIVATE_IDENTITY_KEY_FILENAME);
self.client.public_identity_key_file =
dir.as_ref().join(DEFAULT_PUBLIC_IDENTITY_KEY_FILENAME);
self.client.private_encryption_key_file =
dir.as_ref().join(DEFAULT_PRIVATE_ENCRYPTION_KEY_FILENAME);
self.client.public_encryption_key_file =
dir.as_ref().join(DEFAULT_PUBLIC_ENCRYPTION_KEY_FILENAME);
self.client.gateway_shared_key_file = dir.as_ref().join(DEFAULT_GATEWAY_KEYS_FILENAME);
self.client.ack_key_file = dir.as_ref().join(DEFAULT_ACK_KEY_FILENAME);
self.client.reply_surb_database_path = dir.as_ref().join(DEFAULT_REPLY_STORE_FILENAME);
self.client.database_path = dir.as_ref().join(DEFAULT_CREDENTIAL_STORE_FILENAME);
self
}
#[must_use]
#[doc(hidden)]
// TODO: this totally contradicts our trait... we REALLY have to refactor it...
pub fn reset_nym_root_directory<P: AsRef<Path>>(mut self, dir: P) -> Self
where
T: NymConfig,
{
self.client.nym_root_directory = dir.as_ref().to_owned();
self
}
pub fn set_empty_fields_to_defaults(&mut self) -> bool
where
T: NymConfig,
{
let id = &self.client.id;
let mut changes_made = false;
// identity key setting
if self.client.private_identity_key_file.as_os_str().is_empty() {
changes_made = true;
self.client.private_identity_key_file =
self::Client::<T>::default_private_identity_key_file(id);
}
if self.client.public_identity_key_file.as_os_str().is_empty() {
changes_made = true;
self.client.public_identity_key_file =
self::Client::<T>::default_public_identity_key_file(id);
}
// encryption key setting
if self
.client
.private_encryption_key_file
.as_os_str()
.is_empty()
{
changes_made = true;
self.client.private_encryption_key_file =
self::Client::<T>::default_private_encryption_key_file(id);
}
if self
.client
.public_encryption_key_file
.as_os_str()
.is_empty()
{
changes_made = true;
self.client.public_encryption_key_file =
self::Client::<T>::default_public_encryption_key_file(id);
}
// shared gateway key setting
if self.client.gateway_shared_key_file.as_os_str().is_empty() {
changes_made = true;
self.client.gateway_shared_key_file =
self::Client::<T>::default_gateway_shared_key_file(id);
}
// ack key setting
if self.client.ack_key_file.as_os_str().is_empty() {
changes_made = true;
self.client.ack_key_file = self::Client::<T>::default_ack_key_file(id);
}
if self.client.reply_surb_database_path.as_os_str().is_empty() {
changes_made = true;
self.client.reply_surb_database_path =
self::Client::<T>::default_reply_surb_database_path(id);
}
if self.client.database_path.as_os_str().is_empty() {
changes_made = true;
self.client.database_path = self::Client::<T>::default_database_path(id);
}
changes_made
}
pub fn with_disabled_credentials(mut self, disabled_credentials_mode: bool) -> Self { pub fn with_disabled_credentials(mut self, disabled_credentials_mode: bool) -> Self {
self.client.disabled_credentials_mode = disabled_credentials_mode; self.client.disabled_credentials_mode = disabled_credentials_mode;
self self
@@ -260,7 +125,7 @@ impl<T> Config<T> {
} }
pub fn with_packet_type(mut self, packet_type: PacketType) -> Self { pub fn with_packet_type(mut self, packet_type: PacketType) -> Self {
self.client.packet_type = Some(packet_type); self.debug.traffic.packet_type = packet_type;
self self
} }
@@ -280,6 +145,11 @@ impl<T> Config<T> {
self self
} }
pub fn with_disabled_topology_refresh(mut self, disable_topology_refresh: bool) -> Self {
self.debug.topology.disable_refreshing = disable_topology_refresh;
self
}
pub fn set_no_cover_traffic(&mut self) { pub fn set_no_cover_traffic(&mut self) {
self.debug.cover_traffic.disable_loop_cover_traffic_stream = true; self.debug.cover_traffic.disable_loop_cover_traffic_stream = true;
self.debug.traffic.disable_main_poisson_packet_distribution = true; self.debug.traffic.disable_main_poisson_packet_distribution = true;
@@ -297,34 +167,6 @@ impl<T> Config<T> {
self.client.disabled_credentials_mode self.client.disabled_credentials_mode
} }
pub fn get_nym_root_directory(&self) -> PathBuf {
self.client.nym_root_directory.clone()
}
pub fn get_private_identity_key_file(&self) -> PathBuf {
self.client.private_identity_key_file.clone()
}
pub fn get_public_identity_key_file(&self) -> PathBuf {
self.client.public_identity_key_file.clone()
}
pub fn get_private_encryption_key_file(&self) -> PathBuf {
self.client.private_encryption_key_file.clone()
}
pub fn get_public_encryption_key_file(&self) -> PathBuf {
self.client.public_encryption_key_file.clone()
}
pub fn get_gateway_shared_key_file(&self) -> PathBuf {
self.client.gateway_shared_key_file.clone()
}
pub fn get_ack_key_file(&self) -> PathBuf {
self.client.ack_key_file.clone()
}
pub fn get_validator_endpoints(&self) -> Vec<Url> { pub fn get_validator_endpoints(&self) -> Vec<Url> {
self.client.nyxd_urls.clone() self.client.nyxd_urls.clone()
} }
@@ -348,123 +190,6 @@ impl<T> Config<T> {
pub fn get_gateway_endpoint_config(&self) -> &GatewayEndpointConfig { pub fn get_gateway_endpoint_config(&self) -> &GatewayEndpointConfig {
&self.client.gateway_endpoint &self.client.gateway_endpoint
} }
pub fn get_database_path(&self) -> PathBuf {
self.client.database_path.clone()
}
pub fn get_reply_surb_database_path(&self) -> PathBuf {
self.client.reply_surb_database_path.clone()
}
pub fn get_version(&self) -> &str {
&self.client.version
}
// Debug getters
pub fn get_debug_config(&self) -> &DebugConfig {
&self.debug
}
pub fn get_average_packet_delay(&self) -> Duration {
self.debug.traffic.average_packet_delay
}
pub fn get_average_ack_delay(&self) -> Duration {
self.debug.acknowledgements.average_ack_delay
}
pub fn get_ack_wait_multiplier(&self) -> f64 {
self.debug.acknowledgements.ack_wait_multiplier
}
pub fn get_ack_wait_addition(&self) -> Duration {
self.debug.acknowledgements.ack_wait_addition
}
pub fn get_loop_cover_traffic_average_delay(&self) -> Duration {
self.debug.cover_traffic.loop_cover_traffic_average_delay
}
pub fn get_message_sending_average_delay(&self) -> Duration {
self.debug.traffic.message_sending_average_delay
}
pub fn get_gateway_response_timeout(&self) -> Duration {
self.debug.gateway_connection.gateway_response_timeout
}
pub fn get_topology_refresh_rate(&self) -> Duration {
self.debug.topology.topology_refresh_rate
}
pub fn get_topology_resolution_timeout(&self) -> Duration {
self.debug.topology.topology_resolution_timeout
}
pub fn get_disabled_loop_cover_traffic_stream(&self) -> bool {
self.debug.cover_traffic.disable_loop_cover_traffic_stream
}
pub fn get_disabled_main_poisson_packet_distribution(&self) -> bool {
self.debug.traffic.disable_main_poisson_packet_distribution
}
pub fn get_minimum_reply_surb_storage_threshold(&self) -> usize {
self.debug.reply_surbs.minimum_reply_surb_storage_threshold
}
pub fn get_maximum_reply_surb_storage_threshold(&self) -> usize {
self.debug.reply_surbs.maximum_reply_surb_storage_threshold
}
pub fn get_minimum_reply_surb_request_size(&self) -> u32 {
self.debug.reply_surbs.minimum_reply_surb_request_size
}
pub fn get_maximum_reply_surb_request_size(&self) -> u32 {
self.debug.reply_surbs.maximum_reply_surb_request_size
}
pub fn get_maximum_allowed_reply_surb_request_size(&self) -> u32 {
self.debug
.reply_surbs
.maximum_allowed_reply_surb_request_size
}
pub fn get_maximum_reply_surb_rerequest_waiting_period(&self) -> Duration {
self.debug
.reply_surbs
.maximum_reply_surb_rerequest_waiting_period
}
pub fn get_maximum_reply_surb_drop_waiting_period(&self) -> Duration {
self.debug
.reply_surbs
.maximum_reply_surb_drop_waiting_period
}
pub fn get_maximum_reply_surb_age(&self) -> Duration {
self.debug.reply_surbs.maximum_reply_surb_age
}
pub fn get_maximum_reply_key_age(&self) -> Duration {
self.debug.reply_surbs.maximum_reply_key_age
}
pub fn get_packet_type(&self) -> PacketType {
self.client.packet_type.unwrap_or(PacketType::Mix)
}
}
impl<T: NymConfig> Default for Config<T> {
fn default() -> Self {
Config {
client: Client::<T>::default(),
logging: Default::default(),
debug: Default::default(),
}
}
} }
#[derive(Clone, Debug, Default, Deserialize, PartialEq, Eq, Serialize)] #[derive(Clone, Debug, Default, Deserialize, PartialEq, Eq, Serialize)]
@@ -517,9 +242,8 @@ impl From<nym_topology::gateway::Node> for GatewayEndpointConfig {
} }
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)] #[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
pub struct Client<T> { pub struct Client {
/// Version of the client for which this configuration was created. /// Version of the client for which this configuration was created.
#[serde(default = "missing_string_value")]
pub version: String, pub version: String,
/// ID specifies the human readable ID of this particular client. /// ID specifies the human readable ID of this particular client.
@@ -538,51 +262,14 @@ pub struct Client<T> {
#[serde(alias = "validator_api_urls")] #[serde(alias = "validator_api_urls")]
pub nym_api_urls: Vec<Url>, pub nym_api_urls: Vec<Url>,
/// Path to file containing private identity key.
pub private_identity_key_file: PathBuf,
/// Path to file containing public identity key.
pub public_identity_key_file: PathBuf,
/// Path to file containing private encryption key.
pub private_encryption_key_file: PathBuf,
/// Path to file containing public encryption key.
pub public_encryption_key_file: PathBuf,
/// Path to file containing shared key derived with the specified gateway that is used
/// for all communication with it.
pub gateway_shared_key_file: PathBuf,
/// Path to file containing key used for encrypting and decrypting the content of an
/// acknowledgement so that nobody besides the client knows which packet it refers to.
pub ack_key_file: PathBuf,
/// Information regarding how the client should send data to gateway. /// Information regarding how the client should send data to gateway.
// #[deprecated(note = "this shall be moved to separate file because it doesn't belong here...")]
// TODO: this should be removed from config files and be moved to separate file instead
pub gateway_endpoint: GatewayEndpointConfig, pub gateway_endpoint: GatewayEndpointConfig,
/// Path to the database containing bandwidth credentials of this client.
pub database_path: PathBuf,
/// Path to the persistent store for received reply surbs, unused encryption keys and used sender tags.
// this was set to use #[serde(default)] for the purposes of compatibility for multi-surbs introduced in 1.1.4.
// if you're reading this message and we have already introduced some breaking changes, feel free
// to remove that attribute since at this point the client configs should have gotten regenerated
#[serde(default)]
pub reply_surb_database_path: PathBuf,
/// nym_home_directory specifies absolute path to the home nym Clients directory.
/// It is expected to use default value and hence .toml file should not redefine this field.
pub nym_root_directory: PathBuf,
#[serde(skip)]
pub super_struct: PhantomData<T>,
pub packet_type: Option<PacketType>,
} }
impl<T: NymConfig> Default for Client<T> { impl Client {
fn default() -> Self { pub fn new_default<S: Into<String>>(id: S) -> Self {
let network = NymNetworkDetails::new_mainnet(); let network = NymNetworkDetails::new_mainnet();
let nyxd_urls = network let nyxd_urls = network
.endpoints .endpoints
@@ -595,71 +282,23 @@ impl<T: NymConfig> Default for Client<T> {
.filter_map(|validator| validator.api_url()) .filter_map(|validator| validator.api_url())
.collect::<Vec<_>>(); .collect::<Vec<_>>();
if nym_api_urls.is_empty() {
panic!("we do not have any default nym-api urls available!")
}
// there must be explicit checks for whether id is not empty later
Client { Client {
version: env!("CARGO_PKG_VERSION").to_string(), version: env!("CARGO_PKG_VERSION").to_string(),
id: "".to_string(), id: id.into(),
disabled_credentials_mode: true, disabled_credentials_mode: true,
nyxd_urls, nyxd_urls,
nym_api_urls, nym_api_urls,
private_identity_key_file: Default::default(),
public_identity_key_file: Default::default(),
private_encryption_key_file: Default::default(),
public_encryption_key_file: Default::default(),
gateway_shared_key_file: Default::default(),
ack_key_file: Default::default(),
gateway_endpoint: Default::default(), gateway_endpoint: Default::default(),
database_path: Default::default(),
reply_surb_database_path: Default::default(),
nym_root_directory: T::default_root_directory(),
super_struct: Default::default(),
packet_type: Default::default(),
} }
} }
}
impl<T: NymConfig> Client<T> { pub fn validate(&self) -> bool {
fn default_private_identity_key_file(id: &str) -> PathBuf { !self.gateway_endpoint.gateway_id.is_empty()
T::default_data_directory(id).join("private_identity.pem") && !self.gateway_endpoint.gateway_owner.is_empty()
} && !self.gateway_endpoint.gateway_owner.is_empty()
fn default_public_identity_key_file(id: &str) -> PathBuf {
T::default_data_directory(id).join("public_identity.pem")
}
fn default_private_encryption_key_file(id: &str) -> PathBuf {
T::default_data_directory(id).join("private_encryption.pem")
}
fn default_public_encryption_key_file(id: &str) -> PathBuf {
T::default_data_directory(id).join("public_encryption.pem")
}
fn default_gateway_shared_key_file(id: &str) -> PathBuf {
T::default_data_directory(id).join("gateway_shared.pem")
}
fn default_ack_key_file(id: &str) -> PathBuf {
T::default_data_directory(id).join("ack_key.pem")
}
fn default_reply_surb_database_path(id: &str) -> PathBuf {
T::default_data_directory(id).join("persistent_reply_store.sqlite")
}
fn default_database_path(id: &str) -> PathBuf {
T::default_data_directory(id).join(CRED_DB_FILE_NAME)
} }
} }
#[derive(Debug, Clone, Default, Deserialize, PartialEq, Eq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct Logging {}
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)] #[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
#[serde(default)] #[serde(default)]
pub struct Traffic { pub struct Traffic {
@@ -690,7 +329,7 @@ pub struct Traffic {
/// Do not set it it unless you understand the consequences of that change. /// Do not set it it unless you understand the consequences of that change.
pub secondary_packet_size: Option<PacketSize>, pub secondary_packet_size: Option<PacketSize>,
pub packet_type: Option<PacketType>, pub packet_type: PacketType,
} }
impl Traffic { impl Traffic {
@@ -714,7 +353,7 @@ impl Default for Traffic {
disable_main_poisson_packet_distribution: false, disable_main_poisson_packet_distribution: false,
primary_packet_size: PacketSize::RegularPacket, primary_packet_size: PacketSize::RegularPacket,
secondary_packet_size: None, secondary_packet_size: None,
packet_type: None, packet_type: PacketType::Mix,
} }
} }
} }
@@ -1,19 +1,18 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net> // Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use crate::config::{ use crate::config::old_config_v1_1_19::{
Acknowledgements, Client, Config, CoverTraffic, DebugConfig, GatewayConnection, Logging, AcknowledgementsV1_1_19, ClientV1_1_19, ConfigV1_1_19, CoverTrafficV1_1_19, DebugConfigV1_1_19,
ReplySurbs, Topology, Traffic, DEFAULT_ACK_WAIT_ADDITION, DEFAULT_ACK_WAIT_MULTIPLIER, GatewayConnectionV1_1_19, LoggingV1_1_19, ReplySurbsV1_1_19, TopologyV1_1_19, TrafficV1_1_19,
DEFAULT_AVERAGE_PACKET_DELAY, DEFAULT_GATEWAY_RESPONSE_TIMEOUT, DEFAULT_ACK_WAIT_ADDITION, DEFAULT_ACK_WAIT_MULTIPLIER, DEFAULT_AVERAGE_PACKET_DELAY,
DEFAULT_LOOP_COVER_STREAM_AVERAGE_DELAY, DEFAULT_MAXIMUM_ALLOWED_SURB_REQUEST_SIZE, DEFAULT_GATEWAY_RESPONSE_TIMEOUT, DEFAULT_LOOP_COVER_STREAM_AVERAGE_DELAY,
DEFAULT_MAXIMUM_REPLY_KEY_AGE, DEFAULT_MAXIMUM_REPLY_SURB_AGE, DEFAULT_MAXIMUM_ALLOWED_SURB_REQUEST_SIZE, DEFAULT_MAXIMUM_REPLY_KEY_AGE,
DEFAULT_MAXIMUM_REPLY_SURB_DROP_WAITING_PERIOD, DEFAULT_MAXIMUM_REPLY_SURB_REQUEST_SIZE, DEFAULT_MAXIMUM_REPLY_SURB_AGE, DEFAULT_MAXIMUM_REPLY_SURB_DROP_WAITING_PERIOD,
DEFAULT_MAXIMUM_REPLY_SURB_REREQUEST_WAITING_PERIOD, DEFAULT_MAXIMUM_REPLY_SURB_REQUEST_SIZE, DEFAULT_MAXIMUM_REPLY_SURB_REREQUEST_WAITING_PERIOD,
DEFAULT_MAXIMUM_REPLY_SURB_STORAGE_THRESHOLD, DEFAULT_MESSAGE_STREAM_AVERAGE_DELAY, DEFAULT_MAXIMUM_REPLY_SURB_STORAGE_THRESHOLD, DEFAULT_MESSAGE_STREAM_AVERAGE_DELAY,
DEFAULT_MINIMUM_REPLY_SURB_REQUEST_SIZE, DEFAULT_MINIMUM_REPLY_SURB_STORAGE_THRESHOLD, DEFAULT_MINIMUM_REPLY_SURB_REQUEST_SIZE, DEFAULT_MINIMUM_REPLY_SURB_STORAGE_THRESHOLD,
DEFAULT_TOPOLOGY_REFRESH_RATE, DEFAULT_TOPOLOGY_RESOLUTION_TIMEOUT, DEFAULT_TOPOLOGY_REFRESH_RATE, DEFAULT_TOPOLOGY_RESOLUTION_TIMEOUT,
}; };
use nym_config::NymConfig;
use nym_sphinx::params::PacketSize; use nym_sphinx::params::PacketSize;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::marker::PhantomData; use std::marker::PhantomData;
@@ -40,21 +39,21 @@ impl From<ExtendedPacketSize> for PacketSize {
#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)] #[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
#[serde(deny_unknown_fields)] #[serde(deny_unknown_fields)]
pub struct OldConfigV1_1_13<T> { pub struct OldConfigV1_1_13<T> {
pub client: Client<T>, pub client: ClientV1_1_19<T>,
#[serde(default)] #[serde(default)]
logging: Logging, pub logging: OldLoggingV1_1_13,
#[serde(default)] #[serde(default)]
debug: OldDebugConfigV1_1_13, pub debug: OldDebugConfigV1_1_13,
} }
impl<T: NymConfig> Default for OldConfigV1_1_13<T> { #[derive(Debug, Clone, Default, Deserialize, PartialEq, Eq, Serialize)]
fn default() -> Self { #[serde(deny_unknown_fields)]
OldConfigV1_1_13 { pub struct OldLoggingV1_1_13 {}
client: Client::<T>::default(),
logging: Default::default(), impl From<OldLoggingV1_1_13> for LoggingV1_1_19 {
debug: Default::default(), fn from(_value: OldLoggingV1_1_13) -> Self {
} LoggingV1_1_19 {}
} }
} }
@@ -115,37 +114,36 @@ pub struct OldDebugConfigV1_1_13 {
pub maximum_reply_key_age: Duration, pub maximum_reply_key_age: Duration,
} }
impl From<OldDebugConfigV1_1_13> for DebugConfig { impl From<OldDebugConfigV1_1_13> for DebugConfigV1_1_19 {
fn from(value: OldDebugConfigV1_1_13) -> Self { fn from(value: OldDebugConfigV1_1_13) -> Self {
DebugConfig { DebugConfigV1_1_19 {
traffic: Traffic { traffic: TrafficV1_1_19 {
average_packet_delay: value.average_packet_delay, average_packet_delay: value.average_packet_delay,
message_sending_average_delay: value.message_sending_average_delay, message_sending_average_delay: value.message_sending_average_delay,
disable_main_poisson_packet_distribution: value disable_main_poisson_packet_distribution: value
.disable_main_poisson_packet_distribution, .disable_main_poisson_packet_distribution,
primary_packet_size: PacketSize::RegularPacket, primary_packet_size: PacketSize::RegularPacket,
secondary_packet_size: value.use_extended_packet_size.map(Into::into), secondary_packet_size: value.use_extended_packet_size.map(Into::into),
packet_type: None,
}, },
cover_traffic: CoverTraffic { cover_traffic: CoverTrafficV1_1_19 {
loop_cover_traffic_average_delay: value.loop_cover_traffic_average_delay, loop_cover_traffic_average_delay: value.loop_cover_traffic_average_delay,
disable_loop_cover_traffic_stream: value.disable_loop_cover_traffic_stream, disable_loop_cover_traffic_stream: value.disable_loop_cover_traffic_stream,
..CoverTraffic::default() ..CoverTrafficV1_1_19::default()
}, },
gateway_connection: GatewayConnection { gateway_connection: GatewayConnectionV1_1_19 {
gateway_response_timeout: value.gateway_response_timeout, gateway_response_timeout: value.gateway_response_timeout,
}, },
acknowledgements: Acknowledgements { acknowledgements: AcknowledgementsV1_1_19 {
average_ack_delay: value.average_ack_delay, average_ack_delay: value.average_ack_delay,
ack_wait_multiplier: value.ack_wait_multiplier, ack_wait_multiplier: value.ack_wait_multiplier,
ack_wait_addition: value.ack_wait_addition, ack_wait_addition: value.ack_wait_addition,
}, },
topology: Topology { topology: TopologyV1_1_19 {
topology_refresh_rate: value.topology_refresh_rate, topology_refresh_rate: value.topology_refresh_rate,
topology_resolution_timeout: value.topology_resolution_timeout, topology_resolution_timeout: value.topology_resolution_timeout,
disable_refreshing: false, disable_refreshing: false,
}, },
reply_surbs: ReplySurbs { reply_surbs: ReplySurbsV1_1_19 {
minimum_reply_surb_storage_threshold: value.minimum_reply_surb_storage_threshold, minimum_reply_surb_storage_threshold: value.minimum_reply_surb_storage_threshold,
maximum_reply_surb_storage_threshold: value.maximum_reply_surb_storage_threshold, maximum_reply_surb_storage_threshold: value.maximum_reply_surb_storage_threshold,
minimum_reply_surb_request_size: value.minimum_reply_surb_request_size, minimum_reply_surb_request_size: value.minimum_reply_surb_request_size,
@@ -192,10 +190,10 @@ impl Default for OldDebugConfigV1_1_13 {
} }
} }
impl<T, U> From<OldConfigV1_1_13<T>> for Config<U> { impl<T, U> From<OldConfigV1_1_13<T>> for ConfigV1_1_19<U> {
fn from(value: OldConfigV1_1_13<T>) -> Self { fn from(value: OldConfigV1_1_13<T>) -> Self {
Config { ConfigV1_1_19 {
client: Client { client: ClientV1_1_19 {
version: value.client.version, version: value.client.version,
id: value.client.id, id: value.client.id,
disabled_credentials_mode: value.client.disabled_credentials_mode, disabled_credentials_mode: value.client.disabled_credentials_mode,
@@ -211,10 +209,10 @@ impl<T, U> From<OldConfigV1_1_13<T>> for Config<U> {
database_path: value.client.database_path, database_path: value.client.database_path,
reply_surb_database_path: value.client.reply_surb_database_path, reply_surb_database_path: value.client.reply_surb_database_path,
nym_root_directory: value.client.nym_root_directory, nym_root_directory: value.client.nym_root_directory,
super_struct: PhantomData, super_struct: PhantomData,
packet_type: Some(nym_sphinx::params::PacketType::Mix),
}, },
logging: value.logging, logging: value.logging.into(),
debug: value.debug.into(), debug: value.debug.into(),
} }
} }
@@ -0,0 +1,354 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::config::{
Acknowledgements, CoverTraffic, DebugConfig, GatewayConnection, GatewayEndpointConfig,
ReplySurbs, Topology, Traffic,
};
use nym_sphinx::params::{PacketSize, PacketType};
use serde::{Deserialize, Serialize};
use std::marker::PhantomData;
use std::path::PathBuf;
use std::time::Duration;
use url::Url;
// 'DEBUG'
pub(crate) const DEFAULT_ACK_WAIT_MULTIPLIER: f64 = 1.5;
pub(crate) const DEFAULT_ACK_WAIT_ADDITION: Duration = Duration::from_millis(1_500);
pub(crate) const DEFAULT_LOOP_COVER_STREAM_AVERAGE_DELAY: Duration = Duration::from_millis(200);
pub(crate) const DEFAULT_MESSAGE_STREAM_AVERAGE_DELAY: Duration = Duration::from_millis(20);
pub(crate) const DEFAULT_AVERAGE_PACKET_DELAY: Duration = Duration::from_millis(50);
pub(crate) const DEFAULT_TOPOLOGY_REFRESH_RATE: Duration = Duration::from_secs(5 * 60); // every 5min
pub(crate) const DEFAULT_TOPOLOGY_RESOLUTION_TIMEOUT: Duration = Duration::from_millis(5_000);
// Set this to a high value for now, so that we don't risk sporadic timeouts that might cause
// bought bandwidth tokens to not have time to be spent; Once we remove the gateway from the
// bandwidth bridging protocol, we can come back to a smaller timeout value
pub(crate) const DEFAULT_GATEWAY_RESPONSE_TIMEOUT: Duration = Duration::from_secs(5 * 60);
pub(crate) const DEFAULT_COVER_TRAFFIC_PRIMARY_SIZE_RATIO: f64 = 0.70;
// reply-surbs related:
// define when to request
// clients/client-core/src/client/replies/reply_storage/surb_storage.rs
pub(crate) const DEFAULT_MINIMUM_REPLY_SURB_STORAGE_THRESHOLD: usize = 10;
pub(crate) const DEFAULT_MAXIMUM_REPLY_SURB_STORAGE_THRESHOLD: usize = 200;
// define how much to request at once
// clients/client-core/src/client/replies/reply_controller.rs
pub(crate) const DEFAULT_MINIMUM_REPLY_SURB_REQUEST_SIZE: u32 = 10;
pub(crate) const DEFAULT_MAXIMUM_REPLY_SURB_REQUEST_SIZE: u32 = 100;
pub(crate) const DEFAULT_MAXIMUM_ALLOWED_SURB_REQUEST_SIZE: u32 = 500;
pub(crate) const DEFAULT_MAXIMUM_REPLY_SURB_REREQUEST_WAITING_PERIOD: Duration =
Duration::from_secs(10);
pub(crate) const DEFAULT_MAXIMUM_REPLY_SURB_DROP_WAITING_PERIOD: Duration =
Duration::from_secs(5 * 60);
// 12 hours
pub(crate) const DEFAULT_MAXIMUM_REPLY_SURB_AGE: Duration = Duration::from_secs(12 * 60 * 60);
// 24 hours
pub(crate) const DEFAULT_MAXIMUM_REPLY_KEY_AGE: Duration = Duration::from_secs(24 * 60 * 60);
#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct ConfigV1_1_19<T> {
pub client: ClientV1_1_19<T>,
#[serde(default)]
pub logging: LoggingV1_1_19,
#[serde(default)]
pub debug: DebugConfigV1_1_19,
}
#[derive(Clone, Debug, Default, Deserialize, PartialEq, Eq, Serialize)]
pub struct GatewayEndpointConfigV1_1_19 {
pub gateway_id: String,
pub gateway_owner: String,
pub gateway_listener: String,
}
impl From<GatewayEndpointConfigV1_1_19> for GatewayEndpointConfig {
fn from(value: GatewayEndpointConfigV1_1_19) -> Self {
GatewayEndpointConfig {
gateway_id: value.gateway_id,
gateway_owner: value.gateway_owner,
gateway_listener: value.gateway_listener,
}
}
}
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
pub struct ClientV1_1_19<T> {
pub version: String,
pub id: String,
#[serde(default)]
pub disabled_credentials_mode: bool,
#[serde(alias = "validator_urls")]
pub nyxd_urls: Vec<Url>,
#[serde(alias = "validator_api_urls")]
pub nym_api_urls: Vec<Url>,
pub private_identity_key_file: PathBuf,
pub public_identity_key_file: PathBuf,
pub private_encryption_key_file: PathBuf,
pub public_encryption_key_file: PathBuf,
pub gateway_shared_key_file: PathBuf,
pub ack_key_file: PathBuf,
pub gateway_endpoint: GatewayEndpointConfigV1_1_19,
pub database_path: PathBuf,
#[serde(default)]
pub reply_surb_database_path: PathBuf,
pub nym_root_directory: PathBuf,
#[serde(skip)]
pub super_struct: PhantomData<T>,
}
#[derive(Debug, Clone, Default, Deserialize, PartialEq, Eq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct LoggingV1_1_19 {}
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
#[serde(default)]
pub struct TrafficV1_1_19 {
#[serde(with = "humantime_serde")]
pub average_packet_delay: Duration,
#[serde(with = "humantime_serde")]
pub message_sending_average_delay: Duration,
pub disable_main_poisson_packet_distribution: bool,
pub primary_packet_size: PacketSize,
pub secondary_packet_size: Option<PacketSize>,
}
impl From<TrafficV1_1_19> for Traffic {
fn from(value: TrafficV1_1_19) -> Self {
Traffic {
average_packet_delay: value.average_packet_delay,
message_sending_average_delay: value.message_sending_average_delay,
disable_main_poisson_packet_distribution: value
.disable_main_poisson_packet_distribution,
primary_packet_size: value.primary_packet_size,
secondary_packet_size: value.secondary_packet_size,
packet_type: PacketType::Mix,
}
}
}
impl Default for TrafficV1_1_19 {
fn default() -> Self {
TrafficV1_1_19 {
average_packet_delay: DEFAULT_AVERAGE_PACKET_DELAY,
message_sending_average_delay: DEFAULT_MESSAGE_STREAM_AVERAGE_DELAY,
disable_main_poisson_packet_distribution: false,
primary_packet_size: PacketSize::RegularPacket,
secondary_packet_size: None,
}
}
}
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct CoverTrafficV1_1_19 {
#[serde(with = "humantime_serde")]
pub loop_cover_traffic_average_delay: Duration,
pub cover_traffic_primary_size_ratio: f64,
pub disable_loop_cover_traffic_stream: bool,
}
impl From<CoverTrafficV1_1_19> for CoverTraffic {
fn from(value: CoverTrafficV1_1_19) -> Self {
CoverTraffic {
loop_cover_traffic_average_delay: value.loop_cover_traffic_average_delay,
cover_traffic_primary_size_ratio: value.cover_traffic_primary_size_ratio,
disable_loop_cover_traffic_stream: value.disable_loop_cover_traffic_stream,
}
}
}
impl Default for CoverTrafficV1_1_19 {
fn default() -> Self {
CoverTrafficV1_1_19 {
loop_cover_traffic_average_delay: DEFAULT_LOOP_COVER_STREAM_AVERAGE_DELAY,
cover_traffic_primary_size_ratio: DEFAULT_COVER_TRAFFIC_PRIMARY_SIZE_RATIO,
disable_loop_cover_traffic_stream: false,
}
}
}
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct GatewayConnectionV1_1_19 {
#[serde(with = "humantime_serde")]
pub gateway_response_timeout: Duration,
}
impl From<GatewayConnectionV1_1_19> for GatewayConnection {
fn from(value: GatewayConnectionV1_1_19) -> Self {
GatewayConnection {
gateway_response_timeout: value.gateway_response_timeout,
}
}
}
impl Default for GatewayConnectionV1_1_19 {
fn default() -> Self {
GatewayConnectionV1_1_19 {
gateway_response_timeout: DEFAULT_GATEWAY_RESPONSE_TIMEOUT,
}
}
}
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct AcknowledgementsV1_1_19 {
#[serde(with = "humantime_serde")]
pub average_ack_delay: Duration,
pub ack_wait_multiplier: f64,
#[serde(with = "humantime_serde")]
pub ack_wait_addition: Duration,
}
impl From<AcknowledgementsV1_1_19> for Acknowledgements {
fn from(value: AcknowledgementsV1_1_19) -> Self {
Acknowledgements {
average_ack_delay: value.average_ack_delay,
ack_wait_multiplier: value.ack_wait_multiplier,
ack_wait_addition: value.ack_wait_addition,
}
}
}
impl Default for AcknowledgementsV1_1_19 {
fn default() -> Self {
AcknowledgementsV1_1_19 {
average_ack_delay: DEFAULT_AVERAGE_PACKET_DELAY,
ack_wait_multiplier: DEFAULT_ACK_WAIT_MULTIPLIER,
ack_wait_addition: DEFAULT_ACK_WAIT_ADDITION,
}
}
}
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct TopologyV1_1_19 {
#[serde(with = "humantime_serde")]
pub topology_refresh_rate: Duration,
#[serde(with = "humantime_serde")]
pub topology_resolution_timeout: Duration,
pub disable_refreshing: bool,
}
impl From<TopologyV1_1_19> for Topology {
fn from(value: TopologyV1_1_19) -> Self {
Topology {
topology_refresh_rate: value.topology_refresh_rate,
topology_resolution_timeout: value.topology_resolution_timeout,
disable_refreshing: value.disable_refreshing,
}
}
}
impl Default for TopologyV1_1_19 {
fn default() -> Self {
TopologyV1_1_19 {
topology_refresh_rate: DEFAULT_TOPOLOGY_REFRESH_RATE,
topology_resolution_timeout: DEFAULT_TOPOLOGY_RESOLUTION_TIMEOUT,
disable_refreshing: false,
}
}
}
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct ReplySurbsV1_1_19 {
pub minimum_reply_surb_storage_threshold: usize,
pub maximum_reply_surb_storage_threshold: usize,
pub minimum_reply_surb_request_size: u32,
pub maximum_reply_surb_request_size: u32,
pub maximum_allowed_reply_surb_request_size: u32,
#[serde(with = "humantime_serde")]
pub maximum_reply_surb_rerequest_waiting_period: Duration,
#[serde(with = "humantime_serde")]
pub maximum_reply_surb_drop_waiting_period: Duration,
#[serde(with = "humantime_serde")]
pub maximum_reply_surb_age: Duration,
#[serde(with = "humantime_serde")]
pub maximum_reply_key_age: Duration,
}
impl From<ReplySurbsV1_1_19> for ReplySurbs {
fn from(value: ReplySurbsV1_1_19) -> Self {
ReplySurbs {
minimum_reply_surb_storage_threshold: value.minimum_reply_surb_storage_threshold,
maximum_reply_surb_storage_threshold: value.maximum_reply_surb_storage_threshold,
minimum_reply_surb_request_size: value.minimum_reply_surb_request_size,
maximum_reply_surb_request_size: value.maximum_reply_surb_request_size,
maximum_allowed_reply_surb_request_size: value.maximum_allowed_reply_surb_request_size,
maximum_reply_surb_rerequest_waiting_period: value
.maximum_reply_surb_rerequest_waiting_period,
maximum_reply_surb_drop_waiting_period: value.maximum_reply_surb_drop_waiting_period,
maximum_reply_surb_age: value.maximum_reply_surb_age,
maximum_reply_key_age: value.maximum_reply_key_age,
}
}
}
impl Default for ReplySurbsV1_1_19 {
fn default() -> Self {
ReplySurbsV1_1_19 {
minimum_reply_surb_storage_threshold: DEFAULT_MINIMUM_REPLY_SURB_STORAGE_THRESHOLD,
maximum_reply_surb_storage_threshold: DEFAULT_MAXIMUM_REPLY_SURB_STORAGE_THRESHOLD,
minimum_reply_surb_request_size: DEFAULT_MINIMUM_REPLY_SURB_REQUEST_SIZE,
maximum_reply_surb_request_size: DEFAULT_MAXIMUM_REPLY_SURB_REQUEST_SIZE,
maximum_allowed_reply_surb_request_size: DEFAULT_MAXIMUM_ALLOWED_SURB_REQUEST_SIZE,
maximum_reply_surb_rerequest_waiting_period:
DEFAULT_MAXIMUM_REPLY_SURB_REREQUEST_WAITING_PERIOD,
maximum_reply_surb_drop_waiting_period: DEFAULT_MAXIMUM_REPLY_SURB_DROP_WAITING_PERIOD,
maximum_reply_surb_age: DEFAULT_MAXIMUM_REPLY_SURB_AGE,
maximum_reply_key_age: DEFAULT_MAXIMUM_REPLY_KEY_AGE,
}
}
}
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct DebugConfigV1_1_19 {
pub traffic: TrafficV1_1_19,
pub cover_traffic: CoverTrafficV1_1_19,
pub gateway_connection: GatewayConnectionV1_1_19,
pub acknowledgements: AcknowledgementsV1_1_19,
pub topology: TopologyV1_1_19,
pub reply_surbs: ReplySurbsV1_1_19,
}
impl From<DebugConfigV1_1_19> for DebugConfig {
fn from(value: DebugConfigV1_1_19) -> Self {
DebugConfig {
traffic: value.traffic.into(),
cover_traffic: value.cover_traffic.into(),
gateway_connection: value.gateway_connection.into(),
acknowledgements: value.acknowledgements.into(),
topology: value.topology.into(),
reply_surbs: value.reply_surbs.into(),
}
}
}
// it could be derived, sure, but I'd rather have an explicit implementation in case we had to change
// something manually at some point
#[allow(clippy::derivable_impls)]
impl Default for DebugConfigV1_1_19 {
fn default() -> Self {
DebugConfigV1_1_19 {
traffic: Default::default(),
cover_traffic: Default::default(),
gateway_connection: Default::default(),
acknowledgements: Default::default(),
topology: Default::default(),
reply_surbs: Default::default(),
}
}
}
@@ -1,108 +0,0 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::config::Config;
use std::path::{Path, PathBuf};
#[derive(Debug)]
pub struct ClientKeyPathfinder {
pub identity_private_key: PathBuf,
pub identity_public_key: PathBuf,
pub encryption_private_key: PathBuf,
pub encryption_public_key: PathBuf,
pub gateway_shared_key: PathBuf,
pub ack_key: PathBuf,
}
impl ClientKeyPathfinder {
pub fn new(id: String) -> Self {
let os_config_dir = dirs::config_dir().expect("no config directory known for this OS"); // grabs the OS default config dir
let config_dir = os_config_dir.join("nym").join("clients").join(id);
ClientKeyPathfinder {
identity_private_key: config_dir.join("private_identity.pem"),
identity_public_key: config_dir.join("public_identity.pem"),
encryption_private_key: config_dir.join("private_encryption.pem"),
encryption_public_key: config_dir.join("public_encryption.pem"),
gateway_shared_key: config_dir.join("gateway_shared.pem"),
ack_key: config_dir.join("ack_key.pem"),
}
}
pub fn new_from_config<T>(config: &Config<T>) -> Self {
ClientKeyPathfinder {
identity_private_key: config.get_private_identity_key_file(),
identity_public_key: config.get_public_identity_key_file(),
encryption_private_key: config.get_private_encryption_key_file(),
encryption_public_key: config.get_public_encryption_key_file(),
gateway_shared_key: config.get_gateway_shared_key_file(),
ack_key: config.get_ack_key_file(),
}
}
pub fn identity_key_pair_path(&self) -> nym_pemstore::KeyPairPath {
nym_pemstore::KeyPairPath::new(
self.private_identity_key().to_path_buf(),
self.public_identity_key().to_path_buf(),
)
}
pub fn encryption_key_pair_path(&self) -> nym_pemstore::KeyPairPath {
nym_pemstore::KeyPairPath::new(
self.private_encryption_key().to_path_buf(),
self.public_encryption_key().to_path_buf(),
)
}
pub fn any_file_exists(&self) -> bool {
matches!(self.identity_public_key.try_exists(), Ok(true))
|| matches!(self.identity_private_key.try_exists(), Ok(true))
|| matches!(self.encryption_public_key.try_exists(), Ok(true))
|| matches!(self.encryption_private_key.try_exists(), Ok(true))
|| matches!(self.gateway_shared_key.try_exists(), Ok(true))
|| matches!(self.ack_key.try_exists(), Ok(true))
}
pub fn any_file_exists_and_return(&self) -> Option<PathBuf> {
file_exists(&self.identity_public_key)
.or_else(|| file_exists(&self.identity_private_key))
.or_else(|| file_exists(&self.encryption_public_key))
.or_else(|| file_exists(&self.encryption_private_key))
.or_else(|| file_exists(&self.gateway_shared_key))
.or_else(|| file_exists(&self.ack_key))
}
pub fn gateway_key_file_exists(&self) -> bool {
matches!(self.gateway_shared_key.try_exists(), Ok(true))
}
pub fn private_identity_key(&self) -> &Path {
&self.identity_private_key
}
pub fn public_identity_key(&self) -> &Path {
&self.identity_public_key
}
pub fn private_encryption_key(&self) -> &Path {
&self.encryption_private_key
}
pub fn public_encryption_key(&self) -> &Path {
&self.encryption_public_key
}
pub fn gateway_shared_key(&self) -> &Path {
&self.gateway_shared_key
}
pub fn ack_key(&self) -> &Path {
&self.ack_key
}
}
fn file_exists(path: &Path) -> Option<PathBuf> {
if matches!(path.try_exists(), Ok(true)) {
return Some(path.to_path_buf());
}
None
}
@@ -1,4 +0,0 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
pub mod key_pathfinder;
+22 -81
View File
@@ -8,20 +8,15 @@ use crate::client::key_manager::persistence::KeyStore;
use crate::client::key_manager::{KeyManager, ManagedKeys}; use crate::client::key_manager::{KeyManager, ManagedKeys};
use crate::init::helpers::{choose_gateway_by_latency, current_gateways, uniformly_random_gateway}; use crate::init::helpers::{choose_gateway_by_latency, current_gateways, uniformly_random_gateway};
use crate::{ use crate::{
config::{ config::{disk_persistence::keys_paths::ClientKeysPaths, Config, GatewayEndpointConfig},
persistence::key_pathfinder::ClientKeyPathfinder, ClientCoreConfigTrait, Config,
GatewayEndpointConfig,
},
error::ClientCoreError, error::ClientCoreError,
}; };
use nym_config::NymConfig;
use nym_crypto::asymmetric::{encryption, identity}; use nym_crypto::asymmetric::{encryption, identity};
use nym_sphinx::addressing::{clients::Recipient, nodes::NodeIdentity}; use nym_sphinx::addressing::{clients::Recipient, nodes::NodeIdentity};
use nym_validator_client::client::IdentityKey; use nym_validator_client::client::IdentityKey;
use rand::rngs::OsRng; use rand::rngs::OsRng;
use serde::Serialize; use serde::Serialize;
use std::fmt::{Debug, Display}; use std::fmt::{Debug, Display};
use tap::TapFallible;
use url::Url; use url::Url;
mod helpers; mod helpers;
@@ -122,13 +117,10 @@ pub struct InitResults {
} }
impl InitResults { impl InitResults {
pub fn new<T>(config: &Config<T>, address: &Recipient) -> Self pub fn new(config: &Config, address: &Recipient) -> Self {
where
T: NymConfig,
{
Self { Self {
version: config.get_version().to_string(), version: config.client.version.clone(),
id: config.get_id(), id: config.client.id.clone(),
identity_key: address.identity().to_base58_string(), identity_key: address.identity().to_base58_string(),
encryption_key: address.encryption_key().to_base58_string(), encryption_key: address.encryption_key().to_base58_string(),
gateway_id: config.get_gateway_id(), gateway_id: config.get_gateway_id(),
@@ -155,7 +147,7 @@ pub async fn get_registered_gateway<S>(
key_store: &S::KeyStore, key_store: &S::KeyStore,
setup: GatewaySetup, setup: GatewaySetup,
overwrite_keys: bool, overwrite_keys: bool,
) -> Result<(GatewayEndpointConfig, ManagedKeys), ClientCoreError> ) -> Result<GatewayEndpointConfig, ClientCoreError>
where where
S: MixnetClientStorage, S: MixnetClientStorage,
<S::KeyStore as KeyStore>::StorageError: Send + Sync + 'static, <S::KeyStore as KeyStore>::StorageError: Send + Sync + 'static,
@@ -164,11 +156,11 @@ where
// try load keys // try load keys
let mut managed_keys = match ManagedKeys::try_load(key_store).await { let mut managed_keys = match ManagedKeys::try_load(key_store).await {
Ok(loaded_keys) => { Ok(_) => {
// if we loaded something and we don't have full gateway details, check if we can overwrite the data // if we loaded something and we don't have full gateway details, check if we can overwrite the data
if let GatewaySetup::Predefined { config } = setup { if let GatewaySetup::Predefined { config } = setup {
// we already have defined gateway details AND a shared key, so nothing more for us to do // we already have defined gateway details AND a shared key, so nothing more for us to do
return Ok((config, loaded_keys)); return Ok(config);
} else if overwrite_keys { } else if overwrite_keys {
ManagedKeys::generate_new(&mut rng) ManagedKeys::generate_new(&mut rng)
} else { } else {
@@ -196,7 +188,7 @@ where
// TODO: here we should be probably persisting gateway details as opposed to returning them // TODO: here we should be probably persisting gateway details as opposed to returning them
Ok((gateway_details, managed_keys)) Ok(gateway_details)
} }
/// Convenience function for setting up the gateway for a client given a `Config`. Depending on the /// Convenience function for setting up the gateway for a client given a `Config`. Depending on the
@@ -206,26 +198,22 @@ where
/// b. Create a new gateway configuration but keep existing keys. This assumes that the caller /// b. Create a new gateway configuration but keep existing keys. This assumes that the caller
/// knows what they are doing and that the keys match the requested gateway. /// knows what they are doing and that the keys match the requested gateway.
/// c. Create a new gateway configuration with a newly registered gateway and keys. /// c. Create a new gateway configuration with a newly registered gateway and keys.
pub async fn setup_gateway_from_config<C, T, KSt>( pub async fn setup_gateway_from_config<KSt>(
key_store: &KSt, key_store: &KSt,
register_gateway: bool, register_gateway: bool,
user_chosen_gateway_id: Option<identity::PublicKey>, user_chosen_gateway_id: Option<identity::PublicKey>,
config: &Config<T>, config: &Config,
by_latency: bool, by_latency: bool,
) -> Result<GatewayEndpointConfig, ClientCoreError> ) -> Result<GatewayEndpointConfig, ClientCoreError>
where where
C: NymConfig + ClientCoreConfigTrait,
T: NymConfig,
KSt: KeyStore, KSt: KeyStore,
<KSt as KeyStore>::StorageError: Send + Sync + 'static, <KSt as KeyStore>::StorageError: Send + Sync + 'static,
{ {
let id = config.get_id();
// If we are not going to register gateway, and an explicitly chosen gateway is not passed in, // If we are not going to register gateway, and an explicitly chosen gateway is not passed in,
// load the existing configuration file // load the existing configuration file
if !register_gateway && user_chosen_gateway_id.is_none() { if !register_gateway && user_chosen_gateway_id.is_none() {
eprintln!("Not registering gateway, will reuse existing config and keys"); eprintln!("Not registering gateway, will reuse existing config and keys");
return load_existing_gateway_config::<C>(&id); return Ok(config.client.gateway_endpoint.clone());
} }
let gateway_setup = GatewaySetup::new( let gateway_setup = GatewaySetup::new(
@@ -266,25 +254,6 @@ where
Ok(gateway) Ok(gateway)
} }
/// Read and reuse the existing gateway configuration from a file that was generate earlier.
pub fn load_existing_gateway_config<T>(id: &str) -> Result<GatewayEndpointConfig, ClientCoreError>
where
T: NymConfig + ClientCoreConfigTrait,
{
T::load_from_file(id)
.map(|existing_config| existing_config.get_gateway_endpoint().clone())
.map_err(|err| {
log::error!(
"Unable to configure gateway: {err}. \n
Seems like the client was already initialized but it was not possible to read \
the existing configuration file. \n
CAUTION: Consider backing up your gateway keys and try force gateway registration, or \
removing the existing configuration and starting over."
);
ClientCoreError::CouldNotLoadExistingGatewayConfiguration(err)
})
}
/// Get the full client address from the client keys and the gateway identity /// Get the full client address from the client keys and the gateway identity
pub fn get_client_address( pub fn get_client_address(
key_manager: &KeyManager, key_manager: &KeyManager,
@@ -299,51 +268,23 @@ pub fn get_client_address(
) )
} }
pub fn load_identity_keys(
pathfinder: &ClientKeyPathfinder,
) -> Result<identity::KeyPair, ClientCoreError> {
let identity_keypair: identity::KeyPair =
nym_pemstore::load_keypair(&pathfinder.identity_key_pair_path())
.tap_err(|_| log::error!("Failed to read stored identity key files"))?;
Ok(identity_keypair)
}
/// Get the client address by loading the keys from stored files. /// Get the client address by loading the keys from stored files.
// TODO: rethink that sucker // TODO: rethink that sucker
pub fn get_client_address_from_stored_ondisk_keys<T>( pub fn get_client_address_from_stored_ondisk_keys(
config: &Config<T>, keys_paths: &ClientKeysPaths,
) -> Result<Recipient, ClientCoreError> gateway_config: &GatewayEndpointConfig,
where ) -> Result<Recipient, ClientCoreError> {
T: nym_config::NymConfig, let public_identity: identity::PublicKey =
{ nym_pemstore::load_key(&keys_paths.public_identity_key_file)?;
fn load_identity_keys( let public_encryption: encryption::PublicKey =
pathfinder: &ClientKeyPathfinder, nym_pemstore::load_key(&keys_paths.public_encryption_key_file)?;
) -> Result<identity::KeyPair, ClientCoreError> {
let identity_keypair: identity::KeyPair =
nym_pemstore::load_keypair(&pathfinder.identity_key_pair_path())
.tap_err(|_| log::error!("Failed to read stored identity key files"))?;
Ok(identity_keypair)
}
fn load_sphinx_keys(
pathfinder: &ClientKeyPathfinder,
) -> Result<encryption::KeyPair, ClientCoreError> {
let sphinx_keypair: encryption::KeyPair =
nym_pemstore::load_keypair(&pathfinder.encryption_key_pair_path())
.tap_err(|_| log::error!("Failed to read stored sphinx key files"))?;
Ok(sphinx_keypair)
}
let pathfinder = ClientKeyPathfinder::new_from_config(config);
let identity_keypair = load_identity_keys(&pathfinder)?;
let sphinx_keypair = load_sphinx_keys(&pathfinder)?;
let client_recipient = Recipient::new( let client_recipient = Recipient::new(
*identity_keypair.public_key(), public_identity,
*sphinx_keypair.public_key(), public_encryption,
// TODO: below only works under assumption that gateway address == gateway id // TODO: below only works under assumption that gateway address == gateway id
// (which currently is true) // (which currently is true)
NodeIdentity::from_base58_string(config.get_gateway_id())?, NodeIdentity::from_base58_string(&gateway_config.gateway_id)?,
); );
Ok(client_recipient) Ok(client_recipient)
@@ -1,12 +1,12 @@
use async_trait::async_trait; use async_trait::async_trait;
use cosmrs::AccountId; use cosmrs::AccountId;
use nym_contracts_common::{signing::Nonce, ContractBuildInformation}; use nym_contracts_common::ContractBuildInformation;
use nym_service_provider_directory_common::{ use nym_service_provider_directory_common::{
msg::QueryMsg as SpQueryMsg, msg::QueryMsg as SpQueryMsg,
response::{ response::{
ConfigResponse, PagedServicesListResponse, ServiceInfoResponse, ServicesListResponse, ConfigResponse, PagedServicesListResponse, ServiceInfoResponse, ServicesListResponse,
}, },
NymAddress, Service, ServiceId, NymAddress, ServiceId, ServiceInfo,
}; };
use serde::Deserialize; use serde::Deserialize;
@@ -63,14 +63,17 @@ pub trait SpDirectoryQueryClient {
.await .await
} }
async fn get_all_services(&self) -> Result<Vec<Service>, NyxdError> { async fn get_all_services(&self) -> Result<Vec<ServiceInfo>, NyxdError> {
let mut services = Vec::new(); let mut services = Vec::new();
let mut start_after = None; let mut start_after = None;
loop { loop {
let mut paged_response = self.get_services_paged(start_after.take(), None).await?; let mut paged_response = self.get_services_paged(start_after.take(), None).await?;
let last_id = paged_response.services.last().map(|serv| serv.service_id);
services.append(&mut paged_response.services); services.append(&mut paged_response.services);
if let Some(start_after_res) = paged_response.start_next_after { if let Some(start_after_res) = last_id {
start_after = Some(start_after_res) start_after = Some(start_after_res)
} else { } else {
break; break;
@@ -79,13 +82,6 @@ pub trait SpDirectoryQueryClient {
Ok(services) Ok(services)
} }
async fn get_service_signing_nonce(&self, address: &AccountId) -> Result<Nonce, NyxdError> {
self.query_service_provider_contract(SpQueryMsg::SigningNonce {
address: address.to_string(),
})
.await
}
} }
#[async_trait] #[async_trait]
@@ -2,9 +2,8 @@
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use async_trait::async_trait; use async_trait::async_trait;
use nym_contracts_common::signing::MessageSignature;
use nym_service_provider_directory_common::{ use nym_service_provider_directory_common::{
msg::ExecuteMsg as SpExecuteMsg, NymAddress, ServiceDetails, ServiceId, msg::ExecuteMsg as SpExecuteMsg, NymAddress, ServiceId, ServiceType,
}; };
use crate::nyxd::{ use crate::nyxd::{
@@ -23,16 +22,16 @@ pub trait SpDirectorySigningClient {
async fn announce_service_provider( async fn announce_service_provider(
&self, &self,
service: ServiceDetails, nym_address: NymAddress,
owner_signature: MessageSignature, service_type: ServiceType,
deposit: Coin, deposit: Coin,
fee: Option<Fee>, fee: Option<Fee>,
) -> Result<ExecuteResult, NyxdError> { ) -> Result<ExecuteResult, NyxdError> {
self.execute_service_provider_directory_contract( self.execute_service_provider_directory_contract(
fee, fee,
SpExecuteMsg::Announce { SpExecuteMsg::Announce {
service, nym_address,
owner_signature, service_type,
}, },
vec![deposit], vec![deposit],
) )
-1
View File
@@ -40,4 +40,3 @@ nym-coconut-dkg-common = { path = "../cosmwasm-smart-contracts/coconut-dkg" }
nym-multisig-contract-common = { path = "../cosmwasm-smart-contracts/multisig-contract" } nym-multisig-contract-common = { path = "../cosmwasm-smart-contracts/multisig-contract" }
nym-service-provider-directory-common = { path = "../cosmwasm-smart-contracts/service-provider-directory" } nym-service-provider-directory-common = { path = "../cosmwasm-smart-contracts/service-provider-directory" }
nym-name-service-common = { path = "../cosmwasm-smart-contracts/name-service" } nym-name-service-common = { path = "../cosmwasm-smart-contracts/name-service" }
nym-sphinx = { path = "../../common/nymsphinx" }
@@ -14,7 +14,6 @@ pub struct Mixnet {
pub command: MixnetCommands, pub command: MixnetCommands,
} }
#[allow(clippy::large_enum_variant)]
#[derive(Debug, Subcommand)] #[derive(Debug, Subcommand)]
pub enum MixnetCommands { pub enum MixnetCommands {
/// Query the mixnet directory /// Query the mixnet directory
@@ -15,7 +15,6 @@ pub struct MixnetOperators {
pub command: MixnetOperatorsCommands, pub command: MixnetOperatorsCommands,
} }
#[allow(clippy::large_enum_variant)]
#[derive(Debug, Subcommand)] #[derive(Debug, Subcommand)]
pub enum MixnetOperatorsCommands { pub enum MixnetOperatorsCommands {
/// Manage your mixnode /// Manage your mixnode
@@ -1,7 +1,6 @@
use clap::Parser; use clap::Parser;
use log::info; use log::info;
use nym_contracts_common::signing::MessageSignature; use nym_service_provider_directory_common::{Coin, NymAddress, ServiceType};
use nym_service_provider_directory_common::{Coin, NymAddress, ServiceDetails, ServiceType};
use nym_validator_client::nyxd::traits::SpDirectorySigningClient; use nym_validator_client::nyxd::traits::SpDirectorySigningClient;
use crate::context::SigningClient; use crate::context::SigningClient;
@@ -11,15 +10,9 @@ pub struct Args {
#[clap(long)] #[clap(long)]
pub nym_address: String, pub nym_address: String,
#[clap(long)]
pub signature: MessageSignature,
/// Deposit to be made to the service provider directory, in curent DENOMINATION (e.g. 'unym') /// Deposit to be made to the service provider directory, in curent DENOMINATION (e.g. 'unym')
#[clap(long)] #[clap(long)]
pub deposit: u128, pub deposit: u128,
#[clap(long)]
pub identity_key: String,
} }
pub async fn announce(args: Args, client: SigningClient) { pub async fn announce(args: Args, client: SigningClient) {
@@ -27,17 +20,12 @@ pub async fn announce(args: Args, client: SigningClient) {
let nym_address = NymAddress::Address(args.nym_address); let nym_address = NymAddress::Address(args.nym_address);
let service_type = ServiceType::NetworkRequester; let service_type = ServiceType::NetworkRequester;
let service = ServiceDetails {
nym_address,
service_type,
identity_key: args.identity_key,
};
let denom = client.current_chain_details().mix_denom.base.as_str(); let denom = client.current_chain_details().mix_denom.base.as_str();
let deposit = Coin::new(args.deposit, denom); let deposit = Coin::new(args.deposit, denom);
let res = client let res = client
.announce_service_provider(service, args.signature, deposit.into(), None) .announce_service_provider(nym_address, service_type, deposit.into(), None)
.await .await
.expect("Failed to announce service provider"); .expect("Failed to announce service provider");
@@ -1,61 +0,0 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::{
context::SigningClient,
utils::{account_id_to_cw_addr, DataWrapper},
};
use clap::Parser;
use cosmwasm_std::Coin;
use nym_bin_common::output_format::OutputFormat;
use nym_service_provider_directory_common::{
signing_types::construct_service_provider_announce_sign_payload, NymAddress,
ServiceType::NetworkRequester,
};
use nym_sphinx::addressing::clients::Recipient;
use nym_validator_client::nyxd::traits::SpDirectoryQueryClient;
#[derive(Debug, Parser)]
pub struct Args {
#[clap(long)]
pub nym_address: Recipient,
#[clap(long)]
pub amount: u128,
#[clap(long)]
pub identity_key: String,
#[clap(short, long, default_value_t = OutputFormat::default())]
output: OutputFormat,
}
pub async fn create_payload(args: Args, client: SigningClient) {
let service = nym_service_provider_directory_common::ServiceDetails {
nym_address: NymAddress::new(&args.nym_address.to_string()),
service_type: NetworkRequester,
identity_key: args.identity_key,
};
let denom = client.current_chain_details().mix_denom.base.as_str();
let deposit = Coin::new(args.amount, denom);
let nonce = match client.get_service_signing_nonce(client.address()).await {
Ok(nonce) => nonce,
Err(err) => {
eprint!(
"failed to query for the signing nonce of {}: {err}",
client.address()
);
return;
}
};
let address = account_id_to_cw_addr(client.address());
let payload =
construct_service_provider_announce_sign_payload(nonce, address, deposit, service);
let wrapper = DataWrapper::new(payload.to_base58_string().unwrap());
println!("{}", args.output.format(&wrapper))
}
@@ -1,7 +1,6 @@
use clap::{Args, Subcommand}; use clap::{Args, Subcommand};
pub mod announce; pub mod announce;
pub mod announce_sign_payload;
pub mod delete; pub mod delete;
#[derive(Debug, Args)] #[derive(Debug, Args)]
@@ -11,13 +10,10 @@ pub struct MixnetOperatorsService {
pub command: MixnetOperatorsServiceCommands, pub command: MixnetOperatorsServiceCommands,
} }
#[allow(clippy::large_enum_variant)]
#[derive(Debug, Subcommand)] #[derive(Debug, Subcommand)]
pub enum MixnetOperatorsServiceCommands { pub enum MixnetOperatorsServiceCommands {
/// Announce service provider to the world /// Announce service provider to the world
Announce(announce::Args), Announce(announce::Args),
/// Delete entry for service provider from the directory /// Delete entry for service provider from the directory
Delete(delete::Args), Delete(delete::Args),
/// Create base58-encoded payload required for producing valid announce signature.
CreateServiceAnnounceSignPayload(announce_sign_payload::Args),
} }
@@ -37,7 +37,7 @@ pub async fn query(args: Args, client: &QueryClientWithNyxd) {
for service in res.services { for service in res.services {
table.add_row(vec![ table.add_row(vec![
service.service_id.to_string(), service.service_id.to_string(),
service.announcer.to_string(), service.service.announcer.to_string(),
service.service.service_type.to_string(), service.service.service_type.to_string(),
service.service.nym_address.to_string(), service.service.nym_address.to_string(),
]); ]);
+6 -3
View File
@@ -7,11 +7,14 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
cfg-if = "1.0.0" dirs = { version = "5.0.1", optional = true }
handlebars = "3.0.1" handlebars = "3.5.5"
log = { workspace = true } log = { workspace = true }
serde = { workspace = true, features = ["derive"] } serde = { workspace = true, features = ["derive"] }
toml = "0.5.6" toml = "0.7.4"
url = "2.2" url = "2.2"
nym-network-defaults = { path = "../network-defaults" } nym-network-defaults = { path = "../network-defaults" }
[features]
default = ["dirs"]
+208
View File
@@ -0,0 +1,208 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use nym_network_defaults::mainnet::read_var_if_not_default;
use nym_network_defaults::var_names::CONFIGURED;
use std::any::type_name;
use std::fmt::Debug;
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
use std::str::FromStr;
pub const MISSING_VALUE: &str = "MISSING VALUE";
/// Helper for providing default value for templated config fields.
pub fn missing_string_value<T: From<String>>() -> T {
MISSING_VALUE.to_string().into()
}
/// Helper for providing default INADDR_ANY IpAddr, i.e. `0.0.0.0`
pub fn inaddr_any() -> IpAddr {
IpAddr::V4(Ipv4Addr::UNSPECIFIED)
}
/// Helper for providing default IN6ADDR_ANY_INIT IpAddr, i.e. `::`
pub fn in6addr_any_init() -> IpAddr {
IpAddr::V6(Ipv6Addr::UNSPECIFIED)
}
/// Helper for providing binding warnings if node tries to bind to any of those
pub const SPECIAL_ADDRESSES: &[IpAddr] = &[
IpAddr::V4(Ipv4Addr::LOCALHOST),
IpAddr::V4(Ipv4Addr::UNSPECIFIED),
IpAddr::V4(Ipv4Addr::BROADCAST),
IpAddr::V6(Ipv6Addr::LOCALHOST),
IpAddr::V6(Ipv6Addr::UNSPECIFIED),
];
// TODO: is it really part of 'Config'?
pub trait OptionalSet {
/// If the value is available (i.e. `Some`), the provided closure is applied.
/// Otherwise `self` is returned with no modifications.
fn with_optional<F, T>(self, f: F, val: Option<T>) -> Self
where
F: Fn(Self, T) -> Self,
Self: Sized,
{
if let Some(val) = val {
f(self, val)
} else {
self
}
}
/// If the value is available (i.e. `Some`) it is validated and then the provided closure is applied.
/// Otherwise `self` is returned with no modifications.
fn with_validated_optional<F, T, V, E>(
self,
f: F,
value: Option<T>,
validate: V,
) -> Result<Self, E>
where
F: Fn(Self, T) -> Self,
V: Fn(&T) -> Result<(), E>,
Self: Sized,
{
if let Some(val) = value {
validate(&val)?;
Ok(f(self, val))
} else {
Ok(self)
}
}
/// If the value is available (i.e. `Some`), the provided closure is applied.
/// Otherwise, if the environment was configured and the corresponding variable was set,
/// the value is parsed using the `FromStr` implementation and the closure is applied on that instead.
/// Finally, if none of those were available, `self` is returned with no modifications.
fn with_optional_env<F, T>(self, f: F, val: Option<T>, env_var: &str) -> Self
where
F: Fn(Self, T) -> Self,
T: FromStr,
<T as FromStr>::Err: Debug,
Self: Sized,
{
if let Some(val) = val {
return f(self, val);
} else if std::env::var(CONFIGURED).is_ok() {
if let Some(raw) = read_var_if_not_default(env_var) {
return f(
self,
raw.parse().unwrap_or_else(|err| {
panic!(
"failed to parse value of {raw} into type {}. the error was {:?}",
type_name::<T>(),
err
)
}),
);
}
}
self
}
/// If the value is available (i.e. `Some`), the provided closure is applied.
/// Otherwise, if the environment was configured and the corresponding variable was set,
/// the value is parsed using the provided parser and the closure is applied on that instead.
/// Finally, if none of those were available, `self` is returned with no modifications.
fn with_optional_custom_env<F, T, G>(
self,
f: F,
val: Option<T>,
env_var: &str,
parser: G,
) -> Self
where
F: Fn(Self, T) -> Self,
G: Fn(&str) -> T,
Self: Sized,
{
if let Some(val) = val {
return f(self, val);
} else if std::env::var(CONFIGURED).is_ok() {
if let Some(raw) = read_var_if_not_default(env_var) {
return f(self, parser(&raw));
}
}
self
}
}
// helper for when we want to use `OptionalSet` on an inner field
// (used by clients wanting to set the `BaseConfig` values)
#[macro_export]
macro_rules! define_optional_set_inner {
( $x: ident, $inner_field_name: ident, $inner_field_typ: ty ) => {
impl $x {
pub fn with_optional_inner<F, T>(mut self, f: F, val: Option<T>) -> Self
where
F: Fn($inner_field_typ, T) -> $inner_field_typ,
{
self.$inner_field_name = self.$inner_field_name.with_optional(f, val);
self
}
pub fn with_validated_optional_inner<F, T, V, E>(
mut self,
f: F,
value: Option<T>,
validate: V,
) -> Result<Self, E>
where
F: Fn($inner_field_typ, T) -> $inner_field_typ,
V: Fn(&T) -> Result<(), E>,
{
self.$inner_field_name = self
.$inner_field_name
.with_validated_optional(f, value, validate)?;
Ok(self)
}
pub fn with_optional_env_inner<F, T>(
mut self,
f: F,
val: Option<T>,
env_var: &str,
) -> Self
where
F: Fn($inner_field_typ, T) -> $inner_field_typ,
T: FromStr,
<T as FromStr>::Err: Debug,
{
self.$inner_field_name = self.$inner_field_name.with_optional_env(f, val, env_var);
self
}
pub fn with_optional_custom_env_inner<F, T, G>(
mut self,
f: F,
val: Option<T>,
env_var: &str,
parser: G,
) -> Self
where
F: Fn($inner_field_typ, T) -> $inner_field_typ,
G: Fn(&str) -> T,
{
self.$inner_field_name = self
.$inner_field_name
.with_optional_custom_env(f, val, env_var, parser);
self
}
}
};
}
// this function is only used for parsing values from the network defaults and thus the "expect" there are fine
pub fn parse_urls(raw: &str) -> Vec<url::Url> {
raw.split(',')
.map(|raw_url| {
raw_url
.trim()
.parse()
.expect("one of the provided urls was invalid")
})
.collect()
}
impl<T> OptionalSet for T {}
+55
View File
@@ -0,0 +1,55 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
// removed in 1.1.19/1.1.20
pub mod nym_config {
use serde::de::DeserializeOwned;
use serde::Serialize;
use std::path::{Path, PathBuf};
use std::{fs, io};
pub const CONFIG_DIR: &str = "config";
pub const DATA_DIR: &str = "data";
// no need for anything to do with saving.
pub trait MigrationNymConfig: Serialize + DeserializeOwned {
fn config_file_name() -> String {
"config.toml".to_string()
}
fn default_root_directory() -> PathBuf;
fn default_data_directory(id: &str) -> PathBuf {
Self::default_data_directory_with_root(Self::default_root_directory(), id)
}
fn default_data_directory_with_root<P: AsRef<Path>>(root: P, id: &str) -> PathBuf {
root.as_ref().join(id).join(DATA_DIR)
}
fn default_config_directory(id: &str) -> PathBuf {
Self::default_config_directory_with_root(Self::default_root_directory(), id)
}
fn default_config_directory_with_root<P: AsRef<Path>>(root: P, id: &str) -> PathBuf {
root.as_ref().join(id).join(CONFIG_DIR)
}
fn default_config_file_path(id: &str) -> PathBuf {
Self::default_config_directory(id).join(Self::config_file_name())
}
fn load_from_file(id: &str) -> io::Result<Self> {
let file = Self::default_config_file_path(id);
Self::load_from_filepath(file)
}
fn load_from_filepath<P: AsRef<Path>>(filepath: P) -> io::Result<Self> {
log::trace!("Loading from file: {:#?}", filepath.as_ref().to_owned());
let config_contents = fs::read_to_string(filepath)?;
toml::from_str(&config_contents)
.map_err(|toml_err| io::Error::new(io::ErrorKind::Other, toml_err))
}
}
}
+172 -192
View File
@@ -1,219 +1,199 @@
// Copyright 2020 - Nym Technologies SA <contact@nymtech.net> // Copyright 2020 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use handlebars::Handlebars; use handlebars::{Handlebars, TemplateRenderError};
use nym_network_defaults::mainnet::read_var_if_not_default;
use nym_network_defaults::var_names::CONFIGURED;
use serde::de::DeserializeOwned; use serde::de::DeserializeOwned;
use serde::Serialize; use serde::Serialize;
use std::any::type_name; use std::fs::File;
use std::fmt::Debug; use std::io::Write;
#[cfg(unix)]
use std::os::unix::fs::PermissionsExt;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::str::FromStr;
use std::{fs, io}; use std::{fs, io};
pub use helpers::{parse_urls, OptionalSet};
pub use toml::de::Error as TomlDeError;
pub mod defaults; pub mod defaults;
pub mod helpers;
pub mod legacy_helpers;
pub const CONFIG_DIR: &str = "config"; pub const NYM_DIR: &str = ".nym";
pub const DATA_DIR: &str = "data"; pub const DEFAULT_CONFIG_DIR: &str = "config";
pub const CRED_DB_FILE_NAME: &str = "credentials_database.db"; pub const DEFAULT_DATA_DIR: &str = "data";
pub const DEFAULT_CONFIG_FILENAME: &str = "config.toml";
pub trait NymConfig: Default + Serialize + DeserializeOwned { #[cfg(feature = "dirs")]
pub fn must_get_home() -> PathBuf {
dirs::home_dir().expect("Failed to evaluate $HOME value")
}
#[cfg(feature = "dirs")]
pub fn may_get_home() -> Option<PathBuf> {
dirs::home_dir()
}
pub trait NymConfigTemplate: Serialize {
fn template() -> &'static str; fn template() -> &'static str;
fn config_file_name() -> String { fn format_to_string(&self) -> String {
"config.toml".to_string() // it is responsibility of whoever is implementing the trait to ensure the template is valid
Handlebars::new()
.render_template(Self::template(), &self)
.unwrap()
} }
fn default_root_directory() -> PathBuf; fn format_to_writer<W: Write>(&self, writer: W) -> io::Result<()> {
if let Err(err) =
// default, most probable, implementations; can be easily overridden where required Handlebars::new().render_template_to_write(Self::template(), &self, writer)
fn default_config_directory(id: &str) -> PathBuf { {
Self::default_config_directory_with_root(Self::default_root_directory(), id) match err {
} TemplateRenderError::IOError(err, _) => return Err(err),
other_err => {
fn default_config_directory_with_root<P: AsRef<Path>>(root: P, id: &str) -> PathBuf { // it is responsibility of whoever is implementing the trait to ensure the template is valid
root.as_ref().join(id).join(CONFIG_DIR) panic!("invalid template: {other_err}")
}
fn default_data_directory(id: &str) -> PathBuf {
Self::default_data_directory_with_root(Self::default_root_directory(), id)
}
fn default_data_directory_with_root<P: AsRef<Path>>(root: P, id: &str) -> PathBuf {
root.as_ref().join(id).join(DATA_DIR)
}
fn default_config_file_path(id: &str) -> PathBuf {
Self::default_config_directory(id).join(Self::config_file_name())
}
fn default_config_file_path_with_root<P: AsRef<Path>>(root: P, id: &str) -> PathBuf {
Self::default_config_directory_with_root(root, id).join(Self::config_file_name())
}
// We provide a second set of functions that tries to not panic.
fn try_default_root_directory() -> Option<PathBuf>;
fn try_default_config_directory(id: &str) -> Option<PathBuf> {
Self::try_default_root_directory().map(|d| d.join(id).join(CONFIG_DIR))
}
fn try_default_data_directory(id: &str) -> Option<PathBuf> {
Self::try_default_root_directory().map(|d| d.join(id).join(DATA_DIR))
}
fn try_default_config_file_path(id: &str) -> Option<PathBuf> {
Self::try_default_config_directory(id).map(|d| d.join(Self::config_file_name()))
}
fn root_directory(&self) -> PathBuf;
fn config_directory(&self) -> PathBuf;
fn data_directory(&self) -> PathBuf;
fn save_to_file(&self, custom_location: Option<PathBuf>) -> io::Result<()> {
let reg = Handlebars::new();
// it's whoever is implementing the trait responsibility to make sure you can execute your own template on your data
let templated_config = reg.render_template(Self::template(), self).unwrap();
// make sure the whole directory structure actually exists
match custom_location.clone() {
Some(loc) => {
if let Some(parent_dir) = loc.parent() {
fs::create_dir_all(parent_dir)
} else {
Ok(())
} }
} }
None => fs::create_dir_all(self.config_directory()),
}?;
let location = custom_location
.unwrap_or_else(|| self.config_directory().join(Self::config_file_name()));
log::info!("Configuration file will be saved to {:?}", location);
cfg_if::cfg_if! {
if #[cfg(unix)] {
fs::write(location.clone(), templated_config)?;
let mut perms = fs::metadata(location.clone())?.permissions();
perms.set_mode(0o600);
fs::set_permissions(location, perms)?;
} else {
fs::write(location, templated_config)?;
}
} }
Ok(()) Ok(())
} }
fn load_from_file(id: &str) -> io::Result<Self> {
let file = Self::default_config_file_path(id);
Self::load_from_filepath(file)
}
fn load_from_filepath<P: AsRef<Path>>(filepath: P) -> io::Result<Self> {
log::trace!("Loading from file: {:#?}", filepath.as_ref().to_owned());
let config_contents = fs::read_to_string(filepath)?;
toml::from_str(&config_contents)
.map_err(|toml_err| io::Error::new(io::ErrorKind::Other, toml_err))
}
} }
// this function is only used for parsing values from the network defaults and thus the "expect" there are fine pub fn save_formatted_config_to_file<C, P>(config: &C, path: P) -> io::Result<()>
pub fn parse_urls(raw: &str) -> Vec<url::Url> { where
raw.split(',') C: NymConfigTemplate,
.map(|raw_url| { P: AsRef<Path>,
raw_url {
.trim() log::trace!("trying to save config file to {}", path.as_ref().display());
.parse() let file = File::create(path.as_ref())?;
.expect("one of the provided nym api urls is invalid")
}) // TODO: check for whether any of our configs stores anything sensitive
.collect() // and change that to 0o644 instead
#[cfg(target_family = "unix")]
{
use std::os::unix::fs::PermissionsExt;
let mut perms = fs::metadata(path.as_ref())?.permissions();
perms.set_mode(0o600);
fs::set_permissions(path, perms)?;
}
config.format_to_writer(file)
} }
pub trait OptionalSet { pub fn deserialize_config_from_toml_str<C>(raw: &str) -> Result<C, TomlDeError>
fn with_optional<F, T>(self, f: F, val: Option<T>) -> Self where
where C: DeserializeOwned,
F: Fn(Self, T) -> Self, {
Self: Sized, toml::from_str(raw)
{
if let Some(val) = val {
f(self, val)
} else {
self
}
}
fn with_validated_optional<F, T, V, E>(
self,
f: F,
value: Option<T>,
validate: V,
) -> Result<Self, E>
where
F: Fn(Self, T) -> Self,
V: Fn(&T) -> Result<(), E>,
Self: Sized,
{
if let Some(val) = value {
validate(&val)?;
Ok(f(self, val))
} else {
Ok(self)
}
}
fn with_optional_env<F, T>(self, f: F, val: Option<T>, env_var: &str) -> Self
where
F: Fn(Self, T) -> Self,
T: FromStr,
<T as FromStr>::Err: Debug,
Self: Sized,
{
if let Some(val) = val {
return f(self, val);
} else if std::env::var(CONFIGURED).is_ok() {
if let Some(raw) = read_var_if_not_default(env_var) {
return f(
self,
raw.parse().unwrap_or_else(|err| {
panic!(
"failed to parse value of {raw} into type {}. the error was {:?}",
type_name::<T>(),
err
)
}),
);
}
}
self
}
fn with_optional_custom_env<F, T, G>(
self,
f: F,
val: Option<T>,
env_var: &str,
parser: G,
) -> Self
where
F: Fn(Self, T) -> Self,
G: Fn(&str) -> T,
Self: Sized,
{
if let Some(val) = val {
return f(self, val);
} else if std::env::var(CONFIGURED).is_ok() {
if let Some(raw) = read_var_if_not_default(env_var) {
return f(self, parser(&raw));
}
}
self
}
} }
impl<T> OptionalSet for T where T: NymConfig {} pub fn read_config_from_toml_file<C, P>(path: P) -> io::Result<C>
where
C: DeserializeOwned,
P: AsRef<Path>,
{
log::trace!(
"trying to read config file from {}",
path.as_ref().display()
);
let content = fs::read_to_string(path)?;
// TODO: should we be preserving original error type instead?
deserialize_config_from_toml_str(&content)
.map_err(|toml_err| io::Error::new(io::ErrorKind::Other, toml_err))
}
//
//
//
// pub trait NymConfig: Default + Serialize + DeserializeOwned {
// fn template() -> &'static str;
//
// fn config_file_name() -> String {
// "config.toml".to_string()
// }
//
// fn default_root_directory() -> PathBuf;
//
// // default, most probable, implementations; can be easily overridden where required
// fn default_config_directory(id: &str) -> PathBuf {
// Self::default_root_directory()
// .join(id)
// .join(DEFAULT_CONFIG_DIR)
// }
//
// fn default_data_directory(id: &str) -> PathBuf {
// Self::default_root_directory()
// .join(id)
// .join(DEFAULT_DATA_DIR)
// }
//
// fn default_config_file_path(id: &str) -> PathBuf {
// Self::default_config_directory(id).join(Self::config_file_name())
// }
//
// // We provide a second set of functions that tries to not panic.
//
// fn try_default_root_directory() -> Option<PathBuf>;
//
// fn try_default_config_directory(id: &str) -> Option<PathBuf> {
// Self::try_default_root_directory().map(|d| d.join(id).join(DEFAULT_CONFIG_DIR))
// }
//
// fn try_default_data_directory(id: &str) -> Option<PathBuf> {
// Self::try_default_root_directory().map(|d| d.join(id).join(DEFAULT_DATA_DIR))
// }
//
// fn try_default_config_file_path(id: &str) -> Option<PathBuf> {
// Self::try_default_config_directory(id).map(|d| d.join(Self::config_file_name()))
// }
//
// fn root_directory(&self) -> PathBuf;
// fn config_directory(&self) -> PathBuf;
// fn data_directory(&self) -> PathBuf;
//
// fn save_to_file(&self, custom_location: Option<PathBuf>) -> io::Result<()> {
// Ok(())
// // let reg = Handlebars::new();
// // // it's whoever is implementing the trait responsibility to make sure you can execute your own template on your data
// // let templated_config = reg.render_template(Self::template(), self).unwrap();
// //
// // // make sure the whole directory structure actually exists
// // match custom_location.clone() {
// // Some(loc) => {
// // if let Some(parent_dir) = loc.parent() {
// // fs::create_dir_all(parent_dir)
// // } else {
// // Ok(())
// // }
// // }
// // None => fs::create_dir_all(self.config_directory()),
// // }?;
// //
// // let location = custom_location
// // .unwrap_or_else(|| self.config_directory().join(Self::config_file_name()));
// // log::info!("Configuration file will be saved to {:?}", location);
// //
// // cfg_if::cfg_if! {
// // if #[cfg(unix)] {
// // fs::write(location.clone(), templated_config)?;
// // let mut perms = fs::metadata(location.clone())?.permissions();
// // perms.set_mode(0o600);
// // fs::set_permissions(location, perms)?;
// // } else {
// // fs::write(location, templated_config)?;
// // }
// // }
// //
// // Ok(())
// }
//
// fn load_from_file(id: &str) -> io::Result<Self> {
// let file = Self::default_config_file_path(id);
// log::trace!("Loading from file: {:#?}", file);
// let config_contents = fs::read_to_string(file)?;
//
// toml::from_str(&config_contents)
// .map_err(|toml_err| io::Error::new(io::ErrorKind::Other, toml_err))
// }
// }
@@ -1,6 +1,6 @@
[package] [package]
name = "nym-contracts-common" name = "nym-contracts-common"
version = "0.5.0" version = "0.4.0"
description = "Common library for Nym cosmwasm contracts" description = "Common library for Nym cosmwasm contracts"
edition = { workspace = true } edition = { workspace = true }
authors = { workspace = true } authors = { workspace = true }
@@ -11,9 +11,6 @@ use std::ops::Mul;
use std::str::FromStr; use std::str::FromStr;
use thiserror::Error; use thiserror::Error;
pub type IdentityKey = String;
pub type IdentityKeyRef<'a> = &'a str;
pub fn truncate_decimal(amount: Decimal) -> Uint128 { pub fn truncate_decimal(amount: Decimal) -> Uint128 {
amount * Uint128::new(1) amount * Uint128::new(1)
} }
@@ -1,6 +1,6 @@
[package] [package]
name = "nym-mixnet-contract-common" name = "nym-mixnet-contract-common"
version = "0.6.0" version = "0.5.0"
description = "Common library for the Nym mixnet contract" description = "Common library for the Nym mixnet contract"
rust-version = "1.62" rust-version = "1.62"
edition = { workspace = true } edition = { workspace = true }
@@ -15,7 +15,7 @@ serde = { version = "1.0", features = ["derive"] }
serde_repr = "0.1" serde_repr = "0.1"
schemars = "0.8" schemars = "0.8"
thiserror = "1.0" thiserror = "1.0"
contracts-common = { path = "../contracts-common", package = "nym-contracts-common", version = "0.5.0" } contracts-common = { path = "../contracts-common", package = "nym-contracts-common", version = "0.4.0" }
# use 0.4.1 as that's the version used by cosmwasm-std 1.0.0 # use 0.4.1 as that's the version used by cosmwasm-std 1.0.0
# (and ideally we don't want to pull the same dependency twice) # (and ideally we don't want to pull the same dependency twice)
serde-json-wasm = "=0.4.1" serde-json-wasm = "=0.4.1"
@@ -4,7 +4,6 @@
use crate::error::MixnetContractError; use crate::error::MixnetContractError;
use crate::families::{Family, FamilyHead}; use crate::families::{Family, FamilyHead};
use crate::{Layer, RewardedSetNodeStatus}; use crate::{Layer, RewardedSetNodeStatus};
use contracts_common::IdentityKey;
use cosmwasm_std::Addr; use cosmwasm_std::Addr;
use cosmwasm_std::Coin; use cosmwasm_std::Coin;
use schemars::JsonSchema; use schemars::JsonSchema;
@@ -12,6 +11,8 @@ use serde::{Deserialize, Serialize};
use std::ops::Index; use std::ops::Index;
// type aliases for better reasoning about available data // type aliases for better reasoning about available data
pub type IdentityKey = String;
pub type IdentityKeyRef<'a> = &'a str;
pub type SphinxKey = String; pub type SphinxKey = String;
pub type SphinxKeyRef<'a> = &'a str; pub type SphinxKeyRef<'a> = &'a str;
pub type EpochId = u32; pub type EpochId = u32;
@@ -7,9 +7,5 @@ edition = "2021"
[dependencies] [dependencies]
cosmwasm-std = { workspace = true } cosmwasm-std = { workspace = true }
nym-contracts-common = { path = "../contracts-common", version = "0.5.0" }
schemars = "0.8" schemars = "0.8"
serde = { workspace = true, features = ["derive"] } serde = { workspace = true, features = ["derive"] }
thiserror = { workspace = true }
cw-utils = { workspace = true }
cw-controllers = { workspace = true }
@@ -39,16 +39,16 @@ pub fn new_announce_event(service_id: ServiceId, service: Service) -> Event {
Event::new(ServiceProviderEventType::Announce) Event::new(ServiceProviderEventType::Announce)
.add_attribute(ACTION, ServiceProviderEventType::Announce) .add_attribute(ACTION, ServiceProviderEventType::Announce)
.add_attribute(SERVICE_ID, service_id.to_string()) .add_attribute(SERVICE_ID, service_id.to_string())
.add_attribute(SERVICE_TYPE, service.service.service_type.to_string()) .add_attribute(SERVICE_TYPE, service.service_type.to_string())
.add_attribute(NYM_ADDRESS, service.service.nym_address.to_string()) .add_attribute(NYM_ADDRESS, service.nym_address.to_string())
.add_attribute(OWNER, service.announcer.to_string()) .add_attribute(OWNER, service.announcer.to_string())
} }
pub fn new_delete_id_event(service: Service) -> Event { pub fn new_delete_id_event(service_id: ServiceId, service: Service) -> Event {
Event::new(ServiceProviderEventType::DeleteId) Event::new(ServiceProviderEventType::DeleteId)
.add_attribute(ACTION, ServiceProviderEventType::DeleteId) .add_attribute(ACTION, ServiceProviderEventType::DeleteId)
.add_attribute(SERVICE_ID, service.service_id.to_string()) .add_attribute(SERVICE_ID, service_id.to_string())
.add_attribute(NYM_ADDRESS, service.service.nym_address.to_string()) .add_attribute(NYM_ADDRESS, service.nym_address.to_string())
} }
pub fn new_update_deposit_required_event(deposit_required: Coin) -> Event { pub fn new_update_deposit_required_event(deposit_required: Coin) -> Event {
@@ -1,8 +1,6 @@
pub mod error;
pub mod events; pub mod events;
pub mod msg; pub mod msg;
pub mod response; pub mod response;
pub mod signing_types;
pub mod types; pub mod types;
// Re-export all types at the top-level // Re-export all types at the top-level
@@ -1,6 +1,5 @@
use crate::{NymAddress, ServiceDetails, ServiceId}; use crate::{NymAddress, ServiceId, ServiceType};
use cosmwasm_std::Coin; use cosmwasm_std::Coin;
use nym_contracts_common::signing::MessageSignature;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)] #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
@@ -23,8 +22,8 @@ pub struct MigrateMsg {}
#[serde(rename_all = "snake_case")] #[serde(rename_all = "snake_case")]
pub enum ExecuteMsg { pub enum ExecuteMsg {
Announce { Announce {
service: ServiceDetails, nym_address: NymAddress,
owner_signature: MessageSignature, service_type: ServiceType,
}, },
DeleteId { DeleteId {
service_id: ServiceId, service_id: ServiceId,
@@ -45,12 +44,9 @@ impl ExecuteMsg {
pub fn default_memo(&self) -> String { pub fn default_memo(&self) -> String {
match self { match self {
ExecuteMsg::Announce { ExecuteMsg::Announce {
service, nym_address,
owner_signature: _, service_type,
} => format!( } => format!("announcing {nym_address} as type {service_type}"),
"announcing {} as type {}",
service.nym_address, service.service_type
),
ExecuteMsg::DeleteId { service_id } => { ExecuteMsg::DeleteId { service_id } => {
format!("deleting service with service id {service_id}") format!("deleting service with service id {service_id}")
} }
@@ -80,9 +76,6 @@ pub enum QueryMsg {
limit: Option<u32>, limit: Option<u32>,
start_after: Option<ServiceId>, start_after: Option<ServiceId>,
}, },
SigningNonce {
address: String,
},
Config {}, Config {},
GetContractVersion {}, GetContractVersion {},
#[serde(rename = "get_cw2_contract_version")] #[serde(rename = "get_cw2_contract_version")]
@@ -1,4 +1,4 @@
use crate::{Service, ServiceId}; use crate::{msg::ExecuteMsg, Service, ServiceId, ServiceInfo};
use cosmwasm_std::Coin; use cosmwasm_std::Coin;
use schemars::JsonSchema; use schemars::JsonSchema;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@@ -13,17 +13,22 @@ pub struct ServiceInfoResponse {
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone, JsonSchema)] #[derive(Serialize, Deserialize, PartialEq, Debug, Clone, JsonSchema)]
#[serde(rename_all = "snake_case")] #[serde(rename_all = "snake_case")]
pub struct ServicesListResponse { pub struct ServicesListResponse {
pub services: Vec<Service>, pub services: Vec<ServiceInfo>,
} }
impl ServicesListResponse { impl ServicesListResponse {
pub fn new(services: Vec<Service>) -> ServicesListResponse { pub fn new(services: Vec<(ServiceId, Service)>) -> ServicesListResponse {
ServicesListResponse { services } ServicesListResponse {
services: services
.into_iter()
.map(|(service_id, service)| ServiceInfo::new(service_id, service))
.collect(),
}
} }
} }
impl From<&[Service]> for ServicesListResponse { impl From<&[ServiceInfo]> for ServicesListResponse {
fn from(services: &[Service]) -> Self { fn from(services: &[ServiceInfo]) -> Self {
Self { Self {
services: services.to_vec(), services: services.to_vec(),
} }
@@ -33,17 +38,21 @@ impl From<&[Service]> for ServicesListResponse {
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)] #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
#[serde(rename_all = "snake_case")] #[serde(rename_all = "snake_case")]
pub struct PagedServicesListResponse { pub struct PagedServicesListResponse {
pub services: Vec<Service>, pub services: Vec<ServiceInfo>,
pub per_page: usize, pub per_page: usize,
pub start_next_after: Option<ServiceId>, pub start_next_after: Option<ServiceId>,
} }
impl PagedServicesListResponse { impl PagedServicesListResponse {
pub fn new( pub fn new(
services: Vec<Service>, services: Vec<(ServiceId, Service)>,
per_page: usize, per_page: usize,
start_next_after: Option<ServiceId>, start_next_after: Option<ServiceId>,
) -> PagedServicesListResponse { ) -> PagedServicesListResponse {
let services = services
.into_iter()
.map(|(service_id, service)| ServiceInfo::new(service_id, service))
.collect();
PagedServicesListResponse { PagedServicesListResponse {
services, services,
per_page, per_page,
@@ -57,3 +66,12 @@ impl PagedServicesListResponse {
pub struct ConfigResponse { pub struct ConfigResponse {
pub deposit_required: Coin, pub deposit_required: Coin,
} }
impl From<Service> for ExecuteMsg {
fn from(service: Service) -> Self {
ExecuteMsg::Announce {
nym_address: service.nym_address,
service_type: service.service_type,
}
}
}
@@ -1,33 +0,0 @@
use cosmwasm_std::{Addr, Coin};
use nym_contracts_common::signing::{
ContractMessageContent, MessageType, Nonce, SignableMessage, SigningPurpose,
};
use serde::Serialize;
use crate::ServiceDetails;
pub type SignableServiceProviderAnnounceMsg =
SignableMessage<ContractMessageContent<ServiceProviderAnnounce>>;
#[derive(Serialize)]
pub struct ServiceProviderAnnounce {
service: ServiceDetails,
}
impl SigningPurpose for ServiceProviderAnnounce {
fn message_type() -> MessageType {
MessageType::new("service-provider-announce")
}
}
pub fn construct_service_provider_announce_sign_payload(
nonce: Nonce,
sender: Addr,
deposit: Coin,
service: ServiceDetails,
) -> SignableServiceProviderAnnounceMsg {
let payload = ServiceProviderAnnounce { service };
let proxy = None;
let content = ContractMessageContent::new(sender, proxy, vec![deposit], payload);
SignableMessage::new(nonce, content)
}
@@ -1,7 +1,6 @@
use std::fmt::{Display, Formatter}; use std::fmt::{Display, Formatter};
use cosmwasm_std::{Addr, Coin}; use cosmwasm_std::{Addr, Coin};
use nym_contracts_common::IdentityKey;
use schemars::JsonSchema; use schemars::JsonSchema;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@@ -10,11 +9,11 @@ pub type ServiceId = u32;
#[derive(Serialize, Deserialize, Clone, PartialEq, Debug, JsonSchema)] #[derive(Serialize, Deserialize, Clone, PartialEq, Debug, JsonSchema)]
pub struct Service { pub struct Service {
/// Unique id assigned to the anounced service. /// The address of the service.
pub service_id: ServiceId, pub nym_address: NymAddress,
/// The announced service. /// The service type.
pub service: ServiceDetails, pub service_type: ServiceType,
/// Address of the service owner. /// Service owner.
pub announcer: Addr, pub announcer: Addr,
/// Block height at which the service was added. /// Block height at which the service was added.
pub block_height: u64, pub block_height: u64,
@@ -22,16 +21,6 @@ pub struct Service {
pub deposit: Coin, pub deposit: Coin,
} }
#[derive(Serialize, Deserialize, Clone, PartialEq, Debug, JsonSchema)]
pub struct ServiceDetails {
/// The address of the service.
pub nym_address: NymAddress,
/// The service type.
pub service_type: ServiceType,
/// The identity key of the service.
pub identity_key: IdentityKey,
}
/// The types of addresses supported. /// The types of addresses supported.
#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug, JsonSchema)] #[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug, JsonSchema)]
#[serde(rename_all = "snake_case")] #[serde(rename_all = "snake_case")]
@@ -39,7 +28,7 @@ pub enum NymAddress {
/// String representation of a nym address, which is of the form /// String representation of a nym address, which is of the form
/// client_id.client_enc@gateway_id. /// client_id.client_enc@gateway_id.
Address(String), Address(String),
// String name that can looked up in the nym-name-service contract (once it exists) // For the future when we have a nym-dns contract
//Name(String), //Name(String),
} }
@@ -52,7 +41,6 @@ impl NymAddress {
pub fn as_str(&self) -> &str { pub fn as_str(&self) -> &str {
match self { match self {
NymAddress::Address(address) => address, NymAddress::Address(address) => address,
//NymAddress::Name(name) => name,
} }
} }
} }
@@ -78,3 +66,19 @@ impl std::fmt::Display for ServiceType {
write!(f, "{service_type}") write!(f, "{service_type}")
} }
} }
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub struct ServiceInfo {
pub service_id: ServiceId,
pub service: Service,
}
impl ServiceInfo {
pub fn new(service_id: ServiceId, service: Service) -> Self {
Self {
service_id,
service,
}
}
}
@@ -1,6 +1,6 @@
[package] [package]
name = "nym-vesting-contract-common" name = "nym-vesting-contract-common"
version = "0.7.0" version = "0.6.0"
description = "Common library for the Nym vesting contract" description = "Common library for the Nym vesting contract"
edition = { workspace = true } edition = { workspace = true }
authors = { workspace = true } authors = { workspace = true }
@@ -9,8 +9,8 @@ repository = { workspace = true }
[dependencies] [dependencies]
cosmwasm-std = { workspace = true } cosmwasm-std = { workspace = true }
mixnet-contract-common = { path = "../mixnet-contract", package = "nym-mixnet-contract-common", version = "0.6.0" } mixnet-contract-common = { path = "../mixnet-contract", package = "nym-mixnet-contract-common", version = "0.5.0" }
contracts-common = { path = "../contracts-common", package = "nym-contracts-common", version = "0.5.0" } contracts-common = { path = "../contracts-common", package = "nym-contracts-common", version = "0.4.0" }
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
schemars = "0.8" schemars = "0.8"
ts-rs = {version = "6.1.2", optional = true} ts-rs = {version = "6.1.2", optional = true}
+4 -1
View File
@@ -4,8 +4,11 @@
*/ */
use crate::ephemeral_storage::EphemeralStorage; use crate::ephemeral_storage::EphemeralStorage;
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
use crate::persistent_storage::PersistentStorage; use crate::persistent_storage::PersistentStorage;
#[cfg(not(target_arch = "wasm32"))]
use std::path::Path;
mod backends; mod backends;
pub mod ephemeral_storage; pub mod ephemeral_storage;
@@ -16,7 +19,7 @@ pub mod persistent_storage;
pub mod storage; pub mod storage;
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
pub async fn initialise_persistent_storage(path: std::path::PathBuf) -> PersistentStorage { pub async fn initialise_persistent_storage<P: AsRef<Path>>(path: P) -> PersistentStorage {
match persistent_storage::PersistentStorage::init(path).await { match persistent_storage::PersistentStorage::init(path).await {
Err(err) => panic!("failed to initialise credential storage - {err}"), Err(err) => panic!("failed to initialise credential storage - {err}"),
Ok(storage) => storage, Ok(storage) => storage,
@@ -23,7 +23,7 @@ impl PersistentStorage {
/// # Arguments /// # Arguments
/// ///
/// * `database_path`: path to the database. /// * `database_path`: path to the database.
pub async fn init<P: AsRef<Path> + Send>(database_path: P) -> Result<Self, StorageError> { pub async fn init<P: AsRef<Path>>(database_path: P) -> Result<Self, StorageError> {
debug!( debug!(
"Attempting to connect to database {:?}", "Attempting to connect to database {:?}",
database_path.as_ref().as_os_str() database_path.as_ref().as_os_str()
+2 -2
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "nym-crypto" name = "nym-crypto"
version = "0.4.0" version = "0.3.0"
description = "Crypto library for the nym mixnet" description = "Crypto library for the nym mixnet"
edition = { workspace = true } edition = { workspace = true }
authors = { workspace = true } authors = { workspace = true }
@@ -28,7 +28,7 @@ zeroize = { workspace = true, optional = true, features = ["zeroize_derive"] }
# internal # internal
nym-sphinx-types = { path = "../nymsphinx/types", version = "0.2.0" } nym-sphinx-types = { path = "../nymsphinx/types", version = "0.2.0" }
nym-pemstore = { path = "../../common/pemstore", version = "0.3.0" } nym-pemstore = { path = "../../common/pemstore", version = "0.2.0" }
[dev-dependencies] [dev-dependencies]
rand_chacha = "0.2" rand_chacha = "0.2"
-549
View File
@@ -1,549 +0,0 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
// This should be modified whenever an updated Ethereum contract is uploaded
pub const ETH_JSON_ABI: &str = r#"
[
{
"inputs": [
{
"internalType": "contract CosmosERC20",
"name": "_erc20",
"type": "address"
},
{
"internalType": "contract Gravity",
"name": "_gravityBridge",
"type": "address"
}
],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "uint256",
"name": "Bandwidth",
"type": "uint256"
},
{
"indexed": true,
"internalType": "uint256",
"name": "VerificationKey",
"type": "uint256"
},
{
"indexed": false,
"internalType": "bytes",
"name": "SignedVerificationKey",
"type": "bytes"
},
{
"indexed": false,
"internalType": "string",
"name": "CosmosRecipient",
"type": "string"
}
],
"name": "BBCredentialPurchased",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "bool",
"name": "Enabled",
"type": "bool"
}
],
"name": "CredentialGenerationSwitch",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "previousOwner",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "newOwner",
"type": "address"
}
],
"name": "OwnershipTransferred",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "uint256",
"name": "NewBytesPerToken",
"type": "uint256"
}
],
"name": "RatioChanged",
"type": "event"
},
{
"inputs": [],
"name": "BytesPerToken",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "_amount",
"type": "uint256"
}
],
"name": "bandwidthFromToken",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "_newBytesPerTokenAmount",
"type": "uint256"
}
],
"name": "changeRatio",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "credentialGenerationEnabled",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "bool",
"name": "_generation",
"type": "bool"
}
],
"name": "credentialGenerationSwitch",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "erc20",
"outputs": [
{
"internalType": "contract CosmosERC20",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "_amount",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "_verificationKey",
"type": "uint256"
},
{
"internalType": "bytes",
"name": "_signedVerificationKey",
"type": "bytes"
},
{
"internalType": "string",
"name": "_cosmosRecipient",
"type": "string"
}
],
"name": "generateBasicBandwidthCredential",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "gravityBridge",
"outputs": [
{
"internalType": "contract Gravity",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "owner",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "renounceOwnership",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "newOwner",
"type": "address"
}
],
"name": "transferOwnership",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
}
]
"#;
pub const ETH_ERC20_JSON_ABI: &str = r#"
[
{
"inputs": [
{
"internalType": "string",
"name": "name_",
"type": "string"
},
{
"internalType": "string",
"name": "symbol_",
"type": "string"
}
],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "owner",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "spender",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
"name": "value",
"type": "uint256"
}
],
"name": "Approval",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "from",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "to",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
"name": "value",
"type": "uint256"
}
],
"name": "Transfer",
"type": "event"
},
{
"inputs": [
{
"internalType": "address",
"name": "owner",
"type": "address"
},
{
"internalType": "address",
"name": "spender",
"type": "address"
}
],
"name": "allowance",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "spender",
"type": "address"
},
{
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"name": "approve",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "account",
"type": "address"
}
],
"name": "balanceOf",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "decimals",
"outputs": [
{
"internalType": "uint8",
"name": "",
"type": "uint8"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "spender",
"type": "address"
},
{
"internalType": "uint256",
"name": "subtractedValue",
"type": "uint256"
}
],
"name": "decreaseAllowance",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "spender",
"type": "address"
},
{
"internalType": "uint256",
"name": "addedValue",
"type": "uint256"
}
],
"name": "increaseAllowance",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "name",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "symbol",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "totalSupply",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "recipient",
"type": "address"
},
{
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"name": "transfer",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "sender",
"type": "address"
},
{
"internalType": "address",
"name": "recipient",
"type": "address"
},
{
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"name": "transferFrom",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "nonpayable",
"type": "function"
}
]
"#;
+2 -2
View File
@@ -25,12 +25,12 @@ nym-sphinx-types = { path = "types" }
# those dependencies are due to intriducing preparer and receiver. Perpaphs that indicates they should be moved # those dependencies are due to intriducing preparer and receiver. Perpaphs that indicates they should be moved
# to separate crate? # to separate crate?
nym-crypto = { path = "../crypto", version = "0.4.0" } nym-crypto = { path = "../crypto", version = "0.3.0" }
nym-topology = { path = "../topology" } nym-topology = { path = "../topology" }
[dev-dependencies] [dev-dependencies]
nym-mixnet-contract-common = { path = "../cosmwasm-smart-contracts/mixnet-contract" } nym-mixnet-contract-common = { path = "../cosmwasm-smart-contracts/mixnet-contract" }
nym-crypto = { path = "../crypto", version = "0.4.0", features = ["asymmetric"] } nym-crypto = { path = "../crypto", version = "0.3.0", features = ["asymmetric"] }
# do not include this when compiling into wasm as it somehow when combined together with reqwest, it will require # do not include this when compiling into wasm as it somehow when combined together with reqwest, it will require
# net2 via tokio-util -> tokio -> mio -> net2 # net2 via tokio-util -> tokio -> mio -> net2
@@ -58,6 +58,7 @@ impl SurbAck {
let packet_size = match packet_type { let packet_size = match packet_type {
PacketType::Outfox => surb_ack_payload.len().max(MIN_PACKET_SIZE), PacketType::Outfox => surb_ack_payload.len().max(MIN_PACKET_SIZE),
PacketType::Mix => PacketSize::AckPacket.payload_size(), PacketType::Mix => PacketSize::AckPacket.payload_size(),
#[allow(deprecated)]
PacketType::Vpn => PacketSize::AckPacket.payload_size(), PacketType::Vpn => PacketSize::AckPacket.payload_size(),
}; };
@@ -75,6 +76,7 @@ impl SurbAck {
&destination, &destination,
&delays, &delays,
)?, )?,
#[allow(deprecated)]
PacketType::Vpn => NymPacket::sphinx_build( PacketType::Vpn => NymPacket::sphinx_build(
packet_size, packet_size,
surb_ack_payload, surb_ack_payload,
@@ -105,6 +107,7 @@ impl SurbAck {
PacketSize::OutfoxAckPacket.size() + MAX_NODE_ADDRESS_UNPADDED_LEN PacketSize::OutfoxAckPacket.size() + MAX_NODE_ADDRESS_UNPADDED_LEN
} }
PacketType::Mix => PacketSize::AckPacket.size() + MAX_NODE_ADDRESS_UNPADDED_LEN, PacketType::Mix => PacketSize::AckPacket.size() + MAX_NODE_ADDRESS_UNPADDED_LEN,
#[allow(deprecated)]
PacketType::Vpn => PacketSize::AckPacket.size() + MAX_NODE_ADDRESS_UNPADDED_LEN, PacketType::Vpn => PacketSize::AckPacket.size() + MAX_NODE_ADDRESS_UNPADDED_LEN,
} }
} }
@@ -137,6 +140,7 @@ impl SurbAck {
let packet = match packet_type { let packet = match packet_type {
PacketType::Outfox => NymPacket::outfox_from_bytes(&b[address_offset..])?, PacketType::Outfox => NymPacket::outfox_from_bytes(&b[address_offset..])?,
PacketType::Mix => NymPacket::sphinx_from_bytes(&b[address_offset..])?, PacketType::Mix => NymPacket::sphinx_from_bytes(&b[address_offset..])?,
#[allow(deprecated)]
PacketType::Vpn => NymPacket::sphinx_from_bytes(&b[address_offset..])?, PacketType::Vpn => NymPacket::sphinx_from_bytes(&b[address_offset..])?,
}; };
+1
View File
@@ -85,6 +85,7 @@ impl Decoder for NymCodec {
match header.packet_type { match header.packet_type {
PacketType::Outfox => NymPacket::outfox_from_bytes(slice)?, PacketType::Outfox => NymPacket::outfox_from_bytes(slice)?,
PacketType::Mix => NymPacket::sphinx_from_bytes(slice)?, PacketType::Mix => NymPacket::sphinx_from_bytes(slice)?,
#[allow(deprecated)]
PacketType::Vpn => NymPacket::sphinx_from_bytes(slice)?, PacketType::Vpn => NymPacket::sphinx_from_bytes(slice)?,
} }
} else { } else {
@@ -244,6 +244,7 @@ impl PacketSize {
) -> Result<Self, InvalidPacketSize> { ) -> Result<Self, InvalidPacketSize> {
let overhead = match packet_type { let overhead = match packet_type {
PacketType::Mix => SPHINX_PACKET_OVERHEAD, PacketType::Mix => SPHINX_PACKET_OVERHEAD,
#[allow(deprecated)]
PacketType::Vpn => SPHINX_PACKET_OVERHEAD, PacketType::Vpn => SPHINX_PACKET_OVERHEAD,
PacketType::Outfox => OUTFOX_PACKET_OVERHEAD, PacketType::Outfox => OUTFOX_PACKET_OVERHEAD,
}; };
+11 -2
View File
@@ -1,13 +1,15 @@
// Copyright 2021-2022 - Nym Technologies SA <contact@nymtech.net> // Copyright 2021-2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
#![allow(deprecated)]
// allow the u8 repr of `Vpn` PacketType whilst deprecating all of its other uses
use crate::PacketSize;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::convert::TryFrom; use std::convert::TryFrom;
use std::fmt; use std::fmt;
use thiserror::Error; use thiserror::Error;
use crate::PacketSize;
#[derive(Error, Debug)] #[derive(Error, Debug)]
#[error("{received} is not a valid packet mode tag")] #[error("{received} is not a valid packet mode tag")]
pub struct InvalidPacketType { pub struct InvalidPacketType {
@@ -15,17 +17,23 @@ pub struct InvalidPacketType {
} }
#[repr(u8)] #[repr(u8)]
#[allow(deprecated)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Default, Serialize, Deserialize)] #[derive(Clone, Copy, Debug, PartialEq, Eq, Default, Serialize, Deserialize)]
pub enum PacketType { pub enum PacketType {
/// Represents 'normal' packet sent through the network that should be delayed by an appropriate /// Represents 'normal' packet sent through the network that should be delayed by an appropriate
/// value at each hop. /// value at each hop.
#[default] #[default]
#[serde(rename = "mix")]
#[serde(alias = "sphinx")]
Mix = 0, Mix = 0,
/// Represents a packet that should be sent through the network as fast as possible. /// Represents a packet that should be sent through the network as fast as possible.
#[deprecated]
#[serde(rename = "unsupported-mix-vpn")]
Vpn = 1, Vpn = 1,
/// Abusing this to add Outfox support /// Abusing this to add Outfox support
#[serde(rename = "outfox")]
Outfox = 2, Outfox = 2,
} }
@@ -33,6 +41,7 @@ impl fmt::Display for PacketType {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self { match self {
PacketType::Mix => write!(f, "Mix"), PacketType::Mix => write!(f, "Mix"),
#[allow(deprecated)]
PacketType::Vpn => write!(f, "Vpn"), PacketType::Vpn => write!(f, "Vpn"),
PacketType::Outfox => write!(f, "Outfox"), PacketType::Outfox => write!(f, "Outfox"),
} }
+1
View File
@@ -251,6 +251,7 @@ pub trait FragmentPreparer {
&destination, &destination,
&delays, &delays,
)?, )?,
#[allow(deprecated)]
PacketType::Vpn => NymPacket::sphinx_build( PacketType::Vpn => NymPacket::sphinx_build(
packet_size.payload_size(), packet_size.payload_size(),
packet_payload, packet_payload,
+1 -1
View File
@@ -1,7 +1,7 @@
[package] [package]
name = "nym-pemstore" name = "nym-pemstore"
description = "Store private-public keypairs in PEM format" description = "Store private-public keypairs in PEM format"
version = "0.3.0" version = "0.2.0"
edition = { workspace = true } edition = { workspace = true }
authors = { workspace = true } authors = { workspace = true }
license = { workspace = true } license = { workspace = true }
+32 -167
View File
@@ -1,88 +1,39 @@
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net> // Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use crate::config::template::config_template; pub use nym_client_core::config::Config as BaseClientConfig;
pub use nym_client_core::config::Config as BaseConfig;
pub use nym_client_core::config::MISSING_VALUE;
use nym_client_core::config::{ClientCoreConfigTrait, DebugConfig};
use nym_config::defaults::DEFAULT_SOCKS5_LISTENING_PORT; use nym_config::defaults::DEFAULT_SOCKS5_LISTENING_PORT;
use nym_config::{NymConfig, OptionalSet}; use nym_config::OptionalSet;
use nym_service_providers_common::interface::ProviderInterfaceVersion;
use nym_socks5_requests::Socks5ProtocolVersion;
use nym_sphinx::addressing::clients::Recipient; use nym_sphinx::addressing::clients::Recipient;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::fmt::Debug; use std::fmt::Debug;
use std::path::{Path, PathBuf};
use std::str::FromStr; use std::str::FromStr;
pub mod old_config_v1_1_13; pub use nym_service_providers_common::interface::ProviderInterfaceVersion;
mod template; pub use nym_socks5_requests::Socks5ProtocolVersion;
const DEFAULT_CONNECTION_START_SURBS: u32 = 20; const DEFAULT_CONNECTION_START_SURBS: u32 = 20;
const DEFAULT_PER_REQUEST_SURBS: u32 = 3; const DEFAULT_PER_REQUEST_SURBS: u32 = 3;
#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize)] #[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
#[serde(deny_unknown_fields)] #[serde(deny_unknown_fields)]
pub struct Config { pub struct Config {
#[serde(flatten)] #[serde(flatten)]
base: BaseConfig<Config>, pub base: BaseClientConfig,
socks5: Socks5, pub socks5: Socks5,
}
impl NymConfig for Config {
fn template() -> &'static str {
config_template()
}
fn default_root_directory() -> PathBuf {
#[cfg(not(any(target_os = "android", target_os = "ios")))]
let base_dir = dirs::home_dir().expect("Failed to evaluate $HOME value");
#[cfg(any(target_os = "android", target_os = "ios"))]
let base_dir = PathBuf::from("/tmp");
base_dir.join(".nym").join("socks5-clients")
}
fn try_default_root_directory() -> Option<PathBuf> {
dirs::home_dir().map(|path| path.join(".nym").join("socks5-clients"))
}
fn root_directory(&self) -> PathBuf {
self.base.get_nym_root_directory()
}
fn config_directory(&self) -> PathBuf {
self.root_directory()
.join(self.base.get_id())
.join("config")
}
fn data_directory(&self) -> PathBuf {
self.root_directory().join(self.base.get_id()).join("data")
}
}
impl ClientCoreConfigTrait for Config {
fn get_gateway_endpoint(&self) -> &nym_client_core::config::GatewayEndpointConfig {
self.base.get_gateway_endpoint()
}
} }
impl Config { impl Config {
pub fn new<S: Into<String>>(id: S, provider_mix_address: S) -> Self { pub fn new<S: Into<String>>(id: S, provider_mix_address: S) -> Self {
Config { Config {
base: BaseConfig::new(id), base: BaseClientConfig::new(id),
socks5: Socks5::new(provider_mix_address), socks5: Socks5::new(provider_mix_address),
} }
} }
#[must_use] pub fn from_base(base: BaseClientConfig, socks5: Socks5) -> Self {
pub fn with_root_directory<P: AsRef<Path>>(mut self, root_dir: P) -> Self { Config { base, socks5 }
self.base = self.base.reset_nym_root_directory(root_dir);
let data_dir = self.data_directory();
self.base = self.base.reset_data_directory(data_dir);
self
} }
pub fn validate(&self) -> bool { pub fn validate(&self) -> bool {
@@ -90,63 +41,38 @@ impl Config {
self.base.validate() self.base.validate()
} }
// getters pub fn with_port(mut self, port: u16) -> Self {
pub fn get_base(&self) -> &BaseConfig<Self> { self.socks5.listening_port = port;
&self.base self
} }
pub fn get_base_mut(&mut self) -> &mut BaseConfig<Self> { pub fn with_anonymous_replies(mut self, anonymous_replies: bool) -> Self {
&mut self.base self.socks5.send_anonymously = anonymous_replies;
} self
pub fn get_socks5(&self) -> &Socks5 {
&self.socks5
}
pub fn get_socks5_mut(&mut self) -> &mut Socks5 {
&mut self.socks5
}
pub fn get_debug_settings(&self) -> &DebugConfig {
self.get_base().get_debug_config()
}
pub fn get_config_file_save_location(&self) -> PathBuf {
self.config_directory().join(Self::config_file_name())
} }
// poor man's 'builder' method // poor man's 'builder' method
pub fn with_base<F, T>(mut self, f: F, val: T) -> Self pub fn with_base<F, T>(mut self, f: F, val: T) -> Self
where where
F: Fn(BaseConfig<Self>, T) -> BaseConfig<Self>, F: Fn(BaseClientConfig, T) -> BaseClientConfig,
{ {
self.base = f(self.base, val); self.base = f(self.base, val);
self self
} }
pub fn with_port(mut self, port: u16) -> Self {
self.socks5.with_port(port);
self
}
pub fn with_anonymous_replies(mut self, anonymous_replies: bool) -> Self {
self.socks5.with_anonymous_replies(anonymous_replies);
self
}
// helper methods to use `OptionalSet` trait. Those are defined due to very... ehm. 'specific' structure of this config // helper methods to use `OptionalSet` trait. Those are defined due to very... ehm. 'specific' structure of this config
// (plz, lets refactor it) // (plz, lets refactor it)
pub fn with_optional_ext<F, T>(mut self, f: F, val: Option<T>) -> Self pub fn with_optional_base<F, T>(mut self, f: F, val: Option<T>) -> Self
where where
F: Fn(BaseConfig<Self>, T) -> BaseConfig<Self>, F: Fn(BaseClientConfig, T) -> BaseClientConfig,
{ {
self.base = self.base.with_optional(f, val); self.base = self.base.with_optional(f, val);
self self
} }
pub fn with_optional_env_ext<F, T>(mut self, f: F, val: Option<T>, env_var: &str) -> Self pub fn with_optional_base_env<F, T>(mut self, f: F, val: Option<T>, env_var: &str) -> Self
where where
F: Fn(BaseConfig<Self>, T) -> BaseConfig<Self>, F: Fn(BaseClientConfig, T) -> BaseClientConfig,
T: FromStr, T: FromStr,
<T as FromStr>::Err: Debug, <T as FromStr>::Err: Debug,
{ {
@@ -154,7 +80,7 @@ impl Config {
self self
} }
pub fn with_optional_custom_env_ext<F, T, G>( pub fn with_optional_base_custom_env<F, T, G>(
mut self, mut self,
f: F, f: F,
val: Option<T>, val: Option<T>,
@@ -162,7 +88,7 @@ impl Config {
parser: G, parser: G,
) -> Self ) -> Self
where where
F: Fn(BaseConfig<Self>, T) -> BaseConfig<Self>, F: Fn(BaseClientConfig, T) -> BaseClientConfig,
G: Fn(&str) -> T, G: Fn(&str) -> T,
{ {
self.base = self.base.with_optional_custom_env(f, val, env_var, parser); self.base = self.base.with_optional_custom_env(f, val, env_var, parser);
@@ -174,19 +100,19 @@ impl Config {
#[serde(deny_unknown_fields)] #[serde(deny_unknown_fields)]
pub struct Socks5 { pub struct Socks5 {
/// The port on which the client will be listening for incoming requests /// The port on which the client will be listening for incoming requests
listening_port: u16, pub listening_port: u16,
/// The mix address of the provider to which all requests are going to be sent. /// The mix address of the provider to which all requests are going to be sent.
provider_mix_address: String, pub provider_mix_address: String,
/// The version of the 'service provider' this client is going to use in its communication with the /// The version of the 'service provider' this client is going to use in its communication with the
/// specified socks5 provider. /// specified socks5 provider.
// if in doubt, use the legacy version as initially nobody will be using the updated binaries // if in doubt, use the legacy version as initially nobody will be using the updated binaries
#[serde(default = "ProviderInterfaceVersion::new_legacy")] #[serde(default = "ProviderInterfaceVersion::new_legacy")]
provider_interface_version: ProviderInterfaceVersion, pub provider_interface_version: ProviderInterfaceVersion,
#[serde(default = "Socks5ProtocolVersion::new_legacy")] #[serde(default = "Socks5ProtocolVersion::new_legacy")]
socks5_protocol_version: Socks5ProtocolVersion, pub socks5_protocol_version: Socks5ProtocolVersion,
/// Specifies whether this client is going to use an anonymous sender tag for communication with the service provider. /// 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 /// While this is going to hide its actual address information, it will make the actual communication
@@ -194,10 +120,10 @@ pub struct Socks5 {
/// ///
/// Note that some service providers might not support this. /// Note that some service providers might not support this.
#[serde(default)] #[serde(default)]
send_anonymously: bool, pub send_anonymously: bool,
#[serde(default)] #[serde(default)]
socks5_debug: Socks5Debug, pub socks5_debug: Socks5Debug,
} }
impl Socks5 { impl Socks5 {
@@ -212,81 +138,20 @@ impl Socks5 {
} }
} }
pub fn with_port(&mut self, port: u16) {
self.listening_port = port;
}
pub fn with_provider_mix_address(&mut self, address: String) {
self.provider_mix_address = address;
}
pub fn with_provider_interface_version(&mut self, version: ProviderInterfaceVersion) {
self.provider_interface_version = version;
}
pub fn with_socks5_protocol_version(&mut self, version: Socks5ProtocolVersion) {
self.socks5_protocol_version = version;
}
pub fn with_anonymous_replies(&mut self, anonymous_replies: bool) {
self.send_anonymously = anonymous_replies;
}
pub fn get_raw_provider_mix_address(&self) -> String {
self.provider_mix_address.clone()
}
pub fn get_provider_mix_address(&self) -> Recipient { pub fn get_provider_mix_address(&self) -> Recipient {
Recipient::try_from_base58_string(&self.provider_mix_address) Recipient::try_from_base58_string(&self.provider_mix_address)
.expect("malformed provider address") .expect("malformed provider address")
} }
pub fn get_provider_interface_version(&self) -> ProviderInterfaceVersion {
self.provider_interface_version
}
pub fn get_socks5_protocol_version(&self) -> Socks5ProtocolVersion {
self.socks5_protocol_version
}
pub fn get_send_anonymously(&self) -> bool {
self.send_anonymously
}
pub fn get_listening_port(&self) -> u16 {
self.listening_port
}
pub fn get_connection_start_surbs(&self) -> u32 {
self.socks5_debug.connection_start_surbs
}
pub fn get_per_request_surbs(&self) -> u32 {
self.socks5_debug.per_request_surbs
}
} }
impl Default for Socks5 { #[derive(Clone, Copy, Debug, Deserialize, PartialEq, Eq, Serialize)]
fn default() -> Self {
Socks5 {
listening_port: DEFAULT_SOCKS5_LISTENING_PORT,
provider_mix_address: "".into(),
provider_interface_version: ProviderInterfaceVersion::Legacy,
socks5_protocol_version: Socks5ProtocolVersion::Legacy,
send_anonymously: false,
socks5_debug: Default::default(),
}
}
}
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)]
#[serde(deny_unknown_fields)] #[serde(deny_unknown_fields)]
pub struct Socks5Debug { pub struct Socks5Debug {
/// Number of reply SURBs attached to each `Request::Connect` message. /// Number of reply SURBs attached to each `Request::Connect` message.
connection_start_surbs: u32, pub connection_start_surbs: u32,
/// Number of reply SURBs attached to each `Request::Send` message. /// Number of reply SURBs attached to each `Request::Send` message.
per_request_surbs: u32, pub per_request_surbs: u32,
} }
impl Default for Socks5Debug { impl Default for Socks5Debug {
@@ -3,60 +3,60 @@
use crate::config::{Config, Socks5}; use crate::config::{Config, Socks5};
use nym_client_core::config::old_config_v1_1_13::OldConfigV1_1_13 as OldBaseConfigV1_1_13; use nym_client_core::config::old_config_v1_1_13::OldConfigV1_1_13 as OldBaseConfigV1_1_13;
use nym_config::NymConfig;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::path::PathBuf; use std::path::PathBuf;
#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize)] // #[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
#[serde(deny_unknown_fields)] // #[serde(deny_unknown_fields)]
pub struct OldConfigV1_1_13 { // pub struct OldConfigV1_1_13 {
#[serde(flatten)] // #[serde(flatten)]
base: OldBaseConfigV1_1_13<OldConfigV1_1_13>, // base: OldBaseConfigV1_1_13<OldConfigV1_1_13>,
//
socks5: Socks5, // socks5: Socks5,
} // }
//
impl NymConfig for OldConfigV1_1_13 { // //
fn template() -> &'static str { // // impl NymConfig for OldConfigV1_1_13 {
// not intended to be used // // fn template() -> &'static str {
unimplemented!() // // // not intended to be used
} // // unimplemented!()
// // }
fn default_root_directory() -> PathBuf { // //
#[cfg(not(any(target_os = "android", target_os = "ios")))] // // fn default_root_directory() -> PathBuf {
let base_dir = dirs::home_dir().expect("Failed to evaluate $HOME value"); // // #[cfg(not(target_os = "android"))]
#[cfg(any(target_os = "android", target_os = "ios"))] // // let base_dir = dirs::home_dir().expect("Failed to evaluate $HOME value");
let base_dir = PathBuf::from("/tmp"); // // #[cfg(target_os = "android")]
// // let base_dir = PathBuf::from("/tmp");
base_dir.join(".nym").join("socks5-clients") // //
} // // base_dir.join(".nym").join("socks5-clients")
// // }
fn try_default_root_directory() -> Option<PathBuf> { // //
dirs::home_dir().map(|path| path.join(".nym").join("socks5-clients")) // // fn try_default_root_directory() -> Option<PathBuf> {
} // // dirs::home_dir().map(|path| path.join(".nym").join("socks5-clients"))
// // }
fn root_directory(&self) -> PathBuf { // //
self.base.client.nym_root_directory.clone() // // fn root_directory(&self) -> PathBuf {
} // // self.base.client.nym_root_directory.clone()
// // }
fn config_directory(&self) -> PathBuf { // //
self.root_directory() // // fn config_directory(&self) -> PathBuf {
.join(&self.base.client.id) // // self.root_directory()
.join("config") // // .join(&self.base.client.id)
} // // .join("config")
// // }
fn data_directory(&self) -> PathBuf { // //
self.root_directory() // // fn data_directory(&self) -> PathBuf {
.join(&self.base.client.id) // // self.root_directory()
.join("data") // // .join(&self.base.client.id)
} // // .join("data")
} // // }
// // }
impl From<OldConfigV1_1_13> for Config { //
fn from(value: OldConfigV1_1_13) -> Self { // impl From<OldConfigV1_1_13> for Config {
Config { // fn from(value: OldConfigV1_1_13) -> Self {
base: value.base.into(), // Config {
socks5: value.socks5, // base: value.base.into(),
} // socks5: value.socks5,
} // }
} // }
// }
+19 -23
View File
@@ -1,7 +1,7 @@
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net> // Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use crate::config::{Config, Socks5}; use crate::config::Config;
use crate::error::Socks5ClientCoreError; use crate::error::Socks5ClientCoreError;
use crate::socks::{ use crate::socks::{
authentication::{AuthenticationMethods, Authenticator, User}, authentication::{AuthenticationMethods, Authenticator, User},
@@ -67,8 +67,8 @@ where
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
pub fn start_socks5_listener( pub fn start_socks5_listener(
socks5_config: &Socks5, socks5_config: &config::Socks5,
debug_config: DebugConfig, base_debug: DebugConfig,
client_input: ClientInput, client_input: ClientInput,
client_output: ClientOutput, client_output: ClientOutput,
client_status: ClientState, client_status: ClientState,
@@ -94,25 +94,24 @@ where
.. ..
} = client_status; } = client_status;
let packet_size = debug_config let packet_size = base_debug
.traffic .traffic
.secondary_packet_size .secondary_packet_size
.unwrap_or(debug_config.traffic.primary_packet_size); .unwrap_or(base_debug.traffic.primary_packet_size);
let authenticator = Authenticator::new(auth_methods, allowed_users); let authenticator = Authenticator::new(auth_methods, allowed_users);
let mut sphinx_socks = NymSocksServer::new( let mut sphinx_socks = NymSocksServer::new(
socks5_config.get_listening_port(), socks5_config.listening_port,
authenticator, authenticator,
socks5_config.get_provider_mix_address(), socks5_config.get_provider_mix_address(),
self_address, self_address,
shared_lane_queue_lengths, shared_lane_queue_lengths,
socks::client::Config::new( socks::client::Config::new(
packet_size, packet_size,
socks5_config.get_provider_interface_version(), socks5_config.provider_interface_version,
socks5_config.get_socks5_protocol_version(), socks5_config.socks5_protocol_version,
socks5_config.get_send_anonymously(), socks5_config.send_anonymously,
socks5_config.get_connection_start_surbs(), socks5_config.socks5_debug,
socks5_config.get_per_request_surbs(),
), ),
shutdown.clone(), shutdown.clone(),
packet_type, packet_type,
@@ -191,43 +190,40 @@ where
let (key_store, reply_storage_backend, credential_store) = self.storage.into_split(); let (key_store, reply_storage_backend, credential_store) = self.storage.into_split();
// don't create bandwidth controller if credentials are disabled // don't create bandwidth controller if credentials are disabled
let bandwidth_controller = if self.config.get_base().get_disabled_credentials_mode() { let bandwidth_controller = if self.config.base.client.disabled_credentials_mode {
None None
} else { } else {
Some(non_wasm_helpers::create_bandwidth_controller( Some(non_wasm_helpers::create_bandwidth_controller(
self.config.get_base(), &self.config.base,
credential_store, credential_store,
)) ))
}; };
let base_builder = BaseClientBuilder::<_, S>::new_from_base_config( let base_builder = BaseClientBuilder::<_, S>::new_from_base_config(
self.config.get_base(), &self.config.base,
key_store, key_store,
bandwidth_controller, bandwidth_controller,
reply_storage_backend, reply_storage_backend,
); );
let packet_type = self.config.get_base().get_packet_type(); let packet_type = self.config.base.debug.traffic.packet_type;
let mut started_client = base_builder.start_base(packet_type).await?; let mut started_client = base_builder.start_base().await?;
let self_address = started_client.address; let self_address = started_client.address;
let client_input = started_client.client_input.register_producer(); let client_input = started_client.client_input.register_producer();
let client_output = started_client.client_output.register_consumer(); let client_output = started_client.client_output.register_consumer();
let client_state = started_client.client_state; let client_state = started_client.client_state;
info!( info!("Running with {packet_type} packets",);
"Running with {:?} packets",
self.config.get_base().get_packet_type()
);
Self::start_socks5_listener( Self::start_socks5_listener(
self.config.get_socks5(), &self.config.socks5,
*self.config.get_debug_settings(), self.config.base.debug,
client_input, client_input,
client_output, client_output,
client_state, client_state,
self_address, self_address,
started_client.task_manager.subscribe(), started_client.task_manager.subscribe(),
self.config.get_base().get_packet_type(), packet_type,
); );
info!("Client startup finished!"); info!("Client startup finished!");
@@ -4,6 +4,7 @@ use super::authentication::{AuthenticationMethods, Authenticator, User};
use super::request::{SocksCommand, SocksRequest}; use super::request::{SocksCommand, SocksRequest};
use super::types::{ResponseCodeV4, ResponseCodeV5, SocksProxyError}; use super::types::{ResponseCodeV4, ResponseCodeV5, SocksProxyError};
use super::{SocksVersion, RESERVED, SOCKS4_VERSION, SOCKS5_VERSION}; use super::{SocksVersion, RESERVED, SOCKS4_VERSION, SOCKS5_VERSION};
use crate::config;
use futures::channel::mpsc; use futures::channel::mpsc;
use futures::task::{Context, Poll}; use futures::task::{Context, Poll};
use log::*; use log::*;
@@ -147,16 +148,15 @@ impl Config {
provider_interface_version: ProviderInterfaceVersion, provider_interface_version: ProviderInterfaceVersion,
socks5_protocol_version: Socks5ProtocolVersion, socks5_protocol_version: Socks5ProtocolVersion,
use_surbs_for_responses: bool, use_surbs_for_responses: bool,
connection_start_surbs: u32, debug_config: config::Socks5Debug,
per_request_surbs: u32,
) -> Self { ) -> Self {
Self { Self {
biggest_packet_size, biggest_packet_size,
provider_interface_version, provider_interface_version,
socks5_protocol_version, socks5_protocol_version,
use_surbs_for_responses, use_surbs_for_responses,
connection_start_surbs, connection_start_surbs: debug_config.connection_start_surbs,
per_request_surbs, per_request_surbs: debug_config.per_request_surbs,
} }
} }
@@ -13,7 +13,7 @@ mod inbound;
mod outbound; mod outbound;
// TODO: make this configurable // TODO: make this configurable
const SHUTDOWN_TIMEOUT: Duration = Duration::from_secs(3); const SHUTDOWN_TIMEOUT: Duration = Duration::from_secs(30);
// Send empty keepalive messages regurarly to keep the connection alive. This should be smaller // Send empty keepalive messages regurarly to keep the connection alive. This should be smaller
// than [`MIX_TTL`]. // than [`MIX_TTL`].
-6
View File
@@ -81,7 +81,6 @@ impl GatewayBond {
pub struct GatewayNodeDetailsResponse { pub struct GatewayNodeDetailsResponse {
pub identity_key: String, pub identity_key: String,
pub sphinx_key: String, pub sphinx_key: String,
pub announce_address: String,
pub bind_address: String, pub bind_address: String,
pub version: String, pub version: String,
pub mix_port: u16, pub mix_port: u16,
@@ -93,11 +92,6 @@ impl fmt::Display for GatewayNodeDetailsResponse {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
writeln!(f, "Identity Key: {}", self.identity_key)?; writeln!(f, "Identity Key: {}", self.identity_key)?;
writeln!(f, "Sphinx Key: {}", self.sphinx_key)?; writeln!(f, "Sphinx Key: {}", self.sphinx_key)?;
writeln!(
f,
"Host: {} (bind address: {})",
self.announce_address, self.bind_address
)?;
writeln!(f, "Version: {}", self.version)?; writeln!(f, "Version: {}", self.version)?;
writeln!( writeln!(
f, f,
+4 -11
View File
@@ -13,6 +13,7 @@ use nym_mixnet_contract_common::{
use schemars::JsonSchema; use schemars::JsonSchema;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::fmt; use std::fmt;
use std::net::IpAddr;
#[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))] #[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))]
#[cfg_attr( #[cfg_attr(
@@ -167,31 +168,23 @@ impl MixNodeCostParams {
pub struct MixnodeNodeDetailsResponse { pub struct MixnodeNodeDetailsResponse {
pub identity_key: String, pub identity_key: String,
pub sphinx_key: String, pub sphinx_key: String,
pub announce_address: String, pub bind_address: IpAddr,
pub bind_address: String,
pub version: String, pub version: String,
pub mix_port: u16, pub mix_port: u16,
pub http_api_port: u16, pub http_api_port: u16,
pub verloc_port: u16, pub verloc_port: u16,
pub wallet_address: Option<String>,
} }
impl fmt::Display for MixnodeNodeDetailsResponse { impl fmt::Display for MixnodeNodeDetailsResponse {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let wallet_address = self.wallet_address.clone().unwrap_or_default();
writeln!(f, "Identity Key: {}", self.identity_key)?; writeln!(f, "Identity Key: {}", self.identity_key)?;
writeln!(f, "Sphinx Key: {}", self.sphinx_key)?; writeln!(f, "Sphinx Key: {}", self.sphinx_key)?;
writeln!( writeln!(f, "Host: {}", self.bind_address)?;
f,
"Host: {} (bind address: {})",
self.announce_address, self.bind_address
)?;
writeln!(f, "Version: {}", self.version)?; writeln!(f, "Version: {}", self.version)?;
writeln!( writeln!(
f, f,
"Mix Port: {}, Verloc port: {}, Http Port: {}\n", "Mix Port: {}, Verloc port: {}, Http Port: {}\n",
self.mix_port, self.verloc_port, self.http_api_port self.mix_port, self.verloc_port, self.http_api_port
)?; )
writeln!(f, "You are bonding to wallet address: {wallet_address}\n\n")
} }
} }
+5 -13
View File
@@ -1319,7 +1319,7 @@ dependencies = [
[[package]] [[package]]
name = "nym-contracts-common" name = "nym-contracts-common"
version = "0.5.0" version = "0.4.0"
dependencies = [ dependencies = [
"bs58", "bs58",
"cosmwasm-std", "cosmwasm-std",
@@ -1330,7 +1330,7 @@ dependencies = [
[[package]] [[package]]
name = "nym-crypto" name = "nym-crypto"
version = "0.4.0" version = "0.3.0"
dependencies = [ dependencies = [
"bs58", "bs58",
"ed25519-dalek", "ed25519-dalek",
@@ -1378,7 +1378,7 @@ dependencies = [
[[package]] [[package]]
name = "nym-mixnet-contract-common" name = "nym-mixnet-contract-common"
version = "0.6.0" version = "0.5.0"
dependencies = [ dependencies = [
"bs58", "bs58",
"cosmwasm-std", "cosmwasm-std",
@@ -1455,7 +1455,7 @@ dependencies = [
[[package]] [[package]]
name = "nym-pemstore" name = "nym-pemstore"
version = "0.3.0" version = "0.2.0"
dependencies = [ dependencies = [
"pem", "pem",
] ]
@@ -1465,7 +1465,6 @@ name = "nym-service-provider-directory"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"bs58",
"cosmwasm-std", "cosmwasm-std",
"cw-controllers", "cw-controllers",
"cw-multi-test", "cw-multi-test",
@@ -1473,10 +1472,7 @@ dependencies = [
"cw-utils", "cw-utils",
"cw2", "cw2",
"nym-contracts-common", "nym-contracts-common",
"nym-crypto",
"nym-service-provider-directory-common", "nym-service-provider-directory-common",
"rand_chacha 0.2.2",
"rstest",
"semver", "semver",
"serde", "serde",
"thiserror", "thiserror",
@@ -1488,12 +1484,8 @@ name = "nym-service-provider-directory-common"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"cosmwasm-std", "cosmwasm-std",
"cw-controllers",
"cw-utils",
"nym-contracts-common",
"schemars", "schemars",
"serde", "serde",
"thiserror",
] ]
[[package]] [[package]]
@@ -1530,7 +1522,7 @@ dependencies = [
[[package]] [[package]]
name = "nym-vesting-contract-common" name = "nym-vesting-contract-common"
version = "0.7.0" version = "0.6.0"
dependencies = [ dependencies = [
"cosmwasm-std", "cosmwasm-std",
"nym-contracts-common", "nym-contracts-common",
+3 -3
View File
@@ -22,9 +22,9 @@ name = "mixnet_contract"
crate-type = ["cdylib", "rlib"] crate-type = ["cdylib", "rlib"]
[dependencies] [dependencies]
mixnet-contract-common = { path = "../../common/cosmwasm-smart-contracts/mixnet-contract", package = "nym-mixnet-contract-common", version = "0.6.0" } mixnet-contract-common = { path = "../../common/cosmwasm-smart-contracts/mixnet-contract", package = "nym-mixnet-contract-common", version = "0.5.0" }
vesting-contract-common = { path = "../../common/cosmwasm-smart-contracts/vesting-contract", package = "nym-vesting-contract-common", version = "0.7.0" } vesting-contract-common = { path = "../../common/cosmwasm-smart-contracts/vesting-contract", package = "nym-vesting-contract-common", version = "0.6.0" }
nym-contracts-common = { path = "../../common/cosmwasm-smart-contracts/contracts-common", version = "0.5.0" } nym-contracts-common = { path = "../../common/cosmwasm-smart-contracts/contracts-common", version = "0.4.0" }
cosmwasm-std = { workspace = true } cosmwasm-std = { workspace = true }
cosmwasm-storage = { workspace = true } cosmwasm-storage = { workspace = true }
+1 -1
View File
@@ -14,7 +14,7 @@ mod mixnet_contract_settings;
mod mixnodes; mod mixnodes;
mod queued_migrations; mod queued_migrations;
mod rewards; mod rewards;
pub mod signing; mod signing;
mod support; mod support;
#[cfg(feature = "contract-testing")] #[cfg(feature = "contract-testing")]
+1 -1
View File
@@ -12,7 +12,7 @@ cw-controllers = { workspace = true }
cw-storage-plus = { workspace = true } cw-storage-plus = { workspace = true }
cw-utils = { workspace = true } cw-utils = { workspace = true }
cw2 = { workspace = true } cw2 = { workspace = true }
nym-contracts-common = { path = "../../common/cosmwasm-smart-contracts/contracts-common", version = "0.5.0" } nym-contracts-common = { path = "../../common/cosmwasm-smart-contracts/contracts-common", version = "0.4.0" }
nym-name-service-common = { path = "../../common/cosmwasm-smart-contracts/name-service" } nym-name-service-common = { path = "../../common/cosmwasm-smart-contracts/name-service" }
semver = { version = "1.0.16", default-features = false } semver = { version = "1.0.16", default-features = false }
serde = { version = "1.0.155", default-features = false, features = ["derive"] } serde = { version = "1.0.155", default-features = false, features = ["derive"] }
+1 -1
View File
@@ -188,7 +188,6 @@ mod tests {
use super::*; use super::*;
type TestDeps = OwnedDeps<MemoryStorage, MockApi, MockQuerier>; type TestDeps = OwnedDeps<MemoryStorage, MockApi, MockQuerier>;
#[rstest::fixture] #[rstest::fixture]
fn deps() -> TestDeps { fn deps() -> TestDeps {
instantiate_test_contract() instantiate_test_contract()
@@ -692,6 +691,7 @@ mod tests {
#[test] #[test]
#[ignore] #[ignore]
fn max_page_limit_is_applied() { fn max_page_limit_is_applied() {
// WIP(JON)
todo!(); todo!();
} }
} }

Some files were not shown because too many files have changed in this diff Show More