Compare commits
99 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 887ae8c789 | |||
| 12759a8460 | |||
| 00b737d362 | |||
| bd7b5db68f | |||
| 80184c3a51 | |||
| a13e9d8cc3 | |||
| 003a835ee6 | |||
| a60f37ae88 | |||
| 8d400ed4e0 | |||
| e4ba6c815e | |||
| 1ee18d9efe | |||
| 1fc7e07028 | |||
| 8758bea17c | |||
| 9d8a686760 | |||
| 435d9d3115 | |||
| 275cd9ff92 | |||
| 8435cf91e5 | |||
| 3460ce70a3 | |||
| 0ddaf3b50b | |||
| a103acaf70 | |||
| 08aa0af562 | |||
| 493390d92b | |||
| 8113948f48 | |||
| c3e3ef1737 | |||
| 45f4eeeff2 | |||
| f76d677f64 | |||
| 050a58affa | |||
| 065b3891f2 | |||
| 59da117e8f | |||
| 3d13274219 | |||
| 561566f3c4 | |||
| 6879c211ee | |||
| c7f2ef7074 | |||
| fb43e917cb | |||
| e79450a082 | |||
| 2e365026b7 | |||
| cd706aa67e | |||
| 304b192f52 | |||
| 8c979e3bac | |||
| 279b00d833 | |||
| 49fd0dc9e1 | |||
| 9a9d91cb4f | |||
| 5c08a89be3 | |||
| fd88776998 | |||
| 1339e20420 | |||
| 51b511b27e | |||
| 27ac34522c | |||
| 5e0d1bb14e | |||
| c16746a47b | |||
| a21052b72e | |||
| 92e9da7be5 | |||
| 143b336978 | |||
| d4293c9bae | |||
| e2d1806e49 | |||
| 469f85fc49 | |||
| 1202a2f5f4 | |||
| 6030bf6c95 | |||
| 09a771f58f | |||
| 676a909aee | |||
| e37145422c | |||
| 4ad52accc0 | |||
| 784fae2204 | |||
| 8aa5711bee | |||
| 07022314fc | |||
| 76c3081470 | |||
| d399161d31 | |||
| 27fb4ae0cc | |||
| 74392a2886 | |||
| 457c478a03 | |||
| 5e95992427 | |||
| d7eecd481c | |||
| e08fc4894b | |||
| fabd48b7ea | |||
| 894e0bd1bf | |||
| f86e088663 | |||
| f76300669a | |||
| 333ace1f97 | |||
| 487bf6732e | |||
| 5d4a0fef55 | |||
| 1627146c0e | |||
| ae40a00b8f | |||
| 7f3c0470e0 | |||
| 1bc26ed79f | |||
| 60fa5cfeb8 | |||
| 3b7088aeea | |||
| 803850be74 | |||
| 3dc62a9a60 | |||
| 5753b79997 | |||
| 2a6aa13ecd | |||
| d5c9e1d8cb | |||
| 87751894d9 | |||
| c8c3928575 | |||
| 2fa8da8117 | |||
| 4548ef4d05 | |||
| 7f147ee2b0 | |||
| 48bcd7e802 | |||
| aad028be3f | |||
| 6db3b34bcb | |||
| f9383578da |
@@ -5,7 +5,7 @@ on:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-20.04-16-core
|
||||
runs-on: arc-ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install Dependencies (Linux)
|
||||
@@ -99,24 +99,3 @@ jobs:
|
||||
run: vercel deploy --prebuilt --prod --token=${{ secrets.VERCEL_TOKEN }}
|
||||
working-directory: dist/docs
|
||||
continue-on-error: false
|
||||
|
||||
- name: Matrix - Node Install
|
||||
run: npm install
|
||||
working-directory: .github/workflows/support-files
|
||||
- name: Matrix - Send Notification
|
||||
env:
|
||||
NYM_NOTIFICATION_KIND: cd-docs
|
||||
NYM_PROJECT_NAME: "Docs CD"
|
||||
NYM_CI_WWW_BASE: "${{ secrets.NYM_CD_WWW_BASE }}"
|
||||
NYM_CI_WWW_LOCATION: "${{ env.GITHUB_REF_SLUG }}"
|
||||
GIT_COMMIT_MESSAGE: "${{ github.event.head_commit.message }}"
|
||||
GIT_BRANCH: "${GITHUB_REF##*/}"
|
||||
MATRIX_SERVER: "${{ secrets.MATRIX_SERVER }}"
|
||||
MATRIX_ROOM: "${{ secrets.MATRIX_ROOM_DOCS }}"
|
||||
MATRIX_USER_ID: "${{ secrets.MATRIX_USER_ID }}"
|
||||
MATRIX_TOKEN: "${{ secrets.MATRIX_TOKEN }}"
|
||||
MATRIX_DEVICE_ID: "${{ secrets.MATRIX_DEVICE_ID }}"
|
||||
IS_SUCCESS: "${{ job.status == 'success' }}"
|
||||
uses: docker://keybaseio/client:stable-node
|
||||
with:
|
||||
args: .github/workflows/support-files/notifications/entry_point.sh
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
name: ci-build-ts
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
paths:
|
||||
- "ts-packages/**"
|
||||
@@ -9,7 +10,7 @@ on:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-20.04-16-core
|
||||
runs-on: arc-ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install rsync
|
||||
@@ -45,23 +46,3 @@ jobs:
|
||||
REMOTE_USER: ${{ secrets.CI_WWW_REMOTE_USER }}
|
||||
TARGET: ${{ secrets.CI_WWW_REMOTE_TARGET }}/ts-${{ env.GITHUB_REF_SLUG }}-example
|
||||
EXCLUDE: "/dist/, /node_modules/"
|
||||
- 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
|
||||
|
||||
@@ -26,6 +26,7 @@ on:
|
||||
- "nym-api/**"
|
||||
- "nym-node/**"
|
||||
- "nym-outfox/**"
|
||||
- 'nym-data-observatory/**'
|
||||
- "nym-validator-rewarder/**"
|
||||
- "sdk/rust/nym-sdk/**"
|
||||
- "service-providers/**"
|
||||
@@ -96,6 +97,7 @@ jobs:
|
||||
target/release/nym-socks5-client
|
||||
target/release/nym-api
|
||||
target/release/nym-network-requester
|
||||
target/release/nym-data-observatory
|
||||
target/release/nym-cli
|
||||
target/release/nymvisor
|
||||
target/release/nym-node
|
||||
@@ -113,6 +115,7 @@ jobs:
|
||||
cp target/release/nym-socks5-client $OUTPUT_DIR
|
||||
cp target/release/nym-api $OUTPUT_DIR
|
||||
cp target/release/nym-network-requester $OUTPUT_DIR
|
||||
cp target/release/nym-data-observatory $OUTPUT_DIR
|
||||
cp target/release/nymvisor $OUTPUT_DIR
|
||||
cp target/release/nym-node $OUTPUT_DIR
|
||||
cp target/release/nym-cli $OUTPUT_DIR
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
name: ci-build-vpn-api-wasm
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- 'common/**'
|
||||
- 'nym-vpn-api/**'
|
||||
- '.github/workflows/ci-build-vpn-api-wasm.yml'
|
||||
|
||||
jobs:
|
||||
wasm:
|
||||
runs-on: arc-ubuntu-22.04
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
steps:
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install Rust toolchain
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
profile: minimal
|
||||
toolchain: stable
|
||||
target: wasm32-unknown-unknown
|
||||
override: true
|
||||
components: rustfmt, clippy
|
||||
|
||||
- name: Install wasm-pack
|
||||
run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
|
||||
|
||||
- name: Install wasm-opt
|
||||
uses: ./.github/actions/install-wasm-opt
|
||||
with:
|
||||
version: '116'
|
||||
|
||||
- name: Install wasm-bindgen-cli
|
||||
run: cargo install wasm-bindgen-cli
|
||||
|
||||
- name: "Build"
|
||||
run: make
|
||||
working-directory: nym-vpn-api/vpn-api-lib-wasm
|
||||
@@ -0,0 +1,45 @@
|
||||
name: ci-build-vpn-api
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- 'common/**'
|
||||
- 'nym-vpn-api/**'
|
||||
- '.github/workspace/ci-build-vpn-api.yml'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: arc-ubuntu-22.04
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
MANIFEST_PATH: "--manifest-path nym-vpn-api/Cargo.toml"
|
||||
steps:
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install rust toolchain
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
profile: minimal
|
||||
toolchain: stable
|
||||
override: true
|
||||
components: rustfmt, clippy
|
||||
|
||||
- name: Check formatting
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: fmt
|
||||
args: ${{ env.MANIFEST_PATH }} --all -- --check
|
||||
|
||||
- name: Build
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: build
|
||||
args: ${{ env.MANIFEST_PATH }} --workspace --all-targets
|
||||
|
||||
- name: Clippy
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: clippy
|
||||
args: ${{ env.MANIFEST_PATH }} --workspace --all-targets -- -D warnings
|
||||
@@ -16,6 +16,7 @@ on:
|
||||
- 'nym-api/**'
|
||||
- 'nym-node/**'
|
||||
- 'nym-outfox/**'
|
||||
- 'nym-data-observatory/**'
|
||||
- 'nym-validator-rewarder/**'
|
||||
- 'tools/**'
|
||||
- 'wasm/**'
|
||||
@@ -29,7 +30,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [arc-ubuntu-20.04, custom-runner-mac-m1]
|
||||
os: [ arc-ubuntu-20.04, custom-runner-mac-m1 ]
|
||||
runs-on: ${{ matrix.os }}
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
@@ -61,14 +62,6 @@ jobs:
|
||||
with:
|
||||
command: build
|
||||
|
||||
# while disabled by default, this build ensures nothing is broken within
|
||||
# `axum` feature
|
||||
- name: Build with `axum` feature
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: build
|
||||
args: --features axum
|
||||
|
||||
- name: Build all examples
|
||||
if: contains(matrix.os, 'ubuntu')
|
||||
uses: actions-rs/cargo@v1
|
||||
@@ -94,4 +87,4 @@ jobs:
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: clippy
|
||||
args: --workspace --all-targets --features axum -- -D warnings
|
||||
args: --workspace --all-targets -- -D warnings
|
||||
|
||||
@@ -22,4 +22,4 @@ jobs:
|
||||
with:
|
||||
log-level: warn
|
||||
command: check ${{ matrix.checks }}
|
||||
argument: --all-features
|
||||
arguments: --all-features
|
||||
|
||||
@@ -10,7 +10,7 @@ on:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-20.04-16-core
|
||||
runs-on: arc-ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install Dependencies (Linux)
|
||||
@@ -70,24 +70,3 @@ jobs:
|
||||
REMOTE_USER: ${{ secrets.CI_WWW_REMOTE_USER }}
|
||||
TARGET: ${{ secrets.CI_WWW_REMOTE_TARGET }}/docs-${{ env.GITHUB_REF_SLUG }}
|
||||
EXCLUDE: "/node_modules/"
|
||||
|
||||
- name: Matrix - Node Install
|
||||
run: npm install
|
||||
working-directory: .github/workflows/support-files
|
||||
- name: Matrix - Send Notification
|
||||
env:
|
||||
NYM_NOTIFICATION_KIND: ci-docs
|
||||
NYM_PROJECT_NAME: "Docs CI"
|
||||
NYM_CI_WWW_BASE: "${{ secrets.NYM_CI_WWW_BASE }}"
|
||||
NYM_CI_WWW_LOCATION: "docs-${{ env.GITHUB_REF_SLUG }}"
|
||||
GIT_COMMIT_MESSAGE: "${{ github.event.head_commit.message }}"
|
||||
GIT_BRANCH: "${GITHUB_REF##*/}"
|
||||
MATRIX_SERVER: "${{ secrets.MATRIX_SERVER }}"
|
||||
MATRIX_ROOM: "${{ secrets.MATRIX_ROOM_DOCS }}"
|
||||
MATRIX_USER_ID: "${{ secrets.MATRIX_USER_ID }}"
|
||||
MATRIX_TOKEN: "${{ secrets.MATRIX_TOKEN }}"
|
||||
MATRIX_DEVICE_ID: "${{ secrets.MATRIX_DEVICE_ID }}"
|
||||
IS_SUCCESS: "${{ job.status == 'success' }}"
|
||||
uses: docker://keybaseio/client:stable-node
|
||||
with:
|
||||
args: .github/workflows/support-files/notifications/entry_point.sh
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
name: ci-lint-typescript
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
paths:
|
||||
- "ts-packages/**"
|
||||
@@ -14,7 +15,7 @@ on:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-20.04-16-core
|
||||
runs-on: arc-ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: rlespinasse/github-slug-action@v3.x
|
||||
@@ -53,24 +54,3 @@ jobs:
|
||||
run: yarn lint
|
||||
- name: Typecheck with tsc
|
||||
run: yarn tsc
|
||||
|
||||
- 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,7 +4,7 @@ on:
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
runs-on: ubuntu-20.04-16-core
|
||||
runs-on: arc-ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
name: Build and upload Node Status API container to harbor.nymte.ch
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
WORKING_DIRECTORY: "nym-node-status-api"
|
||||
CONTAINER_NAME: "node-status-api"
|
||||
|
||||
jobs:
|
||||
build-container:
|
||||
runs-on: arc-ubuntu-22.04-dind
|
||||
steps:
|
||||
- name: Login to Harbor
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: harbor.nymte.ch
|
||||
username: ${{ secrets.HARBOR_ROBOT_USERNAME }}
|
||||
password: ${{ secrets.HARBOR_ROBOT_SECRET }}
|
||||
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Configure git identity
|
||||
run: |
|
||||
git config --global user.email "lawrence@nymtech.net"
|
||||
git config --global user.name "Lawrence Stalder"
|
||||
|
||||
- name: Get version from cargo.toml
|
||||
uses: mikefarah/yq@v4.44.3
|
||||
id: get_version
|
||||
with:
|
||||
cmd: yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/Cargo.toml
|
||||
|
||||
- name: Check if tag exists
|
||||
run: |
|
||||
if git rev-parse ${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.value }} >/dev/null 2>&1; then
|
||||
echo "Tag ${{ steps.get_version.outputs.value }} already exists"
|
||||
fi
|
||||
|
||||
- name: Remove existing tag if exists
|
||||
run: |
|
||||
if git rev-parse ${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.value }} >/dev/null 2>&1; then
|
||||
git push --delete origin ${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.value }}
|
||||
git tag -d ${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.value }}
|
||||
fi
|
||||
|
||||
- name: Create tag
|
||||
run: |
|
||||
git tag -a ${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.value }} -m "Version ${{ steps.get_version.outputs.value }}"
|
||||
git push origin ${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.value }}
|
||||
|
||||
- name: BuildAndPushImageOnHarbor
|
||||
run: |
|
||||
docker build -f ${{ env.WORKING_DIRECTORY }}/Dockerfile . -t harbor.nymte.ch/nym/${{ env.CONTAINER_NAME }}:${{ steps.get_version.outputs.value }} -t harbor.nymte.ch/nym/${{ env.CONTAINER_NAME }}:latest
|
||||
docker push harbor.nymte.ch/nym/${{ env.CONTAINER_NAME }} --all-tags
|
||||
@@ -4,6 +4,82 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [2024.11-wedel] (2024-09-23)
|
||||
|
||||
- Backport #4894 to fix ci ([#4899])
|
||||
- Bugfix/ticketbook false double spending ([#4892])
|
||||
- fix: allow updating globally stored signatures ([#4891])
|
||||
- [DOCs/operators]: Document changelog for patch/2024.10-caramello ([#4886])
|
||||
- [DOCs/operators]: Post release docs updates ([#4874])
|
||||
- Bump defguard to github latest version ([#4872])
|
||||
- chore: removed completed queued mixnet migration ([#4865])
|
||||
- Disable push trigger and add missing paths in ci-build ([#4864])
|
||||
- Fix linux conditional in ci-build.yml ([#4863])
|
||||
- Remove golang workaround in ci-sdk-wasm ([#4858])
|
||||
- Revert runner for ci-docs ([#4855])
|
||||
- Move credential verification into common crate ([#4853])
|
||||
- Fix test failure in ipr request size ([#4844])
|
||||
- Start switching over jobs to arc-ubuntu-20.04 ([#4843])
|
||||
- Use ecash credential type for bandwidth value ([#4840])
|
||||
- Create nym-repo-setup debian package and nym-vpn meta package ([#4837])
|
||||
- Remove serde_crate named import ([#4832])
|
||||
- Run cargo autoinherit following last weeks dependabot updates ([#4831])
|
||||
- revamped ticketbook serialisation and exposed additional cli methods ([#4827])
|
||||
- Expose wireguard details on self described endpoint ([#4825])
|
||||
- Remove unused wireguard flag from SDK ([#4823])
|
||||
- Add `axum` server to `nym-api` ([#4803])
|
||||
- Run cargo-autoinherit for a few new crates ([#4801])
|
||||
- Update dependabot ([#4796])
|
||||
- Fix clippy for unwrap_or_default ([#4783])
|
||||
- Enable dependabot version upgrades for root rust workspace ([#4778])
|
||||
- Persist used wireguard private IPs ([#4771])
|
||||
- Avoid race on ip and registration structures ([#4766])
|
||||
- docs/hotfix ([#4765])
|
||||
- chore: remove repetitive words ([#4763])
|
||||
- Make gateway latency check generic ([#4759])
|
||||
- Remove duplicate stat count for retransmissions ([#4756])
|
||||
- Update peer refresh value ([#4754])
|
||||
- Remove deprecated mark_as_success and use new disarm ([#4751])
|
||||
- Add get_mixnodes_described to validator_client ([#4725])
|
||||
- New Network Monitor ([#4610])
|
||||
|
||||
[#4899]: https://github.com/nymtech/nym/pull/4899
|
||||
[#4892]: https://github.com/nymtech/nym/pull/4892
|
||||
[#4891]: https://github.com/nymtech/nym/pull/4891
|
||||
[#4886]: https://github.com/nymtech/nym/pull/4886
|
||||
[#4874]: https://github.com/nymtech/nym/pull/4874
|
||||
[#4872]: https://github.com/nymtech/nym/pull/4872
|
||||
[#4865]: https://github.com/nymtech/nym/pull/4865
|
||||
[#4864]: https://github.com/nymtech/nym/pull/4864
|
||||
[#4863]: https://github.com/nymtech/nym/pull/4863
|
||||
[#4858]: https://github.com/nymtech/nym/pull/4858
|
||||
[#4855]: https://github.com/nymtech/nym/pull/4855
|
||||
[#4853]: https://github.com/nymtech/nym/pull/4853
|
||||
[#4844]: https://github.com/nymtech/nym/pull/4844
|
||||
[#4843]: https://github.com/nymtech/nym/pull/4843
|
||||
[#4840]: https://github.com/nymtech/nym/pull/4840
|
||||
[#4837]: https://github.com/nymtech/nym/pull/4837
|
||||
[#4832]: https://github.com/nymtech/nym/pull/4832
|
||||
[#4831]: https://github.com/nymtech/nym/pull/4831
|
||||
[#4827]: https://github.com/nymtech/nym/pull/4827
|
||||
[#4825]: https://github.com/nymtech/nym/pull/4825
|
||||
[#4823]: https://github.com/nymtech/nym/pull/4823
|
||||
[#4803]: https://github.com/nymtech/nym/pull/4803
|
||||
[#4801]: https://github.com/nymtech/nym/pull/4801
|
||||
[#4796]: https://github.com/nymtech/nym/pull/4796
|
||||
[#4783]: https://github.com/nymtech/nym/pull/4783
|
||||
[#4778]: https://github.com/nymtech/nym/pull/4778
|
||||
[#4771]: https://github.com/nymtech/nym/pull/4771
|
||||
[#4766]: https://github.com/nymtech/nym/pull/4766
|
||||
[#4765]: https://github.com/nymtech/nym/pull/4765
|
||||
[#4763]: https://github.com/nymtech/nym/pull/4763
|
||||
[#4759]: https://github.com/nymtech/nym/pull/4759
|
||||
[#4756]: https://github.com/nymtech/nym/pull/4756
|
||||
[#4754]: https://github.com/nymtech/nym/pull/4754
|
||||
[#4751]: https://github.com/nymtech/nym/pull/4751
|
||||
[#4725]: https://github.com/nymtech/nym/pull/4725
|
||||
[#4610]: https://github.com/nymtech/nym/pull/4610
|
||||
|
||||
## [2024.10-caramello] (2024-09-10)
|
||||
|
||||
- Backport 4844 and 4845 ([#4857])
|
||||
|
||||
Generated
+1582
-433
File diff suppressed because it is too large
Load Diff
+29
-10
@@ -103,6 +103,9 @@ members = [
|
||||
"mixnode",
|
||||
"sdk/lib/socks5-listener",
|
||||
"sdk/rust/nym-sdk",
|
||||
"sdk/ffi/shared",
|
||||
"sdk/ffi/go",
|
||||
"sdk/ffi/cpp",
|
||||
"service-providers/authenticator",
|
||||
"service-providers/common",
|
||||
"service-providers/ip-packet-router",
|
||||
@@ -111,11 +114,14 @@ members = [
|
||||
"nym-api",
|
||||
"nym-browser-extension/storage",
|
||||
"nym-api/nym-api-requests",
|
||||
"nym-data-observatory",
|
||||
"nym-node",
|
||||
"nym-node/nym-node-http-api",
|
||||
"nym-node/nym-node-requests",
|
||||
"nym-node-status-api",
|
||||
"nym-outfox",
|
||||
"nym-validator-rewarder",
|
||||
"tools/echo-server",
|
||||
"tools/internal/ssl-inject",
|
||||
# "tools/internal/sdk-version-bump",
|
||||
"tools/internal/testnet-manager",
|
||||
@@ -130,6 +136,11 @@ members = [
|
||||
"wasm/mix-fetch",
|
||||
"wasm/node-tester",
|
||||
"wasm/zknym-lib",
|
||||
"tools/internal/testnet-manager",
|
||||
"tools/internal/testnet-manager/dkg-bypass-contract",
|
||||
"tools/echo-server",
|
||||
"tools/internal/contract-state-importer/importer-cli",
|
||||
"tools/internal/contract-state-importer/importer-contract",
|
||||
]
|
||||
|
||||
default-members = [
|
||||
@@ -139,8 +150,10 @@ default-members = [
|
||||
"gateway",
|
||||
"mixnode",
|
||||
"nym-api",
|
||||
"nym-data-observatory",
|
||||
"nym-node",
|
||||
"nym-validator-rewarder",
|
||||
"nym-node-status-api",
|
||||
"service-providers/authenticator",
|
||||
"service-providers/ip-packet-router",
|
||||
"service-providers/network-requester",
|
||||
@@ -153,7 +166,6 @@ exclude = [
|
||||
"nym-wallet",
|
||||
"nym-vpn/ui/src-tauri",
|
||||
"cpu-cycles",
|
||||
"sdk/ffi/cpp",
|
||||
]
|
||||
|
||||
[workspace.package]
|
||||
@@ -174,9 +186,9 @@ aes-gcm-siv = "0.11.1"
|
||||
aead = "0.5.2"
|
||||
anyhow = "1.0.89"
|
||||
argon2 = "0.5.0"
|
||||
async-trait = "0.1.82"
|
||||
async-trait = "0.1.83"
|
||||
axum = "0.7.5"
|
||||
axum-extra = "0.9.3"
|
||||
axum-extra = "0.9.4"
|
||||
base64 = "0.22.1"
|
||||
bincode = "1.3.3"
|
||||
bip39 = { version = "2.0.0", features = ["zeroize"] }
|
||||
@@ -189,7 +201,7 @@ blake3 = "1.5.4"
|
||||
bloomfilter = "1.0.14"
|
||||
bs58 = "0.5.1"
|
||||
bytecodec = "0.4.15"
|
||||
bytes = "1.7.1"
|
||||
bytes = "1.7.2"
|
||||
cargo_metadata = "0.18.1"
|
||||
celes = "2.4.0"
|
||||
cfg-if = "1.0.0"
|
||||
@@ -197,7 +209,7 @@ chacha20 = "0.9.0"
|
||||
chacha20poly1305 = "0.10.1"
|
||||
chrono = "0.4.31"
|
||||
cipher = "0.4.3"
|
||||
clap = "4.5.17"
|
||||
clap = "4.5.18"
|
||||
clap_complete = "4.5"
|
||||
clap_complete_fig = "4.5"
|
||||
colored = "2.0"
|
||||
@@ -213,7 +225,8 @@ ctr = "0.9.1"
|
||||
cupid = "0.6.1"
|
||||
curve25519-dalek = "4.1"
|
||||
dashmap = "5.5.3"
|
||||
defguard_wireguard_rs = "0.4.2"
|
||||
# We want https://github.com/DefGuard/wireguard-rs/pull/64 , but there's no crates.io release being pushed out anymore
|
||||
defguard_wireguard_rs = { git = "https://github.com/DefGuard/wireguard-rs.git", rev = "v0.4.7" }
|
||||
digest = "0.10.7"
|
||||
dirs = "5.0"
|
||||
doc-comment = "0.3"
|
||||
@@ -221,10 +234,12 @@ dotenvy = "0.15.6"
|
||||
ecdsa = "0.16"
|
||||
ed25519-dalek = "2.1"
|
||||
etherparse = "0.13.0"
|
||||
envy = "0.4"
|
||||
eyre = "0.6.9"
|
||||
fastrand = "2.1.1"
|
||||
flate2 = "1.0.33"
|
||||
flate2 = "1.0.34"
|
||||
futures = "0.3.28"
|
||||
futures-util = "0.3"
|
||||
generic-array = "0.14.7"
|
||||
getrandom = "0.2.10"
|
||||
getset = "0.1.3"
|
||||
@@ -254,6 +269,7 @@ ledger-transport-hid = "0.10.0"
|
||||
log = "0.4"
|
||||
maxminddb = "0.23.0"
|
||||
mime = "0.3.17"
|
||||
moka = { version = "0.12", features = ["future"] }
|
||||
nix = "0.27.1"
|
||||
notify = "5.1.0"
|
||||
okapi = "0.7.0"
|
||||
@@ -264,6 +280,7 @@ parking_lot = "0.12.3"
|
||||
pem = "0.8"
|
||||
petgraph = "0.6.5"
|
||||
pin-project = "1.0"
|
||||
pin-project-lite = "0.2.14"
|
||||
pretty_env_logger = "0.4.0"
|
||||
publicsuffix = "2.2.3"
|
||||
quote = "1"
|
||||
@@ -286,6 +303,7 @@ serde = "1.0.210"
|
||||
serde_bytes = "0.11.15"
|
||||
serde_derive = "1.0"
|
||||
serde_json = "1.0.128"
|
||||
serde_json_path = "0.6.7"
|
||||
serde_repr = "0.1"
|
||||
serde_with = "3.9.0"
|
||||
serde_yaml = "0.9.25"
|
||||
@@ -298,9 +316,9 @@ subtle-encoding = "0.5"
|
||||
syn = "1"
|
||||
sysinfo = "0.30.13"
|
||||
tap = "1.0.1"
|
||||
tar = "0.4.41"
|
||||
tar = "0.4.42"
|
||||
tempfile = "3.5.0"
|
||||
thiserror = "1.0.63"
|
||||
thiserror = "1.0.64"
|
||||
time = "0.3.30"
|
||||
tokio = "1.39"
|
||||
tokio-stream = "0.1.16"
|
||||
@@ -315,7 +333,8 @@ tracing = "0.1.37"
|
||||
tracing-opentelemetry = "0.19.0"
|
||||
tracing-subscriber = "0.3.16"
|
||||
tracing-tree = "0.2.2"
|
||||
ts-rs = "7.0.0"
|
||||
tracing-log = "0.2"
|
||||
ts-rs = "10.0.0"
|
||||
tungstenite = { version = "0.20.1", default-features = false }
|
||||
url = "2.5"
|
||||
utoipa = "4.2"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "nym-client"
|
||||
version = "1.1.40"
|
||||
version = "1.1.41"
|
||||
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.40"
|
||||
version = "1.1.41"
|
||||
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"
|
||||
|
||||
@@ -6,6 +6,7 @@ pub mod v2;
|
||||
|
||||
mod error;
|
||||
|
||||
pub use error::Error;
|
||||
pub use v2 as latest;
|
||||
|
||||
pub const CURRENT_VERSION: u8 = 2;
|
||||
|
||||
@@ -10,4 +10,4 @@ pub use registration::{ClientMac, GatewayClient, InitMessage, Nonce};
|
||||
#[cfg(feature = "verify")]
|
||||
pub use registration::HmacSha256;
|
||||
|
||||
const VERSION: u8 = 1;
|
||||
pub const VERSION: u8 = 1;
|
||||
|
||||
@@ -26,7 +26,7 @@ pub type HmacSha256 = Hmac<Sha256>;
|
||||
pub type Nonce = u64;
|
||||
pub type Taken = Option<SystemTime>;
|
||||
|
||||
pub const BANDWIDTH_CAP_PER_DAY: u64 = 1024 * 1024 * 1024; // 1 GB
|
||||
pub const BANDWIDTH_CAP_PER_DAY: i64 = 1024 * 1024 * 1024; // 1 GB
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct InitMessage {
|
||||
|
||||
@@ -62,8 +62,113 @@ impl From<v1::registration::GatewayClient> for v2::registration::GatewayClient {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<v2::registration::GatewayClient> for v1::registration::GatewayClient {
|
||||
fn from(gw_client: v2::registration::GatewayClient) -> Self {
|
||||
Self {
|
||||
pub_key: gw_client.pub_key,
|
||||
private_ip: gw_client.private_ip,
|
||||
mac: gw_client.mac.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<v1::registration::ClientMac> for v2::registration::ClientMac {
|
||||
fn from(mac: v1::registration::ClientMac) -> Self {
|
||||
Self::new(mac.to_vec())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<v2::registration::ClientMac> for v1::registration::ClientMac {
|
||||
fn from(mac: v2::registration::ClientMac) -> Self {
|
||||
Self::new(mac.to_vec())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<v2::response::AuthenticatorResponse> for v1::response::AuthenticatorResponse {
|
||||
fn from(authenticator_response: v2::response::AuthenticatorResponse) -> Self {
|
||||
Self {
|
||||
version: authenticator_response.protocol.version,
|
||||
data: authenticator_response.data.into(),
|
||||
reply_to: authenticator_response.reply_to,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<v2::response::AuthenticatorResponseData> for v1::response::AuthenticatorResponseData {
|
||||
fn from(authenticator_response_data: v2::response::AuthenticatorResponseData) -> Self {
|
||||
match authenticator_response_data {
|
||||
v2::response::AuthenticatorResponseData::PendingRegistration(
|
||||
pending_registration_response,
|
||||
) => v1::response::AuthenticatorResponseData::PendingRegistration(
|
||||
pending_registration_response.into(),
|
||||
),
|
||||
v2::response::AuthenticatorResponseData::Registered(registered_response) => {
|
||||
v1::response::AuthenticatorResponseData::Registered(registered_response.into())
|
||||
}
|
||||
v2::response::AuthenticatorResponseData::RemainingBandwidth(
|
||||
remaining_bandwidth_response,
|
||||
) => v1::response::AuthenticatorResponseData::RemainingBandwidth(
|
||||
remaining_bandwidth_response.into(),
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<v2::response::PendingRegistrationResponse> for v1::response::PendingRegistrationResponse {
|
||||
fn from(value: v2::response::PendingRegistrationResponse) -> Self {
|
||||
Self {
|
||||
request_id: value.request_id,
|
||||
reply_to: value.reply_to,
|
||||
reply: value.reply.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<v2::response::RegisteredResponse> for v1::response::RegisteredResponse {
|
||||
fn from(value: v2::response::RegisteredResponse) -> Self {
|
||||
Self {
|
||||
request_id: value.request_id,
|
||||
reply_to: value.reply_to,
|
||||
reply: value.reply.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<v2::response::RemainingBandwidthResponse> for v1::response::RemainingBandwidthResponse {
|
||||
fn from(value: v2::response::RemainingBandwidthResponse) -> Self {
|
||||
Self {
|
||||
request_id: value.request_id,
|
||||
reply_to: value.reply_to,
|
||||
reply: value.reply.map(Into::into),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<v2::registration::RegistrationData> for v1::registration::RegistrationData {
|
||||
fn from(value: v2::registration::RegistrationData) -> Self {
|
||||
Self {
|
||||
nonce: value.nonce,
|
||||
gateway_data: value.gateway_data.into(),
|
||||
wg_port: value.wg_port,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<v2::registration::RegistredData> for v1::registration::RegistredData {
|
||||
fn from(value: v2::registration::RegistredData) -> Self {
|
||||
Self {
|
||||
pub_key: value.pub_key,
|
||||
private_ip: value.private_ip,
|
||||
wg_port: value.wg_port,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<v2::registration::RemainingBandwidthData> for v1::registration::RemainingBandwidthData {
|
||||
fn from(value: v2::registration::RemainingBandwidthData) -> Self {
|
||||
Self {
|
||||
available_bandwidth: value.available_bandwidth as u64,
|
||||
suspended: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,4 +6,4 @@ pub mod registration;
|
||||
pub mod request;
|
||||
pub mod response;
|
||||
|
||||
const VERSION: u8 = 2;
|
||||
pub const VERSION: u8 = 2;
|
||||
|
||||
@@ -66,7 +66,7 @@ pub struct RegistredData {
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct RemainingBandwidthData {
|
||||
pub available_bandwidth: u64,
|
||||
pub available_bandwidth: i64,
|
||||
}
|
||||
|
||||
/// Client that wants to register sends its PublicKey bytes mac digest encrypted with a DH shared secret.
|
||||
|
||||
@@ -16,7 +16,7 @@ use nym_credential_storage::models::RetrievedTicketbook;
|
||||
use nym_credential_storage::storage::Storage;
|
||||
use nym_credentials::ecash::bandwidth::CredentialSpendingData;
|
||||
use nym_credentials_interface::{
|
||||
AnnotatedCoinIndexSignature, AnnotatedExpirationDateSignature, VerificationKeyAuth,
|
||||
AnnotatedCoinIndexSignature, AnnotatedExpirationDateSignature, TicketType, VerificationKeyAuth,
|
||||
};
|
||||
use nym_ecash_time::Date;
|
||||
use nym_validator_client::nym_api::EpochId;
|
||||
@@ -64,9 +64,10 @@ impl<C, St: Storage> BandwidthController<C, St> {
|
||||
BandwidthController { storage, client }
|
||||
}
|
||||
|
||||
/// Tries to retrieve one of the stored, unused credentials that hasn't yet expired.
|
||||
/// Tries to retrieve one of the stored, unused credentials for the given type that hasn't yet expired.
|
||||
pub async fn get_next_usable_ticketbook(
|
||||
&self,
|
||||
ticketbook_type: TicketType,
|
||||
tickets: u32,
|
||||
) -> Result<RetrievedTicketbook, BandwidthControllerError>
|
||||
where
|
||||
@@ -74,7 +75,7 @@ impl<C, St: Storage> BandwidthController<C, St> {
|
||||
{
|
||||
let Some(ticketbook) = self
|
||||
.storage
|
||||
.get_next_unspent_usable_ticketbook(tickets)
|
||||
.get_next_unspent_usable_ticketbook(ticketbook_type.to_string(), tickets)
|
||||
.await
|
||||
.map_err(BandwidthControllerError::credential_storage_error)?
|
||||
else {
|
||||
@@ -181,6 +182,7 @@ impl<C, St: Storage> BandwidthController<C, St> {
|
||||
|
||||
pub async fn prepare_ecash_ticket(
|
||||
&self,
|
||||
ticketbook_type: TicketType,
|
||||
provider_pk: [u8; 32],
|
||||
tickets_to_spend: u32,
|
||||
) -> Result<PreparedCredential, BandwidthControllerError>
|
||||
@@ -188,7 +190,9 @@ impl<C, St: Storage> BandwidthController<C, St> {
|
||||
C: DkgQueryClient + Sync + Send,
|
||||
<St as Storage>::StorageError: Send + Sync + 'static,
|
||||
{
|
||||
let retrieved_ticketbook = self.get_next_usable_ticketbook(tickets_to_spend).await?;
|
||||
let retrieved_ticketbook = self
|
||||
.get_next_usable_ticketbook(ticketbook_type, tickets_to_spend)
|
||||
.await?;
|
||||
|
||||
let ticketbook_id = retrieved_ticketbook.ticketbook_id;
|
||||
let epoch_id = retrieved_ticketbook.ticketbook.epoch_id();
|
||||
|
||||
@@ -3,11 +3,11 @@ use log::{debug, error};
|
||||
use nym_explorer_client::{ExplorerClient, PrettyDetailedMixNodeBond};
|
||||
use nym_network_defaults::var_names::EXPLORER_API;
|
||||
use nym_topology::{
|
||||
nym_topology_from_detailed,
|
||||
nym_topology_from_basic_info,
|
||||
provider_trait::{async_trait, TopologyProvider},
|
||||
NymTopology,
|
||||
};
|
||||
use nym_validator_client::client::MixId;
|
||||
use nym_validator_client::client::NodeId;
|
||||
use rand::{prelude::SliceRandom, thread_rng};
|
||||
use std::collections::HashMap;
|
||||
use tap::TapOptional;
|
||||
@@ -39,10 +39,10 @@ fn create_explorer_client() -> Option<ExplorerClient> {
|
||||
|
||||
fn group_mixnodes_by_country_code(
|
||||
mixnodes: Vec<PrettyDetailedMixNodeBond>,
|
||||
) -> HashMap<CountryGroup, Vec<MixId>> {
|
||||
) -> HashMap<CountryGroup, Vec<NodeId>> {
|
||||
mixnodes
|
||||
.into_iter()
|
||||
.fold(HashMap::<CountryGroup, Vec<MixId>>::new(), |mut acc, m| {
|
||||
.fold(HashMap::<CountryGroup, Vec<NodeId>>::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());
|
||||
@@ -53,7 +53,7 @@ fn group_mixnodes_by_country_code(
|
||||
})
|
||||
}
|
||||
|
||||
fn log_mixnode_distribution(mixnodes: &HashMap<CountryGroup, Vec<MixId>>) {
|
||||
fn log_mixnode_distribution(mixnodes: &HashMap<CountryGroup, Vec<NodeId>>) {
|
||||
let mixnode_distribution = mixnodes
|
||||
.iter()
|
||||
.map(|(k, v)| format!("{}: {}", k, v.len()))
|
||||
@@ -110,7 +110,7 @@ impl GeoAwareTopologyProvider {
|
||||
}
|
||||
|
||||
async fn get_topology(&self) -> Option<NymTopology> {
|
||||
let mixnodes = match self.validator_client.get_cached_active_mixnodes().await {
|
||||
let mixnodes = match self.validator_client.get_basic_mixnodes(None).await {
|
||||
Err(err) => {
|
||||
error!("failed to get network mixnodes - {err}");
|
||||
return None;
|
||||
@@ -118,7 +118,7 @@ impl GeoAwareTopologyProvider {
|
||||
Ok(mixes) => mixes,
|
||||
};
|
||||
|
||||
let gateways = match self.validator_client.get_cached_gateways().await {
|
||||
let gateways = match self.validator_client.get_basic_gateways(None).await {
|
||||
Err(err) => {
|
||||
error!("failed to get network gateways - {err}");
|
||||
return None;
|
||||
@@ -182,10 +182,10 @@ impl GeoAwareTopologyProvider {
|
||||
|
||||
let mixnodes = mixnodes
|
||||
.into_iter()
|
||||
.filter(|m| filtered_mixnode_ids.contains(&m.mix_id()))
|
||||
.filter(|m| filtered_mixnode_ids.contains(&m.node_id))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let topology = nym_topology_from_detailed(mixnodes, gateways)
|
||||
let topology = nym_topology_from_basic_info(&mixnodes, &gateways)
|
||||
.filter_system_version(&self.client_version);
|
||||
|
||||
// TODO: return real error type
|
||||
|
||||
@@ -187,16 +187,6 @@ pub enum ClientCoreError {
|
||||
source: Ed25519RecoveryError,
|
||||
},
|
||||
|
||||
#[error("the account owner of gateway {gateway_id} ({raw_owner}) is malformed: {err}")]
|
||||
MalformedGatewayOwnerAccountAddress {
|
||||
gateway_id: String,
|
||||
|
||||
raw_owner: String,
|
||||
|
||||
// just use the string formatting as opposed to underlying type to avoid having to import cosmrs
|
||||
err: String,
|
||||
},
|
||||
|
||||
#[error(
|
||||
"the listening address of gateway {gateway_id} ({raw_listener}) is malformed: {source}"
|
||||
)]
|
||||
|
||||
@@ -53,7 +53,7 @@ pub trait ConnectableGateway {
|
||||
fn is_wss(&self) -> bool;
|
||||
}
|
||||
|
||||
impl ConnectableGateway for gateway::Node {
|
||||
impl ConnectableGateway for gateway::LegacyNode {
|
||||
fn identity(&self) -> &identity::PublicKey {
|
||||
self.identity()
|
||||
}
|
||||
@@ -82,7 +82,7 @@ pub async fn current_gateways<R: Rng>(
|
||||
rng: &mut R,
|
||||
nym_apis: &[Url],
|
||||
user_agent: Option<UserAgent>,
|
||||
) -> Result<Vec<gateway::Node>, ClientCoreError> {
|
||||
) -> Result<Vec<gateway::LegacyNode>, ClientCoreError> {
|
||||
let nym_api = nym_apis
|
||||
.choose(rng)
|
||||
.ok_or(ClientCoreError::ListOfNymApisIsEmpty)?;
|
||||
@@ -94,14 +94,14 @@ pub async fn current_gateways<R: Rng>(
|
||||
|
||||
log::debug!("Fetching list of gateways from: {nym_api}");
|
||||
|
||||
let gateways = client.get_cached_described_gateways().await?;
|
||||
let gateways = client.get_basic_gateways(None).await?;
|
||||
log::debug!("Found {} gateways", gateways.len());
|
||||
log::trace!("Gateways: {:#?}", gateways);
|
||||
|
||||
let valid_gateways = gateways
|
||||
.into_iter()
|
||||
.iter()
|
||||
.filter_map(|gateway| gateway.try_into().ok())
|
||||
.collect::<Vec<gateway::Node>>();
|
||||
.collect::<Vec<gateway::LegacyNode>>();
|
||||
log::debug!("Ater checking validity: {}", valid_gateways.len());
|
||||
log::trace!("Valid gateways: {:#?}", valid_gateways);
|
||||
|
||||
@@ -118,7 +118,7 @@ pub async fn current_gateways<R: Rng>(
|
||||
pub async fn current_mixnodes<R: Rng>(
|
||||
rng: &mut R,
|
||||
nym_apis: &[Url],
|
||||
) -> Result<Vec<mix::Node>, ClientCoreError> {
|
||||
) -> Result<Vec<mix::LegacyNode>, ClientCoreError> {
|
||||
let nym_api = nym_apis
|
||||
.choose(rng)
|
||||
.ok_or(ClientCoreError::ListOfNymApisIsEmpty)?;
|
||||
@@ -126,11 +126,11 @@ pub async fn current_mixnodes<R: Rng>(
|
||||
|
||||
log::trace!("Fetching list of mixnodes from: {nym_api}");
|
||||
|
||||
let mixnodes = client.get_cached_mixnodes().await?;
|
||||
let mixnodes = client.get_basic_mixnodes(None).await?;
|
||||
let valid_mixnodes = mixnodes
|
||||
.into_iter()
|
||||
.filter_map(|mixnode| (&mixnode.bond_information).try_into().ok())
|
||||
.collect::<Vec<mix::Node>>();
|
||||
.iter()
|
||||
.filter_map(|mixnode| mixnode.try_into().ok())
|
||||
.collect::<Vec<mix::LegacyNode>>();
|
||||
|
||||
// we were always filtering by version so I'm not removing that 'feature'
|
||||
let filtered_mixnodes = valid_mixnodes.filter_by_version(env!("CARGO_PKG_VERSION"));
|
||||
@@ -273,9 +273,9 @@ fn filter_by_tls<G: ConnectableGateway>(
|
||||
|
||||
pub(super) fn uniformly_random_gateway<R: Rng>(
|
||||
rng: &mut R,
|
||||
gateways: &[gateway::Node],
|
||||
gateways: &[gateway::LegacyNode],
|
||||
must_use_tls: bool,
|
||||
) -> Result<gateway::Node, ClientCoreError> {
|
||||
) -> Result<gateway::LegacyNode, ClientCoreError> {
|
||||
filter_by_tls(gateways, must_use_tls)?
|
||||
.choose(rng)
|
||||
.ok_or(ClientCoreError::NoGatewaysOnNetwork)
|
||||
@@ -284,9 +284,9 @@ pub(super) fn uniformly_random_gateway<R: Rng>(
|
||||
|
||||
pub(super) fn get_specified_gateway(
|
||||
gateway_identity: IdentityKeyRef,
|
||||
gateways: &[gateway::Node],
|
||||
gateways: &[gateway::LegacyNode],
|
||||
must_use_tls: bool,
|
||||
) -> Result<gateway::Node, ClientCoreError> {
|
||||
) -> Result<gateway::LegacyNode, ClientCoreError> {
|
||||
log::debug!("Requesting specified gateway: {}", gateway_identity);
|
||||
let user_gateway = identity::PublicKey::from_base58_string(gateway_identity)
|
||||
.map_err(ClientCoreError::UnableToCreatePublicKeyFromGatewayId)?;
|
||||
|
||||
@@ -50,7 +50,7 @@ async fn setup_new_gateway<K, D>(
|
||||
key_store: &K,
|
||||
details_store: &D,
|
||||
selection_specification: GatewaySelectionSpecification,
|
||||
available_gateways: Vec<gateway::Node>,
|
||||
available_gateways: Vec<gateway::LegacyNode>,
|
||||
) -> Result<InitialisationResult, ClientCoreError>
|
||||
where
|
||||
K: KeyStore,
|
||||
|
||||
@@ -18,7 +18,6 @@ use nym_validator_client::client::IdentityKey;
|
||||
use nym_validator_client::nyxd::AccountId;
|
||||
use serde::Serialize;
|
||||
use std::fmt::Display;
|
||||
use std::str::FromStr;
|
||||
use std::sync::Arc;
|
||||
use time::OffsetDateTime;
|
||||
use url::Url;
|
||||
@@ -39,7 +38,7 @@ pub enum SelectedGateway {
|
||||
|
||||
impl SelectedGateway {
|
||||
pub fn from_topology_node(
|
||||
node: gateway::Node,
|
||||
node: gateway::LegacyNode,
|
||||
must_use_tls: bool,
|
||||
) -> Result<Self, ClientCoreError> {
|
||||
let gateway_listener = if must_use_tls {
|
||||
@@ -51,20 +50,6 @@ impl SelectedGateway {
|
||||
node.clients_address()
|
||||
};
|
||||
|
||||
let gateway_owner_address = node
|
||||
.owner
|
||||
.as_ref()
|
||||
.map(|raw_owner| {
|
||||
AccountId::from_str(raw_owner).map_err(|source| {
|
||||
ClientCoreError::MalformedGatewayOwnerAccountAddress {
|
||||
gateway_id: node.identity_key.to_base58_string(),
|
||||
raw_owner: raw_owner.clone(),
|
||||
err: source.to_string(),
|
||||
}
|
||||
})
|
||||
})
|
||||
.transpose()?;
|
||||
|
||||
let gateway_listener =
|
||||
Url::parse(&gateway_listener).map_err(|source| ClientCoreError::MalformedListener {
|
||||
gateway_id: node.identity_key.to_base58_string(),
|
||||
@@ -74,7 +59,7 @@ impl SelectedGateway {
|
||||
|
||||
Ok(SelectedGateway::Remote {
|
||||
gateway_id: node.identity_key,
|
||||
gateway_owner_address,
|
||||
gateway_owner_address: None,
|
||||
gateway_listener,
|
||||
})
|
||||
}
|
||||
@@ -215,7 +200,7 @@ pub enum GatewaySetup {
|
||||
specification: GatewaySelectionSpecification,
|
||||
|
||||
// TODO: seems to be a bit inefficient to pass them by value
|
||||
available_gateways: Vec<gateway::Node>,
|
||||
available_gateways: Vec<gateway::LegacyNode>,
|
||||
},
|
||||
|
||||
ReuseConnection {
|
||||
|
||||
@@ -24,6 +24,7 @@ zeroize.workspace = true
|
||||
nym-bandwidth-controller = { path = "../../bandwidth-controller" }
|
||||
nym-credentials = { path = "../../credentials" }
|
||||
nym-credential-storage = { path = "../../credential-storage" }
|
||||
nym-credentials-interface = { path = "../../credentials-interface" }
|
||||
nym-crypto = { path = "../../crypto" }
|
||||
nym-gateway-requests = { path = "../../gateway-requests" }
|
||||
nym-network-defaults = { path = "../../network-defaults" }
|
||||
|
||||
@@ -2,21 +2,37 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use si_scale::helpers::bibytes2;
|
||||
use std::sync::atomic::{AtomicI64, Ordering};
|
||||
use std::sync::atomic::{AtomicBool, AtomicI64, Ordering};
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
use time::OffsetDateTime;
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
pub(crate) struct BandwidthClaimGuard {
|
||||
inner: Arc<ClientBandwidthInner>,
|
||||
}
|
||||
|
||||
impl Drop for BandwidthClaimGuard {
|
||||
fn drop(&mut self) {
|
||||
let old = self.inner.claiming_more.swap(false, Ordering::SeqCst);
|
||||
assert!(
|
||||
old,
|
||||
"critical failure: there were multiple BandwidthClaimGuard existing"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ClientBandwidth {
|
||||
inner: Arc<ClientBandwidthInner>,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct ClientBandwidthInner {
|
||||
/// the actual bandwidth amount (in bytes) available
|
||||
available: AtomicI64,
|
||||
|
||||
/// flag to indicate whether this client is currently in the process of claiming additional bandwidth
|
||||
claiming_more: AtomicBool,
|
||||
|
||||
/// defines the timestamp when the bandwidth information has been logged to the logs stream
|
||||
last_logged_ts: AtomicI64,
|
||||
|
||||
@@ -29,11 +45,28 @@ impl ClientBandwidth {
|
||||
ClientBandwidth {
|
||||
inner: Arc::new(ClientBandwidthInner {
|
||||
available: AtomicI64::new(0),
|
||||
claiming_more: AtomicBool::new(false),
|
||||
last_logged_ts: AtomicI64::new(0),
|
||||
last_updated_ts: AtomicI64::new(0),
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn begin_bandwidth_claim(&self) -> Option<BandwidthClaimGuard> {
|
||||
if self
|
||||
.inner
|
||||
.claiming_more
|
||||
.compare_exchange(false, true, Ordering::SeqCst, Ordering::SeqCst)
|
||||
.is_ok()
|
||||
{
|
||||
Some(BandwidthClaimGuard {
|
||||
inner: self.inner.clone(),
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn remaining(&self) -> i64 {
|
||||
self.inner.available.load(Ordering::Acquire)
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ use nym_bandwidth_controller::{BandwidthController, BandwidthStatusMessage};
|
||||
use nym_credential_storage::ephemeral_storage::EphemeralStorage as EphemeralCredentialStorage;
|
||||
use nym_credential_storage::storage::Storage as CredentialStorage;
|
||||
use nym_credentials::CredentialSpendingData;
|
||||
use nym_credentials_interface::TicketType;
|
||||
use nym_crypto::asymmetric::identity;
|
||||
use nym_gateway_requests::registration::handshake::client_handshake;
|
||||
use nym_gateway_requests::{
|
||||
@@ -724,6 +725,11 @@ impl<C, St> GatewayClient<C, St> {
|
||||
return Err(GatewayClientError::NoBandwidthControllerAvailable);
|
||||
}
|
||||
|
||||
let Some(_claim_guard) = self.bandwidth.begin_bandwidth_claim() else {
|
||||
debug!("there's already an existing bandwidth claim ongoing");
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
warn!("Not enough bandwidth. Trying to get more bandwidth, this might take a while");
|
||||
if !self.cfg.bandwidth.require_tickets {
|
||||
info!("The client is running in disabled credentials mode - attempting to claim bandwidth without a credential");
|
||||
@@ -743,7 +749,11 @@ impl<C, St> GatewayClient<C, St> {
|
||||
}
|
||||
let prepared_credential = self
|
||||
.unchecked_bandwidth_controller()
|
||||
.prepare_ecash_ticket(self.gateway_identity.to_bytes(), TICKETS_TO_SPEND)
|
||||
.prepare_ecash_ticket(
|
||||
TicketType::V1MixnetEntry,
|
||||
self.gateway_identity.to_bytes(),
|
||||
TICKETS_TO_SPEND,
|
||||
)
|
||||
.await?;
|
||||
|
||||
match self.claim_ecash_bandwidth(prepared_credential.data).await {
|
||||
|
||||
@@ -20,11 +20,12 @@ nym-coconut-bandwidth-contract-common = { path = "../../cosmwasm-smart-contracts
|
||||
nym-ecash-contract-common = { path = "../../cosmwasm-smart-contracts/ecash-contract" }
|
||||
nym-multisig-contract-common = { path = "../../cosmwasm-smart-contracts/multisig-contract" }
|
||||
nym-group-contract-common = { path = "../../cosmwasm-smart-contracts/group-contract" }
|
||||
nym-serde-helpers = { path = "../../serde-helpers", features = ["hex", "base64"] }
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
serde_json = { workspace = true }
|
||||
nym-http-api-client = { path = "../../../common/http-api-client" }
|
||||
thiserror = { workspace = true }
|
||||
log = { workspace = true }
|
||||
tracing = { workspace = true }
|
||||
url = { workspace = true, features = ["serde"] }
|
||||
tokio = { workspace = true, features = ["sync", "time"] }
|
||||
time = { workspace = true, features = ["formatting"] }
|
||||
|
||||
@@ -17,11 +17,11 @@ use nym_api_requests::ecash::{
|
||||
BlindSignRequestBody, BlindedSignatureResponse, PartialCoinIndicesSignatureResponse,
|
||||
PartialExpirationDateSignatureResponse, VerificationKeyResponse,
|
||||
};
|
||||
use nym_api_requests::models::{DescribedGateway, MixNodeBondAnnotated};
|
||||
use nym_api_requests::models::{
|
||||
GatewayCoreStatusResponse, MixnodeCoreStatusResponse, MixnodeStatusResponse,
|
||||
RewardEstimationResponse, StakeSaturationResponse,
|
||||
};
|
||||
use nym_api_requests::models::{LegacyDescribedGateway, MixNodeBondAnnotated};
|
||||
use nym_api_requests::nym_nodes::SkimmedNode;
|
||||
use nym_coconut_dkg_common::types::EpochId;
|
||||
use nym_http_api_client::UserAgent;
|
||||
@@ -31,7 +31,7 @@ use url::Url;
|
||||
|
||||
pub use crate::nym_api::NymApiClientExt;
|
||||
pub use nym_mixnet_contract_common::{
|
||||
mixnode::MixNodeDetails, GatewayBond, IdentityKey, IdentityKeyRef, MixId,
|
||||
mixnode::MixNodeDetails, GatewayBond, IdentityKey, IdentityKeyRef, NodeId,
|
||||
};
|
||||
|
||||
// re-export the type to not break existing imports
|
||||
@@ -265,6 +265,13 @@ impl NymApiClient {
|
||||
NymApiClient { nym_api }
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
pub fn new_with_timeout(api_url: Url, timeout: std::time::Duration) -> Self {
|
||||
let nym_api = nym_api::Client::new(api_url, Some(timeout));
|
||||
|
||||
NymApiClient { nym_api }
|
||||
}
|
||||
|
||||
pub fn new_with_user_agent(api_url: Url, user_agent: UserAgent) -> Self {
|
||||
let nym_api = nym_api::Client::builder::<_, ValidatorClientError>(api_url)
|
||||
.expect("invalid api url")
|
||||
@@ -327,7 +334,7 @@ impl NymApiClient {
|
||||
|
||||
pub async fn get_cached_described_gateways(
|
||||
&self,
|
||||
) -> Result<Vec<DescribedGateway>, ValidatorClientError> {
|
||||
) -> Result<Vec<LegacyDescribedGateway>, ValidatorClientError> {
|
||||
Ok(self.nym_api.get_gateways_described().await?)
|
||||
}
|
||||
|
||||
@@ -344,7 +351,7 @@ impl NymApiClient {
|
||||
|
||||
pub async fn get_mixnode_core_status_count(
|
||||
&self,
|
||||
mix_id: MixId,
|
||||
mix_id: NodeId,
|
||||
since: Option<i64>,
|
||||
) -> Result<MixnodeCoreStatusResponse, ValidatorClientError> {
|
||||
Ok(self
|
||||
@@ -355,21 +362,21 @@ impl NymApiClient {
|
||||
|
||||
pub async fn get_mixnode_status(
|
||||
&self,
|
||||
mix_id: MixId,
|
||||
mix_id: NodeId,
|
||||
) -> Result<MixnodeStatusResponse, ValidatorClientError> {
|
||||
Ok(self.nym_api.get_mixnode_status(mix_id).await?)
|
||||
}
|
||||
|
||||
pub async fn get_mixnode_reward_estimation(
|
||||
&self,
|
||||
mix_id: MixId,
|
||||
mix_id: NodeId,
|
||||
) -> Result<RewardEstimationResponse, ValidatorClientError> {
|
||||
Ok(self.nym_api.get_mixnode_reward_estimation(mix_id).await?)
|
||||
}
|
||||
|
||||
pub async fn get_mixnode_stake_saturation(
|
||||
&self,
|
||||
mix_id: MixId,
|
||||
mix_id: NodeId,
|
||||
) -> Result<StakeSaturationResponse, ValidatorClientError> {
|
||||
Ok(self.nym_api.get_mixnode_stake_saturation(mix_id).await?)
|
||||
}
|
||||
|
||||
@@ -121,36 +121,36 @@ async fn test_nyxd_connection(
|
||||
{
|
||||
Ok(Err(NyxdError::TendermintErrorRpc(e))) => {
|
||||
// If we get a tendermint-rpc error, we classify the node as not contactable
|
||||
log::warn!("Checking: nyxd url: {url}: {}: {}", "failed".red(), e);
|
||||
tracing::warn!("Checking: nyxd url: {url}: {}: {}", "failed".red(), e);
|
||||
false
|
||||
}
|
||||
Ok(Err(NyxdError::AbciError { code, log, .. })) => {
|
||||
// We accept the mixnet contract not found as ok from a connection standpoint. This happens
|
||||
// for example on a pre-launch network.
|
||||
log::debug!(
|
||||
tracing::debug!(
|
||||
"Checking: nyxd url: {url}: {}, but with abci error: {code}: {log}",
|
||||
"success".green()
|
||||
);
|
||||
code == 18
|
||||
}
|
||||
Ok(Err(error @ NyxdError::NoContractAddressAvailable(_))) => {
|
||||
log::warn!("Checking: nyxd url: {url}: {}: {error}", "failed".red());
|
||||
tracing::warn!("Checking: nyxd url: {url}: {}: {error}", "failed".red());
|
||||
false
|
||||
}
|
||||
Ok(Err(e)) => {
|
||||
// For any other error, we're optimistic and just try anyway.
|
||||
log::warn!(
|
||||
tracing::warn!(
|
||||
"Checking: nyxd_url: {url}: {}, but with error: {e}",
|
||||
"success".green()
|
||||
);
|
||||
true
|
||||
}
|
||||
Ok(Ok(_)) => {
|
||||
log::debug!("Checking: nyxd_url: {url}: {}", "success".green());
|
||||
tracing::debug!("Checking: nyxd_url: {url}: {}", "success".green());
|
||||
true
|
||||
}
|
||||
Err(e) => {
|
||||
log::warn!("Checking: nyxd_url: {url}: {}: {e}", "failed".red());
|
||||
tracing::warn!("Checking: nyxd_url: {url}: {}: {e}", "failed".red());
|
||||
false
|
||||
}
|
||||
};
|
||||
@@ -169,15 +169,15 @@ async fn test_nym_api_connection(
|
||||
.await
|
||||
{
|
||||
Ok(Ok(_)) => {
|
||||
log::debug!("Checking: api_url: {url}: {}", "success".green());
|
||||
tracing::debug!("Checking: api_url: {url}: {}", "success".green());
|
||||
true
|
||||
}
|
||||
Ok(Err(e)) => {
|
||||
log::debug!("Checking: api_url: {url}: {}: {e}", "failed".red());
|
||||
tracing::debug!("Checking: api_url: {url}: {}: {e}", "failed".red());
|
||||
false
|
||||
}
|
||||
Err(e) => {
|
||||
log::debug!("Checking: api_url: {url}: {}: {e}", "failed".red());
|
||||
tracing::debug!("Checking: api_url: {url}: {}: {e}", "failed".red());
|
||||
false
|
||||
}
|
||||
};
|
||||
|
||||
@@ -10,8 +10,9 @@ use nym_api_requests::ecash::models::{
|
||||
VerifyEcashTicketBody,
|
||||
};
|
||||
use nym_api_requests::ecash::VerificationKeyResponse;
|
||||
use nym_api_requests::models::DescribedMixNode;
|
||||
use nym_api_requests::nym_nodes::{CachedNodesResponse, SkimmedNode};
|
||||
use nym_api_requests::models::{
|
||||
AnnotationResponse, LegacyDescribedMixNode, NodePerformanceResponse,
|
||||
};
|
||||
pub use nym_api_requests::{
|
||||
ecash::{
|
||||
models::{
|
||||
@@ -23,21 +24,23 @@ pub use nym_api_requests::{
|
||||
VerifyEcashCredentialBody,
|
||||
},
|
||||
models::{
|
||||
ComputeRewardEstParam, DescribedGateway, GatewayBondAnnotated, GatewayCoreStatusResponse,
|
||||
ComputeRewardEstParam, GatewayBondAnnotated, GatewayCoreStatusResponse,
|
||||
GatewayStatusReportResponse, GatewayUptimeHistoryResponse, InclusionProbabilityResponse,
|
||||
MixNodeBondAnnotated, MixnodeCoreStatusResponse, MixnodeStatusReportResponse,
|
||||
MixnodeStatusResponse, MixnodeUptimeHistoryResponse, RewardEstimationResponse,
|
||||
StakeSaturationResponse, UptimeResponse,
|
||||
LegacyDescribedGateway, MixNodeBondAnnotated, MixnodeCoreStatusResponse,
|
||||
MixnodeStatusReportResponse, MixnodeStatusResponse, MixnodeUptimeHistoryResponse,
|
||||
RewardEstimationResponse, StakeSaturationResponse, UptimeResponse,
|
||||
},
|
||||
nym_nodes::{CachedNodesResponse, SkimmedNode},
|
||||
};
|
||||
pub use nym_coconut_dkg_common::types::EpochId;
|
||||
use nym_contracts_common::IdentityKey;
|
||||
pub use nym_http_api_client::Client;
|
||||
use nym_http_api_client::{ApiClient, NO_PARAMS};
|
||||
use nym_mixnet_contract_common::mixnode::MixNodeDetails;
|
||||
use nym_mixnet_contract_common::{GatewayBond, IdentityKeyRef, MixId};
|
||||
use nym_mixnet_contract_common::{GatewayBond, IdentityKeyRef, NodeId};
|
||||
use time::format_description::BorrowedFormatItem;
|
||||
use time::Date;
|
||||
use tracing::instrument;
|
||||
|
||||
pub mod error;
|
||||
pub mod routes;
|
||||
@@ -49,11 +52,13 @@ pub fn rfc_3339_date() -> Vec<BorrowedFormatItem<'static>> {
|
||||
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
||||
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
|
||||
pub trait NymApiClientExt: ApiClient {
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
async fn get_mixnodes(&self) -> Result<Vec<MixNodeDetails>, NymAPIError> {
|
||||
self.get_json(&[routes::API_VERSION, routes::MIXNODES], NO_PARAMS)
|
||||
.await
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
async fn get_mixnodes_detailed(&self) -> Result<Vec<MixNodeBondAnnotated>, NymAPIError> {
|
||||
self.get_json(
|
||||
&[
|
||||
@@ -67,6 +72,7 @@ pub trait NymApiClientExt: ApiClient {
|
||||
.await
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
async fn get_gateways_detailed(&self) -> Result<Vec<GatewayBondAnnotated>, NymAPIError> {
|
||||
self.get_json(
|
||||
&[
|
||||
@@ -80,6 +86,7 @@ pub trait NymApiClientExt: ApiClient {
|
||||
.await
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
async fn get_mixnodes_detailed_unfiltered(
|
||||
&self,
|
||||
) -> Result<Vec<MixNodeBondAnnotated>, NymAPIError> {
|
||||
@@ -95,12 +102,14 @@ pub trait NymApiClientExt: ApiClient {
|
||||
.await
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
async fn get_gateways(&self) -> Result<Vec<GatewayBond>, NymAPIError> {
|
||||
self.get_json(&[routes::API_VERSION, routes::GATEWAYS], NO_PARAMS)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn get_gateways_described(&self) -> Result<Vec<DescribedGateway>, NymAPIError> {
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
async fn get_gateways_described(&self) -> Result<Vec<LegacyDescribedGateway>, NymAPIError> {
|
||||
self.get_json(
|
||||
&[routes::API_VERSION, routes::GATEWAYS, routes::DESCRIBED],
|
||||
NO_PARAMS,
|
||||
@@ -108,7 +117,8 @@ pub trait NymApiClientExt: ApiClient {
|
||||
.await
|
||||
}
|
||||
|
||||
async fn get_mixnodes_described(&self) -> Result<Vec<DescribedMixNode>, NymAPIError> {
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
async fn get_mixnodes_described(&self) -> Result<Vec<LegacyDescribedMixNode>, NymAPIError> {
|
||||
self.get_json(
|
||||
&[routes::API_VERSION, routes::MIXNODES, routes::DESCRIBED],
|
||||
NO_PARAMS,
|
||||
@@ -116,6 +126,7 @@ pub trait NymApiClientExt: ApiClient {
|
||||
.await
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip_all)]
|
||||
async fn get_basic_mixnodes(
|
||||
&self,
|
||||
semver_compatibility: Option<String>,
|
||||
@@ -139,6 +150,7 @@ pub trait NymApiClientExt: ApiClient {
|
||||
.await
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
async fn get_basic_gateways(
|
||||
&self,
|
||||
semver_compatibility: Option<String>,
|
||||
@@ -162,6 +174,7 @@ pub trait NymApiClientExt: ApiClient {
|
||||
.await
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
async fn get_active_mixnodes(&self) -> Result<Vec<MixNodeDetails>, NymAPIError> {
|
||||
self.get_json(
|
||||
&[routes::API_VERSION, routes::MIXNODES, routes::ACTIVE],
|
||||
@@ -170,6 +183,7 @@ pub trait NymApiClientExt: ApiClient {
|
||||
.await
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
async fn get_active_mixnodes_detailed(&self) -> Result<Vec<MixNodeBondAnnotated>, NymAPIError> {
|
||||
self.get_json(
|
||||
&[
|
||||
@@ -184,6 +198,7 @@ pub trait NymApiClientExt: ApiClient {
|
||||
.await
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
async fn get_rewarded_mixnodes(&self) -> Result<Vec<MixNodeDetails>, NymAPIError> {
|
||||
self.get_json(
|
||||
&[routes::API_VERSION, routes::MIXNODES, routes::REWARDED],
|
||||
@@ -192,9 +207,10 @@ pub trait NymApiClientExt: ApiClient {
|
||||
.await
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
async fn get_mixnode_report(
|
||||
&self,
|
||||
mix_id: MixId,
|
||||
mix_id: NodeId,
|
||||
) -> Result<MixnodeStatusReportResponse, NymAPIError> {
|
||||
self.get_json(
|
||||
&[
|
||||
@@ -209,6 +225,7 @@ pub trait NymApiClientExt: ApiClient {
|
||||
.await
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
async fn get_gateway_report(
|
||||
&self,
|
||||
identity: IdentityKeyRef<'_>,
|
||||
@@ -226,9 +243,10 @@ pub trait NymApiClientExt: ApiClient {
|
||||
.await
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
async fn get_mixnode_history(
|
||||
&self,
|
||||
mix_id: MixId,
|
||||
mix_id: NodeId,
|
||||
) -> Result<MixnodeUptimeHistoryResponse, NymAPIError> {
|
||||
self.get_json(
|
||||
&[
|
||||
@@ -243,6 +261,7 @@ pub trait NymApiClientExt: ApiClient {
|
||||
.await
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
async fn get_gateway_history(
|
||||
&self,
|
||||
identity: IdentityKeyRef<'_>,
|
||||
@@ -260,6 +279,7 @@ pub trait NymApiClientExt: ApiClient {
|
||||
.await
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
async fn get_rewarded_mixnodes_detailed(
|
||||
&self,
|
||||
) -> Result<Vec<MixNodeBondAnnotated>, NymAPIError> {
|
||||
@@ -276,6 +296,7 @@ pub trait NymApiClientExt: ApiClient {
|
||||
.await
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
async fn get_gateway_core_status_count(
|
||||
&self,
|
||||
identity: IdentityKeyRef<'_>,
|
||||
@@ -307,9 +328,10 @@ pub trait NymApiClientExt: ApiClient {
|
||||
}
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
async fn get_mixnode_core_status_count(
|
||||
&self,
|
||||
mix_id: MixId,
|
||||
mix_id: NodeId,
|
||||
since: Option<i64>,
|
||||
) -> Result<MixnodeCoreStatusResponse, NymAPIError> {
|
||||
if let Some(since) = since {
|
||||
@@ -339,9 +361,10 @@ pub trait NymApiClientExt: ApiClient {
|
||||
}
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
async fn get_mixnode_status(
|
||||
&self,
|
||||
mix_id: MixId,
|
||||
mix_id: NodeId,
|
||||
) -> Result<MixnodeStatusResponse, NymAPIError> {
|
||||
self.get_json(
|
||||
&[
|
||||
@@ -356,9 +379,10 @@ pub trait NymApiClientExt: ApiClient {
|
||||
.await
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
async fn get_mixnode_reward_estimation(
|
||||
&self,
|
||||
mix_id: MixId,
|
||||
mix_id: NodeId,
|
||||
) -> Result<RewardEstimationResponse, NymAPIError> {
|
||||
self.get_json(
|
||||
&[
|
||||
@@ -373,9 +397,10 @@ pub trait NymApiClientExt: ApiClient {
|
||||
.await
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
async fn compute_mixnode_reward_estimation(
|
||||
&self,
|
||||
mix_id: MixId,
|
||||
mix_id: NodeId,
|
||||
request_body: &ComputeRewardEstParam,
|
||||
) -> Result<RewardEstimationResponse, NymAPIError> {
|
||||
self.post_json(
|
||||
@@ -392,9 +417,10 @@ pub trait NymApiClientExt: ApiClient {
|
||||
.await
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
async fn get_mixnode_stake_saturation(
|
||||
&self,
|
||||
mix_id: MixId,
|
||||
mix_id: NodeId,
|
||||
) -> Result<StakeSaturationResponse, NymAPIError> {
|
||||
self.get_json(
|
||||
&[
|
||||
@@ -409,9 +435,10 @@ pub trait NymApiClientExt: ApiClient {
|
||||
.await
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
async fn get_mixnode_inclusion_probability(
|
||||
&self,
|
||||
mix_id: MixId,
|
||||
mix_id: NodeId,
|
||||
) -> Result<InclusionProbabilityResponse, NymAPIError> {
|
||||
self.get_json(
|
||||
&[
|
||||
@@ -426,7 +453,24 @@ pub trait NymApiClientExt: ApiClient {
|
||||
.await
|
||||
}
|
||||
|
||||
async fn get_mixnode_avg_uptime(&self, mix_id: MixId) -> Result<UptimeResponse, NymAPIError> {
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
async fn get_current_node_performance(
|
||||
&self,
|
||||
node_id: NodeId,
|
||||
) -> Result<NodePerformanceResponse, NymAPIError> {
|
||||
self.get_json_from(format!("/v1/nym-nodes/performance/{node_id}"))
|
||||
.await
|
||||
}
|
||||
|
||||
async fn get_node_annotation(
|
||||
&self,
|
||||
node_id: NodeId,
|
||||
) -> Result<AnnotationResponse, NymAPIError> {
|
||||
self.get_json_from(format!("/v1/nym-nodes/annotation/{node_id}"))
|
||||
.await
|
||||
}
|
||||
|
||||
async fn get_mixnode_avg_uptime(&self, mix_id: NodeId) -> Result<UptimeResponse, NymAPIError> {
|
||||
self.get_json(
|
||||
&[
|
||||
routes::API_VERSION,
|
||||
@@ -440,7 +484,8 @@ pub trait NymApiClientExt: ApiClient {
|
||||
.await
|
||||
}
|
||||
|
||||
async fn get_mixnodes_blacklisted(&self) -> Result<Vec<MixId>, NymAPIError> {
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
async fn get_mixnodes_blacklisted(&self) -> Result<Vec<NodeId>, NymAPIError> {
|
||||
self.get_json(
|
||||
&[routes::API_VERSION, routes::MIXNODES, routes::BLACKLISTED],
|
||||
NO_PARAMS,
|
||||
@@ -448,6 +493,7 @@ pub trait NymApiClientExt: ApiClient {
|
||||
.await
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
async fn get_gateways_blacklisted(&self) -> Result<Vec<IdentityKey>, NymAPIError> {
|
||||
self.get_json(
|
||||
&[routes::API_VERSION, routes::GATEWAYS, routes::BLACKLISTED],
|
||||
@@ -456,6 +502,7 @@ pub trait NymApiClientExt: ApiClient {
|
||||
.await
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self, request_body))]
|
||||
async fn blind_sign(
|
||||
&self,
|
||||
request_body: &BlindSignRequestBody,
|
||||
@@ -472,6 +519,7 @@ pub trait NymApiClientExt: ApiClient {
|
||||
.await
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self, request_body))]
|
||||
async fn verify_ecash_ticket(
|
||||
&self,
|
||||
request_body: &VerifyEcashTicketBody,
|
||||
@@ -488,6 +536,7 @@ pub trait NymApiClientExt: ApiClient {
|
||||
.await
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self, request_body))]
|
||||
async fn batch_redeem_ecash_tickets(
|
||||
&self,
|
||||
request_body: &BatchRedeemTicketsBody,
|
||||
@@ -504,6 +553,7 @@ pub trait NymApiClientExt: ApiClient {
|
||||
.await
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
async fn double_spending_filter_v1(&self) -> Result<SpentCredentialsResponse, NymAPIError> {
|
||||
self.get_json(
|
||||
&[
|
||||
@@ -516,6 +566,7 @@ pub trait NymApiClientExt: ApiClient {
|
||||
.await
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
async fn partial_expiration_date_signatures(
|
||||
&self,
|
||||
expiration_date: Option<Date>,
|
||||
@@ -539,6 +590,7 @@ pub trait NymApiClientExt: ApiClient {
|
||||
.await
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
async fn partial_coin_indices_signatures(
|
||||
&self,
|
||||
epoch_id: Option<EpochId>,
|
||||
@@ -559,6 +611,7 @@ pub trait NymApiClientExt: ApiClient {
|
||||
.await
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
async fn global_expiration_date_signatures(
|
||||
&self,
|
||||
expiration_date: Option<Date>,
|
||||
@@ -582,6 +635,7 @@ pub trait NymApiClientExt: ApiClient {
|
||||
.await
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
async fn global_coin_indices_signatures(
|
||||
&self,
|
||||
epoch_id: Option<EpochId>,
|
||||
@@ -602,6 +656,7 @@ pub trait NymApiClientExt: ApiClient {
|
||||
.await
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
async fn master_verification_key(
|
||||
&self,
|
||||
epoch_id: Option<EpochId>,
|
||||
@@ -621,6 +676,7 @@ pub trait NymApiClientExt: ApiClient {
|
||||
.await
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
async fn epoch_credentials(
|
||||
&self,
|
||||
dkg_epoch: EpochId,
|
||||
@@ -637,6 +693,7 @@ pub trait NymApiClientExt: ApiClient {
|
||||
.await
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
async fn issued_credential(
|
||||
&self,
|
||||
credential_id: i64,
|
||||
@@ -653,6 +710,7 @@ pub trait NymApiClientExt: ApiClient {
|
||||
.await
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
async fn issued_credentials(
|
||||
&self,
|
||||
credential_ids: Vec<i64>,
|
||||
|
||||
@@ -38,6 +38,7 @@ pub mod ecash {
|
||||
pub const STATUS_ROUTES: &str = "status";
|
||||
pub const MIXNODE: &str = "mixnode";
|
||||
pub const GATEWAY: &str = "gateway";
|
||||
pub const NYM_NODES: &str = "nym-nodes";
|
||||
|
||||
pub const CORE_STATUS_COUNT: &str = "core-status-count";
|
||||
pub const SINCE_ARG: &str = "since";
|
||||
@@ -52,5 +53,6 @@ pub const STAKE_SATURATION: &str = "stake-saturation";
|
||||
pub const INCLUSION_CHANCE: &str = "inclusion-probability";
|
||||
pub const SUBMIT_GATEWAY: &str = "submit-gateway-monitoring-results";
|
||||
pub const SUBMIT_NODE: &str = "submit-node-monitoring-results";
|
||||
pub const PERFORMANCE: &str = "performance";
|
||||
|
||||
pub const SERVICE_PROVIDERS: &str = "services";
|
||||
|
||||
@@ -8,9 +8,9 @@ use crate::nyxd::CosmWasmClient;
|
||||
use async_trait::async_trait;
|
||||
use cosmrs::AccountId;
|
||||
use cosmwasm_std::Addr;
|
||||
use log::trace;
|
||||
use nym_coconut_dkg_common::types::{ChunkIndex, NodeIndex, StateAdvanceResponse};
|
||||
use serde::Deserialize;
|
||||
use tracing::trace;
|
||||
|
||||
use nym_coconut_dkg_common::dealer::RegisteredDealerDetails;
|
||||
pub use nym_coconut_dkg_common::{
|
||||
|
||||
+350
-163
@@ -8,28 +8,33 @@ use crate::nyxd::CosmWasmClient;
|
||||
use async_trait::async_trait;
|
||||
use cosmrs::AccountId;
|
||||
use nym_contracts_common::signing::Nonce;
|
||||
use nym_mixnet_contract_common::gateway::{PreassignedGatewayIdsResponse, PreassignedId};
|
||||
use nym_mixnet_contract_common::nym_node::{
|
||||
EpochAssignmentResponse, NodeDetailsByIdentityResponse, NodeOwnershipResponse,
|
||||
NodeRewardingDetailsResponse, PagedNymNodeBondsResponse, PagedNymNodeDetailsResponse,
|
||||
PagedUnbondedNymNodesResponse, Role, RolesMetadataResponse, StakeSaturationResponse,
|
||||
UnbondedNodeResponse, UnbondedNymNode,
|
||||
};
|
||||
use nym_mixnet_contract_common::reward_params::WorkFactor;
|
||||
use nym_mixnet_contract_common::{
|
||||
delegation,
|
||||
delegation::{MixNodeDelegationResponse, OwnerProxySubKey},
|
||||
families::{Family, FamilyHead},
|
||||
delegation::{NodeDelegationResponse, OwnerProxySubKey},
|
||||
mixnode::{
|
||||
MixnodeRewardingDetailsResponse, PagedMixnodesDetailsResponse,
|
||||
PagedUnbondedMixnodesResponse, StakeSaturationResponse, UnbondedMixnodeResponse,
|
||||
MixStakeSaturationResponse, MixnodeRewardingDetailsResponse, PagedMixnodesDetailsResponse,
|
||||
PagedUnbondedMixnodesResponse, UnbondedMixnodeResponse,
|
||||
},
|
||||
reward_params::{Performance, RewardingParams},
|
||||
rewarding::{EstimatedCurrentEpochRewardResponse, PendingRewardResponse},
|
||||
ContractBuildInformation, ContractState, ContractStateParams, CurrentIntervalResponse,
|
||||
Delegation, EpochEventId, EpochStatus, FamilyByHeadResponse, FamilyByLabelResponse,
|
||||
FamilyMembersByHeadResponse, FamilyMembersByLabelResponse, GatewayBond, GatewayBondResponse,
|
||||
GatewayOwnershipResponse, IdentityKey, IdentityKeyRef, IntervalEventId, LayerDistribution,
|
||||
MixId, MixNodeBond, MixNodeDetails, MixOwnershipResponse, MixnodeDetailsByIdentityResponse,
|
||||
MixnodeDetailsResponse, NumberOfPendingEventsResponse, PagedAllDelegationsResponse,
|
||||
PagedDelegatorDelegationsResponse, PagedFamiliesResponse, PagedGatewayResponse,
|
||||
PagedMembersResponse, PagedMixNodeDelegationsResponse, PagedMixnodeBondsResponse,
|
||||
PagedRewardedSetResponse, PendingEpochEvent, PendingEpochEventResponse,
|
||||
PendingEpochEventsResponse, PendingIntervalEvent, PendingIntervalEventResponse,
|
||||
PendingIntervalEventsResponse, QueryMsg as MixnetQueryMsg, RewardedSetNodeStatus,
|
||||
UnbondedMixnode,
|
||||
Delegation, EpochEventId, EpochStatus, GatewayBond, GatewayBondResponse,
|
||||
GatewayOwnershipResponse, IdentityKey, IdentityKeyRef, IntervalEventId, MixNodeBond,
|
||||
MixNodeDetails, MixOwnershipResponse, MixnodeDetailsByIdentityResponse, MixnodeDetailsResponse,
|
||||
NodeId, NumberOfPendingEventsResponse, NymNodeBond, NymNodeDetails,
|
||||
PagedAllDelegationsResponse, PagedDelegatorDelegationsResponse, PagedGatewayResponse,
|
||||
PagedMixnodeBondsResponse, PagedNodeDelegationsResponse, PendingEpochEvent,
|
||||
PendingEpochEventResponse, PendingEpochEventsResponse, PendingIntervalEvent,
|
||||
PendingIntervalEventResponse, PendingIntervalEventsResponse, QueryMsg as MixnetQueryMsg,
|
||||
RewardedSet, UnbondedMixnode,
|
||||
};
|
||||
use serde::Deserialize;
|
||||
|
||||
@@ -91,56 +96,11 @@ pub trait MixnetQueryClient {
|
||||
.await
|
||||
}
|
||||
|
||||
async fn get_rewarded_set_paged(
|
||||
&self,
|
||||
start_after: Option<MixId>,
|
||||
limit: Option<u32>,
|
||||
) -> Result<PagedRewardedSetResponse, NyxdError> {
|
||||
self.query_mixnet_contract(MixnetQueryMsg::GetRewardedSet { limit, start_after })
|
||||
.await
|
||||
}
|
||||
|
||||
async fn get_all_node_families_paged(
|
||||
&self,
|
||||
start_after: Option<String>,
|
||||
limit: Option<u32>,
|
||||
) -> Result<PagedFamiliesResponse, NyxdError> {
|
||||
self.query_mixnet_contract(MixnetQueryMsg::GetAllFamiliesPaged { limit, start_after })
|
||||
.await
|
||||
}
|
||||
|
||||
async fn get_all_family_members_paged(
|
||||
&self,
|
||||
start_after: Option<String>,
|
||||
limit: Option<u32>,
|
||||
) -> Result<PagedMembersResponse, NyxdError> {
|
||||
self.query_mixnet_contract(MixnetQueryMsg::GetAllMembersPaged { limit, start_after })
|
||||
.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(
|
||||
&self,
|
||||
start_after: Option<MixId>,
|
||||
start_after: Option<NodeId>,
|
||||
limit: Option<u32>,
|
||||
) -> Result<PagedMixnodeBondsResponse, NyxdError> {
|
||||
self.query_mixnet_contract(MixnetQueryMsg::GetMixNodeBonds { limit, start_after })
|
||||
@@ -149,26 +109,26 @@ pub trait MixnetQueryClient {
|
||||
|
||||
async fn get_mixnodes_detailed_paged(
|
||||
&self,
|
||||
start_after: Option<MixId>,
|
||||
start_after: Option<NodeId>,
|
||||
limit: Option<u32>,
|
||||
) -> Result<PagedMixnodesDetailsResponse, NyxdError> {
|
||||
self.query_mixnet_contract(MixnetQueryMsg::GetMixNodesDetailed { limit, start_after })
|
||||
.await
|
||||
}
|
||||
|
||||
async fn get_unbonded_paged(
|
||||
async fn get_unbonded_mixnodes_paged(
|
||||
&self,
|
||||
start_after: Option<MixId>,
|
||||
start_after: Option<NodeId>,
|
||||
limit: Option<u32>,
|
||||
) -> Result<PagedUnbondedMixnodesResponse, NyxdError> {
|
||||
self.query_mixnet_contract(MixnetQueryMsg::GetUnbondedMixNodes { limit, start_after })
|
||||
.await
|
||||
}
|
||||
|
||||
async fn get_unbonded_by_owner_paged(
|
||||
async fn get_unbonded_mixnodes_by_owner_paged(
|
||||
&self,
|
||||
owner: &AccountId,
|
||||
start_after: Option<MixId>,
|
||||
start_after: Option<NodeId>,
|
||||
limit: Option<u32>,
|
||||
) -> Result<PagedUnbondedMixnodesResponse, NyxdError> {
|
||||
self.query_mixnet_contract(MixnetQueryMsg::GetUnbondedMixNodesByOwner {
|
||||
@@ -179,10 +139,10 @@ pub trait MixnetQueryClient {
|
||||
.await
|
||||
}
|
||||
|
||||
async fn get_unbonded_by_identity_paged(
|
||||
async fn get_unbonded_mixnodes_by_identity_paged(
|
||||
&self,
|
||||
identity_key: IdentityKeyRef<'_>,
|
||||
start_after: Option<MixId>,
|
||||
start_after: Option<NodeId>,
|
||||
limit: Option<u32>,
|
||||
) -> Result<PagedUnbondedMixnodesResponse, NyxdError> {
|
||||
self.query_mixnet_contract(MixnetQueryMsg::GetUnbondedMixNodesByIdentityKey {
|
||||
@@ -205,7 +165,7 @@ pub trait MixnetQueryClient {
|
||||
|
||||
async fn get_mixnode_details(
|
||||
&self,
|
||||
mix_id: MixId,
|
||||
mix_id: NodeId,
|
||||
) -> Result<MixnodeDetailsResponse, NyxdError> {
|
||||
self.query_mixnet_contract(MixnetQueryMsg::GetMixnodeDetails { mix_id })
|
||||
.await
|
||||
@@ -223,7 +183,7 @@ pub trait MixnetQueryClient {
|
||||
|
||||
async fn get_mixnode_rewarding_details(
|
||||
&self,
|
||||
mix_id: MixId,
|
||||
mix_id: NodeId,
|
||||
) -> Result<MixnodeRewardingDetailsResponse, NyxdError> {
|
||||
self.query_mixnet_contract(MixnetQueryMsg::GetMixnodeRewardingDetails { mix_id })
|
||||
.await
|
||||
@@ -231,24 +191,24 @@ pub trait MixnetQueryClient {
|
||||
|
||||
async fn get_mixnode_stake_saturation(
|
||||
&self,
|
||||
mix_id: MixId,
|
||||
) -> Result<StakeSaturationResponse, NyxdError> {
|
||||
mix_id: NodeId,
|
||||
) -> Result<MixStakeSaturationResponse, NyxdError> {
|
||||
self.query_mixnet_contract(MixnetQueryMsg::GetStakeSaturation { mix_id })
|
||||
.await
|
||||
}
|
||||
|
||||
async fn get_unbonded_mixnode_information(
|
||||
&self,
|
||||
mix_id: MixId,
|
||||
mix_id: NodeId,
|
||||
) -> Result<UnbondedMixnodeResponse, NyxdError> {
|
||||
self.query_mixnet_contract(MixnetQueryMsg::GetUnbondedMixNodeInformation { mix_id })
|
||||
.await
|
||||
}
|
||||
|
||||
async fn get_layer_distribution(&self) -> Result<LayerDistribution, NyxdError> {
|
||||
self.query_mixnet_contract(MixnetQueryMsg::GetLayerDistribution {})
|
||||
.await
|
||||
}
|
||||
// async fn get_layer_distribution(&self) -> Result<LayerDistribution, NyxdError> {
|
||||
// self.query_mixnet_contract(MixnetQueryMsg::GetRoleDistribution {})
|
||||
// .await
|
||||
// }
|
||||
|
||||
// gateway-related:
|
||||
|
||||
@@ -281,17 +241,142 @@ pub trait MixnetQueryClient {
|
||||
.await
|
||||
}
|
||||
|
||||
async fn get_preassigned_gateway_ids_paged(
|
||||
&self,
|
||||
start_after: Option<IdentityKey>,
|
||||
limit: Option<u32>,
|
||||
) -> Result<PreassignedGatewayIdsResponse, NyxdError> {
|
||||
self.query_mixnet_contract(MixnetQueryMsg::GetPreassignedGatewayIds { start_after, limit })
|
||||
.await
|
||||
}
|
||||
|
||||
// nym-nodes related:
|
||||
async fn get_nymnode_bonds_paged(
|
||||
&self,
|
||||
start_after: Option<NodeId>,
|
||||
limit: Option<u32>,
|
||||
) -> Result<PagedNymNodeBondsResponse, NyxdError> {
|
||||
self.query_mixnet_contract(MixnetQueryMsg::GetNymNodeBondsPaged { limit, start_after })
|
||||
.await
|
||||
}
|
||||
|
||||
async fn get_nymnodes_detailed_paged(
|
||||
&self,
|
||||
start_after: Option<NodeId>,
|
||||
limit: Option<u32>,
|
||||
) -> Result<PagedNymNodeDetailsResponse, NyxdError> {
|
||||
self.query_mixnet_contract(MixnetQueryMsg::GetNymNodesDetailedPaged { limit, start_after })
|
||||
.await
|
||||
}
|
||||
|
||||
async fn get_unbonded_nymnodes_paged(
|
||||
&self,
|
||||
start_after: Option<NodeId>,
|
||||
limit: Option<u32>,
|
||||
) -> Result<PagedUnbondedNymNodesResponse, NyxdError> {
|
||||
self.query_mixnet_contract(MixnetQueryMsg::GetUnbondedNymNodesPaged { limit, start_after })
|
||||
.await
|
||||
}
|
||||
|
||||
async fn get_unbonded_nymnodes_by_owner_paged(
|
||||
&self,
|
||||
owner: &AccountId,
|
||||
start_after: Option<NodeId>,
|
||||
limit: Option<u32>,
|
||||
) -> Result<PagedUnbondedNymNodesResponse, NyxdError> {
|
||||
self.query_mixnet_contract(MixnetQueryMsg::GetUnbondedNymNodesByOwnerPaged {
|
||||
owner: owner.to_string(),
|
||||
limit,
|
||||
start_after,
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
async fn get_unbonded_nymnodes_by_identity_paged(
|
||||
&self,
|
||||
identity_key: IdentityKeyRef<'_>,
|
||||
start_after: Option<NodeId>,
|
||||
limit: Option<u32>,
|
||||
) -> Result<PagedUnbondedNymNodesResponse, NyxdError> {
|
||||
self.query_mixnet_contract(MixnetQueryMsg::GetUnbondedNymNodesByIdentityKeyPaged {
|
||||
identity_key: identity_key.to_string(),
|
||||
limit,
|
||||
start_after,
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
async fn get_owned_nymnode(
|
||||
&self,
|
||||
address: &AccountId,
|
||||
) -> Result<NodeOwnershipResponse, NyxdError> {
|
||||
self.query_mixnet_contract(MixnetQueryMsg::GetOwnedNymNode {
|
||||
address: address.to_string(),
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
async fn get_nymnode_details(
|
||||
&self,
|
||||
node_id: NodeId,
|
||||
) -> Result<NodeOwnershipResponse, NyxdError> {
|
||||
self.query_mixnet_contract(MixnetQueryMsg::GetNymNodeDetails { node_id })
|
||||
.await
|
||||
}
|
||||
|
||||
async fn get_nymnode_details_by_identity(
|
||||
&self,
|
||||
node_identity: IdentityKey,
|
||||
) -> Result<NodeDetailsByIdentityResponse, NyxdError> {
|
||||
self.query_mixnet_contract(MixnetQueryMsg::GetNymNodeDetailsByIdentityKey { node_identity })
|
||||
.await
|
||||
}
|
||||
|
||||
async fn get_nymnode_rewarding_details(
|
||||
&self,
|
||||
node_id: NodeId,
|
||||
) -> Result<NodeRewardingDetailsResponse, NyxdError> {
|
||||
self.query_mixnet_contract(MixnetQueryMsg::GetNodeRewardingDetails { node_id })
|
||||
.await
|
||||
}
|
||||
|
||||
async fn get_node_stake_saturation(
|
||||
&self,
|
||||
node_id: NodeId,
|
||||
) -> Result<StakeSaturationResponse, NyxdError> {
|
||||
self.query_mixnet_contract(MixnetQueryMsg::GetNodeStakeSaturation { node_id })
|
||||
.await
|
||||
}
|
||||
|
||||
async fn get_unbonded_nymnode_information(
|
||||
&self,
|
||||
node_id: NodeId,
|
||||
) -> Result<UnbondedNodeResponse, NyxdError> {
|
||||
self.query_mixnet_contract(MixnetQueryMsg::GetUnbondedNymNode { node_id })
|
||||
.await
|
||||
}
|
||||
|
||||
async fn get_role_assignment(&self, role: Role) -> Result<EpochAssignmentResponse, NyxdError> {
|
||||
self.query_mixnet_contract(MixnetQueryMsg::GetRoleAssignment { role })
|
||||
.await
|
||||
}
|
||||
|
||||
async fn get_rewarded_set_metadata(&self) -> Result<RolesMetadataResponse, NyxdError> {
|
||||
self.query_mixnet_contract(MixnetQueryMsg::GetRewardedSetMetadata {})
|
||||
.await
|
||||
}
|
||||
|
||||
// delegation-related:
|
||||
|
||||
/// Gets list of all delegations towards particular mixnode on particular page.
|
||||
async fn get_mixnode_delegations_paged(
|
||||
&self,
|
||||
mix_id: MixId,
|
||||
node_id: NodeId,
|
||||
start_after: Option<String>,
|
||||
limit: Option<u32>,
|
||||
) -> Result<PagedMixNodeDelegationsResponse, NyxdError> {
|
||||
self.query_mixnet_contract(MixnetQueryMsg::GetMixnodeDelegations {
|
||||
mix_id,
|
||||
) -> Result<PagedNodeDelegationsResponse, NyxdError> {
|
||||
self.query_mixnet_contract(MixnetQueryMsg::GetNodeDelegations {
|
||||
node_id,
|
||||
start_after,
|
||||
limit,
|
||||
})
|
||||
@@ -302,7 +387,7 @@ pub trait MixnetQueryClient {
|
||||
async fn get_delegator_delegations_paged(
|
||||
&self,
|
||||
delegator: &AccountId,
|
||||
start_after: Option<(MixId, OwnerProxySubKey)>,
|
||||
start_after: Option<(NodeId, OwnerProxySubKey)>,
|
||||
limit: Option<u32>,
|
||||
) -> Result<PagedDelegatorDelegationsResponse, NyxdError> {
|
||||
self.query_mixnet_contract(MixnetQueryMsg::GetDelegatorDelegations {
|
||||
@@ -316,12 +401,12 @@ pub trait MixnetQueryClient {
|
||||
/// Checks value of delegation of given client towards particular mixnode.
|
||||
async fn get_delegation_details(
|
||||
&self,
|
||||
mix_id: MixId,
|
||||
node_id: NodeId,
|
||||
delegator: &AccountId,
|
||||
proxy: Option<String>,
|
||||
) -> Result<MixNodeDelegationResponse, NyxdError> {
|
||||
) -> Result<NodeDelegationResponse, NyxdError> {
|
||||
self.query_mixnet_contract(MixnetQueryMsg::GetDelegationDetails {
|
||||
mix_id,
|
||||
node_id,
|
||||
delegator: delegator.to_string(),
|
||||
proxy,
|
||||
})
|
||||
@@ -351,21 +436,21 @@ pub trait MixnetQueryClient {
|
||||
|
||||
async fn get_pending_mixnode_operator_reward(
|
||||
&self,
|
||||
mix_id: MixId,
|
||||
node_id: NodeId,
|
||||
) -> Result<PendingRewardResponse, NyxdError> {
|
||||
self.query_mixnet_contract(MixnetQueryMsg::GetPendingMixNodeOperatorReward { mix_id })
|
||||
self.query_mixnet_contract(MixnetQueryMsg::GetPendingNodeOperatorReward { node_id })
|
||||
.await
|
||||
}
|
||||
|
||||
async fn get_pending_delegator_reward(
|
||||
&self,
|
||||
delegator: &AccountId,
|
||||
mix_id: MixId,
|
||||
node_id: NodeId,
|
||||
proxy: Option<String>,
|
||||
) -> Result<PendingRewardResponse, NyxdError> {
|
||||
self.query_mixnet_contract(MixnetQueryMsg::GetPendingDelegatorReward {
|
||||
address: delegator.to_string(),
|
||||
mix_id,
|
||||
node_id,
|
||||
proxy,
|
||||
})
|
||||
.await
|
||||
@@ -374,12 +459,14 @@ pub trait MixnetQueryClient {
|
||||
// given the provided performance, estimate the reward at the end of the current epoch
|
||||
async fn get_estimated_current_epoch_operator_reward(
|
||||
&self,
|
||||
mix_id: MixId,
|
||||
node_id: NodeId,
|
||||
estimated_performance: Performance,
|
||||
estimated_work: Option<WorkFactor>,
|
||||
) -> Result<EstimatedCurrentEpochRewardResponse, NyxdError> {
|
||||
self.query_mixnet_contract(MixnetQueryMsg::GetEstimatedCurrentEpochOperatorReward {
|
||||
mix_id,
|
||||
node_id,
|
||||
estimated_performance,
|
||||
estimated_work,
|
||||
})
|
||||
.await
|
||||
}
|
||||
@@ -388,15 +475,15 @@ pub trait MixnetQueryClient {
|
||||
async fn get_estimated_current_epoch_delegator_reward(
|
||||
&self,
|
||||
delegator: &AccountId,
|
||||
mix_id: MixId,
|
||||
proxy: Option<String>,
|
||||
node_id: NodeId,
|
||||
estimated_performance: Performance,
|
||||
estimated_work: Option<WorkFactor>,
|
||||
) -> Result<EstimatedCurrentEpochRewardResponse, NyxdError> {
|
||||
self.query_mixnet_contract(MixnetQueryMsg::GetEstimatedCurrentEpochDelegatorReward {
|
||||
address: delegator.to_string(),
|
||||
mix_id,
|
||||
proxy,
|
||||
node_id,
|
||||
estimated_performance,
|
||||
estimated_work,
|
||||
})
|
||||
.await
|
||||
}
|
||||
@@ -450,22 +537,6 @@ pub trait MixnetQueryClient {
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
async fn get_node_family_by_label(
|
||||
&self,
|
||||
label: String,
|
||||
) -> Result<FamilyByLabelResponse, NyxdError> {
|
||||
self.query_mixnet_contract(MixnetQueryMsg::GetFamilyByLabel { label })
|
||||
.await
|
||||
}
|
||||
|
||||
async fn get_node_family_by_head(
|
||||
&self,
|
||||
head: String,
|
||||
) -> Result<FamilyByHeadResponse, NyxdError> {
|
||||
self.query_mixnet_contract(MixnetQueryMsg::GetFamilyByHead { head })
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
// extension trait to the query client to deal with the paged queries
|
||||
@@ -473,18 +544,35 @@ pub trait MixnetQueryClient {
|
||||
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
||||
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
|
||||
pub trait PagedMixnetQueryClient: MixnetQueryClient {
|
||||
async fn get_all_node_families(&self) -> Result<Vec<Family>, NyxdError> {
|
||||
collect_paged!(self, get_all_node_families_paged, families)
|
||||
async fn get_all_nymnode_bonds(&self) -> Result<Vec<NymNodeBond>, NyxdError> {
|
||||
collect_paged!(self, get_nymnode_bonds_paged, nodes)
|
||||
}
|
||||
|
||||
async fn get_all_family_members(&self) -> Result<Vec<(IdentityKey, FamilyHead)>, NyxdError> {
|
||||
collect_paged!(self, get_all_family_members_paged, members)
|
||||
async fn get_all_nymnodes_detailed(&self) -> Result<Vec<NymNodeDetails>, NyxdError> {
|
||||
collect_paged!(self, get_nymnodes_detailed_paged, nodes)
|
||||
}
|
||||
|
||||
async fn get_all_rewarded_set_mixnodes(
|
||||
async fn get_all_unbonded_nymnodes(&self) -> Result<Vec<UnbondedNymNode>, NyxdError> {
|
||||
collect_paged!(self, get_unbonded_nymnodes_paged, nodes)
|
||||
}
|
||||
|
||||
async fn get_all_unbonded_nymnodes_by_owner(
|
||||
&self,
|
||||
) -> Result<Vec<(MixId, RewardedSetNodeStatus)>, NyxdError> {
|
||||
collect_paged!(self, get_rewarded_set_paged, nodes)
|
||||
owner: &AccountId,
|
||||
) -> Result<Vec<UnbondedNymNode>, NyxdError> {
|
||||
collect_paged!(self, get_unbonded_nymnodes_by_owner_paged, nodes, owner)
|
||||
}
|
||||
|
||||
async fn get_all_unbonded_nymnodes_by_identity(
|
||||
&self,
|
||||
identity_key: IdentityKeyRef<'_>,
|
||||
) -> Result<Vec<UnbondedNymNode>, NyxdError> {
|
||||
collect_paged!(
|
||||
self,
|
||||
get_unbonded_nymnodes_by_identity_paged,
|
||||
nodes,
|
||||
identity_key
|
||||
)
|
||||
}
|
||||
|
||||
async fn get_all_mixnode_bonds(&self) -> Result<Vec<MixNodeBond>, NyxdError> {
|
||||
@@ -495,31 +583,40 @@ pub trait PagedMixnetQueryClient: MixnetQueryClient {
|
||||
collect_paged!(self, get_mixnodes_detailed_paged, nodes)
|
||||
}
|
||||
|
||||
async fn get_all_unbonded_mixnodes(&self) -> Result<Vec<(MixId, UnbondedMixnode)>, NyxdError> {
|
||||
collect_paged!(self, get_unbonded_paged, nodes)
|
||||
async fn get_all_unbonded_mixnodes(&self) -> Result<Vec<(NodeId, UnbondedMixnode)>, NyxdError> {
|
||||
collect_paged!(self, get_unbonded_mixnodes_paged, nodes)
|
||||
}
|
||||
|
||||
async fn get_all_unbonded_mixnodes_by_owner(
|
||||
&self,
|
||||
owner: &AccountId,
|
||||
) -> Result<Vec<(MixId, UnbondedMixnode)>, NyxdError> {
|
||||
collect_paged!(self, get_unbonded_by_owner_paged, nodes, owner)
|
||||
) -> Result<Vec<(NodeId, UnbondedMixnode)>, NyxdError> {
|
||||
collect_paged!(self, get_unbonded_mixnodes_by_owner_paged, nodes, owner)
|
||||
}
|
||||
|
||||
async fn get_all_unbonded_mixnodes_by_identity(
|
||||
&self,
|
||||
identity_key: IdentityKeyRef<'_>,
|
||||
) -> Result<Vec<(MixId, UnbondedMixnode)>, NyxdError> {
|
||||
collect_paged!(self, get_unbonded_by_identity_paged, nodes, identity_key)
|
||||
) -> Result<Vec<(NodeId, UnbondedMixnode)>, NyxdError> {
|
||||
collect_paged!(
|
||||
self,
|
||||
get_unbonded_mixnodes_by_identity_paged,
|
||||
nodes,
|
||||
identity_key
|
||||
)
|
||||
}
|
||||
|
||||
async fn get_all_gateways(&self) -> Result<Vec<GatewayBond>, NyxdError> {
|
||||
collect_paged!(self, get_gateways_paged, nodes)
|
||||
}
|
||||
|
||||
async fn get_all_preassigned_gateway_ids(&self) -> Result<Vec<PreassignedId>, NyxdError> {
|
||||
collect_paged!(self, get_preassigned_gateway_ids_paged, ids)
|
||||
}
|
||||
|
||||
async fn get_all_single_mixnode_delegations(
|
||||
&self,
|
||||
mix_id: MixId,
|
||||
mix_id: NodeId,
|
||||
) -> Result<Vec<Delegation>, NyxdError> {
|
||||
collect_paged!(self, get_mixnode_delegations_paged, delegations, mix_id)
|
||||
}
|
||||
@@ -554,6 +651,65 @@ pub trait PagedMixnetQueryClient: MixnetQueryClient {
|
||||
#[async_trait]
|
||||
impl<T> PagedMixnetQueryClient for T where T: MixnetQueryClient {}
|
||||
|
||||
// extension help to provide extra functionalities based on existing queries:
|
||||
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
||||
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
|
||||
pub trait MixnetQueryClientExt: MixnetQueryClient {
|
||||
async fn get_rewarded_set(&self) -> Result<RewardedSet, NyxdError> {
|
||||
let error_response = |message| Err(NyxdError::extension_query_failure("mixnet", message));
|
||||
|
||||
let metadata = self.get_rewarded_set_metadata().await?;
|
||||
if !metadata.metadata.fully_assigned {
|
||||
return error_response("the rewarded set hasn't been fully assigned for this epoch");
|
||||
}
|
||||
let expected_epoch_id = metadata.metadata.epoch_id;
|
||||
|
||||
// if we have to query those things more frequently, we could do it concurrently,
|
||||
// but as it stands now, it happens so infrequently it might as well be sequential
|
||||
let entry = self.get_role_assignment(Role::EntryGateway).await?;
|
||||
if entry.epoch_id != expected_epoch_id {
|
||||
return error_response("the nodes assigned for 'entry' returned unexpected epoch_id");
|
||||
}
|
||||
|
||||
let exit = self.get_role_assignment(Role::ExitGateway).await?;
|
||||
if exit.epoch_id != expected_epoch_id {
|
||||
return error_response("the nodes assigned for 'exit' returned unexpected epoch_id");
|
||||
}
|
||||
|
||||
let layer1 = self.get_role_assignment(Role::Layer1).await?;
|
||||
if layer1.epoch_id != expected_epoch_id {
|
||||
return error_response("the nodes assigned for 'layer1' returned unexpected epoch_id");
|
||||
}
|
||||
|
||||
let layer2 = self.get_role_assignment(Role::Layer2).await?;
|
||||
if layer2.epoch_id != expected_epoch_id {
|
||||
return error_response("the nodes assigned for 'layer2' returned unexpected epoch_id");
|
||||
}
|
||||
|
||||
let layer3 = self.get_role_assignment(Role::Layer3).await?;
|
||||
if layer3.epoch_id != expected_epoch_id {
|
||||
return error_response("the nodes assigned for 'layer3' returned unexpected epoch_id");
|
||||
}
|
||||
|
||||
let standby = self.get_role_assignment(Role::Standby).await?;
|
||||
if standby.epoch_id != expected_epoch_id {
|
||||
return error_response("the nodes assigned for 'standby' returned unexpected epoch_id");
|
||||
}
|
||||
|
||||
Ok(RewardedSet {
|
||||
entry_gateways: entry.nodes,
|
||||
exit_gateways: exit.nodes,
|
||||
layer1: layer1.nodes,
|
||||
layer2: layer2.nodes,
|
||||
layer3: layer3.nodes,
|
||||
standby: standby.nodes,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<T> MixnetQueryClientExt for T where T: MixnetQueryClient {}
|
||||
|
||||
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
||||
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
|
||||
impl<C> MixnetQueryClient for C
|
||||
@@ -585,24 +741,6 @@ mod tests {
|
||||
) -> u32 {
|
||||
match msg {
|
||||
MixnetQueryMsg::Admin {} => client.admin().ignore(),
|
||||
MixnetQueryMsg::GetAllFamiliesPaged { limit, start_after } => client
|
||||
.get_all_family_members_paged(start_after, limit)
|
||||
.ignore(),
|
||||
MixnetQueryMsg::GetAllMembersPaged { limit, start_after } => client
|
||||
.get_all_family_members_paged(start_after, limit)
|
||||
.ignore(),
|
||||
MixnetQueryMsg::GetFamilyByHead { head } => {
|
||||
client.get_node_family_by_head(head).ignore()
|
||||
}
|
||||
MixnetQueryMsg::GetFamilyByLabel { label } => {
|
||||
client.get_node_family_by_label(label).ignore()
|
||||
}
|
||||
MixnetQueryMsg::GetFamilyMembersByHead { head } => {
|
||||
client.get_family_members_by_head(head).ignore()
|
||||
}
|
||||
MixnetQueryMsg::GetFamilyMembersByLabel { label } => {
|
||||
client.get_family_members_by_label(label).ignore()
|
||||
}
|
||||
MixnetQueryMsg::GetContractVersion {} => client.get_mixnet_contract_version().ignore(),
|
||||
MixnetQueryMsg::GetCW2ContractVersion {} => {
|
||||
client.get_mixnet_contract_cw2_version().ignore()
|
||||
@@ -617,31 +755,28 @@ mod tests {
|
||||
MixnetQueryMsg::GetCurrentIntervalDetails {} => {
|
||||
client.get_current_interval_details().ignore()
|
||||
}
|
||||
MixnetQueryMsg::GetRewardedSet { limit, start_after } => {
|
||||
client.get_rewarded_set_paged(start_after, limit).ignore()
|
||||
}
|
||||
MixnetQueryMsg::GetMixNodeBonds { limit, start_after } => {
|
||||
client.get_mixnode_bonds_paged(start_after, limit).ignore()
|
||||
}
|
||||
MixnetQueryMsg::GetMixNodesDetailed { limit, start_after } => client
|
||||
.get_mixnodes_detailed_paged(start_after, limit)
|
||||
.ignore(),
|
||||
MixnetQueryMsg::GetUnbondedMixNodes { limit, start_after } => {
|
||||
client.get_unbonded_paged(start_after, limit).ignore()
|
||||
}
|
||||
MixnetQueryMsg::GetUnbondedMixNodes { limit, start_after } => client
|
||||
.get_unbonded_mixnodes_paged(start_after, limit)
|
||||
.ignore(),
|
||||
MixnetQueryMsg::GetUnbondedMixNodesByOwner {
|
||||
owner,
|
||||
limit,
|
||||
start_after,
|
||||
} => client
|
||||
.get_unbonded_by_owner_paged(&owner.parse().unwrap(), start_after, limit)
|
||||
.get_unbonded_mixnodes_by_owner_paged(&owner.parse().unwrap(), start_after, limit)
|
||||
.ignore(),
|
||||
MixnetQueryMsg::GetUnbondedMixNodesByIdentityKey {
|
||||
identity_key,
|
||||
limit,
|
||||
start_after,
|
||||
} => client
|
||||
.get_unbonded_by_identity_paged(&identity_key, start_after, limit)
|
||||
.get_unbonded_mixnodes_by_identity_paged(&identity_key, start_after, limit)
|
||||
.ignore(),
|
||||
MixnetQueryMsg::GetOwnedMixnode { address } => {
|
||||
client.get_owned_mixnode(&address.parse().unwrap()).ignore()
|
||||
@@ -661,7 +796,6 @@ mod tests {
|
||||
MixnetQueryMsg::GetBondedMixnodeDetailsByIdentity { mix_identity } => client
|
||||
.get_mixnode_details_by_identity(mix_identity)
|
||||
.ignore(),
|
||||
MixnetQueryMsg::GetLayerDistribution {} => client.get_layer_distribution().ignore(),
|
||||
MixnetQueryMsg::GetGateways { start_after, limit } => {
|
||||
client.get_gateways_paged(start_after, limit).ignore()
|
||||
}
|
||||
@@ -671,8 +805,8 @@ mod tests {
|
||||
MixnetQueryMsg::GetOwnedGateway { address } => {
|
||||
client.get_owned_gateway(&address.parse().unwrap()).ignore()
|
||||
}
|
||||
MixnetQueryMsg::GetMixnodeDelegations {
|
||||
mix_id,
|
||||
MixnetQueryMsg::GetNodeDelegations {
|
||||
node_id: mix_id,
|
||||
start_after,
|
||||
limit,
|
||||
} => client
|
||||
@@ -686,7 +820,7 @@ mod tests {
|
||||
.get_delegator_delegations_paged(&delegator.parse().unwrap(), start_after, limit)
|
||||
.ignore(),
|
||||
MixnetQueryMsg::GetDelegationDetails {
|
||||
mix_id,
|
||||
node_id: mix_id,
|
||||
delegator,
|
||||
proxy,
|
||||
} => client
|
||||
@@ -698,33 +832,38 @@ mod tests {
|
||||
MixnetQueryMsg::GetPendingOperatorReward { address } => client
|
||||
.get_pending_operator_reward(&address.parse().unwrap())
|
||||
.ignore(),
|
||||
MixnetQueryMsg::GetPendingMixNodeOperatorReward { mix_id } => {
|
||||
MixnetQueryMsg::GetPendingNodeOperatorReward { node_id: mix_id } => {
|
||||
client.get_pending_mixnode_operator_reward(mix_id).ignore()
|
||||
}
|
||||
MixnetQueryMsg::GetPendingDelegatorReward {
|
||||
address,
|
||||
mix_id,
|
||||
node_id: mix_id,
|
||||
proxy,
|
||||
} => client
|
||||
.get_pending_delegator_reward(&address.parse().unwrap(), mix_id, proxy)
|
||||
.ignore(),
|
||||
MixnetQueryMsg::GetEstimatedCurrentEpochOperatorReward {
|
||||
mix_id,
|
||||
node_id,
|
||||
estimated_performance,
|
||||
estimated_work,
|
||||
} => client
|
||||
.get_estimated_current_epoch_operator_reward(mix_id, estimated_performance)
|
||||
.get_estimated_current_epoch_operator_reward(
|
||||
node_id,
|
||||
estimated_performance,
|
||||
estimated_work,
|
||||
)
|
||||
.ignore(),
|
||||
MixnetQueryMsg::GetEstimatedCurrentEpochDelegatorReward {
|
||||
address,
|
||||
mix_id,
|
||||
proxy,
|
||||
node_id,
|
||||
estimated_performance,
|
||||
estimated_work,
|
||||
} => client
|
||||
.get_estimated_current_epoch_delegator_reward(
|
||||
&address.parse().unwrap(),
|
||||
mix_id,
|
||||
proxy,
|
||||
node_id,
|
||||
estimated_performance,
|
||||
estimated_work,
|
||||
)
|
||||
.ignore(),
|
||||
MixnetQueryMsg::GetPendingEpochEvents { limit, start_after } => client
|
||||
@@ -745,6 +884,54 @@ mod tests {
|
||||
MixnetQueryMsg::GetSigningNonce { address } => {
|
||||
client.get_signing_nonce(&address.parse().unwrap()).ignore()
|
||||
}
|
||||
MixnetQueryMsg::GetPreassignedGatewayIds { start_after, limit } => client
|
||||
.get_preassigned_gateway_ids_paged(start_after, limit)
|
||||
.ignore(),
|
||||
MixnetQueryMsg::GetNymNodeBondsPaged { limit, start_after } => {
|
||||
client.get_nymnode_bonds_paged(limit, start_after).ignore()
|
||||
}
|
||||
MixnetQueryMsg::GetNymNodesDetailedPaged { limit, start_after } => client
|
||||
.get_nymnodes_detailed_paged(limit, start_after)
|
||||
.ignore(),
|
||||
MixnetQueryMsg::GetUnbondedNymNode { node_id } => {
|
||||
client.get_unbonded_nymnode_information(node_id).ignore()
|
||||
}
|
||||
MixnetQueryMsg::GetUnbondedNymNodesPaged { limit, start_after } => client
|
||||
.get_unbonded_nymnodes_paged(limit, start_after)
|
||||
.ignore(),
|
||||
MixnetQueryMsg::GetUnbondedNymNodesByOwnerPaged {
|
||||
owner,
|
||||
limit,
|
||||
start_after,
|
||||
} => client
|
||||
.get_unbonded_nymnodes_by_owner_paged(&owner.parse().unwrap(), limit, start_after)
|
||||
.ignore(),
|
||||
MixnetQueryMsg::GetUnbondedNymNodesByIdentityKeyPaged {
|
||||
identity_key,
|
||||
limit,
|
||||
start_after,
|
||||
} => client
|
||||
.get_unbonded_nymnodes_by_identity_paged(&identity_key, limit, start_after)
|
||||
.ignore(),
|
||||
MixnetQueryMsg::GetOwnedNymNode { address } => {
|
||||
client.get_owned_nymnode(&address.parse().unwrap()).ignore()
|
||||
}
|
||||
MixnetQueryMsg::GetNymNodeDetails { node_id } => {
|
||||
client.get_nymnode_details(node_id).ignore()
|
||||
}
|
||||
MixnetQueryMsg::GetNymNodeDetailsByIdentityKey { node_identity } => client
|
||||
.get_nymnode_details_by_identity(node_identity)
|
||||
.ignore(),
|
||||
MixnetQueryMsg::GetNodeRewardingDetails { node_id } => {
|
||||
client.get_nymnode_rewarding_details(node_id).ignore()
|
||||
}
|
||||
MixnetQueryMsg::GetNodeStakeSaturation { node_id } => {
|
||||
client.get_node_stake_saturation(node_id).ignore()
|
||||
}
|
||||
MixnetQueryMsg::GetRoleAssignment { role } => client.get_role_assignment(role).ignore(),
|
||||
MixnetQueryMsg::GetRewardedSetMetadata {} => {
|
||||
client.get_rewarded_set_metadata().ignore()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+122
-240
@@ -10,13 +10,15 @@ use crate::signing::signer::OfflineSigner;
|
||||
use async_trait::async_trait;
|
||||
use cosmrs::AccountId;
|
||||
use nym_contracts_common::signing::MessageSignature;
|
||||
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::reward_params::{IntervalRewardingParamsUpdate, Performance};
|
||||
use nym_mixnet_contract_common::mixnode::{MixNodeConfigUpdate, NodeCostParams};
|
||||
use nym_mixnet_contract_common::nym_node::NodeConfigUpdate;
|
||||
use nym_mixnet_contract_common::reward_params::{
|
||||
ActiveSetUpdate, IntervalRewardingParamsUpdate, NodeRewardingParameters,
|
||||
};
|
||||
use nym_mixnet_contract_common::{
|
||||
ContractStateParams, ExecuteMsg as MixnetExecuteMsg, Gateway, Layer, LayerAssignment, MixId,
|
||||
MixNode,
|
||||
ContractStateParams, ExecuteMsg as MixnetExecuteMsg, Gateway, MixNode, NodeId, NymNode,
|
||||
RoleAssignment,
|
||||
};
|
||||
|
||||
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
||||
@@ -70,14 +72,14 @@ pub trait MixnetSigningClient {
|
||||
|
||||
async fn update_active_set_size(
|
||||
&self,
|
||||
active_set_size: u32,
|
||||
update: ActiveSetUpdate,
|
||||
force_immediately: bool,
|
||||
fee: Option<Fee>,
|
||||
) -> Result<ExecuteResult, NyxdError> {
|
||||
self.execute_mixnet_contract(
|
||||
fee,
|
||||
MixnetExecuteMsg::UpdateActiveSetSize {
|
||||
active_set_size,
|
||||
MixnetExecuteMsg::UpdateActiveSetDistribution {
|
||||
update,
|
||||
force_immediately,
|
||||
},
|
||||
vec![],
|
||||
@@ -126,37 +128,6 @@ pub trait MixnetSigningClient {
|
||||
.await
|
||||
}
|
||||
|
||||
async fn advance_current_epoch(
|
||||
&self,
|
||||
new_rewarded_set: Vec<LayerAssignment>,
|
||||
expected_active_set_size: u32,
|
||||
fee: Option<Fee>,
|
||||
) -> Result<ExecuteResult, NyxdError> {
|
||||
self.execute_mixnet_contract(
|
||||
fee,
|
||||
MixnetExecuteMsg::AdvanceCurrentEpoch {
|
||||
new_rewarded_set,
|
||||
expected_active_set_size,
|
||||
},
|
||||
vec![],
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn assign_node_layer(
|
||||
&self,
|
||||
mix_id: MixId,
|
||||
layer: Layer,
|
||||
fee: Option<Fee>,
|
||||
) -> Result<ExecuteResult, NyxdError> {
|
||||
self.execute_mixnet_contract(
|
||||
fee,
|
||||
MixnetExecuteMsg::AssignNodeLayer { mix_id, layer },
|
||||
vec![],
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn reconcile_epoch_events(
|
||||
&self,
|
||||
limit: Option<u32>,
|
||||
@@ -170,126 +141,21 @@ pub trait MixnetSigningClient {
|
||||
.await
|
||||
}
|
||||
|
||||
// family related
|
||||
async fn create_family(
|
||||
async fn assign_roles(
|
||||
&self,
|
||||
label: String,
|
||||
assignment: RoleAssignment,
|
||||
fee: Option<Fee>,
|
||||
) -> Result<ExecuteResult, NyxdError> {
|
||||
self.execute_mixnet_contract(fee, MixnetExecuteMsg::CreateFamily { label }, vec![])
|
||||
self.execute_mixnet_contract(fee, MixnetExecuteMsg::AssignRoles { assignment }, vec![])
|
||||
.await
|
||||
}
|
||||
|
||||
async fn create_family_on_behalf(
|
||||
&self,
|
||||
owner_address: String,
|
||||
label: String,
|
||||
fee: Option<Fee>,
|
||||
) -> Result<ExecuteResult, NyxdError> {
|
||||
self.execute_mixnet_contract(
|
||||
fee,
|
||||
MixnetExecuteMsg::CreateFamilyOnBehalf {
|
||||
owner_address,
|
||||
label,
|
||||
},
|
||||
vec![],
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn join_family(
|
||||
&self,
|
||||
join_permit: MessageSignature,
|
||||
family_head: FamilyHead,
|
||||
fee: Option<Fee>,
|
||||
) -> Result<ExecuteResult, NyxdError> {
|
||||
self.execute_mixnet_contract(
|
||||
fee,
|
||||
MixnetExecuteMsg::JoinFamily {
|
||||
join_permit,
|
||||
family_head,
|
||||
},
|
||||
vec![],
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn join_family_on_behalf(
|
||||
&self,
|
||||
member_address: String,
|
||||
join_permit: MessageSignature,
|
||||
family_head: FamilyHead,
|
||||
fee: Option<Fee>,
|
||||
) -> Result<ExecuteResult, NyxdError> {
|
||||
self.execute_mixnet_contract(
|
||||
fee,
|
||||
MixnetExecuteMsg::JoinFamilyOnBehalf {
|
||||
member_address,
|
||||
join_permit,
|
||||
family_head,
|
||||
},
|
||||
vec![],
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn leave_family(
|
||||
&self,
|
||||
family_head: FamilyHead,
|
||||
fee: Option<Fee>,
|
||||
) -> Result<ExecuteResult, NyxdError> {
|
||||
self.execute_mixnet_contract(fee, MixnetExecuteMsg::LeaveFamily { family_head }, vec![])
|
||||
.await
|
||||
}
|
||||
|
||||
async fn leave_family_on_behalf(
|
||||
&self,
|
||||
member_address: String,
|
||||
family_head: FamilyHead,
|
||||
fee: Option<Fee>,
|
||||
) -> Result<ExecuteResult, NyxdError> {
|
||||
self.execute_mixnet_contract(
|
||||
fee,
|
||||
MixnetExecuteMsg::LeaveFamilyOnBehalf {
|
||||
member_address,
|
||||
family_head,
|
||||
},
|
||||
vec![],
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn kick_family_member(
|
||||
&self,
|
||||
member: String,
|
||||
fee: Option<Fee>,
|
||||
) -> Result<ExecuteResult, NyxdError> {
|
||||
self.execute_mixnet_contract(fee, MixnetExecuteMsg::KickFamilyMember { member }, vec![])
|
||||
.await
|
||||
}
|
||||
|
||||
async fn kick_family_member_on_behalf(
|
||||
&self,
|
||||
head_address: String,
|
||||
member: String,
|
||||
fee: Option<Fee>,
|
||||
) -> Result<ExecuteResult, NyxdError> {
|
||||
self.execute_mixnet_contract(
|
||||
fee,
|
||||
MixnetExecuteMsg::KickFamilyMemberOnBehalf {
|
||||
head_address,
|
||||
member,
|
||||
},
|
||||
vec![],
|
||||
)
|
||||
.await
|
||||
}
|
||||
// mixnode-related:
|
||||
|
||||
async fn bond_mixnode(
|
||||
&self,
|
||||
mix_node: MixNode,
|
||||
cost_params: MixNodeCostParams,
|
||||
cost_params: NodeCostParams,
|
||||
owner_signature: MessageSignature,
|
||||
pledge: Coin,
|
||||
fee: Option<Fee>,
|
||||
@@ -310,7 +176,7 @@ pub trait MixnetSigningClient {
|
||||
&self,
|
||||
owner: AccountId,
|
||||
mix_node: MixNode,
|
||||
cost_params: MixNodeCostParams,
|
||||
cost_params: NodeCostParams,
|
||||
owner_signature: MessageSignature,
|
||||
pledge: Coin,
|
||||
fee: Option<Fee>,
|
||||
@@ -409,14 +275,14 @@ pub trait MixnetSigningClient {
|
||||
.await
|
||||
}
|
||||
|
||||
async fn update_mixnode_cost_params(
|
||||
async fn update_cost_params(
|
||||
&self,
|
||||
new_costs: MixNodeCostParams,
|
||||
new_costs: NodeCostParams,
|
||||
fee: Option<Fee>,
|
||||
) -> Result<ExecuteResult, NyxdError> {
|
||||
self.execute_mixnet_contract(
|
||||
fee,
|
||||
MixnetExecuteMsg::UpdateMixnodeCostParams { new_costs },
|
||||
MixnetExecuteMsg::UpdateCostParams { new_costs },
|
||||
vec![],
|
||||
)
|
||||
.await
|
||||
@@ -425,7 +291,7 @@ pub trait MixnetSigningClient {
|
||||
async fn update_mixnode_cost_params_on_behalf(
|
||||
&self,
|
||||
owner: AccountId,
|
||||
new_costs: MixNodeCostParams,
|
||||
new_costs: NodeCostParams,
|
||||
fee: Option<Fee>,
|
||||
) -> Result<ExecuteResult, NyxdError> {
|
||||
self.execute_mixnet_contract(
|
||||
@@ -559,26 +425,75 @@ pub trait MixnetSigningClient {
|
||||
.await
|
||||
}
|
||||
|
||||
// delegation-related:
|
||||
// nym-node related:
|
||||
async fn migrate_legacy_mixnode(&self, fee: Option<Fee>) -> Result<ExecuteResult, NyxdError> {
|
||||
self.execute_mixnet_contract(fee, MixnetExecuteMsg::MigrateMixnode {}, vec![])
|
||||
.await
|
||||
}
|
||||
|
||||
async fn delegate_to_mixnode(
|
||||
async fn migrate_legacy_gateway(
|
||||
&self,
|
||||
mix_id: MixId,
|
||||
amount: Coin,
|
||||
cost_params: Option<NodeCostParams>,
|
||||
fee: Option<Fee>,
|
||||
) -> Result<ExecuteResult, NyxdError> {
|
||||
self.execute_mixnet_contract(
|
||||
fee,
|
||||
MixnetExecuteMsg::DelegateToMixnode { mix_id },
|
||||
vec![amount],
|
||||
MixnetExecuteMsg::MigrateGateway { cost_params },
|
||||
vec![],
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn bond_nymnode(
|
||||
&self,
|
||||
node: NymNode,
|
||||
cost_params: NodeCostParams,
|
||||
owner_signature: MessageSignature,
|
||||
pledge: Coin,
|
||||
fee: Option<Fee>,
|
||||
) -> Result<ExecuteResult, NyxdError> {
|
||||
self.execute_mixnet_contract(
|
||||
fee,
|
||||
MixnetExecuteMsg::BondNymNode {
|
||||
node,
|
||||
cost_params,
|
||||
owner_signature,
|
||||
},
|
||||
vec![pledge],
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn unbond_nymnode(&self, fee: Option<Fee>) -> Result<ExecuteResult, NyxdError> {
|
||||
self.execute_mixnet_contract(fee, MixnetExecuteMsg::UnbondNymNode {}, vec![])
|
||||
.await
|
||||
}
|
||||
|
||||
async fn update_nymnode_config(
|
||||
&self,
|
||||
update: NodeConfigUpdate,
|
||||
fee: Option<Fee>,
|
||||
) -> Result<ExecuteResult, NyxdError> {
|
||||
self.execute_mixnet_contract(fee, MixnetExecuteMsg::UpdateNodeConfig { update }, vec![])
|
||||
.await
|
||||
}
|
||||
|
||||
// delegation-related:
|
||||
|
||||
async fn delegate(
|
||||
&self,
|
||||
node_id: NodeId,
|
||||
amount: Coin,
|
||||
fee: Option<Fee>,
|
||||
) -> Result<ExecuteResult, NyxdError> {
|
||||
self.execute_mixnet_contract(fee, MixnetExecuteMsg::Delegate { node_id }, vec![amount])
|
||||
.await
|
||||
}
|
||||
|
||||
async fn delegate_to_mixnode_on_behalf(
|
||||
&self,
|
||||
delegate: AccountId,
|
||||
mix_id: MixId,
|
||||
mix_id: NodeId,
|
||||
amount: Coin,
|
||||
fee: Option<Fee>,
|
||||
) -> Result<ExecuteResult, NyxdError> {
|
||||
@@ -593,23 +508,19 @@ pub trait MixnetSigningClient {
|
||||
.await
|
||||
}
|
||||
|
||||
async fn undelegate_from_mixnode(
|
||||
async fn undelegate(
|
||||
&self,
|
||||
mix_id: MixId,
|
||||
node_id: NodeId,
|
||||
fee: Option<Fee>,
|
||||
) -> Result<ExecuteResult, NyxdError> {
|
||||
self.execute_mixnet_contract(
|
||||
fee,
|
||||
MixnetExecuteMsg::UndelegateFromMixnode { mix_id },
|
||||
vec![],
|
||||
)
|
||||
.await
|
||||
self.execute_mixnet_contract(fee, MixnetExecuteMsg::Undelegate { node_id }, vec![])
|
||||
.await
|
||||
}
|
||||
|
||||
async fn undelegate_to_mixnode_on_behalf(
|
||||
&self,
|
||||
delegate: AccountId,
|
||||
mix_id: MixId,
|
||||
mix_id: NodeId,
|
||||
fee: Option<Fee>,
|
||||
) -> Result<ExecuteResult, NyxdError> {
|
||||
self.execute_mixnet_contract(
|
||||
@@ -625,18 +536,15 @@ pub trait MixnetSigningClient {
|
||||
|
||||
// reward-related
|
||||
|
||||
async fn reward_mixnode(
|
||||
async fn reward_node(
|
||||
&self,
|
||||
mix_id: MixId,
|
||||
performance: Performance,
|
||||
node_id: NodeId,
|
||||
params: NodeRewardingParameters,
|
||||
fee: Option<Fee>,
|
||||
) -> Result<ExecuteResult, NyxdError> {
|
||||
self.execute_mixnet_contract(
|
||||
fee,
|
||||
MixnetExecuteMsg::RewardMixnode {
|
||||
mix_id,
|
||||
performance,
|
||||
},
|
||||
MixnetExecuteMsg::RewardNode { node_id, params },
|
||||
vec![],
|
||||
)
|
||||
.await
|
||||
@@ -664,12 +572,12 @@ pub trait MixnetSigningClient {
|
||||
|
||||
async fn withdraw_delegator_reward(
|
||||
&self,
|
||||
mix_id: MixId,
|
||||
node_id: NodeId,
|
||||
fee: Option<Fee>,
|
||||
) -> Result<ExecuteResult, NyxdError> {
|
||||
self.execute_mixnet_contract(
|
||||
fee,
|
||||
MixnetExecuteMsg::WithdrawDelegatorReward { mix_id },
|
||||
MixnetExecuteMsg::WithdrawDelegatorReward { node_id },
|
||||
vec![],
|
||||
)
|
||||
.await
|
||||
@@ -678,7 +586,7 @@ pub trait MixnetSigningClient {
|
||||
async fn withdraw_delegator_reward_on_behalf(
|
||||
&self,
|
||||
owner: AccountId,
|
||||
mix_id: MixId,
|
||||
mix_id: NodeId,
|
||||
fee: Option<Fee>,
|
||||
) -> Result<ExecuteResult, NyxdError> {
|
||||
self.execute_mixnet_contract(
|
||||
@@ -699,7 +607,7 @@ pub trait MixnetSigningClient {
|
||||
|
||||
async fn migrate_vested_delegation(
|
||||
&self,
|
||||
mix_id: MixId,
|
||||
mix_id: NodeId,
|
||||
fee: Option<Fee>,
|
||||
) -> Result<ExecuteResult, NyxdError> {
|
||||
self.execute_mixnet_contract(
|
||||
@@ -761,6 +669,7 @@ where
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::nyxd::contract_traits::tests::{mock_coin, IgnoreValue};
|
||||
use nym_mixnet_contract_common::ExecuteMsg;
|
||||
|
||||
// it's enough that this compiles and clippy is happy about it
|
||||
#[allow(dead_code)]
|
||||
@@ -770,56 +679,17 @@ mod tests {
|
||||
) {
|
||||
match msg {
|
||||
MixnetExecuteMsg::UpdateAdmin { admin } => client.update_admin(admin, None).ignore(),
|
||||
MixnetExecuteMsg::AssignNodeLayer { mix_id, layer } => {
|
||||
client.assign_node_layer(mix_id, layer, None).ignore()
|
||||
}
|
||||
MixnetExecuteMsg::CreateFamily { label } => client.create_family(label, None).ignore(),
|
||||
MixnetExecuteMsg::JoinFamily {
|
||||
join_permit,
|
||||
family_head,
|
||||
} => client.join_family(join_permit, family_head, None).ignore(),
|
||||
MixnetExecuteMsg::LeaveFamily { family_head } => {
|
||||
client.leave_family(family_head, None).ignore()
|
||||
}
|
||||
MixnetExecuteMsg::KickFamilyMember { member } => {
|
||||
client.kick_family_member(member, None).ignore()
|
||||
}
|
||||
MixnetExecuteMsg::CreateFamilyOnBehalf {
|
||||
owner_address,
|
||||
label,
|
||||
} => client
|
||||
.create_family_on_behalf(owner_address, label, None)
|
||||
.ignore(),
|
||||
MixnetExecuteMsg::JoinFamilyOnBehalf {
|
||||
member_address,
|
||||
join_permit,
|
||||
family_head,
|
||||
} => client
|
||||
.join_family_on_behalf(member_address, join_permit, family_head, None)
|
||||
.ignore(),
|
||||
MixnetExecuteMsg::LeaveFamilyOnBehalf {
|
||||
member_address,
|
||||
family_head,
|
||||
} => client
|
||||
.leave_family_on_behalf(member_address, family_head, None)
|
||||
.ignore(),
|
||||
MixnetExecuteMsg::KickFamilyMemberOnBehalf {
|
||||
head_address,
|
||||
member,
|
||||
} => client
|
||||
.kick_family_member_on_behalf(head_address, member, None)
|
||||
.ignore(),
|
||||
MixnetExecuteMsg::UpdateRewardingValidatorAddress { address } => client
|
||||
.update_rewarding_validator_address(address.parse().unwrap(), None)
|
||||
.ignore(),
|
||||
MixnetExecuteMsg::UpdateContractStateParams { updated_parameters } => client
|
||||
.update_contract_state_params(updated_parameters, None)
|
||||
.ignore(),
|
||||
MixnetExecuteMsg::UpdateActiveSetSize {
|
||||
active_set_size,
|
||||
MixnetExecuteMsg::UpdateActiveSetDistribution {
|
||||
update,
|
||||
force_immediately,
|
||||
} => client
|
||||
.update_active_set_size(active_set_size, force_immediately, None)
|
||||
.update_active_set_size(update, force_immediately, None)
|
||||
.ignore(),
|
||||
MixnetExecuteMsg::UpdateRewardingParams {
|
||||
updated_params,
|
||||
@@ -842,12 +712,6 @@ mod tests {
|
||||
MixnetExecuteMsg::BeginEpochTransition {} => {
|
||||
client.begin_epoch_transition(None).ignore()
|
||||
}
|
||||
MixnetExecuteMsg::AdvanceCurrentEpoch {
|
||||
new_rewarded_set,
|
||||
expected_active_set_size,
|
||||
} => client
|
||||
.advance_current_epoch(new_rewarded_set, expected_active_set_size, None)
|
||||
.ignore(),
|
||||
MixnetExecuteMsg::ReconcileEpochEvents { limit } => {
|
||||
client.reconcile_epoch_events(limit, None).ignore()
|
||||
}
|
||||
@@ -887,8 +751,8 @@ mod tests {
|
||||
MixnetExecuteMsg::UnbondMixnodeOnBehalf { owner } => client
|
||||
.unbond_mixnode_on_behalf(owner.parse().unwrap(), None)
|
||||
.ignore(),
|
||||
MixnetExecuteMsg::UpdateMixnodeCostParams { new_costs } => {
|
||||
client.update_mixnode_cost_params(new_costs, None).ignore()
|
||||
MixnetExecuteMsg::UpdateCostParams { new_costs } => {
|
||||
client.update_cost_params(new_costs, None).ignore()
|
||||
}
|
||||
MixnetExecuteMsg::UpdateMixnodeCostParamsOnBehalf { new_costs, owner } => client
|
||||
.update_mixnode_cost_params_on_behalf(owner.parse().unwrap(), new_costs, None)
|
||||
@@ -928,29 +792,28 @@ mod tests {
|
||||
MixnetExecuteMsg::UpdateGatewayConfigOnBehalf { new_config, owner } => client
|
||||
.update_gateway_config_on_behalf(owner.parse().unwrap(), new_config, None)
|
||||
.ignore(),
|
||||
MixnetExecuteMsg::DelegateToMixnode { mix_id } => client
|
||||
.delegate_to_mixnode(mix_id, mock_coin(), None)
|
||||
.ignore(),
|
||||
MixnetExecuteMsg::Delegate { node_id: mix_id } => {
|
||||
client.delegate(mix_id, mock_coin(), None).ignore()
|
||||
}
|
||||
MixnetExecuteMsg::DelegateToMixnodeOnBehalf { mix_id, delegate } => client
|
||||
.delegate_to_mixnode_on_behalf(delegate.parse().unwrap(), mix_id, mock_coin(), None)
|
||||
.ignore(),
|
||||
MixnetExecuteMsg::UndelegateFromMixnode { mix_id } => {
|
||||
client.undelegate_from_mixnode(mix_id, None).ignore()
|
||||
MixnetExecuteMsg::Undelegate { node_id: mix_id } => {
|
||||
client.undelegate(mix_id, None).ignore()
|
||||
}
|
||||
MixnetExecuteMsg::UndelegateFromMixnodeOnBehalf { mix_id, delegate } => client
|
||||
.undelegate_to_mixnode_on_behalf(delegate.parse().unwrap(), mix_id, None)
|
||||
.ignore(),
|
||||
MixnetExecuteMsg::RewardMixnode {
|
||||
mix_id,
|
||||
performance,
|
||||
} => client.reward_mixnode(mix_id, performance, None).ignore(),
|
||||
MixnetExecuteMsg::RewardNode { node_id, params } => {
|
||||
client.reward_node(node_id, params, None).ignore()
|
||||
}
|
||||
MixnetExecuteMsg::WithdrawOperatorReward {} => {
|
||||
client.withdraw_operator_reward(None).ignore()
|
||||
}
|
||||
MixnetExecuteMsg::WithdrawOperatorRewardOnBehalf { owner } => client
|
||||
.withdraw_operator_reward_on_behalf(owner.parse().unwrap(), None)
|
||||
.ignore(),
|
||||
MixnetExecuteMsg::WithdrawDelegatorReward { mix_id } => {
|
||||
MixnetExecuteMsg::WithdrawDelegatorReward { node_id: mix_id } => {
|
||||
client.withdraw_delegator_reward(mix_id, None).ignore()
|
||||
}
|
||||
MixnetExecuteMsg::WithdrawDelegatorRewardOnBehalf { mix_id, owner } => client
|
||||
@@ -963,6 +826,25 @@ mod tests {
|
||||
client.migrate_vested_delegation(mix_id, None).ignore()
|
||||
}
|
||||
|
||||
ExecuteMsg::AssignRoles { assignment } => {
|
||||
client.assign_roles(assignment, None).ignore()
|
||||
}
|
||||
ExecuteMsg::MigrateMixnode {} => client.migrate_legacy_mixnode(None).ignore(),
|
||||
ExecuteMsg::MigrateGateway { cost_params } => {
|
||||
client.migrate_legacy_gateway(cost_params, None).ignore()
|
||||
}
|
||||
ExecuteMsg::BondNymNode {
|
||||
node,
|
||||
cost_params,
|
||||
owner_signature,
|
||||
} => client
|
||||
.bond_nymnode(node, cost_params, owner_signature, mock_coin(), None)
|
||||
.ignore(),
|
||||
ExecuteMsg::UnbondNymNode {} => client.unbond_nymnode(None).ignore(),
|
||||
ExecuteMsg::UpdateNodeConfig { update } => {
|
||||
client.update_nymnode_config(update, None).ignore()
|
||||
}
|
||||
|
||||
#[cfg(feature = "contract-testing")]
|
||||
MixnetExecuteMsg::TestingResolveAllPendingEvents { .. } => {
|
||||
client.testing_resolve_all_pending_events(None).ignore()
|
||||
|
||||
+5
-5
@@ -9,7 +9,7 @@ use crate::nyxd::CosmWasmClient;
|
||||
use async_trait::async_trait;
|
||||
use cosmwasm_std::{Coin as CosmWasmCoin, Timestamp};
|
||||
use nym_contracts_common::ContractBuildInformation;
|
||||
use nym_mixnet_contract_common::MixId;
|
||||
use nym_mixnet_contract_common::NodeId;
|
||||
use nym_vesting_contract_common::{
|
||||
messages::QueryMsg as VestingQueryMsg, Account, AccountVestingCoins, AccountsResponse,
|
||||
AllDelegationsResponse, BaseVestingAccountInfo, DelegationTimesResponse,
|
||||
@@ -238,7 +238,7 @@ pub trait VestingQueryClient {
|
||||
async fn get_vesting_delegation(
|
||||
&self,
|
||||
address: &str,
|
||||
mix_id: MixId,
|
||||
mix_id: NodeId,
|
||||
block_timestamp_secs: u64,
|
||||
) -> Result<VestingDelegation, NyxdError> {
|
||||
self.query_vesting_contract(VestingQueryMsg::GetDelegation {
|
||||
@@ -252,7 +252,7 @@ pub trait VestingQueryClient {
|
||||
async fn get_total_delegation_amount(
|
||||
&self,
|
||||
address: &str,
|
||||
mix_id: MixId,
|
||||
mix_id: NodeId,
|
||||
) -> Result<Coin, NyxdError> {
|
||||
self.query_vesting_contract(VestingQueryMsg::GetTotalDelegationAmount {
|
||||
address: address.to_string(),
|
||||
@@ -264,7 +264,7 @@ pub trait VestingQueryClient {
|
||||
async fn get_delegation_timestamps(
|
||||
&self,
|
||||
address: &str,
|
||||
mix_id: MixId,
|
||||
mix_id: NodeId,
|
||||
) -> Result<DelegationTimesResponse, NyxdError> {
|
||||
self.query_vesting_contract(VestingQueryMsg::GetDelegationTimes {
|
||||
address: address.to_string(),
|
||||
@@ -275,7 +275,7 @@ pub trait VestingQueryClient {
|
||||
|
||||
async fn get_all_vesting_delegations_paged(
|
||||
&self,
|
||||
start_after: Option<(u32, MixId, u64)>,
|
||||
start_after: Option<(u32, NodeId, u64)>,
|
||||
limit: Option<u32>,
|
||||
) -> Result<AllDelegationsResponse, NyxdError> {
|
||||
self.query_vesting_contract(VestingQueryMsg::GetAllDelegations { start_after, limit })
|
||||
|
||||
+8
-68
@@ -9,10 +9,9 @@ use crate::signing::signer::OfflineSigner;
|
||||
use async_trait::async_trait;
|
||||
use cosmrs::AccountId;
|
||||
use nym_contracts_common::signing::MessageSignature;
|
||||
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_mixnet_contract_common::mixnode::{MixNodeConfigUpdate, NodeCostParams};
|
||||
use nym_mixnet_contract_common::{Gateway, MixNode, NodeId};
|
||||
use nym_vesting_contract_common::messages::ExecuteMsg as VestingExecuteMsg;
|
||||
use nym_vesting_contract_common::{PledgeCap, VestingSpecification};
|
||||
|
||||
@@ -28,7 +27,7 @@ pub trait VestingSigningClient {
|
||||
|
||||
async fn vesting_update_mixnode_cost_params(
|
||||
&self,
|
||||
new_costs: MixNodeCostParams,
|
||||
new_costs: NodeCostParams,
|
||||
fee: Option<Fee>,
|
||||
) -> Result<ExecuteResult, NyxdError> {
|
||||
self.execute_vesting_contract(
|
||||
@@ -124,7 +123,7 @@ pub trait VestingSigningClient {
|
||||
async fn vesting_bond_mixnode(
|
||||
&self,
|
||||
mix_node: MixNode,
|
||||
cost_params: MixNodeCostParams,
|
||||
cost_params: NodeCostParams,
|
||||
owner_signature: MessageSignature,
|
||||
pledge: Coin,
|
||||
fee: Option<Fee>,
|
||||
@@ -204,7 +203,7 @@ pub trait VestingSigningClient {
|
||||
async fn vesting_track_undelegation(
|
||||
&self,
|
||||
address: &str,
|
||||
mix_id: MixId,
|
||||
mix_id: NodeId,
|
||||
amount: Coin,
|
||||
fee: Option<Fee>,
|
||||
) -> Result<ExecuteResult, NyxdError> {
|
||||
@@ -222,7 +221,7 @@ pub trait VestingSigningClient {
|
||||
|
||||
async fn vesting_delegate_to_mixnode(
|
||||
&self,
|
||||
mix_id: MixId,
|
||||
mix_id: NodeId,
|
||||
amount: Coin,
|
||||
on_behalf_of: Option<String>,
|
||||
fee: Option<Fee>,
|
||||
@@ -241,7 +240,7 @@ pub trait VestingSigningClient {
|
||||
|
||||
async fn vesting_undelegate_from_mixnode(
|
||||
&self,
|
||||
mix_id: MixId,
|
||||
mix_id: NodeId,
|
||||
on_behalf_of: Option<String>,
|
||||
fee: Option<Fee>,
|
||||
) -> Result<ExecuteResult, NyxdError> {
|
||||
@@ -301,7 +300,7 @@ pub trait VestingSigningClient {
|
||||
|
||||
async fn vesting_withdraw_delegator_reward(
|
||||
&self,
|
||||
mix_id: MixId,
|
||||
mix_id: NodeId,
|
||||
fee: Option<Fee>,
|
||||
) -> Result<ExecuteResult, NyxdError> {
|
||||
self.execute_vesting_contract(
|
||||
@@ -354,50 +353,6 @@ pub trait VestingSigningClient {
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn vesting_create_family(
|
||||
&self,
|
||||
label: String,
|
||||
fee: Option<Fee>,
|
||||
) -> Result<ExecuteResult, NyxdError> {
|
||||
self.execute_vesting_contract(fee, VestingExecuteMsg::CreateFamily { label }, vec![])
|
||||
.await
|
||||
}
|
||||
|
||||
async fn vesting_join_family(
|
||||
&self,
|
||||
join_permit: MessageSignature,
|
||||
family_head: FamilyHead,
|
||||
fee: Option<Fee>,
|
||||
) -> Result<ExecuteResult, NyxdError> {
|
||||
self.execute_vesting_contract(
|
||||
fee,
|
||||
VestingExecuteMsg::JoinFamily {
|
||||
join_permit,
|
||||
family_head,
|
||||
},
|
||||
vec![],
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn vesting_leave_family(
|
||||
&self,
|
||||
family_head: FamilyHead,
|
||||
fee: Option<Fee>,
|
||||
) -> Result<ExecuteResult, NyxdError> {
|
||||
self.execute_vesting_contract(fee, VestingExecuteMsg::LeaveFamily { family_head }, vec![])
|
||||
.await
|
||||
}
|
||||
|
||||
async fn vesting_kick_family_member(
|
||||
&self,
|
||||
member: String,
|
||||
fee: Option<Fee>,
|
||||
) -> Result<ExecuteResult, NyxdError> {
|
||||
self.execute_vesting_contract(fee, VestingExecuteMsg::KickFamilyMember { member }, vec![])
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
||||
@@ -446,21 +401,6 @@ mod tests {
|
||||
msg: VestingExecuteMsg,
|
||||
) {
|
||||
match msg {
|
||||
VestingExecuteMsg::CreateFamily { label } => {
|
||||
client.vesting_create_family(label, None).ignore()
|
||||
}
|
||||
VestingExecuteMsg::JoinFamily {
|
||||
join_permit,
|
||||
family_head,
|
||||
} => client
|
||||
.vesting_join_family(join_permit, family_head, None)
|
||||
.ignore(),
|
||||
VestingExecuteMsg::LeaveFamily { family_head } => {
|
||||
client.vesting_leave_family(family_head, None).ignore()
|
||||
}
|
||||
VestingExecuteMsg::KickFamilyMember { member } => {
|
||||
client.vesting_kick_family_member(member, None).ignore()
|
||||
}
|
||||
VestingExecuteMsg::TrackReward { amount, address } => client
|
||||
.vesting_track_reward(amount.into(), address, None)
|
||||
.ignore(),
|
||||
|
||||
+47
-14
@@ -5,7 +5,7 @@ use crate::nyxd;
|
||||
use crate::nyxd::coin::Coin;
|
||||
use crate::nyxd::cosmwasm_client::helpers::{create_pagination, next_page_key};
|
||||
use crate::nyxd::cosmwasm_client::types::{
|
||||
Account, CodeDetails, Contract, ContractCodeId, SequenceResponse, SimulateResponse,
|
||||
Account, CodeDetails, Contract, ContractCodeId, Model, SequenceResponse, SimulateResponse,
|
||||
};
|
||||
use crate::nyxd::error::NyxdError;
|
||||
use crate::nyxd::Query;
|
||||
@@ -21,15 +21,14 @@ use cosmrs::proto::cosmos::tx::v1beta1::{
|
||||
SimulateRequest, SimulateResponse as ProtoSimulateResponse,
|
||||
};
|
||||
use cosmrs::proto::cosmwasm::wasm::v1::{
|
||||
QueryCodeRequest, QueryCodeResponse, QueryCodesRequest, QueryCodesResponse,
|
||||
QueryContractHistoryRequest, QueryContractHistoryResponse, QueryContractInfoRequest,
|
||||
QueryContractInfoResponse, QueryContractsByCodeRequest, QueryContractsByCodeResponse,
|
||||
QueryRawContractStateRequest, QueryRawContractStateResponse, QuerySmartContractStateRequest,
|
||||
QuerySmartContractStateResponse,
|
||||
QueryAllContractStateRequest, QueryAllContractStateResponse, QueryCodeRequest,
|
||||
QueryCodeResponse, QueryCodesRequest, QueryCodesResponse, QueryContractHistoryRequest,
|
||||
QueryContractHistoryResponse, QueryContractInfoRequest, QueryContractInfoResponse,
|
||||
QueryContractsByCodeRequest, QueryContractsByCodeResponse, QueryRawContractStateRequest,
|
||||
QueryRawContractStateResponse, QuerySmartContractStateRequest, QuerySmartContractStateResponse,
|
||||
};
|
||||
use cosmrs::tendermint::{block, chain, Hash};
|
||||
use cosmrs::{AccountId, Coin as CosmosCoin, Tx};
|
||||
use log::trace;
|
||||
use prost::Message;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
@@ -68,7 +67,7 @@ pub trait CosmWasmClient: TendermintRpcClient {
|
||||
Res: Message + Default,
|
||||
{
|
||||
if let Some(ref abci_path) = path {
|
||||
trace!("performing query on abci path {abci_path}")
|
||||
tracing::trace!("performing query on abci path {abci_path}")
|
||||
}
|
||||
let mut buf = Vec::with_capacity(req.encoded_len());
|
||||
req.encode(&mut buf)?;
|
||||
@@ -218,17 +217,19 @@ pub trait CosmWasmClient: TendermintRpcClient {
|
||||
|
||||
loop {
|
||||
let mut res = self
|
||||
.tx_search(query.clone(), false, page, 100, Order::Ascending)
|
||||
.tx_search(query.clone(), false, page, per_page, Order::Ascending)
|
||||
.await?;
|
||||
|
||||
results.append(&mut res.txs);
|
||||
// sanity check for if tendermint's maximum per_page was modified -
|
||||
// we don't want to accidentally be stuck in an infinite loop
|
||||
if res.total_count == 0 || res.txs.is_empty() {
|
||||
let early_break = res.total_count == 0 || res.txs.is_empty();
|
||||
results.append(&mut res.txs);
|
||||
|
||||
if early_break {
|
||||
break;
|
||||
}
|
||||
|
||||
if res.total_count >= per_page {
|
||||
if res.total_count > results.len() as u32 {
|
||||
page += 1
|
||||
} else {
|
||||
break;
|
||||
@@ -295,7 +296,7 @@ pub trait CosmWasmClient: TendermintRpcClient {
|
||||
|
||||
let start = Instant::now();
|
||||
loop {
|
||||
log::debug!(
|
||||
tracing::debug!(
|
||||
"Polling for result of including {} in a block...",
|
||||
broadcasted.hash
|
||||
);
|
||||
@@ -442,6 +443,38 @@ pub trait CosmWasmClient: TendermintRpcClient {
|
||||
.collect::<Result<_, _>>()?)
|
||||
}
|
||||
|
||||
async fn query_all_contract_state(&self, address: &AccountId) -> Result<Vec<Model>, NyxdError> {
|
||||
let path = Some("/cosmwasm.wasm.v1.Query/AllContractState".to_owned());
|
||||
|
||||
let mut models = Vec::new();
|
||||
let mut pagination = None;
|
||||
|
||||
loop {
|
||||
let req = QueryAllContractStateRequest {
|
||||
address: address.to_string(),
|
||||
pagination,
|
||||
};
|
||||
|
||||
let mut res = self
|
||||
.make_abci_query::<_, QueryAllContractStateResponse>(path.clone(), req)
|
||||
.await?;
|
||||
|
||||
let empty_response = res.models.is_empty();
|
||||
models.append(&mut res.models);
|
||||
|
||||
if empty_response {
|
||||
break;
|
||||
}
|
||||
if let Some(next_key) = next_page_key(res.pagination) {
|
||||
pagination = Some(create_pagination(next_key))
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(models.into_iter().map(Into::into).collect())
|
||||
}
|
||||
|
||||
async fn query_contract_raw(
|
||||
&self,
|
||||
address: &AccountId,
|
||||
@@ -488,7 +521,7 @@ pub trait CosmWasmClient: TendermintRpcClient {
|
||||
.make_abci_query::<_, QuerySmartContractStateResponse>(path, req)
|
||||
.await?;
|
||||
|
||||
trace!("raw query response: {}", String::from_utf8_lossy(&res.data));
|
||||
tracing::trace!("raw query response: {}", String::from_utf8_lossy(&res.data));
|
||||
Ok(serde_json::from_slice(&res.data)?)
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -25,12 +25,12 @@ use cosmrs::proto::cosmos::tx::signing::v1beta1::SignMode;
|
||||
use cosmrs::staking::{MsgDelegate, MsgUndelegate};
|
||||
use cosmrs::tx::{self, Msg};
|
||||
use cosmrs::{cosmwasm, AccountId, Any, Tx};
|
||||
use log::debug;
|
||||
use serde::Serialize;
|
||||
use sha2::Digest;
|
||||
use sha2::Sha256;
|
||||
use std::time::SystemTime;
|
||||
use tendermint_rpc::endpoint::broadcast;
|
||||
use tracing::debug;
|
||||
|
||||
fn empty_fee() -> tx::Fee {
|
||||
tx::Fee {
|
||||
|
||||
@@ -7,9 +7,9 @@ use base64::Engine;
|
||||
use cosmrs::abci::TxMsgData;
|
||||
use cosmrs::cosmwasm::MsgExecuteContractResponse;
|
||||
use cosmrs::proto::cosmos::base::query::v1beta1::{PageRequest, PageResponse};
|
||||
use log::error;
|
||||
use prost::bytes::Bytes;
|
||||
use tendermint_rpc::endpoint::broadcast;
|
||||
use tracing::error;
|
||||
|
||||
pub use cosmrs::abci::MsgResponse;
|
||||
|
||||
|
||||
@@ -27,13 +27,34 @@ use cosmrs::vesting::{
|
||||
};
|
||||
use cosmrs::{AccountId, Any, Coin as CosmosCoin};
|
||||
use prost::Message;
|
||||
use serde::Serialize;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
pub use cosmrs::abci::GasInfo;
|
||||
pub use cosmrs::abci::MsgResponse;
|
||||
|
||||
pub type ContractCodeId = u64;
|
||||
|
||||
// yet another thing to put in cosmrs
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct Model {
|
||||
#[serde(with = "nym_serde_helpers::hex")]
|
||||
pub key: Vec<u8>,
|
||||
|
||||
#[serde(with = "nym_serde_helpers::base64")]
|
||||
pub value: Vec<u8>,
|
||||
}
|
||||
|
||||
// follow the cosmwasm serialisation format, i.e. hex for key and base64 for value
|
||||
|
||||
impl From<cosmrs::proto::cosmwasm::wasm::v1::Model> for Model {
|
||||
fn from(model: cosmrs::proto::cosmwasm::wasm::v1::Model) -> Self {
|
||||
Model {
|
||||
key: model.key,
|
||||
value: model.value,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct EmptyMsg {}
|
||||
|
||||
|
||||
@@ -154,6 +154,23 @@ pub enum NyxdError {
|
||||
|
||||
#[error("the response data has invalid size. got {got} bytes, but expected {expected} bytes instead")]
|
||||
MalformedResponseData { got: usize, expected: usize },
|
||||
|
||||
#[error(
|
||||
"one of the extension query for {contract} failed with the following message: {message}"
|
||||
)]
|
||||
ExtensionQueryFailure { contract: String, message: String },
|
||||
}
|
||||
|
||||
impl NyxdError {
|
||||
pub fn extension_query_failure(
|
||||
contract: impl Into<String>,
|
||||
message: impl Into<String>,
|
||||
) -> Self {
|
||||
NyxdError::ExtensionQueryFailure {
|
||||
contract: contract.into(),
|
||||
message: message.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The purpose of parsing the abci query result is that we want to generate the `pretty_log` if
|
||||
|
||||
@@ -9,10 +9,15 @@ use comfy_table::Table;
|
||||
use nym_credential_storage::initialise_persistent_storage;
|
||||
use nym_credential_storage::storage::Storage;
|
||||
use nym_credentials::ecash::bandwidth::serialiser::VersionedSerialise;
|
||||
use nym_credentials_interface::TicketType;
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct Args {
|
||||
/// Specify which type of ticketbook
|
||||
#[clap(long, default_value_t = TicketType::V1MixnetEntry)]
|
||||
pub(crate) ticketbook_type: TicketType,
|
||||
|
||||
/// Specify the index of the ticket to retrieve from the ticketbook.
|
||||
/// By default, the current unspent value is used.
|
||||
#[clap(long, group = "output")]
|
||||
@@ -62,7 +67,7 @@ pub async fn execute(args: Args) -> anyhow::Result<()> {
|
||||
|
||||
let persistent_storage = initialise_persistent_storage(&credentials_store).await;
|
||||
let Some(mut next_ticketbook) = persistent_storage
|
||||
.get_next_unspent_usable_ticketbook(0)
|
||||
.get_next_unspent_usable_ticketbook(args.ticketbook_type.to_string(), 0)
|
||||
.await?
|
||||
else {
|
||||
bail!(
|
||||
|
||||
@@ -107,7 +107,7 @@ async fn issue_to_file(args: Args, client: SigningClient) -> anyhow::Result<()>
|
||||
utils::issue_credential(&client, &credentials_store, &secret, args.ticketbook_type).await?;
|
||||
|
||||
let ticketbook = credentials_store
|
||||
.get_next_unspent_usable_ticketbook(0)
|
||||
.get_next_unspent_usable_ticketbook(args.ticketbook_type.to_string(), 0)
|
||||
.await?
|
||||
.ok_or(anyhow!("we just issued a ticketbook, it must be present!"))?
|
||||
.ticketbook;
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
use clap::Parser;
|
||||
use cosmwasm_std::Decimal;
|
||||
use log::{debug, info};
|
||||
use nym_mixnet_contract_common::reward_params::RewardedSetParams;
|
||||
use nym_mixnet_contract_common::{
|
||||
InitialRewardingParams, InstantiateMsg, OperatingCostRange, Percent, ProfitMarginRange,
|
||||
};
|
||||
@@ -56,11 +57,17 @@ pub struct Args {
|
||||
#[clap(long, default_value_t = 2)]
|
||||
pub interval_pool_emission: u64,
|
||||
|
||||
#[clap(long, default_value_t = 240)]
|
||||
pub rewarded_set_size: u32,
|
||||
#[clap(long, default_value_t = 50)]
|
||||
pub(crate) entry_gateways: u32,
|
||||
|
||||
#[clap(long, default_value_t = 240)]
|
||||
pub active_set_size: u32,
|
||||
#[clap(long, default_value_t = 70)]
|
||||
pub(crate) exit_gateways: u32,
|
||||
|
||||
#[clap(long, default_value_t = 120)]
|
||||
pub(crate) mixnodes: u32,
|
||||
|
||||
#[clap(long, default_value_t = 0)]
|
||||
pub(crate) standby: u32,
|
||||
|
||||
#[clap(long, default_value_t = Percent::zero())]
|
||||
pub minimum_profit_margin_percent: Percent,
|
||||
@@ -95,8 +102,13 @@ pub async fn generate(args: Args) {
|
||||
.expect("active_set_work_factor can't be converted to Decimal"),
|
||||
interval_pool_emission: Percent::from_percentage_value(args.interval_pool_emission)
|
||||
.expect("interval_pool_emission can't be converted to Percent"),
|
||||
rewarded_set_size: args.rewarded_set_size,
|
||||
active_set_size: args.active_set_size,
|
||||
|
||||
rewarded_set_params: RewardedSetParams {
|
||||
entry_gateways: args.entry_gateways,
|
||||
exit_gateways: args.exit_gateways,
|
||||
mixnodes: args.mixnodes,
|
||||
standby: args.standby,
|
||||
},
|
||||
};
|
||||
|
||||
debug!("initial_rewarding_params: {:?}", initial_rewarding_params);
|
||||
|
||||
@@ -7,13 +7,14 @@ pub mod execute_contract;
|
||||
pub mod generators;
|
||||
pub mod init_contract;
|
||||
pub mod migrate_contract;
|
||||
pub mod raw_contract_state;
|
||||
pub mod upload_contract;
|
||||
|
||||
#[derive(Debug, Args)]
|
||||
#[clap(args_conflicts_with_subcommands = true, subcommand_required = true)]
|
||||
pub struct Cosmwasm {
|
||||
#[clap(subcommand)]
|
||||
pub command: Option<CosmwasmCommands>,
|
||||
pub command: CosmwasmCommands,
|
||||
}
|
||||
|
||||
#[derive(Debug, Subcommand)]
|
||||
@@ -28,4 +29,6 @@ pub enum CosmwasmCommands {
|
||||
Migrate(crate::validator::cosmwasm::migrate_contract::Args),
|
||||
/// Execute a WASM smart contract method
|
||||
Execute(crate::validator::cosmwasm::execute_contract::Args),
|
||||
/// Obtain raw contract state of a cosmwasm smart contract
|
||||
RawContractState(crate::validator::cosmwasm::raw_contract_state::Args),
|
||||
}
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::context::QueryClient;
|
||||
use clap::Parser;
|
||||
use cosmrs::AccountId;
|
||||
use log::trace;
|
||||
use nym_validator_client::nyxd::CosmWasmClient;
|
||||
use std::fs;
|
||||
use std::fs::File;
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct Args {
|
||||
#[clap(long, value_parser)]
|
||||
#[clap(help = "The address of contract to get the state of")]
|
||||
pub contract: AccountId,
|
||||
|
||||
#[clap(short, long)]
|
||||
#[clap(help = "Output file for the retrieved contract state")]
|
||||
pub output: PathBuf,
|
||||
}
|
||||
|
||||
pub async fn execute(args: Args, client: QueryClient) -> anyhow::Result<()> {
|
||||
trace!("args: {args:?}");
|
||||
|
||||
let output = File::create(&args.output)?;
|
||||
let raw = client.query_all_contract_state(&args.contract).await?;
|
||||
|
||||
serde_json::to_writer(output, &raw)?;
|
||||
println!(
|
||||
"wrote {} key-value from {} pairs into '{}'",
|
||||
raw.len(),
|
||||
args.contract,
|
||||
fs::canonicalize(args.output)?.display()
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -4,13 +4,13 @@
|
||||
use crate::context::SigningClient;
|
||||
use clap::Parser;
|
||||
use log::info;
|
||||
use nym_mixnet_contract_common::{Coin, MixId};
|
||||
use nym_mixnet_contract_common::{Coin, NodeId};
|
||||
use nym_validator_client::nyxd::contract_traits::{MixnetQueryClient, MixnetSigningClient};
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct Args {
|
||||
#[clap(long)]
|
||||
pub mix_id: Option<MixId>,
|
||||
pub mix_id: Option<NodeId>,
|
||||
|
||||
#[clap(long)]
|
||||
pub identity_key: Option<String>,
|
||||
@@ -43,7 +43,7 @@ pub async fn delegate_to_mixnode(args: Args, client: SigningClient) {
|
||||
let coin = Coin::new(args.amount, denom);
|
||||
|
||||
let res = client
|
||||
.delegate_to_mixnode(mix_id, coin.into(), None)
|
||||
.delegate(mix_id, coin.into(), None)
|
||||
.await
|
||||
.expect("failed to delegate to mixnode!");
|
||||
|
||||
|
||||
@@ -1,21 +1,18 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use std::cmp::Ordering;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::fs;
|
||||
use std::fs::OpenOptions;
|
||||
|
||||
use clap::Parser;
|
||||
use comfy_table::Table;
|
||||
use csv::WriterBuilder;
|
||||
use log::info;
|
||||
use nym_mixnet_contract_common::ExecuteMsg;
|
||||
use nym_mixnet_contract_common::ExecuteMsg::{DelegateToMixnode, UndelegateFromMixnode};
|
||||
|
||||
use nym_mixnet_contract_common::PendingEpochEventKind::{Delegate, Undelegate};
|
||||
use nym_mixnet_contract_common::PendingEpochEventKind;
|
||||
use nym_validator_client::nyxd::contract_traits::{NymContractsProvider, PagedMixnetQueryClient};
|
||||
use nym_validator_client::nyxd::Coin;
|
||||
use std::cmp::Ordering;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::fs;
|
||||
use std::fs::OpenOptions;
|
||||
|
||||
use crate::context::SigningClient;
|
||||
use crate::utils::pretty_coin;
|
||||
@@ -40,7 +37,7 @@ pub struct Args {
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct InputFileRow {
|
||||
pub mix_id: String,
|
||||
pub node_id: String,
|
||||
pub amount: Coin,
|
||||
}
|
||||
#[derive(Debug)]
|
||||
@@ -76,7 +73,7 @@ impl InputFileReader {
|
||||
}
|
||||
|
||||
rows.push(InputFileRow {
|
||||
mix_id,
|
||||
node_id: mix_id,
|
||||
amount: Coin {
|
||||
amount: micro_nym_amount,
|
||||
denom: "unym".to_string(),
|
||||
@@ -140,8 +137,10 @@ async fn fetch_delegation_data(
|
||||
let mut pending_delegation_map: HashMap<String, Coin> = HashMap::new();
|
||||
|
||||
for delegation in delegations {
|
||||
existing_delegation_map
|
||||
.insert(delegation.mix_id.to_string(), Coin::from(delegation.amount));
|
||||
existing_delegation_map.insert(
|
||||
delegation.node_id.to_string(),
|
||||
Coin::from(delegation.amount),
|
||||
);
|
||||
}
|
||||
|
||||
// Look for pending delegate / undelegate events which might be of interest to us
|
||||
@@ -155,27 +154,27 @@ async fn fetch_delegation_data(
|
||||
for event in pending_events {
|
||||
match event.event.kind {
|
||||
// If a pending undelegate tx is found, remove it from delegation map
|
||||
Undelegate { owner, mix_id, .. } => {
|
||||
PendingEpochEventKind::Undelegate { owner, node_id, .. } => {
|
||||
if owner == address.as_ref()
|
||||
&& existing_delegation_map.contains_key(&mix_id.to_string())
|
||||
&& existing_delegation_map.contains_key(&node_id.to_string())
|
||||
{
|
||||
existing_delegation_map.remove(&mix_id.to_string());
|
||||
existing_delegation_map.remove(&node_id.to_string());
|
||||
}
|
||||
}
|
||||
|
||||
// If a pending delegation event is found, gather them to consolidate later
|
||||
Delegate {
|
||||
PendingEpochEventKind::Delegate {
|
||||
owner,
|
||||
mix_id,
|
||||
node_id,
|
||||
amount,
|
||||
..
|
||||
} => {
|
||||
if owner == address.as_ref() {
|
||||
let mut amount = Coin::from(amount);
|
||||
if let Some(pending_record) = pending_delegation_map.get(&mix_id.to_string()) {
|
||||
if let Some(pending_record) = pending_delegation_map.get(&node_id.to_string()) {
|
||||
amount.amount += pending_record.amount;
|
||||
}
|
||||
pending_delegation_map.insert(mix_id.to_string(), amount);
|
||||
pending_delegation_map.insert(node_id.to_string(), amount);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
@@ -217,7 +216,7 @@ pub async fn delegate_to_multiple_mixnodes(args: Args, client: SigningClient) {
|
||||
for row in &records.rows {
|
||||
let input_amount = row.amount.amount;
|
||||
let existing_delegation_amount = existing_delegation_map
|
||||
.get(&row.mix_id)
|
||||
.get(&row.node_id)
|
||||
.map_or(0, |coin| coin.amount);
|
||||
|
||||
match existing_delegation_amount.cmp(&input_amount) {
|
||||
@@ -229,25 +228,26 @@ pub async fn delegate_to_multiple_mixnodes(args: Args, client: SigningClient) {
|
||||
amount: input_amount - existing_delegation_amount,
|
||||
denom: row.amount.denom.clone(),
|
||||
};
|
||||
let mix_id = row.mix_id.clone().parse::<u32>().unwrap();
|
||||
delegation_msgs.push((DelegateToMixnode { mix_id }, vec![difference.clone()]));
|
||||
let node_id = row.node_id.clone().parse::<u32>().unwrap();
|
||||
delegation_msgs.push((ExecuteMsg::Delegate { node_id }, vec![difference.clone()]));
|
||||
delegation_table.add_row(&[
|
||||
row.mix_id.clone(),
|
||||
row.node_id.clone(),
|
||||
pretty_coin(&row.amount),
|
||||
pretty_coin(&difference),
|
||||
]);
|
||||
}
|
||||
|
||||
Ordering::Greater => {
|
||||
let mix_id = row.mix_id.clone().parse::<u32>().unwrap();
|
||||
let node_id = row.node_id.clone().parse::<u32>().unwrap();
|
||||
let coins: Vec<Coin> = vec![];
|
||||
undelegation_msgs.push((UndelegateFromMixnode { mix_id }, coins));
|
||||
undelegation_table.add_row(&[row.mix_id.clone()]);
|
||||
undelegation_msgs.push((ExecuteMsg::Undelegate { node_id }, coins));
|
||||
undelegation_table.add_row(&[row.node_id.clone()]);
|
||||
|
||||
if row.amount.amount > 0 {
|
||||
delegation_msgs.push((DelegateToMixnode { mix_id }, vec![row.amount.clone()]));
|
||||
delegation_msgs
|
||||
.push((ExecuteMsg::Delegate { node_id }, vec![row.amount.clone()]));
|
||||
delegation_table.add_row(&[
|
||||
row.mix_id.clone(),
|
||||
row.node_id.clone(),
|
||||
pretty_coin(&row.amount),
|
||||
pretty_coin(&row.amount),
|
||||
]);
|
||||
|
||||
@@ -4,13 +4,13 @@
|
||||
use crate::context::SigningClient;
|
||||
use clap::Parser;
|
||||
use log::info;
|
||||
use nym_mixnet_contract_common::MixId;
|
||||
use nym_mixnet_contract_common::NodeId;
|
||||
use nym_validator_client::nyxd::contract_traits::{MixnetQueryClient, MixnetSigningClient};
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct Args {
|
||||
#[clap(long)]
|
||||
pub mix_id: Option<MixId>,
|
||||
pub mix_id: Option<NodeId>,
|
||||
|
||||
#[clap(long)]
|
||||
pub identity_key: Option<String>,
|
||||
|
||||
@@ -66,7 +66,7 @@ async fn print_delegations(delegations: Vec<Delegation>, client: &SigningClientW
|
||||
for delegation in delegations {
|
||||
table.add_row(vec![
|
||||
to_iso_timestamp(delegation.height as u32, client).await,
|
||||
delegation.mix_id.to_string(),
|
||||
delegation.node_id.to_string(),
|
||||
pretty_cosmwasm_coin(&delegation.amount),
|
||||
delegation
|
||||
.proxy
|
||||
@@ -93,7 +93,7 @@ async fn print_delegation_events(events: Vec<PendingEpochEvent>, client: &Signin
|
||||
match event.event.kind {
|
||||
PendingEpochEventKind::Delegate {
|
||||
owner,
|
||||
mix_id,
|
||||
node_id: mix_id,
|
||||
amount,
|
||||
proxy,
|
||||
..
|
||||
@@ -110,7 +110,7 @@ async fn print_delegation_events(events: Vec<PendingEpochEvent>, client: &Signin
|
||||
}
|
||||
PendingEpochEventKind::Undelegate {
|
||||
owner,
|
||||
mix_id,
|
||||
node_id: mix_id,
|
||||
proxy,
|
||||
..
|
||||
} => {
|
||||
|
||||
@@ -4,13 +4,13 @@
|
||||
use crate::context::SigningClient;
|
||||
use clap::Parser;
|
||||
use log::info;
|
||||
use nym_mixnet_contract_common::MixId;
|
||||
use nym_mixnet_contract_common::NodeId;
|
||||
use nym_validator_client::nyxd::contract_traits::{MixnetQueryClient, MixnetSigningClient};
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct Args {
|
||||
#[clap(long)]
|
||||
pub mix_id: Option<MixId>,
|
||||
pub mix_id: Option<NodeId>,
|
||||
|
||||
#[clap(long)]
|
||||
pub identity_key: Option<String>,
|
||||
|
||||
+2
-2
@@ -4,13 +4,13 @@
|
||||
use crate::context::SigningClient;
|
||||
use clap::Parser;
|
||||
use log::info;
|
||||
use nym_mixnet_contract_common::MixId;
|
||||
use nym_mixnet_contract_common::NodeId;
|
||||
use nym_validator_client::nyxd::contract_traits::{MixnetQueryClient, MixnetSigningClient};
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct Args {
|
||||
#[clap(long)]
|
||||
pub mix_id: Option<MixId>,
|
||||
pub mix_id: Option<NodeId>,
|
||||
|
||||
#[clap(long)]
|
||||
pub identity_key: Option<String>,
|
||||
|
||||
@@ -4,13 +4,13 @@
|
||||
use crate::context::SigningClient;
|
||||
use clap::Parser;
|
||||
use log::info;
|
||||
use nym_mixnet_contract_common::MixId;
|
||||
use nym_mixnet_contract_common::NodeId;
|
||||
use nym_validator_client::nyxd::contract_traits::{MixnetQueryClient, MixnetSigningClient};
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct Args {
|
||||
#[clap(long)]
|
||||
pub mix_id: Option<MixId>,
|
||||
pub mix_id: Option<NodeId>,
|
||||
|
||||
#[clap(long)]
|
||||
pub identity_key: Option<String>,
|
||||
@@ -36,7 +36,7 @@ pub async fn undelegate_from_mixnode(args: Args, client: SigningClient) {
|
||||
};
|
||||
|
||||
let res = client
|
||||
.undelegate_from_mixnode(mix_id, None)
|
||||
.undelegate(mix_id, None)
|
||||
.await
|
||||
.expect("failed to remove stake from mixnode!");
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
use clap::Parser;
|
||||
use log::info;
|
||||
|
||||
use nym_mixnet_contract_common::{Coin, MixId};
|
||||
use nym_mixnet_contract_common::{Coin, NodeId};
|
||||
use nym_validator_client::nyxd::contract_traits::MixnetQueryClient;
|
||||
use nym_validator_client::nyxd::contract_traits::VestingSigningClient;
|
||||
|
||||
@@ -13,7 +13,7 @@ use crate::context::SigningClient;
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct Args {
|
||||
#[clap(long)]
|
||||
pub mix_id: Option<MixId>,
|
||||
pub mix_id: Option<NodeId>,
|
||||
|
||||
#[clap(long)]
|
||||
pub identity_key: Option<String>,
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
use clap::Parser;
|
||||
use log::info;
|
||||
use nym_mixnet_contract_common::MixId;
|
||||
use nym_mixnet_contract_common::NodeId;
|
||||
use nym_validator_client::nyxd::contract_traits::MixnetQueryClient;
|
||||
use nym_validator_client::nyxd::contract_traits::VestingSigningClient;
|
||||
|
||||
@@ -12,7 +12,7 @@ use crate::context::SigningClient;
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct Args {
|
||||
#[clap(long)]
|
||||
pub mix_id: Option<MixId>,
|
||||
pub mix_id: Option<NodeId>,
|
||||
|
||||
#[clap(long)]
|
||||
pub identity_key: Option<String>,
|
||||
|
||||
@@ -5,6 +5,7 @@ use clap::{Args, Subcommand};
|
||||
|
||||
pub mod bond_gateway;
|
||||
pub mod gateway_bonding_sign_payload;
|
||||
pub mod nymnode_migration;
|
||||
pub mod settings;
|
||||
pub mod unbond_gateway;
|
||||
pub mod vesting_bond_gateway;
|
||||
@@ -31,4 +32,6 @@ pub enum MixnetOperatorsGatewayCommands {
|
||||
VestingUnbond(vesting_unbond_gateway::Args),
|
||||
/// Create base58-encoded payload required for producing valid bonding signature.
|
||||
CreateGatewayBondingSignPayload(gateway_bonding_sign_payload::Args),
|
||||
/// Migrate the gateway into a Nym Node
|
||||
MigrateToNymnode(nymnode_migration::Args),
|
||||
}
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::context::SigningClient;
|
||||
use clap::Parser;
|
||||
use cosmwasm_std::Uint128;
|
||||
use log::info;
|
||||
use nym_contracts_common::Percent;
|
||||
use nym_mixnet_contract_common::{
|
||||
NodeCostParams, DEFAULT_INTERVAL_OPERATING_COST_AMOUNT, DEFAULT_PROFIT_MARGIN_PERCENT,
|
||||
};
|
||||
use nym_validator_client::nyxd::contract_traits::MixnetSigningClient;
|
||||
use nym_validator_client::nyxd::CosmWasmCoin;
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct Args {
|
||||
#[clap(long)]
|
||||
pub profit_margin_percent: Option<u64>,
|
||||
|
||||
#[clap(
|
||||
long,
|
||||
help = "operating cost in current DENOMINATION (so it would be 'unym', rather than 'nym')"
|
||||
)]
|
||||
pub interval_operating_cost: Option<u128>,
|
||||
}
|
||||
|
||||
pub async fn migrate_to_nymnode(args: Args, client: SigningClient) {
|
||||
let denom = client.current_chain_details().mix_denom.base.as_str();
|
||||
|
||||
let cost_params =
|
||||
if args.profit_margin_percent.is_some() || args.interval_operating_cost.is_some() {
|
||||
Some(NodeCostParams {
|
||||
profit_margin_percent: Percent::from_percentage_value(
|
||||
args.profit_margin_percent
|
||||
.unwrap_or(DEFAULT_PROFIT_MARGIN_PERCENT),
|
||||
)
|
||||
.unwrap(),
|
||||
interval_operating_cost: CosmWasmCoin {
|
||||
denom: denom.into(),
|
||||
amount: Uint128::new(
|
||||
args.interval_operating_cost
|
||||
.unwrap_or(DEFAULT_INTERVAL_OPERATING_COST_AMOUNT),
|
||||
),
|
||||
},
|
||||
})
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let res = client
|
||||
.migrate_legacy_gateway(cost_params, None)
|
||||
.await
|
||||
.expect("failed to migrate gateway!");
|
||||
|
||||
info!("migration result: {:?}", res)
|
||||
}
|
||||
@@ -1,20 +1,21 @@
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::context::SigningClient;
|
||||
use clap::Parser;
|
||||
use cosmwasm_std::Uint128;
|
||||
use log::{info, warn};
|
||||
|
||||
use nym_contracts_common::signing::MessageSignature;
|
||||
use nym_mixnet_contract_common::{Coin, MixNodeCostParams, Percent};
|
||||
use nym_mixnet_contract_common::{
|
||||
Coin, NodeCostParams, Percent, DEFAULT_INTERVAL_OPERATING_COST_AMOUNT,
|
||||
DEFAULT_PROFIT_MARGIN_PERCENT,
|
||||
};
|
||||
use nym_network_defaults::{
|
||||
DEFAULT_HTTP_API_LISTENING_PORT, DEFAULT_MIX_LISTENING_PORT, DEFAULT_VERLOC_LISTENING_PORT,
|
||||
};
|
||||
use nym_validator_client::nyxd::contract_traits::MixnetSigningClient;
|
||||
use nym_validator_client::nyxd::CosmWasmCoin;
|
||||
|
||||
use crate::context::SigningClient;
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct Args {
|
||||
#[clap(long)]
|
||||
@@ -42,7 +43,7 @@ pub struct Args {
|
||||
pub version: String,
|
||||
|
||||
#[clap(long)]
|
||||
pub profit_margin_percent: Option<u8>,
|
||||
pub profit_margin_percent: Option<u64>,
|
||||
|
||||
#[clap(
|
||||
long,
|
||||
@@ -85,14 +86,18 @@ pub async fn bond_mixnode(args: Args, client: SigningClient) {
|
||||
|
||||
let coin = Coin::new(args.amount, denom);
|
||||
|
||||
let cost_params = MixNodeCostParams {
|
||||
let cost_params = NodeCostParams {
|
||||
profit_margin_percent: Percent::from_percentage_value(
|
||||
args.profit_margin_percent.unwrap_or(10) as u64,
|
||||
args.profit_margin_percent
|
||||
.unwrap_or(DEFAULT_PROFIT_MARGIN_PERCENT),
|
||||
)
|
||||
.unwrap(),
|
||||
interval_operating_cost: CosmWasmCoin {
|
||||
denom: denom.into(),
|
||||
amount: Uint128::new(args.interval_operating_cost.unwrap_or(40_000_000)),
|
||||
amount: Uint128::new(
|
||||
args.interval_operating_cost
|
||||
.unwrap_or(DEFAULT_INTERVAL_OPERATING_COST_AMOUNT),
|
||||
),
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::context::SigningClient;
|
||||
use clap::Parser;
|
||||
use log::info;
|
||||
use nym_validator_client::nyxd::contract_traits::MixnetSigningClient;
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct Args {
|
||||
/// Label that is going to be used for creating the family
|
||||
#[arg(long)]
|
||||
pub family_label: String,
|
||||
}
|
||||
|
||||
pub async fn create_family(args: Args, client: SigningClient) {
|
||||
info!("Create family");
|
||||
|
||||
let res = client
|
||||
.create_family(args.family_label, None)
|
||||
.await
|
||||
.expect("failed to create family");
|
||||
|
||||
info!("Family creation result: {:?}", res);
|
||||
}
|
||||
-72
@@ -1,72 +0,0 @@
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::context::QueryClient;
|
||||
use crate::utils::DataWrapper;
|
||||
use clap::Parser;
|
||||
use cosmrs::AccountId;
|
||||
use log::info;
|
||||
use nym_bin_common::output_format::OutputFormat;
|
||||
use nym_crypto::asymmetric::identity;
|
||||
use nym_mixnet_contract_common::construct_family_join_permit;
|
||||
use nym_mixnet_contract_common::families::FamilyHead;
|
||||
use nym_validator_client::nyxd::contract_traits::MixnetQueryClient;
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct Args {
|
||||
/// Account address (i.e. owner of the family head) which will be used for issuing the permit
|
||||
#[arg(long)]
|
||||
pub address: AccountId,
|
||||
|
||||
// might as well validate the value when parsing the arguments
|
||||
/// Identity of the member for whom we're issuing the permit
|
||||
#[arg(long)]
|
||||
pub member: identity::PublicKey,
|
||||
|
||||
#[clap(short, long, default_value_t = OutputFormat::default())]
|
||||
output: OutputFormat,
|
||||
}
|
||||
|
||||
pub async fn create_family_join_permit_sign_payload(args: Args, client: QueryClient) {
|
||||
info!("Create family join permit sign payload");
|
||||
|
||||
// get the address of our mixnode to recover the family head information
|
||||
let Some(mixnode) = client
|
||||
.get_owned_mixnode(&args.address)
|
||||
.await
|
||||
.unwrap()
|
||||
.mixnode_details
|
||||
else {
|
||||
eprintln!("{} does not seem to even own a mixnode!", args.address);
|
||||
return;
|
||||
};
|
||||
|
||||
// make sure this mixnode is actually a family head
|
||||
if client
|
||||
.get_node_family_by_head(mixnode.bond_information.identity().to_string())
|
||||
.await
|
||||
.unwrap()
|
||||
.family
|
||||
.is_none()
|
||||
{
|
||||
eprintln!("{} does not even seem to own a family!", args.address);
|
||||
return;
|
||||
}
|
||||
|
||||
let nonce = match client.get_signing_nonce(&args.address).await {
|
||||
Ok(nonce) => nonce,
|
||||
Err(err) => {
|
||||
eprint!(
|
||||
"failed to query for the signing nonce of {}: {err}",
|
||||
args.address
|
||||
);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
let head = FamilyHead::new(mixnode.bond_information.identity());
|
||||
|
||||
let payload = construct_family_join_permit(nonce, head, args.member.to_base58_string());
|
||||
let wrapper = DataWrapper::new(payload.to_base58_string().unwrap());
|
||||
println!("{}", args.output.format(&wrapper))
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::context::SigningClient;
|
||||
use clap::Parser;
|
||||
use log::info;
|
||||
use nym_contracts_common::signing::MessageSignature;
|
||||
use nym_crypto::asymmetric::identity;
|
||||
use nym_mixnet_contract_common::families::FamilyHead;
|
||||
use nym_validator_client::nyxd::contract_traits::MixnetSigningClient;
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct Args {
|
||||
/// The head of the family that we intend to join
|
||||
#[arg(long)]
|
||||
pub family_head: identity::PublicKey,
|
||||
|
||||
/// Permission, as provided by the family head, for joining the family
|
||||
#[arg(long)]
|
||||
pub join_permit: MessageSignature,
|
||||
}
|
||||
|
||||
pub async fn join_family(args: Args, client: SigningClient) {
|
||||
info!("Join family");
|
||||
|
||||
let family_head = FamilyHead::new(args.family_head.to_base58_string());
|
||||
|
||||
let res = client
|
||||
.join_family(args.join_permit, family_head, None)
|
||||
.await
|
||||
.expect("failed to join family");
|
||||
|
||||
info!("Family join result: {:?}", res);
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::context::SigningClient;
|
||||
use clap::Parser;
|
||||
use log::info;
|
||||
use nym_crypto::asymmetric::identity;
|
||||
use nym_validator_client::nyxd::contract_traits::MixnetSigningClient;
|
||||
use nym_validator_client::nyxd::contract_traits::VestingSigningClient;
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct Args {
|
||||
/// The member of the family that we intend to kick
|
||||
#[arg(long)]
|
||||
pub member: identity::PublicKey,
|
||||
|
||||
/// Indicates whether the family was created (and managed) via the vesting contract
|
||||
#[arg(long)]
|
||||
pub with_vesting_account: bool,
|
||||
}
|
||||
|
||||
pub async fn kick_family_member(args: Args, client: SigningClient) {
|
||||
info!("Leave family");
|
||||
|
||||
let member = args.member.to_base58_string();
|
||||
|
||||
let res = if args.with_vesting_account {
|
||||
client
|
||||
.vesting_kick_family_member(member, None)
|
||||
.await
|
||||
.expect("failed to kick family member with vesting account")
|
||||
} else {
|
||||
client
|
||||
.kick_family_member(member, None)
|
||||
.await
|
||||
.expect("failed to kick family member")
|
||||
};
|
||||
|
||||
info!("Family leave result: {:?}", res);
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::context::SigningClient;
|
||||
use clap::Parser;
|
||||
use log::info;
|
||||
use nym_crypto::asymmetric::identity;
|
||||
use nym_mixnet_contract_common::families::FamilyHead;
|
||||
use nym_validator_client::nyxd::contract_traits::MixnetSigningClient;
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct Args {
|
||||
/// The head of the family that we intend to leave
|
||||
#[arg(long)]
|
||||
pub family_head: identity::PublicKey,
|
||||
}
|
||||
|
||||
pub async fn leave_family(args: Args, client: SigningClient) {
|
||||
info!("Leave family");
|
||||
|
||||
let family_head = FamilyHead::new(args.family_head.to_base58_string());
|
||||
|
||||
let res = client
|
||||
.leave_family(family_head, None)
|
||||
.await
|
||||
.expect("failed to leave family");
|
||||
|
||||
info!("Family leave result: {:?}", res);
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use clap::{Args, Subcommand};
|
||||
|
||||
pub mod create_family;
|
||||
pub mod create_family_join_permit_sign_payload;
|
||||
pub mod join_family;
|
||||
pub mod kick_family_member;
|
||||
pub mod leave_family;
|
||||
|
||||
#[derive(Debug, Args)]
|
||||
#[clap(args_conflicts_with_subcommands = true, subcommand_required = true)]
|
||||
pub struct MixnetOperatorsMixnodeFamilies {
|
||||
#[clap(subcommand)]
|
||||
pub command: MixnetOperatorsMixnodeFamiliesCommands,
|
||||
}
|
||||
|
||||
#[derive(Debug, Subcommand)]
|
||||
pub enum MixnetOperatorsMixnodeFamiliesCommands {
|
||||
/// Create family
|
||||
CreateFamily(create_family::Args),
|
||||
|
||||
/// Join family
|
||||
JoinFamily(join_family::Args),
|
||||
|
||||
/// Leave family,
|
||||
LeaveFamily(leave_family::Args),
|
||||
|
||||
/// Kick family member
|
||||
KickFamilyMember(kick_family_member::Args),
|
||||
|
||||
/// Create a message payload that is required to get signed in order to obtain a permit for joining family
|
||||
CreateFamilyJoinPermitSignPayload(create_family_join_permit_sign_payload::Args),
|
||||
}
|
||||
+10
-5
@@ -8,7 +8,8 @@ use cosmwasm_std::{Coin, Uint128};
|
||||
use nym_bin_common::output_format::OutputFormat;
|
||||
use nym_contracts_common::Percent;
|
||||
use nym_mixnet_contract_common::{
|
||||
construct_legacy_mixnode_bonding_sign_payload, MixNodeCostParams,
|
||||
construct_legacy_mixnode_bonding_sign_payload, NodeCostParams,
|
||||
DEFAULT_INTERVAL_OPERATING_COST_AMOUNT, DEFAULT_PROFIT_MARGIN_PERCENT,
|
||||
};
|
||||
use nym_network_defaults::{
|
||||
DEFAULT_HTTP_API_LISTENING_PORT, DEFAULT_MIX_LISTENING_PORT, DEFAULT_VERLOC_LISTENING_PORT,
|
||||
@@ -40,7 +41,7 @@ pub struct Args {
|
||||
pub version: String,
|
||||
|
||||
#[clap(long)]
|
||||
pub profit_margin_percent: Option<u8>,
|
||||
pub profit_margin_percent: Option<u64>,
|
||||
|
||||
#[clap(
|
||||
long,
|
||||
@@ -75,14 +76,18 @@ pub async fn create_payload(args: Args, client: SigningClient) {
|
||||
|
||||
let coin = Coin::new(args.amount, denom);
|
||||
|
||||
let cost_params = MixNodeCostParams {
|
||||
let cost_params = NodeCostParams {
|
||||
profit_margin_percent: Percent::from_percentage_value(
|
||||
args.profit_margin_percent.unwrap_or(10) as u64,
|
||||
args.profit_margin_percent
|
||||
.unwrap_or(DEFAULT_PROFIT_MARGIN_PERCENT),
|
||||
)
|
||||
.unwrap(),
|
||||
interval_operating_cost: CosmWasmCoin {
|
||||
denom: denom.into(),
|
||||
amount: Uint128::new(args.interval_operating_cost.unwrap_or(40_000_000)),
|
||||
amount: Uint128::new(
|
||||
args.interval_operating_cost
|
||||
.unwrap_or(DEFAULT_INTERVAL_OPERATING_COST_AMOUNT),
|
||||
),
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -5,10 +5,10 @@ use clap::{Args, Subcommand};
|
||||
|
||||
pub mod bond_mixnode;
|
||||
pub mod decrease_pledge;
|
||||
pub mod families;
|
||||
pub mod keys;
|
||||
pub mod migrate_vested_mixnode;
|
||||
pub mod mixnode_bonding_sign_payload;
|
||||
pub mod nymnode_migration;
|
||||
pub mod pledge_more;
|
||||
pub mod rewards;
|
||||
pub mod settings;
|
||||
@@ -33,8 +33,6 @@ pub enum MixnetOperatorsMixnodeCommands {
|
||||
Rewards(rewards::MixnetOperatorsMixnodeRewards),
|
||||
/// Manage your mixnode settings stored in the directory
|
||||
Settings(settings::MixnetOperatorsMixnodeSettings),
|
||||
/// Operations for mixnode families
|
||||
Families(families::MixnetOperatorsMixnodeFamilies),
|
||||
/// Bond to a mixnode
|
||||
Bond(bond_mixnode::Args),
|
||||
/// Unbond from a mixnode
|
||||
@@ -55,4 +53,6 @@ pub enum MixnetOperatorsMixnodeCommands {
|
||||
DecreasePledgeVesting(vesting_decrease_pledge::Args),
|
||||
/// Migrate the mixnode to use liquid tokens
|
||||
MigrateVestedNode(migrate_vested_mixnode::Args),
|
||||
/// Migrate the mixnode into a Nym Node
|
||||
MigrateToNymnode(nymnode_migration::Args),
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::context::SigningClient;
|
||||
use clap::Parser;
|
||||
use log::info;
|
||||
use nym_validator_client::nyxd::contract_traits::MixnetSigningClient;
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct Args {}
|
||||
|
||||
pub async fn migrate_to_nymnode(_args: Args, client: SigningClient) {
|
||||
let res = client
|
||||
.migrate_legacy_mixnode(None)
|
||||
.await
|
||||
.expect("failed to migrate mixnode!");
|
||||
|
||||
info!("migration result: {:?}", res)
|
||||
}
|
||||
+10
-62
@@ -2,12 +2,8 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::context::SigningClient;
|
||||
use crate::validator::mixnet::operators::nymnode;
|
||||
use clap::Parser;
|
||||
use cosmwasm_std::Uint128;
|
||||
use log::info;
|
||||
use nym_mixnet_contract_common::{MixNodeCostParams, Percent};
|
||||
use nym_validator_client::nyxd::contract_traits::{MixnetQueryClient, MixnetSigningClient};
|
||||
use nym_validator_client::nyxd::CosmWasmCoin;
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct Args {
|
||||
@@ -24,62 +20,14 @@ pub struct Args {
|
||||
pub interval_operating_cost: Option<u128>,
|
||||
}
|
||||
|
||||
pub async fn update_cost_params(args: Args, client: SigningClient) {
|
||||
let denom = client.current_chain_details().mix_denom.base.as_str();
|
||||
|
||||
fn convert_to_percent(value: u64) -> Percent {
|
||||
Percent::from_percentage_value(value).expect("Invalid value")
|
||||
}
|
||||
|
||||
let default_profit_margin: Percent = convert_to_percent(20);
|
||||
|
||||
let mixownership_response = match client.get_owned_mixnode(&client.address()).await {
|
||||
Ok(response) => response,
|
||||
Err(_) => {
|
||||
eprintln!("Failed to obtain owned mixnode");
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
let mix_id = match mixownership_response.mixnode_details {
|
||||
Some(details) => details.bond_information.mix_id,
|
||||
None => {
|
||||
eprintln!("Failed to obtain mixnode details");
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
let rewarding_response = match client.get_mixnode_rewarding_details(mix_id).await {
|
||||
Ok(details) => details,
|
||||
Err(_) => {
|
||||
eprintln!("Failed to obtain rewarding details");
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
let profit_margin_percent = rewarding_response
|
||||
.rewarding_details
|
||||
.map(|rd| rd.cost_params.profit_margin_percent)
|
||||
.unwrap_or(default_profit_margin);
|
||||
|
||||
let profit_margin_value = args
|
||||
.profit_margin_percent
|
||||
.map(|pm| convert_to_percent(pm as u64))
|
||||
.unwrap_or(profit_margin_percent);
|
||||
|
||||
let cost_params = MixNodeCostParams {
|
||||
profit_margin_percent: profit_margin_value,
|
||||
interval_operating_cost: CosmWasmCoin {
|
||||
denom: denom.into(),
|
||||
amount: Uint128::new(args.interval_operating_cost.unwrap_or(40_000_000)),
|
||||
pub async fn update_cost_params(args: Args, client: SigningClient) -> anyhow::Result<()> {
|
||||
// the below can handle both, nymnode and legacy mixnode
|
||||
nymnode::settings::update_cost_params::update_cost_params(
|
||||
nymnode::settings::update_cost_params::Args {
|
||||
profit_margin_percent: args.profit_margin_percent,
|
||||
interval_operating_cost: args.interval_operating_cost,
|
||||
},
|
||||
};
|
||||
|
||||
info!("Starting mixnode params updating!");
|
||||
let res = client
|
||||
.update_mixnode_cost_params(cost_params, None)
|
||||
.await
|
||||
.expect("failed to update cost params");
|
||||
|
||||
info!("Cost params result: {:?}", res)
|
||||
client,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
@@ -6,7 +6,9 @@ use clap::Parser;
|
||||
use cosmwasm_std::Uint128;
|
||||
use log::{info, warn};
|
||||
use nym_contracts_common::signing::MessageSignature;
|
||||
use nym_mixnet_contract_common::{Coin, MixNodeCostParams};
|
||||
use nym_mixnet_contract_common::{
|
||||
Coin, NodeCostParams, DEFAULT_INTERVAL_OPERATING_COST_AMOUNT, DEFAULT_PROFIT_MARGIN_PERCENT,
|
||||
};
|
||||
use nym_mixnet_contract_common::{MixNode, Percent};
|
||||
use nym_network_defaults::{
|
||||
DEFAULT_HTTP_API_LISTENING_PORT, DEFAULT_MIX_LISTENING_PORT, DEFAULT_VERLOC_LISTENING_PORT,
|
||||
@@ -40,7 +42,7 @@ pub struct Args {
|
||||
pub version: String,
|
||||
|
||||
#[clap(long)]
|
||||
pub profit_margin_percent: Option<u8>,
|
||||
pub profit_margin_percent: Option<u64>,
|
||||
|
||||
#[clap(
|
||||
long,
|
||||
@@ -84,14 +86,18 @@ pub async fn vesting_bond_mixnode(client: SigningClient, args: Args, denom: &str
|
||||
|
||||
let coin = Coin::new(args.amount, denom);
|
||||
|
||||
let cost_params = MixNodeCostParams {
|
||||
let cost_params = NodeCostParams {
|
||||
profit_margin_percent: Percent::from_percentage_value(
|
||||
args.profit_margin_percent.unwrap_or(10) as u64,
|
||||
args.profit_margin_percent
|
||||
.unwrap_or(DEFAULT_PROFIT_MARGIN_PERCENT),
|
||||
)
|
||||
.unwrap(),
|
||||
interval_operating_cost: CosmWasmCoin {
|
||||
denom: denom.into(),
|
||||
amount: Uint128::new(args.interval_operating_cost.unwrap_or(40_000_000)),
|
||||
amount: Uint128::new(
|
||||
args.interval_operating_cost
|
||||
.unwrap_or(DEFAULT_INTERVAL_OPERATING_COST_AMOUNT),
|
||||
),
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ use clap::{Args, Subcommand};
|
||||
pub mod gateway;
|
||||
pub mod identity_key;
|
||||
pub mod mixnode;
|
||||
pub mod nymnode;
|
||||
|
||||
#[derive(Debug, Args)]
|
||||
#[clap(args_conflicts_with_subcommands = true, subcommand_required = true)]
|
||||
@@ -17,9 +18,11 @@ pub struct MixnetOperators {
|
||||
#[allow(clippy::large_enum_variant)]
|
||||
#[derive(Debug, Subcommand)]
|
||||
pub enum MixnetOperatorsCommands {
|
||||
/// Manage your mixnode
|
||||
/// Manage your Nym Node
|
||||
Nymnode(nymnode::MixnetOperatorsNymNode),
|
||||
/// Manage your legacy mixnode
|
||||
Mixnode(mixnode::MixnetOperatorsMixnode),
|
||||
/// Manage your gateway
|
||||
/// Manage your legacy gateway
|
||||
Gateway(gateway::MixnetOperatorsGateway),
|
||||
/// Sign messages using your private identity key
|
||||
IdentityKey(identity_key::MixnetOperatorsIdentityKey),
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::context::SigningClient;
|
||||
use clap::Parser;
|
||||
use cosmwasm_std::Uint128;
|
||||
use log::{info, warn};
|
||||
use nym_contracts_common::signing::MessageSignature;
|
||||
use nym_mixnet_contract_common::{
|
||||
Coin, NodeCostParams, Percent, DEFAULT_INTERVAL_OPERATING_COST_AMOUNT,
|
||||
DEFAULT_PROFIT_MARGIN_PERCENT,
|
||||
};
|
||||
use nym_validator_client::nyxd::contract_traits::MixnetSigningClient;
|
||||
use nym_validator_client::nyxd::CosmWasmCoin;
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct Args {
|
||||
#[clap(long)]
|
||||
pub host: String,
|
||||
|
||||
#[clap(long)]
|
||||
pub signature: MessageSignature,
|
||||
|
||||
#[clap(long)]
|
||||
pub http_api_port: Option<u16>,
|
||||
|
||||
#[clap(long)]
|
||||
pub identity_key: String,
|
||||
|
||||
#[clap(long)]
|
||||
pub profit_margin_percent: Option<u64>,
|
||||
|
||||
#[clap(
|
||||
long,
|
||||
help = "operating cost in current DENOMINATION (so it would be 'unym', rather than 'nym')"
|
||||
)]
|
||||
pub interval_operating_cost: Option<u128>,
|
||||
|
||||
#[clap(
|
||||
long,
|
||||
help = "bonding amount in current DENOMINATION (so it would be 'unym', rather than 'nym')"
|
||||
)]
|
||||
pub amount: u128,
|
||||
|
||||
#[clap(short, long)]
|
||||
pub force: bool,
|
||||
}
|
||||
|
||||
pub async fn bond_nymnode(args: Args, client: SigningClient) {
|
||||
let denom = client.current_chain_details().mix_denom.base.as_str();
|
||||
|
||||
info!("Starting nym node bonding!");
|
||||
|
||||
// if we're trying to bond less than 1 token
|
||||
if args.amount < 1_000_000 && !args.force {
|
||||
warn!("You're trying to bond only {}{} which is less than 1 full token. Are you sure that's what you want? If so, run with `--force` or `-f` flag", args.amount, denom);
|
||||
return;
|
||||
}
|
||||
|
||||
let nymnode = nym_mixnet_contract_common::NymNode {
|
||||
host: args.host,
|
||||
custom_http_port: args.http_api_port,
|
||||
identity_key: args.identity_key,
|
||||
};
|
||||
|
||||
let coin = Coin::new(args.amount, denom);
|
||||
|
||||
let cost_params = NodeCostParams {
|
||||
profit_margin_percent: Percent::from_percentage_value(
|
||||
args.profit_margin_percent
|
||||
.unwrap_or(DEFAULT_PROFIT_MARGIN_PERCENT),
|
||||
)
|
||||
.unwrap(),
|
||||
interval_operating_cost: CosmWasmCoin {
|
||||
denom: denom.into(),
|
||||
amount: Uint128::new(
|
||||
args.interval_operating_cost
|
||||
.unwrap_or(DEFAULT_INTERVAL_OPERATING_COST_AMOUNT),
|
||||
),
|
||||
},
|
||||
};
|
||||
|
||||
let res = client
|
||||
.bond_nymnode(nymnode, cost_params, args.signature, coin.into(), None)
|
||||
.await
|
||||
.expect("failed to bond nymnode!");
|
||||
|
||||
info!("Bonding result: {:?}", res)
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use base64::Engine;
|
||||
use clap::Parser;
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct Args {
|
||||
#[clap(short, long)]
|
||||
pub key: String,
|
||||
}
|
||||
|
||||
pub fn decode_node_key(args: Args) {
|
||||
let b64_decoded = base64::prelude::BASE64_STANDARD
|
||||
.decode(args.key)
|
||||
.expect("failed to decode base64 string");
|
||||
let b58_encoded = bs58::encode(&b64_decoded).into_string();
|
||||
|
||||
println!("{b58_encoded}")
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use clap::{Args, Subcommand};
|
||||
|
||||
pub mod decode_node_key;
|
||||
|
||||
#[derive(Debug, Args)]
|
||||
#[clap(args_conflicts_with_subcommands = true, subcommand_required = true)]
|
||||
pub struct MixnetOperatorsNymNodeKeys {
|
||||
#[clap(subcommand)]
|
||||
pub command: MixnetOperatorsNymNodeKeysCommands,
|
||||
}
|
||||
|
||||
#[derive(Debug, Subcommand)]
|
||||
pub enum MixnetOperatorsNymNodeKeysCommands {
|
||||
/// Decode a Nym Node key
|
||||
DecodeNodeKey(decode_node_key::Args),
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use clap::{Args, Subcommand};
|
||||
|
||||
pub mod bond_nymnode;
|
||||
pub mod keys;
|
||||
pub mod nymnode_bonding_sign_payload;
|
||||
pub mod pledge;
|
||||
pub mod rewards;
|
||||
pub mod settings;
|
||||
pub mod unbond_nymnode;
|
||||
|
||||
#[derive(Debug, Args)]
|
||||
#[clap(args_conflicts_with_subcommands = true, subcommand_required = true)]
|
||||
pub struct MixnetOperatorsNymNode {
|
||||
#[clap(subcommand)]
|
||||
pub command: MixnetOperatorsNymNodeCommands,
|
||||
}
|
||||
|
||||
#[derive(Debug, Subcommand)]
|
||||
pub enum MixnetOperatorsNymNodeCommands {
|
||||
/// Operations for Nym Node keys
|
||||
Keys(keys::MixnetOperatorsNymNodeKeys),
|
||||
|
||||
/// Manage your Nym Node operator rewards
|
||||
Rewards(rewards::MixnetOperatorsNymNodeRewards),
|
||||
|
||||
/// Manage your Nym Node settings stored in the directory
|
||||
Settings(settings::MixnetOperatorsNymNodeSettings),
|
||||
|
||||
/// Manage your Nym Node pledge
|
||||
Pledge(pledge::MixnetOperatorsNymNodePledge),
|
||||
|
||||
/// Bond to a Nym Node
|
||||
Bond(bond_nymnode::Args),
|
||||
|
||||
/// Unbond from a Nym Node
|
||||
Unbond(unbond_nymnode::Args),
|
||||
|
||||
/// Create base58-encoded payload required for producing valid bonding signature.
|
||||
CreateNodeBondingSignPayload(nymnode_bonding_sign_payload::Args),
|
||||
}
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::context::SigningClient;
|
||||
use crate::utils::{account_id_to_cw_addr, DataWrapper};
|
||||
use clap::Parser;
|
||||
use cosmwasm_std::{Coin, Uint128};
|
||||
use nym_bin_common::output_format::OutputFormat;
|
||||
use nym_contracts_common::Percent;
|
||||
use nym_mixnet_contract_common::{
|
||||
construct_nym_node_bonding_sign_payload, NodeCostParams,
|
||||
DEFAULT_INTERVAL_OPERATING_COST_AMOUNT, DEFAULT_PROFIT_MARGIN_PERCENT,
|
||||
};
|
||||
use nym_validator_client::nyxd::contract_traits::MixnetQueryClient;
|
||||
use nym_validator_client::nyxd::CosmWasmCoin;
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct Args {
|
||||
#[clap(long)]
|
||||
pub host: String,
|
||||
|
||||
#[clap(long)]
|
||||
pub identity_key: String,
|
||||
|
||||
#[clap(long)]
|
||||
pub custom_http_api_port: Option<u16>,
|
||||
|
||||
#[clap(long)]
|
||||
pub profit_margin_percent: Option<u64>,
|
||||
|
||||
#[clap(
|
||||
long,
|
||||
help = "operating cost in current DENOMINATION (so it would be 'unym', rather than 'nym')"
|
||||
)]
|
||||
pub interval_operating_cost: Option<u128>,
|
||||
|
||||
#[clap(
|
||||
long,
|
||||
help = "bonding amount in current DENOMINATION (so it would be 'unym', rather than 'nym')"
|
||||
)]
|
||||
pub amount: u128,
|
||||
|
||||
#[clap(short, long, default_value_t = OutputFormat::default())]
|
||||
pub output: OutputFormat,
|
||||
}
|
||||
|
||||
pub async fn create_payload(args: Args, client: SigningClient) {
|
||||
let denom = client.current_chain_details().mix_denom.base.as_str();
|
||||
|
||||
let mixnode = nym_mixnet_contract_common::NymNode {
|
||||
host: args.host,
|
||||
custom_http_port: args.custom_http_api_port,
|
||||
identity_key: args.identity_key,
|
||||
};
|
||||
|
||||
let coin = Coin::new(args.amount, denom);
|
||||
|
||||
let cost_params = NodeCostParams {
|
||||
profit_margin_percent: Percent::from_percentage_value(
|
||||
args.profit_margin_percent
|
||||
.unwrap_or(DEFAULT_PROFIT_MARGIN_PERCENT),
|
||||
)
|
||||
.unwrap(),
|
||||
interval_operating_cost: CosmWasmCoin {
|
||||
denom: denom.into(),
|
||||
amount: Uint128::new(
|
||||
args.interval_operating_cost
|
||||
.unwrap_or(DEFAULT_INTERVAL_OPERATING_COST_AMOUNT),
|
||||
),
|
||||
},
|
||||
};
|
||||
|
||||
let nonce = match client.get_signing_nonce(&client.address()).await {
|
||||
Ok(nonce) => nonce,
|
||||
Err(err) => {
|
||||
eprint!(
|
||||
"failed to query for the signing nonce of {}: {err}",
|
||||
client.address()
|
||||
);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
let address = account_id_to_cw_addr(&client.address());
|
||||
|
||||
let payload =
|
||||
construct_nym_node_bonding_sign_payload(nonce, address, coin, mixnode, cost_params);
|
||||
let wrapper = DataWrapper::new(payload.to_base58_string().unwrap());
|
||||
println!("{}", args.output.format(&wrapper))
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::context::SigningClient;
|
||||
use clap::Parser;
|
||||
use log::info;
|
||||
use nym_mixnet_contract_common::Coin;
|
||||
use nym_validator_client::nyxd::contract_traits::MixnetSigningClient;
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct Args {
|
||||
#[clap(long)]
|
||||
pub decrease_by: u128,
|
||||
}
|
||||
|
||||
pub async fn decrease_pledge(args: Args, client: SigningClient) {
|
||||
let denom = client.current_chain_details().mix_denom.base.as_str();
|
||||
|
||||
info!("Starting to decrease pledge");
|
||||
|
||||
let coin = Coin::new(args.decrease_by, denom);
|
||||
|
||||
let res = client
|
||||
.pledge_more(coin.into(), None)
|
||||
.await
|
||||
.expect("failed to decrease pledge!");
|
||||
|
||||
info!("decreasing pledge: {:?}", res);
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::context::SigningClient;
|
||||
use clap::Parser;
|
||||
use log::info;
|
||||
use nym_mixnet_contract_common::Coin;
|
||||
use nym_validator_client::nyxd::contract_traits::MixnetSigningClient;
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct Args {
|
||||
#[clap(long)]
|
||||
pub amount: u128,
|
||||
}
|
||||
|
||||
pub async fn increase_pledge(args: Args, client: SigningClient) {
|
||||
let denom = client.current_chain_details().mix_denom.base.as_str();
|
||||
|
||||
info!("Starting to pledge more");
|
||||
|
||||
let coin = Coin::new(args.amount, denom);
|
||||
|
||||
let res = client
|
||||
.pledge_more(coin.into(), None)
|
||||
.await
|
||||
.expect("failed to pledge more!");
|
||||
|
||||
info!("pledging more: {:?}", res);
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use clap::{Args, Subcommand};
|
||||
|
||||
pub mod decrease_pledge;
|
||||
pub mod increase_pledge;
|
||||
|
||||
#[derive(Debug, Args)]
|
||||
#[clap(args_conflicts_with_subcommands = true, subcommand_required = true)]
|
||||
pub struct MixnetOperatorsNymNodePledge {
|
||||
#[clap(subcommand)]
|
||||
pub command: MixnetOperatorsNymNodePledgeCommands,
|
||||
}
|
||||
|
||||
#[derive(Debug, Subcommand)]
|
||||
pub enum MixnetOperatorsNymNodePledgeCommands {
|
||||
/// Increase current pledge
|
||||
Increase(increase_pledge::Args),
|
||||
/// decrease current pledge
|
||||
Decrease(decrease_pledge::Args),
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::context::SigningClient;
|
||||
use clap::Parser;
|
||||
use log::info;
|
||||
use nym_validator_client::nyxd::contract_traits::MixnetSigningClient;
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct Args {}
|
||||
|
||||
pub async fn claim_operator_reward(_args: Args, client: SigningClient) {
|
||||
info!("Claim operator reward");
|
||||
|
||||
let res = client
|
||||
.withdraw_operator_reward(None)
|
||||
.await
|
||||
.expect("failed to claim operator reward");
|
||||
|
||||
info!("Claiming operator reward: {:?}", res)
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use clap::{Args, Subcommand};
|
||||
|
||||
pub mod claim_operator_reward;
|
||||
|
||||
#[derive(Debug, Args)]
|
||||
#[clap(args_conflicts_with_subcommands = true, subcommand_required = true)]
|
||||
pub struct MixnetOperatorsNymNodeRewards {
|
||||
#[clap(subcommand)]
|
||||
pub command: MixnetOperatorsNymNodeRewardsCommands,
|
||||
}
|
||||
|
||||
#[derive(Debug, Subcommand)]
|
||||
pub enum MixnetOperatorsNymNodeRewardsCommands {
|
||||
/// Claim rewards
|
||||
Claim(claim_operator_reward::Args),
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use clap::{Args, Subcommand};
|
||||
|
||||
pub mod update_config;
|
||||
pub mod update_cost_params;
|
||||
|
||||
#[derive(Debug, Args)]
|
||||
#[clap(args_conflicts_with_subcommands = true, subcommand_required = true)]
|
||||
pub struct MixnetOperatorsNymNodeSettings {
|
||||
#[clap(subcommand)]
|
||||
pub command: MixnetOperatorsNymNodeSettingsCommands,
|
||||
}
|
||||
|
||||
#[derive(Debug, Subcommand)]
|
||||
pub enum MixnetOperatorsNymNodeSettingsCommands {
|
||||
/// Update Nym Node configuration
|
||||
UpdateConfig(update_config::Args),
|
||||
/// Update Nym Node cost parameters
|
||||
UpdateCostParameters(update_cost_params::Args),
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::context::SigningClient;
|
||||
use clap::Parser;
|
||||
use log::info;
|
||||
use nym_mixnet_contract_common::nym_node::NodeConfigUpdate;
|
||||
use nym_validator_client::nyxd::contract_traits::{MixnetQueryClient, MixnetSigningClient};
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct Args {
|
||||
#[clap(long)]
|
||||
pub host: Option<String>,
|
||||
|
||||
// ideally this would have been `Option<Option<u16>>`, but not sure if clap would have recognised it
|
||||
#[clap(long)]
|
||||
pub custom_http_port: Option<u16>,
|
||||
|
||||
// equivalent to setting `custom_http_port` to `None`
|
||||
#[clap(long)]
|
||||
pub restore_default_http_port: bool,
|
||||
}
|
||||
|
||||
pub async fn update_config(args: Args, client: SigningClient) {
|
||||
info!("Update nym node config!");
|
||||
|
||||
if client
|
||||
.get_owned_nymnode(&client.address())
|
||||
.await
|
||||
.expect("failed to query the chain for nym node details")
|
||||
.details
|
||||
.is_none()
|
||||
{
|
||||
log::warn!("this operator does not own a nym node to update");
|
||||
return;
|
||||
}
|
||||
|
||||
let update = NodeConfigUpdate {
|
||||
host: args.host,
|
||||
custom_http_port: args.custom_http_port,
|
||||
restore_default_http_port: args.restore_default_http_port,
|
||||
};
|
||||
|
||||
let res = client
|
||||
.update_nymnode_config(update, None)
|
||||
.await
|
||||
.expect("updating nym node config");
|
||||
|
||||
info!("nym node config updated: {:?}", res)
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::context::SigningClient;
|
||||
use anyhow::anyhow;
|
||||
use clap::Parser;
|
||||
use cosmwasm_std::Uint128;
|
||||
use log::info;
|
||||
use nym_mixnet_contract_common::{NodeCostParams, Percent};
|
||||
use nym_validator_client::nyxd::contract_traits::{MixnetQueryClient, MixnetSigningClient};
|
||||
use nym_validator_client::nyxd::CosmWasmCoin;
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct Args {
|
||||
#[clap(
|
||||
long,
|
||||
help = "input your profit margin as follows; (so it would be 20, rather than 0.2)"
|
||||
)]
|
||||
pub profit_margin_percent: Option<u8>,
|
||||
|
||||
#[clap(
|
||||
long,
|
||||
help = "operating cost in current DENOMINATION (so it would be 'unym', rather than 'nym')"
|
||||
)]
|
||||
pub interval_operating_cost: Option<u128>,
|
||||
}
|
||||
|
||||
pub async fn update_cost_params(args: Args, client: SigningClient) -> anyhow::Result<()> {
|
||||
let denom = client.current_chain_details().mix_denom.base.as_str();
|
||||
|
||||
let current_parameters = if let Some(client_mixnode) = client
|
||||
.get_owned_mixnode(&client.address())
|
||||
.await?
|
||||
.mixnode_details
|
||||
{
|
||||
client_mixnode.rewarding_details.cost_params
|
||||
} else {
|
||||
client
|
||||
.get_owned_nymnode(&client.address())
|
||||
.await?
|
||||
.details
|
||||
.ok_or_else(|| anyhow!("the client does not own any nodes"))?
|
||||
.rewarding_details
|
||||
.cost_params
|
||||
};
|
||||
|
||||
let profit_margin_percent = args
|
||||
.profit_margin_percent
|
||||
.map(|pm| Percent::from_percentage_value(pm as u64))
|
||||
.unwrap_or(Ok(current_parameters.profit_margin_percent))?;
|
||||
|
||||
let interval_operating_cost = args
|
||||
.interval_operating_cost
|
||||
.map(|oc| CosmWasmCoin {
|
||||
denom: denom.into(),
|
||||
amount: Uint128::new(oc),
|
||||
})
|
||||
.unwrap_or(current_parameters.interval_operating_cost);
|
||||
|
||||
let cost_params = NodeCostParams {
|
||||
profit_margin_percent,
|
||||
interval_operating_cost,
|
||||
};
|
||||
|
||||
info!("Starting cost params updating using {cost_params:?} !");
|
||||
let res = client
|
||||
.update_cost_params(cost_params, None)
|
||||
.await
|
||||
.expect("failed to update cost params");
|
||||
|
||||
info!("Cost params result: {:?}", res);
|
||||
Ok(())
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use clap::Parser;
|
||||
use log::info;
|
||||
use nym_validator_client::nyxd::contract_traits::MixnetSigningClient;
|
||||
|
||||
use crate::context::SigningClient;
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct Args {}
|
||||
|
||||
pub async fn unbond_nymnode(_args: Args, client: SigningClient) {
|
||||
info!("Starting Nym Node unbonding!");
|
||||
|
||||
let res = client
|
||||
.unbond_nymnode(None)
|
||||
.await
|
||||
.expect("failed to unbond Nym Node!");
|
||||
|
||||
info!("Unbonding result: {:?}", res)
|
||||
}
|
||||
@@ -39,7 +39,7 @@ pub async fn query(args: Args, client: &QueryClientWithNyxd) {
|
||||
node.owner.to_string(),
|
||||
node.gateway.host.to_string(),
|
||||
pretty_cosmwasm_coin(&node.pledge_amount),
|
||||
node.gateway.version,
|
||||
node.gateway.version.clone(),
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use cosmwasm_std::{BankMsg, Coin, CosmosMsg, Response};
|
||||
|
||||
pub trait ResponseExt<T> {
|
||||
fn add_optional_message(self, msg: Option<impl Into<CosmosMsg<T>>>) -> Self;
|
||||
|
||||
fn send_tokens(self, to: impl AsRef<str>, amount: Coin) -> Self;
|
||||
}
|
||||
|
||||
impl<T> ResponseExt<T> for Response<T> {
|
||||
fn add_optional_message(self, msg: Option<impl Into<CosmosMsg<T>>>) -> Self {
|
||||
if let Some(msg) = msg {
|
||||
self.add_message(msg)
|
||||
} else {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
fn send_tokens(self, to: impl AsRef<str>, amount: Coin) -> Self {
|
||||
self.add_message(BankMsg::Send {
|
||||
to_address: to.as_ref().to_string(),
|
||||
amount: vec![amount],
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -10,4 +10,6 @@ pub mod events;
|
||||
pub mod signing;
|
||||
pub mod types;
|
||||
|
||||
pub mod helpers;
|
||||
|
||||
pub use types::*;
|
||||
|
||||
@@ -8,7 +8,7 @@ use cosmwasm_std::Uint128;
|
||||
use serde::de::Error;
|
||||
use serde::{Deserialize, Deserializer};
|
||||
use std::fmt::{self, Display, Formatter};
|
||||
use std::ops::Mul;
|
||||
use std::ops::{Deref, Mul};
|
||||
use std::str::FromStr;
|
||||
use thiserror::Error;
|
||||
|
||||
@@ -23,7 +23,7 @@ pub fn truncate_decimal(amount: Decimal) -> Uint128 {
|
||||
#[derive(Error, Debug)]
|
||||
pub enum ContractsCommonError {
|
||||
#[error("Provided percent value ({0}) is greater than 100%")]
|
||||
InvalidPercent(Decimal),
|
||||
InvalidPercent(String),
|
||||
|
||||
#[error("{source}")]
|
||||
StdErr {
|
||||
@@ -41,7 +41,7 @@ pub struct Percent(#[serde(deserialize_with = "de_decimal_percent")] Decimal);
|
||||
impl Percent {
|
||||
pub fn new(value: Decimal) -> Result<Self, ContractsCommonError> {
|
||||
if value > Decimal::one() {
|
||||
Err(ContractsCommonError::InvalidPercent(value))
|
||||
Err(ContractsCommonError::InvalidPercent(value.to_string()))
|
||||
} else {
|
||||
Ok(Percent(value))
|
||||
}
|
||||
@@ -51,11 +51,15 @@ impl Percent {
|
||||
self.0 == Decimal::zero()
|
||||
}
|
||||
|
||||
pub fn zero() -> Self {
|
||||
pub fn is_hundred(&self) -> bool {
|
||||
self == &Self::hundred()
|
||||
}
|
||||
|
||||
pub const fn zero() -> Self {
|
||||
Self(Decimal::zero())
|
||||
}
|
||||
|
||||
pub fn hundred() -> Self {
|
||||
pub const fn hundred() -> Self {
|
||||
Self(Decimal::one())
|
||||
}
|
||||
|
||||
@@ -117,6 +121,70 @@ impl Mul<Uint128> for Percent {
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for Percent {
|
||||
type Target = Decimal;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
// this is not implemented via From traits due to its naive nature and loss of precision
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
pub trait NaiveFloat {
|
||||
fn naive_to_f64(&self) -> f64;
|
||||
|
||||
fn naive_try_from_f64(val: f64) -> Result<Self, ContractsCommonError>
|
||||
where
|
||||
Self: Sized;
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
impl NaiveFloat for Percent {
|
||||
fn naive_to_f64(&self) -> f64 {
|
||||
use cosmwasm_std::Fraction;
|
||||
|
||||
// note: this conversion loses precision with too many decimal places,
|
||||
// but for the purposes of displaying basic performance, that's not an issue
|
||||
self.numerator().u128() as f64 / self.denominator().u128() as f64
|
||||
}
|
||||
|
||||
fn naive_try_from_f64(val: f64) -> Result<Self, ContractsCommonError>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
// we are only interested in positive values between 0 and 1
|
||||
if !(0. ..=1.).contains(&val) {
|
||||
return Err(ContractsCommonError::InvalidPercent(val.to_string()));
|
||||
}
|
||||
|
||||
fn gcd(mut x: u64, mut y: u64) -> u64 {
|
||||
while y > 0 {
|
||||
let rem = x % y;
|
||||
x = y;
|
||||
y = rem;
|
||||
}
|
||||
|
||||
x
|
||||
}
|
||||
|
||||
fn to_rational(x: f64) -> (u64, u64) {
|
||||
let log = x.log2().floor();
|
||||
if log >= 0.0 {
|
||||
(x as u64, 1)
|
||||
} else {
|
||||
let num: u64 = (x / f64::EPSILON) as _;
|
||||
let den: u64 = (1.0 / f64::EPSILON) as _;
|
||||
let gcd = gcd(num, den);
|
||||
(num / gcd, den / gcd)
|
||||
}
|
||||
}
|
||||
|
||||
let (n, d) = to_rational(val);
|
||||
Percent::new(Decimal::from_ratio(n, d))
|
||||
}
|
||||
}
|
||||
|
||||
// implement custom Deserialize because we want to validate Percent has the correct range
|
||||
fn de_decimal_percent<'de, D>(deserializer: D) -> Result<Decimal, D::Error>
|
||||
where
|
||||
@@ -243,4 +311,19 @@ mod tests {
|
||||
let p = serde_json::from_str::<'_, Percent>("\"1.00\"").unwrap();
|
||||
assert_eq!(p.round_to_integer(), 100);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn naive_float_conversion() {
|
||||
// around 15 decimal places is the maximum precision we can handle
|
||||
// which is still way more than enough for what we use it for
|
||||
let float: f64 = "0.546295475423853".parse().unwrap();
|
||||
let percent: Percent = "0.546295475423853".parse().unwrap();
|
||||
|
||||
assert_eq!(float, percent.naive_to_f64());
|
||||
|
||||
let epsilon = Decimal::from_ratio(1u64, 1000000000000000u64);
|
||||
let converted = Percent::naive_try_from_f64(float).unwrap();
|
||||
|
||||
assert!(converted.0 - converted.0 < epsilon);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ repository = { workspace = true }
|
||||
bs58 = { workspace = true }
|
||||
cosmwasm-std = { workspace = true }
|
||||
cosmwasm-schema = { workspace = true }
|
||||
cw-storage-plus.workspace = true
|
||||
cw-controllers = { workspace = true }
|
||||
cw2 = { workspace = true, optional = true }
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
|
||||
@@ -5,6 +5,9 @@ use cosmwasm_std::{Decimal, Uint128};
|
||||
|
||||
pub const TOKEN_SUPPLY: Uint128 = Uint128::new(1_000_000_000_000_000);
|
||||
|
||||
pub const DEFAULT_INTERVAL_OPERATING_COST_AMOUNT: u128 = 40_000_000;
|
||||
pub const DEFAULT_PROFIT_MARGIN_PERCENT: u64 = 20;
|
||||
|
||||
// I'm still not 100% sure how to feel about existence of this file
|
||||
// This is equivalent of representing our display coin with 6 decimal places.
|
||||
// I'm using this one as opposed to "Decimal::one()", as this provides us with higher accuracy
|
||||
|
||||
@@ -3,14 +3,14 @@
|
||||
|
||||
use crate::constants::TOKEN_SUPPLY;
|
||||
use crate::helpers::IntoBaseDecimal;
|
||||
use crate::{Addr, MixId};
|
||||
use crate::{Addr, NodeId};
|
||||
use cosmwasm_schema::cw_serde;
|
||||
use cosmwasm_std::{Coin, Decimal, StdResult};
|
||||
|
||||
// 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
|
||||
pub type OwnerProxySubKey = String;
|
||||
pub type StorageKey = (MixId, OwnerProxySubKey);
|
||||
pub type StorageKey = (NodeId, OwnerProxySubKey);
|
||||
|
||||
// throughout the contract we ensure that our proxy can ONLY ever be the vesting contract
|
||||
// thus this method is equivalent to either using the existing address (for when there's no proxy)
|
||||
@@ -40,8 +40,9 @@ pub struct Delegation {
|
||||
/// Address of the owner of this delegation.
|
||||
pub owner: Addr,
|
||||
|
||||
/// Id of the MixNode that this delegation was performed against.
|
||||
pub mix_id: MixId,
|
||||
/// Id of the Node that this delegation was performed against.
|
||||
#[serde(alias = "mix_id")]
|
||||
pub node_id: NodeId,
|
||||
|
||||
// Note to UI/UX devs: there's absolutely no point in displaying this value to the users,
|
||||
// it would serve them no purpose. It's only used for calculating rewards
|
||||
@@ -56,12 +57,13 @@ pub struct Delegation {
|
||||
|
||||
/// Proxy address used to delegate the funds on behalf of another address
|
||||
pub proxy: Option<Addr>,
|
||||
// TODO: perhaps add a field to indicate if it was made against old mixnode with #[serde(default)]?
|
||||
}
|
||||
|
||||
impl Delegation {
|
||||
pub fn new(
|
||||
owner: Addr,
|
||||
mix_id: MixId,
|
||||
node_id: NodeId,
|
||||
cumulative_reward_ratio: Decimal,
|
||||
amount: Coin,
|
||||
height: u64,
|
||||
@@ -73,7 +75,7 @@ impl Delegation {
|
||||
|
||||
Delegation {
|
||||
owner,
|
||||
mix_id,
|
||||
node_id,
|
||||
cumulative_reward_ratio,
|
||||
amount,
|
||||
height,
|
||||
@@ -82,7 +84,7 @@ impl Delegation {
|
||||
}
|
||||
|
||||
pub fn generate_storage_key(
|
||||
mix_id: MixId,
|
||||
mix_id: NodeId,
|
||||
owner_address: &Addr,
|
||||
proxy: Option<&Addr>,
|
||||
) -> StorageKey {
|
||||
@@ -92,7 +94,7 @@ impl Delegation {
|
||||
// this function might seem a bit redundant, but I'd rather explicitly keep it around in case
|
||||
// some types change in the future
|
||||
pub fn generate_storage_key_with_subkey(
|
||||
mix_id: MixId,
|
||||
mix_id: NodeId,
|
||||
owner_proxy_subkey: OwnerProxySubKey,
|
||||
) -> StorageKey {
|
||||
(mix_id, owner_proxy_subkey)
|
||||
@@ -107,13 +109,13 @@ impl Delegation {
|
||||
}
|
||||
|
||||
pub fn storage_key(&self) -> StorageKey {
|
||||
Self::generate_storage_key(self.mix_id, &self.owner, self.proxy.as_ref())
|
||||
Self::generate_storage_key(self.node_id, &self.owner, self.proxy.as_ref())
|
||||
}
|
||||
}
|
||||
|
||||
/// Response containing paged list of all delegations made towards particular mixnode.
|
||||
/// Response containing paged list of all delegations made towards particular node.
|
||||
#[cw_serde]
|
||||
pub struct PagedMixNodeDelegationsResponse {
|
||||
pub struct PagedNodeDelegationsResponse {
|
||||
/// Each individual delegation made.
|
||||
pub delegations: Vec<Delegation>,
|
||||
|
||||
@@ -121,9 +123,9 @@ pub struct PagedMixNodeDelegationsResponse {
|
||||
pub start_next_after: Option<OwnerProxySubKey>,
|
||||
}
|
||||
|
||||
impl PagedMixNodeDelegationsResponse {
|
||||
impl PagedNodeDelegationsResponse {
|
||||
pub fn new(delegations: Vec<Delegation>, start_next_after: Option<OwnerProxySubKey>) -> Self {
|
||||
PagedMixNodeDelegationsResponse {
|
||||
PagedNodeDelegationsResponse {
|
||||
delegations,
|
||||
start_next_after,
|
||||
}
|
||||
@@ -137,13 +139,13 @@ pub struct PagedDelegatorDelegationsResponse {
|
||||
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)>,
|
||||
pub start_next_after: Option<(NodeId, OwnerProxySubKey)>,
|
||||
}
|
||||
|
||||
impl PagedDelegatorDelegationsResponse {
|
||||
pub fn new(
|
||||
delegations: Vec<Delegation>,
|
||||
start_next_after: Option<(MixId, OwnerProxySubKey)>,
|
||||
start_next_after: Option<(NodeId, OwnerProxySubKey)>,
|
||||
) -> Self {
|
||||
PagedDelegatorDelegationsResponse {
|
||||
delegations,
|
||||
@@ -154,19 +156,24 @@ impl PagedDelegatorDelegationsResponse {
|
||||
|
||||
/// Response containing delegation details.
|
||||
#[cw_serde]
|
||||
pub struct MixNodeDelegationResponse {
|
||||
pub struct NodeDelegationResponse {
|
||||
/// 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.
|
||||
#[deprecated(note = "this field will be removed. use .node_still_bonded instead")]
|
||||
pub mixnode_still_bonded: bool,
|
||||
|
||||
pub node_still_bonded: bool,
|
||||
}
|
||||
|
||||
impl MixNodeDelegationResponse {
|
||||
pub fn new(delegation: Option<Delegation>, mixnode_still_bonded: bool) -> Self {
|
||||
MixNodeDelegationResponse {
|
||||
impl NodeDelegationResponse {
|
||||
pub fn new(delegation: Option<Delegation>, node_still_bonded: bool) -> Self {
|
||||
#[allow(deprecated)]
|
||||
NodeDelegationResponse {
|
||||
delegation,
|
||||
mixnode_still_bonded,
|
||||
mixnode_still_bonded: node_still_bonded,
|
||||
node_still_bonded,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
// Copyright 2022-2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::{EpochEventId, EpochState, IdentityKey, MixId, OperatingCostRange, ProfitMarginRange};
|
||||
use crate::nym_node::Role;
|
||||
use crate::{
|
||||
EpochEventId, EpochState, IntervalEventId, NodeId, OperatingCostRange, ProfitMarginRange,
|
||||
};
|
||||
use contracts_common::signing::verifier::ApiVerifierError;
|
||||
use contracts_common::Percent;
|
||||
use cosmwasm_std::{Addr, Coin, Decimal, Uint128};
|
||||
@@ -34,6 +37,16 @@ pub enum MixnetContractError {
|
||||
#[error("Not enough funds sent for node pledge. (received {received}, minimum {minimum})")]
|
||||
InsufficientPledge { received: Coin, minimum: Coin },
|
||||
|
||||
#[error(
|
||||
"the provided value for node host is too long. it must not be longer than 255 characters"
|
||||
)]
|
||||
HostTooLong,
|
||||
|
||||
#[error(
|
||||
"the provided node identity public key is not a correctly encoded base58 slice of 32 bytes"
|
||||
)]
|
||||
InvalidPubKey,
|
||||
|
||||
#[error("Attempted to reduce node pledge ({current}{denom} - {decrease_by}{denom}) below the minimum amount: {minimum}{denom}")]
|
||||
InvalidPledgeReduction {
|
||||
current: Uint128,
|
||||
@@ -45,11 +58,19 @@ pub enum MixnetContractError {
|
||||
#[error("A pledge change is already pending in this epoch. The event id: {pending_event_id}")]
|
||||
PendingPledgeChange { pending_event_id: EpochEventId },
|
||||
|
||||
#[error(
|
||||
"A cost params change is already pending in this epoch. The event id: {pending_event_id}"
|
||||
)]
|
||||
PendingParamsChange { pending_event_id: IntervalEventId },
|
||||
|
||||
#[error("Not enough funds sent for node delegation. (received {received}, minimum {minimum})")]
|
||||
InsufficientDelegation { received: Coin, minimum: Coin },
|
||||
|
||||
#[error("Node ({node_id}) does not exist")]
|
||||
NymNodeBondNotFound { node_id: NodeId },
|
||||
|
||||
#[error("Mixnode ({mix_id}) does not exist")]
|
||||
MixNodeBondNotFound { mix_id: MixId },
|
||||
MixNodeBondNotFound { mix_id: NodeId },
|
||||
|
||||
#[error("{owner} does not seem to own any mixnodes")]
|
||||
NoAssociatedMixNodeBond { owner: Addr },
|
||||
@@ -57,12 +78,18 @@ pub enum MixnetContractError {
|
||||
#[error("{owner} does not seem to own any gateways")]
|
||||
NoAssociatedGatewayBond { owner: Addr },
|
||||
|
||||
#[error("{owner} does not seem to own any nodes")]
|
||||
NoAssociatedNodeBond { owner: Addr },
|
||||
|
||||
#[error("This address has already bonded a mixnode")]
|
||||
AlreadyOwnsMixnode,
|
||||
|
||||
#[error("This address has already bonded a gateway")]
|
||||
AlreadyOwnsGateway,
|
||||
|
||||
#[error("This address has already bonded a nym-node")]
|
||||
AlreadyOwnsNymNode,
|
||||
|
||||
#[error("Gateway with this identity already exists. Its owner is {owner}")]
|
||||
DuplicateGateway { owner: Addr },
|
||||
|
||||
@@ -103,32 +130,35 @@ pub enum MixnetContractError {
|
||||
epoch_end: i64,
|
||||
},
|
||||
|
||||
#[error("Mixnode {mix_id} has already been rewarded during the current rewarding epoch ({absolute_epoch_id})")]
|
||||
MixnodeAlreadyRewarded {
|
||||
mix_id: MixId,
|
||||
#[error("attempted to reward a gateway node - this has not been fully integrated yet")]
|
||||
GatewayRewarding,
|
||||
|
||||
#[error("node {node_id} has already been rewarded during the current rewarding epoch ({absolute_epoch_id})")]
|
||||
NodeAlreadyRewarded {
|
||||
node_id: NodeId,
|
||||
absolute_epoch_id: u32,
|
||||
},
|
||||
|
||||
#[error("Mixnode {mix_id} hasn't been selected to the rewarding set in this epoch ({absolute_epoch_id})")]
|
||||
MixnodeNotInRewardedSet {
|
||||
mix_id: MixId,
|
||||
absolute_epoch_id: u32,
|
||||
},
|
||||
#[error("node {node_id} hasn't been assigned the role of {role} for this epoch")]
|
||||
IncorrectEpochRole { node_id: NodeId, role: Role },
|
||||
|
||||
#[error("Mixnode {mix_id} is currently in the process of unbonding")]
|
||||
MixnodeIsUnbonding { mix_id: MixId },
|
||||
MixnodeIsUnbonding { mix_id: NodeId },
|
||||
|
||||
#[error("Node {node_id} is currently in the process of unbonding")]
|
||||
NodeIsUnbonding { node_id: NodeId },
|
||||
|
||||
#[error("Mixnode {mix_id} has already unbonded")]
|
||||
MixnodeHasUnbonded { mix_id: MixId },
|
||||
MixnodeHasUnbonded { mix_id: NodeId },
|
||||
|
||||
#[error("The contract has ended up in a state that was deemed impossible: {comment}")]
|
||||
InconsistentState { comment: String },
|
||||
|
||||
#[error(
|
||||
"Could not find any delegation information associated with mixnode {mix_id} for {address} (proxy: {proxy:?})"
|
||||
"Could not find any delegation information associated with node {node_id} for {address} (proxy: {proxy:?})"
|
||||
)]
|
||||
NoMixnodeDelegationFound {
|
||||
mix_id: MixId,
|
||||
NodeDelegationNotFound {
|
||||
node_id: NodeId,
|
||||
address: String,
|
||||
proxy: Option<String>,
|
||||
},
|
||||
@@ -136,63 +166,18 @@ pub enum MixnetContractError {
|
||||
#[error("Provided message to update rewarding params did not contain any updates")]
|
||||
EmptyParamsChangeMsg,
|
||||
|
||||
#[error("Provided active set size is bigger than the rewarded set")]
|
||||
#[error("one of the roles in the new active set is empty")]
|
||||
EmptyRoleAssignment,
|
||||
|
||||
#[error("the number of mixnodes in the rewarded set is not divisible by the number of mix-layers (3)")]
|
||||
UnevenLayerAssignment,
|
||||
|
||||
#[error("provided active set is bigger than the rewarded set")]
|
||||
InvalidActiveSetSize,
|
||||
|
||||
#[error("Provided rewarded set size is smaller than the active set")]
|
||||
InvalidRewardedSetSize,
|
||||
|
||||
#[error("Provided active set size is zero")]
|
||||
ZeroActiveSet,
|
||||
|
||||
#[error("Provided rewarded set size is zero")]
|
||||
ZeroRewardedSet,
|
||||
|
||||
#[error("Received unexpected value for the active set. Got: {received}, expected: {expected}")]
|
||||
UnexpectedActiveSetSize { received: u32, expected: u32 },
|
||||
|
||||
#[error("Received unexpected value for the rewarded set. Got: {received}, expected at most: {expected}")]
|
||||
UnexpectedRewardedSetSize { received: u32, expected: u32 },
|
||||
|
||||
#[error("Mixnode {mix_id} appears multiple times in the provided rewarded set update!")]
|
||||
DuplicateRewardedSetNode { mix_id: MixId },
|
||||
|
||||
#[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),
|
||||
|
||||
#[error("Invalid layer expected 1, 2 or 3, got {0}")]
|
||||
InvalidLayer(u8),
|
||||
|
||||
#[error("Head already has a family")]
|
||||
FamilyCanHaveOnlyOne,
|
||||
|
||||
#[error("Already member of family {0}")]
|
||||
AlreadyMemberOfFamily(String),
|
||||
|
||||
#[error("Can't join own family, family head {head}, member {member}")]
|
||||
CantJoinOwnFamily {
|
||||
head: IdentityKey,
|
||||
member: IdentityKey,
|
||||
},
|
||||
|
||||
#[error("Can't leave own family, family head {head}, member {member}")]
|
||||
CantLeaveOwnFamily {
|
||||
head: IdentityKey,
|
||||
member: IdentityKey,
|
||||
},
|
||||
|
||||
#[error("{member} is not a member of family {head}")]
|
||||
NotAMember {
|
||||
head: IdentityKey,
|
||||
member: IdentityKey,
|
||||
},
|
||||
|
||||
#[error("Feature is not yet implemented")]
|
||||
NotImplemented,
|
||||
|
||||
@@ -219,13 +204,28 @@ pub enum MixnetContractError {
|
||||
|
||||
#[error("attempted to reward mixnode out of order. Attempted to reward {attempted_to_reward} while last rewarded was {last_rewarded}.")]
|
||||
RewardingOutOfOrder {
|
||||
last_rewarded: MixId,
|
||||
attempted_to_reward: MixId,
|
||||
last_rewarded: NodeId,
|
||||
attempted_to_reward: NodeId,
|
||||
},
|
||||
|
||||
#[error("the epoch is currently not in the 'event reconciliation' state. (the state is {current_state})")]
|
||||
EpochNotInEventReconciliationState { current_state: EpochState },
|
||||
|
||||
#[error(
|
||||
"the epoch is currently not in the 'role assignment' state. (the state is {current_state})"
|
||||
)]
|
||||
EpochNotInRoleAssignmentState { current_state: EpochState },
|
||||
|
||||
#[error("unexpected role assignment. got: {got} while expected: {expected}")]
|
||||
UnexpectedRoleAssignment { expected: Role, got: Role },
|
||||
|
||||
#[error("attempted to assign an invalid number of nodes for a role of {role}. got {assigned}, but the maximum allowed is {allowed}")]
|
||||
IllegalRoleCount {
|
||||
role: Role,
|
||||
assigned: u32,
|
||||
allowed: u32,
|
||||
},
|
||||
|
||||
#[error("the epoch is currently not in the 'epoch advancement' state. (the state is {current_state})")]
|
||||
EpochNotInAdvancementState { current_state: EpochState },
|
||||
|
||||
@@ -258,6 +258,17 @@ pub enum MixnetContractError {
|
||||
provided: Uint128,
|
||||
range: OperatingCostRange,
|
||||
},
|
||||
|
||||
#[error(
|
||||
"currently it's not possible to migrate nodes bonded with vesting tokens into a nym-node. please perform vesting->liquid migration first."
|
||||
)]
|
||||
VestingNodeMigration,
|
||||
|
||||
#[error("value {got} does not correspond to any known node role")]
|
||||
UnknownRoleRepresentation { got: u8 },
|
||||
|
||||
#[error("the total work for this epoch seems to be bigger than 1.0!")]
|
||||
TotalWorkAboveOne,
|
||||
}
|
||||
|
||||
impl MixnetContractError {
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::error::MixnetContractError;
|
||||
use crate::gateway::GatewayConfigUpdate;
|
||||
use crate::mixnode::{MixNodeConfigUpdate, MixNodeCostParams};
|
||||
use crate::reward_params::{IntervalRewardParams, IntervalRewardingParamsUpdate};
|
||||
use crate::mixnode::{MixNodeConfigUpdate, NodeCostParams};
|
||||
use crate::nym_node::Role;
|
||||
use crate::reward_params::{ActiveSetUpdate, IntervalRewardParams, IntervalRewardingParamsUpdate};
|
||||
use crate::rewarding::RewardDistribution;
|
||||
use crate::{BlockHeight, ContractStateParams, IdentityKeyRef, Interval, Layer, MixId};
|
||||
use crate::{BlockHeight, ContractStateParams, EpochId, IdentityKeyRef, Interval, NodeId};
|
||||
pub use contracts_common::events::*;
|
||||
use cosmwasm_std::{Addr, Coin, Decimal, Event};
|
||||
use std::fmt::Display;
|
||||
@@ -14,6 +16,11 @@ pub const EVENT_VERSION_PREFIX: &str = "v2_";
|
||||
|
||||
pub enum MixnetEventType {
|
||||
MixnodeBonding,
|
||||
NymNodeBonding,
|
||||
NymNodeUnbonding,
|
||||
PendingNymNodeUnbonding,
|
||||
GatewayMigration,
|
||||
MixnodeMigration,
|
||||
PendingPledgeIncrease,
|
||||
PledgeIncrease,
|
||||
PendingPledgeDecrease,
|
||||
@@ -23,9 +30,9 @@ pub enum MixnetEventType {
|
||||
PendingMixnodeUnbonding,
|
||||
MixnodeUnbonding,
|
||||
MixnodeConfigUpdate,
|
||||
PendingMixnodeCostParamsUpdate,
|
||||
MixnodeCostParamsUpdate,
|
||||
MixnodeRewarding,
|
||||
PendingCostParamsUpdate,
|
||||
CostParamsUpdate,
|
||||
NodeRewarding,
|
||||
WithdrawDelegatorReward,
|
||||
WithdrawOperatorReward,
|
||||
PendingActiveSetUpdate,
|
||||
@@ -41,6 +48,7 @@ pub enum MixnetEventType {
|
||||
RewardingValidatorUpdate,
|
||||
BeginEpochTransition,
|
||||
AdvanceEpoch,
|
||||
RoleAssignment,
|
||||
ExecutePendingEpochEvents,
|
||||
ExecutePendingIntervalEvents,
|
||||
ReconcilePendingEvents,
|
||||
@@ -59,6 +67,11 @@ impl Display for MixnetEventType {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let event_name = match self {
|
||||
MixnetEventType::MixnodeBonding => "mixnode_bonding",
|
||||
MixnetEventType::NymNodeBonding => "nymnode_bonding",
|
||||
MixnetEventType::NymNodeUnbonding => "nymnode_unbonding",
|
||||
MixnetEventType::PendingNymNodeUnbonding => "pending_nymnode_unbonding",
|
||||
MixnetEventType::GatewayMigration => "gateway_migration",
|
||||
MixnetEventType::MixnodeMigration => "mixnode_migration",
|
||||
MixnetEventType::PendingPledgeIncrease => "pending_pledge_increase",
|
||||
MixnetEventType::PledgeIncrease => "pledge_increase",
|
||||
MixnetEventType::PendingPledgeDecrease => "pending_pledge_decrease",
|
||||
@@ -68,9 +81,9 @@ impl Display for MixnetEventType {
|
||||
MixnetEventType::PendingMixnodeUnbonding => "pending_mixnode_unbonding",
|
||||
MixnetEventType::MixnodeConfigUpdate => "mixnode_config_update",
|
||||
MixnetEventType::MixnodeUnbonding => "mixnode_unbonding",
|
||||
MixnetEventType::PendingMixnodeCostParamsUpdate => "pending_mixnode_cost_params_update",
|
||||
MixnetEventType::MixnodeCostParamsUpdate => "mixnode_cost_params_update",
|
||||
MixnetEventType::MixnodeRewarding => "mix_rewarding",
|
||||
MixnetEventType::PendingCostParamsUpdate => "pending_cost_params_update",
|
||||
MixnetEventType::CostParamsUpdate => "cost_params_update",
|
||||
MixnetEventType::NodeRewarding => "node_rewarding",
|
||||
MixnetEventType::WithdrawDelegatorReward => "withdraw_delegator_reward",
|
||||
MixnetEventType::WithdrawOperatorReward => "withdraw_operator_reward",
|
||||
MixnetEventType::PendingActiveSetUpdate => "pending_active_set_update",
|
||||
@@ -87,6 +100,7 @@ impl Display for MixnetEventType {
|
||||
MixnetEventType::RewardingValidatorUpdate => "rewarding_validator_address_update",
|
||||
MixnetEventType::BeginEpochTransition => "beginning_epoch_transition",
|
||||
MixnetEventType::AdvanceEpoch => "advance_epoch",
|
||||
MixnetEventType::RoleAssignment => "role_assignment",
|
||||
MixnetEventType::ExecutePendingEpochEvents => "execute_pending_epoch_events",
|
||||
MixnetEventType::ExecutePendingIntervalEvents => "execute_pending_interval_events",
|
||||
MixnetEventType::ReconcilePendingEvents => "reconcile_pending_events",
|
||||
@@ -103,6 +117,7 @@ impl Display for MixnetEventType {
|
||||
// attributes that are used in multiple places
|
||||
pub const OWNER_KEY: &str = "owner";
|
||||
pub const AMOUNT_KEY: &str = "amount";
|
||||
pub const ERROR_MESSAGE_KEY: &str = "error_message";
|
||||
|
||||
// event-specific attributes
|
||||
|
||||
@@ -113,16 +128,14 @@ pub const UNIT_REWARD_KEY: &str = "unit_reward";
|
||||
|
||||
// bonding/unbonding
|
||||
pub const MIX_ID_KEY: &str = "mix_id";
|
||||
pub const NODE_ID_KEY: &str = "node_id";
|
||||
pub const NODE_IDENTITY_KEY: &str = "identity";
|
||||
pub const ASSIGNED_LAYER_KEY: &str = "assigned_layer";
|
||||
|
||||
// settings change
|
||||
pub const OLD_MINIMUM_MIXNODE_PLEDGE_KEY: &str = "old_minimum_mixnode_pledge";
|
||||
pub const OLD_MINIMUM_GATEWAY_PLEDGE_KEY: &str = "old_minimum_gateway_pledge";
|
||||
pub const OLD_MINIMUM_PLEDGE_KEY: &str = "old_minimum_pledge";
|
||||
pub const OLD_MINIMUM_DELEGATION_KEY: &str = "old_minimum_delegation";
|
||||
|
||||
pub const NEW_MINIMUM_MIXNODE_PLEDGE_KEY: &str = "new_minimum_mixnode_pledge";
|
||||
pub const NEW_MINIMUM_GATEWAY_PLEDGE_KEY: &str = "new_minimum_gateway_pledge";
|
||||
pub const NEW_MINIMUM_PLEDGE_KEY: &str = "new_minimum_pledge";
|
||||
pub const NEW_MINIMUM_DELEGATION_KEY: &str = "new_minimum_delegation";
|
||||
|
||||
pub const OLD_REWARDING_VALIDATOR_ADDRESS_KEY: &str = "old_rewarding_validator_address";
|
||||
@@ -144,14 +157,19 @@ pub const PRIOR_UNIT_REWARD_KEY: &str = "prior_unit_reward";
|
||||
|
||||
pub const NO_REWARD_REASON_KEY: &str = "no_reward_reason";
|
||||
pub const BOND_NOT_FOUND_VALUE: &str = "bond_not_found";
|
||||
pub const ZERO_PERFORMANCE_VALUE: &str = "zero_performance";
|
||||
pub const ZERO_PERFORMANCE_OR_WORK_VALUE: &str = "zero_performance_or_work";
|
||||
|
||||
// rewarded set update
|
||||
pub const ACTIVE_SET_SIZE_KEY: &str = "active_set_size";
|
||||
pub const NUM_MIXNODES_KEY: &str = "num_mixnodes";
|
||||
pub const NUM_ENTRIES_KEY: &str = "num_entry_gateways";
|
||||
pub const NUM_EXITS_KEY: &str = "num_exit_gateways";
|
||||
|
||||
pub const CURRENT_EPOCH_KEY: &str = "current_epoch";
|
||||
pub const NEW_CURRENT_EPOCH_KEY: &str = "new_current_epoch";
|
||||
|
||||
pub const ROLE_KEY: &str = "role";
|
||||
pub const NODE_COUNT_KEY: &str = "node_count";
|
||||
|
||||
// interval
|
||||
pub const EVENTS_EXECUTED_KEY: &str = "number_of_events_executed";
|
||||
pub const EVENT_CREATION_HEIGHT_KEY: &str = "created_at";
|
||||
@@ -163,7 +181,7 @@ pub fn new_delegation_event(
|
||||
created_at: BlockHeight,
|
||||
delegator: &Addr,
|
||||
amount: &Coin,
|
||||
mix_id: MixId,
|
||||
mix_id: NodeId,
|
||||
unit_reward: Decimal,
|
||||
) -> Event {
|
||||
Event::new(MixnetEventType::Delegation)
|
||||
@@ -174,45 +192,57 @@ pub fn new_delegation_event(
|
||||
.add_attribute(UNIT_REWARD_KEY, unit_reward.to_string())
|
||||
}
|
||||
|
||||
pub fn new_delegation_on_unbonded_node_event(delegator: &Addr, mix_id: MixId) -> Event {
|
||||
pub fn new_delegation_on_unbonded_node_event(delegator: &Addr, mix_id: NodeId) -> Event {
|
||||
Event::new(MixnetEventType::Delegation)
|
||||
.add_attribute(DELEGATOR_KEY, delegator)
|
||||
.add_attribute(DELEGATION_TARGET_KEY, mix_id.to_string())
|
||||
}
|
||||
|
||||
pub fn new_pending_delegation_event(delegator: &Addr, amount: &Coin, mix_id: MixId) -> Event {
|
||||
pub fn new_pending_delegation_event(delegator: &Addr, amount: &Coin, mix_id: NodeId) -> Event {
|
||||
Event::new(MixnetEventType::PendingDelegation)
|
||||
.add_attribute(DELEGATOR_KEY, delegator)
|
||||
.add_attribute(AMOUNT_KEY, amount.to_string())
|
||||
.add_attribute(DELEGATION_TARGET_KEY, mix_id.to_string())
|
||||
}
|
||||
|
||||
pub fn new_withdraw_operator_reward_event(owner: &Addr, amount: Coin, mix_id: MixId) -> Event {
|
||||
pub fn new_withdraw_operator_reward_event(owner: &Addr, amount: Coin, mix_id: NodeId) -> Event {
|
||||
Event::new(MixnetEventType::WithdrawOperatorReward)
|
||||
.add_attribute(OWNER_KEY, owner.as_str())
|
||||
.add_attribute(AMOUNT_KEY, amount.to_string())
|
||||
.add_attribute(MIX_ID_KEY, mix_id.to_string())
|
||||
}
|
||||
|
||||
pub fn new_withdraw_delegator_reward_event(delegator: &Addr, amount: Coin, mix_id: MixId) -> Event {
|
||||
pub fn new_withdraw_delegator_reward_event(
|
||||
delegator: &Addr,
|
||||
amount: Coin,
|
||||
mix_id: NodeId,
|
||||
) -> Event {
|
||||
Event::new(MixnetEventType::WithdrawDelegatorReward)
|
||||
.add_attribute(DELEGATOR_KEY, delegator)
|
||||
.add_attribute(AMOUNT_KEY, amount.to_string())
|
||||
.add_attribute(DELEGATION_TARGET_KEY, mix_id.to_string())
|
||||
}
|
||||
|
||||
pub fn new_active_set_update_event(created_at: BlockHeight, new_size: u32) -> Event {
|
||||
pub fn new_active_set_update_failure(err: MixnetContractError) -> Event {
|
||||
Event::new(MixnetEventType::ActiveSetUpdate).add_attribute(ERROR_MESSAGE_KEY, err.to_string())
|
||||
}
|
||||
|
||||
pub fn new_active_set_update_event(created_at: BlockHeight, update: ActiveSetUpdate) -> Event {
|
||||
Event::new(MixnetEventType::ActiveSetUpdate)
|
||||
.add_attribute(EVENT_CREATION_HEIGHT_KEY, created_at.to_string())
|
||||
.add_attribute(ACTIVE_SET_SIZE_KEY, new_size.to_string())
|
||||
.add_attribute(NUM_MIXNODES_KEY, update.mixnodes.to_string())
|
||||
.add_attribute(NUM_ENTRIES_KEY, update.entry_gateways.to_string())
|
||||
.add_attribute(NUM_EXITS_KEY, update.exit_gateways.to_string())
|
||||
}
|
||||
|
||||
pub fn new_pending_active_set_update_event(
|
||||
new_size: u32,
|
||||
update: ActiveSetUpdate,
|
||||
approximate_time_remaining_secs: i64,
|
||||
) -> Event {
|
||||
Event::new(MixnetEventType::PendingActiveSetUpdate)
|
||||
.add_attribute(ACTIVE_SET_SIZE_KEY, new_size.to_string())
|
||||
.add_attribute(NUM_MIXNODES_KEY, update.mixnodes.to_string())
|
||||
.add_attribute(NUM_ENTRIES_KEY, update.entry_gateways.to_string())
|
||||
.add_attribute(NUM_EXITS_KEY, update.exit_gateways.to_string())
|
||||
.add_attribute(
|
||||
APPROXIMATE_TIME_LEFT_SECS_KEY,
|
||||
approximate_time_remaining_secs.to_string(),
|
||||
@@ -221,7 +251,6 @@ pub fn new_pending_active_set_update_event(
|
||||
|
||||
pub fn new_rewarding_params_update_event(
|
||||
created_at: BlockHeight,
|
||||
|
||||
update: IntervalRewardingParamsUpdate,
|
||||
updated: IntervalRewardParams,
|
||||
) -> Event {
|
||||
@@ -252,30 +281,19 @@ pub fn new_pending_rewarding_params_update_event(
|
||||
)
|
||||
}
|
||||
|
||||
pub fn new_undelegation_event(created_at: BlockHeight, delegator: &Addr, mix_id: MixId) -> Event {
|
||||
pub fn new_undelegation_event(created_at: BlockHeight, delegator: &Addr, mix_id: NodeId) -> Event {
|
||||
Event::new(MixnetEventType::Undelegation)
|
||||
.add_attribute(EVENT_CREATION_HEIGHT_KEY, created_at.to_string())
|
||||
.add_attribute(DELEGATOR_KEY, delegator)
|
||||
.add_attribute(MIX_ID_KEY, mix_id.to_string())
|
||||
}
|
||||
|
||||
pub fn new_pending_undelegation_event(delegator: &Addr, mix_id: MixId) -> Event {
|
||||
pub fn new_pending_undelegation_event(delegator: &Addr, mix_id: NodeId) -> Event {
|
||||
Event::new(MixnetEventType::PendingUndelegation)
|
||||
.add_attribute(DELEGATOR_KEY, delegator)
|
||||
.add_attribute(MIX_ID_KEY, mix_id.to_string())
|
||||
}
|
||||
|
||||
pub fn new_gateway_bonding_event(
|
||||
owner: &Addr,
|
||||
amount: &Coin,
|
||||
identity: IdentityKeyRef<'_>,
|
||||
) -> Event {
|
||||
Event::new(MixnetEventType::GatewayBonding)
|
||||
.add_attribute(OWNER_KEY, owner)
|
||||
.add_attribute(NODE_IDENTITY_KEY, identity)
|
||||
.add_attribute(AMOUNT_KEY, amount.to_string())
|
||||
}
|
||||
|
||||
pub fn new_gateway_unbonding_event(
|
||||
owner: &Addr,
|
||||
amount: &Coin,
|
||||
@@ -287,49 +305,85 @@ pub fn new_gateway_unbonding_event(
|
||||
.add_attribute(AMOUNT_KEY, amount.to_string())
|
||||
}
|
||||
|
||||
pub fn new_mixnode_bonding_event(
|
||||
pub fn new_nym_node_bonding_event(
|
||||
owner: &Addr,
|
||||
amount: &Coin,
|
||||
identity: IdentityKeyRef<'_>,
|
||||
mix_id: MixId,
|
||||
assigned_layer: Layer,
|
||||
node_id: NodeId,
|
||||
) -> Event {
|
||||
// coin implements Display trait and we use that implementation here
|
||||
Event::new(MixnetEventType::MixnodeBonding)
|
||||
.add_attribute(MIX_ID_KEY, mix_id.to_string())
|
||||
Event::new(MixnetEventType::NymNodeBonding)
|
||||
.add_attribute(NODE_ID_KEY, node_id.to_string())
|
||||
.add_attribute(NODE_IDENTITY_KEY, identity)
|
||||
.add_attribute(OWNER_KEY, owner)
|
||||
.add_attribute(ASSIGNED_LAYER_KEY, assigned_layer)
|
||||
.add_attribute(AMOUNT_KEY, amount.to_string())
|
||||
}
|
||||
|
||||
pub fn new_pending_pledge_increase_event(mix_id: MixId, amount: &Coin) -> Event {
|
||||
pub fn new_nym_node_unbonding_event(created_at: BlockHeight, node_id: NodeId) -> Event {
|
||||
Event::new(MixnetEventType::NymNodeUnbonding)
|
||||
.add_attribute(EVENT_CREATION_HEIGHT_KEY, created_at.to_string())
|
||||
.add_attribute(NODE_ID_KEY, node_id.to_string())
|
||||
}
|
||||
|
||||
pub fn new_pending_nym_node_unbonding_event(
|
||||
owner: &Addr,
|
||||
identity: IdentityKeyRef<'_>,
|
||||
node_id: NodeId,
|
||||
) -> Event {
|
||||
Event::new(MixnetEventType::PendingNymNodeUnbonding)
|
||||
.add_attribute(NODE_ID_KEY, node_id.to_string())
|
||||
.add_attribute(NODE_IDENTITY_KEY, identity)
|
||||
.add_attribute(OWNER_KEY, owner)
|
||||
}
|
||||
|
||||
pub fn new_migrated_gateway_event(
|
||||
owner: &Addr,
|
||||
identity: IdentityKeyRef<'_>,
|
||||
node_id: NodeId,
|
||||
) -> Event {
|
||||
Event::new(MixnetEventType::GatewayMigration)
|
||||
.add_attribute(NODE_ID_KEY, node_id.to_string())
|
||||
.add_attribute(NODE_IDENTITY_KEY, identity)
|
||||
.add_attribute(OWNER_KEY, owner)
|
||||
}
|
||||
|
||||
pub fn new_migrated_mixnode_event(
|
||||
owner: &Addr,
|
||||
identity: IdentityKeyRef<'_>,
|
||||
node_id: NodeId,
|
||||
) -> Event {
|
||||
Event::new(MixnetEventType::MixnodeMigration)
|
||||
.add_attribute(NODE_ID_KEY, node_id.to_string())
|
||||
.add_attribute(NODE_IDENTITY_KEY, identity)
|
||||
.add_attribute(OWNER_KEY, owner)
|
||||
}
|
||||
|
||||
pub fn new_pending_pledge_increase_event(node_id: NodeId, amount: &Coin) -> Event {
|
||||
Event::new(MixnetEventType::PendingPledgeIncrease)
|
||||
.add_attribute(MIX_ID_KEY, mix_id.to_string())
|
||||
.add_attribute(NODE_ID_KEY, node_id.to_string())
|
||||
.add_attribute(AMOUNT_KEY, amount.to_string())
|
||||
}
|
||||
|
||||
pub fn new_pledge_increase_event(created_at: BlockHeight, mix_id: MixId, amount: &Coin) -> Event {
|
||||
pub fn new_pledge_increase_event(created_at: BlockHeight, node_id: NodeId, amount: &Coin) -> Event {
|
||||
Event::new(MixnetEventType::PledgeIncrease)
|
||||
.add_attribute(EVENT_CREATION_HEIGHT_KEY, created_at.to_string())
|
||||
.add_attribute(MIX_ID_KEY, mix_id.to_string())
|
||||
.add_attribute(NODE_ID_KEY, node_id.to_string())
|
||||
.add_attribute(AMOUNT_KEY, amount.to_string())
|
||||
}
|
||||
|
||||
pub fn new_pending_pledge_decrease_event(mix_id: MixId, amount: &Coin) -> Event {
|
||||
pub fn new_pending_pledge_decrease_event(node_id: NodeId, amount: &Coin) -> Event {
|
||||
Event::new(MixnetEventType::PendingPledgeDecrease)
|
||||
.add_attribute(MIX_ID_KEY, mix_id.to_string())
|
||||
.add_attribute(NODE_ID_KEY, node_id.to_string())
|
||||
.add_attribute(AMOUNT_KEY, amount.to_string())
|
||||
}
|
||||
|
||||
pub fn new_pledge_decrease_event(created_at: BlockHeight, mix_id: MixId, amount: &Coin) -> Event {
|
||||
pub fn new_pledge_decrease_event(created_at: BlockHeight, node_id: NodeId, amount: &Coin) -> Event {
|
||||
Event::new(MixnetEventType::PledgeDecrease)
|
||||
.add_attribute(EVENT_CREATION_HEIGHT_KEY, created_at.to_string())
|
||||
.add_attribute(MIX_ID_KEY, mix_id.to_string())
|
||||
.add_attribute(NODE_ID_KEY, node_id.to_string())
|
||||
.add_attribute(AMOUNT_KEY, amount.to_string())
|
||||
}
|
||||
|
||||
pub fn new_mixnode_unbonding_event(created_at: BlockHeight, mix_id: MixId) -> Event {
|
||||
pub fn new_mixnode_unbonding_event(created_at: BlockHeight, mix_id: NodeId) -> Event {
|
||||
Event::new(MixnetEventType::MixnodeUnbonding)
|
||||
.add_attribute(EVENT_CREATION_HEIGHT_KEY, created_at.to_string())
|
||||
.add_attribute(MIX_ID_KEY, mix_id.to_string())
|
||||
@@ -338,7 +392,7 @@ pub fn new_mixnode_unbonding_event(created_at: BlockHeight, mix_id: MixId) -> Ev
|
||||
pub fn new_pending_mixnode_unbonding_event(
|
||||
owner: &Addr,
|
||||
identity: IdentityKeyRef<'_>,
|
||||
mix_id: MixId,
|
||||
mix_id: NodeId,
|
||||
) -> Event {
|
||||
Event::new(MixnetEventType::PendingMixnodeUnbonding)
|
||||
.add_attribute(MIX_ID_KEY, mix_id.to_string())
|
||||
@@ -347,7 +401,7 @@ pub fn new_pending_mixnode_unbonding_event(
|
||||
}
|
||||
|
||||
pub fn new_mixnode_config_update_event(
|
||||
mix_id: MixId,
|
||||
mix_id: NodeId,
|
||||
owner: &Addr,
|
||||
update: &MixNodeConfigUpdate,
|
||||
) -> Event {
|
||||
@@ -363,23 +417,18 @@ pub fn new_gateway_config_update_event(owner: &Addr, update: &GatewayConfigUpdat
|
||||
.add_attribute(UPDATED_GATEWAY_CONFIG_KEY, update.to_inline_json())
|
||||
}
|
||||
|
||||
pub fn new_mixnode_pending_cost_params_update_event(
|
||||
mix_id: MixId,
|
||||
owner: &Addr,
|
||||
new_costs: &MixNodeCostParams,
|
||||
) -> Event {
|
||||
Event::new(MixnetEventType::PendingMixnodeCostParamsUpdate)
|
||||
.add_attribute(MIX_ID_KEY, mix_id.to_string())
|
||||
.add_attribute(OWNER_KEY, owner)
|
||||
pub fn new_pending_cost_params_update_event(mix_id: NodeId, new_costs: &NodeCostParams) -> Event {
|
||||
Event::new(MixnetEventType::PendingCostParamsUpdate)
|
||||
.add_attribute(NODE_ID_KEY, mix_id.to_string())
|
||||
.add_attribute(UPDATED_MIXNODE_COST_PARAMS_KEY, new_costs.to_inline_json())
|
||||
}
|
||||
|
||||
pub fn new_mixnode_cost_params_update_event(
|
||||
pub fn new_cost_params_update_event(
|
||||
created_at: BlockHeight,
|
||||
mix_id: MixId,
|
||||
new_costs: &MixNodeCostParams,
|
||||
mix_id: NodeId,
|
||||
new_costs: &NodeCostParams,
|
||||
) -> Event {
|
||||
Event::new(MixnetEventType::MixnodeCostParamsUpdate)
|
||||
Event::new(MixnetEventType::CostParamsUpdate)
|
||||
.add_attribute(EVENT_CREATION_HEIGHT_KEY, created_at.to_string())
|
||||
.add_attribute(MIX_ID_KEY, mix_id.to_string())
|
||||
.add_attribute(UPDATED_MIXNODE_COST_PARAMS_KEY, new_costs.to_inline_json())
|
||||
@@ -397,37 +446,25 @@ pub fn new_settings_update_event(
|
||||
) -> Event {
|
||||
let mut event = Event::new(MixnetEventType::ContractSettingsUpdate);
|
||||
|
||||
if old_params.minimum_mixnode_pledge != new_params.minimum_mixnode_pledge {
|
||||
if old_params.minimum_pledge != new_params.minimum_pledge {
|
||||
event = event
|
||||
.add_attribute(
|
||||
OLD_MINIMUM_MIXNODE_PLEDGE_KEY,
|
||||
old_params.minimum_mixnode_pledge.to_string(),
|
||||
OLD_MINIMUM_PLEDGE_KEY,
|
||||
old_params.minimum_pledge.to_string(),
|
||||
)
|
||||
.add_attribute(
|
||||
NEW_MINIMUM_MIXNODE_PLEDGE_KEY,
|
||||
new_params.minimum_mixnode_pledge.to_string(),
|
||||
NEW_MINIMUM_PLEDGE_KEY,
|
||||
new_params.minimum_pledge.to_string(),
|
||||
)
|
||||
}
|
||||
|
||||
if old_params.minimum_gateway_pledge != new_params.minimum_gateway_pledge {
|
||||
event = event
|
||||
.add_attribute(
|
||||
OLD_MINIMUM_GATEWAY_PLEDGE_KEY,
|
||||
old_params.minimum_gateway_pledge.to_string(),
|
||||
)
|
||||
.add_attribute(
|
||||
NEW_MINIMUM_GATEWAY_PLEDGE_KEY,
|
||||
new_params.minimum_gateway_pledge.to_string(),
|
||||
)
|
||||
}
|
||||
|
||||
if old_params.minimum_mixnode_delegation != new_params.minimum_mixnode_delegation {
|
||||
if let Some(ref old) = old_params.minimum_mixnode_delegation {
|
||||
if old_params.minimum_delegation != new_params.minimum_delegation {
|
||||
if let Some(ref old) = old_params.minimum_delegation {
|
||||
event = event.add_attribute(OLD_MINIMUM_DELEGATION_KEY, old.to_string())
|
||||
} else {
|
||||
event = event.add_attribute(OLD_MINIMUM_DELEGATION_KEY, "None")
|
||||
}
|
||||
if let Some(ref new) = new_params.minimum_mixnode_delegation {
|
||||
if let Some(ref new) = new_params.minimum_delegation {
|
||||
event = event.add_attribute(NEW_MINIMUM_DELEGATION_KEY, new.to_string())
|
||||
} else {
|
||||
event = event.add_attribute(NEW_MINIMUM_DELEGATION_KEY, "None")
|
||||
@@ -437,41 +474,41 @@ pub fn new_settings_update_event(
|
||||
event
|
||||
}
|
||||
|
||||
pub fn new_not_found_mix_operator_rewarding_event(interval: Interval, mix_id: MixId) -> Event {
|
||||
Event::new(MixnetEventType::MixnodeRewarding)
|
||||
pub fn new_not_found_node_operator_rewarding_event(interval: Interval, node_id: NodeId) -> Event {
|
||||
Event::new(MixnetEventType::NodeRewarding)
|
||||
.add_attribute(
|
||||
INTERVAL_KEY,
|
||||
interval.current_epoch_absolute_id().to_string(),
|
||||
)
|
||||
.add_attribute(MIX_ID_KEY, mix_id.to_string())
|
||||
.add_attribute(NODE_ID_KEY, node_id.to_string())
|
||||
.add_attribute(NO_REWARD_REASON_KEY, BOND_NOT_FOUND_VALUE)
|
||||
}
|
||||
|
||||
pub fn new_zero_uptime_mix_operator_rewarding_event(interval: Interval, mix_id: MixId) -> Event {
|
||||
Event::new(MixnetEventType::MixnodeRewarding)
|
||||
pub fn new_zero_uptime_mix_operator_rewarding_event(interval: Interval, node_id: NodeId) -> Event {
|
||||
Event::new(MixnetEventType::NodeRewarding)
|
||||
.add_attribute(
|
||||
INTERVAL_KEY,
|
||||
interval.current_epoch_absolute_id().to_string(),
|
||||
)
|
||||
.add_attribute(MIX_ID_KEY, mix_id.to_string())
|
||||
.add_attribute(NO_REWARD_REASON_KEY, ZERO_PERFORMANCE_VALUE)
|
||||
.add_attribute(NODE_ID_KEY, node_id.to_string())
|
||||
.add_attribute(NO_REWARD_REASON_KEY, ZERO_PERFORMANCE_OR_WORK_VALUE)
|
||||
}
|
||||
|
||||
pub fn new_mix_rewarding_event(
|
||||
interval: Interval,
|
||||
mix_id: MixId,
|
||||
node_id: NodeId,
|
||||
reward_distribution: RewardDistribution,
|
||||
prior_delegates: Decimal,
|
||||
prior_unit_reward: Decimal,
|
||||
) -> Event {
|
||||
Event::new(MixnetEventType::MixnodeRewarding)
|
||||
Event::new(MixnetEventType::NodeRewarding)
|
||||
.add_attribute(
|
||||
INTERVAL_KEY,
|
||||
interval.current_epoch_absolute_id().to_string(),
|
||||
)
|
||||
.add_attribute(PRIOR_DELEGATES_KEY, prior_delegates.to_string())
|
||||
.add_attribute(PRIOR_UNIT_REWARD_KEY, prior_unit_reward.to_string())
|
||||
.add_attribute(MIX_ID_KEY, mix_id.to_string())
|
||||
.add_attribute(NODE_ID_KEY, node_id.to_string())
|
||||
.add_attribute(
|
||||
OPERATOR_REWARD_KEY,
|
||||
reward_distribution.operator.to_string(),
|
||||
@@ -489,13 +526,15 @@ pub fn new_epoch_transition_start_event(current_interval: Interval) -> Event {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn new_advance_epoch_event(interval: Interval, rewarded_nodes: u32) -> Event {
|
||||
pub fn new_assigned_role_event(role: Role, nodes: u32) -> Event {
|
||||
Event::new(MixnetEventType::RoleAssignment)
|
||||
.add_attribute(ROLE_KEY, role.to_string())
|
||||
.add_attribute(NODE_COUNT_KEY, nodes.to_string())
|
||||
}
|
||||
|
||||
pub fn new_advance_epoch_event(epoch_id: EpochId) -> Event {
|
||||
Event::new(MixnetEventType::AdvanceEpoch)
|
||||
.add_attribute(
|
||||
NEW_CURRENT_EPOCH_KEY,
|
||||
interval.current_epoch_absolute_id().to_string(),
|
||||
)
|
||||
.add_attribute(REWARDED_SET_NODES_KEY, rewarded_nodes.to_string())
|
||||
.add_attribute(NEW_CURRENT_EPOCH_KEY, epoch_id.to_string())
|
||||
}
|
||||
|
||||
pub fn new_pending_epoch_events_execution_event(executed: u32) -> Event {
|
||||
|
||||
@@ -1,189 +0,0 @@
|
||||
// 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 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")
|
||||
)]
|
||||
#[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",
|
||||
ts(export_to = "ts-packages/types/src/types/rust/NodeFamilyHead.ts")
|
||||
)]
|
||||
#[derive(Debug, Clone, Eq, PartialEq, JsonSchema)]
|
||||
pub struct FamilyHead(IdentityKey);
|
||||
|
||||
impl Serialize for FamilyHead {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
self.0.serialize(serializer)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for FamilyHead {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let inner = IdentityKey::deserialize(deserializer)?;
|
||||
Ok(FamilyHead(inner))
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for FamilyHead {
|
||||
type Err = <IdentityKey as FromStr>::Err;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
// theoretically we should be verifying whether it's a valid base58 value
|
||||
// (or even better, whether it's a valid ed25519 public key), but definition of
|
||||
// `FamilyHead` might change later
|
||||
Ok(FamilyHead(IdentityKey::from_str(s)?))
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for FamilyHead {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
self.0.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl FamilyHead {
|
||||
pub fn new<S: Into<String>>(identity: S) -> Self {
|
||||
FamilyHead(identity.into())
|
||||
}
|
||||
|
||||
pub fn identity(&self) -> IdentityKeyRef<'_> {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Family {
|
||||
pub fn new(head: FamilyHead, label: String) -> Self {
|
||||
Family {
|
||||
head,
|
||||
proxy: None,
|
||||
label,
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn head(&self) -> &FamilyHead {
|
||||
&self.head
|
||||
}
|
||||
|
||||
pub fn head_identity(&self) -> IdentityKeyRef<'_> {
|
||||
self.head.identity()
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn proxy(&self) -> Option<&String> {
|
||||
self.proxy.as_ref()
|
||||
}
|
||||
|
||||
pub fn label(&self) -> &str {
|
||||
&self.label
|
||||
}
|
||||
}
|
||||
|
||||
/// 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::*;
|
||||
|
||||
#[test]
|
||||
fn family_head_serde() {
|
||||
let dummy = FamilyHead::new("foomp");
|
||||
|
||||
let ser_str = serde_json_wasm::to_string(&dummy).unwrap();
|
||||
let de_str: FamilyHead = serde_json_wasm::from_str(&ser_str).unwrap();
|
||||
assert_eq!(dummy, de_str);
|
||||
|
||||
let ser_bytes = serde_json_wasm::to_vec(&dummy).unwrap();
|
||||
let de_bytes: FamilyHead = serde_json_wasm::from_slice(&ser_bytes).unwrap();
|
||||
assert_eq!(dummy, de_bytes);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::{IdentityKey, SphinxKey};
|
||||
use crate::{IdentityKey, NodeId, SphinxKey};
|
||||
use cosmwasm_schema::cw_serde;
|
||||
use cosmwasm_std::{Addr, Coin};
|
||||
use std::cmp::Ordering;
|
||||
@@ -135,7 +135,10 @@ impl Display for GatewayBond {
|
||||
#[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))]
|
||||
#[cfg_attr(
|
||||
feature = "generate-ts",
|
||||
ts(export_to = "ts-packages/types/src/types/rust/GatewayConfigUpdate.ts")
|
||||
ts(
|
||||
export,
|
||||
export_to = "ts-packages/types/src/types/rust/GatewayConfigUpdate.ts"
|
||||
)
|
||||
)]
|
||||
#[cw_serde]
|
||||
pub struct GatewayConfigUpdate {
|
||||
@@ -200,6 +203,23 @@ pub struct GatewayBondResponse {
|
||||
pub gateway: Option<GatewayBond>,
|
||||
}
|
||||
|
||||
#[cw_serde]
|
||||
pub struct PreassignedId {
|
||||
/// The identity key (base58-encoded ed25519 public key) of the gateway.
|
||||
pub identity: IdentityKey,
|
||||
|
||||
/// The id pre-assigned to this gateway
|
||||
pub node_id: NodeId,
|
||||
}
|
||||
|
||||
#[cw_serde]
|
||||
pub struct PreassignedGatewayIdsResponse {
|
||||
pub ids: Vec<PreassignedId>,
|
||||
|
||||
/// Field indicating paging information for the following queries if the caller wishes to get further entries.
|
||||
pub start_next_after: Option<IdentityKey>,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user