Compare commits
142 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| eaa0f055af | |||
| ad507c6a12 | |||
| e5d68a5e7f | |||
| 7ddd819ff3 | |||
| 83b416d12d | |||
| b9c775c3ae | |||
| 6f669866e9 | |||
| 4e61fefec8 | |||
| b4514ecd83 | |||
| 4f6902525e | |||
| 881139e36f | |||
| 32e2557456 | |||
| 8b44820e51 | |||
| 5e6417f837 | |||
| dfb2a2f380 | |||
| d1de751850 | |||
| ecee6ca863 | |||
| 31ea3f92e2 | |||
| f19c934fae | |||
| 10d6f20de7 | |||
| 96b33bfbe4 | |||
| 444c787d0a | |||
| 61fcd4ac69 | |||
| b76802e6eb | |||
| 7d351029a4 | |||
| 4ee445c119 | |||
| 61ddeea495 | |||
| 7b802033b3 | |||
| b484f47369 | |||
| 66979df10c | |||
| 82f161fb91 | |||
| 9d0fd681d4 | |||
| c2ab47a102 | |||
| 8704c21621 | |||
| 03ffb25bf9 | |||
| 70db1ad062 | |||
| 952ed9b642 | |||
| f57fe79686 | |||
| 9179f1c351 | |||
| c4f7a1e09d | |||
| 701012a968 | |||
| 9767f72b8f | |||
| 7b10d92ca4 | |||
| 2c6e5eb673 | |||
| 02fde4e530 | |||
| cc25fc1f32 | |||
| c971e486b5 | |||
| 96a9eb6f6a | |||
| 9eeb61ea0a | |||
| 08042c61ad | |||
| 36c74f30e5 | |||
| fd1d437211 | |||
| 4956d13bdc | |||
| 6478736654 | |||
| d9f6c0723e | |||
| f86050d916 | |||
| 52f5656190 | |||
| 21cd90f238 | |||
| 4e51188d35 | |||
| 22eb199936 | |||
| a2fc1bbc96 | |||
| 621599692f | |||
| 3ad3837c87 | |||
| 4d745e3b7e | |||
| 3a053b8dd6 | |||
| 1f144690da | |||
| eec1895acc | |||
| 72e243042e | |||
| 99864cb7a9 | |||
| 3155728119 | |||
| c253b22f69 | |||
| 66f3a3e9a8 | |||
| 65a1d6d91e | |||
| 44cf9b054b | |||
| 39e2473ef3 | |||
| 93a108863c | |||
| 0905593123 | |||
| ed9223d5a3 | |||
| c2ad4e5bb4 | |||
| 5f7f5ef92d | |||
| 962684ff56 | |||
| 7b3804c078 | |||
| 170f1823e1 | |||
| dc2020559a | |||
| 2b9444cce3 | |||
| 68c1c068ac | |||
| 3d0b70a237 | |||
| 65a6edc78c | |||
| 2ec8349897 | |||
| 38a2d94f80 | |||
| c7fa910516 | |||
| 2fe08274dd | |||
| be89d848dc | |||
| a230a9b8b9 | |||
| 72eae7cdf3 | |||
| 7cae195370 | |||
| dfb16e385c | |||
| 660e1cad0a | |||
| 7c1aa57a7e | |||
| a06e496f78 | |||
| 70599b97b9 | |||
| 02b194bde0 | |||
| 20ec049db5 | |||
| fec3d46b33 | |||
| a4eb3a7dbf | |||
| 28d15f2c4f | |||
| 6078787daa | |||
| 6d93f36c82 | |||
| c6f93e38f5 | |||
| 2159f71888 | |||
| a9abea3446 | |||
| 8e2713c9ba | |||
| 2ba0ef0e35 | |||
| d3713cbc79 | |||
| 4d3fb2b585 | |||
| e65e611859 | |||
| c465eb3efc | |||
| b90136ac4e | |||
| ae5373168d | |||
| 6f3942f6b7 | |||
| 4a25725a11 | |||
| 13f38343aa | |||
| d34c829174 | |||
| f75b4843e8 | |||
| 6963ead65a | |||
| 0425cdeaf0 | |||
| 789914b096 | |||
| 008afe7a85 | |||
| 8acd3a0975 | |||
| fa1519ec6a | |||
| da94b7e8df | |||
| 4aa8cb4647 | |||
| 5d13538508 | |||
| 4bbbcf629d | |||
| 34ef970fd8 | |||
| fec570613c | |||
| 14a904eff0 | |||
| b43844bd7a | |||
| cd89feb57e | |||
| 17553d606e | |||
| b6d9ed960b | |||
| 1d89a887fb |
@@ -41,8 +41,8 @@ jobs:
|
||||
# This is a workaround replacement which builds on the last working commit b332a6b55668f60988e36961f3f62a794ba82ddb and then on current branch
|
||||
- name: Save current branch to ~/current_branch
|
||||
run: git rev-parse --abbrev-ref HEAD > ~/current_branch
|
||||
- name: Git pull & switch to b332a6b55668f60988e36961f3f62a794ba82ddb
|
||||
run: git pull && git checkout b332a6b55668f60988e36961f3f62a794ba82ddb
|
||||
- name: Git pull, reset & switch to b332a6b55668f60988e36961f3f62a794ba82ddb
|
||||
run: git pull && git reset --hard && git checkout b332a6b55668f60988e36961f3f62a794ba82ddb
|
||||
- name: Build all projects in documentation/ & move to ~/dist/docs/ from b332a6b55668f60988e36961f3f62a794ba82ddb
|
||||
run: cd documentation && ./build_all_to_dist.sh
|
||||
|
||||
|
||||
@@ -46,8 +46,8 @@ jobs:
|
||||
# This is a workaround replacement which builds on the last working commit b332a6b55668f60988e36961f3f62a794ba82ddb and then on current branch
|
||||
- name: Save current branch to ~/current_branch
|
||||
run: git rev-parse --abbrev-ref HEAD > ~/current_branch
|
||||
- name: Git pull & switch to b332a6b55668f60988e36961f3f62a794ba82ddb
|
||||
run: git pull && git checkout b332a6b55668f60988e36961f3f62a794ba82ddb
|
||||
- name: Git pull, reset & switch to b332a6b55668f60988e36961f3f62a794ba82ddb
|
||||
run: git pull && git reset --hard && git checkout b332a6b55668f60988e36961f3f62a794ba82ddb
|
||||
- name: Build all projects in documentation/ & move to ~/dist/docs/ from b332a6b55668f60988e36961f3f62a794ba82ddb
|
||||
run: cd documentation && ./build_all_to_dist.sh
|
||||
|
||||
|
||||
@@ -51,6 +51,10 @@ jobs:
|
||||
echo 'RUSTFLAGS="--cfg tokio_unstable"' >> $GITHUB_ENV
|
||||
if: github.event_name == 'workflow_dispatch' && inputs.add_tokio_unstable == true
|
||||
|
||||
- name: Set CARGO_FEATURES
|
||||
run: |
|
||||
echo 'CARGO_FEATURES=--features wireguard' >> $GITHUB_ENV
|
||||
|
||||
- name: Install Rust stable
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
@@ -60,8 +64,8 @@ jobs:
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: build
|
||||
args: --workspace --release
|
||||
|
||||
args: --workspace --release ${{ env.CARGO_FEATURES }}
|
||||
|
||||
- name: Upload Artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
|
||||
+24
-1
@@ -4,6 +4,30 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [2024.8-wispa] (2024-07-10)
|
||||
|
||||
- add event parsing to support cosmos_sdk > 0.50 ([#4697])
|
||||
- Fix NR config compatibility ([#4690])
|
||||
- Remove UserAgent constructor since it's weakly typed ([#4689])
|
||||
- [bugfix]: Node_api_check CLI looked over roles on blacklisted nodes ([#4687])
|
||||
- Add mixnodes to self describing api cache ([#4684])
|
||||
- Move and whole bump of crates to workspace and upgrade some ([#4680])
|
||||
- Remove code that refers to removed nym-network-statistics ([#4679])
|
||||
- Remove nym-network-statistics ([#4678])
|
||||
- Create UserAgent that can be passed from the binary to the nym api client ([#4677])
|
||||
- Add authenticator ([#4667])
|
||||
|
||||
[#4697]: https://github.com/nymtech/nym/pull/4697
|
||||
[#4690]: https://github.com/nymtech/nym/pull/4690
|
||||
[#4689]: https://github.com/nymtech/nym/pull/4689
|
||||
[#4687]: https://github.com/nymtech/nym/pull/4687
|
||||
[#4684]: https://github.com/nymtech/nym/pull/4684
|
||||
[#4680]: https://github.com/nymtech/nym/pull/4680
|
||||
[#4679]: https://github.com/nymtech/nym/pull/4679
|
||||
[#4678]: https://github.com/nymtech/nym/pull/4678
|
||||
[#4677]: https://github.com/nymtech/nym/pull/4677
|
||||
[#4667]: https://github.com/nymtech/nym/pull/4667
|
||||
|
||||
## [2024.7-doubledecker] (2024-07-04)
|
||||
|
||||
- Add an early return in `parse_raw_str_logs` for empty raw log strings. ([#4686])
|
||||
@@ -513,7 +537,6 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
|
||||
[#3187]: https://github.com/nymtech/nym/issues/3187
|
||||
[#3203]: https://github.com/nymtech/nym/pull/3203
|
||||
[#3199]: https://github.com/nymtech/nym/pull/3199
|
||||
>>>>>>> master
|
||||
|
||||
## [v1.1.13] (2023-03-15)
|
||||
|
||||
|
||||
Generated
+101
-77
@@ -1378,7 +1378,7 @@ dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"crossterm_winapi",
|
||||
"libc",
|
||||
"mio",
|
||||
"mio 0.8.11",
|
||||
"parking_lot 0.12.2",
|
||||
"signal-hook",
|
||||
"signal-hook-mio",
|
||||
@@ -1394,7 +1394,7 @@ dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"crossterm_winapi",
|
||||
"libc",
|
||||
"mio",
|
||||
"mio 0.8.11",
|
||||
"parking_lot 0.12.2",
|
||||
"signal-hook",
|
||||
"signal-hook-mio",
|
||||
@@ -2093,14 +2093,14 @@ checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0"
|
||||
|
||||
[[package]]
|
||||
name = "explorer-api"
|
||||
version = "1.1.36"
|
||||
version = "1.1.37"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"clap 4.5.4",
|
||||
"dotenvy",
|
||||
"humantime-serde",
|
||||
"isocountry",
|
||||
"itertools 0.10.5",
|
||||
"itertools 0.12.1",
|
||||
"log",
|
||||
"maxminddb",
|
||||
"nym-bin-common",
|
||||
@@ -2221,7 +2221,7 @@ dependencies = [
|
||||
"atomic 0.6.0",
|
||||
"pear",
|
||||
"serde",
|
||||
"toml 0.8.12",
|
||||
"toml 0.8.14",
|
||||
"uncased",
|
||||
"version_check",
|
||||
]
|
||||
@@ -3272,15 +3272,6 @@ dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.12.1"
|
||||
@@ -3605,6 +3596,18 @@ dependencies = [
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mio"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4569e456d394deccd22ce1c1913e6ea0e54519f577285001215d33557431afe4"
|
||||
dependencies = [
|
||||
"hermit-abi 0.3.9",
|
||||
"libc",
|
||||
"wasi 0.11.0+wasi-snapshot-preview1",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mix-fetch-wasm"
|
||||
version = "1.3.0-rc.0"
|
||||
@@ -3786,7 +3789,7 @@ dependencies = [
|
||||
"inotify",
|
||||
"kqueue",
|
||||
"libc",
|
||||
"mio",
|
||||
"mio 0.8.11",
|
||||
"walkdir",
|
||||
"windows-sys 0.45.0",
|
||||
]
|
||||
@@ -3858,7 +3861,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nym-api"
|
||||
version = "1.1.40"
|
||||
version = "1.1.41"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
@@ -3959,6 +3962,54 @@ dependencies = [
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nym-authenticator"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bincode",
|
||||
"bs58 0.5.1",
|
||||
"bytes",
|
||||
"clap 4.5.4",
|
||||
"fastrand 2.1.0",
|
||||
"futures",
|
||||
"ipnetwork 0.16.0",
|
||||
"log",
|
||||
"nym-authenticator-requests",
|
||||
"nym-bin-common",
|
||||
"nym-client-core",
|
||||
"nym-config",
|
||||
"nym-crypto",
|
||||
"nym-id",
|
||||
"nym-network-defaults",
|
||||
"nym-sdk",
|
||||
"nym-service-providers-common",
|
||||
"nym-sphinx",
|
||||
"nym-task",
|
||||
"nym-types",
|
||||
"nym-wireguard",
|
||||
"nym-wireguard-types",
|
||||
"rand 0.8.5",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
"tokio-stream",
|
||||
"tokio-util",
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nym-authenticator-requests"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bincode",
|
||||
"nym-sphinx",
|
||||
"nym-wireguard-types",
|
||||
"rand 0.8.5",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nym-bandwidth-controller"
|
||||
version = "0.1.0"
|
||||
@@ -4018,7 +4069,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nym-cli"
|
||||
version = "1.1.38"
|
||||
version = "1.1.39"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"base64 0.13.1",
|
||||
@@ -4097,7 +4148,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nym-client"
|
||||
version = "1.1.37"
|
||||
version = "1.1.38"
|
||||
dependencies = [
|
||||
"bs58 0.5.1",
|
||||
"clap 4.5.4",
|
||||
@@ -4282,7 +4333,7 @@ dependencies = [
|
||||
"ff",
|
||||
"getrandom 0.2.15",
|
||||
"group",
|
||||
"itertools 0.10.5",
|
||||
"itertools 0.12.1",
|
||||
"nym-dkg",
|
||||
"nym-pemstore",
|
||||
"rand 0.8.5",
|
||||
@@ -4523,6 +4574,7 @@ dependencies = [
|
||||
"ipnetwork 0.16.0",
|
||||
"log",
|
||||
"nym-api-requests",
|
||||
"nym-authenticator",
|
||||
"nym-bin-common",
|
||||
"nym-config",
|
||||
"nym-credentials",
|
||||
@@ -4537,7 +4589,6 @@ dependencies = [
|
||||
"nym-node-http-api",
|
||||
"nym-pemstore",
|
||||
"nym-sphinx",
|
||||
"nym-statistics-common",
|
||||
"nym-task",
|
||||
"nym-types",
|
||||
"nym-validator-client",
|
||||
@@ -4633,6 +4684,7 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"http 1.1.0",
|
||||
"nym-bin-common",
|
||||
"reqwest 0.12.4",
|
||||
"serde",
|
||||
"serde_json",
|
||||
@@ -4910,7 +4962,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nym-network-requester"
|
||||
version = "1.1.38"
|
||||
version = "1.1.39"
|
||||
dependencies = [
|
||||
"addr",
|
||||
"anyhow",
|
||||
@@ -4939,7 +4991,6 @@ dependencies = [
|
||||
"nym-socks5-proxy-helpers",
|
||||
"nym-socks5-requests",
|
||||
"nym-sphinx",
|
||||
"nym-statistics-common",
|
||||
"nym-task",
|
||||
"nym-types",
|
||||
"pretty_env_logger",
|
||||
@@ -4960,26 +5011,9 @@ dependencies = [
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nym-network-statistics"
|
||||
version = "1.1.34"
|
||||
dependencies = [
|
||||
"dirs 4.0.0",
|
||||
"log",
|
||||
"nym-bin-common",
|
||||
"nym-statistics-common",
|
||||
"nym-task",
|
||||
"pretty_env_logger",
|
||||
"rocket",
|
||||
"serde",
|
||||
"sqlx",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nym-node"
|
||||
version = "1.1.4"
|
||||
version = "1.1.5"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bip39",
|
||||
@@ -4991,6 +5025,7 @@ dependencies = [
|
||||
"cupid",
|
||||
"humantime-serde",
|
||||
"ipnetwork 0.16.0",
|
||||
"nym-authenticator",
|
||||
"nym-bin-common",
|
||||
"nym-client-core-config-types",
|
||||
"nym-config",
|
||||
@@ -5014,7 +5049,7 @@ dependencies = [
|
||||
"sysinfo 0.30.12",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
"toml 0.8.12",
|
||||
"toml 0.8.14",
|
||||
"tracing",
|
||||
"url",
|
||||
"zeroize",
|
||||
@@ -5160,7 +5195,7 @@ dependencies = [
|
||||
"chacha20poly1305",
|
||||
"criterion",
|
||||
"curve25519-dalek 4.1.2",
|
||||
"fastrand 1.9.0",
|
||||
"fastrand 2.1.0",
|
||||
"getrandom 0.2.15",
|
||||
"log",
|
||||
"rand 0.8.5",
|
||||
@@ -5241,7 +5276,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nym-socks5-client"
|
||||
version = "1.1.37"
|
||||
version = "1.1.38"
|
||||
dependencies = [
|
||||
"bs58 0.5.1",
|
||||
"clap 4.5.4",
|
||||
@@ -5260,6 +5295,7 @@ dependencies = [
|
||||
"nym-socks5-client-core",
|
||||
"nym-sphinx",
|
||||
"nym-topology",
|
||||
"nym-validator-client",
|
||||
"rand 0.8.5",
|
||||
"serde",
|
||||
"serde_json",
|
||||
@@ -5505,20 +5541,6 @@ dependencies = [
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nym-statistics-common"
|
||||
version = "1.0.1"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"log",
|
||||
"reqwest 0.12.4",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sqlx",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nym-store-cipher"
|
||||
version = "0.1.0"
|
||||
@@ -5593,7 +5615,7 @@ dependencies = [
|
||||
"cosmwasm-std",
|
||||
"eyre",
|
||||
"hmac",
|
||||
"itertools 0.11.0",
|
||||
"itertools 0.12.1",
|
||||
"log",
|
||||
"nym-config",
|
||||
"nym-crypto",
|
||||
@@ -5632,7 +5654,7 @@ dependencies = [
|
||||
"eyre",
|
||||
"flate2",
|
||||
"futures",
|
||||
"itertools 0.10.5",
|
||||
"itertools 0.12.1",
|
||||
"log",
|
||||
"nym-api-requests",
|
||||
"nym-coconut",
|
||||
@@ -5732,6 +5754,7 @@ name = "nym-wireguard"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"base64 0.21.7",
|
||||
"chrono",
|
||||
"dashmap",
|
||||
"defguard_wireguard_rs",
|
||||
"ip_network",
|
||||
@@ -5740,6 +5763,7 @@ dependencies = [
|
||||
"nym-network-defaults",
|
||||
"nym-task",
|
||||
"nym-wireguard-types",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
"tokio-stream",
|
||||
"x25519-dalek",
|
||||
@@ -5767,7 +5791,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nymvisor"
|
||||
version = "0.1.3"
|
||||
version = "0.1.4"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bytes",
|
||||
@@ -7594,9 +7618,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_spanned"
|
||||
version = "0.6.5"
|
||||
version = "0.6.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1"
|
||||
checksum = "79e674e01f999af37c49f70a6ede167a8a60b2503e56c5599532a65baa5969a0"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
@@ -7733,7 +7757,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "29ad2e15f37ec9a6cc544097b78a1ec90001e9f71b81338ca39f430adaca99af"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"mio",
|
||||
"mio 0.8.11",
|
||||
"signal-hook",
|
||||
]
|
||||
|
||||
@@ -8442,22 +8466,21 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.37.0"
|
||||
version = "1.39.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787"
|
||||
checksum = "daa4fb1bc778bd6f04cbfc4bb2d06a7396a8f299dc33ea1900cedaa316f467b1"
|
||||
dependencies = [
|
||||
"backtrace",
|
||||
"bytes",
|
||||
"libc",
|
||||
"mio",
|
||||
"num_cpus",
|
||||
"mio 1.0.1",
|
||||
"parking_lot 0.12.2",
|
||||
"pin-project-lite",
|
||||
"signal-hook-registry",
|
||||
"socket2",
|
||||
"tokio-macros",
|
||||
"tracing",
|
||||
"windows-sys 0.48.0",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -8472,9 +8495,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tokio-macros"
|
||||
version = "2.2.0"
|
||||
version = "2.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b"
|
||||
checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -8616,21 +8639,21 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.8.12"
|
||||
version = "0.8.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e9dd1545e8208b4a5af1aa9bbd0b4cf7e9ea08fabc5d0a5c67fcaafa17433aa3"
|
||||
checksum = "6f49eb2ab21d2f26bd6db7bf383edc527a7ebaee412d17af4d40fdccd442f335"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_spanned",
|
||||
"toml_datetime",
|
||||
"toml_edit 0.22.12",
|
||||
"toml_edit 0.22.14",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml_datetime"
|
||||
version = "0.6.5"
|
||||
version = "0.6.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1"
|
||||
checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
@@ -8650,9 +8673,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "toml_edit"
|
||||
version = "0.22.12"
|
||||
version = "0.22.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d3328d4f68a705b2a4498da1d580585d39a6510f98318a2cec3018a7ec61ddef"
|
||||
checksum = "f21c7aaf97f1bd9ca9d4f9e73b0a6c74bd5afef56f2bc931943a6e1c37e04e38"
|
||||
dependencies = [
|
||||
"indexmap 2.2.6",
|
||||
"serde",
|
||||
@@ -9427,6 +9450,7 @@ dependencies = [
|
||||
name = "wasm-utils"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"console_error_panic_hook",
|
||||
"futures",
|
||||
"getrandom 0.2.15",
|
||||
"gloo-net",
|
||||
|
||||
+18
-8
@@ -20,6 +20,7 @@ members = [
|
||||
"clients/native",
|
||||
"clients/native/websocket-requests",
|
||||
"clients/socks5",
|
||||
"common/authenticator-requests",
|
||||
"common/async-file-watcher",
|
||||
"common/bandwidth-controller",
|
||||
"common/bin-common",
|
||||
@@ -76,7 +77,6 @@ members = [
|
||||
"common/socks5-client-core",
|
||||
"common/socks5/proxy-helpers",
|
||||
"common/socks5/requests",
|
||||
"common/statistics",
|
||||
"common/store-cipher",
|
||||
"common/task",
|
||||
"common/topology",
|
||||
@@ -96,10 +96,10 @@ members = [
|
||||
"mixnode",
|
||||
"sdk/lib/socks5-listener",
|
||||
"sdk/rust/nym-sdk",
|
||||
"service-providers/authenticator",
|
||||
"service-providers/common",
|
||||
"service-providers/ip-packet-router",
|
||||
"service-providers/network-requester",
|
||||
"service-providers/network-statistics",
|
||||
"nym-api",
|
||||
"nym-browser-extension/storage",
|
||||
"nym-api/nym-api-requests",
|
||||
@@ -127,7 +127,6 @@ default-members = [
|
||||
"clients/socks5",
|
||||
"gateway",
|
||||
"service-providers/network-requester",
|
||||
"service-providers/network-statistics",
|
||||
"mixnode",
|
||||
"nym-api",
|
||||
"tools/nymvisor",
|
||||
@@ -192,12 +191,15 @@ cupid = "0.6.1"
|
||||
curve25519-dalek = "4.1"
|
||||
dashmap = "5.5.3"
|
||||
defguard_wireguard_rs = "0.4.2"
|
||||
digest = "0.10.7"
|
||||
dirs = "4.0"
|
||||
doc-comment = "0.3"
|
||||
dotenvy = "0.15.6"
|
||||
ecdsa = "0.16"
|
||||
ed25519-dalek = "2.1"
|
||||
etherparse = "0.13.0"
|
||||
eyre = "0.6.9"
|
||||
fastrand = "2.1.0"
|
||||
flate2 = "1.0.28"
|
||||
futures = "0.3.28"
|
||||
generic-array = "0.14.7"
|
||||
@@ -209,14 +211,15 @@ hex = "0.4.3"
|
||||
hex-literal = "0.3.3"
|
||||
hkdf = "0.12.3"
|
||||
hmac = "0.12.1"
|
||||
http = "1"
|
||||
httpcodec = "0.2.3"
|
||||
humantime = "2.1.0"
|
||||
humantime-serde = "1.1.1"
|
||||
http = "1"
|
||||
hyper = "1.3.1"
|
||||
indexed_db_futures = "0.3.0"
|
||||
inquire = "0.6.2"
|
||||
ip_network = "0.4.1"
|
||||
ipnetwork = "0.16"
|
||||
isocountry = "0.3.2"
|
||||
k256 = "0.13"
|
||||
lazy_static = "1.4.0"
|
||||
@@ -239,6 +242,7 @@ publicsuffix = "2.2.3"
|
||||
quote = "1"
|
||||
rand = "0.8.5"
|
||||
rand-07 = "0.7.3"
|
||||
rand_chacha = "0.3"
|
||||
rand_chacha_02 = "0.2"
|
||||
rand_core = "0.6.3"
|
||||
rand_distr = "0.4"
|
||||
@@ -252,6 +256,7 @@ rocket_cors = "0.6.0"
|
||||
rocket_okapi = "0.8.0"
|
||||
safer-ffi = "0.1.4"
|
||||
schemars = "0.8.1"
|
||||
semver = "1.0.23"
|
||||
serde = "1.0.152"
|
||||
serde_bytes = "0.11.6"
|
||||
serde_derive = "1.0"
|
||||
@@ -259,22 +264,25 @@ serde_json = "1.0.91"
|
||||
serde_repr = "0.1"
|
||||
serde_with = "3.4.0"
|
||||
serde_yaml = "0.9.25"
|
||||
sha2 = "0.10.8"
|
||||
si-scale = "0.2.2"
|
||||
sphinx-packet = "0.1.1"
|
||||
sqlx = "0.6.3"
|
||||
strum = "0.25"
|
||||
subtle-encoding = "0.5"
|
||||
syn = "1"
|
||||
sysinfo = "0.30.12"
|
||||
tap = "1.0.1"
|
||||
tar = "0.4.40"
|
||||
tempfile = "3.5.0"
|
||||
thiserror = "1.0.48"
|
||||
time = "0.3.30"
|
||||
tokio = "1.33.0"
|
||||
tokio-stream = "0.1.14"
|
||||
tokio-test = "0.4.2"
|
||||
tokio = "1.39"
|
||||
tokio-stream = "0.1.15"
|
||||
tokio-test = "0.4.4"
|
||||
tokio-tungstenite = { version = "0.20.1" }
|
||||
tokio-util = "0.7.10"
|
||||
tokio-util = "0.7.11"
|
||||
toml = "0.8.14"
|
||||
tower = "0.4.13"
|
||||
tower-http = "0.5.2"
|
||||
tracing = "0.1.37"
|
||||
@@ -289,6 +297,7 @@ utoipa-swagger-ui = "6.0.0"
|
||||
vergen = { version = "=8.3.1", default-features = false }
|
||||
walkdir = "2"
|
||||
wasm-bindgen-test = "0.3.36"
|
||||
x25519-dalek = "2.0.0"
|
||||
zeroize = "1.6.0"
|
||||
|
||||
prometheus = { version = "0.13.0" }
|
||||
@@ -336,6 +345,7 @@ wasm-bindgen = "0.2.92"
|
||||
wasm-bindgen-futures = "0.4.39"
|
||||
wasmtimer = "0.2.0"
|
||||
web-sys = "0.3.69"
|
||||
itertools = "0.12.0"
|
||||
|
||||
|
||||
# Profile settings for individual crates
|
||||
|
||||
@@ -7,86 +7,66 @@ SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
The platform is composed of multiple Rust crates. Top-level executable binary crates include:
|
||||
|
||||
* nym-mixnode - shuffles [Sphinx](https://github.com/nymtech/sphinx) packets together to provide privacy against network-level attackers.
|
||||
* nym-client - an executable which you can build into your own applications. Use it for interacting with Nym nodes.
|
||||
* nym-socks5-client - a Socks5 proxy you can run on your machine and use with existing applications.
|
||||
* nym-gateway - acts sort of like a mailbox for mixnet messages, which removes the need for direct delivery to potentially offline or firewalled devices.
|
||||
* nym-network-monitor - sends packets through the full system to check that they are working as expected, and stores node uptime histories as the basis of a rewards system ("mixmining" or "proof-of-mixing").
|
||||
* nym-explorer - a (projected) block explorer and (existing) mixnet viewer.
|
||||
* nym-wallet - a desktop wallet implemented using the [Tauri](https://tauri.studio/en/docs/about/intro) framework.
|
||||
* `nym-node` - a tool for running a node within the Nym network. Nym Nodes containing functionality such as `mixnode`, `entry-gateway` and `exit-gateway` are fundamental components of Nym Mixnet architecture. Nym Nodes are ran by decentralised node operators. Read more about `nym-node` in [Operators Guide documentation](https://nymtech.net/operators/nodes/nym-node.html). Network functionality of `nym-node` (labeled with `--mode` flag) can be:
|
||||
- `mixnode` - shuffles [Sphinx](https://github.com/nymtech/sphinx) packets together to provide privacy against network-level attackers.
|
||||
- `gateway` - acts sort of like a mailbox for mixnet messages, which removes the need for direct delivery to potentially offline or firewalled devices. Gateways can be further categorized as `entry-gateway` and `exit-gateway`. The latter has an extra embedded IP packet router and Network requester to route data to the internet.
|
||||
* `nym-client` - an executable which you can build into your own applications. Use it for interacting with Nym nodes.
|
||||
* `nym-socks5-client` - a Socks5 proxy you can run on your machine and use with existing applications.
|
||||
* `nym-explorer` - a (projected) block explorer and (existing) mixnet viewer.
|
||||
* `nym-wallet` - a desktop wallet implemented using the [Tauri](https://tauri.studio/en/docs/about/intro) framework.
|
||||
<!-- coming soon
|
||||
* `nym-network-monitor` - sends packets through the full system to check that they are working as expected, and stores node uptime histories as the basis of a rewards system ("mixmining" or "proof-of-mixing").
|
||||
-->
|
||||
|
||||
```ascii
|
||||
┌─►mix──┐ mix mix
|
||||
│ │
|
||||
Entry │ │ Exit
|
||||
client ───► Gateway ──┘ mix │ mix ┌─►mix ───► Gateway ───► internet
|
||||
│ │
|
||||
│ │
|
||||
mix └─►mix──┘ mix
|
||||
|
||||
```
|
||||
|
||||
[](https://github.com/nymtech/nym/actions?query=branch%3Adevelop)
|
||||
|
||||
|
||||
### Building
|
||||
|
||||
Platform build instructions are available on [our docs site](https://nymtech.net/docs/binaries/pre-built-binaries.html).
|
||||
Wallet build instructions are also available on [our docs site](https://nymtech.net/docs/wallet/desktop-wallet.html).
|
||||
* Platform build instructions are available on Nym [Operators Guide documentation](https://nymtech.net/operators/binaries/building-nym.html).
|
||||
* Wallet build instructions are available on Nym [Technical docs](https://nymtech.net/docs/wallet/desktop-wallet.html).
|
||||
|
||||
### Developing
|
||||
|
||||
There's a `.env.sample-dev` file provided which you can rename to `.env` if you want convenient logging, backtrace, or other environment variables pre-set. The `.env` file is ignored so you don't need to worry about checking it in.
|
||||
There's a [`sandbox.env`](https://github.com/nymtech/nym/envs/sandbox.env) file provided which you can rename to `.env` if you want convenient testing environment. Read more about sandbox environment in our [Operators Guide page](https://nymtech.net/operators/sandbox.html).
|
||||
|
||||
For Typescript components, please see [ts-packages](./ts-packages).
|
||||
References for developers:
|
||||
|
||||
* [Developers Portal](https://nymtech.net/developers)
|
||||
* [Typescript SDKs](https://sdk.nymtech.net/)
|
||||
* [Technical Documentation - Nym network overview](https://nymtech.net/docs/)
|
||||
* [Release Cycle - git flow](https://nymtech.net/operators/release-cycle.html)
|
||||
|
||||
### 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 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)
|
||||
* The various developer channels on [Discord](https://nymtech.net/go/discord)
|
||||
|
||||
### Rewards
|
||||
### Tokenomics & Rewards
|
||||
|
||||
Node, node operator and delegator rewards are determined according to the principles laid out in the section 6 of [Nym Whitepaper](https://nymtech.net/nym-whitepaper.pdf). Below is a TLDR of the variables and formulas involved in calculating the epoch rewards. Initial reward pool is set to 250 million Nym, making the circulating supply 750 million Nym.
|
||||
|
||||
|Symbol|Definition|
|
||||
|---|---|
|
||||
|<img src="https://render.githubusercontent.com/render/math?math=R#gh-light-mode-only"><img src="https://render.githubusercontent.com/render/math?math=\color{white}R#gh-dark-mode-only">|global share of rewards available, starts at 2% of the reward pool.
|
||||
|<img src="https://render.githubusercontent.com/render/math?math=R_{i}#gh-light-mode-only"><img src="https://render.githubusercontent.com/render/math?math=\color{white}R_{i}#gh-dark-mode-only">|node reward for mixnode `i`.
|
||||
|<img src="https://render.githubusercontent.com/render/math?math=\sigma_{i}#gh-light-mode-only"><img src="https://render.githubusercontent.com/render/math?math=\color{white}\sigma_{i}#gh-dark-mode-only">|ratio of total node stake (node bond + all delegations) to the token circulating supply.
|
||||
|<img src="https://render.githubusercontent.com/render/math?math=\lambda_{i}#gh-light-mode-only"><img src="https://render.githubusercontent.com/render/math?math=\color{white}\lambda_{i}#gh-dark-mode-only">|ratio of stake operator has pledged to their node to the token circulating supply.
|
||||
|<img src="https://render.githubusercontent.com/render/math?math=\omega_{i}#gh-light-mode-only"><img src="https://render.githubusercontent.com/render/math?math=\color{white}\omega_{i}#gh-dark-mode-only">|fraction of total effort undertaken by node `i`, set to `1/k`.
|
||||
|<img src="https://render.githubusercontent.com/render/math?math=k#gh-light-mode-only"><img src="https://render.githubusercontent.com/render/math?math=\color{white}k#gh-dark-mode-only">|number of nodes stakeholders are incentivised to create, set by the validators, a matter of governance. Currently determined by the `reward set` size, and set to 720 in testnet Sandbox.
|
||||
|<img src="https://render.githubusercontent.com/render/math?math=\alpha#gh-light-mode-only"><img src="https://render.githubusercontent.com/render/math?math=\color{white}\alpha#gh-dark-mode-only">|A Sybil attack resistance parameter - the higher this parameter is set, the stronger the reduction in competitiveness for a Sybil attacker.
|
||||
|<img src="https://render.githubusercontent.com/render/math?math=PM_{i}#gh-light-mode-only"><img src="https://render.githubusercontent.com/render/math?math=\color{white}PM_{i}#gh-dark-mode-only">|declared profit margin of operator `i`, defaults to 10%.
|
||||
|<img src="https://render.githubusercontent.com/render/math?math=PF_{i}#gh-light-mode-only"><img src="https://render.githubusercontent.com/render/math?math=\color{white}PF_{i}#gh-dark-mode-only">|uptime of node `i`, scaled to 0 - 1, for the rewarding epoch
|
||||
|<img src="https://render.githubusercontent.com/render/math?math=PP_{i}#gh-light-mode-only"><img src="https://render.githubusercontent.com/render/math?math=\color{white}PP_{i}#gh-dark-mode-only">|cost of operating node `i` for the duration of the rewarding epoch, set to 40 NYMs.
|
||||
|
||||
Node reward for node `i` is determined as:
|
||||
|
||||
<img src="https://render.githubusercontent.com/render/math?math=R_{i}=PF_{i} \cdot R \cdot (\sigma^'_{i} \cdot \omega_{i} \cdot k %2b \alpha \cdot \lambda^'_{i} \cdot \sigma^'_{i} \cdot k)/(1 %2b \alpha)#gh-light-mode-only">
|
||||
<img src="https://render.githubusercontent.com/render/math?math=\color{white}R_{i}=PF_{i} \cdot R \cdot (\sigma^'_{i} \cdot \omega_{i} \cdot k %2b \alpha \cdot \lambda^'_{i} \cdot \sigma^'_{i} \cdot k)/(1 %2b \alpha)#gh-dark-mode-only">
|
||||
where:
|
||||
|
||||
<img src="https://render.githubusercontent.com/render/math?math=\sigma^'_{i} = min\{\sigma_{i}, 1/k\}#gh-light-mode-only">
|
||||
<img src="https://render.githubusercontent.com/render/math?math=\color{white}\sigma^'_{i} = min\{\sigma_{i}, 1/k\}#gh-dark-mode-only">
|
||||
|
||||
and
|
||||
|
||||
<img src="https://render.githubusercontent.com/render/math?math=\lambda^'_{i} = min\{\lambda_{i}, 1/k\}#gh-light-mode-only">
|
||||
<img src="https://render.githubusercontent.com/render/math?math=\color{white}\lambda^'_{i} = min\{\lambda_{i}, 1/k\}#gh-dark-mode-only">
|
||||
|
||||
Operator of node `i` is credited with the following amount:
|
||||
|
||||
<img src="https://render.githubusercontent.com/render/math?math=min\{PP_{i},R_{i})\} %2b max\{0, (PM_{i} %2b (1 - PM_{i}) \cdot \lambda_{i}/\delta_{i}) \cdot (R_{i} - PP_{i})\}#gh-light-mode-only">
|
||||
<img src="https://render.githubusercontent.com/render/math?math=\color{white}min\{PP_{i},R_{i})\} %2b max\{0, (PM_{i} %2b (1 - PM_{i}) \cdot \lambda_{i}/\delta_{i}) \cdot (R_{i} - PP_{i})\}#gh-dark-mode-only">
|
||||
|
||||
Delegate with stake `s` receives:
|
||||
|
||||
<img src="https://render.githubusercontent.com/render/math?math=max\{0, (1-PM_{i}) \cdot (s^'/\sigma_{i}) \cdot (R_{i} - PP_{i})\}#gh-light-mode-only">
|
||||
<img src="https://render.githubusercontent.com/render/math?math=\color{white}max\{0, (1-PM_{i}) \cdot (s^'/\sigma_{i}) \cdot (R_{i} - PP_{i})\}#gh-dark-mode-only">
|
||||
|
||||
where `s'` is stake `s` scaled over total token circulating supply.
|
||||
Nym network economic incentives, operator and validator rewards, and scalability of the network are determined according to the principles laid out in the section 6 of [Nym Whitepaper](https://nymtech.net/nym-whitepaper.pdf).
|
||||
Initial reward pool is set to 250 million Nym, making the circulating supply 750 million Nym.
|
||||
|
||||
### Licensing and copyright information
|
||||
|
||||
This is a monorepo and components that make up Nym as a system are licensed individually, so for accurate information, please check individual files.
|
||||
|
||||
As a general approach, licensing is as follows this pattern:
|
||||
|
||||
- applications and binaries are GPLv3
|
||||
- libraries and components are Apache 2.0 or MIT
|
||||
- documentation is Apache 2.0 or CC0-1.0
|
||||
|
||||
Again, for accurate information, please check individual files.
|
||||
Nym Node Operators and Validators Temrs and Conditions can be found [here](https://nymtech.net/terms-and-conditions/operators/v1.0.0).
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "nym-client"
|
||||
version = "1.1.37"
|
||||
version = "1.1.38"
|
||||
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jędrzej Stuczyński <andrew@nymtech.net>"]
|
||||
description = "Implementation of the Nym Client"
|
||||
edition = "2021"
|
||||
@@ -23,7 +23,7 @@ url = { workspace = true }
|
||||
|
||||
bs58 = { workspace = true }
|
||||
clap = { workspace = true, features = ["cargo", "derive"] }
|
||||
dirs = "4.0"
|
||||
dirs = { workspace = true }
|
||||
log = { workspace = true } # self explanatory
|
||||
rand = { workspace = true }
|
||||
serde = { workspace = true, features = ["derive"] } # for config serialization/deserialization
|
||||
@@ -37,7 +37,7 @@ zeroize = { workspace = true }
|
||||
|
||||
## internal
|
||||
nym-bandwidth-controller = { path = "../../common/bandwidth-controller" }
|
||||
nym-bin-common = { path = "../../common/bin-common", features = ["output_format"] }
|
||||
nym-bin-common = { path = "../../common/bin-common", features = ["output_format", "clap"] }
|
||||
nym-client-core = { path = "../../common/client-core", features = ["fs-surb-storage", "fs-gateways-storage", "cli"] }
|
||||
nym-config = { path = "../../common/config" }
|
||||
nym-credential-storage = { path = "../../common/credential-storage" }
|
||||
|
||||
@@ -106,8 +106,10 @@ impl SocketClient {
|
||||
};
|
||||
|
||||
let storage = self.initialise_storage().await?;
|
||||
let user_agent = nym_bin_common::bin_info!().into();
|
||||
|
||||
let mut base_client = BaseClientBuilder::new(&self.config.base, storage, dkg_query_client);
|
||||
let mut base_client = BaseClientBuilder::new(&self.config.base, storage, dkg_query_client)
|
||||
.with_user_agent(user_agent);
|
||||
|
||||
if let Some(custom_mixnet) = &self.custom_mixnet {
|
||||
base_client = base_client.with_stored_topology(custom_mixnet)?;
|
||||
|
||||
@@ -22,8 +22,9 @@ impl AsRef<CommonClientAddGatewayArgs> for Args {
|
||||
}
|
||||
|
||||
pub(crate) async fn execute(args: Args) -> Result<(), ClientError> {
|
||||
let user_agent = nym_bin_common::bin_info!().into();
|
||||
let output = args.output;
|
||||
let res = add_gateway::<CliNativeClient, _>(args).await?;
|
||||
let res = add_gateway::<CliNativeClient, _>(args, Some(user_agent)).await?;
|
||||
|
||||
println!("{}", output.format(&res));
|
||||
Ok(())
|
||||
|
||||
@@ -73,7 +73,6 @@ impl From<Init> for OverrideConfig {
|
||||
fn from(init_config: Init) -> Self {
|
||||
OverrideConfig {
|
||||
nym_apis: init_config.common_args.nym_apis,
|
||||
fronting_domains: init_config.common_args.fronting_domains,
|
||||
disable_socket: init_config.disable_socket,
|
||||
port: init_config.port,
|
||||
host: init_config.host,
|
||||
@@ -115,8 +114,9 @@ impl Display for InitResults {
|
||||
pub(crate) async fn execute(args: Init) -> Result<(), ClientError> {
|
||||
eprintln!("Initialising client...");
|
||||
|
||||
let user_agent = nym_bin_common::bin_info!().into();
|
||||
let output = args.output;
|
||||
let res = initialise_client::<CliNativeClient>(args).await?;
|
||||
let res = initialise_client::<CliNativeClient>(args, Some(user_agent)).await?;
|
||||
|
||||
let init_results = InitResults::new(res);
|
||||
println!("{}", output.format(&init_results));
|
||||
|
||||
@@ -97,7 +97,6 @@ pub(crate) enum Commands {
|
||||
// Configuration that can be overridden.
|
||||
pub(crate) struct OverrideConfig {
|
||||
nym_apis: Option<Vec<url::Url>>,
|
||||
fronting_domains: Option<Vec<url::Url>>,
|
||||
disable_socket: Option<bool>,
|
||||
port: Option<u16>,
|
||||
host: Option<IpAddr>,
|
||||
@@ -134,10 +133,6 @@ pub(crate) fn override_config(config: Config, args: OverrideConfig) -> Config {
|
||||
.with_base(BaseClientConfig::with_disabled_cover_traffic, args.no_cover)
|
||||
.with_optional(Config::with_port, args.port)
|
||||
.with_optional(Config::with_host, args.host)
|
||||
.with_optional_ext(
|
||||
BaseClientConfig::with_fronting_domains,
|
||||
args.fronting_domains,
|
||||
)
|
||||
.with_optional_custom_env_ext(
|
||||
BaseClientConfig::with_custom_nym_apis,
|
||||
args.nym_apis,
|
||||
|
||||
@@ -36,7 +36,6 @@ impl From<Run> for OverrideConfig {
|
||||
fn from(run_config: Run) -> Self {
|
||||
OverrideConfig {
|
||||
nym_apis: run_config.common_args.nym_apis,
|
||||
fronting_domains: run_config.common_args.fronting_domains,
|
||||
disable_socket: run_config.disable_socket,
|
||||
port: run_config.port,
|
||||
host: run_config.host,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "nym-socks5-client"
|
||||
version = "1.1.37"
|
||||
version = "1.1.38"
|
||||
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"]
|
||||
description = "A SOCKS5 localhost proxy that converts incoming messages to Sphinx and sends them to a Nym address"
|
||||
edition = "2021"
|
||||
@@ -25,17 +25,18 @@ zeroize = { workspace = true }
|
||||
nym-bin-common = { path = "../../common/bin-common", features = ["output_format"] }
|
||||
nym-client-core = { path = "../../common/client-core", features = ["fs-surb-storage", "fs-gateways-storage", "cli"] }
|
||||
nym-config = { path = "../../common/config" }
|
||||
nym-credential-storage = { path = "../../common/credential-storage" }
|
||||
nym-credentials = { path = "../../common/credentials" }
|
||||
nym-crypto = { path = "../../common/crypto" }
|
||||
nym-gateway-requests = { path = "../../gateway/gateway-requests" }
|
||||
nym-credential-storage = { path = "../../common/credential-storage" }
|
||||
nym-id = { path = "../../common/nym-id" }
|
||||
nym-network-defaults = { path = "../../common/network-defaults" }
|
||||
nym-sphinx = { path = "../../common/nymsphinx" }
|
||||
nym-ordered-buffer = { path = "../../common/socks5/ordered-buffer" }
|
||||
nym-pemstore = { path = "../../common/pemstore" }
|
||||
nym-topology = { path = "../../common/topology" }
|
||||
nym-socks5-client-core = { path = "../../common/socks5-client-core" }
|
||||
nym-id = { path = "../../common/nym-id" }
|
||||
nym-sphinx = { path = "../../common/nymsphinx" }
|
||||
nym-topology = { path = "../../common/topology" }
|
||||
nym-validator-client = { path = "../../common/client-libs/validator-client", features = ["http-client"] }
|
||||
|
||||
[features]
|
||||
default = []
|
||||
|
||||
@@ -22,8 +22,9 @@ impl AsRef<CommonClientAddGatewayArgs> for Args {
|
||||
}
|
||||
|
||||
pub(crate) async fn execute(args: Args) -> Result<(), Socks5ClientError> {
|
||||
let user_agent = nym_bin_common::bin_info!().into();
|
||||
let output = args.output;
|
||||
let res = add_gateway::<CliSocks5Client, _>(args).await?;
|
||||
let res = add_gateway::<CliSocks5Client, _>(args, Some(user_agent)).await?;
|
||||
|
||||
println!("{}", output.format(&res));
|
||||
Ok(())
|
||||
|
||||
@@ -129,8 +129,9 @@ impl Display for InitResults {
|
||||
pub(crate) async fn execute(args: Init) -> Result<(), Socks5ClientError> {
|
||||
eprintln!("Initialising client...");
|
||||
|
||||
let user_agent = nym_bin_common::bin_info!().into();
|
||||
let output = args.output;
|
||||
let res = initialise_client::<CliSocks5Client>(args).await?;
|
||||
let res = initialise_client::<CliSocks5Client>(args, Some(user_agent)).await?;
|
||||
|
||||
let init_results = InitResults::new(res);
|
||||
println!("{}", output.format(&init_results));
|
||||
|
||||
@@ -116,7 +116,13 @@ pub(crate) async fn execute(args: Run) -> Result<(), Box<dyn std::error::Error +
|
||||
let storage =
|
||||
OnDiskPersistent::from_paths(config.storage_paths.common_paths, &config.core.base.debug)
|
||||
.await?;
|
||||
NymClient::new(config.core, storage, args.common_args.custom_mixnet)
|
||||
.run_forever()
|
||||
.await
|
||||
let user_agent = nym_bin_common::bin_info!().into();
|
||||
NymClient::new(
|
||||
config.core,
|
||||
storage,
|
||||
user_agent,
|
||||
args.common_args.custom_mixnet,
|
||||
)
|
||||
.run_forever()
|
||||
.await
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
[package]
|
||||
name = "nym-authenticator-requests"
|
||||
version = "0.1.0"
|
||||
authors.workspace = true
|
||||
repository.workspace = true
|
||||
homepage.workspace = true
|
||||
documentation.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
|
||||
[dependencies]
|
||||
bincode = { workspace = true }
|
||||
rand = { workspace = true }
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
|
||||
nym-sphinx = { path = "../nymsphinx" }
|
||||
nym-wireguard-types = { path = "../wireguard-types" }
|
||||
@@ -0,0 +1,13 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
pub mod v1;
|
||||
|
||||
pub const CURRENT_VERSION: u8 = 1;
|
||||
|
||||
fn make_bincode_serializer() -> impl bincode::Options {
|
||||
use bincode::Options;
|
||||
bincode::DefaultOptions::new()
|
||||
.with_big_endian()
|
||||
.with_varint_encoding()
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
pub mod request;
|
||||
pub mod response;
|
||||
|
||||
const VERSION: u8 = 1;
|
||||
@@ -0,0 +1,84 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use nym_sphinx::addressing::Recipient;
|
||||
use nym_wireguard_types::{GatewayClient, InitMessage, PeerPublicKey};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::make_bincode_serializer;
|
||||
|
||||
use super::VERSION;
|
||||
|
||||
fn generate_random() -> u64 {
|
||||
use rand::RngCore;
|
||||
let mut rng = rand::rngs::OsRng;
|
||||
rng.next_u64()
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct AuthenticatorRequest {
|
||||
pub version: u8,
|
||||
pub data: AuthenticatorRequestData,
|
||||
pub reply_to: Recipient,
|
||||
pub request_id: u64,
|
||||
}
|
||||
|
||||
impl AuthenticatorRequest {
|
||||
pub fn from_reconstructed_message(
|
||||
message: &nym_sphinx::receiver::ReconstructedMessage,
|
||||
) -> Result<Self, bincode::Error> {
|
||||
use bincode::Options;
|
||||
make_bincode_serializer().deserialize(&message.message)
|
||||
}
|
||||
|
||||
pub fn new_initial_request(init_message: InitMessage, reply_to: Recipient) -> (Self, u64) {
|
||||
let request_id = generate_random();
|
||||
(
|
||||
Self {
|
||||
version: VERSION,
|
||||
data: AuthenticatorRequestData::Initial(init_message),
|
||||
reply_to,
|
||||
request_id,
|
||||
},
|
||||
request_id,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn new_final_request(gateway_client: GatewayClient, reply_to: Recipient) -> (Self, u64) {
|
||||
let request_id = generate_random();
|
||||
(
|
||||
Self {
|
||||
version: VERSION,
|
||||
data: AuthenticatorRequestData::Final(gateway_client),
|
||||
reply_to,
|
||||
request_id,
|
||||
},
|
||||
request_id,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn new_query_request(peer_public_key: PeerPublicKey, reply_to: Recipient) -> (Self, u64) {
|
||||
let request_id = generate_random();
|
||||
(
|
||||
Self {
|
||||
version: VERSION,
|
||||
data: AuthenticatorRequestData::QueryBandwidth(peer_public_key),
|
||||
reply_to,
|
||||
request_id,
|
||||
},
|
||||
request_id,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn to_bytes(&self) -> Result<Vec<u8>, bincode::Error> {
|
||||
use bincode::Options;
|
||||
make_bincode_serializer().serialize(self)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub enum AuthenticatorRequestData {
|
||||
Initial(InitMessage),
|
||||
Final(GatewayClient),
|
||||
QueryBandwidth(PeerPublicKey),
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use nym_sphinx::addressing::Recipient;
|
||||
use nym_wireguard_types::registration::{RegistrationData, RegistredData, RemainingBandwidthData};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::make_bincode_serializer;
|
||||
|
||||
use super::VERSION;
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct AuthenticatorResponse {
|
||||
pub version: u8,
|
||||
pub data: AuthenticatorResponseData,
|
||||
pub reply_to: Recipient,
|
||||
}
|
||||
|
||||
impl AuthenticatorResponse {
|
||||
pub fn new_pending_registration_success(
|
||||
registration_data: RegistrationData,
|
||||
request_id: u64,
|
||||
reply_to: Recipient,
|
||||
) -> Self {
|
||||
Self {
|
||||
version: VERSION,
|
||||
data: AuthenticatorResponseData::PendingRegistration(PendingRegistrationResponse {
|
||||
reply: registration_data,
|
||||
reply_to,
|
||||
request_id,
|
||||
}),
|
||||
reply_to,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_registered(
|
||||
registred_data: RegistredData,
|
||||
reply_to: Recipient,
|
||||
request_id: u64,
|
||||
) -> Self {
|
||||
Self {
|
||||
version: VERSION,
|
||||
data: AuthenticatorResponseData::Registered(RegisteredResponse {
|
||||
reply: registred_data,
|
||||
reply_to,
|
||||
request_id,
|
||||
}),
|
||||
reply_to,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_remaining_bandwidth(
|
||||
remaining_bandwidth_data: Option<RemainingBandwidthData>,
|
||||
reply_to: Recipient,
|
||||
request_id: u64,
|
||||
) -> Self {
|
||||
Self {
|
||||
version: VERSION,
|
||||
data: AuthenticatorResponseData::RemainingBandwidth(RemainingBandwidthResponse {
|
||||
reply: remaining_bandwidth_data,
|
||||
reply_to,
|
||||
request_id,
|
||||
}),
|
||||
reply_to,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn recipient(&self) -> Recipient {
|
||||
self.reply_to
|
||||
}
|
||||
|
||||
pub fn to_bytes(&self) -> Result<Vec<u8>, bincode::Error> {
|
||||
use bincode::Options;
|
||||
make_bincode_serializer().serialize(self)
|
||||
}
|
||||
|
||||
pub fn from_reconstructed_message(
|
||||
message: &nym_sphinx::receiver::ReconstructedMessage,
|
||||
) -> Result<Self, bincode::Error> {
|
||||
use bincode::Options;
|
||||
make_bincode_serializer().deserialize(&message.message)
|
||||
}
|
||||
|
||||
pub fn id(&self) -> Option<u64> {
|
||||
match &self.data {
|
||||
AuthenticatorResponseData::PendingRegistration(response) => Some(response.request_id),
|
||||
AuthenticatorResponseData::Registered(response) => Some(response.request_id),
|
||||
AuthenticatorResponseData::RemainingBandwidth(response) => Some(response.request_id),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub enum AuthenticatorResponseData {
|
||||
PendingRegistration(PendingRegistrationResponse),
|
||||
Registered(RegisteredResponse),
|
||||
RemainingBandwidth(RemainingBandwidthResponse),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct PendingRegistrationResponse {
|
||||
pub request_id: u64,
|
||||
pub reply_to: Recipient,
|
||||
pub reply: RegistrationData,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct RegisteredResponse {
|
||||
pub request_id: u64,
|
||||
pub reply_to: Recipient,
|
||||
pub reply: RegistredData,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct RemainingBandwidthResponse {
|
||||
pub request_id: u64,
|
||||
pub reply_to: Recipient,
|
||||
pub reply: Option<RemainingBandwidthData>,
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// See other comments for other TaskStatus message enumds about abusing the Error trait when we
|
||||
// should have a new trait for TaskStatus messages
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum BandwidthStatusMessage {
|
||||
#[error("remaining bandwidth: {0}")]
|
||||
RemainingBandwidth(i64),
|
||||
|
||||
#[error("no bandwidth left")]
|
||||
NoBandwidth,
|
||||
}
|
||||
@@ -14,8 +14,11 @@ use nym_validator_client::coconut::all_coconut_api_clients;
|
||||
use nym_validator_client::nym_api::EpochId;
|
||||
use nym_validator_client::nyxd::contract_traits::DkgQueryClient;
|
||||
|
||||
pub use event::BandwidthStatusMessage;
|
||||
|
||||
pub mod acquire;
|
||||
pub mod error;
|
||||
mod event;
|
||||
mod utils;
|
||||
|
||||
#[derive(Debug)]
|
||||
|
||||
@@ -9,9 +9,9 @@ repository = { workspace = true }
|
||||
|
||||
[dependencies]
|
||||
const-str = { workspace = true }
|
||||
clap = { workspace = true, features = ["derive"] }
|
||||
clap_complete = { workspace = true }
|
||||
clap_complete_fig = { workspace = true }
|
||||
clap = { workspace = true, features = ["derive"], optional = true }
|
||||
clap_complete = { workspace = true, optional = true }
|
||||
clap_complete_fig = { workspace = true, optional = true }
|
||||
log = { workspace = true }
|
||||
pretty_env_logger = { workspace = true }
|
||||
semver = "0.11"
|
||||
@@ -34,7 +34,7 @@ vergen = { workspace = true, features = ["build", "git", "gitcl", "rustc", "carg
|
||||
[features]
|
||||
default = []
|
||||
openapi = ["utoipa"]
|
||||
output_format = ["serde_json"]
|
||||
output_format = ["serde_json", "dep:clap"]
|
||||
bin_info_schema = ["schemars"]
|
||||
basic_tracing = ["tracing-subscriber"]
|
||||
tracing = [
|
||||
@@ -44,3 +44,4 @@ tracing = [
|
||||
"tracing-opentelemetry",
|
||||
"opentelemetry",
|
||||
]
|
||||
clap = [ "dep:clap", "dep:clap_complete", "dep:clap_complete_fig" ]
|
||||
|
||||
@@ -44,6 +44,10 @@ pub struct BinaryBuildInformation {
|
||||
/// Provides the cargo debug mode that was used for the build.
|
||||
// NOTE: keep the old name cargo_profile instead of cargo_debug for backwards compatibility
|
||||
pub cargo_profile: &'static str,
|
||||
|
||||
// VERGEN_CARGO_TARGET_TRIPLE
|
||||
/// Provides the cargo target triple that was used for the build.
|
||||
pub cargo_triple: &'static str,
|
||||
}
|
||||
|
||||
impl BinaryBuildInformation {
|
||||
@@ -66,6 +70,7 @@ impl BinaryBuildInformation {
|
||||
rustc_version: env!("VERGEN_RUSTC_SEMVER"),
|
||||
rustc_channel: env!("VERGEN_RUSTC_CHANNEL"),
|
||||
cargo_profile,
|
||||
cargo_triple: env!("VERGEN_CARGO_TARGET_TRIPLE"),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,6 +100,7 @@ impl BinaryBuildInformation {
|
||||
rustc_version: env!("VERGEN_RUSTC_SEMVER"),
|
||||
rustc_channel: env!("VERGEN_RUSTC_CHANNEL"),
|
||||
cargo_profile,
|
||||
cargo_triple: env!("VERGEN_CARGO_TARGET_TRIPLE"),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,6 +115,7 @@ impl BinaryBuildInformation {
|
||||
rustc_version: self.rustc_version.to_owned(),
|
||||
rustc_channel: self.rustc_channel.to_owned(),
|
||||
cargo_profile: self.cargo_profile.to_owned(),
|
||||
cargo_triple: self.cargo_triple.to_owned(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,6 +163,15 @@ pub struct BinaryBuildInformationOwned {
|
||||
/// Provides the cargo debug mode that was used for the build.
|
||||
// NOTE: keep the old name cargo_profile instead of cargo_debug for backwards compatibility
|
||||
pub cargo_profile: String,
|
||||
|
||||
// VERGEN_CARGO_TARGET_TRIPLE
|
||||
/// Provides the cargo target triple that was used for the build.
|
||||
#[serde(default = "unknown")]
|
||||
pub cargo_triple: String,
|
||||
}
|
||||
|
||||
fn unknown() -> String {
|
||||
"unknown".to_string()
|
||||
}
|
||||
|
||||
impl Display for BinaryBuildInformationOwned {
|
||||
|
||||
@@ -2,9 +2,11 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
pub mod build_information;
|
||||
pub mod completions;
|
||||
pub mod logging;
|
||||
pub mod version_checker;
|
||||
|
||||
#[cfg(feature = "clap")]
|
||||
pub mod completions;
|
||||
|
||||
#[cfg(feature = "output_format")]
|
||||
pub mod output_format;
|
||||
|
||||
@@ -10,7 +10,7 @@ license.workspace = true
|
||||
|
||||
[dependencies]
|
||||
async-trait = { workspace = true }
|
||||
base64 = "0.21.2"
|
||||
base64 = { workspace = true }
|
||||
bs58 = { workspace = true }
|
||||
cfg-if = { workspace = true }
|
||||
clap = { workspace = true, optional = true }
|
||||
@@ -20,7 +20,7 @@ log = { workspace = true }
|
||||
rand = { workspace = true }
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
serde_json = { workspace = true }
|
||||
sha2 = "0.10.6"
|
||||
sha2 = { workspace = true }
|
||||
si-scale = { workspace = true }
|
||||
tap = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
|
||||
@@ -117,11 +117,6 @@ impl Config {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_fronting_domains(mut self, fronting_domains: Vec<Url>) -> Self {
|
||||
self.client.fronting_domains = Some(fronting_domains);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn set_custom_nym_apis(&mut self, nym_api_urls: Vec<Url>) {
|
||||
self.client.nym_api_urls = nym_api_urls;
|
||||
}
|
||||
@@ -294,10 +289,6 @@ impl Config {
|
||||
pub fn get_nym_api_endpoints(&self) -> Vec<Url> {
|
||||
self.client.nym_api_urls.clone()
|
||||
}
|
||||
|
||||
pub fn get_fronting_domains(&self) -> Option<Vec<Url>> {
|
||||
self.client.fronting_domains.clone()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
|
||||
@@ -323,9 +314,6 @@ pub struct Client {
|
||||
/// Addresses to APIs running on validator from which the client gets the view of the network.
|
||||
#[serde(alias = "validator_api_urls")]
|
||||
pub nym_api_urls: Vec<Url>,
|
||||
|
||||
/// Domain to use for domain fronting censorship circumvention
|
||||
pub fronting_domains: Option<Vec<Url>>,
|
||||
}
|
||||
|
||||
impl Client {
|
||||
@@ -352,7 +340,6 @@ impl Client {
|
||||
disabled_credentials_mode: true,
|
||||
nyxd_urls,
|
||||
nym_api_urls,
|
||||
fronting_domains: None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -362,7 +349,6 @@ impl Client {
|
||||
disabled_credentials_mode: bool,
|
||||
nyxd_urls: Vec<Url>,
|
||||
nym_api_urls: Vec<Url>,
|
||||
fronting_domains: Option<Vec<Url>>,
|
||||
) -> Self {
|
||||
Client {
|
||||
version: version.into(),
|
||||
@@ -370,7 +356,6 @@ impl Client {
|
||||
disabled_credentials_mode,
|
||||
nyxd_urls,
|
||||
nym_api_urls,
|
||||
fronting_domains,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,7 +95,6 @@ impl From<ConfigV5> for Config {
|
||||
id: value.client.id,
|
||||
disabled_credentials_mode: value.client.disabled_credentials_mode,
|
||||
nyxd_urls: value.client.nyxd_urls,
|
||||
fronting_domains: None, //SW need proper migrations if it gets applied
|
||||
nym_api_urls: value.client.nym_api_urls,
|
||||
},
|
||||
debug: DebugConfig {
|
||||
|
||||
@@ -16,6 +16,7 @@ use log::info;
|
||||
use nym_client_core_gateways_storage::GatewayDetails;
|
||||
use nym_crypto::asymmetric::identity;
|
||||
use nym_topology::NymTopology;
|
||||
use nym_validator_client::UserAgent;
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[cfg_attr(feature = "cli", derive(clap::Args))]
|
||||
@@ -60,7 +61,10 @@ pub struct CommonClientAddGatewayArgs {
|
||||
pub custom_mixnet: Option<PathBuf>,
|
||||
}
|
||||
|
||||
pub async fn add_gateway<C, A>(args: A) -> Result<GatewayInfo, C::Error>
|
||||
pub async fn add_gateway<C, A>(
|
||||
args: A,
|
||||
user_agent: Option<UserAgent>,
|
||||
) -> Result<GatewayInfo, C::Error>
|
||||
where
|
||||
A: AsRef<CommonClientAddGatewayArgs>,
|
||||
C: CliClient,
|
||||
@@ -111,7 +115,8 @@ where
|
||||
hardcoded_topology.get_gateways()
|
||||
} else {
|
||||
let mut rng = rand::thread_rng();
|
||||
crate::init::helpers::current_gateways(&mut rng, &core.client.nym_api_urls, None).await?
|
||||
crate::init::helpers::current_gateways(&mut rng, &core.client.nym_api_urls, user_agent)
|
||||
.await?
|
||||
};
|
||||
|
||||
// since we're registering with a brand new gateway,
|
||||
|
||||
@@ -16,6 +16,7 @@ use log::info;
|
||||
use nym_client_core_gateways_storage::GatewayDetails;
|
||||
use nym_crypto::asymmetric::identity;
|
||||
use nym_topology::NymTopology;
|
||||
use nym_validator_client::UserAgent;
|
||||
use rand::rngs::OsRng;
|
||||
use std::path::PathBuf;
|
||||
|
||||
@@ -70,13 +71,6 @@ pub struct CommonClientInitArgs {
|
||||
)]
|
||||
pub nym_apis: Option<Vec<url::Url>>,
|
||||
|
||||
///Comma separated list of urls to use for domain fronting
|
||||
#[cfg_attr(
|
||||
feature = "cli",
|
||||
clap(long, value_delimiter = ',', requires = "nym_apis", hide = true)
|
||||
)]
|
||||
pub fronting_domains: Option<Vec<url::Url>>,
|
||||
|
||||
/// Path to .json file containing custom network specification.
|
||||
#[cfg_attr(feature = "cli", clap(long, group = "network", hide = true))]
|
||||
pub custom_mixnet: Option<PathBuf>,
|
||||
@@ -103,6 +97,7 @@ pub struct InitResultsWithConfig<T> {
|
||||
|
||||
pub async fn initialise_client<C>(
|
||||
init_args: C::InitArgs,
|
||||
user_agent: Option<UserAgent>,
|
||||
) -> Result<InitResultsWithConfig<C::Config>, C::Error>
|
||||
where
|
||||
C: InitialisableClient,
|
||||
@@ -151,16 +146,6 @@ where
|
||||
.collect::<Vec<&str>>()
|
||||
.join(",")
|
||||
);
|
||||
if let Some(fronting_domains) = &core.client.fronting_domains {
|
||||
log::info!(
|
||||
"fronted by : {}",
|
||||
fronting_domains
|
||||
.iter()
|
||||
.map(|url| url.host_str().unwrap_or_default())
|
||||
.collect::<Vec<&str>>()
|
||||
.join(",")
|
||||
);
|
||||
}
|
||||
|
||||
let key_store = OnDiskKeys::new(paths.keys.clone());
|
||||
let details_store = setup_fs_gateways_storage(&paths.gateway_registrations).await?;
|
||||
@@ -180,12 +165,8 @@ where
|
||||
hardcoded_topology.get_gateways()
|
||||
} else {
|
||||
let mut rng = rand::thread_rng();
|
||||
crate::init::helpers::current_gateways(
|
||||
&mut rng,
|
||||
&core.client.nym_api_urls,
|
||||
core.client.fronting_domains.as_ref(),
|
||||
)
|
||||
.await?
|
||||
crate::init::helpers::current_gateways(&mut rng, &core.client.nym_api_urls, user_agent)
|
||||
.await?
|
||||
};
|
||||
|
||||
let gateway_setup = GatewaySetup::New {
|
||||
|
||||
@@ -35,13 +35,6 @@ pub struct CommonClientRunArgs {
|
||||
)]
|
||||
pub nym_apis: Option<Vec<url::Url>>,
|
||||
|
||||
///Comma separated list of urls to use for domain fronting
|
||||
#[cfg_attr(
|
||||
feature = "cli",
|
||||
clap(long, value_delimiter = ',', requires = "nym_apis", hide = true)
|
||||
)]
|
||||
pub fronting_domains: Option<Vec<url::Url>>,
|
||||
|
||||
/// Path to .json file containing custom network specification.
|
||||
#[cfg_attr(feature = "cli", clap(long, group = "network", hide = true))]
|
||||
pub custom_mixnet: Option<PathBuf>,
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
|
||||
use super::packet_statistics_control::PacketStatisticsReporter;
|
||||
use super::received_buffer::ReceivedBufferMessage;
|
||||
use super::topology_control::fronted_api_provider::FrontedApiTopologyProvider;
|
||||
use super::topology_control::geo_aware_provider::GeoAwareTopologyProvider;
|
||||
use crate::client::base_client::storage::helpers::store_client_keys;
|
||||
use crate::client::base_client::storage::MixnetClientStorage;
|
||||
@@ -54,7 +53,7 @@ use nym_task::connections::{ConnectionCommandReceiver, ConnectionCommandSender,
|
||||
use nym_task::{TaskClient, TaskHandle};
|
||||
use nym_topology::provider_trait::TopologyProvider;
|
||||
use nym_topology::HardcodedTopologyProvider;
|
||||
use nym_validator_client::nyxd::contract_traits::DkgQueryClient;
|
||||
use nym_validator_client::{nyxd::contract_traits::DkgQueryClient, UserAgent};
|
||||
use rand::rngs::OsRng;
|
||||
use std::fmt::Debug;
|
||||
use std::os::raw::c_int as RawFd;
|
||||
@@ -185,6 +184,7 @@ pub struct BaseClientBuilder<'a, C, S: MixnetClientStorage> {
|
||||
custom_topology_provider: Option<Box<dyn TopologyProvider + Send + Sync>>,
|
||||
custom_gateway_transceiver: Option<Box<dyn GatewayTransceiver + Send>>,
|
||||
shutdown: Option<TaskClient>,
|
||||
user_agent: Option<UserAgent>,
|
||||
|
||||
setup_method: GatewaySetup,
|
||||
}
|
||||
@@ -208,6 +208,7 @@ where
|
||||
custom_topology_provider: None,
|
||||
custom_gateway_transceiver: None,
|
||||
shutdown: None,
|
||||
user_agent: None,
|
||||
setup_method: GatewaySetup::MustLoad { gateway_id: None },
|
||||
}
|
||||
}
|
||||
@@ -251,6 +252,12 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn with_user_agent(mut self, user_agent: UserAgent) -> Self {
|
||||
self.user_agent = Some(user_agent);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_stored_topology<P: AsRef<Path>>(
|
||||
mut self,
|
||||
file: P,
|
||||
@@ -468,29 +475,19 @@ where
|
||||
custom_provider: Option<Box<dyn TopologyProvider + Send + Sync>>,
|
||||
config_topology: config::Topology,
|
||||
nym_api_urls: Vec<Url>,
|
||||
fronting_domains: Option<Vec<Url>>,
|
||||
user_agent: Option<UserAgent>,
|
||||
) -> Box<dyn TopologyProvider + Send + Sync> {
|
||||
// if no custom provider was ... provided ..., create one using nym-api
|
||||
custom_provider.unwrap_or_else(|| match config_topology.topology_structure {
|
||||
config::TopologyStructure::NymApi => match fronting_domains {
|
||||
Some(domains) => Box::new(FrontedApiTopologyProvider::new(
|
||||
nym_api_provider::Config {
|
||||
min_mixnode_performance: config_topology.minimum_mixnode_performance,
|
||||
min_gateway_performance: config_topology.minimum_gateway_performance,
|
||||
},
|
||||
nym_api_urls,
|
||||
domains,
|
||||
env!("CARGO_PKG_VERSION").to_string(),
|
||||
)),
|
||||
None => Box::new(NymApiTopologyProvider::new(
|
||||
nym_api_provider::Config {
|
||||
min_mixnode_performance: config_topology.minimum_mixnode_performance,
|
||||
min_gateway_performance: config_topology.minimum_gateway_performance,
|
||||
},
|
||||
nym_api_urls,
|
||||
env!("CARGO_PKG_VERSION").to_string(),
|
||||
)),
|
||||
},
|
||||
config::TopologyStructure::NymApi => Box::new(NymApiTopologyProvider::new(
|
||||
nym_api_provider::Config {
|
||||
min_mixnode_performance: config_topology.minimum_mixnode_performance,
|
||||
min_gateway_performance: config_topology.minimum_gateway_performance,
|
||||
},
|
||||
nym_api_urls,
|
||||
env!("CARGO_PKG_VERSION").to_string(),
|
||||
user_agent,
|
||||
)),
|
||||
config::TopologyStructure::GeoAware(group_by) => {
|
||||
Box::new(GeoAwareTopologyProvider::new(
|
||||
nym_api_urls,
|
||||
@@ -702,7 +699,7 @@ where
|
||||
self.custom_topology_provider.take(),
|
||||
self.config.debug.topology,
|
||||
self.config.get_nym_api_endpoints(),
|
||||
self.config.get_fronting_domains(),
|
||||
self.user_agent.clone(),
|
||||
);
|
||||
|
||||
// needs to be started as the first thing to block if required waiting for the gateway
|
||||
|
||||
@@ -1,147 +0,0 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use async_trait::async_trait;
|
||||
use log::{debug, error, warn};
|
||||
use nym_topology::provider_trait::TopologyProvider;
|
||||
use nym_topology::{NymTopology, NymTopologyError};
|
||||
use rand::prelude::SliceRandom;
|
||||
use rand::thread_rng;
|
||||
use url::Url;
|
||||
|
||||
use super::nym_api_provider::Config;
|
||||
|
||||
pub(crate) struct FrontedApiTopologyProvider {
|
||||
config: Config,
|
||||
|
||||
validator_client: nym_validator_client::client::NymApiClient,
|
||||
nym_api_urls: Vec<Url>,
|
||||
fronting_domains: Vec<Url>,
|
||||
shuffling: Vec<usize>,
|
||||
|
||||
client_version: String,
|
||||
currently_used_api: usize,
|
||||
}
|
||||
|
||||
impl FrontedApiTopologyProvider {
|
||||
pub(crate) fn new(
|
||||
config: Config,
|
||||
nym_api_urls: Vec<Url>,
|
||||
fronting_domains: Vec<Url>,
|
||||
client_version: String,
|
||||
) -> Self {
|
||||
//SW for the PoC, we assume same lenght between fronting domains and api_urls
|
||||
let mut shuffling = (0..nym_api_urls.len()).collect::<Vec<_>>();
|
||||
shuffling.shuffle(&mut thread_rng());
|
||||
|
||||
FrontedApiTopologyProvider {
|
||||
config,
|
||||
validator_client: nym_validator_client::client::NymApiClient::new_fronted(
|
||||
nym_api_urls[shuffling[0]].clone(),
|
||||
fronting_domains[shuffling[0]].clone(),
|
||||
),
|
||||
nym_api_urls,
|
||||
fronting_domains,
|
||||
shuffling,
|
||||
client_version,
|
||||
currently_used_api: 0,
|
||||
}
|
||||
}
|
||||
|
||||
fn use_next_nym_api(&mut self) {
|
||||
if self.nym_api_urls.len() == 1 {
|
||||
warn!("There's only a single nym API available - it won't be possible to use a different one");
|
||||
return;
|
||||
}
|
||||
|
||||
self.currently_used_api = (self.currently_used_api + 1) % self.nym_api_urls.len();
|
||||
self.validator_client.change_nym_api_with_fronting(
|
||||
self.nym_api_urls[self.shuffling[self.currently_used_api]].clone(),
|
||||
self.fronting_domains[self.shuffling[self.currently_used_api]].clone(),
|
||||
);
|
||||
}
|
||||
|
||||
/// Verifies whether nodes a reasonably distributed among all mix layers.
|
||||
///
|
||||
/// In ideal world we would have 33% nodes on layer 1, 33% on layer 2 and 33% on layer 3.
|
||||
/// However, this is a rather unrealistic expectation, instead we check whether there exists
|
||||
/// a layer with more than 66% of nodes or with fewer than 15% and if so, we trigger a failure.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `topology`: active topology constructed from validator api data
|
||||
fn check_layer_distribution(
|
||||
&self,
|
||||
active_topology: &NymTopology,
|
||||
) -> Result<(), NymTopologyError> {
|
||||
let lower_threshold = 0.15;
|
||||
let upper_threshold = 0.66;
|
||||
active_topology.ensure_even_layer_distribution(lower_threshold, upper_threshold)
|
||||
}
|
||||
|
||||
async fn get_current_compatible_topology(&mut self) -> Option<NymTopology> {
|
||||
let mixnodes = match self
|
||||
.validator_client
|
||||
.get_basic_mixnodes(Some(self.client_version.clone()))
|
||||
.await
|
||||
{
|
||||
Err(err) => {
|
||||
error!("failed to get network mixnodes - {err}");
|
||||
return None;
|
||||
}
|
||||
Ok(mixes) => mixes,
|
||||
};
|
||||
|
||||
let gateways = match self
|
||||
.validator_client
|
||||
.get_basic_gateways(Some(self.client_version.clone()))
|
||||
.await
|
||||
{
|
||||
Err(err) => {
|
||||
error!("failed to get network gateways - {err}");
|
||||
return None;
|
||||
}
|
||||
Ok(gateways) => gateways,
|
||||
};
|
||||
|
||||
debug!(
|
||||
"there are {} mixnodes and {} gateways in total (before performance filtering)",
|
||||
mixnodes.len(),
|
||||
gateways.len()
|
||||
);
|
||||
|
||||
let topology = NymTopology::from_unordered(
|
||||
mixnodes.iter().filter(|m| {
|
||||
m.performance.round_to_integer() >= self.config.min_mixnode_performance
|
||||
}),
|
||||
gateways.iter().filter(|g| {
|
||||
g.performance.round_to_integer() >= self.config.min_gateway_performance
|
||||
}),
|
||||
);
|
||||
|
||||
if let Err(err) = self.check_layer_distribution(&topology) {
|
||||
warn!("The current filtered active topology has extremely skewed layer distribution. It cannot be used: {err}");
|
||||
self.use_next_nym_api();
|
||||
None
|
||||
} else {
|
||||
Some(topology)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// hehe, wasm
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
#[async_trait]
|
||||
impl TopologyProvider for FrontedApiTopologyProvider {
|
||||
async fn get_new_topology(&mut self) -> Option<NymTopology> {
|
||||
self.get_current_compatible_topology().await
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
#[async_trait(?Send)]
|
||||
impl TopologyProvider for FrontedApiTopologyProvider {
|
||||
async fn get_new_topology(&mut self) -> Option<NymTopology> {
|
||||
self.get_current_compatible_topology().await
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,6 @@ use tokio::time::sleep;
|
||||
use wasmtimer::tokio::sleep;
|
||||
|
||||
mod accessor;
|
||||
pub(crate) mod fronted_api_provider;
|
||||
pub mod geo_aware_provider;
|
||||
pub(crate) mod nym_api_provider;
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ use async_trait::async_trait;
|
||||
use log::{debug, error, warn};
|
||||
use nym_topology::provider_trait::TopologyProvider;
|
||||
use nym_topology::{NymTopology, NymTopologyError};
|
||||
use nym_validator_client::UserAgent;
|
||||
use rand::prelude::SliceRandom;
|
||||
use rand::thread_rng;
|
||||
use url::Url;
|
||||
@@ -39,14 +40,26 @@ pub(crate) struct NymApiTopologyProvider {
|
||||
}
|
||||
|
||||
impl NymApiTopologyProvider {
|
||||
pub(crate) fn new(config: Config, mut nym_api_urls: Vec<Url>, client_version: String) -> Self {
|
||||
pub(crate) fn new(
|
||||
config: Config,
|
||||
mut nym_api_urls: Vec<Url>,
|
||||
client_version: String,
|
||||
user_agent: Option<UserAgent>,
|
||||
) -> Self {
|
||||
nym_api_urls.shuffle(&mut thread_rng());
|
||||
|
||||
let validator_client = if let Some(user_agent) = user_agent {
|
||||
nym_validator_client::client::NymApiClient::new_with_user_agent(
|
||||
nym_api_urls[0].clone(),
|
||||
user_agent,
|
||||
)
|
||||
} else {
|
||||
nym_validator_client::client::NymApiClient::new(nym_api_urls[0].clone())
|
||||
};
|
||||
|
||||
NymApiTopologyProvider {
|
||||
config,
|
||||
validator_client: nym_validator_client::client::NymApiClient::new(
|
||||
nym_api_urls[0].clone(),
|
||||
),
|
||||
validator_client,
|
||||
nym_api_urls,
|
||||
client_version,
|
||||
currently_used_api: 0,
|
||||
|
||||
@@ -9,7 +9,7 @@ use nym_crypto::asymmetric::identity;
|
||||
use nym_gateway_client::GatewayClient;
|
||||
use nym_topology::{filter::VersionFilterable, gateway, mix};
|
||||
use nym_validator_client::client::IdentityKeyRef;
|
||||
use rand::seq::IteratorRandom;
|
||||
use nym_validator_client::UserAgent;
|
||||
use rand::{seq::SliceRandom, Rng};
|
||||
use std::{sync::Arc, time::Duration};
|
||||
use tungstenite::Message;
|
||||
@@ -60,29 +60,18 @@ impl<'a> GatewayWithLatency<'a> {
|
||||
pub async fn current_gateways<R: Rng>(
|
||||
rng: &mut R,
|
||||
nym_apis: &[Url],
|
||||
fronting_domains: Option<&Vec<Url>>,
|
||||
user_agent: Option<UserAgent>,
|
||||
) -> Result<Vec<gateway::Node>, ClientCoreError> {
|
||||
let client = match fronting_domains {
|
||||
Some(domains) => {
|
||||
let (api_url, fronting_url) = nym_apis
|
||||
.iter()
|
||||
.zip(domains)
|
||||
.choose(rng)
|
||||
.ok_or(ClientCoreError::ListOfNymApisIsEmpty)?;
|
||||
|
||||
nym_validator_client::client::NymApiClient::new_fronted(
|
||||
api_url.clone(),
|
||||
fronting_url.clone(),
|
||||
)
|
||||
}
|
||||
None => {
|
||||
let nym_api = nym_apis
|
||||
.choose(rng)
|
||||
.ok_or(ClientCoreError::ListOfNymApisIsEmpty)?;
|
||||
nym_validator_client::client::NymApiClient::new(nym_api.clone())
|
||||
}
|
||||
let nym_api = nym_apis
|
||||
.choose(rng)
|
||||
.ok_or(ClientCoreError::ListOfNymApisIsEmpty)?;
|
||||
let client = if let Some(user_agent) = user_agent {
|
||||
nym_validator_client::client::NymApiClient::new_with_user_agent(nym_api.clone(), user_agent)
|
||||
} else {
|
||||
nym_validator_client::client::NymApiClient::new(nym_api.clone())
|
||||
};
|
||||
log::debug!("Fetching list of gateways from: {}", client.api_url());
|
||||
|
||||
log::debug!("Fetching list of gateways from: {nym_api}");
|
||||
|
||||
let gateways = client.get_cached_described_gateways().await?;
|
||||
log::debug!("Found {} gateways", gateways.len());
|
||||
|
||||
@@ -11,7 +11,7 @@ use crate::traits::GatewayPacketRouter;
|
||||
use crate::{cleanup_socket_message, try_decrypt_binary_message};
|
||||
use futures::{SinkExt, StreamExt};
|
||||
use log::*;
|
||||
use nym_bandwidth_controller::BandwidthController;
|
||||
use nym_bandwidth_controller::{BandwidthController, BandwidthStatusMessage};
|
||||
use nym_credential_storage::ephemeral_storage::EphemeralStorage as EphemeralCredentialStorage;
|
||||
use nym_credential_storage::storage::Storage as CredentialStorage;
|
||||
use nym_credentials::CredentialSpendingData;
|
||||
@@ -105,8 +105,8 @@ pub struct GatewayClient<C, St = EphemeralCredentialStorage> {
|
||||
// currently unused (but populated)
|
||||
negotiated_protocol: Option<u8>,
|
||||
|
||||
/// Listen to shutdown messages.
|
||||
shutdown: TaskClient,
|
||||
/// Listen to shutdown messages and send notifications back to the task manager
|
||||
task_client: TaskClient,
|
||||
}
|
||||
|
||||
impl<C, St> GatewayClient<C, St> {
|
||||
@@ -117,7 +117,7 @@ impl<C, St> GatewayClient<C, St> {
|
||||
shared_key: Option<Arc<SharedKeys>>,
|
||||
packet_router: PacketRouter,
|
||||
bandwidth_controller: Option<BandwidthController<C, St>>,
|
||||
shutdown: TaskClient,
|
||||
task_client: TaskClient,
|
||||
) -> Self {
|
||||
GatewayClient {
|
||||
authenticated: false,
|
||||
@@ -135,7 +135,7 @@ impl<C, St> GatewayClient<C, St> {
|
||||
reconnection_attempts: DEFAULT_RECONNECTION_ATTEMPTS,
|
||||
reconnection_backoff: DEFAULT_RECONNECTION_BACKOFF,
|
||||
negotiated_protocol: None,
|
||||
shutdown,
|
||||
task_client,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -299,7 +299,7 @@ impl<C, St> GatewayClient<C, St> {
|
||||
|
||||
loop {
|
||||
tokio::select! {
|
||||
_ = self.shutdown.recv() => {
|
||||
_ = self.task_client.recv() => {
|
||||
log::trace!("GatewayClient control response: Received shutdown");
|
||||
log::debug!("GatewayClient control response: Exiting");
|
||||
break Err(GatewayClientError::ConnectionClosedGatewayShutdown);
|
||||
@@ -540,6 +540,9 @@ impl<C, St> GatewayClient<C, St> {
|
||||
self.bandwidth_remaining = bandwidth_remaining;
|
||||
self.negotiated_protocol = protocol_version;
|
||||
log::debug!("authenticated: {status}, bandwidth remaining: {bandwidth_remaining}");
|
||||
self.task_client.send_status_msg(Box::new(
|
||||
BandwidthStatusMessage::RemainingBandwidth(bandwidth_remaining),
|
||||
));
|
||||
Ok(())
|
||||
}
|
||||
ServerResponse::Error { message } => Err(GatewayClientError::GatewayError(message)),
|
||||
@@ -805,7 +808,7 @@ impl<C, St> GatewayClient<C, St> {
|
||||
.as_ref()
|
||||
.expect("no shared key present even though we're authenticated!"),
|
||||
),
|
||||
self.shutdown.clone(),
|
||||
self.task_client.clone(),
|
||||
)
|
||||
}
|
||||
_ => unreachable!(),
|
||||
@@ -879,8 +882,8 @@ impl GatewayClient<InitOnly, EphemeralCredentialStorage> {
|
||||
// perfectly fine here, because it's not meant to be used
|
||||
let (ack_tx, _) = mpsc::unbounded();
|
||||
let (mix_tx, _) = mpsc::unbounded();
|
||||
let shutdown = TaskClient::dummy();
|
||||
let packet_router = PacketRouter::new(ack_tx, mix_tx, shutdown.clone());
|
||||
let task_client = TaskClient::dummy();
|
||||
let packet_router = PacketRouter::new(ack_tx, mix_tx, task_client.clone());
|
||||
|
||||
GatewayClient {
|
||||
authenticated: false,
|
||||
@@ -898,7 +901,7 @@ impl GatewayClient<InitOnly, EphemeralCredentialStorage> {
|
||||
reconnection_attempts: DEFAULT_RECONNECTION_ATTEMPTS,
|
||||
reconnection_backoff: DEFAULT_RECONNECTION_BACKOFF,
|
||||
negotiated_protocol: None,
|
||||
shutdown,
|
||||
task_client,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -906,7 +909,7 @@ impl GatewayClient<InitOnly, EphemeralCredentialStorage> {
|
||||
self,
|
||||
packet_router: PacketRouter,
|
||||
bandwidth_controller: Option<BandwidthController<C, St>>,
|
||||
shutdown: TaskClient,
|
||||
task_client: TaskClient,
|
||||
) -> GatewayClient<C, St> {
|
||||
// invariants that can't be broken
|
||||
// (unless somebody decided to expose some field that wasn't meant to be exposed)
|
||||
@@ -930,7 +933,7 @@ impl GatewayClient<InitOnly, EphemeralCredentialStorage> {
|
||||
reconnection_attempts: self.reconnection_attempts,
|
||||
reconnection_backoff: self.reconnection_backoff,
|
||||
negotiated_protocol: self.negotiated_protocol,
|
||||
shutdown,
|
||||
task_client,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ cw-controllers = { workspace = true }
|
||||
prost = { workspace = true, default-features = false }
|
||||
flate2 = { workspace = true }
|
||||
sha2 = { version = "0.9.5" }
|
||||
itertools = { version = "0.10" }
|
||||
itertools = { workspace = true }
|
||||
zeroize = { workspace = true, features = ["zeroize_derive"] }
|
||||
cosmwasm-std = { workspace = true }
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ use nym_api_requests::models::{
|
||||
RewardEstimationResponse, StakeSaturationResponse,
|
||||
};
|
||||
use nym_api_requests::nym_nodes::SkimmedNode;
|
||||
use nym_http_api_client::UserAgent;
|
||||
use nym_network_defaults::NymNetworkDetails;
|
||||
use url::Url;
|
||||
|
||||
@@ -258,8 +259,12 @@ impl NymApiClient {
|
||||
NymApiClient { nym_api }
|
||||
}
|
||||
|
||||
pub fn new_fronted(api_url: Url, fronting_url: Url) -> Self {
|
||||
let nym_api = nym_api::Client::new_fronted(api_url, fronting_url, None);
|
||||
pub fn new_with_user_agent(api_url: Url, user_agent: UserAgent) -> Self {
|
||||
let nym_api = nym_api::Client::builder::<_, ValidatorClientError>(api_url)
|
||||
.expect("invalid api url")
|
||||
.with_user_agent(user_agent)
|
||||
.build::<ValidatorClientError>()
|
||||
.expect("failed to build nym api client");
|
||||
|
||||
NymApiClient { nym_api }
|
||||
}
|
||||
@@ -272,15 +277,6 @@ impl NymApiClient {
|
||||
self.nym_api.change_base_url(new_endpoint);
|
||||
}
|
||||
|
||||
pub fn change_nym_api_with_fronting(
|
||||
&mut self,
|
||||
new_api_endpoint: Url,
|
||||
new_fronting_domain: Url,
|
||||
) {
|
||||
self.nym_api
|
||||
.change_fronted_url(new_api_endpoint, new_fronting_domain);
|
||||
}
|
||||
|
||||
pub async fn get_basic_mixnodes(
|
||||
&self,
|
||||
semver_compatibility: Option<String>,
|
||||
|
||||
@@ -17,6 +17,7 @@ pub use crate::signing::direct_wallet::DirectSecp256k1HdWallet;
|
||||
pub use client::NymApiClient;
|
||||
pub use client::{Client, CoconutApiClient, Config};
|
||||
pub use nym_api_requests::*;
|
||||
pub use nym_http_api_client::UserAgent;
|
||||
|
||||
#[cfg(feature = "http-client")]
|
||||
pub use cosmrs::rpc::HttpClient as HttpRpcClient;
|
||||
|
||||
@@ -683,6 +683,24 @@ pub trait MixnetSigningClient {
|
||||
.await
|
||||
}
|
||||
|
||||
async fn migrate_vested_mixnode(&self, fee: Option<Fee>) -> Result<ExecuteResult, NyxdError> {
|
||||
self.execute_mixnet_contract(fee, MixnetExecuteMsg::MigrateVestedMixNode {}, vec![])
|
||||
.await
|
||||
}
|
||||
|
||||
async fn migrate_vested_delegation(
|
||||
&self,
|
||||
mix_id: MixId,
|
||||
fee: Option<Fee>,
|
||||
) -> Result<ExecuteResult, NyxdError> {
|
||||
self.execute_mixnet_contract(
|
||||
fee,
|
||||
MixnetExecuteMsg::MigrateVestedDelegation { mix_id },
|
||||
vec![],
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
#[cfg(feature = "contract-testing")]
|
||||
async fn testing_resolve_all_pending_events(
|
||||
&self,
|
||||
@@ -928,6 +946,12 @@ mod tests {
|
||||
MixnetExecuteMsg::WithdrawDelegatorRewardOnBehalf { mix_id, owner } => client
|
||||
.withdraw_delegator_reward_on_behalf(owner.parse().unwrap(), mix_id, None)
|
||||
.ignore(),
|
||||
MixnetExecuteMsg::MigrateVestedMixNode { .. } => {
|
||||
client.migrate_vested_mixnode(None).ignore()
|
||||
}
|
||||
MixnetExecuteMsg::MigrateVestedDelegation { mix_id } => {
|
||||
client.migrate_vested_delegation(mix_id, None).ignore()
|
||||
}
|
||||
|
||||
#[cfg(feature = "contract-testing")]
|
||||
MixnetExecuteMsg::TestingResolveAllPendingEvents { .. } => {
|
||||
|
||||
@@ -437,6 +437,7 @@ where
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::nyxd::contract_traits::tests::{mock_coin, IgnoreValue};
|
||||
use nym_vesting_contract_common::ExecuteMsg;
|
||||
|
||||
// it's enough that this compiles and clippy is happy about it
|
||||
#[allow(dead_code)]
|
||||
@@ -560,6 +561,9 @@ mod tests {
|
||||
VestingExecuteMsg::UpdateLockedPledgeCap { address, cap } => client
|
||||
.update_locked_pledge_cap(address.parse().unwrap(), cap, None)
|
||||
.ignore(),
|
||||
// those will never be manually called by clients
|
||||
ExecuteMsg::TrackMigratedMixnode { .. } => "explicitly_ignored".ignore(),
|
||||
ExecuteMsg::TrackMigratedDelegation { .. } => "explicitly_ignored".ignore(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
+27
-3
@@ -3,7 +3,7 @@
|
||||
|
||||
use crate::nyxd::cosmwasm_client::client_traits::CosmWasmClient;
|
||||
use crate::nyxd::cosmwasm_client::helpers::{compress_wasm_code, CheckResponse};
|
||||
use crate::nyxd::cosmwasm_client::logs::{self, parse_raw_logs};
|
||||
use crate::nyxd::cosmwasm_client::logs::parse_raw_logs;
|
||||
use crate::nyxd::cosmwasm_client::types::*;
|
||||
use crate::nyxd::error::NyxdError;
|
||||
use crate::nyxd::fee::{Fee, DEFAULT_SIMULATED_GAS_MULTIPLIER};
|
||||
@@ -19,6 +19,7 @@ use cosmrs::feegrant::{
|
||||
};
|
||||
use cosmrs::proto::cosmos::tx::signing::v1beta1::SignMode;
|
||||
use cosmrs::staking::{MsgDelegate, MsgUndelegate};
|
||||
use cosmrs::tendermint::abci::{Event, EventAttribute};
|
||||
use cosmrs::tx::{self, Msg};
|
||||
use cosmrs::{cosmwasm, AccountId, Any, Tx};
|
||||
use log::debug;
|
||||
@@ -51,6 +52,20 @@ fn single_unspecified_signer_auth(
|
||||
}
|
||||
.auth_info(empty_fee())
|
||||
}
|
||||
// Searches in events for an event of the given event type which contains an
|
||||
// attribute for with the given key.
|
||||
fn find_attribute<'a>(
|
||||
events: &'a [Event],
|
||||
event_type: &str,
|
||||
attr_key: &str,
|
||||
) -> Option<&'a EventAttribute> {
|
||||
events
|
||||
.iter()
|
||||
.find(|attr| attr.kind == event_type)?
|
||||
.attributes
|
||||
.iter()
|
||||
.find(|attr| attr.key == attr_key)
|
||||
}
|
||||
|
||||
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
||||
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
|
||||
@@ -118,6 +133,7 @@ where
|
||||
.check_response()?;
|
||||
|
||||
let logs = parse_raw_logs(tx_res.tx_result.log)?;
|
||||
let events = tx_res.tx_result.events;
|
||||
let gas_info = GasInfo {
|
||||
gas_wanted: tx_res.tx_result.gas_wanted.try_into().unwrap_or_default(),
|
||||
gas_used: tx_res.tx_result.gas_used.try_into().unwrap_or_default(),
|
||||
@@ -127,7 +143,7 @@ where
|
||||
// the reason I think unwrap here is fine is that if the transaction succeeded and those
|
||||
// fields do not exist or code_id is not a number, there's no way we can recover, we're probably connected
|
||||
// to wrong validator or something
|
||||
let code_id = logs::find_attribute(&logs, "store_code", "code_id")
|
||||
let code_id = find_attribute(&events, "store_code", "code_id")
|
||||
.unwrap()
|
||||
.value
|
||||
.parse()
|
||||
@@ -140,6 +156,7 @@ where
|
||||
compressed_checksum,
|
||||
code_id,
|
||||
logs,
|
||||
events,
|
||||
transaction_hash: tx_res.hash,
|
||||
gas_info,
|
||||
})
|
||||
@@ -182,6 +199,7 @@ where
|
||||
.check_response()?;
|
||||
|
||||
let logs = parse_raw_logs(tx_res.tx_result.log)?;
|
||||
let events = tx_res.tx_result.events;
|
||||
let gas_info = GasInfo {
|
||||
gas_wanted: tx_res.tx_result.gas_wanted.try_into().unwrap_or_default(),
|
||||
gas_used: tx_res.tx_result.gas_used.try_into().unwrap_or_default(),
|
||||
@@ -190,7 +208,7 @@ where
|
||||
// the reason I think unwrap here is fine is that if the transaction succeeded and those
|
||||
// fields do not exist or address is malformed, there's no way we can recover, we're probably connected
|
||||
// to wrong validator or something
|
||||
let contract_address = logs::find_attribute(&logs, "instantiate", "_contract_address")
|
||||
let contract_address = find_attribute(&events, "instantiate", "_contract_address")
|
||||
.unwrap()
|
||||
.value
|
||||
.parse()
|
||||
@@ -199,6 +217,7 @@ where
|
||||
Ok(InstantiateResult {
|
||||
contract_address,
|
||||
logs,
|
||||
events,
|
||||
transaction_hash: tx_res.hash,
|
||||
gas_info,
|
||||
})
|
||||
@@ -231,6 +250,7 @@ where
|
||||
};
|
||||
Ok(ChangeAdminResult {
|
||||
logs: parse_raw_logs(tx_res.tx_result.log)?,
|
||||
events: tx_res.tx_result.events,
|
||||
transaction_hash: tx_res.hash,
|
||||
gas_info,
|
||||
})
|
||||
@@ -261,6 +281,7 @@ where
|
||||
};
|
||||
Ok(ChangeAdminResult {
|
||||
logs: parse_raw_logs(tx_res.tx_result.log)?,
|
||||
events: tx_res.tx_result.events,
|
||||
transaction_hash: tx_res.hash,
|
||||
gas_info,
|
||||
})
|
||||
@@ -298,6 +319,7 @@ where
|
||||
};
|
||||
Ok(MigrateResult {
|
||||
logs: parse_raw_logs(tx_res.tx_result.log)?,
|
||||
events: tx_res.tx_result.events,
|
||||
transaction_hash: tx_res.hash,
|
||||
gas_info,
|
||||
})
|
||||
@@ -335,6 +357,7 @@ where
|
||||
};
|
||||
Ok(ExecuteResult {
|
||||
logs: parse_raw_logs(tx_res.tx_result.log)?,
|
||||
events: tx_res.tx_result.events,
|
||||
data: tx_res.tx_result.data.into(),
|
||||
transaction_hash: tx_res.hash,
|
||||
gas_info,
|
||||
@@ -378,6 +401,7 @@ where
|
||||
};
|
||||
Ok(ExecuteResult {
|
||||
logs: parse_raw_logs(tx_res.tx_result.log)?,
|
||||
events: tx_res.tx_result.events,
|
||||
data: tx_res.tx_result.data.into(),
|
||||
transaction_hash: tx_res.hash,
|
||||
gas_info,
|
||||
|
||||
@@ -35,6 +35,7 @@ pub fn find_attribute<'a>(
|
||||
|
||||
// these two functions were separated so that the internal logic could actually be tested
|
||||
fn parse_raw_str_logs(raw: &str) -> Result<Vec<Log>, NyxdError> {
|
||||
// From Cosmos SDK > 0.50 onwards, log field is not populated
|
||||
if raw.is_empty() {
|
||||
return Ok(Vec::new());
|
||||
}
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// TEMPORARY WORKAROUND:
|
||||
// those features are expected as the below should only get activated whenever
|
||||
// the corresponding features in tendermint-rpc are enabled transitively
|
||||
#![allow(unexpected_cfgs)]
|
||||
|
||||
use crate::nyxd::cosmwasm_client::client_traits::SigningCosmWasmClient;
|
||||
use crate::nyxd::error::NyxdError;
|
||||
use crate::nyxd::{Config, GasPrice, Hash, Height};
|
||||
|
||||
@@ -232,6 +232,8 @@ pub struct UploadResult {
|
||||
|
||||
pub logs: Vec<Log>,
|
||||
|
||||
pub events: Vec<abci::Event>,
|
||||
|
||||
/// Transaction hash (might be used as transaction ID)
|
||||
pub transaction_hash: Hash,
|
||||
|
||||
@@ -269,6 +271,8 @@ pub struct InstantiateResult {
|
||||
|
||||
pub logs: Vec<Log>,
|
||||
|
||||
pub events: Vec<abci::Event>,
|
||||
|
||||
/// Transaction hash (might be used as transaction ID)
|
||||
pub transaction_hash: Hash,
|
||||
|
||||
@@ -279,6 +283,8 @@ pub struct InstantiateResult {
|
||||
pub struct ChangeAdminResult {
|
||||
pub logs: Vec<Log>,
|
||||
|
||||
pub events: Vec<abci::Event>,
|
||||
|
||||
/// Transaction hash (might be used as transaction ID)
|
||||
pub transaction_hash: Hash,
|
||||
|
||||
@@ -289,6 +295,8 @@ pub struct ChangeAdminResult {
|
||||
pub struct MigrateResult {
|
||||
pub logs: Vec<Log>,
|
||||
|
||||
pub events: Vec<abci::Event>,
|
||||
|
||||
/// Transaction hash (might be used as transaction ID)
|
||||
pub transaction_hash: Hash,
|
||||
|
||||
@@ -301,6 +309,8 @@ pub struct ExecuteResult {
|
||||
|
||||
pub data: Vec<u8>,
|
||||
|
||||
pub events: Vec<abci::Event>,
|
||||
|
||||
/// Transaction hash (might be used as transaction ID)
|
||||
pub transaction_hash: Hash,
|
||||
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// TEMPORARY WORKAROUND:
|
||||
// those features are expected as the below should only get activated whenever
|
||||
// the corresponding features in tendermint-rpc are enabled transitively
|
||||
#![allow(unexpected_cfgs)]
|
||||
|
||||
use crate::nyxd::contract_traits::{NymContractsProvider, TypedNymContracts};
|
||||
use crate::nyxd::cosmwasm_client::types::{
|
||||
ChangeAdminResult, ContractCodeId, ExecuteResult, InstantiateOptions, InstantiateResult,
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// TEMPORARY WORKAROUND:
|
||||
// those features are expected as the below should only get activated whenever
|
||||
// the corresponding features in tendermint-rpc are enabled transitively
|
||||
#![allow(unexpected_cfgs)]
|
||||
|
||||
use async_trait::async_trait;
|
||||
use cosmrs::tendermint::{self, abci, block::Height, evidence::Evidence, Genesis, Hash};
|
||||
use serde::{de::DeserializeOwned, Serialize};
|
||||
|
||||
@@ -1,15 +1,26 @@
|
||||
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||
// Copyright 2022-2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use clap::Parser;
|
||||
use log::{debug, info};
|
||||
|
||||
use cosmwasm_std::Decimal;
|
||||
use nym_mixnet_contract_common::{InitialRewardingParams, InstantiateMsg, Percent};
|
||||
use nym_validator_client::nyxd::AccountId;
|
||||
use log::{debug, info};
|
||||
use nym_mixnet_contract_common::{
|
||||
InitialRewardingParams, InstantiateMsg, OperatingCostRange, Percent, ProfitMarginRange,
|
||||
};
|
||||
use nym_network_defaults::mainnet::MIX_DENOM;
|
||||
use nym_network_defaults::TOTAL_SUPPLY;
|
||||
use nym_validator_client::nyxd::{AccountId, Coin};
|
||||
use std::str::FromStr;
|
||||
use std::time::Duration;
|
||||
|
||||
pub fn default_maximum_operating_cost() -> Coin {
|
||||
Coin::new(TOTAL_SUPPLY, MIX_DENOM.base)
|
||||
}
|
||||
|
||||
pub fn default_minimum_operating_cost() -> Coin {
|
||||
Coin::new(0, MIX_DENOM.base)
|
||||
}
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct Args {
|
||||
#[clap(long)]
|
||||
@@ -50,6 +61,18 @@ pub struct Args {
|
||||
|
||||
#[clap(long, default_value_t = 240)]
|
||||
pub active_set_size: u32,
|
||||
|
||||
#[clap(long, default_value_t = Percent::zero())]
|
||||
pub minimum_profit_margin_percent: Percent,
|
||||
|
||||
#[clap(long, default_value_t = Percent::hundred())]
|
||||
pub maximum_profit_margin_percent: Percent,
|
||||
|
||||
#[clap(long, default_value_t = default_minimum_operating_cost())]
|
||||
pub minimum_interval_operating_cost: Coin,
|
||||
|
||||
#[clap(long, default_value_t = default_maximum_operating_cost())]
|
||||
pub maximum_interval_operating_cost: Coin,
|
||||
}
|
||||
|
||||
pub async fn generate(args: Args) {
|
||||
@@ -97,6 +120,10 @@ pub async fn generate(args: Args) {
|
||||
.expect("Rewarding (mix) denom has to be set")
|
||||
});
|
||||
|
||||
if args.minimum_interval_operating_cost.denom != args.maximum_interval_operating_cost.denom {
|
||||
panic!("different denoms for operating cost bounds")
|
||||
}
|
||||
|
||||
let instantiate_msg = InstantiateMsg {
|
||||
rewarding_validator_address: rewarding_validator_address.to_string(),
|
||||
vesting_contract_address: vesting_contract_address.to_string(),
|
||||
@@ -104,6 +131,14 @@ pub async fn generate(args: Args) {
|
||||
epochs_in_interval: args.epochs_in_interval,
|
||||
epoch_duration: Duration::from_secs(args.epoch_duration),
|
||||
initial_rewarding_params,
|
||||
profit_margin: ProfitMarginRange {
|
||||
minimum: args.minimum_profit_margin_percent,
|
||||
maximum: args.maximum_profit_margin_percent,
|
||||
},
|
||||
interval_operating_cost: OperatingCostRange {
|
||||
minimum: args.minimum_interval_operating_cost.amount.into(),
|
||||
maximum: args.maximum_interval_operating_cost.amount.into(),
|
||||
},
|
||||
};
|
||||
|
||||
debug!("instantiate_msg: {:?}", instantiate_msg);
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::context::SigningClient;
|
||||
use clap::Parser;
|
||||
use log::info;
|
||||
use nym_mixnet_contract_common::MixId;
|
||||
use nym_validator_client::nyxd::contract_traits::{MixnetQueryClient, MixnetSigningClient};
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct Args {
|
||||
#[clap(long)]
|
||||
pub mix_id: Option<MixId>,
|
||||
|
||||
#[clap(long)]
|
||||
pub identity_key: Option<String>,
|
||||
}
|
||||
|
||||
pub async fn migrate_vested_delegation(args: Args, client: SigningClient) {
|
||||
let mix_id = match args.mix_id {
|
||||
Some(mix_id) => mix_id,
|
||||
None => {
|
||||
let identity_key = args
|
||||
.identity_key
|
||||
.expect("either mix_id or mix_identity has to be specified");
|
||||
let node_details = client
|
||||
.get_mixnode_details_by_identity(identity_key)
|
||||
.await
|
||||
.expect("contract query failed")
|
||||
.mixnode_details
|
||||
.expect("mixnode with the specified identity doesnt exist");
|
||||
node_details.mix_id()
|
||||
}
|
||||
};
|
||||
|
||||
let res = client
|
||||
.migrate_vested_delegation(mix_id, None)
|
||||
.await
|
||||
.expect("failed to migrate delegation!");
|
||||
|
||||
info!("migration result: {:?}", res)
|
||||
}
|
||||
@@ -7,6 +7,7 @@ pub mod rewards;
|
||||
|
||||
pub mod delegate_to_mixnode;
|
||||
pub mod delegate_to_multiple_mixnodes;
|
||||
pub mod migrate_vested_delegation;
|
||||
pub mod query_for_delegations;
|
||||
pub mod undelegate_from_mixnode;
|
||||
pub mod vesting_delegate_to_mixnode;
|
||||
@@ -35,4 +36,6 @@ pub enum MixnetDelegatorsCommands {
|
||||
DelegateVesting(vesting_delegate_to_mixnode::Args),
|
||||
/// Undelegate from a mixnode (when originally using locked tokens)
|
||||
UndelegateVesting(vesting_undelegate_from_mixnode::Args),
|
||||
/// Migrate the delegation to use liquid tokens
|
||||
MigrateVestedDelegation(migrate_vested_delegation::Args),
|
||||
}
|
||||
|
||||
@@ -96,6 +96,7 @@ async fn print_delegation_events(events: Vec<PendingEpochEvent>, client: &Signin
|
||||
mix_id,
|
||||
amount,
|
||||
proxy,
|
||||
..
|
||||
} => {
|
||||
if owner.as_str() == client.nyxd.address().as_ref() {
|
||||
table.add_row(vec![
|
||||
@@ -111,6 +112,7 @@ async fn print_delegation_events(events: Vec<PendingEpochEvent>, client: &Signin
|
||||
owner,
|
||||
mix_id,
|
||||
proxy,
|
||||
..
|
||||
} => {
|
||||
if owner.as_str() == client.nyxd.address().as_ref() {
|
||||
table.add_row(vec![
|
||||
|
||||
+2
-13
@@ -8,7 +8,7 @@ use cosmwasm_std::Coin;
|
||||
use nym_bin_common::output_format::OutputFormat;
|
||||
use nym_mixnet_contract_common::construct_gateway_bonding_sign_payload;
|
||||
use nym_network_defaults::{DEFAULT_CLIENT_LISTENING_PORT, DEFAULT_MIX_LISTENING_PORT};
|
||||
use nym_validator_client::nyxd::contract_traits::{MixnetQueryClient, NymContractsProvider};
|
||||
use nym_validator_client::nyxd::contract_traits::MixnetQueryClient;
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct Args {
|
||||
@@ -39,10 +39,6 @@ pub struct Args {
|
||||
)]
|
||||
pub amount: u128,
|
||||
|
||||
/// Indicates whether the gateway is going to get bonded via a vesting account
|
||||
#[arg(long)]
|
||||
pub with_vesting_account: bool,
|
||||
|
||||
#[clap(short, long, default_value_t = OutputFormat::default())]
|
||||
output: OutputFormat,
|
||||
}
|
||||
@@ -74,15 +70,8 @@ pub async fn create_payload(args: Args, client: SigningClient) {
|
||||
};
|
||||
|
||||
let address = account_id_to_cw_addr(&client.address());
|
||||
let proxy = if args.with_vesting_account {
|
||||
Some(account_id_to_cw_addr(
|
||||
client.vesting_contract_address().unwrap(),
|
||||
))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let payload = construct_gateway_bonding_sign_payload(nonce, address, proxy, coin, gateway);
|
||||
let payload = construct_gateway_bonding_sign_payload(nonce, address, coin, gateway);
|
||||
let wrapper = DataWrapper::new(payload.to_base58_string().unwrap());
|
||||
println!("{}", args.output.format(&wrapper))
|
||||
}
|
||||
|
||||
@@ -5,33 +5,21 @@ use crate::context::SigningClient;
|
||||
use clap::Parser;
|
||||
use log::info;
|
||||
use nym_validator_client::nyxd::contract_traits::MixnetSigningClient;
|
||||
use nym_validator_client::nyxd::contract_traits::VestingSigningClient;
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct Args {
|
||||
/// Label that is going to be used for creating the family
|
||||
#[arg(long)]
|
||||
pub family_label: String,
|
||||
|
||||
/// Indicates whether the family is going to get created via a vesting account
|
||||
#[arg(long)]
|
||||
pub with_vesting_account: bool,
|
||||
}
|
||||
|
||||
pub async fn create_family(args: Args, client: SigningClient) {
|
||||
info!("Create family");
|
||||
|
||||
let res = if args.with_vesting_account {
|
||||
client
|
||||
.vesting_create_family(args.family_label, None)
|
||||
.await
|
||||
.expect("failed to create family with vesting account")
|
||||
} else {
|
||||
client
|
||||
.create_family(args.family_label, None)
|
||||
.await
|
||||
.expect("failed to create family")
|
||||
};
|
||||
let res = client
|
||||
.create_family(args.family_label, None)
|
||||
.await
|
||||
.expect("failed to create family");
|
||||
|
||||
info!("Family creation result: {:?}", res);
|
||||
}
|
||||
|
||||
+3
-16
@@ -2,7 +2,7 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::context::QueryClient;
|
||||
use crate::utils::{account_id_to_cw_addr, DataWrapper};
|
||||
use crate::utils::DataWrapper;
|
||||
use clap::Parser;
|
||||
use cosmrs::AccountId;
|
||||
use log::info;
|
||||
@@ -10,7 +10,7 @@ use nym_bin_common::output_format::OutputFormat;
|
||||
use nym_crypto::asymmetric::identity;
|
||||
use nym_mixnet_contract_common::construct_family_join_permit;
|
||||
use nym_mixnet_contract_common::families::FamilyHead;
|
||||
use nym_validator_client::nyxd::contract_traits::{MixnetQueryClient, NymContractsProvider};
|
||||
use nym_validator_client::nyxd::contract_traits::MixnetQueryClient;
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct Args {
|
||||
@@ -18,10 +18,6 @@ pub struct Args {
|
||||
#[arg(long)]
|
||||
pub address: AccountId,
|
||||
|
||||
/// Indicates whether the member joining the family is going to use the vesting account for joining.
|
||||
#[arg(long)]
|
||||
pub with_vesting_account: bool,
|
||||
|
||||
// might as well validate the value when parsing the arguments
|
||||
/// Identity of the member for whom we're issuing the permit
|
||||
#[arg(long)]
|
||||
@@ -68,18 +64,9 @@ pub async fn create_family_join_permit_sign_payload(args: Args, client: QueryCli
|
||||
}
|
||||
};
|
||||
|
||||
// let address = account_id_to_cw_addr(&args.address);
|
||||
let proxy = if args.with_vesting_account {
|
||||
Some(account_id_to_cw_addr(
|
||||
client.vesting_contract_address().unwrap(),
|
||||
))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let head = FamilyHead::new(mixnode.bond_information.identity());
|
||||
|
||||
let payload = construct_family_join_permit(nonce, head, proxy, args.member.to_base58_string());
|
||||
let payload = construct_family_join_permit(nonce, head, args.member.to_base58_string());
|
||||
let wrapper = DataWrapper::new(payload.to_base58_string().unwrap());
|
||||
println!("{}", args.output.format(&wrapper))
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ use nym_contracts_common::signing::MessageSignature;
|
||||
use nym_crypto::asymmetric::identity;
|
||||
use nym_mixnet_contract_common::families::FamilyHead;
|
||||
use nym_validator_client::nyxd::contract_traits::MixnetSigningClient;
|
||||
use nym_validator_client::nyxd::contract_traits::VestingSigningClient;
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct Args {
|
||||
@@ -16,10 +15,6 @@ pub struct Args {
|
||||
#[arg(long)]
|
||||
pub family_head: identity::PublicKey,
|
||||
|
||||
/// Indicates whether the member joining the family is going to do so via the vesting contract
|
||||
#[arg(long)]
|
||||
pub with_vesting_account: bool,
|
||||
|
||||
/// Permission, as provided by the family head, for joining the family
|
||||
#[arg(long)]
|
||||
pub join_permit: MessageSignature,
|
||||
@@ -30,17 +25,10 @@ pub async fn join_family(args: Args, client: SigningClient) {
|
||||
|
||||
let family_head = FamilyHead::new(args.family_head.to_base58_string());
|
||||
|
||||
let res = if args.with_vesting_account {
|
||||
client
|
||||
.vesting_join_family(args.join_permit, family_head, None)
|
||||
.await
|
||||
.expect("failed to join family with vesting account")
|
||||
} else {
|
||||
client
|
||||
.join_family(args.join_permit, family_head, None)
|
||||
.await
|
||||
.expect("failed to join family")
|
||||
};
|
||||
let res = client
|
||||
.join_family(args.join_permit, family_head, None)
|
||||
.await
|
||||
.expect("failed to join family");
|
||||
|
||||
info!("Family join result: {:?}", res);
|
||||
}
|
||||
|
||||
@@ -7,17 +7,12 @@ use log::info;
|
||||
use nym_crypto::asymmetric::identity;
|
||||
use nym_mixnet_contract_common::families::FamilyHead;
|
||||
use nym_validator_client::nyxd::contract_traits::MixnetSigningClient;
|
||||
use nym_validator_client::nyxd::contract_traits::VestingSigningClient;
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct Args {
|
||||
/// The head of the family that we intend to leave
|
||||
#[arg(long)]
|
||||
pub family_head: identity::PublicKey,
|
||||
|
||||
/// Indicates whether we joined the family via the vesting contract
|
||||
#[arg(long)]
|
||||
pub with_vesting_account: bool,
|
||||
}
|
||||
|
||||
pub async fn leave_family(args: Args, client: SigningClient) {
|
||||
@@ -25,17 +20,10 @@ pub async fn leave_family(args: Args, client: SigningClient) {
|
||||
|
||||
let family_head = FamilyHead::new(args.family_head.to_base58_string());
|
||||
|
||||
let res = if args.with_vesting_account {
|
||||
client
|
||||
.vesting_leave_family(family_head, None)
|
||||
.await
|
||||
.expect("failed to leave family with vesting account")
|
||||
} else {
|
||||
client
|
||||
.leave_family(family_head, None)
|
||||
.await
|
||||
.expect("failed to leave family")
|
||||
};
|
||||
let res = client
|
||||
.leave_family(family_head, None)
|
||||
.await
|
||||
.expect("failed to leave family");
|
||||
|
||||
info!("Family leave result: {:?}", res);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::context::SigningClient;
|
||||
use clap::Parser;
|
||||
use log::info;
|
||||
use nym_validator_client::nyxd::contract_traits::MixnetSigningClient;
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct Args {}
|
||||
|
||||
pub async fn migrate_vested_mixnode(_args: Args, client: SigningClient) {
|
||||
let res = client
|
||||
.migrate_vested_mixnode(None)
|
||||
.await
|
||||
.expect("failed to migrate mixnode!");
|
||||
|
||||
info!("migration result: {:?}", res)
|
||||
}
|
||||
+2
-13
@@ -11,7 +11,7 @@ use nym_mixnet_contract_common::{construct_mixnode_bonding_sign_payload, MixNode
|
||||
use nym_network_defaults::{
|
||||
DEFAULT_HTTP_API_LISTENING_PORT, DEFAULT_MIX_LISTENING_PORT, DEFAULT_VERLOC_LISTENING_PORT,
|
||||
};
|
||||
use nym_validator_client::nyxd::contract_traits::{MixnetQueryClient, NymContractsProvider};
|
||||
use nym_validator_client::nyxd::contract_traits::MixnetQueryClient;
|
||||
use nym_validator_client::nyxd::CosmWasmCoin;
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
@@ -52,10 +52,6 @@ pub struct Args {
|
||||
)]
|
||||
pub amount: u128,
|
||||
|
||||
/// Indicates whether the mixnode is going to get bonded via a vesting account
|
||||
#[arg(long)]
|
||||
pub with_vesting_account: bool,
|
||||
|
||||
#[clap(short, long, default_value_t = OutputFormat::default())]
|
||||
output: OutputFormat,
|
||||
}
|
||||
@@ -100,16 +96,9 @@ pub async fn create_payload(args: Args, client: SigningClient) {
|
||||
};
|
||||
|
||||
let address = account_id_to_cw_addr(&client.address());
|
||||
let proxy = if args.with_vesting_account {
|
||||
Some(account_id_to_cw_addr(
|
||||
client.vesting_contract_address().unwrap(),
|
||||
))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let payload =
|
||||
construct_mixnode_bonding_sign_payload(nonce, address, proxy, coin, mixnode, cost_params);
|
||||
construct_mixnode_bonding_sign_payload(nonce, address, coin, mixnode, cost_params);
|
||||
let wrapper = DataWrapper::new(payload.to_base58_string().unwrap());
|
||||
println!("{}", args.output.format(&wrapper))
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ pub mod bond_mixnode;
|
||||
pub mod decrease_pledge;
|
||||
pub mod families;
|
||||
pub mod keys;
|
||||
pub mod migrate_vested_mixnode;
|
||||
pub mod mixnode_bonding_sign_payload;
|
||||
pub mod pledge_more;
|
||||
pub mod rewards;
|
||||
@@ -52,4 +53,6 @@ pub enum MixnetOperatorsMixnodeCommands {
|
||||
DecreasePledge(decrease_pledge::Args),
|
||||
/// Decrease pledge with locked tokens
|
||||
DecreasePledgeVesting(vesting_decrease_pledge::Args),
|
||||
/// Migrate the mixnode to use liquid tokens
|
||||
MigrateVestedNode(migrate_vested_mixnode::Args),
|
||||
}
|
||||
|
||||
@@ -218,7 +218,6 @@ where
|
||||
#[derive(Serialize)]
|
||||
pub struct ContractMessageContent<T> {
|
||||
pub sender: Addr,
|
||||
pub proxy: Option<Addr>,
|
||||
pub funds: Vec<Coin>,
|
||||
pub data: T,
|
||||
}
|
||||
@@ -233,25 +232,17 @@ where
|
||||
}
|
||||
|
||||
impl<T> ContractMessageContent<T> {
|
||||
pub fn new(sender: Addr, proxy: Option<Addr>, funds: Vec<Coin>, data: T) -> Self {
|
||||
pub fn new(sender: Addr, funds: Vec<Coin>, data: T) -> Self {
|
||||
ContractMessageContent {
|
||||
sender,
|
||||
proxy,
|
||||
funds,
|
||||
data,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_with_info(info: MessageInfo, signer: Addr, data: T) -> Self {
|
||||
let proxy = if info.sender == signer {
|
||||
None
|
||||
} else {
|
||||
Some(info.sender)
|
||||
};
|
||||
|
||||
ContractMessageContent {
|
||||
sender: signer,
|
||||
proxy,
|
||||
funds: info.funds,
|
||||
data,
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ time = { workspace = true, features = ["parsing", "formatting"] }
|
||||
ts-rs = { workspace = true, optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
rand_chacha = "0.3"
|
||||
rand_chacha = { workspace = true }
|
||||
time = { workspace = true, features = ["serde", "macros"] }
|
||||
|
||||
[features]
|
||||
|
||||
@@ -65,7 +65,6 @@ impl Delegation {
|
||||
cumulative_reward_ratio: Decimal,
|
||||
amount: Coin,
|
||||
height: u64,
|
||||
proxy: Option<Addr>,
|
||||
) -> Self {
|
||||
assert!(
|
||||
amount.amount <= TOKEN_SUPPLY,
|
||||
@@ -78,7 +77,7 @@ impl Delegation {
|
||||
cumulative_reward_ratio,
|
||||
amount,
|
||||
height,
|
||||
proxy,
|
||||
proxy: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
// Copyright 2022-2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::{EpochEventId, EpochState, IdentityKey, MixId};
|
||||
use crate::{EpochEventId, EpochState, IdentityKey, MixId, OperatingCostRange, ProfitMarginRange};
|
||||
use contracts_common::signing::verifier::ApiVerifierError;
|
||||
use contracts_common::Percent;
|
||||
use cosmwasm_std::{Addr, Coin, Decimal, Uint128};
|
||||
use thiserror::Error;
|
||||
|
||||
@@ -76,21 +77,11 @@ pub enum MixnetContractError {
|
||||
#[error("Received multiple coin types during staking")]
|
||||
MultipleDenoms,
|
||||
|
||||
#[error("Proxy address mismatch, expected {existing}, got {incoming}")]
|
||||
ProxyMismatch { existing: String, incoming: String },
|
||||
|
||||
#[error("Proxy address ({received}) is not set to the vesting contract ({vesting_contract})")]
|
||||
ProxyIsNotVestingContract {
|
||||
received: Addr,
|
||||
vesting_contract: Addr,
|
||||
},
|
||||
#[error(
|
||||
"Sender of this message ({received}) is not the vesting contract ({vesting_contract})"
|
||||
)]
|
||||
SenderIsNotVestingContract {
|
||||
received: Addr,
|
||||
vesting_contract: Addr,
|
||||
},
|
||||
|
||||
#[error("Failed to recover ed25519 public key from its base58 representation - {0}")]
|
||||
MalformedEd25519IdentityKey(String),
|
||||
@@ -239,6 +230,30 @@ pub enum MixnetContractError {
|
||||
#[from]
|
||||
source: ApiVerifierError,
|
||||
},
|
||||
|
||||
#[error("this operation is no longer allowed to be performed with vesting tokens. please move them to your liquid balance and try again")]
|
||||
DisabledVestingOperation,
|
||||
|
||||
#[error(
|
||||
"this mixnode has not been bonded with the vesting tokens or has already been migrated"
|
||||
)]
|
||||
NotAVestingMixnode,
|
||||
|
||||
#[error("this delegation has not been performed with the vesting tokens or has already been migrated")]
|
||||
NotAVestingDelegation,
|
||||
|
||||
#[error("the provided profit margin ({provided}) is outside the allowed range: {range}")]
|
||||
ProfitMarginOutsideRange {
|
||||
provided: Percent,
|
||||
range: ProfitMarginRange,
|
||||
},
|
||||
|
||||
#[error("the provided interval operating cost ({provided}{denom}) is outside the allowed range: {range}")]
|
||||
OperatingCostOutsideRange {
|
||||
denom: String,
|
||||
provided: Uint128,
|
||||
range: OperatingCostRange,
|
||||
},
|
||||
}
|
||||
|
||||
impl MixnetContractError {
|
||||
|
||||
@@ -103,7 +103,6 @@ impl Display for MixnetEventType {
|
||||
// attributes that are used in multiple places
|
||||
pub const OWNER_KEY: &str = "owner";
|
||||
pub const AMOUNT_KEY: &str = "amount";
|
||||
pub const PROXY_KEY: &str = "proxy";
|
||||
|
||||
// event-specific attributes
|
||||
|
||||
@@ -163,7 +162,6 @@ pub const NEW_EPOCHS_IN_INTERVAL: &str = "new_epochs_in_interval";
|
||||
pub fn new_delegation_event(
|
||||
created_at: BlockHeight,
|
||||
delegator: &Addr,
|
||||
proxy: &Option<Addr>,
|
||||
amount: &Coin,
|
||||
mix_id: MixId,
|
||||
unit_reward: Decimal,
|
||||
@@ -171,58 +169,34 @@ pub fn new_delegation_event(
|
||||
Event::new(MixnetEventType::Delegation)
|
||||
.add_attribute(EVENT_CREATION_HEIGHT_KEY, created_at.to_string())
|
||||
.add_attribute(DELEGATOR_KEY, delegator)
|
||||
.add_optional_attribute(PROXY_KEY, proxy.as_ref())
|
||||
.add_attribute(AMOUNT_KEY, amount.to_string())
|
||||
.add_attribute(DELEGATION_TARGET_KEY, mix_id.to_string())
|
||||
.add_attribute(UNIT_REWARD_KEY, unit_reward.to_string())
|
||||
}
|
||||
|
||||
pub fn new_delegation_on_unbonded_node_event(
|
||||
delegator: &Addr,
|
||||
proxy: &Option<Addr>,
|
||||
mix_id: MixId,
|
||||
) -> Event {
|
||||
pub fn new_delegation_on_unbonded_node_event(delegator: &Addr, mix_id: MixId) -> Event {
|
||||
Event::new(MixnetEventType::Delegation)
|
||||
.add_attribute(DELEGATOR_KEY, delegator)
|
||||
.add_optional_attribute(PROXY_KEY, proxy.as_ref())
|
||||
.add_attribute(DELEGATION_TARGET_KEY, mix_id.to_string())
|
||||
}
|
||||
|
||||
pub fn new_pending_delegation_event(
|
||||
delegator: &Addr,
|
||||
proxy: &Option<Addr>,
|
||||
amount: &Coin,
|
||||
mix_id: MixId,
|
||||
) -> Event {
|
||||
pub fn new_pending_delegation_event(delegator: &Addr, amount: &Coin, mix_id: MixId) -> Event {
|
||||
Event::new(MixnetEventType::PendingDelegation)
|
||||
.add_attribute(DELEGATOR_KEY, delegator)
|
||||
.add_optional_attribute(PROXY_KEY, proxy.as_ref())
|
||||
.add_attribute(AMOUNT_KEY, amount.to_string())
|
||||
.add_attribute(DELEGATION_TARGET_KEY, mix_id.to_string())
|
||||
}
|
||||
|
||||
pub fn new_withdraw_operator_reward_event(
|
||||
owner: &Addr,
|
||||
proxy: &Option<Addr>,
|
||||
amount: Coin,
|
||||
mix_id: MixId,
|
||||
) -> Event {
|
||||
pub fn new_withdraw_operator_reward_event(owner: &Addr, amount: Coin, mix_id: MixId) -> Event {
|
||||
Event::new(MixnetEventType::WithdrawOperatorReward)
|
||||
.add_attribute(OWNER_KEY, owner.as_str())
|
||||
.add_optional_attribute(PROXY_KEY, proxy.as_ref())
|
||||
.add_attribute(AMOUNT_KEY, amount.to_string())
|
||||
.add_attribute(MIX_ID_KEY, mix_id.to_string())
|
||||
}
|
||||
|
||||
pub fn new_withdraw_delegator_reward_event(
|
||||
delegator: &Addr,
|
||||
proxy: &Option<Addr>,
|
||||
amount: Coin,
|
||||
mix_id: MixId,
|
||||
) -> Event {
|
||||
pub fn new_withdraw_delegator_reward_event(delegator: &Addr, amount: Coin, mix_id: MixId) -> Event {
|
||||
Event::new(MixnetEventType::WithdrawDelegatorReward)
|
||||
.add_attribute(DELEGATOR_KEY, delegator)
|
||||
.add_optional_attribute(PROXY_KEY, proxy.as_ref())
|
||||
.add_attribute(AMOUNT_KEY, amount.to_string())
|
||||
.add_attribute(DELEGATION_TARGET_KEY, mix_id.to_string())
|
||||
}
|
||||
@@ -278,59 +252,43 @@ pub fn new_pending_rewarding_params_update_event(
|
||||
)
|
||||
}
|
||||
|
||||
pub fn new_undelegation_event(
|
||||
created_at: BlockHeight,
|
||||
delegator: &Addr,
|
||||
proxy: &Option<Addr>,
|
||||
mix_id: MixId,
|
||||
) -> Event {
|
||||
pub fn new_undelegation_event(created_at: BlockHeight, delegator: &Addr, mix_id: MixId) -> Event {
|
||||
Event::new(MixnetEventType::Undelegation)
|
||||
.add_attribute(EVENT_CREATION_HEIGHT_KEY, created_at.to_string())
|
||||
.add_attribute(DELEGATOR_KEY, delegator)
|
||||
.add_optional_attribute(PROXY_KEY, proxy.as_ref())
|
||||
.add_attribute(MIX_ID_KEY, mix_id.to_string())
|
||||
}
|
||||
|
||||
pub fn new_pending_undelegation_event(
|
||||
delegator: &Addr,
|
||||
proxy: &Option<Addr>,
|
||||
mix_id: MixId,
|
||||
) -> Event {
|
||||
pub fn new_pending_undelegation_event(delegator: &Addr, mix_id: MixId) -> Event {
|
||||
Event::new(MixnetEventType::PendingUndelegation)
|
||||
.add_attribute(DELEGATOR_KEY, delegator)
|
||||
.add_optional_attribute(PROXY_KEY, proxy.as_ref())
|
||||
.add_attribute(MIX_ID_KEY, mix_id.to_string())
|
||||
}
|
||||
|
||||
pub fn new_gateway_bonding_event(
|
||||
owner: &Addr,
|
||||
proxy: &Option<Addr>,
|
||||
amount: &Coin,
|
||||
identity: IdentityKeyRef<'_>,
|
||||
) -> Event {
|
||||
Event::new(MixnetEventType::GatewayBonding)
|
||||
.add_attribute(OWNER_KEY, owner)
|
||||
.add_attribute(NODE_IDENTITY_KEY, identity)
|
||||
.add_optional_attribute(PROXY_KEY, proxy.as_ref())
|
||||
.add_attribute(AMOUNT_KEY, amount.to_string())
|
||||
}
|
||||
|
||||
pub fn new_gateway_unbonding_event(
|
||||
owner: &Addr,
|
||||
proxy: &Option<Addr>,
|
||||
amount: &Coin,
|
||||
identity: IdentityKeyRef<'_>,
|
||||
) -> Event {
|
||||
Event::new(MixnetEventType::GatewayUnbonding)
|
||||
.add_attribute(OWNER_KEY, owner)
|
||||
.add_attribute(NODE_IDENTITY_KEY, identity)
|
||||
.add_optional_attribute(PROXY_KEY, proxy.as_ref())
|
||||
.add_attribute(AMOUNT_KEY, amount.to_string())
|
||||
}
|
||||
|
||||
pub fn new_mixnode_bonding_event(
|
||||
owner: &Addr,
|
||||
proxy: &Option<Addr>,
|
||||
amount: &Coin,
|
||||
identity: IdentityKeyRef<'_>,
|
||||
mix_id: MixId,
|
||||
@@ -341,7 +299,6 @@ pub fn new_mixnode_bonding_event(
|
||||
.add_attribute(MIX_ID_KEY, mix_id.to_string())
|
||||
.add_attribute(NODE_IDENTITY_KEY, identity)
|
||||
.add_attribute(OWNER_KEY, owner)
|
||||
.add_optional_attribute(PROXY_KEY, proxy.as_ref())
|
||||
.add_attribute(ASSIGNED_LAYER_KEY, assigned_layer)
|
||||
.add_attribute(AMOUNT_KEY, amount.to_string())
|
||||
}
|
||||
@@ -380,7 +337,6 @@ pub fn new_mixnode_unbonding_event(created_at: BlockHeight, mix_id: MixId) -> Ev
|
||||
|
||||
pub fn new_pending_mixnode_unbonding_event(
|
||||
owner: &Addr,
|
||||
proxy: &Option<Addr>,
|
||||
identity: IdentityKeyRef<'_>,
|
||||
mix_id: MixId,
|
||||
) -> Event {
|
||||
@@ -388,43 +344,33 @@ pub fn new_pending_mixnode_unbonding_event(
|
||||
.add_attribute(MIX_ID_KEY, mix_id.to_string())
|
||||
.add_attribute(NODE_IDENTITY_KEY, identity)
|
||||
.add_attribute(OWNER_KEY, owner)
|
||||
.add_optional_attribute(PROXY_KEY, proxy.as_ref())
|
||||
}
|
||||
|
||||
pub fn new_mixnode_config_update_event(
|
||||
mix_id: MixId,
|
||||
owner: &Addr,
|
||||
proxy: &Option<Addr>,
|
||||
update: &MixNodeConfigUpdate,
|
||||
) -> Event {
|
||||
Event::new(MixnetEventType::MixnodeConfigUpdate)
|
||||
.add_attribute(MIX_ID_KEY, mix_id.to_string())
|
||||
.add_attribute(OWNER_KEY, owner)
|
||||
.add_optional_attribute(PROXY_KEY, proxy.as_ref())
|
||||
.add_attribute(UPDATED_MIXNODE_CONFIG_KEY, update.to_inline_json())
|
||||
}
|
||||
|
||||
pub fn new_gateway_config_update_event(
|
||||
owner: &Addr,
|
||||
proxy: &Option<Addr>,
|
||||
update: &GatewayConfigUpdate,
|
||||
) -> Event {
|
||||
pub fn new_gateway_config_update_event(owner: &Addr, update: &GatewayConfigUpdate) -> Event {
|
||||
Event::new(MixnetEventType::GatewayConfigUpdate)
|
||||
.add_attribute(OWNER_KEY, owner)
|
||||
.add_optional_attribute(PROXY_KEY, proxy.as_ref())
|
||||
.add_attribute(UPDATED_GATEWAY_CONFIG_KEY, update.to_inline_json())
|
||||
}
|
||||
|
||||
pub fn new_mixnode_pending_cost_params_update_event(
|
||||
mix_id: MixId,
|
||||
owner: &Addr,
|
||||
proxy: &Option<Addr>,
|
||||
new_costs: &MixNodeCostParams,
|
||||
) -> Event {
|
||||
Event::new(MixnetEventType::PendingMixnodeCostParamsUpdate)
|
||||
.add_attribute(MIX_ID_KEY, mix_id.to_string())
|
||||
.add_attribute(OWNER_KEY, owner)
|
||||
.add_optional_attribute(PROXY_KEY, proxy.as_ref())
|
||||
.add_attribute(UPDATED_MIXNODE_COST_PARAMS_KEY, new_costs.to_inline_json())
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
|
||||
use crate::{IdentityKey, IdentityKeyRef};
|
||||
use cosmwasm_schema::cw_serde;
|
||||
use cosmwasm_std::Addr;
|
||||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
use std::fmt::{Display, Formatter};
|
||||
@@ -84,10 +83,10 @@ impl FamilyHead {
|
||||
}
|
||||
|
||||
impl Family {
|
||||
pub fn new(head: FamilyHead, proxy: Option<Addr>, label: String) -> Self {
|
||||
pub fn new(head: FamilyHead, label: String) -> Self {
|
||||
Family {
|
||||
head,
|
||||
proxy: proxy.map(|p| p.to_string()),
|
||||
proxy: None,
|
||||
label,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,19 +55,13 @@ pub struct GatewayBond {
|
||||
}
|
||||
|
||||
impl GatewayBond {
|
||||
pub fn new(
|
||||
pledge_amount: Coin,
|
||||
owner: Addr,
|
||||
block_height: u64,
|
||||
gateway: Gateway,
|
||||
proxy: Option<Addr>,
|
||||
) -> Self {
|
||||
pub fn new(pledge_amount: Coin, owner: Addr, block_height: u64, gateway: Gateway) -> Self {
|
||||
GatewayBond {
|
||||
pledge_amount,
|
||||
owner,
|
||||
block_height,
|
||||
gateway,
|
||||
proxy,
|
||||
proxy: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,10 @@ use crate::helpers::IntoBaseDecimal;
|
||||
use crate::reward_params::{NodeRewardParams, RewardingParams};
|
||||
use crate::rewarding::helpers::truncate_reward;
|
||||
use crate::rewarding::RewardDistribution;
|
||||
use crate::{Delegation, EpochEventId, EpochId, IdentityKey, MixId, Percent, SphinxKey};
|
||||
use crate::{
|
||||
Delegation, EpochEventId, EpochId, IdentityKey, MixId, OperatingCostRange, Percent,
|
||||
ProfitMarginRange, SphinxKey,
|
||||
};
|
||||
use cosmwasm_schema::cw_serde;
|
||||
use cosmwasm_std::{Addr, Coin, Decimal, StdResult, Uint128};
|
||||
use schemars::JsonSchema;
|
||||
@@ -152,6 +155,16 @@ impl MixNodeRewarding {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn normalise_profit_margin(&mut self, allowed_range: ProfitMarginRange) {
|
||||
self.cost_params.profit_margin_percent =
|
||||
allowed_range.normalise(self.cost_params.profit_margin_percent)
|
||||
}
|
||||
|
||||
pub fn normalise_operating_cost(&mut self, allowed_range: OperatingCostRange) {
|
||||
self.cost_params.interval_operating_cost.amount =
|
||||
allowed_range.normalise(self.cost_params.interval_operating_cost.amount)
|
||||
}
|
||||
|
||||
/// Determines whether this node is still bonded. This is performed via a simple check,
|
||||
/// if there are no tokens left associated with the operator, it means they have unbonded
|
||||
/// and those params only exist for the purposes of calculating rewards for delegators that
|
||||
@@ -518,7 +531,6 @@ impl MixNodeBond {
|
||||
original_pledge: Coin,
|
||||
layer: Layer,
|
||||
mix_node: MixNode,
|
||||
proxy: Option<Addr>,
|
||||
bonding_height: u64,
|
||||
) -> Self {
|
||||
MixNodeBond {
|
||||
@@ -527,7 +539,7 @@ impl MixNodeBond {
|
||||
original_pledge,
|
||||
layer,
|
||||
mix_node,
|
||||
proxy,
|
||||
proxy: None,
|
||||
bonding_height,
|
||||
is_unbonding: false,
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// Copyright 2021-2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::delegation::{self, OwnerProxySubKey};
|
||||
@@ -12,6 +12,7 @@ use crate::reward_params::{
|
||||
IntervalRewardParams, IntervalRewardingParamsUpdate, Performance, RewardingParams,
|
||||
};
|
||||
use crate::types::{ContractStateParams, LayerAssignment, MixId};
|
||||
use crate::{OperatingCostRange, ProfitMarginRange};
|
||||
use contracts_common::{signing::MessageSignature, IdentityKey, Percent};
|
||||
use cosmwasm_schema::cw_serde;
|
||||
use cosmwasm_std::{Coin, Decimal};
|
||||
@@ -57,6 +58,12 @@ pub struct InstantiateMsg {
|
||||
pub epochs_in_interval: u32,
|
||||
pub epoch_duration: Duration,
|
||||
pub initial_rewarding_params: InitialRewardingParams,
|
||||
|
||||
#[serde(default)]
|
||||
pub profit_margin: ProfitMarginRange,
|
||||
|
||||
#[serde(default)]
|
||||
pub interval_operating_cost: OperatingCostRange,
|
||||
}
|
||||
|
||||
#[cw_serde]
|
||||
@@ -269,6 +276,12 @@ pub enum ExecuteMsg {
|
||||
owner: String,
|
||||
},
|
||||
|
||||
// vesting migration:
|
||||
MigrateVestedMixNode {},
|
||||
MigrateVestedDelegation {
|
||||
mix_id: MixId,
|
||||
},
|
||||
|
||||
// testing-only
|
||||
#[cfg(feature = "contract-testing")]
|
||||
TestingResolveAllPendingEvents {
|
||||
@@ -381,6 +394,9 @@ impl ExecuteMsg {
|
||||
ExecuteMsg::WithdrawDelegatorRewardOnBehalf { mix_id, .. } => {
|
||||
format!("withdrawing delegator reward from mixnode {mix_id} on behalf")
|
||||
}
|
||||
ExecuteMsg::MigrateVestedMixNode { .. } => "migrate vested mixnode".into(),
|
||||
ExecuteMsg::MigrateVestedDelegation { .. } => "migrate vested delegation".to_string(),
|
||||
|
||||
#[cfg(feature = "contract-testing")]
|
||||
ExecuteMsg::TestingResolveAllPendingEvents { .. } => {
|
||||
"resolving all pending events".into()
|
||||
|
||||
@@ -38,6 +38,7 @@ pub enum PendingEpochEventKind {
|
||||
/// Request to create a delegation towards particular mixnode.
|
||||
/// Note that if such delegation already exists, it will get updated with the provided token amount.
|
||||
#[serde(alias = "Delegate")]
|
||||
#[non_exhaustive]
|
||||
Delegate {
|
||||
/// The address of the owner of the delegation.
|
||||
owner: Addr,
|
||||
@@ -55,6 +56,7 @@ pub enum PendingEpochEventKind {
|
||||
|
||||
/// Request to remove delegation from particular mixnode.
|
||||
#[serde(alias = "Undelegate")]
|
||||
#[non_exhaustive]
|
||||
Undelegate {
|
||||
/// The address of the owner of the delegation.
|
||||
owner: Addr,
|
||||
@@ -109,6 +111,23 @@ impl PendingEpochEventKind {
|
||||
kind: self,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_delegate(owner: Addr, mix_id: MixId, amount: Coin) -> Self {
|
||||
PendingEpochEventKind::Delegate {
|
||||
owner,
|
||||
mix_id,
|
||||
amount,
|
||||
proxy: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_undelegate(owner: Addr, mix_id: MixId) -> Self {
|
||||
PendingEpochEventKind::Undelegate {
|
||||
owner,
|
||||
mix_id,
|
||||
proxy: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<(EpochEventId, PendingEpochEventData)> for PendingEpochEvent {
|
||||
|
||||
-1
@@ -47,7 +47,6 @@ impl SimulatedNode {
|
||||
self.rewarding_details.total_unit_reward,
|
||||
delegation,
|
||||
42,
|
||||
None,
|
||||
);
|
||||
|
||||
self.delegations.insert(delegator, delegation);
|
||||
|
||||
@@ -37,13 +37,12 @@ impl SigningPurpose for MixnodeBondingPayload {
|
||||
pub fn construct_mixnode_bonding_sign_payload(
|
||||
nonce: Nonce,
|
||||
sender: Addr,
|
||||
proxy: Option<Addr>,
|
||||
pledge: Coin,
|
||||
mix_node: MixNode,
|
||||
cost_params: MixNodeCostParams,
|
||||
) -> SignableMixNodeBondingMsg {
|
||||
let payload = MixnodeBondingPayload::new(mix_node, cost_params);
|
||||
let content = ContractMessageContent::new(sender, proxy, vec![pledge], payload);
|
||||
let content = ContractMessageContent::new(sender, vec![pledge], payload);
|
||||
|
||||
SignableMessage::new(nonce, content)
|
||||
}
|
||||
@@ -68,12 +67,11 @@ impl SigningPurpose for GatewayBondingPayload {
|
||||
pub fn construct_gateway_bonding_sign_payload(
|
||||
nonce: Nonce,
|
||||
sender: Addr,
|
||||
proxy: Option<Addr>,
|
||||
pledge: Coin,
|
||||
gateway: Gateway,
|
||||
) -> SignableGatewayBondingMsg {
|
||||
let payload = GatewayBondingPayload::new(gateway);
|
||||
let content = ContractMessageContent::new(sender, proxy, vec![pledge], payload);
|
||||
let content = ContractMessageContent::new(sender, vec![pledge], payload);
|
||||
|
||||
SignableMessage::new(nonce, content)
|
||||
}
|
||||
@@ -82,17 +80,14 @@ pub fn construct_gateway_bonding_sign_payload(
|
||||
pub struct FamilyJoinPermit {
|
||||
// the granter of this permit
|
||||
family_head: FamilyHead,
|
||||
// whether the **member** will want to join via the proxy (i.e. vesting contract)
|
||||
proxy: Option<Addr>,
|
||||
// the actual member we want to permit to join
|
||||
member_node: IdentityKey,
|
||||
}
|
||||
|
||||
impl FamilyJoinPermit {
|
||||
pub fn new(family_head: FamilyHead, proxy: Option<Addr>, member_node: IdentityKey) -> Self {
|
||||
pub fn new(family_head: FamilyHead, member_node: IdentityKey) -> Self {
|
||||
Self {
|
||||
family_head,
|
||||
proxy,
|
||||
member_node,
|
||||
}
|
||||
}
|
||||
@@ -107,10 +102,9 @@ impl SigningPurpose for FamilyJoinPermit {
|
||||
pub fn construct_family_join_permit(
|
||||
nonce: Nonce,
|
||||
family_head: FamilyHead,
|
||||
proxy: Option<Addr>,
|
||||
member_node: IdentityKey,
|
||||
) -> SignableFamilyJoinPermitMsg {
|
||||
let payload = FamilyJoinPermit::new(family_head, proxy, member_node);
|
||||
let payload = FamilyJoinPermit::new(family_head, member_node);
|
||||
|
||||
// note: we're NOT wrapping it in `ContractMessageContent` because the family head is not going to be the one
|
||||
// sending the message to the contract
|
||||
|
||||
@@ -3,9 +3,11 @@
|
||||
|
||||
use crate::error::MixnetContractError;
|
||||
use crate::Layer;
|
||||
use contracts_common::Percent;
|
||||
use cosmwasm_schema::cw_serde;
|
||||
use cosmwasm_std::Addr;
|
||||
use cosmwasm_std::Coin;
|
||||
use cosmwasm_std::{Addr, Uint128};
|
||||
use std::fmt::{Display, Formatter};
|
||||
use std::ops::Index;
|
||||
|
||||
// type aliases for better reasoning about available data
|
||||
@@ -15,6 +17,65 @@ pub type SphinxKeyRef<'a> = &'a str;
|
||||
pub type MixId = u32;
|
||||
pub type BlockHeight = u64;
|
||||
|
||||
#[cw_serde]
|
||||
pub struct RangedValue<T> {
|
||||
pub minimum: T,
|
||||
pub maximum: T,
|
||||
}
|
||||
|
||||
impl<T> Copy for RangedValue<T> where T: Copy {}
|
||||
|
||||
pub type ProfitMarginRange = RangedValue<Percent>;
|
||||
pub type OperatingCostRange = RangedValue<Uint128>;
|
||||
|
||||
impl<T> Display for RangedValue<T>
|
||||
where
|
||||
T: Display,
|
||||
{
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{} - {}", self.minimum, self.maximum)
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for ProfitMarginRange {
|
||||
fn default() -> Self {
|
||||
ProfitMarginRange {
|
||||
minimum: Percent::zero(),
|
||||
maximum: Percent::hundred(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for OperatingCostRange {
|
||||
fn default() -> Self {
|
||||
OperatingCostRange {
|
||||
minimum: Uint128::zero(),
|
||||
|
||||
// 1 billion (native tokens, i.e. 1 billion * 1'000'000 base tokens) - the total supply
|
||||
maximum: Uint128::new(1_000_000_000_000_000),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> RangedValue<T>
|
||||
where
|
||||
T: Copy + PartialOrd + PartialEq,
|
||||
{
|
||||
pub fn normalise(&self, value: T) -> T {
|
||||
if value < self.minimum {
|
||||
self.minimum
|
||||
} else if value > self.maximum {
|
||||
self.maximum
|
||||
} else {
|
||||
value
|
||||
}
|
||||
}
|
||||
|
||||
pub fn within_range(&self, value: T) -> bool {
|
||||
value >= self.minimum && value <= self.maximum
|
||||
}
|
||||
}
|
||||
|
||||
/// Specifies layer assignment for the given mixnode.
|
||||
#[cw_serde]
|
||||
pub struct LayerAssignment {
|
||||
@@ -154,4 +215,14 @@ pub struct ContractStateParams {
|
||||
|
||||
/// Minimum amount a gateway must pledge to get into the system.
|
||||
pub minimum_gateway_pledge: Coin,
|
||||
|
||||
/// Defines the allowed profit margin range of operators.
|
||||
/// default: 0% - 100%
|
||||
#[serde(default)]
|
||||
pub profit_margin: ProfitMarginRange,
|
||||
|
||||
/// Defines the allowed interval operating cost range of operators.
|
||||
/// default: 0 - 1'000'000'000'000'000 (1 Billion native tokens - the total supply)
|
||||
#[serde(default)]
|
||||
pub interval_operating_cost: OperatingCostRange,
|
||||
}
|
||||
|
||||
@@ -167,3 +167,11 @@ pub fn new_track_undelegation_event() -> Event {
|
||||
pub fn new_track_reward_event() -> Event {
|
||||
Event::new(TRACK_REWARD_EVENT_TYPE)
|
||||
}
|
||||
|
||||
pub fn new_track_migrate_mixnode_event() -> Event {
|
||||
Event::new("track_migrate_vesting_mixnode")
|
||||
}
|
||||
|
||||
pub fn new_track_migrate_delegation_event() -> Event {
|
||||
Event::new("track_migrate_vesting_delegation")
|
||||
}
|
||||
|
||||
@@ -136,6 +136,14 @@ pub enum ExecuteMsg {
|
||||
address: String,
|
||||
cap: PledgeCap,
|
||||
},
|
||||
TrackMigratedMixnode {
|
||||
owner: String,
|
||||
},
|
||||
// no need to track migrated gateways as there are no vesting gateways on mainnet
|
||||
TrackMigratedDelegation {
|
||||
owner: String,
|
||||
mix_id: MixId,
|
||||
},
|
||||
}
|
||||
|
||||
impl ExecuteMsg {
|
||||
@@ -171,6 +179,10 @@ impl ExecuteMsg {
|
||||
ExecuteMsg::TransferOwnership { .. } => "VestingExecuteMsg::TransferOwnership",
|
||||
ExecuteMsg::UpdateStakingAddress { .. } => "VestingExecuteMsg::UpdateStakingAddress",
|
||||
ExecuteMsg::UpdateLockedPledgeCap { .. } => "VestingExecuteMsg::UpdateLockedPledgeCap",
|
||||
ExecuteMsg::TrackMigratedMixnode { .. } => "VestingExecuteMsg::TrackMigratedMixnode",
|
||||
ExecuteMsg::TrackMigratedDelegation { .. } => {
|
||||
"VestingExecuteMsg::TrackMigratedDelegation"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,16 +12,16 @@ aes = { workspace = true, optional = true }
|
||||
bs58 = { workspace = true }
|
||||
blake3 = { workspace = true, features = ["traits-preview"], optional = true }
|
||||
ctr = { workspace = true, optional = true }
|
||||
digest = { version = "0.10.3", optional = true }
|
||||
digest = { workspace = true, optional = true }
|
||||
generic-array = { workspace = true, optional = true }
|
||||
hkdf = { workspace = true, optional = true }
|
||||
hmac = { workspace = true, optional = true }
|
||||
cipher = { workspace = true, optional = true }
|
||||
x25519-dalek = { version = "2.0", optional = true, features = ["static_secrets"]}
|
||||
ed25519-dalek = { version = "2.1", features = ["rand_core"], optional = true }
|
||||
x25519-dalek = { workspace = true, features = ["static_secrets"], optional = true }
|
||||
ed25519-dalek = { workspace = true, features = ["rand_core"], optional = true }
|
||||
rand = { workspace = true, optional = true }
|
||||
serde_bytes = { version = "0.11.6", optional = true }
|
||||
serde_crate = { version = "1.0", optional = true, default_features = false, features = ["derive"], package = "serde" }
|
||||
serde_crate = { version = "1.0", optional = true, default-features = false, features = ["derive"], package = "serde" }
|
||||
subtle-encoding = { workspace = true, features = ["bech32-preview"] }
|
||||
thiserror = { workspace = true }
|
||||
zeroize = { workspace = true, optional = true, features = ["zeroize_derive"] }
|
||||
@@ -31,7 +31,7 @@ nym-sphinx-types = { path = "../nymsphinx/types", version = "0.2.0", default-fea
|
||||
nym-pemstore = { path = "../../common/pemstore", version = "0.3.0" }
|
||||
|
||||
[dev-dependencies]
|
||||
rand_chacha = "0.3"
|
||||
rand_chacha = { workspace = true }
|
||||
|
||||
[features]
|
||||
default = ["sphinx"]
|
||||
|
||||
@@ -19,7 +19,7 @@ bs58 = { workspace = true }
|
||||
|
||||
lazy_static = { workspace = true }
|
||||
rand = { version = "0.8.5", default-features = false}
|
||||
rand_chacha = "0.3"
|
||||
rand_chacha = { workspace = true }
|
||||
rand_core = { workspace = true }
|
||||
sha2 = "0.9"
|
||||
serde = { workspace = true }
|
||||
|
||||
@@ -20,6 +20,8 @@ serde_json = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
tracing = { workspace = true }
|
||||
|
||||
nym-bin-common = { path = "../bin-common" }
|
||||
|
||||
# for request timeout until https://github.com/seanmonstar/reqwest/issues/1135 is fixed
|
||||
[target."cfg(target_arch = \"wasm32\")".dependencies.wasmtimer]
|
||||
workspace = true
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use async_trait::async_trait;
|
||||
use http::header;
|
||||
use reqwest::header::HeaderValue;
|
||||
use reqwest::{RequestBuilder, Response, StatusCode};
|
||||
use serde::de::DeserializeOwned;
|
||||
@@ -15,6 +14,10 @@ use url::Url;
|
||||
|
||||
pub use reqwest::IntoUrl;
|
||||
|
||||
pub use user_agent::UserAgent;
|
||||
|
||||
mod user_agent;
|
||||
|
||||
pub const DEFAULT_TIMEOUT: Duration = Duration::from_secs(10);
|
||||
|
||||
pub type PathSegments<'a> = &'a [&'a str];
|
||||
@@ -97,13 +100,6 @@ impl ClientBuilder {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_host_header(mut self, host: &str) -> Self {
|
||||
let mut headers = header::HeaderMap::new();
|
||||
headers.insert(header::HOST, HeaderValue::from_str(host).unwrap()); //SW Handle this unwrap later
|
||||
self.reqwest_client_builder = self.reqwest_client_builder.default_headers(headers);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_user_agent<V>(mut self, value: V) -> Self
|
||||
where
|
||||
V: TryInto<HeaderValue>,
|
||||
@@ -163,23 +159,6 @@ impl Client {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn new_fronted(base_url: Url, fronting_url: Url, timeout: Option<Duration>) -> Self {
|
||||
let host = base_url.host_str().unwrap();
|
||||
let mut fronted_url = base_url.clone();
|
||||
fronted_url.set_host(fronting_url.host_str()).unwrap();
|
||||
let builder = ClientBuilder::new::<_, String>(fronted_url)
|
||||
.expect(
|
||||
"we provided valid url and we were unwrapping previous construction errors anyway",
|
||||
)
|
||||
.with_host_header(host);
|
||||
|
||||
//SW polish that later if needed
|
||||
match timeout {
|
||||
Some(timeout) => builder.with_timeout(timeout).build::<String>().unwrap(),
|
||||
None => builder.build::<String>().unwrap(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_url<U, E>(url: U, timeout: Option<Duration>) -> Result<Self, HttpClientError<E>>
|
||||
where
|
||||
U: IntoUrl,
|
||||
@@ -204,21 +183,6 @@ impl Client {
|
||||
self.base_url = new_url
|
||||
}
|
||||
|
||||
pub fn change_fronted_url(&mut self, new_api_url: Url, new_fronting_url: Url) {
|
||||
let host = new_api_url.host_str().unwrap();
|
||||
let mut new_fronted_url = new_api_url.clone();
|
||||
new_fronted_url
|
||||
.set_host(new_fronting_url.host_str())
|
||||
.unwrap();
|
||||
let mut headers = header::HeaderMap::new();
|
||||
headers.insert(header::HOST, HeaderValue::from_str(host).unwrap()); //SW Handle this unwrap later
|
||||
self.reqwest_client = reqwest::ClientBuilder::new()
|
||||
.default_headers(headers)
|
||||
.build()
|
||||
.unwrap();
|
||||
self.base_url = new_fronted_url
|
||||
}
|
||||
|
||||
pub fn current_url(&self) -> &Url {
|
||||
&self.base_url
|
||||
}
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use std::fmt;
|
||||
|
||||
use http::HeaderValue;
|
||||
use nym_bin_common::build_information::{BinaryBuildInformation, BinaryBuildInformationOwned};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct UserAgent {
|
||||
pub application: String,
|
||||
pub version: String,
|
||||
pub platform: String,
|
||||
pub git_commit: String,
|
||||
}
|
||||
|
||||
impl fmt::Display for UserAgent {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let abbreviated_commit = self.git_commit.chars().take(7).collect::<String>();
|
||||
write!(
|
||||
f,
|
||||
"{}/{}/{}/{}",
|
||||
self.application, self.version, self.platform, abbreviated_commit
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<UserAgent> for HeaderValue {
|
||||
type Error = http::header::InvalidHeaderValue;
|
||||
|
||||
fn try_from(user_agent: UserAgent) -> Result<Self, Self::Error> {
|
||||
HeaderValue::from_str(&user_agent.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<BinaryBuildInformation> for UserAgent {
|
||||
fn from(build_info: BinaryBuildInformation) -> Self {
|
||||
UserAgent {
|
||||
application: build_info.binary_name.to_string(),
|
||||
version: build_info.build_version.to_string(),
|
||||
platform: build_info.cargo_triple.to_string(),
|
||||
git_commit: build_info.commit_sha.to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<BinaryBuildInformationOwned> for UserAgent {
|
||||
fn from(build_info: BinaryBuildInformationOwned) -> Self {
|
||||
UserAgent {
|
||||
application: build_info.binary_name,
|
||||
version: build_info.build_version,
|
||||
platform: build_info.cargo_triple,
|
||||
git_commit: build_info.commit_sha,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,7 @@ bytes = { workspace = true }
|
||||
nym-bin-common = { path = "../bin-common" }
|
||||
nym-crypto = { path = "../crypto" }
|
||||
nym-sphinx = { path = "../nymsphinx" }
|
||||
rand = "0.8.5"
|
||||
rand = { workspace = true }
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
thiserror = { workspace = true }
|
||||
time = { workspace = true }
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::{v6, v7};
|
||||
|
||||
impl From<v7::response::StaticConnectFailureReason> for v6::response::StaticConnectFailureReason {
|
||||
fn from(failure: v7::response::StaticConnectFailureReason) -> Self {
|
||||
match failure {
|
||||
v7::response::StaticConnectFailureReason::RequestedIpAlreadyInUse => {
|
||||
v6::response::StaticConnectFailureReason::RequestedIpAlreadyInUse
|
||||
}
|
||||
v7::response::StaticConnectFailureReason::RequestedNymAddressAlreadyInUse => {
|
||||
v6::response::StaticConnectFailureReason::RequestedNymAddressAlreadyInUse
|
||||
}
|
||||
v7::response::StaticConnectFailureReason::OutOfDateTimestamp => {
|
||||
v6::response::StaticConnectFailureReason::Other("out of date timestamp".to_string())
|
||||
}
|
||||
v7::response::StaticConnectFailureReason::Other(reason) => {
|
||||
v6::response::StaticConnectFailureReason::Other(reason)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<v7::response::DynamicConnectFailureReason> for v6::response::DynamicConnectFailureReason {
|
||||
fn from(failure: v7::response::DynamicConnectFailureReason) -> Self {
|
||||
match failure {
|
||||
v7::response::DynamicConnectFailureReason::RequestedNymAddressAlreadyInUse => {
|
||||
v6::response::DynamicConnectFailureReason::RequestedNymAddressAlreadyInUse
|
||||
}
|
||||
v7::response::DynamicConnectFailureReason::NoAvailableIp => {
|
||||
v6::response::DynamicConnectFailureReason::NoAvailableIp
|
||||
}
|
||||
v7::response::DynamicConnectFailureReason::Other(err) => {
|
||||
v6::response::DynamicConnectFailureReason::Other(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<v7::response::InfoResponseReply> for v6::response::InfoResponseReply {
|
||||
fn from(reply: v7::response::InfoResponseReply) -> Self {
|
||||
match reply {
|
||||
v7::response::InfoResponseReply::Generic { msg } => {
|
||||
v6::response::InfoResponseReply::Generic { msg }
|
||||
}
|
||||
v7::response::InfoResponseReply::VersionMismatch {
|
||||
request_version,
|
||||
response_version,
|
||||
} => v6::response::InfoResponseReply::VersionMismatch {
|
||||
request_version,
|
||||
response_version,
|
||||
},
|
||||
v7::response::InfoResponseReply::ExitPolicyFilterCheckFailed { dst } => {
|
||||
v6::response::InfoResponseReply::ExitPolicyFilterCheckFailed { dst }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<v7::response::InfoLevel> for v6::response::InfoLevel {
|
||||
fn from(level: v7::response::InfoLevel) -> Self {
|
||||
match level {
|
||||
v7::response::InfoLevel::Info => v6::response::InfoLevel::Info,
|
||||
v7::response::InfoLevel::Warn => v6::response::InfoLevel::Warn,
|
||||
v7::response::InfoLevel::Error => v6::response::InfoLevel::Error,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
pub mod conversion;
|
||||
pub mod request;
|
||||
pub mod response;
|
||||
|
||||
|
||||
@@ -198,6 +198,17 @@ impl IpPacketRequestData {
|
||||
| IpPacketRequestData::Health(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn signable_request(&self) -> Option<Result<Vec<u8>, SignatureError>> {
|
||||
match self {
|
||||
IpPacketRequestData::StaticConnect(request) => Some(request.request()),
|
||||
IpPacketRequestData::DynamicConnect(request) => Some(request.request()),
|
||||
IpPacketRequestData::Disconnect(request) => Some(request.request()),
|
||||
IpPacketRequestData::Data(_) => None,
|
||||
IpPacketRequestData::Ping(_) => None,
|
||||
IpPacketRequestData::Health(_) => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// A static connect request is when the client provides the internal IP address it will use on the
|
||||
|
||||
@@ -42,6 +42,7 @@ pub struct NymNetworkDetails {
|
||||
pub endpoints: Vec<ValidatorDetails>,
|
||||
pub contracts: NymContracts,
|
||||
pub explorer_api: Option<String>,
|
||||
pub nym_vpn_api_url: Option<String>,
|
||||
}
|
||||
|
||||
// by default we assume the same defaults as mainnet, i.e. same prefixes and denoms
|
||||
@@ -71,6 +72,7 @@ impl NymNetworkDetails {
|
||||
endpoints: Default::default(),
|
||||
contracts: Default::default(),
|
||||
explorer_api: Default::default(),
|
||||
nym_vpn_api_url: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,6 +128,7 @@ impl NymNetworkDetails {
|
||||
.with_multisig_contract(get_optional_env(var_names::MULTISIG_CONTRACT_ADDRESS))
|
||||
.with_coconut_dkg_contract(get_optional_env(var_names::COCONUT_DKG_CONTRACT_ADDRESS))
|
||||
.with_explorer_api(get_optional_env(var_names::EXPLORER_API))
|
||||
.with_nym_vpn_api_url(get_optional_env(var_names::NYM_VPN_API))
|
||||
}
|
||||
|
||||
pub fn new_mainnet() -> Self {
|
||||
@@ -155,6 +158,7 @@ impl NymNetworkDetails {
|
||||
),
|
||||
},
|
||||
explorer_api: parse_optional_str(mainnet::EXPLORER_API),
|
||||
nym_vpn_api_url: parse_optional_str(mainnet::NYM_VPN_API),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -263,6 +267,19 @@ impl NymNetworkDetails {
|
||||
self.explorer_api = endpoint.map(Into::into);
|
||||
self
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn with_nym_vpn_api_url<S: Into<String>>(mut self, endpoint: Option<S>) -> Self {
|
||||
self.nym_vpn_api_url = endpoint.map(Into::into);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn nym_vpn_api_url(&self) -> Option<Url> {
|
||||
self.nym_vpn_api_url.as_ref().map(|url| {
|
||||
url.parse()
|
||||
.expect("the provided nym-vpn api url is invalid!")
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Serialize, Deserialize, Clone, PartialEq, Eq)]
|
||||
|
||||
@@ -27,11 +27,11 @@ pub const COCONUT_DKG_CONTRACT_ADDRESS: &str =
|
||||
|
||||
pub const REWARDING_VALIDATOR_ADDRESS: &str = "n10yyd98e2tuwu0f7ypz9dy3hhjw7v772q6287gy";
|
||||
|
||||
pub const STATISTICS_SERVICE_DOMAIN_ADDRESS: &str = "https://mainnet-stats.nymte.ch:8090/";
|
||||
pub const NYXD_URL: &str = "https://rpc.nymtech.net";
|
||||
pub const NYM_API: &str = "https://validator.nymtech.net/api/";
|
||||
pub const NYXD_WS: &str = "wss://rpc.nymtech.net/websocket";
|
||||
pub const EXPLORER_API: &str = "https://explorer.nymtech.net/api/";
|
||||
pub const NYM_VPN_API: &str = "https://nymvpn.net/api/";
|
||||
|
||||
// I'm making clippy mad on purpose, because that url HAS TO be updated and deployed before merging
|
||||
pub const EXIT_POLICY_URL: &str =
|
||||
@@ -110,15 +110,12 @@ pub fn export_to_env() {
|
||||
var_names::REWARDING_VALIDATOR_ADDRESS,
|
||||
REWARDING_VALIDATOR_ADDRESS,
|
||||
);
|
||||
set_var_to_default(
|
||||
var_names::STATISTICS_SERVICE_DOMAIN_ADDRESS,
|
||||
STATISTICS_SERVICE_DOMAIN_ADDRESS,
|
||||
);
|
||||
set_var_to_default(var_names::NYXD, NYXD_URL);
|
||||
set_var_to_default(var_names::NYM_API, NYM_API);
|
||||
set_var_to_default(var_names::NYXD_WEBSOCKET, NYXD_WS);
|
||||
set_var_to_default(var_names::EXPLORER_API, EXPLORER_API);
|
||||
set_var_to_default(var_names::EXIT_POLICY_URL, EXIT_POLICY_URL);
|
||||
set_var_to_default(var_names::NYM_VPN_API, NYM_VPN_API);
|
||||
}
|
||||
|
||||
pub fn export_to_env_if_not_set() {
|
||||
@@ -155,10 +152,6 @@ pub fn export_to_env_if_not_set() {
|
||||
var_names::REWARDING_VALIDATOR_ADDRESS,
|
||||
REWARDING_VALIDATOR_ADDRESS,
|
||||
);
|
||||
set_var_conditionally_to_default(
|
||||
var_names::STATISTICS_SERVICE_DOMAIN_ADDRESS,
|
||||
STATISTICS_SERVICE_DOMAIN_ADDRESS,
|
||||
);
|
||||
set_var_conditionally_to_default(var_names::NYXD, NYXD_URL);
|
||||
set_var_conditionally_to_default(var_names::NYM_API, NYM_API);
|
||||
set_var_conditionally_to_default(var_names::NYXD_WEBSOCKET, NYXD_WS);
|
||||
|
||||
@@ -19,12 +19,12 @@ pub const GROUP_CONTRACT_ADDRESS: &str = "GROUP_CONTRACT_ADDRESS";
|
||||
pub const MULTISIG_CONTRACT_ADDRESS: &str = "MULTISIG_CONTRACT_ADDRESS";
|
||||
pub const COCONUT_DKG_CONTRACT_ADDRESS: &str = "COCONUT_DKG_CONTRACT_ADDRESS";
|
||||
pub const REWARDING_VALIDATOR_ADDRESS: &str = "REWARDING_VALIDATOR_ADDRESS";
|
||||
pub const STATISTICS_SERVICE_DOMAIN_ADDRESS: &str = "STATISTICS_SERVICE_DOMAIN_ADDRESS";
|
||||
pub const NYXD: &str = "NYXD";
|
||||
pub const NYM_API: &str = "NYM_API";
|
||||
pub const NYXD_WEBSOCKET: &str = "NYXD_WS";
|
||||
pub const EXPLORER_API: &str = "EXPLORER_API";
|
||||
pub const EXIT_POLICY_URL: &str = "EXIT_POLICY";
|
||||
pub const NYM_VPN_API: &str = "NYM_VPN_API";
|
||||
|
||||
pub const DKG_TIME_CONFIGURATION: &str = "DKG_TIME_CONFIGURATION";
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ license.workspace = true
|
||||
|
||||
[dependencies]
|
||||
bls12_381 = { workspace = true, default-features = false, features = ["pairings", "alloc", "experimental"] }
|
||||
itertools = "0.10"
|
||||
itertools = { workspace = true }
|
||||
digest = "0.9"
|
||||
rand = "0.8"
|
||||
thiserror = { workspace = true }
|
||||
@@ -33,7 +33,7 @@ default-features = false
|
||||
[dev-dependencies]
|
||||
criterion = { workspace = true, features = ["html_reports"] }
|
||||
doc-comment = { workspace = true }
|
||||
rand_chacha = "0.3"
|
||||
rand_chacha = { workspace = true }
|
||||
|
||||
[[bench]]
|
||||
name = "benchmarks"
|
||||
|
||||
@@ -9,7 +9,7 @@ repository = { workspace = true }
|
||||
|
||||
[dependencies]
|
||||
rand = { workspace = true }
|
||||
serde_crate = { version = "1.0", optional = true, default_features = false, features = ["derive"], package = "serde" }
|
||||
serde_crate = { version = "1.0", optional = true, default-features = false, features = ["derive"], package = "serde" }
|
||||
generic-array = { workspace = true, optional = true, features = ["serde"] }
|
||||
thiserror = { workspace = true }
|
||||
zeroize = { workspace = true }
|
||||
|
||||
@@ -24,4 +24,4 @@ nym-topology = { path = "../../topology" }
|
||||
version = "0.2.83"
|
||||
|
||||
[dev-dependencies]
|
||||
rand_chacha = "0.3"
|
||||
rand_chacha = { workspace = true }
|
||||
|
||||
@@ -17,7 +17,7 @@ cosmrs.workspace = true
|
||||
eyre = { workspace = true }
|
||||
futures.workspace = true
|
||||
humantime = { workspace = true }
|
||||
sha2 = "0.10.8"
|
||||
sha2 = { workspace = true }
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
sqlx = { workspace = true, features = ["runtime-tokio-rustls", "sqlite", "macros", "migrate", "time"] }
|
||||
tendermint.workspace = true
|
||||
|
||||
@@ -8,7 +8,7 @@ license.workspace = true
|
||||
|
||||
[dependencies]
|
||||
anyhow = { workspace = true }
|
||||
dirs = "4.0"
|
||||
dirs = { workspace = true }
|
||||
futures = { workspace = true }
|
||||
log = { workspace = true }
|
||||
pin-project = { workspace = true }
|
||||
|
||||
@@ -27,6 +27,7 @@ use nym_task::manager::TaskStatus;
|
||||
use nym_task::{TaskClient, TaskHandle};
|
||||
|
||||
use anyhow::anyhow;
|
||||
use nym_validator_client::UserAgent;
|
||||
use std::error::Error;
|
||||
use std::path::PathBuf;
|
||||
|
||||
@@ -61,6 +62,8 @@ pub struct NymClient<S> {
|
||||
|
||||
setup_method: GatewaySetup,
|
||||
|
||||
user_agent: UserAgent,
|
||||
|
||||
/// Optional path to a .json file containing standalone network details.
|
||||
custom_mixnet: Option<PathBuf>,
|
||||
}
|
||||
@@ -74,11 +77,17 @@ where
|
||||
<S::GatewaysDetailsStore as GatewaysDetailsStore>::StorageError: Sync + Send,
|
||||
<S::KeyStore as KeyStore>::StorageError: Send + Sync,
|
||||
{
|
||||
pub fn new(config: Config, storage: S, custom_mixnet: Option<PathBuf>) -> Self {
|
||||
pub fn new(
|
||||
config: Config,
|
||||
storage: S,
|
||||
user_agent: UserAgent,
|
||||
custom_mixnet: Option<PathBuf>,
|
||||
) -> Self {
|
||||
NymClient {
|
||||
config,
|
||||
storage,
|
||||
setup_method: GatewaySetup::MustLoad { gateway_id: None },
|
||||
user_agent,
|
||||
custom_mixnet,
|
||||
}
|
||||
}
|
||||
@@ -226,7 +235,8 @@ where
|
||||
|
||||
let mut base_builder =
|
||||
BaseClientBuilder::new(&self.config.base, self.storage, dkg_query_client)
|
||||
.with_gateway_setup(self.setup_method);
|
||||
.with_gateway_setup(self.setup_method)
|
||||
.with_user_agent(self.user_agent);
|
||||
|
||||
if let Some(custom_mixnet) = &self.custom_mixnet {
|
||||
base_builder = base_builder.with_stored_topology(custom_mixnet)?;
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
# Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
[package]
|
||||
name = "nym-statistics-common"
|
||||
version = "1.0.1"
|
||||
edition = "2021"
|
||||
license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
async-trait = { workspace = true }
|
||||
log = { workspace = true }
|
||||
reqwest = { workspace = true, features = ["json"] }
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
serde_json = { workspace = true }
|
||||
sqlx = { workspace = true, features = ["runtime-tokio-rustls", "chrono"]}
|
||||
thiserror = { workspace = true }
|
||||
tokio = { workspace = true, features = ["time"] }
|
||||
@@ -1,51 +0,0 @@
|
||||
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::error::StatsError;
|
||||
use crate::StatsMessage;
|
||||
|
||||
pub const DEFAULT_STATISTICS_SERVICE_ADDRESS: &str = "127.0.0.1";
|
||||
pub const DEFAULT_STATISTICS_SERVICE_PORT: u16 = 8091;
|
||||
|
||||
pub const STATISTICS_SERVICE_VERSION: &str = "/v1";
|
||||
pub const STATISTICS_SERVICE_API_STATISTICS: &str = "statistic";
|
||||
|
||||
pub async fn build_and_send_statistics_request(
|
||||
msg: StatsMessage,
|
||||
url: String,
|
||||
) -> Result<(), StatsError> {
|
||||
reqwest::Client::new()
|
||||
.post(format!(
|
||||
"{url}{STATISTICS_SERVICE_VERSION}/{STATISTICS_SERVICE_API_STATISTICS}"
|
||||
))
|
||||
.json(&msg)
|
||||
.send()
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn build_statistics_request_bytes(msg: StatsMessage) -> Result<Vec<u8>, StatsError> {
|
||||
let json_msg = msg.to_json()?;
|
||||
|
||||
let req = reqwest::Request::new(
|
||||
reqwest::Method::POST,
|
||||
reqwest::Url::parse(&format!(
|
||||
"http://{DEFAULT_STATISTICS_SERVICE_ADDRESS}:{DEFAULT_STATISTICS_SERVICE_PORT}{STATISTICS_SERVICE_VERSION}/{STATISTICS_SERVICE_API_STATISTICS}"
|
||||
))
|
||||
.unwrap(),
|
||||
);
|
||||
let data = format!(
|
||||
"{} {} {:?}\n\
|
||||
Content-Type: application/json\n\
|
||||
Content-Length: {}\n\n\
|
||||
{}\n",
|
||||
req.method().as_str(),
|
||||
req.url().as_str(),
|
||||
req.version(),
|
||||
json_msg.len(),
|
||||
json_msg
|
||||
);
|
||||
|
||||
Ok(data.into_bytes())
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use async_trait::async_trait;
|
||||
use log::error;
|
||||
use sqlx::types::chrono::{DateTime, Utc};
|
||||
use std::time::Duration;
|
||||
use tokio::time;
|
||||
|
||||
use crate::error::StatsError;
|
||||
use crate::StatsMessage;
|
||||
|
||||
const STATISTICS_TIMER_INTERVAL: Duration = Duration::from_secs(60);
|
||||
|
||||
#[async_trait]
|
||||
pub trait StatisticsCollector {
|
||||
async fn create_stats_message(
|
||||
&self,
|
||||
interval: Duration,
|
||||
timestamp: DateTime<Utc>,
|
||||
) -> StatsMessage;
|
||||
async fn send_stats_message(&self, stats_message: StatsMessage) -> Result<(), StatsError>;
|
||||
async fn reset_stats(&mut self);
|
||||
}
|
||||
|
||||
pub struct StatisticsSender<T: StatisticsCollector> {
|
||||
collector: T,
|
||||
interval: Duration,
|
||||
timestamp: DateTime<Utc>,
|
||||
}
|
||||
|
||||
impl<T: StatisticsCollector> StatisticsSender<T> {
|
||||
pub fn new(collector: T) -> Self {
|
||||
StatisticsSender {
|
||||
collector,
|
||||
interval: STATISTICS_TIMER_INTERVAL,
|
||||
timestamp: Utc::now(),
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn run(&mut self) {
|
||||
let mut interval = time::interval(self.interval);
|
||||
loop {
|
||||
interval.tick().await;
|
||||
|
||||
let stats_message = self
|
||||
.collector
|
||||
.create_stats_message(self.interval, self.timestamp)
|
||||
.await;
|
||||
if let Err(e) = self.collector.send_stats_message(stats_message).await {
|
||||
error!("Statistics not sent: {}", e);
|
||||
}
|
||||
self.collector.reset_stats().await;
|
||||
self.timestamp = Utc::now();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum StatsError {
|
||||
#[error("Serde JSON error: {0}")]
|
||||
SerdeJsonError(#[from] serde_json::Error),
|
||||
|
||||
#[error("Reqwest error: {0}")]
|
||||
ReqwestError(#[from] reqwest::Error),
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use error::StatsError;
|
||||
|
||||
pub mod api;
|
||||
pub mod collector;
|
||||
pub mod error;
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub struct StatsMessage {
|
||||
pub stats_data: Vec<StatsData>,
|
||||
pub interval_seconds: u32,
|
||||
pub timestamp: String,
|
||||
}
|
||||
|
||||
impl StatsMessage {
|
||||
pub fn to_json(&self) -> Result<String, StatsError> {
|
||||
Ok(serde_json::to_string(self)?)
|
||||
}
|
||||
|
||||
pub fn from_json(s: &str) -> Result<Self, StatsError> {
|
||||
Ok(serde_json::from_str(s)?)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub enum StatsData {
|
||||
Service(StatsServiceData),
|
||||
Gateway(StatsGatewayData),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub struct StatsGatewayData {
|
||||
pub gateway_id: String,
|
||||
pub inbox_count: u32,
|
||||
}
|
||||
|
||||
impl StatsGatewayData {
|
||||
pub fn new(gateway_id: String, inbox_count: u32) -> Self {
|
||||
StatsGatewayData {
|
||||
gateway_id,
|
||||
inbox_count,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub struct StatsServiceData {
|
||||
pub requested_service: String,
|
||||
pub request_bytes: u32,
|
||||
pub response_bytes: u32,
|
||||
}
|
||||
|
||||
impl StatsServiceData {
|
||||
pub fn new(requested_service: String, request_bytes: u32, response_bytes: u32) -> Self {
|
||||
StatsServiceData {
|
||||
requested_service,
|
||||
request_bytes,
|
||||
response_bytes,
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user