Compare commits
40 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5a7e956c93 | |||
| 3410a2b2e0 | |||
| 1349242367 | |||
| 8f812cc610 | |||
| 05aa0dbd8e | |||
| 5b69b0e7d9 | |||
| be88a9b277 | |||
| fce2c704af | |||
| d8a95d3810 | |||
| 191aa149df | |||
| f4df1a9168 | |||
| 62316244d9 | |||
| a26c6d7a29 | |||
| 8fda246a3c | |||
| 5620fd7009 | |||
| 122612fa03 | |||
| 53db18df2c | |||
| e00910bcb8 | |||
| 0af9b3c6c8 | |||
| 2d60a9da3f | |||
| 795efb9f0b | |||
| 695d34735c | |||
| 314d7a7526 | |||
| a86c1a6a60 | |||
| 7ad2865250 | |||
| 49440bf60e | |||
| b3b43b56be | |||
| 4a23729a6a | |||
| 5711bbd0c1 | |||
| 1b1f0293ec | |||
| 9285aaf487 | |||
| 55bd7f8a61 | |||
| b66c4cf0bb | |||
| 4696470b19 | |||
| c7147ebfb2 | |||
| a344cda916 | |||
| 7b71775e08 | |||
| 5964f104c5 | |||
| 0bfc1be1d5 | |||
| aedacf6c65 |
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
@@ -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
@@ -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"
|
||||
|
||||
@@ -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,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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -16,7 +16,8 @@ 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};
|
||||
@@ -75,6 +76,7 @@ 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>,
|
||||
@@ -99,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 {
|
||||
@@ -122,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(
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Generated
+80
-107
@@ -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"
|
||||
|
||||
@@ -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" }
|
||||
|
||||
@@ -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! {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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...")
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
+1
@@ -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()
|
||||
}
|
||||
|
||||
+1
@@ -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))
|
||||
}
|
||||
}
|
||||
}
|
||||
+7
-4
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -34,6 +34,7 @@ nym-pemstore = { path = "../../common/pemstore", version = "0.3.0" }
|
||||
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"]
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -6,12 +6,8 @@ use std::task::{Context, Poll, Waker};
|
||||
use std::time::Duration;
|
||||
use tokio_stream::Stream;
|
||||
|
||||
pub use tokio::time::error::Error as TimerError;
|
||||
|
||||
// this is a copy of tokio-util delay_queue with `Sleep` and `Instant` being replaced with
|
||||
// `wasm_timer` equivalents
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
mod wasm_delay_queue;
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
type DelayQueue<T> = tokio_util::time::DelayQueue<T>;
|
||||
@@ -23,13 +19,13 @@ pub type QueueKey = tokio_util::time::delay_queue::Key;
|
||||
use tokio::time::Instant;
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
type DelayQueue<T> = crate::wasm_delay_queue::DelayQueue<T>;
|
||||
type DelayQueue<T> = wasmtimer::tokio_util::DelayQueue<T>;
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
pub use crate::wasm_delay_queue::delay_queue::Expired;
|
||||
pub use wasmtimer::tokio_util::delay_queue::Expired;
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
pub type QueueKey = crate::wasm_delay_queue::delay_queue::Key;
|
||||
pub type QueueKey = wasmtimer::tokio_util::delay_queue::Key;
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
use wasm_timer::Instant;
|
||||
use wasmtimer::std::Instant;
|
||||
|
||||
/// A variant of tokio's `DelayQueue`, such that its `Stream` implementation will never return a 'None'.
|
||||
pub struct NonExhaustiveDelayQueue<T> {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,42 +0,0 @@
|
||||
use std::time::Duration;
|
||||
|
||||
mod wheel;
|
||||
|
||||
pub mod delay_queue;
|
||||
|
||||
#[doc(inline)]
|
||||
pub use delay_queue::DelayQueue;
|
||||
|
||||
// ===== Internal utils =====
|
||||
|
||||
enum Round {
|
||||
Up,
|
||||
Down,
|
||||
}
|
||||
|
||||
/// Convert a `Duration` to milliseconds, rounding up and saturating at
|
||||
/// `u64::MAX`.
|
||||
///
|
||||
/// The saturating is fine because `u64::MAX` milliseconds are still many
|
||||
/// million years.
|
||||
#[inline]
|
||||
fn ms(duration: Duration, round: Round) -> u64 {
|
||||
const NANOS_PER_MILLI: u32 = 1_000_000;
|
||||
const MILLIS_PER_SEC: u64 = 1_000;
|
||||
|
||||
// Round up.
|
||||
let millis = match round {
|
||||
Round::Up => (duration.subsec_nanos() + NANOS_PER_MILLI - 1) / NANOS_PER_MILLI,
|
||||
Round::Down => duration.subsec_millis(),
|
||||
};
|
||||
|
||||
duration
|
||||
.as_secs()
|
||||
.saturating_mul(MILLIS_PER_SEC)
|
||||
.saturating_add(u64::from(millis))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn sleep_until(deadline: wasm_timer::Instant) -> wasm_timer::Delay {
|
||||
wasm_timer::Delay::new_at(deadline)
|
||||
}
|
||||
@@ -1,253 +0,0 @@
|
||||
use crate::wasm_delay_queue::wheel::Stack;
|
||||
|
||||
use std::fmt;
|
||||
|
||||
/// Wheel for a single level in the timer. This wheel contains 64 slots.
|
||||
pub(crate) struct Level<T> {
|
||||
level: usize,
|
||||
|
||||
/// Bit field tracking which slots currently contain entries.
|
||||
///
|
||||
/// Using a bit field to track slots that contain entries allows avoiding a
|
||||
/// scan to find entries. This field is updated when entries are added or
|
||||
/// removed from a slot.
|
||||
///
|
||||
/// The least-significant bit represents slot zero.
|
||||
occupied: u64,
|
||||
|
||||
/// Slots
|
||||
slot: [T; LEVEL_MULT],
|
||||
}
|
||||
|
||||
/// Indicates when a slot must be processed next.
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct Expiration {
|
||||
/// The level containing the slot.
|
||||
pub(crate) level: usize,
|
||||
|
||||
/// The slot index.
|
||||
pub(crate) slot: usize,
|
||||
|
||||
/// The instant at which the slot needs to be processed.
|
||||
pub(crate) deadline: u64,
|
||||
}
|
||||
|
||||
/// Level multiplier.
|
||||
///
|
||||
/// Being a power of 2 is very important.
|
||||
const LEVEL_MULT: usize = 64;
|
||||
|
||||
impl<T: Stack> Level<T> {
|
||||
pub(crate) fn new(level: usize) -> Level<T> {
|
||||
// Rust's derived implementations for arrays require that the value
|
||||
// contained by the array be `Copy`. So, here we have to manually
|
||||
// initialize every single slot.
|
||||
macro_rules! s {
|
||||
() => {
|
||||
T::default()
|
||||
};
|
||||
}
|
||||
|
||||
Level {
|
||||
level,
|
||||
occupied: 0,
|
||||
slot: [
|
||||
// It does not look like the necessary traits are
|
||||
// derived for [T; 64].
|
||||
s!(),
|
||||
s!(),
|
||||
s!(),
|
||||
s!(),
|
||||
s!(),
|
||||
s!(),
|
||||
s!(),
|
||||
s!(),
|
||||
s!(),
|
||||
s!(),
|
||||
s!(),
|
||||
s!(),
|
||||
s!(),
|
||||
s!(),
|
||||
s!(),
|
||||
s!(),
|
||||
s!(),
|
||||
s!(),
|
||||
s!(),
|
||||
s!(),
|
||||
s!(),
|
||||
s!(),
|
||||
s!(),
|
||||
s!(),
|
||||
s!(),
|
||||
s!(),
|
||||
s!(),
|
||||
s!(),
|
||||
s!(),
|
||||
s!(),
|
||||
s!(),
|
||||
s!(),
|
||||
s!(),
|
||||
s!(),
|
||||
s!(),
|
||||
s!(),
|
||||
s!(),
|
||||
s!(),
|
||||
s!(),
|
||||
s!(),
|
||||
s!(),
|
||||
s!(),
|
||||
s!(),
|
||||
s!(),
|
||||
s!(),
|
||||
s!(),
|
||||
s!(),
|
||||
s!(),
|
||||
s!(),
|
||||
s!(),
|
||||
s!(),
|
||||
s!(),
|
||||
s!(),
|
||||
s!(),
|
||||
s!(),
|
||||
s!(),
|
||||
s!(),
|
||||
s!(),
|
||||
s!(),
|
||||
s!(),
|
||||
s!(),
|
||||
s!(),
|
||||
s!(),
|
||||
s!(),
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
/// Finds the slot that needs to be processed next and returns the slot and
|
||||
/// `Instant` at which this slot must be processed.
|
||||
pub(crate) fn next_expiration(&self, now: u64) -> Option<Expiration> {
|
||||
// Use the `occupied` bit field to get the index of the next slot that
|
||||
// needs to be processed.
|
||||
let slot = match self.next_occupied_slot(now) {
|
||||
Some(slot) => slot,
|
||||
None => return None,
|
||||
};
|
||||
|
||||
// From the slot index, calculate the `Instant` at which it needs to be
|
||||
// processed. This value *must* be in the future with respect to `now`.
|
||||
|
||||
let level_range = level_range(self.level);
|
||||
let slot_range = slot_range(self.level);
|
||||
|
||||
// TODO: This can probably be simplified w/ power of 2 math
|
||||
let level_start = now - (now % level_range);
|
||||
let deadline = level_start + slot as u64 * slot_range;
|
||||
|
||||
debug_assert!(
|
||||
deadline >= now,
|
||||
"deadline={}; now={}; level={}; slot={}; occupied={:b}",
|
||||
deadline,
|
||||
now,
|
||||
self.level,
|
||||
slot,
|
||||
self.occupied
|
||||
);
|
||||
|
||||
Some(Expiration {
|
||||
level: self.level,
|
||||
slot,
|
||||
deadline,
|
||||
})
|
||||
}
|
||||
|
||||
fn next_occupied_slot(&self, now: u64) -> Option<usize> {
|
||||
if self.occupied == 0 {
|
||||
return None;
|
||||
}
|
||||
|
||||
// Get the slot for now using Maths
|
||||
let now_slot = (now / slot_range(self.level)) as usize;
|
||||
let occupied = self.occupied.rotate_right(now_slot as u32);
|
||||
let zeros = occupied.trailing_zeros() as usize;
|
||||
let slot = (zeros + now_slot) % 64;
|
||||
|
||||
Some(slot)
|
||||
}
|
||||
|
||||
pub(crate) fn add_entry(&mut self, when: u64, item: T::Owned, store: &mut T::Store) {
|
||||
let slot = slot_for(when, self.level);
|
||||
|
||||
self.slot[slot].push(item, store);
|
||||
self.occupied |= occupied_bit(slot);
|
||||
}
|
||||
|
||||
pub(crate) fn remove_entry(&mut self, when: u64, item: &T::Borrowed, store: &mut T::Store) {
|
||||
let slot = slot_for(when, self.level);
|
||||
|
||||
self.slot[slot].remove(item, store);
|
||||
|
||||
if self.slot[slot].is_empty() {
|
||||
// The bit is currently set
|
||||
debug_assert!(self.occupied & occupied_bit(slot) != 0);
|
||||
|
||||
// Unset the bit
|
||||
self.occupied ^= occupied_bit(slot);
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn pop_entry_slot(&mut self, slot: usize, store: &mut T::Store) -> Option<T::Owned> {
|
||||
let ret = self.slot[slot].pop(store);
|
||||
|
||||
if ret.is_some() && self.slot[slot].is_empty() {
|
||||
// The bit is currently set
|
||||
debug_assert!(self.occupied & occupied_bit(slot) != 0);
|
||||
|
||||
self.occupied ^= occupied_bit(slot);
|
||||
}
|
||||
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> fmt::Debug for Level<T> {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt.debug_struct("Level")
|
||||
.field("occupied", &self.occupied)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
fn occupied_bit(slot: usize) -> u64 {
|
||||
1 << slot
|
||||
}
|
||||
|
||||
fn slot_range(level: usize) -> u64 {
|
||||
LEVEL_MULT.pow(level as u32) as u64
|
||||
}
|
||||
|
||||
fn level_range(level: usize) -> u64 {
|
||||
LEVEL_MULT as u64 * slot_range(level)
|
||||
}
|
||||
|
||||
/// Convert a duration (milliseconds) and a level to a slot position
|
||||
fn slot_for(duration: u64, level: usize) -> usize {
|
||||
((duration >> (level * 6)) % LEVEL_MULT as u64) as usize
|
||||
}
|
||||
|
||||
#[cfg(all(test, not(loom)))]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_slot_for() {
|
||||
for pos in 0..64 {
|
||||
assert_eq!(pos as usize, slot_for(pos, 0));
|
||||
}
|
||||
|
||||
for level in 1..5 {
|
||||
for pos in level..64 {
|
||||
let a = pos * 64_usize.pow(level as u32);
|
||||
assert_eq!(pos as usize, slot_for(a as u64, level));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,315 +0,0 @@
|
||||
mod level;
|
||||
pub(crate) use self::level::Expiration;
|
||||
use self::level::Level;
|
||||
|
||||
mod stack;
|
||||
pub(crate) use self::stack::Stack;
|
||||
|
||||
use std::borrow::Borrow;
|
||||
use std::fmt::Debug;
|
||||
use std::usize;
|
||||
|
||||
/// Timing wheel implementation.
|
||||
///
|
||||
/// This type provides the hashed timing wheel implementation that backs `Timer`
|
||||
/// and `DelayQueue`.
|
||||
///
|
||||
/// The structure is generic over `T: Stack`. This allows handling timeout data
|
||||
/// being stored on the heap or in a slab. In order to support the latter case,
|
||||
/// the slab must be passed into each function allowing the implementation to
|
||||
/// lookup timer entries.
|
||||
///
|
||||
/// See `Timer` documentation for some implementation notes.
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct Wheel<T> {
|
||||
/// The number of milliseconds elapsed since the wheel started.
|
||||
elapsed: u64,
|
||||
|
||||
/// Timer wheel.
|
||||
///
|
||||
/// Levels:
|
||||
///
|
||||
/// * 1 ms slots / 64 ms range
|
||||
/// * 64 ms slots / ~ 4 sec range
|
||||
/// * ~ 4 sec slots / ~ 4 min range
|
||||
/// * ~ 4 min slots / ~ 4 hr range
|
||||
/// * ~ 4 hr slots / ~ 12 day range
|
||||
/// * ~ 12 day slots / ~ 2 yr range
|
||||
levels: Vec<Level<T>>,
|
||||
}
|
||||
|
||||
/// Number of levels. Each level has 64 slots. By using 6 levels with 64 slots
|
||||
/// each, the timer is able to track time up to 2 years into the future with a
|
||||
/// precision of 1 millisecond.
|
||||
const NUM_LEVELS: usize = 6;
|
||||
|
||||
/// The maximum duration of a delay
|
||||
const MAX_DURATION: u64 = (1 << (6 * NUM_LEVELS)) - 1;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) enum InsertError {
|
||||
Elapsed,
|
||||
Invalid,
|
||||
}
|
||||
|
||||
impl<T> Wheel<T>
|
||||
where
|
||||
T: Stack,
|
||||
{
|
||||
/// Create a new timing wheel
|
||||
pub(crate) fn new() -> Wheel<T> {
|
||||
let levels = (0..NUM_LEVELS).map(Level::new).collect();
|
||||
|
||||
Wheel { elapsed: 0, levels }
|
||||
}
|
||||
|
||||
/// Return the number of milliseconds that have elapsed since the timing
|
||||
/// wheel's creation.
|
||||
pub(crate) fn elapsed(&self) -> u64 {
|
||||
self.elapsed
|
||||
}
|
||||
|
||||
/// Insert an entry into the timing wheel.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `when`: is the instant at which the entry should be fired. It is
|
||||
/// represented as the number of milliseconds since the creation
|
||||
/// of the timing wheel.
|
||||
///
|
||||
/// * `item`: The item to insert into the wheel.
|
||||
///
|
||||
/// * `store`: The slab or `()` when using heap storage.
|
||||
///
|
||||
/// # Return
|
||||
///
|
||||
/// Returns `Ok` when the item is successfully inserted, `Err` otherwise.
|
||||
///
|
||||
/// `Err(Elapsed)` indicates that `when` represents an instant that has
|
||||
/// already passed. In this case, the caller should fire the timeout
|
||||
/// immediately.
|
||||
///
|
||||
/// `Err(Invalid)` indicates an invalid `when` argument as been supplied.
|
||||
pub(crate) fn insert(
|
||||
&mut self,
|
||||
when: u64,
|
||||
item: T::Owned,
|
||||
store: &mut T::Store,
|
||||
) -> Result<(), (T::Owned, InsertError)> {
|
||||
if when <= self.elapsed {
|
||||
return Err((item, InsertError::Elapsed));
|
||||
} else if when - self.elapsed > MAX_DURATION {
|
||||
return Err((item, InsertError::Invalid));
|
||||
}
|
||||
|
||||
// Get the level at which the entry should be stored
|
||||
let level = self.level_for(when);
|
||||
|
||||
self.levels[level].add_entry(when, item, store);
|
||||
|
||||
debug_assert!({
|
||||
self.levels[level]
|
||||
.next_expiration(self.elapsed)
|
||||
.map(|e| e.deadline >= self.elapsed)
|
||||
.unwrap_or(true)
|
||||
});
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Remove `item` from the timing wheel.
|
||||
#[track_caller]
|
||||
pub(crate) fn remove(&mut self, item: &T::Borrowed, store: &mut T::Store) {
|
||||
let when = T::when(item, store);
|
||||
|
||||
assert!(
|
||||
self.elapsed <= when,
|
||||
"elapsed={}; when={}",
|
||||
self.elapsed,
|
||||
when
|
||||
);
|
||||
|
||||
let level = self.level_for(when);
|
||||
|
||||
self.levels[level].remove_entry(when, item, store);
|
||||
}
|
||||
|
||||
/// Instant at which to poll
|
||||
pub(crate) fn poll_at(&self) -> Option<u64> {
|
||||
self.next_expiration().map(|expiration| expiration.deadline)
|
||||
}
|
||||
|
||||
/// Advances the timer up to the instant represented by `now`.
|
||||
pub(crate) fn poll(&mut self, now: u64, store: &mut T::Store) -> Option<T::Owned> {
|
||||
loop {
|
||||
let expiration = self.next_expiration().and_then(|expiration| {
|
||||
if expiration.deadline > now {
|
||||
None
|
||||
} else {
|
||||
Some(expiration)
|
||||
}
|
||||
});
|
||||
|
||||
match expiration {
|
||||
Some(ref expiration) => {
|
||||
if let Some(item) = self.poll_expiration(expiration, store) {
|
||||
return Some(item);
|
||||
}
|
||||
|
||||
self.set_elapsed(expiration.deadline);
|
||||
}
|
||||
None => {
|
||||
// in this case the poll did not indicate an expiration
|
||||
// _and_ we were not able to find a next expiration in
|
||||
// the current list of timers. advance to the poll's
|
||||
// current time and do nothing else.
|
||||
self.set_elapsed(now);
|
||||
return None;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the instant at which the next timeout expires.
|
||||
fn next_expiration(&self) -> Option<Expiration> {
|
||||
// Check all levels
|
||||
for level in 0..NUM_LEVELS {
|
||||
if let Some(expiration) = self.levels[level].next_expiration(self.elapsed) {
|
||||
// There cannot be any expirations at a higher level that happen
|
||||
// before this one.
|
||||
debug_assert!(self.no_expirations_before(level + 1, expiration.deadline));
|
||||
|
||||
return Some(expiration);
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
/// Used for debug assertions
|
||||
fn no_expirations_before(&self, start_level: usize, before: u64) -> bool {
|
||||
let mut res = true;
|
||||
|
||||
for l2 in start_level..NUM_LEVELS {
|
||||
if let Some(e2) = self.levels[l2].next_expiration(self.elapsed) {
|
||||
if e2.deadline < before {
|
||||
res = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
|
||||
/// iteratively find entries that are between the wheel's current
|
||||
/// time and the expiration time. for each in that population either
|
||||
/// return it for notification (in the case of the last level) or tier
|
||||
/// it down to the next level (in all other cases).
|
||||
pub(crate) fn poll_expiration(
|
||||
&mut self,
|
||||
expiration: &Expiration,
|
||||
store: &mut T::Store,
|
||||
) -> Option<T::Owned> {
|
||||
while let Some(item) = self.pop_entry(expiration, store) {
|
||||
if expiration.level == 0 {
|
||||
debug_assert_eq!(T::when(item.borrow(), store), expiration.deadline);
|
||||
|
||||
return Some(item);
|
||||
} else {
|
||||
let when = T::when(item.borrow(), store);
|
||||
|
||||
let next_level = expiration.level - 1;
|
||||
|
||||
self.levels[next_level].add_entry(when, item, store);
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
fn set_elapsed(&mut self, when: u64) {
|
||||
assert!(
|
||||
self.elapsed <= when,
|
||||
"elapsed={:?}; when={:?}",
|
||||
self.elapsed,
|
||||
when
|
||||
);
|
||||
|
||||
if when > self.elapsed {
|
||||
self.elapsed = when;
|
||||
}
|
||||
}
|
||||
|
||||
fn pop_entry(&mut self, expiration: &Expiration, store: &mut T::Store) -> Option<T::Owned> {
|
||||
self.levels[expiration.level].pop_entry_slot(expiration.slot, store)
|
||||
}
|
||||
|
||||
fn level_for(&self, when: u64) -> usize {
|
||||
level_for(self.elapsed, when)
|
||||
}
|
||||
}
|
||||
|
||||
fn level_for(elapsed: u64, when: u64) -> usize {
|
||||
const SLOT_MASK: u64 = (1 << 6) - 1;
|
||||
|
||||
// Mask in the trailing bits ignored by the level calculation in order to cap
|
||||
// the possible leading zeros
|
||||
let masked = elapsed ^ when | SLOT_MASK;
|
||||
|
||||
let leading_zeros = masked.leading_zeros() as usize;
|
||||
let significant = 63 - leading_zeros;
|
||||
significant / 6
|
||||
}
|
||||
|
||||
#[cfg(all(test, not(loom)))]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_level_for() {
|
||||
for pos in 0..64 {
|
||||
assert_eq!(
|
||||
0,
|
||||
level_for(0, pos),
|
||||
"level_for({}) -- binary = {:b}",
|
||||
pos,
|
||||
pos
|
||||
);
|
||||
}
|
||||
|
||||
for level in 1..5 {
|
||||
for pos in level..64 {
|
||||
let a = pos * 64_usize.pow(level as u32);
|
||||
assert_eq!(
|
||||
level,
|
||||
level_for(0, a as u64),
|
||||
"level_for({}) -- binary = {:b}",
|
||||
a,
|
||||
a
|
||||
);
|
||||
|
||||
if pos > level {
|
||||
let a = a - 1;
|
||||
assert_eq!(
|
||||
level,
|
||||
level_for(0, a as u64),
|
||||
"level_for({}) -- binary = {:b}",
|
||||
a,
|
||||
a
|
||||
);
|
||||
}
|
||||
|
||||
if pos < 64 {
|
||||
let a = a + 1;
|
||||
assert_eq!(
|
||||
level,
|
||||
level_for(0, a as u64),
|
||||
"level_for({}) -- binary = {:b}",
|
||||
a,
|
||||
a
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
use std::borrow::Borrow;
|
||||
use std::cmp::Eq;
|
||||
use std::hash::Hash;
|
||||
|
||||
/// Abstracts the stack operations needed to track timeouts.
|
||||
pub(crate) trait Stack: Default {
|
||||
/// Type of the item stored in the stack
|
||||
type Owned: Borrow<Self::Borrowed>;
|
||||
|
||||
/// Borrowed item
|
||||
type Borrowed: Eq + Hash;
|
||||
|
||||
/// Item storage, this allows a slab to be used instead of just the heap
|
||||
type Store;
|
||||
|
||||
/// Returns `true` if the stack is empty
|
||||
fn is_empty(&self) -> bool;
|
||||
|
||||
/// Push an item onto the stack
|
||||
fn push(&mut self, item: Self::Owned, store: &mut Self::Store);
|
||||
|
||||
/// Pop an item from the stack
|
||||
fn pop(&mut self, store: &mut Self::Store) -> Option<Self::Owned>;
|
||||
|
||||
fn remove(&mut self, item: &Self::Borrowed, store: &mut Self::Store);
|
||||
|
||||
fn when(item: &Self::Borrowed, store: &Self::Store) -> u64;
|
||||
}
|
||||
@@ -40,3 +40,8 @@ path = "framing"
|
||||
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.tokio]
|
||||
version = "1.24.1"
|
||||
features = ["sync"]
|
||||
|
||||
[features]
|
||||
default = ["sphinx"]
|
||||
sphinx = ["nym-crypto/sphinx", "nym-sphinx-params/sphinx", "nym-sphinx-types/sphinx"]
|
||||
outfox = ["nym-crypto/outfox", "nym-sphinx-params/outfox", "nym-sphinx-types/outfox"]
|
||||
|
||||
@@ -12,5 +12,6 @@ bytes = "1.0"
|
||||
tokio-util = { version = "0.7.4", features = ["codec"] }
|
||||
thiserror = "1.0.37"
|
||||
|
||||
nym-sphinx-types = { path = "../types" }
|
||||
nym-sphinx-params = { path = "../params" }
|
||||
nym-sphinx-types = { path = "../types", features = ["sphinx", "outfox"] }
|
||||
nym-sphinx-params = { path = "../params", features = ["sphinx", "outfox"] }
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user