Compare commits

..

56 Commits

Author SHA1 Message Date
Gala 5a7e956c93 ind 2023-08-09 17:50:07 +02:00
Gala 3410a2b2e0 another indent 2023-08-09 17:49:16 +02:00
Gala 1349242367 indent fix 2023-08-09 17:47:02 +02:00
Gala 8f812cc610 test indent 2023-08-09 17:44:13 +02:00
Gala 05aa0dbd8e adding custom.css 2023-08-09 17:39:45 +02:00
Gala 5b69b0e7d9 apply nym style on dev-portal docs 2023-08-09 15:06:28 +02:00
Bogdan-Ștefan Neacşu be88a9b277 Remove stale BBC env var (#3720) 2023-08-08 16:33:50 +01:00
Tommy Verrall fce2c704af Merge pull request #3750 from nymtech/release/v1.1.26
Release/v1.1.26
2023-08-08 16:04:32 +02:00
benedetta davico d8a95d3810 Update Cargo.toml 2023-08-08 15:42:05 +02:00
benedetta davico 191aa149df Update Cargo.toml 2023-08-08 15:37:16 +02:00
benedettadavico f4df1a9168 Merge branch 'release/v1.1.26' of https://github.com/nymtech/nym into release/v1.1.26 2023-08-08 15:22:49 +02:00
benedettadavico 62316244d9 Revert package.json changes needed temporary build 2023-08-08 15:16:22 +02:00
benedettadavico a26c6d7a29 Temporary update to fix windows build 2023-08-08 15:16:22 +02:00
benedettadavico 8fda246a3c Update changelog and versions for release v1.1.26 2023-08-08 15:16:22 +02:00
Bogdan-Ștefan Neacșu 5620fd7009 Set sphinx as default packet type 2023-08-08 15:16:22 +02:00
Bogdan-Ștefan Neacşu 122612fa03 Apply fix from feature/ephemera to develop too (#3698) (#3742) 2023-08-08 15:16:22 +02:00
mfahampshire 53db18df2c rephrased intro 2023-08-08 15:14:20 +02:00
Jon Häggblad e00910bcb8 Add geo-aware mixnet topology provider (#3713)
* WIP: initial work

* wupwup

* WIP: experiments

* Move topology provider and requests to own crate

* Make sure we use the new crate everywhere

* Sort Cargo.toml

* Extract out some functions in geo_aware_provider

* rustfmt

* Add CountryGroup type

* Assign unknown as well

* wipwip

* Add command line flag to socks5-client

* Use geo-aware mixnode selection in nym-connect when in medium mode

* rustfmt

* clippy

* Fix nym-connect build

* wasm fix

* Spelling
2023-08-08 15:14:13 +02:00
benedettadavico 0af9b3c6c8 Revert package.json changes needed temporary build 2023-08-08 14:17:55 +02:00
benedettadavico 2d60a9da3f Temporary update to fix windows build 2023-08-08 11:24:08 +02:00
benedettadavico 795efb9f0b Update changelog and versions for release v1.1.26 2023-08-08 11:15:30 +02:00
Tommy Verrall 695d34735c Merge pull request #3748 from nymtech/feature/fix_default_packet_type 2023-08-07 15:36:31 +02:00
Bogdan-Ștefan Neacșu 314d7a7526 Set sphinx as default packet type 2023-08-07 15:52:03 +03:00
Tommy Verrall a86c1a6a60 Merge pull request #3745 from nymtech/feature/explorer-api-build-info
added --version command to explorer-api
2023-08-07 11:40:04 +02:00
Bogdan-Ștefan Neacşu 7ad2865250 Add empty migration to group contract (#3740) 2023-08-07 12:32:20 +03:00
Bogdan-Ștefan Neacşu 49440bf60e Apply fix from feature/ephemera to develop too (#3698) (#3742) 2023-08-07 12:27:31 +03:00
Jędrzej Stuczyński b3b43b56be added --version command to explorer-api 2023-08-07 10:15:15 +01:00
Mark Sinclair 4a23729a6a Add GitHub Action to build Typescript SDK docs 2023-08-04 16:31:21 +01:00
pierre 5711bbd0c1 feat(nc-android): add runtime permission request 2023-08-04 17:15:01 +02:00
pierre 1b1f0293ec fix(nc-android): text colors 2023-08-04 15:36:06 +02:00
Jędrzej Stuczyński 9285aaf487 Generate json schema for all used contracts (#3693)
* removed sealed impl of serde for tx::Fee

* further upgraded cosmwasm to 1.3.0

* wip

* created schema for mixnet contract

* updated return type of 'GetBondedMixnodeDetailsByIdentity' query

* fixed imported version of serde_json_wasm

* updated return type of 'GetFamilyByHead' query

* updated return type of 'GetFamilyByLabel' query

* updated return type of 'GetFamilyMembersByHead' and 'GetFamilyMembersByLabel' queries

* fixed broken tests due to type changes

* added support for GetFamilyMembersByLabel and GetFamilyMembersByHead queries in 'mixnet_query_client'

* moved 'Account' and 'VestingContractError' to common crate

* created schema for vesting contract

* Added documentation for all query messages in the vesting contract

* improved mixnet contract schema by adding documentation to all query types

* feature-locking cw2 import

* created schema for the name service contract

* created schema for the service provider directory contract

* created schema for the coconut bandwidth contract

* created schema for the coconut dkg contract

* created schema for the coconut cw4 group contract

* created schema for the coconut cw3 multisig contract

* fixed missing import and adjusted makefile

* cargo fmt

* clippy

* adjusted contract CI to build with --lib flag

* missing --lib flag in the makefile

* updated lock files

* makefile for generating the schemas

* added github action to check for schema difference

* adding missing step to checkout the repo
2023-08-03 15:09:07 +01:00
Bogdan-Ștefan Neacşu 55bd7f8a61 Fix doubling the data dir in nym-api (#3739) 2023-08-03 17:07:59 +03:00
Jędrzej Stuczyński b66c4cf0bb removed dependency on wasm-timer fork (#3733) 2023-08-03 11:01:03 +01:00
mfahampshire 4696470b19 rephrased intro 2023-08-02 16:26:41 +02:00
Tommy Verrall 5dacf0c8f8 Merge pull request #3730 from nymtech/qa/fix-api-tests
fix config for prod runs on api tests
2023-08-02 15:05:27 +02:00
Tommy Verrall cbafd37102 fix config 2023-08-02 13:22:02 +02:00
Tommy Verrall e537359c73 Merge pull request #3728 from nymtech/qa/fix-api-tests
fix api tests for no blacklisted nodes
2023-08-02 13:21:00 +02:00
Tommy Verrall 2ed3e646be linting and removing unused imports 2023-08-02 13:02:29 +02:00
Tommy Verrall c725ae4e2b remove console 2023-08-02 12:55:46 +02:00
Tommy Verrall 5ab2c738df fix api tests for no blacklisted nodes 2023-08-02 12:54:09 +02:00
pierre cd70b0de75 build(nc-android): disable sentry upload proguard mapping files 2023-08-02 11:18:30 +02:00
Tommy Verrall 6359b38a5d Merge pull request #3660 from nymtech/dependabot/npm_and_yarn/nym-wallet/webdriver/semver-5.7.2
Bump semver from 5.7.1 to 5.7.2 in /nym-wallet/webdriver
2023-08-02 10:36:36 +02:00
dependabot[bot] 00b5a46cbc Bump semver from 5.7.1 to 5.7.2 in /nym-wallet/webdriver
Bumps [semver](https://github.com/npm/node-semver) from 5.7.1 to 5.7.2.
- [Release notes](https://github.com/npm/node-semver/releases)
- [Changelog](https://github.com/npm/node-semver/blob/v5.7.2/CHANGELOG.md)
- [Commits](https://github.com/npm/node-semver/compare/v5.7.1...v5.7.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-01 15:22:00 +00:00
Fouad e97a068bf0 Type documentation for NymSDK (#3701)
* set up development process for docs

* set up development process for docs

* Add local installs for Typedoc on gitignore

* Add Typedoc comments on types.ts file

* add typedoc config file

* update types and add annotations

* Add updates on types file

* add examples + manage sort order for doc items

* update client methods with examples

* add description of NymMixnetClientOptions

* add description of NymMixnetClientOptions

* fix linting

---------

Co-authored-by: Lorexia <alexia.lorenza.martinel@protonmail.com>
2023-08-01 16:21:12 +01:00
Lorexia c7147ebfb2 Add updates to community list projects 2023-08-01 10:50:49 +02:00
mfahampshire a344cda916 removed old wallet address flag again 2023-08-01 10:50:46 +02:00
Lorexia 15a6af49f0 Add updates to community list projects 2023-08-01 10:49:02 +02:00
mfahampshire 97956afdf6 removed old wallet address flag again 2023-08-01 10:48:52 +02:00
Jon Häggblad 7b71775e08 Add geo-aware mixnet topology provider (#3713)
* WIP: initial work

* wupwup

* WIP: experiments

* Move topology provider and requests to own crate

* Make sure we use the new crate everywhere

* Sort Cargo.toml

* Extract out some functions in geo_aware_provider

* rustfmt

* Add CountryGroup type

* Assign unknown as well

* wipwip

* Add command line flag to socks5-client

* Use geo-aware mixnode selection in nym-connect when in medium mode

* rustfmt

* clippy

* Fix nym-connect build

* wasm fix

* Spelling
2023-07-28 14:48:33 +02:00
pierre 5fbccc3406 build(nc-android): moving build config to kotlin 2023-07-27 19:11:33 +02:00
pierre ac8afe133f fix(nc-desktop): typo 2023-07-27 15:53:55 +02:00
Bogdan-Ștefan Neacşu 19736b1204 Fix develop after bad automerge (#3712) 2023-07-27 13:25:34 +03:00
pierre 6e5f6bf0df ci: fix release strapi actions 2023-07-27 11:42:42 +02:00
Jędrzej Stuczyński 67435e9cdf Feature/simplify cli parsing (#3699)
* added a global flag to disable the printed out banner inside tty

* added a 'build-info' command to our binaries

* added binary name to BinaryBuildInformation

* clippy
2023-07-27 10:20:07 +01:00
Bogdan-Ștefan Neacşu a47899aa77 Apply fix from feature/ephemera to develop too (#3698) 2023-07-27 12:18:08 +03:00
pierre 44fa52a7a7 ci: fix release strapi actions 2023-07-27 11:08:24 +02:00
433 changed files with 44552 additions and 5411 deletions
@@ -0,0 +1,25 @@
name: Check Contract Schema
on:
push:
paths:
- 'contracts/**'
- 'common/**'
pull_request:
paths:
- 'contracts/**'
- 'common/**'
jobs:
check-schema:
name: Generate and check schema
runs-on: ubuntu-latest
steps:
- name: Check out repository code
uses: actions/checkout@v2
- name: Generate the schema
run: make contract-schema
- name: Check for diff
run: git diff --exit-code
+3 -3
View File
@@ -48,12 +48,12 @@ jobs:
RUSTFLAGS: '-C link-arg=-s'
with:
command: build
args: --manifest-path contracts/Cargo.toml --workspace --target wasm32-unknown-unknown
args: --manifest-path contracts/Cargo.toml --workspace --lib --target wasm32-unknown-unknown
- uses: actions-rs/cargo@v1
with:
command: test
args: --manifest-path contracts/Cargo.toml
args: --lib --manifest-path contracts/Cargo.toml
- uses: actions-rs/cargo@v1
with:
@@ -64,4 +64,4 @@ jobs:
if: ${{ matrix.rust != 'nightly' }}
with:
command: clippy
args: --manifest-path contracts/Cargo.toml --workspace --all-targets -- -D warnings
args: --lib --manifest-path contracts/Cargo.toml --workspace --all-targets -- -D warnings
+50
View File
@@ -0,0 +1,50 @@
name: Typescript SDK docs
on:
push:
paths:
- "sdk/typescript/**"
pull_request:
paths:
- "sdk/typescript/**"
jobs:
build:
runs-on: custom-runner-linux
steps:
- uses: actions/checkout@v2
- name: Install rsync
run: sudo apt-get install rsync
continue-on-error: true
- uses: rlespinasse/github-slug-action@v3.x
- uses: actions/setup-node@v3
with:
node-version: 18
- name: Install Rust stable
uses: actions-rs/toolchain@v1
with:
toolchain: stable
- name: Setup yarn
run: npm install -g yarn
- name: Install
run: yarn
- name: Matrix - Node Install
run: npm install
working-directory: .github/workflows/support-files
- name: Matrix - Send Notification
env:
NYM_NOTIFICATION_KIND: ts-packages
NYM_PROJECT_NAME: "ts-packages"
NYM_CI_WWW_BASE: "${{ secrets.NYM_CI_WWW_BASE }}"
NYM_CI_WWW_LOCATION: "ts-${{ env.GITHUB_REF_SLUG }}"
GIT_COMMIT_MESSAGE: "${{ github.event.head_commit.message }}"
GIT_BRANCH: "${GITHUB_REF##*/}"
IS_SUCCESS: "${{ job.status == 'success' }}"
MATRIX_SERVER: "${{ secrets.MATRIX_SERVER }}"
MATRIX_ROOM: "${{ secrets.MATRIX_ROOM }}"
MATRIX_USER_ID: "${{ secrets.MATRIX_USER_ID }}"
MATRIX_TOKEN: "${{ secrets.MATRIX_TOKEN }}"
MATRIX_DEVICE_ID: "${{ secrets.MATRIX_DEVICE_ID }}"
uses: docker://keybaseio/client:stable-node
with:
args: .github/workflows/support-files/notifications/entry_point.sh
+22
View File
@@ -4,6 +4,28 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
## [Unreleased]
## [v1.1.24] (2023-08-08)
- Latency based gateway selection is serial and slow ([#3710])
- Network-requester: strip comments from allow lists ([#3625])
- Remove (or start maintaining) `upgrade` commands from all binaries ([#3600])
- Set sphinx as default packet type ([#3748])
- Apply fix from feature/ephemera to develop too (#3698) ([#3742])
- Feature/coco demos ([#3732])
- Add updates to community list projects ([#3722])
- Add geo-aware mixnet topology provider ([#3713])
- Add updates to community list projects ([#3711])
[#3710]: https://github.com/nymtech/nym/issues/3710
[#3625]: https://github.com/nymtech/nym/issues/3625
[#3600]: https://github.com/nymtech/nym/issues/3600
[#3748]: https://github.com/nymtech/nym/pull/3748
[#3742]: https://github.com/nymtech/nym/pull/3742
[#3732]: https://github.com/nymtech/nym/pull/3732
[#3722]: https://github.com/nymtech/nym/pull/3722
[#3713]: https://github.com/nymtech/nym/pull/3713
[#3711]: https://github.com/nymtech/nym/pull/3711
## [v1.1.23] (2023-07-04)
- nym-cli: add client identity key signing support ([#3576])
Generated
+96 -122
View File
@@ -541,6 +541,12 @@ dependencies = [
"zeroize",
]
[[package]]
name = "bnum"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "845141a4fade3f790628b7daaaa298a25b204fb28907eb54febe5142db6ce653"
[[package]]
name = "bs58"
version = "0.4.0"
@@ -969,9 +975,9 @@ dependencies = [
[[package]]
name = "cosmwasm-crypto"
version = "1.2.5"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75836a10cb9654c54e77ee56da94d592923092a10b369cdb0dbd56acefc16340"
checksum = "0d076a08ec01ed23c4396aca98ec73a38fa1fee5f310465add52b4108181c7a8"
dependencies = [
"digest 0.10.7",
"ed25519-zebra",
@@ -982,18 +988,18 @@ dependencies = [
[[package]]
name = "cosmwasm-derive"
version = "1.2.5"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1c9f7f0e51bfc7295f7b2664fe8513c966428642aa765dad8a74acdab5e0c773"
checksum = "dec361f3c09d7b41221948fc17be9b3c96cb58e55a02f82da36f888a651f2584"
dependencies = [
"syn 1.0.109",
]
[[package]]
name = "cosmwasm-schema"
version = "1.2.5"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f00b363610218eea83f24bbab09e1a7c3920b79f068334fdfcc62f6129ef9fc"
checksum = "bb6b2fb76758ef59cddc77f2e2ae91c22f77da49037e9f182e9c2833f0e959b1"
dependencies = [
"cosmwasm-schema-derive",
"schemars",
@@ -1004,9 +1010,9 @@ dependencies = [
[[package]]
name = "cosmwasm-schema-derive"
version = "1.2.5"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae38f909b2822d32b275c9e2db9728497aa33ffe67dd463bc67c6a3b7092785c"
checksum = "2bfa39422f0d9f1c9a6fd3711573258495314dfa3aae738ea825ecd9964bc659"
dependencies = [
"proc-macro2",
"quote",
@@ -1015,11 +1021,12 @@ dependencies = [
[[package]]
name = "cosmwasm-std"
version = "1.2.5"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a49b85345e811c8e80ec55d0d091e4fcb4f00f97ab058f9be5f614c444a730cb"
checksum = "1f6dc2ee23313add5ecacc3ccac217b9967ad9d2d11bd56e5da6aa65a9da6138"
dependencies = [
"base64 0.13.1",
"bnum",
"cosmwasm-crypto",
"cosmwasm-derive",
"derivative",
@@ -1027,10 +1034,9 @@ dependencies = [
"hex",
"schemars",
"serde",
"serde-json-wasm 0.5.1",
"serde-json-wasm",
"sha2 0.10.6",
"thiserror",
"uint",
]
[[package]]
@@ -1203,12 +1209,6 @@ dependencies = [
"winapi",
]
[[package]]
name = "crunchy"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
[[package]]
name = "crypto-bigint"
version = "0.4.9"
@@ -1370,9 +1370,9 @@ dependencies = [
[[package]]
name = "cw-controllers"
version = "1.0.1"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91440ce8ec4f0642798bc8c8cb6b9b53c1926c6dadaf0eed267a5145cd529071"
checksum = "d5d8edce4b78785f36413f67387e4be7d0cb7d032b5d4164bcc024f9c3f3f2ea"
dependencies = [
"cosmwasm-schema",
"cosmwasm-std",
@@ -1385,9 +1385,9 @@ dependencies = [
[[package]]
name = "cw-storage-plus"
version = "1.0.1"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "053a5083c258acd68386734f428a5a171b29f7d733151ae83090c6fcc9417ffa"
checksum = "3f0e92a069d62067f3472c62e30adedb4cab1754725c0f2a682b3128d2bf3c79"
dependencies = [
"cosmwasm-std",
"schemars",
@@ -1411,22 +1411,23 @@ dependencies = [
[[package]]
name = "cw2"
version = "1.0.1"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8fb70cee2cf0b4a8ff7253e6bc6647107905e8eb37208f87d54f67810faa62f8"
checksum = "29ac2dc7a55ad64173ca1e0a46697c31b7a5c51342f55a1e84a724da4eb99908"
dependencies = [
"cosmwasm-schema",
"cosmwasm-std",
"cw-storage-plus",
"schemars",
"serde",
"thiserror",
]
[[package]]
name = "cw20"
version = "1.0.1"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91666da6c7b40c8dd5ff94df655a28114efc10c79b70b4d06f13c31e37d60609"
checksum = "011c45920f8200bd5d32d4fe52502506f64f2f75651ab408054d4cfc75ca3a9b"
dependencies = [
"cosmwasm-schema",
"cosmwasm-std",
@@ -1437,9 +1438,9 @@ dependencies = [
[[package]]
name = "cw3"
version = "1.0.1"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2fe0b587008aa221cd2a2579a21990a28c4347dc53ad43167c68ad765f5b6efa"
checksum = "171af3d9127de6805a7dd819fb070c7d2f6c3ea85f4193f42cef259f0a7f33d5"
dependencies = [
"cosmwasm-schema",
"cosmwasm-std",
@@ -1452,9 +1453,9 @@ dependencies = [
[[package]]
name = "cw4"
version = "1.0.1"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c236e0bae02ce97e89235a681dd0e07d099524b369f1ef908d704db3e6b049b"
checksum = "a398696307efadaaa2d0850076f865fa706c959d493cb4203314f72be6b77a64"
dependencies = [
"cosmwasm-schema",
"cosmwasm-std",
@@ -1895,7 +1896,7 @@ checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0"
[[package]]
name = "explorer-api"
version = "1.1.23"
version = "1.1.24"
dependencies = [
"chrono",
"clap 4.2.7",
@@ -1903,10 +1904,12 @@ dependencies = [
"humantime-serde",
"isocountry",
"itertools",
"lazy_static",
"log",
"maxminddb",
"nym-bin-common",
"nym-contracts-common",
"nym-explorer-api-requests",
"nym-mixnet-contract-common",
"nym-network-defaults",
"nym-task",
@@ -2924,9 +2927,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
dependencies = [
"cfg-if",
"js-sys",
"wasm-bindgen",
"web-sys",
]
[[package]]
@@ -3530,7 +3530,7 @@ dependencies = [
[[package]]
name = "nym-api"
version = "1.1.24"
version = "1.1.25"
dependencies = [
"anyhow",
"async-trait",
@@ -3667,7 +3667,7 @@ dependencies = [
[[package]]
name = "nym-cli"
version = "1.1.23"
version = "1.1.24"
dependencies = [
"anyhow",
"base64 0.13.1",
@@ -3733,7 +3733,7 @@ dependencies = [
[[package]]
name = "nym-client"
version = "1.1.23"
version = "1.1.24"
dependencies = [
"clap 4.2.7",
"dirs 4.0.0",
@@ -3783,6 +3783,7 @@ dependencies = [
"nym-config",
"nym-credential-storage",
"nym-crypto",
"nym-explorer-api-requests",
"nym-gateway-client",
"nym-gateway-requests",
"nym-network-defaults",
@@ -3793,6 +3794,7 @@ dependencies = [
"nym-topology",
"nym-validator-client",
"rand 0.7.3",
"reqwest",
"serde",
"serde_json",
"sha2 0.10.6",
@@ -3808,8 +3810,8 @@ dependencies = [
"url",
"wasm-bindgen",
"wasm-bindgen-futures",
"wasm-timer",
"wasm-utils",
"wasmtimer",
"zeroize",
]
@@ -3849,22 +3851,21 @@ dependencies = [
name = "nym-coconut-bandwidth-contract-common"
version = "0.1.0"
dependencies = [
"cosmwasm-schema",
"cosmwasm-std",
"cw2",
"nym-multisig-contract-common",
"schemars",
"serde",
]
[[package]]
name = "nym-coconut-dkg-common"
version = "0.1.0"
dependencies = [
"cosmwasm-schema",
"cosmwasm-std",
"cw-utils",
"nym-contracts-common",
"nym-multisig-contract-common",
"schemars",
"serde",
]
[[package]]
@@ -3896,6 +3897,7 @@ name = "nym-contracts-common"
version = "0.5.0"
dependencies = [
"bs58 0.4.0",
"cosmwasm-schema",
"cosmwasm-std",
"schemars",
"serde",
@@ -4005,9 +4007,21 @@ dependencies = [
"syn 1.0.109",
]
[[package]]
name = "nym-explorer-api-requests"
version = "0.1.0"
dependencies = [
"nym-contracts-common",
"nym-mixnet-contract-common",
"nym-validator-client",
"schemars",
"serde",
"ts-rs",
]
[[package]]
name = "nym-gateway"
version = "1.1.23"
version = "1.1.24"
dependencies = [
"anyhow",
"async-trait",
@@ -4082,8 +4096,8 @@ dependencies = [
"url",
"wasm-bindgen",
"wasm-bindgen-futures",
"wasm-timer",
"wasm-utils",
"wasmtimer",
]
[[package]]
@@ -4144,14 +4158,16 @@ name = "nym-mixnet-contract-common"
version = "0.6.0"
dependencies = [
"bs58 0.4.0",
"cosmwasm-schema",
"cosmwasm-std",
"cw2",
"humantime-serde",
"log",
"nym-contracts-common",
"rand_chacha 0.3.1",
"schemars",
"serde",
"serde-json-wasm 0.4.1",
"serde-json-wasm",
"serde_repr",
"thiserror",
"time 0.3.21",
@@ -4160,7 +4176,7 @@ dependencies = [
[[package]]
name = "nym-mixnode"
version = "1.1.24"
version = "1.1.25"
dependencies = [
"anyhow",
"bs58 0.4.0",
@@ -4252,11 +4268,12 @@ dependencies = [
name = "nym-name-service-common"
version = "0.1.0"
dependencies = [
"cosmwasm-schema",
"cosmwasm-std",
"cw-controllers",
"cw-utils",
"cw2",
"nym-contracts-common",
"schemars",
"serde",
"thiserror",
]
@@ -4276,7 +4293,7 @@ dependencies = [
[[package]]
name = "nym-network-requester"
version = "1.1.23"
version = "1.1.24"
dependencies = [
"anyhow",
"async-file-watcher",
@@ -4323,7 +4340,7 @@ dependencies = [
[[package]]
name = "nym-network-statistics"
version = "1.1.23"
version = "1.1.24"
dependencies = [
"dirs 4.0.0",
"log",
@@ -4361,12 +4378,10 @@ dependencies = [
name = "nym-nonexhaustive-delayqueue"
version = "0.1.0"
dependencies = [
"futures-core",
"slab",
"tokio",
"tokio-stream",
"tokio-util",
"wasm-timer",
"wasmtimer",
]
[[package]]
@@ -4454,12 +4469,12 @@ dependencies = [
name = "nym-service-provider-directory-common"
version = "0.1.0"
dependencies = [
"cosmwasm-schema",
"cosmwasm-std",
"cw-controllers",
"cw-utils",
"cw2",
"nym-contracts-common",
"schemars",
"serde",
"thiserror",
]
@@ -4482,7 +4497,7 @@ dependencies = [
[[package]]
name = "nym-socks5-client"
version = "1.1.23"
version = "1.1.24"
dependencies = [
"clap 4.2.7",
"lazy_static",
@@ -4520,7 +4535,9 @@ dependencies = [
"nym-bandwidth-controller",
"nym-client-core",
"nym-config",
"nym-contracts-common",
"nym-credential-storage",
"nym-mixnet-contract-common",
"nym-network-defaults",
"nym-service-providers-common",
"nym-socks5-proxy-helpers",
@@ -4530,10 +4547,13 @@ dependencies = [
"nym-validator-client",
"pin-project",
"rand 0.7.3",
"reqwest",
"schemars",
"serde",
"tap",
"thiserror",
"tokio",
"url",
]
[[package]]
@@ -4809,7 +4829,6 @@ dependencies = [
"nym-config",
"nym-mixnet-contract-common",
"nym-validator-client",
"nym-vesting-contract",
"nym-vesting-contract-common",
"reqwest",
"schemars",
@@ -4851,7 +4870,6 @@ dependencies = [
"nym-name-service-common",
"nym-network-defaults",
"nym-service-provider-directory-common",
"nym-vesting-contract",
"nym-vesting-contract-common",
"openssl",
"prost",
@@ -4867,33 +4885,17 @@ dependencies = [
"zeroize",
]
[[package]]
name = "nym-vesting-contract"
version = "1.4.0"
dependencies = [
"cosmwasm-derive",
"cosmwasm-std",
"cw-storage-plus",
"cw2",
"nym-contracts-common",
"nym-mixnet-contract-common",
"nym-vesting-contract-common",
"schemars",
"semver 1.0.17",
"serde",
"thiserror",
"vergen",
]
[[package]]
name = "nym-vesting-contract-common"
version = "0.7.0"
dependencies = [
"cosmwasm-schema",
"cosmwasm-std",
"cw2",
"nym-contracts-common",
"nym-mixnet-contract-common",
"schemars",
"serde",
"thiserror",
"ts-rs",
]
@@ -4909,7 +4911,6 @@ dependencies = [
"nym-network-defaults",
"nym-types",
"nym-validator-client",
"nym-vesting-contract",
"nym-vesting-contract-common",
"serde",
"serde_json",
@@ -6436,18 +6437,9 @@ dependencies = [
[[package]]
name = "serde-json-wasm"
version = "0.4.1"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "479b4dbc401ca13ee8ce902851b834893251404c4f3c65370a49e047a6be09a5"
dependencies = [
"serde",
]
[[package]]
name = "serde-json-wasm"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "16a62a1fad1e1828b24acac8f2b468971dade7b8c3c2e672bcadefefb1f8c137"
checksum = "a15bee9b04dd165c3f4e142628982ddde884c2022a89e8ddf99c4829bf2c3a58"
dependencies = [
"serde",
]
@@ -6985,12 +6977,6 @@ dependencies = [
"loom",
]
[[package]]
name = "static_assertions"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
[[package]]
name = "stringprep"
version = "0.1.2"
@@ -7202,9 +7188,9 @@ dependencies = [
[[package]]
name = "tendermint-rpc"
version = "0.32.0"
version = "0.32.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd2cc789170db5a35d4e0bb2490035c03ef96df08f119bee25fd8dab5a09aa25"
checksum = "d119d83a130537fc4a98c3c9eb6899ebe857fea4860400a61675bfb5f0b35129"
dependencies = [
"async-trait",
"bytes",
@@ -7823,18 +7809,6 @@ version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e79c4d996edb816c91e4308506774452e55e95c3c9de07b6729e17e15a5ef81"
[[package]]
name = "uint"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52"
dependencies = [
"byteorder",
"crunchy",
"hex",
"static_assertions",
]
[[package]]
name = "uncased"
version = "0.9.9"
@@ -8131,20 +8105,6 @@ version = "0.2.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f"
[[package]]
name = "wasm-timer"
version = "0.2.5"
source = "git+https://github.com/mmsinclair/wasm-timer?rev=b9d1a54ad514c2f230a026afe0dde341e98cd7b6#b9d1a54ad514c2f230a026afe0dde341e98cd7b6"
dependencies = [
"futures",
"js-sys",
"parking_lot 0.11.2",
"pin-utils",
"wasm-bindgen",
"wasm-bindgen-futures",
"web-sys",
]
[[package]]
name = "wasm-utils"
version = "0.1.0"
@@ -8163,6 +8123,20 @@ dependencies = [
"web-sys",
]
[[package]]
name = "wasmtimer"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f656cd8858a5164932d8a90f936700860976ec21eb00e0fe2aa8cab13f6b4cf"
dependencies = [
"futures",
"js-sys",
"parking_lot 0.12.1",
"pin-utils",
"slab",
"wasm-bindgen",
]
[[package]]
name = "web-sys"
version = "0.3.60"
+19 -12
View File
@@ -74,6 +74,7 @@ members = [
"common/types",
"common/wasm-utils",
"explorer-api",
"explorer-api/explorer-api-requests",
"gateway",
"gateway/gateway-requests",
"integrations/bity",
@@ -117,32 +118,38 @@ anyhow = "1.0.71"
async-trait = "0.1.64"
bip39 = { version = "2.0.0", features = ["zeroize"] }
cfg-if = "1.0.0"
cosmwasm-derive = "=1.2.5"
cosmwasm-schema = "=1.2.5"
cosmwasm-std = "=1.2.5"
cosmwasm-storage = "=1.2.5"
cosmwasm-derive = "=1.3.0"
cosmwasm-schema = "=1.3.0"
cosmwasm-std = "=1.3.0"
# use 0.5.0 as that's the version used by cosmwasm-std 1.3.0
# (and ideally we don't want to pull the same dependency twice)
serde-json-wasm = "=0.5.0"
cosmwasm-storage = "=1.3.0"
cosmrs = "=0.14.0"
# same version as used by cosmrs
tendermint-rpc = "=0.32"
cw-utils = "=1.0.1"
cw-storage-plus = "=1.0.1"
cw2 = { version = "=1.0.1" }
cw3 = { version = "=1.0.1" }
cw3-fixed-multisig = { version = "=1.0.1" }
cw4 = { version = "=1.0.1" }
cw-controllers = { version = "=1.0.1" }
cw-storage-plus = "=1.1.0"
cw2 = { version = "=1.1.0" }
cw3 = { version = "=1.1.0" }
cw4 = { version = "=1.1.0" }
cw-controllers = { version = "=1.1.0" }
dotenvy = "0.15.6"
generic-array = "0.14.7"
k256 = "0.13"
getrandom = "0.2.10"
k256 = "0.13"
lazy_static = "1.4.0"
log = "0.4"
once_cell = "1.7.2"
rand = "0.8.5"
reqwest = "0.11.18"
serde = "1.0.152"
serde_json = "1.0.91"
tap = "1.0.1"
tendermint-rpc = "0.32" # same version as used by cosmrs
thiserror = "1.0.38"
tokio = "1.24.1"
url = "2.2"
zeroize = "1.6.0"
# wasm-related dependencies
wasmtimer = "0.2.0"
+5 -2
View File
@@ -73,7 +73,7 @@ endef
# Generate targets for the various cargo workspaces
$(eval $(call add_cargo_workspace,main,.))
$(eval $(call add_cargo_workspace,contracts,contracts,--target wasm32-unknown-unknown))
$(eval $(call add_cargo_workspace,contracts,contracts,--lib --target wasm32-unknown-unknown))
$(eval $(call add_cargo_workspace,wasm-client,clients/webassembly,--target wasm32-unknown-unknown))
$(eval $(call add_cargo_workspace,wallet,nym-wallet,))
$(eval $(call add_cargo_workspace,connect,nym-connect/desktop))
@@ -104,7 +104,7 @@ NAME_SERVICE_CONTRACT=$(CONTRACTS_OUT_DIR)/nym_name_service.wasm
wasm: wasm-build wasm-opt
wasm-build:
RUSTFLAGS='-C link-arg=-s' cargo build --manifest-path contracts/Cargo.toml --release --target wasm32-unknown-unknown
RUSTFLAGS='-C link-arg=-s' cargo build --lib --manifest-path contracts/Cargo.toml --release --target wasm32-unknown-unknown
wasm-opt:
wasm-opt --disable-sign-ext -Os $(VESTING_CONTRACT) -o $(VESTING_CONTRACT)
@@ -112,6 +112,9 @@ wasm-opt:
wasm-opt --disable-sign-ext -Os $(SERVICE_PROVIDER_DIRECTORY_CONTRACT) -o $(SERVICE_PROVIDER_DIRECTORY_CONTRACT)
wasm-opt --disable-sign-ext -Os $(NAME_SERVICE_CONTRACT) -o $(NAME_SERVICE_CONTRACT)
contract-schema:
$(MAKE) -C contracts schema
# -----------------------------------------------------------------------------
# Misc
# -----------------------------------------------------------------------------
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "nym-client"
version = "1.1.23"
version = "1.1.24"
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jędrzej Stuczyński <andrew@nymtech.net>"]
description = "Implementation of the Nym Client"
edition = "2021"
+16
View File
@@ -0,0 +1,16 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use clap::Args;
use nym_bin_common::bin_info_owned;
use nym_bin_common::output_format::OutputFormat;
#[derive(Args)]
pub(crate) struct BuildInfo {
#[clap(short, long, default_value_t = OutputFormat::default())]
output: OutputFormat,
}
pub(crate) fn execute(args: BuildInfo) {
println!("{}", args.output.format(&bin_info_owned!()))
}
+15 -7
View File
@@ -10,7 +10,7 @@ use clap::CommandFactory;
use clap::{Parser, Subcommand};
use lazy_static::lazy_static;
use log::{error, info};
use nym_bin_common::build_information::BinaryBuildInformation;
use nym_bin_common::bin_info;
use nym_bin_common::completions::{fig_generate, ArgShell};
use nym_client_core::client::base_client::storage::gateway_details::{
OnDiskGatewayDetails, PersistedGatewayDetails,
@@ -22,12 +22,12 @@ use nym_config::OptionalSet;
use std::error::Error;
use std::net::IpAddr;
pub(crate) mod build_info;
pub(crate) mod init;
pub(crate) mod run;
lazy_static! {
pub static ref PRETTY_BUILD_INFORMATION: String =
BinaryBuildInformation::new(env!("CARGO_PKG_VERSION")).pretty_print();
pub static ref PRETTY_BUILD_INFORMATION: String = bin_info!().pretty_print();
}
// Helper for passing LONG_VERSION to clap
@@ -42,6 +42,10 @@ pub(crate) struct Cli {
#[clap(short, long)]
pub(crate) config_env_file: Option<std::path::PathBuf>,
/// Flag used for disabling the printed banner in tty.
#[clap(long)]
pub(crate) no_banner: bool,
#[clap(subcommand)]
command: Commands,
}
@@ -54,6 +58,9 @@ pub(crate) enum Commands {
/// Run the Nym client with provided configuration client optionally overriding set parameters
Run(run::Run),
/// Show build information of this binary
BuildInfo(build_info::BuildInfo),
/// Generate shell completions
Completions(ArgShell),
@@ -73,12 +80,13 @@ pub(crate) struct OverrideConfig {
enabled_credentials_mode: Option<bool>,
}
pub(crate) async fn execute(args: &Cli) -> Result<(), Box<dyn Error + Send + Sync>> {
pub(crate) async fn execute(args: Cli) -> Result<(), Box<dyn Error + Send + Sync>> {
let bin_name = "nym-native-client";
match &args.command {
Commands::Init(m) => init::execute(m).await?,
Commands::Run(m) => run::execute(m).await?,
match args.command {
Commands::Init(m) => init::execute(&m).await?,
Commands::Run(m) => run::execute(&m).await?,
Commands::BuildInfo(m) => build_info::execute(m),
Commands::Completions(s) => s.generate(&mut Cli::command(), bin_name),
Commands::GenerateFigSpec => fig_generate(&mut Cli::command(), bin_name),
}
+7 -4
View File
@@ -14,10 +14,13 @@ pub mod websocket;
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
setup_logging();
maybe_print_banner(crate_name!(), crate_version!());
let args = commands::Cli::parse();
setup_env(args.config_env_file.as_ref());
commands::execute(&args).await
if !args.no_banner {
maybe_print_banner(crate_name!(), crate_version!());
}
setup_logging();
commands::execute(args).await
}
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "nym-socks5-client"
version = "1.1.23"
version = "1.1.24"
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"]
description = "A SOCKS5 localhost proxy that converts incoming messages to Sphinx and sends them to a Nym address"
edition = "2021"
+16
View File
@@ -0,0 +1,16 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use clap::Args;
use nym_bin_common::bin_info_owned;
use nym_bin_common::output_format::OutputFormat;
#[derive(Args)]
pub(crate) struct BuildInfo {
#[clap(short, long, default_value_t = OutputFormat::default())]
output: OutputFormat,
}
pub(crate) fn execute(args: BuildInfo) {
println!("{}", args.output.format(&bin_info_owned!()))
}
+1
View File
@@ -94,6 +94,7 @@ impl From<Init> for OverrideConfig {
use_anonymous_replies: init_config.use_reply_surbs,
fastmode: init_config.fastmode,
no_cover: init_config.no_cover,
geo_routing: None,
medium_toggle: false,
nyxd_urls: init_config.nyxd_urls,
enabled_credentials_mode: init_config.enabled_credentials_mode,
+29 -8
View File
@@ -10,24 +10,25 @@ use clap::CommandFactory;
use clap::{Parser, Subcommand};
use lazy_static::lazy_static;
use log::{error, info};
use nym_bin_common::build_information::BinaryBuildInformation;
use nym_bin_common::bin_info;
use nym_bin_common::completions::{fig_generate, ArgShell};
use nym_client_core::client::base_client::storage::gateway_details::{
OnDiskGatewayDetails, PersistedGatewayDetails,
};
use nym_client_core::client::key_manager::persistence::OnDiskKeys;
use nym_client_core::config::GatewayEndpointConfig;
use nym_client_core::client::topology_control::geo_aware_provider::CountryGroup;
use nym_client_core::config::{GatewayEndpointConfig, TopologyStructure};
use nym_client_core::error::ClientCoreError;
use nym_config::OptionalSet;
use nym_sphinx::params::{PacketSize, PacketType};
use std::error::Error;
pub(crate) mod build_info;
pub mod init;
pub(crate) mod run;
lazy_static! {
pub static ref PRETTY_BUILD_INFORMATION: String =
BinaryBuildInformation::new(env!("CARGO_PKG_VERSION")).pretty_print();
pub static ref PRETTY_BUILD_INFORMATION: String = bin_info!().pretty_print();
}
// Helper for passing LONG_VERSION to clap
@@ -42,6 +43,10 @@ pub(crate) struct Cli {
#[clap(short, long)]
pub(crate) config_env_file: Option<std::path::PathBuf>,
/// Flag used for disabling the printed banner in tty.
#[clap(long)]
pub(crate) no_banner: bool,
#[clap(subcommand)]
command: Commands,
}
@@ -54,6 +59,9 @@ pub(crate) enum Commands {
/// Run the Nym client with provided configuration client optionally overriding set parameters
Run(run::Run),
/// Show build information of this binary
BuildInfo(build_info::BuildInfo),
/// Generate shell completions
Completions(ArgShell),
@@ -68,18 +76,20 @@ pub(crate) struct OverrideConfig {
use_anonymous_replies: Option<bool>,
fastmode: bool,
no_cover: bool,
geo_routing: Option<CountryGroup>,
medium_toggle: bool,
nyxd_urls: Option<Vec<url::Url>>,
enabled_credentials_mode: Option<bool>,
outfox: bool,
}
pub(crate) async fn execute(args: &Cli) -> Result<(), Box<dyn Error + Send + Sync>> {
pub(crate) async fn execute(args: Cli) -> Result<(), Box<dyn Error + Send + Sync>> {
let bin_name = "nym-socks5-client";
match &args.command {
Commands::Init(m) => init::execute(m).await?,
Commands::Run(m) => run::execute(m).await?,
match args.command {
Commands::Init(m) => init::execute(&m).await?,
Commands::Run(m) => run::execute(&m).await?,
Commands::BuildInfo(m) => build_info::execute(m),
Commands::Completions(s) => s.generate(&mut Cli::command(), bin_name),
Commands::GenerateFigSpec => fig_generate(&mut Cli::command(), bin_name),
}
@@ -91,6 +101,13 @@ pub(crate) fn override_config(config: Config, args: OverrideConfig) -> Config {
let secondary_packet_size = args.medium_toggle.then_some(PacketSize::ExtendedPacket16);
let no_per_hop_delays = args.medium_toggle;
let topology_structure = if args.medium_toggle || args.geo_routing.is_some() {
// TODO: rethink the default group. I just picked one for now.
TopologyStructure::GeoAware(args.geo_routing.unwrap_or(CountryGroup::Europe))
} else {
TopologyStructure::default()
};
let packet_type = if args.outfox {
PacketType::Outfox
} else {
@@ -114,6 +131,10 @@ pub(crate) fn override_config(config: Config, args: OverrideConfig) -> Config {
// NOTE: see comment above about the order of the other disble cover traffic config
.with_base(BaseClientConfig::with_disabled_cover_traffic, args.no_cover)
.with_base(BaseClientConfig::with_packet_type, packet_type)
.with_base(
BaseClientConfig::with_topology_structure,
topology_structure,
)
.with_optional(Config::with_anonymous_replies, args.use_anonymous_replies)
.with_optional(Config::with_port, args.port)
.with_optional_base_custom_env(
+13
View File
@@ -11,6 +11,7 @@ use clap::Args;
use log::*;
use nym_bin_common::version_checker::is_minor_version_compatible;
use nym_client_core::client::base_client::storage::OnDiskPersistent;
use nym_client_core::client::topology_control::geo_aware_provider::CountryGroup;
use nym_crypto::asymmetric::identity;
use nym_socks5_client_core::NymClient;
use nym_sphinx::addressing::clients::Recipient;
@@ -60,6 +61,10 @@ pub(crate) struct Run {
#[clap(long, hide = true)]
no_cover: bool,
/// Set geo-aware mixnode selection when sending mixnet traffic, for experiments only.
#[clap(long, hide = true, value_parser = validate_country_group)]
geo_routing: Option<CountryGroup>,
/// Enable medium mixnet traffic, for experiments only.
/// This includes things like disabling cover traffic, no per hop delays, etc.
#[clap(long, hide = true)]
@@ -82,6 +87,7 @@ impl From<Run> for OverrideConfig {
use_anonymous_replies: run_config.use_anonymous_replies,
fastmode: run_config.fastmode,
no_cover: run_config.no_cover,
geo_routing: run_config.geo_routing,
medium_toggle: run_config.medium_toggle,
nyxd_urls: run_config.nyxd_urls,
enabled_credentials_mode: run_config.enabled_credentials_mode,
@@ -90,6 +96,13 @@ impl From<Run> for OverrideConfig {
}
}
fn validate_country_group(s: &str) -> Result<CountryGroup, String> {
match s.parse() {
Ok(cg) => Ok(cg),
Err(_) => Err(format!("failed to parse country group: {}", s)),
}
}
// this only checks compatibility between config the binary. It does not take into consideration
// network version. It might do so in the future.
fn version_check(cfg: &Config) -> bool {
+7 -4
View File
@@ -13,10 +13,13 @@ pub mod error;
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
setup_logging();
maybe_print_banner(crate_name!(), crate_version!());
let args = commands::Cli::parse();
setup_env(args.config_env_file.as_ref());
commands::execute(&args).await
if !args.no_banner {
maybe_print_banner(crate_name!(), crate_version!());
}
setup_logging();
commands::execute(args).await
}
+80 -107
View File
@@ -378,6 +378,12 @@ dependencies = [
"zeroize",
]
[[package]]
name = "bnum"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "845141a4fade3f790628b7daaaa298a25b204fb28907eb54febe5142db6ce653"
[[package]]
name = "bs58"
version = "0.4.0"
@@ -658,18 +664,18 @@ dependencies = [
[[package]]
name = "cosmwasm-derive"
version = "1.2.5"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1c9f7f0e51bfc7295f7b2664fe8513c966428642aa765dad8a74acdab5e0c773"
checksum = "dec361f3c09d7b41221948fc17be9b3c96cb58e55a02f82da36f888a651f2584"
dependencies = [
"syn 1.0.109",
]
[[package]]
name = "cosmwasm-schema"
version = "1.2.5"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f00b363610218eea83f24bbab09e1a7c3920b79f068334fdfcc62f6129ef9fc"
checksum = "bb6b2fb76758ef59cddc77f2e2ae91c22f77da49037e9f182e9c2833f0e959b1"
dependencies = [
"cosmwasm-schema-derive",
"schemars",
@@ -680,9 +686,9 @@ dependencies = [
[[package]]
name = "cosmwasm-schema-derive"
version = "1.2.5"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae38f909b2822d32b275c9e2db9728497aa33ffe67dd463bc67c6a3b7092785c"
checksum = "2bfa39422f0d9f1c9a6fd3711573258495314dfa3aae738ea825ecd9964bc659"
dependencies = [
"proc-macro2",
"quote",
@@ -691,11 +697,12 @@ dependencies = [
[[package]]
name = "cosmwasm-std"
version = "1.2.5"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a49b85345e811c8e80ec55d0d091e4fcb4f00f97ab058f9be5f614c444a730cb"
checksum = "1f6dc2ee23313add5ecacc3ccac217b9967ad9d2d11bd56e5da6aa65a9da6138"
dependencies = [
"base64 0.13.1",
"bnum",
"cosmwasm-crypto",
"cosmwasm-derive",
"derivative",
@@ -703,10 +710,9 @@ dependencies = [
"hex",
"schemars",
"serde",
"serde-json-wasm 0.5.1",
"serde-json-wasm",
"sha2 0.10.6",
"thiserror",
"uint",
]
[[package]]
@@ -810,12 +816,6 @@ dependencies = [
"cfg-if 1.0.0",
]
[[package]]
name = "crunchy"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
[[package]]
name = "crypto-bigint"
version = "0.4.9"
@@ -927,9 +927,9 @@ dependencies = [
[[package]]
name = "cw-controllers"
version = "1.0.1"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91440ce8ec4f0642798bc8c8cb6b9b53c1926c6dadaf0eed267a5145cd529071"
checksum = "d5d8edce4b78785f36413f67387e4be7d0cb7d032b5d4164bcc024f9c3f3f2ea"
dependencies = [
"cosmwasm-schema",
"cosmwasm-std",
@@ -942,9 +942,9 @@ dependencies = [
[[package]]
name = "cw-storage-plus"
version = "1.0.1"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "053a5083c258acd68386734f428a5a171b29f7d733151ae83090c6fcc9417ffa"
checksum = "3f0e92a069d62067f3472c62e30adedb4cab1754725c0f2a682b3128d2bf3c79"
dependencies = [
"cosmwasm-std",
"schemars",
@@ -968,15 +968,16 @@ dependencies = [
[[package]]
name = "cw2"
version = "1.0.1"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8fb70cee2cf0b4a8ff7253e6bc6647107905e8eb37208f87d54f67810faa62f8"
checksum = "29ac2dc7a55ad64173ca1e0a46697c31b7a5c51342f55a1e84a724da4eb99908"
dependencies = [
"cosmwasm-schema",
"cosmwasm-std",
"cw-storage-plus",
"schemars",
"serde",
"thiserror",
]
[[package]]
@@ -994,9 +995,9 @@ dependencies = [
[[package]]
name = "cw3"
version = "1.0.1"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2fe0b587008aa221cd2a2579a21990a28c4347dc53ad43167c68ad765f5b6efa"
checksum = "171af3d9127de6805a7dd819fb070c7d2f6c3ea85f4193f42cef259f0a7f33d5"
dependencies = [
"cosmwasm-schema",
"cosmwasm-std",
@@ -1009,9 +1010,9 @@ dependencies = [
[[package]]
name = "cw4"
version = "1.0.1"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c236e0bae02ce97e89235a681dd0e07d099524b369f1ef908d704db3e6b049b"
checksum = "a398696307efadaaa2d0850076f865fa706c959d493cb4203314f72be6b77a64"
dependencies = [
"cosmwasm-schema",
"cosmwasm-std",
@@ -1539,7 +1540,7 @@ checksum = "a604f7a68fbf8103337523b1fadc8ade7361ee3f112f7c680ad179651616aed5"
dependencies = [
"futures-core",
"lock_api",
"parking_lot",
"parking_lot 0.11.2",
]
[[package]]
@@ -2114,9 +2115,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
dependencies = [
"cfg-if 1.0.0",
"js-sys",
"wasm-bindgen",
"web-sys",
]
[[package]]
@@ -2477,6 +2475,7 @@ dependencies = [
"nym-config",
"nym-credential-storage",
"nym-crypto",
"nym-explorer-api-requests",
"nym-gateway-client",
"nym-gateway-requests",
"nym-network-defaults",
@@ -2487,6 +2486,7 @@ dependencies = [
"nym-topology",
"nym-validator-client",
"rand 0.7.3",
"reqwest",
"serde",
"serde_json",
"sha2 0.10.6",
@@ -2501,8 +2501,8 @@ dependencies = [
"url",
"wasm-bindgen",
"wasm-bindgen-futures",
"wasm-timer",
"wasm-utils",
"wasmtimer",
"zeroize",
]
@@ -2539,8 +2539,8 @@ dependencies = [
"wasm-bindgen",
"wasm-bindgen-futures",
"wasm-bindgen-test",
"wasm-timer",
"wasm-utils",
"wasmtimer",
"wee_alloc",
"zeroize",
]
@@ -2569,22 +2569,20 @@ dependencies = [
name = "nym-coconut-bandwidth-contract-common"
version = "0.1.0"
dependencies = [
"cosmwasm-schema",
"cosmwasm-std",
"nym-multisig-contract-common",
"schemars",
"serde",
]
[[package]]
name = "nym-coconut-dkg-common"
version = "0.1.0"
dependencies = [
"cosmwasm-schema",
"cosmwasm-std",
"cw-utils",
"nym-contracts-common",
"nym-multisig-contract-common",
"schemars",
"serde",
]
[[package]]
@@ -2616,6 +2614,7 @@ name = "nym-contracts-common"
version = "0.5.0"
dependencies = [
"bs58 0.4.0",
"cosmwasm-schema",
"cosmwasm-std",
"schemars",
"serde",
@@ -2692,6 +2691,17 @@ dependencies = [
"zeroize",
]
[[package]]
name = "nym-explorer-api-requests"
version = "0.1.0"
dependencies = [
"nym-contracts-common",
"nym-mixnet-contract-common",
"nym-validator-client",
"schemars",
"serde",
]
[[package]]
name = "nym-gateway-client"
version = "0.1.0"
@@ -2719,8 +2729,8 @@ dependencies = [
"url",
"wasm-bindgen",
"wasm-bindgen-futures",
"wasm-timer",
"wasm-utils",
"wasmtimer",
]
[[package]]
@@ -2760,13 +2770,14 @@ name = "nym-mixnet-contract-common"
version = "0.6.0"
dependencies = [
"bs58 0.4.0",
"cosmwasm-schema",
"cosmwasm-std",
"humantime-serde",
"log",
"nym-contracts-common",
"schemars",
"serde",
"serde-json-wasm 0.4.1",
"serde-json-wasm",
"serde_repr",
"thiserror",
"time",
@@ -2791,11 +2802,11 @@ dependencies = [
name = "nym-name-service-common"
version = "0.1.0"
dependencies = [
"cosmwasm-schema",
"cosmwasm-std",
"cw-controllers",
"cw-utils",
"nym-contracts-common",
"schemars",
"serde",
"thiserror",
]
@@ -2836,12 +2847,10 @@ dependencies = [
name = "nym-nonexhaustive-delayqueue"
version = "0.1.0"
dependencies = [
"futures-core",
"slab",
"tokio",
"tokio-stream",
"tokio-util",
"wasm-timer",
"wasmtimer",
]
[[package]]
@@ -2872,12 +2881,11 @@ dependencies = [
name = "nym-service-provider-directory-common"
version = "0.1.0"
dependencies = [
"cosmwasm-schema",
"cosmwasm-std",
"cw-controllers",
"cw-utils",
"nym-contracts-common",
"schemars",
"serde",
"thiserror",
]
@@ -3101,7 +3109,6 @@ dependencies = [
"nym-name-service-common",
"nym-network-defaults",
"nym-service-provider-directory-common",
"nym-vesting-contract",
"nym-vesting-contract-common",
"openssl",
"prost",
@@ -3116,33 +3123,16 @@ dependencies = [
"zeroize",
]
[[package]]
name = "nym-vesting-contract"
version = "1.4.0"
dependencies = [
"cosmwasm-derive",
"cosmwasm-std",
"cw-storage-plus",
"cw2",
"nym-contracts-common",
"nym-mixnet-contract-common",
"nym-vesting-contract-common",
"schemars",
"semver 1.0.17",
"serde",
"thiserror",
"vergen",
]
[[package]]
name = "nym-vesting-contract-common"
version = "0.7.0"
dependencies = [
"cosmwasm-schema",
"cosmwasm-std",
"nym-contracts-common",
"nym-mixnet-contract-common",
"schemars",
"serde",
"thiserror",
]
[[package]]
@@ -3252,6 +3242,16 @@ dependencies = [
"parking_lot_core 0.8.6",
]
[[package]]
name = "parking_lot"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
dependencies = [
"lock_api",
"parking_lot_core 0.9.7",
]
[[package]]
name = "parking_lot_core"
version = "0.8.6"
@@ -4056,18 +4056,9 @@ dependencies = [
[[package]]
name = "serde-json-wasm"
version = "0.4.1"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "479b4dbc401ca13ee8ce902851b834893251404c4f3c65370a49e047a6be09a5"
dependencies = [
"serde",
]
[[package]]
name = "serde-json-wasm"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "16a62a1fad1e1828b24acac8f2b468971dade7b8c3c2e672bcadefefb1f8c137"
checksum = "a15bee9b04dd165c3f4e142628982ddde884c2022a89e8ddf99c4829bf2c3a58"
dependencies = [
"serde",
]
@@ -4511,12 +4502,6 @@ dependencies = [
"tokio-rustls 0.23.4",
]
[[package]]
name = "static_assertions"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
[[package]]
name = "stringprep"
version = "0.1.2"
@@ -4979,18 +4964,6 @@ version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e79c4d996edb816c91e4308506774452e55e95c3c9de07b6729e17e15a5ef81"
[[package]]
name = "uint"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52"
dependencies = [
"byteorder",
"crunchy",
"hex",
"static_assertions",
]
[[package]]
name = "unicode-bidi"
version = "0.3.13"
@@ -5233,20 +5206,6 @@ dependencies = [
"quote",
]
[[package]]
name = "wasm-timer"
version = "0.2.5"
source = "git+https://github.com/mmsinclair/wasm-timer?rev=b9d1a54ad514c2f230a026afe0dde341e98cd7b6#b9d1a54ad514c2f230a026afe0dde341e98cd7b6"
dependencies = [
"futures",
"js-sys",
"parking_lot",
"pin-utils",
"wasm-bindgen",
"wasm-bindgen-futures",
"web-sys",
]
[[package]]
name = "wasm-utils"
version = "0.1.0"
@@ -5265,6 +5224,20 @@ dependencies = [
"web-sys",
]
[[package]]
name = "wasmtimer"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f656cd8858a5164932d8a90f936700860976ec21eb00e0fe2aa8cab13f6b4cf"
dependencies = [
"futures",
"js-sys",
"parking_lot 0.12.1",
"pin-utils",
"slab",
"wasm-bindgen",
]
[[package]]
name = "web-sys"
version = "0.3.60"
+1 -1
View File
@@ -33,7 +33,7 @@ wasm-bindgen-futures = "0.4"
thiserror = "1.0.40"
zeroize = "1.6.0"
wasm-timer = { git = "https://github.com/mmsinclair/wasm-timer", rev = "b9d1a54ad514c2f230a026afe0dde341e98cd7b6"}
wasmtimer = { version = "0.2.0", features = ["tokio"] }
# internal
nym-node-tester-utils = { path = "../../common/node-tester-utils" }
+1
View File
@@ -246,6 +246,7 @@ impl From<TopologyWasm> for ConfigTopology {
topology.topology_resolution_timeout_ms,
),
disable_refreshing: topology.disable_refreshing,
topology_structure: Default::default(),
}
}
}
@@ -10,6 +10,7 @@ use std::collections::HashSet;
use std::time::Duration;
use tokio::sync::MutexGuard as AsyncMutexGuard;
use wasm_utils::{console_error, console_log, console_warn};
use wasmtimer::tokio::sleep;
pub(crate) struct EphemeralTestReceiver<'a> {
sent_packets: u32,
@@ -90,7 +91,7 @@ impl<'a> EphemeralTestReceiver<'a> {
}
pub(crate) async fn perform_test(mut self) -> NodeTestResult {
let mut timeout_fut = wasm_timer::Delay::new(self.timeout_duration);
let mut timeout_fut = sleep(self.timeout_duration);
loop {
tokio::select! {
+70 -29
View File
@@ -5,9 +5,13 @@
// and be used by our smart contracts
use serde::{Deserialize, Serialize};
use std::fmt::{Display, Formatter};
#[derive(Debug)]
pub struct BinaryBuildInformation {
/// Provides the name of the binary, i.e. the content of `CARGO_PKG_NAME` environmental variable.
pub binary_name: &'static str,
// VERGEN_BUILD_TIMESTAMP
/// Provides the build timestamp, for example `2021-02-23T20:14:46.558472672+00:00`.
pub build_timestamp: &'static str,
@@ -43,8 +47,9 @@ pub struct BinaryBuildInformation {
impl BinaryBuildInformation {
// explicitly require the build_version to be passed as it's binary specific
pub const fn new(build_version: &'static str) -> Self {
pub const fn new(binary_name: &'static str, build_version: &'static str) -> Self {
BinaryBuildInformation {
binary_name,
build_timestamp: env!("VERGEN_BUILD_TIMESTAMP"),
build_version,
commit_sha: env!("VERGEN_GIT_SHA"),
@@ -58,6 +63,7 @@ impl BinaryBuildInformation {
pub fn to_owned(&self) -> BinaryBuildInformationOwned {
BinaryBuildInformationOwned {
binary_name: self.binary_name.to_owned(),
build_timestamp: self.build_timestamp.to_owned(),
build_version: self.build_version.to_owned(),
commit_sha: self.commit_sha.to_owned(),
@@ -70,39 +76,15 @@ impl BinaryBuildInformation {
}
pub fn pretty_print(&self) -> String {
format!(
r#"
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
"#,
"Build Timestamp:",
self.build_timestamp,
"Build Version:",
self.build_version,
"Commit SHA:",
self.commit_sha,
"Commit Date:",
self.commit_timestamp,
"Commit Branch:",
self.commit_branch,
"rustc Version:",
self.rustc_version,
"rustc Channel:",
self.rustc_channel,
"cargo Profile:",
self.cargo_profile,
)
self.to_owned().to_string()
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct BinaryBuildInformationOwned {
/// Provides the name of the binary, i.e. the content of `CARGO_PKG_NAME` environmental variable.
pub binary_name: String,
// VERGEN_BUILD_TIMESTAMP
/// Provides the build timestamp, for example `2021-02-23T20:14:46.558472672+00:00`.
pub build_timestamp: String,
@@ -135,3 +117,62 @@ pub struct BinaryBuildInformationOwned {
/// Provides the cargo profile that was used for the build, for example `debug`.
pub cargo_profile: String,
}
impl Display for BinaryBuildInformationOwned {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(
f,
r#"
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
"#,
"Binary Name:",
self.binary_name,
"Build Timestamp:",
self.build_timestamp,
"Build Version:",
self.build_version,
"Commit SHA:",
self.commit_sha,
"Commit Date:",
self.commit_timestamp,
"Commit Branch:",
self.commit_branch,
"rustc Version:",
self.rustc_version,
"rustc Channel:",
self.rustc_channel,
"cargo Profile:",
self.cargo_profile,
)
}
}
// since this macro will get expanded at the callsite, it will pull in correct binary version
#[macro_export]
macro_rules! bin_info {
() => {
$crate::build_information::BinaryBuildInformation::new(
env!("CARGO_PKG_NAME"),
env!("CARGO_PKG_VERSION"),
)
};
}
#[macro_export]
macro_rules! bin_info_owned {
() => {
$crate::build_information::BinaryBuildInformation::new(
env!("CARGO_PKG_NAME"),
env!("CARGO_PKG_VERSION"),
)
.to_owned()
};
}
+9 -7
View File
@@ -10,27 +10,29 @@ rust-version = "1.66"
[dependencies]
async-trait = { workspace = true }
base64 = "0.21.2"
dirs = "4.0"
dashmap = "5.4.0"
dirs = "4.0"
futures = "0.3"
humantime-serde = "1.0"
log = { workspace = true }
rand = { version = "0.7.3", features = ["wasm-bindgen"] }
reqwest = { workspace = true }
serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true }
sha2 = "0.10.6"
tap = "1.0.1"
thiserror = "1.0.34"
url = { version ="2.2", features = ["serde"] }
tungstenite = { version = "0.13.0", default-features = false }
tokio = { version = "1.24.1", features = ["macros"]}
time = "0.3.17"
tokio = { version = "1.24.1", features = ["macros"]}
tungstenite = { version = "0.13.0", default-features = false }
url = { version ="2.2", features = ["serde"] }
zeroize = { workspace = true }
# internal
nym-bandwidth-controller = { path = "../bandwidth-controller" }
nym-config = { path = "../config" }
nym-crypto = { path = "../crypto" }
nym-explorer-api-requests = { path = "../../explorer-api/explorer-api-requests" }
nym-gateway-client = { path = "../client-libs/gateway-client" }
#gateway-client = { path = "../../common/client-libs/gateway-client", default-features = false, features = ["wasm", "coconut"] }
nym-gateway-requests = { path = "../../gateway/gateway-requests" }
@@ -69,9 +71,9 @@ version = "0.4"
[target."cfg(target_arch = \"wasm32\")".dependencies.wasm-bindgen]
version = "0.2.83"
[target."cfg(target_arch = \"wasm32\")".dependencies.wasm-timer]
git = "https://github.com/mmsinclair/wasm-timer"
rev = "b9d1a54ad514c2f230a026afe0dde341e98cd7b6"
[target."cfg(target_arch = \"wasm32\")".dependencies.wasmtimer]
workspace = true
features = ["tokio"]
[target."cfg(target_arch = \"wasm32\")".dependencies.gloo-timers]
version = "0.2.4"
@@ -2,6 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
use super::received_buffer::ReceivedBufferMessage;
use super::topology_control::geo_aware_provider::GeoAwareTopologyProvider;
use crate::client::base_client::storage::MixnetClientStorage;
use crate::client::cover_traffic_stream::LoopCoverTrafficStream;
use crate::client::inbound_messages::{InputMessage, InputMessageReceiver, InputMessageSender};
@@ -339,14 +340,20 @@ where
fn setup_topology_provider(
custom_provider: Option<Box<dyn TopologyProvider + Send + Sync>>,
provider_from_config: config::TopologyStructure,
nym_api_urls: Vec<Url>,
) -> Box<dyn TopologyProvider + Send + Sync> {
// if no custom provider was ... provided ..., create one using nym-api
custom_provider.unwrap_or_else(|| {
Box::new(NymApiTopologyProvider::new(
custom_provider.unwrap_or_else(|| match provider_from_config {
config::TopologyStructure::NymApi => Box::new(NymApiTopologyProvider::new(
nym_api_urls,
env!("CARGO_PKG_VERSION").to_string(),
))
)),
config::TopologyStructure::GeoAware(group) => Box::new(GeoAwareTopologyProvider::new(
nym_api_urls,
env!("CARGO_PKG_VERSION").to_string(),
group,
)),
})
}
@@ -521,8 +528,10 @@ where
let topology_provider = Self::setup_topology_provider(
self.custom_topology_provider.take(),
self.config.debug.topology.topology_structure,
self.config.get_nym_api_endpoints(),
);
Self::start_topology_refresher(
topology_provider,
self.config.debug.topology,
@@ -19,10 +19,10 @@ use std::time::Duration;
use tokio::sync::mpsc::error::TrySendError;
#[cfg(not(target_arch = "wasm32"))]
use tokio::time;
use tokio::time::{sleep, Sleep};
#[cfg(target_arch = "wasm32")]
use wasm_timer;
use wasmtimer::tokio::{sleep, Sleep};
pub struct LoopCoverTrafficStream<R>
where
@@ -39,11 +39,7 @@ where
/// Internal state, determined by `average_message_sending_delay`,
/// used to keep track of when a next packet should be sent out.
#[cfg(not(target_arch = "wasm32"))]
next_delay: Pin<Box<time::Sleep>>,
#[cfg(target_arch = "wasm32")]
next_delay: Pin<Box<wasm_timer::Delay>>,
next_delay: Pin<Box<Sleep>>,
/// Channel used for sending prepared nym packets to `MixTrafficController` that sends them
/// out to the network without any further delays.
@@ -90,17 +86,9 @@ where
// The next interval value is `next_poisson_delay` after the one that just
// yielded.
#[cfg(not(target_arch = "wasm32"))]
{
let now = self.next_delay.deadline();
let next = now + next_poisson_delay;
self.next_delay.as_mut().reset(next);
}
#[cfg(target_arch = "wasm32")]
{
self.next_delay.as_mut().reset(next_poisson_delay);
}
let now = self.next_delay.deadline();
let next = now + next_poisson_delay;
self.next_delay.as_mut().reset(next);
Poll::Ready(Some(()))
}
@@ -120,11 +108,7 @@ impl LoopCoverTrafficStream<OsRng> {
) -> Self {
let rng = OsRng;
#[cfg(not(target_arch = "wasm32"))]
let next_delay = Box::pin(time::sleep(Default::default()));
#[cfg(target_arch = "wasm32")]
let next_delay = Box::pin(wasm_timer::Delay::new(Default::default()));
let next_delay = Box::pin(sleep(Default::default()));
LoopCoverTrafficStream {
ack_key,
@@ -142,12 +126,7 @@ impl LoopCoverTrafficStream<OsRng> {
}
fn set_next_delay(&mut self, amount: Duration) {
#[cfg(not(target_arch = "wasm32"))]
let next_delay = Box::pin(time::sleep(amount));
#[cfg(target_arch = "wasm32")]
let next_delay = Box::pin(wasm_timer::Delay::new(amount));
let next_delay = Box::pin(sleep(amount));
self.next_delay = next_delay;
}
@@ -2,13 +2,12 @@
// SPDX-License-Identifier: Apache-2.0
use std::time::Duration;
use wasm_timer;
pub use wasm_timer::*;
pub use wasmtimer::{std::Instant, tokio::*};
pub type IntervalStream = gloo_timers::future::IntervalStream;
pub(crate) fn get_time_now() -> Instant {
wasm_timer::Instant::now()
Instant::now()
}
pub(crate) fn new_interval_stream(polling_rate: Duration) -> IntervalStream {
@@ -27,9 +27,10 @@ use std::sync::Arc;
use std::time::Duration;
#[cfg(not(target_arch = "wasm32"))]
use tokio::time;
use tokio::time::{sleep, Sleep};
#[cfg(target_arch = "wasm32")]
use wasm_timer;
use wasmtimer::tokio::{sleep, Sleep};
mod sending_delay_controller;
@@ -82,11 +83,7 @@ where
/// Internal state, determined by `average_message_sending_delay`,
/// used to keep track of when a next packet should be sent out.
#[cfg(not(target_arch = "wasm32"))]
next_delay: Option<Pin<Box<time::Sleep>>>,
#[cfg(target_arch = "wasm32")]
next_delay: Option<Pin<Box<wasm_timer::Delay>>>,
next_delay: Option<Pin<Box<Sleep>>>,
// To make sure we don't overload the mix_tx channel, we limit the rate we are pushing
// messages.
@@ -373,17 +370,9 @@ where
// The next interval value is `next_poisson_delay` after the one that just
// yielded.
#[cfg(not(target_arch = "wasm32"))]
{
let now = next_delay.deadline();
let next = now + next_poisson_delay;
next_delay.as_mut().reset(next);
}
#[cfg(target_arch = "wasm32")]
{
next_delay.as_mut().reset(next_poisson_delay);
}
let now = next_delay.deadline();
let next = now + next_poisson_delay;
next_delay.as_mut().reset(next);
// On every iteration we get new messages from upstream. Given that these come bunched
// in `Vec`, this ensures that on average we will fetch messages faster than we can
@@ -421,12 +410,7 @@ where
self.config.traffic.message_sending_average_delay,
);
#[cfg(not(target_arch = "wasm32"))]
let next_delay = Box::pin(time::sleep(sampled));
#[cfg(target_arch = "wasm32")]
let next_delay = Box::pin(wasm_timer::Delay::new(sampled));
let next_delay = Box::pin(sleep(sampled));
self.next_delay = Some(next_delay);
Poll::Pending
@@ -0,0 +1,319 @@
use std::{collections::HashMap, fmt};
use log::{debug, error, info};
use nym_explorer_api_requests::PrettyDetailedMixNodeBond;
use nym_topology::{
nym_topology_from_detailed,
provider_trait::{async_trait, TopologyProvider},
NymTopology,
};
use nym_validator_client::client::MixId;
use rand::{prelude::SliceRandom, thread_rng};
use serde::{Deserialize, Serialize};
use url::Url;
const MIN_NODES_PER_LAYER: usize = 1;
const EXPLORER_API_MIXNODES_URL: &str = "https://explorer.nymtech.net/api/v1/mix-nodes";
// TODO: create a explorer-api-client
async fn fetch_mixnodes_from_explorer_api() -> Option<Vec<PrettyDetailedMixNodeBond>> {
reqwest::get(EXPLORER_API_MIXNODES_URL)
.await
.ok()?
.json::<Vec<PrettyDetailedMixNodeBond>>()
.await
.ok()
}
#[derive(Copy, Clone, Hash, PartialEq, Eq, Serialize, Deserialize, Debug)]
pub enum CountryGroup {
Europe,
NorthAmerica,
SouthAmerica,
Oceania,
Asia,
Africa,
Unknown,
}
impl CountryGroup {
// We map contry codes into group, which initially are continent codes to a first approximation,
// but we do it manually to reserve the right to tweak this distribution for our purposes.
fn new(country_code: &str) -> Self {
let country_code = country_code.to_uppercase();
use CountryGroup::*;
match country_code.as_ref() {
// Europe
"AT" => Europe,
"BG" => Europe,
"CH" => Europe,
"CY" => Europe,
"CZ" => Europe,
"DE" => Europe,
"DK" => Europe,
"ES" => Europe,
"FI" => Europe,
"FR" => Europe,
"GB" => Europe,
"GR" => Europe,
"IE" => Europe,
"IT" => Europe,
"LT" => Europe,
"LU" => Europe,
"LV" => Europe,
"MD" => Europe,
"MT" => Europe,
"NL" => Europe,
"NO" => Europe,
"PL" => Europe,
"RO" => Europe,
"SE" => Europe,
"SK" => Europe,
"TR" => Europe,
"UA" => Europe,
// North America
"CA" => NorthAmerica,
"MX" => NorthAmerica,
"US" => NorthAmerica,
// South America
"AR" => SouthAmerica,
"BR" => SouthAmerica,
"CL" => SouthAmerica,
"CO" => SouthAmerica,
"CR" => SouthAmerica,
"GT" => SouthAmerica,
// Oceania
"AU" => Oceania,
// Asia
"AM" => Asia,
"BH" => Asia,
"CN" => Asia,
"GE" => Asia,
"HK" => Asia,
"ID" => Asia,
"IL" => Asia,
"IN" => Asia,
"JP" => Asia,
"KH" => Asia,
"KR" => Asia,
"KZ" => Asia,
"MY" => Asia,
"RU" => Asia,
"SG" => Asia,
"TH" => Asia,
"VN" => Asia,
// Africa
"SC" => Africa,
"UG" => Africa,
"ZA" => Africa,
// And group level codes work too
"EU" => Europe,
"NA" => NorthAmerica,
"SA" => SouthAmerica,
"OC" => Oceania,
"AS" => Asia,
"AF" => Africa,
// And some aliases
"EUROPE" => Europe,
"NORTHAMERICA" => NorthAmerica,
"SOUTHAMERICA" => SouthAmerica,
"OCEANIA" => Oceania,
"ASIA" => Asia,
"AFRICA" => Africa,
_ => {
info!("Unknown country code: {}", country_code);
Unknown
}
}
}
}
impl fmt::Display for CountryGroup {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use CountryGroup::*;
match self {
Europe => write!(f, "EU"),
NorthAmerica => write!(f, "NA"),
SouthAmerica => write!(f, "SA"),
Oceania => write!(f, "OC"),
Asia => write!(f, "AS"),
Africa => write!(f, "AF"),
Unknown => write!(f, "Unknown"),
}
}
}
impl std::str::FromStr for CountryGroup {
type Err = ();
fn from_str(s: &str) -> Result<Self, Self::Err> {
let group = CountryGroup::new(s);
if group == CountryGroup::Unknown {
Err(())
} else {
Ok(group)
}
}
}
impl CountryGroup {
#[allow(unused)]
fn known(self) -> Option<CountryGroup> {
use CountryGroup::*;
match self {
Europe | NorthAmerica | SouthAmerica | Oceania | Asia | Africa => Some(self),
Unknown => None,
}
}
}
fn group_mixnodes_by_country_code(
mixnodes: Vec<PrettyDetailedMixNodeBond>,
) -> HashMap<CountryGroup, Vec<MixId>> {
mixnodes
.into_iter()
.fold(HashMap::<CountryGroup, Vec<MixId>>::new(), |mut acc, m| {
if let Some(ref location) = m.location {
let country_code = location.two_letter_iso_country_code.clone();
let group_code = CountryGroup::new(country_code.as_str());
let mixnodes = acc.entry(group_code).or_insert_with(Vec::new);
mixnodes.push(m.mix_id);
}
acc
})
}
fn log_mixnode_distribution(mixnodes: &HashMap<CountryGroup, Vec<MixId>>) {
let mixnode_distribution = mixnodes
.iter()
.map(|(k, v)| format!("{}: {}", k, v.len()))
.collect::<Vec<_>>()
.join(", ");
debug!("Mixnode distribution - {}", mixnode_distribution);
}
fn check_layer_integrity(topology: NymTopology) -> Result<(), ()> {
let mixes = topology.mixes();
if mixes.keys().len() < 3 {
error!("Layer is missing in topology!");
return Err(());
}
for (layer, mixnodes) in mixes {
debug!("Layer {:?} has {} mixnodes", layer, mixnodes.len());
if mixnodes.len() < MIN_NODES_PER_LAYER {
error!(
"There are only {} mixnodes in layer {:?}",
mixnodes.len(),
layer
);
return Err(());
}
}
Ok(())
}
pub struct GeoAwareTopologyProvider {
validator_client: nym_validator_client::client::NymApiClient,
filter_on: CountryGroup,
client_version: String,
}
impl GeoAwareTopologyProvider {
pub fn new(
mut nym_api_urls: Vec<Url>,
client_version: String,
filter_on: CountryGroup,
) -> GeoAwareTopologyProvider {
log::info!(
"Creating geo-aware topology provider with filter on {:?}",
filter_on
);
nym_api_urls.shuffle(&mut thread_rng());
GeoAwareTopologyProvider {
validator_client: nym_validator_client::client::NymApiClient::new(
nym_api_urls[0].clone(),
),
filter_on,
client_version,
}
}
async fn get_topology(&self) -> Option<NymTopology> {
let mixnodes = match self.validator_client.get_cached_active_mixnodes().await {
Err(err) => {
error!("failed to get network mixnodes - {err}");
return None;
}
Ok(mixes) => mixes,
};
let gateways = match self.validator_client.get_cached_gateways().await {
Err(err) => {
error!("failed to get network gateways - {err}");
return None;
}
Ok(gateways) => gateways,
};
// Also fetch mixnodes cached by explorer-api, with the purpose of getting their
// geolocation.
debug!("Fetching mixnodes from explorer-api...");
let Some(mixnodes_from_explorer_api) = fetch_mixnodes_from_explorer_api().await else {
error!("failed to get mixnodes from explorer-api");
return None;
};
// Partition mixnodes_from_explorer_api according to the value of
// two_letter_iso_country_code.
// NOTE: we construct the full distribution here, but only use the one we're interested in.
// The reason we this instead of a straight filter is that this opens up the possibility to
// complement a small grouping with mixnodes from adjecent countries.
let mixnode_distribution = group_mixnodes_by_country_code(mixnodes_from_explorer_api);
log_mixnode_distribution(&mixnode_distribution);
let Some(filtered_mixnode_ids) = mixnode_distribution.get(&self.filter_on) else {
error!("no mixnodes found for: {}", self.filter_on);
return None;
};
let mixnodes = mixnodes
.into_iter()
.filter(|m| filtered_mixnode_ids.contains(&m.mix_id()))
.collect::<Vec<_>>();
let topology = nym_topology_from_detailed(mixnodes, gateways)
.filter_system_version(&self.client_version);
// TODO: return real error type
check_layer_integrity(topology.clone()).ok()?;
Some(topology)
}
}
#[cfg(not(target_arch = "wasm32"))]
#[async_trait]
impl TopologyProvider for GeoAwareTopologyProvider {
// this will be manually refreshed on a timer specified inside mixnet client config
async fn get_new_topology(&mut self) -> Option<NymTopology> {
self.get_topology().await
}
}
#[cfg(target_arch = "wasm32")]
#[async_trait(?Send)]
impl TopologyProvider for GeoAwareTopologyProvider {
// this will be manually refreshed on a timer specified inside mixnet client config
async fn get_new_topology(&mut self) -> Option<NymTopology> {
self.get_topology().await
}
}
@@ -10,6 +10,7 @@ use nym_topology::NymTopologyError;
use std::time::Duration;
mod accessor;
pub mod geo_aware_provider;
pub(crate) mod nym_api_provider;
// TODO: move it to config later
+21 -1
View File
@@ -8,7 +8,7 @@ use serde::{Deserialize, Serialize};
use std::time::Duration;
use url::Url;
use crate::error::ClientCoreError;
use crate::{client::topology_control::geo_aware_provider::CountryGroup, error::ClientCoreError};
#[cfg(target_arch = "wasm32")]
use wasm_bindgen::prelude::*;
@@ -158,6 +158,15 @@ impl Config {
self
}
pub fn with_topology_structure(mut self, topology_structure: TopologyStructure) -> Self {
self.set_topology_structure(topology_structure);
self
}
pub fn set_topology_structure(&mut self, topology_structure: TopologyStructure) {
self.debug.topology.topology_structure = topology_structure;
}
pub fn with_no_per_hop_delays(mut self, no_per_hop_delays: bool) -> Self {
if no_per_hop_delays {
self.set_no_per_hop_delays()
@@ -466,6 +475,16 @@ pub struct Topology {
/// the first valid instance.
/// Supersedes `topology_refresh_rate_ms`.
pub disable_refreshing: bool,
/// Specifies the mixnode topology to be used for sending packets.
pub topology_structure: TopologyStructure,
}
#[derive(Default, Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
pub enum TopologyStructure {
#[default]
NymApi,
GeoAware(CountryGroup),
}
impl Default for Topology {
@@ -474,6 +493,7 @@ impl Default for Topology {
topology_refresh_rate: DEFAULT_TOPOLOGY_REFRESH_RATE,
topology_resolution_timeout: DEFAULT_TOPOLOGY_RESOLUTION_TIMEOUT,
disable_refreshing: false,
topology_structure: TopologyStructure::default(),
}
}
}
@@ -267,6 +267,7 @@ impl From<TopologyV1_1_20_2> for Topology {
topology_refresh_rate: value.topology_refresh_rate,
topology_resolution_timeout: value.topology_resolution_timeout,
disable_refreshing: value.disable_refreshing,
topology_structure: Default::default(),
}
}
}
+7 -9
View File
@@ -27,13 +27,17 @@ use tokio_tungstenite::connect_async;
use tokio_tungstenite::{MaybeTlsStream, WebSocketStream};
#[cfg(not(target_arch = "wasm32"))]
type WsConn = WebSocketStream<MaybeTlsStream<TcpStream>>;
#[cfg(not(target_arch = "wasm32"))]
use tokio::time::sleep;
#[cfg(target_arch = "wasm32")]
use nym_bandwidth_controller::wasm_mockups::DirectSigningNyxdClient;
#[cfg(target_arch = "wasm32")]
use wasm_timer::Instant;
#[cfg(target_arch = "wasm32")]
use wasm_utils::websocket::JSWebsocket;
#[cfg(target_arch = "wasm32")]
use wasmtimer::std::Instant;
#[cfg(target_arch = "wasm32")]
use wasmtimer::tokio::sleep;
#[cfg(target_arch = "wasm32")]
type WsConn = JSWebsocket;
@@ -125,15 +129,9 @@ async fn measure_latency(gateway: &gateway::Node) -> Result<GatewayWithLatency,
Ok::<(), ClientCoreError>(())
};
// thanks to wasm we can't use tokio::time::timeout : (
#[cfg(not(target_arch = "wasm32"))]
let timeout = tokio::time::sleep(PING_TIMEOUT);
#[cfg(not(target_arch = "wasm32"))]
let timeout = sleep(PING_TIMEOUT);
tokio::pin!(timeout);
#[cfg(target_arch = "wasm32")]
let mut timeout = wasm_timer::Delay::new(PING_TIMEOUT);
tokio::select! {
_ = &mut timeout => {
warn!("timed out while trying to perform measurement...")
+3 -3
View File
@@ -58,9 +58,9 @@ path = "../../wasm-utils"
features = ["websocket"]
# only import it in wasm. Prefer proper tokio timer in non-wasm
[target."cfg(target_arch = \"wasm32\")".dependencies.wasm-timer]
git = "https://github.com/mmsinclair/wasm-timer"
rev = "b9d1a54ad514c2f230a026afe0dde341e98cd7b6"
[target."cfg(target_arch = \"wasm32\")".dependencies.wasmtimer]
workspace = true
features = ["tokio"]
# this is due to tungstenite using `rand` 0.8 and associated changes in `getrandom` crate
# which now does not support wasm32-unknown-unknown target by default.
@@ -31,14 +31,16 @@ use tungstenite::protocol::Message;
#[cfg(not(target_arch = "wasm32"))]
use nym_validator_client::nyxd::traits::DkgQueryClient;
#[cfg(not(target_arch = "wasm32"))]
use tokio::time::sleep;
#[cfg(not(target_arch = "wasm32"))]
use tokio_tungstenite::connect_async;
#[cfg(target_arch = "wasm32")]
use nym_bandwidth_controller::wasm_mockups::DkgQueryClient;
#[cfg(target_arch = "wasm32")]
use wasm_timer;
#[cfg(target_arch = "wasm32")]
use wasm_utils::websocket::JSWebsocket;
#[cfg(target_arch = "wasm32")]
use wasmtimer::tokio::sleep;
const DEFAULT_RECONNECTION_ATTEMPTS: usize = 10;
const DEFAULT_RECONNECTION_BACKOFF: Duration = Duration::from_secs(5);
@@ -198,15 +200,7 @@ impl<C, St> GatewayClient<C, St> {
}
#[cfg(not(target_arch = "wasm32"))]
tokio::time::sleep(self.reconnection_backoff).await;
#[cfg(target_arch = "wasm32")]
if let Err(err) = wasm_timer::Delay::new(self.reconnection_backoff).await {
error!(
"the timer has gone away while in reconnection backoff! - {}",
err
);
}
sleep(self.reconnection_backoff).await;
}
// final attempt (done separately to be able to return a proper error)
@@ -235,16 +229,9 @@ impl<C, St> GatewayClient<C, St> {
_ => return Err(GatewayClientError::ConnectionInInvalidState),
};
#[cfg(not(target_arch = "wasm32"))]
let timeout = tokio::time::sleep(self.response_timeout_duration);
#[cfg(not(target_arch = "wasm32"))]
let timeout = sleep(self.response_timeout_duration);
tokio::pin!(timeout);
// technically the `wasm_timer` also works outside wasm, but unless required,
// I really prefer to just stick to tokio
#[cfg(target_arch = "wasm32")]
let mut timeout = wasm_timer::Delay::new(self.response_timeout_duration);
loop {
tokio::select! {
_ = self.shutdown.recv() => {
@@ -20,7 +20,6 @@ nym-multisig-contract-common = { path = "../../cosmwasm-smart-contracts/multisig
nym-name-service-common = { path = "../../cosmwasm-smart-contracts/name-service" }
nym-group-contract-common = { path = "../../cosmwasm-smart-contracts/group-contract" }
nym-service-provider-directory-common = { path = "../../cosmwasm-smart-contracts/service-provider-directory" }
nym-vesting-contract = { path = "../../../contracts/vesting" }
serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true }
reqwest = { version = "0.11", features = ["json"] }
@@ -32,7 +32,7 @@ impl Display for AutoFeeGrant {
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum Fee {
Manual(#[serde(with = "sealed::TxFee")] tx::Fee),
Manual(tx::Fee),
Auto(Option<GasAdjustment>),
PayerGranterAuto(AutoFeeGrant),
}
@@ -121,58 +121,3 @@ impl GasAdjustable for Gas {
}
}
}
// a workaround to provide serde implementation for tx::Fee. We don't want to ever expose any of those
// types to the public and ideally they will get replaced by proper implementation inside comrs
mod sealed {
use cosmrs::tx::{self};
use cosmrs::{AccountId, Denom as CosmosDenom};
use cosmrs::{Coin as CosmosCoin, Gas};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
#[derive(Serialize, Deserialize, Clone)]
struct Coin {
denom: CosmosDenom,
amount: u128,
}
impl From<Coin> for CosmosCoin {
fn from(val: Coin) -> Self {
CosmosCoin {
denom: val.denom,
amount: val.amount,
}
}
}
impl From<CosmosCoin> for Coin {
fn from(val: CosmosCoin) -> Self {
Coin {
denom: val.denom,
amount: val.amount,
}
}
}
fn coin_vec_ser<S: Serializer>(val: &[CosmosCoin], serializer: S) -> Result<S::Ok, S::Error> {
let vec: Vec<Coin> = val.iter().cloned().map(Into::into).collect();
vec.serialize(serializer)
}
fn coin_vec_deser<'de, D: Deserializer<'de>>(
deserializer: D,
) -> Result<Vec<CosmosCoin>, D::Error> {
let vec: Vec<Coin> = Deserialize::deserialize(deserializer)?;
Ok(vec.iter().cloned().map(Into::into).collect())
}
#[derive(Serialize, Deserialize)]
#[serde(remote = "tx::Fee")]
pub(super) struct TxFee {
#[serde(serialize_with = "coin_vec_ser")]
#[serde(deserialize_with = "coin_vec_deser")]
pub amount: Vec<CosmosCoin>,
pub gas_limit: Gas,
pub payer: Option<AccountId>,
pub granter: Option<AccountId>,
}
}
@@ -78,7 +78,6 @@ pub struct Config {
// however, I'd really prefer to use something more strongly typed (i.e. AccountId vs String)
pub(crate) mixnet_contract_address: Option<AccountId>,
pub(crate) vesting_contract_address: Option<AccountId>,
pub(crate) bandwidth_claim_contract_address: Option<AccountId>,
pub(crate) coconut_bandwidth_contract_address: Option<AccountId>,
pub(crate) group_contract_address: Option<AccountId>,
pub(crate) multisig_contract_address: Option<AccountId>,
@@ -126,10 +125,6 @@ impl Config {
details.contracts.vesting_contract_address.as_ref(),
prefix,
)?,
bandwidth_claim_contract_address: Self::parse_optional_account(
details.contracts.bandwidth_claim_contract_address.as_ref(),
prefix,
)?,
coconut_bandwidth_contract_address: Self::parse_optional_account(
details
.contracts
@@ -548,10 +543,6 @@ impl<C> NyxdClient<C> {
self.config.vesting_contract_address = Some(address);
}
pub fn set_bandwidth_claim_contract_address(&mut self, address: AccountId) {
self.config.bandwidth_claim_contract_address = Some(address);
}
pub fn set_coconut_bandwidth_contract_address(&mut self, address: AccountId) {
self.config.coconut_bandwidth_contract_address = Some(address);
}
@@ -580,17 +571,6 @@ impl<C> NyxdClient<C> {
self.config.vesting_contract_address.as_ref().unwrap()
}
// TODO: this should get changed into Result<&AccountId, NyxdError> (or Option<&AccountId> in future commits
// note: what unwrap is doing here is just moving a failure that would have normally
// occurred in `connect` when attempting to parse an empty address,
// so it's not introducing new source of failure (just moves it)
pub fn bandwidth_claim_contract_address(&self) -> &AccountId {
self.config
.bandwidth_claim_contract_address
.as_ref()
.unwrap()
}
// TODO: this should get changed into Result<&AccountId, NyxdError> (or Option<&AccountId> in future commits
// note: what unwrap is doing here is just moving a failure that would have normally
// occurred in `connect` when attempting to parse an empty address,
@@ -8,10 +8,9 @@ use async_trait::async_trait;
use cosmrs::AccountId;
use nym_contracts_common::signing::Nonce;
use nym_mixnet_contract_common::delegation::{MixNodeDelegationResponse, OwnerProxySubKey};
use nym_mixnet_contract_common::families::Family;
use nym_mixnet_contract_common::mixnode::{
MixNodeDetails, MixnodeRewardingDetailsResponse, PagedMixnodesDetailsResponse,
PagedUnbondedMixnodesResponse, StakeSaturationResponse, UnbondedMixnodeResponse,
MixnodeRewardingDetailsResponse, PagedMixnodesDetailsResponse, PagedUnbondedMixnodesResponse,
StakeSaturationResponse, UnbondedMixnodeResponse,
};
use nym_mixnet_contract_common::reward_params::{Performance, RewardingParams};
use nym_mixnet_contract_common::rewarding::{
@@ -19,14 +18,15 @@ use nym_mixnet_contract_common::rewarding::{
};
use nym_mixnet_contract_common::{
delegation, ContractBuildInformation, ContractState, ContractStateParams,
CurrentIntervalResponse, EpochEventId, EpochStatus, GatewayBondResponse,
GatewayOwnershipResponse, IdentityKey, IntervalEventId, LayerDistribution, MixId,
MixOwnershipResponse, MixnodeDetailsResponse, NumberOfPendingEventsResponse,
PagedAllDelegationsResponse, PagedDelegatorDelegationsResponse, PagedFamiliesResponse,
PagedGatewayResponse, PagedMembersResponse, PagedMixNodeDelegationsResponse,
PagedMixnodeBondsResponse, PagedRewardedSetResponse, PendingEpochEventResponse,
PendingEpochEventsResponse, PendingIntervalEventResponse, PendingIntervalEventsResponse,
QueryMsg as MixnetQueryMsg,
CurrentIntervalResponse, EpochEventId, EpochStatus, FamilyByHeadResponse,
FamilyByLabelResponse, FamilyMembersByHeadResponse, FamilyMembersByLabelResponse,
GatewayBondResponse, GatewayOwnershipResponse, IdentityKey, IntervalEventId, LayerDistribution,
MixId, MixOwnershipResponse, MixnodeDetailsByIdentityResponse, MixnodeDetailsResponse,
NumberOfPendingEventsResponse, PagedAllDelegationsResponse, PagedDelegatorDelegationsResponse,
PagedFamiliesResponse, PagedGatewayResponse, PagedMembersResponse,
PagedMixNodeDelegationsResponse, PagedMixnodeBondsResponse, PagedRewardedSetResponse,
PendingEpochEventResponse, PendingEpochEventsResponse, PendingIntervalEventResponse,
PendingIntervalEventsResponse, QueryMsg as MixnetQueryMsg,
};
use serde::Deserialize;
@@ -100,6 +100,24 @@ pub trait MixnetQueryClient {
.await
}
async fn get_family_members_by_head<S: Into<String> + Send>(
&self,
head: S,
) -> Result<FamilyMembersByHeadResponse, NyxdError> {
self.query_mixnet_contract(MixnetQueryMsg::GetFamilyMembersByHead { head: head.into() })
.await
}
async fn get_family_members_by_label<S: Into<String> + Send>(
&self,
label: S,
) -> Result<FamilyMembersByLabelResponse, NyxdError> {
self.query_mixnet_contract(MixnetQueryMsg::GetFamilyMembersByLabel {
label: label.into(),
})
.await
}
// mixnode-related:
async fn get_mixnode_bonds_paged(
@@ -178,7 +196,7 @@ pub trait MixnetQueryClient {
async fn get_mixnode_details_by_identity(
&self,
mix_identity: IdentityKey,
) -> Result<Option<MixNodeDetails>, NyxdError> {
) -> Result<MixnodeDetailsByIdentityResponse, NyxdError> {
self.query_mixnet_contract(MixnetQueryMsg::GetBondedMixnodeDetailsByIdentity {
mix_identity,
})
@@ -415,14 +433,17 @@ pub trait MixnetQueryClient {
.await
}
async fn get_node_family_by_label(&self, label: &str) -> Result<Option<Family>, NyxdError> {
async fn get_node_family_by_label(
&self,
label: &str,
) -> Result<FamilyByLabelResponse, NyxdError> {
self.query_mixnet_contract(MixnetQueryMsg::GetFamilyByLabel {
label: label.to_string(),
})
.await
}
async fn get_node_family_by_head(&self, head: &str) -> Result<Option<Family>, NyxdError> {
async fn get_node_family_by_head(&self, head: &str) -> Result<FamilyByHeadResponse, NyxdError> {
self.query_mixnet_contract(MixnetQueryMsg::GetFamilyByHead {
head: head.to_string(),
})
@@ -10,12 +10,11 @@ use cosmwasm_std::{Coin as CosmWasmCoin, Timestamp};
use nym_contracts_common::ContractBuildInformation;
use nym_mixnet_contract_common::MixId;
use nym_vesting_contract_common::{
messages::QueryMsg as VestingQueryMsg, AccountVestingCoins, AccountsResponse,
messages::QueryMsg as VestingQueryMsg, Account, AccountVestingCoins, AccountsResponse,
AllDelegationsResponse, BaseVestingAccountInfo, DelegationTimesResponse,
OriginalVestingResponse, Period, PledgeData, VestingCoinsResponse, VestingDelegation,
};
use serde::Deserialize;
use vesting_contract::vesting::Account;
#[async_trait]
pub trait VestingQueryClient {
@@ -12,10 +12,8 @@ use nym_mixnet_contract_common::families::FamilyHead;
use nym_mixnet_contract_common::gateway::GatewayConfigUpdate;
use nym_mixnet_contract_common::mixnode::{MixNodeConfigUpdate, MixNodeCostParams};
use nym_mixnet_contract_common::{Gateway, MixId, MixNode};
use nym_vesting_contract_common::messages::{
ExecuteMsg as VestingExecuteMsg, VestingSpecification,
};
use nym_vesting_contract_common::PledgeCap;
use nym_vesting_contract_common::messages::ExecuteMsg as VestingExecuteMsg;
use nym_vesting_contract_common::{PledgeCap, VestingSpecification};
#[async_trait]
pub trait VestingSigningClient {
@@ -34,6 +34,7 @@ pub async fn delegate_to_mixnode(args: Args, client: SigningClient) {
.get_mixnode_details_by_identity(identity_key)
.await
.expect("contract query failed")
.mixnode_details
.expect("mixnode with the specified identity doesnt exist");
node_details.mix_id()
}
@@ -29,6 +29,7 @@ pub async fn claim_delegator_reward(args: Args, client: SigningClient) {
.get_mixnode_details_by_identity(identity_key)
.await
.expect("contract query failed")
.mixnode_details
.expect("mixnode with the specified identity doesnt exist");
node_details.mix_id()
}
@@ -29,6 +29,7 @@ pub async fn vesting_claim_delegator_reward(args: Args, client: SigningClient) {
.get_mixnode_details_by_identity(identity_key)
.await
.expect("contract query failed")
.mixnode_details
.expect("mixnode with the specified identity doesnt exist");
node_details.mix_id()
}
@@ -29,6 +29,7 @@ pub async fn undelegate_from_mixnode(args: Args, client: SigningClient) {
.get_mixnode_details_by_identity(identity_key)
.await
.expect("contract query failed")
.mixnode_details
.expect("mixnode with the specified identity doesnt exist");
node_details.mix_id()
}
@@ -40,6 +40,7 @@ pub async fn vesting_delegate_to_mixnode(args: Args, client: SigningClient) {
.get_mixnode_details_by_identity(identity_key)
.await
.expect("contract query failed")
.mixnode_details
.expect("mixnode with the specified identity doesnt exist");
node_details.mix_id()
}
@@ -34,6 +34,7 @@ pub async fn vesting_undelegate_from_mixnode(args: Args, client: SigningClient)
.get_mixnode_details_by_identity(identity_key)
.await
.expect("contract query failed")
.mixnode_details
.expect("mixnode with the specified identity doesnt exist");
node_details.mix_id()
}
@@ -50,6 +50,7 @@ pub async fn create_family_join_permit_sign_payload(args: Args, client: QueryCli
.get_node_family_by_head(mixnode.bond_information.identity())
.await
.unwrap()
.family
.is_none()
{
eprintln!("{} does not even seem to own a family!", args.address);
@@ -28,7 +28,7 @@ pub struct Args {
pub async fn join_family(args: Args, client: SigningClient) {
info!("Join family");
let family_head = FamilyHead::new(&args.family_head.to_base58_string());
let family_head = FamilyHead::new(args.family_head.to_base58_string());
let res = if args.with_vesting_account {
client
@@ -23,7 +23,7 @@ pub struct Args {
pub async fn leave_family(args: Args, client: SigningClient) {
info!("Leave family");
let family_head = FamilyHead::new(&args.family_head.to_base58_string());
let family_head = FamilyHead::new(args.family_head.to_base58_string());
let res = if args.with_vesting_account {
client
@@ -11,7 +11,7 @@ use nym_network_defaults::NymNetworkDetails;
use nym_validator_client::nyxd::traits::VestingSigningClient;
use nym_validator_client::nyxd::AccountId;
use nym_validator_client::nyxd::{CosmosCoin, Denom};
use nym_vesting_contract_common::messages::VestingSpecification;
use nym_vesting_contract_common::types::VestingSpecification;
use nym_vesting_contract_common::PledgeCap;
use crate::context::SigningClient;
@@ -7,6 +7,9 @@ edition = "2021"
[dependencies]
cosmwasm-std = { workspace = true }
schemars = "0.8"
serde = { version = "1.0.103", default-features = false, features = ["derive"] }
cosmwasm-schema = { workspace = true }
cw2 = { workspace = true, optional = true }
nym-multisig-contract-common = { path = "../multisig-contract" }
[features]
schema = ["cw2"]
@@ -1,10 +1,9 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use cosmwasm_schema::cw_serde;
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
#[cw_serde]
pub struct DepositData {
deposit_info: String,
identity_key: String,
@@ -1,39 +1,41 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use cosmwasm_std::Coin;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use crate::{deposit::DepositData, spend_credential::SpendCredentialData};
use cosmwasm_schema::cw_serde;
use cosmwasm_std::Coin;
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
#[cfg(feature = "schema")]
use crate::spend_credential::{PagedSpendCredentialResponse, SpendCredentialResponse};
#[cfg(feature = "schema")]
use cosmwasm_schema::QueryResponses;
#[cw_serde]
pub struct InstantiateMsg {
pub multisig_addr: String,
pub pool_addr: String,
pub mix_denom: String,
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
#[serde(rename_all = "snake_case")]
#[cw_serde]
pub enum ExecuteMsg {
DepositFunds { data: DepositData },
SpendCredential { data: SpendCredentialData },
ReleaseFunds { funds: Coin },
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
#[serde(rename_all = "snake_case")]
#[cw_serde]
#[cfg_attr(feature = "schema", derive(QueryResponses))]
pub enum QueryMsg {
GetSpentCredential {
blinded_serial_number: String,
},
#[cfg_attr(feature = "schema", returns(SpendCredentialResponse))]
GetSpentCredential { blinded_serial_number: String },
#[cfg_attr(feature = "schema", returns(PagedSpendCredentialResponse))]
GetAllSpentCredentials {
limit: Option<u32>,
start_after: Option<String>,
},
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
#[serde(rename_all = "snake_case")]
#[cw_serde]
pub struct MigrateMsg {}
@@ -1,14 +1,13 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use cosmwasm_schema::cw_serde;
use cosmwasm_std::{from_binary, to_binary, Addr, Coin, CosmosMsg, StdResult, WasmMsg};
use nym_multisig_contract_common::msg::ExecuteMsg as MultisigExecuteMsg;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use crate::msg::ExecuteMsg;
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
#[cw_serde]
pub struct SpendCredentialData {
funds: Coin,
blinded_serial_number: String,
@@ -37,13 +36,14 @@ impl SpendCredentialData {
}
}
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
#[cw_serde]
#[derive(Copy)]
pub enum SpendCredentialStatus {
InProgress,
Spent,
}
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
#[cw_serde]
pub struct SpendCredential {
funds: Coin,
blinded_serial_number: String,
@@ -74,10 +74,12 @@ impl SpendCredential {
}
}
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
#[cw_serde]
pub struct PagedSpendCredentialResponse {
pub spend_credentials: Vec<SpendCredential>,
pub per_page: usize,
/// Field indicating paging information for the following queries if the caller wishes to get further entries.
pub start_next_after: Option<String>,
}
@@ -95,7 +97,7 @@ impl PagedSpendCredentialResponse {
}
}
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
#[cw_serde]
pub struct SpendCredentialResponse {
pub spend_credential: Option<SpendCredential>,
}
@@ -6,10 +6,12 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
cosmwasm-schema = { workspace = true }
cosmwasm-std = { workspace = true }
cw-utils = { workspace = true }
schemars = "0.8"
serde = { version = "1.0.103", default-features = false, features = ["derive"] }
contracts-common = { path = "../contracts-common", package = "nym-contracts-common" }
nym-multisig-contract-common = { path = "../multisig-contract" }
[features]
schema = []
@@ -2,11 +2,10 @@
// SPDX-License-Identifier: Apache-2.0
use crate::types::{ContractSafeBytes, EncodedBTEPublicKeyWithProof, NodeIndex};
use cosmwasm_schema::cw_serde;
use cosmwasm_std::Addr;
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)]
#[serde(rename_all = "snake_case")]
#[cw_serde]
pub struct DealerDetails {
pub address: Addr,
pub bte_public_key_with_proof: EncodedBTEPublicKeyWithProof,
@@ -14,8 +13,8 @@ pub struct DealerDetails {
pub assigned_index: NodeIndex,
}
#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
#[serde(rename_all = "snake_case")]
#[cw_serde]
#[derive(Copy)]
pub enum DealerType {
Current,
Past,
@@ -28,8 +27,7 @@ impl DealerType {
}
}
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
#[serde(rename_all = "snake_case")]
#[cw_serde]
pub struct DealerDetailsResponse {
pub details: Option<DealerDetails>,
pub dealer_type: DealerType,
@@ -44,11 +42,12 @@ impl DealerDetailsResponse {
}
}
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
#[serde(rename_all = "snake_case")]
#[cw_serde]
pub struct PagedDealerResponse {
pub dealers: Vec<DealerDetails>,
pub per_page: usize,
/// Field indicating paging information for the following queries if the caller wishes to get further entries.
pub start_next_after: Option<Addr>,
}
@@ -66,8 +65,7 @@ impl PagedDealerResponse {
}
}
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
#[serde(rename_all = "snake_case")]
#[cw_serde]
pub struct ContractDealing {
pub dealing: ContractSafeBytes,
pub dealer: Addr,
@@ -79,11 +77,12 @@ impl ContractDealing {
}
}
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
#[serde(rename_all = "snake_case")]
#[cw_serde]
pub struct PagedDealingsResponse {
pub dealings: Vec<ContractDealing>,
pub per_page: usize,
/// Field indicating paging information for the following queries if the caller wishes to get further entries.
pub start_next_after: Option<Addr>,
}
@@ -3,11 +3,19 @@
use crate::types::{ContractSafeBytes, EncodedBTEPublicKeyWithProof, EpochId, TimeConfiguration};
use crate::verification_key::VerificationKeyShare;
use cosmwasm_schema::cw_serde;
use cosmwasm_std::Addr;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
#[cfg(feature = "schema")]
use crate::{
dealer::{DealerDetailsResponse, PagedDealerResponse, PagedDealingsResponse},
types::{Epoch, InitialReplacementData},
verification_key::PagedVKSharesResponse,
};
#[cfg(feature = "schema")]
use cosmwasm_schema::QueryResponses;
#[cw_serde]
pub struct InstantiateMsg {
pub group_addr: String,
pub multisig_addr: String,
@@ -15,8 +23,7 @@ pub struct InstantiateMsg {
pub mix_denom: String,
}
#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
#[cw_serde]
pub enum ExecuteMsg {
RegisterDealer {
bte_key_with_proof: EncodedBTEPublicKeyWithProof,
@@ -44,28 +51,41 @@ pub enum ExecuteMsg {
AdvanceEpochState {},
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
#[serde(rename_all = "snake_case")]
#[cw_serde]
#[cfg_attr(feature = "schema", derive(QueryResponses))]
pub enum QueryMsg {
#[cfg_attr(feature = "schema", returns(Epoch))]
GetCurrentEpochState {},
#[cfg_attr(feature = "schema", returns(u64))]
GetCurrentEpochThreshold {},
#[cfg_attr(feature = "schema", returns(Option<InitialReplacementData>))]
GetInitialDealers {},
GetDealerDetails {
dealer_address: String,
},
#[cfg_attr(feature = "schema", returns(DealerDetailsResponse))]
GetDealerDetails { dealer_address: String },
#[cfg_attr(feature = "schema", returns(PagedDealerResponse))]
GetCurrentDealers {
limit: Option<u32>,
start_after: Option<String>,
},
#[cfg_attr(feature = "schema", returns(PagedDealerResponse))]
GetPastDealers {
limit: Option<u32>,
start_after: Option<String>,
},
#[cfg_attr(feature = "schema", returns(PagedDealingsResponse))]
GetDealing {
idx: u64,
limit: Option<u32>,
start_after: Option<String>,
},
#[cfg_attr(feature = "schema", returns(PagedVKSharesResponse))]
GetVerificationKeys {
epoch_id: EpochId,
limit: Option<u32>,
@@ -73,6 +93,5 @@ pub enum QueryMsg {
},
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
#[serde(rename_all = "snake_case")]
#[cw_serde]
pub struct MigrateMsg {}
@@ -1,8 +1,7 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2022-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use cosmwasm_schema::cw_serde;
use std::fmt::{Display, Formatter};
use std::str::FromStr;
@@ -18,15 +17,14 @@ pub type EpochId = u64;
// 2 public attributes, 2 private attributes, 1 fixed for coconut credential
pub const TOTAL_DEALINGS: usize = 2 + 2 + 1;
#[derive(Serialize, Deserialize, Default, Clone, Debug, PartialEq, Eq, Ord, PartialOrd)]
#[cw_serde]
pub struct InitialReplacementData {
pub initial_dealers: Vec<Addr>,
pub initial_height: u64,
}
#[derive(
Serialize, Deserialize, Clone, Copy, Debug, PartialEq, Eq, Ord, PartialOrd, JsonSchema,
)]
#[cw_serde]
#[derive(Copy)]
pub struct TimeConfiguration {
// The time sign-up is open for dealers to join
pub public_key_submission_time_secs: u64,
@@ -75,8 +73,8 @@ impl Default for TimeConfiguration {
}
}
#[derive(Serialize, Deserialize, Default, Clone, Copy, Debug, PartialEq, Eq, Ord, PartialOrd)]
#[serde(rename_all = "snake_case")]
#[cw_serde]
#[derive(Copy, Default)]
pub struct Epoch {
pub state: EpochState,
pub epoch_id: EpochId,
@@ -155,8 +153,8 @@ impl Epoch {
// 8. InProgress -> all receivers have all their secrets derived and all is good
//
// Note: It's important that the variant ordering is not changed otherwise it would mess up the derived `PartialOrd`
#[derive(Serialize, Deserialize, Clone, Copy, Debug, PartialEq, Eq, Ord, PartialOrd)]
#[serde(rename_all = "snake_case")]
#[cw_serde]
#[derive(Copy)]
pub enum EpochState {
PublicKeySubmission { resharing: bool },
DealingExchange { resharing: bool },
@@ -3,14 +3,14 @@
use crate::msg::ExecuteMsg;
use crate::types::{EpochId, NodeIndex};
use cosmwasm_schema::cw_serde;
use cosmwasm_std::{from_binary, to_binary, Addr, CosmosMsg, StdResult, Timestamp, WasmMsg};
use cw_utils::Expiration;
use nym_multisig_contract_common::msg::ExecuteMsg as MultisigExecuteMsg;
use serde::{Deserialize, Serialize};
pub type VerificationKeyShare = String;
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
#[cw_serde]
pub struct ContractVKShare {
pub share: VerificationKeyShare,
pub announce_address: String,
@@ -20,11 +20,12 @@ pub struct ContractVKShare {
pub verified: bool,
}
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
#[serde(rename_all = "snake_case")]
#[cw_serde]
pub struct PagedVKSharesResponse {
pub shares: Vec<ContractVKShare>,
pub per_page: usize,
/// Field indicating paging information for the following queries if the caller wishes to get further entries.
pub start_next_after: Option<Addr>,
}
@@ -10,9 +10,10 @@ repository = { workspace = true }
[dependencies]
bs58 = "0.4.0"
cosmwasm-std = { workspace = true }
cosmwasm-schema = { workspace = true }
schemars = "0.8"
serde = { version = "1.0", features = ["derive"] }
thiserror = "1"
serde = { workspace = true, features = ["derive"] }
thiserror = { workspace = true }
[dev-dependencies]
serde_json = "1.0.0"
serde_json = { workspace = true }
@@ -1,8 +1,6 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
#[cfg(feature = "dkg")]
use nym_dkg::{error::DkgError, Dealing};
use schemars::JsonSchema;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::fmt::{Display, Formatter};
@@ -1,16 +1,17 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use cosmwasm_schema::cw_serde;
use cosmwasm_std::Decimal;
use cosmwasm_std::Uint128;
use schemars::JsonSchema;
use serde::de::Error;
use serde::{Deserialize, Deserializer, Serialize};
use serde::{Deserialize, Deserializer};
use std::fmt::{self, Display, Formatter};
use std::ops::Mul;
use std::str::FromStr;
use thiserror::Error;
/// Ed25519 public key strinfified into base58.
pub type IdentityKey = String;
pub type IdentityKeyRef<'a> = &'a str;
@@ -32,9 +33,8 @@ pub enum ContractsCommonError {
/// Percent represents a value between 0 and 100%
/// (i.e. between 0.0 and 1.0)
#[derive(
Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Serialize, Deserialize, JsonSchema,
)]
#[cw_serde]
#[derive(Copy, Default, PartialOrd)]
pub struct Percent(#[serde(deserialize_with = "de_decimal_percent")] Decimal);
impl Percent {
@@ -129,7 +129,7 @@ where
// TODO: there's no reason this couldn't be used for proper binaries, but in that case
// perhaps the struct should get renamed and moved to a "more" common crate
#[derive(Debug, Serialize, Deserialize)]
#[cw_serde]
pub struct ContractBuildInformation {
// VERGEN_BUILD_TIMESTAMP
/// Provides the build timestamp, for example `2021-02-23T20:14:46.558472672+00:00`.
@@ -46,3 +46,5 @@ pub enum QueryMsg {
#[returns(cw_controllers::HooksResponse)]
Hooks {},
}
#[cw_serde]
pub struct MigrateMsg {}
@@ -11,14 +11,16 @@ repository = { workspace = true }
[dependencies]
bs58 = "0.4.0"
cosmwasm-std = { workspace = true }
serde = { version = "1.0", features = ["derive"] }
cosmwasm-schema = { workspace = true }
cw2 = { workspace = true, optional = true }
serde = { workspace = true, features = ["derive"] }
serde_repr = "0.1"
# we still have to preserve that import for `JsonSchema` for `Layer` type (since we can't use cw_serde macro due to custom serde impl)
schemars = "0.8"
thiserror = "1.0"
contracts-common = { path = "../contracts-common", package = "nym-contracts-common", version = "0.5.0" }
# use 0.4.1 as that's the version used by cosmwasm-std 1.0.0
# (and ideally we don't want to pull the same dependency twice)
serde-json-wasm = "=0.4.1"
serde-json-wasm = { workspace = true }
humantime-serde = "1.1.1"
# TO CHECK WHETHER STILL NEEDED:
@@ -33,4 +35,5 @@ time = { version = "0.3.5", features = ["serde", "macros"] }
[features]
default = []
contract-testing = []
schema = ["cw2"]
generate-ts = ['ts-rs']
@@ -1,15 +1,11 @@
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
// due to code generated by JsonSchema
#![allow(clippy::field_reassign_with_default)]
use crate::constants::TOKEN_SUPPLY;
use crate::helpers::IntoBaseDecimal;
use crate::{Addr, MixId};
use cosmwasm_schema::cw_serde;
use cosmwasm_std::{Coin, Decimal, StdResult};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
// just use a string representation of those so that we wouldn't need to bother with decoding bytes
// and trying to figure out whether they're valid, etc
@@ -37,7 +33,9 @@ pub fn generate_owner_storage_subkey(
}
}
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq, JsonSchema)]
/// Information about tokens being delegated towards given mixnode in order to accrue rewards
/// with their work.
#[cw_serde]
pub struct Delegation {
/// Address of the owner of this delegation.
pub owner: Addr,
@@ -114,9 +112,13 @@ impl Delegation {
}
}
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
/// Response containing paged list of all delegations made towards particular mixnode.
#[cw_serde]
pub struct PagedMixNodeDelegationsResponse {
/// Each individual delegation made.
pub delegations: Vec<Delegation>,
/// Field indicating paging information for the following queries if the caller wishes to get further entries.
pub start_next_after: Option<OwnerProxySubKey>,
}
@@ -129,9 +131,13 @@ impl PagedMixNodeDelegationsResponse {
}
}
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
/// Response containing paged list of all delegations made by the particular address.
#[cw_serde]
pub struct PagedDelegatorDelegationsResponse {
/// Each individual delegation made.
pub delegations: Vec<Delegation>,
/// Field indicating paging information for the following queries if the caller wishes to get further entries.
pub start_next_after: Option<(MixId, OwnerProxySubKey)>,
}
@@ -147,9 +153,13 @@ impl PagedDelegatorDelegationsResponse {
}
}
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
/// Response containing delegation details.
#[cw_serde]
pub struct MixNodeDelegationResponse {
/// If the delegation exists, this field contains its detailed information.
pub delegation: Option<Delegation>,
/// Flag indicating whether the node towards which the delegation was made is still bonded in the network.
pub mixnode_still_bonded: bool,
}
@@ -162,9 +172,13 @@ impl MixNodeDelegationResponse {
}
}
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
/// Response containing paged list of all delegations currently active.
#[cw_serde]
pub struct PagedAllDelegationsResponse {
/// Each individual delegation made.
pub delegations: Vec<Delegation>,
/// Field indicating paging information for the following queries if the caller wishes to get further entries.
pub start_next_after: Option<StorageKey>,
}
@@ -165,6 +165,9 @@ pub enum MixnetContractError {
#[error("Family with head {head} does not exist!")]
FamilyDoesNotExist { head: String },
#[error("Family with label {label} does not exist!")]
FamilyLabelDoesNotExist { label: String },
#[error("Family with label '{0}' already exists")]
FamilyWithLabelExists(String),
@@ -1,22 +1,34 @@
// Copyright 2022-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::{IdentityKey, IdentityKeyRef};
use cosmwasm_schema::cw_serde;
use cosmwasm_std::Addr;
use schemars::JsonSchema;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::fmt::{Display, Formatter};
use std::str::FromStr;
/// A group of mixnodes associated with particular staking entity.
/// When defined all nodes belonging to the same family will be prioritised to be put onto the same layer.
#[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))]
#[cfg_attr(
feature = "generate-ts",
ts(export_to = "ts-packages/types/src/types/rust/NodeFamily.ts")
)]
#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq, JsonSchema)]
#[cw_serde]
pub struct Family {
/// Owner of this family.
head: FamilyHead,
/// Optional proxy (i.e. vesting contract address) used when creating the family.
proxy: Option<String>,
/// Human readable label for this family.
label: String,
}
/// Head of particular family as identified by its identity key (i.e. public component of its ed25519 keypair stringified into base58).
#[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))]
#[cfg_attr(
feature = "generate-ts",
@@ -62,8 +74,8 @@ impl Display for FamilyHead {
}
impl FamilyHead {
pub fn new(identity: IdentityKeyRef<'_>) -> Self {
FamilyHead(identity.to_string())
pub fn new<S: Into<String>>(identity: S) -> Self {
FamilyHead(identity.into())
}
pub fn identity(&self) -> IdentityKeyRef<'_> {
@@ -99,6 +111,66 @@ impl Family {
}
}
/// Response containing paged list of all families registered in the contract.
#[cw_serde]
pub struct PagedFamiliesResponse {
/// The families registered in the contract.
pub families: Vec<Family>,
/// Field indicating paging information for the following queries if the caller wishes to get further entries.
pub start_next_after: Option<String>,
}
/// Response containing paged list of all family members (of ALL families) registered in the contract.
#[cw_serde]
pub struct PagedMembersResponse {
/// The members alongside their family heads.
pub members: Vec<(IdentityKey, FamilyHead)>,
/// Field indicating paging information for the following queries if the caller wishes to get further entries.
pub start_next_after: Option<String>,
}
/// Response containing family information.
#[cw_serde]
pub struct FamilyByHeadResponse {
/// The family head used for the query.
pub head: FamilyHead,
/// If applicable, the family associated with the provided head.
pub family: Option<Family>,
}
/// Response containing family information.
#[cw_serde]
pub struct FamilyByLabelResponse {
/// The family label used for the query.
pub label: String,
/// If applicable, the family associated with the provided label.
pub family: Option<Family>,
}
/// Response containing family members information.
#[cw_serde]
pub struct FamilyMembersByHeadResponse {
/// The family head used for the query.
pub head: FamilyHead,
/// All members belonging to the specified family.
pub members: Vec<IdentityKey>,
}
/// Response containing family members information.
#[cw_serde]
pub struct FamilyMembersByLabelResponse {
/// The family label used for the query.
pub label: String,
/// All members belonging to the specified family.
pub members: Vec<IdentityKey>,
}
#[cfg(test)]
mod tests {
use super::*;
@@ -1,34 +1,56 @@
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
// due to code generated by JsonSchema
#![allow(clippy::field_reassign_with_default)]
use crate::{IdentityKey, SphinxKey};
use cosmwasm_schema::cw_serde;
use cosmwasm_std::{Addr, Coin};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use std::cmp::Ordering;
use std::fmt::Display;
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, PartialOrd, Serialize, JsonSchema)]
/// Information provided by the node operator during bonding that are used to allow other entities to use the services of this node.
#[cw_serde]
#[derive(PartialOrd)]
pub struct Gateway {
/// Network address of this gateway, for example 1.1.1.1 or foo.gateway.com
pub host: String,
/// Port used by this gateway for listening for mix packets.
pub mix_port: u16,
/// Port used by this gateway for listening for client requests.
pub clients_port: u16,
/// The physical, self-reported, location of this gateway.
// this field should be deprecated in favour of externally hosted information, like the mixnodes'.
pub location: String,
/// Base58-encoded x25519 public key used for sphinx key derivation.
pub sphinx_key: SphinxKey,
/// Base58 encoded ed25519 EdDSA public key of the gateway used to derive shared keys with clients
pub identity_key: IdentityKey,
/// The self-reported semver version of this gateway.
pub version: String,
}
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
/// Basic gateway information provided by the node operator.
#[cw_serde]
pub struct GatewayBond {
/// Original amount pledged by the operator of this node.
pub pledge_amount: Coin,
/// Address of the owner of this gateway.
pub owner: Addr,
/// Block height at which this gateway has been bonded.
pub block_height: u64,
/// Information provided by the operator for the purposes of bonding.
pub gateway: Gateway,
/// Entity who bonded this gateway on behalf of the owner.
/// If exists, it's most likely the address of the vesting contract.
pub proxy: Option<Addr>,
}
@@ -117,7 +139,7 @@ impl Display for GatewayBond {
feature = "generate-ts",
ts(export_to = "ts-packages/types/src/types/rust/GatewayConfigUpdate.ts")
)]
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
#[cw_serde]
pub struct GatewayConfigUpdate {
pub host: String,
pub mix_port: u16,
@@ -132,10 +154,17 @@ impl GatewayConfigUpdate {
}
}
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
/// Response containing paged list of all gateway bonds in the contract.
#[cw_serde]
pub struct PagedGatewayResponse {
/// The gateway bond information present in the contract.
pub nodes: Vec<GatewayBond>,
/// Maximum number of entries that could be included in a response. `per_page <= nodes.len()`
// this field is rather redundant and should be deprecated.
pub per_page: usize,
/// Field indicating paging information for the following queries if the caller wishes to get further entries.
pub start_next_after: Option<IdentityKey>,
}
@@ -153,15 +182,23 @@ impl PagedGatewayResponse {
}
}
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
/// Response containing details of a gateway belonging to the particular owner.
#[cw_serde]
pub struct GatewayOwnershipResponse {
/// Validated address of the gateway owner.
pub address: Addr,
/// If the provided address owns a gateway, this field contains its details.
pub gateway: Option<GatewayBond>,
}
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
/// Response containing details of a gateway with the provided identity key.
#[cw_serde]
pub struct GatewayBondResponse {
/// The identity key (base58-encoded ed25519 public key) of the gateway.
pub identity: IdentityKey,
/// If there exists a gateway with the provided identity key, this field contains its details.
pub gateway: Option<GatewayBond>,
}
@@ -2,20 +2,20 @@
// SPDX-License-Identifier: Apache-2.0
use crate::error::MixnetContractError;
use crate::pending_events::{PendingEpochEvent, PendingIntervalEvent};
use crate::{
EpochEventId, EpochId, IntervalEventId, IntervalId, MixId, PendingEpochEventData,
PendingIntervalEventData,
};
use crate::MixId;
use cosmwasm_schema::cw_serde;
use cosmwasm_schema::schemars::gen::SchemaGenerator;
use cosmwasm_schema::schemars::schema::{InstanceType, Schema, SchemaObject};
use cosmwasm_schema::schemars::JsonSchema;
use cosmwasm_std::{Addr, Env};
use schemars::gen::SchemaGenerator;
use schemars::schema::{InstanceType, Schema, SchemaObject};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use std::fmt::{Display, Formatter};
use std::time::Duration;
use time::OffsetDateTime;
pub type EpochId = u32;
pub type IntervalId = u32;
// internally, since version 0.3.6, time uses deserialize_any for deserialization, which can't be handled
// by serde wasm. We could just downgrade to 0.3.5 and call it a day, but then it would break
// when we decided to upgrade it at some point in the future. And then it would have been more problematic
@@ -64,12 +64,15 @@ pub(crate) mod string_rfc3339_offset_date_time {
}
}
#[derive(Debug, Serialize, Deserialize, Eq, PartialEq)]
/// The status of the current rewarding epoch.
#[cw_serde]
pub struct EpochStatus {
// TODO: introduce mechanism to allow another validator to take over if no progress has been made in X blocks / Y seconds
/// Specifies either, which validator is currently performing progression into the following epoch (if the epoch is currently being progressed),
/// or which validator was responsible for progressing into the current epoch (if the epoch is currently in progress)
pub being_advanced_by: Addr,
/// The concrete state of the epoch.
pub state: EpochState,
}
@@ -150,7 +153,9 @@ impl EpochStatus {
}
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, Eq, PartialEq)]
/// The state of the current rewarding epoch.
#[cw_serde]
#[derive(Copy)]
pub enum EpochState {
/// Represents the state of an epoch that's in progress (well, duh.)
/// All actions are allowed to be issued.
@@ -159,8 +164,10 @@ pub enum EpochState {
/// Represents the state of an epoch when the rewarding entity has been decided on,
/// and the mixnodes are in the process of being rewarded for their work in this epoch.
Rewarding {
/// The id of the last node that has already received its rewards.
last_rewarded: MixId,
/// The id of the last node that's going to be rewarded before progressing into the next state.
final_node_id: MixId,
// total_rewarded: u32,
},
@@ -191,6 +198,7 @@ impl Display for EpochState {
}
}
/// Specification of a rewarding interval.
#[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))]
#[cfg_attr(
feature = "generate-ts",
@@ -198,7 +206,10 @@ impl Display for EpochState {
)]
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Eq, Serialize)]
pub struct Interval {
/// Monotonously increasing id of this interval.
id: IntervalId,
/// Number of epochs in this interval.
epochs_in_interval: u32,
// TODO add a better TS type generation
@@ -207,10 +218,17 @@ pub struct Interval {
// note: the `ts-rs failed to parse this attribute. It will be ignored.` warning emitted during
// compilation is fine (I guess). `ts-rs` can't handle `with` serde attribute, but that's okay
// since we explicitly specified this field should correspond to typescript's string
/// The timestamp indicating the start of the current rewarding epoch.
current_epoch_start: OffsetDateTime,
/// Monotonously increasing id of the current epoch in this interval.
current_epoch_id: EpochId,
/// The duration of all epochs in this interval.
#[cfg_attr(feature = "generate-ts", ts(type = "{ secs: number; nanos: number; }"))]
epoch_length: Duration,
/// The total amount of elapsed epochs since the first epoch of the first interval.
total_elapsed_epochs: EpochId,
}
@@ -455,11 +473,19 @@ impl Display for Interval {
}
}
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Eq, Serialize)]
/// Information about the current rewarding interval.
#[cw_serde]
pub struct CurrentIntervalResponse {
/// Detailed information about the underlying interval.
pub interval: Interval,
/// The current blocktime
pub current_blocktime: u64,
/// Flag indicating whether the current interval is over and it should be advanced.
pub is_current_interval_over: bool,
/// Flag indicating whether the current epoch is over and it should be advanced.
pub is_current_epoch_over: bool,
}
@@ -489,87 +515,6 @@ impl CurrentIntervalResponse {
}
}
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
pub struct PendingEpochEventsResponse {
pub seconds_until_executable: i64,
pub events: Vec<PendingEpochEvent>,
pub start_next_after: Option<u32>,
}
impl PendingEpochEventsResponse {
pub fn new(
seconds_until_executable: i64,
events: Vec<PendingEpochEvent>,
start_next_after: Option<u32>,
) -> Self {
PendingEpochEventsResponse {
seconds_until_executable,
events,
start_next_after,
}
}
}
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
pub struct PendingIntervalEventsResponse {
pub seconds_until_executable: i64,
pub events: Vec<PendingIntervalEvent>,
pub start_next_after: Option<u32>,
}
impl PendingIntervalEventsResponse {
pub fn new(
seconds_until_executable: i64,
events: Vec<PendingIntervalEvent>,
start_next_after: Option<u32>,
) -> Self {
PendingIntervalEventsResponse {
seconds_until_executable,
events,
start_next_after,
}
}
}
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
pub struct PendingEpochEventResponse {
pub event_id: EpochEventId,
pub event: Option<PendingEpochEventData>,
}
impl PendingEpochEventResponse {
pub fn new(event_id: EpochEventId, event: Option<PendingEpochEventData>) -> Self {
PendingEpochEventResponse { event_id, event }
}
}
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
pub struct PendingIntervalEventResponse {
pub event_id: IntervalEventId,
pub event: Option<PendingIntervalEventData>,
}
impl PendingIntervalEventResponse {
pub fn new(event_id: IntervalEventId, event: Option<PendingIntervalEventData>) -> Self {
PendingIntervalEventResponse { event_id, event }
}
}
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
pub struct NumberOfPendingEventsResponse {
pub epoch_events: u32,
pub interval_events: u32,
}
impl NumberOfPendingEventsResponse {
pub fn new(epoch_events: u32, interval_events: u32) -> Self {
Self {
epoch_events,
interval_events,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
@@ -11,14 +11,14 @@ pub mod events;
pub mod families;
pub mod gateway;
pub mod helpers;
mod interval;
pub mod interval;
pub mod mixnode;
mod msg;
pub mod msg;
pub mod pending_events;
pub mod reward_params;
pub mod rewarding;
pub mod signing_types;
mod types;
pub mod types;
pub use contracts_common::types::*;
pub use cosmwasm_std::{Addr, Coin, Decimal, Fraction};
@@ -26,25 +26,32 @@ pub use delegation::{
Delegation, PagedAllDelegationsResponse, PagedDelegatorDelegationsResponse,
PagedMixNodeDelegationsResponse,
};
pub use families::{
Family, FamilyByHeadResponse, FamilyByLabelResponse, FamilyHead, FamilyMembersByHeadResponse,
FamilyMembersByLabelResponse, PagedFamiliesResponse, PagedMembersResponse,
};
pub use gateway::{
Gateway, GatewayBond, GatewayBondResponse, GatewayConfigUpdate, GatewayOwnershipResponse,
PagedGatewayResponse,
};
pub use interval::{
CurrentIntervalResponse, EpochState, EpochStatus, Interval, NumberOfPendingEventsResponse,
PendingEpochEventResponse, PendingEpochEventsResponse, PendingIntervalEventResponse,
PendingIntervalEventsResponse,
CurrentIntervalResponse, EpochId, EpochState, EpochStatus, Interval, IntervalId,
};
pub use mixnode::{
Layer, MixNode, MixNodeBond, MixNodeConfigUpdate, MixNodeCostParams, MixNodeDetails,
MixNodeRewarding, MixOwnershipResponse, MixnodeDetailsResponse, PagedMixnodeBondsResponse,
RewardedSetNodeStatus, UnbondedMixnode,
MixNodeRewarding, MixOwnershipResponse, MixnodeDetailsByIdentityResponse,
MixnodeDetailsResponse, PagedMixnodeBondsResponse, RewardedSetNodeStatus, UnbondedMixnode,
};
pub use msg::*;
pub use pending_events::{
PendingEpochEvent, PendingEpochEventData, PendingEpochEventKind, PendingIntervalEvent,
PendingIntervalEventData, PendingIntervalEventKind,
EpochEventId, IntervalEventId, NumberOfPendingEventsResponse, PendingEpochEvent,
PendingEpochEventData, PendingEpochEventKind, PendingEpochEventResponse,
PendingEpochEventsResponse, PendingIntervalEvent, PendingIntervalEventData,
PendingIntervalEventKind, PendingIntervalEventResponse, PendingIntervalEventsResponse,
};
pub use reward_params::{IntervalRewardParams, IntervalRewardingParamsUpdate, RewardingParams};
pub use rewarding::{
EstimatedCurrentEpochRewardResponse, PagedRewardedSetResponse, PendingRewardResponse,
};
pub use signing_types::*;
pub use types::*;
@@ -11,19 +11,24 @@ use crate::reward_params::{NodeRewardParams, RewardingParams};
use crate::rewarding::helpers::truncate_reward;
use crate::rewarding::RewardDistribution;
use crate::{Delegation, EpochEventId, EpochId, IdentityKey, MixId, Percent, SphinxKey};
use cosmwasm_schema::cw_serde;
use cosmwasm_std::{Addr, Coin, Decimal, StdResult, Uint128};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use serde_repr::{Deserialize_repr, Serialize_repr};
/// Current state of given node in the rewarded set.
#[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))]
#[cfg_attr(
feature = "generate-ts",
ts(export_to = "ts-packages/types/src/types/rust/RewardedSetNodeStatus.ts")
)]
#[derive(Clone, Copy, Debug, Deserialize, Serialize, JsonSchema, PartialEq, Eq)]
#[cw_serde]
#[derive(Copy)]
pub enum RewardedSetNodeStatus {
/// Node that is currently active, i.e. is expected to be used by clients for mixing packets.
Active,
/// Node that is currently in standby, i.e. it's present in the rewarded set but is not active.
Standby,
}
@@ -33,10 +38,16 @@ impl RewardedSetNodeStatus {
}
}
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
/// Full details associated with given mixnode.
#[cw_serde]
pub struct MixNodeDetails {
/// Basic bond information of this mixnode, such as owner address, original pledge, etc.
pub bond_information: MixNodeBond,
/// Details used for computation of rewarding related data.
pub rewarding_details: MixNodeRewarding,
/// Adjustments to the mixnode that are ought to happen during future epoch transitions.
#[serde(default)]
pub pending_changes: PendingMixNodeChanges,
}
@@ -58,6 +69,10 @@ impl MixNodeDetails {
self.bond_information.mix_id
}
pub fn layer(&self) -> Layer {
self.bond_information.layer
}
pub fn is_unbonding(&self) -> bool {
self.bond_information.is_unbonding
}
@@ -86,7 +101,7 @@ impl MixNodeDetails {
}
}
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
#[cw_serde]
pub struct MixNodeRewarding {
/// Information provided by the operator that influence the cost function.
pub cost_params: MixNodeCostParams,
@@ -464,8 +479,8 @@ impl MixNodeRewarding {
}
}
// operator information + data assigned by the contract(s)
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
/// Basic mixnode information provided by the node operator.
#[cw_serde]
pub struct MixNodeBond {
/// Unique id assigned to the bonded mixnode.
pub mix_id: MixId,
@@ -533,21 +548,24 @@ impl MixNodeBond {
}
}
// information provided by the operator
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
/// Information provided by the node operator during bonding that are used to allow other entities to use the services of this node.
#[cw_serde]
#[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))]
#[cfg_attr(
feature = "generate-ts",
ts(export_to = "ts-packages/types/src/types/rust/Mixnode.ts")
)]
pub struct MixNode {
/// Network address of this mixnode, for example 1.1.1.1:1234 or foo.mixnode.com
/// Network address of this mixnode, for example 1.1.1.1 or foo.mixnode.com
pub host: String,
/// Port used by this mixnode for listening for mix packets.
pub mix_port: u16,
/// Port used by this mixnode for listening for verloc requests.
pub verloc_port: u16,
/// Port used by this mixnode for its http(s) API
pub http_api_port: u16,
/// Base58-encoded x25519 public key used for sphinx key derivation.
@@ -556,11 +574,15 @@ pub struct MixNode {
/// Base58-encoded ed25519 EdDSA public key.
pub identity_key: IdentityKey,
/// The self-reported semver version of this mixnode.
pub version: String,
}
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
/// The cost parameters, or the cost function, defined for the particular mixnode that influences
/// how the rewards should be split between the node operator and its delegators.
#[cw_serde]
pub struct MixNodeCostParams {
/// The profit margin of the associated mixnode, i.e. the desired percent of the reward to be distributed to the operator.
pub profit_margin_percent: Percent,
/// Operating cost of the associated mixnode per the entire interval.
@@ -633,7 +655,8 @@ impl From<Layer> for u8 {
feature = "generate-ts",
ts(export_to = "ts-packages/types/src/types/rust/PendingMixnodeChanges.ts")
)]
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
#[cw_serde]
#[derive(Default, Copy)]
pub struct PendingMixNodeChanges {
pub pledge_change: Option<EpochEventId>,
// pub cost_params_change: Option<IntervalEventId>,
@@ -647,21 +670,27 @@ impl PendingMixNodeChanges {
}
}
/// Basic information of a node that used to be part of the mix network but has already unbonded.
#[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))]
#[cfg_attr(
feature = "generate-ts",
ts(export_to = "ts-packages/types/src/types/rust/UnbondedMixnode.ts")
)]
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
#[cw_serde]
pub struct UnbondedMixnode {
/// Base58-encoded ed25519 EdDSA public key.
pub identity_key: IdentityKey,
/// Address of the owner of this mixnode.
#[cfg_attr(feature = "generate-ts", ts(type = "string"))]
pub owner: Addr,
/// Entity who bonded this mixnode on behalf of the owner.
/// If exists, it's most likely the address of the vesting contract.
#[cfg_attr(feature = "generate-ts", ts(type = "string | null"))]
pub proxy: Option<Addr>,
/// Block height at which this mixnode has unbonded.
#[cfg_attr(feature = "generate-ts", ts(type = "number"))]
pub unbonding_height: u64,
}
@@ -671,7 +700,7 @@ pub struct UnbondedMixnode {
feature = "generate-ts",
ts(export_to = "ts-packages/types/src/types/rust/MixNodeConfigUpdate.ts")
)]
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
#[cw_serde]
pub struct MixNodeConfigUpdate {
pub host: String,
pub mix_port: u16,
@@ -686,10 +715,17 @@ impl MixNodeConfigUpdate {
}
}
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
/// Response containing paged list of all mixnode bonds in the contract.
#[cw_serde]
pub struct PagedMixnodeBondsResponse {
/// The mixnode bond information present in the contract.
pub nodes: Vec<MixNodeBond>,
/// Maximum number of entries that could be included in a response. `per_page <= nodes.len()`
// this field is rather redundant and should be deprecated.
pub per_page: usize,
/// Field indicating paging information for the following queries if the caller wishes to get further entries.
pub start_next_after: Option<MixId>,
}
@@ -703,10 +739,19 @@ impl PagedMixnodeBondsResponse {
}
}
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
/// Response containing paged list of all mixnode details in the contract.
#[cw_serde]
pub struct PagedMixnodesDetailsResponse {
/// All mixnode details stored in the contract.
/// Apart from the basic bond information it also contains details required for all future reward calculation
/// as well as any pending changes requested by the operator.
pub nodes: Vec<MixNodeDetails>,
/// Maximum number of entries that could be included in a response. `per_page <= nodes.len()`
// this field is rather redundant and should be deprecated.
pub per_page: usize,
/// Field indicating paging information for the following queries if the caller wishes to get further entries.
pub start_next_after: Option<MixId>,
}
@@ -724,10 +769,17 @@ impl PagedMixnodesDetailsResponse {
}
}
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
/// Response containing paged list of all mixnodes that have ever unbonded.
#[cw_serde]
pub struct PagedUnbondedMixnodesResponse {
/// The past ids of unbonded mixnodes alongside their basic information such as the owner or the identity key.
pub nodes: Vec<(MixId, UnbondedMixnode)>,
/// Maximum number of entries that could be included in a response. `per_page <= nodes.len()`
// this field is rather redundant and should be deprecated.
pub per_page: usize,
/// Field indicating paging information for the following queries if the caller wishes to get further entries.
pub start_next_after: Option<MixId>,
}
@@ -745,33 +797,68 @@ impl PagedUnbondedMixnodesResponse {
}
}
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
/// Response containing details of a mixnode belonging to the particular owner.
#[cw_serde]
pub struct MixOwnershipResponse {
/// Validated address of the mixnode owner.
pub address: Addr,
/// If the provided address owns a mixnode, this field contains its detailed information.
pub mixnode_details: Option<MixNodeDetails>,
}
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
/// Response containing details of a mixnode with the provided id.
#[cw_serde]
pub struct MixnodeDetailsResponse {
/// Id of the requested mixnode.
pub mix_id: MixId,
/// If there exists a mixnode with the provided id, this field contains its detailed information.
pub mixnode_details: Option<MixNodeDetails>,
}
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
/// Response containing details of a bonded mixnode with the provided identity key.
#[cw_serde]
pub struct MixnodeDetailsByIdentityResponse {
/// The identity key (base58-encoded ed25519 public key) of the mixnode.
pub identity_key: IdentityKey,
/// If there exists a bonded mixnode with the provided identity key, this field contains its detailed information.
pub mixnode_details: Option<MixNodeDetails>,
}
/// Response containing rewarding information of a mixnode with the provided id.
#[cw_serde]
pub struct MixnodeRewardingDetailsResponse {
/// Id of the requested mixnode.
pub mix_id: MixId,
/// If there exists a mixnode with the provided id, this field contains its rewarding information.
pub rewarding_details: Option<MixNodeRewarding>,
}
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
/// Response containing basic information of an unbonded mixnode with the provided id.
#[cw_serde]
pub struct UnbondedMixnodeResponse {
/// Id of the requested mixnode.
pub mix_id: MixId,
/// If there existed a mixnode with the provided id, this field contains its basic information.
pub unbonded_info: Option<UnbondedMixnode>,
}
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
/// Response containing the current state of the stake saturation of a mixnode with the provided id.
#[cw_serde]
pub struct StakeSaturationResponse {
/// Id of the requested mixnode.
pub mix_id: MixId,
/// The current stake saturation of this node that is indirectly used in reward calculation formulas.
/// Note that it can't be larger than 1.
pub current_saturation: Option<Decimal>,
/// The current, absolute, stake saturation of this node.
/// Note that as the name suggests it can be larger than 1.
/// However, anything beyond that value has no effect on the total node reward.
pub uncapped_saturation: Option<Decimal>,
}
@@ -1,28 +1,54 @@
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::delegation::OwnerProxySubKey;
use crate::delegation::{self, OwnerProxySubKey};
use crate::error::MixnetContractError;
use crate::families::FamilyHead;
use crate::gateway::GatewayConfigUpdate;
use crate::gateway::{Gateway, GatewayConfigUpdate};
use crate::helpers::IntoBaseDecimal;
use crate::mixnode::{MixNodeConfigUpdate, MixNodeCostParams};
use crate::mixnode::{Layer, MixNode, MixNodeConfigUpdate, MixNodeCostParams};
use crate::pending_events::{EpochEventId, IntervalEventId};
use crate::reward_params::{
IntervalRewardParams, IntervalRewardingParamsUpdate, Performance, RewardingParams,
};
use crate::{
delegation, ContractStateParams, EpochEventId, IntervalEventId, Layer, LayerAssignment, MixId,
Percent,
};
use crate::{Gateway, IdentityKey, MixNode};
use contracts_common::signing::MessageSignature;
use crate::types::{ContractStateParams, LayerAssignment, MixId};
use contracts_common::{signing::MessageSignature, IdentityKey, Percent};
use cosmwasm_schema::cw_serde;
use cosmwasm_std::{Coin, Decimal};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use std::time::Duration;
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
#[serde(rename_all = "snake_case")]
#[cfg(feature = "schema")]
use crate::{
delegation::{
MixNodeDelegationResponse, PagedAllDelegationsResponse, PagedDelegatorDelegationsResponse,
PagedMixNodeDelegationsResponse,
},
families::{
FamilyByHeadResponse, FamilyByLabelResponse, FamilyMembersByHeadResponse,
FamilyMembersByLabelResponse, PagedFamiliesResponse, PagedMembersResponse,
},
gateway::{GatewayBondResponse, GatewayOwnershipResponse, PagedGatewayResponse},
interval::{CurrentIntervalResponse, EpochStatus},
mixnode::{
MixOwnershipResponse, MixnodeDetailsByIdentityResponse, MixnodeDetailsResponse,
MixnodeRewardingDetailsResponse, PagedMixnodeBondsResponse, PagedMixnodesDetailsResponse,
PagedUnbondedMixnodesResponse, StakeSaturationResponse, UnbondedMixnodeResponse,
},
pending_events::{
NumberOfPendingEventsResponse, PendingEpochEventResponse, PendingEpochEventsResponse,
PendingIntervalEventResponse, PendingIntervalEventsResponse,
},
rewarding::{
EstimatedCurrentEpochRewardResponse, PagedRewardedSetResponse, PendingRewardResponse,
},
types::{ContractState, LayerDistribution},
};
#[cfg(feature = "schema")]
use contracts_common::{signing::Nonce, ContractBuildInformation};
#[cfg(feature = "schema")]
use cosmwasm_schema::QueryResponses;
#[cw_serde]
pub struct InstantiateMsg {
pub rewarding_validator_address: String,
pub vesting_contract_address: String,
@@ -33,8 +59,7 @@ pub struct InstantiateMsg {
pub initial_rewarding_params: InitialRewardingParams,
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
#[serde(rename_all = "snake_case")]
#[cw_serde]
pub struct InitialRewardingParams {
pub initial_reward_pool: Decimal,
pub initial_staking_supply: Decimal,
@@ -76,8 +101,7 @@ impl InitialRewardingParams {
}
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
#[cw_serde]
pub enum ExecuteMsg {
AssignNodeLayer {
mix_id: MixId,
@@ -365,177 +389,376 @@ impl ExecuteMsg {
}
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
#[serde(rename_all = "snake_case")]
#[cw_serde]
#[cfg_attr(feature = "schema", derive(QueryResponses))]
pub enum QueryMsg {
// families
/// Gets the list of families registered in this contract.
#[cfg_attr(feature = "schema", returns(PagedFamiliesResponse))]
GetAllFamiliesPaged {
/// Controls the maximum number of entries returned by the query. Note that too large values will be overwritten by a saner default.
limit: Option<u32>,
/// Pagination control for the values returned by the query. Note that the provided value itself will **not** be used for the response.
start_after: Option<String>,
},
/// Gets the list of all family members registered in this contract.
#[cfg_attr(feature = "schema", returns(PagedMembersResponse))]
GetAllMembersPaged {
/// Controls the maximum number of entries returned by the query. Note that too large values will be overwritten by a saner default.
limit: Option<u32>,
/// Pagination control for the values returned by the query. Note that the provided value itself will **not** be used for the response.
start_after: Option<String>,
},
GetFamilyByHead {
head: String,
},
GetFamilyByLabel {
label: String,
},
GetFamilyMembersByHead {
head: String,
},
GetFamilyMembersByLabel {
label: String,
},
/// Attempts to lookup family information given the family head.
#[cfg_attr(feature = "schema", returns(FamilyByHeadResponse))]
GetFamilyByHead { head: String },
/// Attempts to lookup family information given the family label.
#[cfg_attr(feature = "schema", returns(FamilyByLabelResponse))]
GetFamilyByLabel { label: String },
/// Attempts to retrieve family members given the family head.
#[cfg_attr(feature = "schema", returns(FamilyMembersByHeadResponse))]
GetFamilyMembersByHead { head: String },
/// Attempts to retrieve family members given the family label.
#[cfg_attr(feature = "schema", returns(FamilyMembersByLabelResponse))]
GetFamilyMembersByLabel { label: String },
// state/sys-params-related
/// Gets build information of this contract, such as the commit hash used for the build or rustc version.
#[cfg_attr(feature = "schema", returns(ContractBuildInformation))]
GetContractVersion {},
/// Gets the stored contract version information that's required by the CW2 spec interface for migrations.
#[serde(rename = "get_cw2_contract_version")]
#[cfg_attr(feature = "schema", returns(cw2::ContractVersion))]
GetCW2ContractVersion {},
/// Gets the address of the validator that's allowed to send rewarding transactions and transition the epoch.
#[cfg_attr(feature = "schema", returns(String))]
GetRewardingValidatorAddress {},
/// Gets the contract parameters that could be adjusted in a transaction by the contract admin.
#[cfg_attr(feature = "schema", returns(ContractStateParams))]
GetStateParams {},
/// Gets the current state of the contract.
#[cfg_attr(feature = "schema", returns(ContractState))]
GetState {},
/// Gets the current parameters used for reward calculation.
#[cfg_attr(feature = "schema", returns(RewardingParams))]
GetRewardingParams {},
/// Gets the status of the current rewarding epoch.
#[cfg_attr(feature = "schema", returns(EpochStatus))]
GetEpochStatus {},
/// Get the details of the current rewarding interval.
#[cfg_attr(feature = "schema", returns(CurrentIntervalResponse))]
GetCurrentIntervalDetails {},
/// Gets the current list of mixnodes in the rewarded set.
#[cfg_attr(feature = "schema", returns(PagedRewardedSetResponse))]
GetRewardedSet {
/// Controls the maximum number of entries returned by the query. Note that too large values will be overwritten by a saner default.
limit: Option<u32>,
/// Pagination control for the values returned by the query. Note that the provided value itself will **not** be used for the response.
start_after: Option<MixId>,
},
// mixnode-related:
/// Gets the basic list of all currently bonded mixnodes.
#[cfg_attr(feature = "schema", returns(PagedMixnodeBondsResponse))]
GetMixNodeBonds {
/// Controls the maximum number of entries returned by the query. Note that too large values will be overwritten by a saner default.
limit: Option<u32>,
/// Pagination control for the values returned by the query. Note that the provided value itself will **not** be used for the response.
start_after: Option<MixId>,
},
/// Gets the detailed list of all currently bonded mixnodes.
#[cfg_attr(feature = "schema", returns(PagedMixnodesDetailsResponse))]
GetMixNodesDetailed {
/// Controls the maximum number of entries returned by the query. Note that too large values will be overwritten by a saner default.
limit: Option<u32>,
/// Pagination control for the values returned by the query. Note that the provided value itself will **not** be used for the response.
start_after: Option<MixId>,
},
/// Gets the basic list of all unbonded mixnodes.
#[cfg_attr(feature = "schema", returns(PagedUnbondedMixnodesResponse))]
GetUnbondedMixNodes {
/// Controls the maximum number of entries returned by the query. Note that too large values will be overwritten by a saner default.
limit: Option<u32>,
/// Pagination control for the values returned by the query. Note that the provided value itself will **not** be used for the response.
start_after: Option<MixId>,
},
/// Gets the basic list of all unbonded mixnodes that belonged to a particular owner.
#[cfg_attr(feature = "schema", returns(PagedUnbondedMixnodesResponse))]
GetUnbondedMixNodesByOwner {
/// The address of the owner of the the mixnodes used for the query.
owner: String,
/// Controls the maximum number of entries returned by the query. Note that too large values will be overwritten by a saner default.
limit: Option<u32>,
/// Pagination control for the values returned by the query. Note that the provided value itself will **not** be used for the response.
start_after: Option<MixId>,
},
/// Gets the basic list of all unbonded mixnodes that used the particular identity key.
#[cfg_attr(feature = "schema", returns(PagedUnbondedMixnodesResponse))]
GetUnbondedMixNodesByIdentityKey {
/// The identity key (base58-encoded ed25519 public key) of the mixnode used for the query.
identity_key: String,
/// Controls the maximum number of entries returned by the query. Note that too large values will be overwritten by a saner default.
limit: Option<u32>,
/// Pagination control for the values returned by the query. Note that the provided value itself will **not** be used for the response.
start_after: Option<MixId>,
},
/// Gets the detailed mixnode information belonging to the particular owner.
#[cfg_attr(feature = "schema", returns(MixOwnershipResponse))]
GetOwnedMixnode {
/// Address of the mixnode owner to use for the query.
address: String,
},
/// Gets the detailed mixnode information of a node with the provided id.
#[cfg_attr(feature = "schema", returns(MixnodeDetailsResponse))]
GetMixnodeDetails {
/// Id of the node to query.
mix_id: MixId,
},
/// Gets the rewarding information of a mixnode with the provided id.
#[cfg_attr(feature = "schema", returns(MixnodeRewardingDetailsResponse))]
GetMixnodeRewardingDetails {
/// Id of the node to query.
mix_id: MixId,
},
/// Gets the stake saturation of a mixnode with the provided id.
#[cfg_attr(feature = "schema", returns(StakeSaturationResponse))]
GetStakeSaturation {
/// Id of the node to query.
mix_id: MixId,
},
/// Gets the basic information of an unbonded mixnode with the provided id.
#[cfg_attr(feature = "schema", returns(UnbondedMixnodeResponse))]
GetUnbondedMixNodeInformation {
/// Id of the node to query.
mix_id: MixId,
},
/// Gets the detailed mixnode information of a node given its current identity key.
#[cfg_attr(feature = "schema", returns(MixnodeDetailsByIdentityResponse))]
GetBondedMixnodeDetailsByIdentity {
/// The identity key (base58-encoded ed25519 public key) of the mixnode used for the query.
mix_identity: IdentityKey,
},
/// Gets the current layer configuration of the mix network.
#[cfg_attr(feature = "schema", returns(LayerDistribution))]
GetLayerDistribution {},
// gateway-related:
/// Gets the basic list of all currently bonded gateways.
#[cfg_attr(feature = "schema", returns(PagedGatewayResponse))]
GetGateways {
/// Pagination control for the values returned by the query. Note that the provided value itself will **not** be used for the response.
start_after: Option<IdentityKey>,
/// Controls the maximum number of entries returned by the query. Note that too large values will be overwritten by a saner default.
limit: Option<u32>,
},
/// Gets the gateway details of a node given its identity key.
#[cfg_attr(feature = "schema", returns(GatewayBondResponse))]
GetGatewayBond {
/// The identity key (base58-encoded ed25519 public key) of the gateway used for the query.
identity: IdentityKey,
},
/// Gets the detailed gateway information belonging to the particular owner.
#[cfg_attr(feature = "schema", returns(GatewayOwnershipResponse))]
GetOwnedGateway {
/// Address of the gateway owner to use for the query.
address: String,
},
// delegation-related:
// gets all [paged] delegations associated with particular mixnode
/// Gets all delegations associated with particular mixnode
#[cfg_attr(feature = "schema", returns(PagedMixNodeDelegationsResponse))]
GetMixnodeDelegations {
/// Id of the node to query.
mix_id: MixId,
// since `start_after` is user-provided input, we can't use `Addr` as we
// can't guarantee it's validated.
start_after: Option<String>,
/// Pagination control for the values returned by the query. Note that the provided value itself will **not** be used for the response.
start_after: Option<OwnerProxySubKey>,
/// Controls the maximum number of entries returned by the query. Note that too large values will be overwritten by a saner default.
limit: Option<u32>,
},
// gets all [paged] delegations associated with particular delegator
/// Gets all delegations associated with particular delegator
#[cfg_attr(feature = "schema", returns(PagedDelegatorDelegationsResponse))]
GetDelegatorDelegations {
// since `delegator` is user-provided input, we can't use `Addr` as we
// can't guarantee it's validated.
/// The address of the owner of the delegations.
delegator: String,
/// Pagination control for the values returned by the query. Note that the provided value itself will **not** be used for the response.
start_after: Option<(MixId, OwnerProxySubKey)>,
/// Controls the maximum number of entries returned by the query. Note that too large values will be overwritten by a saner default.
limit: Option<u32>,
},
// gets delegation associated with particular mixnode, delegator pair
/// Gets delegation information associated with particular mixnode - delegator pair
#[cfg_attr(feature = "schema", returns(MixNodeDelegationResponse))]
GetDelegationDetails {
/// Id of the node to query.
mix_id: MixId,
/// The address of the owner of the delegation.
delegator: String,
/// Entity who made the delegation on behalf of the owner.
/// If present, it's most likely the address of the vesting contract.
proxy: Option<String>,
},
// gets all delegations in the system
/// Gets all delegations in the system
#[cfg_attr(feature = "schema", returns(PagedAllDelegationsResponse))]
GetAllDelegations {
/// Pagination control for the values returned by the query. Note that the provided value itself will **not** be used for the response.
start_after: Option<delegation::StorageKey>,
/// Controls the maximum number of entries returned by the query. Note that too large values will be overwritten by a saner default.
limit: Option<u32>,
},
// rewards related
/// Gets the reward amount accrued by the node operator that has not yet been claimed.
#[cfg_attr(feature = "schema", returns(PendingRewardResponse))]
GetPendingOperatorReward {
/// Address of the operator to use for the query.
address: String,
},
/// Gets the reward amount accrued by the particular mixnode that has not yet been claimed.
#[cfg_attr(feature = "schema", returns(PendingRewardResponse))]
GetPendingMixNodeOperatorReward {
/// Id of the node to query.
mix_id: MixId,
},
/// Gets the reward amount accrued by the particular delegator that has not yet been claimed.
#[cfg_attr(feature = "schema", returns(PendingRewardResponse))]
GetPendingDelegatorReward {
/// Address of the delegator to use for the query.
address: String,
/// Id of the node to query.
mix_id: MixId,
/// Entity who made the delegation on behalf of the owner.
/// If present, it's most likely the address of the vesting contract.
proxy: Option<String>,
},
// given the provided performance, estimate the reward at the end of the current epoch
/// Given the provided node performance, attempt to estimate the operator reward for the current epoch.
#[cfg_attr(feature = "schema", returns(EstimatedCurrentEpochRewardResponse))]
GetEstimatedCurrentEpochOperatorReward {
/// Id of the node to query.
mix_id: MixId,
/// The estimated performance for the current epoch of the given node.
estimated_performance: Performance,
},
/// Given the provided node performance, attempt to estimate the delegator reward for the current epoch.
#[cfg_attr(feature = "schema", returns(EstimatedCurrentEpochRewardResponse))]
GetEstimatedCurrentEpochDelegatorReward {
/// Address of the delegator to use for the query.
address: String,
/// Id of the node to query.
mix_id: MixId,
/// Entity who made the delegation on behalf of the owner.
/// If present, it's most likely the address of the vesting contract.
proxy: Option<String>,
/// The estimated performance for the current epoch of the given node.
estimated_performance: Performance,
},
// interval-related
/// Gets the list of all currently pending epoch events that will be resolved once the current epoch finishes.
#[cfg_attr(feature = "schema", returns(PendingEpochEventsResponse))]
GetPendingEpochEvents {
/// Controls the maximum number of entries returned by the query. Note that too large values will be overwritten by a saner default.
limit: Option<u32>,
/// Pagination control for the values returned by the query. Note that the provided value itself will **not** be used for the response.
start_after: Option<u32>,
},
/// Gets the list of all currently pending interval events that will be resolved once the current interval finishes.
#[cfg_attr(feature = "schema", returns(PendingIntervalEventsResponse))]
GetPendingIntervalEvents {
/// Controls the maximum number of entries returned by the query. Note that too large values will be overwritten by a saner default.
limit: Option<u32>,
/// Pagination control for the values returned by the query. Note that the provided value itself will **not** be used for the response.
start_after: Option<u32>,
},
/// Gets detailed information about a pending epoch event given its id.
#[cfg_attr(feature = "schema", returns(PendingEpochEventResponse))]
GetPendingEpochEvent {
/// The unique id associated with the event.
event_id: EpochEventId,
},
/// Gets detailed information about a pending interval event given its id.
#[cfg_attr(feature = "schema", returns(PendingIntervalEventResponse))]
GetPendingIntervalEvent {
/// The unique id associated with the event.
event_id: IntervalEventId,
},
/// Gets the information about the number of currently pending epoch and interval events.
#[cfg_attr(feature = "schema", returns(NumberOfPendingEventsResponse))]
GetNumberOfPendingEvents {},
// signing-related
/// Gets the signing nonce associated with the particular cosmos address.
#[cfg_attr(feature = "schema", returns(Nonce))]
GetSigningNonce {
/// Cosmos address used for the query of the signing nonce.
address: String,
},
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
#[serde(rename_all = "snake_case")]
#[cw_serde]
pub struct MigrateMsg {
pub vesting_contract_address: Option<String>,
}
@@ -3,49 +3,95 @@
use crate::mixnode::MixNodeCostParams;
use crate::reward_params::IntervalRewardingParamsUpdate;
use crate::{BlockHeight, EpochEventId, IntervalEventId, MixId};
use crate::{BlockHeight, MixId};
use cosmwasm_schema::cw_serde;
use cosmwasm_std::{Addr, Coin};
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
pub type EpochEventId = u32;
pub type IntervalEventId = u32;
/// A request made at some point in the current epoch that's going to get resolved once the epoch rolls over.
#[cw_serde]
pub struct PendingEpochEvent {
/// The unique id associated with the event.
pub id: EpochEventId,
/// The underlying event details, containing its type and information on how it should get resolved.
pub event: PendingEpochEventData,
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
/// Details of a particular pending epoch event.
#[cw_serde]
pub struct PendingEpochEventData {
/// The block height at which the request has been made.
pub created_at: BlockHeight,
/// The underlying event data, containing its concrete type and information on how it should get resolved.
pub kind: PendingEpochEventKind,
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
/// Enum encompassing all possible epoch events.
#[cw_serde]
pub enum PendingEpochEventKind {
// can't just pass the `Delegation` struct here as it's impossible to determine
// `cumulative_reward_ratio` ahead of time
/// Request to create a delegation towards particular mixnode.
/// Note that if such delegation already exists, it will get updated with the provided token amount.
Delegate {
/// The address of the owner of the delegation.
owner: Addr,
/// The id of the mixnode used for the delegation.
mix_id: MixId,
/// The amount of tokens to use for the delegation.
amount: Coin,
/// Entity who made the delegation on behalf of the owner.
/// If present, it's most likely the address of the vesting contract.
proxy: Option<Addr>,
},
/// Request to remove delegation from particular mixnode.
Undelegate {
/// The address of the owner of the delegation.
owner: Addr,
/// The id of the mixnode used for the delegation.
mix_id: MixId,
/// Entity who made the delegation on behalf of the owner.
/// If present, it's most likely the address of the vesting contract.
proxy: Option<Addr>,
},
/// Request to pledge more tokens (by the node operator) towards its node.
PledgeMore {
/// The id of the mixnode that will have its pledge updated.
mix_id: MixId,
/// The amount of additional tokens to use by the pledge.
amount: Coin,
},
/// Request to decrease amount of pledged tokens (by the node operator) from its node.
DecreasePledge {
/// The id of the mixnode that will have its pledge updated.
mix_id: MixId,
/// The amount of tokens that should be removed from the pledge.
decrease_by: Coin,
},
/// Request to unbond a mixnode and completely remove it from the network.
UnbondMixnode {
/// The id of the mixnode that will get unbonded.
mix_id: MixId,
},
/// Request to update the current size of the active set.
UpdateActiveSetSize {
/// The new desired size of the active set.
new_size: u32,
},
}
@@ -68,29 +114,50 @@ impl From<(EpochEventId, PendingEpochEventData)> for PendingEpochEvent {
}
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
/// A request made at some point in the current interval that's going to get resolved once the interval rolls over.
#[cw_serde]
pub struct PendingIntervalEvent {
/// The unique id associated with the event.
pub id: IntervalEventId,
/// The underlying event details, containing its type and information on how it should get resolved.
pub event: PendingIntervalEventData,
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
/// Details of a particular pending interval event.
#[cw_serde]
pub struct PendingIntervalEventData {
/// The block height at which the request has been made.
pub created_at: BlockHeight,
/// The underlying event data, containing its concrete type and information on how it should get resolved.
pub kind: PendingIntervalEventKind,
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
/// Enum encompassing all possible interval events.
#[cw_serde]
pub enum PendingIntervalEventKind {
/// Request to update cost parameters of given mixnode.
ChangeMixCostParams {
/// The id of the mixnode that will have its cost parameters updated.
mix_id: MixId,
/// The new updated cost function of this mixnode.
new_costs: MixNodeCostParams,
},
/// Request to update the underlying rewarding parameters used by the system
UpdateRewardingParams {
/// The detailed specification of the update.
update: IntervalRewardingParamsUpdate,
},
/// Request to change the next interval configuration.
UpdateIntervalConfig {
/// The new number of epochs in intervals.
epochs_in_interval: u32,
/// The new epoch duration.
epoch_duration_secs: u64,
},
}
@@ -112,3 +179,102 @@ impl From<(IntervalEventId, PendingIntervalEventData)> for PendingIntervalEvent
}
}
}
/// Response containing all currently pending epoch events that will be resolved once the current epoch finishes.
#[cw_serde]
pub struct PendingEpochEventsResponse {
/// Amount of seconds until the events would be eligible to be resolved.
/// It's equivalent to the time until the current epoch finishes.
pub seconds_until_executable: i64,
/// The currently pending events.
pub events: Vec<PendingEpochEvent>,
/// Field indicating paging information for the following queries if the caller wishes to get further entries.
pub start_next_after: Option<u32>,
}
impl PendingEpochEventsResponse {
pub fn new(
seconds_until_executable: i64,
events: Vec<PendingEpochEvent>,
start_next_after: Option<u32>,
) -> Self {
PendingEpochEventsResponse {
seconds_until_executable,
events,
start_next_after,
}
}
}
/// Response containing all currently pending interval events that will be resolved once the current interval finishes.
#[cw_serde]
pub struct PendingIntervalEventsResponse {
/// Amount of seconds until the events would be eligible to be resolved.
/// It's equivalent to the time until the current interval finishes.
pub seconds_until_executable: i64,
/// The currently pending events.
pub events: Vec<PendingIntervalEvent>,
/// Field indicating paging information for the following queries if the caller wishes to get further entries.
pub start_next_after: Option<u32>,
}
impl PendingIntervalEventsResponse {
pub fn new(
seconds_until_executable: i64,
events: Vec<PendingIntervalEvent>,
start_next_after: Option<u32>,
) -> Self {
PendingIntervalEventsResponse {
seconds_until_executable,
events,
start_next_after,
}
}
}
#[cw_serde]
pub struct PendingEpochEventResponse {
pub event_id: EpochEventId,
pub event: Option<PendingEpochEventData>,
}
impl PendingEpochEventResponse {
pub fn new(event_id: EpochEventId, event: Option<PendingEpochEventData>) -> Self {
PendingEpochEventResponse { event_id, event }
}
}
#[cw_serde]
pub struct PendingIntervalEventResponse {
pub event_id: IntervalEventId,
pub event: Option<PendingIntervalEventData>,
}
impl PendingIntervalEventResponse {
pub fn new(event_id: IntervalEventId, event: Option<PendingIntervalEventData>) -> Self {
PendingIntervalEventResponse { event_id, event }
}
}
/// Response containing number of currently pending epoch and interval events.
#[cw_serde]
pub struct NumberOfPendingEventsResponse {
/// The number of the currently pending epoch events.
pub epoch_events: u32,
/// The number of the currently pending epoch events.
pub interval_events: u32,
}
impl NumberOfPendingEventsResponse {
pub fn new(epoch_events: u32, interval_events: u32) -> Self {
Self {
epoch_events,
interval_events,
}
}
}
@@ -3,9 +3,8 @@
use crate::helpers::IntoBaseDecimal;
use crate::{error::MixnetContractError, Percent};
use cosmwasm_schema::cw_serde;
use cosmwasm_std::Decimal;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
pub type Performance = Percent;
@@ -15,7 +14,8 @@ pub type Performance = Percent;
feature = "generate-ts",
ts(export_to = "ts-packages/types/src/types/rust/IntervalRewardParams.ts")
)]
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Eq, PartialOrd, Serialize, JsonSchema)]
#[cw_serde]
#[derive(Copy)]
pub struct IntervalRewardParams {
/// Current value of the rewarding pool.
/// It is expected to be constant throughout the interval.
@@ -74,21 +74,26 @@ impl IntervalRewardParams {
}
}
/// Parameters used for reward calculation.
#[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))]
#[cfg_attr(
feature = "generate-ts",
ts(export_to = "ts-packages/types/src/types/rust/RewardingParams.ts")
)]
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Eq, PartialOrd, Serialize, JsonSchema)]
#[cw_serde]
#[derive(Copy)]
pub struct RewardingParams {
/// Parameters that should remain unchanged throughout an interval.
pub interval: IntervalRewardParams,
// while the active set size can change between epochs to accommodate for bandwidth demands,
// while the rewarded set size can change between epochs to accommodate for bandwidth demands,
// the active set size should be unchanged between epochs and should only be adjusted between
// intervals. However, it makes more sense to keep both of those values together as they're
// very strongly related to each other.
/// The expected number of mixnodes in the rewarded set (i.e. active + standby).
pub rewarded_set_size: u32,
/// The expected number of mixnodes in the active set.
pub active_set_size: u32,
}
@@ -224,9 +229,14 @@ impl RewardingParams {
}
// TODO: possibly refactor this
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Eq, PartialOrd, Serialize, JsonSchema)]
/// Parameters used for rewarding particular mixnode.
#[cw_serde]
#[derive(Copy)]
pub struct NodeRewardParams {
/// Performance of the particular node in the current epoch.
pub performance: Percent,
/// Flag indicating whether the node has been in the active set during the epoch.
pub in_active_set: bool,
}
@@ -239,33 +249,40 @@ impl NodeRewardParams {
}
}
/// Specification on how the rewarding params should be updated.
#[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))]
#[cfg_attr(
feature = "generate-ts",
ts(export_to = "ts-packages/types/src/types/rust/IntervalRewardingParamsUpdate.ts")
)]
#[derive(
Clone, Copy, Debug, Default, Deserialize, PartialEq, Eq, PartialOrd, Serialize, JsonSchema,
)]
#[cw_serde]
#[derive(Copy, Default)]
pub struct IntervalRewardingParamsUpdate {
#[cfg_attr(feature = "generate-ts", ts(type = "string | null"))]
/// Defines the new value of the reward pool.
pub reward_pool: Option<Decimal>,
#[cfg_attr(feature = "generate-ts", ts(type = "string | null"))]
/// Defines the new value of the staking supply.
pub staking_supply: Option<Decimal>,
#[cfg_attr(feature = "generate-ts", ts(type = "string | null"))]
/// Defines the new value of the staking supply scale factor.
pub staking_supply_scale_factor: Option<Percent>,
#[cfg_attr(feature = "generate-ts", ts(type = "string | null"))]
/// Defines the new value of the sybil resistance percent.
pub sybil_resistance_percent: Option<Percent>,
#[cfg_attr(feature = "generate-ts", ts(type = "string | null"))]
/// Defines the new value of the active set work factor.
pub active_set_work_factor: Option<Decimal>,
#[cfg_attr(feature = "generate-ts", ts(type = "string | null"))]
/// Defines the new value of the interval pool emission rate.
pub interval_pool_emission: Option<Percent>,
/// Defines the new size of the rewarded set.
pub rewarded_set_size: Option<u32>,
}
@@ -1,9 +1,9 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::{MixId, RewardedSetNodeStatus};
use cosmwasm_schema::cw_serde;
use cosmwasm_std::{Coin, Decimal};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
pub mod helpers;
pub mod simulator;
@@ -13,32 +13,52 @@ pub mod simulator;
feature = "generate-ts",
ts(export_to = "ts-packages/types/src/types/rust/RewardEstimate.ts")
)]
#[derive(Clone, Copy, Debug, Default, Deserialize, Serialize, JsonSchema, PartialEq, Eq)]
#[cw_serde]
#[derive(Copy, Default)]
pub struct RewardEstimate {
/// The amount of **decimal** coins that are going to get distributed to the node,
/// i.e. the operator and all its delegators.
#[cfg_attr(feature = "generate-ts", ts(type = "string"))]
pub total_node_reward: Decimal,
// note that operator reward includes the operating_cost,
// i.e. say total_node_reward was `1nym` and operating_cost was `2nym`
// in that case the operator reward would still be `1nym` as opposed to 0
/// The share of the reward that is going to get distributed to the node operator.
#[cfg_attr(feature = "generate-ts", ts(type = "string"))]
pub operator: Decimal,
/// The share of the reward that is going to get distributed among the node delegators.
#[cfg_attr(feature = "generate-ts", ts(type = "string"))]
pub delegates: Decimal,
/// The operating cost of this node. Note: it's already included in the operator reward.
#[cfg_attr(feature = "generate-ts", ts(type = "string"))]
pub operating_cost: Decimal,
}
#[derive(Clone, Copy, Debug, Default, Deserialize, Serialize, JsonSchema, PartialEq, Eq)]
#[cw_serde]
#[derive(Copy, Default)]
pub struct RewardDistribution {
/// The share of the reward that is going to get distributed to the node operator.
pub operator: Decimal,
/// The share of the reward that is going to get distributed among the node delegators.
pub delegates: Decimal,
}
#[derive(Clone, Debug, Default, Deserialize, Serialize, JsonSchema, PartialEq, Eq)]
/// Response containing information about accrued rewards.
#[cw_serde]
#[derive(Default)]
pub struct PendingRewardResponse {
/// The amount of tokens initially staked.
pub amount_staked: Option<Coin>,
/// The amount of tokens that could be claimed.
pub amount_earned: Option<Coin>,
/// The full pending rewards. Note that it's nearly identical to `amount_earned`,
/// however, it contains few additional decimal points for more accurate reward calculation.
pub amount_earned_detailed: Option<Decimal>,
/// The associated mixnode is still fully bonded, meaning it is neither unbonded
@@ -46,14 +66,25 @@ pub struct PendingRewardResponse {
pub mixnode_still_fully_bonded: bool,
}
#[derive(Clone, Debug, Default, Deserialize, Serialize, JsonSchema, PartialEq, Eq)]
/// Response containing estimation of node rewards for the current epoch.
#[cw_serde]
pub struct EstimatedCurrentEpochRewardResponse {
/// The amount of tokens initially staked.
pub original_stake: Option<Coin>,
/// The current stake value given all past rewarding and compounding since the original staking was performed.
pub current_stake_value: Option<Coin>,
/// The current stake value. Note that it's nearly identical to `current_stake_value`,
/// however, it contains few additional decimal points for more accurate reward calculation.
pub current_stake_value_detailed_amount: Option<Decimal>,
/// The reward estimation for the current epoch, i.e. the amount of tokens that could be claimable
/// after the epoch finishes and the state of the network does not change.
pub estimation: Option<Coin>,
/// The full reward estimation. Note that it's nearly identical to `estimation`,
/// however, it contains few additional decimal points for more accurate reward calculation.
pub detailed_estimation_amount: Option<Decimal>,
}
@@ -68,3 +99,13 @@ impl EstimatedCurrentEpochRewardResponse {
}
}
}
/// Response containing paged list of all mixnodes in the rewarded set.
#[cw_serde]
pub struct PagedRewardedSetResponse {
/// Nodes in the current rewarded set.
pub nodes: Vec<(MixId, RewardedSetNodeStatus)>,
/// Field indicating paging information for the following queries if the caller wishes to get further entries.
pub start_next_after: Option<MixId>,
}
@@ -2,29 +2,26 @@
// SPDX-License-Identifier: Apache-2.0
use crate::error::MixnetContractError;
use crate::families::{Family, FamilyHead};
use crate::{Layer, RewardedSetNodeStatus};
use contracts_common::IdentityKey;
use crate::Layer;
use cosmwasm_schema::cw_serde;
use cosmwasm_std::Addr;
use cosmwasm_std::Coin;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use std::ops::Index;
// type aliases for better reasoning about available data
pub type SphinxKey = String;
pub type SphinxKeyRef<'a> = &'a str;
pub type EpochId = u32;
pub type IntervalId = u32;
pub type MixId = u32;
pub type BlockHeight = u64;
pub type EpochEventId = u32;
pub type IntervalEventId = u32;
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Serialize, Deserialize, Debug, Clone, JsonSchema, PartialEq, Eq)]
/// Specifies layer assignment for the given mixnode.
#[cw_serde]
pub struct LayerAssignment {
/// The id of the mixnode.
mix_id: MixId,
/// The layer to which it's going to be assigned
layer: Layer,
}
@@ -42,10 +39,17 @@ impl LayerAssignment {
}
}
#[derive(Debug, Default, Serialize, Deserialize, Copy, Clone, Eq, PartialEq)]
/// The current layer distribution of the mix network.
#[cw_serde]
#[derive(Copy, Default)]
pub struct LayerDistribution {
/// Number of nodes on the first layer.
pub layer1: u64,
/// Number of nodes on the second layer.
pub layer2: u64,
/// Number of nodes on the third layer.
pub layer3: u64,
}
@@ -118,19 +122,29 @@ impl Index<Layer> for LayerDistribution {
}
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
/// The current state of the mixnet contract.
#[cw_serde]
pub struct ContractState {
pub owner: Addr, // only the owner account can update state
/// Address of the contract owner.
pub owner: Addr,
/// Address of "rewarding validator" (nym-api) that's allowed to send any rewarding-related transactions.
pub rewarding_validator_address: Addr,
/// Address of the vesting contract to which the mixnet contract would be sending all
/// track-related messages.
pub vesting_contract_address: Addr,
/// The expected denom used for rewarding (and realistically any other operation).
/// Default: `unym`
pub rewarding_denom: String,
/// Contract parameters that could be adjusted in a transaction the contract admin.
pub params: ContractStateParams,
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
/// Contract parameters that could be adjusted in a transaction by the contract admin.
#[cw_serde]
pub struct ContractStateParams {
/// Minimum amount a delegator must stake in orders for his delegation to get accepted.
pub minimum_mixnode_delegation: Option<Coin>,
@@ -141,21 +155,3 @@ pub struct ContractStateParams {
/// Minimum amount a gateway must pledge to get into the system.
pub minimum_gateway_pledge: Coin,
}
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq, JsonSchema)]
pub struct PagedRewardedSetResponse {
pub nodes: Vec<(MixId, RewardedSetNodeStatus)>,
pub start_next_after: Option<MixId>,
}
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq, JsonSchema)]
pub struct PagedFamiliesResponse {
pub families: Vec<Family>,
pub start_next_after: Option<String>,
}
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq, JsonSchema)]
pub struct PagedMembersResponse {
pub members: Vec<(IdentityKey, FamilyHead)>,
pub start_next_after: Option<String>,
}
@@ -8,7 +8,7 @@ edition = "2021"
[dependencies]
cw-utils = { workspace = true }
cw3 = { workspace = true }
cw4 = { workspace= true }
cw4 = { workspace = true }
cw-storage-plus = { workspace = true }
cosmwasm-schema = { workspace = true }
cosmwasm-std = { workspace = true }
@@ -6,10 +6,14 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
cosmwasm-schema = { workspace = true }
cosmwasm-std = { workspace = true }
cw2 = { workspace = true, optional = true }
cw-controllers = { workspace = true }
cw-utils = { workspace = true }
nym-contracts-common = { path = "../contracts-common", version = "0.5.0" }
schemars = "0.8"
serde = { workspace = true, features = ["derive"] }
thiserror = { workspace = true }
[features]
schema = ["cw2"]
@@ -1,10 +1,22 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::{Address, NameDetails, NameId, NymName};
use cosmwasm_schema::cw_serde;
use cosmwasm_std::Coin;
use nym_contracts_common::signing::MessageSignature;
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
#[serde(rename_all = "snake_case")]
#[cfg(feature = "schema")]
use crate::{
response::{ConfigResponse, NamesListResponse, PagedNamesListResponse},
types::RegisteredName,
};
#[cfg(feature = "schema")]
use cosmwasm_schema::QueryResponses;
#[cfg(feature = "schema")]
use nym_contracts_common::{signing::Nonce, ContractBuildInformation};
#[cw_serde]
pub struct InstantiateMsg {
pub deposit_required: Coin,
}
@@ -15,22 +27,23 @@ impl InstantiateMsg {
}
}
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
#[serde(rename_all = "snake_case")]
#[cw_serde]
pub struct MigrateMsg {}
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
#[serde(rename_all = "snake_case")]
#[cw_serde]
pub enum ExecuteMsg {
/// Announcing a name pointing to a nym-address
Register {
name: NameDetails,
owner_signature: MessageSignature,
},
/// Delete a name entry by id
DeleteId { name_id: NameId },
/// Delete a name entry by name
DeleteName { name: NymName },
/// Change the deposit required for announcing a name
UpdateDepositRequired { deposit_required: Coin },
}
@@ -61,33 +74,42 @@ impl ExecuteMsg {
}
}
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
#[serde(rename_all = "snake_case")]
#[cw_serde]
#[cfg_attr(feature = "schema", derive(QueryResponses))]
pub enum QueryMsg {
/// Query the name by it's assigned id
NameId {
name_id: NameId,
},
// Query the names by the registrator
ByOwner {
owner: String,
},
ByName {
name: NymName,
},
ByAddress {
address: Address,
},
#[cfg_attr(feature = "schema", returns(RegisteredName))]
NameId { name_id: NameId },
/// Query the names by the registrator
#[cfg_attr(feature = "schema", returns(NamesListResponse))]
ByOwner { owner: String },
#[cfg_attr(feature = "schema", returns(RegisteredName))]
ByName { name: NymName },
#[cfg_attr(feature = "schema", returns(NamesListResponse))]
ByAddress { address: Address },
#[cfg_attr(feature = "schema", returns(PagedNamesListResponse))]
All {
limit: Option<u32>,
start_after: Option<NameId>,
},
SigningNonce {
address: String,
},
#[cfg_attr(feature = "schema", returns(Nonce))]
SigningNonce { address: String },
#[cfg_attr(feature = "schema", returns(ConfigResponse))]
Config {},
/// Gets build information of this contract, such as the commit hash used for the build or rustc version.
#[cfg_attr(feature = "schema", returns(ContractBuildInformation))]
GetContractVersion {},
/// Gets the stored contract version information that's required by the CW2 spec interface for migrations.
#[serde(rename = "get_cw2_contract_version")]
#[cfg_attr(feature = "schema", returns(cw2::ContractVersion))]
GetCW2ContractVersion {},
}
@@ -1,10 +1,11 @@
use crate::{NameId, RegisteredName};
use cosmwasm_std::Coin;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone, JsonSchema)]
#[serde(rename_all = "snake_case")]
use crate::{NameId, RegisteredName};
use cosmwasm_schema::cw_serde;
use cosmwasm_std::Coin;
#[cw_serde]
pub struct NamesListResponse {
pub names: Vec<RegisteredName>,
}
@@ -23,11 +24,12 @@ impl From<&[RegisteredName]> for NamesListResponse {
}
}
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
#[serde(rename_all = "snake_case")]
#[cw_serde]
pub struct PagedNamesListResponse {
pub names: Vec<RegisteredName>,
pub per_page: usize,
/// Field indicating paging information for the following queries if the caller wishes to get further entries.
pub start_next_after: Option<NameId>,
}
@@ -45,8 +47,7 @@ impl PagedNamesListResponse {
}
}
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
#[serde(rename_all = "snake_case")]
#[cw_serde]
pub struct ConfigResponse {
pub deposit_required: Coin,
}
@@ -1,14 +1,15 @@
use std::fmt::{Display, Formatter};
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use cosmwasm_schema::cw_serde;
use cosmwasm_std::{Addr, Coin};
use nym_contracts_common::IdentityKey;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use std::fmt::{Display, Formatter};
/// The directory of names are indexed by [`NameId`].
pub type NameId = u32;
#[derive(Serialize, Deserialize, Clone, PartialEq, Debug, JsonSchema)]
#[cw_serde]
pub struct RegisteredName {
/// Unique id assigned to the registerd name.
pub id: NameId,
@@ -33,7 +34,7 @@ impl RegisteredName {
}
}
#[derive(Serialize, Deserialize, Clone, PartialEq, Debug, JsonSchema)]
#[cw_serde]
pub struct NameDetails {
/// The name pointing to the nym address
pub name: NymName,
@@ -48,8 +49,7 @@ pub struct NameDetails {
/// String representation of a nym address, which is of the form
/// client_id.client_enc@gateway_id.
/// NOTE: entirely unvalidated.
#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug, JsonSchema)]
#[serde(rename_all = "snake_case")]
#[cw_serde]
pub enum Address {
NymAddress(String),
// Possible extension:
@@ -83,8 +83,7 @@ impl Display for Address {
}
/// Name stored and pointing a to a nym-address
#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug, JsonSchema)]
#[serde(rename_all = "snake_case")]
#[cw_serde]
pub struct NymName(String);
#[derive(Debug)]
@@ -6,10 +6,13 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
cosmwasm-schema = { workspace = true }
cosmwasm-std = { workspace = true }
cw2 = { workspace = true, optional = true }
cw-controllers = { workspace = true }
cw-utils = { workspace = true }
nym-contracts-common = { path = "../contracts-common", version = "0.5.0" }
schemars = "0.8"
serde = { workspace = true, features = ["derive"] }
thiserror = { workspace = true }
[features]
schema = ["cw2"]
@@ -1,10 +1,22 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::{NymAddress, ServiceDetails, ServiceId};
use cosmwasm_schema::cw_serde;
use cosmwasm_std::Coin;
use nym_contracts_common::signing::MessageSignature;
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
#[serde(rename_all = "snake_case")]
#[cfg(feature = "schema")]
use crate::{
response::{ConfigResponse, PagedServicesListResponse, ServicesListResponse},
types::Service,
};
#[cfg(feature = "schema")]
use cosmwasm_schema::QueryResponses;
#[cfg(feature = "schema")]
use nym_contracts_common::{signing::Nonce, ContractBuildInformation};
#[cw_serde]
pub struct InstantiateMsg {
pub deposit_required: Coin,
}
@@ -15,12 +27,10 @@ impl InstantiateMsg {
}
}
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
#[serde(rename_all = "snake_case")]
#[cw_serde]
pub struct MigrateMsg {}
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
#[serde(rename_all = "snake_case")]
#[cw_serde]
pub enum ExecuteMsg {
Announce {
service: ServiceDetails,
@@ -64,28 +74,37 @@ impl ExecuteMsg {
}
}
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
#[serde(rename_all = "snake_case")]
#[cw_serde]
#[cfg_attr(feature = "schema", derive(QueryResponses))]
pub enum QueryMsg {
ServiceId {
service_id: ServiceId,
},
ByAnnouncer {
announcer: String,
},
ByNymAddress {
nym_address: NymAddress,
},
#[cfg_attr(feature = "schema", returns(Service))]
ServiceId { service_id: ServiceId },
#[cfg_attr(feature = "schema", returns(ServicesListResponse))]
ByAnnouncer { announcer: String },
#[cfg_attr(feature = "schema", returns(ServicesListResponse))]
ByNymAddress { nym_address: NymAddress },
#[cfg_attr(feature = "schema", returns(PagedServicesListResponse))]
All {
limit: Option<u32>,
start_after: Option<ServiceId>,
},
SigningNonce {
address: String,
},
#[cfg_attr(feature = "schema", returns(Nonce))]
SigningNonce { address: String },
#[cfg_attr(feature = "schema", returns(ConfigResponse))]
Config {},
/// Gets build information of this contract, such as the commit hash used for the build or rustc version.
#[cfg_attr(feature = "schema", returns(ContractBuildInformation))]
GetContractVersion {},
/// Gets the stored contract version information that's required by the CW2 spec interface for migrations.
#[serde(rename = "get_cw2_contract_version")]
#[cfg_attr(feature = "schema", returns(cw2::ContractVersion))]
GetCW2ContractVersion {},
}
@@ -1,17 +1,17 @@
use crate::{Service, ServiceId};
use cosmwasm_std::Coin;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
#[serde(rename_all = "snake_case")]
use crate::{Service, ServiceId};
use cosmwasm_schema::cw_serde;
use cosmwasm_std::Coin;
#[cw_serde]
pub struct ServiceInfoResponse {
pub service_id: ServiceId,
pub service: Option<Service>,
}
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone, JsonSchema)]
#[serde(rename_all = "snake_case")]
#[cw_serde]
pub struct ServicesListResponse {
pub services: Vec<Service>,
}
@@ -30,11 +30,12 @@ impl From<&[Service]> for ServicesListResponse {
}
}
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
#[serde(rename_all = "snake_case")]
#[cw_serde]
pub struct PagedServicesListResponse {
pub services: Vec<Service>,
pub per_page: usize,
/// Field indicating paging information for the following queries if the caller wishes to get further entries.
pub start_next_after: Option<ServiceId>,
}
@@ -52,8 +53,7 @@ impl PagedServicesListResponse {
}
}
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
#[serde(rename_all = "snake_case")]
#[cw_serde]
pub struct ConfigResponse {
pub deposit_required: Coin,
}
@@ -1,15 +1,17 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::ServiceDetails;
use cosmwasm_schema::cw_serde;
use cosmwasm_std::{Addr, Coin};
use nym_contracts_common::signing::{
ContractMessageContent, MessageType, Nonce, SignableMessage, SigningPurpose,
};
use serde::Serialize;
use crate::ServiceDetails;
pub type SignableServiceProviderAnnounceMsg =
SignableMessage<ContractMessageContent<ServiceProviderAnnounce>>;
#[derive(Serialize)]
#[cw_serde]
pub struct ServiceProviderAnnounce {
service: ServiceDetails,
}
@@ -1,14 +1,15 @@
use std::fmt::{Display, Formatter};
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use cosmwasm_schema::cw_serde;
use cosmwasm_std::{Addr, Coin};
use nym_contracts_common::IdentityKey;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use std::fmt::{Display, Formatter};
/// The directory of services are indexed by [`ServiceId`].
pub type ServiceId = u32;
#[derive(Serialize, Deserialize, Clone, PartialEq, Debug, JsonSchema)]
#[cw_serde]
pub struct Service {
/// Unique id assigned to the anounced service.
pub service_id: ServiceId,
@@ -22,7 +23,7 @@ pub struct Service {
pub deposit: Coin,
}
#[derive(Serialize, Deserialize, Clone, PartialEq, Debug, JsonSchema)]
#[cw_serde]
pub struct ServiceDetails {
/// The address of the service.
pub nym_address: NymAddress,
@@ -33,8 +34,7 @@ pub struct ServiceDetails {
}
/// The types of addresses supported.
#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug, JsonSchema)]
#[serde(rename_all = "snake_case")]
#[cw_serde]
pub enum NymAddress {
/// String representation of a nym address, which is of the form
/// client_id.client_enc@gateway_id.
@@ -64,8 +64,7 @@ impl Display for NymAddress {
}
/// The type of services provider supported
#[derive(Serialize, Deserialize, Copy, Clone, PartialEq, Eq, Debug, JsonSchema)]
#[serde(rename_all = "snake_case")]
#[cw_serde]
pub enum ServiceType {
NetworkRequester,
}
@@ -9,11 +9,14 @@ repository = { workspace = true }
[dependencies]
cosmwasm-std = { workspace = true }
cosmwasm-schema = { workspace = true }
cw2 = { workspace = true, optional = true }
mixnet-contract-common = { path = "../mixnet-contract", package = "nym-mixnet-contract-common", version = "0.6.0" }
contracts-common = { path = "../contracts-common", package = "nym-contracts-common", version = "0.5.0" }
serde = { version = "1.0", features = ["derive"] }
schemars = "0.8"
thiserror = "1.0"
ts-rs = {version = "6.1.2", optional = true}
[features]
schema = ["cw2"]
generate-ts = ["ts-rs"]
@@ -0,0 +1,124 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::{Period, PledgeCap, VestingContractError, VestingPeriod};
use cosmwasm_schema::cw_serde;
use cosmwasm_std::{Addr, Coin, Timestamp};
// this shouldn't really be exposed like this, but we really don't want to migrate the contract just for this...
pub type VestingAccountStorageKey = u32;
/// Vesting account information.
#[cw_serde]
pub struct Account {
/// Address of the owner of the vesting account.
pub owner_address: Addr,
/// Optional address of an account allowed to perform staking on behalf of the owner.
pub staking_address: Option<Addr>,
/// The starting vesting time.
pub start_time: Timestamp,
/// All vesting periods for this account.
pub periods: Vec<VestingPeriod>,
/// The initial amount of coins used creation of this account.
pub coin: Coin,
/// The id/storage_key of this vesting account.
pub storage_key: VestingAccountStorageKey,
/// Optional custom pledge cap of this vesting account.
#[serde(default)]
pub pledge_cap: Option<PledgeCap>,
}
impl Account {
pub fn pledge_cap(&self) -> PledgeCap {
self.pledge_cap.clone().unwrap_or_default()
}
pub fn coin(&self) -> Coin {
self.coin.clone()
}
pub fn num_vesting_periods(&self) -> usize {
self.periods.len()
}
pub fn period_duration(&self) -> Result<u64, VestingContractError> {
self.periods
.get(0)
.ok_or(VestingContractError::UnpopulatedVestingPeriods {
owner: self.owner_address.clone(),
})
.map(|p| p.period_seconds)
}
pub fn storage_key(&self) -> u32 {
self.storage_key
}
pub fn owner_address(&self) -> Addr {
self.owner_address.clone()
}
pub fn staking_address(&self) -> Option<&Addr> {
self.staking_address.as_ref()
}
pub fn periods(&self) -> Vec<VestingPeriod> {
self.periods.clone()
}
pub fn start_time(&self) -> Timestamp {
self.start_time
}
pub fn tokens_per_period(&self) -> Result<u128, VestingContractError> {
let amount = self.coin.amount.u128();
if amount < self.num_vesting_periods() as u128 {
Err(VestingContractError::ImprobableVestingAmount(amount))
} else {
// Remainder tokens will be lumped into the last period.
Ok(amount / self.num_vesting_periods() as u128)
}
}
/// Returns the index of the next vesting period. Unless the current time is somehow in the past or vesting has not started yet.
/// In case vesting is over it will always return NUM_VESTING_PERIODS.
pub fn get_current_vesting_period(
&self,
block_time: Timestamp,
) -> Result<Period, VestingContractError> {
let first_period =
self.periods
.first()
.ok_or(VestingContractError::UnpopulatedVestingPeriods {
owner: self.owner_address.clone(),
})?;
let last_period =
self.periods
.last()
.ok_or(VestingContractError::UnpopulatedVestingPeriods {
owner: self.owner_address.clone(),
})?;
if block_time.seconds() < first_period.start_time {
Ok(Period::Before)
} else if last_period.end_time() < block_time {
Ok(Period::After)
} else {
let mut index = 0;
for period in &self.periods {
if block_time < period.end_time() {
break;
}
index += 1;
}
Ok(Period::In(index))
}
}
}
@@ -1,10 +1,13 @@
use crate::storage::AccountStorageKey;
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::account::VestingAccountStorageKey;
use cosmwasm_std::{Addr, Coin, OverflowError, StdError, Uint128};
use mixnet_contract_common::MixId;
use thiserror::Error;
#[derive(Error, Debug, PartialEq)]
pub enum ContractError {
pub enum VestingContractError {
#[error("VESTING ({}): {0}", line!())]
Std(#[from] StdError),
@@ -27,7 +30,7 @@ pub enum ContractError {
InsufficientSpendable(String, u128),
#[error(
"VESTING ({}):Only delegation owner can perform delegation actions, {0} is not the delegation owner"
"VESTING ({}):Only delegation owner can perform delegation actions, {0} is not the delegation owner"
, line!())]
NotDelegate(String),
@@ -91,7 +94,7 @@ pub enum ContractError {
#[error("VESTING: {address} ({acc_id} has already performed {num} individual delegations towards {mix_id}. No further delegations are allowed. Please consider consolidating those delegations instead. The current cap is {cap}.")]
TooManyDelegations {
address: Addr,
acc_id: AccountStorageKey,
acc_id: VestingAccountStorageKey,
mix_id: MixId,
num: u32,
cap: u32,
@@ -4,83 +4,31 @@
#![warn(clippy::expect_used)]
#![warn(clippy::unwrap_used)]
use contracts_common::Percent;
use cosmwasm_std::{Addr, Coin, Timestamp, Uint128};
use cosmwasm_schema::cw_serde;
use cosmwasm_std::{Addr, Coin};
use mixnet_contract_common::MixId;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use std::str::FromStr;
pub use messages::{ExecuteMsg, InitMsg, MigrateMsg, QueryMsg};
pub mod account;
pub mod error;
pub mod events;
pub mod messages;
pub mod types;
#[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))]
#[cfg_attr(
feature = "generate-ts",
ts(export_to = "ts-packages/types/src/types/rust/Period.ts")
)]
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Clone, JsonSchema)]
pub enum Period {
Before,
In(usize),
After,
}
pub use account::Account;
pub use error::VestingContractError;
pub use messages::{ExecuteMsg, InitMsg, MigrateMsg, QueryMsg};
pub use types::*;
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
pub struct PledgeData {
pub amount: Coin,
pub block_time: Timestamp,
}
impl PledgeData {
pub fn amount(&self) -> Coin {
self.amount.clone()
}
pub fn block_time(&self) -> Timestamp {
self.block_time
}
pub fn new(amount: Coin, block_time: Timestamp) -> Self {
Self { amount, block_time }
}
}
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
pub enum PledgeCap {
Percent(Percent),
Absolute(Uint128), // This has to be in unym
}
impl FromStr for PledgeCap {
type Err = String;
fn from_str(cap: &str) -> Result<Self, Self::Err> {
let cap = cap.replace('_', "").replace(',', ".");
match Percent::from_str(&cap) {
Ok(p) => Ok(PledgeCap::Percent(p)),
Err(_) => match cap.parse::<u128>() {
Ok(i) => Ok(PledgeCap::Absolute(Uint128::from(i))),
Err(_e) => Err(format!("Could not parse {cap} as Percent or Uint128")),
},
}
}
}
impl Default for PledgeCap {
fn default() -> Self {
#[allow(clippy::expect_used)]
PledgeCap::Percent(Percent::from_percentage_value(10).expect("This can never fail!"))
}
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
/// Details about the original vesting specification used when the account was created.
#[cw_serde]
pub struct OriginalVestingResponse {
/// The original amount that was used for the creation of this vesting account
pub amount: Coin,
/// The number of vesting periods that the account was created with
pub number_of_periods: usize,
/// Duration of each vesting period in seconds
pub period_duration: u64,
}
@@ -106,57 +54,73 @@ impl OriginalVestingResponse {
}
}
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Clone, JsonSchema)]
pub struct VestingDelegation {
pub account_id: u32,
pub mix_id: MixId,
pub block_timestamp: u64,
pub amount: Uint128,
}
impl VestingDelegation {
pub fn storage_key(&self) -> (u32, MixId, u64) {
(self.account_id, self.mix_id, self.block_timestamp)
}
}
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Clone, JsonSchema)]
/// Response containing timestamps of all delegations made towards particular mixnode by given vesting account.
#[cw_serde]
pub struct DelegationTimesResponse {
/// Address of this account's owner
pub owner: Addr,
/// Id associated with this account
pub account_id: u32,
/// Id of the mixnode towards which the delegation was made
pub mix_id: MixId,
/// All timestamps where a delegation was made
pub delegation_timestamps: Vec<u64>,
}
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Clone, JsonSchema)]
/// Response containing paged list of all vesting delegations made using vesting coins.
#[cw_serde]
pub struct AllDelegationsResponse {
/// The actual vesting delegations made.
pub delegations: Vec<VestingDelegation>,
/// Field indicating paging information for the following queries if the caller wishes to get further entries.
pub start_next_after: Option<(u32, MixId, u64)>,
}
#[derive(Debug, Serialize, Deserialize, Clone, JsonSchema)]
/// Basic information regarding particular vesting account alongside the amount of vesting coins.
#[cw_serde]
pub struct AccountVestingCoins {
/// Id associated with this account
pub account_id: u32,
/// Address of this account's owner
pub owner: Addr,
/// Coins that are still vesting belonging to this account.
pub still_vesting: Coin,
}
#[derive(Debug, Serialize, Deserialize, Clone, JsonSchema)]
/// Response containing vesting coins held in this contract
#[cw_serde]
pub struct VestingCoinsResponse {
/// The actual accounts, and their vesting coins, returned by the query.
pub accounts: Vec<AccountVestingCoins>,
/// Field indicating paging information for the following queries if the caller wishes to get further entries.
pub start_next_after: Option<Addr>,
}
#[derive(Debug, Serialize, Deserialize, Clone, JsonSchema)]
/// Basic information regarding particular vesting account
#[cw_serde]
pub struct BaseVestingAccountInfo {
/// Id associated with this account
pub account_id: u32,
/// Address of this account's owner
pub owner: Addr,
// TODO: should this particular query/response expose anything else?
}
#[derive(Debug, Serialize, Deserialize, Clone, JsonSchema)]
/// Response containing basic vesting account information
#[cw_serde]
pub struct AccountsResponse {
/// The actual accounts returned by the query.
pub accounts: Vec<BaseVestingAccountInfo>,
/// Field indicating paging information for the following queries if the caller wishes to get further entries.
pub start_next_after: Option<Addr>,
}
@@ -1,4 +1,9 @@
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::{PledgeCap, VestingSpecification};
use contracts_common::signing::MessageSignature;
use cosmwasm_schema::cw_serde;
use cosmwasm_std::{Coin, Timestamp};
use mixnet_contract_common::families::FamilyHead;
use mixnet_contract_common::{
@@ -6,57 +11,30 @@ use mixnet_contract_common::{
mixnode::{MixNodeConfigUpdate, MixNodeCostParams},
Gateway, IdentityKey, MixId, MixNode,
};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use crate::PledgeCap;
#[cfg(feature = "schema")]
use contracts_common::ContractBuildInformation;
#[cfg(feature = "schema")]
use cosmwasm_schema::QueryResponses;
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
#[serde(rename_all = "snake_case")]
#[cfg(feature = "schema")]
use crate::{
account::Account,
types::{Period, PledgeData, VestingDelegation},
AccountsResponse, AllDelegationsResponse, DelegationTimesResponse, OriginalVestingResponse,
VestingCoinsResponse,
};
#[cw_serde]
pub struct InitMsg {
pub mixnet_contract_address: String,
pub mix_denom: String,
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
#[serde(rename_all = "snake_case")]
#[cw_serde]
pub struct MigrateMsg {}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema, Default)]
pub struct VestingSpecification {
start_time: Option<u64>,
period_seconds: Option<u64>,
num_periods: Option<u64>,
}
impl VestingSpecification {
pub fn new(
start_time: Option<u64>,
period_seconds: Option<u64>,
num_periods: Option<u64>,
) -> Self {
Self {
start_time,
period_seconds,
num_periods,
}
}
pub fn start_time(&self) -> Option<u64> {
self.start_time
}
pub fn period_seconds(&self) -> u64 {
self.period_seconds.unwrap_or(3 * 30 * 86400)
}
pub fn num_periods(&self) -> u64 {
self.num_periods.unwrap_or(8)
}
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
#[serde(rename_all = "snake_case")]
#[cw_serde]
pub enum ExecuteMsg {
// Families
/// Only owner of the node can crate the family with node as head
@@ -197,93 +175,226 @@ impl ExecuteMsg {
}
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
#[serde(rename_all = "snake_case")]
/// Queries exposed by this contract.
#[cw_serde]
#[cfg_attr(feature = "schema", derive(QueryResponses))]
pub enum QueryMsg {
/// Gets build information of this contract, such as the commit hash used for the build or rustc version.
#[cfg_attr(feature = "schema", returns(ContractBuildInformation))]
GetContractVersion {},
/// Gets the stored contract version information that's required by the CW2 spec interface for migrations.
#[serde(rename = "get_cw2_contract_version")]
#[cfg_attr(feature = "schema", returns(cw2::ContractVersion))]
GetCW2ContractVersion {},
/// Gets the list of vesting accounts held in this contract.
#[cfg_attr(feature = "schema", returns(AccountsResponse))]
GetAccountsPaged {
/// Pagination control for the values returned by the query. Note that the provided value itself will **not** be used for the response.
start_next_after: Option<String>,
/// Controls the maximum number of entries returned by the query. Note that too large values will be overwritten by a saner default.
limit: Option<u32>,
},
/// Gets the list of coins that are still vesting for each account held in this contract.
#[cfg_attr(feature = "schema", returns(VestingCoinsResponse))]
GetAccountsVestingCoinsPaged {
/// Pagination control for the values returned by the query. Note that the provided value itself will **not** be used for the response.
start_next_after: Option<String>,
/// Controls the maximum number of entries returned by the query. Note that too large values will be overwritten by a saner default.
limit: Option<u32>,
},
/// Returns the amount of locked coins for the provided vesting account,
/// i.e. coins that are still vesting but have not been staked.
/// `locked_coins = vesting_coins - staked_coins`
#[cfg_attr(feature = "schema", returns(Coin))]
LockedCoins {
/// Address of the vesting account in question.
vesting_account_address: String,
/// (deprecated) Optional argument specifying that the query should be performed against non-current block.
block_time: Option<Timestamp>,
},
/// Returns the amount of spendable coins for the provided vesting account,
/// i.e. coins that could be withdrawn.
/// `spendable_coins = account_balance - locked_coins`
/// note: `account_balance` is the amount of coins still physically present in this contract, i.e. not withdrawn or staked.
#[cfg_attr(feature = "schema", returns(Coin))]
SpendableCoins {
/// Address of the vesting account in question.
vesting_account_address: String,
/// (deprecated) Optional argument specifying that the query should be performed against non-current block.
block_time: Option<Timestamp>,
},
/// Returns the amount of coins that have already vested for the provided vesting account address.
#[cfg_attr(feature = "schema", returns(Coin))]
GetVestedCoins {
/// Address of the vesting account in question.
vesting_account_address: String,
/// (deprecated) Optional argument specifying that the query should be performed against non-current block.
block_time: Option<Timestamp>,
},
/// Returns the amount of coins that are still vesting for the provided vesting account address.
#[cfg_attr(feature = "schema", returns(Coin))]
GetVestingCoins {
/// Address of the vesting account in question.
vesting_account_address: String,
/// (deprecated) Optional argument specifying that the query should be performed against non-current block.
block_time: Option<Timestamp>,
},
/// Returns the starting vesting time for the provided vesting account,
/// i.e. the beginning of the first vesting period.
#[cfg_attr(feature = "schema", returns(Timestamp))]
GetStartTime {
/// Address of the vesting account in question.
vesting_account_address: String,
},
/// Returns the ending vesting time for the provided vesting account,
/// i.e. the end of the last vesting period.
#[cfg_attr(feature = "schema", returns(Timestamp))]
GetEndTime {
/// Address of the vesting account in question.
vesting_account_address: String,
},
/// Returns the initial vesting specification used for the provided vesting account address.
#[cfg_attr(feature = "schema", returns(OriginalVestingResponse))]
GetOriginalVesting {
/// Address of the vesting account in question.
vesting_account_address: String,
},
/// Returns the total amount of coins accrued through claimed staking rewards by the provided vesting account.
#[cfg_attr(feature = "schema", returns(Coin))]
GetHistoricalVestingStakingReward {
/// Address of the vesting account in question.
vesting_account_address: String,
},
/// Returns the amount of spendable vesting coins for the provided vesting account,
/// i.e. coins that could be withdrawn that originated from the vesting specification.
#[cfg_attr(feature = "schema", returns(Coin))]
GetSpendableVestedCoins {
/// Address of the vesting account in question.
vesting_account_address: String,
},
/// Returns the amount of spendable reward coins for the provided vesting account,
/// i.e. coins that could be withdrawn that originated from the claimed staking rewards.
#[cfg_attr(feature = "schema", returns(Coin))]
GetSpendableRewardCoins {
/// Address of the vesting account in question.
vesting_account_address: String,
},
/// Returns the amount of coins that are currently delegated for the provided vesting account address.
#[cfg_attr(feature = "schema", returns(Coin))]
GetDelegatedCoins {
/// Address of the vesting account in question.
vesting_account_address: String,
},
/// Returns the amount of coins that are currently pledged for the provided vesting account address.
#[cfg_attr(feature = "schema", returns(Coin))]
GetPledgedCoins {
/// Address of the vesting account in question.
vesting_account_address: String,
},
/// Returns the amount of coins that are currently staked (i.e. delegations + pledges) for the provided vesting account address.
#[cfg_attr(feature = "schema", returns(Coin))]
GetStakedCoins {
/// Address of the vesting account in question.
vesting_account_address: String,
},
/// Returns the amount of coins that got withdrawn for the provided vesting account address.
#[cfg_attr(feature = "schema", returns(Coin))]
GetWithdrawnCoins {
/// Address of the vesting account in question.
vesting_account_address: String,
},
/// Returns detailed information associated with the account for the provided vesting account address.
#[cfg_attr(feature = "schema", returns(Account))]
GetAccount {
/// Address of the vesting account in question.
address: String,
},
/// Returns pledge information (if applicable) for bonded mixnode for the provided vesting account address.
#[cfg_attr(feature = "schema", returns(Option<PledgeData>))]
GetMixnode {
/// Address of the vesting account in question.
address: String,
},
/// Returns pledge information (if applicable) for bonded gateway for the provided vesting account address.
#[cfg_attr(feature = "schema", returns(Option<PledgeData>))]
GetGateway {
/// Address of the vesting account in question.
address: String,
},
/// Returns the current vesting period for the provided vesting account address.
#[cfg_attr(feature = "schema", returns(Period))]
GetCurrentVestingPeriod {
/// Address of the vesting account in question.
address: String,
},
/// Returns the information about particular vesting delegation.
#[cfg_attr(feature = "schema", returns(VestingDelegation))]
GetDelegation {
/// Address of the vesting account in question.
address: String,
/// Id of the mixnode towards which the delegation has been made.
mix_id: MixId,
/// Block timestamp of the delegation.
block_timestamp_secs: u64,
},
/// Returns the total amount of coins delegated towards particular mixnode by the provided vesting account address.
#[cfg_attr(feature = "schema", returns(Coin))]
GetTotalDelegationAmount {
/// Address of the vesting account in question.
address: String,
/// Id of the mixnode towards which the delegations have been made.
mix_id: MixId,
},
/// Returns timestamps of delegations made towards particular mixnode by the provided vesting account address.
#[cfg_attr(feature = "schema", returns(DelegationTimesResponse))]
GetDelegationTimes {
/// Address of the vesting account in question.
address: String,
/// Id of the mixnode towards which the delegations have been made.
mix_id: MixId,
},
/// Returns all active delegations made with vesting tokens stored in this contract.
#[cfg_attr(feature = "schema", returns(AllDelegationsResponse))]
GetAllDelegations {
/// Pagination control for the values returned by the query. Note that the provided value itself will **not** be used for the response.
start_after: Option<(u32, MixId, u64)>,
/// Controls the maximum number of entries returned by the query. Note that too large values will be overwritten by a saner default.
limit: Option<u32>,
},
}
@@ -0,0 +1,166 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use contracts_common::Percent;
use cosmwasm_schema::cw_serde;
use cosmwasm_std::{Coin, Timestamp, Uint128};
use mixnet_contract_common::MixId;
use std::str::FromStr;
#[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))]
#[cfg_attr(
feature = "generate-ts",
ts(export_to = "ts-packages/types/src/types/rust/Period.ts")
)]
#[cw_serde]
/// The vesting period.
pub enum Period {
/// Defines a pre-vesting period.
Before,
/// Defines currently active vesting period.
In(usize),
/// Defines a post-vesting period.
After,
}
/// Information regarding pledge (i.e. mixnode or gateway bonding) made with vesting tokens.
#[cw_serde]
pub struct PledgeData {
/// The amount pledged.
pub amount: Coin,
/// The block timestamp where the pledge occurred.
pub block_time: Timestamp,
}
impl PledgeData {
pub fn amount(&self) -> Coin {
self.amount.clone()
}
pub fn block_time(&self) -> Timestamp {
self.block_time
}
pub fn new(amount: Coin, block_time: Timestamp) -> Self {
Self { amount, block_time }
}
}
/// Defines cap for pleding/staking tokens.
#[cw_serde]
pub enum PledgeCap {
/// Specifies a percent-based pledge cap, i.e. only given % of tokens could be pledged/staked.
Percent(Percent),
/// Specifies an absolute pledge cap, i.e. an explicit value that could be pledged/staked.
Absolute(Uint128), // This has to be in unym
}
impl FromStr for PledgeCap {
type Err = String;
fn from_str(cap: &str) -> Result<Self, Self::Err> {
let cap = cap.replace('_', "").replace(',', ".");
match Percent::from_str(&cap) {
Ok(p) => Ok(PledgeCap::Percent(p)),
Err(_) => match cap.parse::<u128>() {
Ok(i) => Ok(PledgeCap::Absolute(Uint128::from(i))),
Err(_e) => Err(format!("Could not parse {cap} as Percent or Uint128")),
},
}
}
}
impl Default for PledgeCap {
fn default() -> Self {
#[allow(clippy::expect_used)]
PledgeCap::Percent(Percent::from_percentage_value(10).expect("This can never fail!"))
}
}
/// Vesting period details.
#[cw_serde]
pub struct VestingPeriod {
/// The start time of this vesting period, as unix timestamp.
pub start_time: u64,
/// The duration (in seconds) of the vesting period.
pub period_seconds: u64,
}
impl VestingPeriod {
pub fn end_time(&self) -> Timestamp {
Timestamp::from_seconds(self.start_time + self.period_seconds)
}
}
#[cw_serde]
#[derive(Default)]
pub struct VestingSpecification {
start_time: Option<u64>,
period_seconds: Option<u64>,
num_periods: Option<u64>,
}
impl VestingSpecification {
pub fn new(
start_time: Option<u64>,
period_seconds: Option<u64>,
num_periods: Option<u64>,
) -> Self {
Self {
start_time,
period_seconds,
num_periods,
}
}
pub fn start_time(&self) -> Option<u64> {
self.start_time
}
pub fn period_seconds(&self) -> u64 {
self.period_seconds.unwrap_or(3 * 30 * 86400)
}
pub fn num_periods(&self) -> u64 {
self.num_periods.unwrap_or(8)
}
pub fn populate_vesting_periods(&self, start_time: u64) -> Vec<VestingPeriod> {
let mut periods = Vec::with_capacity(self.num_periods() as usize);
for i in 0..self.num_periods() {
let period = VestingPeriod {
start_time: start_time + i * self.period_seconds(),
period_seconds: self.period_seconds(),
};
periods.push(period);
}
periods
}
}
/// Details about particular vesting delegation.
#[cw_serde]
pub struct VestingDelegation {
/// The id of the vesting account that has made the delegation.
pub account_id: u32,
/// The id of the mixnode towards which the delegation has been made.
pub mix_id: MixId,
/// The block timestamp when the delegation has been made.
pub block_timestamp: u64,
/// The raw amount delegated (interpreted to be in the same denom as the underlying vesting specification)
pub amount: Uint128,
}
impl VestingDelegation {
pub fn storage_key(&self) -> (u32, MixId, u64) {
(self.account_id, self.mix_id, self.block_timestamp)
}
}
+4 -1
View File
@@ -27,14 +27,17 @@ thiserror = "1.0.37"
zeroize = { workspace = true, optional = true, features = ["zeroize_derive"] }
# internal
nym-sphinx-types = { path = "../nymsphinx/types", version = "0.2.0" }
nym-sphinx-types = { path = "../nymsphinx/types", version = "0.2.0", default-features = false }
nym-pemstore = { path = "../../common/pemstore", version = "0.3.0" }
[dev-dependencies]
rand_chacha = "0.2"
[features]
default = ["sphinx"]
serde = ["serde_crate", "serde_bytes", "ed25519-dalek/serde", "x25519-dalek/serde"]
asymmetric = ["x25519-dalek", "ed25519-dalek", "zeroize"]
hashing = ["blake3", "digest", "hkdf", "hmac", "generic-array"]
symmetric = ["aes", "ctr", "cipher", "generic-array"]
sphinx = ["nym-sphinx-types/sphinx"]
outfox = ["nym-sphinx-types/outfox"]
@@ -273,36 +273,42 @@ impl PemStorableKey for PrivateKey {
}
// compatibility with sphinx keys:
#[cfg(feature = "sphinx")]
impl From<PublicKey> for nym_sphinx_types::PublicKey {
fn from(key: PublicKey) -> Self {
nym_sphinx_types::PublicKey::from(key.to_bytes())
}
}
#[cfg(feature = "sphinx")]
impl<'a> From<&'a PublicKey> for nym_sphinx_types::PublicKey {
fn from(key: &'a PublicKey) -> Self {
nym_sphinx_types::PublicKey::from((*key).to_bytes())
}
}
#[cfg(feature = "sphinx")]
impl From<nym_sphinx_types::PublicKey> for PublicKey {
fn from(pub_key: nym_sphinx_types::PublicKey) -> Self {
Self(x25519_dalek::PublicKey::from(*pub_key.as_bytes()))
}
}
#[cfg(feature = "sphinx")]
impl From<PrivateKey> for nym_sphinx_types::PrivateKey {
fn from(key: PrivateKey) -> Self {
nym_sphinx_types::PrivateKey::from(key.to_bytes())
}
}
#[cfg(feature = "sphinx")]
impl<'a> From<&'a PrivateKey> for nym_sphinx_types::PrivateKey {
fn from(key: &'a PrivateKey) -> Self {
nym_sphinx_types::PrivateKey::from(key.to_bytes())
}
}
#[cfg(feature = "sphinx")]
impl From<nym_sphinx_types::PrivateKey> for PrivateKey {
fn from(private_key: nym_sphinx_types::PrivateKey) -> Self {
let private_key_bytes = private_key.to_bytes();
@@ -5,6 +5,7 @@ pub use ed25519_dalek::ed25519::signature::Signature as SignatureTrait;
pub use ed25519_dalek::SignatureError;
pub use ed25519_dalek::{Verifier, PUBLIC_KEY_LENGTH, SECRET_KEY_LENGTH, SIGNATURE_LENGTH};
use nym_pemstore::traits::{PemStorableKey, PemStorableKeyPair};
#[cfg(feature = "sphinx")]
use nym_sphinx_types::{DestinationAddressBytes, DESTINATION_ADDRESS_LENGTH};
use std::fmt::{self, Display, Formatter};
use std::str::FromStr;
@@ -113,6 +114,7 @@ impl Display for PublicKey {
}
impl PublicKey {
#[cfg(feature = "sphinx")]
pub fn derive_destination_address(&self) -> DestinationAddressBytes {
let mut temporary_address = [0u8; DESTINATION_ADDRESS_LENGTH];
let public_key_bytes = self.to_bytes();
-14
View File
@@ -25,7 +25,6 @@ pub struct ChainDetails {
pub struct NymContracts {
pub mixnet_contract_address: Option<String>,
pub vesting_contract_address: Option<String>,
pub bandwidth_claim_contract_address: Option<String>,
pub coconut_bandwidth_contract_address: Option<String>,
pub group_contract_address: Option<String>,
pub multisig_contract_address: Option<String>,
@@ -112,10 +111,6 @@ impl NymNetworkDetails {
.with_vesting_contract(Some(
var(var_names::VESTING_CONTRACT_ADDRESS).expect("vesting contract not set"),
))
.with_bandwidth_claim_contract(Some(
var(var_names::BANDWIDTH_CLAIM_CONTRACT_ADDRESS)
.expect("bandwidth claim contract not set"),
))
.with_coconut_bandwidth_contract(Some(
var(var_names::COCONUT_BANDWIDTH_CONTRACT_ADDRESS)
.expect("coconut bandwidth contract not set"),
@@ -151,9 +146,6 @@ impl NymNetworkDetails {
contracts: NymContracts {
mixnet_contract_address: parse_optional_str(mainnet::MIXNET_CONTRACT_ADDRESS),
vesting_contract_address: parse_optional_str(mainnet::VESTING_CONTRACT_ADDRESS),
bandwidth_claim_contract_address: parse_optional_str(
mainnet::BANDWIDTH_CLAIM_CONTRACT_ADDRESS,
),
coconut_bandwidth_contract_address: parse_optional_str(
mainnet::COCONUT_BANDWIDTH_CONTRACT_ADDRESS,
),
@@ -216,12 +208,6 @@ impl NymNetworkDetails {
self
}
#[must_use]
pub fn with_bandwidth_claim_contract<S: Into<String>>(mut self, contract: Option<S>) -> Self {
self.contracts.bandwidth_claim_contract_address = contract.map(Into::into);
self
}
#[must_use]
pub fn with_coconut_bandwidth_contract<S: Into<String>>(mut self, contract: Option<S>) -> Self {
self.contracts.coconut_bandwidth_contract_address = contract.map(Into::into);
-10
View File
@@ -13,8 +13,6 @@ pub const MIXNET_CONTRACT_ADDRESS: &str =
"n17srjznxl9dvzdkpwpw24gg668wc73val88a6m5ajg6ankwvz9wtst0cznr";
pub const VESTING_CONTRACT_ADDRESS: &str =
"n1nc5tatafv6eyq7llkr2gv50ff9e22mnf70qgjlv737ktmt4eswrq73f2nw";
pub(crate) const BANDWIDTH_CLAIM_CONTRACT_ADDRESS: &str =
"n19lc9u84cz0yz3fww5283nucc9yvr8gsjmgeul0";
pub(crate) const COCONUT_BANDWIDTH_CONTRACT_ADDRESS: &str =
"n19lc9u84cz0yz3fww5283nucc9yvr8gsjmgeul0";
pub(crate) const GROUP_CONTRACT_ADDRESS: &str = "n19lc9u84cz0yz3fww5283nucc9yvr8gsjmgeul0";
@@ -70,10 +68,6 @@ pub fn export_to_env() {
var_names::VESTING_CONTRACT_ADDRESS,
VESTING_CONTRACT_ADDRESS,
);
set_var_to_default(
var_names::BANDWIDTH_CLAIM_CONTRACT_ADDRESS,
BANDWIDTH_CLAIM_CONTRACT_ADDRESS,
);
set_var_to_default(
var_names::COCONUT_BANDWIDTH_CONTRACT_ADDRESS,
COCONUT_BANDWIDTH_CONTRACT_ADDRESS,
@@ -115,10 +109,6 @@ pub fn export_to_env_if_not_set() {
var_names::VESTING_CONTRACT_ADDRESS,
VESTING_CONTRACT_ADDRESS,
);
set_var_conditionally_to_default(
var_names::BANDWIDTH_CLAIM_CONTRACT_ADDRESS,
BANDWIDTH_CLAIM_CONTRACT_ADDRESS,
);
set_var_conditionally_to_default(
var_names::COCONUT_BANDWIDTH_CONTRACT_ADDRESS,
COCONUT_BANDWIDTH_CONTRACT_ADDRESS,
-1
View File
@@ -12,7 +12,6 @@ pub const STAKE_DENOM_DISPLAY: &str = "STAKE_DENOM_DISPLAY";
pub const DENOMS_EXPONENT: &str = "DENOMS_EXPONENT";
pub const MIXNET_CONTRACT_ADDRESS: &str = "MIXNET_CONTRACT_ADDRESS";
pub const VESTING_CONTRACT_ADDRESS: &str = "VESTING_CONTRACT_ADDRESS";
pub const BANDWIDTH_CLAIM_CONTRACT_ADDRESS: &str = "BANDWIDTH_CLAIM_CONTRACT_ADDRESS";
pub const COCONUT_BANDWIDTH_CONTRACT_ADDRESS: &str = "COCONUT_BANDWIDTH_CONTRACT_ADDRESS";
pub const GROUP_CONTRACT_ADDRESS: &str = "GROUP_CONTRACT_ADDRESS";
pub const MULTISIG_CONTRACT_ADDRESS: &str = "MULTISIG_CONTRACT_ADDRESS";
+9 -9
View File
@@ -7,16 +7,16 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
tokio = { version = "1.24.1", features = [] }
tokio-stream = "0.1.11" # this one seems to be a thing until `Stream` trait is stabilised in stdlib
tokio-util = { version = "0.7.4", features = ["time"] }
[target."cfg(target_arch = \"wasm32\")".dependencies.wasm-timer]
git = "https://github.com/mmsinclair/wasm-timer"
rev = "b9d1a54ad514c2f230a026afe0dde341e98cd7b6"
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.tokio]
workspace = true
[target."cfg(target_arch = \"wasm32\")".dependencies.slab]
version = "0.4.4"
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.tokio-util]
version = "0.7.4"
features = ["time"]
[target."cfg(target_arch = \"wasm32\")".dependencies.wasmtimer]
workspace = true
features = ["tokio", "tokio-util"]
[target."cfg(target_arch = \"wasm32\")".dependencies.futures-core]
version = "0.3.0"

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