merged with fbdf31b879
This commit is contained in:
+10
-1
@@ -1,5 +1,7 @@
|
||||
# Changelog
|
||||
|
||||
Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Added
|
||||
@@ -9,7 +11,6 @@
|
||||
- gateway: Added gateway coconut verifications and validator-api communication for double spending protection ([#1261])
|
||||
- mixnet-contract: Added ClaimOperatorReward and ClaimDelegatorReward messages ([#1292])
|
||||
- mixnet-contract: Replace all naked `-` with `saturating_sub`.
|
||||
- network-requester: send traffic statistics from all network requesters and receive it in a special network-requester that aggregates the data and exposes it via a rest API ([#1267], [#1278]).
|
||||
- validator-api: add `estimated_node_profit` and `estimated_operator_cost` to `reward-estimate` endpoint ([#1284])
|
||||
- validator-api: add detailed mixnode bond endpoints, and explorer-api makes use of that data to append stake saturation.
|
||||
- validator-api: add Swagger to document the REST API ([#1249]).
|
||||
@@ -20,6 +21,7 @@
|
||||
- wallet: compound and claim reward endpoints for operators and delegators ([#1302])
|
||||
- wallet: require password to switch accounts
|
||||
- wallet: the wallet backend learned how to keep track of validator name, either hardcoded or by querying the status endpoint.
|
||||
- network-statistics: a new mixnet service that aggregates and exposes anonymized data about mixnet services ([#1328])
|
||||
|
||||
### Fixed
|
||||
|
||||
@@ -29,11 +31,15 @@
|
||||
- mixnet-contract: replaced integer division with fixed for performance calculations ([#1284])
|
||||
- mixnet-contract: Under certain circumstances nodes could not be unbonded ([#1255](https://github.com/nymtech/nym/issues/1255)) ([#1258])
|
||||
- mixnode, gateway: attempting to determine reconnection backoff to persistently failing mixnode could result in a crash ([#1260])
|
||||
- mixnode: the mixnode learned how to shutdown gracefully.
|
||||
- vesting-contract: replaced `checked_sub` with `saturating_sub` to fix the underflow in `get_vesting_tokens` ([#1275])
|
||||
- native & socks5 clients: fail early when clients try to re-init with a different gateway, which is not supported yet ([#1322])
|
||||
|
||||
### Changed
|
||||
|
||||
- validator-client: created internal `Coin` type that replaces coins from `cosmrs` and `cosmwasm` for API entrypoints [[#1295]]
|
||||
- all: updated all `cosmwasm`-related dependencies to `1.0.0` and `cw-storage-plus` to `0.13.4` [[#1318]]
|
||||
- network-requester: allow to voluntarily store and send statistical data about the number of bytes the proxied server serves ([#1328])
|
||||
|
||||
[#1249]: https://github.com/nymtech/nym/pull/1249
|
||||
[#1256]: https://github.com/nymtech/nym/pull/1256
|
||||
@@ -49,6 +55,9 @@
|
||||
[#1292]: https://github.com/nymtech/nym/pull/1292
|
||||
[#1295]: https://github.com/nymtech/nym/pull/1295
|
||||
[#1302]: https://github.com/nymtech/nym/pull/1302
|
||||
[#1318]: https://github.com/nymtech/nym/pull/1318
|
||||
[#1322]: https://github.com/nymtech/nym/pull/1322
|
||||
[#1328]: https://github.com/nymtech/nym/pull/1328
|
||||
|
||||
## [nym-wallet-v1.0.4](https://github.com/nymtech/nym/tree/nym-wallet-v1.0.4) (2022-05-04)
|
||||
|
||||
|
||||
Generated
+81
-132
@@ -245,7 +245,7 @@ checksum = "873faa4363bfc54c36a48321da034c92a0645a363eed34d948683ffc1706e37f"
|
||||
dependencies = [
|
||||
"bs58",
|
||||
"hmac 0.11.0",
|
||||
"k256 0.10.4",
|
||||
"k256",
|
||||
"once_cell",
|
||||
"pbkdf2",
|
||||
"rand_core 0.6.3",
|
||||
@@ -695,12 +695,6 @@ dependencies = [
|
||||
"tracing-subscriber",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "const-oid"
|
||||
version = "0.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9d6f2aa4d0537bcc1c74df8755072bd31c1ef1a3a1b85a68e8404a8c353b7b8b"
|
||||
|
||||
[[package]]
|
||||
name = "const-oid"
|
||||
version = "0.7.1"
|
||||
@@ -778,10 +772,10 @@ checksum = "8413275b23cb5a0734d9d1e3e33f0b5b94547c1e94776dbc3149dbf46588a533"
|
||||
dependencies = [
|
||||
"bip32",
|
||||
"cosmos-sdk-proto",
|
||||
"ecdsa 0.13.4",
|
||||
"ecdsa",
|
||||
"eyre",
|
||||
"getrandom 0.2.6",
|
||||
"k256 0.10.4",
|
||||
"k256",
|
||||
"prost 0.10.3",
|
||||
"prost-types 0.10.1",
|
||||
"rand_core 0.6.3",
|
||||
@@ -795,31 +789,31 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cosmwasm-crypto"
|
||||
version = "1.0.0-beta8"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "37e70111e9701c3ec43bfbff0e523cd4cb115876b4d3433813436dd0934ee962"
|
||||
checksum = "5eb0afef2325df81aadbf9be1233f522ed8f6e91df870c764bc44cca2b1415bd"
|
||||
dependencies = [
|
||||
"digest 0.9.0",
|
||||
"ed25519-zebra",
|
||||
"k256 0.9.6",
|
||||
"k256",
|
||||
"rand_core 0.6.3",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cosmwasm-derive"
|
||||
version = "1.0.0-beta8"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "58bc2ad5d86be5f6068833f63e20786768db6890019c095dd7775232184fb7b3"
|
||||
checksum = "4b36e527620a2a3e00e46b6e731ab6c9b68d11069c986f7d7be8eba79ef081a4"
|
||||
dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cosmwasm-std"
|
||||
version = "1.0.0-beta8"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "915ca82bd944f116f3a9717481f3fa657e4a73f28c4887288761ebb24e6fbe10"
|
||||
checksum = "875994993c2082a6fcd406937bf0fca21c349e4a624f3810253a14fa83a3a195"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"cosmwasm-crypto",
|
||||
@@ -1037,18 +1031,6 @@ dependencies = [
|
||||
"x25519-dalek",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crypto-bigint"
|
||||
version = "0.2.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f83bd3bb4314701c568e340cd8cf78c975aa0ca79e03d3f6d1677d5b0c9c0c03"
|
||||
dependencies = [
|
||||
"generic-array 0.14.5",
|
||||
"rand_core 0.6.3",
|
||||
"subtle 2.4.1",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crypto-bigint"
|
||||
version = "0.3.2"
|
||||
@@ -1156,9 +1138,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cw-storage-plus"
|
||||
version = "0.13.2"
|
||||
version = "0.13.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9336ecef1e19d56cf6e3e932475fc6a3dee35eec5a386e07917a1d1ba6bb0e35"
|
||||
checksum = "648b1507290bbc03a8d88463d7cd9b04b1fa0155e5eef366c4fa052b9caaac7a"
|
||||
dependencies = [
|
||||
"cosmwasm-std",
|
||||
"schemars",
|
||||
@@ -1246,22 +1228,13 @@ dependencies = [
|
||||
"num_cpus",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "der"
|
||||
version = "0.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "79b71cca7d95d7681a4b3b9cdf63c8dbc3730d0584c2c74e31416d64a90493f4"
|
||||
dependencies = [
|
||||
"const-oid 0.6.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "der"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6919815d73839e7ad218de758883aae3a257ba6759ce7a9992501efbb53d705c"
|
||||
dependencies = [
|
||||
"const-oid 0.7.1",
|
||||
"const-oid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1404,26 +1377,14 @@ version = "1.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "21e50f3adc76d6a43f5ed73b698a87d0760ca74617f60f7c3b879003536fdd28"
|
||||
|
||||
[[package]]
|
||||
name = "ecdsa"
|
||||
version = "0.12.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "43ee23aa5b4f68c7a092b5c3beb25f50c406adc75e2363634f242f28ab255372"
|
||||
dependencies = [
|
||||
"der 0.4.5",
|
||||
"elliptic-curve 0.10.6",
|
||||
"hmac 0.11.0",
|
||||
"signature",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ecdsa"
|
||||
version = "0.13.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d0d69ae62e0ce582d56380743515fefaf1a8c70cec685d9677636d7e30ae9dc9"
|
||||
dependencies = [
|
||||
"der 0.5.1",
|
||||
"elliptic-curve 0.11.12",
|
||||
"der",
|
||||
"elliptic-curve",
|
||||
"rfc6979",
|
||||
"signature",
|
||||
]
|
||||
@@ -1474,22 +1435,6 @@ version = "1.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
|
||||
|
||||
[[package]]
|
||||
name = "elliptic-curve"
|
||||
version = "0.10.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "beca177dcb8eb540133e7680baff45e7cc4d93bf22002676cec549f82343721b"
|
||||
dependencies = [
|
||||
"crypto-bigint 0.2.11",
|
||||
"ff 0.10.1",
|
||||
"generic-array 0.14.5",
|
||||
"group 0.10.0",
|
||||
"pkcs8 0.7.6",
|
||||
"rand_core 0.6.3",
|
||||
"subtle 2.4.1",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "elliptic-curve"
|
||||
version = "0.11.12"
|
||||
@@ -1497,8 +1442,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "25b477563c2bfed38a3b7a60964c49e058b2510ad3f12ba3483fd8f62c2306d6"
|
||||
dependencies = [
|
||||
"base16ct",
|
||||
"crypto-bigint 0.3.2",
|
||||
"der 0.5.1",
|
||||
"crypto-bigint",
|
||||
"der",
|
||||
"ff 0.11.0",
|
||||
"generic-array 0.14.5",
|
||||
"group 0.11.0",
|
||||
@@ -2149,7 +2094,7 @@ dependencies = [
|
||||
"indexmap",
|
||||
"slab",
|
||||
"tokio",
|
||||
"tokio-util 0.7.1",
|
||||
"tokio-util 0.7.3",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
@@ -2641,18 +2586,6 @@ dependencies = [
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "k256"
|
||||
version = "0.9.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "903ae2481bcdfdb7b68e0a9baa4b7c9aff600b9ae2e8e5bb5833b8c91ab851ea"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"ecdsa 0.12.4",
|
||||
"elliptic-curve 0.10.6",
|
||||
"sha2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "k256"
|
||||
version = "0.10.4"
|
||||
@@ -2660,8 +2593,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "19c3a5e0a0b8450278feda242592512e09f61c72e018b8cd5c859482802daf2d"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"ecdsa 0.13.4",
|
||||
"elliptic-curve 0.11.12",
|
||||
"ecdsa",
|
||||
"elliptic-curve",
|
||||
"sec1",
|
||||
"sha2",
|
||||
"sha3",
|
||||
@@ -2879,7 +2812,7 @@ dependencies = [
|
||||
"log",
|
||||
"nymsphinx",
|
||||
"tokio",
|
||||
"tokio-util 0.6.9",
|
||||
"tokio-util 0.7.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2920,7 +2853,7 @@ dependencies = [
|
||||
"rand 0.8.5",
|
||||
"serde",
|
||||
"tokio",
|
||||
"tokio-util 0.6.9",
|
||||
"tokio-util 0.7.3",
|
||||
"url",
|
||||
"validator-client",
|
||||
"version-checker",
|
||||
@@ -3010,7 +2943,7 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"tokio",
|
||||
"tokio-stream",
|
||||
"tokio-util 0.6.9",
|
||||
"tokio-util 0.7.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3145,7 +3078,7 @@ dependencies = [
|
||||
"tokio",
|
||||
"tokio-stream",
|
||||
"tokio-tungstenite",
|
||||
"tokio-util 0.6.9",
|
||||
"tokio-util 0.7.3",
|
||||
"url",
|
||||
"validator-client",
|
||||
"vergen",
|
||||
@@ -3181,8 +3114,9 @@ dependencies = [
|
||||
"rocket",
|
||||
"serde",
|
||||
"serial_test",
|
||||
"task",
|
||||
"tokio",
|
||||
"tokio-util 0.6.9",
|
||||
"tokio-util 0.7.3",
|
||||
"toml",
|
||||
"topology",
|
||||
"url",
|
||||
@@ -3195,7 +3129,6 @@ dependencies = [
|
||||
name = "nym-network-requester"
|
||||
version = "1.0.1"
|
||||
dependencies = [
|
||||
"bincode",
|
||||
"clap 2.34.0",
|
||||
"dirs",
|
||||
"futures",
|
||||
@@ -3209,16 +3142,32 @@ dependencies = [
|
||||
"publicsuffix",
|
||||
"rand 0.7.3",
|
||||
"reqwest",
|
||||
"rocket",
|
||||
"serde",
|
||||
"socks5-requests",
|
||||
"sqlx",
|
||||
"statistics",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
"tokio-tungstenite",
|
||||
"websocket-requests",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nym-network-statistics"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"dirs",
|
||||
"log",
|
||||
"pretty_env_logger",
|
||||
"rocket",
|
||||
"serde",
|
||||
"sqlx",
|
||||
"statistics",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
"tokio-tungstenite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nym-socks5-client"
|
||||
version = "1.0.1"
|
||||
@@ -3475,7 +3424,7 @@ dependencies = [
|
||||
"bytes",
|
||||
"nymsphinx-params",
|
||||
"nymsphinx-types",
|
||||
"tokio-util 0.6.9",
|
||||
"tokio-util 0.7.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3857,24 +3806,14 @@ version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
||||
|
||||
[[package]]
|
||||
name = "pkcs8"
|
||||
version = "0.7.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ee3ef9b64d26bad0536099c816c6734379e45bbd5f14798def6809e5cc350447"
|
||||
dependencies = [
|
||||
"der 0.4.5",
|
||||
"spki 0.4.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pkcs8"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7cabda3fb821068a9a4fab19a683eac3af12edf0f34b94a8be53c4972b8149d0"
|
||||
dependencies = [
|
||||
"der 0.5.1",
|
||||
"spki 0.5.4",
|
||||
"der",
|
||||
"spki",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
@@ -4100,7 +4039,7 @@ dependencies = [
|
||||
"socks5-requests",
|
||||
"tokio",
|
||||
"tokio-test",
|
||||
"tokio-util 0.6.9",
|
||||
"tokio-util 0.7.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4499,7 +4438,7 @@ version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "96ef608575f6392792f9ecf7890c00086591d29a83910939d430753f7c050525"
|
||||
dependencies = [
|
||||
"crypto-bigint 0.3.2",
|
||||
"crypto-bigint",
|
||||
"hmac 0.11.0",
|
||||
"zeroize",
|
||||
]
|
||||
@@ -4832,9 +4771,9 @@ version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08da66b8b0965a5555b6bd6639e68ccba85e1e2506f5fbb089e93f8a04e1a2d1"
|
||||
dependencies = [
|
||||
"der 0.5.1",
|
||||
"der",
|
||||
"generic-array 0.14.5",
|
||||
"pkcs8 0.8.0",
|
||||
"pkcs8",
|
||||
"subtle 2.4.1",
|
||||
"zeroize",
|
||||
]
|
||||
@@ -4936,9 +4875,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde-json-wasm"
|
||||
version = "0.3.2"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "042ac496d97e5885149d34139bad1d617192770d7eb8f1866da2317ff4501853"
|
||||
checksum = "479b4dbc401ca13ee8ce902851b834893251404c4f3c65370a49e047a6be09a5"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
@@ -5285,15 +5224,6 @@ dependencies = [
|
||||
"lock_api",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "spki"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c01a0c15da1b0b0e1494112e7af814a678fec9bd157881b49beac661e9b6f32"
|
||||
dependencies = [
|
||||
"der 0.4.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "spki"
|
||||
version = "0.5.4"
|
||||
@@ -5301,7 +5231,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "44d01ac02a6ccf3e07db148d2be087da624fea0221a16152ed01f0496a6b0a27"
|
||||
dependencies = [
|
||||
"base64ct",
|
||||
"der 0.5.1",
|
||||
"der",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -5433,6 +5363,16 @@ version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
||||
|
||||
[[package]]
|
||||
name = "statistics"
|
||||
version = "1.0.1"
|
||||
dependencies = [
|
||||
"reqwest",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "stdweb"
|
||||
version = "0.4.20"
|
||||
@@ -5576,6 +5516,15 @@ version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
|
||||
|
||||
[[package]]
|
||||
name = "task"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"log",
|
||||
"tokio",
|
||||
"tokio-util 0.7.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tempfile"
|
||||
version = "3.3.0"
|
||||
@@ -5602,7 +5551,7 @@ dependencies = [
|
||||
"ed25519-dalek",
|
||||
"flex-error",
|
||||
"futures",
|
||||
"k256 0.10.4",
|
||||
"k256",
|
||||
"num-traits",
|
||||
"once_cell",
|
||||
"prost 0.10.3",
|
||||
@@ -5828,9 +5777,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.17.0"
|
||||
version = "1.19.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2af73ac49756f3f7c01172e34a23e5d0216f6c32333757c2c61feb2bbff5a5ee"
|
||||
checksum = "95eec79ea28c00a365f539f1961e9278fbcaf81c0ff6aaf0e93c181352446948"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"libc",
|
||||
@@ -5891,9 +5840,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tokio-stream"
|
||||
version = "0.1.8"
|
||||
version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "50145484efff8818b5ccd256697f36863f587da82cf8b409c53adf1e840798e3"
|
||||
checksum = "df54d54117d6fdc4e4fea40fe1e4e566b3505700e148a6827e59b34b0d2600d9"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"pin-project-lite",
|
||||
@@ -5938,20 +5887,20 @@ dependencies = [
|
||||
"futures-sink",
|
||||
"log",
|
||||
"pin-project-lite",
|
||||
"slab",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-util"
|
||||
version = "0.7.1"
|
||||
version = "0.7.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0edfdeb067411dba2044da6d1cb2df793dd35add7888d73c16e3381ded401764"
|
||||
checksum = "cc463cd8deddc3770d20f9852143d50bf6094e640b485cb2e189a2099085ff45"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"futures-core",
|
||||
"futures-sink",
|
||||
"pin-project-lite",
|
||||
"slab",
|
||||
"tokio",
|
||||
"tracing",
|
||||
]
|
||||
@@ -6036,7 +5985,7 @@ dependencies = [
|
||||
"rand 0.8.5",
|
||||
"slab",
|
||||
"tokio",
|
||||
"tokio-util 0.7.1",
|
||||
"tokio-util 0.7.3",
|
||||
"tower-layer",
|
||||
"tower-service",
|
||||
"tracing",
|
||||
|
||||
@@ -53,8 +53,10 @@ members = [
|
||||
"common/nymsphinx/params",
|
||||
"common/nymsphinx/types",
|
||||
"common/pemstore",
|
||||
"common/statistics",
|
||||
"common/socks5/proxy-helpers",
|
||||
"common/socks5/requests",
|
||||
"common/task",
|
||||
"common/topology",
|
||||
"common/types",
|
||||
"common/wasm-utils",
|
||||
@@ -63,6 +65,7 @@ members = [
|
||||
"gateway/gateway-requests",
|
||||
"mixnode",
|
||||
"service-providers/network-requester",
|
||||
"service-providers/network-statistics",
|
||||
"validator-api",
|
||||
"validator-api/validator-api-requests",
|
||||
"tools/ts-rs-cli"
|
||||
|
||||
@@ -14,7 +14,7 @@ log = "0.4"
|
||||
rand = { version = "0.7.3", features = ["wasm-bindgen"] }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
sled = "0.34"
|
||||
tokio = { version = "1.4", features = ["macros"] }
|
||||
tokio = { version = "1.19.1", features = ["macros"] }
|
||||
url = { version ="2.2", features = ["serde"] }
|
||||
|
||||
# internal
|
||||
|
||||
+3
-8
@@ -6,7 +6,7 @@ use crate::client::real_messages_control::acknowledgement_control::Retransmissio
|
||||
use futures::channel::mpsc::{self, UnboundedReceiver, UnboundedSender};
|
||||
use futures::StreamExt;
|
||||
use log::*;
|
||||
use nonexhaustive_delayqueue::{Expired, NonExhaustiveDelayQueue, QueueKey, TimerError};
|
||||
use nonexhaustive_delayqueue::{Expired, NonExhaustiveDelayQueue, QueueKey};
|
||||
use nymsphinx::chunking::fragment::FragmentIdentifier;
|
||||
use nymsphinx::Delay as SphinxDelay;
|
||||
use std::collections::HashMap;
|
||||
@@ -209,16 +209,11 @@ impl ActionController {
|
||||
}
|
||||
|
||||
// note: when the entry expires it's automatically removed from pending_acks_timers
|
||||
fn handle_expired_ack_timer(
|
||||
&mut self,
|
||||
expired_ack: Result<Expired<FragmentIdentifier>, TimerError>,
|
||||
) {
|
||||
fn handle_expired_ack_timer(&mut self, expired_ack: Expired<FragmentIdentifier>) {
|
||||
// I'm honestly not sure how to handle it, because getting it means other things in our
|
||||
// system are already misbehaving. If we ever see this panic, then I guess we should worry
|
||||
// about it. Perhaps just reschedule it at later point?
|
||||
let frag_id = expired_ack
|
||||
.expect("Tokio timer returned an error!")
|
||||
.into_inner();
|
||||
let frag_id = expired_ack.into_inner();
|
||||
|
||||
trace!("{} has expired", frag_id);
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ rand = "0.7.3"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
thiserror = "1.0"
|
||||
url = "2.2"
|
||||
tokio = { version = "1.4", features = ["rt-multi-thread", "net", "signal", "macros"] } # async runtime
|
||||
tokio = { version = "1.19.1", features = ["rt-multi-thread", "net", "signal", "macros"] } # async runtime
|
||||
|
||||
coconut-interface = { path = "../../common/coconut-interface" }
|
||||
credentials = { path = "../../common/credentials" }
|
||||
|
||||
@@ -27,7 +27,7 @@ pretty_env_logger = "0.4" # for formatting log messages
|
||||
rand = { version = "0.7.3", features = ["wasm-bindgen"] } # rng-related traits + some rng implementation to use
|
||||
serde = { version = "1.0.104", features = ["derive"] } # for config serialization/deserialization
|
||||
sled = "0.34" # for storage of replySURB decryption keys
|
||||
tokio = { version = "1.4", features = ["rt-multi-thread", "net", "signal"] } # async runtime
|
||||
tokio = { version = "1.19.1", features = ["rt-multi-thread", "net", "signal"] } # async runtime
|
||||
tokio-tungstenite = "0.14" # websocket
|
||||
|
||||
## internal
|
||||
|
||||
@@ -119,6 +119,7 @@ async fn gateway_details(
|
||||
.expect("The list of validator apis is empty");
|
||||
let validator_client = validator_client::ApiClient::new(validator_api.clone());
|
||||
|
||||
log::trace!("Fetching list of gateways from: {}", validator_api);
|
||||
let gateways = validator_client.get_cached_gateways().await.unwrap();
|
||||
let valid_gateways = gateways
|
||||
.into_iter()
|
||||
@@ -186,6 +187,9 @@ pub async fn execute(matches: ArgMatches<'static>) {
|
||||
let id = matches.value_of("id").unwrap(); // required for now
|
||||
|
||||
let already_init = if Config::default_config_file_path(Some(id)).exists() {
|
||||
if matches.is_present("gateway") {
|
||||
panic!("At the moment, gateway information can't be overwritten. If you want to point to a different gateway, client {}'s directory will need to be manually removed", id);
|
||||
}
|
||||
println!("Client \"{}\" was already initialised before! Config information will be overwritten (but keys will be kept)!", id);
|
||||
true
|
||||
} else {
|
||||
@@ -210,12 +214,14 @@ pub async fn execute(matches: ArgMatches<'static>) {
|
||||
let mut key_manager = KeyManager::new(&mut rng);
|
||||
|
||||
let chosen_gateway_id = matches.value_of("gateway");
|
||||
log::trace!("Chosen gateway: {:?}", chosen_gateway_id);
|
||||
|
||||
let gateway_details = gateway_details(
|
||||
config.get_base().get_validator_api_endpoints(),
|
||||
chosen_gateway_id,
|
||||
)
|
||||
.await;
|
||||
log::trace!("Used gateway: {}", gateway_details);
|
||||
let shared_keys =
|
||||
register_with_gateway(&gateway_details, key_manager.identity_keypair()).await;
|
||||
|
||||
@@ -238,8 +244,14 @@ pub async fn execute(matches: ArgMatches<'static>) {
|
||||
.save_to_file(None)
|
||||
.expect("Failed to save the config file");
|
||||
println!("Saved configuration file to {:?}", config_save_location);
|
||||
println!("Using gateway: {}", config.get_base().get_gateway_id(),);
|
||||
println!("Client configuration completed.\n\n\n");
|
||||
println!("Using gateway: {}", config.get_base().get_gateway_id());
|
||||
log::debug!("Gateway id: {}", config.get_base().get_gateway_id());
|
||||
log::debug!("Gateway owner: {}", config.get_base().get_gateway_owner());
|
||||
log::debug!(
|
||||
"Gateway listener: {}",
|
||||
config.get_base().get_gateway_listener()
|
||||
);
|
||||
println!("Client configuration completed.");
|
||||
|
||||
show_address(&config);
|
||||
}
|
||||
|
||||
@@ -39,15 +39,11 @@ pub(crate) fn override_config(mut config: Config, matches: &ArgMatches<'_>) -> C
|
||||
.set_custom_validator_apis(parse_validators(raw_validators));
|
||||
}
|
||||
|
||||
if let Some(gateway_id) = matches.value_of("gateway") {
|
||||
config.get_base_mut().with_gateway_id(gateway_id);
|
||||
}
|
||||
|
||||
if matches.is_present("disable-socket") {
|
||||
config = config.with_socket(SocketType::None);
|
||||
}
|
||||
|
||||
if let Some(port) = matches.value_of("port").map(|port| port.parse::<u16>()) {
|
||||
if let Some(port) = matches.value_of("port").map(str::parse) {
|
||||
if let Err(err) = port {
|
||||
// if port was overridden, it must be parsable
|
||||
panic!("Invalid port value provided - {:?}", err);
|
||||
|
||||
@@ -70,7 +70,9 @@ pub fn command_args<'a, 'b>() -> clap::App<'a, 'b> {
|
||||
fn version_check(cfg: &Config) -> bool {
|
||||
let binary_version = env!("CARGO_PKG_VERSION");
|
||||
let config_version = cfg.get_base().get_version();
|
||||
if binary_version != config_version {
|
||||
if binary_version == config_version {
|
||||
true
|
||||
} else {
|
||||
warn!("The mixnode binary has different version than what is specified in config file! {} and {}", binary_version, config_version);
|
||||
if is_minor_version_compatible(binary_version, config_version) {
|
||||
info!("but they are still semver compatible. However, consider running the `upgrade` command");
|
||||
@@ -79,8 +81,6 @@ fn version_check(cfg: &Config) -> bool {
|
||||
error!("and they are semver incompatible! - please run the `upgrade` command before attempting `run` again");
|
||||
false
|
||||
}
|
||||
} else {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -131,22 +131,22 @@ fn minor_0_12_upgrade(
|
||||
config
|
||||
}
|
||||
|
||||
fn do_upgrade(mut config: Config, matches: &ArgMatches<'_>, package_version: Version) {
|
||||
fn do_upgrade(mut config: Config, matches: &ArgMatches<'_>, package_version: &Version) {
|
||||
loop {
|
||||
let config_version = parse_config_version(&config);
|
||||
|
||||
if config_version == package_version {
|
||||
if &config_version == package_version {
|
||||
println!("You're using the most recent version!");
|
||||
return;
|
||||
}
|
||||
|
||||
config = match config_version.major {
|
||||
0 => match config_version.minor {
|
||||
9 | 10 => outdated_upgrade(&config_version, &package_version),
|
||||
11 => minor_0_12_upgrade(config, matches, &config_version, &package_version),
|
||||
_ => unsupported_upgrade(&config_version, &package_version),
|
||||
9 | 10 => outdated_upgrade(&config_version, package_version),
|
||||
11 => minor_0_12_upgrade(config, matches, &config_version, package_version),
|
||||
_ => unsupported_upgrade(&config_version, package_version),
|
||||
},
|
||||
_ => unsupported_upgrade(&config_version, &package_version),
|
||||
_ => unsupported_upgrade(&config_version, package_version),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -167,5 +167,5 @@ pub fn execute(matches: &ArgMatches<'_>) {
|
||||
}
|
||||
|
||||
// here be upgrade path to 0.9.X and beyond based on version number from config
|
||||
do_upgrade(existing_config, matches, package_version)
|
||||
do_upgrade(existing_config, matches, &package_version)
|
||||
}
|
||||
|
||||
@@ -108,5 +108,7 @@ fn setup_logging() {
|
||||
.filter_module("want", log::LevelFilter::Warn)
|
||||
.filter_module("tungstenite", log::LevelFilter::Warn)
|
||||
.filter_module("tokio_tungstenite", log::LevelFilter::Warn)
|
||||
.filter_module("handlebars", log::LevelFilter::Warn)
|
||||
.filter_module("sled", log::LevelFilter::Warn)
|
||||
.init();
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ pretty_env_logger = "0.4"
|
||||
rand = { version = "0.7.3", features = ["wasm-bindgen"] }
|
||||
serde = { version = "1.0", features = ["derive"] } # for config serialization/deserialization
|
||||
snafu = "0.6"
|
||||
tokio = { version = "1.4", features = ["rt-multi-thread", "net", "signal"] }
|
||||
tokio = { version = "1.19.1", features = ["rt-multi-thread", "net", "signal"] }
|
||||
url = "2.2"
|
||||
|
||||
# internal
|
||||
|
||||
@@ -187,6 +187,9 @@ pub async fn execute(matches: ArgMatches<'static>) {
|
||||
let provider_address = matches.value_of("provider").unwrap();
|
||||
|
||||
let already_init = if Config::default_config_file_path(Some(id)).exists() {
|
||||
if matches.is_present("gateway") {
|
||||
panic!("At the moment, gateway information can't be overwritten. If you want to point to a different gateway, client {}'s directory will need to be manually removed", id);
|
||||
}
|
||||
println!("Socks5 client \"{}\" was already initialised before! Config information will be overwritten (but keys will be kept)!", id);
|
||||
true
|
||||
} else {
|
||||
|
||||
@@ -39,10 +39,6 @@ pub(crate) fn override_config(mut config: Config, matches: &ArgMatches<'_>) -> C
|
||||
.set_custom_validator_apis(parse_validators(raw_validators));
|
||||
}
|
||||
|
||||
if let Some(gateway_id) = matches.value_of("gateway") {
|
||||
config.get_base_mut().with_gateway_id(gateway_id);
|
||||
}
|
||||
|
||||
if let Some(port) = matches.value_of("port").map(|port| port.parse::<u16>()) {
|
||||
if let Err(err) = port {
|
||||
// if port was overridden, it must be parsable
|
||||
|
||||
@@ -35,7 +35,7 @@ default-features = false
|
||||
|
||||
# non-wasm-only dependencies
|
||||
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.tokio]
|
||||
version = "1.4"
|
||||
version = "1.19.1"
|
||||
features = ["macros", "rt", "net", "sync", "time"]
|
||||
|
||||
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.tokio-tungstenite]
|
||||
|
||||
@@ -83,7 +83,7 @@ impl GatewayClient {
|
||||
) -> Self {
|
||||
GatewayClient {
|
||||
authenticated: false,
|
||||
disabled_credentials_mode: false,
|
||||
disabled_credentials_mode: true,
|
||||
bandwidth_remaining: 0,
|
||||
gateway_address,
|
||||
gateway_identity,
|
||||
@@ -100,8 +100,8 @@ impl GatewayClient {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_disabled_credentials_mode(&mut self, _disabled_credentials_mode: bool) {
|
||||
self.disabled_credentials_mode = false;
|
||||
pub fn set_disabled_credentials_mode(&mut self, disabled_credentials_mode: bool) {
|
||||
self.disabled_credentials_mode = disabled_credentials_mode;
|
||||
}
|
||||
|
||||
// TODO: later convert into proper builder methods
|
||||
|
||||
@@ -9,8 +9,8 @@ edition = "2021"
|
||||
[dependencies]
|
||||
futures = "0.3"
|
||||
log = "0.4.8"
|
||||
tokio = { version = "1.4", features = ["time", "net", "rt"] }
|
||||
tokio-util = { version = "0.6", features = ["codec"] }
|
||||
tokio = { version = "1.19.1", features = ["time", "net", "rt"] }
|
||||
tokio-util = { version = "0.7.3", features = ["codec"] }
|
||||
|
||||
# internal
|
||||
nymsphinx = {path = "../../nymsphinx" }
|
||||
|
||||
@@ -22,7 +22,7 @@ reqwest = { version = "0.11", features = ["json"] }
|
||||
thiserror = "1"
|
||||
log = "0.4"
|
||||
url = { version = "2.2", features = ["serde"] }
|
||||
tokio = { version = "1.10", features = ["sync", "time"] }
|
||||
tokio = { version = "1.19.1", features = ["sync", "time"] }
|
||||
futures = "0.3"
|
||||
|
||||
coconut-interface = { path = "../../coconut-interface" }
|
||||
@@ -40,7 +40,7 @@ prost = { version = "0.10", default-features = false, optional = true }
|
||||
flate2 = { version = "1.0.20", optional = true }
|
||||
sha2 = { version = "0.9.5", optional = true }
|
||||
itertools = { version = "0.10", optional = true }
|
||||
cosmwasm-std = { version = "1.0.0-beta8", optional = true }
|
||||
cosmwasm-std = { version = "1.0.0", optional = true }
|
||||
execute = { path = "../../execute" }
|
||||
|
||||
ts-rs = "6.1.2"
|
||||
|
||||
@@ -189,23 +189,23 @@ impl NymdClient<SigningNymdClient> {
|
||||
client: SigningNymdClient::connect_with_signer(endpoint, wallet, gas_price)?,
|
||||
client_address: Some(client_address),
|
||||
simulated_gas_multiplier: DEFAULT_SIMULATED_GAS_MULTIPLIER,
|
||||
mixnet_contract_address: DEFAULT_NETWORK
|
||||
mixnet_contract_address: network
|
||||
.mixnet_contract_address()
|
||||
.parse()
|
||||
.expect("Error parsing mixnet contract address"),
|
||||
vesting_contract_address: DEFAULT_NETWORK
|
||||
vesting_contract_address: network
|
||||
.vesting_contract_address()
|
||||
.parse()
|
||||
.expect("Error parsing vesting contract address"),
|
||||
bandwidth_claim_contract_address: DEFAULT_NETWORK
|
||||
bandwidth_claim_contract_address: network
|
||||
.bandwidth_claim_contract_address()
|
||||
.parse()
|
||||
.expect("Error parsing bandwidth claim contract address"),
|
||||
coconut_bandwidth_contract_address: DEFAULT_NETWORK
|
||||
coconut_bandwidth_contract_address: network
|
||||
.coconut_bandwidth_contract_address()
|
||||
.parse()
|
||||
.unwrap(),
|
||||
multisig_contract_address: DEFAULT_NETWORK.multisig_contract_address().parse().unwrap(),
|
||||
multisig_contract_address: network.multisig_contract_address().parse().unwrap(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,6 @@ pub trait NymConfig: Default + Serialize + DeserializeOwned {
|
||||
fn template() -> &'static str;
|
||||
|
||||
fn config_file_name() -> String {
|
||||
log::trace!("NymdConfig::config_file_name");
|
||||
"config.toml".to_string()
|
||||
}
|
||||
|
||||
@@ -23,7 +22,6 @@ pub trait NymConfig: Default + Serialize + DeserializeOwned {
|
||||
|
||||
// default, most probable, implementations; can be easily overridden where required
|
||||
fn default_config_directory(id: Option<&str>) -> PathBuf {
|
||||
log::trace!("NymdConfig::default_config_directory");
|
||||
if let Some(id) = id {
|
||||
Self::default_root_directory().join(id).join("config")
|
||||
} else {
|
||||
@@ -32,7 +30,6 @@ pub trait NymConfig: Default + Serialize + DeserializeOwned {
|
||||
}
|
||||
|
||||
fn default_data_directory(id: Option<&str>) -> PathBuf {
|
||||
log::trace!("NymdConfig::default_data_path");
|
||||
if let Some(id) = id {
|
||||
Self::default_root_directory().join(id).join("data")
|
||||
} else {
|
||||
@@ -41,7 +38,6 @@ pub trait NymConfig: Default + Serialize + DeserializeOwned {
|
||||
}
|
||||
|
||||
fn default_config_file_path(id: Option<&str>) -> PathBuf {
|
||||
log::trace!("NymdConfig::default_config_file_path");
|
||||
Self::default_config_directory(id).join(Self::config_file_name())
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,6 @@ edition = "2021"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
cosmwasm-std = "1.0.0-beta6"
|
||||
cosmwasm-std = "1.0.0"
|
||||
schemars = "0.8"
|
||||
serde = { version = "1.0.103", default-features = false, features = ["derive"] }
|
||||
|
||||
@@ -7,4 +7,4 @@ edition = "2021"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
cosmwasm-std = "1.0.0-beta8"
|
||||
cosmwasm-std = "1.0.0"
|
||||
|
||||
@@ -7,7 +7,7 @@ edition = "2021"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
cosmwasm-std = "1.0.0-beta8"
|
||||
cosmwasm-std = "1.0.0"
|
||||
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_repr = "0.1"
|
||||
|
||||
@@ -460,7 +460,7 @@ impl MixNodeBond {
|
||||
.unwrap_or_default();
|
||||
let operator_reward = self.operator_reward(params);
|
||||
// Total reward has to be the sum of operator and delegator rewards
|
||||
let delegators_reward = node_profit - operator_reward;
|
||||
let delegators_reward = node_profit.saturating_sub(operator_reward);
|
||||
|
||||
Ok(RewardEstimate {
|
||||
total_node_reward: total_node_reward.try_into()?,
|
||||
|
||||
@@ -9,6 +9,6 @@ edition = "2021"
|
||||
cw-utils = { version = "0.13.1" }
|
||||
cw3 = { version = "0.13.1" }
|
||||
cw4 = { version = "0.13.1" }
|
||||
cosmwasm-std = "1.0.0-beta6"
|
||||
cosmwasm-std = "1.0.0"
|
||||
schemars = "0.8"
|
||||
serde = { version = "1.0.103", default-features = false, features = ["derive"] }
|
||||
@@ -6,11 +6,11 @@ edition = "2021"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
cosmwasm-std = "1.0.0-beta8"
|
||||
cosmwasm-std = "1.0.0"
|
||||
mixnet-contract-common = { path = "../mixnet-contract" }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
schemars = "0.8"
|
||||
cw-storage-plus = "0.13.2"
|
||||
cw-storage-plus = "0.13.4"
|
||||
config = { path = "../../config" }
|
||||
ts-rs = "6.1.2"
|
||||
|
||||
|
||||
@@ -12,9 +12,9 @@ nymcoconut = { path = "../nymcoconut" }
|
||||
log = "0.4"
|
||||
sqlx = { version = "0.5", features = ["runtime-tokio-rustls", "sqlite", "macros", "migrate"]}
|
||||
thiserror = "1.0"
|
||||
tokio = { version = "1.4", features = [ "rt-multi-thread", "net", "signal", "fs" ] }
|
||||
tokio = { version = "1.19.1", features = [ "rt-multi-thread", "net", "signal", "fs" ] }
|
||||
|
||||
|
||||
[build-dependencies]
|
||||
sqlx = { version = "0.5", features = ["runtime-tokio-rustls", "sqlite", "macros", "migrate"] }
|
||||
tokio = { version = "1.4", features = ["rt-multi-thread", "macros"] }
|
||||
tokio = { version = "1.19.1", features = ["rt-multi-thread", "macros"] }
|
||||
@@ -14,8 +14,8 @@ humantime-serde = "1.0"
|
||||
log = "0.4"
|
||||
rand = "0.8"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
tokio = { version = "1.4", features = ["time", "macros", "rt", "net", "io-util"] }
|
||||
tokio-util = { version = "0.6", features = ["codec"] }
|
||||
tokio = { version = "1.19.1", features = ["time", "macros", "rt", "net", "io-util"] }
|
||||
tokio-util = { version = "0.7.3", features = ["codec"] }
|
||||
url = "2.2"
|
||||
|
||||
crypto = { path = "../crypto" }
|
||||
|
||||
@@ -7,6 +7,6 @@ edition = "2021"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
tokio = { version = "1.4", features = [] }
|
||||
tokio-stream = "0.1" # this one seems to be a thing until `Stream` trait is stabilised in stdlib
|
||||
tokio-util = { version = "0.6", features = ["time"] }
|
||||
tokio = { version = "1.19.1", features = [] }
|
||||
tokio-stream = "0.1.9" # this one seems to be a thing until `Stream` trait is stabilised in stdlib
|
||||
tokio-util = { version = "0.7.3", features = ["time"] }
|
||||
|
||||
@@ -33,5 +33,5 @@ mixnet-contract-common = { path = "../cosmwasm-smart-contracts/mixnet-contract"
|
||||
path = "framing"
|
||||
|
||||
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.tokio]
|
||||
version = "1.4"
|
||||
version = "1.19.1"
|
||||
features = ["sync"]
|
||||
|
||||
@@ -8,7 +8,7 @@ edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
bytes = "1.0"
|
||||
tokio-util = { version = "0.6", features = ["codec"] }
|
||||
tokio-util = { version = "0.7.3", features = ["codec"] }
|
||||
|
||||
nymsphinx-types = { path = "../types" }
|
||||
nymsphinx-params = { path = "../params" }
|
||||
|
||||
@@ -8,8 +8,8 @@ edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
bytes = "1.0"
|
||||
tokio = { version = "1.4", features = [ "net", "io-util", "sync", "macros", "time", "rt-multi-thread" ] }
|
||||
tokio-util = { version = "0.6", features = [ "io" ] } # reason for getting this guy is to to able to port to tokio 1.X more quickly by being able to use
|
||||
tokio = { version = "1.19.1", features = [ "net", "io-util", "sync", "macros", "time", "rt-multi-thread" ] }
|
||||
tokio-util = { version = "0.7.3", features = [ "io" ] } # reason for getting this guy is to to able to port to tokio 1.X more quickly by being able to use
|
||||
# their `read_buf` [from the util crate] replacement rather than having to rethink/reimplement `AvailableReader` with the new AsyncRead trait definition.
|
||||
# In the long run, the dependency should probably get removed in favour of pure-tokio implementation, but for time being it's fine.
|
||||
futures = "0.3"
|
||||
@@ -18,4 +18,4 @@ socks5-requests = { path = "../requests" }
|
||||
ordered-buffer = { path = "../ordered-buffer" }
|
||||
|
||||
[dev-dependencies]
|
||||
tokio-test = "0.4"
|
||||
tokio-test = "0.4.2"
|
||||
@@ -32,6 +32,26 @@ impl Message {
|
||||
const REQUEST_FLAG: u8 = 0;
|
||||
const RESPONSE_FLAG: u8 = 1;
|
||||
|
||||
pub fn conn_id(&self) -> u64 {
|
||||
match self {
|
||||
Message::Request(req) => match req {
|
||||
Request::Connect(c) => c.conn_id,
|
||||
Request::Send(conn_id, _, _) => *conn_id,
|
||||
},
|
||||
Message::Response(resp) => resp.connection_id,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn size(&self) -> usize {
|
||||
match self {
|
||||
Message::Request(req) => match req {
|
||||
Request::Connect(_) => 0,
|
||||
Request::Send(_, data, _) => data.len(),
|
||||
},
|
||||
Message::Response(resp) => resp.data.len(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn try_from_bytes(b: &[u8]) -> Result<Message, MessageError> {
|
||||
if b.is_empty() {
|
||||
return Err(MessageError::NoData);
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
# Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
[package]
|
||||
name = "statistics"
|
||||
version = "1.0.1"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
reqwest = "0.11"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
thiserror = "1"
|
||||
@@ -0,0 +1,40 @@
|
||||
// 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 = 8090;
|
||||
|
||||
pub const STATISTICS_SERVICE_VERSION: &str = "/v1";
|
||||
pub const STATISTICS_SERVICE_API_STATISTICS: &str = "statistic";
|
||||
|
||||
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())
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
// 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),
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
// 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 error;
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub struct StatsMessage {
|
||||
pub stats_data: Vec<StatsServiceData>,
|
||||
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 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,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
[package]
|
||||
name = "task"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
log = "0.4"
|
||||
tokio = { version = "1.19.1", features = ["rt-multi-thread", "net", "signal"] }
|
||||
tokio-util = { version = "0.7.3", features = ["codec"] }
|
||||
|
||||
[dev-dependencies]
|
||||
tokio = { version = "1.19.1", features = ["rt-multi-thread", "net", "signal", "test-util", "macros"] }
|
||||
@@ -0,0 +1,6 @@
|
||||
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
pub mod shutdown;
|
||||
|
||||
pub use shutdown::{ShutdownListener, ShutdownNotifier};
|
||||
@@ -0,0 +1,106 @@
|
||||
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use std::time::Duration;
|
||||
|
||||
use tokio::sync::watch::{self, error::SendError};
|
||||
|
||||
const SHUTDOWN_TIMER_SECS: u64 = 5;
|
||||
|
||||
/// Used to notify other tasks to gracefully shutdown
|
||||
#[derive(Debug)]
|
||||
pub struct ShutdownNotifier {
|
||||
notify_tx: watch::Sender<()>,
|
||||
notify_rx: Option<watch::Receiver<()>>,
|
||||
}
|
||||
|
||||
impl Default for ShutdownNotifier {
|
||||
fn default() -> Self {
|
||||
let (notify_tx, notify_rx) = watch::channel(());
|
||||
Self {
|
||||
notify_tx,
|
||||
notify_rx: Some(notify_rx),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ShutdownNotifier {
|
||||
pub fn subscribe(&self) -> ShutdownListener {
|
||||
ShutdownListener::new(
|
||||
self.notify_rx
|
||||
.as_ref()
|
||||
.expect("Unable to subscribe to shutdown notifier that is already shutdown")
|
||||
.clone(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn signal_shutdown(&self) -> Result<(), SendError<()>> {
|
||||
self.notify_tx.send(())
|
||||
}
|
||||
|
||||
pub async fn wait_for_shutdown(&mut self) {
|
||||
if let Some(notify_rx) = self.notify_rx.take() {
|
||||
drop(notify_rx);
|
||||
}
|
||||
|
||||
tokio::select! {
|
||||
_ = self.notify_tx.closed() => {
|
||||
log::info!("All registered tasks succesfully shutdown");
|
||||
},
|
||||
_ = tokio::signal::ctrl_c() => {
|
||||
log::info!("Forcing shutdown");
|
||||
}
|
||||
_ = tokio::time::sleep(Duration::from_secs(SHUTDOWN_TIMER_SECS)) => {
|
||||
log::info!("Timout reached, forcing shutdown");
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Listen for shutdown notifications
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ShutdownListener {
|
||||
shutdown: bool,
|
||||
notify: watch::Receiver<()>,
|
||||
}
|
||||
|
||||
impl ShutdownListener {
|
||||
pub fn new(notify: watch::Receiver<()>) -> ShutdownListener {
|
||||
ShutdownListener {
|
||||
shutdown: false,
|
||||
notify,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_shutdown(&self) -> bool {
|
||||
self.shutdown
|
||||
}
|
||||
|
||||
pub async fn recv(&mut self) {
|
||||
if self.shutdown {
|
||||
return;
|
||||
}
|
||||
let _ = self.notify.changed().await;
|
||||
self.shutdown = true;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[tokio::test]
|
||||
async fn signal_shutdown() {
|
||||
let shutdown = ShutdownNotifier::default();
|
||||
let mut listener = shutdown.subscribe();
|
||||
|
||||
let task = tokio::spawn(async move {
|
||||
tokio::select! {
|
||||
_ = listener.recv() => 42,
|
||||
}
|
||||
});
|
||||
|
||||
shutdown.signal_shutdown().unwrap();
|
||||
assert_eq!(task.await.unwrap(), 42);
|
||||
}
|
||||
}
|
||||
@@ -93,6 +93,16 @@ impl Node {
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Node {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"Node(id: {}, owner: {}, stake: {}, location: {}, host: {})",
|
||||
self.identity_key, self.owner, self.stake, self.location, self.host,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl filter::Versioned for Node {
|
||||
fn version(&self) -> String {
|
||||
self.version.clone()
|
||||
|
||||
Generated
+81
-40
@@ -66,12 +66,24 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "base16ct"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce"
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
|
||||
|
||||
[[package]]
|
||||
name = "base64ct"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dea908e7347a8c64e378c17e30ef880ad73e3b4498346b055c2c00ea342f3179"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
@@ -245,9 +257,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "const-oid"
|
||||
version = "0.6.2"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9d6f2aa4d0537bcc1c74df8755072bd31c1ef1a3a1b85a68e8404a8c353b7b8b"
|
||||
checksum = "e4c78c047431fee22c1a7bb92e00ad095a02a983affe4d8a72e2a2c62c1b94f3"
|
||||
|
||||
[[package]]
|
||||
name = "contracts-common"
|
||||
@@ -258,9 +270,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cosmwasm-crypto"
|
||||
version = "1.0.0-beta8"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "37e70111e9701c3ec43bfbff0e523cd4cb115876b4d3433813436dd0934ee962"
|
||||
checksum = "5eb0afef2325df81aadbf9be1233f522ed8f6e91df870c764bc44cca2b1415bd"
|
||||
dependencies = [
|
||||
"digest 0.9.0",
|
||||
"ed25519-zebra",
|
||||
@@ -271,18 +283,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cosmwasm-derive"
|
||||
version = "1.0.0-beta8"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "58bc2ad5d86be5f6068833f63e20786768db6890019c095dd7775232184fb7b3"
|
||||
checksum = "4b36e527620a2a3e00e46b6e731ab6c9b68d11069c986f7d7be8eba79ef081a4"
|
||||
dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cosmwasm-schema"
|
||||
version = "1.0.0-beta7"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "63f79866e7b2190b6b6cb06959e308183c8d9511a8530f7292073f3cddc963db"
|
||||
checksum = "772e80bbad231a47a2068812b723a1ff81dd4a0d56c9391ac748177bea3a61da"
|
||||
dependencies = [
|
||||
"schemars",
|
||||
"serde_json",
|
||||
@@ -290,9 +302,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cosmwasm-std"
|
||||
version = "1.0.0-beta8"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "915ca82bd944f116f3a9717481f3fa657e4a73f28c4887288761ebb24e6fbe10"
|
||||
checksum = "875994993c2082a6fcd406937bf0fca21c349e4a624f3810253a14fa83a3a195"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"cosmwasm-crypto",
|
||||
@@ -307,9 +319,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cosmwasm-storage"
|
||||
version = "1.0.0-beta8"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1c4be9fd8c9d3ae7d0c32a925ecbc20707007ce0cba1f7538c0d78b7a2d3729b"
|
||||
checksum = "d18403b07304d15d304dad11040d45bbcaf78d603b4be3fb5e2685c16f9229b5"
|
||||
dependencies = [
|
||||
"cosmwasm-std",
|
||||
"serde",
|
||||
@@ -346,9 +358,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "crypto-bigint"
|
||||
version = "0.2.11"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f83bd3bb4314701c568e340cd8cf78c975aa0ca79e03d3f6d1677d5b0c9c0c03"
|
||||
checksum = "03c6a1d5fa1de37e071642dfa44ec552ca5b299adb128fab16138e24b548fd21"
|
||||
dependencies = [
|
||||
"generic-array 0.14.5",
|
||||
"rand_core 0.6.3",
|
||||
@@ -400,9 +412,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cw-controllers"
|
||||
version = "0.13.2"
|
||||
version = "0.13.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1bc6d042b14823b0e9f33f5cdd67a1eb9b16a7d79f7547b1a73c8870b518b97b"
|
||||
checksum = "4f0bc6019b4d3d81e11f5c384bcce7173e2210bd654d75c6c9668e12cca05dfa"
|
||||
dependencies = [
|
||||
"cosmwasm-std",
|
||||
"cw-storage-plus",
|
||||
@@ -433,9 +445,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cw-storage-plus"
|
||||
version = "0.13.2"
|
||||
version = "0.13.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9336ecef1e19d56cf6e3e932475fc6a3dee35eec5a386e07917a1d1ba6bb0e35"
|
||||
checksum = "648b1507290bbc03a8d88463d7cd9b04b1fa0155e5eef366c4fa052b9caaac7a"
|
||||
dependencies = [
|
||||
"cosmwasm-std",
|
||||
"schemars",
|
||||
@@ -444,9 +456,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cw-utils"
|
||||
version = "0.13.2"
|
||||
version = "0.13.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "babd2c090f39d07ce5bf2556962305e795daa048ce20a93709eb591476e4a29e"
|
||||
checksum = "9dbaecb78c8e8abfd6b4258c7f4fbeb5c49a5e45ee4d910d3240ee8e1d714e1b"
|
||||
dependencies = [
|
||||
"cosmwasm-std",
|
||||
"schemars",
|
||||
@@ -544,9 +556,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "der"
|
||||
version = "0.4.5"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "79b71cca7d95d7681a4b3b9cdf63c8dbc3730d0584c2c74e31416d64a90493f4"
|
||||
checksum = "6919815d73839e7ad218de758883aae3a257ba6759ce7a9992501efbb53d705c"
|
||||
dependencies = [
|
||||
"const-oid",
|
||||
]
|
||||
@@ -588,13 +600,13 @@ checksum = "ee2626afccd7561a06cf1367e2950c4718ea04565e20fb5029b6c7d8ad09abcf"
|
||||
|
||||
[[package]]
|
||||
name = "ecdsa"
|
||||
version = "0.12.4"
|
||||
version = "0.13.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "43ee23aa5b4f68c7a092b5c3beb25f50c406adc75e2363634f242f28ab255372"
|
||||
checksum = "d0d69ae62e0ce582d56380743515fefaf1a8c70cec685d9677636d7e30ae9dc9"
|
||||
dependencies = [
|
||||
"der",
|
||||
"elliptic-curve",
|
||||
"hmac",
|
||||
"rfc6979",
|
||||
"signature",
|
||||
]
|
||||
|
||||
@@ -644,16 +656,18 @@ checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
|
||||
|
||||
[[package]]
|
||||
name = "elliptic-curve"
|
||||
version = "0.10.6"
|
||||
version = "0.11.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "beca177dcb8eb540133e7680baff45e7cc4d93bf22002676cec549f82343721b"
|
||||
checksum = "25b477563c2bfed38a3b7a60964c49e058b2510ad3f12ba3483fd8f62c2306d6"
|
||||
dependencies = [
|
||||
"base16ct",
|
||||
"crypto-bigint",
|
||||
"der",
|
||||
"ff",
|
||||
"generic-array 0.14.5",
|
||||
"group",
|
||||
"pkcs8",
|
||||
"rand_core 0.6.3",
|
||||
"sec1",
|
||||
"subtle 2.4.1",
|
||||
"zeroize",
|
||||
]
|
||||
@@ -686,9 +700,9 @@ checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
|
||||
|
||||
[[package]]
|
||||
name = "ff"
|
||||
version = "0.10.1"
|
||||
version = "0.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d0f40b2dcd8bc322217a5f6559ae5f9e9d1de202a2ecee2e9eafcbece7562a4f"
|
||||
checksum = "131655483be284720a17d74ff97592b8e76576dc25563148601df2d7c9080924"
|
||||
dependencies = [
|
||||
"rand_core 0.6.3",
|
||||
"subtle 2.4.1",
|
||||
@@ -793,9 +807,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "group"
|
||||
version = "0.10.0"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1c363a5301b8f153d80747126a04b3c82073b9fe3130571a9d170cacdeaf7912"
|
||||
checksum = "bc5ac374b108929de78460075f3dc439fa66df9d8fc77e8f12caa5165fcf0c89"
|
||||
dependencies = [
|
||||
"ff",
|
||||
"rand_core 0.6.3",
|
||||
@@ -916,13 +930,14 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "k256"
|
||||
version = "0.9.6"
|
||||
version = "0.10.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "903ae2481bcdfdb7b68e0a9baa4b7c9aff600b9ae2e8e5bb5833b8c91ab851ea"
|
||||
checksum = "19c3a5e0a0b8450278feda242592512e09f61c72e018b8cd5c859482802daf2d"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"ecdsa",
|
||||
"elliptic-curve",
|
||||
"sec1",
|
||||
"sha2",
|
||||
]
|
||||
|
||||
@@ -1197,12 +1212,13 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pkcs8"
|
||||
version = "0.7.6"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ee3ef9b64d26bad0536099c816c6734379e45bbd5f14798def6809e5cc350447"
|
||||
checksum = "7cabda3fb821068a9a4fab19a683eac3af12edf0f34b94a8be53c4972b8149d0"
|
||||
dependencies = [
|
||||
"der",
|
||||
"spki",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1363,6 +1379,17 @@ version = "0.6.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
|
||||
|
||||
[[package]]
|
||||
name = "rfc6979"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "96ef608575f6392792f9ecf7890c00086591d29a83910939d430753f7c050525"
|
||||
dependencies = [
|
||||
"crypto-bigint",
|
||||
"hmac",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc_version"
|
||||
version = "0.4.0"
|
||||
@@ -1408,6 +1435,19 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sec1"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08da66b8b0965a5555b6bd6639e68ccba85e1e2506f5fbb089e93f8a04e1a2d1"
|
||||
dependencies = [
|
||||
"der",
|
||||
"generic-array 0.14.5",
|
||||
"pkcs8",
|
||||
"subtle 2.4.1",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "1.0.4"
|
||||
@@ -1425,9 +1465,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde-json-wasm"
|
||||
version = "0.3.2"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "042ac496d97e5885149d34139bad1d617192770d7eb8f1866da2317ff4501853"
|
||||
checksum = "479b4dbc401ca13ee8ce902851b834893251404c4f3c65370a49e047a6be09a5"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
@@ -1536,10 +1576,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "spki"
|
||||
version = "0.4.1"
|
||||
version = "0.5.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c01a0c15da1b0b0e1494112e7af814a678fec9bd157881b49beac661e9b6f32"
|
||||
checksum = "44d01ac02a6ccf3e07db148d2be087da624fea0221a16152ed01f0496a6b0a27"
|
||||
dependencies = [
|
||||
"base64ct",
|
||||
"der",
|
||||
]
|
||||
|
||||
|
||||
@@ -14,8 +14,8 @@ config = { path = "../../common/config"}
|
||||
[dependencies]
|
||||
bandwidth-claim-contract = { path = "../../common/bandwidth-claim-contract" }
|
||||
|
||||
cosmwasm-std = "1.0.0-beta8"
|
||||
cosmwasm-storage = "1.0.0-beta8"
|
||||
cosmwasm-std = "1.0.0"
|
||||
cosmwasm-storage = "1.0.0"
|
||||
|
||||
schemars = "0.8"
|
||||
serde = { version = "1.0.103", default-features = false, features = ["derive"] }
|
||||
|
||||
@@ -13,10 +13,10 @@ bandwidth-claim-contract = { path = "../../common/bandwidth-claim-contract" }
|
||||
coconut-bandwidth-contract-common = { path = "../../common/cosmwasm-smart-contracts/coconut-bandwidth-contract" }
|
||||
config = { path = "../../common/config"}
|
||||
|
||||
cosmwasm-std = "1.0.0-beta8"
|
||||
cosmwasm-storage = "1.0.0-beta8"
|
||||
cw-storage-plus = "0.13.2"
|
||||
cw-controllers = "0.13.2"
|
||||
cosmwasm-std = "1.0.0"
|
||||
cosmwasm-storage = "1.0.0"
|
||||
cw-storage-plus = "0.13.4"
|
||||
cw-controllers = "0.13.4"
|
||||
|
||||
schemars = "0.8"
|
||||
serde = { version = "1.0.103", default-features = false, features = ["derive"] }
|
||||
|
||||
@@ -20,9 +20,9 @@ mixnet-contract-common = { path = "../../common/cosmwasm-smart-contracts/mixnet-
|
||||
vesting-contract-common = { path = "../../common/cosmwasm-smart-contracts/vesting-contract" }
|
||||
config = { path = "../../common/config"}
|
||||
|
||||
cosmwasm-std = "1.0.0-beta8"
|
||||
cosmwasm-storage = "1.0.0-beta8"
|
||||
cw-storage-plus = "0.13.2"
|
||||
cosmwasm-std = "1.0.0"
|
||||
cosmwasm-storage = "1.0.0"
|
||||
cw-storage-plus = "0.13.4"
|
||||
|
||||
az = "1.2.0"
|
||||
bs58 = "0.4.0"
|
||||
@@ -33,7 +33,7 @@ time = { version = "0.3", features = ["macros"] }
|
||||
hex = "0.4.3"
|
||||
|
||||
[dev-dependencies]
|
||||
cosmwasm-schema = "1.0.0-beta3"
|
||||
cosmwasm-schema = "1.0.0"
|
||||
fixed = "1.1"
|
||||
rand_chacha = "0.2"
|
||||
rand = "0.7"
|
||||
|
||||
@@ -23,7 +23,7 @@ cw3 = { version = "0.13.1" }
|
||||
cw3-fixed-multisig = { version = "0.13.1", features = ["library"] }
|
||||
cw4 = { version = "0.13.1" }
|
||||
cw-storage-plus = { version = "0.13.1" }
|
||||
cosmwasm-std = { version = "1.0.0-beta6" }
|
||||
cosmwasm-std = { version = "1.0.0" }
|
||||
schemars = "0.8.1"
|
||||
serde = { version = "1.0.103", default-features = false, features = ["derive"] }
|
||||
thiserror = { version = "1.0.23" }
|
||||
@@ -31,6 +31,6 @@ thiserror = { version = "1.0.23" }
|
||||
multisig-contract-common = { path= "../../../common/cosmwasm-smart-contracts/multisig-contract" }
|
||||
|
||||
[dev-dependencies]
|
||||
cosmwasm-schema = { version = "1.0.0-beta6" }
|
||||
cosmwasm-schema = { version = "1.0.0" }
|
||||
cw4-group = { path = "../cw4-group", version = "0.13.1" }
|
||||
cw-multi-test = { version = "0.13.1" }
|
||||
|
||||
@@ -29,10 +29,10 @@ cw2 = { version = "0.13.1" }
|
||||
cw4 = { version = "0.13.1" }
|
||||
cw-controllers = { version = "0.13.1" }
|
||||
cw-storage-plus = { version = "0.13.1" }
|
||||
cosmwasm-std = { version = "1.0.0-beta6" }
|
||||
cosmwasm-std = { version = "1.0.0" }
|
||||
schemars = "0.8.1"
|
||||
serde = { version = "1.0.103", default-features = false, features = ["derive"] }
|
||||
thiserror = { version = "1.0.23" }
|
||||
|
||||
[dev-dependencies]
|
||||
cosmwasm-schema = { version = "1.0.0-beta6" }
|
||||
cosmwasm-schema = { version = "1.0.0" }
|
||||
|
||||
@@ -18,8 +18,8 @@ mixnet-contract-common = { path = "../../common/cosmwasm-smart-contracts/mixnet-
|
||||
vesting-contract-common = { path = "../../common/cosmwasm-smart-contracts/vesting-contract" }
|
||||
config = { path = "../../common/config" }
|
||||
|
||||
cosmwasm-std = { version = "1.0.0-beta8"}
|
||||
cw-storage-plus = { version = "0.13.1", features = ["iterator"] }
|
||||
cosmwasm-std = { version = "1.0.0 "}
|
||||
cw-storage-plus = { version = "0.13.4", features = ["iterator"] }
|
||||
|
||||
schemars = "0.8"
|
||||
serde = { version = "1.0", default-features = false, features = ["derive"] }
|
||||
|
||||
@@ -21,7 +21,7 @@ schemars = { version = "0.8", features = ["preserve_order"] }
|
||||
serde = "1.0.126"
|
||||
serde_json = "1.0.66"
|
||||
thiserror = "1.0.29"
|
||||
tokio = {version = "1.9.0", features = ["full"] }
|
||||
tokio = {version = "1.19.1", features = ["full"] }
|
||||
|
||||
mixnet-contract-common = { path = "../common/cosmwasm-smart-contracts/mixnet-contract" }
|
||||
network-defaults = { path = "../common/network-defaults" }
|
||||
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
import {
|
||||
CountryDataResponse,
|
||||
DelegationsResponse,
|
||||
UniqDelegationsResponse,
|
||||
GatewayResponse,
|
||||
MixNodeDescriptionResponse,
|
||||
MixNodeResponse,
|
||||
@@ -117,6 +118,9 @@ export class Api {
|
||||
static fetchDelegationsById = async (id: string): Promise<DelegationsResponse> =>
|
||||
(await fetch(`${MIXNODE_API}/${id}/delegations`)).json();
|
||||
|
||||
static fetchUniqDelegationsById = async (id: string): Promise<UniqDelegationsResponse> =>
|
||||
(await fetch(`${MIXNODE_API}/${id}/delegations/summed`)).json();
|
||||
|
||||
static fetchStatsById = async (id: string): Promise<StatsResponse> =>
|
||||
(await fetch(`${MIXNODE_API}/${id}/stats`)).json();
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ import { currencyToString } from '../../utils/currency';
|
||||
import { useMixnodeContext } from '../../context/mixnode';
|
||||
|
||||
export const BondBreakdownTable: React.FC = () => {
|
||||
const { mixNode, delegations } = useMixnodeContext();
|
||||
const { mixNode, delegations, uniqDelegations } = useMixnodeContext();
|
||||
const [showDelegations, toggleShowDelegations] = React.useState<boolean>(false);
|
||||
|
||||
const [bonds, setBonds] = React.useState({
|
||||
@@ -91,14 +91,14 @@ export const BondBreakdownTable: React.FC = () => {
|
||||
}}
|
||||
align="left"
|
||||
>
|
||||
Bond total
|
||||
Stake total
|
||||
</TableCell>
|
||||
<TableCell align="left" data-testid="bond-total-amount">
|
||||
{bonds.bondsTotal}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell align="left">Self</TableCell>
|
||||
<TableCell align="left">Bond</TableCell>
|
||||
<TableCell align="left" data-testid="pledge-total-amount">
|
||||
{bonds.pledges}
|
||||
</TableCell>
|
||||
@@ -155,7 +155,7 @@ export const BondBreakdownTable: React.FC = () => {
|
||||
fontWeight: 400,
|
||||
}}
|
||||
>
|
||||
{`(${delegations?.data?.length} delegators)`}
|
||||
{`(${uniqDelegations?.data?.length} delegators)`}
|
||||
</Typography>
|
||||
</Box>
|
||||
<Table stickyHeader>
|
||||
@@ -177,7 +177,7 @@ export const BondBreakdownTable: React.FC = () => {
|
||||
}}
|
||||
align="left"
|
||||
>
|
||||
Stake
|
||||
Amount
|
||||
</TableCell>
|
||||
<TableCell
|
||||
sx={{
|
||||
@@ -187,13 +187,13 @@ export const BondBreakdownTable: React.FC = () => {
|
||||
}}
|
||||
align="left"
|
||||
>
|
||||
Share from bond
|
||||
Share of stake
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
|
||||
<TableBody>
|
||||
{delegations?.data?.map(({ owner, amount: { amount, denom } }) => (
|
||||
{uniqDelegations?.data?.map(({ owner, amount: { amount, denom } }) => (
|
||||
<TableRow key={owner}>
|
||||
<TableCell sx={matches ? { width: 190 } : null} align="left">
|
||||
{owner}
|
||||
|
||||
@@ -2,6 +2,7 @@ import * as React from 'react';
|
||||
import {
|
||||
ApiState,
|
||||
DelegationsResponse,
|
||||
UniqDelegationsResponse,
|
||||
MixNodeDescriptionResponse,
|
||||
MixNodeEconomicDynamicsStatsResponse,
|
||||
MixNodeResponseItem,
|
||||
@@ -18,6 +19,7 @@ import { mixNodeResponseItemToMixnodeRowType, MixnodeRowType } from '../componen
|
||||
|
||||
interface MixnodeState {
|
||||
delegations?: ApiState<DelegationsResponse>;
|
||||
uniqDelegations?: ApiState<UniqDelegationsResponse>;
|
||||
description?: ApiState<MixNodeDescriptionResponse>;
|
||||
economicDynamicsStats?: ApiState<MixNodeEconomicDynamicsStatsResponse>;
|
||||
mixNode?: ApiState<MixNodeResponseItem | undefined>;
|
||||
@@ -55,6 +57,12 @@ export const MixnodeContextProvider: React.FC<MixnodeContextProviderProps> = ({
|
||||
'Failed to fetch delegations for mixnode',
|
||||
);
|
||||
|
||||
const [uniqDelegations, fetchUniqDelegations, clearUniqDelegations] = useApiState<UniqDelegationsResponse>(
|
||||
mixNodeIdentityKey,
|
||||
Api.fetchUniqDelegationsById,
|
||||
'Failed to fetch delegations for mixnode',
|
||||
);
|
||||
|
||||
const [status, fetchStatus, clearStatus] = useApiState<StatusResponse>(
|
||||
mixNodeIdentityKey,
|
||||
Api.fetchStatusById,
|
||||
@@ -90,6 +98,7 @@ export const MixnodeContextProvider: React.FC<MixnodeContextProviderProps> = ({
|
||||
// when the identity key changes, remove all previous data
|
||||
clearMixnodeById();
|
||||
clearDelegations();
|
||||
clearUniqDelegations();
|
||||
clearStatus();
|
||||
clearStats();
|
||||
clearDescription();
|
||||
@@ -105,6 +114,7 @@ export const MixnodeContextProvider: React.FC<MixnodeContextProviderProps> = ({
|
||||
setMixnodeRow(mixNodeResponseItemToMixnodeRowType(value.data));
|
||||
Promise.all([
|
||||
fetchDelegations(),
|
||||
fetchUniqDelegations(),
|
||||
fetchStatus(),
|
||||
fetchStats(),
|
||||
fetchDescription(),
|
||||
@@ -117,6 +127,7 @@ export const MixnodeContextProvider: React.FC<MixnodeContextProviderProps> = ({
|
||||
const state = React.useMemo<MixnodeState>(
|
||||
() => ({
|
||||
delegations,
|
||||
uniqDelegations,
|
||||
mixNode,
|
||||
mixNodeRow,
|
||||
description,
|
||||
@@ -128,6 +139,7 @@ export const MixnodeContextProvider: React.FC<MixnodeContextProviderProps> = ({
|
||||
[
|
||||
{
|
||||
delegations,
|
||||
uniqDelegations,
|
||||
mixNode,
|
||||
mixNodeRow,
|
||||
description,
|
||||
|
||||
@@ -29,7 +29,7 @@ const columns: ColumnsType[] = [
|
||||
|
||||
{
|
||||
field: 'bond',
|
||||
title: 'Bond',
|
||||
title: 'Stake',
|
||||
flex: 1,
|
||||
headerAlign: 'left',
|
||||
},
|
||||
@@ -95,7 +95,7 @@ const PageMixnodeDetailWithState: React.FC = () => {
|
||||
|
||||
<Grid container spacing={2} mt={0}>
|
||||
<Grid item xs={12}>
|
||||
<ContentCard title="Bond Breakdown">
|
||||
<ContentCard title="Stake Breakdown">
|
||||
<BondBreakdownTable />
|
||||
</ContentCard>
|
||||
</Grid>
|
||||
|
||||
@@ -125,24 +125,6 @@ export const PageMixnodes: React.FC = () => {
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
field: 'bond',
|
||||
headerName: 'Bond',
|
||||
renderHeader: () => <CustomColumnHeading headingTitle="Bond" />,
|
||||
type: 'number',
|
||||
headerClassName: 'MuiDataGrid-header-override',
|
||||
width: 200,
|
||||
headerAlign: 'left',
|
||||
renderCell: (params: GridRenderCellParams) => (
|
||||
<MuiLink
|
||||
sx={getCellStyles(theme, params.row)}
|
||||
component={RRDLink}
|
||||
to={`/network-components/mixnode/${params.row.identity_key}`}
|
||||
>
|
||||
{currencyToString(params.value)}
|
||||
</MuiLink>
|
||||
),
|
||||
},
|
||||
{
|
||||
field: 'location',
|
||||
headerName: 'Location',
|
||||
@@ -162,24 +144,6 @@ export const PageMixnodes: React.FC = () => {
|
||||
</Button>
|
||||
),
|
||||
},
|
||||
{
|
||||
field: 'self_percentage',
|
||||
headerName: 'Self %',
|
||||
width: 110,
|
||||
headerClassName: 'MuiDataGrid-header-override',
|
||||
renderHeader: () => <CustomColumnHeading headingTitle="Self %" />,
|
||||
type: 'number',
|
||||
headerAlign: 'left',
|
||||
renderCell: (params: GridRenderCellParams) => (
|
||||
<MuiLink
|
||||
sx={getCellStyles(theme, params.row)}
|
||||
component={RRDLink}
|
||||
to={`/network-components/mixnode/${params.row.identity_key}`}
|
||||
>
|
||||
{params.value}%
|
||||
</MuiLink>
|
||||
),
|
||||
},
|
||||
{
|
||||
field: 'host',
|
||||
headerName: 'Host',
|
||||
@@ -198,19 +162,59 @@ export const PageMixnodes: React.FC = () => {
|
||||
),
|
||||
},
|
||||
{
|
||||
field: 'layer',
|
||||
headerName: 'Layer',
|
||||
renderHeader: () => <CustomColumnHeading headingTitle="Layer" />,
|
||||
field: 'bond',
|
||||
headerName: 'Stake',
|
||||
renderHeader: () => <CustomColumnHeading headingTitle="Stake" />,
|
||||
type: 'number',
|
||||
headerClassName: 'MuiDataGrid-header-override',
|
||||
width: 110,
|
||||
width: 200,
|
||||
headerAlign: 'left',
|
||||
renderCell: (params: GridRenderCellParams) => (
|
||||
<MuiLink
|
||||
sx={{ ...getCellStyles(theme, params.row), textAlign: 'left' }}
|
||||
sx={getCellStyles(theme, params.row)}
|
||||
component={RRDLink}
|
||||
to={`/network-components/mixnode/${params.row.identity_key}`}
|
||||
>
|
||||
{params.value}
|
||||
{currencyToString(params.value)}
|
||||
</MuiLink>
|
||||
),
|
||||
},
|
||||
{
|
||||
field: 'stake_saturation',
|
||||
headerName: 'Stake Saturation',
|
||||
renderHeader: () => <CustomColumnHeading headingTitle="Stake Saturation" />,
|
||||
headerClassName: 'MuiDataGrid-header-override',
|
||||
width: 175,
|
||||
headerAlign: 'left',
|
||||
renderCell: (params: GridRenderCellParams) => (
|
||||
<MuiLink
|
||||
sx={{
|
||||
textAlign: 'left',
|
||||
color: params.value > 100 ? theme.palette.warning.main : 'inherit',
|
||||
...getCellStyles(theme, params.row),
|
||||
}}
|
||||
component={RRDLink}
|
||||
to={`/network-components/mixnode/${params.row.identity_key}`}
|
||||
>
|
||||
{`${params.value.toFixed(2)} %`}
|
||||
</MuiLink>
|
||||
),
|
||||
},
|
||||
{
|
||||
field: 'self_percentage',
|
||||
headerName: 'Self %',
|
||||
width: 110,
|
||||
headerClassName: 'MuiDataGrid-header-override',
|
||||
renderHeader: () => <CustomColumnHeading headingTitle="Self %" />,
|
||||
type: 'number',
|
||||
headerAlign: 'left',
|
||||
renderCell: (params: GridRenderCellParams) => (
|
||||
<MuiLink
|
||||
sx={getCellStyles(theme, params.row)}
|
||||
component={RRDLink}
|
||||
to={`/network-components/mixnode/${params.row.identity_key}`}
|
||||
>
|
||||
{params.value}%
|
||||
</MuiLink>
|
||||
),
|
||||
},
|
||||
@@ -248,27 +252,6 @@ export const PageMixnodes: React.FC = () => {
|
||||
</MuiLink>
|
||||
),
|
||||
},
|
||||
{
|
||||
field: 'stake_saturation',
|
||||
headerName: 'Stake Saturation',
|
||||
renderHeader: () => <CustomColumnHeading headingTitle="Stake Saturation" />,
|
||||
headerClassName: 'MuiDataGrid-header-override',
|
||||
width: 175,
|
||||
headerAlign: 'left',
|
||||
renderCell: (params: GridRenderCellParams) => (
|
||||
<MuiLink
|
||||
sx={{
|
||||
textAlign: 'left',
|
||||
color: params.value > 100 ? theme.palette.warning.main : 'inherit',
|
||||
...getCellStyles(theme, params.row),
|
||||
}}
|
||||
component={RRDLink}
|
||||
to={`/network-components/mixnode/${params.row.identity_key}`}
|
||||
>
|
||||
{`${params.value.toFixed(2)} %`}
|
||||
</MuiLink>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
const handlePageSize = (event: SelectChangeEvent<string>) => {
|
||||
|
||||
@@ -171,8 +171,15 @@ export type Delegation = {
|
||||
block_height: number;
|
||||
};
|
||||
|
||||
export type DelegationUniq = {
|
||||
owner: string;
|
||||
amount: Amount;
|
||||
};
|
||||
|
||||
export type DelegationsResponse = Delegation[];
|
||||
|
||||
export type UniqDelegationsResponse = DelegationUniq[];
|
||||
|
||||
export interface CountryDataResponse {
|
||||
[threeLetterCountryCode: string]: CountryData;
|
||||
}
|
||||
|
||||
+4
-4
@@ -31,10 +31,10 @@ serde = { version = "1.0.104", features = ["derive"] }
|
||||
sqlx = { version = "0.5", features = ["runtime-tokio-rustls", "sqlite", "macros", "migrate"] }
|
||||
subtle-encoding = { version = "0.5", features = ["bech32-preview"]}
|
||||
thiserror = "1"
|
||||
tokio = { version = "1.4", features = [ "rt-multi-thread", "net", "signal", "fs" ] }
|
||||
tokio-stream = { version = "0.1", features = [ "fs" ] }
|
||||
tokio = { version = "1.19.1", features = [ "rt-multi-thread", "net", "signal", "fs" ] }
|
||||
tokio-stream = { version = "0.1.9", features = [ "fs" ] }
|
||||
tokio-tungstenite = "0.14"
|
||||
tokio-util = { version = "0.6", features = [ "codec" ] }
|
||||
tokio-util = { version = "0.7.3", features = [ "codec" ] }
|
||||
url = { version = "2.2", features = [ "serde" ] }
|
||||
web3 = "0.17.0"
|
||||
|
||||
@@ -59,6 +59,6 @@ coconut = ["coconut-interface", "gateway-requests/coconut", "gateway-client/coco
|
||||
eth = []
|
||||
|
||||
[build-dependencies]
|
||||
tokio = { version = "1.4", features = ["rt-multi-thread", "macros"] }
|
||||
tokio = { version = "1.19.1", features = ["rt-multi-thread", "macros"] }
|
||||
sqlx = { version = "0.5", features = ["runtime-tokio-rustls", "sqlite", "macros", "migrate"] }
|
||||
vergen = { version = "5", default-features = false, features = ["build", "git", "rustc", "cargo"] }
|
||||
|
||||
+4
-3
@@ -28,8 +28,8 @@ pretty_env_logger = "0.4.0"
|
||||
rand = "0.7.3"
|
||||
rocket = { version="0.5.0-rc.1", features = ["json"] }
|
||||
serde = { version="1.0", features = ["derive"] }
|
||||
tokio = { version="1.8", features = ["rt-multi-thread", "net", "signal"] }
|
||||
tokio-util = { version="0.6.7", features = ["codec"] }
|
||||
tokio = { version="1.19.1", features = ["rt-multi-thread", "net", "signal"] }
|
||||
tokio-util = { version="0.7.3", features = ["codec"] }
|
||||
toml = "0.5.8"
|
||||
url = { version = "2.2", features = ["serde"] }
|
||||
lazy_static = "1.4.0"
|
||||
@@ -43,13 +43,14 @@ mixnode-common = { path="../common/mixnode-common" }
|
||||
nonexhaustive-delayqueue = { path="../common/nonexhaustive-delayqueue" }
|
||||
nymsphinx = { path="../common/nymsphinx" }
|
||||
pemstore = { path="../common/pemstore" }
|
||||
task = { path = "../common/task" }
|
||||
topology = { path="../common/topology" }
|
||||
validator-client = { path="../common/client-libs/validator-client" }
|
||||
version-checker = { path="../common/version-checker" }
|
||||
|
||||
[dev-dependencies]
|
||||
serial_test = "0.5"
|
||||
tokio = { version="1.8", features = ["rt-multi-thread", "net", "signal", "test-util"] }
|
||||
tokio = { version="1.19.1", features = ["rt-multi-thread", "net", "signal", "test-util"] }
|
||||
|
||||
nymsphinx-types = { path = "../common/nymsphinx/types" }
|
||||
nymsphinx-params = { path = "../common/nymsphinx/params" }
|
||||
|
||||
@@ -5,6 +5,7 @@ use crate::node::listener::connection_handler::packet_processing::{
|
||||
MixProcessingResult, PacketProcessor,
|
||||
};
|
||||
use crate::node::packet_delayforwarder::PacketDelayForwardSender;
|
||||
use crate::node::ShutdownListener;
|
||||
use futures::StreamExt;
|
||||
use log::{error, info};
|
||||
use nymsphinx::forwarding::packet::MixPacket;
|
||||
@@ -69,28 +70,40 @@ impl ConnectionHandler {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn handle_connection(self, conn: TcpStream, remote: SocketAddr) {
|
||||
pub(crate) async fn handle_connection(
|
||||
self,
|
||||
conn: TcpStream,
|
||||
remote: SocketAddr,
|
||||
mut shutdown: ShutdownListener,
|
||||
) {
|
||||
debug!("Starting connection handler for {:?}", remote);
|
||||
let mut framed_conn = Framed::new(conn, SphinxCodec);
|
||||
while let Some(framed_sphinx_packet) = framed_conn.next().await {
|
||||
match framed_sphinx_packet {
|
||||
Ok(framed_sphinx_packet) => {
|
||||
// TODO: benchmark spawning tokio task with full processing vs just processing it
|
||||
// synchronously (without delaying inside of course,
|
||||
// delay is moved to a global DelayQueue)
|
||||
// under higher load in single and multi-threaded situation.
|
||||
while !shutdown.is_shutdown() {
|
||||
tokio::select! {
|
||||
Some(framed_sphinx_packet) = framed_conn.next() => {
|
||||
match framed_sphinx_packet {
|
||||
Ok(framed_sphinx_packet) => {
|
||||
// TODO: benchmark spawning tokio task with full processing vs just processing it
|
||||
// synchronously (without delaying inside of course,
|
||||
// delay is moved to a global DelayQueue)
|
||||
// under higher load in single and multi-threaded situation.
|
||||
|
||||
// in theory we could process multiple sphinx packet from the same connection in parallel,
|
||||
// but we already handle multiple concurrent connections so if anything, making
|
||||
// that change would only slow things down
|
||||
self.handle_received_packet(framed_sphinx_packet);
|
||||
}
|
||||
Err(err) => {
|
||||
error!(
|
||||
"The socket connection got corrupted with error: {:?}. Closing the socket",
|
||||
err
|
||||
);
|
||||
return;
|
||||
// in theory we could process multiple sphinx packet from the same connection in parallel,
|
||||
// but we already handle multiple concurrent connections so if anything, making
|
||||
// that change would only slow things down
|
||||
self.handle_received_packet(framed_sphinx_packet);
|
||||
}
|
||||
Err(err) => {
|
||||
error!(
|
||||
"The socket connection got corrupted with error: {:?}. Closing the socket",
|
||||
err
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
},
|
||||
_ = shutdown.recv() => {
|
||||
log::trace!("ConnectionHandler: received shutdown");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -99,5 +112,6 @@ impl ConnectionHandler {
|
||||
"Closing connection from {:?}",
|
||||
framed_conn.into_inner().peer_addr()
|
||||
);
|
||||
log::trace!("ConnectionHandler: Exiting");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,18 +8,22 @@ use std::process;
|
||||
use tokio::net::TcpListener;
|
||||
use tokio::task::JoinHandle;
|
||||
|
||||
use super::ShutdownListener;
|
||||
|
||||
pub(crate) mod connection_handler;
|
||||
|
||||
pub(crate) struct Listener {
|
||||
address: SocketAddr,
|
||||
shutdown: ShutdownListener,
|
||||
}
|
||||
|
||||
impl Listener {
|
||||
pub(crate) fn new(address: SocketAddr) -> Self {
|
||||
Listener { address }
|
||||
pub(crate) fn new(address: SocketAddr, shutdown: ShutdownListener) -> Self {
|
||||
Listener { address, shutdown }
|
||||
}
|
||||
|
||||
async fn run(&mut self, connection_handler: ConnectionHandler) {
|
||||
log::trace!("Starting Listener");
|
||||
let listener = match TcpListener::bind(self.address).await {
|
||||
Ok(listener) => listener,
|
||||
Err(err) => {
|
||||
@@ -28,15 +32,23 @@ impl Listener {
|
||||
}
|
||||
};
|
||||
|
||||
loop {
|
||||
match listener.accept().await {
|
||||
Ok((socket, remote_addr)) => {
|
||||
let handler = connection_handler.clone();
|
||||
tokio::spawn(handler.handle_connection(socket, remote_addr));
|
||||
while !self.shutdown.is_shutdown() {
|
||||
tokio::select! {
|
||||
connection = listener.accept() => {
|
||||
match connection {
|
||||
Ok((socket, remote_addr)) => {
|
||||
let handler = connection_handler.clone();
|
||||
tokio::spawn(handler.handle_connection(socket, remote_addr, self.shutdown.clone()));
|
||||
}
|
||||
Err(err) => warn!("Failed to accept incoming connection - {:?}", err),
|
||||
}
|
||||
},
|
||||
_ = self.shutdown.recv() => {
|
||||
log::trace!("Listener: Received shutdown");
|
||||
}
|
||||
Err(err) => warn!("Failed to accept incoming connection - {:?}", err),
|
||||
}
|
||||
};
|
||||
}
|
||||
log::trace!("Listener: Exiting");
|
||||
}
|
||||
|
||||
pub(crate) fn start(mut self, connection_handler: ConnectionHandler) -> JoinHandle<()> {
|
||||
|
||||
+40
-11
@@ -25,6 +25,7 @@ use rand::thread_rng;
|
||||
use std::net::SocketAddr;
|
||||
use std::process;
|
||||
use std::sync::Arc;
|
||||
use task::{ShutdownListener, ShutdownNotifier};
|
||||
use version_checker::parse_version;
|
||||
|
||||
mod http;
|
||||
@@ -149,11 +150,15 @@ impl MixNode {
|
||||
});
|
||||
}
|
||||
|
||||
fn start_node_stats_controller(&self) -> (SharedNodeStats, node_statistics::UpdateSender) {
|
||||
fn start_node_stats_controller(
|
||||
&self,
|
||||
shutdown: ShutdownListener,
|
||||
) -> (SharedNodeStats, node_statistics::UpdateSender) {
|
||||
info!("Starting node stats controller...");
|
||||
let controller = node_statistics::Controller::new(
|
||||
self.config.get_node_stats_logging_delay(),
|
||||
self.config.get_node_stats_updating_delay(),
|
||||
shutdown,
|
||||
);
|
||||
let node_stats_pointer = controller.get_node_stats_data_pointer();
|
||||
let update_sender = controller.start();
|
||||
@@ -165,6 +170,7 @@ impl MixNode {
|
||||
&self,
|
||||
node_stats_update_sender: node_statistics::UpdateSender,
|
||||
delay_forwarding_channel: PacketDelayForwardSender,
|
||||
shutdown: ShutdownListener,
|
||||
) {
|
||||
info!("Starting socket listener...");
|
||||
|
||||
@@ -178,12 +184,13 @@ impl MixNode {
|
||||
self.config.get_mix_port(),
|
||||
);
|
||||
|
||||
Listener::new(listening_address).start(connection_handler);
|
||||
Listener::new(listening_address, shutdown).start(connection_handler);
|
||||
}
|
||||
|
||||
fn start_packet_delay_forwarder(
|
||||
&mut self,
|
||||
node_stats_update_sender: node_statistics::UpdateSender,
|
||||
shutdown: ShutdownListener,
|
||||
) -> PacketDelayForwardSender {
|
||||
info!("Starting packet delay-forwarder...");
|
||||
|
||||
@@ -197,6 +204,7 @@ impl MixNode {
|
||||
let mut packet_forwarder = DelayForwarder::new(
|
||||
mixnet_client::Client::new(client_config),
|
||||
node_stats_update_sender,
|
||||
shutdown,
|
||||
);
|
||||
|
||||
let packet_sender = packet_forwarder.sender();
|
||||
@@ -259,7 +267,10 @@ impl MixNode {
|
||||
let existing_nodes = match validator_client.get_cached_mixnodes().await {
|
||||
Ok(nodes) => nodes,
|
||||
Err(err) => {
|
||||
error!("failed to grab initial network mixnodes - {}\n Please try to startup again in few minutes", err);
|
||||
error!(
|
||||
"failed to grab initial network mixnodes - {err}\n \
|
||||
Please try to startup again in few minutes",
|
||||
);
|
||||
process::exit(1);
|
||||
}
|
||||
};
|
||||
@@ -272,16 +283,26 @@ impl MixNode {
|
||||
.map(|node| node.mix_node.identity_key.clone())
|
||||
}
|
||||
|
||||
async fn wait_for_interrupt(&self) {
|
||||
async fn wait_for_interrupt(&self, mut shutdown: ShutdownNotifier) {
|
||||
if let Err(e) = tokio::signal::ctrl_c().await {
|
||||
error!(
|
||||
"There was an error while capturing SIGINT - {:?}. We will terminate regardless",
|
||||
"There was an error while capturing SIGINT - {:?}. \
|
||||
We will terminate regardless",
|
||||
e
|
||||
);
|
||||
}
|
||||
println!(
|
||||
"Received SIGINT - the mixnode will terminate now (threads are not yet nicely stopped, if you see stack traces that's alright)."
|
||||
"Received SIGINT - the mixnode will terminate now \
|
||||
(threads are not yet nicely stopped, if you see stack traces that's alright)."
|
||||
);
|
||||
|
||||
log::info!("Sending shutdown");
|
||||
shutdown.signal_shutdown().ok();
|
||||
|
||||
log::info!("Waiting for tasks to finish... (Press ctrl-c to force)");
|
||||
shutdown.wait_for_shutdown().await;
|
||||
|
||||
log::info!("Stopping nym mixnode");
|
||||
}
|
||||
|
||||
pub async fn run(&mut self) {
|
||||
@@ -299,15 +320,23 @@ impl MixNode {
|
||||
}
|
||||
}
|
||||
|
||||
let (node_stats_pointer, node_stats_update_sender) = self.start_node_stats_controller();
|
||||
let delay_forwarding_channel =
|
||||
self.start_packet_delay_forwarder(node_stats_update_sender.clone());
|
||||
self.start_socket_listener(node_stats_update_sender, delay_forwarding_channel);
|
||||
let shutdown = ShutdownNotifier::default();
|
||||
|
||||
let (node_stats_pointer, node_stats_update_sender) =
|
||||
self.start_node_stats_controller(shutdown.subscribe());
|
||||
let delay_forwarding_channel = self
|
||||
.start_packet_delay_forwarder(node_stats_update_sender.clone(), shutdown.subscribe());
|
||||
self.start_socket_listener(
|
||||
node_stats_update_sender,
|
||||
delay_forwarding_channel,
|
||||
shutdown.subscribe(),
|
||||
);
|
||||
|
||||
// TODO: these two also needs to be shutdown
|
||||
let atomic_verloc_results = self.start_verloc_measurements();
|
||||
self.start_http_api(atomic_verloc_results, node_stats_pointer);
|
||||
|
||||
info!("Finished nym mixnode startup procedure - it should now be able to receive mix traffic!");
|
||||
self.wait_for_interrupt().await
|
||||
self.wait_for_interrupt(shutdown).await
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,8 @@ use std::sync::Arc;
|
||||
use std::time::{Duration, SystemTime};
|
||||
use tokio::sync::{RwLock, RwLockReadGuard};
|
||||
|
||||
use super::ShutdownListener;
|
||||
|
||||
// convenience aliases
|
||||
type PacketsMap = HashMap<String, u64>;
|
||||
type PacketDataReceiver = mpsc::UnboundedReceiver<PacketEvent>;
|
||||
@@ -209,28 +211,45 @@ impl CurrentPacketData {
|
||||
struct UpdateHandler {
|
||||
current_data: CurrentPacketData,
|
||||
update_receiver: PacketDataReceiver,
|
||||
shutdown: ShutdownListener,
|
||||
}
|
||||
|
||||
impl UpdateHandler {
|
||||
fn new(current_data: CurrentPacketData, update_receiver: PacketDataReceiver) -> Self {
|
||||
fn new(
|
||||
current_data: CurrentPacketData,
|
||||
update_receiver: PacketDataReceiver,
|
||||
shutdown: ShutdownListener,
|
||||
) -> Self {
|
||||
UpdateHandler {
|
||||
current_data,
|
||||
update_receiver,
|
||||
shutdown,
|
||||
}
|
||||
}
|
||||
|
||||
async fn run(&mut self) {
|
||||
while let Some(packet_data) = self.update_receiver.next().await {
|
||||
match packet_data {
|
||||
PacketEvent::Received => self.current_data.increment_received(),
|
||||
PacketEvent::Sent(destination) => {
|
||||
self.current_data.increment_sent(destination).await
|
||||
log::trace!("Starting UpdateHandler");
|
||||
while !self.shutdown.is_shutdown() {
|
||||
tokio::select! {
|
||||
Some(packet_data) = self.update_receiver.next() => {
|
||||
match packet_data {
|
||||
PacketEvent::Received => self.current_data.increment_received(),
|
||||
PacketEvent::Sent(destination) => {
|
||||
self.current_data.increment_sent(destination).await
|
||||
}
|
||||
PacketEvent::Dropped(destination) => {
|
||||
self.current_data.increment_dropped(destination).await
|
||||
}
|
||||
}
|
||||
}
|
||||
PacketEvent::Dropped(destination) => {
|
||||
self.current_data.increment_dropped(destination).await
|
||||
_ = self.shutdown.recv() => {
|
||||
log::trace!("UpdateHandler: Received shutdown");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
log::trace!("UpdateHandler: Exiting");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -274,6 +293,7 @@ struct StatsUpdater {
|
||||
updating_delay: Duration,
|
||||
current_packet_data: CurrentPacketData,
|
||||
current_stats: SharedNodeStats,
|
||||
shutdown: ShutdownListener,
|
||||
}
|
||||
|
||||
impl StatsUpdater {
|
||||
@@ -281,11 +301,13 @@ impl StatsUpdater {
|
||||
updating_delay: Duration,
|
||||
current_packet_data: CurrentPacketData,
|
||||
current_stats: SharedNodeStats,
|
||||
shutdown: ShutdownListener,
|
||||
) -> Self {
|
||||
StatsUpdater {
|
||||
updating_delay,
|
||||
current_packet_data,
|
||||
current_stats,
|
||||
shutdown,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -295,11 +317,16 @@ impl StatsUpdater {
|
||||
self.current_stats.update(received, sent, dropped).await;
|
||||
}
|
||||
|
||||
async fn run(&self) {
|
||||
loop {
|
||||
tokio::time::sleep(self.updating_delay).await;
|
||||
self.update_stats().await
|
||||
async fn run(&mut self) {
|
||||
while !self.shutdown.is_shutdown() {
|
||||
tokio::select! {
|
||||
_ = tokio::time::sleep(self.updating_delay) => self.update_stats().await,
|
||||
_ = self.shutdown.recv() => {
|
||||
log::trace!("StatsUpdater: Received shutdown");
|
||||
}
|
||||
}
|
||||
}
|
||||
log::trace!("StatsUpdater: Exiting");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -308,13 +335,15 @@ impl StatsUpdater {
|
||||
struct PacketStatsConsoleLogger {
|
||||
logging_delay: Duration,
|
||||
stats: SharedNodeStats,
|
||||
shutdown: ShutdownListener,
|
||||
}
|
||||
|
||||
impl PacketStatsConsoleLogger {
|
||||
fn new(logging_delay: Duration, stats: SharedNodeStats) -> Self {
|
||||
fn new(logging_delay: Duration, stats: SharedNodeStats, shutdown: ShutdownListener) -> Self {
|
||||
PacketStatsConsoleLogger {
|
||||
logging_delay,
|
||||
stats,
|
||||
shutdown,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -387,10 +416,16 @@ impl PacketStatsConsoleLogger {
|
||||
}
|
||||
|
||||
async fn run(&mut self) {
|
||||
loop {
|
||||
tokio::time::sleep(self.logging_delay).await;
|
||||
self.log_running_stats().await;
|
||||
log::trace!("Starting PacketStatsConsoleLogger");
|
||||
while !self.shutdown.is_shutdown() {
|
||||
tokio::select! {
|
||||
_ = tokio::time::sleep(self.logging_delay) => self.log_running_stats().await,
|
||||
_ = self.shutdown.recv() => {
|
||||
log::trace!("PacketStatsConsoleLogger: Received shutdown");
|
||||
}
|
||||
};
|
||||
}
|
||||
log::trace!("PacketStatsConsoleLogger: Exiting");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -413,19 +448,32 @@ pub struct Controller {
|
||||
}
|
||||
|
||||
impl Controller {
|
||||
pub(crate) fn new(logging_delay: Duration, stats_updating_delay: Duration) -> Self {
|
||||
pub(crate) fn new(
|
||||
logging_delay: Duration,
|
||||
stats_updating_delay: Duration,
|
||||
shutdown: ShutdownListener,
|
||||
) -> Self {
|
||||
let (sender, receiver) = mpsc::unbounded();
|
||||
let shared_packet_data = CurrentPacketData::new();
|
||||
let shared_node_stats = SharedNodeStats::new();
|
||||
|
||||
Controller {
|
||||
update_handler: UpdateHandler::new(shared_packet_data.clone(), receiver),
|
||||
update_handler: UpdateHandler::new(
|
||||
shared_packet_data.clone(),
|
||||
receiver,
|
||||
shutdown.clone(),
|
||||
),
|
||||
update_sender: UpdateSender::new(sender),
|
||||
console_logger: PacketStatsConsoleLogger::new(logging_delay, shared_node_stats.clone()),
|
||||
console_logger: PacketStatsConsoleLogger::new(
|
||||
logging_delay,
|
||||
shared_node_stats.clone(),
|
||||
shutdown.clone(),
|
||||
),
|
||||
stats_updater: StatsUpdater::new(
|
||||
stats_updating_delay,
|
||||
shared_packet_data,
|
||||
shared_node_stats.clone(),
|
||||
shutdown,
|
||||
),
|
||||
node_stats: shared_node_stats,
|
||||
}
|
||||
@@ -441,7 +489,7 @@ impl Controller {
|
||||
pub(crate) fn start(self) -> UpdateSender {
|
||||
// move out of self
|
||||
let mut update_handler = self.update_handler;
|
||||
let stats_updater = self.stats_updater;
|
||||
let mut stats_updater = self.stats_updater;
|
||||
let mut console_logger = self.console_logger;
|
||||
|
||||
tokio::spawn(async move { update_handler.run().await });
|
||||
@@ -455,12 +503,15 @@ impl Controller {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use task::ShutdownNotifier;
|
||||
|
||||
#[tokio::test]
|
||||
async fn node_stats_reported_are_received() {
|
||||
let logging_delay = Duration::from_millis(20);
|
||||
let stats_updating_delay = Duration::from_millis(10);
|
||||
let node_stats_controller = Controller::new(logging_delay, stats_updating_delay);
|
||||
let shutdown = ShutdownNotifier::default();
|
||||
let node_stats_controller =
|
||||
Controller::new(logging_delay, stats_updating_delay, shutdown.subscribe());
|
||||
|
||||
let node_stats_pointer = node_stats_controller.get_node_stats_data_pointer();
|
||||
let update_sender = node_stats_controller.start();
|
||||
|
||||
@@ -4,11 +4,13 @@
|
||||
use crate::node::node_statistics::UpdateSender;
|
||||
use futures::channel::mpsc;
|
||||
use futures::StreamExt;
|
||||
use nonexhaustive_delayqueue::{Expired, NonExhaustiveDelayQueue, TimerError};
|
||||
use nonexhaustive_delayqueue::{Expired, NonExhaustiveDelayQueue};
|
||||
use nymsphinx::forwarding::packet::MixPacket;
|
||||
use std::io;
|
||||
use tokio::time::Instant;
|
||||
|
||||
use super::ShutdownListener;
|
||||
|
||||
// Delay + MixPacket vs Instant + MixPacket
|
||||
|
||||
// rather than using Duration directly, we use an Instant, this way we minimise skew due to
|
||||
@@ -26,13 +28,18 @@ where
|
||||
packet_sender: PacketDelayForwardSender,
|
||||
packet_receiver: PacketDelayForwardReceiver,
|
||||
node_stats_update_sender: UpdateSender,
|
||||
shutdown: ShutdownListener,
|
||||
}
|
||||
|
||||
impl<C> DelayForwarder<C>
|
||||
where
|
||||
C: mixnet_client::SendWithoutResponse,
|
||||
{
|
||||
pub(crate) fn new(client: C, node_stats_update_sender: UpdateSender) -> DelayForwarder<C> {
|
||||
pub(crate) fn new(
|
||||
client: C,
|
||||
node_stats_update_sender: UpdateSender,
|
||||
shutdown: ShutdownListener,
|
||||
) -> DelayForwarder<C> {
|
||||
let (packet_sender, packet_receiver) = mpsc::unbounded();
|
||||
|
||||
DelayForwarder::<C> {
|
||||
@@ -41,6 +48,7 @@ where
|
||||
packet_sender,
|
||||
packet_receiver,
|
||||
node_stats_update_sender,
|
||||
shutdown,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,13 +83,8 @@ where
|
||||
}
|
||||
|
||||
/// Upon packet being finished getting delayed, forward it to the mixnet.
|
||||
fn handle_done_delaying(&mut self, packet: Option<Result<Expired<MixPacket>, TimerError>>) {
|
||||
// those are critical errors that I don't think can be recovered from.
|
||||
let delayed = packet.expect("the queue has unexpectedly terminated!");
|
||||
let delayed_packet = delayed
|
||||
.expect("Encountered timer issue within the runtime!")
|
||||
.into_inner();
|
||||
|
||||
fn handle_done_delaying(&mut self, packet: Expired<MixPacket>) {
|
||||
let delayed_packet = packet.into_inner();
|
||||
self.forward_packet(delayed_packet)
|
||||
}
|
||||
|
||||
@@ -102,18 +105,24 @@ where
|
||||
}
|
||||
|
||||
pub(crate) async fn run(&mut self) {
|
||||
log::trace!("Starting DelayForwarder");
|
||||
loop {
|
||||
tokio::select! {
|
||||
delayed = self.delay_queue.next() => {
|
||||
self.handle_done_delaying(delayed);
|
||||
self.handle_done_delaying(delayed.unwrap());
|
||||
}
|
||||
new_packet = self.packet_receiver.next() => {
|
||||
// this one is impossible to ever panic - the object itself contains a sender
|
||||
// and hence it can't happen that ALL senders are dropped
|
||||
self.handle_new_packet(new_packet.unwrap())
|
||||
}
|
||||
_ = self.shutdown.recv() => {
|
||||
log::trace!("DelayForwarder: Received shutdown");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
log::trace!("DelayForwarder: Exiting");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,6 +134,8 @@ mod tests {
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::time::Duration;
|
||||
|
||||
use task::ShutdownNotifier;
|
||||
|
||||
use nymsphinx::addressing::nodes::NymNodeRoutingAddress;
|
||||
use nymsphinx_params::packet_sizes::PacketSize;
|
||||
use nymsphinx_params::PacketMode;
|
||||
@@ -194,7 +205,9 @@ mod tests {
|
||||
let node_stats_update_sender = UpdateSender::new(stats_sender);
|
||||
let client = TestClient::default();
|
||||
let client_packets_sent = client.packets_sent.clone();
|
||||
let mut delay_forwarder = DelayForwarder::new(client, node_stats_update_sender);
|
||||
let shutdown = ShutdownNotifier::default();
|
||||
let mut delay_forwarder =
|
||||
DelayForwarder::new(client, node_stats_update_sender, shutdown.subscribe());
|
||||
let packet_sender = delay_forwarder.sender();
|
||||
|
||||
// Spawn the worker, listening on packet_sender channel
|
||||
|
||||
Generated
+42
-120
@@ -328,7 +328,7 @@ checksum = "873faa4363bfc54c36a48321da034c92a0645a363eed34d948683ffc1706e37f"
|
||||
dependencies = [
|
||||
"bs58",
|
||||
"hmac",
|
||||
"k256 0.10.2",
|
||||
"k256",
|
||||
"once_cell",
|
||||
"pbkdf2",
|
||||
"rand_core 0.6.3",
|
||||
@@ -763,12 +763,6 @@ dependencies = [
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "const-oid"
|
||||
version = "0.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9d6f2aa4d0537bcc1c74df8755072bd31c1ef1a3a1b85a68e8404a8c353b7b8b"
|
||||
|
||||
[[package]]
|
||||
name = "const-oid"
|
||||
version = "0.7.1"
|
||||
@@ -854,10 +848,10 @@ checksum = "8413275b23cb5a0734d9d1e3e33f0b5b94547c1e94776dbc3149dbf46588a533"
|
||||
dependencies = [
|
||||
"bip32",
|
||||
"cosmos-sdk-proto",
|
||||
"ecdsa 0.13.4",
|
||||
"ecdsa",
|
||||
"eyre",
|
||||
"getrandom 0.2.5",
|
||||
"k256 0.10.2",
|
||||
"k256",
|
||||
"prost",
|
||||
"prost-types",
|
||||
"rand_core 0.6.3",
|
||||
@@ -871,31 +865,31 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cosmwasm-crypto"
|
||||
version = "1.0.0-beta8"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "37e70111e9701c3ec43bfbff0e523cd4cb115876b4d3433813436dd0934ee962"
|
||||
checksum = "5eb0afef2325df81aadbf9be1233f522ed8f6e91df870c764bc44cca2b1415bd"
|
||||
dependencies = [
|
||||
"digest 0.9.0",
|
||||
"ed25519-zebra",
|
||||
"k256 0.9.6",
|
||||
"k256",
|
||||
"rand_core 0.6.3",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cosmwasm-derive"
|
||||
version = "1.0.0-beta8"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "58bc2ad5d86be5f6068833f63e20786768db6890019c095dd7775232184fb7b3"
|
||||
checksum = "4b36e527620a2a3e00e46b6e731ab6c9b68d11069c986f7d7be8eba79ef081a4"
|
||||
dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cosmwasm-std"
|
||||
version = "1.0.0-beta8"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "915ca82bd944f116f3a9717481f3fa657e4a73f28c4887288761ebb24e6fbe10"
|
||||
checksum = "875994993c2082a6fcd406937bf0fca21c349e4a624f3810253a14fa83a3a195"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"cosmwasm-crypto",
|
||||
@@ -976,18 +970,6 @@ version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
|
||||
|
||||
[[package]]
|
||||
name = "crypto-bigint"
|
||||
version = "0.2.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f83bd3bb4314701c568e340cd8cf78c975aa0ca79e03d3f6d1677d5b0c9c0c03"
|
||||
dependencies = [
|
||||
"generic-array 0.14.5",
|
||||
"rand_core 0.6.3",
|
||||
"subtle",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crypto-bigint"
|
||||
version = "0.3.2"
|
||||
@@ -1096,9 +1078,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cw-storage-plus"
|
||||
version = "0.13.2"
|
||||
version = "0.13.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9336ecef1e19d56cf6e3e932475fc6a3dee35eec5a386e07917a1d1ba6bb0e35"
|
||||
checksum = "648b1507290bbc03a8d88463d7cd9b04b1fa0155e5eef366c4fa052b9caaac7a"
|
||||
dependencies = [
|
||||
"cosmwasm-std",
|
||||
"schemars",
|
||||
@@ -1231,22 +1213,13 @@ dependencies = [
|
||||
"byteorder",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "der"
|
||||
version = "0.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "79b71cca7d95d7681a4b3b9cdf63c8dbc3730d0584c2c74e31416d64a90493f4"
|
||||
dependencies = [
|
||||
"const-oid 0.6.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "der"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6919815d73839e7ad218de758883aae3a257ba6759ce7a9992501efbb53d705c"
|
||||
dependencies = [
|
||||
"const-oid 0.7.1",
|
||||
"const-oid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1382,26 +1355,14 @@ version = "3.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6907e25393cdcc1f4f3f513d9aac1e840eb1cc341a0fccb01171f7d14d10b946"
|
||||
|
||||
[[package]]
|
||||
name = "ecdsa"
|
||||
version = "0.12.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "43ee23aa5b4f68c7a092b5c3beb25f50c406adc75e2363634f242f28ab255372"
|
||||
dependencies = [
|
||||
"der 0.4.5",
|
||||
"elliptic-curve 0.10.6",
|
||||
"hmac",
|
||||
"signature",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ecdsa"
|
||||
version = "0.13.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d0d69ae62e0ce582d56380743515fefaf1a8c70cec685d9677636d7e30ae9dc9"
|
||||
dependencies = [
|
||||
"der 0.5.1",
|
||||
"elliptic-curve 0.11.12",
|
||||
"der",
|
||||
"elliptic-curve",
|
||||
"rfc6979",
|
||||
"signature",
|
||||
]
|
||||
@@ -1448,22 +1409,6 @@ version = "1.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
|
||||
|
||||
[[package]]
|
||||
name = "elliptic-curve"
|
||||
version = "0.10.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "beca177dcb8eb540133e7680baff45e7cc4d93bf22002676cec549f82343721b"
|
||||
dependencies = [
|
||||
"crypto-bigint 0.2.11",
|
||||
"ff 0.10.1",
|
||||
"generic-array 0.14.5",
|
||||
"group 0.10.0",
|
||||
"pkcs8 0.7.6",
|
||||
"rand_core 0.6.3",
|
||||
"subtle",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "elliptic-curve"
|
||||
version = "0.11.12"
|
||||
@@ -1471,8 +1416,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "25b477563c2bfed38a3b7a60964c49e058b2510ad3f12ba3483fd8f62c2306d6"
|
||||
dependencies = [
|
||||
"base16ct",
|
||||
"crypto-bigint 0.3.2",
|
||||
"der 0.5.1",
|
||||
"crypto-bigint",
|
||||
"der",
|
||||
"ff 0.11.0",
|
||||
"generic-array 0.14.5",
|
||||
"group 0.11.0",
|
||||
@@ -2625,25 +2570,13 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "k256"
|
||||
version = "0.9.6"
|
||||
version = "0.10.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "903ae2481bcdfdb7b68e0a9baa4b7c9aff600b9ae2e8e5bb5833b8c91ab851ea"
|
||||
checksum = "19c3a5e0a0b8450278feda242592512e09f61c72e018b8cd5c859482802daf2d"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"ecdsa 0.12.4",
|
||||
"elliptic-curve 0.10.6",
|
||||
"sha2 0.9.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "k256"
|
||||
version = "0.10.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1cc5937366afd3b38071f400d1ce5bd8b1d40b5083cc14e6f8dbcc4032a7f5bb"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"ecdsa 0.13.4",
|
||||
"elliptic-curve 0.11.12",
|
||||
"ecdsa",
|
||||
"elliptic-curve",
|
||||
"sec1",
|
||||
"sha2 0.9.9",
|
||||
"sha3",
|
||||
@@ -2816,14 +2749,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mio"
|
||||
version = "0.8.0"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ba272f85fa0b41fc91872be579b3bbe0f56b792aa361a380eb669469f68dafb2"
|
||||
checksum = "52da4364ffb0e4fe33a9841a98a3f3014fb964045ce4f7a45a398243c8d6b0c9"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"log",
|
||||
"miow",
|
||||
"ntapi",
|
||||
"wasi 0.11.0+wasi-snapshot-preview1",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
@@ -3592,24 +3526,14 @@ version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
||||
|
||||
[[package]]
|
||||
name = "pkcs8"
|
||||
version = "0.7.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ee3ef9b64d26bad0536099c816c6734379e45bbd5f14798def6809e5cc350447"
|
||||
dependencies = [
|
||||
"der 0.4.5",
|
||||
"spki 0.4.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pkcs8"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7cabda3fb821068a9a4fab19a683eac3af12edf0f34b94a8be53c4972b8149d0"
|
||||
dependencies = [
|
||||
"der 0.5.1",
|
||||
"spki 0.5.4",
|
||||
"der",
|
||||
"spki",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
@@ -4134,7 +4058,7 @@ version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "96ef608575f6392792f9ecf7890c00086591d29a83910939d430753f7c050525"
|
||||
dependencies = [
|
||||
"crypto-bigint 0.3.2",
|
||||
"crypto-bigint",
|
||||
"hmac",
|
||||
"zeroize",
|
||||
]
|
||||
@@ -4318,9 +4242,9 @@ version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08da66b8b0965a5555b6bd6639e68ccba85e1e2506f5fbb089e93f8a04e1a2d1"
|
||||
dependencies = [
|
||||
"der 0.5.1",
|
||||
"der",
|
||||
"generic-array 0.14.5",
|
||||
"pkcs8 0.8.0",
|
||||
"pkcs8",
|
||||
"subtle",
|
||||
"zeroize",
|
||||
]
|
||||
@@ -4403,9 +4327,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde-json-wasm"
|
||||
version = "0.3.2"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "042ac496d97e5885149d34139bad1d617192770d7eb8f1866da2317ff4501853"
|
||||
checksum = "479b4dbc401ca13ee8ce902851b834893251404c4f3c65370a49e047a6be09a5"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
@@ -4680,15 +4604,6 @@ version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
|
||||
|
||||
[[package]]
|
||||
name = "spki"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c01a0c15da1b0b0e1494112e7af814a678fec9bd157881b49beac661e9b6f32"
|
||||
dependencies = [
|
||||
"der 0.4.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "spki"
|
||||
version = "0.5.4"
|
||||
@@ -4696,7 +4611,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "44d01ac02a6ccf3e07db148d2be087da624fea0221a16152ed01f0496a6b0a27"
|
||||
dependencies = [
|
||||
"base64ct",
|
||||
"der 0.5.1",
|
||||
"der",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -5128,7 +5043,7 @@ dependencies = [
|
||||
"ed25519-dalek",
|
||||
"flex-error",
|
||||
"futures",
|
||||
"k256 0.10.2",
|
||||
"k256",
|
||||
"num-traits",
|
||||
"once_cell",
|
||||
"prost",
|
||||
@@ -5303,15 +5218,16 @@ checksum = "25eb0ca3468fc0acc11828786797f6ef9aa1555e4a211a60d64cc8e4d1be47d6"
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.17.0"
|
||||
version = "1.19.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2af73ac49756f3f7c01172e34a23e5d0216f6c32333757c2c61feb2bbff5a5ee"
|
||||
checksum = "c51a52ed6686dd62c320f9b89299e9dfb46f730c7a48e635c19f21d116cb1439"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"libc",
|
||||
"memchr",
|
||||
"mio",
|
||||
"num_cpus",
|
||||
"once_cell",
|
||||
"pin-project-lite",
|
||||
"socket2",
|
||||
"tokio-macros",
|
||||
@@ -5731,6 +5647,12 @@ version = "0.10.2+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.0+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.79"
|
||||
|
||||
@@ -38,7 +38,7 @@ strum = { version = "0.23", features = ["derive"] }
|
||||
tauri = { version = "=1.0.0-rc.2", features = ["clipboard-all", "shell-open", "updater", "window-maximize"] }
|
||||
tendermint-rpc = "0.23.0"
|
||||
thiserror = "1.0"
|
||||
tokio = { version = "1.10", features = ["sync", "time"] }
|
||||
tokio = { version = "1.19.1", features = ["sync", "time"] }
|
||||
toml = "0.5.8"
|
||||
url = "2.2"
|
||||
|
||||
@@ -47,7 +47,7 @@ argon2 = { version = "0.3.2", features = ["std"] }
|
||||
base64 = "0.13"
|
||||
zeroize = "1.4.3"
|
||||
|
||||
cosmwasm-std = "1.0.0-beta8"
|
||||
cosmwasm-std = "1.0.0"
|
||||
cosmrs = "0.7.0"
|
||||
|
||||
validator-client = { path = "../../common/client-libs/validator-client", features = [
|
||||
|
||||
@@ -616,8 +616,51 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
// This decryptes a stored wallet file using the same procedure as when signing in. Most tests
|
||||
// related to the encryped wallet storage is in `wallet_storage`.
|
||||
#[test]
|
||||
fn decrypt_stored_wallet_multiple_for_sign_in() {
|
||||
// WIP(JON): same as above but with file containing multiple accounts
|
||||
const SAVED_WALLET: &str = "src/wallet_storage/test-data/saved-wallet-1.0.5.json";
|
||||
let wallet_file = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join(SAVED_WALLET);
|
||||
let login_id = wallet_storage::LoginId::new(DEFAULT_LOGIN_ID.to_string());
|
||||
let account_id = wallet_storage::AccountId::new("default".to_string());
|
||||
let password = wallet_storage::UserPassword::new("password11!".to_string());
|
||||
let hd_path: DerivationPath = COSMOS_DERIVATION_PATH.parse().unwrap();
|
||||
|
||||
let stored_login =
|
||||
wallet_storage::load_existing_login_at_file(&wallet_file, &login_id, &password)
|
||||
.unwrap();
|
||||
let mnemonic = extract_first_mnemonic(&stored_login).unwrap();
|
||||
|
||||
let expected_mnemonic = bip39::Mnemonic::from_str("arrow capable abstract industry elevator nominee december piece hotel feed lounge web faint sword veteran bundle hour page actual laptop horror gold test warrior").unwrap();
|
||||
assert_eq!(mnemonic, expected_mnemonic);
|
||||
|
||||
let all_accounts: Vec<_> = stored_login
|
||||
.unwrap_into_multiple_accounts(account_id)
|
||||
.into_accounts()
|
||||
.collect();
|
||||
|
||||
let expected_mn2 = bip39::Mnemonic::from_str("border hurt skull lunar goddess second danger game dismiss exhaust oven thumb dog drama onion false orchard spice tent next predict invite cherry green").unwrap();
|
||||
let expected_mn3 = bip39::Mnemonic::from_str("gentle crowd rule snap girl urge flat jump winner cluster night sand museum stock grunt quick tree acquire traffic major awake tag rack peasant").unwrap();
|
||||
let expected_mn4 = bip39::Mnemonic::from_str("debris blue skin annual inhale text border rigid spatial lesson coconut yard horn crystal control survey version vote hawk neck frame arrive oblige width").unwrap();
|
||||
|
||||
assert_eq!(
|
||||
all_accounts,
|
||||
vec![
|
||||
WalletAccount::new(
|
||||
"default".into(),
|
||||
MnemonicAccount::new(expected_mnemonic, hd_path.clone())
|
||||
),
|
||||
WalletAccount::new(
|
||||
"account2".into(),
|
||||
MnemonicAccount::new(expected_mn2, hd_path.clone()),
|
||||
),
|
||||
WalletAccount::new(
|
||||
"foobar".into(),
|
||||
MnemonicAccount::new(expected_mn3, hd_path.clone()),
|
||||
),
|
||||
WalletAccount::new("42".into(), MnemonicAccount::new(expected_mn4, hd_path)),
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,9 +2,11 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::error::BackendError;
|
||||
use crate::nymd_client;
|
||||
use crate::operations::simulate::{FeeDetails, SimulateResult};
|
||||
use crate::WalletState;
|
||||
use mixnet_contract_common::IdentityKey;
|
||||
use mixnet_contract_common::IdentityKey;
|
||||
use mixnet_contract_common::{ExecuteMsg, Gateway, MixNode};
|
||||
use nym_types::currency::DecCoin;
|
||||
|
||||
@@ -229,3 +231,49 @@ pub async fn simulate_compound_delegator_reward(
|
||||
let gas_price = client.nymd.gas_price().clone();
|
||||
guard.create_detailed_fee(SimulateResult::new(result.gas_info, gas_price))
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn simulate_claim_operator_reward(
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<FeeDetails, BackendError> {
|
||||
let result = nymd_client!(state)
|
||||
.simulate_claim_operator_reward(None)
|
||||
.await?;
|
||||
let gas_price = nymd_client!(state).gas_price().clone();
|
||||
Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn simulate_compound_operator_reward(
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<FeeDetails, BackendError> {
|
||||
let result = nymd_client!(state)
|
||||
.simulate_compound_operator_reward(None)
|
||||
.await?;
|
||||
let gas_price = nymd_client!(state).gas_price().clone();
|
||||
Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn simulate_claim_delegator_reward(
|
||||
mix_identity: IdentityKey,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<FeeDetails, BackendError> {
|
||||
let result = nymd_client!(state)
|
||||
.simulate_claim_delegator_reward(mix_identity, None)
|
||||
.await?;
|
||||
let gas_price = nymd_client!(state).gas_price().clone();
|
||||
Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn simulate_compound_delegator_reward(
|
||||
mix_identity: IdentityKey,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<FeeDetails, BackendError> {
|
||||
let result = nymd_client!(state)
|
||||
.simulate_compound_delegator_reward(mix_identity, None)
|
||||
.await?;
|
||||
let gas_price = nymd_client!(state).gas_price().clone();
|
||||
Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee())
|
||||
}
|
||||
|
||||
@@ -2,9 +2,11 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::error::BackendError;
|
||||
use crate::nymd_client;
|
||||
use crate::operations::simulate::{FeeDetails, SimulateResult};
|
||||
use crate::WalletState;
|
||||
use mixnet_contract_common::IdentityKey;
|
||||
use mixnet_contract_common::IdentityKey;
|
||||
use mixnet_contract_common::{Gateway, MixNode};
|
||||
use nym_types::currency::DecCoin;
|
||||
use vesting_contract_common::ExecuteMsg;
|
||||
@@ -211,3 +213,49 @@ pub async fn simulate_vesting_compound_delegator_reward(
|
||||
let gas_price = client.nymd.gas_price().clone();
|
||||
guard.create_detailed_fee(SimulateResult::new(result.gas_info, gas_price))
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn simulate_vesting_claim_operator_reward(
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<FeeDetails, BackendError> {
|
||||
let result = nymd_client!(state)
|
||||
.simulate_vesting_claim_operator_reward(None)
|
||||
.await?;
|
||||
let gas_price = nymd_client!(state).gas_price().clone();
|
||||
Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn simulate_vesting_compound_operator_reward(
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<FeeDetails, BackendError> {
|
||||
let result = nymd_client!(state)
|
||||
.simulate_vesting_compound_operator_reward(None)
|
||||
.await?;
|
||||
let gas_price = nymd_client!(state).gas_price().clone();
|
||||
Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn simulate_vesting_claim_delegator_reward(
|
||||
mix_identity: IdentityKey,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<FeeDetails, BackendError> {
|
||||
let result = nymd_client!(state)
|
||||
.simulate_vesting_claim_delegator_reward(mix_identity, None)
|
||||
.await?;
|
||||
let gas_price = nymd_client!(state).gas_price().clone();
|
||||
Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn simulate_vesting_compound_delegator_reward(
|
||||
mix_identity: IdentityKey,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<FeeDetails, BackendError> {
|
||||
let result = nymd_client!(state)
|
||||
.simulate_vesting_compound_delegator_reward(mix_identity, None)
|
||||
.await?;
|
||||
let gas_price = nymd_client!(state).gas_price().clone();
|
||||
Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee())
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@ edition = "2021"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
bincode = "1.3"
|
||||
clap = "2.33.0"
|
||||
dirs = "3.0"
|
||||
futures = "0.3"
|
||||
@@ -18,12 +17,12 @@ ipnetwork = "0.17"
|
||||
log = "0.4"
|
||||
pretty_env_logger = "0.4"
|
||||
publicsuffix = "1.5"
|
||||
rand = "0.7"
|
||||
reqwest = { version = "0.11", features = ["json"] }
|
||||
rocket = { version = "0.5.0-rc.1", features = ["json"], optional = true }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
sqlx = { version = "0.5", features = ["runtime-tokio-rustls", "sqlite", "macros", "migrate", "chrono"]}
|
||||
sqlx = { version = "0.5", features = ["runtime-tokio-rustls", "chrono"]}
|
||||
thiserror = "1"
|
||||
tokio = { version = "1.4", features = [ "net", "rt-multi-thread", "macros", "time" ] }
|
||||
tokio = { version = "1.19.1", features = [ "net", "rt-multi-thread", "macros", "time" ] }
|
||||
tokio-tungstenite = "0.14"
|
||||
|
||||
|
||||
@@ -33,14 +32,5 @@ nymsphinx = { path = "../../common/nymsphinx" }
|
||||
ordered-buffer = {path = "../../common/socks5/ordered-buffer"}
|
||||
proxy-helpers = { path = "../../common/socks5/proxy-helpers" }
|
||||
socks5-requests = { path = "../../common/socks5/requests" }
|
||||
statistics = { path = "../../common/statistics" }
|
||||
websocket-requests = { path = "../../clients/native/websocket-requests" }
|
||||
|
||||
[dev-dependencies]
|
||||
rand = "0.7"
|
||||
|
||||
[build-dependencies]
|
||||
sqlx = { version = "0.5", features = ["runtime-tokio-rustls", "sqlite", "macros", "migrate"] }
|
||||
tokio = { version = "1.4", features = ["rt-multi-thread", "macros"] }
|
||||
|
||||
[features]
|
||||
stats-service = ["rocket"]
|
||||
@@ -19,8 +19,7 @@ Running in `open-proxy` mode allows any traffic to be proxied by the network
|
||||
requester.
|
||||
|
||||
### Statistics service
|
||||
The network requester can be build and ran as a gatherer of statistics from all
|
||||
the other network requesters on the mixnet. For that, build the binary with the
|
||||
`stats-service` feature enabled. The native client address that corresponds to
|
||||
this network requester would have to be built into the constants of all the
|
||||
other network requesters that are sending the data.
|
||||
The network requester can be ran as a gatherer of statistics for all
|
||||
the services it proxies. For that, run the binary with the
|
||||
`enable-statistics` flag enabled. Anonymized statistics are then sent to
|
||||
a central server, through the mixnet.
|
||||
@@ -5,7 +5,7 @@ use futures::channel::mpsc;
|
||||
use nymsphinx::addressing::clients::Recipient;
|
||||
use proxy_helpers::connection_controller::ConnectionReceiver;
|
||||
use proxy_helpers::proxy_runner::ProxyRunner;
|
||||
use socks5_requests::{ConnectionId, RemoteAddress, Response};
|
||||
use socks5_requests::{ConnectionId, Message as Socks5Message, RemoteAddress, Response};
|
||||
use std::io;
|
||||
use tokio::net::TcpStream;
|
||||
|
||||
@@ -39,7 +39,7 @@ impl Connection {
|
||||
pub(crate) async fn run_proxy(
|
||||
&mut self,
|
||||
mix_receiver: ConnectionReceiver,
|
||||
mix_sender: mpsc::UnboundedSender<(Response, Recipient)>,
|
||||
mix_sender: mpsc::UnboundedSender<(Socks5Message, Recipient)>,
|
||||
) {
|
||||
let stream = self.conn.take().unwrap();
|
||||
let remote_source_address = "???".to_string(); // we don't know ip address of requester
|
||||
@@ -54,7 +54,10 @@ impl Connection {
|
||||
connection_id,
|
||||
)
|
||||
.run(move |conn_id, read_data, socket_closed| {
|
||||
(Response::new(conn_id, read_data, socket_closed), recipient)
|
||||
(
|
||||
Socks5Message::Response(Response::new(conn_id, read_data, socket_closed)),
|
||||
recipient,
|
||||
)
|
||||
})
|
||||
.await
|
||||
.into_inner();
|
||||
|
||||
@@ -3,22 +3,19 @@
|
||||
|
||||
use crate::allowed_hosts::{HostsStore, OutboundRequestFilter};
|
||||
use crate::connection::Connection;
|
||||
use crate::statistics::{Statistics, StatsData, Timer};
|
||||
use crate::statistics::{StatisticsCollector, StatisticsSender, Timer};
|
||||
use crate::websocket;
|
||||
use crate::websocket::TSWebsocketStream;
|
||||
use futures::channel::mpsc;
|
||||
use futures::stream::{SplitSink, SplitStream};
|
||||
use futures::{SinkExt, StreamExt};
|
||||
use log::*;
|
||||
use nymsphinx::addressing::clients::{ClientIdentity, Recipient};
|
||||
use nymsphinx::addressing::clients::Recipient;
|
||||
use nymsphinx::receiver::ReconstructedMessage;
|
||||
use proxy_helpers::connection_controller::{Controller, ControllerCommand, ControllerSender};
|
||||
use socks5_requests::{ConnectionId, Message as Socks5Message, Request, Response};
|
||||
use std::collections::HashMap;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::RwLock;
|
||||
use tokio_tungstenite::tungstenite::protocol::Message;
|
||||
use websocket::WebsocketConnectionError;
|
||||
use websocket_requests::{requests::ClientRequest, responses::ServerResponse};
|
||||
@@ -28,20 +25,18 @@ static ACTIVE_PROXIES: AtomicUsize = AtomicUsize::new(0);
|
||||
|
||||
pub struct ServiceProvider {
|
||||
listening_address: String,
|
||||
description: String,
|
||||
#[cfg(feature = "stats-service")]
|
||||
db_path: PathBuf,
|
||||
outbound_request_filter: OutboundRequestFilter,
|
||||
open_proxy: bool,
|
||||
enable_statistics: bool,
|
||||
stats_provider_addr: Option<Recipient>,
|
||||
}
|
||||
|
||||
impl ServiceProvider {
|
||||
pub fn new(
|
||||
listening_address: String,
|
||||
description: String,
|
||||
open_proxy: bool,
|
||||
enable_statistics: bool,
|
||||
stats_provider_addr: Option<Recipient>,
|
||||
) -> ServiceProvider {
|
||||
let allowed_hosts = HostsStore::new(
|
||||
HostsStore::default_base_dir(),
|
||||
@@ -53,21 +48,13 @@ impl ServiceProvider {
|
||||
PathBuf::from("unknown.list"),
|
||||
);
|
||||
|
||||
#[cfg(feature = "stats-service")]
|
||||
let db_path = HostsStore::default_base_dir()
|
||||
.join("service-providers")
|
||||
.join("network-requester")
|
||||
.join("db.sqlite");
|
||||
|
||||
let outbound_request_filter = OutboundRequestFilter::new(allowed_hosts, unknown_hosts);
|
||||
ServiceProvider {
|
||||
listening_address,
|
||||
description,
|
||||
#[cfg(feature = "stats-service")]
|
||||
db_path,
|
||||
outbound_request_filter,
|
||||
open_proxy,
|
||||
enable_statistics,
|
||||
stats_provider_addr,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,21 +62,29 @@ impl ServiceProvider {
|
||||
/// via the `websocket_writer`.
|
||||
async fn mixnet_response_listener(
|
||||
mut websocket_writer: SplitSink<TSWebsocketStream, Message>,
|
||||
mut mix_reader: mpsc::UnboundedReceiver<(Response, Recipient)>,
|
||||
response_stats_data: &Option<Arc<RwLock<StatsData>>>,
|
||||
mut mix_reader: mpsc::UnboundedReceiver<(Socks5Message, Recipient)>,
|
||||
stats_collector: Option<StatisticsCollector>,
|
||||
) {
|
||||
// TODO: wire SURBs in here once they're available
|
||||
while let Some((response, return_address)) = mix_reader.next().await {
|
||||
if let Some(response_stats_data) = response_stats_data {
|
||||
response_stats_data
|
||||
.write()
|
||||
while let Some((msg, return_address)) = mix_reader.next().await {
|
||||
if let Some(stats_collector) = stats_collector.as_ref() {
|
||||
if let Some(remote_addr) = stats_collector
|
||||
.connected_services
|
||||
.read()
|
||||
.await
|
||||
.processed(return_address.identity(), response.data.len() as u32);
|
||||
.get(&msg.conn_id())
|
||||
{
|
||||
stats_collector
|
||||
.response_stats_data
|
||||
.write()
|
||||
.await
|
||||
.processed(remote_addr, msg.size() as u32);
|
||||
}
|
||||
}
|
||||
// make 'request' to native-websocket client
|
||||
let response_message = ClientRequest::Send {
|
||||
recipient: return_address,
|
||||
message: Socks5Message::Response(response).into_bytes(),
|
||||
message: msg.into_bytes(),
|
||||
with_reply_surb: false,
|
||||
};
|
||||
|
||||
@@ -135,7 +130,7 @@ impl ServiceProvider {
|
||||
remote_addr: String,
|
||||
return_address: Recipient,
|
||||
controller_sender: ControllerSender,
|
||||
mix_input_sender: mpsc::UnboundedSender<(Response, Recipient)>,
|
||||
mix_input_sender: mpsc::UnboundedSender<(Socks5Message, Recipient)>,
|
||||
) {
|
||||
let mut conn = match Connection::new(conn_id, remote_addr.clone(), return_address).await {
|
||||
Ok(conn) => conn,
|
||||
@@ -148,7 +143,10 @@ impl ServiceProvider {
|
||||
|
||||
// inform the remote that the connection is closed before it even was established
|
||||
mix_input_sender
|
||||
.unbounded_send((Response::new(conn_id, Vec::new(), true), return_address))
|
||||
.unbounded_send((
|
||||
Socks5Message::Response(Response::new(conn_id, Vec::new(), true)),
|
||||
return_address,
|
||||
))
|
||||
.unwrap();
|
||||
|
||||
return;
|
||||
@@ -187,7 +185,7 @@ impl ServiceProvider {
|
||||
fn handle_proxy_connect(
|
||||
&mut self,
|
||||
controller_sender: &mut ControllerSender,
|
||||
mix_input_sender: &mpsc::UnboundedSender<(Response, Recipient)>,
|
||||
mix_input_sender: &mpsc::UnboundedSender<(Socks5Message, Recipient)>,
|
||||
conn_id: ConnectionId,
|
||||
remote_addr: String,
|
||||
return_address: Recipient,
|
||||
@@ -227,12 +225,10 @@ impl ServiceProvider {
|
||||
|
||||
async fn handle_proxy_message(
|
||||
&mut self,
|
||||
#[cfg(feature = "stats-service")] storage: &crate::storage::NetworkRequesterStorage,
|
||||
raw_request: &[u8],
|
||||
controller_sender: &mut ControllerSender,
|
||||
mix_input_sender: &mpsc::UnboundedSender<(Response, Recipient)>,
|
||||
request_stats_data: &Option<Arc<RwLock<StatsData>>>,
|
||||
connected_clients: &mut HashMap<ConnectionId, ClientIdentity>,
|
||||
mix_input_sender: &mpsc::UnboundedSender<(Socks5Message, Recipient)>,
|
||||
stats_collector: Option<StatisticsCollector>,
|
||||
) {
|
||||
let deserialized_msg = match Socks5Message::try_from_bytes(raw_request) {
|
||||
Ok(msg) => msg,
|
||||
@@ -244,8 +240,12 @@ impl ServiceProvider {
|
||||
match deserialized_msg {
|
||||
Socks5Message::Request(deserialized_request) => match deserialized_request {
|
||||
Request::Connect(req) => {
|
||||
if self.enable_statistics {
|
||||
connected_clients.insert(req.conn_id, *req.return_address.identity());
|
||||
if let Some(stats_collector) = stats_collector {
|
||||
stats_collector
|
||||
.connected_services
|
||||
.write()
|
||||
.await
|
||||
.insert(req.conn_id, req.remote_addr.clone());
|
||||
}
|
||||
self.handle_proxy_connect(
|
||||
controller_sender,
|
||||
@@ -257,29 +257,24 @@ impl ServiceProvider {
|
||||
}
|
||||
|
||||
Request::Send(conn_id, data, closed) => {
|
||||
if let Some(request_stats_data) = request_stats_data {
|
||||
if let Some(client_identity) = connected_clients.get(&conn_id) {
|
||||
request_stats_data
|
||||
if let Some(stats_collector) = stats_collector {
|
||||
if let Some(remote_addr) = stats_collector
|
||||
.connected_services
|
||||
.read()
|
||||
.await
|
||||
.get(&conn_id)
|
||||
{
|
||||
stats_collector
|
||||
.request_stats_data
|
||||
.write()
|
||||
.await
|
||||
.processed(client_identity, data.len() as u32);
|
||||
.processed(remote_addr, data.len() as u32);
|
||||
}
|
||||
}
|
||||
self.handle_proxy_send(controller_sender, conn_id, data, closed)
|
||||
}
|
||||
},
|
||||
Socks5Message::Response(_deserialized_response) =>
|
||||
{
|
||||
#[cfg(feature = "stats-service")]
|
||||
match crate::statistics::StatsMessage::from_bytes(&_deserialized_response.data) {
|
||||
Ok(data) => {
|
||||
if let Err(e) = storage.insert_service_statistics(data).await {
|
||||
error!("Could not store received statistics: {}", e);
|
||||
}
|
||||
}
|
||||
Err(e) => error!("Malformed statistics received: {}", e),
|
||||
}
|
||||
}
|
||||
Socks5Message::Response(_) => {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -292,7 +287,8 @@ impl ServiceProvider {
|
||||
|
||||
// channels responsible for managing messages that are to be sent to the mix network. The receiver is
|
||||
// going to be used by `mixnet_response_listener`
|
||||
let (mix_input_sender, mix_input_receiver) = mpsc::unbounded::<(Response, Recipient)>();
|
||||
let (mix_input_sender, mix_input_receiver) =
|
||||
mpsc::unbounded::<(Socks5Message, Recipient)>();
|
||||
|
||||
let (mut timer_sender, timer_receiver) = Timer::new();
|
||||
let interval = timer_sender.interval();
|
||||
@@ -306,53 +302,35 @@ impl ServiceProvider {
|
||||
active_connections_controller.run().await;
|
||||
});
|
||||
|
||||
let mut request_stats_data = None;
|
||||
let mut response_stats_data = None;
|
||||
let stats_collector = if self.enable_statistics {
|
||||
let mut stats_sender =
|
||||
StatisticsSender::new(interval, timer_receiver, self.stats_provider_addr)
|
||||
.await
|
||||
.expect("Statistics controller could not be bootstrapped");
|
||||
let stats_collector = StatisticsCollector::from(&stats_sender);
|
||||
|
||||
if self.enable_statistics {
|
||||
let mut stats = Statistics::new(self.description.clone(), interval, timer_receiver)
|
||||
.await
|
||||
.expect("Statistics controller could not be bootstrapped");
|
||||
request_stats_data = Some(Arc::clone(stats.request_data()));
|
||||
response_stats_data = Some(Arc::clone(stats.response_data()));
|
||||
let mix_input_sender_clone = mix_input_sender.clone();
|
||||
tokio::spawn(async move {
|
||||
stats.run(&mix_input_sender_clone).await;
|
||||
stats_sender.run(&mix_input_sender_clone).await;
|
||||
});
|
||||
}
|
||||
|
||||
#[cfg(feature = "stats-service")]
|
||||
let storage = crate::storage::NetworkRequesterStorage::init(self.db_path.as_path())
|
||||
.await
|
||||
.expect("Could not create network requester storage");
|
||||
|
||||
#[cfg(feature = "stats-service")]
|
||||
tokio::spawn(
|
||||
rocket::build()
|
||||
.mount(
|
||||
"/v1",
|
||||
rocket::routes![crate::storage::post_mixnet_statistics],
|
||||
)
|
||||
.manage(storage.clone())
|
||||
.ignite()
|
||||
.await
|
||||
.expect("Could not ignite stats api service")
|
||||
.launch(),
|
||||
);
|
||||
Some(stats_collector)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let stats_collector_clone = stats_collector.clone();
|
||||
// start the listener for mix messages
|
||||
tokio::spawn(async move {
|
||||
Self::mixnet_response_listener(
|
||||
websocket_writer,
|
||||
mix_input_receiver,
|
||||
&response_stats_data,
|
||||
stats_collector_clone,
|
||||
)
|
||||
.await;
|
||||
});
|
||||
|
||||
println!("\nAll systems go. Press CTRL-C to stop the server.");
|
||||
// for each incoming message from the websocket... (which in 99.99% cases is going to be a mix message)
|
||||
let mut connected_clients = HashMap::new();
|
||||
loop {
|
||||
let received = match Self::read_websocket_message(&mut websocket_reader).await {
|
||||
Some(msg) => msg,
|
||||
@@ -366,13 +344,10 @@ impl ServiceProvider {
|
||||
// TODO: here be potential SURB (i.e. received.reply_SURB)
|
||||
|
||||
self.handle_proxy_message(
|
||||
#[cfg(feature = "stats-service")]
|
||||
&storage,
|
||||
&raw_message,
|
||||
&mut controller_sender,
|
||||
&mix_input_sender,
|
||||
&request_stats_data,
|
||||
&mut connected_clients,
|
||||
stats_collector.clone(),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
|
||||
@@ -4,19 +4,18 @@
|
||||
use clap::{App, Arg, ArgMatches};
|
||||
|
||||
use network_defaults::DEFAULT_WEBSOCKET_LISTENING_PORT;
|
||||
use nymsphinx::addressing::clients::Recipient;
|
||||
|
||||
mod allowed_hosts;
|
||||
mod connection;
|
||||
mod core;
|
||||
mod statistics;
|
||||
#[cfg(feature = "stats-service")]
|
||||
mod storage;
|
||||
mod websocket;
|
||||
|
||||
const OPEN_PROXY_ARG: &str = "open-proxy";
|
||||
const WS_PORT: &str = "websocket-port";
|
||||
const DESCRIPTION: &str = "description";
|
||||
const ENABLE_STATISTICS: &str = "enable-statistics";
|
||||
const STATISTICS_RECIPIENT: &str = "statistics-recipient";
|
||||
|
||||
fn parse_args<'a>() -> ArgMatches<'a> {
|
||||
App::new("Nym Network Requester")
|
||||
@@ -37,15 +36,14 @@ fn parse_args<'a>() -> ArgMatches<'a> {
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name(ENABLE_STATISTICS)
|
||||
.help("enable mixnet statistics that get sent to a Nym server")
|
||||
.long(ENABLE_STATISTICS)
|
||||
.requires(DESCRIPTION),
|
||||
.help("enable service statistics that get sent to a statistics aggregator server")
|
||||
.long(ENABLE_STATISTICS),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name(DESCRIPTION)
|
||||
.help("service description")
|
||||
.long(DESCRIPTION)
|
||||
.short("d")
|
||||
Arg::with_name(STATISTICS_RECIPIENT)
|
||||
.help("mixnet client address where a statistics aggregator is running. The default value is a Nym aggregator client")
|
||||
.long(STATISTICS_RECIPIENT)
|
||||
.requires(ENABLE_STATISTICS)
|
||||
.takes_value(true),
|
||||
)
|
||||
.get_matches()
|
||||
@@ -63,9 +61,15 @@ async fn main() {
|
||||
|
||||
let enable_statistics = matches.is_present(ENABLE_STATISTICS);
|
||||
if enable_statistics {
|
||||
println!("\n\nTHE NETWORK REQUESTER STATISTICS ARE ENABLED. IT WILL COLLECT AND SEND STATISTICS TO A NYM SERVER. PLEASE QUIT IF YOU DON'T WANT THIS TO HAPPEN AND START WITHOUT THE {} FLAG .\n\n", ENABLE_STATISTICS);
|
||||
println!("\n\nTHE NETWORK REQUESTER STATISTICS ARE ENABLED. IT WILL COLLECT AND SEND ANONYMIZED STATISTICS TO A CENTRAL SERVER. PLEASE QUIT IF YOU DON'T WANT THIS TO HAPPEN AND START WITHOUT THE {} FLAG .\n\n", ENABLE_STATISTICS);
|
||||
}
|
||||
|
||||
let stats_provider_addr = matches
|
||||
.value_of(STATISTICS_RECIPIENT)
|
||||
.map(Recipient::try_from_base58_string)
|
||||
.transpose()
|
||||
.unwrap_or(None);
|
||||
|
||||
let uri = format!(
|
||||
"ws://localhost:{}",
|
||||
matches
|
||||
@@ -73,12 +77,9 @@ async fn main() {
|
||||
.unwrap_or(&DEFAULT_WEBSOCKET_LISTENING_PORT.to_string())
|
||||
);
|
||||
|
||||
let description = matches
|
||||
.value_of(DESCRIPTION)
|
||||
.unwrap_or("undefined")
|
||||
.to_string();
|
||||
println!("Starting socks5 service provider:");
|
||||
let mut server = core::ServiceProvider::new(uri, description, open_proxy, enable_statistics);
|
||||
let mut server =
|
||||
core::ServiceProvider::new(uri, open_proxy, enable_statistics, stats_provider_addr);
|
||||
server.run().await;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
use futures::channel::mpsc;
|
||||
use futures::StreamExt;
|
||||
use log::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use rand::RngCore;
|
||||
use serde::Deserialize;
|
||||
use sqlx::types::chrono::{DateTime, Utc};
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::sync::Arc;
|
||||
@@ -12,50 +13,20 @@ use std::time::Duration;
|
||||
use tokio::sync::RwLock;
|
||||
|
||||
use network_defaults::DEFAULT_NETWORK;
|
||||
use nymsphinx::addressing::clients::{ClientIdentity, Recipient};
|
||||
use socks5_requests::Response;
|
||||
use nymsphinx::addressing::clients::Recipient;
|
||||
use ordered_buffer::OrderedMessageSender;
|
||||
use socks5_requests::{ConnectionId, Message as Socks5Message, RemoteAddress, Request};
|
||||
use statistics::api::{
|
||||
build_statistics_request_bytes, DEFAULT_STATISTICS_SERVICE_ADDRESS,
|
||||
DEFAULT_STATISTICS_SERVICE_PORT,
|
||||
};
|
||||
use statistics::{StatsMessage, StatsServiceData};
|
||||
|
||||
use super::error::StatsError;
|
||||
|
||||
const REMOTE_SOURCE_OF_STATS_PROVIDER_CONFIG: &str =
|
||||
"https://nymtech.net/.wellknown/network-requester/stats-provider.json";
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub struct StatsMessage {
|
||||
pub description: String,
|
||||
pub stats_data: Vec<StatsClientData>,
|
||||
pub interval_seconds: u32,
|
||||
pub timestamp: String,
|
||||
}
|
||||
|
||||
impl StatsMessage {
|
||||
pub fn to_bytes(&self) -> Result<Vec<u8>, StatsError> {
|
||||
Ok(bincode::serialize(self)?)
|
||||
}
|
||||
|
||||
#[cfg(feature = "stats-service")]
|
||||
pub fn from_bytes(b: &[u8]) -> Result<Self, StatsError> {
|
||||
Ok(bincode::deserialize(b)?)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub struct StatsClientData {
|
||||
pub client_identity: String,
|
||||
pub request_bytes: u32,
|
||||
pub response_bytes: u32,
|
||||
}
|
||||
|
||||
impl StatsClientData {
|
||||
pub fn new(client_identity: String, request_bytes: u32, response_bytes: u32) -> Self {
|
||||
StatsClientData {
|
||||
client_identity,
|
||||
request_bytes,
|
||||
response_bytes,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct StatsData {
|
||||
client_processed_bytes: HashMap<String, u32>,
|
||||
@@ -68,13 +39,12 @@ impl StatsData {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn processed(&mut self, client_identity: &ClientIdentity, bytes: u32) {
|
||||
let client_identity_bs58 = client_identity.to_base58_string();
|
||||
if let Some(curr_bytes) = self.client_processed_bytes.get_mut(&client_identity_bs58) {
|
||||
pub fn processed(&mut self, remote_addr: &str, bytes: u32) {
|
||||
if let Some(curr_bytes) = self.client_processed_bytes.get_mut(remote_addr) {
|
||||
*curr_bytes += bytes;
|
||||
} else {
|
||||
self.client_processed_bytes
|
||||
.insert(client_identity_bs58, bytes);
|
||||
.insert(remote_addr.to_string(), bytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -103,8 +73,24 @@ impl OptionalStatsProviderConfig {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Statistics {
|
||||
description: String,
|
||||
#[derive(Clone)]
|
||||
pub struct StatisticsCollector {
|
||||
pub(crate) request_stats_data: Arc<RwLock<StatsData>>,
|
||||
pub(crate) response_stats_data: Arc<RwLock<StatsData>>,
|
||||
pub(crate) connected_services: Arc<RwLock<HashMap<ConnectionId, RemoteAddress>>>,
|
||||
}
|
||||
|
||||
impl StatisticsCollector {
|
||||
pub fn from(stats: &StatisticsSender) -> Self {
|
||||
Self {
|
||||
request_stats_data: Arc::clone(&stats.request_data),
|
||||
response_stats_data: Arc::clone(&stats.response_data),
|
||||
connected_services: Arc::new(RwLock::new(HashMap::new())),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct StatisticsSender {
|
||||
request_data: Arc<RwLock<StatsData>>,
|
||||
response_data: Arc<RwLock<StatsData>>,
|
||||
interval_seconds: u32,
|
||||
@@ -113,11 +99,11 @@ pub struct Statistics {
|
||||
stats_provider_addr: Recipient,
|
||||
}
|
||||
|
||||
impl Statistics {
|
||||
impl StatisticsSender {
|
||||
pub async fn new(
|
||||
description: String,
|
||||
interval_seconds: Duration,
|
||||
timer_receiver: mpsc::Receiver<()>,
|
||||
stats_provider_addr: Option<Recipient>,
|
||||
) -> Result<Self, StatsError> {
|
||||
let client = reqwest::Client::builder()
|
||||
.timeout(Duration::from_secs(3))
|
||||
@@ -128,15 +114,16 @@ impl Statistics {
|
||||
.await?
|
||||
.json()
|
||||
.await?;
|
||||
let stats_provider_addr = Recipient::try_from_base58_string(
|
||||
stats_provider_config
|
||||
.stats_client_address()
|
||||
.ok_or(StatsError::InvalidClientAddress)?,
|
||||
)
|
||||
.map_err(|_| StatsError::InvalidClientAddress)?;
|
||||
let stats_provider_addr = stats_provider_addr.unwrap_or(
|
||||
Recipient::try_from_base58_string(
|
||||
stats_provider_config
|
||||
.stats_client_address()
|
||||
.ok_or(StatsError::InvalidClientAddress)?,
|
||||
)
|
||||
.map_err(|_| StatsError::InvalidClientAddress)?,
|
||||
);
|
||||
|
||||
Ok(Statistics {
|
||||
description,
|
||||
Ok(StatisticsSender {
|
||||
request_data: Arc::new(RwLock::new(StatsData::new())),
|
||||
response_data: Arc::new(RwLock::new(StatsData::new())),
|
||||
timestamp: Utc::now(),
|
||||
@@ -146,15 +133,10 @@ impl Statistics {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn request_data(&self) -> &Arc<RwLock<StatsData>> {
|
||||
&self.request_data
|
||||
}
|
||||
|
||||
pub fn response_data(&self) -> &Arc<RwLock<StatsData>> {
|
||||
&self.response_data
|
||||
}
|
||||
|
||||
pub async fn run(&mut self, mix_input_sender: &mpsc::UnboundedSender<(Response, Recipient)>) {
|
||||
pub async fn run(
|
||||
&mut self,
|
||||
mix_input_sender: &mpsc::UnboundedSender<(Socks5Message, Recipient)>,
|
||||
) {
|
||||
loop {
|
||||
if self.timer_receiver.next().await == None {
|
||||
error!("Timer thread has died. No more statistics will be sent");
|
||||
@@ -162,42 +144,62 @@ impl Statistics {
|
||||
let stats_data = {
|
||||
let request_data_bytes = self.request_data.read().await;
|
||||
let response_data_bytes = self.response_data.read().await;
|
||||
let clients: HashSet<String> = request_data_bytes
|
||||
let services: HashSet<String> = request_data_bytes
|
||||
.client_processed_bytes
|
||||
.keys()
|
||||
.chain(response_data_bytes.client_processed_bytes.keys())
|
||||
.cloned()
|
||||
.collect();
|
||||
clients
|
||||
services
|
||||
.into_iter()
|
||||
.map(|client_identity| {
|
||||
.map(|requested_service| {
|
||||
let request_bytes = request_data_bytes
|
||||
.client_processed_bytes
|
||||
.get(&client_identity)
|
||||
.get(&requested_service)
|
||||
.copied()
|
||||
.unwrap_or(0);
|
||||
let response_bytes = response_data_bytes
|
||||
.client_processed_bytes
|
||||
.get(&client_identity)
|
||||
.get(&requested_service)
|
||||
.copied()
|
||||
.unwrap_or(0);
|
||||
StatsClientData::new(client_identity, request_bytes, response_bytes)
|
||||
StatsServiceData::new(requested_service, request_bytes, response_bytes)
|
||||
})
|
||||
.collect()
|
||||
};
|
||||
|
||||
let stats_message = StatsMessage {
|
||||
description: self.description.clone(),
|
||||
stats_data,
|
||||
interval_seconds: self.interval_seconds,
|
||||
timestamp: self.timestamp.to_rfc3339(),
|
||||
};
|
||||
match stats_message.to_bytes() {
|
||||
match build_statistics_request_bytes(stats_message) {
|
||||
Ok(data) => {
|
||||
trace!("Sending data to statistics service");
|
||||
trace!("Connecting to statistics service");
|
||||
let mut rng = rand::rngs::OsRng;
|
||||
let conn_id = rng.next_u64();
|
||||
let connect_req = Request::new_connect(
|
||||
conn_id,
|
||||
format!(
|
||||
"{}:{}",
|
||||
DEFAULT_STATISTICS_SERVICE_ADDRESS, DEFAULT_STATISTICS_SERVICE_PORT
|
||||
),
|
||||
self.stats_provider_addr,
|
||||
);
|
||||
mix_input_sender
|
||||
.unbounded_send((
|
||||
Response::new(0, data, false),
|
||||
Socks5Message::Request(connect_req),
|
||||
self.stats_provider_addr,
|
||||
))
|
||||
.unwrap();
|
||||
|
||||
trace!("Sending data to statistics service");
|
||||
let mut message_sender = OrderedMessageSender::new();
|
||||
let ordered_msg = message_sender.wrap_message(data).into_bytes();
|
||||
let send_req = Request::new_send(conn_id, ordered_msg, true);
|
||||
mix_input_sender
|
||||
.unbounded_send((
|
||||
Socks5Message::Request(send_req),
|
||||
self.stats_provider_addr,
|
||||
))
|
||||
.unwrap();
|
||||
|
||||
@@ -5,9 +5,6 @@ use thiserror::Error;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum StatsError {
|
||||
#[error("Bincode error: {0}")]
|
||||
BincodeError(#[from] bincode::Error),
|
||||
|
||||
#[error("Reqwuest error {0}")]
|
||||
ReqwestError(#[from] reqwest::Error),
|
||||
|
||||
|
||||
@@ -5,5 +5,5 @@ mod comm;
|
||||
mod error;
|
||||
mod timer;
|
||||
|
||||
pub use comm::{Statistics, StatsClientData, StatsData, StatsMessage};
|
||||
pub use comm::{StatisticsCollector, StatisticsSender, StatsData};
|
||||
pub use timer::Timer;
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use rocket::serde::json::Json;
|
||||
use rocket::State;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::storage::NetworkRequesterStorage;
|
||||
|
||||
#[derive(Clone, Serialize, Deserialize, Debug)]
|
||||
pub struct MixnetStatisticsRequest {
|
||||
// date, RFC 3339 format
|
||||
since: String,
|
||||
// date, RFC 3339 format
|
||||
until: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Serialize, Deserialize, Debug)]
|
||||
pub struct MixnetStatisticsResponse {
|
||||
pub service_description: String,
|
||||
pub client_identity: String,
|
||||
pub request_processed_bytes: u32,
|
||||
pub response_processed_bytes: u32,
|
||||
pub interval_seconds: u32,
|
||||
pub timestamp: String,
|
||||
}
|
||||
|
||||
#[rocket::post("/mixnet-statistics", data = "<mixnet_statistics_request>")]
|
||||
pub(crate) async fn post_mixnet_statistics(
|
||||
mixnet_statistics_request: Json<MixnetStatisticsRequest>,
|
||||
storage: &State<NetworkRequesterStorage>,
|
||||
) -> Json<Vec<MixnetStatisticsResponse>> {
|
||||
let mixnet_statistics = storage
|
||||
.get_service_statistics_in_interval(
|
||||
&mixnet_statistics_request.since,
|
||||
&mixnet_statistics_request.until,
|
||||
)
|
||||
.await
|
||||
.unwrap()
|
||||
.into_iter()
|
||||
.map(|data| MixnetStatisticsResponse {
|
||||
service_description: data.service_description,
|
||||
client_identity: data.client_identity,
|
||||
request_processed_bytes: data.request_processed_bytes as u32,
|
||||
response_processed_bytes: data.response_processed_bytes as u32,
|
||||
interval_seconds: data.interval_seconds as u32,
|
||||
timestamp: data.timestamp.to_string(),
|
||||
})
|
||||
.collect();
|
||||
|
||||
Json(mixnet_statistics)
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
[package]
|
||||
name = "nym-network-statistics"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
dirs = "3.0"
|
||||
log = "0.4"
|
||||
pretty_env_logger = "0.4"
|
||||
rocket = { version = "0.5.0-rc.1", features = ["json"] }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
sqlx = { version = "0.5", features = ["runtime-tokio-rustls", "sqlite", "macros", "migrate", "chrono"]}
|
||||
thiserror = "1"
|
||||
tokio = { version = "1.4", features = [ "net", "rt-multi-thread", "macros", "time" ] }
|
||||
tokio-tungstenite = "0.14"
|
||||
|
||||
statistics = { path = "../../common/statistics" }
|
||||
|
||||
[build-dependencies]
|
||||
sqlx = { version = "0.5", features = ["runtime-tokio-rustls", "sqlite", "macros", "migrate"] }
|
||||
tokio = { version = "1.4", features = ["rt-multi-thread", "macros"] }
|
||||
@@ -0,0 +1,7 @@
|
||||
[default]
|
||||
limits = { forms = "64 kB", json = "1 MiB" }
|
||||
port = 8090
|
||||
address = "127.0.0.1"
|
||||
|
||||
[release]
|
||||
address = "0.0.0.0"
|
||||
+1
-1
@@ -7,7 +7,7 @@ use std::env;
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
let out_dir = env::var("OUT_DIR").unwrap();
|
||||
let database_path = format!("{}/network-requester-example.sqlite", out_dir);
|
||||
let database_path = format!("{}/network-statistics-example.sqlite", out_dir);
|
||||
|
||||
let mut conn = SqliteConnection::connect(&*format!("sqlite://{}?mode=rwc", database_path))
|
||||
.await
|
||||
+2
-3
@@ -3,11 +3,10 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
CREATE TABLE mixnet_statistics
|
||||
CREATE TABLE service_statistics
|
||||
(
|
||||
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||
service_description VARCHAR NOT NULL,
|
||||
client_identity VARCHAR NOT NULL,
|
||||
requested_service VARCHAR NOT NULL,
|
||||
request_processed_bytes INTEGER NOT NULL,
|
||||
response_processed_bytes INTEGER NOT NULL,
|
||||
interval_seconds INTEGER NOT NULL,
|
||||
@@ -0,0 +1,31 @@
|
||||
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use rocket::http::{ContentType, Status};
|
||||
use rocket::response::Responder;
|
||||
use rocket::{response, Request, Response};
|
||||
use std::io::Cursor;
|
||||
|
||||
use crate::storage::error::NetworkStatisticsStorageError;
|
||||
|
||||
pub type Result<T> = std::result::Result<T, NetworkStatisticsAPIError>;
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum NetworkStatisticsAPIError {
|
||||
#[error("{0}")]
|
||||
RocketError(#[from] Box<rocket::Error>),
|
||||
|
||||
#[error("{0}")]
|
||||
StorageError(#[from] NetworkStatisticsStorageError),
|
||||
}
|
||||
|
||||
impl<'r, 'o: 'r> Responder<'r, 'o> for NetworkStatisticsAPIError {
|
||||
fn respond_to(self, _: &'r Request<'_>) -> response::Result<'o> {
|
||||
let err_msg = self.to_string();
|
||||
Response::build()
|
||||
.header(ContentType::Plain)
|
||||
.sized_body(err_msg.len(), Cursor::new(err_msg))
|
||||
.status(Status::BadRequest)
|
||||
.ok()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use log::*;
|
||||
use rocket::{Ignite, Rocket};
|
||||
|
||||
use crate::storage::NetworkStatisticsStorage;
|
||||
use error::Result;
|
||||
use routes::{post_all_statistics, post_statistic};
|
||||
|
||||
use statistics::api::STATISTICS_SERVICE_VERSION;
|
||||
|
||||
mod error;
|
||||
mod routes;
|
||||
|
||||
pub(crate) struct NetworkStatisticsAPI {
|
||||
rocket: Rocket<Ignite>,
|
||||
}
|
||||
|
||||
impl NetworkStatisticsAPI {
|
||||
pub async fn init(storage: NetworkStatisticsStorage) -> Result<Self> {
|
||||
let rocket = rocket::build()
|
||||
.mount(
|
||||
STATISTICS_SERVICE_VERSION,
|
||||
rocket::routes![post_all_statistics, post_statistic],
|
||||
)
|
||||
.manage(storage.clone())
|
||||
.ignite()
|
||||
.await
|
||||
.map_err(Box::new)?;
|
||||
|
||||
Ok(NetworkStatisticsAPI { rocket })
|
||||
}
|
||||
|
||||
pub async fn run(self) {
|
||||
let shutdown_handle = self.rocket.shutdown();
|
||||
tokio::spawn(self.rocket.launch());
|
||||
|
||||
if let Err(e) = tokio::signal::ctrl_c().await {
|
||||
error!(
|
||||
"There was an error while capturing SIGINT - {:?}. We will terminate regardless",
|
||||
e
|
||||
);
|
||||
}
|
||||
info!("Received SIGINT - the network statistics API will terminate now");
|
||||
shutdown_handle.notify();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use rocket::serde::json::Json;
|
||||
use rocket::State;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use statistics::StatsMessage;
|
||||
|
||||
use crate::api::error::Result;
|
||||
use crate::storage::NetworkStatisticsStorage;
|
||||
|
||||
#[derive(Clone, Serialize, Deserialize, Debug)]
|
||||
pub struct ServiceStatisticsRequest {
|
||||
// date, RFC 3339 format
|
||||
since: String,
|
||||
// date, RFC 3339 format
|
||||
until: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Serialize, Deserialize, Debug)]
|
||||
pub struct ServiceStatistic {
|
||||
pub requested_service: String,
|
||||
pub request_processed_bytes: u32,
|
||||
pub response_processed_bytes: u32,
|
||||
pub interval_seconds: u32,
|
||||
pub timestamp: String,
|
||||
}
|
||||
|
||||
#[rocket::post("/all-statistics", data = "<all_statistics_request>")]
|
||||
pub(crate) async fn post_all_statistics(
|
||||
all_statistics_request: Json<ServiceStatisticsRequest>,
|
||||
storage: &State<NetworkStatisticsStorage>,
|
||||
) -> Result<Json<Vec<ServiceStatistic>>> {
|
||||
let service_statistics = storage
|
||||
.get_service_statistics_in_interval(
|
||||
&all_statistics_request.since,
|
||||
&all_statistics_request.until,
|
||||
)
|
||||
.await?
|
||||
.into_iter()
|
||||
.map(|data| ServiceStatistic {
|
||||
requested_service: data.requested_service,
|
||||
request_processed_bytes: data.request_processed_bytes as u32,
|
||||
response_processed_bytes: data.response_processed_bytes as u32,
|
||||
interval_seconds: data.interval_seconds as u32,
|
||||
timestamp: data.timestamp.to_string(),
|
||||
})
|
||||
.collect();
|
||||
|
||||
Ok(Json(service_statistics))
|
||||
}
|
||||
|
||||
#[rocket::post("/statistic", data = "<statistic>")]
|
||||
pub(crate) async fn post_statistic(
|
||||
statistic: Json<StatsMessage>,
|
||||
storage: &State<NetworkStatisticsStorage>,
|
||||
) -> Result<Json<()>> {
|
||||
storage.insert_service_statistics(statistic.0).await?;
|
||||
Ok(Json(()))
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
use api::NetworkStatisticsAPI;
|
||||
|
||||
mod api;
|
||||
mod storage;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
setup_logging();
|
||||
|
||||
let base_dir = default_base_dir();
|
||||
let storage = storage::NetworkStatisticsStorage::init(&base_dir)
|
||||
.await
|
||||
.expect("Could not create network statistics storage");
|
||||
|
||||
let api = NetworkStatisticsAPI::init(storage)
|
||||
.await
|
||||
.expect("Could not ignite stats api service");
|
||||
api.run().await;
|
||||
}
|
||||
|
||||
fn setup_logging() {
|
||||
let mut log_builder = pretty_env_logger::formatted_timed_builder();
|
||||
if let Ok(s) = ::std::env::var("RUST_LOG") {
|
||||
log_builder.parse_filters(&s);
|
||||
} else {
|
||||
// default to 'Info'
|
||||
log_builder.filter(None, log::LevelFilter::Info);
|
||||
}
|
||||
|
||||
log_builder
|
||||
.filter_module("hyper", log::LevelFilter::Warn)
|
||||
.filter_module("tokio_reactor", log::LevelFilter::Warn)
|
||||
.filter_module("reqwest", log::LevelFilter::Warn)
|
||||
.filter_module("mio", log::LevelFilter::Warn)
|
||||
.filter_module("want", log::LevelFilter::Warn)
|
||||
.init();
|
||||
}
|
||||
|
||||
/// Returns the default base directory for the storefile.
|
||||
///
|
||||
/// This is split out so we can easily inject our own base_dir for unit tests.
|
||||
fn default_base_dir() -> PathBuf {
|
||||
dirs::home_dir()
|
||||
.expect("no home directory known for this OS")
|
||||
.join(".nym")
|
||||
.join("service-providers")
|
||||
.join("network-statistics")
|
||||
}
|
||||
+4
-1
@@ -2,7 +2,10 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum NetworkRequesterStorageError {
|
||||
pub enum NetworkStatisticsStorageError {
|
||||
#[error("File system error - {0}")]
|
||||
FSError(#[from] std::io::Error),
|
||||
|
||||
#[error("SQL error - {0}")]
|
||||
InternalDatabaseError(#[from] sqlx::Error),
|
||||
|
||||
+8
-11
@@ -3,7 +3,7 @@
|
||||
|
||||
use sqlx::types::chrono::{DateTime, Utc};
|
||||
|
||||
use crate::storage::models::MixnetStatistics;
|
||||
use crate::storage::models::ServiceStatistics;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct StorageManager {
|
||||
@@ -16,24 +16,21 @@ impl StorageManager {
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `service_description`: Description of the service that gathered the data.
|
||||
/// * `client_identity`: Client that connected to the service.
|
||||
/// * `requested_service`: Address of the service requested.
|
||||
/// * `request_processed_bytes`: Number of bytes for socks5 requests.
|
||||
/// * `response_processed_bytes`: Number of bytes for socks5 responses.
|
||||
/// * `interval_seconds`: Duration in seconds in which the data was gathered.
|
||||
pub(super) async fn insert_service_statistics(
|
||||
&self,
|
||||
service_description: String,
|
||||
client_identity: String,
|
||||
requested_service: String,
|
||||
request_processed_bytes: u32,
|
||||
response_processed_bytes: u32,
|
||||
interval_seconds: u32,
|
||||
timestamp: DateTime<Utc>,
|
||||
) -> Result<(), sqlx::Error> {
|
||||
sqlx::query!(
|
||||
"INSERT INTO mixnet_statistics(service_description, client_identity, request_processed_bytes, response_processed_bytes, interval_seconds, timestamp) VALUES (?, ?, ?, ?, ?, ?)",
|
||||
service_description,
|
||||
client_identity,
|
||||
"INSERT INTO service_statistics(requested_service, request_processed_bytes, response_processed_bytes, interval_seconds, timestamp) VALUES (?, ?, ?, ?, ?)",
|
||||
requested_service,
|
||||
request_processed_bytes,
|
||||
response_processed_bytes,
|
||||
interval_seconds,
|
||||
@@ -55,10 +52,10 @@ impl StorageManager {
|
||||
&self,
|
||||
since: DateTime<Utc>,
|
||||
until: DateTime<Utc>,
|
||||
) -> Result<Vec<MixnetStatistics>, sqlx::Error> {
|
||||
) -> Result<Vec<ServiceStatistics>, sqlx::Error> {
|
||||
sqlx::query_as!(
|
||||
MixnetStatistics,
|
||||
"SELECT * FROM mixnet_statistics WHERE timestamp BETWEEN ? AND ?",
|
||||
ServiceStatistics,
|
||||
"SELECT * FROM service_statistics WHERE timestamp BETWEEN ? AND ?",
|
||||
since,
|
||||
until
|
||||
)
|
||||
+21
-21
@@ -4,27 +4,28 @@
|
||||
use log::*;
|
||||
use sqlx::types::chrono::{DateTime, Utc};
|
||||
use sqlx::ConnectOptions;
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use crate::statistics::StatsMessage;
|
||||
use crate::storage::error::NetworkRequesterStorageError;
|
||||
use statistics::StatsMessage;
|
||||
|
||||
use crate::storage::error::NetworkStatisticsStorageError;
|
||||
use crate::storage::manager::StorageManager;
|
||||
use crate::storage::models::MixnetStatistics;
|
||||
pub(crate) use crate::storage::routes::post_mixnet_statistics;
|
||||
use crate::storage::models::ServiceStatistics;
|
||||
|
||||
mod error;
|
||||
pub(crate) mod error;
|
||||
mod manager;
|
||||
mod models;
|
||||
mod routes;
|
||||
|
||||
// note that clone here is fine as upon cloning the same underlying pool will be used
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct NetworkRequesterStorage {
|
||||
pub(crate) struct NetworkStatisticsStorage {
|
||||
manager: StorageManager,
|
||||
}
|
||||
|
||||
impl NetworkRequesterStorage {
|
||||
pub async fn init(database_path: &Path) -> Result<Self, NetworkRequesterStorageError> {
|
||||
impl NetworkStatisticsStorage {
|
||||
pub async fn init(base_dir: &PathBuf) -> Result<Self, NetworkStatisticsStorageError> {
|
||||
std::fs::create_dir_all(base_dir)?;
|
||||
let database_path = base_dir.join("db.sqlite");
|
||||
let mut opts = sqlx::sqlite::SqliteConnectOptions::new()
|
||||
.filename(database_path)
|
||||
.create_if_missing(true);
|
||||
@@ -36,7 +37,7 @@ impl NetworkRequesterStorage {
|
||||
sqlx::migrate!("./migrations").run(&connection_pool).await?;
|
||||
info!("Database migration finished!");
|
||||
|
||||
let storage = NetworkRequesterStorage {
|
||||
let storage = NetworkStatisticsStorage {
|
||||
manager: StorageManager { connection_pool },
|
||||
};
|
||||
|
||||
@@ -51,17 +52,16 @@ impl NetworkRequesterStorage {
|
||||
pub(super) async fn insert_service_statistics(
|
||||
&self,
|
||||
msg: StatsMessage,
|
||||
) -> Result<(), NetworkRequesterStorageError> {
|
||||
) -> Result<(), NetworkStatisticsStorageError> {
|
||||
let timestamp: DateTime<Utc> = DateTime::parse_from_rfc3339(&msg.timestamp)
|
||||
.map_err(|_| NetworkRequesterStorageError::TimestampParse)?
|
||||
.map_err(|_| NetworkStatisticsStorageError::TimestampParse)?
|
||||
.into();
|
||||
for client_data in msg.stats_data {
|
||||
for service_data in msg.stats_data {
|
||||
self.manager
|
||||
.insert_service_statistics(
|
||||
msg.description.clone(),
|
||||
client_data.client_identity.clone(),
|
||||
client_data.request_bytes,
|
||||
client_data.response_bytes,
|
||||
service_data.requested_service.clone(),
|
||||
service_data.request_bytes,
|
||||
service_data.response_bytes,
|
||||
msg.interval_seconds,
|
||||
timestamp,
|
||||
)
|
||||
@@ -81,12 +81,12 @@ impl NetworkRequesterStorage {
|
||||
&self,
|
||||
since: &str,
|
||||
until: &str,
|
||||
) -> Result<Vec<MixnetStatistics>, NetworkRequesterStorageError> {
|
||||
) -> Result<Vec<ServiceStatistics>, NetworkStatisticsStorageError> {
|
||||
let since = DateTime::parse_from_rfc3339(since)
|
||||
.map_err(|_| NetworkRequesterStorageError::TimestampParse)?
|
||||
.map_err(|_| NetworkStatisticsStorageError::TimestampParse)?
|
||||
.into();
|
||||
let until = DateTime::parse_from_rfc3339(until)
|
||||
.map_err(|_| NetworkRequesterStorageError::TimestampParse)?
|
||||
.map_err(|_| NetworkStatisticsStorageError::TimestampParse)?
|
||||
.into();
|
||||
Ok(self
|
||||
.manager
|
||||
+2
-3
@@ -4,11 +4,10 @@
|
||||
use sqlx::types::chrono::NaiveDateTime;
|
||||
|
||||
// Internally used struct to catch results from the database to get mixnet statistics
|
||||
pub(crate) struct MixnetStatistics {
|
||||
pub(crate) struct ServiceStatistics {
|
||||
#[allow(dead_code)]
|
||||
pub(crate) id: i64,
|
||||
pub(crate) service_description: String,
|
||||
pub(crate) client_identity: String,
|
||||
pub(crate) requested_service: String,
|
||||
pub(crate) request_processed_bytes: i64,
|
||||
pub(crate) response_processed_bytes: i64,
|
||||
pub(crate) interval_seconds: i64,
|
||||
@@ -33,8 +33,8 @@ serde = "1.0"
|
||||
serde_json = "1.0"
|
||||
thiserror = "1"
|
||||
time = { version = "0.3", features = ["serde-human-readable", "parsing"]}
|
||||
tokio = { version = "1.4", features = ["rt-multi-thread", "macros", "signal", "time"] }
|
||||
tokio-stream = "0.1.8"
|
||||
tokio = { version = "1.19.1", features = ["rt-multi-thread", "macros", "signal", "time"] }
|
||||
tokio-stream = "0.1.9"
|
||||
url = "2.2"
|
||||
|
||||
ts-rs = "6.1.2"
|
||||
@@ -52,7 +52,7 @@ schemars = { version = "0.8", features = ["preserve_order"] }
|
||||
## internal
|
||||
coconut-bandwidth-contract-common = { path = "../common/cosmwasm-smart-contracts/coconut-bandwidth-contract" }
|
||||
config = { path = "../common/config" }
|
||||
cosmwasm-std = "1.0.0-beta8"
|
||||
cosmwasm-std = "1.0.0"
|
||||
crypto = { path="../common/crypto" }
|
||||
gateway-client = { path="../common/client-libs/gateway-client" }
|
||||
mixnet-contract-common = { path= "../common/cosmwasm-smart-contracts/mixnet-contract" }
|
||||
@@ -75,7 +75,7 @@ no-reward = []
|
||||
generate-ts = []
|
||||
|
||||
[build-dependencies]
|
||||
tokio = { version = "1.4", features = ["rt-multi-thread", "macros"] }
|
||||
tokio = { version = "1.19.1", features = ["rt-multi-thread", "macros"] }
|
||||
sqlx = { version = "0.5", features = ["runtime-tokio-rustls", "sqlite", "macros", "migrate"] }
|
||||
vergen = { version = "5", default-features = false, features = ["build", "git", "rustc", "cargo"] }
|
||||
|
||||
|
||||
@@ -211,6 +211,7 @@ pub(crate) async fn get_mixnode_inclusion_probability(
|
||||
identity: String,
|
||||
) -> Json<Option<InclusionProbabilityResponse>> {
|
||||
let mixnodes = cache.mixnodes().await;
|
||||
let rewarding_params = cache.epoch_reward_params().await.into_inner();
|
||||
|
||||
if let Some(target_mixnode) = mixnodes.iter().find(|x| x.identity() == &identity) {
|
||||
let total_bonded_tokens = mixnodes
|
||||
@@ -218,17 +219,23 @@ pub(crate) async fn get_mixnode_inclusion_probability(
|
||||
.fold(0u128, |acc, x| acc + x.total_bond().unwrap_or_default())
|
||||
as f64;
|
||||
|
||||
let rewarding_params = cache.epoch_reward_params().await.into_inner();
|
||||
let rewarded_set_size = rewarding_params.rewarded_set_size() as f64;
|
||||
let active_set_size = rewarding_params.active_set_size() as f64;
|
||||
|
||||
let prob_one_draw =
|
||||
target_mixnode.total_bond().unwrap_or_default() as f64 / total_bonded_tokens;
|
||||
// Chance to be selected in any draw for active set
|
||||
let prob_active_set = active_set_size * prob_one_draw;
|
||||
let prob_active_set = if mixnodes.len() <= active_set_size as usize {
|
||||
1.0
|
||||
} else {
|
||||
active_set_size * prob_one_draw
|
||||
};
|
||||
// This is likely slightly too high, as we're not correcting form them not being selected in active, should be chance to be selected, minus the chance for being not selected in reserve
|
||||
let prob_reserve_set = (rewarded_set_size - active_set_size) * prob_one_draw;
|
||||
// (rewarded_set_size - active_set_size) * prob_one_draw * (1. - prob_active_set);
|
||||
let prob_reserve_set = if mixnodes.len() <= rewarded_set_size as usize {
|
||||
1.0
|
||||
} else {
|
||||
(rewarded_set_size - active_set_size) * prob_one_draw
|
||||
};
|
||||
|
||||
Json(Some(InclusionProbabilityResponse {
|
||||
in_active: prob_active_set.into(),
|
||||
|
||||
Reference in New Issue
Block a user