Compare commits
89 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7f840b889f | |||
| 5cd67b22b3 | |||
| 25c6748ae9 | |||
| 78d2ffa923 | |||
| ecdbe034fa | |||
| 3e46c8630d | |||
| 93e962524a | |||
| 5b6c1c032c | |||
| 135f1a6e7f | |||
| c61f89144e | |||
| 67fe368e65 | |||
| 522229459b | |||
| e3d8b71ea2 | |||
| 4f98fde362 | |||
| aa75e54419 | |||
| 5190a541a6 | |||
| 3a39fff006 | |||
| 0e302b83ab | |||
| 0d0637fe19 | |||
| 1f0c0090dc | |||
| 4f960330b1 | |||
| a273980aa0 | |||
| 13a55f00d8 | |||
| 4feec780d4 | |||
| 35c044c340 | |||
| ac5539a0fa | |||
| 9c569cbb62 | |||
| 72485cacd3 | |||
| 56d36d2c46 | |||
| 8fb54dd4e7 | |||
| 44d59ff8c2 | |||
| a8caf19f8c | |||
| 53b44fb9c6 | |||
| c0959e853e | |||
| 144df00782 | |||
| be4708cc84 | |||
| d5cddec03c | |||
| 7c26cab4e6 | |||
| f0bcf8c36f | |||
| ac2f0a172e | |||
| 898070bc87 | |||
| cc707660aa | |||
| 31624cf4e4 | |||
| e6a69170a4 | |||
| bc5e19514e | |||
| 5c76b8483e | |||
| a9526c216f | |||
| 903af16a6b | |||
| 0de79b6953 | |||
| fd2fafb52a | |||
| fadb5b4ff9 | |||
| 955583d0f0 | |||
| 3924c53d09 | |||
| c0025ee9c6 | |||
| 7dd0516b63 | |||
| d3cd3c9157 | |||
| 83680473e0 | |||
| 7f9a9f7a0a | |||
| e7ccb38502 | |||
| 1f4c19d396 | |||
| 64842f40d7 | |||
| 2ec18721fc | |||
| 2ef1ac452f | |||
| 6b3700aefe | |||
| e2e06df4e6 | |||
| 835d4f46f6 | |||
| d71ef635e2 | |||
| 6e3773a095 | |||
| 050d370396 | |||
| 29340ed00c | |||
| 2b062b3e5b | |||
| b405adb9e5 | |||
| 5c3c0ac39e | |||
| 1cc06ef349 | |||
| 2bef1603ab | |||
| 11a458a43d | |||
| 1fbf37e0ec | |||
| bc8efda08f | |||
| cecd0b2b0a | |||
| 62fa2ae5e4 | |||
| db2ce8070c | |||
| 70138ff54a | |||
| 30e93c33bb | |||
| ec4955f814 | |||
| e013517348 | |||
| 2041b03046 | |||
| 0b6adf59ce | |||
| d95df4b286 | |||
| 4f109169af |
@@ -1,3 +1,3 @@
|
||||
unreleased=true
|
||||
future-release=v0.12.1
|
||||
future-release=v0.12.0
|
||||
since-tag=v0.11.0
|
||||
|
||||
@@ -1,27 +1,5 @@
|
||||
# Changelog
|
||||
|
||||
## [v0.12.1](https://github.com/nymtech/nym/tree/v0.12.1) (2021-12-23)
|
||||
|
||||
[Full Changelog](https://github.com/nymtech/nym/compare/v0.12.0...v0.12.1)
|
||||
|
||||
**Implemented enhancements:**
|
||||
|
||||
- Add version check to binaries [\#967](https://github.com/nymtech/nym/issues/967)
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- \[Issue\] NYM wallet doesn't work after login [\#995](https://github.com/nymtech/nym/issues/995)
|
||||
- \[Issue\] [\#993](https://github.com/nymtech/nym/issues/993)
|
||||
- NYM wallet setup trouble\[Issue\] [\#958](https://github.com/nymtech/nym/issues/958)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Update wallet version [\#998](https://github.com/nymtech/nym/pull/998) ([tommyv1987](https://github.com/tommyv1987))
|
||||
- Fix wallet build instructions [\#997](https://github.com/nymtech/nym/pull/997) ([tommyv1987](https://github.com/tommyv1987))
|
||||
- Make the separation between testnet-mode and erc20 bandwidth mode clearer [\#994](https://github.com/nymtech/nym/pull/994) ([neacsu](https://github.com/neacsu))
|
||||
- Bump @openzeppelin/contracts from 3.4.0 to 4.4.1 in /contracts/basic-bandwidth-generation [\#983](https://github.com/nymtech/nym/pull/983) ([dependabot[bot]](https://github.com/apps/dependabot))
|
||||
- Differentiate staking and ownership [\#961](https://github.com/nymtech/nym/pull/961) ([durch](https://github.com/durch))
|
||||
|
||||
## [v0.12.0](https://github.com/nymtech/nym/tree/v0.12.0) (2021-12-21)
|
||||
|
||||
[Full Changelog](https://github.com/nymtech/nym/compare/v0.11.0...v0.12.0)
|
||||
@@ -80,7 +58,6 @@
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Update wallet to align with versioning on nodes and gateways [\#991](https://github.com/nymtech/nym/pull/991) ([tommyv1987](https://github.com/tommyv1987))
|
||||
- Fix success view messages. [\#990](https://github.com/nymtech/nym/pull/990) ([tommyv1987](https://github.com/tommyv1987))
|
||||
- Feature/enable signature check [\#989](https://github.com/nymtech/nym/pull/989) ([neacsu](https://github.com/neacsu))
|
||||
- Update mixnet contract address [\#988](https://github.com/nymtech/nym/pull/988) ([neacsu](https://github.com/neacsu))
|
||||
|
||||
Generated
+256
-76
@@ -208,7 +208,24 @@ dependencies = [
|
||||
"serde_json",
|
||||
"serde_urlencoded 0.6.1",
|
||||
"url",
|
||||
"wildmatch",
|
||||
"wildmatch 1.1.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "attohttpc"
|
||||
version = "0.18.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e69e13a99a7e6e070bb114f7ff381e58c7ccc188630121fc4c2fe4bcf24cd072"
|
||||
dependencies = [
|
||||
"flate2",
|
||||
"http",
|
||||
"log",
|
||||
"native-tls",
|
||||
"openssl",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"url",
|
||||
"wildmatch 2.1.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -260,6 +277,12 @@ version = "0.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
|
||||
|
||||
[[package]]
|
||||
name = "base64ct"
|
||||
version = "1.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "874f8444adcb4952a8bc51305c8be95c8ec8237bb0d2e78d2e039f771f8828a0"
|
||||
|
||||
[[package]]
|
||||
name = "binascii"
|
||||
version = "0.1.4"
|
||||
@@ -277,14 +300,16 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "bip32"
|
||||
version = "0.2.2"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c2d0f0fc59c7ba0333eed9dcc1b6980baa7b7a4dc7c6c5885994d0674f7adf34"
|
||||
checksum = "873faa4363bfc54c36a48321da034c92a0645a363eed34d948683ffc1706e37f"
|
||||
dependencies = [
|
||||
"bs58",
|
||||
"hkd32",
|
||||
"hmac",
|
||||
"k256",
|
||||
"k256 0.10.1",
|
||||
"once_cell",
|
||||
"pbkdf2",
|
||||
"rand_core 0.6.3",
|
||||
"ripemd160",
|
||||
"sha2",
|
||||
"subtle 2.4.1",
|
||||
@@ -342,9 +367,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "blake3"
|
||||
version = "1.0.0"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dcd555c66291d5f836dbb6883b48660ece810fe25a31f3bdfb911945dff2691f"
|
||||
checksum = "526c210b4520e416420759af363083471656e819a75e831b8d2c9d5a584f2413"
|
||||
dependencies = [
|
||||
"arrayref",
|
||||
"arrayvec 0.7.1",
|
||||
@@ -406,8 +431,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "54757888b09a69be70b5ec303e382a74227392086ba808cb01eeca29233a2397"
|
||||
dependencies = [
|
||||
"digest 0.9.0",
|
||||
"ff",
|
||||
"group",
|
||||
"ff 0.10.1",
|
||||
"group 0.10.0",
|
||||
"pairing",
|
||||
"rand_core 0.6.3",
|
||||
"subtle 2.4.1",
|
||||
@@ -762,6 +787,12 @@ version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fdab415d6744056100f40250a66bc430c1a46f7a02e20bc11c94c79a0f0464df"
|
||||
|
||||
[[package]]
|
||||
name = "const-oid"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e4c78c047431fee22c1a7bb92e00ad095a02a983affe4d8a72e2a2c62c1b94f3"
|
||||
|
||||
[[package]]
|
||||
name = "const_fn"
|
||||
version = "0.4.8"
|
||||
@@ -774,6 +805,13 @@ version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc"
|
||||
|
||||
[[package]]
|
||||
name = "contracts-common"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"cosmwasm-std",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "convert_case"
|
||||
version = "0.4.0"
|
||||
@@ -875,8 +913,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cosmos-sdk-proto"
|
||||
version = "0.8.0"
|
||||
source = "git+https://github.com/cosmos/cosmos-rust?rev=e5a1872083abb3d88fa62dda966e7f5408deba58#e5a1872083abb3d88fa62dda966e7f5408deba58"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c0254ffee603f5301d6a66963d9e1cc5091479c22e2e925e1f7689c8027a0828"
|
||||
dependencies = [
|
||||
"prost",
|
||||
"prost-types",
|
||||
@@ -885,15 +924,16 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cosmrs"
|
||||
version = "0.3.0"
|
||||
source = "git+https://github.com/cosmos/cosmos-rust?rev=e5a1872083abb3d88fa62dda966e7f5408deba58#e5a1872083abb3d88fa62dda966e7f5408deba58"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "505ea048e9ff2f906d6b954f9f8157d903ca468bfb301d906b40ecc25ba6838d"
|
||||
dependencies = [
|
||||
"bip32",
|
||||
"cosmos-sdk-proto",
|
||||
"ecdsa",
|
||||
"ecdsa 0.13.4",
|
||||
"eyre",
|
||||
"getrandom 0.2.3",
|
||||
"k256",
|
||||
"k256 0.10.1",
|
||||
"prost",
|
||||
"prost-types",
|
||||
"rand_core 0.6.3",
|
||||
@@ -913,7 +953,7 @@ checksum = "a380b87642204557629c9b72988c47b55fbfe6d474960adba56b22331504956a"
|
||||
dependencies = [
|
||||
"digest 0.9.0",
|
||||
"ed25519-zebra",
|
||||
"k256",
|
||||
"k256 0.9.6",
|
||||
"rand_core 0.5.1",
|
||||
"thiserror",
|
||||
]
|
||||
@@ -1118,6 +1158,18 @@ dependencies = [
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crypto-bigint"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "03c6a1d5fa1de37e071642dfa44ec552ca5b299adb128fab16138e24b548fd21"
|
||||
dependencies = [
|
||||
"generic-array 0.14.4",
|
||||
"rand_core 0.6.3",
|
||||
"subtle 2.4.1",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crypto-mac"
|
||||
version = "0.7.0"
|
||||
@@ -1220,9 +1272,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cw-storage-plus"
|
||||
version = "0.10.3"
|
||||
version = "0.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d3b8b840947313c1a1cccf056836cd79a60b4526bdcd6582995be37dc97be4ae"
|
||||
checksum = "7d7ee1963302b0ac2a9d42fe0faec826209c17452bfd36fbfd9d002a88929261"
|
||||
dependencies = [
|
||||
"cosmwasm-std",
|
||||
"schemars",
|
||||
@@ -1335,7 +1387,16 @@ version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2adca118c71ecd9ae094d4b68257b3fdfcb711a612b9eec7b5a0d27a5a70a5b4"
|
||||
dependencies = [
|
||||
"const-oid",
|
||||
"const-oid 0.6.1",
|
||||
]
|
||||
|
||||
[[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",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1544,17 +1605,29 @@ version = "0.12.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "43ee23aa5b4f68c7a092b5c3beb25f50c406adc75e2363634f242f28ab255372"
|
||||
dependencies = [
|
||||
"der",
|
||||
"elliptic-curve",
|
||||
"der 0.4.3",
|
||||
"elliptic-curve 0.10.6",
|
||||
"hmac",
|
||||
"signature",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ed25519"
|
||||
version = "1.2.0"
|
||||
name = "ecdsa"
|
||||
version = "0.13.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4620d40f6d2601794401d6dd95a5cf69b6c157852539470eeda433a99b3c0efc"
|
||||
checksum = "d0d69ae62e0ce582d56380743515fefaf1a8c70cec685d9677636d7e30ae9dc9"
|
||||
dependencies = [
|
||||
"der 0.5.1",
|
||||
"elliptic-curve 0.11.6",
|
||||
"rfc6979",
|
||||
"signature",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ed25519"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "74e1069e39f1454367eb2de793ed062fac4c35c2934b76a81d90dd9abcd28816"
|
||||
dependencies = [
|
||||
"signature",
|
||||
]
|
||||
@@ -1599,16 +1672,33 @@ version = "0.10.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "beca177dcb8eb540133e7680baff45e7cc4d93bf22002676cec549f82343721b"
|
||||
dependencies = [
|
||||
"crypto-bigint",
|
||||
"ff",
|
||||
"crypto-bigint 0.2.10",
|
||||
"ff 0.10.1",
|
||||
"generic-array 0.14.4",
|
||||
"group",
|
||||
"pkcs8",
|
||||
"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.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "decb3a27ea454a5f23f96eb182af0671c12694d64ecc33dada74edd1301f6cfc"
|
||||
dependencies = [
|
||||
"crypto-bigint 0.3.2",
|
||||
"der 0.5.1",
|
||||
"ff 0.11.0",
|
||||
"generic-array 0.14.4",
|
||||
"group 0.11.0",
|
||||
"rand_core 0.6.3",
|
||||
"sec1",
|
||||
"subtle 2.4.1",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "embed_plist"
|
||||
version = "1.2.0"
|
||||
@@ -1729,7 +1819,7 @@ dependencies = [
|
||||
"humantime-serde",
|
||||
"isocountry",
|
||||
"log",
|
||||
"mixnet-contract",
|
||||
"mixnet-contract-common",
|
||||
"network-defaults",
|
||||
"okapi",
|
||||
"pretty_env_logger",
|
||||
@@ -1780,6 +1870,16 @@ dependencies = [
|
||||
"subtle 2.4.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ff"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b2958d04124b9f27f175eaeb9a9f383d026098aa837eadd8ba22c11f13a05b9e"
|
||||
dependencies = [
|
||||
"rand_core 0.6.3",
|
||||
"subtle 2.4.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "field-offset"
|
||||
version = "0.3.4"
|
||||
@@ -2422,7 +2522,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1c363a5301b8f153d80747126a04b3c82073b9fe3130571a9d170cacdeaf7912"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"ff",
|
||||
"ff 0.10.1",
|
||||
"rand_core 0.6.3",
|
||||
"subtle 2.4.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "group"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bc5ac374b108929de78460075f3dc439fa66df9d8fc77e8f12caa5165fcf0c89"
|
||||
dependencies = [
|
||||
"ff 0.11.0",
|
||||
"rand_core 0.6.3",
|
||||
"subtle 2.4.1",
|
||||
]
|
||||
@@ -2595,20 +2706,6 @@ version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "21e4590e13640f19f249fe3e4eca5113bc4289f2497710378190e7f4bd96f45b"
|
||||
|
||||
[[package]]
|
||||
name = "hkd32"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "84f2a5541afe0725f0b95619d6af614f48c1b176385b8aa30918cfb8c4bfafc8"
|
||||
dependencies = [
|
||||
"hmac",
|
||||
"once_cell",
|
||||
"pbkdf2",
|
||||
"rand_core 0.6.3",
|
||||
"sha2",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hkdf"
|
||||
version = "0.11.0"
|
||||
@@ -3050,8 +3147,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "903ae2481bcdfdb7b68e0a9baa4b7c9aff600b9ae2e8e5bb5833b8c91ab851ea"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"ecdsa",
|
||||
"elliptic-curve",
|
||||
"ecdsa 0.12.4",
|
||||
"elliptic-curve 0.10.6",
|
||||
"sha2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "k256"
|
||||
version = "0.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7511aa19fa182a8a4885760c4e5675b17173b02ae86ec5d376d34f5278c874b9"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"ecdsa 0.13.4",
|
||||
"elliptic-curve 0.11.6",
|
||||
"sec1",
|
||||
"sha2",
|
||||
"sha3",
|
||||
]
|
||||
@@ -3309,10 +3419,11 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mixnet-contract"
|
||||
name = "mixnet-contract-common"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"az",
|
||||
"contracts-common",
|
||||
"cosmwasm-std",
|
||||
"fixed",
|
||||
"log",
|
||||
@@ -3438,6 +3549,7 @@ checksum = "c44922cb3dbb1c70b5e5f443d63b64363a898564d739ba5198e3a9138442868d"
|
||||
name = "network-defaults"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"hex-literal",
|
||||
"serde",
|
||||
"time 0.3.3",
|
||||
@@ -3767,6 +3879,7 @@ name = "nym-validator-api"
|
||||
version = "0.12.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"attohttpc 0.18.0",
|
||||
"clap",
|
||||
"coconut-interface",
|
||||
"config",
|
||||
@@ -3779,7 +3892,7 @@ dependencies = [
|
||||
"getset",
|
||||
"humantime-serde",
|
||||
"log",
|
||||
"mixnet-contract",
|
||||
"mixnet-contract-common",
|
||||
"nymsphinx",
|
||||
"pin-project",
|
||||
"pretty_env_logger",
|
||||
@@ -3798,6 +3911,7 @@ dependencies = [
|
||||
"tokio",
|
||||
"topology",
|
||||
"url",
|
||||
"validator-api-requests",
|
||||
"validator-client",
|
||||
"vergen",
|
||||
"version-checker",
|
||||
@@ -3813,9 +3927,9 @@ dependencies = [
|
||||
"criterion",
|
||||
"digest 0.9.0",
|
||||
"doc-comment",
|
||||
"ff",
|
||||
"ff 0.10.1",
|
||||
"getrandom 0.2.3",
|
||||
"group",
|
||||
"group 0.10.0",
|
||||
"itertools",
|
||||
"rand 0.8.4",
|
||||
"serde",
|
||||
@@ -3829,7 +3943,7 @@ name = "nymsphinx"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"crypto",
|
||||
"mixnet-contract",
|
||||
"mixnet-contract-common",
|
||||
"nymsphinx-acknowledgements",
|
||||
"nymsphinx-addressing",
|
||||
"nymsphinx-anonymous-replies",
|
||||
@@ -4062,7 +4176,7 @@ version = "0.20.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7de9d09263c9966e8196fe0380c9dbbc7ea114b5cf371ba29004bc1f9c6db7f3"
|
||||
dependencies = [
|
||||
"group",
|
||||
"group 0.10.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4155,9 +4269,9 @@ checksum = "acbf547ad0c65e31259204bd90935776d1c693cec2f4ff7abb7a1bbbd40dfe58"
|
||||
|
||||
[[package]]
|
||||
name = "pbkdf2"
|
||||
version = "0.8.0"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d95f5254224e617595d2cc3cc73ff0a5eaf2637519e25f03388154e9378b6ffa"
|
||||
checksum = "f05894bce6a1ba4be299d0c5f29563e08af2bc18bb7d48313113bed71e904739"
|
||||
dependencies = [
|
||||
"crypto-mac 0.11.1",
|
||||
]
|
||||
@@ -4415,8 +4529,19 @@ version = "0.7.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ee3ef9b64d26bad0536099c816c6734379e45bbd5f14798def6809e5cc350447"
|
||||
dependencies = [
|
||||
"der",
|
||||
"spki",
|
||||
"der 0.4.3",
|
||||
"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",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -5055,6 +5180,17 @@ dependencies = [
|
||||
"winreg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rfc6979"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "96ef608575f6392792f9ecf7890c00086591d29a83910939d430753f7c050525"
|
||||
dependencies = [
|
||||
"crypto-bigint 0.3.2",
|
||||
"hmac",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rfd"
|
||||
version = "0.4.4"
|
||||
@@ -5409,6 +5545,19 @@ dependencies = [
|
||||
"untrusted",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sec1"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08da66b8b0965a5555b6bd6639e68ccba85e1e2506f5fbb089e93f8a04e1a2d1"
|
||||
dependencies = [
|
||||
"der 0.5.1",
|
||||
"generic-array 0.14.4",
|
||||
"pkcs8 0.8.0",
|
||||
"subtle 2.4.1",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "secp256k1"
|
||||
version = "0.20.3"
|
||||
@@ -5874,7 +6023,17 @@ version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c01a0c15da1b0b0e1494112e7af814a678fec9bd157881b49beac661e9b6f32"
|
||||
dependencies = [
|
||||
"der",
|
||||
"der 0.4.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "spki"
|
||||
version = "0.5.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "44d01ac02a6ccf3e07db148d2be087da624fea0221a16152ed01f0496a6b0a27"
|
||||
dependencies = [
|
||||
"base64ct",
|
||||
"der 0.5.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -6440,7 +6599,7 @@ version = "1.0.0-beta.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "79a0579dcc6fb883fe90dd3c66d76b8b8f4a1786e1e915e314b2017a500ede09"
|
||||
dependencies = [
|
||||
"attohttpc",
|
||||
"attohttpc 0.17.0",
|
||||
"bincode",
|
||||
"cfg_aliases",
|
||||
"dirs-next",
|
||||
@@ -6590,18 +6749,17 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tendermint"
|
||||
version = "0.23.0"
|
||||
version = "0.23.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "50d1cdb0236becb17ab35a2ed1566503e412fd910944dc940239857bb7663652"
|
||||
checksum = "a9ef686b8ecd36550d0581f0989c9d8607090b23005df479d8e6ba348b5800b9"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"bytes",
|
||||
"chrono",
|
||||
"ed25519",
|
||||
"ed25519-dalek",
|
||||
"flex-error",
|
||||
"futures",
|
||||
"k256",
|
||||
"k256 0.10.1",
|
||||
"num-traits",
|
||||
"once_cell",
|
||||
"prost",
|
||||
@@ -6616,14 +6774,15 @@ dependencies = [
|
||||
"subtle 2.4.1",
|
||||
"subtle-encoding",
|
||||
"tendermint-proto",
|
||||
"time 0.3.3",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tendermint-config"
|
||||
version = "0.23.0"
|
||||
version = "0.23.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2a1f94250d30e3011130a09756b05985d8dbfbd562cf261b5a17e36d89a37992"
|
||||
checksum = "ecc127f82e7a8c7337c1f293d65a821380d3407c4c44bc979ef4da0ebc3b31ed"
|
||||
dependencies = [
|
||||
"flex-error",
|
||||
"serde",
|
||||
@@ -6635,12 +6794,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tendermint-proto"
|
||||
version = "0.23.0"
|
||||
version = "0.23.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ff16a7b42bdbcf31c8cd10a4cffc7631f2a301360ba3a3f71dde48eabfa5bced"
|
||||
checksum = "a9e0a0251fd81bed7420bea0f4d91c2a58f6c9fa34d5b2f70bed0ba8890de5aa"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"chrono",
|
||||
"flex-error",
|
||||
"num-derive",
|
||||
"num-traits",
|
||||
@@ -6649,20 +6807,20 @@ dependencies = [
|
||||
"serde",
|
||||
"serde_bytes",
|
||||
"subtle-encoding",
|
||||
"time 0.3.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tendermint-rpc"
|
||||
version = "0.23.0"
|
||||
version = "0.23.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c7842dcd5edb60b077572aa92ff8b29fc810b9b463310f9810a2607474130db4"
|
||||
checksum = "626c493e9ced3a9de37583bbd929f4b6dbd49aa513ab9b4776aa44a9332ce9b5"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"bytes",
|
||||
"chrono",
|
||||
"flex-error",
|
||||
"futures",
|
||||
"getrandom 0.1.16",
|
||||
"getrandom 0.2.3",
|
||||
"http",
|
||||
"hyper",
|
||||
"hyper-proxy",
|
||||
@@ -6677,6 +6835,7 @@ dependencies = [
|
||||
"tendermint-config",
|
||||
"tendermint-proto",
|
||||
"thiserror",
|
||||
"time 0.3.3",
|
||||
"tokio",
|
||||
"tracing",
|
||||
"url",
|
||||
@@ -6955,7 +7114,7 @@ dependencies = [
|
||||
"bs58",
|
||||
"crypto",
|
||||
"log",
|
||||
"mixnet-contract",
|
||||
"mixnet-contract-common",
|
||||
"nymsphinx-addressing",
|
||||
"nymsphinx-types",
|
||||
"rand 0.7.3",
|
||||
@@ -7187,6 +7346,14 @@ dependencies = [
|
||||
"getrandom 0.2.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "validator-api-requests"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"ts-rs",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "validator-client"
|
||||
version = "0.1.0"
|
||||
@@ -7201,7 +7368,7 @@ dependencies = [
|
||||
"flate2",
|
||||
"itertools",
|
||||
"log",
|
||||
"mixnet-contract",
|
||||
"mixnet-contract-common",
|
||||
"network-defaults",
|
||||
"prost",
|
||||
"reqwest",
|
||||
@@ -7211,6 +7378,7 @@ dependencies = [
|
||||
"thiserror",
|
||||
"ts-rs",
|
||||
"url",
|
||||
"validator-api-requests",
|
||||
"vesting-contract",
|
||||
]
|
||||
|
||||
@@ -7275,12 +7443,18 @@ dependencies = [
|
||||
"config",
|
||||
"cosmwasm-std",
|
||||
"cw-storage-plus",
|
||||
"getrandom 0.2.3",
|
||||
"mixnet-contract",
|
||||
"rand 0.8.4",
|
||||
"mixnet-contract-common",
|
||||
"schemars",
|
||||
"serde",
|
||||
"thiserror",
|
||||
"vesting-contract-common",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "vesting-contract-common"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"cosmwasm-std",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -7613,6 +7787,12 @@ version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f44b95f62d34113cf558c93511ac93027e03e9c29a60dd0fd70e6e025c7270a"
|
||||
|
||||
[[package]]
|
||||
name = "wildmatch"
|
||||
version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d6c48bd20df7e4ced539c12f570f937c6b4884928a87fee70a479d72f031d4e0"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
|
||||
+4
-1
@@ -26,7 +26,9 @@ members = [
|
||||
"common/credentials",
|
||||
"common/crypto",
|
||||
"common/bandwidth-claim-contract",
|
||||
"common/mixnet-contract",
|
||||
"common/cosmwasm-smart-contracts/contracts-common",
|
||||
"common/cosmwasm-smart-contracts/mixnet-contract",
|
||||
"common/cosmwasm-smart-contracts/vesting-contract",
|
||||
"common/mixnode-common",
|
||||
"common/network-defaults",
|
||||
"common/nonexhaustive-delayqueue",
|
||||
@@ -52,6 +54,7 @@ members = [
|
||||
"mixnode",
|
||||
"service-providers/network-requester",
|
||||
"validator-api",
|
||||
"validator-api/validator-api-requests",
|
||||
]
|
||||
|
||||
default-members = [
|
||||
|
||||
@@ -21,7 +21,8 @@ The platform is composed of multiple Rust crates. Top-level executable binary cr
|
||||
|
||||
### Building
|
||||
|
||||
Platform build instructions are available on [our docs site](https://nymtech.net/docs/0.11.0/overview/index/).
|
||||
Platform build instructions are available on [our docs site](https://nymtech.net/docs/stable/run-nym-nodes/build-nym).
|
||||
Wallet build instructions are also available on [our docs site](https://nymtech.net/docs/stable/nym-apps/wallet#for-developers).
|
||||
|
||||
### Developing
|
||||
|
||||
|
||||
@@ -13,7 +13,6 @@ use nymsphinx::utils::sample_poisson_duration;
|
||||
use rand::{rngs::OsRng, CryptoRng, Rng};
|
||||
use std::pin::Pin;
|
||||
use std::sync::Arc;
|
||||
use tokio::runtime::Handle;
|
||||
use tokio::task::JoinHandle;
|
||||
use tokio::time;
|
||||
|
||||
@@ -165,8 +164,8 @@ impl LoopCoverTrafficStream<OsRng> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn start(mut self, handle: &Handle) -> JoinHandle<()> {
|
||||
handle.spawn(async move {
|
||||
pub fn start(mut self) -> JoinHandle<()> {
|
||||
tokio::spawn(async move {
|
||||
self.run().await;
|
||||
})
|
||||
}
|
||||
|
||||
@@ -79,9 +79,9 @@ impl KeyManager {
|
||||
))?;
|
||||
|
||||
let gateway_shared_key: SharedKeys =
|
||||
pemstore::load_key(&client_pathfinder.gateway_shared_key().to_owned())?;
|
||||
pemstore::load_key(client_pathfinder.gateway_shared_key())?;
|
||||
|
||||
let ack_key: AckKey = pemstore::load_key(&client_pathfinder.ack_key().to_owned())?;
|
||||
let ack_key: AckKey = pemstore::load_key(client_pathfinder.ack_key())?;
|
||||
|
||||
// TODO: ack key is never stored so it is generated now. But perhaps it should be stored
|
||||
// after all for consistency sake?
|
||||
|
||||
@@ -6,7 +6,6 @@ use futures::StreamExt;
|
||||
use gateway_client::GatewayClient;
|
||||
use log::*;
|
||||
use nymsphinx::forwarding::packet::MixPacket;
|
||||
use tokio::runtime::Handle;
|
||||
use tokio::task::JoinHandle;
|
||||
|
||||
pub type BatchMixMessageSender = mpsc::UnboundedSender<Vec<MixPacket>>;
|
||||
@@ -72,8 +71,8 @@ impl MixTrafficController {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn start(mut self, handle: &Handle) -> JoinHandle<()> {
|
||||
handle.spawn(async move {
|
||||
pub fn start(mut self) -> JoinHandle<()> {
|
||||
tokio::spawn(async move {
|
||||
self.run().await;
|
||||
})
|
||||
}
|
||||
|
||||
@@ -22,7 +22,6 @@ use nymsphinx::addressing::clients::Recipient;
|
||||
use rand::{rngs::OsRng, CryptoRng, Rng};
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
use tokio::runtime::Handle;
|
||||
use tokio::task::JoinHandle;
|
||||
|
||||
mod acknowledgement_control;
|
||||
@@ -170,10 +169,8 @@ impl RealMessagesController<OsRng> {
|
||||
self.ack_control = Some(ack_control_fut.await.unwrap());
|
||||
}
|
||||
|
||||
// &Handle is only passed for consistency sake with other client modules, but I think
|
||||
// when we get to refactoring, we should apply gateway approach and make it implicit
|
||||
pub fn start(mut self, handle: &Handle) -> JoinHandle<Self> {
|
||||
handle.spawn(async move {
|
||||
pub fn start(mut self) -> JoinHandle<Self> {
|
||||
tokio::spawn(async move {
|
||||
self.run().await;
|
||||
self
|
||||
})
|
||||
|
||||
@@ -15,7 +15,6 @@ use nymsphinx::params::{ReplySurbEncryptionAlgorithm, ReplySurbKeyDigestAlgorith
|
||||
use nymsphinx::receiver::{MessageReceiver, MessageRecoveryError, ReconstructedMessage};
|
||||
use std::collections::HashSet;
|
||||
use std::sync::Arc;
|
||||
use tokio::runtime::Handle;
|
||||
use tokio::task::JoinHandle;
|
||||
|
||||
// Buffer Requests to say "hey, send any reconstructed messages to this channel"
|
||||
@@ -291,8 +290,8 @@ impl RequestReceiver {
|
||||
}
|
||||
}
|
||||
|
||||
fn start(mut self, handle: &Handle) -> JoinHandle<()> {
|
||||
handle.spawn(async move {
|
||||
fn start(mut self) -> JoinHandle<()> {
|
||||
tokio::spawn(async move {
|
||||
while let Some(request) = self.query_receiver.next().await {
|
||||
match request {
|
||||
ReceivedBufferMessage::ReceiverAnnounce(sender) => {
|
||||
@@ -322,8 +321,8 @@ impl FragmentedMessageReceiver {
|
||||
mixnet_packet_receiver,
|
||||
}
|
||||
}
|
||||
fn start(mut self, handle: &Handle) -> JoinHandle<()> {
|
||||
handle.spawn(async move {
|
||||
fn start(mut self) -> JoinHandle<()> {
|
||||
tokio::spawn(async move {
|
||||
while let Some(new_messages) = self.mixnet_packet_receiver.next().await {
|
||||
self.received_buffer.handle_new_received(new_messages).await;
|
||||
}
|
||||
@@ -355,9 +354,9 @@ impl ReceivedMessagesBufferController {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn start(self, handle: &Handle) {
|
||||
pub fn start(self) {
|
||||
// TODO: should we do anything with JoinHandle(s) returned by start methods?
|
||||
self.fragmented_message_receiver.start(handle);
|
||||
self.request_receiver.start(handle);
|
||||
self.fragmented_message_receiver.start();
|
||||
self.request_receiver.start();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ impl ReplyKeyStorage {
|
||||
) -> Result<(), ReplyKeyStorageError> {
|
||||
let digest = encryption_key.compute_digest();
|
||||
|
||||
let insertion_result = match self.db.insert(digest.to_vec(), encryption_key.to_bytes()) {
|
||||
let insertion_result = match self.db.insert(digest, encryption_key.to_bytes()) {
|
||||
Err(e) => Err(ReplyKeyStorageError::DbWriteError(e)),
|
||||
Ok(existing_key) => {
|
||||
if existing_key.is_some() {
|
||||
@@ -79,7 +79,7 @@ impl ReplyKeyStorage {
|
||||
&self,
|
||||
key_digest: EncryptionKeyDigest,
|
||||
) -> Result<Option<SurbEncryptionKey>, ReplyKeyStorageError> {
|
||||
let removal_result = match self.db.remove(&key_digest.to_vec()) {
|
||||
let removal_result = match self.db.remove(key_digest) {
|
||||
Err(e) => Err(ReplyKeyStorageError::DbReadError(e)),
|
||||
Ok(existing_key) => {
|
||||
Ok(existing_key.map(|existing_key| self.read_encryption_key(existing_key)))
|
||||
|
||||
@@ -10,7 +10,6 @@ use std::ops::Deref;
|
||||
use std::sync::Arc;
|
||||
use std::time;
|
||||
use std::time::Duration;
|
||||
use tokio::runtime::Handle;
|
||||
use tokio::sync::{RwLock, RwLockReadGuard};
|
||||
use tokio::task::JoinHandle;
|
||||
use topology::{nym_topology_from_bonds, NymTopology};
|
||||
@@ -304,8 +303,8 @@ impl TopologyRefresher {
|
||||
self.topology_accessor.is_routable().await
|
||||
}
|
||||
|
||||
pub fn start(mut self, handle: &Handle) -> JoinHandle<()> {
|
||||
handle.spawn(async move {
|
||||
pub fn start(mut self) -> JoinHandle<()> {
|
||||
tokio::spawn(async move {
|
||||
loop {
|
||||
tokio::time::sleep(self.refresh_rate).await;
|
||||
self.refresh().await;
|
||||
|
||||
@@ -35,7 +35,7 @@ async fn send_file_with_reply() {
|
||||
let (mut ws_stream, _) = connect_async(uri).await.unwrap();
|
||||
|
||||
let recipient = get_self_address(&mut ws_stream).await;
|
||||
println!("our full address is: {}", recipient.to_string());
|
||||
println!("our full address is: {}", recipient);
|
||||
|
||||
let read_data = std::fs::read("examples/dummy_file").unwrap();
|
||||
|
||||
@@ -83,7 +83,7 @@ async fn send_file_without_reply() {
|
||||
let (mut ws_stream, _) = connect_async(uri).await.unwrap();
|
||||
|
||||
let recipient = get_self_address(&mut ws_stream).await;
|
||||
println!("our full address is: {}", recipient.to_string());
|
||||
println!("our full address is: {}", recipient);
|
||||
|
||||
let read_data = std::fs::read("examples/dummy_file").unwrap();
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ async fn send_text_with_reply() {
|
||||
let (mut ws_stream, _) = connect_async(uri).await.unwrap();
|
||||
|
||||
let recipient = get_self_address(&mut ws_stream).await;
|
||||
println!("our full address is: {}", recipient.to_string());
|
||||
println!("our full address is: {}", recipient);
|
||||
|
||||
let send_request = json!({
|
||||
"type" : "send",
|
||||
@@ -76,7 +76,7 @@ async fn send_text_without_reply() {
|
||||
let (mut ws_stream, _) = connect_async(uri).await.unwrap();
|
||||
|
||||
let recipient = get_self_address(&mut ws_stream).await;
|
||||
println!("our full address is: {}", recipient.to_string());
|
||||
println!("our full address is: {}", recipient);
|
||||
|
||||
let send_request = json!({
|
||||
"type" : "send",
|
||||
|
||||
@@ -32,7 +32,6 @@ use nymsphinx::addressing::clients::Recipient;
|
||||
use nymsphinx::addressing::nodes::NodeIdentity;
|
||||
use nymsphinx::anonymous_replies::ReplySurb;
|
||||
use nymsphinx::receiver::ReconstructedMessage;
|
||||
use tokio::runtime::Runtime;
|
||||
|
||||
use crate::client::config::{Config, SocketType};
|
||||
use crate::websocket;
|
||||
@@ -44,11 +43,6 @@ pub struct NymClient {
|
||||
/// key filepaths, etc.
|
||||
config: Config,
|
||||
|
||||
/// Tokio runtime used for futures execution.
|
||||
// TODO: JS: Personally I think I prefer the implicit way of using it that we've done with the
|
||||
// gateway.
|
||||
runtime: Runtime,
|
||||
|
||||
/// KeyManager object containing smart pointers to all relevant keys used by the client.
|
||||
key_manager: KeyManager,
|
||||
|
||||
@@ -68,7 +62,6 @@ impl NymClient {
|
||||
let key_manager = KeyManager::load_keys(&pathfinder).expect("failed to load stored keys");
|
||||
|
||||
NymClient {
|
||||
runtime: Runtime::new().unwrap(),
|
||||
config,
|
||||
key_manager,
|
||||
input_tx: None,
|
||||
@@ -94,9 +87,6 @@ impl NymClient {
|
||||
mix_tx: BatchMixMessageSender,
|
||||
) {
|
||||
info!("Starting loop cover traffic stream...");
|
||||
// we need to explicitly enter runtime due to "next_delay: time::delay_for(Default::default())"
|
||||
// set in the constructor which HAS TO be called within context of a tokio runtime
|
||||
let _guard = self.runtime.enter();
|
||||
|
||||
LoopCoverTrafficStream::new(
|
||||
self.key_manager.ack_key(),
|
||||
@@ -109,7 +99,7 @@ impl NymClient {
|
||||
self.as_mix_recipient(),
|
||||
topology_accessor,
|
||||
)
|
||||
.start(self.runtime.handle());
|
||||
.start();
|
||||
}
|
||||
|
||||
fn start_real_traffic_controller(
|
||||
@@ -131,10 +121,6 @@ impl NymClient {
|
||||
);
|
||||
|
||||
info!("Starting real traffic stream...");
|
||||
// we need to explicitly enter runtime due to "next_delay: time::delay_for(Default::default())"
|
||||
// set in the constructor [of OutQueueControl] which HAS TO be called within context of a tokio runtime
|
||||
// When refactoring this restriction should definitely be removed.
|
||||
let _guard = self.runtime.enter();
|
||||
|
||||
RealMessagesController::new(
|
||||
controller_config,
|
||||
@@ -144,7 +130,7 @@ impl NymClient {
|
||||
topology_accessor,
|
||||
reply_key_storage,
|
||||
)
|
||||
.start(self.runtime.handle());
|
||||
.start();
|
||||
}
|
||||
|
||||
// buffer controlling all messages fetched from provider
|
||||
@@ -162,10 +148,10 @@ impl NymClient {
|
||||
mixnet_receiver,
|
||||
reply_key_storage,
|
||||
)
|
||||
.start(self.runtime.handle())
|
||||
.start()
|
||||
}
|
||||
|
||||
fn start_gateway_client(
|
||||
async fn start_gateway_client(
|
||||
&mut self,
|
||||
mixnet_message_sender: MixnetMessageSender,
|
||||
ack_sender: AcknowledgementSender,
|
||||
@@ -182,47 +168,44 @@ impl NymClient {
|
||||
let gateway_identity = identity::PublicKey::from_base58_string(gateway_id)
|
||||
.expect("provided gateway id is invalid!");
|
||||
|
||||
self.runtime.block_on(async {
|
||||
#[cfg(feature = "coconut")]
|
||||
let bandwidth_controller = BandwidthController::new(
|
||||
self.config.get_base().get_validator_api_endpoints(),
|
||||
*self.key_manager.identity_keypair().public_key(),
|
||||
);
|
||||
#[cfg(not(feature = "coconut"))]
|
||||
let bandwidth_controller = BandwidthController::new(
|
||||
self.config.get_base().get_eth_endpoint(),
|
||||
self.config.get_base().get_eth_private_key(),
|
||||
self.config.get_base().get_backup_bandwidth_token_keys_dir(),
|
||||
)
|
||||
.expect("Could not create bandwidth controller");
|
||||
#[cfg(feature = "coconut")]
|
||||
let bandwidth_controller = BandwidthController::new(
|
||||
self.config.get_base().get_validator_api_endpoints(),
|
||||
*self.key_manager.identity_keypair().public_key(),
|
||||
);
|
||||
#[cfg(not(feature = "coconut"))]
|
||||
let bandwidth_controller = BandwidthController::new(
|
||||
self.config.get_base().get_eth_endpoint(),
|
||||
self.config.get_base().get_eth_private_key(),
|
||||
self.config.get_base().get_backup_bandwidth_token_keys_dir(),
|
||||
)
|
||||
.expect("Could not create bandwidth controller");
|
||||
|
||||
let mut gateway_client = GatewayClient::new(
|
||||
gateway_address,
|
||||
self.key_manager.identity_keypair(),
|
||||
gateway_identity,
|
||||
Some(self.key_manager.gateway_shared_key()),
|
||||
mixnet_message_sender,
|
||||
ack_sender,
|
||||
self.config.get_base().get_gateway_response_timeout(),
|
||||
Some(bandwidth_controller),
|
||||
);
|
||||
let mut gateway_client = GatewayClient::new(
|
||||
gateway_address,
|
||||
self.key_manager.identity_keypair(),
|
||||
gateway_identity,
|
||||
Some(self.key_manager.gateway_shared_key()),
|
||||
mixnet_message_sender,
|
||||
ack_sender,
|
||||
self.config.get_base().get_gateway_response_timeout(),
|
||||
Some(bandwidth_controller),
|
||||
);
|
||||
|
||||
if self.config.get_base().get_testnet_mode() {
|
||||
gateway_client.set_testnet_mode(true)
|
||||
}
|
||||
if self.config.get_base().get_testnet_mode() {
|
||||
gateway_client.set_testnet_mode(true)
|
||||
}
|
||||
gateway_client
|
||||
.authenticate_and_start()
|
||||
.await
|
||||
.expect("could not authenticate and start up the gateway connection");
|
||||
|
||||
gateway_client
|
||||
.authenticate_and_start()
|
||||
.await
|
||||
.expect("could not authenticate and start up the gateway connection");
|
||||
|
||||
gateway_client
|
||||
})
|
||||
gateway_client
|
||||
}
|
||||
|
||||
// future responsible for periodically polling directory server and updating
|
||||
// the current global view of topology
|
||||
fn start_topology_refresher(&mut self, topology_accessor: TopologyAccessor) {
|
||||
async fn start_topology_refresher(&mut self, topology_accessor: TopologyAccessor) {
|
||||
let topology_refresher_config = TopologyRefresherConfig::new(
|
||||
self.config.get_base().get_validator_api_endpoints(),
|
||||
self.config.get_base().get_topology_refresh_rate(),
|
||||
@@ -233,13 +216,10 @@ impl NymClient {
|
||||
// before returning, block entire runtime to refresh the current network view so that any
|
||||
// components depending on topology would see a non-empty view
|
||||
info!("Obtaining initial network topology");
|
||||
self.runtime.block_on(topology_refresher.refresh());
|
||||
topology_refresher.refresh().await;
|
||||
|
||||
// TODO: a slightly more graceful termination here
|
||||
if !self
|
||||
.runtime
|
||||
.block_on(topology_refresher.is_topology_routable())
|
||||
{
|
||||
if !topology_refresher.is_topology_routable().await {
|
||||
panic!(
|
||||
"The current network topology seem to be insufficient to route any packets through\
|
||||
- check if enough nodes and a gateway are online"
|
||||
@@ -247,7 +227,7 @@ impl NymClient {
|
||||
}
|
||||
|
||||
info!("Starting topology refresher...");
|
||||
topology_refresher.start(self.runtime.handle());
|
||||
topology_refresher.start();
|
||||
}
|
||||
|
||||
// controller for sending sphinx packets to mixnet (either real traffic or cover traffic)
|
||||
@@ -260,7 +240,7 @@ impl NymClient {
|
||||
gateway_client: GatewayClient,
|
||||
) {
|
||||
info!("Starting mix traffic controller...");
|
||||
MixTrafficController::new(mix_rx, gateway_client).start(self.runtime.handle());
|
||||
MixTrafficController::new(mix_rx, gateway_client).start();
|
||||
}
|
||||
|
||||
fn start_websocket_listener(
|
||||
@@ -273,8 +253,7 @@ impl NymClient {
|
||||
let websocket_handler =
|
||||
websocket::Handler::new(msg_input, buffer_requester, self.as_mix_recipient());
|
||||
|
||||
websocket::Listener::new(self.config.get_listening_port())
|
||||
.start(self.runtime.handle(), websocket_handler);
|
||||
websocket::Listener::new(self.config.get_listening_port()).start(websocket_handler);
|
||||
}
|
||||
|
||||
/// EXPERIMENTAL DIRECT RUST API
|
||||
@@ -321,9 +300,9 @@ impl NymClient {
|
||||
}
|
||||
|
||||
/// blocking version of `start` method. Will run forever (or until SIGINT is sent)
|
||||
pub fn run_forever(&mut self) {
|
||||
self.start();
|
||||
if let Err(e) = self.runtime.block_on(tokio::signal::ctrl_c()) {
|
||||
pub async fn run_forever(&mut self) {
|
||||
self.start().await;
|
||||
if let Err(e) = tokio::signal::ctrl_c().await {
|
||||
error!(
|
||||
"There was an error while capturing SIGINT - {:?}. We will terminate regardless",
|
||||
e
|
||||
@@ -335,7 +314,7 @@ impl NymClient {
|
||||
);
|
||||
}
|
||||
|
||||
pub fn start(&mut self) {
|
||||
pub async fn start(&mut self) {
|
||||
info!("Starting nym client");
|
||||
// channels for inter-component communication
|
||||
// TODO: make the channels be internally created by the relevant components
|
||||
@@ -367,14 +346,17 @@ impl NymClient {
|
||||
|
||||
// the components are started in very specific order. Unless you know what you are doing,
|
||||
// do not change that.
|
||||
self.start_topology_refresher(shared_topology_accessor.clone());
|
||||
self.start_topology_refresher(shared_topology_accessor.clone())
|
||||
.await;
|
||||
self.start_received_messages_buffer_controller(
|
||||
received_buffer_request_receiver,
|
||||
mixnet_messages_receiver,
|
||||
reply_key_storage.clone(),
|
||||
);
|
||||
|
||||
let gateway_client = self.start_gateway_client(mixnet_messages_sender, ack_sender);
|
||||
let gateway_client = self
|
||||
.start_gateway_client(mixnet_messages_sender, ack_sender)
|
||||
.await;
|
||||
|
||||
self.start_mix_traffic_controller(sphinx_message_receiver, gateway_client);
|
||||
self.start_real_traffic_controller(
|
||||
|
||||
@@ -32,6 +32,7 @@ use url::Url;
|
||||
use crate::client::config::Config;
|
||||
use crate::commands::override_config;
|
||||
#[cfg(feature = "eth")]
|
||||
#[cfg(not(feature = "coconut"))]
|
||||
use crate::commands::{
|
||||
DEFAULT_ETH_ENDPOINT, DEFAULT_ETH_PRIVATE_KEY, ETH_ENDPOINT_ARG_NAME, ETH_PRIVATE_KEY_ARG_NAME,
|
||||
TESTNET_MODE_ARG_NAME,
|
||||
@@ -72,6 +73,7 @@ pub fn command_args<'a, 'b>() -> clap::App<'a, 'b> {
|
||||
.help("Mostly debug-related option to increase default traffic rate so that you would not need to modify config post init")
|
||||
);
|
||||
#[cfg(feature = "eth")]
|
||||
#[cfg(not(feature = "coconut"))]
|
||||
let app = app
|
||||
.arg(
|
||||
Arg::with_name(TESTNET_MODE_ARG_NAME)
|
||||
@@ -217,7 +219,7 @@ fn show_address(config: &Config) {
|
||||
println!("\nThe address of this client is: {}", client_recipient);
|
||||
}
|
||||
|
||||
pub fn execute(matches: &ArgMatches) {
|
||||
pub async fn execute(matches: ArgMatches<'static>) {
|
||||
println!("Initialising client...");
|
||||
|
||||
let id = matches.value_of("id").unwrap(); // required for now
|
||||
@@ -235,7 +237,7 @@ pub fn execute(matches: &ArgMatches) {
|
||||
|
||||
// TODO: ideally that should be the last thing that's being done to config.
|
||||
// However, we are later further overriding it with gateway id
|
||||
config = override_config(config, matches);
|
||||
config = override_config(config, &matches);
|
||||
if matches.is_present("fastmode") {
|
||||
config.get_base_mut().set_high_default_traffic_volume();
|
||||
}
|
||||
@@ -248,26 +250,20 @@ pub fn execute(matches: &ArgMatches) {
|
||||
|
||||
let chosen_gateway_id = matches.value_of("gateway");
|
||||
|
||||
let registration_fut = async {
|
||||
let gate_details = gateway_details(
|
||||
config.get_base().get_validator_api_endpoints(),
|
||||
chosen_gateway_id,
|
||||
)
|
||||
.await;
|
||||
config
|
||||
.get_base_mut()
|
||||
.with_gateway_id(gate_details.identity_key.to_base58_string());
|
||||
let shared_keys =
|
||||
register_with_gateway(&gate_details, key_manager.identity_keypair()).await;
|
||||
(shared_keys, gate_details.clients_address())
|
||||
};
|
||||
|
||||
// TODO: is there perhaps a way to make it work without having to spawn entire runtime?
|
||||
let rt = tokio::runtime::Runtime::new().unwrap();
|
||||
let (shared_keys, gateway_listener) = rt.block_on(registration_fut);
|
||||
let gateway_details = gateway_details(
|
||||
config.get_base().get_validator_api_endpoints(),
|
||||
chosen_gateway_id,
|
||||
)
|
||||
.await;
|
||||
config
|
||||
.get_base_mut()
|
||||
.with_gateway_listener(gateway_listener);
|
||||
.with_gateway_id(gateway_details.identity_key.to_base58_string());
|
||||
let shared_keys =
|
||||
register_with_gateway(&gateway_details, key_manager.identity_keypair()).await;
|
||||
|
||||
config
|
||||
.get_base_mut()
|
||||
.with_gateway_listener(gateway_details.clients_address());
|
||||
key_manager.insert_gateway_shared_key(shared_keys);
|
||||
|
||||
let pathfinder = ClientKeyPathfinder::new_from_config(config.get_base());
|
||||
|
||||
@@ -5,6 +5,7 @@ use crate::client::config::Config;
|
||||
use crate::client::NymClient;
|
||||
use crate::commands::override_config;
|
||||
#[cfg(feature = "eth")]
|
||||
#[cfg(not(feature = "coconut"))]
|
||||
use crate::commands::{ETH_ENDPOINT_ARG_NAME, ETH_PRIVATE_KEY_ARG_NAME, TESTNET_MODE_ARG_NAME};
|
||||
use clap::{App, Arg, ArgMatches};
|
||||
use config::NymConfig;
|
||||
@@ -42,6 +43,7 @@ pub fn command_args<'a, 'b>() -> clap::App<'a, 'b> {
|
||||
.takes_value(true)
|
||||
);
|
||||
#[cfg(feature = "eth")]
|
||||
#[cfg(not(feature = "coconut"))]
|
||||
let app = app
|
||||
.arg(
|
||||
Arg::with_name(TESTNET_MODE_ARG_NAME)
|
||||
@@ -80,7 +82,7 @@ fn version_check(cfg: &Config) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn execute(matches: &ArgMatches) {
|
||||
pub async fn execute(matches: ArgMatches<'static>) {
|
||||
let id = matches.value_of("id").unwrap();
|
||||
|
||||
let mut config = match Config::load_from_file(Some(id)) {
|
||||
@@ -91,12 +93,12 @@ pub fn execute(matches: &ArgMatches) {
|
||||
}
|
||||
};
|
||||
|
||||
config = override_config(config, matches);
|
||||
config = override_config(config, &matches);
|
||||
|
||||
if !version_check(&config) {
|
||||
error!("failed the local version check");
|
||||
return;
|
||||
}
|
||||
|
||||
NymClient::new(config).run_forever();
|
||||
NymClient::new(config).run_forever().await;
|
||||
}
|
||||
|
||||
@@ -7,7 +7,8 @@ pub mod client;
|
||||
pub mod commands;
|
||||
pub mod websocket;
|
||||
|
||||
fn main() {
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
dotenv::dotenv().ok();
|
||||
setup_logging();
|
||||
println!("{}", banner());
|
||||
@@ -22,13 +23,13 @@ fn main() {
|
||||
.subcommand(commands::upgrade::command_args())
|
||||
.get_matches();
|
||||
|
||||
execute(arg_matches);
|
||||
execute(arg_matches).await;
|
||||
}
|
||||
|
||||
fn execute(matches: ArgMatches) {
|
||||
async fn execute(matches: ArgMatches<'static>) {
|
||||
match matches.subcommand() {
|
||||
("init", Some(m)) => commands::init::execute(m),
|
||||
("run", Some(m)) => commands::run::execute(m),
|
||||
("init", Some(m)) => commands::init::execute(m.clone()).await,
|
||||
("run", Some(m)) => commands::run::execute(m.clone()).await,
|
||||
("upgrade", Some(m)) => commands::upgrade::execute(m),
|
||||
_ => println!("{}", usage()),
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ use super::handler::Handler;
|
||||
use log::*;
|
||||
use std::{net::SocketAddr, process, sync::Arc};
|
||||
use tokio::io::AsyncWriteExt;
|
||||
use tokio::runtime;
|
||||
use tokio::{sync::Notify, task::JoinHandle};
|
||||
|
||||
enum State {
|
||||
@@ -87,9 +86,9 @@ impl Listener {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn start(mut self, rt_handle: &runtime::Handle, handler: Handler) -> JoinHandle<()> {
|
||||
pub(crate) fn start(mut self, handler: Handler) -> JoinHandle<()> {
|
||||
info!("Running websocket on {:?}", self.address.to_string());
|
||||
|
||||
rt_handle.spawn(async move { self.run(handler).await })
|
||||
tokio::spawn(async move { self.run(handler).await })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,6 @@ use gateway_client::{
|
||||
use log::*;
|
||||
use nymsphinx::addressing::clients::Recipient;
|
||||
use nymsphinx::addressing::nodes::NodeIdentity;
|
||||
use tokio::runtime::Runtime;
|
||||
|
||||
use crate::client::config::Config;
|
||||
use crate::socks::{
|
||||
@@ -43,11 +42,6 @@ pub struct NymClient {
|
||||
/// key filepaths, etc.
|
||||
config: Config,
|
||||
|
||||
/// Tokio runtime used for futures execution.
|
||||
// TODO: JS: Personally I think I prefer the implicit way of using it that we've done with the
|
||||
// gateway.
|
||||
runtime: Runtime,
|
||||
|
||||
/// KeyManager object containing smart pointers to all relevant keys used by the client.
|
||||
key_manager: KeyManager,
|
||||
}
|
||||
@@ -58,7 +52,6 @@ impl NymClient {
|
||||
let key_manager = KeyManager::load_keys(&pathfinder).expect("failed to load stored keys");
|
||||
|
||||
NymClient {
|
||||
runtime: Runtime::new().unwrap(),
|
||||
config,
|
||||
key_manager,
|
||||
}
|
||||
@@ -82,9 +75,6 @@ impl NymClient {
|
||||
mix_tx: BatchMixMessageSender,
|
||||
) {
|
||||
info!("Starting loop cover traffic stream...");
|
||||
// we need to explicitly enter runtime due to "next_delay: time::delay_for(Default::default())"
|
||||
// set in the constructor which HAS TO be called within context of a tokio runtime
|
||||
let _guard = self.runtime.enter();
|
||||
|
||||
LoopCoverTrafficStream::new(
|
||||
self.key_manager.ack_key(),
|
||||
@@ -97,7 +87,7 @@ impl NymClient {
|
||||
self.as_mix_recipient(),
|
||||
topology_accessor,
|
||||
)
|
||||
.start(self.runtime.handle());
|
||||
.start();
|
||||
}
|
||||
|
||||
fn start_real_traffic_controller(
|
||||
@@ -119,10 +109,6 @@ impl NymClient {
|
||||
);
|
||||
|
||||
info!("Starting real traffic stream...");
|
||||
// we need to explicitly enter runtime due to "next_delay: time::delay_for(Default::default())"
|
||||
// set in the constructor [of OutQueueControl] which HAS TO be called within context of a tokio runtime
|
||||
// When refactoring this restriction should definitely be removed.
|
||||
let _guard = self.runtime.enter();
|
||||
|
||||
RealMessagesController::new(
|
||||
controller_config,
|
||||
@@ -132,7 +118,7 @@ impl NymClient {
|
||||
topology_accessor,
|
||||
reply_key_storage,
|
||||
)
|
||||
.start(self.runtime.handle());
|
||||
.start();
|
||||
}
|
||||
|
||||
// buffer controlling all messages fetched from provider
|
||||
@@ -150,10 +136,10 @@ impl NymClient {
|
||||
mixnet_receiver,
|
||||
reply_key_storage,
|
||||
)
|
||||
.start(self.runtime.handle())
|
||||
.start()
|
||||
}
|
||||
|
||||
fn start_gateway_client(
|
||||
async fn start_gateway_client(
|
||||
&mut self,
|
||||
mixnet_message_sender: MixnetMessageSender,
|
||||
ack_sender: AcknowledgementSender,
|
||||
@@ -170,47 +156,44 @@ impl NymClient {
|
||||
let gateway_identity = identity::PublicKey::from_base58_string(gateway_id)
|
||||
.expect("provided gateway id is invalid!");
|
||||
|
||||
self.runtime.block_on(async {
|
||||
#[cfg(feature = "coconut")]
|
||||
let bandwidth_controller = BandwidthController::new(
|
||||
self.config.get_base().get_validator_api_endpoints(),
|
||||
*self.key_manager.identity_keypair().public_key(),
|
||||
);
|
||||
#[cfg(not(feature = "coconut"))]
|
||||
let bandwidth_controller = BandwidthController::new(
|
||||
self.config.get_base().get_eth_endpoint(),
|
||||
self.config.get_base().get_eth_private_key(),
|
||||
self.config.get_base().get_backup_bandwidth_token_keys_dir(),
|
||||
)
|
||||
.expect("Could not create bandwidth controller");
|
||||
#[cfg(feature = "coconut")]
|
||||
let bandwidth_controller = BandwidthController::new(
|
||||
self.config.get_base().get_validator_api_endpoints(),
|
||||
*self.key_manager.identity_keypair().public_key(),
|
||||
);
|
||||
#[cfg(not(feature = "coconut"))]
|
||||
let bandwidth_controller = BandwidthController::new(
|
||||
self.config.get_base().get_eth_endpoint(),
|
||||
self.config.get_base().get_eth_private_key(),
|
||||
self.config.get_base().get_backup_bandwidth_token_keys_dir(),
|
||||
)
|
||||
.expect("Could not create bandwidth controller");
|
||||
|
||||
let mut gateway_client = GatewayClient::new(
|
||||
gateway_address,
|
||||
self.key_manager.identity_keypair(),
|
||||
gateway_identity,
|
||||
Some(self.key_manager.gateway_shared_key()),
|
||||
mixnet_message_sender,
|
||||
ack_sender,
|
||||
self.config.get_base().get_gateway_response_timeout(),
|
||||
Some(bandwidth_controller),
|
||||
);
|
||||
let mut gateway_client = GatewayClient::new(
|
||||
gateway_address,
|
||||
self.key_manager.identity_keypair(),
|
||||
gateway_identity,
|
||||
Some(self.key_manager.gateway_shared_key()),
|
||||
mixnet_message_sender,
|
||||
ack_sender,
|
||||
self.config.get_base().get_gateway_response_timeout(),
|
||||
Some(bandwidth_controller),
|
||||
);
|
||||
|
||||
if self.config.get_base().get_testnet_mode() {
|
||||
gateway_client.set_testnet_mode(true)
|
||||
}
|
||||
if self.config.get_base().get_testnet_mode() {
|
||||
gateway_client.set_testnet_mode(true)
|
||||
}
|
||||
gateway_client
|
||||
.authenticate_and_start()
|
||||
.await
|
||||
.expect("could not authenticate and start up the gateway connection");
|
||||
|
||||
gateway_client
|
||||
.authenticate_and_start()
|
||||
.await
|
||||
.expect("could not authenticate and start up the gateway connection");
|
||||
|
||||
gateway_client
|
||||
})
|
||||
gateway_client
|
||||
}
|
||||
|
||||
// future responsible for periodically polling directory server and updating
|
||||
// the current global view of topology
|
||||
fn start_topology_refresher(&mut self, topology_accessor: TopologyAccessor) {
|
||||
async fn start_topology_refresher(&mut self, topology_accessor: TopologyAccessor) {
|
||||
let topology_refresher_config = TopologyRefresherConfig::new(
|
||||
self.config.get_base().get_validator_api_endpoints(),
|
||||
self.config.get_base().get_topology_refresh_rate(),
|
||||
@@ -221,13 +204,10 @@ impl NymClient {
|
||||
// before returning, block entire runtime to refresh the current network view so that any
|
||||
// components depending on topology would see a non-empty view
|
||||
info!("Obtaining initial network topology");
|
||||
self.runtime.block_on(topology_refresher.refresh());
|
||||
topology_refresher.refresh().await;
|
||||
|
||||
// TODO: a slightly more graceful termination here
|
||||
if !self
|
||||
.runtime
|
||||
.block_on(topology_refresher.is_topology_routable())
|
||||
{
|
||||
if !topology_refresher.is_topology_routable().await {
|
||||
panic!(
|
||||
"The current network topology seem to be insufficient to route any packets through\
|
||||
- check if enough nodes and a gateway are online"
|
||||
@@ -235,7 +215,7 @@ impl NymClient {
|
||||
}
|
||||
|
||||
info!("Starting topology refresher...");
|
||||
topology_refresher.start(self.runtime.handle());
|
||||
topology_refresher.start();
|
||||
}
|
||||
|
||||
// controller for sending sphinx packets to mixnet (either real traffic or cover traffic)
|
||||
@@ -248,7 +228,7 @@ impl NymClient {
|
||||
gateway_client: GatewayClient,
|
||||
) {
|
||||
info!("Starting mix traffic controller...");
|
||||
MixTrafficController::new(mix_rx, gateway_client).start(self.runtime.handle());
|
||||
MixTrafficController::new(mix_rx, gateway_client).start();
|
||||
}
|
||||
|
||||
fn start_socks5_listener(
|
||||
@@ -267,14 +247,13 @@ impl NymClient {
|
||||
self.config.get_provider_mix_address(),
|
||||
self.as_mix_recipient(),
|
||||
);
|
||||
self.runtime
|
||||
.spawn(async move { sphinx_socks.serve(msg_input, buffer_requester).await });
|
||||
tokio::spawn(async move { sphinx_socks.serve(msg_input, buffer_requester).await });
|
||||
}
|
||||
|
||||
/// blocking version of `start` method. Will run forever (or until SIGINT is sent)
|
||||
pub fn run_forever(&mut self) {
|
||||
self.start();
|
||||
if let Err(e) = self.runtime.block_on(tokio::signal::ctrl_c()) {
|
||||
pub async fn run_forever(&mut self) {
|
||||
self.start().await;
|
||||
if let Err(e) = tokio::signal::ctrl_c().await {
|
||||
error!(
|
||||
"There was an error while capturing SIGINT - {:?}. We will terminate regardless",
|
||||
e
|
||||
@@ -286,7 +265,7 @@ impl NymClient {
|
||||
);
|
||||
}
|
||||
|
||||
pub fn start(&mut self) {
|
||||
pub async fn start(&mut self) {
|
||||
info!("Starting nym client");
|
||||
// channels for inter-component communication
|
||||
// TODO: make the channels be internally created by the relevant components
|
||||
@@ -318,14 +297,17 @@ impl NymClient {
|
||||
|
||||
// the components are started in very specific order. Unless you know what you are doing,
|
||||
// do not change that.
|
||||
self.start_topology_refresher(shared_topology_accessor.clone());
|
||||
self.start_topology_refresher(shared_topology_accessor.clone())
|
||||
.await;
|
||||
self.start_received_messages_buffer_controller(
|
||||
received_buffer_request_receiver,
|
||||
mixnet_messages_receiver,
|
||||
reply_key_storage.clone(),
|
||||
);
|
||||
|
||||
let gateway_client = self.start_gateway_client(mixnet_messages_sender, ack_sender);
|
||||
let gateway_client = self
|
||||
.start_gateway_client(mixnet_messages_sender, ack_sender)
|
||||
.await;
|
||||
|
||||
self.start_mix_traffic_controller(sphinx_message_receiver, gateway_client);
|
||||
self.start_real_traffic_controller(
|
||||
|
||||
@@ -30,6 +30,7 @@ use url::Url;
|
||||
use crate::client::config::Config;
|
||||
use crate::commands::override_config;
|
||||
#[cfg(feature = "eth")]
|
||||
#[cfg(not(feature = "coconut"))]
|
||||
use crate::commands::{
|
||||
DEFAULT_ETH_ENDPOINT, DEFAULT_ETH_PRIVATE_KEY, ETH_ENDPOINT_ARG_NAME, ETH_PRIVATE_KEY_ARG_NAME,
|
||||
TESTNET_MODE_ARG_NAME,
|
||||
@@ -72,6 +73,7 @@ pub fn command_args<'a, 'b>() -> clap::App<'a, 'b> {
|
||||
.help("Mostly debug-related option to increase default traffic rate so that you would not need to modify config post init")
|
||||
);
|
||||
#[cfg(feature = "eth")]
|
||||
#[cfg(not(feature = "coconut"))]
|
||||
let app = app
|
||||
.arg(
|
||||
Arg::with_name(TESTNET_MODE_ARG_NAME)
|
||||
@@ -217,7 +219,7 @@ fn show_address(config: &Config) {
|
||||
println!("\nThe address of this client is: {}", client_recipient);
|
||||
}
|
||||
|
||||
pub fn execute(matches: &ArgMatches) {
|
||||
pub async fn execute(matches: ArgMatches<'static>) {
|
||||
println!("Initialising client...");
|
||||
|
||||
let id = matches.value_of("id").unwrap(); // required for now
|
||||
@@ -236,7 +238,7 @@ pub fn execute(matches: &ArgMatches) {
|
||||
|
||||
// TODO: ideally that should be the last thing that's being done to config.
|
||||
// However, we are later further overriding it with gateway id
|
||||
config = override_config(config, matches);
|
||||
config = override_config(config, &matches);
|
||||
if matches.is_present("fastmode") {
|
||||
config.get_base_mut().set_high_default_traffic_volume();
|
||||
}
|
||||
@@ -249,26 +251,20 @@ pub fn execute(matches: &ArgMatches) {
|
||||
|
||||
let chosen_gateway_id = matches.value_of("gateway");
|
||||
|
||||
let registration_fut = async {
|
||||
let gate_details = gateway_details(
|
||||
config.get_base().get_validator_api_endpoints(),
|
||||
chosen_gateway_id,
|
||||
)
|
||||
.await;
|
||||
config
|
||||
.get_base_mut()
|
||||
.with_gateway_id(gate_details.identity_key.to_base58_string());
|
||||
let shared_keys =
|
||||
register_with_gateway(&gate_details, key_manager.identity_keypair()).await;
|
||||
(shared_keys, gate_details.clients_address())
|
||||
};
|
||||
|
||||
// TODO: is there perhaps a way to make it work without having to spawn entire runtime?
|
||||
let rt = tokio::runtime::Runtime::new().unwrap();
|
||||
let (shared_keys, gateway_listener) = rt.block_on(registration_fut);
|
||||
let gateway_details = gateway_details(
|
||||
config.get_base().get_validator_api_endpoints(),
|
||||
chosen_gateway_id,
|
||||
)
|
||||
.await;
|
||||
config
|
||||
.get_base_mut()
|
||||
.with_gateway_listener(gateway_listener);
|
||||
.with_gateway_id(gateway_details.identity_key.to_base58_string());
|
||||
let shared_keys =
|
||||
register_with_gateway(&gateway_details, key_manager.identity_keypair()).await;
|
||||
|
||||
config
|
||||
.get_base_mut()
|
||||
.with_gateway_listener(gateway_details.clients_address());
|
||||
key_manager.insert_gateway_shared_key(shared_keys);
|
||||
|
||||
let pathfinder = ClientKeyPathfinder::new_from_config(config.get_base());
|
||||
|
||||
@@ -5,6 +5,7 @@ use crate::client::config::Config;
|
||||
use crate::client::NymClient;
|
||||
use crate::commands::override_config;
|
||||
#[cfg(feature = "eth")]
|
||||
#[cfg(not(feature = "coconut"))]
|
||||
use crate::commands::{ETH_ENDPOINT_ARG_NAME, ETH_PRIVATE_KEY_ARG_NAME, TESTNET_MODE_ARG_NAME};
|
||||
use clap::{App, Arg, ArgMatches};
|
||||
use config::NymConfig;
|
||||
@@ -48,6 +49,7 @@ pub fn command_args<'a, 'b>() -> clap::App<'a, 'b> {
|
||||
.takes_value(true)
|
||||
);
|
||||
#[cfg(feature = "eth")]
|
||||
#[cfg(not(feature = "coconut"))]
|
||||
let app = app
|
||||
.arg(
|
||||
Arg::with_name(TESTNET_MODE_ARG_NAME)
|
||||
@@ -86,7 +88,7 @@ fn version_check(cfg: &Config) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn execute(matches: &ArgMatches) {
|
||||
pub async fn execute(matches: ArgMatches<'static>) {
|
||||
let id = matches.value_of("id").unwrap();
|
||||
|
||||
let mut config = match Config::load_from_file(Some(id)) {
|
||||
@@ -97,12 +99,12 @@ pub fn execute(matches: &ArgMatches) {
|
||||
}
|
||||
};
|
||||
|
||||
config = override_config(config, matches);
|
||||
config = override_config(config, &matches);
|
||||
|
||||
if !version_check(&config) {
|
||||
error!("failed the local version check");
|
||||
return;
|
||||
}
|
||||
|
||||
NymClient::new(config).run_forever();
|
||||
NymClient::new(config).run_forever().await;
|
||||
}
|
||||
|
||||
@@ -7,7 +7,8 @@ pub mod client;
|
||||
mod commands;
|
||||
pub mod socks;
|
||||
|
||||
fn main() {
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
dotenv::dotenv().ok();
|
||||
setup_logging();
|
||||
println!("{}", banner());
|
||||
@@ -22,13 +23,13 @@ fn main() {
|
||||
.subcommand(commands::upgrade::command_args())
|
||||
.get_matches();
|
||||
|
||||
execute(arg_matches);
|
||||
execute(arg_matches).await;
|
||||
}
|
||||
|
||||
fn execute(matches: ArgMatches) {
|
||||
async fn execute(matches: ArgMatches<'static>) {
|
||||
match matches.subcommand() {
|
||||
("init", Some(m)) => commands::init::execute(m),
|
||||
("run", Some(m)) => commands::run::execute(m),
|
||||
("init", Some(m)) => commands::init::execute(m.clone()).await,
|
||||
("run", Some(m)) => commands::run::execute(m.clone()).await,
|
||||
("upgrade", Some(m)) => commands::upgrade::execute(m),
|
||||
_ => println!("{}", usage()),
|
||||
}
|
||||
|
||||
@@ -433,6 +433,14 @@ export default class ValidatorClient implements INymClient {
|
||||
return (this.client as ISigningClient).undelegateFromMixNode(this.mixnetContract, mixIdentity, fee, memo);
|
||||
}
|
||||
|
||||
public async updateMixnodeConfig(
|
||||
mixIdentity: string,
|
||||
fee: StdFee | 'auto' | number,
|
||||
profitPercentage: number,
|
||||
): Promise<ExecuteResult> {
|
||||
return (this.client as ISigningClient).updateMixnodeConfig(this.mixnetContract, mixIdentity, profitPercentage, fee);
|
||||
}
|
||||
|
||||
public async updateContractStateParams(
|
||||
newParams: ContractStateParams,
|
||||
fee?: StdFee | 'auto' | number,
|
||||
@@ -441,4 +449,4 @@ export default class ValidatorClient implements INymClient {
|
||||
this.assertSigning();
|
||||
return (this.client as ISigningClient).updateContractStateParams(this.mixnetContract, newParams, fee, memo);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -178,6 +178,13 @@ export interface ISigningClient extends IQueryClient, ICosmWasmSigning, INymSign
|
||||
memo?: string,
|
||||
): Promise<ExecuteResult>;
|
||||
|
||||
updateMixnodeConfig(
|
||||
mixnetContractAddress: string,
|
||||
mixIdentity: string,
|
||||
profitMarginPercent: number,
|
||||
fee: StdFee | 'auto' | number,
|
||||
): Promise<ExecuteResult>;
|
||||
|
||||
updateContractStateParams(
|
||||
mixnetContractAddress: string,
|
||||
newParams: ContractStateParams,
|
||||
@@ -448,6 +455,20 @@ export default class SigningClient extends SigningCosmWasmClient implements ISig
|
||||
);
|
||||
}
|
||||
|
||||
updateMixnodeConfig(
|
||||
mixnetContractAddress: string,
|
||||
mixIdentity: string,
|
||||
profitMarginPercent: number,
|
||||
fee: StdFee | 'auto' | number,
|
||||
): Promise<ExecuteResult> {
|
||||
return this.execute(
|
||||
this.clientAddress,
|
||||
mixnetContractAddress,
|
||||
{ update_mixnode_config: { profit_margin_percent: profitMarginPercent, mix_identity: mixIdentity } },
|
||||
fee,
|
||||
);
|
||||
}
|
||||
|
||||
updateContractStateParams(
|
||||
mixnetContractAddress: string,
|
||||
newParams: ContractStateParams,
|
||||
|
||||
@@ -135,6 +135,7 @@ export type MixNode = {
|
||||
sphinx_key: string;
|
||||
identity_key: string;
|
||||
version: string;
|
||||
profit_margin_percent: number;
|
||||
};
|
||||
|
||||
export type GatewayBond = {
|
||||
|
||||
@@ -9,7 +9,7 @@ rust-version = "1.56"
|
||||
|
||||
[dependencies]
|
||||
base64 = "0.13"
|
||||
mixnet-contract = { path="../../../common/mixnet-contract" }
|
||||
mixnet-contract-common = { path= "../../cosmwasm-smart-contracts/mixnet-contract" }
|
||||
vesting-contract = { path="../../../contracts/vesting" }
|
||||
serde = { version="1", features=["derive"] }
|
||||
serde_json = "1"
|
||||
@@ -20,6 +20,7 @@ url = { version = "2.2", features = ["serde"] }
|
||||
|
||||
coconut-interface = { path = "../../coconut-interface" }
|
||||
network-defaults = { path = "../../network-defaults" }
|
||||
validator-api-requests = { path = "../../../validator-api/validator-api-requests" }
|
||||
|
||||
# required for nymd-client
|
||||
# at some point it might be possible to make it wasm-compatible
|
||||
@@ -27,8 +28,7 @@ network-defaults = { path = "../../network-defaults" }
|
||||
async-trait = { version = "0.1.51", optional = true }
|
||||
bip39 = { version = "1", features = ["rand"], optional = true }
|
||||
config = { path = "../../config", optional = true }
|
||||
#cosmrs = { version = "0.3", features = ["rpc", "bip32", "cosmwasm"], optional = true }
|
||||
cosmrs = { git = "https://github.com/cosmos/cosmos-rust", rev="e5a1872083abb3d88fa62dda966e7f5408deba58", features = ["rpc", "bip32", "cosmwasm"], optional = true }
|
||||
cosmrs = { version = "0.4.1", features = ["rpc", "bip32", "cosmwasm"], optional = true }
|
||||
prost = { version = "0.9", default-features = false, optional = true }
|
||||
flate2 = { version = "1.0.20", optional = true }
|
||||
sha2 = { version = "0.9.5", optional = true }
|
||||
@@ -38,3 +38,4 @@ ts-rs = {version = "5.1", optional = true}
|
||||
|
||||
[features]
|
||||
nymd-client = ["async-trait", "bip39", "config", "cosmrs", "prost", "flate2", "sha2", "itertools", "cosmwasm-std"]
|
||||
typescript-types = ["ts-rs", "validator-api-requests/ts-rs"]
|
||||
|
||||
@@ -6,21 +6,26 @@ use crate::nymd::{
|
||||
error::NymdError, CosmWasmClient, NymdClient, QueryNymdClient, SigningNymdClient,
|
||||
};
|
||||
#[cfg(feature = "nymd-client")]
|
||||
use mixnet_contract::ContractStateParams;
|
||||
use mixnet_contract_common::ContractStateParams;
|
||||
|
||||
use crate::{validator_api, ValidatorClientError};
|
||||
use coconut_interface::{BlindSignRequestBody, BlindedSignatureResponse, VerificationKeyResponse};
|
||||
#[cfg(feature = "nymd-client")]
|
||||
use mixnet_contract::{
|
||||
use mixnet_contract_common::{
|
||||
Delegation, MixnetContractVersion, MixnodeRewardingStatusResponse, RewardingIntervalResponse,
|
||||
};
|
||||
use mixnet_contract::{GatewayBond, MixNodeBond};
|
||||
use mixnet_contract_common::{GatewayBond, IdentityKeyRef, MixNodeBond};
|
||||
|
||||
#[cfg(feature = "nymd-client")]
|
||||
use std::str::FromStr;
|
||||
use url::Url;
|
||||
use validator_api_requests::models::{
|
||||
CoreNodeStatusResponse, MixnodeStatusResponse, RewardEstimationResponse,
|
||||
StakeSaturationResponse,
|
||||
};
|
||||
|
||||
#[cfg(feature = "nymd-client")]
|
||||
#[must_use]
|
||||
pub struct Config {
|
||||
api_url: Url,
|
||||
nymd_url: Url,
|
||||
@@ -127,14 +132,14 @@ impl Client<QueryNymdClient> {
|
||||
let validator_api_client = validator_api::Client::new(config.api_url.clone());
|
||||
let nymd_client = NymdClient::connect(
|
||||
config.nymd_url.as_str(),
|
||||
config.mixnet_contract_address.clone().unwrap_or_else(|| {
|
||||
Some(config.mixnet_contract_address.clone().unwrap_or_else(|| {
|
||||
cosmrs::AccountId::from_str(network_defaults::DEFAULT_MIXNET_CONTRACT_ADDRESS)
|
||||
.unwrap()
|
||||
}),
|
||||
config.vesting_contract_address.clone().unwrap_or_else(|| {
|
||||
})),
|
||||
Some(config.vesting_contract_address.clone().unwrap_or_else(|| {
|
||||
cosmrs::AccountId::from_str(network_defaults::DEFAULT_VESTING_CONTRACT_ADDRESS)
|
||||
.unwrap()
|
||||
}),
|
||||
})),
|
||||
)?;
|
||||
|
||||
Ok(Client {
|
||||
@@ -152,8 +157,8 @@ impl Client<QueryNymdClient> {
|
||||
pub fn change_nymd(&mut self, new_endpoint: Url) -> Result<(), ValidatorClientError> {
|
||||
self.nymd = NymdClient::connect(
|
||||
new_endpoint.as_ref(),
|
||||
self.mixnet_contract_address.clone().unwrap(),
|
||||
self.vesting_contract_address.clone().unwrap(),
|
||||
self.mixnet_contract_address.clone(),
|
||||
self.vesting_contract_address.clone(),
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
@@ -208,7 +213,7 @@ impl<C> Client<C> {
|
||||
|
||||
pub async fn get_rewarding_status(
|
||||
&self,
|
||||
mix_identity: mixnet_contract::IdentityKey,
|
||||
mix_identity: mixnet_contract_common::IdentityKey,
|
||||
rewarding_interval_nonce: u32,
|
||||
) -> Result<MixnodeRewardingStatusResponse, ValidatorClientError>
|
||||
where
|
||||
@@ -297,8 +302,8 @@ impl<C> Client<C> {
|
||||
|
||||
pub async fn get_all_nymd_single_mixnode_delegations(
|
||||
&self,
|
||||
identity: mixnet_contract::IdentityKey,
|
||||
) -> Result<Vec<mixnet_contract::Delegation>, ValidatorClientError>
|
||||
identity: mixnet_contract_common::IdentityKey,
|
||||
) -> Result<Vec<mixnet_contract_common::Delegation>, ValidatorClientError>
|
||||
where
|
||||
C: CosmWasmClient + Sync,
|
||||
{
|
||||
@@ -420,6 +425,12 @@ impl ApiClient {
|
||||
Ok(self.validator_api.get_active_mixnodes().await?)
|
||||
}
|
||||
|
||||
pub async fn get_cached_rewarded_mixnodes(
|
||||
&self,
|
||||
) -> Result<Vec<MixNodeBond>, ValidatorClientError> {
|
||||
Ok(self.validator_api.get_rewarded_mixnodes().await?)
|
||||
}
|
||||
|
||||
pub async fn get_cached_mixnodes(&self) -> Result<Vec<MixNodeBond>, ValidatorClientError> {
|
||||
Ok(self.validator_api.get_mixnodes().await?)
|
||||
}
|
||||
@@ -428,6 +439,55 @@ impl ApiClient {
|
||||
Ok(self.validator_api.get_gateways().await?)
|
||||
}
|
||||
|
||||
pub async fn get_gateway_core_status_count(
|
||||
&self,
|
||||
identity: IdentityKeyRef<'_>,
|
||||
since: Option<i64>,
|
||||
) -> Result<CoreNodeStatusResponse, ValidatorClientError> {
|
||||
Ok(self
|
||||
.validator_api
|
||||
.get_gateway_core_status_count(identity, since)
|
||||
.await?)
|
||||
}
|
||||
|
||||
pub async fn get_mixnode_core_status_count(
|
||||
&self,
|
||||
identity: IdentityKeyRef<'_>,
|
||||
since: Option<i64>,
|
||||
) -> Result<CoreNodeStatusResponse, ValidatorClientError> {
|
||||
Ok(self
|
||||
.validator_api
|
||||
.get_mixnode_core_status_count(identity, since)
|
||||
.await?)
|
||||
}
|
||||
|
||||
pub async fn get_mixnode_status(
|
||||
&self,
|
||||
identity: IdentityKeyRef<'_>,
|
||||
) -> Result<MixnodeStatusResponse, ValidatorClientError> {
|
||||
Ok(self.validator_api.get_mixnode_status(identity).await?)
|
||||
}
|
||||
|
||||
pub async fn get_mixnode_reward_estimation(
|
||||
&self,
|
||||
identity: IdentityKeyRef<'_>,
|
||||
) -> Result<RewardEstimationResponse, ValidatorClientError> {
|
||||
Ok(self
|
||||
.validator_api
|
||||
.get_mixnode_reward_estimation(identity)
|
||||
.await?)
|
||||
}
|
||||
|
||||
pub async fn get_mixnode_stake_saturation(
|
||||
&self,
|
||||
identity: IdentityKeyRef<'_>,
|
||||
) -> Result<StakeSaturationResponse, ValidatorClientError> {
|
||||
Ok(self
|
||||
.validator_api
|
||||
.get_mixnode_stake_saturation(identity)
|
||||
.await?)
|
||||
}
|
||||
|
||||
pub async fn blind_sign(
|
||||
&self,
|
||||
request_body: &BlindSignRequestBody,
|
||||
|
||||
@@ -9,6 +9,7 @@ pub mod validator_api;
|
||||
|
||||
pub use crate::client::ApiClient;
|
||||
pub use crate::error::ValidatorClientError;
|
||||
pub use validator_api_requests::*;
|
||||
|
||||
#[cfg(feature = "nymd-client")]
|
||||
pub use client::{Client, Config};
|
||||
|
||||
@@ -13,6 +13,7 @@ use cosmrs::proto::cosmos::auth::v1beta1::{
|
||||
};
|
||||
use cosmrs::proto::cosmos::bank::v1beta1::{
|
||||
QueryAllBalancesRequest, QueryAllBalancesResponse, QueryBalanceRequest, QueryBalanceResponse,
|
||||
QueryTotalSupplyRequest, QueryTotalSupplyResponse,
|
||||
};
|
||||
use cosmrs::proto::cosmos::tx::v1beta1::{
|
||||
SimulateRequest, SimulateResponse as ProtoSimulateResponse,
|
||||
@@ -27,6 +28,7 @@ use cosmrs::tendermint::abci::Code as AbciCode;
|
||||
use cosmrs::tendermint::abci::Transaction;
|
||||
use cosmrs::tendermint::{abci, block, chain};
|
||||
use cosmrs::{tx, AccountId, Coin, Denom, Tx};
|
||||
use cosmwasm_std::Coin as CosmWasmCoin;
|
||||
use prost::Message;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::convert::{TryFrom, TryInto};
|
||||
@@ -162,6 +164,43 @@ pub trait CosmWasmClient: rpc::Client {
|
||||
.map_err(|_| NymdError::SerializationError("Coins".to_owned()))
|
||||
}
|
||||
|
||||
// this is annoyingly and inconsistently returning `Vec<CosmWasmCoin>` rather than
|
||||
// Vec<Coin>, since cosmrs::Coin can't deal with IBC denoms.
|
||||
// Presumably after https://github.com/cosmos/cosmos-rust/issues/173 is resolved,
|
||||
// the code could be adjusted
|
||||
async fn get_total_supply(&self) -> Result<Vec<CosmWasmCoin>, NymdError> {
|
||||
let path = Some("/cosmos.bank.v1beta1.Query/TotalSupply".parse().unwrap());
|
||||
|
||||
let mut supply = Vec::new();
|
||||
let mut pagination = None;
|
||||
|
||||
loop {
|
||||
let req = QueryTotalSupplyRequest { pagination };
|
||||
|
||||
let mut res = self
|
||||
.make_abci_query::<_, QueryTotalSupplyResponse>(path.clone(), req)
|
||||
.await?;
|
||||
|
||||
supply.append(&mut res.supply);
|
||||
if let Some(pagination_info) = res.pagination {
|
||||
pagination = Some(create_pagination(pagination_info.next_key))
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
supply
|
||||
.into_iter()
|
||||
.map(|coin| {
|
||||
coin.amount.parse().map(|amount| CosmWasmCoin {
|
||||
denom: coin.denom,
|
||||
amount,
|
||||
})
|
||||
})
|
||||
.collect::<Result<_, _>>()
|
||||
.map_err(|_| NymdError::SerializationError("Coins".to_owned()))
|
||||
}
|
||||
|
||||
async fn get_tx(&self, id: tx::Hash) -> Result<TxResponse, NymdError> {
|
||||
Ok(self.tx(id, false).await?)
|
||||
}
|
||||
|
||||
@@ -160,10 +160,7 @@ pub trait SigningCosmWasmClient: CosmWasmClient {
|
||||
{
|
||||
let init_msg = cosmwasm::MsgInstantiateContract {
|
||||
sender: sender_address.clone(),
|
||||
admin: options
|
||||
.as_mut()
|
||||
.map(|options| options.admin.take())
|
||||
.flatten(),
|
||||
admin: options.as_mut().and_then(|options| options.admin.take()),
|
||||
code_id,
|
||||
// now this is a weird one. the protobuf files say this field is optional,
|
||||
// but if you omit it, the initialisation will fail CheckTx
|
||||
|
||||
@@ -20,6 +20,7 @@ pub enum Operation {
|
||||
BondMixnodeOnBehalf,
|
||||
UnbondMixnode,
|
||||
UnbondMixnodeOnBehalf,
|
||||
UpdateMixnodeConfig,
|
||||
DelegateToMixnode,
|
||||
DelegateToMixnodeOnBehalf,
|
||||
UndelegateFromMixnode,
|
||||
@@ -57,6 +58,7 @@ impl fmt::Display for Operation {
|
||||
Operation::BondMixnode => f.write_str("BondMixnode"),
|
||||
Operation::BondMixnodeOnBehalf => f.write_str("BondMixnodeOnBehalf"),
|
||||
Operation::UnbondMixnode => f.write_str("UnbondMixnode"),
|
||||
Operation::UpdateMixnodeConfig => f.write_str("UpdateMixnodeConfig"),
|
||||
Operation::UnbondMixnodeOnBehalf => f.write_str("UnbondMixnodeOnBehalf"),
|
||||
Operation::BondGateway => f.write_str("BondGateway"),
|
||||
Operation::BondGatewayOnBehalf => f.write_str("BondGatewayOnBehalf"),
|
||||
@@ -94,6 +96,7 @@ impl Operation {
|
||||
Operation::BondMixnodeOnBehalf => 200_000u64.into(),
|
||||
Operation::UnbondMixnode => 175_000u64.into(),
|
||||
Operation::UnbondMixnodeOnBehalf => 175_000u64.into(),
|
||||
Operation::UpdateMixnodeConfig => 175_000u64.into(),
|
||||
Operation::DelegateToMixnode => 175_000u64.into(),
|
||||
Operation::DelegateToMixnodeOnBehalf => 175_000u64.into(),
|
||||
Operation::UndelegateFromMixnode => 175_000u64.into(),
|
||||
|
||||
@@ -13,7 +13,7 @@ use cosmrs::rpc::{Error as TendermintRpcError, HttpClientUrl};
|
||||
use cosmwasm_std::{Coin, Uint128};
|
||||
pub use fee::gas_price::GasPrice;
|
||||
use fee::helpers::Operation;
|
||||
use mixnet_contract::{
|
||||
use mixnet_contract_common::{
|
||||
ContractStateParams, Delegation, ExecuteMsg, Gateway, GatewayBond, GatewayOwnershipResponse,
|
||||
IdentityKey, LayerDistribution, MixNode, MixNodeBond, MixOwnershipResponse,
|
||||
MixnetContractVersion, MixnodeRewardingStatusResponse, PagedAllDelegationsResponse,
|
||||
@@ -57,16 +57,16 @@ pub struct NymdClient<C> {
|
||||
impl NymdClient<QueryNymdClient> {
|
||||
pub fn connect<U>(
|
||||
endpoint: U,
|
||||
mixnet_contract_address: AccountId,
|
||||
vesting_contract_address: AccountId,
|
||||
mixnet_contract_address: Option<AccountId>,
|
||||
vesting_contract_address: Option<AccountId>,
|
||||
) -> Result<NymdClient<QueryNymdClient>, NymdError>
|
||||
where
|
||||
U: TryInto<HttpClientUrl, Error = TendermintRpcError>,
|
||||
{
|
||||
Ok(NymdClient {
|
||||
client: QueryNymdClient::new(endpoint)?,
|
||||
mixnet_contract_address: Some(mixnet_contract_address),
|
||||
vesting_contract_address: Some(vesting_contract_address),
|
||||
mixnet_contract_address,
|
||||
vesting_contract_address,
|
||||
client_address: None,
|
||||
custom_gas_limits: Default::default(),
|
||||
simulated_gas_multiplier: DEFAULT_SIMULATED_GAS_MULTIPLIER,
|
||||
@@ -255,6 +255,13 @@ impl<C> NymdClient<C> {
|
||||
self.get_balance(address, self.denom()?).await
|
||||
}
|
||||
|
||||
pub async fn get_total_supply(&self) -> Result<Vec<Coin>, NymdError>
|
||||
where
|
||||
C: CosmWasmClient + Sync,
|
||||
{
|
||||
self.client.get_total_supply().await
|
||||
}
|
||||
|
||||
pub async fn get_contract_settings(&self) -> Result<ContractStateParams, NymdError>
|
||||
where
|
||||
C: CosmWasmClient + Sync,
|
||||
@@ -289,7 +296,7 @@ impl<C> NymdClient<C> {
|
||||
|
||||
pub async fn get_rewarding_status(
|
||||
&self,
|
||||
mix_identity: mixnet_contract::IdentityKey,
|
||||
mix_identity: mixnet_contract_common::IdentityKey,
|
||||
rewarding_interval_nonce: u32,
|
||||
) -> Result<MixnodeRewardingStatusResponse, NymdError>
|
||||
where
|
||||
@@ -773,6 +780,31 @@ impl<C> NymdClient<C> {
|
||||
.await
|
||||
}
|
||||
|
||||
/// Update the configuration of a mixnode. Right now, only possible for profit margin.
|
||||
pub async fn update_mixnode_config(
|
||||
&self,
|
||||
profit_margin_percent: u8,
|
||||
) -> Result<ExecuteResult, NymdError>
|
||||
where
|
||||
C: SigningCosmWasmClient + Sync,
|
||||
{
|
||||
let fee = self.operation_fee(Operation::UpdateMixnodeConfig);
|
||||
|
||||
let req = ExecuteMsg::UpdateMixnodeConfig {
|
||||
profit_margin_percent,
|
||||
};
|
||||
self.client
|
||||
.execute(
|
||||
self.address(),
|
||||
self.mixnet_contract_address()?,
|
||||
&req,
|
||||
fee,
|
||||
"Updating mixnode configuration from rust!",
|
||||
Vec::new(),
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
/// Delegates specified amount of stake to particular mixnode.
|
||||
pub async fn delegate_to_mixnode(
|
||||
&self,
|
||||
|
||||
@@ -8,7 +8,7 @@ use crate::nymd::fee::helpers::Operation;
|
||||
use crate::nymd::{cosmwasm_coin_to_cosmos_coin, NymdClient};
|
||||
use async_trait::async_trait;
|
||||
use cosmwasm_std::Coin;
|
||||
use mixnet_contract::{Gateway, IdentityKey, IdentityKeyRef, MixNode};
|
||||
use mixnet_contract_common::{Gateway, IdentityKey, IdentityKeyRef, MixNode};
|
||||
use vesting_contract::messages::ExecuteMsg as VestingExecuteMsg;
|
||||
|
||||
#[async_trait]
|
||||
|
||||
@@ -133,6 +133,7 @@ impl DirectSecp256k1HdWallet {
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub struct DirectSecp256k1HdWalletBuilder {
|
||||
/// The password to use when deriving a BIP39 seed from a mnemonic.
|
||||
bip39_password: String,
|
||||
|
||||
@@ -1,16 +1,25 @@
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// Copyright 2021-2022 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::validator_api::error::ValidatorAPIError;
|
||||
use crate::validator_api::routes::{CORE_STATUS_COUNT, SINCE_ARG};
|
||||
use coconut_interface::{BlindSignRequestBody, BlindedSignatureResponse, VerificationKeyResponse};
|
||||
use mixnet_contract::{GatewayBond, MixNodeBond};
|
||||
use mixnet_contract_common::{GatewayBond, IdentityKeyRef, MixNodeBond};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashMap;
|
||||
use url::Url;
|
||||
use validator_api_requests::models::{
|
||||
CoreNodeStatusResponse, MixnodeStatusResponse, RewardEstimationResponse,
|
||||
StakeSaturationResponse,
|
||||
};
|
||||
|
||||
pub mod error;
|
||||
pub(crate) mod routes;
|
||||
|
||||
type PathSegments<'a> = &'a [&'a str];
|
||||
type Params<'a, K, V> = &'a [(K, V)];
|
||||
|
||||
const NO_PARAMS: Params<'_, &'_ str, &'_ str> = &[];
|
||||
|
||||
pub struct Client {
|
||||
url: Url,
|
||||
@@ -30,24 +39,33 @@ impl Client {
|
||||
self.url = new_url
|
||||
}
|
||||
|
||||
async fn query_validator_api<T>(&self, path: PathSegments<'_>) -> Result<T, ValidatorAPIError>
|
||||
async fn query_validator_api<T, K, V>(
|
||||
&self,
|
||||
path: PathSegments<'_>,
|
||||
params: Params<'_, K, V>,
|
||||
) -> Result<T, ValidatorAPIError>
|
||||
where
|
||||
for<'a> T: Deserialize<'a>,
|
||||
K: AsRef<str>,
|
||||
V: AsRef<str>,
|
||||
{
|
||||
let url = create_api_url(&self.url, path);
|
||||
let url = create_api_url(&self.url, path, params);
|
||||
Ok(self.reqwest_client.get(url).send().await?.json().await?)
|
||||
}
|
||||
|
||||
async fn post_validator_api<B, T>(
|
||||
async fn post_validator_api<B, T, K, V>(
|
||||
&self,
|
||||
path: PathSegments<'_>,
|
||||
params: Params<'_, K, V>,
|
||||
json_body: &B,
|
||||
) -> Result<T, ValidatorAPIError>
|
||||
where
|
||||
B: Serialize + ?Sized,
|
||||
for<'a> T: Deserialize<'a>,
|
||||
K: AsRef<str>,
|
||||
V: AsRef<str>,
|
||||
{
|
||||
let url = create_api_url(&self.url, path);
|
||||
let url = create_api_url(&self.url, path, params);
|
||||
Ok(self
|
||||
.reqwest_client
|
||||
.post(url)
|
||||
@@ -59,18 +77,159 @@ impl Client {
|
||||
}
|
||||
|
||||
pub async fn get_mixnodes(&self) -> Result<Vec<MixNodeBond>, ValidatorAPIError> {
|
||||
self.query_validator_api(&[routes::API_VERSION, routes::MIXNODES])
|
||||
self.query_validator_api(&[routes::API_VERSION, routes::MIXNODES], NO_PARAMS)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn get_gateways(&self) -> Result<Vec<GatewayBond>, ValidatorAPIError> {
|
||||
self.query_validator_api(&[routes::API_VERSION, routes::GATEWAYS])
|
||||
self.query_validator_api(&[routes::API_VERSION, routes::GATEWAYS], NO_PARAMS)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn get_active_mixnodes(&self) -> Result<Vec<MixNodeBond>, ValidatorAPIError> {
|
||||
self.query_validator_api(&[routes::API_VERSION, routes::MIXNODES, routes::ACTIVE])
|
||||
self.query_validator_api(
|
||||
&[routes::API_VERSION, routes::MIXNODES, routes::ACTIVE],
|
||||
NO_PARAMS,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn get_rewarded_mixnodes(&self) -> Result<Vec<MixNodeBond>, ValidatorAPIError> {
|
||||
self.query_validator_api(
|
||||
&[routes::API_VERSION, routes::MIXNODES, routes::REWARDED],
|
||||
NO_PARAMS,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn get_probs_mixnode_rewarded(
|
||||
&self,
|
||||
mixnode_id: &str,
|
||||
) -> Result<HashMap<String, f32>, ValidatorAPIError> {
|
||||
self.query_validator_api(
|
||||
&[
|
||||
routes::API_VERSION,
|
||||
routes::MIXNODES,
|
||||
routes::REWARDED,
|
||||
routes::INCLUSION_CHANCE,
|
||||
mixnode_id,
|
||||
],
|
||||
NO_PARAMS,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn get_gateway_core_status_count(
|
||||
&self,
|
||||
identity: IdentityKeyRef<'_>,
|
||||
since: Option<i64>,
|
||||
) -> Result<CoreNodeStatusResponse, ValidatorAPIError> {
|
||||
if let Some(since) = since {
|
||||
self.query_validator_api(
|
||||
&[
|
||||
routes::API_VERSION,
|
||||
routes::STATUS_ROUTES,
|
||||
routes::GATEWAY,
|
||||
identity,
|
||||
CORE_STATUS_COUNT,
|
||||
],
|
||||
&[(SINCE_ARG, since.to_string())],
|
||||
)
|
||||
.await
|
||||
} else {
|
||||
self.query_validator_api(
|
||||
&[
|
||||
routes::API_VERSION,
|
||||
routes::STATUS_ROUTES,
|
||||
routes::GATEWAY,
|
||||
identity,
|
||||
],
|
||||
NO_PARAMS,
|
||||
)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn get_mixnode_core_status_count(
|
||||
&self,
|
||||
identity: IdentityKeyRef<'_>,
|
||||
since: Option<i64>,
|
||||
) -> Result<CoreNodeStatusResponse, ValidatorAPIError> {
|
||||
if let Some(since) = since {
|
||||
self.query_validator_api(
|
||||
&[
|
||||
routes::API_VERSION,
|
||||
routes::STATUS_ROUTES,
|
||||
routes::MIXNODE,
|
||||
identity,
|
||||
CORE_STATUS_COUNT,
|
||||
],
|
||||
&[(SINCE_ARG, since.to_string())],
|
||||
)
|
||||
.await
|
||||
} else {
|
||||
self.query_validator_api(
|
||||
&[
|
||||
routes::API_VERSION,
|
||||
routes::STATUS_ROUTES,
|
||||
routes::MIXNODE,
|
||||
identity,
|
||||
],
|
||||
NO_PARAMS,
|
||||
)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn get_mixnode_status(
|
||||
&self,
|
||||
identity: IdentityKeyRef<'_>,
|
||||
) -> Result<MixnodeStatusResponse, ValidatorAPIError> {
|
||||
self.query_validator_api(
|
||||
&[
|
||||
routes::API_VERSION,
|
||||
routes::STATUS_ROUTES,
|
||||
routes::MIXNODE,
|
||||
identity,
|
||||
routes::STATUS,
|
||||
],
|
||||
NO_PARAMS,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn get_mixnode_reward_estimation(
|
||||
&self,
|
||||
identity: IdentityKeyRef<'_>,
|
||||
) -> Result<RewardEstimationResponse, ValidatorAPIError> {
|
||||
self.query_validator_api(
|
||||
&[
|
||||
routes::API_VERSION,
|
||||
routes::STATUS_ROUTES,
|
||||
routes::MIXNODE,
|
||||
identity,
|
||||
routes::REWARD_ESTIMATION,
|
||||
],
|
||||
NO_PARAMS,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn get_mixnode_stake_saturation(
|
||||
&self,
|
||||
identity: IdentityKeyRef<'_>,
|
||||
) -> Result<StakeSaturationResponse, ValidatorAPIError> {
|
||||
self.query_validator_api(
|
||||
&[
|
||||
routes::API_VERSION,
|
||||
routes::STATUS_ROUTES,
|
||||
routes::MIXNODE,
|
||||
identity,
|
||||
routes::STAKE_SATURATION,
|
||||
],
|
||||
NO_PARAMS,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn blind_sign(
|
||||
@@ -79,6 +238,7 @@ impl Client {
|
||||
) -> Result<BlindedSignatureResponse, ValidatorAPIError> {
|
||||
self.post_validator_api(
|
||||
&[routes::API_VERSION, routes::COCONUT_BLIND_SIGN],
|
||||
NO_PARAMS,
|
||||
request_body,
|
||||
)
|
||||
.await
|
||||
@@ -87,13 +247,20 @@ impl Client {
|
||||
pub async fn get_coconut_verification_key(
|
||||
&self,
|
||||
) -> Result<VerificationKeyResponse, ValidatorAPIError> {
|
||||
self.query_validator_api(&[routes::API_VERSION, routes::COCONUT_VERIFICATION_KEY])
|
||||
.await
|
||||
self.query_validator_api(
|
||||
&[routes::API_VERSION, routes::COCONUT_VERIFICATION_KEY],
|
||||
NO_PARAMS,
|
||||
)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
// utility function that should solve the double slash problem in validator API forever.
|
||||
fn create_api_url(base: &Url, segments: PathSegments<'_>) -> Url {
|
||||
fn create_api_url<K: AsRef<str>, V: AsRef<str>>(
|
||||
base: &Url,
|
||||
segments: PathSegments<'_>,
|
||||
params: Params<'_, K, V>,
|
||||
) -> Url {
|
||||
let mut url = base.clone();
|
||||
let mut path_segments = url
|
||||
.path_segments_mut()
|
||||
@@ -108,6 +275,10 @@ fn create_api_url(base: &Url, segments: PathSegments<'_>) -> Url {
|
||||
// and can be dropped
|
||||
drop(path_segments);
|
||||
|
||||
if !params.is_empty() {
|
||||
url.query_pairs_mut().extend_pairs(params);
|
||||
}
|
||||
|
||||
url
|
||||
}
|
||||
|
||||
@@ -122,51 +293,66 @@ mod tests {
|
||||
// works with 1 segment
|
||||
assert_eq!(
|
||||
"http://foomp.com/foo",
|
||||
create_api_url(&base_url, &["foo"]).as_str()
|
||||
create_api_url(&base_url, &["foo"], NO_PARAMS).as_str()
|
||||
);
|
||||
|
||||
// works with 2 segments
|
||||
assert_eq!(
|
||||
"http://foomp.com/foo/bar",
|
||||
create_api_url(&base_url, &["foo", "bar"]).as_str()
|
||||
create_api_url(&base_url, &["foo", "bar"], NO_PARAMS).as_str()
|
||||
);
|
||||
|
||||
// works with leading slash
|
||||
assert_eq!(
|
||||
"http://foomp.com/foo",
|
||||
create_api_url(&base_url, &["/foo"]).as_str()
|
||||
create_api_url(&base_url, &["/foo"], NO_PARAMS).as_str()
|
||||
);
|
||||
assert_eq!(
|
||||
"http://foomp.com/foo/bar",
|
||||
create_api_url(&base_url, &["/foo", "bar"]).as_str()
|
||||
create_api_url(&base_url, &["/foo", "bar"], NO_PARAMS).as_str()
|
||||
);
|
||||
assert_eq!(
|
||||
"http://foomp.com/foo/bar",
|
||||
create_api_url(&base_url, &["foo", "/bar"]).as_str()
|
||||
create_api_url(&base_url, &["foo", "/bar"], NO_PARAMS).as_str()
|
||||
);
|
||||
|
||||
// works with trailing slash
|
||||
assert_eq!(
|
||||
"http://foomp.com/foo",
|
||||
create_api_url(&base_url, &["foo/"]).as_str()
|
||||
create_api_url(&base_url, &["foo/"], NO_PARAMS).as_str()
|
||||
);
|
||||
assert_eq!(
|
||||
"http://foomp.com/foo/bar",
|
||||
create_api_url(&base_url, &["foo/", "bar"]).as_str()
|
||||
create_api_url(&base_url, &["foo/", "bar"], NO_PARAMS).as_str()
|
||||
);
|
||||
assert_eq!(
|
||||
"http://foomp.com/foo/bar",
|
||||
create_api_url(&base_url, &["foo", "bar/"]).as_str()
|
||||
create_api_url(&base_url, &["foo", "bar/"], NO_PARAMS).as_str()
|
||||
);
|
||||
|
||||
// works with both leading and trailing slash
|
||||
assert_eq!(
|
||||
"http://foomp.com/foo",
|
||||
create_api_url(&base_url, &["/foo/"]).as_str()
|
||||
create_api_url(&base_url, &["/foo/"], NO_PARAMS).as_str()
|
||||
);
|
||||
assert_eq!(
|
||||
"http://foomp.com/foo/bar",
|
||||
create_api_url(&base_url, &["/foo/", "/bar/"]).as_str()
|
||||
create_api_url(&base_url, &["/foo/", "/bar/"], NO_PARAMS).as_str()
|
||||
);
|
||||
|
||||
// adds params
|
||||
assert_eq!(
|
||||
"http://foomp.com/foo/bar?foomp=baz",
|
||||
create_api_url(&base_url, &["foo", "bar"], &[("foomp", "baz")]).as_str()
|
||||
);
|
||||
assert_eq!(
|
||||
"http://foomp.com/foo/bar?arg1=val1&arg2=val2",
|
||||
create_api_url(
|
||||
&base_url,
|
||||
&["/foo/", "/bar/"],
|
||||
&[("arg1", "val1"), ("arg2", "val2")]
|
||||
)
|
||||
.as_str()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,19 @@ pub const MIXNODES: &str = "mixnodes";
|
||||
pub const GATEWAYS: &str = "gateways";
|
||||
|
||||
pub const ACTIVE: &str = "active";
|
||||
pub const REWARDED: &str = "rewarded";
|
||||
|
||||
pub const COCONUT_BLIND_SIGN: &str = "blind_sign";
|
||||
pub const COCONUT_VERIFICATION_KEY: &str = "verification_key";
|
||||
pub const COCONUT_BLIND_SIGN: &str = "blind-sign";
|
||||
pub const COCONUT_VERIFICATION_KEY: &str = "verification-key";
|
||||
|
||||
pub const STATUS_ROUTES: &str = "status";
|
||||
pub const MIXNODE: &str = "mixnode";
|
||||
pub const GATEWAY: &str = "gateway";
|
||||
|
||||
pub const CORE_STATUS_COUNT: &str = "core-status-count";
|
||||
pub const SINCE_ARG: &str = "since";
|
||||
|
||||
pub const STATUS: &str = "status";
|
||||
pub const REWARD_ESTIMATION: &str = "reward-estimation";
|
||||
pub const STAKE_SATURATION: &str = "stake-saturation";
|
||||
pub const INCLUSION_CHANCE: &str = "inclusion-probability";
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
[package]
|
||||
name = "contracts-common"
|
||||
version = "0.1.0"
|
||||
authors = ["Jędrzej Stuczyński <andrew@nymtech.net>"]
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
cosmwasm-std = "1.0.0-beta3"
|
||||
@@ -0,0 +1,30 @@
|
||||
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use cosmwasm_std::Event;
|
||||
|
||||
/// Looks up value of particular attribute in the provided event. If it fails to find it,
|
||||
/// the function panics.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `event`: event to search through.
|
||||
/// * `key`: key associated with the particular attribute
|
||||
pub fn must_find_attribute(event: &Event, key: &str) -> String {
|
||||
may_find_attribute(event, key).unwrap()
|
||||
}
|
||||
|
||||
/// Looks up value of particular attribute in the provided event. Returns None if it does not exist.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `event`: event to search through.
|
||||
/// * `key`: key associated with the particular attribute
|
||||
pub fn may_find_attribute(event: &Event, key: &str) -> Option<String> {
|
||||
for attr in &event.attributes {
|
||||
if attr.key == key {
|
||||
return Some(attr.value.clone());
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
pub mod events;
|
||||
+4
-2
@@ -1,5 +1,5 @@
|
||||
[package]
|
||||
name = "mixnet-contract"
|
||||
name = "mixnet-contract-common"
|
||||
version = "0.1.0"
|
||||
authors = ["Jędrzej Stuczyński <andrew@nymtech.net>"]
|
||||
edition = "2018"
|
||||
@@ -14,10 +14,12 @@ serde_repr = "0.1"
|
||||
schemars = "0.8"
|
||||
ts-rs = { version = "5.1", optional = true }
|
||||
thiserror = "1.0"
|
||||
network-defaults = { path = "../network-defaults" }
|
||||
network-defaults = { path = "../../network-defaults" }
|
||||
fixed = { version = "1.1", features = ["serde"] }
|
||||
az = "1.1"
|
||||
log = "0.4.14"
|
||||
|
||||
contracts-common = { path = "../contracts-common" }
|
||||
|
||||
[features]
|
||||
default = []
|
||||
@@ -0,0 +1,353 @@
|
||||
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::mixnode::NodeRewardResult;
|
||||
use crate::{ContractStateParams, Delegation, IdentityKeyRef, Layer};
|
||||
use cosmwasm_std::{Addr, Coin, Event, Uint128};
|
||||
|
||||
pub use contracts_common::events::*;
|
||||
|
||||
// event types
|
||||
pub const DELEGATION_EVENT_TYPE: &str = "delegation";
|
||||
pub const UNDELEGATION_EVENT_TYPE: &str = "undelegation";
|
||||
pub const GATEWAY_BONDING_EVENT_TYPE: &str = "gateway_bonding";
|
||||
pub const GATEWAY_UNBONDING_EVENT_TYPE: &str = "gateway_unbonding";
|
||||
pub const MIXNODE_BONDING_EVENT_TYPE: &str = "mixnode_bonding";
|
||||
pub const MIXNODE_UNBONDING_EVENT_TYPE: &str = "mixnode_unbonding";
|
||||
pub const SETTINGS_UPDATE_EVENT_TYPE: &str = "settings_update";
|
||||
pub const BEGIN_REWARDING_EVENT_TYPE: &str = "begin_rewarding";
|
||||
pub const OPERATOR_REWARDING_EVENT_TYPE: &str = "mix_rewarding";
|
||||
pub const MIX_DELEGATORS_REWARDING_EVENT_TYPE: &str = "mix_delegators_rewarding";
|
||||
pub const FINISH_REWARDING_EVENT_TYPE: &str = "finish_rewarding";
|
||||
|
||||
// attributes that are used in multiple places
|
||||
pub const OWNER_KEY: &str = "owner";
|
||||
pub const AMOUNT_KEY: &str = "amount";
|
||||
pub const PROXY_KEY: &str = "proxy";
|
||||
|
||||
// event-specific attributes
|
||||
|
||||
// delegation/undelegation
|
||||
pub const DELEGATOR_KEY: &str = "delegator";
|
||||
pub const DELEGATION_TARGET_KEY: &str = "delegation_target";
|
||||
pub const DELEGATION_HEIGHT_KEY: &str = "delegation_latest_block_height";
|
||||
|
||||
// bonding/unbonding
|
||||
pub const NODE_IDENTITY_KEY: &str = "identity";
|
||||
pub const ASSIGNED_LAYER_KEY: &str = "assigned_layer";
|
||||
|
||||
// settings change
|
||||
pub const OLD_MINIMUM_MIXNODE_PLEDGE_KEY: &str = "old_minimum_mixnode_pledge";
|
||||
pub const OLD_MINIMUM_GATEWAY_PLEDGE_KEY: &str = "old_minimum_gateway_pledge";
|
||||
pub const OLD_MIXNODE_REWARDED_SET_SIZE_KEY: &str = "old_mixnode_rewarded_set_size";
|
||||
pub const OLD_MIXNODE_ACTIVE_SET_SIZE_KEY: &str = "old_mixnode_active_set_size";
|
||||
pub const OLD_ACTIVE_SET_WORK_FACTOR_KEY: &str = "old_active_set_work_factor";
|
||||
|
||||
pub const NEW_MINIMUM_MIXNODE_PLEDGE_KEY: &str = "new_minimum_mixnode_pledge";
|
||||
pub const NEW_MINIMUM_GATEWAY_PLEDGE_KEY: &str = "new_minimum_gateway_pledge";
|
||||
pub const NEW_MIXNODE_REWARDED_SET_SIZE_KEY: &str = "new_mixnode_rewarded_set_size";
|
||||
pub const NEW_MIXNODE_ACTIVE_SET_SIZE_KEY: &str = "new_mixnode_active_set_size";
|
||||
pub const NEW_ACTIVE_SET_WORK_FACTOR_KEY: &str = "new_active_set_work_factor";
|
||||
|
||||
// rewarding
|
||||
pub const REWARDING_INTERVAL_NONCE_KEY: &str = "rewarding_interval_nonce";
|
||||
pub const TOTAL_MIXNODE_REWARD_KEY: &str = "total_node_reward";
|
||||
pub const OPERATOR_REWARD_KEY: &str = "operator_reward";
|
||||
pub const LAMBDA_KEY: &str = "lambda";
|
||||
pub const SIGMA_KEY: &str = "sigma";
|
||||
pub const DISTRIBUTED_DELEGATION_REWARDS_KEY: &str = "distributed_delegation_rewards";
|
||||
pub const FURTHER_DELEGATIONS_TO_REWARD_KEY: &str = "further_delegations";
|
||||
pub const NO_REWARD_REASON_KEY: &str = "no_reward_reason";
|
||||
pub const BOND_NOT_FOUND_VALUE: &str = "bond_not_found";
|
||||
pub const BOND_TOO_FRESH_VALUE: &str = "bond_too_fresh";
|
||||
pub const ZERO_UPTIME_VALUE: &str = "zero_uptime";
|
||||
|
||||
pub fn new_delegation_event(
|
||||
delegator: &Addr,
|
||||
proxy: &Option<Addr>,
|
||||
amount: &Coin,
|
||||
mix_identity: IdentityKeyRef,
|
||||
) -> Event {
|
||||
let mut event = Event::new(DELEGATION_EVENT_TYPE).add_attribute(DELEGATOR_KEY, delegator);
|
||||
|
||||
if let Some(proxy) = proxy {
|
||||
event = event.add_attribute(PROXY_KEY, proxy)
|
||||
}
|
||||
|
||||
// coin implements Display trait and we use that implementation here
|
||||
event
|
||||
.add_attribute(AMOUNT_KEY, amount.to_string())
|
||||
.add_attribute(DELEGATION_TARGET_KEY, mix_identity)
|
||||
}
|
||||
|
||||
pub fn new_undelegation_event(
|
||||
delegator: &Addr,
|
||||
proxy: &Option<Addr>,
|
||||
old_delegation: &Delegation,
|
||||
mix_identity: IdentityKeyRef,
|
||||
) -> Event {
|
||||
let mut event = Event::new(UNDELEGATION_EVENT_TYPE).add_attribute(DELEGATOR_KEY, delegator);
|
||||
|
||||
if let Some(proxy) = proxy {
|
||||
event = event.add_attribute(PROXY_KEY, proxy)
|
||||
}
|
||||
|
||||
// coin implements Display trait and we use that implementation here
|
||||
event
|
||||
.add_attribute(AMOUNT_KEY, old_delegation.amount.to_string())
|
||||
.add_attribute(
|
||||
DELEGATION_HEIGHT_KEY,
|
||||
old_delegation.block_height.to_string(),
|
||||
)
|
||||
.add_attribute(DELEGATION_TARGET_KEY, mix_identity)
|
||||
}
|
||||
|
||||
pub fn new_gateway_bonding_event(
|
||||
owner: &Addr,
|
||||
proxy: &Option<Addr>,
|
||||
amount: &Coin,
|
||||
identity: IdentityKeyRef,
|
||||
) -> Event {
|
||||
let mut event = Event::new(GATEWAY_BONDING_EVENT_TYPE)
|
||||
.add_attribute(OWNER_KEY, owner)
|
||||
.add_attribute(NODE_IDENTITY_KEY, identity);
|
||||
|
||||
if let Some(proxy) = proxy {
|
||||
event = event.add_attribute(PROXY_KEY, proxy)
|
||||
}
|
||||
|
||||
// coin implements Display trait and we use that implementation here
|
||||
event.add_attribute(AMOUNT_KEY, amount.to_string())
|
||||
}
|
||||
|
||||
pub fn new_gateway_unbonding_event(
|
||||
owner: &Addr,
|
||||
proxy: &Option<Addr>,
|
||||
amount: &Coin,
|
||||
identity: IdentityKeyRef,
|
||||
) -> Event {
|
||||
let mut event = Event::new(GATEWAY_UNBONDING_EVENT_TYPE)
|
||||
.add_attribute(OWNER_KEY, owner)
|
||||
.add_attribute(NODE_IDENTITY_KEY, identity);
|
||||
|
||||
if let Some(proxy) = proxy {
|
||||
event = event.add_attribute(PROXY_KEY, proxy)
|
||||
}
|
||||
|
||||
// coin implements Display trait and we use that implementation here
|
||||
event.add_attribute(AMOUNT_KEY, amount.to_string())
|
||||
}
|
||||
|
||||
pub fn new_mixnode_bonding_event(
|
||||
owner: &Addr,
|
||||
proxy: &Option<Addr>,
|
||||
amount: &Coin,
|
||||
identity: IdentityKeyRef,
|
||||
assigned_layer: Layer,
|
||||
) -> Event {
|
||||
let mut event = Event::new(MIXNODE_BONDING_EVENT_TYPE)
|
||||
.add_attribute(OWNER_KEY, owner)
|
||||
.add_attribute(NODE_IDENTITY_KEY, identity);
|
||||
|
||||
if let Some(proxy) = proxy {
|
||||
event = event.add_attribute(PROXY_KEY, proxy)
|
||||
}
|
||||
|
||||
// coin implements Display trait and we use that implementation here
|
||||
event
|
||||
.add_attribute(ASSIGNED_LAYER_KEY, assigned_layer)
|
||||
.add_attribute(AMOUNT_KEY, amount.to_string())
|
||||
}
|
||||
|
||||
pub fn new_mixnode_unbonding_event(
|
||||
owner: &Addr,
|
||||
proxy: &Option<Addr>,
|
||||
amount: &Coin,
|
||||
identity: IdentityKeyRef,
|
||||
) -> Event {
|
||||
let mut event = Event::new(MIXNODE_UNBONDING_EVENT_TYPE)
|
||||
.add_attribute(OWNER_KEY, owner)
|
||||
.add_attribute(NODE_IDENTITY_KEY, identity);
|
||||
|
||||
if let Some(proxy) = proxy {
|
||||
event = event.add_attribute(PROXY_KEY, proxy)
|
||||
}
|
||||
|
||||
// coin implements Display trait and we use that implementation here
|
||||
event.add_attribute(AMOUNT_KEY, amount.to_string())
|
||||
}
|
||||
|
||||
pub fn new_settings_update_event(
|
||||
old_params: &ContractStateParams,
|
||||
new_params: &ContractStateParams,
|
||||
) -> Event {
|
||||
let mut event = Event::new(SETTINGS_UPDATE_EVENT_TYPE);
|
||||
|
||||
if old_params.minimum_mixnode_pledge != new_params.minimum_mixnode_pledge {
|
||||
event = event
|
||||
.add_attribute(
|
||||
OLD_MINIMUM_MIXNODE_PLEDGE_KEY,
|
||||
old_params.minimum_mixnode_pledge,
|
||||
)
|
||||
.add_attribute(
|
||||
NEW_MINIMUM_MIXNODE_PLEDGE_KEY,
|
||||
new_params.minimum_mixnode_pledge,
|
||||
)
|
||||
}
|
||||
|
||||
if old_params.minimum_gateway_pledge != new_params.minimum_gateway_pledge {
|
||||
event = event
|
||||
.add_attribute(
|
||||
OLD_MINIMUM_GATEWAY_PLEDGE_KEY,
|
||||
old_params.minimum_gateway_pledge,
|
||||
)
|
||||
.add_attribute(
|
||||
NEW_MINIMUM_GATEWAY_PLEDGE_KEY,
|
||||
new_params.minimum_gateway_pledge,
|
||||
)
|
||||
}
|
||||
|
||||
if old_params.mixnode_rewarded_set_size != new_params.mixnode_rewarded_set_size {
|
||||
event = event
|
||||
.add_attribute(
|
||||
OLD_MIXNODE_REWARDED_SET_SIZE_KEY,
|
||||
old_params.mixnode_rewarded_set_size.to_string(),
|
||||
)
|
||||
.add_attribute(
|
||||
NEW_MIXNODE_REWARDED_SET_SIZE_KEY,
|
||||
new_params.mixnode_rewarded_set_size.to_string(),
|
||||
)
|
||||
}
|
||||
|
||||
if old_params.mixnode_active_set_size != new_params.mixnode_active_set_size {
|
||||
event = event
|
||||
.add_attribute(
|
||||
OLD_MIXNODE_ACTIVE_SET_SIZE_KEY,
|
||||
old_params.mixnode_active_set_size.to_string(),
|
||||
)
|
||||
.add_attribute(
|
||||
NEW_MIXNODE_ACTIVE_SET_SIZE_KEY,
|
||||
new_params.mixnode_active_set_size.to_string(),
|
||||
)
|
||||
}
|
||||
|
||||
if old_params.active_set_work_factor != new_params.active_set_work_factor {
|
||||
event = event
|
||||
.add_attribute(
|
||||
OLD_ACTIVE_SET_WORK_FACTOR_KEY,
|
||||
old_params.active_set_work_factor.to_string(),
|
||||
)
|
||||
.add_attribute(
|
||||
NEW_ACTIVE_SET_WORK_FACTOR_KEY,
|
||||
new_params.active_set_work_factor.to_string(),
|
||||
)
|
||||
}
|
||||
|
||||
event
|
||||
}
|
||||
|
||||
pub fn new_begin_rewarding_event(rewarding_interval_nonce: u32) -> Event {
|
||||
Event::new(BEGIN_REWARDING_EVENT_TYPE).add_attribute(
|
||||
REWARDING_INTERVAL_NONCE_KEY,
|
||||
rewarding_interval_nonce.to_string(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn new_finish_rewarding_event(rewarding_interval_nonce: u32) -> Event {
|
||||
Event::new(FINISH_REWARDING_EVENT_TYPE).add_attribute(
|
||||
REWARDING_INTERVAL_NONCE_KEY,
|
||||
rewarding_interval_nonce.to_string(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn new_not_found_mix_operator_rewarding_event(
|
||||
rewarding_interval_nonce: u32,
|
||||
identity: IdentityKeyRef,
|
||||
) -> Event {
|
||||
Event::new(OPERATOR_REWARDING_EVENT_TYPE)
|
||||
.add_attribute(
|
||||
REWARDING_INTERVAL_NONCE_KEY,
|
||||
rewarding_interval_nonce.to_string(),
|
||||
)
|
||||
.add_attribute(NODE_IDENTITY_KEY, identity)
|
||||
.add_attribute(NO_REWARD_REASON_KEY, BOND_NOT_FOUND_VALUE)
|
||||
}
|
||||
|
||||
pub fn new_too_fresh_bond_mix_operator_rewarding_event(
|
||||
rewarding_interval_nonce: u32,
|
||||
identity: IdentityKeyRef,
|
||||
) -> Event {
|
||||
Event::new(OPERATOR_REWARDING_EVENT_TYPE)
|
||||
.add_attribute(
|
||||
REWARDING_INTERVAL_NONCE_KEY,
|
||||
rewarding_interval_nonce.to_string(),
|
||||
)
|
||||
.add_attribute(NODE_IDENTITY_KEY, identity)
|
||||
.add_attribute(NO_REWARD_REASON_KEY, BOND_TOO_FRESH_VALUE)
|
||||
}
|
||||
|
||||
pub fn new_zero_uptime_mix_operator_rewarding_event(
|
||||
rewarding_interval_nonce: u32,
|
||||
identity: IdentityKeyRef,
|
||||
) -> Event {
|
||||
Event::new(OPERATOR_REWARDING_EVENT_TYPE)
|
||||
.add_attribute(
|
||||
REWARDING_INTERVAL_NONCE_KEY,
|
||||
rewarding_interval_nonce.to_string(),
|
||||
)
|
||||
.add_attribute(NODE_IDENTITY_KEY, identity)
|
||||
.add_attribute(NO_REWARD_REASON_KEY, ZERO_UPTIME_VALUE)
|
||||
}
|
||||
|
||||
pub fn new_mix_operator_rewarding_event(
|
||||
rewarding_interval_nonce: u32,
|
||||
identity: IdentityKeyRef,
|
||||
node_reward_result: NodeRewardResult,
|
||||
operator_reward: Uint128,
|
||||
delegation_rewards_distributed: Uint128,
|
||||
further_delegations: bool,
|
||||
) -> Event {
|
||||
Event::new(OPERATOR_REWARDING_EVENT_TYPE)
|
||||
.add_attribute(
|
||||
REWARDING_INTERVAL_NONCE_KEY,
|
||||
rewarding_interval_nonce.to_string(),
|
||||
)
|
||||
.add_attribute(NODE_IDENTITY_KEY, identity)
|
||||
.add_attribute(
|
||||
TOTAL_MIXNODE_REWARD_KEY,
|
||||
node_reward_result.reward().to_string(),
|
||||
)
|
||||
.add_attribute(LAMBDA_KEY, node_reward_result.lambda().to_string())
|
||||
.add_attribute(SIGMA_KEY, node_reward_result.sigma().to_string())
|
||||
.add_attribute(OPERATOR_REWARD_KEY, operator_reward)
|
||||
.add_attribute(
|
||||
DISTRIBUTED_DELEGATION_REWARDS_KEY,
|
||||
delegation_rewards_distributed,
|
||||
)
|
||||
.add_attribute(
|
||||
FURTHER_DELEGATIONS_TO_REWARD_KEY,
|
||||
further_delegations.to_string(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn new_mix_delegators_rewarding_event(
|
||||
rewarding_interval_nonce: u32,
|
||||
identity: IdentityKeyRef,
|
||||
delegation_rewards_distributed: Uint128,
|
||||
further_delegations: bool,
|
||||
) -> Event {
|
||||
Event::new(MIX_DELEGATORS_REWARDING_EVENT_TYPE)
|
||||
.add_attribute(
|
||||
REWARDING_INTERVAL_NONCE_KEY,
|
||||
rewarding_interval_nonce.to_string(),
|
||||
)
|
||||
.add_attribute(NODE_IDENTITY_KEY, identity)
|
||||
.add_attribute(
|
||||
DISTRIBUTED_DELEGATION_REWARDS_KEY,
|
||||
delegation_rewards_distributed,
|
||||
)
|
||||
.add_attribute(
|
||||
FURTHER_DELEGATIONS_TO_REWARD_KEY,
|
||||
further_delegations.to_string(),
|
||||
)
|
||||
}
|
||||
+1
@@ -3,6 +3,7 @@
|
||||
|
||||
mod delegation;
|
||||
pub mod error;
|
||||
pub mod events;
|
||||
mod gateway;
|
||||
pub mod mixnode;
|
||||
mod msg;
|
||||
+16
-1
@@ -53,6 +53,16 @@ pub enum Layer {
|
||||
Three = 3,
|
||||
}
|
||||
|
||||
impl From<Layer> for String {
|
||||
fn from(layer: Layer) -> Self {
|
||||
if layer == Layer::Gateway {
|
||||
"gateway".to_string()
|
||||
} else {
|
||||
(layer as u8).to_string()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, JsonSchema, PartialEq, Serialize, Deserialize, Copy)]
|
||||
pub struct NodeRewardParams {
|
||||
period_reward_pool: Uint128,
|
||||
@@ -243,7 +253,7 @@ impl DelegatorRewardParams {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct NodeRewardResult {
|
||||
reward: U128,
|
||||
lambda: U128,
|
||||
@@ -327,6 +337,11 @@ impl MixNodeBond {
|
||||
self.total_delegation.clone()
|
||||
}
|
||||
|
||||
pub fn stake_saturation(&self, circulating_supply: u128, rewarded_set_size: u32) -> U128 {
|
||||
self.total_bond_to_circulating_supply(circulating_supply)
|
||||
* U128::from_num(rewarded_set_size)
|
||||
}
|
||||
|
||||
pub fn pledge_to_circulating_supply(&self, circulating_supply: u128) -> U128 {
|
||||
U128::from_num(self.pledge_amount().amount.u128()) / U128::from_num(circulating_supply)
|
||||
}
|
||||
+3
@@ -20,6 +20,9 @@ pub enum ExecuteMsg {
|
||||
owner_signature: String,
|
||||
},
|
||||
UnbondMixnode {},
|
||||
UpdateMixnodeConfig {
|
||||
profit_margin_percent: u8,
|
||||
},
|
||||
BondGateway {
|
||||
gateway: Gateway,
|
||||
owner_signature: String,
|
||||
@@ -0,0 +1,9 @@
|
||||
[package]
|
||||
name = "vesting-contract-common"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
cosmwasm-std = "1.0.0-beta3"
|
||||
@@ -0,0 +1,133 @@
|
||||
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use cosmwasm_std::{Addr, Coin, Event, Timestamp};
|
||||
|
||||
// event types
|
||||
pub const WITHDRAW_EVENT_TYPE: &str = "vested_coins_withdraw";
|
||||
pub const OWNERSHIP_TRANSFER_EVENT_TYPE: &str = "ownership_transfer";
|
||||
pub const STAKING_ADDRESS_UPDATE_EVENT_TYPE: &str = "staking_address_update";
|
||||
pub const NEW_PERIODIC_VESTING_ACCOUNT_EVENT_TYPE: &str = "new_periodic_vesting_account";
|
||||
|
||||
pub const VESTING_DELEGATION_EVENT_TYPE: &str = "vesting_delegation";
|
||||
pub const VESTING_UNDELEGATION_EVENT_TYPE: &str = "vesting_undelegation";
|
||||
pub const VESTING_GATEWAY_BONDING_EVENT_TYPE: &str = "vesting_gateway_bonding";
|
||||
pub const VESTING_GATEWAY_UNBONDING_EVENT_TYPE: &str = "vesting_gateway_unbonding";
|
||||
pub const VESTING_MIXNODE_BONDING_EVENT_TYPE: &str = "vesting_mixnode_bonding";
|
||||
pub const VESTING_MIXNODE_UNBONDING_EVENT_TYPE: &str = "vesting_mixnode_unbonding";
|
||||
|
||||
pub const TRACK_MIXNODE_UNBOND_EVENT_TYPE: &str = "track_mixnode_unbond";
|
||||
pub const TRACK_GATEWAY_UNBOND_EVENT_TYPE: &str = "track_gateway_unbond";
|
||||
pub const TRACK_UNDELEGATION_EVENT_TYPE: &str = "track_undelegation";
|
||||
|
||||
// attributes that are used in multiple places
|
||||
pub const OWNER_KEY: &str = "owner";
|
||||
pub const AMOUNT_KEY: &str = "amount";
|
||||
|
||||
// event-specific attributes
|
||||
|
||||
// withdraw
|
||||
pub const REMAINING_SPENDABLE_KEY: &str = "remaining_spendable";
|
||||
|
||||
// ownership transfer
|
||||
pub const FROM_ACCOUNT_KEY: &str = "from";
|
||||
pub const TO_ACCOUNT_KEY: &str = "to";
|
||||
pub const NO_VALUE_VALUE: &str = "none";
|
||||
|
||||
// new vesting account
|
||||
pub const START_TIME_KEY: &str = "start_time";
|
||||
pub const STAKING_ADDRESS_KEY: &str = "staking_address";
|
||||
|
||||
// OPEN QUESTION: would it make sense to also emit amount of vesting/locked coins here?
|
||||
// however, then it would require additional storage reads.
|
||||
pub fn new_vested_coins_withdraw_event(
|
||||
address: &Addr,
|
||||
amount: &Coin,
|
||||
remaining_spendable: &Coin,
|
||||
) -> Event {
|
||||
Event::new(WITHDRAW_EVENT_TYPE)
|
||||
.add_attribute(OWNER_KEY, address)
|
||||
.add_attribute(AMOUNT_KEY, amount.to_string())
|
||||
.add_attribute(REMAINING_SPENDABLE_KEY, remaining_spendable.to_string())
|
||||
}
|
||||
|
||||
pub fn new_ownership_transfer_event(from: &Addr, to: &Addr) -> Event {
|
||||
Event::new(OWNERSHIP_TRANSFER_EVENT_TYPE)
|
||||
.add_attribute(FROM_ACCOUNT_KEY, from)
|
||||
.add_attribute(TO_ACCOUNT_KEY, to)
|
||||
}
|
||||
|
||||
pub fn new_staking_address_update_event(from: &Option<Addr>, to: &Option<Addr>) -> Event {
|
||||
let mut event = Event::new(OWNERSHIP_TRANSFER_EVENT_TYPE);
|
||||
|
||||
if let Some(from) = from {
|
||||
event = event.add_attribute(FROM_ACCOUNT_KEY, from)
|
||||
} else {
|
||||
event = event.add_attribute(FROM_ACCOUNT_KEY, NO_VALUE_VALUE);
|
||||
}
|
||||
|
||||
if let Some(to) = to {
|
||||
event = event.add_attribute(TO_ACCOUNT_KEY, to)
|
||||
} else {
|
||||
event = event.add_attribute(TO_ACCOUNT_KEY, NO_VALUE_VALUE);
|
||||
}
|
||||
|
||||
event
|
||||
}
|
||||
|
||||
pub fn new_periodic_vesting_account_event(
|
||||
owner_address: &Addr,
|
||||
amount: &Coin,
|
||||
staking_address: &Option<Addr>,
|
||||
start_time: Timestamp,
|
||||
) -> Event {
|
||||
let mut event = Event::new(NEW_PERIODIC_VESTING_ACCOUNT_EVENT_TYPE)
|
||||
.add_attribute(OWNER_KEY, owner_address)
|
||||
.add_attribute(AMOUNT_KEY, amount.to_string());
|
||||
|
||||
if let Some(staking_address) = staking_address {
|
||||
event = event.add_attribute(STAKING_ADDRESS_KEY, staking_address);
|
||||
}
|
||||
|
||||
event.add_attribute(START_TIME_KEY, start_time.to_string())
|
||||
}
|
||||
|
||||
// In most cases the events are rather barebone as there's no point in attaching
|
||||
// bunch of data to them as it would be redundant. It is because in most cases when the event is emitted
|
||||
// a call to the mixnet contract is made that throws another event with relevant attributes already attached.
|
||||
|
||||
pub fn new_vesting_gateway_bonding_event() -> Event {
|
||||
Event::new(VESTING_GATEWAY_BONDING_EVENT_TYPE)
|
||||
}
|
||||
|
||||
pub fn new_vesting_gateway_unbonding_event() -> Event {
|
||||
Event::new(VESTING_GATEWAY_UNBONDING_EVENT_TYPE)
|
||||
}
|
||||
|
||||
pub fn new_vesting_mixnode_bonding_event() -> Event {
|
||||
Event::new(VESTING_MIXNODE_BONDING_EVENT_TYPE)
|
||||
}
|
||||
|
||||
pub fn new_vesting_mixnode_unbonding_event() -> Event {
|
||||
Event::new(VESTING_MIXNODE_UNBONDING_EVENT_TYPE)
|
||||
}
|
||||
|
||||
pub fn new_vesting_delegation_event() -> Event {
|
||||
Event::new(VESTING_DELEGATION_EVENT_TYPE)
|
||||
}
|
||||
|
||||
pub fn new_vesting_undelegation_event() -> Event {
|
||||
Event::new(VESTING_UNDELEGATION_EVENT_TYPE)
|
||||
}
|
||||
|
||||
pub fn new_track_mixnode_unbond_event() -> Event {
|
||||
Event::new(TRACK_MIXNODE_UNBOND_EVENT_TYPE)
|
||||
}
|
||||
|
||||
pub fn new_track_gateway_unbond_event() -> Event {
|
||||
Event::new(TRACK_GATEWAY_UNBOND_EVENT_TYPE)
|
||||
}
|
||||
|
||||
pub fn new_track_undelegation_event() -> Event {
|
||||
Event::new(TRACK_UNDELEGATION_EVENT_TYPE)
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
pub mod events;
|
||||
@@ -9,7 +9,7 @@ edition = "2018"
|
||||
[dependencies]
|
||||
aes = { version = "0.7.4", features = ["ctr"] }
|
||||
bs58 = "0.4.0"
|
||||
blake3 = { version = "1.0.0", features = ["traits-preview"] }
|
||||
blake3 = { version = "~1.2.0", features = ["traits-preview"] }
|
||||
digest = "0.9.0"
|
||||
generic-array = "0.14"
|
||||
hkdf = "0.11.0"
|
||||
|
||||
@@ -22,7 +22,7 @@ where
|
||||
|
||||
let hkdf = Hkdf::<D>::new(salt, ikm);
|
||||
let mut okm = vec![0u8; okm_length];
|
||||
hkdf.expand(info.unwrap_or_else(|| &[]), &mut okm)?;
|
||||
hkdf.expand(info.unwrap_or(&[]), &mut okm)?;
|
||||
|
||||
Ok(okm)
|
||||
}
|
||||
|
||||
@@ -77,6 +77,7 @@ impl Config {
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub struct ConfigBuilder(Config);
|
||||
|
||||
impl ConfigBuilder {
|
||||
|
||||
@@ -7,6 +7,7 @@ edition = "2018"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
cfg-if = "1.0.0"
|
||||
hex-literal = "0.3.3"
|
||||
serde = {version = "1.0", features = ["derive"]}
|
||||
url = "2.2"
|
||||
|
||||
@@ -0,0 +1,130 @@
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::{milhon, qa, sandbox, ValidatorDetails};
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
|
||||
pub enum Network {
|
||||
MILHON,
|
||||
QA,
|
||||
SANDBOX,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub struct NetworkDetails {
|
||||
bech32_prefix: String,
|
||||
denom: String,
|
||||
mixnet_contract_address: String,
|
||||
vesting_contract_address: String,
|
||||
bandwidth_claim_contract_address: String,
|
||||
rewarding_validator_address: String,
|
||||
validators: Vec<ValidatorDetails>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub struct SupportedNetworks {
|
||||
networks: HashMap<Network, NetworkDetails>,
|
||||
}
|
||||
|
||||
impl SupportedNetworks {
|
||||
pub fn new(support: Vec<Network>) -> Self {
|
||||
let mut networks = HashMap::new();
|
||||
|
||||
for network in support {
|
||||
match network {
|
||||
Network::MILHON => networks.insert(
|
||||
Network::MILHON,
|
||||
NetworkDetails {
|
||||
bech32_prefix: String::from(milhon::BECH32_PREFIX),
|
||||
denom: String::from(milhon::DENOM),
|
||||
mixnet_contract_address: String::from(milhon::MIXNET_CONTRACT_ADDRESS),
|
||||
vesting_contract_address: String::from(milhon::VESTING_CONTRACT_ADDRESS),
|
||||
bandwidth_claim_contract_address: String::from(
|
||||
milhon::BANDWIDTH_CLAIM_CONTRACT_ADDRESS,
|
||||
),
|
||||
rewarding_validator_address: String::from(
|
||||
milhon::REWARDING_VALIDATOR_ADDRESS,
|
||||
),
|
||||
validators: milhon::validators(),
|
||||
},
|
||||
),
|
||||
Network::QA => networks.insert(
|
||||
Network::QA,
|
||||
NetworkDetails {
|
||||
bech32_prefix: String::from(qa::BECH32_PREFIX),
|
||||
denom: String::from(qa::DENOM),
|
||||
mixnet_contract_address: String::from(qa::MIXNET_CONTRACT_ADDRESS),
|
||||
vesting_contract_address: String::from(qa::VESTING_CONTRACT_ADDRESS),
|
||||
bandwidth_claim_contract_address: String::from(
|
||||
qa::BANDWIDTH_CLAIM_CONTRACT_ADDRESS,
|
||||
),
|
||||
rewarding_validator_address: String::from(qa::REWARDING_VALIDATOR_ADDRESS),
|
||||
validators: qa::validators(),
|
||||
},
|
||||
),
|
||||
Network::SANDBOX => networks.insert(
|
||||
Network::SANDBOX,
|
||||
NetworkDetails {
|
||||
bech32_prefix: String::from(sandbox::BECH32_PREFIX),
|
||||
denom: String::from(sandbox::DENOM),
|
||||
mixnet_contract_address: String::from(sandbox::MIXNET_CONTRACT_ADDRESS),
|
||||
vesting_contract_address: String::from(sandbox::VESTING_CONTRACT_ADDRESS),
|
||||
bandwidth_claim_contract_address: String::from(
|
||||
sandbox::BANDWIDTH_CLAIM_CONTRACT_ADDRESS,
|
||||
),
|
||||
rewarding_validator_address: String::from(
|
||||
sandbox::REWARDING_VALIDATOR_ADDRESS,
|
||||
),
|
||||
validators: sandbox::validators(),
|
||||
},
|
||||
),
|
||||
};
|
||||
}
|
||||
SupportedNetworks { networks }
|
||||
}
|
||||
|
||||
pub fn bech32_prefix(&self, network: Network) -> Option<&str> {
|
||||
self.networks
|
||||
.get(&network)
|
||||
.map(|network_details| network_details.bech32_prefix.as_str())
|
||||
}
|
||||
|
||||
pub fn denom(&self, network: Network) -> Option<&str> {
|
||||
self.networks
|
||||
.get(&network)
|
||||
.map(|network_details| network_details.denom.as_str())
|
||||
}
|
||||
|
||||
pub fn mixnet_contract_address(&self, network: Network) -> Option<&str> {
|
||||
self.networks
|
||||
.get(&network)
|
||||
.map(|network_details| network_details.mixnet_contract_address.as_str())
|
||||
}
|
||||
|
||||
pub fn vesting_contract_address(&self, network: Network) -> Option<&str> {
|
||||
self.networks
|
||||
.get(&network)
|
||||
.map(|network_details| network_details.vesting_contract_address.as_str())
|
||||
}
|
||||
|
||||
pub fn bandwidth_claim_contract_address(&self, network: Network) -> Option<&str> {
|
||||
self.networks
|
||||
.get(&network)
|
||||
.map(|network_details| network_details.bandwidth_claim_contract_address.as_str())
|
||||
}
|
||||
|
||||
pub fn rewarding_validator_address(&self, network: Network) -> Option<&str> {
|
||||
self.networks
|
||||
.get(&network)
|
||||
.map(|network_details| network_details.rewarding_validator_address.as_str())
|
||||
}
|
||||
|
||||
pub fn validators(&self, network: Network) -> Option<&Vec<ValidatorDetails>> {
|
||||
self.networks
|
||||
.get(&network)
|
||||
.map(|network_details| &network_details.validators)
|
||||
}
|
||||
}
|
||||
@@ -5,16 +5,63 @@ use std::time::Duration;
|
||||
use time::OffsetDateTime;
|
||||
use url::Url;
|
||||
|
||||
pub mod all;
|
||||
pub mod eth_contract;
|
||||
#[cfg(network = "milhon")]
|
||||
pub mod milhon;
|
||||
#[cfg(network = "sandbox")]
|
||||
pub mod sandbox;
|
||||
mod milhon;
|
||||
mod qa;
|
||||
mod sandbox;
|
||||
|
||||
#[cfg(network = "milhon")]
|
||||
pub use milhon::*;
|
||||
#[cfg(network = "sandbox")]
|
||||
pub use sandbox::*;
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(network = "milhon")] {
|
||||
pub const BECH32_PREFIX: &str = milhon::BECH32_PREFIX;
|
||||
pub const DENOM: &str = milhon::DENOM;
|
||||
|
||||
pub const DEFAULT_MIXNET_CONTRACT_ADDRESS: &str = milhon::MIXNET_CONTRACT_ADDRESS;
|
||||
pub const DEFAULT_VESTING_CONTRACT_ADDRESS: &str = milhon::VESTING_CONTRACT_ADDRESS;
|
||||
pub const DEFAULT_BANDWIDTH_CLAIM_CONTRACT_ADDRESS: &str = milhon::BANDWIDTH_CLAIM_CONTRACT_ADDRESS;
|
||||
pub const DEFAULT_REWARDING_VALIDATOR_ADDRESS: &str = milhon::REWARDING_VALIDATOR_ADDRESS;
|
||||
|
||||
pub fn default_validators() -> Vec<ValidatorDetails> {
|
||||
milhon::validators()
|
||||
}
|
||||
|
||||
pub fn default_network() -> all::Network {
|
||||
all::Network::MILHON
|
||||
}
|
||||
} else if #[cfg(network = "qa")] {
|
||||
pub const BECH32_PREFIX: &str = qa::BECH32_PREFIX;
|
||||
pub const DENOM: &str = qa::DENOM;
|
||||
|
||||
pub const DEFAULT_MIXNET_CONTRACT_ADDRESS: &str = qa::MIXNET_CONTRACT_ADDRESS;
|
||||
pub const DEFAULT_VESTING_CONTRACT_ADDRESS: &str = qa::VESTING_CONTRACT_ADDRESS;
|
||||
pub const DEFAULT_BANDWIDTH_CLAIM_CONTRACT_ADDRESS: &str = qa::BANDWIDTH_CLAIM_CONTRACT_ADDRESS;
|
||||
pub const DEFAULT_REWARDING_VALIDATOR: &str = qa::REWARDING_VALIDATOR_ADDRESS;
|
||||
|
||||
pub fn default_validators() -> Vec<ValidatorDetails> {
|
||||
qa::validators()
|
||||
}
|
||||
|
||||
pub fn default_network() -> all::Network {
|
||||
all::Network::QA
|
||||
}
|
||||
} else if #[cfg(network = "sandbox")] {
|
||||
pub const BECH32_PREFIX: &str = sandbox::BECH32_PREFIX;
|
||||
pub const DENOM: &str = sandbox::DENOM;
|
||||
|
||||
pub const DEFAULT_MIXNET_CONTRACT_ADDRESS: &str = sandbox::MIXNET_CONTRACT_ADDRESS;
|
||||
pub const DEFAULT_VESTING_CONTRACT_ADDRESS: &str = sandbox::VESTING_CONTRACT_ADDRESS;
|
||||
pub const DEFAULT_BANDWIDTH_CLAIM_CONTRACT_ADDRESS: &str = sandbox::BANDWIDTH_CLAIM_CONTRACT_ADDRESS;
|
||||
pub const DEFAULT_REWARDING_VALIDATOR: &str = sandbox::REWARDING_VALIDATOR_ADDRESS;
|
||||
|
||||
pub fn default_validators() -> Vec<ValidatorDetails> {
|
||||
sandbox::validators()
|
||||
}
|
||||
|
||||
pub fn default_network() -> all::Network {
|
||||
all::Network::SANDBOX
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct ValidatorDetails {
|
||||
@@ -47,25 +94,6 @@ impl ValidatorDetails {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(network = "milhon")]
|
||||
pub fn default_validators() -> Vec<ValidatorDetails> {
|
||||
vec![
|
||||
ValidatorDetails::new(
|
||||
"https://testnet-milhon-validator1.nymtech.net",
|
||||
Some("https://testnet-milhon-validator1.nymtech.net/api"),
|
||||
),
|
||||
ValidatorDetails::new("https://testnet-milhon-validator2.nymtech.net", None),
|
||||
]
|
||||
}
|
||||
|
||||
#[cfg(network = "sandbox")]
|
||||
pub fn default_validators() -> Vec<ValidatorDetails> {
|
||||
vec![ValidatorDetails::new(
|
||||
"https://sandbox-validator.nymtech.net",
|
||||
Some("https://sandbox-validator.nymtech.net/api"),
|
||||
)]
|
||||
}
|
||||
|
||||
pub fn default_nymd_endpoints() -> Vec<Url> {
|
||||
default_validators()
|
||||
.iter()
|
||||
@@ -80,6 +108,13 @@ pub fn default_api_endpoints() -> Vec<Url> {
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub const ETH_CONTRACT_ADDRESS: [u8; 20] =
|
||||
hex_literal::hex!("9fEE3e28c17dbB87310A51F13C4fbf4331A6f102");
|
||||
// Name of the event triggered by the eth contract. If the event name is changed,
|
||||
// this would also need to be changed; It is currently tested against the json abi
|
||||
pub const ETH_EVENT_NAME: &str = "Burned";
|
||||
pub const ETH_BURN_FUNCTION_NAME: &str = "burnTokenForAccessCode";
|
||||
|
||||
// Ethereum constants used for token bridge
|
||||
/// How much bandwidth (in bytes) one token can buy
|
||||
const BYTES_PER_TOKEN: u64 = 1024 * 1024 * 1024;
|
||||
|
||||
@@ -1,17 +1,23 @@
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
pub const BECH32_PREFIX: &str = "punk";
|
||||
pub const DENOM: &str = "upunk";
|
||||
use crate::ValidatorDetails;
|
||||
|
||||
pub const DEFAULT_MIXNET_CONTRACT_ADDRESS: &str = "punk10pyejy66429refv3g35g2t7am0was7yalwrzen";
|
||||
pub const DEFAULT_VESTING_CONTRACT_ADDRESS: &str = "";
|
||||
pub const BANDWIDTH_CLAIM_CONTRACT_ADDRESS: &str = "punk1jld76tqw4wnpfenmay2xkv86nr3j0w426eka82";
|
||||
pub const REWARDING_VALIDATOR_ADDRESS: &str = "punk1v9qauwdq5terag6uvfsdytcs2d0sdmfdy7hgk3";
|
||||
pub const ETH_CONTRACT_ADDRESS: [u8; 20] =
|
||||
hex_literal::hex!("9fEE3e28c17dbB87310A51F13C4fbf4331A6f102");
|
||||
pub(crate) const BECH32_PREFIX: &str = "punk";
|
||||
pub(crate) const DENOM: &str = "upunk";
|
||||
|
||||
// Name of the event triggered by the eth contract. If the event name is changed,
|
||||
// this would also need to be changed; It is currently tested against the json abi
|
||||
pub const ETH_EVENT_NAME: &str = "Burned";
|
||||
pub const ETH_BURN_FUNCTION_NAME: &str = "burnTokenForAccessCode";
|
||||
pub(crate) const MIXNET_CONTRACT_ADDRESS: &str = "punk10pyejy66429refv3g35g2t7am0was7yalwrzen";
|
||||
pub(crate) const VESTING_CONTRACT_ADDRESS: &str = "";
|
||||
pub(crate) const BANDWIDTH_CLAIM_CONTRACT_ADDRESS: &str =
|
||||
"punk1jld76tqw4wnpfenmay2xkv86nr3j0w426eka82";
|
||||
pub(crate) const REWARDING_VALIDATOR_ADDRESS: &str = "punk1v9qauwdq5terag6uvfsdytcs2d0sdmfdy7hgk3";
|
||||
|
||||
pub(crate) fn validators() -> Vec<ValidatorDetails> {
|
||||
vec![
|
||||
ValidatorDetails::new(
|
||||
"https://testnet-milhon-validator1.nymtech.net",
|
||||
Some("https://testnet-milhon-validator1.nymtech.net/api"),
|
||||
),
|
||||
ValidatorDetails::new("https://testnet-milhon-validator2.nymtech.net", None),
|
||||
]
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::ValidatorDetails;
|
||||
|
||||
pub(crate) const BECH32_PREFIX: &str = "nymt";
|
||||
pub(crate) const DENOM: &str = "unymt";
|
||||
|
||||
pub(crate) const MIXNET_CONTRACT_ADDRESS: &str = "nymt14hj2tavq8fpesdwxxcu44rty3hh90vhuysqrsr";
|
||||
pub(crate) const VESTING_CONTRACT_ADDRESS: &str = "nymt17p9rzwnnfxcjp32un9ug7yhhzgtkhvl9f8xzkv";
|
||||
pub(crate) const BANDWIDTH_CLAIM_CONTRACT_ADDRESS: &str =
|
||||
"nymt17p9rzwnnfxcjp32un9ug7yhhzgtkhvl9f8xzkv";
|
||||
pub(crate) const REWARDING_VALIDATOR_ADDRESS: &str = "nymt1dn52nx8wv9wkqmrvj6tcmdzh4es6jt8tr7f6j9";
|
||||
|
||||
pub(crate) fn validators() -> Vec<ValidatorDetails> {
|
||||
vec![ValidatorDetails::new(
|
||||
"https://qa-validator.nymtech.net",
|
||||
Some("https://qa-validator.nymtech.net/api"),
|
||||
)]
|
||||
}
|
||||
@@ -1,17 +1,20 @@
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
pub const BECH32_PREFIX: &str = "nymt";
|
||||
pub const DENOM: &str = "unymt";
|
||||
use crate::ValidatorDetails;
|
||||
|
||||
pub const DEFAULT_MIXNET_CONTRACT_ADDRESS: &str = "nymt1ghd753shjuwexxywmgs4xz7x2q732vcnstz02j";
|
||||
pub const DEFAULT_VESTING_CONTRACT_ADDRESS: &str = "nymt1nc5tatafv6eyq7llkr2gv50ff9e22mnfp9pc5s";
|
||||
pub const BANDWIDTH_CLAIM_CONTRACT_ADDRESS: &str = "nymt17p9rzwnnfxcjp32un9ug7yhhzgtkhvl9f8xzkv";
|
||||
pub const REWARDING_VALIDATOR_ADDRESS: &str = "nymt17zujduc46wvkwvp6f062mm5xhr7jc3fewvqu9e";
|
||||
pub const ETH_CONTRACT_ADDRESS: [u8; 20] =
|
||||
hex_literal::hex!("9fEE3e28c17dbB87310A51F13C4fbf4331A6f102");
|
||||
pub(crate) const BECH32_PREFIX: &str = "nymt";
|
||||
pub(crate) const DENOM: &str = "unymt";
|
||||
|
||||
// Name of the event triggered by the eth contract. If the event name is changed,
|
||||
// this would also need to be changed; It is currently tested against the json abi
|
||||
pub const ETH_EVENT_NAME: &str = "Burned";
|
||||
pub const ETH_BURN_FUNCTION_NAME: &str = "burnTokenForAccessCode";
|
||||
pub(crate) const MIXNET_CONTRACT_ADDRESS: &str = "nymt1ghd753shjuwexxywmgs4xz7x2q732vcnstz02j";
|
||||
pub(crate) const VESTING_CONTRACT_ADDRESS: &str = "nymt1nc5tatafv6eyq7llkr2gv50ff9e22mnfp9pc5s";
|
||||
pub(crate) const BANDWIDTH_CLAIM_CONTRACT_ADDRESS: &str =
|
||||
"nymt17p9rzwnnfxcjp32un9ug7yhhzgtkhvl9f8xzkv";
|
||||
pub(crate) const REWARDING_VALIDATOR_ADDRESS: &str = "nymt17zujduc46wvkwvp6f062mm5xhr7jc3fewvqu9e";
|
||||
|
||||
pub(crate) fn validators() -> Vec<ValidatorDetails> {
|
||||
vec![ValidatorDetails::new(
|
||||
"https://sandbox-validator.nymtech.net",
|
||||
Some("https://sandbox-validator.nymtech.net/api"),
|
||||
)]
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ crypto = { path = "../crypto" }
|
||||
topology = { path = "../topology" }
|
||||
|
||||
[dev-dependencies]
|
||||
mixnet-contract = { path = "../mixnet-contract" }
|
||||
mixnet-contract-common = { path = "../cosmwasm-smart-contracts/mixnet-contract" }
|
||||
|
||||
# do not include this when compiling into wasm as it somehow when combined together with reqwest, it will require
|
||||
# net2 via tokio-util -> tokio -> mio -> net2
|
||||
|
||||
@@ -54,6 +54,7 @@ impl From<NymTopologyError> for PreparationError {
|
||||
/// an optional reply-SURB, padding it to appropriate length, encrypting its content,
|
||||
/// and chunking into appropriate size [`Fragment`]s.
|
||||
#[cfg_attr(not(target_arch = "wasm32"), derive(Clone))]
|
||||
#[must_use]
|
||||
pub struct MessagePreparer<R: CryptoRng + Rng> {
|
||||
/// Instance of a cryptographically secure random number generator.
|
||||
rng: R,
|
||||
@@ -386,13 +387,7 @@ where
|
||||
// (note: surb_ack_bytes contains SURB_ACK_FIRST_HOP || SURB_ACK_DATA )
|
||||
let packet_payload: Vec<_> = surb_ack_bytes
|
||||
.into_iter()
|
||||
.chain(
|
||||
reply_surb
|
||||
.encryption_key()
|
||||
.compute_digest()
|
||||
.to_vec()
|
||||
.into_iter(),
|
||||
)
|
||||
.chain(reply_surb.encryption_key().compute_digest().iter().copied())
|
||||
.chain(reply_content.into_iter())
|
||||
.collect();
|
||||
|
||||
|
||||
@@ -58,6 +58,7 @@ impl MessageReceiver {
|
||||
}
|
||||
|
||||
/// Allows setting non-default number of expected mix hops in the network.
|
||||
#[must_use]
|
||||
pub fn with_mix_hops(mut self, hops: u8) -> Self {
|
||||
self.num_mix_hops = hops;
|
||||
self
|
||||
@@ -186,7 +187,7 @@ impl Default for MessageReceiver {
|
||||
mod message_receiver {
|
||||
use super::*;
|
||||
use crypto::asymmetric::identity;
|
||||
use mixnet_contract::Layer;
|
||||
use mixnet_contract_common::Layer;
|
||||
use nymsphinx_addressing::clients::Recipient;
|
||||
use rand::rngs::OsRng;
|
||||
use std::collections::HashMap;
|
||||
|
||||
@@ -13,7 +13,7 @@ rand = { version = "0.7.3", features = ["wasm-bindgen"] }
|
||||
|
||||
## internal
|
||||
crypto = { path = "../crypto" }
|
||||
mixnet-contract = { path = "../mixnet-contract" }
|
||||
mixnet-contract-common = { path = "../cosmwasm-smart-contracts/mixnet-contract" }
|
||||
nymsphinx-addressing = { path = "../nymsphinx/addressing" }
|
||||
nymsphinx-types = { path = "../nymsphinx/types" }
|
||||
version-checker = { path = "../version-checker" }
|
||||
|
||||
@@ -9,6 +9,7 @@ pub trait Versioned: Clone {
|
||||
}
|
||||
|
||||
pub trait VersionFilterable<T> {
|
||||
#[must_use]
|
||||
fn filter_by_version(&self, expected_version: &str) -> Self;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
use crate::{filter, NetworkAddress};
|
||||
use crypto::asymmetric::{encryption, identity};
|
||||
use mixnet_contract::GatewayBond;
|
||||
use mixnet_contract_common::GatewayBond;
|
||||
use nymsphinx_addressing::nodes::{NodeIdentity, NymNodeRoutingAddress};
|
||||
use nymsphinx_types::Node as SphinxNode;
|
||||
use std::convert::{TryFrom, TryInto};
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
use crate::filter::VersionFilterable;
|
||||
use log::warn;
|
||||
use mixnet_contract::{GatewayBond, MixNodeBond};
|
||||
use mixnet_contract_common::{GatewayBond, MixNodeBond};
|
||||
use nymsphinx_addressing::nodes::NodeIdentity;
|
||||
use nymsphinx_types::Node as SphinxNode;
|
||||
use rand::Rng;
|
||||
@@ -206,10 +206,12 @@ impl NymTopology {
|
||||
true
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn filter_system_version(&self, expected_version: &str) -> Self {
|
||||
self.filter_node_versions(expected_version, expected_version)
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn filter_node_versions(
|
||||
&self,
|
||||
expected_mix_version: &str,
|
||||
@@ -272,7 +274,7 @@ mod converting_mixes_to_vec {
|
||||
use crypto::asymmetric::{encryption, identity};
|
||||
|
||||
use super::*;
|
||||
use mixnet_contract::Layer;
|
||||
use mixnet_contract_common::Layer;
|
||||
|
||||
#[test]
|
||||
fn returns_a_vec_with_hashmap_values() {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
use crate::{filter, NetworkAddress};
|
||||
use crypto::asymmetric::{encryption, identity};
|
||||
use mixnet_contract::{Layer, MixNodeBond};
|
||||
use mixnet_contract_common::{Layer, MixNodeBond};
|
||||
use nymsphinx_addressing::nodes::NymNodeRoutingAddress;
|
||||
use nymsphinx_types::Node as SphinxNode;
|
||||
use std::convert::{TryFrom, TryInto};
|
||||
|
||||
Generated
+58
-76
@@ -236,11 +236,18 @@ version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc"
|
||||
|
||||
[[package]]
|
||||
name = "contracts-common"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"cosmwasm-std",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cosmwasm-crypto"
|
||||
version = "1.0.0-beta3"
|
||||
version = "1.0.0-beta4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a380b87642204557629c9b72988c47b55fbfe6d474960adba56b22331504956a"
|
||||
checksum = "f903ebbabc0d4880dbc76148efb8be8fc29fa4bf294c440c3d70da1c8bcafff7"
|
||||
dependencies = [
|
||||
"digest 0.9.0",
|
||||
"ed25519-zebra",
|
||||
@@ -251,9 +258,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cosmwasm-derive"
|
||||
version = "1.0.0-beta3"
|
||||
version = "1.0.0-beta4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "866713b2fe13f23038c7d8824c3059d1f28dd94685fb406d1533c4eeeefeefae"
|
||||
checksum = "832bebef577ecb394603de8e2bf0de429b74aa364e17dec18e15ce37e71b0cae"
|
||||
dependencies = [
|
||||
"syn",
|
||||
]
|
||||
@@ -270,9 +277,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cosmwasm-std"
|
||||
version = "1.0.0-beta3"
|
||||
version = "1.0.0-beta4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8dbb9939b31441dfa9af3ec9740c8a24d585688401eff1b6b386abb7ad0d10a8"
|
||||
checksum = "6238c45840cc9de5a39f0f619e3a4f7c38c5d2c6ac9e3e4d72751ee045e6d7da"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"cosmwasm-crypto",
|
||||
@@ -286,9 +293,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cosmwasm-storage"
|
||||
version = "1.0.0-beta3"
|
||||
version = "1.0.0-beta4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b4a4e55f0d64fed54cd2202301b8d466af8de044589247dabd77a4222f52f749"
|
||||
checksum = "f472c0bfd584a4510702537d0b65c5331095e76099586a12f749fd69afda9c5e"
|
||||
dependencies = [
|
||||
"cosmwasm-std",
|
||||
"serde",
|
||||
@@ -326,7 +333,7 @@ dependencies = [
|
||||
"log",
|
||||
"nymsphinx-types",
|
||||
"pemstore",
|
||||
"rand 0.7.3",
|
||||
"rand",
|
||||
"subtle-encoding",
|
||||
"x25519-dalek",
|
||||
]
|
||||
@@ -387,9 +394,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cw-storage-plus"
|
||||
version = "0.10.3"
|
||||
version = "0.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d3b8b840947313c1a1cccf056836cd79a60b4526bdcd6582995be37dc97be4ae"
|
||||
checksum = "7d7ee1963302b0ac2a9d42fe0faec826209c17452bfd36fbfd9d002a88929261"
|
||||
dependencies = [
|
||||
"cosmwasm-std",
|
||||
"schemars",
|
||||
@@ -458,7 +465,7 @@ checksum = "c762bae6dcaf24c4c84667b8579785430908723d5c889f469d76a41d59cc7a9d"
|
||||
dependencies = [
|
||||
"curve25519-dalek",
|
||||
"ed25519",
|
||||
"rand 0.7.3",
|
||||
"rand",
|
||||
"serde",
|
||||
"sha2",
|
||||
"zeroize",
|
||||
@@ -592,10 +599,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"js-sys",
|
||||
"libc",
|
||||
"wasi 0.10.2+wasi-snapshot-preview1",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -833,8 +838,31 @@ checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f"
|
||||
[[package]]
|
||||
name = "mixnet-contract"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bs58",
|
||||
"config",
|
||||
"cosmwasm-schema",
|
||||
"cosmwasm-std",
|
||||
"cosmwasm-storage",
|
||||
"crypto",
|
||||
"cw-storage-plus",
|
||||
"fixed",
|
||||
"mixnet-contract-common",
|
||||
"rand",
|
||||
"rand_chacha",
|
||||
"schemars",
|
||||
"serde",
|
||||
"thiserror",
|
||||
"vergen",
|
||||
"vesting-contract",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mixnet-contract-common"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"az",
|
||||
"contracts-common",
|
||||
"cosmwasm-std",
|
||||
"fixed",
|
||||
"log",
|
||||
@@ -845,32 +873,11 @@ dependencies = [
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mixnet-contracts"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bs58",
|
||||
"config",
|
||||
"cosmwasm-schema",
|
||||
"cosmwasm-std",
|
||||
"cosmwasm-storage",
|
||||
"crypto",
|
||||
"cw-storage-plus",
|
||||
"fixed",
|
||||
"mixnet-contract",
|
||||
"rand 0.7.3",
|
||||
"rand_chacha 0.2.2",
|
||||
"schemars",
|
||||
"serde",
|
||||
"thiserror",
|
||||
"vergen",
|
||||
"vesting-contract",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "network-defaults"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"hex-literal",
|
||||
"serde",
|
||||
"time 0.3.5",
|
||||
@@ -1067,21 +1074,9 @@ checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
|
||||
dependencies = [
|
||||
"getrandom 0.1.16",
|
||||
"libc",
|
||||
"rand_chacha 0.2.2",
|
||||
"rand_chacha",
|
||||
"rand_core 0.5.1",
|
||||
"rand_hc 0.2.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.8.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"rand_chacha 0.3.1",
|
||||
"rand_core 0.6.3",
|
||||
"rand_hc 0.3.1",
|
||||
"rand_hc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1094,16 +1089,6 @@ dependencies = [
|
||||
"rand_core 0.5.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_chacha"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
|
||||
dependencies = [
|
||||
"ppv-lite86",
|
||||
"rand_core 0.6.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.5.1"
|
||||
@@ -1129,7 +1114,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c9e9532ada3929fb8b2e9dbe28d1e06c9b2cc65813f074fcb6bd5fbefeff9d56"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
"rand 0.7.3",
|
||||
"rand",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1141,15 +1126,6 @@ dependencies = [
|
||||
"rand_core 0.5.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_hc"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7"
|
||||
dependencies = [
|
||||
"rand_core 0.6.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.5.4"
|
||||
@@ -1227,9 +1203,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde-json-wasm"
|
||||
version = "0.3.1"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "50eef3672ec8fa45f3457fd423ba131117786784a895548021976117c1ded449"
|
||||
checksum = "042ac496d97e5885149d34139bad1d617192770d7eb8f1866da2317ff4501853"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
@@ -1330,7 +1306,7 @@ dependencies = [
|
||||
"hmac",
|
||||
"lioness",
|
||||
"log",
|
||||
"rand 0.7.3",
|
||||
"rand",
|
||||
"rand_distr",
|
||||
"sha2",
|
||||
"subtle 2.4.1",
|
||||
@@ -1558,12 +1534,18 @@ dependencies = [
|
||||
"config",
|
||||
"cosmwasm-std",
|
||||
"cw-storage-plus",
|
||||
"getrandom 0.2.3",
|
||||
"mixnet-contract",
|
||||
"rand 0.8.4",
|
||||
"mixnet-contract-common",
|
||||
"schemars",
|
||||
"serde",
|
||||
"thiserror",
|
||||
"vesting-contract-common",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "vesting-contract-common"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"cosmwasm-std",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
+9
-9
@@ -1556,9 +1556,9 @@
|
||||
}
|
||||
},
|
||||
"@openzeppelin/contracts": {
|
||||
"version": "4.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-4.4.1.tgz",
|
||||
"integrity": "sha512-o+pHCf/yMLSlV5MkDQEzEQL402i6SoRnktru+0rdSxVEFZcTzzGhZCAtZjUFyKGazMSv1TilzMg+RbED1N8XHQ=="
|
||||
"version": "4.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-4.4.2.tgz",
|
||||
"integrity": "sha512-NyJV7sJgoGYqbtNUWgzzOGW4T6rR19FmX1IJgXGdapGPWsuMelGJn9h03nos0iqfforCbCB0iYIR0MtIuIFLLw=="
|
||||
},
|
||||
"@openzeppelin/test-helpers": {
|
||||
"version": "0.5.15",
|
||||
@@ -5059,9 +5059,9 @@
|
||||
}
|
||||
},
|
||||
"follow-redirects": {
|
||||
"version": "1.14.4",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.4.tgz",
|
||||
"integrity": "sha512-zwGkiSXC1MUJG/qmeIFH2HBJx9u0V46QGUe3YR1fXG8bXQxq7fLj0RjLZQ5nubr9qNJUZrH+xUcwXEoXNpfS+g==",
|
||||
"version": "1.14.7",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.7.tgz",
|
||||
"integrity": "sha512-+hbxoLbFMbRKDwohX8GkTataGqO6Jb7jGwpAlwgy2bIz25XtRm7KEzJM76R1WiNT5SwZkX4Y75SwBolkpmE7iQ==",
|
||||
"dev": true
|
||||
},
|
||||
"for-each": {
|
||||
@@ -17880,9 +17880,9 @@
|
||||
"integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM="
|
||||
},
|
||||
"shelljs": {
|
||||
"version": "0.8.4",
|
||||
"resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.4.tgz",
|
||||
"integrity": "sha512-7gk3UZ9kOfPLIAbslLzyWeGiEqx9e3rxwZM0KE6EL8GlGwjym9Mrlx5/p33bWTu9YG6vcS4MBxYZDHYr5lr8BQ==",
|
||||
"version": "0.8.5",
|
||||
"resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz",
|
||||
"integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"glob": "^7.0.0",
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
"dependencies": {
|
||||
"@nomiclabs/hardhat-truffle5": "^2.0.2",
|
||||
"@nomiclabs/hardhat-web3": "^2.0.0",
|
||||
"@openzeppelin/contracts": "^4.4.1",
|
||||
"@openzeppelin/contracts": "^4.4.2",
|
||||
"@openzeppelin/test-helpers": "^0.5.15",
|
||||
"dotenv": "^10.0.0",
|
||||
"find-config": "^1.0.0"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
[package]
|
||||
name = "mixnet-contracts"
|
||||
name = "mixnet-contract"
|
||||
version = "0.1.0"
|
||||
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"]
|
||||
edition = "2018"
|
||||
@@ -16,13 +16,13 @@ exclude = [
|
||||
crate-type = ["cdylib", "rlib"]
|
||||
|
||||
[dependencies]
|
||||
mixnet-contract = { path = "../../common/mixnet-contract" }
|
||||
mixnet-contract-common = { path = "../../common/cosmwasm-smart-contracts/mixnet-contract" }
|
||||
config = { path = "../../common/config"}
|
||||
vesting-contract = { path = "../vesting" }
|
||||
|
||||
cosmwasm-std = "1.0.0-beta3"
|
||||
cosmwasm-storage = "1.0.0-beta3"
|
||||
cw-storage-plus = "0.10.3"
|
||||
cosmwasm-std = "1.0.0-beta4"
|
||||
cosmwasm-storage = "1.0.0-beta4"
|
||||
cw-storage-plus = "0.11.1"
|
||||
|
||||
bs58 = "0.4.0"
|
||||
schemars = "0.8"
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
extern crate mixnet_contract;
|
||||
|
||||
use cosmwasm_schema::{export_schema, remove_schemas, schema_for};
|
||||
use mixnet_contract::{ExecuteMsg, InstantiateMsg, MixNodeBond, QueryMsg};
|
||||
use mixnet_contract_common::{ExecuteMsg, InstantiateMsg, MixNodeBond, QueryMsg};
|
||||
use std::env::current_dir;
|
||||
use std::fs::create_dir_all;
|
||||
|
||||
|
||||
@@ -23,7 +23,9 @@ use crate::rewards::storage as rewards_storage;
|
||||
use cosmwasm_std::{
|
||||
entry_point, to_binary, Addr, Deps, DepsMut, Env, MessageInfo, QueryResponse, Response, Uint128,
|
||||
};
|
||||
use mixnet_contract::{ContractStateParams, ExecuteMsg, InstantiateMsg, MigrateMsg, QueryMsg};
|
||||
use mixnet_contract_common::{
|
||||
ContractStateParams, ExecuteMsg, InstantiateMsg, MigrateMsg, QueryMsg,
|
||||
};
|
||||
|
||||
/// Constant specifying minimum of coin required to bond a gateway
|
||||
pub const INITIAL_GATEWAY_PLEDGE: Uint128 = Uint128::new(100_000_000);
|
||||
@@ -104,6 +106,14 @@ pub fn execute(
|
||||
ExecuteMsg::UnbondMixnode {} => {
|
||||
crate::mixnodes::transactions::try_remove_mixnode(deps, info)
|
||||
}
|
||||
ExecuteMsg::UpdateMixnodeConfig {
|
||||
profit_margin_percent,
|
||||
} => crate::mixnodes::transactions::try_update_mixnode_config(
|
||||
deps,
|
||||
env,
|
||||
info,
|
||||
profit_margin_percent,
|
||||
),
|
||||
ExecuteMsg::BondGateway {
|
||||
gateway,
|
||||
owner_signature,
|
||||
@@ -292,14 +302,14 @@ pub mod tests {
|
||||
use config::defaults::DENOM;
|
||||
use cosmwasm_std::testing::{mock_dependencies, mock_env, mock_info};
|
||||
use cosmwasm_std::{coins, from_binary};
|
||||
use mixnet_contract::PagedMixnodeResponse;
|
||||
use mixnet_contract_common::PagedMixnodeResponse;
|
||||
|
||||
#[test]
|
||||
fn initialize_contract() {
|
||||
let mut deps = mock_dependencies();
|
||||
let env = mock_env();
|
||||
let msg = InstantiateMsg {
|
||||
rewarding_validator_address: config::defaults::REWARDING_VALIDATOR_ADDRESS.to_string(),
|
||||
rewarding_validator_address: config::defaults::DEFAULT_REWARDING_VALIDATOR.to_string(),
|
||||
};
|
||||
let info = mock_info("creator", &[]);
|
||||
|
||||
|
||||
@@ -7,10 +7,10 @@ use cosmwasm_std::Deps;
|
||||
use cosmwasm_std::Order;
|
||||
use cosmwasm_std::StdResult;
|
||||
use cw_storage_plus::{Bound, PrimaryKey};
|
||||
use mixnet_contract::PagedAllDelegationsResponse;
|
||||
use mixnet_contract::PagedDelegatorDelegationsResponse;
|
||||
use mixnet_contract::PagedMixDelegationsResponse;
|
||||
use mixnet_contract::{Delegation, IdentityKey};
|
||||
use mixnet_contract_common::{
|
||||
Delegation, IdentityKey, PagedAllDelegationsResponse, PagedDelegatorDelegationsResponse,
|
||||
PagedMixDelegationsResponse,
|
||||
};
|
||||
|
||||
pub(crate) fn query_all_network_delegations_paged(
|
||||
deps: Deps,
|
||||
@@ -140,7 +140,7 @@ pub(crate) mod tests {
|
||||
#[cfg(test)]
|
||||
mod querying_for_mixnode_delegations_paged {
|
||||
use super::*;
|
||||
use mixnet_contract::IdentityKey;
|
||||
use mixnet_contract_common::IdentityKey;
|
||||
|
||||
#[test]
|
||||
fn retrieval_obeys_limits() {
|
||||
@@ -281,7 +281,7 @@ pub(crate) mod tests {
|
||||
mod querying_for_all_mixnode_delegations_paged {
|
||||
use super::*;
|
||||
use crate::support::tests::test_helpers;
|
||||
use mixnet_contract::IdentityKey;
|
||||
use mixnet_contract_common::IdentityKey;
|
||||
|
||||
#[test]
|
||||
fn retrieval_obeys_limits() {
|
||||
@@ -444,7 +444,7 @@ pub(crate) mod tests {
|
||||
|
||||
// add delegation from a different address
|
||||
let delegation = Delegation::new(
|
||||
delegation_owner2.clone(),
|
||||
delegation_owner2,
|
||||
node_identity1.clone(),
|
||||
coin(1234, DENOM),
|
||||
1234,
|
||||
@@ -474,7 +474,7 @@ pub(crate) mod tests {
|
||||
// add delegation for a different node
|
||||
let delegation = Delegation::new(
|
||||
delegation_owner1.clone(),
|
||||
node_identity2.clone(),
|
||||
node_identity2,
|
||||
coin(1234, DENOM),
|
||||
1234,
|
||||
None,
|
||||
@@ -493,11 +493,7 @@ pub(crate) mod tests {
|
||||
identity: node_identity1.clone(),
|
||||
address: Addr::unchecked(delegation_owner1.clone())
|
||||
}),
|
||||
query_mixnode_delegation(
|
||||
deps.as_ref(),
|
||||
node_identity1.clone(),
|
||||
delegation_owner1.to_string()
|
||||
)
|
||||
query_mixnode_delegation(deps.as_ref(), node_identity1, delegation_owner1.to_string())
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use cw_storage_plus::{Index, IndexList, IndexedMap, MultiIndex};
|
||||
use mixnet_contract::{Addr, Delegation, IdentityKey};
|
||||
use mixnet_contract_common::{Addr, Delegation, IdentityKey};
|
||||
|
||||
// storage prefixes
|
||||
const DELEGATION_PK_NAMESPACE: &str = "dl";
|
||||
@@ -17,9 +17,9 @@ pub(crate) const DELEGATION_PAGE_DEFAULT_LIMIT: u32 = 250;
|
||||
type PrimaryKey = Vec<u8>;
|
||||
|
||||
pub(crate) struct DelegationIndex<'a> {
|
||||
pub(crate) owner: MultiIndex<'a, (Addr, PrimaryKey), Delegation>,
|
||||
pub(crate) owner: MultiIndex<'a, Addr, Delegation>,
|
||||
|
||||
pub(crate) mixnode: MultiIndex<'a, (IdentityKey, PrimaryKey), Delegation>,
|
||||
pub(crate) mixnode: MultiIndex<'a, IdentityKey, Delegation>,
|
||||
}
|
||||
|
||||
impl<'a> IndexList<Delegation> for DelegationIndex<'a> {
|
||||
@@ -46,12 +46,12 @@ impl<'a> IndexList<Delegation> for DelegationIndex<'a> {
|
||||
pub(crate) fn delegations<'a>() -> IndexedMap<'a, PrimaryKey, Delegation, DelegationIndex<'a>> {
|
||||
let indexes = DelegationIndex {
|
||||
owner: MultiIndex::new(
|
||||
|d, pk| (d.owner.clone(), pk),
|
||||
|d| d.owner.clone(),
|
||||
DELEGATION_PK_NAMESPACE,
|
||||
DELEGATION_OWNER_IDX_NAMESPACE,
|
||||
),
|
||||
mixnode: MultiIndex::new(
|
||||
|d, pk| (d.node_identity.clone(), pk),
|
||||
|d| d.node_identity.clone(),
|
||||
DELEGATION_PK_NAMESPACE,
|
||||
DELEGATION_MIXNODE_IDX_NAMESPACE,
|
||||
),
|
||||
@@ -64,7 +64,7 @@ pub(crate) fn delegations<'a>() -> IndexedMap<'a, PrimaryKey, Delegation, Delega
|
||||
mod tests {
|
||||
use crate::delegations::storage;
|
||||
use cosmwasm_std::Addr;
|
||||
use mixnet_contract::IdentityKey;
|
||||
use mixnet_contract_common::IdentityKey;
|
||||
|
||||
#[cfg(test)]
|
||||
mod reverse_mix_delegations {
|
||||
@@ -74,7 +74,7 @@ mod tests {
|
||||
use cosmwasm_std::testing::mock_env;
|
||||
use cosmwasm_std::{coin, Order};
|
||||
use cw_storage_plus::PrimaryKey;
|
||||
use mixnet_contract::Delegation;
|
||||
use mixnet_contract_common::Delegation;
|
||||
|
||||
#[test]
|
||||
fn reverse_mix_delegation_exists() {
|
||||
@@ -94,7 +94,7 @@ mod tests {
|
||||
storage::delegations()
|
||||
.save(
|
||||
&mut deps.storage,
|
||||
(node_identity.clone(), delegation_owner.clone()).joined_key(),
|
||||
(node_identity, delegation_owner.clone()).joined_key(),
|
||||
&dummy_data,
|
||||
)
|
||||
.unwrap();
|
||||
@@ -131,7 +131,7 @@ mod tests {
|
||||
// add delegation for a different node
|
||||
let dummy_data = Delegation::new(
|
||||
delegation_owner1.clone(),
|
||||
node_identity2.clone(),
|
||||
node_identity2,
|
||||
delegation.clone(),
|
||||
mock_env().block.height,
|
||||
None,
|
||||
@@ -156,14 +156,14 @@ mod tests {
|
||||
let dummy_data = Delegation::new(
|
||||
delegation_owner2.clone(),
|
||||
node_identity1.clone(),
|
||||
delegation.clone(),
|
||||
delegation,
|
||||
mock_env().block.height,
|
||||
None,
|
||||
);
|
||||
storage::delegations()
|
||||
.save(
|
||||
&mut deps.storage,
|
||||
(node_identity1.clone(), delegation_owner2.clone()).joined_key(),
|
||||
(node_identity1.clone(), delegation_owner2).joined_key(),
|
||||
&dummy_data,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
@@ -7,8 +7,8 @@ use crate::support::helpers::generate_storage_key;
|
||||
use config::defaults::DENOM;
|
||||
use cosmwasm_std::{coins, wasm_execute, Addr, BankMsg, Coin, DepsMut, Env, MessageInfo, Response};
|
||||
use cw_storage_plus::PrimaryKey;
|
||||
use mixnet_contract::Delegation;
|
||||
use mixnet_contract::IdentityKey;
|
||||
use mixnet_contract_common::events::{new_delegation_event, new_undelegation_event};
|
||||
use mixnet_contract_common::{Delegation, IdentityKey};
|
||||
use vesting_contract::messages::ExecuteMsg as VestingContractExecuteMsg;
|
||||
|
||||
fn validate_delegation_stake(mut delegation: Vec<Coin>) -> Result<Coin, ContractError> {
|
||||
@@ -113,16 +113,21 @@ pub(crate) fn _try_delegate_to_mixnode(
|
||||
}
|
||||
None => Delegation::new(
|
||||
delegate.to_owned(),
|
||||
mix_identity,
|
||||
amount,
|
||||
mix_identity.clone(),
|
||||
amount.clone(),
|
||||
env.block.height,
|
||||
proxy,
|
||||
proxy.clone(),
|
||||
),
|
||||
})
|
||||
},
|
||||
)?;
|
||||
|
||||
Ok(Response::default())
|
||||
Ok(Response::new().add_event(new_delegation_event(
|
||||
&delegate,
|
||||
&proxy,
|
||||
&amount,
|
||||
&mix_identity,
|
||||
)))
|
||||
}
|
||||
|
||||
pub(crate) fn try_remove_delegation_from_mixnode(
|
||||
@@ -204,14 +209,19 @@ pub(crate) fn _try_remove_delegation_from_mixnode(
|
||||
let msg = Some(VestingContractExecuteMsg::TrackUndelegation {
|
||||
owner: delegate.as_str().to_string(),
|
||||
mix_identity: mix_identity.clone(),
|
||||
amount: old_delegation.amount,
|
||||
amount: old_delegation.amount.clone(),
|
||||
});
|
||||
|
||||
let track_undelegation_msg = wasm_execute(proxy, &msg, coins(0, DENOM))?;
|
||||
|
||||
response = response.add_message(track_undelegation_msg);
|
||||
}
|
||||
Ok(response)
|
||||
Ok(response.add_event(new_undelegation_event(
|
||||
&delegate,
|
||||
&proxy,
|
||||
&old_delegation,
|
||||
&mix_identity,
|
||||
)))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -530,7 +540,7 @@ mod tests {
|
||||
try_delegate_to_mixnode(
|
||||
deps.as_mut(),
|
||||
env1,
|
||||
mock_info(delegation_owner1.as_str(), &[delegation1.clone()]),
|
||||
mock_info(delegation_owner1.as_str(), &[delegation1]),
|
||||
identity.clone(),
|
||||
)
|
||||
.unwrap();
|
||||
@@ -544,7 +554,7 @@ mod tests {
|
||||
try_delegate_to_mixnode(
|
||||
deps.as_mut(),
|
||||
env2,
|
||||
mock_info(delegation_owner2.as_str(), &[delegation2.clone()]),
|
||||
mock_info(delegation_owner2.as_str(), &[delegation2]),
|
||||
identity.clone(),
|
||||
)
|
||||
.unwrap();
|
||||
@@ -699,7 +709,7 @@ mod tests {
|
||||
try_delegate_to_mixnode(
|
||||
deps.as_mut(),
|
||||
mock_env(),
|
||||
mock_info(delegation_owner.as_str(), &vec![delegation_amount.clone()]),
|
||||
mock_info(delegation_owner.as_str(), &[delegation_amount.clone()]),
|
||||
identity.clone(),
|
||||
)
|
||||
.unwrap();
|
||||
@@ -722,6 +732,7 @@ mod tests {
|
||||
|
||||
#[cfg(test)]
|
||||
mod removing_mix_stake_delegation {
|
||||
use crate::delegations::queries::query_mixnode_delegation;
|
||||
use cosmwasm_std::coin;
|
||||
use cosmwasm_std::testing::mock_env;
|
||||
use cosmwasm_std::testing::mock_info;
|
||||
@@ -774,11 +785,27 @@ mod tests {
|
||||
identity.clone(),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
Ok(Response::new().add_message(BankMsg::Send {
|
||||
let delegation = query_mixnode_delegation(
|
||||
deps.as_ref(),
|
||||
identity.clone(),
|
||||
delegation_owner.clone().into_string(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let expected_response = Response::new()
|
||||
.add_message(BankMsg::Send {
|
||||
to_address: delegation_owner.clone().into(),
|
||||
amount: coins(100, DENOM),
|
||||
})),
|
||||
})
|
||||
.add_event(new_undelegation_event(
|
||||
&delegation_owner,
|
||||
&None,
|
||||
&delegation,
|
||||
&identity,
|
||||
));
|
||||
|
||||
assert_eq!(
|
||||
Ok(expected_response),
|
||||
try_remove_delegation_from_mixnode(
|
||||
deps.as_mut(),
|
||||
mock_info(delegation_owner.as_str(), &[]),
|
||||
@@ -819,12 +846,27 @@ mod tests {
|
||||
identity.clone(),
|
||||
)
|
||||
.unwrap();
|
||||
try_remove_mixnode(deps.as_mut(), mock_info(mixnode_owner, &[])).unwrap();
|
||||
assert_eq!(
|
||||
Ok(Response::new().add_message(BankMsg::Send {
|
||||
let delegation = query_mixnode_delegation(
|
||||
deps.as_ref(),
|
||||
identity.clone(),
|
||||
delegation_owner.clone().into_string(),
|
||||
)
|
||||
.unwrap();
|
||||
let expected_response = Response::new()
|
||||
.add_message(BankMsg::Send {
|
||||
to_address: delegation_owner.clone().into(),
|
||||
amount: coins(100, DENOM),
|
||||
})),
|
||||
})
|
||||
.add_event(new_undelegation_event(
|
||||
&delegation_owner,
|
||||
&None,
|
||||
&delegation,
|
||||
&identity,
|
||||
));
|
||||
|
||||
try_remove_mixnode(deps.as_mut(), mock_info(mixnode_owner, &[])).unwrap();
|
||||
assert_eq!(
|
||||
Ok(expected_response),
|
||||
try_remove_delegation_from_mixnode(
|
||||
deps.as_mut(),
|
||||
mock_info(delegation_owner.as_str(), &[]),
|
||||
@@ -853,7 +895,7 @@ mod tests {
|
||||
assert!(try_delegate_to_mixnode(
|
||||
deps.as_mut(),
|
||||
mock_env(),
|
||||
mock_info(delegation_owner1.as_str(), &[delegation1.clone()]),
|
||||
mock_info(delegation_owner1.as_str(), &[delegation1]),
|
||||
identity.clone(),
|
||||
)
|
||||
.is_ok());
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
use config::defaults::DENOM;
|
||||
use cosmwasm_std::{Addr, StdError};
|
||||
use mixnet_contract::IdentityKey;
|
||||
use mixnet_contract_common::IdentityKey;
|
||||
use thiserror::Error;
|
||||
|
||||
/// Custom errors for contract failure conditions.
|
||||
|
||||
@@ -5,7 +5,9 @@ use super::storage;
|
||||
use crate::mixnodes::storage::{BOND_PAGE_DEFAULT_LIMIT, BOND_PAGE_MAX_LIMIT}; // Keeps gateway and mixnode retrieval in sync by re-using the constant. Could be split into its own constant.
|
||||
use cosmwasm_std::{Deps, Order, StdResult};
|
||||
use cw_storage_plus::Bound;
|
||||
use mixnet_contract::{GatewayBond, GatewayOwnershipResponse, IdentityKey, PagedGatewayResponse};
|
||||
use mixnet_contract_common::{
|
||||
GatewayBond, GatewayOwnershipResponse, IdentityKey, PagedGatewayResponse,
|
||||
};
|
||||
|
||||
pub(crate) fn query_gateways_paged(
|
||||
deps: Deps,
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
use cosmwasm_std::Addr;
|
||||
use cw_storage_plus::{Index, IndexList, IndexedMap, UniqueIndex};
|
||||
use mixnet_contract::{GatewayBond, IdentityKeyRef};
|
||||
use mixnet_contract_common::{GatewayBond, IdentityKeyRef};
|
||||
|
||||
// storage prefixes
|
||||
const GATEWAYS_PK_NAMESPACE: &str = "gt";
|
||||
@@ -41,9 +41,7 @@ mod tests {
|
||||
use cosmwasm_std::StdResult;
|
||||
use cosmwasm_std::Storage;
|
||||
use cosmwasm_std::{coin, Addr, Uint128};
|
||||
use mixnet_contract::GatewayBond;
|
||||
use mixnet_contract::IdentityKey;
|
||||
use mixnet_contract::{Gateway, IdentityKeyRef};
|
||||
use mixnet_contract_common::{Gateway, GatewayBond, IdentityKey, IdentityKeyRef};
|
||||
|
||||
// currently this is only used in tests but may become useful later on
|
||||
pub(crate) fn read_gateway_pledge_amount(
|
||||
@@ -87,7 +85,7 @@ mod tests {
|
||||
|
||||
let gateway_bond = GatewayBond {
|
||||
pledge_amount: coin(pledge_amount, DENOM),
|
||||
owner: node_owner.clone(),
|
||||
owner: node_owner,
|
||||
block_height: 12_345,
|
||||
gateway: Gateway {
|
||||
identity_key: node_identity.clone(),
|
||||
|
||||
@@ -9,7 +9,8 @@ use config::defaults::DENOM;
|
||||
use cosmwasm_std::{
|
||||
coins, wasm_execute, Addr, BankMsg, Coin, DepsMut, Env, MessageInfo, Response, Uint128,
|
||||
};
|
||||
use mixnet_contract::{Gateway, GatewayBond, Layer};
|
||||
use mixnet_contract_common::events::{new_gateway_bonding_event, new_gateway_unbonding_event};
|
||||
use mixnet_contract_common::{Gateway, GatewayBond, Layer};
|
||||
use vesting_contract::messages::ExecuteMsg as VestingContractExecuteMsg;
|
||||
|
||||
pub fn try_add_gateway(
|
||||
@@ -97,12 +98,24 @@ pub(crate) fn _try_add_gateway(
|
||||
&gateway.identity_key,
|
||||
)?;
|
||||
|
||||
let bond = GatewayBond::new(pledge, owner, env.block.height, gateway, proxy);
|
||||
let gateway_identity = gateway.identity_key.clone();
|
||||
let bond = GatewayBond::new(
|
||||
pledge.clone(),
|
||||
owner.clone(),
|
||||
env.block.height,
|
||||
gateway,
|
||||
proxy.clone(),
|
||||
);
|
||||
|
||||
storage::gateways().save(deps.storage, bond.identity(), &bond)?;
|
||||
mixnet_params_storage::increment_layer_count(deps.storage, Layer::Gateway)?;
|
||||
|
||||
Ok(Response::new())
|
||||
Ok(Response::new().add_event(new_gateway_bonding_event(
|
||||
&owner,
|
||||
&proxy,
|
||||
&pledge,
|
||||
&gateway_identity,
|
||||
)))
|
||||
}
|
||||
|
||||
pub fn try_remove_gateway_on_behalf(
|
||||
@@ -155,23 +168,24 @@ pub(crate) fn _try_remove_gateway(
|
||||
// decrement layer count
|
||||
mixnet_params_storage::decrement_layer_count(deps.storage, Layer::Gateway)?;
|
||||
|
||||
let mut response = Response::new()
|
||||
.add_message(return_tokens)
|
||||
.add_attribute("action", "unbond")
|
||||
.add_attribute("address", owner.clone())
|
||||
.add_attribute("gateway_bond", gateway_bond.to_string());
|
||||
let mut response = Response::new().add_message(return_tokens);
|
||||
|
||||
if let Some(proxy) = &proxy {
|
||||
let msg = VestingContractExecuteMsg::TrackUnbondGateway {
|
||||
owner: owner.as_str().to_string(),
|
||||
amount: gateway_bond.pledge_amount,
|
||||
amount: gateway_bond.pledge_amount(),
|
||||
};
|
||||
|
||||
let track_unbond_message = wasm_execute(proxy, &msg, coins(0, DENOM))?;
|
||||
response = response.add_message(track_unbond_message);
|
||||
}
|
||||
|
||||
Ok(response)
|
||||
Ok(response.add_event(new_gateway_unbonding_event(
|
||||
&owner,
|
||||
&proxy,
|
||||
&gateway_bond.pledge_amount,
|
||||
gateway_bond.identity(),
|
||||
)))
|
||||
}
|
||||
|
||||
fn validate_gateway_pledge(
|
||||
@@ -212,12 +226,10 @@ pub mod tests {
|
||||
use crate::support::tests;
|
||||
use crate::support::tests::test_helpers;
|
||||
use config::defaults::DENOM;
|
||||
use cosmwasm_std::attr;
|
||||
use cosmwasm_std::testing::{mock_env, mock_info};
|
||||
use cosmwasm_std::{coins, BankMsg, Response};
|
||||
use cosmwasm_std::{from_binary, Addr, Uint128};
|
||||
use mixnet_contract::Gateway;
|
||||
use mixnet_contract::{ExecuteMsg, PagedGatewayResponse, QueryMsg};
|
||||
use mixnet_contract_common::{ExecuteMsg, Gateway, PagedGatewayResponse, QueryMsg};
|
||||
|
||||
#[test]
|
||||
fn gateway_add() {
|
||||
@@ -454,19 +466,6 @@ pub mod tests {
|
||||
let msg = ExecuteMsg::UnbondGateway {};
|
||||
let remove_fred = execute(deps.as_mut(), mock_env(), info.clone(), msg).unwrap();
|
||||
|
||||
// we should see log messages come back showing an unbond message
|
||||
let expected_attributes = vec![
|
||||
attr("action", "unbond"),
|
||||
attr("address", "fred"),
|
||||
attr(
|
||||
"gateway_bond",
|
||||
format!(
|
||||
"amount: {} {}, owner: fred, identity: {}",
|
||||
INITIAL_GATEWAY_PLEDGE, DENOM, fred_identity
|
||||
),
|
||||
),
|
||||
];
|
||||
|
||||
// we should see a funds transfer from the contract back to fred
|
||||
let expected_message = BankMsg::Send {
|
||||
to_address: String::from(info.sender),
|
||||
@@ -474,11 +473,17 @@ pub mod tests {
|
||||
};
|
||||
|
||||
// run the executor and check that we got back the correct results
|
||||
let expected = Response::new()
|
||||
.add_attributes(expected_attributes)
|
||||
.add_message(expected_message);
|
||||
let expected_response =
|
||||
Response::new()
|
||||
.add_message(expected_message)
|
||||
.add_event(new_gateway_unbonding_event(
|
||||
&Addr::unchecked("fred"),
|
||||
&None,
|
||||
&tests::fixtures::good_gateway_pledge()[0],
|
||||
&fred_identity,
|
||||
));
|
||||
|
||||
assert_eq!(remove_fred, expected);
|
||||
assert_eq!(expected_response, remove_fred);
|
||||
|
||||
// only 1 node now exists, owned by bob:
|
||||
let gateway_bonds = tests::queries::get_gateways(&mut deps);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use cosmwasm_std::Addr;
|
||||
use mixnet_contract::ContractStateParams;
|
||||
use mixnet_contract_common::ContractStateParams;
|
||||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
|
||||
use super::storage;
|
||||
use cosmwasm_std::{Deps, StdResult};
|
||||
use mixnet_contract::{ContractStateParams, MixnetContractVersion, RewardingIntervalResponse};
|
||||
use mixnet_contract_common::{
|
||||
ContractStateParams, MixnetContractVersion, RewardingIntervalResponse,
|
||||
};
|
||||
|
||||
pub(crate) fn query_contract_settings_params(deps: Deps) -> StdResult<ContractStateParams> {
|
||||
storage::CONTRACT_STATE
|
||||
|
||||
@@ -5,8 +5,7 @@ use crate::mixnet_contract_settings::models::ContractState;
|
||||
use cosmwasm_std::StdResult;
|
||||
use cosmwasm_std::Storage;
|
||||
use cw_storage_plus::Item;
|
||||
use mixnet_contract::Layer;
|
||||
use mixnet_contract::LayerDistribution;
|
||||
use mixnet_contract_common::{Layer, LayerDistribution};
|
||||
|
||||
pub(crate) const CONTRACT_STATE: Item<ContractState> = Item::new("config");
|
||||
pub(crate) const LAYERS: Item<LayerDistribution> = Item::new("layers");
|
||||
|
||||
@@ -6,7 +6,8 @@ use crate::error::ContractError;
|
||||
use cosmwasm_std::DepsMut;
|
||||
use cosmwasm_std::MessageInfo;
|
||||
use cosmwasm_std::Response;
|
||||
use mixnet_contract::ContractStateParams;
|
||||
use mixnet_contract_common::events::new_settings_update_event;
|
||||
use mixnet_contract_common::ContractStateParams;
|
||||
|
||||
pub(crate) fn try_update_contract_settings(
|
||||
deps: DepsMut,
|
||||
@@ -34,10 +35,12 @@ pub(crate) fn try_update_contract_settings(
|
||||
return Err(ContractError::InvalidActiveSetSize);
|
||||
}
|
||||
|
||||
let response = Response::new().add_event(new_settings_update_event(&state.params, ¶ms));
|
||||
|
||||
state.params = params;
|
||||
storage::CONTRACT_STATE.save(deps.storage, &state)?;
|
||||
|
||||
Ok(Response::default())
|
||||
Ok(response)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -49,7 +52,7 @@ pub mod tests {
|
||||
use crate::support::tests::test_helpers;
|
||||
use cosmwasm_std::testing::mock_info;
|
||||
use cosmwasm_std::Response;
|
||||
use mixnet_contract::ContractStateParams;
|
||||
use mixnet_contract_common::ContractStateParams;
|
||||
|
||||
#[test]
|
||||
fn updating_contract_settings() {
|
||||
@@ -63,14 +66,13 @@ pub mod tests {
|
||||
active_set_work_factor: 10,
|
||||
};
|
||||
|
||||
let initial_params = storage::CONTRACT_STATE
|
||||
.load(deps.as_ref().storage)
|
||||
.unwrap()
|
||||
.params;
|
||||
|
||||
// sanity check to ensure new_params are different than the default ones
|
||||
assert_ne!(
|
||||
new_params,
|
||||
storage::CONTRACT_STATE
|
||||
.load(deps.as_ref().storage)
|
||||
.unwrap()
|
||||
.params
|
||||
);
|
||||
assert_ne!(new_params, initial_params);
|
||||
|
||||
// cannot be updated from non-owner account
|
||||
let info = mock_info("not-the-creator", &[]);
|
||||
@@ -80,7 +82,10 @@ pub mod tests {
|
||||
// but works fine from the creator account
|
||||
let info = mock_info("creator", &[]);
|
||||
let res = try_update_contract_settings(deps.as_mut(), info, new_params.clone());
|
||||
assert_eq!(res, Ok(Response::default()));
|
||||
assert_eq!(
|
||||
res,
|
||||
Ok(Response::new().add_event(new_settings_update_event(&initial_params, &new_params)))
|
||||
);
|
||||
|
||||
// and the state is actually updated
|
||||
let current_state = storage::CONTRACT_STATE.load(deps.as_ref().storage).unwrap();
|
||||
@@ -90,21 +95,21 @@ pub mod tests {
|
||||
let info = mock_info("creator", &[]);
|
||||
let mut new_params = current_state.params.clone();
|
||||
new_params.mixnode_rewarded_set_size = new_params.mixnode_active_set_size - 1;
|
||||
let res = try_update_contract_settings(deps.as_mut(), info, new_params.clone());
|
||||
let res = try_update_contract_settings(deps.as_mut(), info, new_params);
|
||||
assert_eq!(Err(ContractError::InvalidActiveSetSize), res);
|
||||
|
||||
// error is thrown for 0 size rewarded set
|
||||
let info = mock_info("creator", &[]);
|
||||
let mut new_params = current_state.params.clone();
|
||||
new_params.mixnode_rewarded_set_size = 0;
|
||||
let res = try_update_contract_settings(deps.as_mut(), info, new_params.clone());
|
||||
let res = try_update_contract_settings(deps.as_mut(), info, new_params);
|
||||
assert_eq!(Err(ContractError::ZeroRewardedSet), res);
|
||||
|
||||
// error is thrown for 0 size active set
|
||||
let info = mock_info("creator", &[]);
|
||||
let mut new_params = current_state.params.clone();
|
||||
let mut new_params = current_state.params;
|
||||
new_params.mixnode_active_set_size = 0;
|
||||
let res = try_update_contract_settings(deps.as_mut(), info, new_params.clone());
|
||||
let res = try_update_contract_settings(deps.as_mut(), info, new_params);
|
||||
assert_eq!(Err(ContractError::ZeroActiveSet), res);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,9 @@
|
||||
use super::storage;
|
||||
use cosmwasm_std::{Deps, Order, StdResult};
|
||||
use cw_storage_plus::Bound;
|
||||
use mixnet_contract::{IdentityKey, MixNodeBond, MixOwnershipResponse, PagedMixnodeResponse};
|
||||
use mixnet_contract_common::{
|
||||
IdentityKey, MixNodeBond, MixOwnershipResponse, PagedMixnodeResponse,
|
||||
};
|
||||
|
||||
pub fn query_mixnodes_paged(
|
||||
deps: Deps,
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
use crate::mixnet_contract_settings::storage as mixnet_params_storage;
|
||||
use cosmwasm_std::{Deps, StdResult};
|
||||
use mixnet_contract::LayerDistribution;
|
||||
use mixnet_contract_common::LayerDistribution;
|
||||
|
||||
pub(crate) fn query_layer_distribution(deps: Deps) -> StdResult<LayerDistribution> {
|
||||
mixnet_params_storage::LAYERS.load(deps.storage)
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
use config::defaults::DENOM;
|
||||
use cosmwasm_std::{StdResult, Storage, Uint128};
|
||||
use cw_storage_plus::{Index, IndexList, IndexedMap, Map, UniqueIndex};
|
||||
use mixnet_contract::{Addr, Coin, IdentityKeyRef, Layer, MixNode, MixNodeBond};
|
||||
use mixnet_contract_common::{Addr, Coin, IdentityKeyRef, Layer, MixNode, MixNodeBond};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt::{Display, Formatter};
|
||||
|
||||
@@ -49,7 +49,6 @@ pub(crate) struct StoredMixnodeBond {
|
||||
pub layer: Layer,
|
||||
pub block_height: u64,
|
||||
pub mix_node: MixNode,
|
||||
pub profit_margin_percent: Option<u8>,
|
||||
pub proxy: Option<Addr>,
|
||||
}
|
||||
|
||||
@@ -60,7 +59,6 @@ impl StoredMixnodeBond {
|
||||
layer: Layer,
|
||||
block_height: u64,
|
||||
mix_node: MixNode,
|
||||
profit_margin_percent: Option<u8>,
|
||||
proxy: Option<Addr>,
|
||||
) -> Self {
|
||||
StoredMixnodeBond {
|
||||
@@ -69,7 +67,6 @@ impl StoredMixnodeBond {
|
||||
layer,
|
||||
block_height,
|
||||
mix_node,
|
||||
profit_margin_percent,
|
||||
proxy,
|
||||
}
|
||||
}
|
||||
@@ -141,8 +138,7 @@ mod tests {
|
||||
use config::defaults::DENOM;
|
||||
use cosmwasm_std::testing::MockStorage;
|
||||
use cosmwasm_std::{coin, Addr, Uint128};
|
||||
use mixnet_contract::IdentityKey;
|
||||
use mixnet_contract::MixNode;
|
||||
use mixnet_contract_common::{IdentityKey, MixNode};
|
||||
|
||||
#[test]
|
||||
fn mixnode_single_read_retrieval() {
|
||||
@@ -173,14 +169,13 @@ mod tests {
|
||||
|
||||
let mixnode_bond = StoredMixnodeBond {
|
||||
pledge_amount: coin(pledge_value, DENOM),
|
||||
owner: node_owner.clone(),
|
||||
owner: node_owner,
|
||||
layer: Layer::One,
|
||||
block_height: 12_345,
|
||||
mix_node: MixNode {
|
||||
identity_key: node_identity.clone(),
|
||||
..tests::fixtures::mix_node_fixture()
|
||||
},
|
||||
profit_margin_percent: None,
|
||||
proxy: None,
|
||||
};
|
||||
|
||||
|
||||
@@ -11,7 +11,8 @@ use config::defaults::DENOM;
|
||||
use cosmwasm_std::{
|
||||
coins, wasm_execute, Addr, BankMsg, Coin, DepsMut, Env, MessageInfo, Response, Uint128,
|
||||
};
|
||||
use mixnet_contract::MixNode;
|
||||
use mixnet_contract_common::events::{new_mixnode_bonding_event, new_mixnode_unbonding_event};
|
||||
use mixnet_contract_common::MixNode;
|
||||
use vesting_contract::messages::ExecuteMsg as VestingContractExecuteMsg;
|
||||
|
||||
pub fn try_add_mixnode(
|
||||
@@ -109,13 +110,12 @@ fn _try_add_mixnode(
|
||||
let layer = layer_distribution.choose_with_fewest();
|
||||
|
||||
let stored_bond = StoredMixnodeBond::new(
|
||||
pledge_amount,
|
||||
owner,
|
||||
pledge_amount.clone(),
|
||||
owner.clone(),
|
||||
layer,
|
||||
env.block.height,
|
||||
mix_node,
|
||||
None,
|
||||
proxy,
|
||||
proxy.clone(),
|
||||
);
|
||||
|
||||
// technically we don't have to set the total_delegation bucket, but it makes things easier
|
||||
@@ -133,7 +133,13 @@ fn _try_add_mixnode(
|
||||
|
||||
mixnet_params_storage::increment_layer_count(deps.storage, stored_bond.layer)?;
|
||||
|
||||
Ok(Response::new())
|
||||
Ok(Response::new().add_event(new_mixnode_bonding_event(
|
||||
&owner,
|
||||
&proxy,
|
||||
&pledge_amount,
|
||||
identity,
|
||||
stored_bond.layer,
|
||||
)))
|
||||
}
|
||||
|
||||
pub fn try_remove_mixnode_on_behalf(
|
||||
@@ -186,22 +192,60 @@ pub(crate) fn _try_remove_mixnode(
|
||||
// decrement layer count
|
||||
mixnet_params_storage::decrement_layer_count(deps.storage, mixnode_bond.layer)?;
|
||||
|
||||
let mut response = Response::new()
|
||||
.add_message(return_tokens)
|
||||
.add_attribute("action", "unbond")
|
||||
.add_attribute("mixnode_bond", mixnode_bond.to_string());
|
||||
let mut response = Response::new().add_message(return_tokens);
|
||||
|
||||
if let Some(proxy) = &proxy {
|
||||
let msg = VestingContractExecuteMsg::TrackUnbondMixnode {
|
||||
owner: owner.as_str().to_string(),
|
||||
amount: mixnode_bond.pledge_amount,
|
||||
amount: mixnode_bond.pledge_amount(),
|
||||
};
|
||||
|
||||
let track_unbond_message = wasm_execute(proxy, &msg, coins(0, DENOM))?;
|
||||
response = response.add_message(track_unbond_message);
|
||||
}
|
||||
|
||||
Ok(response)
|
||||
Ok(response.add_event(new_mixnode_unbonding_event(
|
||||
&owner,
|
||||
&proxy,
|
||||
&mixnode_bond.pledge_amount,
|
||||
mixnode_bond.identity(),
|
||||
)))
|
||||
}
|
||||
|
||||
pub(crate) fn try_update_mixnode_config(
|
||||
deps: DepsMut,
|
||||
env: Env,
|
||||
info: MessageInfo,
|
||||
profit_margin_percent: u8,
|
||||
) -> Result<Response, ContractError> {
|
||||
let owner = deps.api.addr_validate(info.sender.as_ref())?;
|
||||
let mix_identity = storage::mixnodes()
|
||||
.idx
|
||||
.owner
|
||||
.item(deps.storage, owner.clone())?
|
||||
.ok_or(ContractError::NoAssociatedMixNodeBond { owner })?
|
||||
.1
|
||||
.identity()
|
||||
.clone();
|
||||
|
||||
// We don't have to check lower bound as its an u8
|
||||
if profit_margin_percent > 100 {
|
||||
return Err(ContractError::InvalidProfitMarginPercent(
|
||||
profit_margin_percent,
|
||||
));
|
||||
}
|
||||
|
||||
storage::mixnodes().update(deps.storage, &mix_identity, |mixnode_bond_opt| {
|
||||
mixnode_bond_opt
|
||||
.map(|mut mixnode_bond| {
|
||||
mixnode_bond.mix_node.profit_margin_percent = profit_margin_percent;
|
||||
mixnode_bond.block_height = env.block.height;
|
||||
mixnode_bond
|
||||
})
|
||||
.ok_or(ContractError::NoBondFound)
|
||||
})?;
|
||||
|
||||
Ok(Response::new())
|
||||
}
|
||||
|
||||
fn validate_mixnode_pledge(
|
||||
@@ -242,13 +286,12 @@ pub mod tests {
|
||||
use crate::support::tests;
|
||||
use crate::support::tests::test_helpers;
|
||||
use config::defaults::DENOM;
|
||||
use cosmwasm_std::attr;
|
||||
use cosmwasm_std::testing::{mock_env, mock_info};
|
||||
use cosmwasm_std::{coins, BankMsg, Response};
|
||||
use cosmwasm_std::{from_binary, Addr, Uint128};
|
||||
use mixnet_contract::Layer;
|
||||
use mixnet_contract::MixNode;
|
||||
use mixnet_contract::{ExecuteMsg, LayerDistribution, PagedMixnodeResponse, QueryMsg};
|
||||
use mixnet_contract_common::{
|
||||
ExecuteMsg, Layer, LayerDistribution, MixNode, PagedMixnodeResponse, QueryMsg,
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn mixnode_add() {
|
||||
@@ -507,18 +550,6 @@ pub mod tests {
|
||||
let msg = ExecuteMsg::UnbondMixnode {};
|
||||
let remove_fred = execute(deps.as_mut(), mock_env(), info.clone(), msg).unwrap();
|
||||
|
||||
// we should see log messages come back showing an unbond message
|
||||
let expected_attributes = vec![
|
||||
attr("action", "unbond"),
|
||||
attr(
|
||||
"mixnode_bond",
|
||||
format!(
|
||||
"amount: {}{}, owner: fred, identity: {}",
|
||||
INITIAL_MIXNODE_PLEDGE, DENOM, fred_identity
|
||||
),
|
||||
),
|
||||
];
|
||||
|
||||
// we should see a funds transfer from the contract back to fred
|
||||
let expected_message = BankMsg::Send {
|
||||
to_address: String::from(info.sender),
|
||||
@@ -526,11 +557,17 @@ pub mod tests {
|
||||
};
|
||||
|
||||
// run the executor and check that we got back the correct results
|
||||
let expected = Response::new()
|
||||
.add_attributes(expected_attributes)
|
||||
.add_message(expected_message);
|
||||
let expected_response =
|
||||
Response::new()
|
||||
.add_message(expected_message)
|
||||
.add_event(new_mixnode_unbonding_event(
|
||||
&Addr::unchecked("fred"),
|
||||
&None,
|
||||
&tests::fixtures::good_gateway_pledge()[0],
|
||||
&fred_identity,
|
||||
));
|
||||
|
||||
assert_eq!(remove_fred, expected);
|
||||
assert_eq!(expected_response, remove_fred);
|
||||
|
||||
// only 1 node now exists, owned by bob:
|
||||
let mix_node_bonds = tests::queries::get_mix_nodes(&mut deps);
|
||||
@@ -587,6 +624,77 @@ pub mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn updating_mixnode_config() {
|
||||
let sender = "bob";
|
||||
let mut deps = test_helpers::init_contract();
|
||||
let info = mock_info(sender, &[]);
|
||||
|
||||
// try updating a non existing mixnode bond
|
||||
let msg = ExecuteMsg::UpdateMixnodeConfig {
|
||||
profit_margin_percent: 10,
|
||||
};
|
||||
let ret = execute(deps.as_mut(), mock_env(), info.clone(), msg);
|
||||
assert_eq!(
|
||||
ret,
|
||||
Err(ContractError::NoAssociatedMixNodeBond {
|
||||
owner: Addr::unchecked(sender)
|
||||
})
|
||||
);
|
||||
|
||||
test_helpers::add_mixnode(
|
||||
sender,
|
||||
tests::fixtures::good_mixnode_pledge(),
|
||||
deps.as_mut(),
|
||||
);
|
||||
|
||||
// check the initial profit margin is set to the fixture value
|
||||
let fixture_profit_margin = tests::fixtures::mix_node_fixture().profit_margin_percent;
|
||||
assert_eq!(
|
||||
fixture_profit_margin,
|
||||
storage::mixnodes()
|
||||
.idx
|
||||
.owner
|
||||
.item(deps.as_ref().storage, Addr::unchecked("bob"))
|
||||
.unwrap()
|
||||
.unwrap()
|
||||
.1
|
||||
.mix_node
|
||||
.profit_margin_percent
|
||||
);
|
||||
|
||||
// try updating with an invalid value
|
||||
let profit_margin_percent = 101;
|
||||
let msg = ExecuteMsg::UpdateMixnodeConfig {
|
||||
profit_margin_percent,
|
||||
};
|
||||
let ret = execute(deps.as_mut(), mock_env(), info.clone(), msg);
|
||||
assert_eq!(
|
||||
ret,
|
||||
Err(ContractError::InvalidProfitMarginPercent(
|
||||
profit_margin_percent
|
||||
))
|
||||
);
|
||||
|
||||
let profit_margin_percent = fixture_profit_margin + 10;
|
||||
let msg = ExecuteMsg::UpdateMixnodeConfig {
|
||||
profit_margin_percent,
|
||||
};
|
||||
execute(deps.as_mut(), mock_env(), info, msg).unwrap();
|
||||
assert_eq!(
|
||||
profit_margin_percent,
|
||||
storage::mixnodes()
|
||||
.idx
|
||||
.owner
|
||||
.item(deps.as_ref().storage, Addr::unchecked("bob"))
|
||||
.unwrap()
|
||||
.unwrap()
|
||||
.1
|
||||
.mix_node
|
||||
.profit_margin_percent
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn validating_mixnode_bond() {
|
||||
// you must send SOME funds
|
||||
@@ -649,6 +757,6 @@ pub mod tests {
|
||||
assert_eq!(alice_node.mix_node.identity_key, alice_identity);
|
||||
assert_eq!(alice_node.layer, Layer::One);
|
||||
assert_eq!(bob_node.mix_node.identity_key, bob_identity);
|
||||
assert_eq!(bob_node.layer, mixnet_contract::Layer::Two);
|
||||
assert_eq!(bob_node.layer, mixnet_contract_common::Layer::Two);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,8 +5,8 @@ use super::storage;
|
||||
use crate::error::ContractError;
|
||||
use crate::mixnodes::storage as mixnodes_storage;
|
||||
use cosmwasm_std::{Addr, Storage, Uint128};
|
||||
use mixnet_contract::mixnode::DelegatorRewardParams;
|
||||
use mixnet_contract::{
|
||||
use mixnet_contract_common::mixnode::DelegatorRewardParams;
|
||||
use mixnet_contract_common::{
|
||||
IdentityKey, IdentityKeyRef, PendingDelegatorRewarding, RewardingResult, RewardingStatus,
|
||||
};
|
||||
|
||||
@@ -64,7 +64,7 @@ pub(crate) fn update_rewarding_status(
|
||||
if let Some(next_start) = next_start {
|
||||
storage::REWARDING_STATUS.save(
|
||||
storage,
|
||||
(rewarding_interval_nonce.into(), mix_identity),
|
||||
(rewarding_interval_nonce, mix_identity),
|
||||
&RewardingStatus::PendingNextDelegatorPage(PendingDelegatorRewarding {
|
||||
running_results: rewarding_results,
|
||||
next_start,
|
||||
@@ -74,7 +74,7 @@ pub(crate) fn update_rewarding_status(
|
||||
} else {
|
||||
storage::REWARDING_STATUS.save(
|
||||
storage,
|
||||
(rewarding_interval_nonce.into(), mix_identity),
|
||||
(rewarding_interval_nonce, mix_identity),
|
||||
&RewardingStatus::Complete(rewarding_results),
|
||||
)?;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
use super::storage;
|
||||
use cosmwasm_std::Uint128;
|
||||
use cosmwasm_std::{Deps, StdResult};
|
||||
use mixnet_contract::{IdentityKey, MixnodeRewardingStatusResponse};
|
||||
use mixnet_contract_common::{IdentityKey, MixnodeRewardingStatusResponse};
|
||||
|
||||
pub(crate) fn query_reward_pool(deps: Deps) -> StdResult<Uint128> {
|
||||
storage::REWARD_POOL.load(deps.storage)
|
||||
@@ -19,10 +19,8 @@ pub(crate) fn query_rewarding_status(
|
||||
mix_identity: IdentityKey,
|
||||
rewarding_interval_nonce: u32,
|
||||
) -> StdResult<MixnodeRewardingStatusResponse> {
|
||||
let status = storage::REWARDING_STATUS.may_load(
|
||||
deps.storage,
|
||||
(rewarding_interval_nonce.into(), mix_identity),
|
||||
)?;
|
||||
let status = storage::REWARDING_STATUS
|
||||
.may_load(deps.storage, (rewarding_interval_nonce, mix_identity))?;
|
||||
|
||||
Ok(MixnodeRewardingStatusResponse { status })
|
||||
}
|
||||
@@ -46,7 +44,9 @@ pub(crate) mod tests {
|
||||
};
|
||||
use config::defaults::DENOM;
|
||||
use cosmwasm_std::{coin, Addr};
|
||||
use mixnet_contract::{RewardingResult, RewardingStatus, MIXNODE_DELEGATORS_PAGE_LIMIT};
|
||||
use mixnet_contract_common::{
|
||||
RewardingResult, RewardingStatus, MIXNODE_DELEGATORS_PAGE_LIMIT,
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn returns_empty_status_for_unrewarded_nodes() {
|
||||
@@ -75,14 +75,14 @@ pub(crate) mod tests {
|
||||
try_begin_mixnode_rewarding(deps.as_mut(), env.clone(), info.clone(), 1).unwrap();
|
||||
try_reward_mixnode(
|
||||
deps.as_mut(),
|
||||
env.clone(),
|
||||
env,
|
||||
info.clone(),
|
||||
node_identity.clone(),
|
||||
tests::fixtures::node_rewarding_params_fixture(100),
|
||||
1,
|
||||
)
|
||||
.unwrap();
|
||||
try_finish_mixnode_rewarding(deps.as_mut(), info.clone(), 1).unwrap();
|
||||
try_finish_mixnode_rewarding(deps.as_mut(), info, 1).unwrap();
|
||||
|
||||
assert!(query_rewarding_status(deps.as_ref(), node_identity, 2)
|
||||
.unwrap()
|
||||
@@ -120,7 +120,7 @@ pub(crate) mod tests {
|
||||
1,
|
||||
)
|
||||
.unwrap();
|
||||
try_finish_mixnode_rewarding(deps.as_mut(), info.clone(), 1).unwrap();
|
||||
try_finish_mixnode_rewarding(deps.as_mut(), info, 1).unwrap();
|
||||
|
||||
let res = query_rewarding_status(deps.as_ref(), node_identity, 1).unwrap();
|
||||
assert!(matches!(res.status, Some(RewardingStatus::Complete(..))));
|
||||
@@ -151,10 +151,7 @@ pub(crate) mod tests {
|
||||
try_delegate_to_mixnode(
|
||||
deps.as_mut(),
|
||||
env.clone(),
|
||||
mock_info(
|
||||
&*format!("delegator{:04}", i),
|
||||
&vec![coin(200_000000, DENOM)],
|
||||
),
|
||||
mock_info(&*format!("delegator{:04}", i), &[coin(200_000000, DENOM)]),
|
||||
node_identity.clone(),
|
||||
)
|
||||
.unwrap();
|
||||
@@ -167,7 +164,7 @@ pub(crate) mod tests {
|
||||
|
||||
try_reward_mixnode(
|
||||
deps.as_mut(),
|
||||
env.clone(),
|
||||
env,
|
||||
info.clone(),
|
||||
node_identity.clone(),
|
||||
tests::fixtures::node_rewarding_params_fixture(100),
|
||||
@@ -176,13 +173,8 @@ pub(crate) mod tests {
|
||||
.unwrap();
|
||||
|
||||
// rewards all pending
|
||||
try_reward_next_mixnode_delegators(
|
||||
deps.as_mut(),
|
||||
info.clone(),
|
||||
node_identity.to_string(),
|
||||
2,
|
||||
)
|
||||
.unwrap();
|
||||
try_reward_next_mixnode_delegators(deps.as_mut(), info, node_identity.to_string(), 2)
|
||||
.unwrap();
|
||||
|
||||
let res = query_rewarding_status(deps.as_ref(), node_identity, 2).unwrap();
|
||||
assert!(matches!(res.status, Some(RewardingStatus::Complete(..))));
|
||||
@@ -222,10 +214,7 @@ pub(crate) mod tests {
|
||||
try_delegate_to_mixnode(
|
||||
deps.as_mut(),
|
||||
env.clone(),
|
||||
mock_info(
|
||||
&*format!("delegator{:04}", i),
|
||||
&vec![coin(200_000000, DENOM)],
|
||||
),
|
||||
mock_info(&*format!("delegator{:04}", i), &[coin(200_000000, DENOM)]),
|
||||
node_identity.clone(),
|
||||
)
|
||||
.unwrap();
|
||||
@@ -238,7 +227,7 @@ pub(crate) mod tests {
|
||||
|
||||
try_reward_mixnode(
|
||||
deps.as_mut(),
|
||||
env.clone(),
|
||||
env,
|
||||
info,
|
||||
node_identity.clone(),
|
||||
tests::fixtures::node_rewarding_params_fixture(100),
|
||||
|
||||
@@ -4,11 +4,12 @@
|
||||
use crate::error::ContractError;
|
||||
use config::defaults::TOTAL_SUPPLY;
|
||||
use cosmwasm_std::{StdResult, Storage, Uint128};
|
||||
use cw_storage_plus::{Item, Map, U32Key};
|
||||
use mixnet_contract::{IdentityKey, RewardingStatus};
|
||||
use cw_storage_plus::{Item, Map};
|
||||
use mixnet_contract_common::{IdentityKey, RewardingStatus};
|
||||
|
||||
pub(crate) const REWARD_POOL: Item<Uint128> = Item::new("pool");
|
||||
pub(crate) const REWARDING_STATUS: Map<(U32Key, IdentityKey), RewardingStatus> = Map::new("rm");
|
||||
// TODO: Do we need a migration for this?
|
||||
pub(crate) const REWARDING_STATUS: Map<(u32, IdentityKey), RewardingStatus> = Map::new("rm");
|
||||
|
||||
// approximately 1 day (assuming 5s per block)
|
||||
pub(crate) const MINIMUM_BLOCK_AGE_FOR_REWARDING: u64 = 17280;
|
||||
|
||||
@@ -9,8 +9,13 @@ use crate::mixnodes::storage as mixnodes_storage;
|
||||
use crate::rewards::helpers;
|
||||
use cosmwasm_std::{Addr, DepsMut, Env, MessageInfo, Response, StdResult, Storage, Uint128};
|
||||
use cw_storage_plus::{Bound, PrimaryKey};
|
||||
use mixnet_contract::mixnode::{DelegatorRewardParams, NodeRewardParams};
|
||||
use mixnet_contract::{
|
||||
use mixnet_contract_common::events::{
|
||||
new_begin_rewarding_event, new_finish_rewarding_event, new_mix_delegators_rewarding_event,
|
||||
new_mix_operator_rewarding_event, new_not_found_mix_operator_rewarding_event,
|
||||
new_too_fresh_bond_mix_operator_rewarding_event, new_zero_uptime_mix_operator_rewarding_event,
|
||||
};
|
||||
use mixnet_contract_common::mixnode::{DelegatorRewardParams, NodeRewardParams};
|
||||
use mixnet_contract_common::{
|
||||
IdentityKey, RewardingResult, RewardingStatus, MIXNODE_DELEGATORS_PAGE_LIMIT,
|
||||
};
|
||||
|
||||
@@ -106,10 +111,7 @@ pub(crate) fn try_begin_mixnode_rewarding(
|
||||
|
||||
mixnet_params_storage::CONTRACT_STATE.save(deps.storage, &state)?;
|
||||
|
||||
Ok(Response::new().add_attribute(
|
||||
"rewarding interval nonce",
|
||||
rewarding_interval_nonce.to_string(),
|
||||
))
|
||||
Ok(Response::new().add_event(new_begin_rewarding_event(rewarding_interval_nonce)))
|
||||
}
|
||||
|
||||
fn reward_mix_delegators(
|
||||
@@ -199,7 +201,7 @@ pub(crate) fn try_reward_next_mixnode_delegators(
|
||||
|
||||
match storage::REWARDING_STATUS.may_load(
|
||||
deps.storage,
|
||||
(rewarding_interval_nonce.into(), mix_identity.clone()),
|
||||
(rewarding_interval_nonce, mix_identity.clone()),
|
||||
)? {
|
||||
None => {
|
||||
// we haven't called 'regular' try_reward_mixnode, i.e. the operator itself
|
||||
@@ -232,21 +234,26 @@ pub(crate) fn try_reward_next_mixnode_delegators(
|
||||
let mut rewarding_results = next_page_info.running_results;
|
||||
rewarding_results.total_delegator_reward += delegation_rewarding_result.total_rewarded;
|
||||
|
||||
let round_increase = delegation_rewarding_result.total_rewarded.to_string();
|
||||
let round_increase = delegation_rewarding_result.total_rewarded;
|
||||
let more_delegators = delegation_rewarding_result.start_next.is_some();
|
||||
|
||||
helpers::update_rewarding_status(
|
||||
deps.storage,
|
||||
rewarding_interval_nonce,
|
||||
mix_identity,
|
||||
mix_identity.clone(),
|
||||
rewarding_results,
|
||||
delegation_rewarding_result.start_next,
|
||||
next_page_info.rewarding_params,
|
||||
)?;
|
||||
|
||||
Ok(Response::new()
|
||||
.add_attribute("current round delegation increase", round_increase)
|
||||
.add_attribute("more delegators to reward", more_delegators.to_string()))
|
||||
Ok(
|
||||
Response::new().add_event(new_mix_delegators_rewarding_event(
|
||||
rewarding_interval_nonce,
|
||||
&mix_identity,
|
||||
round_increase,
|
||||
more_delegators,
|
||||
)),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -264,7 +271,7 @@ pub(crate) fn try_reward_mixnode(
|
||||
// check if the mixnode hasn't been rewarded in this rewarding interval already
|
||||
match storage::REWARDING_STATUS.may_load(
|
||||
deps.storage,
|
||||
(rewarding_interval_nonce.into(), mix_identity.clone()),
|
||||
(rewarding_interval_nonce, mix_identity.clone()),
|
||||
)? {
|
||||
None => (),
|
||||
Some(RewardingStatus::Complete(_)) => {
|
||||
@@ -283,68 +290,91 @@ pub(crate) fn try_reward_mixnode(
|
||||
let current_bond = match mixnodes_storage::read_full_mixnode_bond(deps.storage, &mix_identity)?
|
||||
{
|
||||
Some(bond) => bond,
|
||||
None => return Ok(Response::new().add_attribute("result", "bond not found")),
|
||||
None => {
|
||||
return Ok(
|
||||
Response::new().add_event(new_not_found_mix_operator_rewarding_event(
|
||||
rewarding_interval_nonce,
|
||||
&mix_identity,
|
||||
)),
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
let mut node_reward = "0".to_string();
|
||||
let mut operator_reward = Uint128::zero();
|
||||
let mut total_delegation_increase = Uint128::zero();
|
||||
let mut more_delegators = false;
|
||||
|
||||
// check if node is old enough for rewarding and if its uptime is non-zero
|
||||
if current_bond.block_height + storage::MINIMUM_BLOCK_AGE_FOR_REWARDING <= env.block.height
|
||||
&& params.uptime() > 0
|
||||
{
|
||||
let mut node_reward_params = params;
|
||||
node_reward_params.set_reward_blockstamp(env.block.height);
|
||||
|
||||
let operator_reward_result = current_bond.reward(&node_reward_params);
|
||||
node_reward = operator_reward_result.reward().to_string();
|
||||
|
||||
// Omitting the price per packet function now, it follows that base operator reward is the node_reward
|
||||
operator_reward = Uint128::new(current_bond.operator_reward(&node_reward_params));
|
||||
|
||||
let delegator_params = DelegatorRewardParams::new(¤t_bond, node_reward_params);
|
||||
let delegation_rewarding_result =
|
||||
reward_mix_delegators(deps.storage, mix_identity.clone(), None, delegator_params)?;
|
||||
|
||||
helpers::update_post_rewarding_storage(
|
||||
deps.storage,
|
||||
&mix_identity,
|
||||
operator_reward,
|
||||
delegation_rewarding_result.total_rewarded,
|
||||
)?;
|
||||
|
||||
let rewarding_results = RewardingResult {
|
||||
operator_reward,
|
||||
total_delegator_reward: delegation_rewarding_result.total_rewarded,
|
||||
};
|
||||
|
||||
total_delegation_increase = rewarding_results.total_delegator_reward;
|
||||
more_delegators = delegation_rewarding_result.start_next.is_some();
|
||||
|
||||
helpers::update_rewarding_status(
|
||||
deps.storage,
|
||||
rewarding_interval_nonce,
|
||||
mix_identity,
|
||||
rewarding_results,
|
||||
delegation_rewarding_result.start_next,
|
||||
delegator_params,
|
||||
)?;
|
||||
} else {
|
||||
// node is not eligible for rewarding, so we're done immediately
|
||||
// check if node is old enough for rewarding
|
||||
if current_bond.block_height + storage::MINIMUM_BLOCK_AGE_FOR_REWARDING > env.block.height {
|
||||
storage::REWARDING_STATUS.save(
|
||||
deps.storage,
|
||||
(rewarding_interval_nonce.into(), mix_identity),
|
||||
(rewarding_interval_nonce, mix_identity.clone()),
|
||||
&RewardingStatus::Complete(Default::default()),
|
||||
)?;
|
||||
|
||||
return Ok(
|
||||
Response::new().add_event(new_too_fresh_bond_mix_operator_rewarding_event(
|
||||
rewarding_interval_nonce,
|
||||
&mix_identity,
|
||||
)),
|
||||
);
|
||||
}
|
||||
|
||||
Ok(Response::new()
|
||||
.add_attribute("node reward", node_reward)
|
||||
.add_attribute("operator reward", operator_reward)
|
||||
.add_attribute("total delegation increase", total_delegation_increase)
|
||||
.add_attribute("more delegators to reward", more_delegators.to_string()))
|
||||
// check if it has non-zero uptime
|
||||
if params.uptime() == 0 {
|
||||
storage::REWARDING_STATUS.save(
|
||||
deps.storage,
|
||||
(rewarding_interval_nonce, mix_identity.clone()),
|
||||
&RewardingStatus::Complete(Default::default()),
|
||||
)?;
|
||||
|
||||
return Ok(
|
||||
Response::new().add_event(new_zero_uptime_mix_operator_rewarding_event(
|
||||
rewarding_interval_nonce,
|
||||
&mix_identity,
|
||||
)),
|
||||
);
|
||||
}
|
||||
|
||||
let mut node_reward_params = params;
|
||||
node_reward_params.set_reward_blockstamp(env.block.height);
|
||||
|
||||
let node_reward_result = current_bond.reward(&node_reward_params);
|
||||
|
||||
// Omitting the price per packet function now, it follows that base operator reward is the node_reward
|
||||
let operator_reward = Uint128::new(current_bond.operator_reward(&node_reward_params));
|
||||
|
||||
let delegator_params = DelegatorRewardParams::new(¤t_bond, node_reward_params);
|
||||
let delegation_rewarding_result =
|
||||
reward_mix_delegators(deps.storage, mix_identity.clone(), None, delegator_params)?;
|
||||
|
||||
helpers::update_post_rewarding_storage(
|
||||
deps.storage,
|
||||
&mix_identity,
|
||||
operator_reward,
|
||||
delegation_rewarding_result.total_rewarded,
|
||||
)?;
|
||||
|
||||
let rewarding_results = RewardingResult {
|
||||
operator_reward,
|
||||
total_delegator_reward: delegation_rewarding_result.total_rewarded,
|
||||
};
|
||||
let total_delegator_reward = rewarding_results.total_delegator_reward;
|
||||
let further_delegations = delegation_rewarding_result.start_next.is_some();
|
||||
|
||||
helpers::update_rewarding_status(
|
||||
deps.storage,
|
||||
rewarding_interval_nonce,
|
||||
mix_identity.clone(),
|
||||
rewarding_results,
|
||||
delegation_rewarding_result.start_next,
|
||||
delegator_params,
|
||||
)?;
|
||||
|
||||
Ok(Response::new().add_event(new_mix_operator_rewarding_event(
|
||||
rewarding_interval_nonce,
|
||||
&mix_identity,
|
||||
node_reward_result,
|
||||
operator_reward,
|
||||
total_delegator_reward,
|
||||
further_delegations,
|
||||
)))
|
||||
}
|
||||
|
||||
pub(crate) fn try_finish_mixnode_rewarding(
|
||||
@@ -374,7 +404,7 @@ pub(crate) fn try_finish_mixnode_rewarding(
|
||||
state.rewarding_in_progress = false;
|
||||
mixnet_params_storage::CONTRACT_STATE.save(deps.storage, &state)?;
|
||||
|
||||
Ok(Response::new())
|
||||
Ok(Response::new().add_event(new_finish_rewarding_event(rewarding_interval_nonce)))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -394,11 +424,15 @@ pub mod tests {
|
||||
use config::defaults::DENOM;
|
||||
use cosmwasm_std::testing::{mock_env, mock_info};
|
||||
use cosmwasm_std::Coin;
|
||||
use cosmwasm_std::{attr, Order};
|
||||
use cosmwasm_std::Order;
|
||||
use cosmwasm_std::{coin, coins, Addr, Uint128};
|
||||
use mixnet_contract::mixnode::NodeRewardParams;
|
||||
use mixnet_contract::{Delegation, MixNode};
|
||||
use mixnet_contract::{IdentityKey, Layer};
|
||||
use mixnet_contract_common::events::{
|
||||
must_find_attribute, BOND_TOO_FRESH_VALUE, DISTRIBUTED_DELEGATION_REWARDS_KEY,
|
||||
FURTHER_DELEGATIONS_TO_REWARD_KEY, NO_REWARD_REASON_KEY, OPERATOR_REWARDING_EVENT_TYPE,
|
||||
OPERATOR_REWARD_KEY, TOTAL_MIXNODE_REWARD_KEY,
|
||||
};
|
||||
use mixnet_contract_common::mixnode::NodeRewardParams;
|
||||
use mixnet_contract_common::{Delegation, IdentityKey, Layer, MixNode};
|
||||
|
||||
#[cfg(test)]
|
||||
mod beginning_mixnode_rewarding {
|
||||
@@ -426,7 +460,7 @@ pub mod tests {
|
||||
|
||||
let res = try_begin_mixnode_rewarding(
|
||||
deps.as_mut(),
|
||||
env.clone(),
|
||||
env,
|
||||
mock_info(rewarding_validator_address.as_ref(), &[]),
|
||||
1,
|
||||
);
|
||||
@@ -452,7 +486,7 @@ pub mod tests {
|
||||
|
||||
let res = try_begin_mixnode_rewarding(
|
||||
deps.as_mut(),
|
||||
env.clone(),
|
||||
env,
|
||||
mock_info(rewarding_validator_address.as_ref(), &[]),
|
||||
2,
|
||||
);
|
||||
@@ -547,7 +581,7 @@ pub mod tests {
|
||||
|
||||
let res = try_begin_mixnode_rewarding(
|
||||
deps.as_mut(),
|
||||
env.clone(),
|
||||
env,
|
||||
mock_info(rewarding_validator_address.as_ref(), &[]),
|
||||
43,
|
||||
);
|
||||
@@ -774,9 +808,9 @@ pub mod tests {
|
||||
|
||||
let res = try_reward_mixnode(
|
||||
deps.as_mut(),
|
||||
env.clone(),
|
||||
env,
|
||||
info,
|
||||
node_identity.clone(),
|
||||
node_identity,
|
||||
tests::fixtures::node_rewarding_params_fixture(100),
|
||||
1,
|
||||
);
|
||||
@@ -836,9 +870,9 @@ pub mod tests {
|
||||
|
||||
let res = try_reward_mixnode(
|
||||
deps.as_mut(),
|
||||
env.clone(),
|
||||
env,
|
||||
info,
|
||||
node_identity.clone(),
|
||||
node_identity,
|
||||
tests::fixtures::node_rewarding_params_fixture(100),
|
||||
1,
|
||||
);
|
||||
@@ -900,7 +934,7 @@ pub mod tests {
|
||||
deps.as_mut(),
|
||||
env,
|
||||
info,
|
||||
node_identity.clone(),
|
||||
node_identity,
|
||||
tests::fixtures::node_rewarding_params_fixture(100),
|
||||
2,
|
||||
);
|
||||
@@ -923,14 +957,13 @@ pub mod tests {
|
||||
let initial_delegation = 20000_000000;
|
||||
let mixnode_bond = StoredMixnodeBond {
|
||||
pledge_amount: coin(initial_bond, DENOM),
|
||||
owner: node_owner.clone(),
|
||||
owner: node_owner,
|
||||
layer: Layer::One,
|
||||
block_height: env.block.height,
|
||||
mix_node: MixNode {
|
||||
identity_key: node_identity.clone(),
|
||||
..tests::fixtures::mix_node_fixture()
|
||||
},
|
||||
profit_margin_percent: Some(10),
|
||||
proxy: None,
|
||||
};
|
||||
|
||||
@@ -988,13 +1021,11 @@ pub mod tests {
|
||||
.unwrap()
|
||||
.u128()
|
||||
);
|
||||
|
||||
assert_eq!(res.attributes[0], attr("node reward", "0"));
|
||||
assert_eq!(res.attributes[1], attr("operator reward", "0"));
|
||||
assert_eq!(res.attributes[2], attr("total delegation increase", "0"));
|
||||
assert_eq!(1, res.events.len());
|
||||
assert_eq!(OPERATOR_REWARDING_EVENT_TYPE, res.events[0].ty);
|
||||
assert_eq!(
|
||||
res.attributes[3],
|
||||
attr("more delegators to reward", false.to_string())
|
||||
BOND_TOO_FRESH_VALUE,
|
||||
must_find_attribute(&res.events[0], NO_REWARD_REASON_KEY)
|
||||
);
|
||||
|
||||
// reward can happen now, but only for bonded node
|
||||
@@ -1027,12 +1058,18 @@ pub mod tests {
|
||||
.u128()
|
||||
);
|
||||
|
||||
assert_ne!(res.attributes[0], attr("node reward", "0"));
|
||||
assert_ne!(res.attributes[1], attr("operator reward", "0"));
|
||||
assert_eq!(res.attributes[2], attr("total delegation increase", "0"));
|
||||
assert_eq!(1, res.events.len());
|
||||
let event = &res.events[0];
|
||||
assert_eq!(OPERATOR_REWARDING_EVENT_TYPE, event.ty);
|
||||
assert_ne!("0", must_find_attribute(event, TOTAL_MIXNODE_REWARD_KEY));
|
||||
assert_ne!("0", must_find_attribute(event, OPERATOR_REWARD_KEY));
|
||||
assert_eq!(
|
||||
res.attributes[3],
|
||||
attr("more delegators to reward", false.to_string())
|
||||
"0",
|
||||
must_find_attribute(event, DISTRIBUTED_DELEGATION_REWARDS_KEY)
|
||||
);
|
||||
assert_eq!(
|
||||
false.to_string(),
|
||||
must_find_attribute(event, FURTHER_DELEGATIONS_TO_REWARD_KEY)
|
||||
);
|
||||
|
||||
// reward happens now, both for node owner and delegators
|
||||
@@ -1047,7 +1084,7 @@ pub mod tests {
|
||||
try_begin_mixnode_rewarding(deps.as_mut(), env.clone(), info.clone(), 3).unwrap();
|
||||
let res = try_reward_mixnode(
|
||||
deps.as_mut(),
|
||||
env.clone(),
|
||||
env,
|
||||
info.clone(),
|
||||
node_identity.clone(),
|
||||
tests::fixtures::node_rewarding_params_fixture(100),
|
||||
@@ -1070,12 +1107,18 @@ pub mod tests {
|
||||
> initial_delegation
|
||||
);
|
||||
|
||||
assert_ne!(res.attributes[0], attr("node reward", "0"));
|
||||
assert_ne!(res.attributes[1], attr("operator reward", "0"));
|
||||
assert_ne!(res.attributes[2], attr("total delegation increase", "0"));
|
||||
assert_eq!(1, res.events.len());
|
||||
let event = &res.events[0];
|
||||
assert_eq!(OPERATOR_REWARDING_EVENT_TYPE, event.ty);
|
||||
assert_ne!("0", must_find_attribute(event, TOTAL_MIXNODE_REWARD_KEY));
|
||||
assert_ne!("0", must_find_attribute(event, OPERATOR_REWARD_KEY));
|
||||
assert_ne!(
|
||||
"0",
|
||||
must_find_attribute(event, DISTRIBUTED_DELEGATION_REWARDS_KEY)
|
||||
);
|
||||
assert_eq!(
|
||||
res.attributes[3],
|
||||
attr("more delegators to reward", false.to_string())
|
||||
false.to_string(),
|
||||
must_find_attribute(event, FURTHER_DELEGATIONS_TO_REWARD_KEY)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1198,7 +1241,7 @@ pub mod tests {
|
||||
);
|
||||
assert_eq!(
|
||||
mixnodes_storage::TOTAL_DELEGATION
|
||||
.load(&deps.storage, &node_identity.clone())
|
||||
.load(&deps.storage, &node_identity)
|
||||
.unwrap()
|
||||
.u128(),
|
||||
pre_reward_delegation + mix1_delegator1_reward + mix1_delegator2_reward
|
||||
@@ -1214,7 +1257,7 @@ pub mod tests {
|
||||
|
||||
// it's all correctly saved
|
||||
match storage::REWARDING_STATUS
|
||||
.load(deps.as_ref().storage, (1.into(), node_identity.clone()))
|
||||
.load(deps.as_ref().storage, (1u32, node_identity))
|
||||
.unwrap()
|
||||
{
|
||||
RewardingStatus::Complete(result) => assert_eq!(
|
||||
@@ -1244,6 +1287,7 @@ pub mod tests {
|
||||
.unwrap();
|
||||
let rewarding_validator_address = current_state.rewarding_validator_address;
|
||||
|
||||
#[allow(clippy::inconsistent_digit_grouping)]
|
||||
let mix_bond = Uint128::new(10000_000_000);
|
||||
let delegation_value = 2000_000000;
|
||||
|
||||
@@ -1263,7 +1307,7 @@ pub mod tests {
|
||||
env.clone(),
|
||||
mock_info(
|
||||
&*format!("delegator{}", i),
|
||||
&vec![coin(delegation_value, DENOM)],
|
||||
&[coin(delegation_value, DENOM)],
|
||||
),
|
||||
node_identity.clone(),
|
||||
)
|
||||
@@ -1291,8 +1335,8 @@ pub mod tests {
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
res.attributes[3],
|
||||
attr("more delegators to reward", false.to_string())
|
||||
false.to_string(),
|
||||
must_find_attribute(&res.events[0], FURTHER_DELEGATIONS_TO_REWARD_KEY)
|
||||
);
|
||||
|
||||
try_finish_mixnode_rewarding(
|
||||
@@ -1325,6 +1369,7 @@ pub mod tests {
|
||||
.unwrap();
|
||||
let rewarding_validator_address = current_state.rewarding_validator_address;
|
||||
|
||||
#[allow(clippy::inconsistent_digit_grouping)]
|
||||
let mix_bond = Uint128::new(10000_000_000);
|
||||
let delegation_value = 2000_000000;
|
||||
|
||||
@@ -1344,7 +1389,7 @@ pub mod tests {
|
||||
env.clone(),
|
||||
mock_info(
|
||||
&*format!("delegator{}", i),
|
||||
&vec![coin(delegation_value, DENOM)],
|
||||
&[coin(delegation_value, DENOM)],
|
||||
),
|
||||
node_identity.clone(),
|
||||
)
|
||||
@@ -1372,8 +1417,8 @@ pub mod tests {
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
res.attributes[3],
|
||||
attr("more delegators to reward", false.to_string())
|
||||
false.to_string(),
|
||||
must_find_attribute(&res.events[0], FURTHER_DELEGATIONS_TO_REWARD_KEY)
|
||||
);
|
||||
|
||||
try_finish_mixnode_rewarding(
|
||||
@@ -1406,6 +1451,7 @@ pub mod tests {
|
||||
.unwrap();
|
||||
let rewarding_validator_address = current_state.rewarding_validator_address;
|
||||
|
||||
#[allow(clippy::inconsistent_digit_grouping)]
|
||||
let mix_bond = Uint128::new(10000_000_000);
|
||||
let delegation_value = 2000_000000;
|
||||
|
||||
@@ -1425,7 +1471,7 @@ pub mod tests {
|
||||
env.clone(),
|
||||
mock_info(
|
||||
&*format!("delegator{:04}", i),
|
||||
&vec![coin(delegation_value, DENOM)],
|
||||
&[coin(delegation_value, DENOM)],
|
||||
),
|
||||
node_identity.clone(),
|
||||
)
|
||||
@@ -1453,8 +1499,8 @@ pub mod tests {
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
res.attributes[3],
|
||||
attr("more delegators to reward", true.to_string())
|
||||
true.to_string(),
|
||||
must_find_attribute(&res.events[0], FURTHER_DELEGATIONS_TO_REWARD_KEY)
|
||||
);
|
||||
|
||||
try_finish_mixnode_rewarding(
|
||||
@@ -1477,7 +1523,7 @@ pub mod tests {
|
||||
|
||||
let delegation = test_helpers::read_delegation(
|
||||
&deps.storage,
|
||||
node_identity.clone(),
|
||||
node_identity,
|
||||
format!("delegator{:04}", MIXNODE_DELEGATORS_PAGE_LIMIT),
|
||||
)
|
||||
.unwrap();
|
||||
@@ -1493,6 +1539,8 @@ pub mod tests {
|
||||
let mut env = mock_env();
|
||||
|
||||
let node_owner: Addr = Addr::unchecked("bob");
|
||||
|
||||
#[allow(clippy::inconsistent_digit_grouping)]
|
||||
let node_identity = test_helpers::add_mixnode(
|
||||
node_owner.as_str(),
|
||||
coins(10000_000_000, DENOM),
|
||||
@@ -1512,7 +1560,7 @@ pub mod tests {
|
||||
env.clone(),
|
||||
mock_info(
|
||||
&*format!("delegator{:04}", i),
|
||||
&vec![coin(base_delegation, DENOM)],
|
||||
&[coin(base_delegation, DENOM)],
|
||||
),
|
||||
node_identity.clone(),
|
||||
)
|
||||
@@ -1531,7 +1579,7 @@ pub mod tests {
|
||||
for delegation in delegations_storage::delegations()
|
||||
.idx
|
||||
.mixnode
|
||||
.prefix(node_identity.clone())
|
||||
.prefix(node_identity)
|
||||
.range(deps.as_ref().storage, None, None, Order::Ascending)
|
||||
{
|
||||
actual_reward +=
|
||||
@@ -1546,6 +1594,8 @@ pub mod tests {
|
||||
|
||||
// with paging
|
||||
let node_owner: Addr = Addr::unchecked("alice");
|
||||
|
||||
#[allow(clippy::inconsistent_digit_grouping)]
|
||||
let node_identity = test_helpers::add_mixnode(
|
||||
node_owner.as_str(),
|
||||
coins(10000_000_000, DENOM),
|
||||
@@ -1565,7 +1615,7 @@ pub mod tests {
|
||||
env.clone(),
|
||||
mock_info(
|
||||
&*format!("delegator{:04}", i),
|
||||
&vec![coin(base_delegation, DENOM)],
|
||||
&[coin(base_delegation, DENOM)],
|
||||
),
|
||||
node_identity.clone(),
|
||||
)
|
||||
@@ -1585,7 +1635,7 @@ pub mod tests {
|
||||
.idx
|
||||
.mixnode
|
||||
.prefix(node_identity.clone())
|
||||
.range(deps.as_ref().storage, None, None, Order::Ascending)
|
||||
.range_raw(deps.as_ref().storage, None, None, Order::Ascending)
|
||||
{
|
||||
let (primary_key, delegation) = delegation.unwrap();
|
||||
let delegator_reward = Uint128::new(delegation.amount.amount.u128() - base_delegation);
|
||||
@@ -1629,7 +1679,7 @@ pub mod tests {
|
||||
for delegation in delegations_storage::delegations()
|
||||
.idx
|
||||
.mixnode
|
||||
.prefix(node_identity.clone())
|
||||
.prefix(node_identity)
|
||||
.range(deps.as_ref().storage, Some(start), None, Order::Ascending)
|
||||
{
|
||||
actual_reward +=
|
||||
@@ -1686,7 +1736,7 @@ pub mod tests {
|
||||
|
||||
try_begin_mixnode_rewarding(
|
||||
deps.as_mut(),
|
||||
env.clone(),
|
||||
env,
|
||||
mock_info(rewarding_validator_address.as_ref(), &[]),
|
||||
1,
|
||||
)
|
||||
@@ -1718,6 +1768,8 @@ pub mod tests {
|
||||
let rewarding_validator_address = current_state.rewarding_validator_address;
|
||||
|
||||
let node_owner: Addr = Addr::unchecked("alice");
|
||||
|
||||
#[allow(clippy::inconsistent_digit_grouping)]
|
||||
let node_identity = test_helpers::add_mixnode(
|
||||
node_owner.as_str(),
|
||||
coins(10000_000_000, DENOM),
|
||||
@@ -1753,7 +1805,7 @@ pub mod tests {
|
||||
|
||||
assert_eq!(
|
||||
Err(ContractError::MixnodeAlreadyRewarded {
|
||||
identity: node_identity.clone()
|
||||
identity: node_identity
|
||||
}),
|
||||
res
|
||||
);
|
||||
@@ -1767,6 +1819,8 @@ pub mod tests {
|
||||
|
||||
// there was another page of delegators, but they were already dealt with
|
||||
let node_owner: Addr = Addr::unchecked("bob");
|
||||
|
||||
#[allow(clippy::inconsistent_digit_grouping)]
|
||||
let node_identity = test_helpers::add_mixnode(
|
||||
node_owner.as_str(),
|
||||
coins(10000_000_000, DENOM),
|
||||
@@ -1777,10 +1831,7 @@ pub mod tests {
|
||||
try_delegate_to_mixnode(
|
||||
deps.as_mut(),
|
||||
env.clone(),
|
||||
mock_info(
|
||||
&*format!("delegator{:04}", i),
|
||||
&vec![coin(2000_000000, DENOM)],
|
||||
),
|
||||
mock_info(&*format!("delegator{:04}", i), &[coin(2000_000000, DENOM)]),
|
||||
node_identity.clone(),
|
||||
)
|
||||
.unwrap();
|
||||
@@ -1799,7 +1850,7 @@ pub mod tests {
|
||||
|
||||
try_reward_mixnode(
|
||||
deps.as_mut(),
|
||||
env.clone(),
|
||||
env,
|
||||
info,
|
||||
node_identity.clone(),
|
||||
tests::fixtures::node_rewarding_params_fixture(100),
|
||||
@@ -1825,7 +1876,7 @@ pub mod tests {
|
||||
|
||||
assert_eq!(
|
||||
Err(ContractError::MixnodeAlreadyRewarded {
|
||||
identity: node_identity.clone()
|
||||
identity: node_identity
|
||||
}),
|
||||
res
|
||||
);
|
||||
@@ -1848,6 +1899,7 @@ pub mod tests {
|
||||
.unwrap();
|
||||
let rewarding_validator_address = current_state.rewarding_validator_address;
|
||||
|
||||
#[allow(clippy::inconsistent_digit_grouping)]
|
||||
let mix_bond = Uint128::new(10000_000_000);
|
||||
let delegation_value = 2000_000000;
|
||||
|
||||
@@ -1869,7 +1921,7 @@ pub mod tests {
|
||||
env.clone(),
|
||||
mock_info(
|
||||
&*format!("delegator{:04}", i),
|
||||
&vec![coin(delegation_value, DENOM)],
|
||||
&[coin(delegation_value, DENOM)],
|
||||
),
|
||||
node_identity.clone(),
|
||||
)
|
||||
@@ -1889,7 +1941,7 @@ pub mod tests {
|
||||
|
||||
try_reward_mixnode(
|
||||
deps.as_mut(),
|
||||
env.clone(),
|
||||
env,
|
||||
info,
|
||||
node_identity.clone(),
|
||||
tests::fixtures::node_rewarding_params_fixture(100),
|
||||
@@ -1945,6 +1997,7 @@ pub mod tests {
|
||||
.unwrap();
|
||||
let rewarding_validator_address = current_state.rewarding_validator_address;
|
||||
|
||||
#[allow(clippy::inconsistent_digit_grouping)]
|
||||
let mix_bond = Uint128::new(10000_000_000);
|
||||
let delegation_value = 2000_000000;
|
||||
|
||||
@@ -1966,7 +2019,7 @@ pub mod tests {
|
||||
env.clone(),
|
||||
mock_info(
|
||||
&*format!("delegator{:04}", i),
|
||||
&vec![coin(delegation_value, DENOM)],
|
||||
&[coin(delegation_value, DENOM)],
|
||||
),
|
||||
node_identity.clone(),
|
||||
)
|
||||
@@ -1979,7 +2032,7 @@ pub mod tests {
|
||||
try_delegate_to_mixnode(
|
||||
deps.as_mut(),
|
||||
env.clone(),
|
||||
mock_info("delegator0123", &vec![coin(delegation_value, DENOM)]),
|
||||
mock_info("delegator0123", &[coin(delegation_value, DENOM)]),
|
||||
node_identity.clone(),
|
||||
)
|
||||
.unwrap();
|
||||
@@ -1989,7 +2042,7 @@ pub mod tests {
|
||||
env.clone(),
|
||||
mock_info(
|
||||
&*format!("delegator{:04}", 123 + MIXNODE_DELEGATORS_PAGE_LIMIT),
|
||||
&vec![coin(delegation_value, DENOM)],
|
||||
&[coin(delegation_value, DENOM)],
|
||||
),
|
||||
node_identity.clone(),
|
||||
)
|
||||
@@ -2008,7 +2061,7 @@ pub mod tests {
|
||||
|
||||
try_reward_mixnode(
|
||||
deps.as_mut(),
|
||||
env.clone(),
|
||||
env,
|
||||
info,
|
||||
node_identity.clone(),
|
||||
tests::fixtures::node_rewarding_params_fixture(100),
|
||||
|
||||
@@ -5,7 +5,7 @@ use crate::error::ContractError;
|
||||
use crate::gateways::storage as gateways_storage;
|
||||
use crate::mixnodes::storage as mixnodes_storage;
|
||||
use cosmwasm_std::{Addr, Deps, Storage};
|
||||
use mixnet_contract::IdentityKeyRef;
|
||||
use mixnet_contract_common::IdentityKeyRef;
|
||||
|
||||
pub fn generate_storage_key(address: &Addr, proxy: Option<&Addr>) -> Vec<u8> {
|
||||
if let Some(proxy) = &proxy {
|
||||
|
||||
@@ -6,8 +6,8 @@ use crate::mixnodes::storage as mixnodes_storage;
|
||||
use crate::{mixnodes::storage::StoredMixnodeBond, support::tests};
|
||||
use config::defaults::{DENOM, TOTAL_SUPPLY};
|
||||
use cosmwasm_std::{coin, Addr, Coin};
|
||||
use mixnet_contract::mixnode::NodeRewardParams;
|
||||
use mixnet_contract::{Gateway, GatewayBond, Layer, MixNode};
|
||||
use mixnet_contract_common::mixnode::NodeRewardParams;
|
||||
use mixnet_contract_common::{Gateway, GatewayBond, Layer, MixNode};
|
||||
|
||||
pub fn mix_node_fixture() -> MixNode {
|
||||
MixNode {
|
||||
@@ -59,7 +59,6 @@ pub(crate) fn stored_mixnode_bond_fixture(owner: &str) -> mixnodes_storage::Stor
|
||||
..super::fixtures::mix_node_fixture()
|
||||
},
|
||||
None,
|
||||
None,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use mixnet_contract::{ExecuteMsg, Gateway, IdentityKey, MixNode};
|
||||
use mixnet_contract_common::{ExecuteMsg, Gateway, IdentityKey, MixNode};
|
||||
use rand::thread_rng;
|
||||
|
||||
use crate::support::tests;
|
||||
|
||||
@@ -28,7 +28,7 @@ pub mod test_helpers {
|
||||
use cosmwasm_std::{Addr, StdResult, Storage};
|
||||
use cosmwasm_std::{Empty, MemoryStorage};
|
||||
use cw_storage_plus::PrimaryKey;
|
||||
use mixnet_contract::{Delegation, Gateway, IdentityKeyRef, InstantiateMsg, MixNode};
|
||||
use mixnet_contract_common::{Delegation, Gateway, IdentityKeyRef, InstantiateMsg, MixNode};
|
||||
use rand::thread_rng;
|
||||
|
||||
pub fn add_mixnode(sender: &str, stake: Vec<Coin>, deps: DepsMut) -> String {
|
||||
@@ -81,7 +81,7 @@ pub mod test_helpers {
|
||||
pub fn init_contract() -> OwnedDeps<MemoryStorage, MockApi, MockQuerier<Empty>> {
|
||||
let mut deps = mock_dependencies();
|
||||
let msg = InstantiateMsg {
|
||||
rewarding_validator_address: config::defaults::REWARDING_VALIDATOR_ADDRESS.to_string(),
|
||||
rewarding_validator_address: config::defaults::DEFAULT_REWARDING_VALIDATOR.to_string(),
|
||||
};
|
||||
let env = mock_env();
|
||||
let info = mock_info("creator", &[]);
|
||||
|
||||
@@ -4,7 +4,7 @@ use cosmwasm_std::{
|
||||
testing::{mock_env, MockApi, MockQuerier, MockStorage},
|
||||
Addr, Coin, OwnedDeps,
|
||||
};
|
||||
use mixnet_contract::{
|
||||
use mixnet_contract_common::{
|
||||
GatewayBond, MixNodeBond, PagedGatewayResponse, PagedMixnodeResponse, QueryMsg,
|
||||
};
|
||||
|
||||
|
||||
@@ -14,14 +14,13 @@ exclude = [
|
||||
crate-type = ["cdylib", "rlib"]
|
||||
|
||||
[dependencies]
|
||||
mixnet-contract = { path = "../../common/mixnet-contract" }
|
||||
mixnet-contract-common = { path = "../../common/cosmwasm-smart-contracts/mixnet-contract" }
|
||||
vesting-contract-common = { path = "../../common/cosmwasm-smart-contracts/vesting-contract" }
|
||||
config = { path = "../../common/config" }
|
||||
|
||||
cosmwasm-std = { version = "1.0.0-beta3"}
|
||||
cw-storage-plus = { version = "0.10.3", features = ["iterator"] }
|
||||
cw-storage-plus = { version = "0.11.1", features = ["iterator"] }
|
||||
|
||||
schemars = "0.8"
|
||||
serde = { version = "1.0.103", default-features = false, features = ["derive"] }
|
||||
thiserror = { version = "1.0.23" }
|
||||
rand = {version = "0.8.4", features = ["std_rng"]}
|
||||
getrandom = { version = "0.2.3", features = ["js"]}
|
||||
thiserror = { version = "1.0.23" }
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user