Compare commits

..

89 Commits

Author SHA1 Message Date
Jędrzej Stuczyński 7f840b889f Merge branch 'feature/optional-contract-addresses' into temp-jstuczyn-branch 2022-01-20 17:32:57 +00:00
Jędrzej Stuczyński 5cd67b22b3 Made contract addresses for query NymdClient construction optional
Similarly as it is the case when creating SigningNymdClient
2022-01-20 17:03:16 +00:00
Jędrzej Stuczyński 25c6748ae9 Cargo fmt 2022-01-20 15:52:32 +00:00
Jędrzej Stuczyński 78d2ffa923 Introduced RPC query for total token supply 2022-01-20 15:47:46 +00:00
Jędrzej Stuczyński ecdbe034fa Implemented beta clippy lint recommendations (#1051) 2022-01-19 20:32:48 +01:00
Tommy Verrall 3e46c8630d Merge pull request #1050 from nymtech/update/validator-client-profit-percentage
add new function to update profit percentage
2022-01-19 16:18:47 +00:00
fmtabbara 93e962524a update types 2022-01-19 14:05:43 +00:00
dependabot[bot] 5b6c1c032c Bump shelljs in /contracts/basic-bandwidth-generation (#1043)
Bumps [shelljs](https://github.com/shelljs/shelljs) from 0.8.4 to 0.8.5.
- [Release notes](https://github.com/shelljs/shelljs/releases)
- [Changelog](https://github.com/shelljs/shelljs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/shelljs/shelljs/compare/v0.8.4...v0.8.5)

---
updated-dependencies:
- dependency-name: shelljs
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-01-19 14:00:19 +00:00
dependabot[bot] 135f1a6e7f Bump follow-redirects in /contracts/basic-bandwidth-generation (#1041)
Bumps [follow-redirects](https://github.com/follow-redirects/follow-redirects) from 1.14.4 to 1.14.7.
- [Release notes](https://github.com/follow-redirects/follow-redirects/releases)
- [Commits](https://github.com/follow-redirects/follow-redirects/compare/v1.14.4...v1.14.7)

---
updated-dependencies:
- dependency-name: follow-redirects
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-01-19 14:00:12 +00:00
dependabot[bot] c61f89144e Bump follow-redirects from 1.14.5 to 1.14.7 in /testnet-faucet (#1040)
Bumps [follow-redirects](https://github.com/follow-redirects/follow-redirects) from 1.14.5 to 1.14.7.
- [Release notes](https://github.com/follow-redirects/follow-redirects/releases)
- [Commits](https://github.com/follow-redirects/follow-redirects/compare/v1.14.5...v1.14.7)

---
updated-dependencies:
- dependency-name: follow-redirects
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-01-19 14:00:06 +00:00
Tommy Verrall 67fe368e65 Merge pull request #1033 from nymtech/feature/configurable_wallet
Feature/configurable wallet
2022-01-19 10:36:17 +00:00
Bogdan-Ștefan Neacşu 522229459b Fix clippy on relevant lints (#1044)
* Fix clippy on relevant lints

return_self_not_must_use still produces errors, but that will be
auto-fixed once the change to move it to pedantic is released to beta
channel

* Run fmt
2022-01-18 21:37:51 +01:00
Drazen Urch e3d8b71ea2 Endpoint for rewarded set inclusion probabilities (#1042)
* Add validator-api endpoint

* Add validator-client method

* Make it a bit nicer

* Address review comments

* Cap probability at 1.
2022-01-18 21:26:15 +01:00
Fouad 4f98fde362 Merge pull request #1046 from nymtech/feature/additional-bond-validation
Feature/additional bond validation
2022-01-18 12:57:14 +00:00
fmtabbara aa75e54419 dont display warnings on successful bond or delegate 2022-01-18 11:45:27 +00:00
fmtabbara 5190a541a6 add warning to delegate page 2022-01-18 11:30:56 +00:00
fmtabbara 3a39fff006 PR updates 2022-01-18 10:16:36 +00:00
fmtabbara 0e302b83ab add warning for unbonding 2022-01-17 18:42:13 +00:00
Fouad 0d0637fe19 Merge pull request #1036 from nymtech/feature/node-settings-update
Feature/node settings update
2022-01-17 18:16:24 +00:00
fmtabbara 1f0c0090dc merge develop 2022-01-17 17:53:14 +00:00
fmtabbara 4f960330b1 Merge branch 'develop' into feature/additional-bond-validation
merge develop
2022-01-17 17:36:41 +00:00
fmtabbara a273980aa0 refactor 2022-01-17 17:34:39 +00:00
neacsu 13a55f00d8 [ci skip] Generate TS types 2022-01-17 15:50:06 +00:00
Bogdan-Ștefan Neacșu 4feec780d4 Use fn new() for Account 2022-01-17 17:39:21 +02:00
Bogdan-Ștefan Neacșu 35c044c340 Store all clients and discard mnemonic 2022-01-17 17:24:52 +02:00
Bogdan-Ștefan Neacșu ac5539a0fa Export ts type file 2022-01-17 14:44:43 +02:00
Bogdan-Ștefan Neacșu 9c569cbb62 Expose switch_network to frontend 2022-01-17 14:13:15 +02:00
Bogdan-Ștefan Neacșu 72485cacd3 Pass possible network values using Network type
Export a Network type to TS and make seamless transitions between this
type and the network defaults one. We may have more networks supported
in the backend then in the frontend at a certain moment in time.
2022-01-17 13:38:10 +02:00
Drazen Urch 56d36d2c46 Migrate to cw-storage-plus 0.11.1 (#1035) 2022-01-14 20:59:40 +01:00
Drazen Urch 8fb54dd4e7 Feature/downcast reward estimation (#1031)
* Downcast u128 to u64

* fmt

* Fix status

* fmt
2022-01-14 20:57:51 +01:00
dependabot[bot] 44d59ff8c2 Bump @openzeppelin/contracts in /contracts/basic-bandwidth-generation (#1034)
Bumps [@openzeppelin/contracts](https://github.com/OpenZeppelin/openzeppelin-contracts) from 4.4.1 to 4.4.2.
- [Release notes](https://github.com/OpenZeppelin/openzeppelin-contracts/releases)
- [Changelog](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/CHANGELOG.md)
- [Commits](https://github.com/OpenZeppelin/openzeppelin-contracts/compare/v4.4.1...v4.4.2)

---
updated-dependencies:
- dependency-name: "@openzeppelin/contracts"
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-01-14 15:50:57 +00:00
fmtabbara a8caf19f8c additional balance check before bonding 2022-01-14 14:32:16 +00:00
fmtabbara 53b44fb9c6 remove unused import 2022-01-13 17:30:11 +00:00
fmtabbara c0959e853e spacing updates 2022-01-13 17:07:18 +00:00
fmtabbara 144df00782 fix conflicts and refine UI 2022-01-13 16:40:59 +00:00
Fouad be4708cc84 Merge pull request #1028 from nymtech/feature/ui-updates
Wallet UI updates
2022-01-13 15:45:36 +00:00
fmtabbara d5cddec03c merge develop 2022-01-13 15:36:06 +00:00
fmtabbara 7c26cab4e6 get updated mixnode details after bonding/unbonding txs 2022-01-13 15:32:29 +00:00
Bogdan-Ștefan Neacșu f0bcf8c36f Update wallet backend 2022-01-13 17:20:17 +02:00
Bogdan-Ștefan Neacșu ac2f0a172e Store multiple network values in one place 2022-01-13 17:20:17 +02:00
Bogdan-Ștefan Neacșu 898070bc87 Rename some defaults 2022-01-13 17:20:17 +02:00
Bogdan-Ștefan Neacșu cc707660aa Expose both default and specific network values 2022-01-13 17:20:17 +02:00
fmtabbara 31624cf4e4 fix Rust u128 -> TS BiInt issue 2022-01-13 11:22:04 +00:00
fmtabbara e6a69170a4 raise mixnodedetails to main context 2022-01-13 11:22:04 +00:00
Bogdan-Ștefan Neacşu bc5e19514e Remove migration code (#1027) 2022-01-13 11:59:56 +01:00
fmtabbara 5c76b8483e add new function to update profit percentage 2022-01-13 10:10:42 +00:00
fmtabbara a9526c216f [ci skip] Generate TS types 2022-01-12 21:49:08 +00:00
fmtabbara 903af16a6b update settings state 2022-01-12 21:39:12 +00:00
fmtabbara 0de79b6953 create fee component 2022-01-12 21:38:06 +00:00
fmtabbara fd2fafb52a [ci skip] Generate TS types 2022-01-12 20:39:36 +00:00
fmtabbara fadb5b4ff9 update ui and state 2022-01-12 20:30:56 +00:00
fmtabbara 955583d0f0 merge develop 2022-01-12 16:04:48 +00:00
Fouad 3924c53d09 Merge pull request #1014 from nymtech/feature/update-profit-percentage
update frontend to use new profit update api
2022-01-12 15:33:28 +00:00
fmtabbara c0025ee9c6 update getfee function 2022-01-12 15:30:47 +00:00
fmtabbara 7dd0516b63 only request when settings open 2022-01-12 14:07:46 +00:00
fmtabbara d3cd3c9157 Merge branch 'develop' into feature/update-profit-percentage
merge develop
2022-01-12 12:49:59 +00:00
fmtabbara 83680473e0 Merge branch 'develop' into feature/additional-node-details
merge develop
2022-01-12 11:38:08 +00:00
fmtabbara 7f9a9f7a0a update node icon 2022-01-12 11:03:48 +00:00
fmtabbara e7ccb38502 use fullwidth input 2022-01-12 10:13:44 +00:00
Bogdan-Ștefan Neacşu 1f4c19d396 Add network defaults for qa (#1017)
* Add network defaults for qa

* update contract addresses

- have not updated the bandwith credential address - currently vesting

Co-authored-by: Tommy Verrall <tommyvez@protonmail.com>
2022-01-12 09:56:20 +01:00
fmtabbara 64842f40d7 integrate with new api 2022-01-11 19:41:16 +00:00
fmtabbara 2ec18721fc Merge branch 'develop' into feature/ui-updates
merge develop
2022-01-11 18:14:11 +00:00
fmtabbara 2ef1ac452f fix bug - send from address not showing 2022-01-11 18:11:46 +00:00
Jędrzej Stuczyński 6b3700aefe Feature/expanded events (#1015)
* Expanded emitted events for delegation-related transactions

* Expanded emitted events for gateway-related transactions

* Expanded emitted events for mixnode-related transactions

* Expanded emitted events for settings update transaction

* Expanded emitted events for rewarding-related transactions

* Fixed attribute look up in tests

* Making linter happier

* Reorganised cosmwasm contract-related modules

* Introduced similar event handling to the vesting contract
2022-01-11 16:56:12 +00:00
Jędrzej Stuczyński e2e06df4e6 Feature/validator api client endpoints (#1024)
* Moved mixnode status route to node status api module

* Introduced validator-api endpoint for estimating mixnode's reward

* Stake saturation endpoint

* kebab-cased coconut routes

* Created separate crate for validator API models

* Additional routes in validator API client

* Introduced support for new queries in the wallet

* Typescript type derivation

* Fixed up date in license notice
2022-01-11 16:37:07 +00:00
Jędrzej Stuczyński 835d4f46f6 Introduced denom check when trying to withdraw vested coins (#1018)
* Introduced denom check when trying to withdraw vested coins

* Using correct denom in the relevant unit test
2022-01-11 16:31:39 +00:00
Jędrzej Stuczyński d71ef635e2 Restricted blake3 dependency (#1025) 2022-01-11 16:22:55 +00:00
Bogdan-Ștefan Neacşu 6e3773a095 Feature/remove unused profit margin (#1011)
* Remove unused field, to avoid confusion

* Add migration code

* Update tests

* Make clippy happy
2022-01-11 16:05:15 +01:00
Jędrzej Stuczyński 050d370396 Updated cosmrs to 0.4.1 (#1023) 2022-01-11 11:26:34 +00:00
Jędrzej Stuczyński 29340ed00c Feature/additional mixnode endpoints (#1019)
* Moved mixnode status route to node status api module

* Introduced validator-api endpoint for estimating mixnode's reward

* Stake saturation endpoint
2022-01-11 09:38:39 +00:00
fmtabbara 2b062b3e5b add link to network explorer 2022-01-10 23:00:17 +00:00
fmtabbara b405adb9e5 add icons to card headers and balance padding 2022-01-10 22:36:12 +00:00
fmtabbara 5c3c0ac39e remove border lines and grey bg for card component 2022-01-10 21:17:47 +00:00
fmtabbara 1cc06ef349 update get_approx_fee to new function name _outdated_get_approx_fee 2022-01-10 17:31:43 +00:00
fmtabbara 2bef1603ab style updates 2022-01-10 17:27:01 +00:00
Mx 11a458a43d Merge pull request #1020 from RiccardoMasutti/patch-1
Fix 404 link
2022-01-10 18:00:58 +01:00
Jędrzej Stuczyński 1fbf37e0ec Changed wallet's client to a full validator client (#1021)
So that it could use validator API calls in the near future
2022-01-10 11:17:08 +00:00
Riccardo Masutti bc8efda08f Add wallet build instructions
Added wallet link
2022-01-09 16:00:17 +01:00
Riccardo Masutti cecd0b2b0a Fix 404 link 2022-01-09 15:56:45 +01:00
Jędrzej Stuczyński 62fa2ae5e4 Feature/node state endpoint (#1013)
* Introduced route to check mixnode's status (active/standby/inactive/not_found)

* Restored default validator API caching interval to a more sane value

* Changed status route
2022-01-07 11:57:38 +00:00
fmtabbara db2ce8070c display mixnode update fee 2022-01-06 16:16:32 +00:00
fmtabbara 70138ff54a update frontend to use new profit update api 2022-01-06 13:00:50 +00:00
Bogdan-Ștefan Neacşu 30e93c33bb Feature/configure profit (#1008)
* Introduce a method to update mixnode configuration

Right now, only for profit_margin_percent

* Check that the new profit margin is valid

* Extend a bit the test coverage of mixnode update

* Create validator client function

* [ci skip] Generate TS types

* Update wallet

* Update the bond height as well, as if a rebond was made

Co-authored-by: neacsu <neacsu@users.noreply.github.com>
2022-01-06 13:03:14 +01:00
Jędrzej Stuczyński ec4955f814 Feature/explorer node status (#1010)
* Restored mixnode refresh rate to a more sane value

* Moved PrettyMixNodeBondWithLocation to models.rs

* Renaming

* Exposed ability to query for rewarded mixnodes in the validator client

* Reorganised mix_nodes module

* Determining mixnode status (active/standby/inactive)

* Moved LocationCache to separate lock

* Minor cleanup

* Changed serialization case of status enum

* Made clippy happier

* Slightly better grammar
2022-01-06 10:38:14 +00:00
Drazen Urch e013517348 Use serial integer instead of random (#1009)
* Use serial integer instead of random

* [ci skip] Generate TS types

* cargo fmt

* Return u32
2022-01-05 15:28:17 +01:00
Bogdan-Ștefan Neacșu 2041b03046 Missed takes_value() call 2022-01-04 17:12:41 +01:00
Bogdan-Ștefan Neacşu 0b6adf59ce Feature/fix gateway sign (#1004)
* Include version check in sign command

* Ask for wallet address the same way as mixnode

The reason for this is that the cosmos mnemonic that is asked at
init is for the address that gets rewarded for gateway usage.
Since that address is not necessarly set now and it can take a
default value, we won't be using that to derive the address in the
signing process.
2022-01-04 13:49:24 +01:00
Jędrzej Stuczyński d95df4b286 Feature/implicit runtime (#973)
* Made mixnode runtime implicit

* Ibid for native and socks5 clients
2022-01-04 11:00:48 +00:00
Bogdan-Ștefan Neacşu 4f109169af Fix clippy (#1003) 2022-01-03 14:32:37 +01:00
220 changed files with 4763 additions and 2245 deletions
+1 -1
View File
@@ -1,3 +1,3 @@
unreleased=true
future-release=v0.12.1
future-release=v0.12.0
since-tag=v0.11.0
-23
View File
@@ -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
View File
@@ -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
View File
@@ -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 = [
+2 -1
View File
@@ -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",
+49 -67
View File
@@ -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(
+16 -20
View File
@@ -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 -3
View File
@@ -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;
}
+6 -5
View File
@@ -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()),
}
+2 -3
View File
@@ -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 })
}
}
+49 -67
View File
@@ -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(
+16 -20
View File
@@ -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 -3
View File
@@ -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;
}
+6 -5
View File
@@ -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()),
}
+9 -1
View File
@@ -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);
}
}
}
+21
View File
@@ -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,
+1
View File
@@ -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;
@@ -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(),
)
}
@@ -3,6 +3,7 @@
mod delegation;
pub mod error;
pub mod events;
mod gateway;
pub mod mixnode;
mod msg;
@@ -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)
}
@@ -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;
+1 -1
View File
@@ -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"
+1 -1
View File
@@ -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)
}
+1
View File
@@ -77,6 +77,7 @@ impl Config {
}
}
#[must_use]
pub struct ConfigBuilder(Config);
impl ConfigBuilder {
+1
View File
@@ -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"
+130
View File
@@ -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)
}
}
+62 -27
View File
@@ -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;
+18 -12
View File
@@ -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),
]
}
+20
View File
@@ -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"),
)]
}
+15 -12
View File
@@ -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"),
)]
}
+1 -1
View File
@@ -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
+2 -7
View File
@@ -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();
+2 -1
View File
@@ -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;
+1 -1
View File
@@ -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" }
+1
View File
@@ -9,6 +9,7 @@ pub trait Versioned: Clone {
}
pub trait VersionFilterable<T> {
#[must_use]
fn filter_by_version(&self, expected_version: &str) -> Self;
}
+1 -1
View File
@@ -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};
+4 -2
View File
@@ -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() {
+1 -1
View File
@@ -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};
+58 -76
View File
@@ -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
View File
@@ -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"
+5 -5
View File
@@ -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"
+1 -1
View File
@@ -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;
+13 -3
View File
@@ -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", &[]);
+9 -13
View File
@@ -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())
)
}
+11 -11
View File
@@ -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());
+1 -1
View File
@@ -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.
+3 -1
View File
@@ -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 -5
View File
@@ -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(),
+35 -30
View File
@@ -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, &params));
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)
+3 -8
View File
@@ -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,
};
+141 -33
View File
@@ -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);
}
}
+4 -4
View File
@@ -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),
)?;
}
+15 -26
View File
@@ -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 -3
View File
@@ -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;
+183 -130
View File
@@ -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(&current_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(&current_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),
+1 -1
View File
@@ -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;
+2 -2
View File
@@ -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,
};
+4 -5
View File
@@ -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