Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7a9f13c08d | |||
| 6b1b04f53c | |||
| 6723690584 | |||
| c4d7c9eb16 | |||
| afa2f07636 | |||
| 5dd2acfcac | |||
| 03c702d498 | |||
| c7dbcc097d | |||
| 80f6c2c32a | |||
| c9a36a21a1 | |||
| 9eb4ca3aad |
@@ -0,0 +1,9 @@
|
||||
# Description
|
||||
|
||||
Closes: #XXXX
|
||||
|
||||
<!-- If appropriate, insert relevant description here -->
|
||||
|
||||
# Checklist:
|
||||
|
||||
- [ ] added a changelog entry to `CHANGELOG.md`
|
||||
@@ -9,11 +9,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Install Dependencies (Linux)
|
||||
run: sudo apt-get update && sudo apt-get install -y build-essential curl wget libssl-dev libudev-dev squashfs-tools protobuf-compiler git python3 && sudo apt-get update --fix-missing
|
||||
- name: Install pip3
|
||||
run: sudo apt install -y python3-pip
|
||||
- name: Install Python3 modules
|
||||
run: sudo pip3 install pandas tabulate
|
||||
run: sudo apt-get update && sudo apt-get install -y build-essential curl wget libssl-dev libudev-dev squashfs-tools protobuf-compiler
|
||||
- name: Install rsync
|
||||
run: sudo apt-get install rsync
|
||||
- uses: rlespinasse/github-slug-action@v3.x
|
||||
@@ -34,24 +30,9 @@ jobs:
|
||||
- name: Remove existing Nym config directory (`~/.nym/`)
|
||||
run: cd documentation && ./remove_existing_config.sh
|
||||
continue-on-error: false
|
||||
# This is the original flow
|
||||
# - name: Build all projects in documentation/ & move to ~/dist/docs/
|
||||
# run: cd documentation && ./build_all_to_dist.sh
|
||||
|
||||
# This is a workaround replacement which builds on the last working commit b332a6b55668f60988e36961f3f62a794ba82ddb and then on current branch
|
||||
- name: Save current branch to ~/current_branch
|
||||
run: git rev-parse --abbrev-ref HEAD > ~/current_branch
|
||||
- name: Git pull & switch to b332a6b55668f60988e36961f3f62a794ba82ddb
|
||||
run: git pull && git checkout b332a6b55668f60988e36961f3f62a794ba82ddb
|
||||
- name: Build all projects in documentation/ & move to ~/dist/docs/ from b332a6b55668f60988e36961f3f62a794ba82ddb
|
||||
- name: Build all projects in documentation/ & move to ~/dist/docs/
|
||||
run: cd documentation && ./build_all_to_dist.sh
|
||||
|
||||
- name: Switch to current branch
|
||||
run: git checkout $echo "$(cat ~/current_branch)"
|
||||
- name: Build all projects in documentation/ & move to ~/dist/docs/ on current branch
|
||||
run: cd documentation && ./build_all_to_dist.sh && rm ~/current_branch
|
||||
|
||||
# End of replacemet
|
||||
continue-on-error: false
|
||||
|
||||
- name: Post process
|
||||
run: cd documentation && ./post_process.sh
|
||||
|
||||
@@ -112,7 +112,6 @@ jobs:
|
||||
target/release/nym-network-statistics
|
||||
target/release/nym-cli
|
||||
target/release/nymvisor
|
||||
target/release/nym-node
|
||||
retention-days: 30
|
||||
|
||||
# If this was a pull_request or nightly, upload to build server
|
||||
@@ -131,7 +130,6 @@ jobs:
|
||||
cp target/release/nym-network-requester $OUTPUT_DIR
|
||||
cp target/release/nym-network-statistics $OUTPUT_DIR
|
||||
cp target/release/nymvisor $OUTPUT_DIR
|
||||
cp target/release/nym-node $OUTPUT_DIR
|
||||
cp target/release/nym-cli $OUTPUT_DIR
|
||||
cp target/release/explorer-api $OUTPUT_DIR
|
||||
if [ ${{ github.event_name == 'workflow_dispatch' && inputs.enable_deb == true }} = true ]; then
|
||||
|
||||
@@ -35,7 +35,7 @@ jobs:
|
||||
- name: Install Rust stable
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: 1.77
|
||||
toolchain: stable
|
||||
target: wasm32-unknown-unknown
|
||||
override: true
|
||||
|
||||
@@ -58,6 +58,8 @@ jobs:
|
||||
cp contracts/target/wasm32-unknown-unknown/release/nym_coconut_dkg.wasm $OUTPUT_DIR
|
||||
cp contracts/target/wasm32-unknown-unknown/release/cw3_flex_multisig.wasm $OUTPUT_DIR
|
||||
cp contracts/target/wasm32-unknown-unknown/release/cw4_group.wasm $OUTPUT_DIR
|
||||
cp contracts/target/wasm32-unknown-unknown/release/nym_service_provider_directory.wasm $OUTPUT_DIR
|
||||
cp contracts/target/wasm32-unknown-unknown/release/nym_name_service.wasm $OUTPUT_DIR
|
||||
|
||||
- name: Deploy branch to CI www
|
||||
continue-on-error: true
|
||||
|
||||
@@ -13,11 +13,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Install Dependencies (Linux)
|
||||
run: sudo apt-get update && sudo apt-get install -y build-essential curl wget libssl-dev libudev-dev squashfs-tools protobuf-compiler git python3 && sudo apt-get update --fix-missing
|
||||
- name: Install pip3
|
||||
run: sudo apt install -y python3-pip
|
||||
- name: Install Python3 modules
|
||||
run: sudo pip3 install pandas tabulate
|
||||
run: sudo apt-get update && sudo apt-get install -y build-essential curl wget libssl-dev libudev-dev squashfs-tools protobuf-compiler
|
||||
- name: Install rsync
|
||||
run: sudo apt-get install rsync
|
||||
- uses: rlespinasse/github-slug-action@v3.x
|
||||
@@ -38,25 +34,9 @@ jobs:
|
||||
- name: Remove existing Nym config directory (`~/.nym/`)
|
||||
run: cd documentation && ./remove_existing_config.sh
|
||||
continue-on-error: false
|
||||
|
||||
# This is the original flow
|
||||
# - name: Build all projects in documentation/ & move to ~/dist/docs/
|
||||
# run: cd documentation && ./build_all_to_dist.sh
|
||||
|
||||
# This is a workaround replacement which builds on the last working commit b332a6b55668f60988e36961f3f62a794ba82ddb and then on current branch
|
||||
- name: Save current branch to ~/current_branch
|
||||
run: git rev-parse --abbrev-ref HEAD > ~/current_branch
|
||||
- name: Git pull & switch to b332a6b55668f60988e36961f3f62a794ba82ddb
|
||||
run: git pull && git checkout b332a6b55668f60988e36961f3f62a794ba82ddb
|
||||
- name: Build all projects in documentation/ & move to ~/dist/docs/ from b332a6b55668f60988e36961f3f62a794ba82ddb
|
||||
- name: Build all projects in documentation/ & move to ~/dist/docs/
|
||||
run: cd documentation && ./build_all_to_dist.sh
|
||||
|
||||
- name: Switch to current branch
|
||||
run: git checkout $echo "$(cat ~/current_branch)"
|
||||
- name: Build all projects in documentation/ & move to ~/dist/docs/ on current branch
|
||||
run: cd documentation && ./build_all_to_dist.sh && rm ~/current_branch
|
||||
|
||||
# End of replacemet
|
||||
continue-on-error: false
|
||||
|
||||
- name: Deploy branch to CI www
|
||||
continue-on-error: true
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
name: ci-nym-connect-desktop-rust
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- "nym-connect/desktop/src-tauri/**"
|
||||
- "nym-connect/desktop/src-tauri/Cargo.toml"
|
||||
- "clients/client-core/**"
|
||||
- "clients/socks5/**"
|
||||
- "common/**"
|
||||
- "gateway/gateway-requests/**"
|
||||
- "contracts/vesting/**"
|
||||
- "nym-api/nym-api-requests/**"
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: [self-hosted, custom-linux]
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
steps:
|
||||
- name: Install Dependencies (Linux)
|
||||
run: sudo apt-get update && sudo apt-get -y install libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev squashfs-tools libayatana-appindicator3-dev
|
||||
continue-on-error: true
|
||||
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- 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: --manifest-path nym-connect/desktop/Cargo.toml --all -- --check
|
||||
|
||||
- name: Build all binaries
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: build
|
||||
args: --manifest-path nym-connect/desktop/Cargo.toml --workspace
|
||||
|
||||
- name: Run all tests
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: test
|
||||
args: --manifest-path nym-connect/desktop/Cargo.toml --workspace
|
||||
|
||||
- uses: actions-rs/clippy-check@v1
|
||||
name: Clippy checks
|
||||
continue-on-error: true
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
args: --manifest-path nym-connect/desktop/Cargo.toml --workspace --all-features
|
||||
|
||||
- name: Run clippy
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: clippy
|
||||
args: --manifest-path nym-connect/desktop/Cargo.toml --workspace --all-features -- -D warnings
|
||||
@@ -0,0 +1,72 @@
|
||||
name: ci-nym-connect-desktop
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- 'nym-connect/desktop/**'
|
||||
|
||||
defaults:
|
||||
run:
|
||||
working-directory: nym-connect/desktop
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: custom-linux
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Install rsync
|
||||
run: sudo apt-get install rsync
|
||||
continue-on-error: true
|
||||
- uses: rlespinasse/github-slug-action@v3.x
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18
|
||||
- name: Install Yarn
|
||||
run: npm install -g yarn
|
||||
- name: Install Rust stable
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
- name: Install wasm-pack
|
||||
run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
|
||||
- name: Install project dependencies
|
||||
run: cd ../.. && yarn --network-timeout 100000
|
||||
|
||||
- name: Install app dependencies
|
||||
run: yarn
|
||||
continue-on-error: true
|
||||
|
||||
- name: Set environment from the example
|
||||
run: cp .env.sample .env
|
||||
- run: yarn storybook:build
|
||||
- name: Deploy branch to CI www
|
||||
continue-on-error: true
|
||||
uses: easingthemes/ssh-deploy@main
|
||||
env:
|
||||
SSH_PRIVATE_KEY: ${{ secrets.CI_WWW_SSH_PRIVATE_KEY }}
|
||||
ARGS: "-rltgoDzvO --delete"
|
||||
SOURCE: "nym-connect/desktop/storybook-static/"
|
||||
REMOTE_HOST: ${{ secrets.CI_WWW_REMOTE_HOST }}
|
||||
REMOTE_USER: ${{ secrets.CI_WWW_REMOTE_USER }}
|
||||
TARGET: ${{ secrets.CI_WWW_REMOTE_TARGET }}/nym-connect-${{ env.GITHUB_REF_SLUG }}
|
||||
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: nym-connect
|
||||
NYM_PROJECT_NAME: "nym-connect"
|
||||
NYM_CI_WWW_BASE: "${{ secrets.NYM_CI_WWW_BASE }}"
|
||||
NYM_CI_WWW_LOCATION: "nym-connect-${{ 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
|
||||
@@ -17,7 +17,7 @@ jobs:
|
||||
- uses: rlespinasse/github-slug-action@v3.x
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18.17
|
||||
node-version: 18
|
||||
- name: Install Rust stable
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
name: nightly-nym-connect-desktop-build
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: '14 1 * * *'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-20.04, macos-latest, windows-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
MANIFEST_PATH: --manifest-path nym-connect/desktop/Cargo.toml
|
||||
continue-on-error: true
|
||||
steps:
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Install Dependencies (Linux)
|
||||
run: sudo apt-get update && sudo apt-get install -y libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev squashfs-tools
|
||||
if: matrix.os == 'ubuntu-20.04'
|
||||
|
||||
- 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 }} --release --workspace
|
||||
|
||||
- name: Unit tests
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: test
|
||||
args: ${{ env.MANIFEST_PATH }} --workspace
|
||||
|
||||
- name: Clippy
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: clippy
|
||||
args: ${{ env.MANIFEST_PATH }} --workspace --all-targets -- -D warnings
|
||||
|
||||
notification:
|
||||
needs: build
|
||||
runs-on: custom-linux
|
||||
steps:
|
||||
- name: Collect jobs status
|
||||
uses: technote-space/workflow-conclusion-action@v2
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v3
|
||||
- name: install npm
|
||||
uses: actions/setup-node@v3
|
||||
if: env.WORKFLOW_CONCLUSION == 'failure'
|
||||
with:
|
||||
node-version: 18
|
||||
- name: Matrix - Node Install
|
||||
if: env.WORKFLOW_CONCLUSION == 'failure'
|
||||
run: npm install
|
||||
working-directory: .github/workflows/support-files
|
||||
- name: Matrix - Send Notification
|
||||
if: env.WORKFLOW_CONCLUSION == 'failure'
|
||||
env:
|
||||
NYM_NOTIFICATION_KIND: nightly
|
||||
NYM_PROJECT_NAME: "nym-connect-desktop-nightly-build"
|
||||
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
|
||||
GIT_COMMIT_MESSAGE: "${{ github.event.head_commit.message }}"
|
||||
GIT_BRANCH: "${GITHUB_REF##*/}"
|
||||
IS_SUCCESS: "${{ env.WORKFLOW_CONCLUSION == 'success' }}"
|
||||
MATRIX_SERVER: "${{ secrets.MATRIX_SERVER }}"
|
||||
MATRIX_ROOM: "${{ secrets.MATRIX_ROOM_NIGHTLY }}"
|
||||
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
|
||||
@@ -1,27 +0,0 @@
|
||||
name: pr-validation
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- develop
|
||||
- 'release/**'
|
||||
types:
|
||||
- labeled
|
||||
- unlabeled
|
||||
- opened
|
||||
- reopened
|
||||
- synchronize
|
||||
- edited
|
||||
- milestoned
|
||||
- demilestoned
|
||||
|
||||
env:
|
||||
LABELS: ${{ join( github.event.pull_request.labels.*.name, ' ' ) }}
|
||||
|
||||
jobs:
|
||||
check-milestone:
|
||||
name: Check Milestone
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- if: github.event.pull_request.milestone == null && contains( env.LABELS, 'no-milestone' ) == false
|
||||
run: exit 1
|
||||
@@ -30,7 +30,6 @@ jobs:
|
||||
mixnode_hash: ${{ steps.binary-hashes.outputs.mixnode_hash }}
|
||||
gateway_hash: ${{ steps.binary-hashes.outputs.gateway_hash }}
|
||||
nymvisor_hash: ${{ steps.binary-hashes.outputs.nymvisor_hash }}
|
||||
nymnode_hash: ${{ steps.binary-hashes.outputs.nymnode_hash }}
|
||||
socks5_hash: ${{ steps.binary-hashes.outputs.socks5_hash }}
|
||||
netreq_hash: ${{ steps.binary-hashes.outputs.netreq_hash }}
|
||||
cli_hash: ${{ steps.binary-hashes.outputs.cli_hash }}
|
||||
@@ -39,7 +38,6 @@ jobs:
|
||||
mixnode_version: ${{ steps.binary-versions.outputs.mixnode_version }}
|
||||
gateway_version: ${{ steps.binary-versions.outputs.gateway_version }}
|
||||
nymvisor_version: ${{ steps.binary-versions.outputs.nymvisor_version }}
|
||||
nymnode_version: ${{ steps.binary-versions.outputs.nymnode_version }}
|
||||
socks5_version: ${{ steps.binary-versions.outputs.socks5_version }}
|
||||
netreq_version: ${{ steps.binary-versions.outputs.netreq_version }}
|
||||
cli_version: ${{ steps.binary-versions.outputs.cli_version }}
|
||||
@@ -83,7 +81,6 @@ jobs:
|
||||
target/release/nym-network-statistics
|
||||
target/release/nym-cli
|
||||
target/release/nymvisor
|
||||
target/release/nym-node
|
||||
retention-days: 30
|
||||
|
||||
- id: create-release
|
||||
@@ -102,7 +99,6 @@ jobs:
|
||||
target/release/nym-network-statistics
|
||||
target/release/nym-cli
|
||||
target/release/nymvisor
|
||||
target/release/nym-node
|
||||
|
||||
push-release-data-client:
|
||||
if: ${{ (startsWith(github.ref, 'refs/tags/nym-binaries-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }}
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
name: publish-nym-connect-macos
|
||||
on:
|
||||
workflow_dispatch:
|
||||
release:
|
||||
types: [created]
|
||||
|
||||
defaults:
|
||||
run:
|
||||
working-directory: nym-connect/desktop
|
||||
|
||||
jobs:
|
||||
publish-tauri:
|
||||
if: ${{ (startsWith(github.ref, 'refs/tags/nym-connect-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
platform: [macos-12-large]
|
||||
runs-on: ${{ matrix.platform }}
|
||||
|
||||
outputs:
|
||||
release_id: ${{ steps.create-release.outputs.id }}
|
||||
release_date: ${{ fromJSON(steps.create-release.outputs.assets)[0].created_at }}
|
||||
version: ${{ steps.release-info.outputs.version }}
|
||||
filename: ${{ steps.release-info.outputs.filename }}
|
||||
file_hash: ${{ steps.release-info.outputs.file_hash }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18
|
||||
|
||||
- name: Install Rust stable
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
target: wasm32-unknown-unknown
|
||||
|
||||
- name: Install wasm-pack
|
||||
run: |
|
||||
export WASM_PACK_VERSION="v0.12.1"
|
||||
curl -LO https://github.com/rustwasm/wasm-pack/releases/download/${WASM_PACK_VERSION}/wasm-pack-${WASM_PACK_VERSION}-x86_64-apple-darwin.tar.gz
|
||||
tar xvzf wasm-pack-${WASM_PACK_VERSION}-x86_64-apple-darwin.tar.gz -C $HOME/.cargo/bin --strip-components=1
|
||||
rm wasm-pack-${WASM_PACK_VERSION}-x86_64-apple-darwin.tar.gz
|
||||
|
||||
- name: Install the Apple developer certificate for code signing
|
||||
env:
|
||||
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
|
||||
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
|
||||
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
|
||||
run: |
|
||||
# create variables
|
||||
CERTIFICATE_PATH=$RUNNER_TEMP/build_certificate.p12
|
||||
KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db
|
||||
|
||||
# import certificate and provisioning profile from secrets
|
||||
echo -n "$APPLE_CERTIFICATE" | base64 --decode --output $CERTIFICATE_PATH
|
||||
|
||||
# create temporary keychain
|
||||
security create-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
|
||||
security set-keychain-settings -lut 21600 $KEYCHAIN_PATH
|
||||
security unlock-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
|
||||
|
||||
# import certificate to keychain
|
||||
security import $CERTIFICATE_PATH -P "$APPLE_CERTIFICATE_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH
|
||||
security list-keychain -d user -s $KEYCHAIN_PATH
|
||||
|
||||
- name: Create env file
|
||||
uses: timheuer/base64-to-file@v1.2
|
||||
with:
|
||||
fileName: '.env'
|
||||
encodedString: ${{ secrets.WALLET_ADMIN_ADDRESS }}
|
||||
|
||||
- name: Install project dependencies
|
||||
shell: bash
|
||||
run: cd .. && yarn --network-timeout 100000
|
||||
|
||||
- name: Install app dependencies and build it
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
ENABLE_CODE_SIGNING: ${{ secrets.APPLE_CERTIFICATE }}
|
||||
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
|
||||
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
|
||||
APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_IDENTITY_ID }}
|
||||
APPLE_ID: ${{ secrets.APPLE_ID }}
|
||||
APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
|
||||
TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
|
||||
TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
|
||||
SENTRY_DSN_RUST: ${{ secrets.SENTRY_DSN_RUST }}
|
||||
SENTRY_DSN_JS: ${{ secrets.SENTRY_DSN_JS }}
|
||||
run: yarn && yarn build
|
||||
|
||||
- name: Upload Artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: nym-connect_1.0.0_x64.dmg
|
||||
path: nym-connect/desktop/target/release/bundle/dmg/nym-connect_1*_x64.dmg
|
||||
retention-days: 30
|
||||
|
||||
- name: Clean up keychain
|
||||
if: ${{ always() }}
|
||||
run: |
|
||||
security delete-keychain $RUNNER_TEMP/app-signing.keychain-db
|
||||
|
||||
- id: create-release
|
||||
name: Upload to release based on tag name
|
||||
uses: softprops/action-gh-release@v1
|
||||
if: github.event_name == 'release'
|
||||
with:
|
||||
files: |
|
||||
nym-connect/desktop/target/release/bundle/dmg/*.dmg
|
||||
nym-connect/desktop/target/release/bundle/macos/*.app.tar.gz*
|
||||
|
||||
push-release-data:
|
||||
if: ${{ (startsWith(github.ref, 'refs/tags/nym-connect-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }}
|
||||
uses: ./.github/workflows/release-calculate-hash.yml
|
||||
needs: publish-tauri
|
||||
with:
|
||||
release_tag: ${{ github.ref_name }}
|
||||
secrets: inherit
|
||||
@@ -0,0 +1,89 @@
|
||||
name: publish-nym-connect-ubuntu
|
||||
on:
|
||||
workflow_dispatch:
|
||||
release:
|
||||
types: [created]
|
||||
|
||||
defaults:
|
||||
run:
|
||||
working-directory: nym-connect/desktop
|
||||
|
||||
jobs:
|
||||
publish-tauri:
|
||||
if: ${{ (startsWith(github.ref, 'refs/tags/nym-connect-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
platform: [custom-ubuntu-20.04]
|
||||
runs-on: ${{ matrix.platform }}
|
||||
|
||||
outputs:
|
||||
release_id: ${{ steps.create-release.outputs.id }}
|
||||
release_date: ${{ fromJSON(steps.create-release.outputs.assets)[0].created_at }}
|
||||
version: ${{ steps.release-info.outputs.version }}
|
||||
filename: ${{ steps.release-info.outputs.filename }}
|
||||
file_hash: ${{ steps.release-info.outputs.file_hash }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Tauri dependencies
|
||||
run: >
|
||||
sudo apt-get update &&
|
||||
sudo apt-get install -y webkit2gtk-4.0 libayatana-appindicator3-dev
|
||||
continue-on-error: true
|
||||
|
||||
- name: Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18
|
||||
|
||||
- name: Install Rust stable
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
|
||||
- name: Install project dependencies
|
||||
shell: bash
|
||||
run: cd .. && yarn --network-timeout 100000
|
||||
|
||||
- name: Install app dependencies
|
||||
run: yarn
|
||||
|
||||
- name: Create env file
|
||||
uses: timheuer/base64-to-file@v1.2
|
||||
with:
|
||||
fileName: '.env'
|
||||
encodedString: ${{ secrets.WALLET_ADMIN_ADDRESS }}
|
||||
|
||||
- name: Build app
|
||||
run: yarn build
|
||||
env:
|
||||
TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
|
||||
TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
|
||||
SENTRY_DSN_RUST: ${{ secrets.SENTRY_DSN_RUST }}
|
||||
SENTRY_DSN_JS: ${{ secrets.SENTRY_DSN_JS }}
|
||||
|
||||
- name: Upload Artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: nym-connect.AppImage.tar.gz
|
||||
path: nym-connect/desktop/target/release/bundle/appimage/nym-connect_1*_amd64.AppImage
|
||||
retention-days: 30
|
||||
|
||||
- id: create-release
|
||||
name: Upload to release based on tag name
|
||||
uses: softprops/action-gh-release@v1
|
||||
if: github.event_name == 'release'
|
||||
with:
|
||||
files: |
|
||||
nym-connect/desktop/target/release/bundle/appimage/*.AppImage
|
||||
nym-connect/desktop/target/release/bundle/appimage/*.AppImage.tar.gz*
|
||||
|
||||
push-release-data:
|
||||
if: ${{ (startsWith(github.ref, 'refs/tags/nym-connect-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }}
|
||||
uses: ./.github/workflows/release-calculate-hash.yml
|
||||
needs: publish-tauri
|
||||
with:
|
||||
release_tag: ${{ github.ref_name }}
|
||||
secrets: inherit
|
||||
@@ -0,0 +1,108 @@
|
||||
name: publish-nym-connect-win10
|
||||
on:
|
||||
workflow_dispatch:
|
||||
release:
|
||||
types: [created]
|
||||
|
||||
defaults:
|
||||
run:
|
||||
working-directory: nym-connect/desktop
|
||||
|
||||
jobs:
|
||||
publish-tauri:
|
||||
if: ${{ (startsWith(github.ref, 'refs/tags/nym-connect-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
platform: [windows10]
|
||||
runs-on: ${{ matrix.platform }}
|
||||
|
||||
outputs:
|
||||
release_id: ${{ steps.create-release.outputs.id }}
|
||||
release_date: ${{ fromJSON(steps.create-release.outputs.assets)[0].created_at }}
|
||||
version: ${{ steps.release-info.outputs.version }}
|
||||
filename: ${{ steps.release-info.outputs.filename }}
|
||||
file_hash: ${{ steps.release-info.outputs.file_hash }}
|
||||
|
||||
steps:
|
||||
- name: Clean up first
|
||||
continue-on-error: true
|
||||
working-directory: .
|
||||
run: |
|
||||
cd ..
|
||||
del /s /q /A:H nym
|
||||
rmdir /s /q nym
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Import signing certificate
|
||||
env:
|
||||
WINDOWS_CERTIFICATE: ${{ secrets.WINDOWS_CERTIFICATE }}
|
||||
WINDOWS_CERTIFICATE_PASSWORD: ${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }}
|
||||
run: |
|
||||
New-Item -ItemType directory -Path certificate
|
||||
Set-Content -Path certificate/tempCert.txt -Value $env:WINDOWS_CERTIFICATE
|
||||
certutil -decode certificate/tempCert.txt certificate/certificate.pfx
|
||||
Remove-Item -path certificate -include tempCert.txt
|
||||
Import-PfxCertificate -FilePath certificate/certificate.pfx -CertStoreLocation Cert:\CurrentUser\My -Password (ConvertTo-SecureString -String $env:WINDOWS_CERTIFICATE_PASSWORD -Force -AsPlainText)
|
||||
|
||||
- name: Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18
|
||||
|
||||
- name: Install Rust stable
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
|
||||
- name: Create env file
|
||||
uses: timheuer/base64-to-file@v1.2
|
||||
with:
|
||||
fileName: '.env'
|
||||
encodedString: ${{ secrets.WALLET_ADMIN_ADDRESS }}
|
||||
|
||||
- name: Install project dependencies
|
||||
shell: bash
|
||||
run: cd .. && yarn --network-timeout 100000
|
||||
|
||||
- name: Install app dependencies
|
||||
shell: bash
|
||||
run: yarn --network-timeout 100000
|
||||
|
||||
- name: Build and sign it
|
||||
shell: bash
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
ENABLE_CODE_SIGNING: ${{ secrets.WINDOWS_CERTIFICATE }}
|
||||
WINDOWS_CERTIFICATE: ${{ secrets.WINDOWS_CERTIFICATE }}
|
||||
WINDOWS_CERTIFICATE_PASSWORD: ${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }}
|
||||
TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
|
||||
TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
|
||||
SENTRY_DSN_RUST: ${{ secrets.SENTRY_DSN_RUST }}
|
||||
SENTRY_DSN_JS: ${{ secrets.SENTRY_DSN_JS }}
|
||||
run: yarn build
|
||||
|
||||
- name: Upload Artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: nym-connect_1.0.0_x64_en-US.msi
|
||||
path: nym-connect/desktop/target/release/bundle/msi/nym-connect_1*_x64_en-US.msi
|
||||
retention-days: 30
|
||||
|
||||
- id: create-release
|
||||
name: Upload to release based on tag name
|
||||
uses: softprops/action-gh-release@v1
|
||||
if: github.event_name == 'release'
|
||||
with:
|
||||
files: |
|
||||
nym-connect/desktop/target/release/bundle/msi/*.msi
|
||||
nym-connect/desktop/target/release/bundle/msi/*.msi.zip*
|
||||
|
||||
push-release-data:
|
||||
if: ${{ (startsWith(github.ref, 'refs/tags/nym-connect-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }}
|
||||
uses: ./.github/workflows/release-calculate-hash.yml
|
||||
needs: publish-tauri
|
||||
with:
|
||||
release_tag: ${{ github.ref_name }}
|
||||
secrets: inherit
|
||||
@@ -102,18 +102,6 @@ jobs:
|
||||
nym-wallet/target/release/bundle/dmg/*.dmg
|
||||
nym-wallet/target/release/bundle/macos/*.app.tar.gz*
|
||||
|
||||
- name: Deploy artifacts to CI www
|
||||
continue-on-error: true
|
||||
uses: easingthemes/ssh-deploy@main
|
||||
env:
|
||||
SSH_PRIVATE_KEY: ${{ secrets.CI_WWW_SSH_PRIVATE_KEY }}
|
||||
ARGS: "-avzr"
|
||||
SOURCE: "nym-wallet/target/release/bundle/macos/nym-wallet.app.tar.gz"
|
||||
REMOTE_HOST: ${{ secrets.CI_WWW_REMOTE_HOST }}
|
||||
REMOTE_USER: ${{ secrets.CI_WWW_REMOTE_USER }}
|
||||
TARGET: ${{ secrets.CI_WWW_REMOTE_TARGET }}/builds/${{ github.ref_name }}/nym-wallet
|
||||
EXCLUDE: "/dist/, /node_modules/"
|
||||
|
||||
push-release-data:
|
||||
if: ${{ (startsWith(github.ref, 'refs/tags/nym-wallet-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }}
|
||||
uses: ./.github/workflows/release-calculate-hash.yml
|
||||
|
||||
@@ -77,18 +77,6 @@ jobs:
|
||||
nym-wallet/target/release/bundle/appimage/*.AppImage
|
||||
nym-wallet/target/release/bundle/appimage/*.AppImage.tar.gz*
|
||||
|
||||
- name: Deploy artifacts to CI www
|
||||
continue-on-error: true
|
||||
uses: easingthemes/ssh-deploy@main
|
||||
env:
|
||||
SSH_PRIVATE_KEY: ${{ secrets.CI_WWW_SSH_PRIVATE_KEY }}
|
||||
ARGS: "-avzr"
|
||||
SOURCE: "nym-wallet/target/release/bundle/appimage/nym-wallet*.AppImage.tar.gz"
|
||||
REMOTE_HOST: ${{ secrets.CI_WWW_REMOTE_HOST }}
|
||||
REMOTE_USER: ${{ secrets.CI_WWW_REMOTE_USER }}
|
||||
TARGET: ${{ secrets.CI_WWW_REMOTE_TARGET }}/builds/${{ github.ref_name }}/nym-wallet
|
||||
EXCLUDE: "/dist/, /node_modules/"
|
||||
|
||||
push-release-data:
|
||||
if: ${{ (startsWith(github.ref, 'refs/tags/nym-wallet-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }}
|
||||
uses: ./.github/workflows/release-calculate-hash.yml
|
||||
|
||||
@@ -97,18 +97,6 @@ jobs:
|
||||
nym-wallet/target/release/bundle/msi/*.msi
|
||||
nym-wallet/target/release/bundle/msi/*.msi.zip*
|
||||
|
||||
- name: Deploy artifacts to CI www
|
||||
continue-on-error: true
|
||||
uses: easingthemes/ssh-deploy@main
|
||||
env:
|
||||
SSH_PRIVATE_KEY: ${{ secrets.CI_WWW_SSH_PRIVATE_KEY }}
|
||||
ARGS: "-avzr"
|
||||
SOURCE: "nym-wallet/target/release/bundle/msi/nym-wallet_1.*.msi"
|
||||
REMOTE_HOST: ${{ secrets.CI_WWW_REMOTE_HOST }}
|
||||
REMOTE_USER: ${{ secrets.CI_WWW_REMOTE_USER }}
|
||||
TARGET: ${{ secrets.CI_WWW_REMOTE_TARGET }}/builds/${{ github.ref_name }}/nym-wallet
|
||||
EXCLUDE: "/dist/, /node_modules/"
|
||||
|
||||
push-release-data:
|
||||
if: ${{ (startsWith(github.ref, 'refs/tags/nym-wallet-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }}
|
||||
uses: ./.github/workflows/release-calculate-hash.yml
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
const Handlebars = require('handlebars');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
async function addToContextAndValidate(context) {
|
||||
if (!context.env.NYM_CI_WWW_LOCATION) {
|
||||
throw new Error('Please ensure the env var NYM_CI_WWW_LOCATION is set');
|
||||
}
|
||||
if (!context.env.NYM_CI_WWW_BASE) {
|
||||
throw new Error('Please ensure the env var NYM_CI_WWW_BASE is set');
|
||||
}
|
||||
}
|
||||
|
||||
async function getMessageBody(context) {
|
||||
const source = fs
|
||||
.readFileSync(
|
||||
context.env.IS_SUCCESS === 'true'
|
||||
? path.resolve(__dirname, 'templates', 'success')
|
||||
: path.resolve(__dirname, 'templates', 'failure'),
|
||||
)
|
||||
.toString();
|
||||
const template = Handlebars.compile(source);
|
||||
return template(context);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
addToContextAndValidate,
|
||||
getMessageBody,
|
||||
};
|
||||
@@ -0,0 +1,16 @@
|
||||
🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥
|
||||
> :rocket: {{ env.NYM_PROJECT_NAME }}
|
||||
>
|
||||
> 🔴 **FAILURE** :cry:
|
||||
>
|
||||
> `branch` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/tree/{{ env.GIT_BRANCH_NAME }}
|
||||
>
|
||||
> `commit` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/commit/{{ env.GITHUB_SHA }}
|
||||
>
|
||||
> `build ` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/actions/runs/{{ env.GITHUB_RUN_ID }}
|
||||
>
|
||||
|
||||
Commit message:
|
||||
```
|
||||
{{ env.GIT_COMMIT_MESSAGE }}
|
||||
```
|
||||
@@ -0,0 +1,16 @@
|
||||
🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩
|
||||
> :rocket: {{ env.NYM_PROJECT_NAME }} ➡️➡️➡️➡️➡️ **View storybook:** https://{{ env.NYM_CI_WWW_LOCATION }}.{{ env.NYM_CI_WWW_BASE }}/
|
||||
>
|
||||
> ✅ **SUCCESS**
|
||||
>
|
||||
> `branch` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/tree/{{ env.GIT_BRANCH_NAME }}
|
||||
>
|
||||
> `commit` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/commit/{{ env.GITHUB_SHA }}
|
||||
>
|
||||
> `build ` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/actions/runs/{{ env.GITHUB_RUN_ID }}
|
||||
>
|
||||
|
||||
Commit message by `{{ env.GITHUB_ACTOR }}` at {{ timestamp }}:
|
||||
```
|
||||
{{ env.GIT_COMMIT_MESSAGE }}
|
||||
```
|
||||
@@ -4,69 +4,6 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [2024.5-ragusa] (2024-05-22)
|
||||
|
||||
- Feature/nym node api location ([#4605])
|
||||
- Add optional signature to IPR request/response ([#4604])
|
||||
- Feature/unstable tested nodes endpoint ([#4601])
|
||||
- nym-api: make report/avg_uptime endpoints ignore blacklist ([#4599])
|
||||
- removed blocking for coconut in the final epoch state ([#4598])
|
||||
- allow using explicit admin address for issuing freepasses ([#4595])
|
||||
- Use rfc3339 for last_polled in described nym-api endpoint ([#4591])
|
||||
- Explicitly handle constraint unique violation when importing credential ([#4588])
|
||||
- [bugfix] noop flag for nym-api for nymvisor compatibility ([#4586])
|
||||
- Chore/additional helpers ([#4585])
|
||||
- Feature/wasm coconut ([#4584])
|
||||
- upgraded axum and related deps to the most recent version ([#4573])
|
||||
- Feature/nyxd scraper pruning ([#4564])
|
||||
- Run cargo autoinherit on the main workspace ([#4553])
|
||||
- Add rustls-tls to reqwest in validator-client ([#4552])
|
||||
- Feature/rewarder voucher issuance ([#4548])
|
||||
- make sure 'OffsetDateTimeJsonSchemaWrapper' is serialised with legacy format ([#4613])
|
||||
|
||||
|
||||
[#4613]: https://github.com/nymtech/nym/pull/4613
|
||||
[#4605]: https://github.com/nymtech/nym/pull/4605
|
||||
[#4604]: https://github.com/nymtech/nym/pull/4604
|
||||
[#4601]: https://github.com/nymtech/nym/pull/4601
|
||||
[#4599]: https://github.com/nymtech/nym/pull/4599
|
||||
[#4598]: https://github.com/nymtech/nym/pull/4598
|
||||
[#4595]: https://github.com/nymtech/nym/pull/4595
|
||||
[#4591]: https://github.com/nymtech/nym/pull/4591
|
||||
[#4588]: https://github.com/nymtech/nym/pull/4588
|
||||
[#4586]: https://github.com/nymtech/nym/pull/4586
|
||||
[#4585]: https://github.com/nymtech/nym/pull/4585
|
||||
[#4584]: https://github.com/nymtech/nym/pull/4584
|
||||
[#4573]: https://github.com/nymtech/nym/pull/4573
|
||||
[#4564]: https://github.com/nymtech/nym/pull/4564
|
||||
[#4553]: https://github.com/nymtech/nym/pull/4553
|
||||
[#4552]: https://github.com/nymtech/nym/pull/4552
|
||||
[#4548]: https://github.com/nymtech/nym/pull/4548
|
||||
|
||||
## [2024.4-nutella] (2024-05-08)
|
||||
|
||||
- [fix] apply disable_poisson_rate from internal NR/IPR cfgs ([#4579])
|
||||
- updating sign commands to include nym-node ([#4578])
|
||||
- changed nym-node redirects from 308 'Permanent Redirect' to 303: 'See Other' ([#4572])
|
||||
|
||||
[#4579]: https://github.com/nymtech/nym/pull/4579
|
||||
[#4578]: https://github.com/nymtech/nym/pull/4578
|
||||
[#4572]: https://github.com/nymtech/nym/pull/4572
|
||||
|
||||
## [2024.3-eclipse] (2024-04-22)
|
||||
|
||||
- Initial release of the first iteration of the Nym Node
|
||||
- Improvements to gateway functionality
|
||||
- IPR development
|
||||
- Removal of allow list in favour of implementing an exit policy
|
||||
- Explorer delegation: enables direct delegation to nodes via the Nym Explorer
|
||||
|
||||
|
||||
## [2024.2-fast-and-furious] (2024-03-25)
|
||||
|
||||
- Internal testing pre-release
|
||||
|
||||
|
||||
## [2024.1-marabou] (2024-02-15)
|
||||
|
||||
**New Features:**
|
||||
|
||||
Generated
+3326
-1678
File diff suppressed because it is too large
Load Diff
+33
-135
@@ -24,7 +24,6 @@ members = [
|
||||
"common/bandwidth-controller",
|
||||
"common/bin-common",
|
||||
"common/client-core",
|
||||
"common/client-core/config-types",
|
||||
"common/client-core/surb-storage",
|
||||
"common/client-core/gateways-storage",
|
||||
"common/client-libs/gateway-client",
|
||||
@@ -35,11 +34,13 @@ members = [
|
||||
"common/cosmwasm-smart-contracts/coconut-bandwidth-contract",
|
||||
"common/cosmwasm-smart-contracts/coconut-dkg",
|
||||
"common/cosmwasm-smart-contracts/contracts-common",
|
||||
# "common/cosmwasm-smart-contracts/ephemera",
|
||||
"common/cosmwasm-smart-contracts/group-contract",
|
||||
"common/cosmwasm-smart-contracts/mixnet-contract",
|
||||
"common/cosmwasm-smart-contracts/multisig-contract",
|
||||
"common/cosmwasm-smart-contracts/name-service",
|
||||
"common/cosmwasm-smart-contracts/service-provider-directory",
|
||||
"common/cosmwasm-smart-contracts/vesting-contract",
|
||||
"common/country-group",
|
||||
"common/credential-storage",
|
||||
"common/credentials",
|
||||
"common/credential-utils",
|
||||
@@ -49,7 +50,6 @@ members = [
|
||||
"common/execute",
|
||||
"common/exit-policy",
|
||||
"common/http-api-client",
|
||||
"common/http-api-common",
|
||||
"common/inclusion-probability",
|
||||
"common/ip-packet-requests",
|
||||
"common/ledger",
|
||||
@@ -104,7 +104,6 @@ members = [
|
||||
"nym-browser-extension/storage",
|
||||
"nym-api/nym-api-requests",
|
||||
"nym-node",
|
||||
"nym-node/nym-node-http-api",
|
||||
"nym-node/nym-node-requests",
|
||||
"nym-outfox",
|
||||
"nym-validator-rewarder",
|
||||
@@ -116,10 +115,10 @@ members = [
|
||||
"tools/nymvisor",
|
||||
"tools/ts-rs-cli",
|
||||
"wasm/client",
|
||||
# "wasm/full-nym-wasm", # If we uncomment this again, remember to also uncomment the profile settings below
|
||||
# "wasm/full-nym-wasm",
|
||||
"wasm/mix-fetch",
|
||||
"wasm/node-tester",
|
||||
"wasm/zknym-lib",
|
||||
"common/nym-metrics",
|
||||
]
|
||||
|
||||
default-members = [
|
||||
@@ -133,13 +132,15 @@ default-members = [
|
||||
"tools/nymvisor",
|
||||
"explorer-api",
|
||||
"nym-validator-rewarder",
|
||||
"nym-node"
|
||||
]
|
||||
|
||||
exclude = [
|
||||
"explorer",
|
||||
"contracts",
|
||||
"nym-wallet",
|
||||
"nym-connect/mobile/src-tauri",
|
||||
"nym-connect/desktop",
|
||||
"nym-vpn/ui/src-tauri",
|
||||
"cpu-cycles",
|
||||
"sdk/ffi/cpp",
|
||||
]
|
||||
@@ -153,142 +154,43 @@ edition = "2021"
|
||||
license = "Apache-2.0"
|
||||
|
||||
[workspace.dependencies]
|
||||
addr = "0.15.6"
|
||||
aes = "0.8.1"
|
||||
aes-gcm = "0.10.1"
|
||||
anyhow = "1.0.71"
|
||||
argon2 = "0.5.0"
|
||||
async-trait = "0.1.68"
|
||||
axum = "0.7.5"
|
||||
axum-extra = "0.9.3"
|
||||
axum = "0.6.20"
|
||||
base64 = "0.21.4"
|
||||
bincode = "1.3.3"
|
||||
bs58 = "0.5.0"
|
||||
bip39 = { version = "2.0.0", features = ["zeroize"] }
|
||||
bitvec = "1.0.0"
|
||||
blake3 = "1.3.1"
|
||||
bs58 = "0.5.1"
|
||||
bytecodec = "0.4.15"
|
||||
bytes = "1.5.0"
|
||||
cargo_metadata = "0.18.1"
|
||||
celes = "2.4.0"
|
||||
cfg-if = "1.0.0"
|
||||
chacha20 = "0.9.0"
|
||||
chacha20poly1305 = "0.10.1"
|
||||
chrono = "0.4.31"
|
||||
cipher = "0.4.3"
|
||||
clap = "4.4.7"
|
||||
clap_complete = "4.0"
|
||||
clap_complete_fig = "4.0"
|
||||
colored = "2.0"
|
||||
comfy-table = "6.0.0"
|
||||
console-subscriber = "0.1.1"
|
||||
console_error_panic_hook = "0.1"
|
||||
const-str = "0.5.6"
|
||||
const_format = "0.2.32"
|
||||
criterion = "0.4"
|
||||
csv = "1.3.0"
|
||||
ctr = "0.9.1"
|
||||
cupid = "0.6.1"
|
||||
curve25519-dalek = "4.1"
|
||||
cfg-if = "1.0.0"
|
||||
dashmap = "5.5.3"
|
||||
defguard_wireguard_rs = "0.4.2"
|
||||
doc-comment = "0.3"
|
||||
dotenvy = "0.15.6"
|
||||
ecdsa = "0.16"
|
||||
ed25519-dalek = "2.1"
|
||||
etherparse = "0.13.0"
|
||||
eyre = "0.6.9"
|
||||
flate2 = "1.0.28"
|
||||
futures = "0.3.28"
|
||||
generic-array = "0.14.7"
|
||||
getrandom = "0.2.10"
|
||||
getset = "0.1.1"
|
||||
handlebars = "3.5.5"
|
||||
headers = "0.4.0"
|
||||
hex = "0.4.3"
|
||||
hex-literal = "0.3.3"
|
||||
hkdf = "0.12.3"
|
||||
hmac = "0.12.1"
|
||||
httpcodec = "0.2.3"
|
||||
humantime = "2.1.0"
|
||||
humantime-serde = "1.1.1"
|
||||
http = "1"
|
||||
hyper = "1.3.1"
|
||||
indexed_db_futures = "0.3.0"
|
||||
inquire = "0.6.2"
|
||||
ip_network = "0.4.1"
|
||||
isocountry = "0.3.2"
|
||||
hyper = "0.14.27"
|
||||
k256 = "0.13"
|
||||
lazy_static = "1.4.0"
|
||||
ledger-transport = "0.10.0"
|
||||
ledger-transport-hid = "0.10.0"
|
||||
log = "0.4"
|
||||
maxminddb = "0.23.0"
|
||||
mime = "0.3.17"
|
||||
nix = "0.27.1"
|
||||
notify = "5.1.0"
|
||||
okapi = "0.7.0"
|
||||
once_cell = "1.7.2"
|
||||
opentelemetry = "0.19.0"
|
||||
opentelemetry-jaeger = "0.18.0"
|
||||
parking_lot = "0.12.1"
|
||||
pem = "0.8"
|
||||
pin-project = "1.0"
|
||||
pretty_env_logger = "0.4.0"
|
||||
publicsuffix = "2.2.3"
|
||||
quote = "1"
|
||||
rand = "0.8.5"
|
||||
rand-07 = "0.7.3"
|
||||
rand_chacha_02 = "0.2"
|
||||
rand_core = "0.6.3"
|
||||
rand_distr = "0.4"
|
||||
rand_pcg = "0.3.1"
|
||||
rand_seeder = "0.2.3"
|
||||
rayon = "1.5.1"
|
||||
regex = "1.8.4"
|
||||
reqwest = { version = "0.12.4", default-features = false }
|
||||
rocket = "0.5.0"
|
||||
rocket_cors = "0.6.0"
|
||||
rocket_okapi = "0.8.0"
|
||||
safer-ffi = "0.1.4"
|
||||
reqwest = { version = "0.11.22", default-features = false }
|
||||
schemars = "0.8.1"
|
||||
serde = "1.0.152"
|
||||
serde_bytes = "0.11.6"
|
||||
serde_derive = "1.0"
|
||||
serde_json = "1.0.91"
|
||||
serde_repr = "0.1"
|
||||
serde_with = "3.4.0"
|
||||
serde_yaml = "0.9.25"
|
||||
si-scale = "0.2.2"
|
||||
sphinx-packet = "0.1.1"
|
||||
sqlx = "0.6.3"
|
||||
strum = "0.25"
|
||||
subtle-encoding = "0.5"
|
||||
syn = "1"
|
||||
tap = "1.0.1"
|
||||
tar = "0.4.40"
|
||||
tempfile = "3.5.0"
|
||||
thiserror = "1.0.48"
|
||||
time = "0.3.30"
|
||||
thiserror = "1.0.48"
|
||||
tokio = "1.33.0"
|
||||
tokio-stream = "0.1.14"
|
||||
tokio-test = "0.4.2"
|
||||
tokio-tungstenite = { version = "0.20.1" }
|
||||
tokio-util = "0.7.10"
|
||||
tower = "0.4.13"
|
||||
tower-http = "0.5.2"
|
||||
tokio-tungstenite = { version = "0.20.1" }
|
||||
tracing = "0.1.37"
|
||||
tracing-opentelemetry = "0.19.0"
|
||||
tracing-subscriber = "0.3.16"
|
||||
tracing-tree = "0.2.2"
|
||||
ts-rs = "7.0.0"
|
||||
tungstenite = { version = "0.20.1", default-features = false }
|
||||
ts-rs = "7.0.0"
|
||||
utoipa = "3.5.0"
|
||||
utoipa-swagger-ui = "3.1.5"
|
||||
url = "2.4"
|
||||
utoipa = "4.2.0"
|
||||
utoipa-swagger-ui = "6.0.0"
|
||||
vergen = { version = "=8.3.1", default-features = false }
|
||||
walkdir = "2"
|
||||
wasm-bindgen-test = "0.3.36"
|
||||
zeroize = "1.6.0"
|
||||
|
||||
prometheus = { version = "0.13.0" }
|
||||
@@ -296,9 +198,10 @@ prometheus = { version = "0.13.0" }
|
||||
# coconut/DKG related
|
||||
# unfortunately until https://github.com/zkcrypto/bls12_381/issues/10 is resolved, we have to rely on the fork
|
||||
# as we need to be able to serialize Gt so that we could create the lookup table for baby-step-giant-step algorithm
|
||||
bls12_381 = { git = "https://github.com/jstuczyn/bls12_381", default-features = false, branch = "feature/gt-serialization-0.8.0" }
|
||||
group = { version = "0.13.0", default-features = false }
|
||||
ff = { version = "0.13.0", default-features = false }
|
||||
bls12_381 = { git = "https://github.com/jstuczyn/bls12_381", branch = "feature/gt-serialization-0.8.0" }
|
||||
group = "0.13.0"
|
||||
ff = "0.13.0"
|
||||
|
||||
|
||||
# cosmwasm-related
|
||||
cosmwasm-derive = "=1.4.3"
|
||||
@@ -317,26 +220,24 @@ cw4 = { version = "=1.1.2" }
|
||||
cw-controllers = { version = "=1.1.0" }
|
||||
|
||||
# cosmrs-related
|
||||
bip32 = { version = "0.5.1", default-features = false }
|
||||
bip32 = "0.5.1"
|
||||
|
||||
# temporarily using a fork again (yay.) because we need staking and slashing support
|
||||
cosmrs = { git = "https://github.com/jstuczyn/cosmos-rust", branch = "nym-temp/all-validator-features" }
|
||||
#cosmrs = { git = "https://github.com/jstuczyn/cosmos-rust", branch = "nym-temp/all-validator-features" } # unfortuntely we need a fork by yours truly to get the staking support
|
||||
tendermint = "0.34" # same version as used by cosmrs
|
||||
tendermint-rpc = "0.34" # same version as used by cosmrs
|
||||
prost = { version = "0.12", default-features = false }
|
||||
prost = "0.12"
|
||||
|
||||
# wasm-related dependencies
|
||||
gloo-utils = "0.2.0"
|
||||
gloo-net = "0.5.0"
|
||||
js-sys = "0.3.69"
|
||||
serde-wasm-bindgen = "0.6.5"
|
||||
gloo-utils = "0.1.7"
|
||||
js-sys = "0.3.63"
|
||||
serde-wasm-bindgen = "0.5.0"
|
||||
tsify = "0.4.5"
|
||||
wasm-bindgen = "0.2.92"
|
||||
wasm-bindgen-futures = "0.4.39"
|
||||
wasm-bindgen = "0.2.86"
|
||||
wasm-bindgen-futures = "0.4.37"
|
||||
wasmtimer = "0.2.0"
|
||||
web-sys = "0.3.69"
|
||||
|
||||
web-sys = "0.3.63"
|
||||
|
||||
# Profile settings for individual crates
|
||||
|
||||
@@ -352,12 +253,9 @@ opt-level = 'z'
|
||||
# lto = true
|
||||
opt-level = 'z'
|
||||
|
||||
# Commented out since the crate is also commented out from the inclusion in the
|
||||
# workspace above. We should uncomment this if we re-include it in the
|
||||
# workspace
|
||||
#[profile.release.package.nym-wasm-sdk]
|
||||
## lto = true
|
||||
#opt-level = 'z'
|
||||
[profile.release.package.nym-wasm-sdk]
|
||||
# lto = true
|
||||
opt-level = 'z'
|
||||
|
||||
[profile.release.package.mix-fetch-wasm]
|
||||
# lto = true
|
||||
|
||||
@@ -92,6 +92,7 @@ endef
|
||||
$(eval $(call add_cargo_workspace,main,.))
|
||||
$(eval $(call add_cargo_workspace,contracts,contracts,--lib --target wasm32-unknown-unknown,RUSTFLAGS='-C link-arg=-s'))
|
||||
$(eval $(call add_cargo_workspace,wallet,nym-wallet))
|
||||
$(eval $(call add_cargo_workspace,connect,nym-connect/desktop))
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# SDK
|
||||
@@ -104,7 +105,6 @@ sdk-wasm-build:
|
||||
$(MAKE) -C wasm/client
|
||||
$(MAKE) -C wasm/node-tester
|
||||
$(MAKE) -C wasm/mix-fetch
|
||||
$(MAKE) -C wasm/zknym-lib
|
||||
#$(MAKE) -C wasm/full-nym-wasm
|
||||
|
||||
# run this from npm/yarn to ensure tools are in the path, e.g. yarn build:sdk from root of repo
|
||||
@@ -115,7 +115,7 @@ sdk-typescript-build:
|
||||
yarn --cwd sdk/typescript/codegen/contract-clients build
|
||||
|
||||
# NOTE: These targets are part of the main workspace (but not as wasm32-unknown-unknown)
|
||||
WASM_CRATES = extension-storage nym-client-wasm nym-node-tester-wasm zknym-lib
|
||||
WASM_CRATES = extension-storage nym-client-wasm nym-node-tester-wasm
|
||||
|
||||
sdk-wasm-test:
|
||||
#cargo test $(addprefix -p , $(WASM_CRATES)) --target wasm32-unknown-unknown -- -Dwarnings
|
||||
@@ -133,7 +133,7 @@ clippy: sdk-wasm-lint
|
||||
# Build contracts ready for deploy
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
CONTRACTS=vesting_contract mixnet_contract
|
||||
CONTRACTS=vesting_contract mixnet_contract nym_service_provider_directory nym_name_service
|
||||
CONTRACTS_WASM=$(addsuffix .wasm, $(CONTRACTS))
|
||||
CONTRACTS_OUT_DIR=contracts/target/wasm32-unknown-unknown/release
|
||||
|
||||
@@ -185,4 +185,4 @@ deb-gateway: build-nym-gateway
|
||||
deb-cli: build-nym-cli
|
||||
cargo deb -p nym-cli
|
||||
|
||||
deb: deb-mixnode deb-gateway deb-cli
|
||||
deb: deb-mixnode deb-gateway deb-cli
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "nym-client"
|
||||
version = "1.1.35"
|
||||
version = "1.1.33"
|
||||
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jędrzej Stuczyński <andrew@nymtech.net>"]
|
||||
description = "Implementation of the Nym Client"
|
||||
edition = "2021"
|
||||
@@ -25,11 +25,11 @@ bs58 = { workspace = true }
|
||||
clap = { workspace = true, features = ["cargo", "derive"] }
|
||||
dirs = "4.0"
|
||||
log = { workspace = true } # self explanatory
|
||||
rand = { workspace = true }
|
||||
rand = { version = "0.7.3", features = ["wasm-bindgen"] } # rng-related traits + some rng implementation to use
|
||||
serde = { workspace = true, features = ["derive"] } # for config serialization/deserialization
|
||||
serde_json = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
tap = { workspace = true }
|
||||
tap = "1.0.1"
|
||||
time = { workspace = true }
|
||||
tokio = { workspace = true, features = ["rt-multi-thread", "net", "signal"] } # async runtime
|
||||
tokio-tungstenite = { workspace = true }
|
||||
|
||||
+236
-78
@@ -744,18 +744,6 @@
|
||||
"concat-map": "0.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/braces": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
|
||||
"integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"fill-range": "^7.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/browserslist": {
|
||||
"version": "4.20.2",
|
||||
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.20.2.tgz",
|
||||
@@ -874,6 +862,51 @@
|
||||
"fsevents": "~2.3.2"
|
||||
}
|
||||
},
|
||||
"node_modules/chokidar/node_modules/braces": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
|
||||
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"fill-range": "^7.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/chokidar/node_modules/fill-range": {
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
|
||||
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"to-regex-range": "^5.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/chokidar/node_modules/is-number": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
||||
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/chokidar/node_modules/to-regex-range": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"is-number": "^7.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/chrome-trace-event": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz",
|
||||
@@ -1560,6 +1593,39 @@
|
||||
"node": ">=8.6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/fast-glob/node_modules/braces": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
|
||||
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"fill-range": "^7.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/fast-glob/node_modules/fill-range": {
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
|
||||
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"to-regex-range": "^5.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/fast-glob/node_modules/is-number": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
||||
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/fast-glob/node_modules/micromatch": {
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz",
|
||||
@@ -1573,6 +1639,18 @@
|
||||
"node": ">=8.6"
|
||||
}
|
||||
},
|
||||
"node_modules/fast-glob/node_modules/to-regex-range": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"is-number": "^7.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/fast-json-stable-stringify": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
|
||||
@@ -1605,18 +1683,6 @@
|
||||
"node": ">=0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/fill-range": {
|
||||
"version": "7.1.1",
|
||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
|
||||
"integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"to-regex-range": "^5.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/finalhandler": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz",
|
||||
@@ -2071,6 +2137,39 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/http-proxy-middleware/node_modules/braces": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
|
||||
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"fill-range": "^7.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/http-proxy-middleware/node_modules/fill-range": {
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
|
||||
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"to-regex-range": "^5.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/http-proxy-middleware/node_modules/is-number": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
||||
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/http-proxy-middleware/node_modules/micromatch": {
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz",
|
||||
@@ -2084,6 +2183,18 @@
|
||||
"node": ">=8.6"
|
||||
}
|
||||
},
|
||||
"node_modules/http-proxy-middleware/node_modules/to-regex-range": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"is-number": "^7.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/human-signals": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz",
|
||||
@@ -2250,15 +2361,6 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/is-number": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
||||
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/is-path-cwd": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz",
|
||||
@@ -3751,18 +3853,6 @@
|
||||
"integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/to-regex-range": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"is-number": "^7.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/toidentifier": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
|
||||
@@ -5123,15 +5213,6 @@
|
||||
"concat-map": "0.0.1"
|
||||
}
|
||||
},
|
||||
"braces": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
|
||||
"integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"fill-range": "^7.1.1"
|
||||
}
|
||||
},
|
||||
"browserslist": {
|
||||
"version": "4.20.2",
|
||||
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.20.2.tgz",
|
||||
@@ -5202,6 +5283,41 @@
|
||||
"is-glob": "~4.0.1",
|
||||
"normalize-path": "~3.0.0",
|
||||
"readdirp": "~3.6.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"braces": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
|
||||
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"fill-range": "^7.0.1"
|
||||
}
|
||||
},
|
||||
"fill-range": {
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
|
||||
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"to-regex-range": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"is-number": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
||||
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
|
||||
"dev": true
|
||||
},
|
||||
"to-regex-range": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-number": "^7.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"chrome-trace-event": {
|
||||
@@ -5736,6 +5852,30 @@
|
||||
"micromatch": "^4.0.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"braces": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
|
||||
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"fill-range": "^7.0.1"
|
||||
}
|
||||
},
|
||||
"fill-range": {
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
|
||||
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"to-regex-range": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"is-number": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
||||
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
|
||||
"dev": true
|
||||
},
|
||||
"micromatch": {
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz",
|
||||
@@ -5745,6 +5885,15 @@
|
||||
"braces": "^3.0.1",
|
||||
"picomatch": "^2.2.3"
|
||||
}
|
||||
},
|
||||
"to-regex-range": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-number": "^7.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -5777,15 +5926,6 @@
|
||||
"websocket-driver": ">=0.5.1"
|
||||
}
|
||||
},
|
||||
"fill-range": {
|
||||
"version": "7.1.1",
|
||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
|
||||
"integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"to-regex-range": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"finalhandler": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz",
|
||||
@@ -6107,6 +6247,30 @@
|
||||
"micromatch": "^4.0.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"braces": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
|
||||
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"fill-range": "^7.0.1"
|
||||
}
|
||||
},
|
||||
"fill-range": {
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
|
||||
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"to-regex-range": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"is-number": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
||||
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
|
||||
"dev": true
|
||||
},
|
||||
"micromatch": {
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz",
|
||||
@@ -6116,6 +6280,15 @@
|
||||
"braces": "^3.0.1",
|
||||
"picomatch": "^2.2.3"
|
||||
}
|
||||
},
|
||||
"to-regex-range": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-number": "^7.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -6234,12 +6407,6 @@
|
||||
"is-extglob": "^2.1.1"
|
||||
}
|
||||
},
|
||||
"is-number": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
||||
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
|
||||
"dev": true
|
||||
},
|
||||
"is-path-cwd": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz",
|
||||
@@ -7357,15 +7524,6 @@
|
||||
"integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==",
|
||||
"dev": true
|
||||
},
|
||||
"to-regex-range": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-number": "^7.0.0"
|
||||
}
|
||||
},
|
||||
"toidentifier": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
|
||||
|
||||
@@ -8,7 +8,5 @@ use nym_client_core::cli_helpers::client_import_credential::{
|
||||
};
|
||||
|
||||
pub(crate) async fn execute(args: CommonClientImportCredentialArgs) -> Result<(), ClientError> {
|
||||
import_credential::<CliNativeClient, _>(args).await?;
|
||||
println!("successfully imported credential!");
|
||||
Ok(())
|
||||
import_credential::<CliNativeClient, _>(args).await
|
||||
}
|
||||
|
||||
@@ -23,9 +23,6 @@ pub enum ClientError {
|
||||
#[error("Attempted to start the client in invalid socket mode")]
|
||||
InvalidSocketMode,
|
||||
|
||||
#[error(transparent)]
|
||||
ConfigUpgradeFailure(#[from] nym_client_core::config::ConfigUpgradeFailure),
|
||||
|
||||
#[error(transparent)]
|
||||
NymIdError(#[from] NymIdError),
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "nym-socks5-client"
|
||||
version = "1.1.35"
|
||||
version = "1.1.33"
|
||||
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"
|
||||
@@ -13,10 +13,10 @@ clap = { workspace = true, features = ["cargo", "derive"] }
|
||||
log = { workspace = true }
|
||||
serde = { workspace = true, features = ["derive"] } # for config serialization/deserialization
|
||||
serde_json = { workspace = true }
|
||||
tap = { workspace = true }
|
||||
tap = "1.0.1"
|
||||
thiserror = { workspace = true }
|
||||
tokio = { workspace = true, features = ["rt-multi-thread", "net", "signal"] }
|
||||
rand = { workspace = true }
|
||||
tokio = { version = "1.24.1", features = ["rt-multi-thread", "net", "signal"] }
|
||||
rand = "0.7.3"
|
||||
time = { workspace = true }
|
||||
url = { workspace = true }
|
||||
zeroize = { workspace = true }
|
||||
|
||||
@@ -10,7 +10,5 @@ use nym_client_core::cli_helpers::client_import_credential::{
|
||||
pub(crate) async fn execute(
|
||||
args: CommonClientImportCredentialArgs,
|
||||
) -> Result<(), Socks5ClientError> {
|
||||
import_credential::<CliSocks5Client, _>(args).await?;
|
||||
println!("successfully imported credential!");
|
||||
Ok(())
|
||||
import_credential::<CliSocks5Client, _>(args).await
|
||||
}
|
||||
|
||||
@@ -23,9 +23,6 @@ pub enum Socks5ClientError {
|
||||
#[error(transparent)]
|
||||
ClientCoreError(#[from] ClientCoreError),
|
||||
|
||||
#[error(transparent)]
|
||||
ConfigUpgradeFailure(#[from] nym_client_core::config::ConfigUpgradeFailure),
|
||||
|
||||
#[error(transparent)]
|
||||
NymIdError(#[from] NymIdError),
|
||||
}
|
||||
|
||||
@@ -8,6 +8,6 @@ license.workspace = true
|
||||
|
||||
[dependencies]
|
||||
futures = { workspace = true }
|
||||
log = { workspace = true }
|
||||
notify = { workspace = true }
|
||||
log = "0.4"
|
||||
notify = "5.1.0"
|
||||
tokio = { workspace = true, features = ["time"] }
|
||||
|
||||
@@ -9,7 +9,7 @@ license.workspace = true
|
||||
[dependencies]
|
||||
bip39 = { workspace = true }
|
||||
log = { workspace = true }
|
||||
rand = { workspace = true }
|
||||
rand = "0.7.3"
|
||||
thiserror = { workspace = true }
|
||||
url = { workspace = true }
|
||||
zeroize = { workspace = true }
|
||||
|
||||
@@ -8,28 +8,41 @@ license = { workspace = true }
|
||||
repository = { workspace = true }
|
||||
|
||||
[dependencies]
|
||||
const-str = { workspace = true }
|
||||
atty = "0.2"
|
||||
const-str = "0.5.6"
|
||||
clap = { workspace = true, features = ["derive"] }
|
||||
clap_complete = { workspace = true }
|
||||
clap_complete_fig = { workspace = true }
|
||||
clap_complete = "4.0"
|
||||
clap_complete_fig = "4.0"
|
||||
log = { workspace = true }
|
||||
pretty_env_logger = { workspace = true }
|
||||
pretty_env_logger = "0.4.0"
|
||||
semver = "0.11"
|
||||
schemars = { workspace = true, features = ["preserve_order"], optional = true }
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
serde_json = { workspace = true, optional = true }
|
||||
|
||||
## tracing
|
||||
tracing-subscriber = { workspace = true, features = ["env-filter"], optional = true }
|
||||
tracing-tree = { workspace = true, optional = true }
|
||||
opentelemetry-jaeger = { workspace = true, features = ["rt-tokio", "collector_client", "isahc_collector_client"], optional = true }
|
||||
tracing-opentelemetry = { workspace = true, optional = true }
|
||||
tracing-subscriber = { version = "0.3.16", features = [
|
||||
"env-filter",
|
||||
], optional = true }
|
||||
tracing-tree = { version = "0.2.2", optional = true }
|
||||
opentelemetry-jaeger = { version = "0.18.0", optional = true, features = [
|
||||
"rt-tokio",
|
||||
"collector_client",
|
||||
"isahc_collector_client",
|
||||
] }
|
||||
tracing-opentelemetry = { version = "0.19.0", optional = true }
|
||||
utoipa = { workspace = true, optional = true }
|
||||
opentelemetry = { workspace = true, features = ["rt-tokio"], optional = true }
|
||||
opentelemetry = { version = "0.19.0", optional = true, features = ["rt-tokio"] }
|
||||
|
||||
|
||||
[build-dependencies]
|
||||
vergen = { workspace = true, features = ["build", "git", "gitcl", "rustc", "cargo"] }
|
||||
vergen = { version = "=8.2.6", default-features = false, features = [
|
||||
"build",
|
||||
"git",
|
||||
"gitcl",
|
||||
"rustc",
|
||||
"cargo",
|
||||
] }
|
||||
|
||||
[features]
|
||||
default = []
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::io::IsTerminal;
|
||||
|
||||
#[cfg(feature = "tracing")]
|
||||
pub use opentelemetry;
|
||||
@@ -15,7 +14,7 @@ pub use tracing_subscriber;
|
||||
#[cfg(feature = "tracing")]
|
||||
pub use tracing_tree;
|
||||
|
||||
#[derive(Debug, Default, Copy, Clone, Deserialize, PartialEq, Eq, Serialize)]
|
||||
#[derive(Debug, Default, Clone, Deserialize, PartialEq, Eq, Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct LoggingSettings {
|
||||
// well, we need to implement something here at some point...
|
||||
@@ -121,7 +120,7 @@ pub fn banner(crate_name: &str, crate_version: &str) -> String {
|
||||
}
|
||||
|
||||
pub fn maybe_print_banner(crate_name: &str, crate_version: &str) {
|
||||
if std::io::stdout().is_terminal() {
|
||||
if atty::is(atty::Stream::Stdout) {
|
||||
println!("{}", banner(crate_name, crate_version))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,31 +3,30 @@ name = "nym-client-core"
|
||||
version = "1.1.15"
|
||||
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"]
|
||||
edition = "2021"
|
||||
rust-version = "1.70"
|
||||
rust-version = "1.66"
|
||||
license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
async-trait = { workspace = true }
|
||||
bincode = { workspace = true }
|
||||
base64 = "0.21.2"
|
||||
bs58 = { workspace = true }
|
||||
cfg-if = { workspace = true }
|
||||
cfg-if = "1.0.0"
|
||||
clap = { workspace = true, optional = true }
|
||||
futures = { workspace = true }
|
||||
humantime-serde = { workspace = true }
|
||||
humantime-serde = "1.0"
|
||||
log = { workspace = true }
|
||||
rand = { workspace = true }
|
||||
rand = { version = "0.7.3", features = ["wasm-bindgen"] }
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
serde_json = { workspace = true }
|
||||
sha2 = "0.10.6"
|
||||
si-scale = { workspace = true }
|
||||
tap = { workspace = true }
|
||||
si-scale = "0.2.2"
|
||||
tap = "1.0.1"
|
||||
thiserror = { workspace = true }
|
||||
url = { workspace = true, features = ["serde"] }
|
||||
tungstenite = { workspace = true, default-features = false }
|
||||
tokio = { workspace = true, features = ["macros"] }
|
||||
tokio-util = { workspace = true, features = ["codec"] }
|
||||
time = { workspace = true }
|
||||
zeroize = { workspace = true }
|
||||
|
||||
@@ -35,7 +34,6 @@ zeroize = { workspace = true }
|
||||
nym-id = { path = "../nym-id" }
|
||||
nym-bandwidth-controller = { path = "../bandwidth-controller" }
|
||||
nym-config = { path = "../config" }
|
||||
nym-country-group = { path = "../country-group" }
|
||||
nym-crypto = { path = "../crypto" }
|
||||
nym-explorer-client = { path = "../../explorer-api/explorer-client" }
|
||||
nym-gateway-client = { path = "../client-libs/gateway-client" }
|
||||
@@ -49,9 +47,6 @@ nym-validator-client = { path = "../client-libs/validator-client", default-featu
|
||||
nym-task = { path = "../task" }
|
||||
nym-credential-storage = { path = "../credential-storage" }
|
||||
nym-network-defaults = { path = "../network-defaults" }
|
||||
nym-client-core-config-types = { path = "./config-types", features = [
|
||||
"disk-persistence",
|
||||
] }
|
||||
nym-client-core-surb-storage = { path = "./surb-storage" }
|
||||
nym-client-core-gateways-storage = { path = "./gateways-storage" }
|
||||
|
||||
@@ -77,17 +72,8 @@ workspace = true
|
||||
features = ["time"]
|
||||
|
||||
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.tokio-tungstenite]
|
||||
workspace = true
|
||||
features = ["rustls-tls-webpki-roots"]
|
||||
|
||||
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.tungstenite]
|
||||
workspace = true
|
||||
default-features = true
|
||||
features = ["rustls-tls-webpki-roots"]
|
||||
|
||||
[target."cfg(target_arch = \"wasm32\")".dependencies.tungstenite]
|
||||
workspace = true
|
||||
default-features = false
|
||||
version = "0.20.1"
|
||||
features = ["rustls-tls-native-roots"]
|
||||
|
||||
[target."cfg(target_arch = \"wasm32\")".dependencies.wasm-bindgen-futures]
|
||||
workspace = true
|
||||
@@ -112,7 +98,7 @@ version = "0.3.17"
|
||||
features = ["wasm-bindgen"]
|
||||
|
||||
[dev-dependencies]
|
||||
tempfile = { workspace = true }
|
||||
tempfile = "3.1.0"
|
||||
|
||||
[features]
|
||||
default = []
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
[package]
|
||||
name = "nym-client-core-config-types"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
humantime-serde = { workspace = true }
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
thiserror.workspace = true
|
||||
url = { workspace = true, features = ["serde"] }
|
||||
|
||||
nym-config = { path = "../../config" }
|
||||
|
||||
nym-country-group = { path = "../../country-group" }
|
||||
nym-pemstore = { path = "../../pemstore", optional = true }
|
||||
|
||||
# those are pulling so many deps T.T
|
||||
nym-sphinx-params = { path = "../../nymsphinx/params" }
|
||||
nym-sphinx-addressing = { path = "../../nymsphinx/addressing" }
|
||||
|
||||
|
||||
[features]
|
||||
disk-persistence = ["nym-pemstore"]
|
||||
@@ -1,9 +0,0 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
pub mod v1;
|
||||
pub mod v2;
|
||||
|
||||
// aliases for backwards compatibility
|
||||
pub use v1 as old_v1_1_20_2;
|
||||
pub use v2 as old_v1_1_33;
|
||||
@@ -1,37 +0,0 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::disk_persistence::old::v2::{
|
||||
ClientKeysPathsV2, CommonClientPathsV2, DEFAULT_GATEWAY_DETAILS_FILENAME,
|
||||
};
|
||||
use crate::error::ConfigUpgradeFailure;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::path::PathBuf;
|
||||
|
||||
// aliases for backwards compatibility
|
||||
pub type CommonClientPathsV1_1_20_2 = CommonClientPathsV1;
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct CommonClientPathsV1 {
|
||||
pub keys: ClientKeysPathsV2,
|
||||
pub credentials_database: PathBuf,
|
||||
pub reply_surb_database: PathBuf,
|
||||
}
|
||||
|
||||
impl CommonClientPathsV1 {
|
||||
pub fn upgrade_default(self) -> Result<CommonClientPathsV2, ConfigUpgradeFailure> {
|
||||
let data_dir = self
|
||||
.reply_surb_database
|
||||
.parent()
|
||||
.ok_or_else(|| ConfigUpgradeFailure {
|
||||
current_version: "1.1.20-2".to_string(),
|
||||
})?;
|
||||
Ok(CommonClientPathsV2 {
|
||||
keys: self.keys,
|
||||
gateway_details: data_dir.join(DEFAULT_GATEWAY_DETAILS_FILENAME),
|
||||
credentials_database: self.credentials_database,
|
||||
reply_surb_database: self.reply_surb_database,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
#[error("unable to upgrade config file from `{current_version}`")]
|
||||
pub struct ConfigUpgradeFailure {
|
||||
pub current_version: String,
|
||||
}
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum InvalidTrafficModeFailure {
|
||||
#[error("attempted to set medium toggle traffic mode with fast mode flag")]
|
||||
MediumToggleWithFastMode,
|
||||
|
||||
#[error("attempted to set medium toggle traffic mode with no cover flag")]
|
||||
MediumToggleWithNoCover,
|
||||
}
|
||||
@@ -1,677 +0,0 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use nym_config::defaults::NymNetworkDetails;
|
||||
use nym_sphinx_addressing::Recipient;
|
||||
use nym_sphinx_params::{PacketSize, PacketType};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::time::Duration;
|
||||
use url::Url;
|
||||
|
||||
#[cfg(feature = "disk-persistence")]
|
||||
pub mod disk_persistence;
|
||||
pub mod error;
|
||||
pub mod old;
|
||||
|
||||
pub use error::ConfigUpgradeFailure;
|
||||
|
||||
// 'DEBUG'
|
||||
const DEFAULT_ACK_WAIT_MULTIPLIER: f64 = 1.5;
|
||||
|
||||
const DEFAULT_ACK_WAIT_ADDITION: Duration = Duration::from_millis(1_500);
|
||||
const DEFAULT_LOOP_COVER_STREAM_AVERAGE_DELAY: Duration = Duration::from_millis(200);
|
||||
const DEFAULT_MESSAGE_STREAM_AVERAGE_DELAY: Duration = Duration::from_millis(20);
|
||||
const DEFAULT_AVERAGE_PACKET_DELAY: Duration = Duration::from_millis(50);
|
||||
const DEFAULT_TOPOLOGY_REFRESH_RATE: Duration = Duration::from_secs(5 * 60); // every 5min
|
||||
const DEFAULT_TOPOLOGY_RESOLUTION_TIMEOUT: Duration = Duration::from_millis(5_000);
|
||||
|
||||
// the same values as our current (10.06.24) blacklist
|
||||
const DEFAULT_MIN_MIXNODE_PERFORMANCE: u8 = 50;
|
||||
const DEFAULT_MIN_GATEWAY_PERFORMANCE: u8 = 50;
|
||||
|
||||
const DEFAULT_MAX_STARTUP_GATEWAY_WAITING_PERIOD: Duration = Duration::from_secs(70 * 60); // 70min -> full epoch (1h) + a bit of overhead
|
||||
|
||||
// Set this to a high value for now, so that we don't risk sporadic timeouts that might cause
|
||||
// bought bandwidth tokens to not have time to be spent; Once we remove the gateway from the
|
||||
// bandwidth bridging protocol, we can come back to a smaller timeout value
|
||||
const DEFAULT_GATEWAY_RESPONSE_TIMEOUT: Duration = Duration::from_secs(5 * 60);
|
||||
|
||||
const DEFAULT_COVER_TRAFFIC_PRIMARY_SIZE_RATIO: f64 = 0.70;
|
||||
|
||||
// reply-surbs related:
|
||||
|
||||
// define when to request
|
||||
// clients/client-core/src/client/replies/reply_storage/surb_storage.rs
|
||||
const DEFAULT_MINIMUM_REPLY_SURB_STORAGE_THRESHOLD: usize = 10;
|
||||
const DEFAULT_MAXIMUM_REPLY_SURB_STORAGE_THRESHOLD: usize = 200;
|
||||
|
||||
// define how much to request at once
|
||||
// clients/client-core/src/client/replies/reply_controller.rs
|
||||
const DEFAULT_MINIMUM_REPLY_SURB_REQUEST_SIZE: u32 = 10;
|
||||
const DEFAULT_MAXIMUM_REPLY_SURB_REQUEST_SIZE: u32 = 100;
|
||||
|
||||
const DEFAULT_MAXIMUM_ALLOWED_SURB_REQUEST_SIZE: u32 = 500;
|
||||
|
||||
const DEFAULT_MAXIMUM_REPLY_SURB_REREQUEST_WAITING_PERIOD: Duration = Duration::from_secs(10);
|
||||
const DEFAULT_MAXIMUM_REPLY_SURB_DROP_WAITING_PERIOD: Duration = Duration::from_secs(5 * 60);
|
||||
|
||||
// 12 hours
|
||||
const DEFAULT_MAXIMUM_REPLY_SURB_AGE: Duration = Duration::from_secs(12 * 60 * 60);
|
||||
|
||||
// 24 hours
|
||||
const DEFAULT_MAXIMUM_REPLY_KEY_AGE: Duration = Duration::from_secs(24 * 60 * 60);
|
||||
|
||||
use crate::error::InvalidTrafficModeFailure;
|
||||
pub use nym_country_group::CountryGroup;
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct Config {
|
||||
pub client: Client,
|
||||
|
||||
#[serde(default)]
|
||||
pub debug: DebugConfig,
|
||||
}
|
||||
|
||||
impl Config {
|
||||
pub fn new<S1, S2>(id: S1, version: S2) -> Self
|
||||
where
|
||||
S1: Into<String>,
|
||||
S2: Into<String>,
|
||||
{
|
||||
Config {
|
||||
client: Client::new_default(id, version),
|
||||
debug: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_client_config(client: Client, debug: DebugConfig) -> Self {
|
||||
Config { client, debug }
|
||||
}
|
||||
|
||||
pub fn validate(&self) -> bool {
|
||||
self.debug.validate()
|
||||
}
|
||||
|
||||
pub fn with_debug_config(mut self, debug: DebugConfig) -> Self {
|
||||
self.debug = debug;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_disabled_credentials(mut self, disabled_credentials_mode: bool) -> Self {
|
||||
self.client.disabled_credentials_mode = disabled_credentials_mode;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_custom_nyxd(mut self, urls: Vec<Url>) -> Self {
|
||||
self.client.nyxd_urls = urls;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn set_custom_nyxd(&mut self, nyxd_urls: Vec<Url>) {
|
||||
self.client.nyxd_urls = nyxd_urls;
|
||||
}
|
||||
|
||||
pub fn with_custom_nym_apis(mut self, nym_api_urls: Vec<Url>) -> Self {
|
||||
self.client.nym_api_urls = nym_api_urls;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn set_custom_nym_apis(&mut self, nym_api_urls: Vec<Url>) {
|
||||
self.client.nym_api_urls = nym_api_urls;
|
||||
}
|
||||
|
||||
pub fn with_high_default_traffic_volume(mut self, enabled: bool) -> Self {
|
||||
if enabled {
|
||||
self.set_high_default_traffic_volume();
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_packet_type(mut self, packet_type: PacketType) -> Self {
|
||||
self.debug.traffic.packet_type = packet_type;
|
||||
self
|
||||
}
|
||||
|
||||
// TODO: this should be refactored properly
|
||||
// as of 12.09.23 the below is true (not sure how this comment will rot in the future)
|
||||
// medium_toggle:
|
||||
// - sets secondary packet size to 16kb
|
||||
// - disables poisson distribution of the main traffic stream
|
||||
// - sets the cover traffic stream to 1 packet / 5s (on average)
|
||||
// - disables per hop delay
|
||||
//
|
||||
// fastmode (to be renamed to `fast-poisson`):
|
||||
// - sets average per hop delay to 10ms
|
||||
// - sets the cover traffic stream to 1 packet / 2000s (on average); for all intents and purposes it disables the stream
|
||||
// - sets the poisson distribution of the main traffic stream to 4ms, i.e. 250 packets / s on average
|
||||
//
|
||||
// no_cover:
|
||||
// - disables poisson distribution of the main traffic stream
|
||||
// - disables the secondary cover traffic stream
|
||||
#[doc(hidden)]
|
||||
pub fn try_apply_traffic_modes(
|
||||
&mut self,
|
||||
disable_poisson_process: bool,
|
||||
medium_toggle: bool,
|
||||
fast_mode: bool,
|
||||
no_cover: bool,
|
||||
) -> Result<(), InvalidTrafficModeFailure> {
|
||||
if disable_poisson_process {
|
||||
self.set_no_poisson_process()
|
||||
}
|
||||
|
||||
if medium_toggle {
|
||||
if fast_mode {
|
||||
return Err(InvalidTrafficModeFailure::MediumToggleWithFastMode);
|
||||
}
|
||||
if no_cover {
|
||||
return Err(InvalidTrafficModeFailure::MediumToggleWithNoCover);
|
||||
}
|
||||
|
||||
self.set_experimental_medium_toggle();
|
||||
}
|
||||
|
||||
if fast_mode {
|
||||
self.set_high_default_traffic_volume()
|
||||
}
|
||||
|
||||
if no_cover {
|
||||
self.set_no_cover_traffic();
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn set_high_default_traffic_volume(&mut self) {
|
||||
self.debug.traffic.average_packet_delay = Duration::from_millis(10);
|
||||
// basically don't really send cover messages
|
||||
self.debug.cover_traffic.loop_cover_traffic_average_delay =
|
||||
Duration::from_millis(2_000_000);
|
||||
// 250 "real" messages / s
|
||||
self.debug.traffic.message_sending_average_delay = Duration::from_millis(4);
|
||||
}
|
||||
|
||||
/// Enable medium mixnet traffic, for experiments only.
|
||||
/// This includes things like disabling cover traffic, no per hop delays, etc.
|
||||
#[doc(hidden)]
|
||||
pub fn set_experimental_medium_toggle(&mut self) {
|
||||
self.set_no_cover_traffic_with_keepalive();
|
||||
self.set_no_per_hop_delays();
|
||||
self.debug.traffic.secondary_packet_size = Some(PacketSize::ExtendedPacket16);
|
||||
}
|
||||
|
||||
pub fn with_disabled_poisson_process(mut self, disabled: bool) -> Self {
|
||||
if disabled {
|
||||
self.set_no_poisson_process()
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
pub fn set_no_poisson_process(&mut self) {
|
||||
self.debug.traffic.disable_main_poisson_packet_distribution = true;
|
||||
}
|
||||
|
||||
pub fn with_disabled_cover_traffic(mut self, disabled: bool) -> Self {
|
||||
if disabled {
|
||||
self.set_no_cover_traffic()
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
pub fn set_no_cover_traffic(&mut self) {
|
||||
self.debug.cover_traffic.disable_loop_cover_traffic_stream = true;
|
||||
self.debug.traffic.disable_main_poisson_packet_distribution = true;
|
||||
}
|
||||
|
||||
pub fn with_disabled_cover_traffic_with_keepalive(mut self, disabled: bool) -> Self {
|
||||
if disabled {
|
||||
self.set_no_cover_traffic_with_keepalive()
|
||||
}
|
||||
self
|
||||
}
|
||||
pub fn set_no_cover_traffic_with_keepalive(&mut self) {
|
||||
self.debug.traffic.disable_main_poisson_packet_distribution = true;
|
||||
self.debug.cover_traffic.loop_cover_traffic_average_delay = Duration::from_secs(5);
|
||||
}
|
||||
|
||||
pub fn with_disabled_topology_refresh(mut self, disable_topology_refresh: bool) -> Self {
|
||||
self.debug.topology.disable_refreshing = disable_topology_refresh;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_topology_structure(mut self, topology_structure: TopologyStructure) -> Self {
|
||||
self.set_topology_structure(topology_structure);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn set_topology_structure(&mut self, topology_structure: TopologyStructure) {
|
||||
self.debug.topology.topology_structure = topology_structure;
|
||||
}
|
||||
|
||||
pub fn with_no_per_hop_delays(mut self, no_per_hop_delays: bool) -> Self {
|
||||
if no_per_hop_delays {
|
||||
self.set_no_per_hop_delays()
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
pub fn set_no_per_hop_delays(&mut self) {
|
||||
self.debug.traffic.average_packet_delay = Duration::ZERO;
|
||||
self.debug.acknowledgements.average_ack_delay = Duration::ZERO;
|
||||
}
|
||||
|
||||
pub fn with_secondary_packet_size(mut self, secondary_packet_size: Option<PacketSize>) -> Self {
|
||||
self.set_secondary_packet_size(secondary_packet_size);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn set_secondary_packet_size(&mut self, secondary_packet_size: Option<PacketSize>) {
|
||||
self.debug.traffic.secondary_packet_size = secondary_packet_size;
|
||||
}
|
||||
|
||||
pub fn set_custom_version(&mut self, version: &str) {
|
||||
self.client.version = version.to_string();
|
||||
}
|
||||
|
||||
pub fn get_id(&self) -> String {
|
||||
self.client.id.clone()
|
||||
}
|
||||
|
||||
pub fn get_disabled_credentials_mode(&self) -> bool {
|
||||
self.client.disabled_credentials_mode
|
||||
}
|
||||
|
||||
pub fn get_validator_endpoints(&self) -> Vec<Url> {
|
||||
self.client.nyxd_urls.clone()
|
||||
}
|
||||
|
||||
pub fn get_nym_api_endpoints(&self) -> Vec<Url> {
|
||||
self.client.nym_api_urls.clone()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
|
||||
// note: the deny_unknown_fields is VITAL here to allow upgrades from v1.1.20_2
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct Client {
|
||||
/// Version of the client for which this configuration was created.
|
||||
pub version: String,
|
||||
|
||||
/// ID specifies the human readable ID of this particular client.
|
||||
pub id: String,
|
||||
|
||||
/// Indicates whether this client is running in a disabled credentials mode, thus attempting
|
||||
/// to claim bandwidth without presenting bandwidth credentials.
|
||||
// TODO: this should be moved to `debug.gateway_connection`
|
||||
#[serde(default)]
|
||||
pub disabled_credentials_mode: bool,
|
||||
|
||||
/// Addresses to nyxd validators via which the client can communicate with the chain.
|
||||
#[serde(alias = "validator_urls")]
|
||||
pub nyxd_urls: Vec<Url>,
|
||||
|
||||
/// Addresses to APIs running on validator from which the client gets the view of the network.
|
||||
#[serde(alias = "validator_api_urls")]
|
||||
pub nym_api_urls: Vec<Url>,
|
||||
}
|
||||
|
||||
impl Client {
|
||||
pub fn new_default<S1, S2>(id: S1, version: S2) -> Self
|
||||
where
|
||||
S1: Into<String>,
|
||||
S2: Into<String>,
|
||||
{
|
||||
let network = NymNetworkDetails::new_mainnet();
|
||||
let nyxd_urls = network
|
||||
.endpoints
|
||||
.iter()
|
||||
.map(|validator| validator.nyxd_url())
|
||||
.collect();
|
||||
let nym_api_urls = network
|
||||
.endpoints
|
||||
.iter()
|
||||
.filter_map(|validator| validator.api_url())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
Client {
|
||||
version: version.into(),
|
||||
id: id.into(),
|
||||
disabled_credentials_mode: true,
|
||||
nyxd_urls,
|
||||
nym_api_urls,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new<S: Into<String>>(
|
||||
id: S,
|
||||
version: S,
|
||||
disabled_credentials_mode: bool,
|
||||
nyxd_urls: Vec<Url>,
|
||||
nym_api_urls: Vec<Url>,
|
||||
) -> Self {
|
||||
Client {
|
||||
version: version.into(),
|
||||
id: id.into(),
|
||||
disabled_credentials_mode,
|
||||
nyxd_urls,
|
||||
nym_api_urls,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default, deny_unknown_fields)]
|
||||
pub struct Traffic {
|
||||
/// The parameter of Poisson distribution determining how long, on average,
|
||||
/// sent packet is going to be delayed at any given mix node.
|
||||
/// So for a packet going through three mix nodes, on average, it will take three times this value
|
||||
/// until the packet reaches its destination.
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub average_packet_delay: Duration,
|
||||
|
||||
/// The parameter of Poisson distribution determining how long, on average,
|
||||
/// it is going to take another 'real traffic stream' message to be sent.
|
||||
/// If no real packets are available and cover traffic is enabled,
|
||||
/// a loop cover message is sent instead in order to preserve the rate.
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub message_sending_average_delay: Duration,
|
||||
|
||||
/// Controls whether the main packet stream constantly produces packets according to the predefined
|
||||
/// poisson distribution.
|
||||
pub disable_main_poisson_packet_distribution: bool,
|
||||
|
||||
/// Specifies the packet size used for sent messages.
|
||||
/// Do not override it unless you understand the consequences of that change.
|
||||
pub primary_packet_size: PacketSize,
|
||||
|
||||
/// Specifies the optional auxiliary packet size for optimizing message streams.
|
||||
/// Note that its use decreases overall anonymity.
|
||||
/// Do not set it it unless you understand the consequences of that change.
|
||||
pub secondary_packet_size: Option<PacketSize>,
|
||||
|
||||
pub packet_type: PacketType,
|
||||
}
|
||||
|
||||
impl Traffic {
|
||||
pub fn validate(&self) -> bool {
|
||||
if let Some(secondary_packet_size) = self.secondary_packet_size {
|
||||
if secondary_packet_size == PacketSize::AckPacket
|
||||
|| secondary_packet_size == self.primary_packet_size
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Traffic {
|
||||
fn default() -> Self {
|
||||
Traffic {
|
||||
average_packet_delay: DEFAULT_AVERAGE_PACKET_DELAY,
|
||||
message_sending_average_delay: DEFAULT_MESSAGE_STREAM_AVERAGE_DELAY,
|
||||
disable_main_poisson_packet_distribution: false,
|
||||
primary_packet_size: PacketSize::RegularPacket,
|
||||
secondary_packet_size: None,
|
||||
packet_type: PacketType::Mix,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default, deny_unknown_fields)]
|
||||
pub struct CoverTraffic {
|
||||
/// The parameter of Poisson distribution determining how long, on average,
|
||||
/// it is going to take for another loop cover traffic message to be sent.
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub loop_cover_traffic_average_delay: Duration,
|
||||
|
||||
/// Specifies the ratio of `primary_packet_size` to `secondary_packet_size` used in cover traffic.
|
||||
/// Only applicable if `secondary_packet_size` is enabled.
|
||||
pub cover_traffic_primary_size_ratio: f64,
|
||||
|
||||
/// Controls whether the dedicated loop cover traffic stream should be enabled.
|
||||
/// (and sending packets, on average, every [Self::loop_cover_traffic_average_delay])
|
||||
pub disable_loop_cover_traffic_stream: bool,
|
||||
}
|
||||
|
||||
impl Default for CoverTraffic {
|
||||
fn default() -> Self {
|
||||
CoverTraffic {
|
||||
loop_cover_traffic_average_delay: DEFAULT_LOOP_COVER_STREAM_AVERAGE_DELAY,
|
||||
cover_traffic_primary_size_ratio: DEFAULT_COVER_TRAFFIC_PRIMARY_SIZE_RATIO,
|
||||
disable_loop_cover_traffic_stream: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default, deny_unknown_fields)]
|
||||
pub struct GatewayConnection {
|
||||
/// How long we're willing to wait for a response to a message sent to the gateway,
|
||||
/// before giving up on it.
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub gateway_response_timeout: Duration,
|
||||
}
|
||||
|
||||
impl Default for GatewayConnection {
|
||||
fn default() -> Self {
|
||||
GatewayConnection {
|
||||
gateway_response_timeout: DEFAULT_GATEWAY_RESPONSE_TIMEOUT,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default, deny_unknown_fields)]
|
||||
pub struct Acknowledgements {
|
||||
/// The parameter of Poisson distribution determining how long, on average,
|
||||
/// sent acknowledgement is going to be delayed at any given mix node.
|
||||
/// So for an ack going through three mix nodes, on average, it will take three times this value
|
||||
/// until the packet reaches its destination.
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub average_ack_delay: Duration,
|
||||
|
||||
/// Value multiplied with the expected round trip time of an acknowledgement packet before
|
||||
/// it is assumed it was lost and retransmission of the data packet happens.
|
||||
/// In an ideal network with 0 latency, this value would have been 1.
|
||||
pub ack_wait_multiplier: f64,
|
||||
|
||||
/// Value added to the expected round trip time of an acknowledgement packet before
|
||||
/// it is assumed it was lost and retransmission of the data packet happens.
|
||||
/// In an ideal network with 0 latency, this value would have been 0.
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub ack_wait_addition: Duration,
|
||||
}
|
||||
|
||||
impl Default for Acknowledgements {
|
||||
fn default() -> Self {
|
||||
Acknowledgements {
|
||||
average_ack_delay: DEFAULT_AVERAGE_PACKET_DELAY,
|
||||
ack_wait_multiplier: DEFAULT_ACK_WAIT_MULTIPLIER,
|
||||
ack_wait_addition: DEFAULT_ACK_WAIT_ADDITION,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default, deny_unknown_fields)]
|
||||
pub struct Topology {
|
||||
/// The uniform delay every which clients are querying the directory server
|
||||
/// to try to obtain a compatible network topology to send sphinx packets through.
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub topology_refresh_rate: Duration,
|
||||
|
||||
/// During topology refresh, test packets are sent through every single possible network
|
||||
/// path. This timeout determines waiting period until it is decided that the packet
|
||||
/// did not reach its destination.
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub topology_resolution_timeout: Duration,
|
||||
|
||||
/// Specifies whether the client should not refresh the network topology after obtaining
|
||||
/// the first valid instance.
|
||||
/// Supersedes `topology_refresh_rate_ms`.
|
||||
pub disable_refreshing: bool,
|
||||
|
||||
/// Defines how long the client is going to wait on startup for its gateway to come online,
|
||||
/// before abandoning the procedure.
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub max_startup_gateway_waiting_period: Duration,
|
||||
|
||||
/// Specifies the mixnode topology to be used for sending packets.
|
||||
pub topology_structure: TopologyStructure,
|
||||
|
||||
/// Specifies a minimum performance of a mixnode that is used on route construction.
|
||||
/// This setting is only applicable when `NymApi` topology is used.
|
||||
pub minimum_mixnode_performance: u8,
|
||||
|
||||
/// Specifies a minimum performance of a gateway that is used on route construction.
|
||||
/// This setting is only applicable when `NymApi` topology is used.
|
||||
pub minimum_gateway_performance: u8,
|
||||
}
|
||||
|
||||
#[allow(clippy::large_enum_variant)]
|
||||
#[derive(Default, Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub enum TopologyStructure {
|
||||
#[default]
|
||||
NymApi,
|
||||
GeoAware(GroupBy),
|
||||
}
|
||||
|
||||
#[allow(clippy::large_enum_variant)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub enum GroupBy {
|
||||
CountryGroup(CountryGroup),
|
||||
NymAddress(Recipient),
|
||||
}
|
||||
|
||||
impl std::fmt::Display for GroupBy {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
GroupBy::CountryGroup(group) => write!(f, "group: {group}"),
|
||||
GroupBy::NymAddress(address) => write!(f, "address: {address}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Topology {
|
||||
fn default() -> Self {
|
||||
Topology {
|
||||
topology_refresh_rate: DEFAULT_TOPOLOGY_REFRESH_RATE,
|
||||
topology_resolution_timeout: DEFAULT_TOPOLOGY_RESOLUTION_TIMEOUT,
|
||||
disable_refreshing: false,
|
||||
max_startup_gateway_waiting_period: DEFAULT_MAX_STARTUP_GATEWAY_WAITING_PERIOD,
|
||||
topology_structure: TopologyStructure::default(),
|
||||
minimum_mixnode_performance: DEFAULT_MIN_MIXNODE_PERFORMANCE,
|
||||
minimum_gateway_performance: DEFAULT_MIN_GATEWAY_PERFORMANCE,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default, deny_unknown_fields)]
|
||||
pub struct ReplySurbs {
|
||||
/// Defines the minimum number of reply surbs the client wants to keep in its storage at all times.
|
||||
/// It can only allow to go below that value if its to request additional reply surbs.
|
||||
pub minimum_reply_surb_storage_threshold: usize,
|
||||
|
||||
/// Defines the maximum number of reply surbs the client wants to keep in its storage at any times.
|
||||
pub maximum_reply_surb_storage_threshold: usize,
|
||||
|
||||
/// Defines the minimum number of reply surbs the client would request.
|
||||
pub minimum_reply_surb_request_size: u32,
|
||||
|
||||
/// Defines the maximum number of reply surbs the client would request.
|
||||
pub maximum_reply_surb_request_size: u32,
|
||||
|
||||
/// Defines the maximum number of reply surbs a remote party is allowed to request from this client at once.
|
||||
pub maximum_allowed_reply_surb_request_size: u32,
|
||||
|
||||
/// Defines maximum amount of time the client is going to wait for reply surbs before explicitly asking
|
||||
/// for more even though in theory they wouldn't need to.
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub maximum_reply_surb_rerequest_waiting_period: Duration,
|
||||
|
||||
/// Defines maximum amount of time the client is going to wait for reply surbs before
|
||||
/// deciding it's never going to get them and would drop all pending messages
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub maximum_reply_surb_drop_waiting_period: Duration,
|
||||
|
||||
/// Defines maximum amount of time given reply surb is going to be valid for.
|
||||
/// This is going to be superseded by key rotation once implemented.
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub maximum_reply_surb_age: Duration,
|
||||
|
||||
/// Defines maximum amount of time given reply key is going to be valid for.
|
||||
/// This is going to be superseded by key rotation once implemented.
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub maximum_reply_key_age: Duration,
|
||||
|
||||
/// Specifies the number of mixnet hops the packet should go through. If not specified, then
|
||||
/// the default value is used.
|
||||
pub surb_mix_hops: Option<u8>,
|
||||
}
|
||||
|
||||
impl Default for ReplySurbs {
|
||||
fn default() -> Self {
|
||||
ReplySurbs {
|
||||
minimum_reply_surb_storage_threshold: DEFAULT_MINIMUM_REPLY_SURB_STORAGE_THRESHOLD,
|
||||
maximum_reply_surb_storage_threshold: DEFAULT_MAXIMUM_REPLY_SURB_STORAGE_THRESHOLD,
|
||||
minimum_reply_surb_request_size: DEFAULT_MINIMUM_REPLY_SURB_REQUEST_SIZE,
|
||||
maximum_reply_surb_request_size: DEFAULT_MAXIMUM_REPLY_SURB_REQUEST_SIZE,
|
||||
maximum_allowed_reply_surb_request_size: DEFAULT_MAXIMUM_ALLOWED_SURB_REQUEST_SIZE,
|
||||
maximum_reply_surb_rerequest_waiting_period:
|
||||
DEFAULT_MAXIMUM_REPLY_SURB_REREQUEST_WAITING_PERIOD,
|
||||
maximum_reply_surb_drop_waiting_period: DEFAULT_MAXIMUM_REPLY_SURB_DROP_WAITING_PERIOD,
|
||||
maximum_reply_surb_age: DEFAULT_MAXIMUM_REPLY_SURB_AGE,
|
||||
maximum_reply_key_age: DEFAULT_MAXIMUM_REPLY_KEY_AGE,
|
||||
surb_mix_hops: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default, deny_unknown_fields)]
|
||||
pub struct DebugConfig {
|
||||
/// Defines all configuration options related to traffic streams.
|
||||
pub traffic: Traffic,
|
||||
|
||||
/// Defines all configuration options related to cover traffic stream(s).
|
||||
pub cover_traffic: CoverTraffic,
|
||||
|
||||
/// Defines all configuration options related to the gateway connection.
|
||||
pub gateway_connection: GatewayConnection,
|
||||
|
||||
/// Defines all configuration options related to acknowledgements, such as delays or wait timeouts.
|
||||
pub acknowledgements: Acknowledgements,
|
||||
|
||||
/// Defines all configuration options related topology, such as refresh rates or timeouts.
|
||||
pub topology: Topology,
|
||||
|
||||
/// Defines all configuration options related to reply SURBs.
|
||||
pub reply_surbs: ReplySurbs,
|
||||
}
|
||||
|
||||
impl DebugConfig {
|
||||
pub fn validate(&self) -> bool {
|
||||
// no other sections have explicit requirements (yet)
|
||||
self.traffic.validate()
|
||||
}
|
||||
}
|
||||
|
||||
// it could be derived, sure, but I'd rather have an explicit implementation in case we had to change
|
||||
// something manually at some point
|
||||
#[allow(clippy::derivable_impls)]
|
||||
impl Default for DebugConfig {
|
||||
fn default() -> Self {
|
||||
DebugConfig {
|
||||
traffic: Default::default(),
|
||||
cover_traffic: Default::default(),
|
||||
gateway_connection: Default::default(),
|
||||
acknowledgements: Default::default(),
|
||||
topology: Default::default(),
|
||||
reply_surbs: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
pub mod v1;
|
||||
pub mod v2;
|
||||
pub mod v3;
|
||||
pub mod v4;
|
||||
pub mod v5;
|
||||
|
||||
// aliases for backwards compatibility
|
||||
pub use v1 as old_config_v1_1_13;
|
||||
pub use v2 as old_config_v1_1_20;
|
||||
pub use v3 as old_config_v1_1_20_2;
|
||||
pub use v4 as old_config_v1_1_30;
|
||||
pub use v5 as old_config_v1_1_33;
|
||||
-18
@@ -1,18 +0,0 @@
|
||||
/*
|
||||
* Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
CREATE TABLE remote_gateway_details_temp
|
||||
(
|
||||
gateway_id_bs58 TEXT NOT NULL UNIQUE PRIMARY KEY REFERENCES registered_gateway (gateway_id_bs58),
|
||||
derived_aes128_ctr_blake3_hmac_keys_bs58 TEXT NOT NULL,
|
||||
gateway_owner_address TEXT,
|
||||
gateway_listener TEXT NOT NULL,
|
||||
wg_tun_address TEXT
|
||||
);
|
||||
|
||||
INSERT INTO remote_gateway_details_temp SELECT * FROM remote_gateway_details;
|
||||
|
||||
DROP TABLE remote_gateway_details;
|
||||
ALTER TABLE remote_gateway_details_temp RENAME TO remote_gateway_details;
|
||||
@@ -27,12 +27,6 @@ pub struct GatewayRegistration {
|
||||
pub registration_timestamp: OffsetDateTime,
|
||||
}
|
||||
|
||||
impl GatewayRegistration {
|
||||
pub fn gateway_id(&self) -> identity::PublicKey {
|
||||
self.details.gateway_id()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a GatewayRegistration> for RawRegisteredGateway {
|
||||
fn from(value: &'a GatewayRegistration) -> Self {
|
||||
RawRegisteredGateway {
|
||||
@@ -65,7 +59,7 @@ impl GatewayDetails {
|
||||
pub fn new_remote(
|
||||
gateway_id: identity::PublicKey,
|
||||
derived_aes128_ctr_blake3_hmac_keys: Arc<SharedKeys>,
|
||||
gateway_owner_address: Option<AccountId>,
|
||||
gateway_owner_address: AccountId,
|
||||
gateway_listener: Url,
|
||||
wg_tun_address: Option<Url>,
|
||||
) -> Self {
|
||||
@@ -170,7 +164,7 @@ pub struct RegisteredGateway {
|
||||
pub struct RawRemoteGatewayDetails {
|
||||
pub gateway_id_bs58: String,
|
||||
pub derived_aes128_ctr_blake3_hmac_keys_bs58: String,
|
||||
pub gateway_owner_address: Option<String>,
|
||||
pub gateway_owner_address: String,
|
||||
pub gateway_listener: String,
|
||||
pub wg_tun_address: Option<String>,
|
||||
}
|
||||
@@ -195,19 +189,14 @@ impl TryFrom<RawRemoteGatewayDetails> for RemoteGatewayDetails {
|
||||
})?,
|
||||
);
|
||||
|
||||
let gateway_owner_address = value
|
||||
.gateway_owner_address
|
||||
.as_ref()
|
||||
.map(|raw_owner| {
|
||||
AccountId::from_str(raw_owner).map_err(|source| {
|
||||
BadGateway::MalformedGatewayOwnerAccountAddress {
|
||||
gateway_id: value.gateway_id_bs58.clone(),
|
||||
raw_owner: raw_owner.clone(),
|
||||
source,
|
||||
}
|
||||
})
|
||||
})
|
||||
.transpose()?;
|
||||
let gateway_owner_address =
|
||||
AccountId::from_str(&value.gateway_owner_address).map_err(|source| {
|
||||
BadGateway::MalformedGatewayOwnerAccountAddress {
|
||||
gateway_id: value.gateway_id_bs58.clone(),
|
||||
raw_owner: value.gateway_owner_address.clone(),
|
||||
source,
|
||||
}
|
||||
})?;
|
||||
|
||||
let gateway_listener = Url::parse(&value.gateway_listener).map_err(|source| {
|
||||
BadGateway::MalformedListener {
|
||||
@@ -246,7 +235,7 @@ impl<'a> From<&'a RemoteGatewayDetails> for RawRemoteGatewayDetails {
|
||||
derived_aes128_ctr_blake3_hmac_keys_bs58: value
|
||||
.derived_aes128_ctr_blake3_hmac_keys
|
||||
.to_base58_string(),
|
||||
gateway_owner_address: value.gateway_owner_address.as_ref().map(|o| o.to_string()),
|
||||
gateway_owner_address: value.gateway_owner_address.to_string(),
|
||||
gateway_listener: value.gateway_listener.to_string(),
|
||||
wg_tun_address: value.wg_tun_address.as_ref().map(|addr| addr.to_string()),
|
||||
}
|
||||
@@ -261,7 +250,7 @@ pub struct RemoteGatewayDetails {
|
||||
// the keys will be zeroized
|
||||
pub derived_aes128_ctr_blake3_hmac_keys: Arc<SharedKeys>,
|
||||
|
||||
pub gateway_owner_address: Option<AccountId>,
|
||||
pub gateway_owner_address: AccountId,
|
||||
|
||||
pub gateway_listener: Url,
|
||||
|
||||
@@ -309,12 +298,3 @@ pub struct CustomGatewayDetails {
|
||||
pub gateway_id: identity::PublicKey,
|
||||
pub data: Option<Vec<u8>>,
|
||||
}
|
||||
|
||||
impl CustomGatewayDetails {
|
||||
pub fn new(gateway_id: identity::PublicKey) -> CustomGatewayDetails {
|
||||
Self {
|
||||
gateway_id,
|
||||
data: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ use crate::client::replies::reply_storage::{
|
||||
};
|
||||
use crate::client::topology_control::nym_api_provider::NymApiTopologyProvider;
|
||||
use crate::client::topology_control::{
|
||||
nym_api_provider, TopologyAccessor, TopologyRefresher, TopologyRefresherConfig,
|
||||
TopologyAccessor, TopologyRefresher, TopologyRefresherConfig,
|
||||
};
|
||||
use crate::config::{Config, DebugConfig};
|
||||
use crate::error::ClientCoreError;
|
||||
@@ -35,12 +35,11 @@ use crate::init::{
|
||||
};
|
||||
use crate::{config, spawn_future};
|
||||
use futures::channel::mpsc;
|
||||
use futures::SinkExt;
|
||||
use log::{debug, error, info, warn};
|
||||
use nym_bandwidth_controller::BandwidthController;
|
||||
use nym_client_core_gateways_storage::{GatewayDetails, GatewaysDetailsStore};
|
||||
use nym_credential_storage::storage::Storage as CredentialStorage;
|
||||
use nym_crypto::asymmetric::{encryption, identity};
|
||||
use nym_crypto::asymmetric::encryption;
|
||||
use nym_gateway_client::{
|
||||
AcknowledgementReceiver, GatewayClient, GatewayConfig, MixnetMessageReceiver, PacketRouter,
|
||||
};
|
||||
@@ -60,7 +59,6 @@ use std::fmt::Debug;
|
||||
use std::os::raw::c_int as RawFd;
|
||||
use std::path::Path;
|
||||
use std::sync::Arc;
|
||||
use tokio_util::sync::{PollSendError, PollSender};
|
||||
use url::Url;
|
||||
|
||||
#[cfg(all(
|
||||
@@ -80,7 +78,10 @@ pub struct ClientInput {
|
||||
}
|
||||
|
||||
impl ClientInput {
|
||||
pub async fn send(&mut self, message: InputMessage) -> Result<(), PollSendError<InputMessage>> {
|
||||
pub async fn send(
|
||||
&self,
|
||||
message: InputMessage,
|
||||
) -> Result<(), tokio::sync::mpsc::error::SendError<InputMessage>> {
|
||||
self.input_sender.send(message).await
|
||||
}
|
||||
}
|
||||
@@ -387,10 +388,7 @@ where
|
||||
|
||||
let cfg = GatewayConfig::new(
|
||||
details.gateway_id,
|
||||
details
|
||||
.gateway_owner_address
|
||||
.as_ref()
|
||||
.map(|o| o.to_string()),
|
||||
Some(details.gateway_owner_address.to_string()),
|
||||
gateway_listener,
|
||||
);
|
||||
GatewayClient::new(
|
||||
@@ -464,16 +462,12 @@ where
|
||||
|
||||
fn setup_topology_provider(
|
||||
custom_provider: Option<Box<dyn TopologyProvider + Send + Sync>>,
|
||||
config_topology: config::Topology,
|
||||
provider_from_config: config::TopologyStructure,
|
||||
nym_api_urls: Vec<Url>,
|
||||
) -> Box<dyn TopologyProvider + Send + Sync> {
|
||||
// if no custom provider was ... provided ..., create one using nym-api
|
||||
custom_provider.unwrap_or_else(|| match config_topology.topology_structure {
|
||||
custom_provider.unwrap_or_else(|| match provider_from_config {
|
||||
config::TopologyStructure::NymApi => Box::new(NymApiTopologyProvider::new(
|
||||
nym_api_provider::Config {
|
||||
min_mixnode_performance: config_topology.minimum_mixnode_performance,
|
||||
min_gateway_performance: config_topology.minimum_gateway_performance,
|
||||
},
|
||||
nym_api_urls,
|
||||
env!("CARGO_PKG_VERSION").to_string(),
|
||||
)),
|
||||
@@ -676,7 +670,6 @@ where
|
||||
let self_address = Self::mix_address(&init_res);
|
||||
let ack_key = init_res.client_keys.ack_key();
|
||||
let encryption_keys = init_res.client_keys.encryption_keypair();
|
||||
let identity_keys = init_res.client_keys.identity_keypair();
|
||||
|
||||
// the components are started in very specific order. Unless you know what you are doing,
|
||||
// do not change that.
|
||||
@@ -686,7 +679,7 @@ where
|
||||
|
||||
let topology_provider = Self::setup_topology_provider(
|
||||
self.custom_topology_provider.take(),
|
||||
self.config.debug.topology,
|
||||
self.config.debug.topology.topology_structure,
|
||||
self.config.get_nym_api_endpoints(),
|
||||
);
|
||||
|
||||
@@ -799,11 +792,10 @@ where
|
||||
|
||||
Ok(BaseClient {
|
||||
address: self_address,
|
||||
identity_keys,
|
||||
client_input: ClientInputStatus::AwaitingProducer {
|
||||
client_input: ClientInput {
|
||||
connection_command_sender: client_connection_tx,
|
||||
input_sender: PollSender::new(input_sender),
|
||||
input_sender,
|
||||
},
|
||||
},
|
||||
client_output: ClientOutputStatus::AwaitingConsumer {
|
||||
@@ -824,7 +816,6 @@ where
|
||||
|
||||
pub struct BaseClient {
|
||||
pub address: Recipient,
|
||||
pub identity_keys: Arc<identity::KeyPair>,
|
||||
pub client_input: ClientInputStatus,
|
||||
pub client_output: ClientOutputStatus,
|
||||
pub client_state: ClientState,
|
||||
|
||||
@@ -92,11 +92,11 @@ pub mod v1_1_33 {
|
||||
message: format!("the stored gateway id was malformed: {err}"),
|
||||
})?,
|
||||
derived_aes128_ctr_blake3_hmac_keys: Arc::new(gateway_shared_key),
|
||||
gateway_owner_address: Some(gateway_owner.parse().map_err(|err| {
|
||||
gateway_owner_address: gateway_owner.parse().map_err(|err| {
|
||||
ClientCoreError::UpgradeFailure {
|
||||
message: format!("the stored gateway owner address was malformed: {err}"),
|
||||
}
|
||||
})?),
|
||||
})?,
|
||||
gateway_listener: gateway_listener.parse().map_err(|err| {
|
||||
ClientCoreError::UpgradeFailure {
|
||||
message: format!("the stored gateway listener address was malformed: {err}"),
|
||||
|
||||
@@ -1,26 +1,16 @@
|
||||
// Copyright 2020-2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use nym_sphinx::addressing::clients::Recipient;
|
||||
use nym_sphinx::anonymous_replies::requests::AnonymousSenderTag;
|
||||
use nym_sphinx::forwarding::packet::MixPacket;
|
||||
use nym_sphinx::params::PacketType;
|
||||
use nym_task::connections::TransmissionLane;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::convert::TryInto;
|
||||
use tokio_util::{
|
||||
bytes::Buf,
|
||||
bytes::BytesMut,
|
||||
codec::{Decoder, Encoder},
|
||||
};
|
||||
|
||||
use crate::error::ClientCoreError;
|
||||
|
||||
pub type InputMessageSender = tokio_util::sync::PollSender<InputMessage>;
|
||||
pub type InputMessageSender = tokio::sync::mpsc::Sender<InputMessage>;
|
||||
pub type InputMessageReceiver = tokio::sync::mpsc::Receiver<InputMessage>;
|
||||
|
||||
const LENGHT_ENCODING_PREFIX_SIZE: usize = 4;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[derive(Debug)]
|
||||
pub enum InputMessage {
|
||||
/// Fire an already prepared mix packets into the network.
|
||||
/// No guarantees are made about it. For example no retransmssion
|
||||
@@ -74,10 +64,6 @@ pub enum InputMessage {
|
||||
}
|
||||
|
||||
impl InputMessage {
|
||||
pub fn simple(data: &[u8], recipient: Recipient) -> Self {
|
||||
InputMessage::new_regular(recipient, data.to_vec(), TransmissionLane::General, None)
|
||||
}
|
||||
|
||||
pub fn new_premade(
|
||||
msgs: Vec<MixPacket>,
|
||||
lane: TransmissionLane,
|
||||
@@ -211,70 +197,4 @@ impl InputMessage {
|
||||
InputMessage::MessageWrapper { message, .. } => message.lane(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn serialized_size(&self) -> u64 {
|
||||
bincode::serialized_size(self).expect("failed to get serialized InputMessage size")
|
||||
+ LENGHT_ENCODING_PREFIX_SIZE as u64
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Tests
|
||||
pub struct AdressedInputMessageCodec(pub Recipient);
|
||||
|
||||
impl Encoder<&[u8]> for AdressedInputMessageCodec {
|
||||
type Error = ClientCoreError;
|
||||
|
||||
fn encode(&mut self, item: &[u8], buf: &mut BytesMut) -> Result<(), Self::Error> {
|
||||
let mut codec = InputMessageCodec;
|
||||
let input_message = InputMessage::simple(item, self.0.clone());
|
||||
codec.encode(input_message, buf)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct InputMessageCodec;
|
||||
|
||||
impl Encoder<InputMessage> for InputMessageCodec {
|
||||
type Error = ClientCoreError;
|
||||
|
||||
fn encode(&mut self, item: InputMessage, buf: &mut BytesMut) -> Result<(), Self::Error> {
|
||||
let encoded = bincode::serialize(&item).expect("failed to serialize InputMessage");
|
||||
let encoded_len = encoded.len() as u32;
|
||||
let mut encoded_with_len = encoded_len.to_le_bytes().to_vec();
|
||||
encoded_with_len.extend(encoded);
|
||||
buf.reserve(encoded_with_len.len());
|
||||
buf.extend_from_slice(&encoded_with_len);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Decoder for InputMessageCodec {
|
||||
type Item = InputMessage;
|
||||
type Error = ClientCoreError;
|
||||
|
||||
fn decode(&mut self, buf: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
|
||||
if buf.len() < LENGHT_ENCODING_PREFIX_SIZE {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
let len = u32::from_le_bytes(
|
||||
buf[0..LENGHT_ENCODING_PREFIX_SIZE]
|
||||
.try_into()
|
||||
.expect("Could not coarce to array"),
|
||||
) as usize;
|
||||
if buf.len() < len + LENGHT_ENCODING_PREFIX_SIZE {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
let decoded = match bincode::deserialize(
|
||||
&buf[LENGHT_ENCODING_PREFIX_SIZE..len + LENGHT_ENCODING_PREFIX_SIZE],
|
||||
) {
|
||||
Ok(decoded) => decoded,
|
||||
Err(_) => return Ok(None),
|
||||
};
|
||||
|
||||
buf.advance(len + LENGHT_ENCODING_PREFIX_SIZE);
|
||||
|
||||
Ok(Some(decoded))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ use std::error::Error;
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
use crate::config::disk_persistence::ClientKeysPaths;
|
||||
use crate::config::disk_persistence::keys_paths::ClientKeysPaths;
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
use nym_crypto::asymmetric::{encryption, identity};
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use crate::config::GroupBy;
|
||||
use log::{debug, error};
|
||||
use std::{collections::HashMap, fmt};
|
||||
|
||||
use log::{debug, error, info};
|
||||
use nym_explorer_client::{ExplorerClient, PrettyDetailedMixNodeBond};
|
||||
use nym_network_defaults::var_names::EXPLORER_API;
|
||||
use nym_topology::{
|
||||
@@ -9,11 +10,11 @@ use nym_topology::{
|
||||
};
|
||||
use nym_validator_client::client::MixId;
|
||||
use rand::{prelude::SliceRandom, thread_rng};
|
||||
use std::collections::HashMap;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tap::TapOptional;
|
||||
use url::Url;
|
||||
|
||||
pub use nym_country_group::CountryGroup;
|
||||
use crate::config::GroupBy;
|
||||
|
||||
const MIN_NODES_PER_LAYER: usize = 1;
|
||||
|
||||
@@ -37,6 +38,158 @@ fn create_explorer_client() -> Option<ExplorerClient> {
|
||||
Some(client)
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Hash, PartialEq, Eq, Serialize, Deserialize, Debug)]
|
||||
pub enum CountryGroup {
|
||||
Europe,
|
||||
NorthAmerica,
|
||||
SouthAmerica,
|
||||
Oceania,
|
||||
Asia,
|
||||
Africa,
|
||||
Unknown,
|
||||
}
|
||||
|
||||
impl CountryGroup {
|
||||
// We map contry codes into group, which initially are continent codes to a first approximation,
|
||||
// but we do it manually to reserve the right to tweak this distribution for our purposes.
|
||||
// NOTE: I did this quickly and it's not a complete list of all countries, but only those that
|
||||
// were present in the network at the time. Please add more as needed.
|
||||
fn new(country_code: &str) -> Self {
|
||||
let country_code = country_code.to_uppercase();
|
||||
use CountryGroup::*;
|
||||
match country_code.as_ref() {
|
||||
// Europe
|
||||
"AT" => Europe,
|
||||
"BG" => Europe,
|
||||
"CH" => Europe,
|
||||
"CY" => Europe,
|
||||
"CZ" => Europe,
|
||||
"DE" => Europe,
|
||||
"DK" => Europe,
|
||||
"ES" => Europe,
|
||||
"FI" => Europe,
|
||||
"FR" => Europe,
|
||||
"GB" => Europe,
|
||||
"GR" => Europe,
|
||||
"IE" => Europe,
|
||||
"IT" => Europe,
|
||||
"LT" => Europe,
|
||||
"LU" => Europe,
|
||||
"LV" => Europe,
|
||||
"MD" => Europe,
|
||||
"MT" => Europe,
|
||||
"NL" => Europe,
|
||||
"NO" => Europe,
|
||||
"PL" => Europe,
|
||||
"RO" => Europe,
|
||||
"SE" => Europe,
|
||||
"SK" => Europe,
|
||||
"TR" => Europe,
|
||||
"UA" => Europe,
|
||||
|
||||
// North America
|
||||
"CA" => NorthAmerica,
|
||||
"MX" => NorthAmerica,
|
||||
"US" => NorthAmerica,
|
||||
|
||||
// South America
|
||||
"AR" => SouthAmerica,
|
||||
"BR" => SouthAmerica,
|
||||
"CL" => SouthAmerica,
|
||||
"CO" => SouthAmerica,
|
||||
"CR" => SouthAmerica,
|
||||
"GT" => SouthAmerica,
|
||||
|
||||
// Oceania
|
||||
"AU" => Oceania,
|
||||
|
||||
// Asia
|
||||
"AM" => Asia,
|
||||
"BH" => Asia,
|
||||
"CN" => Asia,
|
||||
"GE" => Asia,
|
||||
"HK" => Asia,
|
||||
"ID" => Asia,
|
||||
"IL" => Asia,
|
||||
"IN" => Asia,
|
||||
"JP" => Asia,
|
||||
"KH" => Asia,
|
||||
"KR" => Asia,
|
||||
"KZ" => Asia,
|
||||
"MY" => Asia,
|
||||
"RU" => Asia,
|
||||
"SG" => Asia,
|
||||
"TH" => Asia,
|
||||
"VN" => Asia,
|
||||
|
||||
// Africa
|
||||
"SC" => Africa,
|
||||
"UG" => Africa,
|
||||
"ZA" => Africa,
|
||||
|
||||
// And group level codes work too
|
||||
"EU" => Europe,
|
||||
"NA" => NorthAmerica,
|
||||
"SA" => SouthAmerica,
|
||||
"OC" => Oceania,
|
||||
"AS" => Asia,
|
||||
"AF" => Africa,
|
||||
|
||||
// And some aliases
|
||||
"EUROPE" => Europe,
|
||||
"NORTHAMERICA" => NorthAmerica,
|
||||
"SOUTHAMERICA" => SouthAmerica,
|
||||
"OCEANIA" => Oceania,
|
||||
"ASIA" => Asia,
|
||||
"AFRICA" => Africa,
|
||||
|
||||
_ => {
|
||||
info!("Unknown country code: {}", country_code);
|
||||
Unknown
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for CountryGroup {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
use CountryGroup::*;
|
||||
match self {
|
||||
Europe => write!(f, "EU"),
|
||||
NorthAmerica => write!(f, "NA"),
|
||||
SouthAmerica => write!(f, "SA"),
|
||||
Oceania => write!(f, "OC"),
|
||||
Asia => write!(f, "AS"),
|
||||
Africa => write!(f, "AF"),
|
||||
Unknown => write!(f, "Unknown"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::str::FromStr for CountryGroup {
|
||||
type Err = ();
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
let group = CountryGroup::new(s);
|
||||
if group == CountryGroup::Unknown {
|
||||
Err(())
|
||||
} else {
|
||||
Ok(group)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl CountryGroup {
|
||||
#[allow(unused)]
|
||||
fn known(self) -> Option<CountryGroup> {
|
||||
use CountryGroup::*;
|
||||
match self {
|
||||
Europe | NorthAmerica | SouthAmerica | Oceania | Asia | Africa => Some(self),
|
||||
Unknown => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn group_mixnodes_by_country_code(
|
||||
mixnodes: Vec<PrettyDetailedMixNodeBond>,
|
||||
) -> HashMap<CountryGroup, Vec<MixId>> {
|
||||
|
||||
@@ -2,35 +2,14 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use async_trait::async_trait;
|
||||
use log::{debug, error, warn};
|
||||
use log::{error, warn};
|
||||
use nym_topology::provider_trait::TopologyProvider;
|
||||
use nym_topology::{NymTopology, NymTopologyError};
|
||||
use nym_topology::{nym_topology_from_detailed, NymTopology, NymTopologyError};
|
||||
use rand::prelude::SliceRandom;
|
||||
use rand::thread_rng;
|
||||
use url::Url;
|
||||
|
||||
// the same values as our current (10.06.24) blacklist
|
||||
pub const DEFAULT_MIN_MIXNODE_PERFORMANCE: u8 = 50;
|
||||
pub const DEFAULT_MIN_GATEWAY_PERFORMANCE: u8 = 50;
|
||||
|
||||
pub(crate) struct Config {
|
||||
pub(crate) min_mixnode_performance: u8,
|
||||
pub(crate) min_gateway_performance: u8,
|
||||
}
|
||||
|
||||
impl Default for Config {
|
||||
fn default() -> Self {
|
||||
// old values that decided on blacklist membership
|
||||
Config {
|
||||
min_mixnode_performance: DEFAULT_MIN_MIXNODE_PERFORMANCE,
|
||||
min_gateway_performance: DEFAULT_MIN_GATEWAY_PERFORMANCE,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct NymApiTopologyProvider {
|
||||
config: Config,
|
||||
|
||||
validator_client: nym_validator_client::client::NymApiClient,
|
||||
nym_api_urls: Vec<Url>,
|
||||
|
||||
@@ -39,11 +18,10 @@ pub(crate) struct NymApiTopologyProvider {
|
||||
}
|
||||
|
||||
impl NymApiTopologyProvider {
|
||||
pub(crate) fn new(config: Config, mut nym_api_urls: Vec<Url>, client_version: String) -> Self {
|
||||
pub(crate) fn new(mut nym_api_urls: Vec<Url>, client_version: String) -> Self {
|
||||
nym_api_urls.shuffle(&mut thread_rng());
|
||||
|
||||
NymApiTopologyProvider {
|
||||
config,
|
||||
validator_client: nym_validator_client::client::NymApiClient::new(
|
||||
nym_api_urls[0].clone(),
|
||||
),
|
||||
@@ -83,11 +61,7 @@ impl NymApiTopologyProvider {
|
||||
}
|
||||
|
||||
async fn get_current_compatible_topology(&mut self) -> Option<NymTopology> {
|
||||
let mixnodes = match self
|
||||
.validator_client
|
||||
.get_basic_mixnodes(Some(self.client_version.clone()))
|
||||
.await
|
||||
{
|
||||
let mixnodes = match self.validator_client.get_cached_active_mixnodes().await {
|
||||
Err(err) => {
|
||||
error!("failed to get network mixnodes - {err}");
|
||||
return None;
|
||||
@@ -95,11 +69,7 @@ impl NymApiTopologyProvider {
|
||||
Ok(mixes) => mixes,
|
||||
};
|
||||
|
||||
let gateways = match self
|
||||
.validator_client
|
||||
.get_basic_gateways(Some(self.client_version.clone()))
|
||||
.await
|
||||
{
|
||||
let gateways = match self.validator_client.get_cached_described_gateways().await {
|
||||
Err(err) => {
|
||||
error!("failed to get network gateways - {err}");
|
||||
return None;
|
||||
@@ -107,20 +77,8 @@ impl NymApiTopologyProvider {
|
||||
Ok(gateways) => gateways,
|
||||
};
|
||||
|
||||
debug!(
|
||||
"there are {} mixnodes and {} gateways in total (before performance filtering)",
|
||||
mixnodes.len(),
|
||||
gateways.len()
|
||||
);
|
||||
|
||||
let topology = NymTopology::from_unordered(
|
||||
mixnodes.iter().filter(|m| {
|
||||
m.performance.round_to_integer() >= self.config.min_mixnode_performance
|
||||
}),
|
||||
gateways.iter().filter(|g| {
|
||||
g.performance.round_to_integer() >= self.config.min_gateway_performance
|
||||
}),
|
||||
);
|
||||
let topology = nym_topology_from_detailed(mixnodes, gateways)
|
||||
.filter_system_version(&self.client_version);
|
||||
|
||||
if let Err(err) = self.check_layer_distribution(&topology) {
|
||||
warn!("The current filtered active topology has extremely skewed layer distribution. It cannot be used: {err}");
|
||||
|
||||
+1
-39
@@ -1,53 +1,15 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
pub mod old;
|
||||
|
||||
// preserve old structure for easier migration
|
||||
pub use old::{old_v1_1_20_2, old_v1_1_33};
|
||||
|
||||
pub const DEFAULT_REPLY_SURB_DB_FILENAME: &str = "persistent_reply_store.sqlite";
|
||||
pub const DEFAULT_CREDENTIALS_DB_FILENAME: &str = "credentials_database.db";
|
||||
pub const DEFAULT_GATEWAYS_DETAILS_DB_FILENAME: &str = "gateways_registrations.sqlite";
|
||||
|
||||
pub const DEFAULT_PRIVATE_IDENTITY_KEY_FILENAME: &str = "private_identity.pem";
|
||||
pub const DEFAULT_PUBLIC_IDENTITY_KEY_FILENAME: &str = "public_identity.pem";
|
||||
pub const DEFAULT_PRIVATE_ENCRYPTION_KEY_FILENAME: &str = "private_encryption.pem";
|
||||
pub const DEFAULT_PUBLIC_ENCRYPTION_KEY_FILENAME: &str = "public_encryption.pem";
|
||||
pub const DEFAULT_ACK_KEY_FILENAME: &str = "ack_key.pem";
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct CommonClientPaths {
|
||||
pub keys: ClientKeysPaths,
|
||||
|
||||
/// Path to the file containing information about gateways used by this client,
|
||||
/// i.e. details such as their public keys, owner addresses or the network information.
|
||||
pub gateway_registrations: PathBuf,
|
||||
|
||||
/// Path to the database containing bandwidth credentials of this client.
|
||||
pub credentials_database: PathBuf,
|
||||
|
||||
/// Path to the persistent store for received reply surbs, unused encryption keys and used sender tags.
|
||||
pub reply_surb_database: PathBuf,
|
||||
}
|
||||
|
||||
impl CommonClientPaths {
|
||||
pub fn new_base<P: AsRef<Path>>(base_data_directory: P) -> Self {
|
||||
let base_dir = base_data_directory.as_ref();
|
||||
|
||||
CommonClientPaths {
|
||||
credentials_database: base_dir.join(DEFAULT_CREDENTIALS_DB_FILENAME),
|
||||
reply_surb_database: base_dir.join(DEFAULT_REPLY_SURB_DB_FILENAME),
|
||||
gateway_registrations: base_dir.join(DEFAULT_GATEWAYS_DETAILS_DB_FILENAME),
|
||||
keys: ClientKeysPaths::new_base(base_data_directory),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
|
||||
pub struct ClientKeysPaths {
|
||||
/// Path to file containing private identity key.
|
||||
@@ -0,0 +1,43 @@
|
||||
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::config::disk_persistence::keys_paths::ClientKeysPaths;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
pub mod keys_paths;
|
||||
pub mod old_v1_1_20_2;
|
||||
pub mod old_v1_1_33;
|
||||
|
||||
pub const DEFAULT_REPLY_SURB_DB_FILENAME: &str = "persistent_reply_store.sqlite";
|
||||
pub const DEFAULT_CREDENTIALS_DB_FILENAME: &str = "credentials_database.db";
|
||||
pub const DEFAULT_GATEWAYS_DETAILS_DB_FILENAME: &str = "gateways_registrations.sqlite";
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct CommonClientPaths {
|
||||
pub keys: ClientKeysPaths,
|
||||
|
||||
/// Path to the file containing information about gateways used by this client,
|
||||
/// i.e. details such as their public keys, owner addresses or the network information.
|
||||
pub gateway_registrations: PathBuf,
|
||||
|
||||
/// Path to the database containing bandwidth credentials of this client.
|
||||
pub credentials_database: PathBuf,
|
||||
|
||||
/// Path to the persistent store for received reply surbs, unused encryption keys and used sender tags.
|
||||
pub reply_surb_database: PathBuf,
|
||||
}
|
||||
|
||||
impl CommonClientPaths {
|
||||
pub fn new_base<P: AsRef<Path>>(base_data_directory: P) -> Self {
|
||||
let base_dir = base_data_directory.as_ref();
|
||||
|
||||
CommonClientPaths {
|
||||
credentials_database: base_dir.join(DEFAULT_CREDENTIALS_DB_FILENAME),
|
||||
reply_surb_database: base_dir.join(DEFAULT_REPLY_SURB_DB_FILENAME),
|
||||
gateway_registrations: base_dir.join(DEFAULT_GATEWAYS_DETAILS_DB_FILENAME),
|
||||
keys: ClientKeysPaths::new_base(base_data_directory),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::config::disk_persistence::old_v1_1_33::{
|
||||
ClientKeysPathsV1_1_33, CommonClientPathsV1_1_33, DEFAULT_GATEWAY_DETAILS_FILENAME,
|
||||
};
|
||||
use crate::error::ClientCoreError;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct CommonClientPathsV1_1_20_2 {
|
||||
pub keys: ClientKeysPathsV1_1_33,
|
||||
pub credentials_database: PathBuf,
|
||||
pub reply_surb_database: PathBuf,
|
||||
}
|
||||
|
||||
impl CommonClientPathsV1_1_20_2 {
|
||||
pub fn upgrade_default(self) -> Result<CommonClientPathsV1_1_33, ClientCoreError> {
|
||||
let data_dir = self.reply_surb_database.parent().ok_or_else(|| {
|
||||
ClientCoreError::ConfigFileUpgradeFailure {
|
||||
current_version: "1.1.20-2".to_string(),
|
||||
}
|
||||
})?;
|
||||
Ok(CommonClientPathsV1_1_33 {
|
||||
keys: self.keys,
|
||||
gateway_details: data_dir.join(DEFAULT_GATEWAY_DETAILS_FILENAME),
|
||||
credentials_database: self.credentials_database,
|
||||
reply_surb_database: self.reply_surb_database,
|
||||
})
|
||||
}
|
||||
}
|
||||
+13
-18
@@ -1,20 +1,16 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::disk_persistence::ClientKeysPaths;
|
||||
use crate::disk_persistence::{CommonClientPaths, DEFAULT_GATEWAYS_DETAILS_DB_FILENAME};
|
||||
use crate::error::ConfigUpgradeFailure;
|
||||
use crate::config::disk_persistence::keys_paths::ClientKeysPaths;
|
||||
use crate::config::disk_persistence::{CommonClientPaths, DEFAULT_GATEWAYS_DETAILS_DB_FILENAME};
|
||||
use crate::error::ClientCoreError;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::path::PathBuf;
|
||||
|
||||
pub const DEFAULT_GATEWAY_DETAILS_FILENAME: &str = "gateway_details.json";
|
||||
|
||||
// aliases for backwards compatibility
|
||||
pub type CommonClientPathsV1_1_33 = CommonClientPathsV2;
|
||||
pub type ClientKeysPathsV1_1_33 = ClientKeysPathsV2;
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
|
||||
pub struct ClientKeysPathsV2 {
|
||||
pub struct ClientKeysPathsV1_1_33 {
|
||||
/// Path to file containing private identity key.
|
||||
pub private_identity_key_file: PathBuf,
|
||||
|
||||
@@ -36,7 +32,7 @@ pub struct ClientKeysPathsV2 {
|
||||
pub ack_key_file: PathBuf,
|
||||
}
|
||||
|
||||
impl ClientKeysPathsV2 {
|
||||
impl ClientKeysPathsV1_1_33 {
|
||||
pub fn upgrade(self) -> ClientKeysPaths {
|
||||
ClientKeysPaths {
|
||||
private_identity_key_file: self.private_identity_key_file,
|
||||
@@ -50,8 +46,8 @@ impl ClientKeysPathsV2 {
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct CommonClientPathsV2 {
|
||||
pub keys: ClientKeysPathsV2,
|
||||
pub struct CommonClientPathsV1_1_33 {
|
||||
pub keys: ClientKeysPathsV1_1_33,
|
||||
|
||||
/// Path to the file containing information about gateway used by this client,
|
||||
/// i.e. details such as its public key, owner address or the network information.
|
||||
@@ -64,16 +60,15 @@ pub struct CommonClientPathsV2 {
|
||||
pub reply_surb_database: PathBuf,
|
||||
}
|
||||
|
||||
impl CommonClientPathsV2 {
|
||||
impl CommonClientPathsV1_1_33 {
|
||||
// note that during the upgrade process, the caller will need to extract the key and gateway details
|
||||
// manually and resave them in the new database
|
||||
pub fn upgrade_default(self) -> Result<CommonClientPaths, ConfigUpgradeFailure> {
|
||||
let data_dir = self
|
||||
.gateway_details
|
||||
.parent()
|
||||
.ok_or_else(|| ConfigUpgradeFailure {
|
||||
pub fn upgrade_default(self) -> Result<CommonClientPaths, ClientCoreError> {
|
||||
let data_dir = self.gateway_details.parent().ok_or_else(|| {
|
||||
ClientCoreError::ConfigFileUpgradeFailure {
|
||||
current_version: "1.1.33".to_string(),
|
||||
})?;
|
||||
}
|
||||
})?;
|
||||
|
||||
Ok(CommonClientPaths {
|
||||
keys: self.keys.upgrade(),
|
||||
@@ -1,9 +1,602 @@
|
||||
// Copyright 2021-2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
pub use nym_client_core_config_types::disk_persistence;
|
||||
pub use nym_client_core_config_types::old::{
|
||||
old_config_v1_1_13, old_config_v1_1_20, old_config_v1_1_20_2, old_config_v1_1_30,
|
||||
old_config_v1_1_33,
|
||||
use crate::client::topology_control::geo_aware_provider::CountryGroup;
|
||||
use nym_config::defaults::NymNetworkDetails;
|
||||
use nym_sphinx::{
|
||||
addressing::clients::Recipient,
|
||||
params::{PacketSize, PacketType},
|
||||
};
|
||||
pub use nym_client_core_config_types::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::time::Duration;
|
||||
use url::Url;
|
||||
|
||||
pub mod disk_persistence;
|
||||
pub mod old_config_v1_1_13;
|
||||
pub mod old_config_v1_1_20;
|
||||
pub mod old_config_v1_1_20_2;
|
||||
pub mod old_config_v1_1_30;
|
||||
pub mod old_config_v1_1_33;
|
||||
|
||||
// 'DEBUG'
|
||||
const DEFAULT_ACK_WAIT_MULTIPLIER: f64 = 1.5;
|
||||
|
||||
const DEFAULT_ACK_WAIT_ADDITION: Duration = Duration::from_millis(1_500);
|
||||
const DEFAULT_LOOP_COVER_STREAM_AVERAGE_DELAY: Duration = Duration::from_millis(200);
|
||||
const DEFAULT_MESSAGE_STREAM_AVERAGE_DELAY: Duration = Duration::from_millis(20);
|
||||
const DEFAULT_AVERAGE_PACKET_DELAY: Duration = Duration::from_millis(50);
|
||||
const DEFAULT_TOPOLOGY_REFRESH_RATE: Duration = Duration::from_secs(5 * 60); // every 5min
|
||||
const DEFAULT_TOPOLOGY_RESOLUTION_TIMEOUT: Duration = Duration::from_millis(5_000);
|
||||
const DEFAULT_MAX_STARTUP_GATEWAY_WAITING_PERIOD: Duration = Duration::from_secs(70 * 60); // 70min -> full epoch (1h) + a bit of overhead
|
||||
|
||||
// Set this to a high value for now, so that we don't risk sporadic timeouts that might cause
|
||||
// bought bandwidth tokens to not have time to be spent; Once we remove the gateway from the
|
||||
// bandwidth bridging protocol, we can come back to a smaller timeout value
|
||||
const DEFAULT_GATEWAY_RESPONSE_TIMEOUT: Duration = Duration::from_secs(5 * 60);
|
||||
|
||||
const DEFAULT_COVER_TRAFFIC_PRIMARY_SIZE_RATIO: f64 = 0.70;
|
||||
|
||||
// reply-surbs related:
|
||||
|
||||
// define when to request
|
||||
// clients/client-core/src/client/replies/reply_storage/surb_storage.rs
|
||||
const DEFAULT_MINIMUM_REPLY_SURB_STORAGE_THRESHOLD: usize = 10;
|
||||
const DEFAULT_MAXIMUM_REPLY_SURB_STORAGE_THRESHOLD: usize = 200;
|
||||
|
||||
// define how much to request at once
|
||||
// clients/client-core/src/client/replies/reply_controller.rs
|
||||
const DEFAULT_MINIMUM_REPLY_SURB_REQUEST_SIZE: u32 = 10;
|
||||
const DEFAULT_MAXIMUM_REPLY_SURB_REQUEST_SIZE: u32 = 100;
|
||||
|
||||
const DEFAULT_MAXIMUM_ALLOWED_SURB_REQUEST_SIZE: u32 = 500;
|
||||
|
||||
const DEFAULT_MAXIMUM_REPLY_SURB_REREQUEST_WAITING_PERIOD: Duration = Duration::from_secs(10);
|
||||
const DEFAULT_MAXIMUM_REPLY_SURB_DROP_WAITING_PERIOD: Duration = Duration::from_secs(5 * 60);
|
||||
|
||||
// 12 hours
|
||||
const DEFAULT_MAXIMUM_REPLY_SURB_AGE: Duration = Duration::from_secs(12 * 60 * 60);
|
||||
|
||||
// 24 hours
|
||||
const DEFAULT_MAXIMUM_REPLY_KEY_AGE: Duration = Duration::from_secs(24 * 60 * 60);
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct Config {
|
||||
pub client: Client,
|
||||
|
||||
#[serde(default)]
|
||||
pub debug: DebugConfig,
|
||||
}
|
||||
|
||||
impl Config {
|
||||
pub fn new<S1, S2>(id: S1, version: S2) -> Self
|
||||
where
|
||||
S1: Into<String>,
|
||||
S2: Into<String>,
|
||||
{
|
||||
Config {
|
||||
client: Client::new_default(id, version),
|
||||
debug: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_client_config(client: Client, debug: DebugConfig) -> Self {
|
||||
Config { client, debug }
|
||||
}
|
||||
|
||||
pub fn validate(&self) -> bool {
|
||||
self.debug.validate()
|
||||
}
|
||||
|
||||
pub fn with_debug_config(mut self, debug: DebugConfig) -> Self {
|
||||
self.debug = debug;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_disabled_credentials(mut self, disabled_credentials_mode: bool) -> Self {
|
||||
self.client.disabled_credentials_mode = disabled_credentials_mode;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_custom_nyxd(mut self, urls: Vec<Url>) -> Self {
|
||||
self.client.nyxd_urls = urls;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn set_custom_nyxd(&mut self, nyxd_urls: Vec<Url>) {
|
||||
self.client.nyxd_urls = nyxd_urls;
|
||||
}
|
||||
|
||||
pub fn with_custom_nym_apis(mut self, nym_api_urls: Vec<Url>) -> Self {
|
||||
self.client.nym_api_urls = nym_api_urls;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn set_custom_nym_apis(&mut self, nym_api_urls: Vec<Url>) {
|
||||
self.client.nym_api_urls = nym_api_urls;
|
||||
}
|
||||
|
||||
pub fn with_high_default_traffic_volume(mut self, enabled: bool) -> Self {
|
||||
if enabled {
|
||||
self.set_high_default_traffic_volume();
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_packet_type(mut self, packet_type: PacketType) -> Self {
|
||||
self.debug.traffic.packet_type = packet_type;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn set_high_default_traffic_volume(&mut self) {
|
||||
self.debug.traffic.average_packet_delay = Duration::from_millis(10);
|
||||
// basically don't really send cover messages
|
||||
self.debug.cover_traffic.loop_cover_traffic_average_delay =
|
||||
Duration::from_millis(2_000_000);
|
||||
// 250 "real" messages / s
|
||||
self.debug.traffic.message_sending_average_delay = Duration::from_millis(4);
|
||||
}
|
||||
|
||||
pub fn with_disabled_poisson_process(mut self, disabled: bool) -> Self {
|
||||
if disabled {
|
||||
self.set_no_poisson_process()
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
pub fn set_no_poisson_process(&mut self) {
|
||||
self.debug.traffic.disable_main_poisson_packet_distribution = true;
|
||||
}
|
||||
|
||||
pub fn with_disabled_cover_traffic(mut self, disabled: bool) -> Self {
|
||||
if disabled {
|
||||
self.set_no_cover_traffic()
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
pub fn set_no_cover_traffic(&mut self) {
|
||||
self.debug.cover_traffic.disable_loop_cover_traffic_stream = true;
|
||||
self.debug.traffic.disable_main_poisson_packet_distribution = true;
|
||||
}
|
||||
|
||||
pub fn with_disabled_cover_traffic_with_keepalive(mut self, disabled: bool) -> Self {
|
||||
if disabled {
|
||||
self.set_no_cover_traffic_with_keepalive()
|
||||
}
|
||||
self
|
||||
}
|
||||
pub fn set_no_cover_traffic_with_keepalive(&mut self) {
|
||||
self.debug.traffic.disable_main_poisson_packet_distribution = true;
|
||||
self.debug.cover_traffic.loop_cover_traffic_average_delay = Duration::from_secs(5);
|
||||
}
|
||||
|
||||
pub fn with_disabled_topology_refresh(mut self, disable_topology_refresh: bool) -> Self {
|
||||
self.debug.topology.disable_refreshing = disable_topology_refresh;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_topology_structure(mut self, topology_structure: TopologyStructure) -> Self {
|
||||
self.set_topology_structure(topology_structure);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn set_topology_structure(&mut self, topology_structure: TopologyStructure) {
|
||||
self.debug.topology.topology_structure = topology_structure;
|
||||
}
|
||||
|
||||
pub fn with_no_per_hop_delays(mut self, no_per_hop_delays: bool) -> Self {
|
||||
if no_per_hop_delays {
|
||||
self.set_no_per_hop_delays()
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
pub fn set_no_per_hop_delays(&mut self) {
|
||||
self.debug.traffic.average_packet_delay = Duration::ZERO;
|
||||
self.debug.acknowledgements.average_ack_delay = Duration::ZERO;
|
||||
}
|
||||
|
||||
pub fn with_secondary_packet_size(mut self, secondary_packet_size: Option<PacketSize>) -> Self {
|
||||
self.set_secondary_packet_size(secondary_packet_size);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn set_secondary_packet_size(&mut self, secondary_packet_size: Option<PacketSize>) {
|
||||
self.debug.traffic.secondary_packet_size = secondary_packet_size;
|
||||
}
|
||||
|
||||
pub fn set_custom_version(&mut self, version: &str) {
|
||||
self.client.version = version.to_string();
|
||||
}
|
||||
|
||||
pub fn get_id(&self) -> String {
|
||||
self.client.id.clone()
|
||||
}
|
||||
|
||||
pub fn get_disabled_credentials_mode(&self) -> bool {
|
||||
self.client.disabled_credentials_mode
|
||||
}
|
||||
|
||||
pub fn get_validator_endpoints(&self) -> Vec<Url> {
|
||||
self.client.nyxd_urls.clone()
|
||||
}
|
||||
|
||||
pub fn get_nym_api_endpoints(&self) -> Vec<Url> {
|
||||
self.client.nym_api_urls.clone()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
|
||||
// note: the deny_unknown_fields is VITAL here to allow upgrades from v1.1.20_2
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct Client {
|
||||
/// Version of the client for which this configuration was created.
|
||||
pub version: String,
|
||||
|
||||
/// ID specifies the human readable ID of this particular client.
|
||||
pub id: String,
|
||||
|
||||
/// Indicates whether this client is running in a disabled credentials mode, thus attempting
|
||||
/// to claim bandwidth without presenting bandwidth credentials.
|
||||
// TODO: this should be moved to `debug.gateway_connection`
|
||||
#[serde(default)]
|
||||
pub disabled_credentials_mode: bool,
|
||||
|
||||
/// Addresses to nyxd validators via which the client can communicate with the chain.
|
||||
#[serde(alias = "validator_urls")]
|
||||
pub nyxd_urls: Vec<Url>,
|
||||
|
||||
/// Addresses to APIs running on validator from which the client gets the view of the network.
|
||||
#[serde(alias = "validator_api_urls")]
|
||||
pub nym_api_urls: Vec<Url>,
|
||||
}
|
||||
|
||||
impl Client {
|
||||
pub fn new_default<S1, S2>(id: S1, version: S2) -> Self
|
||||
where
|
||||
S1: Into<String>,
|
||||
S2: Into<String>,
|
||||
{
|
||||
let network = NymNetworkDetails::new_mainnet();
|
||||
let nyxd_urls = network
|
||||
.endpoints
|
||||
.iter()
|
||||
.map(|validator| validator.nyxd_url())
|
||||
.collect();
|
||||
let nym_api_urls = network
|
||||
.endpoints
|
||||
.iter()
|
||||
.filter_map(|validator| validator.api_url())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
Client {
|
||||
version: version.into(),
|
||||
id: id.into(),
|
||||
disabled_credentials_mode: true,
|
||||
nyxd_urls,
|
||||
nym_api_urls,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new<S: Into<String>>(
|
||||
id: S,
|
||||
disabled_credentials_mode: bool,
|
||||
nyxd_urls: Vec<Url>,
|
||||
nym_api_urls: Vec<Url>,
|
||||
) -> Self {
|
||||
Client {
|
||||
version: env!("CARGO_PKG_VERSION").to_string(),
|
||||
id: id.into(),
|
||||
disabled_credentials_mode,
|
||||
nyxd_urls,
|
||||
nym_api_urls,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default, deny_unknown_fields)]
|
||||
pub struct Traffic {
|
||||
/// The parameter of Poisson distribution determining how long, on average,
|
||||
/// sent packet is going to be delayed at any given mix node.
|
||||
/// So for a packet going through three mix nodes, on average, it will take three times this value
|
||||
/// until the packet reaches its destination.
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub average_packet_delay: Duration,
|
||||
|
||||
/// The parameter of Poisson distribution determining how long, on average,
|
||||
/// it is going to take another 'real traffic stream' message to be sent.
|
||||
/// If no real packets are available and cover traffic is enabled,
|
||||
/// a loop cover message is sent instead in order to preserve the rate.
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub message_sending_average_delay: Duration,
|
||||
|
||||
/// Controls whether the main packet stream constantly produces packets according to the predefined
|
||||
/// poisson distribution.
|
||||
pub disable_main_poisson_packet_distribution: bool,
|
||||
|
||||
/// Specifies the packet size used for sent messages.
|
||||
/// Do not override it unless you understand the consequences of that change.
|
||||
pub primary_packet_size: PacketSize,
|
||||
|
||||
/// Specifies the optional auxiliary packet size for optimizing message streams.
|
||||
/// Note that its use decreases overall anonymity.
|
||||
/// Do not set it it unless you understand the consequences of that change.
|
||||
pub secondary_packet_size: Option<PacketSize>,
|
||||
|
||||
pub packet_type: PacketType,
|
||||
}
|
||||
|
||||
impl Traffic {
|
||||
pub fn validate(&self) -> bool {
|
||||
if let Some(secondary_packet_size) = self.secondary_packet_size {
|
||||
if secondary_packet_size == PacketSize::AckPacket
|
||||
|| secondary_packet_size == self.primary_packet_size
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Traffic {
|
||||
fn default() -> Self {
|
||||
Traffic {
|
||||
average_packet_delay: DEFAULT_AVERAGE_PACKET_DELAY,
|
||||
message_sending_average_delay: DEFAULT_MESSAGE_STREAM_AVERAGE_DELAY,
|
||||
disable_main_poisson_packet_distribution: false,
|
||||
primary_packet_size: PacketSize::RegularPacket,
|
||||
secondary_packet_size: None,
|
||||
packet_type: PacketType::Mix,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default, deny_unknown_fields)]
|
||||
pub struct CoverTraffic {
|
||||
/// The parameter of Poisson distribution determining how long, on average,
|
||||
/// it is going to take for another loop cover traffic message to be sent.
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub loop_cover_traffic_average_delay: Duration,
|
||||
|
||||
/// Specifies the ratio of `primary_packet_size` to `secondary_packet_size` used in cover traffic.
|
||||
/// Only applicable if `secondary_packet_size` is enabled.
|
||||
pub cover_traffic_primary_size_ratio: f64,
|
||||
|
||||
/// Controls whether the dedicated loop cover traffic stream should be enabled.
|
||||
/// (and sending packets, on average, every [Self::loop_cover_traffic_average_delay])
|
||||
pub disable_loop_cover_traffic_stream: bool,
|
||||
}
|
||||
|
||||
impl Default for CoverTraffic {
|
||||
fn default() -> Self {
|
||||
CoverTraffic {
|
||||
loop_cover_traffic_average_delay: DEFAULT_LOOP_COVER_STREAM_AVERAGE_DELAY,
|
||||
cover_traffic_primary_size_ratio: DEFAULT_COVER_TRAFFIC_PRIMARY_SIZE_RATIO,
|
||||
disable_loop_cover_traffic_stream: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default, deny_unknown_fields)]
|
||||
pub struct GatewayConnection {
|
||||
/// How long we're willing to wait for a response to a message sent to the gateway,
|
||||
/// before giving up on it.
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub gateway_response_timeout: Duration,
|
||||
}
|
||||
|
||||
impl Default for GatewayConnection {
|
||||
fn default() -> Self {
|
||||
GatewayConnection {
|
||||
gateway_response_timeout: DEFAULT_GATEWAY_RESPONSE_TIMEOUT,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default, deny_unknown_fields)]
|
||||
pub struct Acknowledgements {
|
||||
/// The parameter of Poisson distribution determining how long, on average,
|
||||
/// sent acknowledgement is going to be delayed at any given mix node.
|
||||
/// So for an ack going through three mix nodes, on average, it will take three times this value
|
||||
/// until the packet reaches its destination.
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub average_ack_delay: Duration,
|
||||
|
||||
/// Value multiplied with the expected round trip time of an acknowledgement packet before
|
||||
/// it is assumed it was lost and retransmission of the data packet happens.
|
||||
/// In an ideal network with 0 latency, this value would have been 1.
|
||||
pub ack_wait_multiplier: f64,
|
||||
|
||||
/// Value added to the expected round trip time of an acknowledgement packet before
|
||||
/// it is assumed it was lost and retransmission of the data packet happens.
|
||||
/// In an ideal network with 0 latency, this value would have been 0.
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub ack_wait_addition: Duration,
|
||||
}
|
||||
|
||||
impl Default for Acknowledgements {
|
||||
fn default() -> Self {
|
||||
Acknowledgements {
|
||||
average_ack_delay: DEFAULT_AVERAGE_PACKET_DELAY,
|
||||
ack_wait_multiplier: DEFAULT_ACK_WAIT_MULTIPLIER,
|
||||
ack_wait_addition: DEFAULT_ACK_WAIT_ADDITION,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default, deny_unknown_fields)]
|
||||
pub struct Topology {
|
||||
/// The uniform delay every which clients are querying the directory server
|
||||
/// to try to obtain a compatible network topology to send sphinx packets through.
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub topology_refresh_rate: Duration,
|
||||
|
||||
/// During topology refresh, test packets are sent through every single possible network
|
||||
/// path. This timeout determines waiting period until it is decided that the packet
|
||||
/// did not reach its destination.
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub topology_resolution_timeout: Duration,
|
||||
|
||||
/// Specifies whether the client should not refresh the network topology after obtaining
|
||||
/// the first valid instance.
|
||||
/// Supersedes `topology_refresh_rate_ms`.
|
||||
pub disable_refreshing: bool,
|
||||
|
||||
/// Defines how long the client is going to wait on startup for its gateway to come online,
|
||||
/// before abandoning the procedure.
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub max_startup_gateway_waiting_period: Duration,
|
||||
|
||||
/// Specifies the mixnode topology to be used for sending packets.
|
||||
pub topology_structure: TopologyStructure,
|
||||
}
|
||||
|
||||
#[allow(clippy::large_enum_variant)]
|
||||
#[derive(Default, Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub enum TopologyStructure {
|
||||
#[default]
|
||||
NymApi,
|
||||
GeoAware(GroupBy),
|
||||
}
|
||||
|
||||
#[allow(clippy::large_enum_variant)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub enum GroupBy {
|
||||
CountryGroup(CountryGroup),
|
||||
NymAddress(Recipient),
|
||||
}
|
||||
|
||||
impl std::fmt::Display for GroupBy {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
GroupBy::CountryGroup(group) => write!(f, "group: {}", group),
|
||||
GroupBy::NymAddress(address) => write!(f, "address: {}", address),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Topology {
|
||||
fn default() -> Self {
|
||||
Topology {
|
||||
topology_refresh_rate: DEFAULT_TOPOLOGY_REFRESH_RATE,
|
||||
topology_resolution_timeout: DEFAULT_TOPOLOGY_RESOLUTION_TIMEOUT,
|
||||
disable_refreshing: false,
|
||||
max_startup_gateway_waiting_period: DEFAULT_MAX_STARTUP_GATEWAY_WAITING_PERIOD,
|
||||
topology_structure: TopologyStructure::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default, deny_unknown_fields)]
|
||||
pub struct ReplySurbs {
|
||||
/// Defines the minimum number of reply surbs the client wants to keep in its storage at all times.
|
||||
/// It can only allow to go below that value if its to request additional reply surbs.
|
||||
pub minimum_reply_surb_storage_threshold: usize,
|
||||
|
||||
/// Defines the maximum number of reply surbs the client wants to keep in its storage at any times.
|
||||
pub maximum_reply_surb_storage_threshold: usize,
|
||||
|
||||
/// Defines the minimum number of reply surbs the client would request.
|
||||
pub minimum_reply_surb_request_size: u32,
|
||||
|
||||
/// Defines the maximum number of reply surbs the client would request.
|
||||
pub maximum_reply_surb_request_size: u32,
|
||||
|
||||
/// Defines the maximum number of reply surbs a remote party is allowed to request from this client at once.
|
||||
pub maximum_allowed_reply_surb_request_size: u32,
|
||||
|
||||
/// Defines maximum amount of time the client is going to wait for reply surbs before explicitly asking
|
||||
/// for more even though in theory they wouldn't need to.
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub maximum_reply_surb_rerequest_waiting_period: Duration,
|
||||
|
||||
/// Defines maximum amount of time the client is going to wait for reply surbs before
|
||||
/// deciding it's never going to get them and would drop all pending messages
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub maximum_reply_surb_drop_waiting_period: Duration,
|
||||
|
||||
/// Defines maximum amount of time given reply surb is going to be valid for.
|
||||
/// This is going to be superseded by key rotation once implemented.
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub maximum_reply_surb_age: Duration,
|
||||
|
||||
/// Defines maximum amount of time given reply key is going to be valid for.
|
||||
/// This is going to be superseded by key rotation once implemented.
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub maximum_reply_key_age: Duration,
|
||||
|
||||
/// Specifies the number of mixnet hops the packet should go through. If not specified, then
|
||||
/// the default value is used.
|
||||
pub surb_mix_hops: Option<u8>,
|
||||
}
|
||||
|
||||
impl Default for ReplySurbs {
|
||||
fn default() -> Self {
|
||||
ReplySurbs {
|
||||
minimum_reply_surb_storage_threshold: DEFAULT_MINIMUM_REPLY_SURB_STORAGE_THRESHOLD,
|
||||
maximum_reply_surb_storage_threshold: DEFAULT_MAXIMUM_REPLY_SURB_STORAGE_THRESHOLD,
|
||||
minimum_reply_surb_request_size: DEFAULT_MINIMUM_REPLY_SURB_REQUEST_SIZE,
|
||||
maximum_reply_surb_request_size: DEFAULT_MAXIMUM_REPLY_SURB_REQUEST_SIZE,
|
||||
maximum_allowed_reply_surb_request_size: DEFAULT_MAXIMUM_ALLOWED_SURB_REQUEST_SIZE,
|
||||
maximum_reply_surb_rerequest_waiting_period:
|
||||
DEFAULT_MAXIMUM_REPLY_SURB_REREQUEST_WAITING_PERIOD,
|
||||
maximum_reply_surb_drop_waiting_period: DEFAULT_MAXIMUM_REPLY_SURB_DROP_WAITING_PERIOD,
|
||||
maximum_reply_surb_age: DEFAULT_MAXIMUM_REPLY_SURB_AGE,
|
||||
maximum_reply_key_age: DEFAULT_MAXIMUM_REPLY_KEY_AGE,
|
||||
surb_mix_hops: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default, deny_unknown_fields)]
|
||||
pub struct DebugConfig {
|
||||
/// Defines all configuration options related to traffic streams.
|
||||
pub traffic: Traffic,
|
||||
|
||||
/// Defines all configuration options related to cover traffic stream(s).
|
||||
pub cover_traffic: CoverTraffic,
|
||||
|
||||
/// Defines all configuration options related to the gateway connection.
|
||||
pub gateway_connection: GatewayConnection,
|
||||
|
||||
/// Defines all configuration options related to acknowledgements, such as delays or wait timeouts.
|
||||
pub acknowledgements: Acknowledgements,
|
||||
|
||||
/// Defines all configuration options related topology, such as refresh rates or timeouts.
|
||||
pub topology: Topology,
|
||||
|
||||
/// Defines all configuration options related to reply SURBs.
|
||||
pub reply_surbs: ReplySurbs,
|
||||
}
|
||||
|
||||
impl DebugConfig {
|
||||
pub fn validate(&self) -> bool {
|
||||
// no other sections have explicit requirements (yet)
|
||||
self.traffic.validate()
|
||||
}
|
||||
}
|
||||
|
||||
// it could be derived, sure, but I'd rather have an explicit implementation in case we had to change
|
||||
// something manually at some point
|
||||
#[allow(clippy::derivable_impls)]
|
||||
impl Default for DebugConfig {
|
||||
fn default() -> Self {
|
||||
DebugConfig {
|
||||
traffic: Default::default(),
|
||||
cover_traffic: Default::default(),
|
||||
gateway_connection: Default::default(),
|
||||
acknowledgements: Default::default(),
|
||||
topology: Default::default(),
|
||||
reply_surbs: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+35
-40
@@ -1,28 +1,23 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::old::v2::{
|
||||
AcknowledgementsV2, ClientV2, ConfigV2, CoverTrafficV2, DebugConfigV2, GatewayConnectionV2,
|
||||
LoggingV2, ReplySurbsV2, TopologyV2, TrafficV2, DEFAULT_ACK_WAIT_ADDITION,
|
||||
DEFAULT_ACK_WAIT_MULTIPLIER, DEFAULT_AVERAGE_PACKET_DELAY, DEFAULT_GATEWAY_RESPONSE_TIMEOUT,
|
||||
DEFAULT_LOOP_COVER_STREAM_AVERAGE_DELAY, DEFAULT_MAXIMUM_ALLOWED_SURB_REQUEST_SIZE,
|
||||
DEFAULT_MAXIMUM_REPLY_KEY_AGE, DEFAULT_MAXIMUM_REPLY_SURB_AGE,
|
||||
DEFAULT_MAXIMUM_REPLY_SURB_DROP_WAITING_PERIOD, DEFAULT_MAXIMUM_REPLY_SURB_REQUEST_SIZE,
|
||||
DEFAULT_MAXIMUM_REPLY_SURB_REREQUEST_WAITING_PERIOD,
|
||||
use crate::config::old_config_v1_1_20::{
|
||||
AcknowledgementsV1_1_20, ClientV1_1_20, ConfigV1_1_20, CoverTrafficV1_1_20, DebugConfigV1_1_20,
|
||||
GatewayConnectionV1_1_20, LoggingV1_1_20, ReplySurbsV1_1_20, TopologyV1_1_20, TrafficV1_1_20,
|
||||
DEFAULT_ACK_WAIT_ADDITION, DEFAULT_ACK_WAIT_MULTIPLIER, DEFAULT_AVERAGE_PACKET_DELAY,
|
||||
DEFAULT_GATEWAY_RESPONSE_TIMEOUT, DEFAULT_LOOP_COVER_STREAM_AVERAGE_DELAY,
|
||||
DEFAULT_MAXIMUM_ALLOWED_SURB_REQUEST_SIZE, DEFAULT_MAXIMUM_REPLY_KEY_AGE,
|
||||
DEFAULT_MAXIMUM_REPLY_SURB_AGE, DEFAULT_MAXIMUM_REPLY_SURB_DROP_WAITING_PERIOD,
|
||||
DEFAULT_MAXIMUM_REPLY_SURB_REQUEST_SIZE, DEFAULT_MAXIMUM_REPLY_SURB_REREQUEST_WAITING_PERIOD,
|
||||
DEFAULT_MAXIMUM_REPLY_SURB_STORAGE_THRESHOLD, DEFAULT_MESSAGE_STREAM_AVERAGE_DELAY,
|
||||
DEFAULT_MINIMUM_REPLY_SURB_REQUEST_SIZE, DEFAULT_MINIMUM_REPLY_SURB_STORAGE_THRESHOLD,
|
||||
DEFAULT_TOPOLOGY_REFRESH_RATE, DEFAULT_TOPOLOGY_RESOLUTION_TIMEOUT,
|
||||
};
|
||||
use nym_sphinx_params::PacketSize;
|
||||
use nym_sphinx::params::PacketSize;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::marker::PhantomData;
|
||||
use std::time::Duration;
|
||||
|
||||
// aliases for backwards compatibility
|
||||
pub type OldConfigV1_1_13<T> = ConfigV1<T>;
|
||||
pub type OldLoggingV1_1_13 = LoggingV1;
|
||||
pub type OldDebugConfigV1_1_13 = DebugConfigV1;
|
||||
|
||||
#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum ExtendedPacketSize {
|
||||
@@ -43,28 +38,28 @@ impl From<ExtendedPacketSize> for PacketSize {
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct ConfigV1<T> {
|
||||
pub client: ClientV2<T>,
|
||||
pub struct OldConfigV1_1_13<T> {
|
||||
pub client: ClientV1_1_20<T>,
|
||||
|
||||
#[serde(default)]
|
||||
pub logging: LoggingV1,
|
||||
pub logging: OldLoggingV1_1_13,
|
||||
#[serde(default)]
|
||||
pub debug: DebugConfigV1,
|
||||
pub debug: OldDebugConfigV1_1_13,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, Deserialize, PartialEq, Eq, Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct LoggingV1 {}
|
||||
pub struct OldLoggingV1_1_13 {}
|
||||
|
||||
impl From<LoggingV1> for LoggingV2 {
|
||||
fn from(_value: LoggingV1) -> Self {
|
||||
LoggingV2 {}
|
||||
impl From<OldLoggingV1_1_13> for LoggingV1_1_20 {
|
||||
fn from(_value: OldLoggingV1_1_13) -> Self {
|
||||
LoggingV1_1_20 {}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default, deny_unknown_fields)]
|
||||
pub struct DebugConfigV1 {
|
||||
pub struct OldDebugConfigV1_1_13 {
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub average_packet_delay: Duration,
|
||||
|
||||
@@ -119,10 +114,10 @@ pub struct DebugConfigV1 {
|
||||
pub maximum_reply_key_age: Duration,
|
||||
}
|
||||
|
||||
impl From<DebugConfigV1> for DebugConfigV2 {
|
||||
fn from(value: DebugConfigV1) -> Self {
|
||||
DebugConfigV2 {
|
||||
traffic: TrafficV2 {
|
||||
impl From<OldDebugConfigV1_1_13> for DebugConfigV1_1_20 {
|
||||
fn from(value: OldDebugConfigV1_1_13) -> Self {
|
||||
DebugConfigV1_1_20 {
|
||||
traffic: TrafficV1_1_20 {
|
||||
average_packet_delay: value.average_packet_delay,
|
||||
message_sending_average_delay: value.message_sending_average_delay,
|
||||
disable_main_poisson_packet_distribution: value
|
||||
@@ -130,25 +125,25 @@ impl From<DebugConfigV1> for DebugConfigV2 {
|
||||
primary_packet_size: PacketSize::RegularPacket,
|
||||
secondary_packet_size: value.use_extended_packet_size.map(Into::into),
|
||||
},
|
||||
cover_traffic: CoverTrafficV2 {
|
||||
cover_traffic: CoverTrafficV1_1_20 {
|
||||
loop_cover_traffic_average_delay: value.loop_cover_traffic_average_delay,
|
||||
disable_loop_cover_traffic_stream: value.disable_loop_cover_traffic_stream,
|
||||
..CoverTrafficV2::default()
|
||||
..CoverTrafficV1_1_20::default()
|
||||
},
|
||||
gateway_connection: GatewayConnectionV2 {
|
||||
gateway_connection: GatewayConnectionV1_1_20 {
|
||||
gateway_response_timeout: value.gateway_response_timeout,
|
||||
},
|
||||
acknowledgements: AcknowledgementsV2 {
|
||||
acknowledgements: AcknowledgementsV1_1_20 {
|
||||
average_ack_delay: value.average_ack_delay,
|
||||
ack_wait_multiplier: value.ack_wait_multiplier,
|
||||
ack_wait_addition: value.ack_wait_addition,
|
||||
},
|
||||
topology: TopologyV2 {
|
||||
topology: TopologyV1_1_20 {
|
||||
topology_refresh_rate: value.topology_refresh_rate,
|
||||
topology_resolution_timeout: value.topology_resolution_timeout,
|
||||
disable_refreshing: false,
|
||||
},
|
||||
reply_surbs: ReplySurbsV2 {
|
||||
reply_surbs: ReplySurbsV1_1_20 {
|
||||
minimum_reply_surb_storage_threshold: value.minimum_reply_surb_storage_threshold,
|
||||
maximum_reply_surb_storage_threshold: value.maximum_reply_surb_storage_threshold,
|
||||
minimum_reply_surb_request_size: value.minimum_reply_surb_request_size,
|
||||
@@ -166,9 +161,9 @@ impl From<DebugConfigV1> for DebugConfigV2 {
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for DebugConfigV1 {
|
||||
impl Default for OldDebugConfigV1_1_13 {
|
||||
fn default() -> Self {
|
||||
DebugConfigV1 {
|
||||
OldDebugConfigV1_1_13 {
|
||||
average_packet_delay: DEFAULT_AVERAGE_PACKET_DELAY,
|
||||
average_ack_delay: DEFAULT_AVERAGE_PACKET_DELAY,
|
||||
ack_wait_multiplier: DEFAULT_ACK_WAIT_MULTIPLIER,
|
||||
@@ -195,10 +190,10 @@ impl Default for DebugConfigV1 {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> From<ConfigV1<T>> for ConfigV2<U> {
|
||||
fn from(value: ConfigV1<T>) -> Self {
|
||||
ConfigV2 {
|
||||
client: ClientV2 {
|
||||
impl<T, U> From<OldConfigV1_1_13<T>> for ConfigV1_1_20<U> {
|
||||
fn from(value: OldConfigV1_1_13<T>) -> Self {
|
||||
ConfigV1_1_20 {
|
||||
client: ClientV1_1_20 {
|
||||
version: value.client.version,
|
||||
id: value.client.id,
|
||||
disabled_credentials_mode: value.client.disabled_credentials_mode,
|
||||
+63
-76
@@ -1,11 +1,12 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::old::v3::{
|
||||
AcknowledgementsV3, CoverTrafficV3, DebugConfigV3, GatewayConnectionV3,
|
||||
GatewayEndpointConfigV3, ReplySurbsV3, TopologyV3, TrafficV3,
|
||||
use crate::config::old_config_v1_1_20_2::{
|
||||
AcknowledgementsV1_1_20_2, CoverTrafficV1_1_20_2, DebugConfigV1_1_20_2,
|
||||
GatewayConnectionV1_1_20_2, GatewayEndpointConfigV1_1_20_2, ReplySurbsV1_1_20_2,
|
||||
TopologyV1_1_20_2, TrafficV1_1_20_2,
|
||||
};
|
||||
use nym_sphinx_params::{PacketSize, PacketType};
|
||||
use nym_sphinx::params::{PacketSize, PacketType};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::marker::PhantomData;
|
||||
use std::path::PathBuf;
|
||||
@@ -53,41 +54,27 @@ pub(crate) const DEFAULT_MAXIMUM_REPLY_SURB_AGE: Duration = Duration::from_secs(
|
||||
// 24 hours
|
||||
pub(crate) const DEFAULT_MAXIMUM_REPLY_KEY_AGE: Duration = Duration::from_secs(24 * 60 * 60);
|
||||
|
||||
// aliases for backwards compatibility
|
||||
pub type ConfigV1_1_20<T> = ConfigV2<T>;
|
||||
pub type ClientV1_1_20<T> = ClientV2<T>;
|
||||
pub type LoggingV1_1_20 = LoggingV2;
|
||||
pub type DebugConfigV1_1_20 = DebugConfigV2;
|
||||
pub type GatewayEndpointConfigV1_1_20 = GatewayEndpointConfigV2;
|
||||
|
||||
pub type TrafficV1_1_20 = TrafficV2;
|
||||
pub type CoverTrafficV1_1_20 = CoverTrafficV2;
|
||||
pub type GatewayConnectionV1_1_20 = GatewayConnectionV2;
|
||||
pub type AcknowledgementsV1_1_20 = AcknowledgementsV2;
|
||||
pub type TopologyV1_1_20 = TopologyV2;
|
||||
pub type ReplySurbsV1_1_20 = ReplySurbsV2;
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct ConfigV2<T> {
|
||||
pub client: ClientV2<T>,
|
||||
pub struct ConfigV1_1_20<T> {
|
||||
pub client: ClientV1_1_20<T>,
|
||||
|
||||
#[serde(default)]
|
||||
pub logging: LoggingV2,
|
||||
pub logging: LoggingV1_1_20,
|
||||
#[serde(default)]
|
||||
pub debug: DebugConfigV2,
|
||||
pub debug: DebugConfigV1_1_20,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default, Deserialize, PartialEq, Eq, Serialize)]
|
||||
pub struct GatewayEndpointConfigV2 {
|
||||
pub struct GatewayEndpointConfigV1_1_20 {
|
||||
pub gateway_id: String,
|
||||
pub gateway_owner: String,
|
||||
pub gateway_listener: String,
|
||||
}
|
||||
|
||||
impl From<GatewayEndpointConfigV2> for GatewayEndpointConfigV3 {
|
||||
fn from(value: GatewayEndpointConfigV2) -> Self {
|
||||
GatewayEndpointConfigV3 {
|
||||
impl From<GatewayEndpointConfigV1_1_20> for GatewayEndpointConfigV1_1_20_2 {
|
||||
fn from(value: GatewayEndpointConfigV1_1_20) -> Self {
|
||||
GatewayEndpointConfigV1_1_20_2 {
|
||||
gateway_id: value.gateway_id,
|
||||
gateway_owner: value.gateway_owner,
|
||||
gateway_listener: value.gateway_listener,
|
||||
@@ -96,7 +83,7 @@ impl From<GatewayEndpointConfigV2> for GatewayEndpointConfigV3 {
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
|
||||
pub struct ClientV2<T> {
|
||||
pub struct ClientV1_1_20<T> {
|
||||
pub version: String,
|
||||
pub id: String,
|
||||
#[serde(default)]
|
||||
@@ -111,7 +98,7 @@ pub struct ClientV2<T> {
|
||||
pub public_encryption_key_file: PathBuf,
|
||||
pub gateway_shared_key_file: PathBuf,
|
||||
pub ack_key_file: PathBuf,
|
||||
pub gateway_endpoint: GatewayEndpointConfigV2,
|
||||
pub gateway_endpoint: GatewayEndpointConfigV1_1_20,
|
||||
pub database_path: PathBuf,
|
||||
#[serde(default)]
|
||||
pub reply_surb_database_path: PathBuf,
|
||||
@@ -123,11 +110,11 @@ pub struct ClientV2<T> {
|
||||
|
||||
#[derive(Debug, Clone, Default, Deserialize, PartialEq, Eq, Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct LoggingV2 {}
|
||||
pub struct LoggingV1_1_20 {}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default)]
|
||||
pub struct TrafficV2 {
|
||||
pub struct TrafficV1_1_20 {
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub average_packet_delay: Duration,
|
||||
#[serde(with = "humantime_serde")]
|
||||
@@ -137,9 +124,9 @@ pub struct TrafficV2 {
|
||||
pub secondary_packet_size: Option<PacketSize>,
|
||||
}
|
||||
|
||||
impl From<TrafficV2> for TrafficV3 {
|
||||
fn from(value: TrafficV2) -> Self {
|
||||
TrafficV3 {
|
||||
impl From<TrafficV1_1_20> for TrafficV1_1_20_2 {
|
||||
fn from(value: TrafficV1_1_20) -> Self {
|
||||
TrafficV1_1_20_2 {
|
||||
average_packet_delay: value.average_packet_delay,
|
||||
message_sending_average_delay: value.message_sending_average_delay,
|
||||
disable_main_poisson_packet_distribution: value
|
||||
@@ -151,9 +138,9 @@ impl From<TrafficV2> for TrafficV3 {
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for TrafficV2 {
|
||||
impl Default for TrafficV1_1_20 {
|
||||
fn default() -> Self {
|
||||
TrafficV2 {
|
||||
TrafficV1_1_20 {
|
||||
average_packet_delay: DEFAULT_AVERAGE_PACKET_DELAY,
|
||||
message_sending_average_delay: DEFAULT_MESSAGE_STREAM_AVERAGE_DELAY,
|
||||
disable_main_poisson_packet_distribution: false,
|
||||
@@ -165,16 +152,16 @@ impl Default for TrafficV2 {
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default, deny_unknown_fields)]
|
||||
pub struct CoverTrafficV2 {
|
||||
pub struct CoverTrafficV1_1_20 {
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub loop_cover_traffic_average_delay: Duration,
|
||||
pub cover_traffic_primary_size_ratio: f64,
|
||||
pub disable_loop_cover_traffic_stream: bool,
|
||||
}
|
||||
|
||||
impl From<CoverTrafficV2> for CoverTrafficV3 {
|
||||
fn from(value: CoverTrafficV2) -> Self {
|
||||
CoverTrafficV3 {
|
||||
impl From<CoverTrafficV1_1_20> for CoverTrafficV1_1_20_2 {
|
||||
fn from(value: CoverTrafficV1_1_20) -> Self {
|
||||
CoverTrafficV1_1_20_2 {
|
||||
loop_cover_traffic_average_delay: value.loop_cover_traffic_average_delay,
|
||||
cover_traffic_primary_size_ratio: value.cover_traffic_primary_size_ratio,
|
||||
disable_loop_cover_traffic_stream: value.disable_loop_cover_traffic_stream,
|
||||
@@ -182,9 +169,9 @@ impl From<CoverTrafficV2> for CoverTrafficV3 {
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for CoverTrafficV2 {
|
||||
impl Default for CoverTrafficV1_1_20 {
|
||||
fn default() -> Self {
|
||||
CoverTrafficV2 {
|
||||
CoverTrafficV1_1_20 {
|
||||
loop_cover_traffic_average_delay: DEFAULT_LOOP_COVER_STREAM_AVERAGE_DELAY,
|
||||
cover_traffic_primary_size_ratio: DEFAULT_COVER_TRAFFIC_PRIMARY_SIZE_RATIO,
|
||||
disable_loop_cover_traffic_stream: false,
|
||||
@@ -194,22 +181,22 @@ impl Default for CoverTrafficV2 {
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default, deny_unknown_fields)]
|
||||
pub struct GatewayConnectionV2 {
|
||||
pub struct GatewayConnectionV1_1_20 {
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub gateway_response_timeout: Duration,
|
||||
}
|
||||
|
||||
impl From<GatewayConnectionV2> for GatewayConnectionV3 {
|
||||
fn from(value: GatewayConnectionV2) -> Self {
|
||||
GatewayConnectionV3 {
|
||||
impl From<GatewayConnectionV1_1_20> for GatewayConnectionV1_1_20_2 {
|
||||
fn from(value: GatewayConnectionV1_1_20) -> Self {
|
||||
GatewayConnectionV1_1_20_2 {
|
||||
gateway_response_timeout: value.gateway_response_timeout,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for GatewayConnectionV2 {
|
||||
impl Default for GatewayConnectionV1_1_20 {
|
||||
fn default() -> Self {
|
||||
GatewayConnectionV2 {
|
||||
GatewayConnectionV1_1_20 {
|
||||
gateway_response_timeout: DEFAULT_GATEWAY_RESPONSE_TIMEOUT,
|
||||
}
|
||||
}
|
||||
@@ -217,7 +204,7 @@ impl Default for GatewayConnectionV2 {
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default, deny_unknown_fields)]
|
||||
pub struct AcknowledgementsV2 {
|
||||
pub struct AcknowledgementsV1_1_20 {
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub average_ack_delay: Duration,
|
||||
pub ack_wait_multiplier: f64,
|
||||
@@ -225,9 +212,9 @@ pub struct AcknowledgementsV2 {
|
||||
pub ack_wait_addition: Duration,
|
||||
}
|
||||
|
||||
impl From<AcknowledgementsV2> for AcknowledgementsV3 {
|
||||
fn from(value: AcknowledgementsV2) -> Self {
|
||||
AcknowledgementsV3 {
|
||||
impl From<AcknowledgementsV1_1_20> for AcknowledgementsV1_1_20_2 {
|
||||
fn from(value: AcknowledgementsV1_1_20) -> Self {
|
||||
AcknowledgementsV1_1_20_2 {
|
||||
average_ack_delay: value.average_ack_delay,
|
||||
ack_wait_multiplier: value.ack_wait_multiplier,
|
||||
ack_wait_addition: value.ack_wait_addition,
|
||||
@@ -235,9 +222,9 @@ impl From<AcknowledgementsV2> for AcknowledgementsV3 {
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for AcknowledgementsV2 {
|
||||
impl Default for AcknowledgementsV1_1_20 {
|
||||
fn default() -> Self {
|
||||
AcknowledgementsV2 {
|
||||
AcknowledgementsV1_1_20 {
|
||||
average_ack_delay: DEFAULT_AVERAGE_PACKET_DELAY,
|
||||
ack_wait_multiplier: DEFAULT_ACK_WAIT_MULTIPLIER,
|
||||
ack_wait_addition: DEFAULT_ACK_WAIT_ADDITION,
|
||||
@@ -247,7 +234,7 @@ impl Default for AcknowledgementsV2 {
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default, deny_unknown_fields)]
|
||||
pub struct TopologyV2 {
|
||||
pub struct TopologyV1_1_20 {
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub topology_refresh_rate: Duration,
|
||||
#[serde(with = "humantime_serde")]
|
||||
@@ -255,9 +242,9 @@ pub struct TopologyV2 {
|
||||
pub disable_refreshing: bool,
|
||||
}
|
||||
|
||||
impl From<TopologyV2> for TopologyV3 {
|
||||
fn from(value: TopologyV2) -> Self {
|
||||
TopologyV3 {
|
||||
impl From<TopologyV1_1_20> for TopologyV1_1_20_2 {
|
||||
fn from(value: TopologyV1_1_20) -> Self {
|
||||
TopologyV1_1_20_2 {
|
||||
topology_refresh_rate: value.topology_refresh_rate,
|
||||
topology_resolution_timeout: value.topology_resolution_timeout,
|
||||
disable_refreshing: value.disable_refreshing,
|
||||
@@ -265,9 +252,9 @@ impl From<TopologyV2> for TopologyV3 {
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for TopologyV2 {
|
||||
impl Default for TopologyV1_1_20 {
|
||||
fn default() -> Self {
|
||||
TopologyV2 {
|
||||
TopologyV1_1_20 {
|
||||
topology_refresh_rate: DEFAULT_TOPOLOGY_REFRESH_RATE,
|
||||
topology_resolution_timeout: DEFAULT_TOPOLOGY_RESOLUTION_TIMEOUT,
|
||||
disable_refreshing: false,
|
||||
@@ -277,7 +264,7 @@ impl Default for TopologyV2 {
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default, deny_unknown_fields)]
|
||||
pub struct ReplySurbsV2 {
|
||||
pub struct ReplySurbsV1_1_20 {
|
||||
pub minimum_reply_surb_storage_threshold: usize,
|
||||
pub maximum_reply_surb_storage_threshold: usize,
|
||||
pub minimum_reply_surb_request_size: u32,
|
||||
@@ -293,9 +280,9 @@ pub struct ReplySurbsV2 {
|
||||
pub maximum_reply_key_age: Duration,
|
||||
}
|
||||
|
||||
impl From<ReplySurbsV2> for ReplySurbsV3 {
|
||||
fn from(value: ReplySurbsV2) -> Self {
|
||||
ReplySurbsV3 {
|
||||
impl From<ReplySurbsV1_1_20> for ReplySurbsV1_1_20_2 {
|
||||
fn from(value: ReplySurbsV1_1_20) -> Self {
|
||||
ReplySurbsV1_1_20_2 {
|
||||
minimum_reply_surb_storage_threshold: value.minimum_reply_surb_storage_threshold,
|
||||
maximum_reply_surb_storage_threshold: value.maximum_reply_surb_storage_threshold,
|
||||
minimum_reply_surb_request_size: value.minimum_reply_surb_request_size,
|
||||
@@ -310,9 +297,9 @@ impl From<ReplySurbsV2> for ReplySurbsV3 {
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for ReplySurbsV2 {
|
||||
impl Default for ReplySurbsV1_1_20 {
|
||||
fn default() -> Self {
|
||||
ReplySurbsV2 {
|
||||
ReplySurbsV1_1_20 {
|
||||
minimum_reply_surb_storage_threshold: DEFAULT_MINIMUM_REPLY_SURB_STORAGE_THRESHOLD,
|
||||
maximum_reply_surb_storage_threshold: DEFAULT_MAXIMUM_REPLY_SURB_STORAGE_THRESHOLD,
|
||||
minimum_reply_surb_request_size: DEFAULT_MINIMUM_REPLY_SURB_REQUEST_SIZE,
|
||||
@@ -329,18 +316,18 @@ impl Default for ReplySurbsV2 {
|
||||
|
||||
#[derive(Debug, Default, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default, deny_unknown_fields)]
|
||||
pub struct DebugConfigV2 {
|
||||
pub traffic: TrafficV2,
|
||||
pub cover_traffic: CoverTrafficV2,
|
||||
pub gateway_connection: GatewayConnectionV2,
|
||||
pub acknowledgements: AcknowledgementsV2,
|
||||
pub topology: TopologyV2,
|
||||
pub reply_surbs: ReplySurbsV2,
|
||||
pub struct DebugConfigV1_1_20 {
|
||||
pub traffic: TrafficV1_1_20,
|
||||
pub cover_traffic: CoverTrafficV1_1_20,
|
||||
pub gateway_connection: GatewayConnectionV1_1_20,
|
||||
pub acknowledgements: AcknowledgementsV1_1_20,
|
||||
pub topology: TopologyV1_1_20,
|
||||
pub reply_surbs: ReplySurbsV1_1_20,
|
||||
}
|
||||
|
||||
impl From<DebugConfigV2> for DebugConfigV3 {
|
||||
fn from(value: DebugConfigV2) -> Self {
|
||||
DebugConfigV3 {
|
||||
impl From<DebugConfigV1_1_20> for DebugConfigV1_1_20_2 {
|
||||
fn from(value: DebugConfigV1_1_20) -> Self {
|
||||
DebugConfigV1_1_20_2 {
|
||||
traffic: value.traffic.into(),
|
||||
cover_traffic: value.cover_traffic.into(),
|
||||
gateway_connection: value.gateway_connection.into(),
|
||||
+67
-80
@@ -1,12 +1,12 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::old::v4::{
|
||||
AcknowledgementsV4, ClientV4, ConfigV4, CoverTrafficV4, DebugConfigV4, GatewayConnectionV4,
|
||||
ReplySurbsV4, TopologyV4, TrafficV4,
|
||||
use crate::config::old_config_v1_1_30::{
|
||||
AcknowledgementsV1_1_30, ClientV1_1_30, ConfigV1_1_30, CoverTrafficV1_1_30, DebugConfigV1_1_30,
|
||||
GatewayConnectionV1_1_30, ReplySurbsV1_1_30, TopologyV1_1_30, TrafficV1_1_30,
|
||||
};
|
||||
use crate::old::v5::GatewayEndpointConfigV5;
|
||||
use nym_sphinx_params::{PacketSize, PacketType};
|
||||
use crate::config::old_config_v1_1_33::OldGatewayEndpointConfigV1_1_33;
|
||||
use nym_sphinx::params::{PacketSize, PacketType};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::time::Duration;
|
||||
use url::Url;
|
||||
@@ -50,31 +50,18 @@ const DEFAULT_MAXIMUM_REPLY_SURB_AGE: Duration = Duration::from_secs(12 * 60 * 6
|
||||
// 24 hours
|
||||
const DEFAULT_MAXIMUM_REPLY_KEY_AGE: Duration = Duration::from_secs(24 * 60 * 60);
|
||||
|
||||
// aliases for backwards compatibility
|
||||
pub type ConfigV1_1_20_2 = ConfigV3;
|
||||
pub type ClientV1_1_20_2 = ClientV3;
|
||||
pub type DebugConfigV1_1_20_2 = DebugConfigV3;
|
||||
pub type GatewayEndpointConfigV1_1_20_2 = GatewayEndpointConfigV3;
|
||||
|
||||
pub type TrafficV1_1_20_2 = TrafficV3;
|
||||
pub type CoverTrafficV1_1_20_2 = CoverTrafficV3;
|
||||
pub type GatewayConnectionV1_1_20_2 = GatewayConnectionV3;
|
||||
pub type AcknowledgementsV1_1_20_2 = AcknowledgementsV3;
|
||||
pub type TopologyV1_1_20_2 = TopologyV3;
|
||||
pub type ReplySurbsV1_1_20_2 = ReplySurbsV3;
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct ConfigV3 {
|
||||
pub client: ClientV3,
|
||||
pub struct ConfigV1_1_20_2 {
|
||||
pub client: ClientV1_1_20_2,
|
||||
|
||||
#[serde(default)]
|
||||
pub debug: DebugConfigV3,
|
||||
pub debug: DebugConfigV1_1_20_2,
|
||||
}
|
||||
|
||||
impl From<ConfigV3> for ConfigV4 {
|
||||
fn from(value: ConfigV3) -> Self {
|
||||
ConfigV4 {
|
||||
impl From<ConfigV1_1_20_2> for ConfigV1_1_30 {
|
||||
fn from(value: ConfigV1_1_20_2) -> Self {
|
||||
ConfigV1_1_30 {
|
||||
client: value.client.into(),
|
||||
debug: value.debug.into(),
|
||||
}
|
||||
@@ -82,7 +69,7 @@ impl From<ConfigV3> for ConfigV4 {
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default, Deserialize, PartialEq, Eq, Serialize)]
|
||||
pub struct GatewayEndpointConfigV3 {
|
||||
pub struct GatewayEndpointConfigV1_1_20_2 {
|
||||
/// gateway_id specifies ID of the gateway to which the client should send messages.
|
||||
/// If initially omitted, a random gateway will be chosen from the available topology.
|
||||
pub gateway_id: String,
|
||||
@@ -94,9 +81,9 @@ pub struct GatewayEndpointConfigV3 {
|
||||
pub gateway_listener: String,
|
||||
}
|
||||
|
||||
impl From<GatewayEndpointConfigV3> for GatewayEndpointConfigV5 {
|
||||
fn from(value: GatewayEndpointConfigV3) -> Self {
|
||||
GatewayEndpointConfigV5 {
|
||||
impl From<GatewayEndpointConfigV1_1_20_2> for OldGatewayEndpointConfigV1_1_33 {
|
||||
fn from(value: GatewayEndpointConfigV1_1_20_2) -> Self {
|
||||
OldGatewayEndpointConfigV1_1_33 {
|
||||
gateway_id: value.gateway_id,
|
||||
gateway_owner: value.gateway_owner,
|
||||
gateway_listener: value.gateway_listener,
|
||||
@@ -105,7 +92,7 @@ impl From<GatewayEndpointConfigV3> for GatewayEndpointConfigV5 {
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
|
||||
pub struct ClientV3 {
|
||||
pub struct ClientV1_1_20_2 {
|
||||
pub version: String,
|
||||
|
||||
pub id: String,
|
||||
@@ -118,12 +105,12 @@ pub struct ClientV3 {
|
||||
|
||||
#[serde(alias = "validator_api_urls")]
|
||||
pub nym_api_urls: Vec<Url>,
|
||||
pub gateway_endpoint: GatewayEndpointConfigV3,
|
||||
pub gateway_endpoint: GatewayEndpointConfigV1_1_20_2,
|
||||
}
|
||||
|
||||
impl From<ClientV3> for ClientV4 {
|
||||
fn from(value: ClientV3) -> Self {
|
||||
ClientV4 {
|
||||
impl From<ClientV1_1_20_2> for ClientV1_1_30 {
|
||||
fn from(value: ClientV1_1_20_2) -> Self {
|
||||
ClientV1_1_30 {
|
||||
version: value.version,
|
||||
id: value.id,
|
||||
disabled_credentials_mode: value.disabled_credentials_mode,
|
||||
@@ -135,7 +122,7 @@ impl From<ClientV3> for ClientV4 {
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default)]
|
||||
pub struct TrafficV3 {
|
||||
pub struct TrafficV1_1_20_2 {
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub average_packet_delay: Duration,
|
||||
#[serde(with = "humantime_serde")]
|
||||
@@ -146,9 +133,9 @@ pub struct TrafficV3 {
|
||||
pub packet_type: PacketType,
|
||||
}
|
||||
|
||||
impl From<TrafficV3> for TrafficV4 {
|
||||
fn from(value: TrafficV3) -> Self {
|
||||
TrafficV4 {
|
||||
impl From<TrafficV1_1_20_2> for TrafficV1_1_30 {
|
||||
fn from(value: TrafficV1_1_20_2) -> Self {
|
||||
TrafficV1_1_30 {
|
||||
average_packet_delay: value.average_packet_delay,
|
||||
message_sending_average_delay: value.message_sending_average_delay,
|
||||
disable_main_poisson_packet_distribution: value
|
||||
@@ -160,9 +147,9 @@ impl From<TrafficV3> for TrafficV4 {
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for TrafficV3 {
|
||||
impl Default for TrafficV1_1_20_2 {
|
||||
fn default() -> Self {
|
||||
TrafficV3 {
|
||||
TrafficV1_1_20_2 {
|
||||
average_packet_delay: DEFAULT_AVERAGE_PACKET_DELAY,
|
||||
message_sending_average_delay: DEFAULT_MESSAGE_STREAM_AVERAGE_DELAY,
|
||||
disable_main_poisson_packet_distribution: false,
|
||||
@@ -175,16 +162,16 @@ impl Default for TrafficV3 {
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default, deny_unknown_fields)]
|
||||
pub struct CoverTrafficV3 {
|
||||
pub struct CoverTrafficV1_1_20_2 {
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub loop_cover_traffic_average_delay: Duration,
|
||||
pub cover_traffic_primary_size_ratio: f64,
|
||||
pub disable_loop_cover_traffic_stream: bool,
|
||||
}
|
||||
|
||||
impl From<CoverTrafficV3> for CoverTrafficV4 {
|
||||
fn from(value: CoverTrafficV3) -> Self {
|
||||
CoverTrafficV4 {
|
||||
impl From<CoverTrafficV1_1_20_2> for CoverTrafficV1_1_30 {
|
||||
fn from(value: CoverTrafficV1_1_20_2) -> Self {
|
||||
CoverTrafficV1_1_30 {
|
||||
loop_cover_traffic_average_delay: value.loop_cover_traffic_average_delay,
|
||||
cover_traffic_primary_size_ratio: value.cover_traffic_primary_size_ratio,
|
||||
disable_loop_cover_traffic_stream: value.disable_loop_cover_traffic_stream,
|
||||
@@ -192,9 +179,9 @@ impl From<CoverTrafficV3> for CoverTrafficV4 {
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for CoverTrafficV3 {
|
||||
impl Default for CoverTrafficV1_1_20_2 {
|
||||
fn default() -> Self {
|
||||
CoverTrafficV3 {
|
||||
CoverTrafficV1_1_20_2 {
|
||||
loop_cover_traffic_average_delay: DEFAULT_LOOP_COVER_STREAM_AVERAGE_DELAY,
|
||||
cover_traffic_primary_size_ratio: DEFAULT_COVER_TRAFFIC_PRIMARY_SIZE_RATIO,
|
||||
disable_loop_cover_traffic_stream: false,
|
||||
@@ -204,22 +191,22 @@ impl Default for CoverTrafficV3 {
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default, deny_unknown_fields)]
|
||||
pub struct GatewayConnectionV3 {
|
||||
pub struct GatewayConnectionV1_1_20_2 {
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub gateway_response_timeout: Duration,
|
||||
}
|
||||
|
||||
impl From<GatewayConnectionV3> for GatewayConnectionV4 {
|
||||
fn from(value: GatewayConnectionV3) -> Self {
|
||||
GatewayConnectionV4 {
|
||||
impl From<GatewayConnectionV1_1_20_2> for GatewayConnectionV1_1_30 {
|
||||
fn from(value: GatewayConnectionV1_1_20_2) -> Self {
|
||||
GatewayConnectionV1_1_30 {
|
||||
gateway_response_timeout: value.gateway_response_timeout,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for GatewayConnectionV3 {
|
||||
impl Default for GatewayConnectionV1_1_20_2 {
|
||||
fn default() -> Self {
|
||||
GatewayConnectionV3 {
|
||||
GatewayConnectionV1_1_20_2 {
|
||||
gateway_response_timeout: DEFAULT_GATEWAY_RESPONSE_TIMEOUT,
|
||||
}
|
||||
}
|
||||
@@ -227,7 +214,7 @@ impl Default for GatewayConnectionV3 {
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default, deny_unknown_fields)]
|
||||
pub struct AcknowledgementsV3 {
|
||||
pub struct AcknowledgementsV1_1_20_2 {
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub average_ack_delay: Duration,
|
||||
pub ack_wait_multiplier: f64,
|
||||
@@ -235,9 +222,9 @@ pub struct AcknowledgementsV3 {
|
||||
pub ack_wait_addition: Duration,
|
||||
}
|
||||
|
||||
impl From<AcknowledgementsV3> for AcknowledgementsV4 {
|
||||
fn from(value: AcknowledgementsV3) -> Self {
|
||||
AcknowledgementsV4 {
|
||||
impl From<AcknowledgementsV1_1_20_2> for AcknowledgementsV1_1_30 {
|
||||
fn from(value: AcknowledgementsV1_1_20_2) -> Self {
|
||||
AcknowledgementsV1_1_30 {
|
||||
average_ack_delay: value.average_ack_delay,
|
||||
ack_wait_multiplier: value.ack_wait_multiplier,
|
||||
ack_wait_addition: value.ack_wait_addition,
|
||||
@@ -245,9 +232,9 @@ impl From<AcknowledgementsV3> for AcknowledgementsV4 {
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for AcknowledgementsV3 {
|
||||
impl Default for AcknowledgementsV1_1_20_2 {
|
||||
fn default() -> Self {
|
||||
AcknowledgementsV3 {
|
||||
AcknowledgementsV1_1_20_2 {
|
||||
average_ack_delay: DEFAULT_AVERAGE_PACKET_DELAY,
|
||||
ack_wait_multiplier: DEFAULT_ACK_WAIT_MULTIPLIER,
|
||||
ack_wait_addition: DEFAULT_ACK_WAIT_ADDITION,
|
||||
@@ -257,7 +244,7 @@ impl Default for AcknowledgementsV3 {
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default, deny_unknown_fields)]
|
||||
pub struct TopologyV3 {
|
||||
pub struct TopologyV1_1_20_2 {
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub topology_refresh_rate: Duration,
|
||||
#[serde(with = "humantime_serde")]
|
||||
@@ -265,9 +252,9 @@ pub struct TopologyV3 {
|
||||
pub disable_refreshing: bool,
|
||||
}
|
||||
|
||||
impl Default for TopologyV3 {
|
||||
impl Default for TopologyV1_1_20_2 {
|
||||
fn default() -> Self {
|
||||
TopologyV3 {
|
||||
TopologyV1_1_20_2 {
|
||||
topology_refresh_rate: DEFAULT_TOPOLOGY_REFRESH_RATE,
|
||||
topology_resolution_timeout: DEFAULT_TOPOLOGY_RESOLUTION_TIMEOUT,
|
||||
disable_refreshing: false,
|
||||
@@ -275,9 +262,9 @@ impl Default for TopologyV3 {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<TopologyV3> for TopologyV4 {
|
||||
fn from(value: TopologyV3) -> Self {
|
||||
TopologyV4 {
|
||||
impl From<TopologyV1_1_20_2> for TopologyV1_1_30 {
|
||||
fn from(value: TopologyV1_1_20_2) -> Self {
|
||||
TopologyV1_1_30 {
|
||||
topology_refresh_rate: value.topology_refresh_rate,
|
||||
topology_resolution_timeout: value.topology_resolution_timeout,
|
||||
disable_refreshing: value.disable_refreshing,
|
||||
@@ -288,7 +275,7 @@ impl From<TopologyV3> for TopologyV4 {
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default, deny_unknown_fields)]
|
||||
pub struct ReplySurbsV3 {
|
||||
pub struct ReplySurbsV1_1_20_2 {
|
||||
pub minimum_reply_surb_storage_threshold: usize,
|
||||
pub maximum_reply_surb_storage_threshold: usize,
|
||||
pub minimum_reply_surb_request_size: u32,
|
||||
@@ -304,9 +291,9 @@ pub struct ReplySurbsV3 {
|
||||
pub maximum_reply_key_age: Duration,
|
||||
}
|
||||
|
||||
impl Default for ReplySurbsV3 {
|
||||
impl Default for ReplySurbsV1_1_20_2 {
|
||||
fn default() -> Self {
|
||||
ReplySurbsV3 {
|
||||
ReplySurbsV1_1_20_2 {
|
||||
minimum_reply_surb_storage_threshold: DEFAULT_MINIMUM_REPLY_SURB_STORAGE_THRESHOLD,
|
||||
maximum_reply_surb_storage_threshold: DEFAULT_MAXIMUM_REPLY_SURB_STORAGE_THRESHOLD,
|
||||
minimum_reply_surb_request_size: DEFAULT_MINIMUM_REPLY_SURB_REQUEST_SIZE,
|
||||
@@ -321,9 +308,9 @@ impl Default for ReplySurbsV3 {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ReplySurbsV3> for ReplySurbsV4 {
|
||||
fn from(value: ReplySurbsV3) -> Self {
|
||||
ReplySurbsV4 {
|
||||
impl From<ReplySurbsV1_1_20_2> for ReplySurbsV1_1_30 {
|
||||
fn from(value: ReplySurbsV1_1_20_2) -> Self {
|
||||
ReplySurbsV1_1_30 {
|
||||
minimum_reply_surb_storage_threshold: value.minimum_reply_surb_storage_threshold,
|
||||
maximum_reply_surb_storage_threshold: value.maximum_reply_surb_storage_threshold,
|
||||
minimum_reply_surb_request_size: value.minimum_reply_surb_request_size,
|
||||
@@ -340,18 +327,18 @@ impl From<ReplySurbsV3> for ReplySurbsV4 {
|
||||
|
||||
#[derive(Debug, Default, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default, deny_unknown_fields)]
|
||||
pub struct DebugConfigV3 {
|
||||
pub traffic: TrafficV3,
|
||||
pub cover_traffic: CoverTrafficV3,
|
||||
pub gateway_connection: GatewayConnectionV3,
|
||||
pub acknowledgements: AcknowledgementsV3,
|
||||
pub topology: TopologyV3,
|
||||
pub reply_surbs: ReplySurbsV3,
|
||||
pub struct DebugConfigV1_1_20_2 {
|
||||
pub traffic: TrafficV1_1_20_2,
|
||||
pub cover_traffic: CoverTrafficV1_1_20_2,
|
||||
pub gateway_connection: GatewayConnectionV1_1_20_2,
|
||||
pub acknowledgements: AcknowledgementsV1_1_20_2,
|
||||
pub topology: TopologyV1_1_20_2,
|
||||
pub reply_surbs: ReplySurbsV1_1_20_2,
|
||||
}
|
||||
|
||||
impl From<DebugConfigV3> for DebugConfigV4 {
|
||||
fn from(value: DebugConfigV3) -> Self {
|
||||
DebugConfigV4 {
|
||||
impl From<DebugConfigV1_1_20_2> for DebugConfigV1_1_30 {
|
||||
fn from(value: DebugConfigV1_1_20_2) -> Self {
|
||||
DebugConfigV1_1_30 {
|
||||
traffic: value.traffic.into(),
|
||||
cover_traffic: value.cover_traffic.into(),
|
||||
gateway_connection: value.gateway_connection.into(),
|
||||
+67
-76
@@ -1,13 +1,16 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::old::v5::{
|
||||
AcknowledgementsV5, ClientV5, ConfigV5, CoverTrafficV5, DebugConfigV5, GatewayConnectionV5,
|
||||
GroupByV5, ReplySurbsV5, TopologyStructureV5, TopologyV5, TrafficV5,
|
||||
use crate::client::topology_control::geo_aware_provider::CountryGroup;
|
||||
use crate::config::old_config_v1_1_33::{
|
||||
AcknowledgementsV1_1_33, ClientV1_1_33, ConfigV1_1_33, CoverTrafficV1_1_33, DebugConfigV1_1_33,
|
||||
GatewayConnectionV1_1_33, GroupByV1_1_33, ReplySurbsV1_1_33, TopologyStructureV1_1_33,
|
||||
TopologyV1_1_33, TrafficV1_1_33,
|
||||
};
|
||||
use nym_sphinx::{
|
||||
addressing::clients::Recipient,
|
||||
params::{PacketSize, PacketType},
|
||||
};
|
||||
use crate::CountryGroup;
|
||||
use nym_sphinx_addressing::Recipient;
|
||||
use nym_sphinx_params::{PacketSize, PacketType};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::time::Duration;
|
||||
use url::Url;
|
||||
@@ -53,39 +56,27 @@ const DEFAULT_MAXIMUM_REPLY_SURB_AGE: Duration = Duration::from_secs(12 * 60 * 6
|
||||
// 24 hours
|
||||
const DEFAULT_MAXIMUM_REPLY_KEY_AGE: Duration = Duration::from_secs(24 * 60 * 60);
|
||||
|
||||
// aliases for backwards compatibility
|
||||
pub type ConfigV1_1_30 = ConfigV4;
|
||||
pub type ClientV1_1_30 = ClientV4;
|
||||
pub type DebugConfigV1_1_30 = DebugConfigV4;
|
||||
|
||||
pub type TrafficV1_1_30 = TrafficV4;
|
||||
pub type CoverTrafficV1_1_30 = CoverTrafficV4;
|
||||
pub type GatewayConnectionV1_1_30 = GatewayConnectionV4;
|
||||
pub type AcknowledgementsV1_1_30 = AcknowledgementsV4;
|
||||
pub type TopologyV1_1_30 = TopologyV4;
|
||||
pub type ReplySurbsV1_1_30 = ReplySurbsV4;
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct ConfigV4 {
|
||||
pub client: ClientV4,
|
||||
pub struct ConfigV1_1_30 {
|
||||
pub client: ClientV1_1_30,
|
||||
|
||||
#[serde(default)]
|
||||
pub debug: DebugConfigV4,
|
||||
pub debug: DebugConfigV1_1_30,
|
||||
}
|
||||
|
||||
impl From<ConfigV4> for ConfigV5 {
|
||||
fn from(value: ConfigV4) -> Self {
|
||||
ConfigV5 {
|
||||
client: ClientV5 {
|
||||
impl From<ConfigV1_1_30> for ConfigV1_1_33 {
|
||||
fn from(value: ConfigV1_1_30) -> Self {
|
||||
ConfigV1_1_33 {
|
||||
client: ClientV1_1_33 {
|
||||
version: value.client.version,
|
||||
id: value.client.id,
|
||||
disabled_credentials_mode: value.client.disabled_credentials_mode,
|
||||
nyxd_urls: value.client.nyxd_urls,
|
||||
nym_api_urls: value.client.nym_api_urls,
|
||||
},
|
||||
debug: DebugConfigV5 {
|
||||
traffic: TrafficV5 {
|
||||
debug: DebugConfigV1_1_33 {
|
||||
traffic: TrafficV1_1_33 {
|
||||
average_packet_delay: value.debug.traffic.average_packet_delay,
|
||||
message_sending_average_delay: value
|
||||
.debug
|
||||
@@ -99,7 +90,7 @@ impl From<ConfigV4> for ConfigV5 {
|
||||
secondary_packet_size: value.debug.traffic.secondary_packet_size,
|
||||
packet_type: value.debug.traffic.packet_type,
|
||||
},
|
||||
cover_traffic: CoverTrafficV5 {
|
||||
cover_traffic: CoverTrafficV1_1_33 {
|
||||
loop_cover_traffic_average_delay: value
|
||||
.debug
|
||||
.cover_traffic
|
||||
@@ -113,18 +104,18 @@ impl From<ConfigV4> for ConfigV5 {
|
||||
.cover_traffic
|
||||
.disable_loop_cover_traffic_stream,
|
||||
},
|
||||
gateway_connection: GatewayConnectionV5 {
|
||||
gateway_connection: GatewayConnectionV1_1_33 {
|
||||
gateway_response_timeout: value
|
||||
.debug
|
||||
.gateway_connection
|
||||
.gateway_response_timeout,
|
||||
},
|
||||
acknowledgements: AcknowledgementsV5 {
|
||||
acknowledgements: AcknowledgementsV1_1_33 {
|
||||
average_ack_delay: value.debug.acknowledgements.average_ack_delay,
|
||||
ack_wait_multiplier: value.debug.acknowledgements.ack_wait_multiplier,
|
||||
ack_wait_addition: value.debug.acknowledgements.ack_wait_addition,
|
||||
},
|
||||
topology: TopologyV5 {
|
||||
topology: TopologyV1_1_33 {
|
||||
topology_refresh_rate: value.debug.topology.topology_refresh_rate,
|
||||
topology_resolution_timeout: value.debug.topology.topology_resolution_timeout,
|
||||
disable_refreshing: value.debug.topology.disable_refreshing,
|
||||
@@ -134,7 +125,7 @@ impl From<ConfigV4> for ConfigV5 {
|
||||
.max_startup_gateway_waiting_period,
|
||||
topology_structure: value.debug.topology.topology_structure.into(),
|
||||
},
|
||||
reply_surbs: ReplySurbsV5 {
|
||||
reply_surbs: ReplySurbsV1_1_33 {
|
||||
minimum_reply_surb_storage_threshold: value
|
||||
.debug
|
||||
.reply_surbs
|
||||
@@ -178,7 +169,7 @@ impl From<ConfigV4> for ConfigV5 {
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
|
||||
// note: the deny_unknown_fields is VITAL here to allow upgrades from v1.1.20_2
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct ClientV4 {
|
||||
pub struct ClientV1_1_30 {
|
||||
/// Version of the client for which this configuration was created.
|
||||
pub version: String,
|
||||
|
||||
@@ -202,7 +193,7 @@ pub struct ClientV4 {
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default, deny_unknown_fields)]
|
||||
pub struct TrafficV4 {
|
||||
pub struct TrafficV1_1_30 {
|
||||
/// The parameter of Poisson distribution determining how long, on average,
|
||||
/// sent packet is going to be delayed at any given mix node.
|
||||
/// So for a packet going through three mix nodes, on average, it will take three times this value
|
||||
@@ -233,9 +224,9 @@ pub struct TrafficV4 {
|
||||
pub packet_type: PacketType,
|
||||
}
|
||||
|
||||
impl Default for TrafficV4 {
|
||||
impl Default for TrafficV1_1_30 {
|
||||
fn default() -> Self {
|
||||
TrafficV4 {
|
||||
TrafficV1_1_30 {
|
||||
average_packet_delay: DEFAULT_AVERAGE_PACKET_DELAY,
|
||||
message_sending_average_delay: DEFAULT_MESSAGE_STREAM_AVERAGE_DELAY,
|
||||
disable_main_poisson_packet_distribution: false,
|
||||
@@ -248,7 +239,7 @@ impl Default for TrafficV4 {
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default, deny_unknown_fields)]
|
||||
pub struct CoverTrafficV4 {
|
||||
pub struct CoverTrafficV1_1_30 {
|
||||
/// The parameter of Poisson distribution determining how long, on average,
|
||||
/// it is going to take for another loop cover traffic message to be sent.
|
||||
#[serde(with = "humantime_serde")]
|
||||
@@ -263,9 +254,9 @@ pub struct CoverTrafficV4 {
|
||||
pub disable_loop_cover_traffic_stream: bool,
|
||||
}
|
||||
|
||||
impl Default for CoverTrafficV4 {
|
||||
impl Default for CoverTrafficV1_1_30 {
|
||||
fn default() -> Self {
|
||||
CoverTrafficV4 {
|
||||
CoverTrafficV1_1_30 {
|
||||
loop_cover_traffic_average_delay: DEFAULT_LOOP_COVER_STREAM_AVERAGE_DELAY,
|
||||
cover_traffic_primary_size_ratio: DEFAULT_COVER_TRAFFIC_PRIMARY_SIZE_RATIO,
|
||||
disable_loop_cover_traffic_stream: false,
|
||||
@@ -275,16 +266,16 @@ impl Default for CoverTrafficV4 {
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default, deny_unknown_fields)]
|
||||
pub struct GatewayConnectionV4 {
|
||||
pub struct GatewayConnectionV1_1_30 {
|
||||
/// How long we're willing to wait for a response to a message sent to the gateway,
|
||||
/// before giving up on it.
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub gateway_response_timeout: Duration,
|
||||
}
|
||||
|
||||
impl Default for GatewayConnectionV4 {
|
||||
impl Default for GatewayConnectionV1_1_30 {
|
||||
fn default() -> Self {
|
||||
GatewayConnectionV4 {
|
||||
GatewayConnectionV1_1_30 {
|
||||
gateway_response_timeout: DEFAULT_GATEWAY_RESPONSE_TIMEOUT,
|
||||
}
|
||||
}
|
||||
@@ -292,7 +283,7 @@ impl Default for GatewayConnectionV4 {
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default, deny_unknown_fields)]
|
||||
pub struct AcknowledgementsV4 {
|
||||
pub struct AcknowledgementsV1_1_30 {
|
||||
/// The parameter of Poisson distribution determining how long, on average,
|
||||
/// sent acknowledgement is going to be delayed at any given mix node.
|
||||
/// So for an ack going through three mix nodes, on average, it will take three times this value
|
||||
@@ -312,9 +303,9 @@ pub struct AcknowledgementsV4 {
|
||||
pub ack_wait_addition: Duration,
|
||||
}
|
||||
|
||||
impl Default for AcknowledgementsV4 {
|
||||
impl Default for AcknowledgementsV1_1_30 {
|
||||
fn default() -> Self {
|
||||
AcknowledgementsV4 {
|
||||
AcknowledgementsV1_1_30 {
|
||||
average_ack_delay: DEFAULT_AVERAGE_PACKET_DELAY,
|
||||
ack_wait_multiplier: DEFAULT_ACK_WAIT_MULTIPLIER,
|
||||
ack_wait_addition: DEFAULT_ACK_WAIT_ADDITION,
|
||||
@@ -324,7 +315,7 @@ impl Default for AcknowledgementsV4 {
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default, deny_unknown_fields)]
|
||||
pub struct TopologyV4 {
|
||||
pub struct TopologyV1_1_30 {
|
||||
/// The uniform delay every which clients are querying the directory server
|
||||
/// to try to obtain a compatible network topology to send sphinx packets through.
|
||||
#[serde(with = "humantime_serde")]
|
||||
@@ -347,23 +338,23 @@ pub struct TopologyV4 {
|
||||
pub max_startup_gateway_waiting_period: Duration,
|
||||
|
||||
/// Specifies the mixnode topology to be used for sending packets.
|
||||
pub topology_structure: TopologyStructureV4,
|
||||
pub topology_structure: TopologyStructureV1_1_30,
|
||||
}
|
||||
|
||||
#[allow(clippy::large_enum_variant)]
|
||||
#[derive(Default, Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub enum TopologyStructureV4 {
|
||||
pub enum TopologyStructureV1_1_30 {
|
||||
#[default]
|
||||
NymApi,
|
||||
GeoAware(GroupByV4),
|
||||
GeoAware(GroupByV1_1_30),
|
||||
}
|
||||
|
||||
impl From<TopologyStructureV4> for TopologyStructureV5 {
|
||||
fn from(value: TopologyStructureV4) -> Self {
|
||||
impl From<TopologyStructureV1_1_30> for TopologyStructureV1_1_33 {
|
||||
fn from(value: TopologyStructureV1_1_30) -> Self {
|
||||
match value {
|
||||
TopologyStructureV4::NymApi => TopologyStructureV5::NymApi,
|
||||
TopologyStructureV4::GeoAware(group_by) => {
|
||||
TopologyStructureV5::GeoAware(group_by.into())
|
||||
TopologyStructureV1_1_30::NymApi => TopologyStructureV1_1_33::NymApi,
|
||||
TopologyStructureV1_1_30::GeoAware(group_by) => {
|
||||
TopologyStructureV1_1_33::GeoAware(group_by.into())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -371,44 +362,44 @@ impl From<TopologyStructureV4> for TopologyStructureV5 {
|
||||
|
||||
#[allow(clippy::large_enum_variant)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub enum GroupByV4 {
|
||||
pub enum GroupByV1_1_30 {
|
||||
CountryGroup(CountryGroup),
|
||||
NymAddress(Recipient),
|
||||
}
|
||||
|
||||
impl From<GroupByV4> for GroupByV5 {
|
||||
fn from(value: GroupByV4) -> Self {
|
||||
impl From<GroupByV1_1_30> for GroupByV1_1_33 {
|
||||
fn from(value: GroupByV1_1_30) -> Self {
|
||||
match value {
|
||||
GroupByV4::CountryGroup(country) => GroupByV5::CountryGroup(country),
|
||||
GroupByV4::NymAddress(addr) => GroupByV5::NymAddress(addr),
|
||||
GroupByV1_1_30::CountryGroup(country) => GroupByV1_1_33::CountryGroup(country),
|
||||
GroupByV1_1_30::NymAddress(addr) => GroupByV1_1_33::NymAddress(addr),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for GroupByV4 {
|
||||
impl std::fmt::Display for GroupByV1_1_30 {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
GroupByV4::CountryGroup(group) => write!(f, "group: {}", group),
|
||||
GroupByV4::NymAddress(address) => write!(f, "address: {}", address),
|
||||
GroupByV1_1_30::CountryGroup(group) => write!(f, "group: {}", group),
|
||||
GroupByV1_1_30::NymAddress(address) => write!(f, "address: {}", address),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for TopologyV4 {
|
||||
impl Default for TopologyV1_1_30 {
|
||||
fn default() -> Self {
|
||||
TopologyV4 {
|
||||
TopologyV1_1_30 {
|
||||
topology_refresh_rate: DEFAULT_TOPOLOGY_REFRESH_RATE,
|
||||
topology_resolution_timeout: DEFAULT_TOPOLOGY_RESOLUTION_TIMEOUT,
|
||||
disable_refreshing: false,
|
||||
max_startup_gateway_waiting_period: DEFAULT_MAX_STARTUP_GATEWAY_WAITING_PERIOD,
|
||||
topology_structure: TopologyStructureV4::default(),
|
||||
topology_structure: TopologyStructureV1_1_30::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default, deny_unknown_fields)]
|
||||
pub struct ReplySurbsV4 {
|
||||
pub struct ReplySurbsV1_1_30 {
|
||||
/// Defines the minimum number of reply surbs the client wants to keep in its storage at all times.
|
||||
/// It can only allow to go below that value if its to request additional reply surbs.
|
||||
pub minimum_reply_surb_storage_threshold: usize,
|
||||
@@ -446,9 +437,9 @@ pub struct ReplySurbsV4 {
|
||||
pub maximum_reply_key_age: Duration,
|
||||
}
|
||||
|
||||
impl Default for ReplySurbsV4 {
|
||||
impl Default for ReplySurbsV1_1_30 {
|
||||
fn default() -> Self {
|
||||
ReplySurbsV4 {
|
||||
ReplySurbsV1_1_30 {
|
||||
minimum_reply_surb_storage_threshold: DEFAULT_MINIMUM_REPLY_SURB_STORAGE_THRESHOLD,
|
||||
maximum_reply_surb_storage_threshold: DEFAULT_MAXIMUM_REPLY_SURB_STORAGE_THRESHOLD,
|
||||
minimum_reply_surb_request_size: DEFAULT_MINIMUM_REPLY_SURB_REQUEST_SIZE,
|
||||
@@ -465,22 +456,22 @@ impl Default for ReplySurbsV4 {
|
||||
|
||||
#[derive(Debug, Default, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default, deny_unknown_fields)]
|
||||
pub struct DebugConfigV4 {
|
||||
pub struct DebugConfigV1_1_30 {
|
||||
/// Defines all configuration options related to traffic streams.
|
||||
pub traffic: TrafficV4,
|
||||
pub traffic: TrafficV1_1_30,
|
||||
|
||||
/// Defines all configuration options related to cover traffic stream(s).
|
||||
pub cover_traffic: CoverTrafficV4,
|
||||
pub cover_traffic: CoverTrafficV1_1_30,
|
||||
|
||||
/// Defines all configuration options related to the gateway connection.
|
||||
pub gateway_connection: GatewayConnectionV4,
|
||||
pub gateway_connection: GatewayConnectionV1_1_30,
|
||||
|
||||
/// Defines all configuration options related to acknowledgements, such as delays or wait timeouts.
|
||||
pub acknowledgements: AcknowledgementsV4,
|
||||
pub acknowledgements: AcknowledgementsV1_1_30,
|
||||
|
||||
/// Defines all configuration options related topology, such as refresh rates or timeouts.
|
||||
pub topology: TopologyV4,
|
||||
pub topology: TopologyV1_1_30,
|
||||
|
||||
/// Defines all configuration options related to reply SURBs.
|
||||
pub reply_surbs: ReplySurbsV4,
|
||||
pub reply_surbs: ReplySurbsV1_1_30,
|
||||
}
|
||||
+59
-68
@@ -1,12 +1,15 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::{
|
||||
Acknowledgements, Client, Config, CountryGroup, CoverTraffic, DebugConfig, GatewayConnection,
|
||||
GroupBy, ReplySurbs, Topology, TopologyStructure, Traffic,
|
||||
use crate::client::topology_control::geo_aware_provider::CountryGroup;
|
||||
use crate::config::{
|
||||
Acknowledgements, Client, Config, CoverTraffic, DebugConfig, GatewayConnection, GroupBy,
|
||||
ReplySurbs, Topology, TopologyStructure, Traffic,
|
||||
};
|
||||
use nym_sphinx::{
|
||||
addressing::clients::Recipient,
|
||||
params::{PacketSize, PacketType},
|
||||
};
|
||||
use nym_sphinx_addressing::Recipient;
|
||||
use nym_sphinx_params::{PacketSize, PacketType};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::time::Duration;
|
||||
use url::Url;
|
||||
@@ -52,21 +55,8 @@ const DEFAULT_MAXIMUM_REPLY_SURB_AGE: Duration = Duration::from_secs(12 * 60 * 6
|
||||
// 24 hours
|
||||
const DEFAULT_MAXIMUM_REPLY_KEY_AGE: Duration = Duration::from_secs(24 * 60 * 60);
|
||||
|
||||
// aliases for backwards compatibility
|
||||
pub type ConfigV1_1_33 = ConfigV5;
|
||||
pub type ClientV1_1_33 = ClientV5;
|
||||
pub type DebugConfigV1_1_33 = DebugConfigV5;
|
||||
pub type OldGatewayEndpointConfigV1_1_33 = GatewayEndpointConfigV5;
|
||||
|
||||
pub type TrafficV1_1_33 = TrafficV5;
|
||||
pub type CoverTrafficV1_1_33 = CoverTrafficV5;
|
||||
pub type GatewayConnectionV1_1_33 = GatewayConnectionV5;
|
||||
pub type AcknowledgementsV1_1_33 = AcknowledgementsV5;
|
||||
pub type TopologyV1_1_33 = TopologyV5;
|
||||
pub type ReplySurbsV1_1_33 = ReplySurbsV5;
|
||||
|
||||
#[derive(Clone, Debug, Default, Deserialize, PartialEq, Eq, Serialize)]
|
||||
pub struct GatewayEndpointConfigV5 {
|
||||
pub struct OldGatewayEndpointConfigV1_1_33 {
|
||||
/// gateway_id specifies ID of the gateway to which the client should send messages.
|
||||
/// If initially omitted, a random gateway will be chosen from the available topology.
|
||||
pub gateway_id: String,
|
||||
@@ -80,15 +70,15 @@ pub struct GatewayEndpointConfigV5 {
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct ConfigV5 {
|
||||
pub client: ClientV5,
|
||||
pub struct ConfigV1_1_33 {
|
||||
pub client: ClientV1_1_33,
|
||||
|
||||
#[serde(default)]
|
||||
pub debug: DebugConfigV5,
|
||||
pub debug: DebugConfigV1_1_33,
|
||||
}
|
||||
|
||||
impl From<ConfigV5> for Config {
|
||||
fn from(value: ConfigV5) -> Self {
|
||||
impl From<ConfigV1_1_33> for Config {
|
||||
fn from(value: ConfigV1_1_33) -> Self {
|
||||
Config {
|
||||
client: Client {
|
||||
version: value.client.version,
|
||||
@@ -146,7 +136,6 @@ impl From<ConfigV5> for Config {
|
||||
.topology
|
||||
.max_startup_gateway_waiting_period,
|
||||
topology_structure: value.debug.topology.topology_structure.into(),
|
||||
..Default::default()
|
||||
},
|
||||
reply_surbs: ReplySurbs {
|
||||
minimum_reply_surb_storage_threshold: value
|
||||
@@ -189,7 +178,7 @@ impl From<ConfigV5> for Config {
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
|
||||
// note: the deny_unknown_fields is VITAL here to allow upgrades from v1.1.20_2
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct ClientV5 {
|
||||
pub struct ClientV1_1_33 {
|
||||
/// Version of the client for which this configuration was created.
|
||||
pub version: String,
|
||||
|
||||
@@ -213,7 +202,7 @@ pub struct ClientV5 {
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default, deny_unknown_fields)]
|
||||
pub struct TrafficV5 {
|
||||
pub struct TrafficV1_1_33 {
|
||||
/// The parameter of Poisson distribution determining how long, on average,
|
||||
/// sent packet is going to be delayed at any given mix node.
|
||||
/// So for a packet going through three mix nodes, on average, it will take three times this value
|
||||
@@ -244,9 +233,9 @@ pub struct TrafficV5 {
|
||||
pub packet_type: PacketType,
|
||||
}
|
||||
|
||||
impl Default for TrafficV5 {
|
||||
impl Default for TrafficV1_1_33 {
|
||||
fn default() -> Self {
|
||||
TrafficV5 {
|
||||
TrafficV1_1_33 {
|
||||
average_packet_delay: DEFAULT_AVERAGE_PACKET_DELAY,
|
||||
message_sending_average_delay: DEFAULT_MESSAGE_STREAM_AVERAGE_DELAY,
|
||||
disable_main_poisson_packet_distribution: false,
|
||||
@@ -259,7 +248,7 @@ impl Default for TrafficV5 {
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default, deny_unknown_fields)]
|
||||
pub struct CoverTrafficV5 {
|
||||
pub struct CoverTrafficV1_1_33 {
|
||||
/// The parameter of Poisson distribution determining how long, on average,
|
||||
/// it is going to take for another loop cover traffic message to be sent.
|
||||
#[serde(with = "humantime_serde")]
|
||||
@@ -274,9 +263,9 @@ pub struct CoverTrafficV5 {
|
||||
pub disable_loop_cover_traffic_stream: bool,
|
||||
}
|
||||
|
||||
impl Default for CoverTrafficV5 {
|
||||
impl Default for CoverTrafficV1_1_33 {
|
||||
fn default() -> Self {
|
||||
CoverTrafficV5 {
|
||||
CoverTrafficV1_1_33 {
|
||||
loop_cover_traffic_average_delay: DEFAULT_LOOP_COVER_STREAM_AVERAGE_DELAY,
|
||||
cover_traffic_primary_size_ratio: DEFAULT_COVER_TRAFFIC_PRIMARY_SIZE_RATIO,
|
||||
disable_loop_cover_traffic_stream: false,
|
||||
@@ -286,16 +275,16 @@ impl Default for CoverTrafficV5 {
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default, deny_unknown_fields)]
|
||||
pub struct GatewayConnectionV5 {
|
||||
pub struct GatewayConnectionV1_1_33 {
|
||||
/// How long we're willing to wait for a response to a message sent to the gateway,
|
||||
/// before giving up on it.
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub gateway_response_timeout: Duration,
|
||||
}
|
||||
|
||||
impl Default for GatewayConnectionV5 {
|
||||
impl Default for GatewayConnectionV1_1_33 {
|
||||
fn default() -> Self {
|
||||
GatewayConnectionV5 {
|
||||
GatewayConnectionV1_1_33 {
|
||||
gateway_response_timeout: DEFAULT_GATEWAY_RESPONSE_TIMEOUT,
|
||||
}
|
||||
}
|
||||
@@ -303,7 +292,7 @@ impl Default for GatewayConnectionV5 {
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default, deny_unknown_fields)]
|
||||
pub struct AcknowledgementsV5 {
|
||||
pub struct AcknowledgementsV1_1_33 {
|
||||
/// The parameter of Poisson distribution determining how long, on average,
|
||||
/// sent acknowledgement is going to be delayed at any given mix node.
|
||||
/// So for an ack going through three mix nodes, on average, it will take three times this value
|
||||
@@ -323,9 +312,9 @@ pub struct AcknowledgementsV5 {
|
||||
pub ack_wait_addition: Duration,
|
||||
}
|
||||
|
||||
impl Default for AcknowledgementsV5 {
|
||||
impl Default for AcknowledgementsV1_1_33 {
|
||||
fn default() -> Self {
|
||||
AcknowledgementsV5 {
|
||||
AcknowledgementsV1_1_33 {
|
||||
average_ack_delay: DEFAULT_AVERAGE_PACKET_DELAY,
|
||||
ack_wait_multiplier: DEFAULT_ACK_WAIT_MULTIPLIER,
|
||||
ack_wait_addition: DEFAULT_ACK_WAIT_ADDITION,
|
||||
@@ -335,7 +324,7 @@ impl Default for AcknowledgementsV5 {
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default, deny_unknown_fields)]
|
||||
pub struct TopologyV5 {
|
||||
pub struct TopologyV1_1_33 {
|
||||
/// The uniform delay every which clients are querying the directory server
|
||||
/// to try to obtain a compatible network topology to send sphinx packets through.
|
||||
#[serde(with = "humantime_serde")]
|
||||
@@ -358,66 +347,68 @@ pub struct TopologyV5 {
|
||||
pub max_startup_gateway_waiting_period: Duration,
|
||||
|
||||
/// Specifies the mixnode topology to be used for sending packets.
|
||||
pub topology_structure: TopologyStructureV5,
|
||||
pub topology_structure: TopologyStructureV1_1_33,
|
||||
}
|
||||
|
||||
#[allow(clippy::large_enum_variant)]
|
||||
#[derive(Default, Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub enum TopologyStructureV5 {
|
||||
pub enum TopologyStructureV1_1_33 {
|
||||
#[default]
|
||||
NymApi,
|
||||
GeoAware(GroupByV5),
|
||||
GeoAware(GroupByV1_1_33),
|
||||
}
|
||||
|
||||
impl From<TopologyStructureV5> for TopologyStructure {
|
||||
fn from(value: TopologyStructureV5) -> Self {
|
||||
impl From<TopologyStructureV1_1_33> for TopologyStructure {
|
||||
fn from(value: TopologyStructureV1_1_33) -> Self {
|
||||
match value {
|
||||
TopologyStructureV5::NymApi => TopologyStructure::NymApi,
|
||||
TopologyStructureV5::GeoAware(group_by) => TopologyStructure::GeoAware(group_by.into()),
|
||||
TopologyStructureV1_1_33::NymApi => TopologyStructure::NymApi,
|
||||
TopologyStructureV1_1_33::GeoAware(group_by) => {
|
||||
TopologyStructure::GeoAware(group_by.into())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::large_enum_variant)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub enum GroupByV5 {
|
||||
pub enum GroupByV1_1_33 {
|
||||
CountryGroup(CountryGroup),
|
||||
NymAddress(Recipient),
|
||||
}
|
||||
|
||||
impl From<GroupByV5> for GroupBy {
|
||||
fn from(value: GroupByV5) -> Self {
|
||||
impl From<GroupByV1_1_33> for GroupBy {
|
||||
fn from(value: GroupByV1_1_33) -> Self {
|
||||
match value {
|
||||
GroupByV5::CountryGroup(country) => GroupBy::CountryGroup(country),
|
||||
GroupByV5::NymAddress(addr) => GroupBy::NymAddress(addr),
|
||||
GroupByV1_1_33::CountryGroup(country) => GroupBy::CountryGroup(country),
|
||||
GroupByV1_1_33::NymAddress(addr) => GroupBy::NymAddress(addr),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for GroupByV5 {
|
||||
impl std::fmt::Display for GroupByV1_1_33 {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
GroupByV5::CountryGroup(group) => write!(f, "group: {}", group),
|
||||
GroupByV5::NymAddress(address) => write!(f, "address: {}", address),
|
||||
GroupByV1_1_33::CountryGroup(group) => write!(f, "group: {}", group),
|
||||
GroupByV1_1_33::NymAddress(address) => write!(f, "address: {}", address),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for TopologyV5 {
|
||||
impl Default for TopologyV1_1_33 {
|
||||
fn default() -> Self {
|
||||
TopologyV5 {
|
||||
TopologyV1_1_33 {
|
||||
topology_refresh_rate: DEFAULT_TOPOLOGY_REFRESH_RATE,
|
||||
topology_resolution_timeout: DEFAULT_TOPOLOGY_RESOLUTION_TIMEOUT,
|
||||
disable_refreshing: false,
|
||||
max_startup_gateway_waiting_period: DEFAULT_MAX_STARTUP_GATEWAY_WAITING_PERIOD,
|
||||
topology_structure: TopologyStructureV5::default(),
|
||||
topology_structure: TopologyStructureV1_1_33::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default, deny_unknown_fields)]
|
||||
pub struct ReplySurbsV5 {
|
||||
pub struct ReplySurbsV1_1_33 {
|
||||
/// Defines the minimum number of reply surbs the client wants to keep in its storage at all times.
|
||||
/// It can only allow to go below that value if its to request additional reply surbs.
|
||||
pub minimum_reply_surb_storage_threshold: usize,
|
||||
@@ -459,9 +450,9 @@ pub struct ReplySurbsV5 {
|
||||
pub surb_mix_hops: Option<u8>,
|
||||
}
|
||||
|
||||
impl Default for ReplySurbsV5 {
|
||||
impl Default for ReplySurbsV1_1_33 {
|
||||
fn default() -> Self {
|
||||
ReplySurbsV5 {
|
||||
ReplySurbsV1_1_33 {
|
||||
minimum_reply_surb_storage_threshold: DEFAULT_MINIMUM_REPLY_SURB_STORAGE_THRESHOLD,
|
||||
maximum_reply_surb_storage_threshold: DEFAULT_MAXIMUM_REPLY_SURB_STORAGE_THRESHOLD,
|
||||
minimum_reply_surb_request_size: DEFAULT_MINIMUM_REPLY_SURB_REQUEST_SIZE,
|
||||
@@ -479,22 +470,22 @@ impl Default for ReplySurbsV5 {
|
||||
|
||||
#[derive(Debug, Default, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default, deny_unknown_fields)]
|
||||
pub struct DebugConfigV5 {
|
||||
pub struct DebugConfigV1_1_33 {
|
||||
/// Defines all configuration options related to traffic streams.
|
||||
pub traffic: TrafficV5,
|
||||
pub traffic: TrafficV1_1_33,
|
||||
|
||||
/// Defines all configuration options related to cover traffic stream(s).
|
||||
pub cover_traffic: CoverTrafficV5,
|
||||
pub cover_traffic: CoverTrafficV1_1_33,
|
||||
|
||||
/// Defines all configuration options related to the gateway connection.
|
||||
pub gateway_connection: GatewayConnectionV5,
|
||||
pub gateway_connection: GatewayConnectionV1_1_33,
|
||||
|
||||
/// Defines all configuration options related to acknowledgements, such as delays or wait timeouts.
|
||||
pub acknowledgements: AcknowledgementsV5,
|
||||
pub acknowledgements: AcknowledgementsV1_1_33,
|
||||
|
||||
/// Defines all configuration options related topology, such as refresh rates or timeouts.
|
||||
pub topology: TopologyV5,
|
||||
pub topology: TopologyV1_1_33,
|
||||
|
||||
/// Defines all configuration options related to reply SURBs.
|
||||
pub reply_surbs: ReplySurbsV5,
|
||||
pub reply_surbs: ReplySurbsV1_1_33,
|
||||
}
|
||||
@@ -29,7 +29,7 @@ pub enum SelectedGateway {
|
||||
Remote {
|
||||
gateway_id: identity::PublicKey,
|
||||
|
||||
gateway_owner_address: Option<AccountId>,
|
||||
gateway_owner_address: AccountId,
|
||||
|
||||
gateway_listener: Url,
|
||||
|
||||
@@ -84,19 +84,13 @@ impl SelectedGateway {
|
||||
|
||||
let wg_tun_address = wg_tun_address(wg_tun_ip_address, &node)?;
|
||||
|
||||
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_owner_address = AccountId::from_str(&node.owner).map_err(|source| {
|
||||
ClientCoreError::MalformedGatewayOwnerAccountAddress {
|
||||
gateway_id: node.identity_key.to_base58_string(),
|
||||
raw_owner: node.owner,
|
||||
err: source.to_string(),
|
||||
}
|
||||
})?;
|
||||
|
||||
let gateway_listener =
|
||||
Url::parse(&gateway_listener).map_err(|source| ClientCoreError::MalformedListener {
|
||||
|
||||
@@ -14,10 +14,8 @@ futures = { workspace = true }
|
||||
log = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
url = { workspace = true }
|
||||
rand = { workspace = true }
|
||||
tokio = { workspace = true, features = ["macros"] }
|
||||
si-scale = { workspace = true }
|
||||
time.workspace = true
|
||||
rand = { version = "0.7.3", features = ["wasm-bindgen"] }
|
||||
tokio = { version = "1.24.1", features = ["macros"] }
|
||||
|
||||
# internal
|
||||
nym-bandwidth-controller = { path = "../../bandwidth-controller" }
|
||||
@@ -48,7 +46,10 @@ features = ["net", "sync", "time"]
|
||||
|
||||
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.tokio-tungstenite]
|
||||
workspace = true
|
||||
features = ["rustls-tls-webpki-roots"]
|
||||
# the choice of this particular tls feature was arbitrary;
|
||||
# if you reckon a different one would be more appropriate, feel free to change it
|
||||
# features = ["native-tls"]
|
||||
features = ["rustls-tls-native-roots"]
|
||||
|
||||
# wasm-only dependencies
|
||||
[target."cfg(target_arch = \"wasm32\")".dependencies.wasm-bindgen]
|
||||
|
||||
@@ -220,18 +220,9 @@ impl<C, St> GatewayClient<C, St> {
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
pub async fn establish_connection(&mut self) -> Result<(), GatewayClientError> {
|
||||
debug!(
|
||||
"Attemting to establish connection to gateway at: {}",
|
||||
self.gateway_address
|
||||
);
|
||||
let ws_stream = match connect_async(&self.gateway_address).await {
|
||||
Ok((ws_stream, _)) => ws_stream,
|
||||
Err(error) => {
|
||||
return Err(GatewayClientError::NetworkConnectionFailed {
|
||||
address: self.gateway_address.clone(),
|
||||
source: error,
|
||||
})
|
||||
}
|
||||
Err(e) => return Err(GatewayClientError::NetworkError(e)),
|
||||
};
|
||||
|
||||
self.connection = SocketState::Available(Box::new(ws_stream));
|
||||
@@ -451,7 +442,7 @@ impl<C, St> GatewayClient<C, St> {
|
||||
}
|
||||
|
||||
debug_assert!(self.connection.is_available());
|
||||
log::debug!("Registering gateway");
|
||||
log::trace!("Registering gateway");
|
||||
|
||||
// it's fine to instantiate it here as it's only used once (during authentication or registration)
|
||||
// and putting it into the GatewayClient struct would be a hassle
|
||||
@@ -503,7 +494,6 @@ impl<C, St> GatewayClient<C, St> {
|
||||
if !self.connection.is_established() {
|
||||
return Err(GatewayClientError::ConnectionNotEstablished);
|
||||
}
|
||||
log::debug!("Authenticating with gateway");
|
||||
|
||||
// it's fine to instantiate it here as it's only used once (during authentication or registration)
|
||||
// and putting it into the GatewayClient struct would be a hassle
|
||||
@@ -539,7 +529,6 @@ impl<C, St> GatewayClient<C, St> {
|
||||
self.authenticated = status;
|
||||
self.bandwidth_remaining = bandwidth_remaining;
|
||||
self.negotiated_protocol = protocol_version;
|
||||
log::debug!("authenticated: {status}, bandwidth remaining: {bandwidth_remaining}");
|
||||
Ok(())
|
||||
}
|
||||
ServerResponse::Error { message } => Err(GatewayClientError::GatewayError(message)),
|
||||
@@ -552,11 +541,10 @@ impl<C, St> GatewayClient<C, St> {
|
||||
&mut self,
|
||||
) -> Result<Arc<SharedKeys>, GatewayClientError> {
|
||||
if self.authenticated {
|
||||
debug!("Already authenticated");
|
||||
return if let Some(shared_key) = &self.shared_key {
|
||||
Ok(Arc::clone(shared_key))
|
||||
} else {
|
||||
Err(GatewayClientError::AuthenticationFailureWithPreexistingSharedKey)
|
||||
Err(GatewayClientError::AuthenticationFailure)
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -23,9 +23,6 @@ pub enum GatewayClientError {
|
||||
#[error("There was a network error: {0}")]
|
||||
NetworkErrorWasm(#[from] JsError),
|
||||
|
||||
#[error("connection failed: {address}: {source}")]
|
||||
NetworkConnectionFailed { address: String, source: WsError },
|
||||
|
||||
#[error("Invalid URL: {0}")]
|
||||
InvalidURL(String),
|
||||
|
||||
@@ -74,9 +71,6 @@ pub enum GatewayClientError {
|
||||
#[error("Authentication failure")]
|
||||
AuthenticationFailure,
|
||||
|
||||
#[error("Authentication failure with preexisting shared key")]
|
||||
AuthenticationFailureWithPreexistingSharedKey,
|
||||
|
||||
#[error("Timed out")]
|
||||
Timeout,
|
||||
|
||||
|
||||
@@ -10,14 +10,9 @@ use futures::stream::{SplitSink, SplitStream};
|
||||
use futures::{SinkExt, StreamExt};
|
||||
use log::*;
|
||||
use nym_gateway_requests::registration::handshake::SharedKeys;
|
||||
use nym_gateway_requests::ServerResponse;
|
||||
use nym_task::TaskClient;
|
||||
use si_scale::helpers::bibytes2;
|
||||
use std::os::raw::c_int as RawFd;
|
||||
use std::sync::atomic::{AtomicI64, Ordering};
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
use time::OffsetDateTime;
|
||||
use tungstenite::Message;
|
||||
|
||||
#[cfg(unix)]
|
||||
@@ -53,21 +48,6 @@ pub(crate) fn ws_fd(_conn: &WsConn) -> Option<RawFd> {
|
||||
None
|
||||
}
|
||||
|
||||
// disgusting? absolutely, but does the trick for now
|
||||
static LAST_LOGGED_BANDWIDTH_TS: AtomicI64 = AtomicI64::new(0);
|
||||
|
||||
fn maybe_log_bandwidth(remaining: i64) {
|
||||
// SAFETY: this value is always populated with valid timestamps
|
||||
let last =
|
||||
OffsetDateTime::from_unix_timestamp(LAST_LOGGED_BANDWIDTH_TS.load(Ordering::Relaxed))
|
||||
.unwrap();
|
||||
let now = OffsetDateTime::now_utc();
|
||||
if last + Duration::from_secs(10) < now {
|
||||
log::info!("remaining bandwidth: {}", bibytes2(remaining as f64));
|
||||
LAST_LOGGED_BANDWIDTH_TS.store(now.unix_timestamp(), Ordering::Relaxed)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct PartiallyDelegated {
|
||||
sink_half: SplitSink<WsConn, Message>,
|
||||
@@ -76,10 +56,7 @@ pub(crate) struct PartiallyDelegated {
|
||||
}
|
||||
|
||||
impl PartiallyDelegated {
|
||||
fn recover_received_plaintexts(
|
||||
ws_msgs: Vec<Message>,
|
||||
shared_key: &SharedKeys,
|
||||
) -> Result<Vec<Vec<u8>>, GatewayClientError> {
|
||||
fn recover_received_plaintexts(ws_msgs: Vec<Message>, shared_key: &SharedKeys) -> Vec<Vec<u8>> {
|
||||
let mut plaintexts = Vec::with_capacity(ws_msgs.len());
|
||||
for ws_msg in ws_msgs {
|
||||
match ws_msg {
|
||||
@@ -97,32 +74,15 @@ impl PartiallyDelegated {
|
||||
// TODO: those can return the "send confirmations" - perhaps it should be somehow worked around?
|
||||
Message::Text(text) => {
|
||||
trace!(
|
||||
"received a text message - probably a response to some previous query! - {text}",
|
||||
"received a text message - probably a response to some previous query! - {}",
|
||||
text
|
||||
);
|
||||
match ServerResponse::try_from(text)
|
||||
.map_err(|_| GatewayClientError::MalformedResponse)?
|
||||
{
|
||||
ServerResponse::Send {
|
||||
remaining_bandwidth,
|
||||
} => maybe_log_bandwidth(remaining_bandwidth),
|
||||
ServerResponse::Error { message } => {
|
||||
error!("gateway failure: {message}");
|
||||
return Err(GatewayClientError::GatewayError(message));
|
||||
}
|
||||
other => {
|
||||
warn!(
|
||||
"received illegal message of type {} in an authenticated client",
|
||||
other.name()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
_ => continue,
|
||||
}
|
||||
}
|
||||
Ok(plaintexts)
|
||||
plaintexts
|
||||
}
|
||||
|
||||
fn route_socket_messages(
|
||||
@@ -130,7 +90,7 @@ impl PartiallyDelegated {
|
||||
packet_router: &PacketRouter,
|
||||
shared_key: &SharedKeys,
|
||||
) -> Result<(), GatewayClientError> {
|
||||
let plaintexts = Self::recover_received_plaintexts(ws_msgs, shared_key)?;
|
||||
let plaintexts = Self::recover_received_plaintexts(ws_msgs, shared_key);
|
||||
packet_router.route_received(plaintexts)
|
||||
}
|
||||
|
||||
@@ -170,8 +130,7 @@ impl PartiallyDelegated {
|
||||
};
|
||||
|
||||
if let Err(err) = Self::route_socket_messages(ws_msgs, &packet_router, shared_key.as_ref()) {
|
||||
log::error!("Route socket messages failed: {err}");
|
||||
break Err(err)
|
||||
log::warn!("Route socket messages failed: {err}");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -10,18 +10,22 @@ license.workspace = true
|
||||
|
||||
[dependencies]
|
||||
base64 = "0.13"
|
||||
colored = { workspace = true }
|
||||
colored = "2.0"
|
||||
|
||||
nym-coconut-dkg-common = { path = "../../cosmwasm-smart-contracts/coconut-dkg" }
|
||||
nym-contracts-common = { path = "../../cosmwasm-smart-contracts/contracts-common" }
|
||||
nym-ephemera-common = { path = "../../cosmwasm-smart-contracts/ephemera" }
|
||||
nym-mixnet-contract-common = { path = "../../cosmwasm-smart-contracts/mixnet-contract" }
|
||||
nym-vesting-contract-common = { path = "../../cosmwasm-smart-contracts/vesting-contract" }
|
||||
nym-coconut-bandwidth-contract-common = { path = "../../cosmwasm-smart-contracts/coconut-bandwidth-contract" }
|
||||
nym-multisig-contract-common = { path = "../../cosmwasm-smart-contracts/multisig-contract" }
|
||||
nym-name-service-common = { path = "../../cosmwasm-smart-contracts/name-service" }
|
||||
nym-group-contract-common = { path = "../../cosmwasm-smart-contracts/group-contract" }
|
||||
nym-service-provider-directory-common = { path = "../../cosmwasm-smart-contracts/service-provider-directory" }
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
serde_json = { workspace = true }
|
||||
nym-http-api-client = { path = "../../../common/http-api-client" }
|
||||
reqwest = { workspace = true, features = ["json"] }
|
||||
nym-http-api-client = { path = "../../../common/http-api-client"}
|
||||
thiserror = { workspace = true }
|
||||
log = { workspace = true }
|
||||
url = { workspace = true, features = ["serde"] }
|
||||
@@ -45,14 +49,14 @@ tendermint-rpc = { workspace = true }
|
||||
# of cargo's feature unification we'd get `bip32/std` meaning we'd get `std::error::Error` for the re-exported (via cosmrs) bip32::Error type
|
||||
bip32 = { workspace = true, default-features = false, features = ["std"] }
|
||||
|
||||
eyre = { workspace = true }
|
||||
eyre = { version = "0.6" }
|
||||
cw-utils = { workspace = true }
|
||||
cw2 = { workspace = true }
|
||||
cw3 = { workspace = true }
|
||||
cw4 = { workspace = true }
|
||||
cw-controllers = { workspace = true }
|
||||
prost = { workspace = true, default-features = false }
|
||||
flate2 = { workspace = true }
|
||||
flate2 = { version = "1.0.20" }
|
||||
sha2 = { version = "0.9.5" }
|
||||
itertools = { version = "0.10" }
|
||||
zeroize = { workspace = true, features = ["zeroize_derive"] }
|
||||
@@ -63,14 +67,6 @@ cosmwasm-std = { workspace = true }
|
||||
workspace = true
|
||||
features = ["tokio"]
|
||||
|
||||
[target."cfg(target_arch = \"wasm32\")".dependencies.reqwest]
|
||||
workspace = true
|
||||
features = ["json"]
|
||||
|
||||
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.reqwest]
|
||||
workspace = true
|
||||
features = ["json", "rustls-tls"]
|
||||
|
||||
[dev-dependencies]
|
||||
bip39 = { workspace = true }
|
||||
cosmrs = { workspace = true, features = ["bip32"] }
|
||||
@@ -83,6 +79,14 @@ name = "offline_signing"
|
||||
# (traits would need to be moved around and refactored themselves)
|
||||
required-features = ["http-client"]
|
||||
|
||||
[[example]]
|
||||
name = "query_service_provider_directory"
|
||||
required-features = ["http-client"]
|
||||
|
||||
[[example]]
|
||||
name = "query_name_service"
|
||||
required-features = ["http-client"]
|
||||
|
||||
[features]
|
||||
default = ["http-client"]
|
||||
http-client = ["cosmrs/rpc"]
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
use std::str::FromStr;
|
||||
|
||||
use cosmrs::AccountId;
|
||||
use nym_name_service_common::Address;
|
||||
use nym_network_defaults::{setup_env, NymNetworkDetails};
|
||||
use nym_validator_client::nyxd::contract_traits::{
|
||||
NameServiceQueryClient, PagedNameServiceQueryClient,
|
||||
};
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
setup_env(Some("../../../envs/qa.env"));
|
||||
let network_details = NymNetworkDetails::new_from_env();
|
||||
let config =
|
||||
nym_validator_client::Config::try_from_nym_network_details(&network_details).unwrap();
|
||||
let client = nym_validator_client::Client::new_query(config).unwrap();
|
||||
|
||||
let config = client.nyxd.get_name_service_config().await.unwrap();
|
||||
println!("config: {config:?}");
|
||||
|
||||
let names_paged = client.nyxd.get_names_paged(None, None).await.unwrap();
|
||||
println!("names (paged): {names_paged:#?}");
|
||||
|
||||
let names = client.nyxd.get_all_names().await.unwrap();
|
||||
println!("names: {names:#?}");
|
||||
|
||||
let owner = AccountId::from_str("n1hmf957kc7arcd39rl7xq8l0a4zyg7kxnv7su87").unwrap();
|
||||
let names_by_owner = client.nyxd.get_names_by_owner(owner).await.unwrap();
|
||||
println!("names (by owner): {names_by_owner:#?}");
|
||||
|
||||
let nym_address = Address::new("client_id.client_key@gateway_id").unwrap();
|
||||
let names_by_address = client.nyxd.get_names_by_address(nym_address).await.unwrap();
|
||||
println!("names (by address): {names_by_address:#?}");
|
||||
|
||||
let service_info = client.nyxd.get_name_entry(1).await;
|
||||
println!("service info: {service_info:#?}");
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
use std::str::FromStr;
|
||||
|
||||
use cosmrs::AccountId;
|
||||
use nym_network_defaults::{setup_env, NymNetworkDetails};
|
||||
use nym_service_provider_directory_common::NymAddress;
|
||||
use nym_validator_client::nyxd::contract_traits::{
|
||||
PagedSpDirectoryQueryClient, SpDirectoryQueryClient,
|
||||
};
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
setup_env(Some("../../../envs/qa.env"));
|
||||
let network_details = NymNetworkDetails::new_from_env();
|
||||
let config =
|
||||
nym_validator_client::Config::try_from_nym_network_details(&network_details).unwrap();
|
||||
let client = nym_validator_client::Client::new_query(config).unwrap();
|
||||
|
||||
let config = client.nyxd.get_service_config().await.unwrap();
|
||||
println!("config: {config:?}");
|
||||
|
||||
let services_paged = client.nyxd.get_services_paged(None, None).await.unwrap();
|
||||
println!("services (paged): {services_paged:#?}");
|
||||
|
||||
let services = client.nyxd.get_all_services().await.unwrap();
|
||||
println!("services: {services:#?}");
|
||||
|
||||
let announcer = AccountId::from_str("n1hmf957kc7arcd39rl7xq8l0a4zyg7kxnv7su87").unwrap();
|
||||
let services_by_announcer = client
|
||||
.nyxd
|
||||
.get_services_by_announcer(announcer)
|
||||
.await
|
||||
.unwrap();
|
||||
println!("services (by announcer): {services_by_announcer:#?}");
|
||||
|
||||
let nym_address = NymAddress::new("foo.bar@gateway");
|
||||
let services_by_nym_address = client
|
||||
.nyxd
|
||||
.get_services_by_nym_address(nym_address)
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(services_by_announcer, services_by_nym_address);
|
||||
|
||||
let service_info = client.nyxd.get_service_info(1).await;
|
||||
println!("service info: {service_info:#?}");
|
||||
}
|
||||
@@ -18,7 +18,6 @@ use nym_api_requests::models::{
|
||||
GatewayCoreStatusResponse, MixnodeCoreStatusResponse, MixnodeStatusResponse,
|
||||
RewardEstimationResponse, StakeSaturationResponse,
|
||||
};
|
||||
use nym_api_requests::nym_nodes::SkimmedNode;
|
||||
use nym_network_defaults::NymNetworkDetails;
|
||||
use url::Url;
|
||||
|
||||
@@ -266,28 +265,6 @@ impl NymApiClient {
|
||||
self.nym_api.change_base_url(new_endpoint);
|
||||
}
|
||||
|
||||
pub async fn get_basic_mixnodes(
|
||||
&self,
|
||||
semver_compatibility: Option<String>,
|
||||
) -> Result<Vec<SkimmedNode>, ValidatorClientError> {
|
||||
Ok(self
|
||||
.nym_api
|
||||
.get_basic_mixnodes(semver_compatibility)
|
||||
.await?
|
||||
.nodes)
|
||||
}
|
||||
|
||||
pub async fn get_basic_gateways(
|
||||
&self,
|
||||
semver_compatibility: Option<String>,
|
||||
) -> Result<Vec<SkimmedNode>, ValidatorClientError> {
|
||||
Ok(self
|
||||
.nym_api
|
||||
.get_basic_gateways(semver_compatibility)
|
||||
.await?
|
||||
.nodes)
|
||||
}
|
||||
|
||||
pub async fn get_cached_active_mixnodes(
|
||||
&self,
|
||||
) -> Result<Vec<MixNodeDetails>, ValidatorClientError> {
|
||||
|
||||
@@ -25,13 +25,14 @@ pub use nym_coconut_dkg_common::types::EpochId;
|
||||
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_name_service_common::response::NamesListResponse;
|
||||
use nym_service_provider_directory_common::response::ServicesListResponse;
|
||||
|
||||
pub mod error;
|
||||
pub mod routes;
|
||||
|
||||
use nym_api_requests::coconut::models::FreePassNonceResponse;
|
||||
use nym_api_requests::coconut::FreePassRequest;
|
||||
use nym_api_requests::nym_nodes::{CachedNodesResponse, SkimmedNode};
|
||||
pub use nym_http_api_client::Client;
|
||||
|
||||
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
||||
@@ -96,52 +97,6 @@ pub trait NymApiClientExt: ApiClient {
|
||||
.await
|
||||
}
|
||||
|
||||
async fn get_basic_mixnodes(
|
||||
&self,
|
||||
semver_compatibility: Option<String>,
|
||||
) -> Result<CachedNodesResponse<SkimmedNode>, NymAPIError> {
|
||||
let params = if let Some(semver_compatibility) = &semver_compatibility {
|
||||
vec![("semver_compatibility", semver_compatibility.as_str())]
|
||||
} else {
|
||||
vec![]
|
||||
};
|
||||
|
||||
self.get_json(
|
||||
&[
|
||||
routes::API_VERSION,
|
||||
"unstable",
|
||||
"nym-nodes",
|
||||
"mixnodes",
|
||||
"skimmed",
|
||||
],
|
||||
¶ms,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn get_basic_gateways(
|
||||
&self,
|
||||
semver_compatibility: Option<String>,
|
||||
) -> Result<CachedNodesResponse<SkimmedNode>, NymAPIError> {
|
||||
let params = if let Some(semver_compatibility) = &semver_compatibility {
|
||||
vec![("semver_compatibility", semver_compatibility.as_str())]
|
||||
} else {
|
||||
vec![]
|
||||
};
|
||||
|
||||
self.get_json(
|
||||
&[
|
||||
routes::API_VERSION,
|
||||
"unstable",
|
||||
"nym-nodes",
|
||||
"gateways",
|
||||
"skimmed",
|
||||
],
|
||||
¶ms,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn get_active_mixnodes(&self) -> Result<Vec<MixNodeDetails>, NymAPIError> {
|
||||
self.get_json(
|
||||
&[routes::API_VERSION, routes::MIXNODES, routes::ACTIVE],
|
||||
@@ -537,6 +492,19 @@ pub trait NymApiClientExt: ApiClient {
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn get_service_providers(&self) -> Result<ServicesListResponse, NymAPIError> {
|
||||
log::trace!("Getting service providers");
|
||||
self.get_json(&[routes::API_VERSION, routes::SERVICE_PROVIDERS], NO_PARAMS)
|
||||
.await
|
||||
}
|
||||
|
||||
//async fn get_registered_names(&self) -> Result<Vec<NameEntry>, NymAPIError> {
|
||||
async fn get_registered_names(&self) -> Result<NamesListResponse, NymAPIError> {
|
||||
log::trace!("Getting registered names");
|
||||
self.get_json(&[routes::API_VERSION, routes::REGISTERED_NAMES], NO_PARAMS)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
||||
|
||||
@@ -40,3 +40,4 @@ pub const STAKE_SATURATION: &str = "stake-saturation";
|
||||
pub const INCLUSION_CHANCE: &str = "inclusion-probability";
|
||||
|
||||
pub const SERVICE_PROVIDERS: &str = "services";
|
||||
pub const REGISTERED_NAMES: &str = "names";
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::collect_paged;
|
||||
use crate::nyxd::contract_traits::NymContractsProvider;
|
||||
use crate::nyxd::error::NyxdError;
|
||||
use crate::nyxd::CosmWasmClient;
|
||||
use async_trait::async_trait;
|
||||
use nym_ephemera_common::msg::QueryMsg as EphemeraQueryMsg;
|
||||
use nym_ephemera_common::peers::PagedPeerResponse;
|
||||
use nym_ephemera_common::types::JsonPeerInfo;
|
||||
use serde::Deserialize;
|
||||
|
||||
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
||||
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
|
||||
pub trait EphemeraQueryClient {
|
||||
async fn query_ephemera_contract<T>(&self, query: EphemeraQueryMsg) -> Result<T, NyxdError>
|
||||
where
|
||||
for<'a> T: Deserialize<'a>;
|
||||
|
||||
async fn get_peers_paged(
|
||||
&self,
|
||||
start_after: Option<String>,
|
||||
limit: Option<u32>,
|
||||
) -> Result<PagedPeerResponse, NyxdError> {
|
||||
let request = EphemeraQueryMsg::GetPeers { start_after, limit };
|
||||
self.query_ephemera_contract(request).await
|
||||
}
|
||||
}
|
||||
|
||||
// extension trait to the query client to deal with the paged queries
|
||||
// (it didn't feel appropriate to combine it with the existing trait
|
||||
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
||||
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
|
||||
pub trait PagedEphemeraQueryClient: EphemeraQueryClient {
|
||||
async fn get_all_ephemera_peers(&self) -> Result<Vec<JsonPeerInfo>, NyxdError> {
|
||||
collect_paged!(self, get_peers_paged, peers)
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<T> PagedEphemeraQueryClient for T where T: EphemeraQueryClient {}
|
||||
|
||||
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
||||
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
|
||||
impl<C> EphemeraQueryClient for C
|
||||
where
|
||||
C: CosmWasmClient + NymContractsProvider + Send + Sync,
|
||||
{
|
||||
async fn query_ephemera_contract<T>(&self, query: EphemeraQueryMsg) -> Result<T, NyxdError>
|
||||
where
|
||||
for<'a> T: Deserialize<'a>,
|
||||
{
|
||||
let ephemera_contract_address = &self
|
||||
.ephemera_contract_address()
|
||||
.ok_or_else(|| NyxdError::unavailable_contract_address("ephemera contract"))?;
|
||||
self.query_contract_smart(ephemera_contract_address, &query)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::nyxd::contract_traits::tests::IgnoreValue;
|
||||
|
||||
// it's enough that this compiles and clippy is happy about it
|
||||
#[allow(dead_code)]
|
||||
fn all_query_variants_are_covered<C: EphemeraQueryClient + Send + Sync>(
|
||||
client: C,
|
||||
msg: EphemeraQueryMsg,
|
||||
) {
|
||||
match msg {
|
||||
EphemeraQueryMsg::GetPeers { limit, start_after } => {
|
||||
client.get_peers_paged(start_after, limit).ignore()
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
+86
@@ -0,0 +1,86 @@
|
||||
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::nyxd::contract_traits::NymContractsProvider;
|
||||
use crate::nyxd::cosmwasm_client::types::ExecuteResult;
|
||||
use crate::nyxd::error::NyxdError;
|
||||
use crate::nyxd::{Coin, Fee, SigningCosmWasmClient};
|
||||
use crate::signing::signer::OfflineSigner;
|
||||
use async_trait::async_trait;
|
||||
use nym_ephemera_common::msg::ExecuteMsg as EphemeraExecuteMsg;
|
||||
use nym_ephemera_common::types::JsonPeerInfo;
|
||||
|
||||
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
||||
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
|
||||
pub trait EphemeraSigningClient {
|
||||
async fn execute_ephemera_contract(
|
||||
&self,
|
||||
fee: Option<Fee>,
|
||||
msg: EphemeraExecuteMsg,
|
||||
memo: String,
|
||||
funds: Vec<Coin>,
|
||||
) -> Result<ExecuteResult, NyxdError>;
|
||||
|
||||
async fn register_as_peer(
|
||||
&self,
|
||||
peer_info: JsonPeerInfo,
|
||||
fee: Option<Fee>,
|
||||
) -> Result<ExecuteResult, NyxdError> {
|
||||
let req = EphemeraExecuteMsg::RegisterPeer { peer_info };
|
||||
|
||||
self.execute_ephemera_contract(fee, req, "registering as peer".to_string(), vec![])
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
||||
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
|
||||
impl<C> EphemeraSigningClient for C
|
||||
where
|
||||
C: SigningCosmWasmClient + NymContractsProvider + Sync,
|
||||
NyxdError: From<<Self as OfflineSigner>::Error>,
|
||||
{
|
||||
async fn execute_ephemera_contract(
|
||||
&self,
|
||||
fee: Option<Fee>,
|
||||
msg: EphemeraExecuteMsg,
|
||||
memo: String,
|
||||
funds: Vec<Coin>,
|
||||
) -> Result<ExecuteResult, NyxdError> {
|
||||
let ephemera_contract_address = self
|
||||
.ephemera_contract_address()
|
||||
.ok_or_else(|| NyxdError::unavailable_contract_address("ephemera contract"))?;
|
||||
|
||||
let fee = fee.unwrap_or(Fee::Auto(Some(self.simulated_gas_multiplier())));
|
||||
let signer_address = &self.signer_addresses()?[0];
|
||||
|
||||
self.execute(
|
||||
signer_address,
|
||||
ephemera_contract_address,
|
||||
&msg,
|
||||
fee,
|
||||
memo,
|
||||
funds,
|
||||
)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::nyxd::contract_traits::tests::IgnoreValue;
|
||||
|
||||
// it's enough that this compiles and clippy is happy about it
|
||||
#[allow(dead_code)]
|
||||
fn all_execute_variants_are_covered<C: EphemeraSigningClient + Send + Sync>(
|
||||
client: C,
|
||||
msg: EphemeraExecuteMsg,
|
||||
) {
|
||||
match msg {
|
||||
EphemeraExecuteMsg::RegisterPeer { peer_info } => {
|
||||
client.register_as_peer(peer_info, None).ignore()
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -10,17 +10,23 @@ use std::str::FromStr;
|
||||
// query clients
|
||||
pub mod coconut_bandwidth_query_client;
|
||||
pub mod dkg_query_client;
|
||||
pub mod ephemera_query_client;
|
||||
pub mod group_query_client;
|
||||
pub mod mixnet_query_client;
|
||||
pub mod multisig_query_client;
|
||||
pub mod name_service_query_client;
|
||||
pub mod sp_directory_query_client;
|
||||
pub mod vesting_query_client;
|
||||
|
||||
// signing clients
|
||||
pub mod coconut_bandwidth_signing_client;
|
||||
pub mod dkg_signing_client;
|
||||
pub mod ephemera_signing_client;
|
||||
pub mod group_signing_client;
|
||||
pub mod mixnet_signing_client;
|
||||
pub mod multisig_signing_client;
|
||||
pub mod name_service_signing_client;
|
||||
pub mod sp_directory_signing_client;
|
||||
pub mod vesting_signing_client;
|
||||
|
||||
// re-export query traits
|
||||
@@ -28,17 +34,23 @@ pub use coconut_bandwidth_query_client::{
|
||||
CoconutBandwidthQueryClient, PagedCoconutBandwidthQueryClient,
|
||||
};
|
||||
pub use dkg_query_client::{DkgQueryClient, PagedDkgQueryClient};
|
||||
pub use ephemera_query_client::{EphemeraQueryClient, PagedEphemeraQueryClient};
|
||||
pub use group_query_client::{GroupQueryClient, PagedGroupQueryClient};
|
||||
pub use mixnet_query_client::{MixnetQueryClient, PagedMixnetQueryClient};
|
||||
pub use multisig_query_client::{MultisigQueryClient, PagedMultisigQueryClient};
|
||||
pub use name_service_query_client::{NameServiceQueryClient, PagedNameServiceQueryClient};
|
||||
pub use sp_directory_query_client::{PagedSpDirectoryQueryClient, SpDirectoryQueryClient};
|
||||
pub use vesting_query_client::{PagedVestingQueryClient, VestingQueryClient};
|
||||
|
||||
// re-export signing traits
|
||||
pub use coconut_bandwidth_signing_client::CoconutBandwidthSigningClient;
|
||||
pub use dkg_signing_client::DkgSigningClient;
|
||||
pub use ephemera_signing_client::EphemeraSigningClient;
|
||||
pub use group_signing_client::GroupSigningClient;
|
||||
pub use mixnet_signing_client::MixnetSigningClient;
|
||||
pub use multisig_signing_client::MultisigSigningClient;
|
||||
pub use name_service_signing_client::NameServiceSigningClient;
|
||||
pub use sp_directory_signing_client::SpDirectorySigningClient;
|
||||
pub use vesting_signing_client::VestingSigningClient;
|
||||
|
||||
// helper for providing blanket implementation for query clients
|
||||
@@ -52,6 +64,13 @@ pub trait NymContractsProvider {
|
||||
fn dkg_contract_address(&self) -> Option<&AccountId>;
|
||||
fn group_contract_address(&self) -> Option<&AccountId>;
|
||||
fn multisig_contract_address(&self) -> Option<&AccountId>;
|
||||
|
||||
// ephemera-related
|
||||
fn ephemera_contract_address(&self) -> Option<&AccountId>;
|
||||
|
||||
// SPs
|
||||
fn name_service_contract_address(&self) -> Option<&AccountId>;
|
||||
fn service_provider_contract_address(&self) -> Option<&AccountId>;
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
@@ -63,6 +82,11 @@ pub struct TypedNymContracts {
|
||||
pub group_contract_address: Option<AccountId>,
|
||||
pub multisig_contract_address: Option<AccountId>,
|
||||
pub coconut_dkg_contract_address: Option<AccountId>,
|
||||
|
||||
pub ephemera_contract_address: Option<AccountId>,
|
||||
|
||||
pub service_provider_directory_contract_address: Option<AccountId>,
|
||||
pub name_service_contract_address: Option<AccountId>,
|
||||
}
|
||||
|
||||
impl TryFrom<NymContracts> for TypedNymContracts {
|
||||
@@ -94,6 +118,18 @@ impl TryFrom<NymContracts> for TypedNymContracts {
|
||||
.coconut_dkg_contract_address
|
||||
.map(|addr| addr.parse())
|
||||
.transpose()?,
|
||||
ephemera_contract_address: value
|
||||
.ephemera_contract_address
|
||||
.map(|addr| addr.parse())
|
||||
.transpose()?,
|
||||
service_provider_directory_contract_address: value
|
||||
.service_provider_directory_contract_address
|
||||
.map(|addr| addr.parse())
|
||||
.transpose()?,
|
||||
name_service_contract_address: value
|
||||
.name_service_contract_address
|
||||
.map(|addr| addr.parse())
|
||||
.transpose()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
+144
@@ -0,0 +1,144 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::collect_paged;
|
||||
use crate::nyxd::contract_traits::NymContractsProvider;
|
||||
use crate::nyxd::{error::NyxdError, CosmWasmClient};
|
||||
use async_trait::async_trait;
|
||||
use cosmrs::AccountId;
|
||||
use nym_contracts_common::{signing::Nonce, ContractBuildInformation};
|
||||
use nym_name_service_common::{
|
||||
msg::QueryMsg as NameQueryMsg,
|
||||
response::{ConfigResponse, NamesListResponse, PagedNamesListResponse},
|
||||
Address, NameId, NymName, RegisteredName,
|
||||
};
|
||||
use serde::Deserialize;
|
||||
|
||||
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
||||
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
|
||||
pub trait NameServiceQueryClient {
|
||||
async fn query_name_service_contract<T>(&self, query: NameQueryMsg) -> Result<T, NyxdError>
|
||||
where
|
||||
for<'a> T: Deserialize<'a>;
|
||||
|
||||
async fn get_name_service_config(&self) -> Result<ConfigResponse, NyxdError> {
|
||||
self.query_name_service_contract(NameQueryMsg::Config {})
|
||||
.await
|
||||
}
|
||||
|
||||
async fn get_name_entry(&self, name_id: NameId) -> Result<RegisteredName, NyxdError> {
|
||||
self.query_name_service_contract(NameQueryMsg::NameId { name_id })
|
||||
.await
|
||||
}
|
||||
|
||||
async fn get_names_paged(
|
||||
&self,
|
||||
start_after: Option<NameId>,
|
||||
limit: Option<u32>,
|
||||
) -> Result<PagedNamesListResponse, NyxdError> {
|
||||
self.query_name_service_contract(NameQueryMsg::All { limit, start_after })
|
||||
.await
|
||||
}
|
||||
|
||||
async fn get_name_signing_nonce(&self, address: &AccountId) -> Result<Nonce, NyxdError> {
|
||||
self.query_name_service_contract(NameQueryMsg::SigningNonce {
|
||||
address: address.to_string(),
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
async fn get_names_by_owner(&self, owner: AccountId) -> Result<NamesListResponse, NyxdError> {
|
||||
self.query_name_service_contract(NameQueryMsg::ByOwner {
|
||||
owner: owner.to_string(),
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
async fn get_names_by_nym_name(&self, name: NymName) -> Result<NamesListResponse, NyxdError> {
|
||||
self.query_name_service_contract(NameQueryMsg::ByName { name })
|
||||
.await
|
||||
}
|
||||
|
||||
async fn get_names_by_address(&self, address: Address) -> Result<NamesListResponse, NyxdError> {
|
||||
self.query_name_service_contract(NameQueryMsg::ByAddress { address })
|
||||
.await
|
||||
}
|
||||
|
||||
async fn get_name_service_contract_version(
|
||||
&self,
|
||||
) -> Result<ContractBuildInformation, NyxdError> {
|
||||
self.query_name_service_contract(NameQueryMsg::GetContractVersion {})
|
||||
.await
|
||||
}
|
||||
|
||||
async fn get_name_service_contract_cw2_version(
|
||||
&self,
|
||||
) -> Result<cw2::ContractVersion, NyxdError> {
|
||||
self.query_name_service_contract(NameQueryMsg::GetCW2ContractVersion {})
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
||||
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
|
||||
pub trait PagedNameServiceQueryClient: NameServiceQueryClient {
|
||||
async fn get_all_names(&self) -> Result<Vec<RegisteredName>, NyxdError> {
|
||||
collect_paged!(self, get_names_paged, names)
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<T> PagedNameServiceQueryClient for T where T: NameServiceQueryClient {}
|
||||
|
||||
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
||||
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
|
||||
impl<C> NameServiceQueryClient for C
|
||||
where
|
||||
C: CosmWasmClient + NymContractsProvider + Send + Sync,
|
||||
{
|
||||
async fn query_name_service_contract<T>(&self, query: NameQueryMsg) -> Result<T, NyxdError>
|
||||
where
|
||||
for<'a> T: Deserialize<'a>,
|
||||
{
|
||||
let name_service_contract_address = &self
|
||||
.name_service_contract_address()
|
||||
.ok_or_else(|| NyxdError::unavailable_contract_address("name service contract"))?;
|
||||
self.query_contract_smart(name_service_contract_address, &query)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::nyxd::contract_traits::tests::IgnoreValue;
|
||||
|
||||
// it's enough that this compiles and clippy is happy about it
|
||||
#[allow(dead_code)]
|
||||
fn all_query_variants_are_covered<C: NameServiceQueryClient + Send + Sync>(
|
||||
client: C,
|
||||
msg: NameQueryMsg,
|
||||
) {
|
||||
match msg {
|
||||
NameQueryMsg::NameId { name_id } => client.get_name_entry(name_id).ignore(),
|
||||
NameQueryMsg::ByOwner { owner } => {
|
||||
client.get_names_by_owner(owner.parse().unwrap()).ignore()
|
||||
}
|
||||
NameQueryMsg::ByName { name } => client.get_names_by_nym_name(name).ignore(),
|
||||
NameQueryMsg::ByAddress { address } => client.get_names_by_address(address).ignore(),
|
||||
NameQueryMsg::All { limit, start_after } => {
|
||||
client.get_names_paged(limit, start_after).ignore()
|
||||
}
|
||||
NameQueryMsg::SigningNonce { address } => client
|
||||
.get_name_signing_nonce(&address.parse().unwrap())
|
||||
.ignore(),
|
||||
NameQueryMsg::Config {} => client.get_name_service_config().ignore(),
|
||||
NameQueryMsg::GetContractVersion {} => {
|
||||
client.get_name_service_contract_version().ignore()
|
||||
}
|
||||
NameQueryMsg::GetCW2ContractVersion {} => {
|
||||
client.get_name_service_contract_cw2_version().ignore()
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
+138
@@ -0,0 +1,138 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use async_trait::async_trait;
|
||||
use nym_contracts_common::signing::MessageSignature;
|
||||
use nym_name_service_common::{msg::ExecuteMsg as NameExecuteMsg, NameDetails, NameId, NymName};
|
||||
|
||||
use crate::nyxd::contract_traits::NymContractsProvider;
|
||||
use crate::nyxd::{
|
||||
coin::Coin, cosmwasm_client::types::ExecuteResult, error::NyxdError, Fee, SigningCosmWasmClient,
|
||||
};
|
||||
use crate::signing::signer::OfflineSigner;
|
||||
|
||||
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
||||
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
|
||||
pub trait NameServiceSigningClient {
|
||||
async fn execute_name_service_contract(
|
||||
&self,
|
||||
fee: Option<Fee>,
|
||||
msg: NameExecuteMsg,
|
||||
funds: Vec<Coin>,
|
||||
) -> Result<ExecuteResult, NyxdError>;
|
||||
|
||||
async fn register_name(
|
||||
&self,
|
||||
name: NameDetails,
|
||||
owner_signature: MessageSignature,
|
||||
deposit: Coin,
|
||||
fee: Option<Fee>,
|
||||
) -> Result<ExecuteResult, NyxdError> {
|
||||
self.execute_name_service_contract(
|
||||
fee,
|
||||
NameExecuteMsg::Register {
|
||||
name,
|
||||
owner_signature,
|
||||
},
|
||||
vec![deposit],
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn delete_name_by_id(
|
||||
&self,
|
||||
name_id: NameId,
|
||||
fee: Option<Fee>,
|
||||
) -> Result<ExecuteResult, NyxdError> {
|
||||
self.execute_name_service_contract(fee, NameExecuteMsg::DeleteId { name_id }, vec![])
|
||||
.await
|
||||
}
|
||||
|
||||
async fn delete_service_provider_by_name(
|
||||
&self,
|
||||
name: NymName,
|
||||
fee: Option<Fee>,
|
||||
) -> Result<ExecuteResult, NyxdError> {
|
||||
self.execute_name_service_contract(fee, NameExecuteMsg::DeleteName { name }, vec![])
|
||||
.await
|
||||
}
|
||||
|
||||
async fn update_deposit_required(
|
||||
&self,
|
||||
deposit_required: Coin,
|
||||
fee: Option<Fee>,
|
||||
) -> Result<ExecuteResult, NyxdError> {
|
||||
self.execute_name_service_contract(
|
||||
fee,
|
||||
NameExecuteMsg::UpdateDepositRequired {
|
||||
deposit_required: deposit_required.into(),
|
||||
},
|
||||
vec![],
|
||||
)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
||||
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
|
||||
impl<C> NameServiceSigningClient for C
|
||||
where
|
||||
C: SigningCosmWasmClient + NymContractsProvider + Sync,
|
||||
NyxdError: From<<Self as OfflineSigner>::Error>,
|
||||
{
|
||||
async fn execute_name_service_contract(
|
||||
&self,
|
||||
fee: Option<Fee>,
|
||||
msg: NameExecuteMsg,
|
||||
funds: Vec<Coin>,
|
||||
) -> Result<ExecuteResult, NyxdError> {
|
||||
let name_service_contract_address = &self
|
||||
.name_service_contract_address()
|
||||
.ok_or_else(|| NyxdError::unavailable_contract_address("name service contract"))?;
|
||||
|
||||
let fee = fee.unwrap_or(Fee::Auto(Some(self.simulated_gas_multiplier())));
|
||||
let memo = msg.default_memo();
|
||||
|
||||
let signer_address = &self.signer_addresses()?[0];
|
||||
self.execute(
|
||||
signer_address,
|
||||
name_service_contract_address,
|
||||
&msg,
|
||||
fee,
|
||||
memo,
|
||||
funds,
|
||||
)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::nyxd::contract_traits::tests::{mock_coin, IgnoreValue};
|
||||
|
||||
// it's enough that this compiles and clippy is happy about it
|
||||
#[allow(dead_code)]
|
||||
fn all_execute_variants_are_covered<C: NameServiceSigningClient + Send + Sync>(
|
||||
client: C,
|
||||
msg: NameExecuteMsg,
|
||||
) {
|
||||
match msg {
|
||||
NameExecuteMsg::Register {
|
||||
name,
|
||||
owner_signature,
|
||||
} => client
|
||||
.register_name(name, owner_signature, mock_coin(), None)
|
||||
.ignore(),
|
||||
NameExecuteMsg::DeleteId { name_id } => {
|
||||
client.delete_name_by_id(name_id, None).ignore()
|
||||
}
|
||||
NameExecuteMsg::DeleteName { name } => {
|
||||
client.delete_service_provider_by_name(name, None).ignore()
|
||||
}
|
||||
NameExecuteMsg::UpdateDepositRequired { deposit_required } => client
|
||||
.update_deposit_required(deposit_required.into(), None)
|
||||
.ignore(),
|
||||
};
|
||||
}
|
||||
}
|
||||
+142
@@ -0,0 +1,142 @@
|
||||
use crate::collect_paged;
|
||||
use async_trait::async_trait;
|
||||
use cosmrs::AccountId;
|
||||
use nym_contracts_common::{signing::Nonce, ContractBuildInformation};
|
||||
use nym_service_provider_directory_common::{
|
||||
msg::QueryMsg as SpQueryMsg,
|
||||
response::{
|
||||
ConfigResponse, PagedServicesListResponse, ServiceInfoResponse, ServicesListResponse,
|
||||
},
|
||||
NymAddress, Service, ServiceId,
|
||||
};
|
||||
use serde::Deserialize;
|
||||
|
||||
use crate::nyxd::contract_traits::NymContractsProvider;
|
||||
use crate::nyxd::{error::NyxdError, CosmWasmClient};
|
||||
|
||||
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
||||
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
|
||||
pub trait SpDirectoryQueryClient {
|
||||
async fn query_service_provider_contract<T>(&self, query: SpQueryMsg) -> Result<T, NyxdError>
|
||||
where
|
||||
for<'a> T: Deserialize<'a>;
|
||||
|
||||
async fn get_service_config(&self) -> Result<ConfigResponse, NyxdError> {
|
||||
self.query_service_provider_contract(SpQueryMsg::Config {})
|
||||
.await
|
||||
}
|
||||
|
||||
async fn get_service_info(
|
||||
&self,
|
||||
service_id: ServiceId,
|
||||
) -> Result<ServiceInfoResponse, NyxdError> {
|
||||
self.query_service_provider_contract(SpQueryMsg::ServiceId { service_id })
|
||||
.await
|
||||
}
|
||||
|
||||
async fn get_services_paged(
|
||||
&self,
|
||||
start_after: Option<ServiceId>,
|
||||
limit: Option<u32>,
|
||||
) -> Result<PagedServicesListResponse, NyxdError> {
|
||||
self.query_service_provider_contract(SpQueryMsg::All { limit, start_after })
|
||||
.await
|
||||
}
|
||||
|
||||
async fn get_services_by_announcer(
|
||||
&self,
|
||||
announcer: AccountId,
|
||||
) -> Result<ServicesListResponse, NyxdError> {
|
||||
self.query_service_provider_contract(SpQueryMsg::ByAnnouncer {
|
||||
announcer: announcer.to_string(),
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
async fn get_services_by_nym_address(
|
||||
&self,
|
||||
nym_address: NymAddress,
|
||||
) -> Result<ServicesListResponse, NyxdError> {
|
||||
self.query_service_provider_contract(SpQueryMsg::ByNymAddress { nym_address })
|
||||
.await
|
||||
}
|
||||
|
||||
async fn get_sp_contract_version(&self) -> Result<ContractBuildInformation, NyxdError> {
|
||||
self.query_service_provider_contract(SpQueryMsg::GetContractVersion {})
|
||||
.await
|
||||
}
|
||||
|
||||
async fn get_sp_contract_cw2_version(&self) -> Result<cw2::ContractVersion, NyxdError> {
|
||||
self.query_service_provider_contract(SpQueryMsg::GetCW2ContractVersion {})
|
||||
.await
|
||||
}
|
||||
|
||||
async fn get_service_signing_nonce(&self, address: &AccountId) -> Result<Nonce, NyxdError> {
|
||||
self.query_service_provider_contract(SpQueryMsg::SigningNonce {
|
||||
address: address.to_string(),
|
||||
})
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
||||
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
|
||||
pub trait PagedSpDirectoryQueryClient: SpDirectoryQueryClient {
|
||||
async fn get_all_services(&self) -> Result<Vec<Service>, NyxdError> {
|
||||
collect_paged!(self, get_services_paged, services)
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<T> PagedSpDirectoryQueryClient for T where T: SpDirectoryQueryClient {}
|
||||
|
||||
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
||||
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
|
||||
impl<C> SpDirectoryQueryClient for C
|
||||
where
|
||||
C: CosmWasmClient + NymContractsProvider + Send + Sync,
|
||||
{
|
||||
async fn query_service_provider_contract<T>(&self, query: SpQueryMsg) -> Result<T, NyxdError>
|
||||
where
|
||||
for<'a> T: Deserialize<'a>,
|
||||
{
|
||||
let sp_directory_contract_address =
|
||||
&self.service_provider_contract_address().ok_or_else(|| {
|
||||
NyxdError::unavailable_contract_address("service provider directory contract")
|
||||
})?;
|
||||
self.query_contract_smart(sp_directory_contract_address, &query)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::nyxd::contract_traits::tests::IgnoreValue;
|
||||
|
||||
// it's enough that this compiles and clippy is happy about it
|
||||
#[allow(dead_code)]
|
||||
fn all_query_variants_are_covered<C: SpDirectoryQueryClient + Send + Sync>(
|
||||
client: C,
|
||||
msg: SpQueryMsg,
|
||||
) {
|
||||
match msg {
|
||||
SpQueryMsg::ServiceId { service_id } => client.get_service_info(service_id).ignore(),
|
||||
SpQueryMsg::ByAnnouncer { announcer } => client
|
||||
.get_services_by_announcer(announcer.parse().unwrap())
|
||||
.ignore(),
|
||||
SpQueryMsg::ByNymAddress { nym_address } => {
|
||||
client.get_services_by_nym_address(nym_address).ignore()
|
||||
}
|
||||
SpQueryMsg::All { limit, start_after } => {
|
||||
client.get_services_paged(start_after, limit).ignore()
|
||||
}
|
||||
SpQueryMsg::SigningNonce { address } => client
|
||||
.get_service_signing_nonce(&address.parse().unwrap())
|
||||
.ignore(),
|
||||
SpQueryMsg::Config {} => client.get_service_config().ignore(),
|
||||
SpQueryMsg::GetContractVersion {} => client.get_sp_contract_version().ignore(),
|
||||
SpQueryMsg::GetCW2ContractVersion {} => client.get_sp_contract_cw2_version().ignore(),
|
||||
};
|
||||
}
|
||||
}
|
||||
+148
@@ -0,0 +1,148 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::nyxd::contract_traits::NymContractsProvider;
|
||||
use crate::nyxd::{
|
||||
coin::Coin, cosmwasm_client::types::ExecuteResult, error::NyxdError, Fee, SigningCosmWasmClient,
|
||||
};
|
||||
use crate::signing::signer::OfflineSigner;
|
||||
use async_trait::async_trait;
|
||||
use nym_contracts_common::signing::MessageSignature;
|
||||
use nym_service_provider_directory_common::{
|
||||
msg::ExecuteMsg as SpExecuteMsg, NymAddress, ServiceDetails, ServiceId,
|
||||
};
|
||||
|
||||
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
||||
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
|
||||
pub trait SpDirectorySigningClient {
|
||||
async fn execute_service_provider_directory_contract(
|
||||
&self,
|
||||
fee: Option<Fee>,
|
||||
msg: SpExecuteMsg,
|
||||
funds: Vec<Coin>,
|
||||
) -> Result<ExecuteResult, NyxdError>;
|
||||
|
||||
async fn announce_service_provider(
|
||||
&self,
|
||||
service: ServiceDetails,
|
||||
owner_signature: MessageSignature,
|
||||
deposit: Coin,
|
||||
fee: Option<Fee>,
|
||||
) -> Result<ExecuteResult, NyxdError> {
|
||||
self.execute_service_provider_directory_contract(
|
||||
fee,
|
||||
SpExecuteMsg::Announce {
|
||||
service,
|
||||
owner_signature,
|
||||
},
|
||||
vec![deposit],
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn delete_service_provider_by_id(
|
||||
&self,
|
||||
service_id: ServiceId,
|
||||
fee: Option<Fee>,
|
||||
) -> Result<ExecuteResult, NyxdError> {
|
||||
self.execute_service_provider_directory_contract(
|
||||
fee,
|
||||
SpExecuteMsg::DeleteId { service_id },
|
||||
vec![],
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn delete_service_provider_by_nym_address(
|
||||
&self,
|
||||
nym_address: NymAddress,
|
||||
fee: Option<Fee>,
|
||||
) -> Result<ExecuteResult, NyxdError> {
|
||||
self.execute_service_provider_directory_contract(
|
||||
fee,
|
||||
SpExecuteMsg::DeleteNymAddress { nym_address },
|
||||
vec![],
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn update_deposit_required(
|
||||
&self,
|
||||
deposit_required: Coin,
|
||||
fee: Option<Fee>,
|
||||
) -> Result<ExecuteResult, NyxdError> {
|
||||
self.execute_service_provider_directory_contract(
|
||||
fee,
|
||||
SpExecuteMsg::UpdateDepositRequired {
|
||||
deposit_required: deposit_required.into(),
|
||||
},
|
||||
vec![],
|
||||
)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
||||
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
|
||||
impl<C> SpDirectorySigningClient for C
|
||||
where
|
||||
C: SigningCosmWasmClient + NymContractsProvider + Sync,
|
||||
NyxdError: From<<Self as OfflineSigner>::Error>,
|
||||
{
|
||||
async fn execute_service_provider_directory_contract(
|
||||
&self,
|
||||
fee: Option<Fee>,
|
||||
msg: SpExecuteMsg,
|
||||
funds: Vec<Coin>,
|
||||
) -> Result<ExecuteResult, NyxdError> {
|
||||
let sp_directory_contract_address =
|
||||
&self.service_provider_contract_address().ok_or_else(|| {
|
||||
NyxdError::unavailable_contract_address("service provider directory contract")
|
||||
})?;
|
||||
|
||||
let fee = fee.unwrap_or(Fee::Auto(Some(self.simulated_gas_multiplier())));
|
||||
let memo = msg.default_memo();
|
||||
|
||||
let signer_address = &self.signer_addresses()?[0];
|
||||
self.execute(
|
||||
signer_address,
|
||||
sp_directory_contract_address,
|
||||
&msg,
|
||||
fee,
|
||||
memo,
|
||||
funds,
|
||||
)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::nyxd::contract_traits::tests::{mock_coin, IgnoreValue};
|
||||
|
||||
// it's enough that this compiles and clippy is happy about it
|
||||
#[allow(dead_code)]
|
||||
fn all_execute_variants_are_covered<C: SpDirectorySigningClient + Send + Sync>(
|
||||
client: C,
|
||||
msg: SpExecuteMsg,
|
||||
) {
|
||||
match msg {
|
||||
SpExecuteMsg::Announce {
|
||||
service,
|
||||
owner_signature,
|
||||
} => client
|
||||
.announce_service_provider(service, owner_signature, mock_coin(), None)
|
||||
.ignore(),
|
||||
SpExecuteMsg::DeleteId { service_id } => client
|
||||
.delete_service_provider_by_id(service_id, None)
|
||||
.ignore(),
|
||||
SpExecuteMsg::DeleteNymAddress { nym_address } => client
|
||||
.delete_service_provider_by_nym_address(nym_address, None)
|
||||
.ignore(),
|
||||
SpExecuteMsg::UpdateDepositRequired { deposit_required } => client
|
||||
.update_deposit_required(deposit_required.into(), None)
|
||||
.ignore(),
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -140,6 +140,6 @@ mod tests {
|
||||
|
||||
let fee = &gas_price * gas_limit;
|
||||
// the failing behaviour was result value of 3937
|
||||
assert_eq!(fee.amount, 3938u128);
|
||||
assert_eq!(fee.amount, 3938u64.into());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,8 +70,6 @@ use crate::http_client;
|
||||
use crate::{DirectSigningHttpRpcNyxdClient, QueryHttpRpcNyxdClient};
|
||||
#[cfg(feature = "http-client")]
|
||||
use cosmrs::rpc::{HttpClient, HttpClientUrl};
|
||||
use nym_contracts_common::build_information::CONTRACT_BUILD_INFO_STORAGE_KEY;
|
||||
use nym_contracts_common::ContractBuildInformation;
|
||||
|
||||
pub mod coin;
|
||||
pub mod contract_traits;
|
||||
@@ -248,6 +246,12 @@ impl<C, S> NyxdClient<C, S> {
|
||||
self.config.contracts.multisig_contract_address = Some(address);
|
||||
}
|
||||
|
||||
pub fn set_service_provider_contract_address(&mut self, address: AccountId) {
|
||||
self.config
|
||||
.contracts
|
||||
.service_provider_directory_contract_address = Some(address);
|
||||
}
|
||||
|
||||
pub fn set_simulated_gas_multiplier(&mut self, multiplier: f32) {
|
||||
self.config.simulated_gas_multiplier = multiplier;
|
||||
}
|
||||
@@ -280,6 +284,21 @@ impl<C, S> NymContractsProvider for NyxdClient<C, S> {
|
||||
fn multisig_contract_address(&self) -> Option<&AccountId> {
|
||||
self.config.contracts.multisig_contract_address.as_ref()
|
||||
}
|
||||
|
||||
fn ephemera_contract_address(&self) -> Option<&AccountId> {
|
||||
self.config.contracts.ephemera_contract_address.as_ref()
|
||||
}
|
||||
|
||||
fn name_service_contract_address(&self) -> Option<&AccountId> {
|
||||
self.config.contracts.name_service_contract_address.as_ref()
|
||||
}
|
||||
|
||||
fn service_provider_contract_address(&self) -> Option<&AccountId> {
|
||||
self.config
|
||||
.contracts
|
||||
.service_provider_directory_contract_address
|
||||
.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
// queries
|
||||
@@ -330,33 +349,6 @@ where
|
||||
.await
|
||||
.map(|block| block.block_id.hash)
|
||||
}
|
||||
|
||||
pub async fn try_get_cw2_contract_version(
|
||||
&self,
|
||||
contract_address: &AccountId,
|
||||
) -> Option<cw2::ContractVersion> {
|
||||
let raw_info = self
|
||||
.query_contract_raw(contract_address, b"contract_info".to_vec())
|
||||
.await
|
||||
.ok()?;
|
||||
|
||||
serde_json::from_slice(&raw_info).ok()
|
||||
}
|
||||
|
||||
pub async fn try_get_contract_build_information(
|
||||
&self,
|
||||
contract_address: &AccountId,
|
||||
) -> Option<ContractBuildInformation> {
|
||||
let raw_info = self
|
||||
.query_contract_raw(
|
||||
contract_address,
|
||||
CONTRACT_BUILD_INFO_STORAGE_KEY.as_bytes().to_vec(),
|
||||
)
|
||||
.await
|
||||
.ok()?;
|
||||
|
||||
serde_json::from_slice(&raw_info).ok()
|
||||
}
|
||||
}
|
||||
|
||||
// signing
|
||||
|
||||
@@ -10,26 +10,26 @@ anyhow = { workspace = true }
|
||||
base64 = "0.13.0"
|
||||
bip39 = { workspace = true }
|
||||
bs58 = { workspace = true }
|
||||
comfy-table = { workspace = true }
|
||||
cfg-if = { workspace = true }
|
||||
comfy-table = "6.0.0"
|
||||
cfg-if = "1.0.0"
|
||||
clap = { workspace = true, features = ["derive"] }
|
||||
csv = { workspace = true }
|
||||
csv = "1.3.0"
|
||||
cw-utils = { workspace = true }
|
||||
futures = { workspace = true }
|
||||
handlebars = { workspace = true }
|
||||
humantime-serde = { workspace = true }
|
||||
inquire = { workspace = true }
|
||||
handlebars = "3.0.1"
|
||||
humantime-serde = "1.0"
|
||||
inquire = "0.6.2"
|
||||
k256 = { workspace = true, features = ["ecdsa", "sha256"] }
|
||||
log = { workspace = true }
|
||||
rand = {version = "0.6", features = ["std"] }
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
time = { workspace = true, features = ["parsing", "formatting"] }
|
||||
tokio = { workspace = true, features = ["sync"]}
|
||||
toml = "0.5.6"
|
||||
url = { workspace = true }
|
||||
tap = { workspace = true }
|
||||
tap = "1"
|
||||
zeroize = { workspace = true }
|
||||
|
||||
cosmrs = { workspace = true }
|
||||
@@ -46,6 +46,8 @@ nym-vesting-contract-common = { path = "../cosmwasm-smart-contracts/vesting-cont
|
||||
nym-coconut-bandwidth-contract-common = { path = "../cosmwasm-smart-contracts/coconut-bandwidth-contract" }
|
||||
nym-coconut-dkg-common = { path = "../cosmwasm-smart-contracts/coconut-dkg" }
|
||||
nym-multisig-contract-common = { path = "../cosmwasm-smart-contracts/multisig-contract" }
|
||||
nym-service-provider-directory-common = { path = "../cosmwasm-smart-contracts/service-provider-directory" }
|
||||
nym-name-service-common = { path = "../cosmwasm-smart-contracts/name-service" }
|
||||
nym-sphinx = { path = "../../common/nymsphinx" }
|
||||
nym-client-core = { path = "../../common/client-core" }
|
||||
nym-config = { path = "../../common/config" }
|
||||
|
||||
@@ -148,10 +148,6 @@ pub async fn execute(args: Args, client: SigningClient) -> anyhow::Result<()> {
|
||||
bail!("the provided free pass request has too long expiry (expiry is set to on {expiration_date})")
|
||||
}
|
||||
|
||||
if expiration_date < now {
|
||||
bail!("the provided free pass expiry is set in the past!")
|
||||
}
|
||||
|
||||
// issuance start
|
||||
block_until_coconut_is_available(&client).await?;
|
||||
|
||||
|
||||
@@ -1,354 +0,0 @@
|
||||
// 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_validator_client::nyxd::contract_traits::{NymContractsProvider, PagedMixnetQueryClient};
|
||||
use nym_validator_client::nyxd::Coin;
|
||||
|
||||
use crate::context::SigningClient;
|
||||
use crate::utils::pretty_coin;
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct Args {
|
||||
#[clap(long)]
|
||||
pub memo: Option<String>,
|
||||
|
||||
#[clap(
|
||||
long,
|
||||
help = "Input csv files with delegation amounts. Format: (mixID, amount(in NYM))"
|
||||
)]
|
||||
pub input: String,
|
||||
|
||||
#[clap(
|
||||
long,
|
||||
help = "An output file path (CSV format) to create or append a log of results to"
|
||||
)]
|
||||
pub output: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct InputFileRow {
|
||||
pub mix_id: String,
|
||||
pub amount: Coin,
|
||||
}
|
||||
#[derive(Debug)]
|
||||
pub struct InputFileReader {
|
||||
pub rows: Vec<InputFileRow>,
|
||||
}
|
||||
|
||||
impl InputFileReader {
|
||||
pub fn new(path: &str) -> Result<InputFileReader, anyhow::Error> {
|
||||
let file_contents = fs::read_to_string(path)?;
|
||||
let mut rows = Vec::new();
|
||||
let mut mix_id_set = HashSet::new();
|
||||
|
||||
for line in file_contents
|
||||
.lines()
|
||||
.map(str::trim)
|
||||
.filter(|line| !line.is_empty())
|
||||
{
|
||||
let tokens: Vec<_> = line.split(',').collect();
|
||||
if tokens.len() != 2 {
|
||||
anyhow::bail!("Incorrect format: {}", line);
|
||||
}
|
||||
let mix_id = tokens[0].trim().to_string();
|
||||
let input_amount = tokens[1]
|
||||
.trim()
|
||||
.parse::<u128>()
|
||||
.map_err(|_| anyhow::anyhow!("'{}' has an invalid amount", line))?;
|
||||
|
||||
let micro_nym_amount = input_amount * 1_000_000;
|
||||
|
||||
if !mix_id_set.insert(mix_id.clone()) {
|
||||
anyhow::bail!("Duplicate mix_id found: {}", mix_id);
|
||||
}
|
||||
|
||||
rows.push(InputFileRow {
|
||||
mix_id,
|
||||
amount: Coin {
|
||||
amount: micro_nym_amount,
|
||||
denom: "unym".to_string(),
|
||||
},
|
||||
});
|
||||
}
|
||||
Ok(InputFileReader { rows })
|
||||
}
|
||||
}
|
||||
|
||||
fn write_to_csv(
|
||||
output_details: Vec<[String; 3]>,
|
||||
output_file: Option<String>,
|
||||
) -> Result<(), anyhow::Error> {
|
||||
if let Some(file_path) = output_file {
|
||||
// Determine if the file exists and is not empty
|
||||
let file_exists = fs::metadata(&file_path)
|
||||
.map(|metadata| metadata.len() > 0)
|
||||
.unwrap_or(false);
|
||||
|
||||
// Open the file for appending or creation
|
||||
let file = OpenOptions::new()
|
||||
.append(true)
|
||||
.create(true)
|
||||
.open(&file_path)?;
|
||||
|
||||
if !file_exists {
|
||||
let mut wtr = csv::Writer::from_writer(&file);
|
||||
wtr.write_record(["Operation", "Transaction Hash", "Timestamp"])?;
|
||||
wtr.flush()?;
|
||||
}
|
||||
|
||||
let mut wtr = WriterBuilder::new()
|
||||
.has_headers(!file_exists)
|
||||
.from_writer(file);
|
||||
|
||||
// Write the details to the CSV file
|
||||
for detail in output_details {
|
||||
wtr.write_record(&detail)?;
|
||||
}
|
||||
wtr.flush()?;
|
||||
info!("All operations saved to output file");
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn fetch_delegation_data(
|
||||
client: &SigningClient,
|
||||
) -> Result<HashMap<String, Coin>, anyhow::Error> {
|
||||
let address = client.address();
|
||||
// Fetch all delegations for the user
|
||||
let delegations = match client.get_all_delegator_delegations(&address).await {
|
||||
Ok(delegations) => delegations,
|
||||
Err(e) => {
|
||||
anyhow::bail!("Error fetching delegations: {}", e)
|
||||
}
|
||||
};
|
||||
|
||||
// Build a map to make it easier to handle delegation data
|
||||
let mut existing_delegation_map: HashMap<String, Coin> = HashMap::new();
|
||||
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));
|
||||
}
|
||||
|
||||
// Look for pending delegate / undelegate events which might be of interest to us
|
||||
let pending_events = match client.get_all_pending_epoch_events().await {
|
||||
Ok(events) => events,
|
||||
Err(e) => {
|
||||
anyhow::bail!("Error fetching pending epoch events: {}", e);
|
||||
}
|
||||
};
|
||||
|
||||
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, .. } => {
|
||||
if owner == address.as_ref()
|
||||
&& existing_delegation_map.contains_key(&mix_id.to_string())
|
||||
{
|
||||
existing_delegation_map.remove(&mix_id.to_string());
|
||||
}
|
||||
}
|
||||
|
||||
// If a pending delegation event is found, gather them to consolidate later
|
||||
Delegate {
|
||||
owner,
|
||||
mix_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()) {
|
||||
amount.amount += pending_record.amount;
|
||||
}
|
||||
pending_delegation_map.insert(mix_id.to_string(), amount);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
}
|
||||
|
||||
// Consolidate pending events into delegation map
|
||||
for (mix_id, amount) in pending_delegation_map {
|
||||
existing_delegation_map
|
||||
.entry(mix_id)
|
||||
.and_modify(|e| e.amount += amount.amount)
|
||||
.or_insert(amount);
|
||||
}
|
||||
|
||||
Ok(existing_delegation_map)
|
||||
}
|
||||
|
||||
pub async fn delegate_to_multiple_mixnodes(args: Args, client: SigningClient) {
|
||||
let records = match InputFileReader::new(&args.input) {
|
||||
Ok(records) => records,
|
||||
Err(e) => {
|
||||
println!("Error reading input file: {}", e);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
let existing_delegation_map = fetch_delegation_data(&client)
|
||||
.await
|
||||
.expect("Could not fetch existing delegations");
|
||||
|
||||
let mut delegation_table = Table::new();
|
||||
let mut undelegation_table = Table::new();
|
||||
let mut delegation_msgs: Vec<(ExecuteMsg, Vec<Coin>)> = Vec::new();
|
||||
let mut undelegation_msgs: Vec<(ExecuteMsg, Vec<Coin>)> = Vec::new();
|
||||
|
||||
delegation_table.set_header(["Mix ID", "Input Amount", "Adjusted Amount"]);
|
||||
undelegation_table.set_header(["Mix ID"]);
|
||||
|
||||
for row in &records.rows {
|
||||
let input_amount = row.amount.amount;
|
||||
let existing_delegation_amount = existing_delegation_map
|
||||
.get(&row.mix_id)
|
||||
.map_or(0, |coin| coin.amount);
|
||||
|
||||
match existing_delegation_amount.cmp(&input_amount) {
|
||||
Ordering::Equal => continue, // No action needed if amounts are equal
|
||||
|
||||
Ordering::Less => {
|
||||
// Delegate the difference if the existing delegation is less
|
||||
let difference = Coin {
|
||||
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()]));
|
||||
delegation_table.add_row(&[
|
||||
row.mix_id.clone(),
|
||||
pretty_coin(&row.amount),
|
||||
pretty_coin(&difference),
|
||||
]);
|
||||
}
|
||||
|
||||
Ordering::Greater => {
|
||||
let mix_id = row.mix_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()]);
|
||||
|
||||
if row.amount.amount > 0 {
|
||||
delegation_msgs.push((DelegateToMixnode { mix_id }, vec![row.amount.clone()]));
|
||||
delegation_table.add_row(&[
|
||||
row.mix_id.clone(),
|
||||
pretty_coin(&row.amount),
|
||||
pretty_coin(&row.amount),
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if delegation_msgs.is_empty() && undelegation_msgs.is_empty() {
|
||||
println!("Nothing to do. Delegations are up-to-date!");
|
||||
return;
|
||||
}
|
||||
|
||||
if !undelegation_msgs.is_empty() {
|
||||
println!("Undelegation records : \n{}\n\n", undelegation_table);
|
||||
}
|
||||
|
||||
if !delegation_msgs.is_empty() {
|
||||
println!("Delegation records : \n{}\n\n", delegation_table);
|
||||
}
|
||||
|
||||
let ans = inquire::Confirm::new("Do you want to continue with the shown operations?")
|
||||
.with_default(false)
|
||||
.with_help_message("You must confirm before the transactions are signed")
|
||||
.prompt();
|
||||
|
||||
if let Err(e) = ans {
|
||||
info!("Aborting, {}...", e);
|
||||
return;
|
||||
}
|
||||
|
||||
if let Ok(false) = ans {
|
||||
info!("Aborting:: User denied proceeding with signing!");
|
||||
return;
|
||||
}
|
||||
|
||||
let mut output_details: Vec<[String; 3]> = Vec::new();
|
||||
let now = time::OffsetDateTime::now_utc();
|
||||
let now = now
|
||||
.format(&time::format_description::well_known::Rfc3339)
|
||||
.unwrap();
|
||||
|
||||
let mixnet_contract = client
|
||||
.mixnet_contract_address()
|
||||
.expect("mixnet contract address is not available");
|
||||
|
||||
// Execute all undelegation transactions
|
||||
if !undelegation_msgs.is_empty() {
|
||||
let res = client
|
||||
.execute_multiple(
|
||||
mixnet_contract,
|
||||
undelegation_msgs.clone(),
|
||||
None,
|
||||
format!(
|
||||
"Undelegate from {} nodes via nym-cli",
|
||||
undelegation_msgs.len()
|
||||
),
|
||||
)
|
||||
.await
|
||||
.expect("Could not undelegate!");
|
||||
|
||||
println!(
|
||||
"Undelegation transaction successful : {}",
|
||||
res.transaction_hash
|
||||
);
|
||||
output_details.push([
|
||||
"Undelegate".to_string(),
|
||||
res.transaction_hash.to_string(),
|
||||
now.clone(),
|
||||
]);
|
||||
}
|
||||
|
||||
// Execute all delegation delegations
|
||||
if !delegation_msgs.is_empty() {
|
||||
let res = client
|
||||
.execute_multiple(
|
||||
mixnet_contract,
|
||||
delegation_msgs,
|
||||
None,
|
||||
format!(
|
||||
"Delegatation to {} nodes via nym-cli",
|
||||
undelegation_msgs.len()
|
||||
),
|
||||
)
|
||||
.await
|
||||
.expect("Could not delegate");
|
||||
|
||||
println!(
|
||||
"Delegation transaction successful : {}",
|
||||
res.transaction_hash
|
||||
);
|
||||
output_details.push([
|
||||
"Delegate".to_string(),
|
||||
res.transaction_hash.to_string(),
|
||||
now.clone(),
|
||||
]);
|
||||
}
|
||||
|
||||
if args.output.is_some() {
|
||||
if let Err(e) = write_to_csv(output_details, args.output) {
|
||||
info!("Failed to write to CSV, {}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,6 @@ use clap::{Args, Subcommand};
|
||||
pub mod rewards;
|
||||
|
||||
pub mod delegate_to_mixnode;
|
||||
pub mod delegate_to_multiple_mixnodes;
|
||||
pub mod query_for_delegations;
|
||||
pub mod undelegate_from_mixnode;
|
||||
pub mod vesting_delegate_to_mixnode;
|
||||
@@ -27,8 +26,6 @@ pub enum MixnetDelegatorsCommands {
|
||||
Rewards(rewards::MixnetDelegatorsReward),
|
||||
/// Delegate to a mixnode
|
||||
Delegate(delegate_to_mixnode::Args),
|
||||
/// Perform bulk delegations from an input file
|
||||
DelegateMulti(delegate_to_multiple_mixnodes::Args),
|
||||
/// Undelegate from a mixnode
|
||||
Undelegate(undelegate_from_mixnode::Args),
|
||||
/// Delegate to a mixnode with locked tokens
|
||||
|
||||
@@ -6,6 +6,8 @@ use clap::{Args, Subcommand};
|
||||
pub mod gateway;
|
||||
pub mod identity_key;
|
||||
pub mod mixnode;
|
||||
pub mod name;
|
||||
pub mod service;
|
||||
|
||||
#[derive(Debug, Args)]
|
||||
#[clap(args_conflicts_with_subcommands = true, subcommand_required = true)]
|
||||
@@ -21,6 +23,10 @@ pub enum MixnetOperatorsCommands {
|
||||
Mixnode(mixnode::MixnetOperatorsMixnode),
|
||||
/// Manage your gateway
|
||||
Gateway(gateway::MixnetOperatorsGateway),
|
||||
/// Manage your service
|
||||
ServiceProvider(service::MixnetOperatorsService),
|
||||
/// Manage your registered name
|
||||
Name(name::MixnetOperatorsName),
|
||||
/// Sign messages using your private identity key
|
||||
IdentityKey(identity_key::MixnetOperatorsIdentityKey),
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
use clap::Parser;
|
||||
use log::{error, info};
|
||||
use nym_name_service_common::NameId;
|
||||
use nym_validator_client::nyxd::{contract_traits::NameServiceSigningClient, error::NyxdError};
|
||||
use tap::TapFallible;
|
||||
|
||||
use crate::context::SigningClient;
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct Args {
|
||||
#[clap(long)]
|
||||
pub id: NameId,
|
||||
}
|
||||
|
||||
pub async fn delete(args: Args, client: SigningClient) -> Result<(), NyxdError> {
|
||||
info!("Deleting registered name alias with id {}", args.id);
|
||||
|
||||
let res = client
|
||||
.delete_name_by_id(args.id, None)
|
||||
.await
|
||||
.tap_err(|err| error!("Failed to delete name: {err:#?}"))?;
|
||||
|
||||
info!("Deleted: {res:?}");
|
||||
Ok(())
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
use clap::{Args, Subcommand};
|
||||
|
||||
pub mod delete;
|
||||
pub mod register;
|
||||
pub mod register_sign_payload;
|
||||
|
||||
#[derive(Debug, Args)]
|
||||
#[clap(args_conflicts_with_subcommands = true, subcommand_required = true)]
|
||||
pub struct MixnetOperatorsName {
|
||||
#[clap(subcommand)]
|
||||
pub command: MixnetOperatorsNameCommands,
|
||||
}
|
||||
|
||||
#[derive(Debug, Subcommand)]
|
||||
pub enum MixnetOperatorsNameCommands {
|
||||
/// Register a name alias for a nym address
|
||||
Register(register::Args),
|
||||
/// Delete name alias for a nym address
|
||||
Delete(delete::Args),
|
||||
/// Create base58-encoded payload required for producing valiid register signature.
|
||||
CreateNameRegisterPayload(register_sign_payload::Args),
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
use clap::Parser;
|
||||
use log::{error, info};
|
||||
use nym_contracts_common::signing::MessageSignature;
|
||||
use nym_name_service_common::{Address, Coin, NameDetails, NymName};
|
||||
use nym_sphinx::addressing::clients::Recipient;
|
||||
use nym_validator_client::nyxd::{contract_traits::NameServiceSigningClient, error::NyxdError};
|
||||
use tap::TapFallible;
|
||||
|
||||
use crate::context::SigningClient;
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct Args {
|
||||
/// Name alias
|
||||
#[clap(long)]
|
||||
pub name: NymName,
|
||||
|
||||
/// Nym address that the alias is pointing to
|
||||
#[clap(long)]
|
||||
pub nym_address: Recipient,
|
||||
|
||||
#[clap(long)]
|
||||
pub signature: MessageSignature,
|
||||
|
||||
/// Deposit to be made to the service provider directory, in curent DENOMINATION (e.g. 'unym')
|
||||
#[clap(long)]
|
||||
pub deposit: u128,
|
||||
}
|
||||
|
||||
pub async fn register(args: Args, client: SigningClient) -> Result<(), NyxdError> {
|
||||
info!(
|
||||
"Registering name alias '{}' for nym address '{}'",
|
||||
args.name, args.nym_address
|
||||
);
|
||||
|
||||
let address = Address::new(&args.nym_address.to_string()).expect("invalid address");
|
||||
let identity_key = address.client_id().to_string();
|
||||
let name = NameDetails {
|
||||
name: args.name,
|
||||
address,
|
||||
identity_key,
|
||||
};
|
||||
|
||||
let denom = client.current_chain_details().mix_denom.base.as_str();
|
||||
let deposit = Coin::new(args.deposit, denom);
|
||||
|
||||
let res = client
|
||||
.register_name(name, args.signature, deposit.into(), None)
|
||||
.await
|
||||
.tap_err(|err| error!("Failed to register name: {err:#?}"))?;
|
||||
|
||||
info!("Registered name: {res:?}");
|
||||
Ok(())
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::{
|
||||
context::SigningClient,
|
||||
utils::{account_id_to_cw_addr, DataWrapper},
|
||||
};
|
||||
|
||||
use clap::Parser;
|
||||
use cosmwasm_std::Coin;
|
||||
|
||||
use nym_bin_common::output_format::OutputFormat;
|
||||
use nym_name_service_common::{
|
||||
signing_types::construct_name_register_sign_payload, Address, NymName,
|
||||
};
|
||||
use nym_sphinx::addressing::clients::Recipient;
|
||||
use nym_validator_client::nyxd::{contract_traits::NameServiceQueryClient, error::NyxdError};
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct Args {
|
||||
// The name to register.
|
||||
#[arg(long)]
|
||||
pub name: NymName,
|
||||
|
||||
/// The nym address the name should point to.
|
||||
#[arg(long)]
|
||||
pub nym_address: Recipient,
|
||||
|
||||
#[arg(long)]
|
||||
pub amount: u128,
|
||||
|
||||
#[arg(short, long, default_value_t = OutputFormat::default())]
|
||||
output: OutputFormat,
|
||||
}
|
||||
|
||||
pub async fn create_payload(args: Args, client: SigningClient) -> Result<(), NyxdError> {
|
||||
let address = Address::new(&args.nym_address.to_string()).expect("invalid address");
|
||||
let identity_key = address.client_id().to_string();
|
||||
let name = nym_name_service_common::NameDetails {
|
||||
name: args.name,
|
||||
address,
|
||||
identity_key,
|
||||
};
|
||||
|
||||
let denom = client.current_chain_details().mix_denom.base.as_str();
|
||||
let deposit = Coin::new(args.amount, denom);
|
||||
|
||||
let nonce = match client.get_name_signing_nonce(&client.address()).await {
|
||||
Ok(nonce) => nonce,
|
||||
Err(err) => {
|
||||
eprint!(
|
||||
"failed to query for the signing nonce of {}: {err}",
|
||||
client.address()
|
||||
);
|
||||
return Err(err);
|
||||
}
|
||||
};
|
||||
|
||||
let address = account_id_to_cw_addr(&client.address());
|
||||
let payload = construct_name_register_sign_payload(nonce, address, deposit, name);
|
||||
let wrapper = DataWrapper::new(payload.to_base58_string().unwrap());
|
||||
println!("{}", args.output.format(&wrapper));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
use clap::Parser;
|
||||
use log::info;
|
||||
use nym_contracts_common::signing::MessageSignature;
|
||||
use nym_service_provider_directory_common::{Coin, NymAddress, ServiceDetails, ServiceType};
|
||||
use nym_validator_client::nyxd::contract_traits::SpDirectorySigningClient;
|
||||
|
||||
use crate::context::SigningClient;
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct Args {
|
||||
#[clap(long)]
|
||||
pub nym_address: String,
|
||||
|
||||
#[clap(long)]
|
||||
pub signature: MessageSignature,
|
||||
|
||||
/// Deposit to be made to the service provider directory, in curent DENOMINATION (e.g. 'unym')
|
||||
#[clap(long)]
|
||||
pub deposit: u128,
|
||||
|
||||
#[clap(long)]
|
||||
pub identity_key: String,
|
||||
}
|
||||
|
||||
pub async fn announce(args: Args, client: SigningClient) {
|
||||
info!("Annoucing service provider");
|
||||
|
||||
let nym_address = NymAddress::Address(args.nym_address);
|
||||
let service_type = ServiceType::NetworkRequester;
|
||||
let service = ServiceDetails {
|
||||
nym_address,
|
||||
service_type,
|
||||
identity_key: args.identity_key,
|
||||
};
|
||||
|
||||
let denom = client.current_chain_details().mix_denom.base.as_str();
|
||||
let deposit = Coin::new(args.deposit, denom);
|
||||
|
||||
let res = client
|
||||
.announce_service_provider(service, args.signature, deposit.into(), None)
|
||||
.await
|
||||
.expect("Failed to announce service provider");
|
||||
|
||||
info!("Announced service provider: {res:?}");
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::{
|
||||
context::SigningClient,
|
||||
utils::{account_id_to_cw_addr, DataWrapper},
|
||||
};
|
||||
|
||||
use clap::Parser;
|
||||
use cosmwasm_std::Coin;
|
||||
|
||||
use nym_bin_common::output_format::OutputFormat;
|
||||
use nym_service_provider_directory_common::{
|
||||
signing_types::construct_service_provider_announce_sign_payload, NymAddress,
|
||||
ServiceType::NetworkRequester,
|
||||
};
|
||||
use nym_sphinx::addressing::clients::Recipient;
|
||||
use nym_validator_client::nyxd::contract_traits::SpDirectoryQueryClient;
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct Args {
|
||||
#[clap(long)]
|
||||
pub nym_address: Recipient,
|
||||
|
||||
#[clap(long)]
|
||||
pub amount: u128,
|
||||
|
||||
#[clap(long)]
|
||||
pub identity_key: String,
|
||||
|
||||
#[clap(short, long, default_value_t = OutputFormat::default())]
|
||||
output: OutputFormat,
|
||||
}
|
||||
|
||||
pub async fn create_payload(args: Args, client: SigningClient) {
|
||||
let service = nym_service_provider_directory_common::ServiceDetails {
|
||||
nym_address: NymAddress::new(&args.nym_address.to_string()),
|
||||
service_type: NetworkRequester,
|
||||
identity_key: args.identity_key,
|
||||
};
|
||||
|
||||
let denom = client.current_chain_details().mix_denom.base.as_str();
|
||||
let deposit = Coin::new(args.amount, denom);
|
||||
|
||||
let nonce = match client.get_service_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_service_provider_announce_sign_payload(nonce, address, deposit, service);
|
||||
let wrapper = DataWrapper::new(payload.to_base58_string().unwrap());
|
||||
println!("{}", args.output.format(&wrapper))
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
use clap::Parser;
|
||||
use log::info;
|
||||
use nym_service_provider_directory_common::ServiceId;
|
||||
use nym_validator_client::nyxd::contract_traits::SpDirectorySigningClient;
|
||||
|
||||
use crate::context::SigningClient;
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct Args {
|
||||
#[clap(long)]
|
||||
pub id: ServiceId,
|
||||
}
|
||||
|
||||
pub async fn delete(args: Args, client: SigningClient) {
|
||||
info!("Deleting service provider with id {}", args.id);
|
||||
|
||||
let res = client
|
||||
.delete_service_provider_by_id(args.id, None)
|
||||
.await
|
||||
.expect("Failed to delete service provider");
|
||||
|
||||
info!("Deleted: {res:?}");
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
use clap::{Args, Subcommand};
|
||||
|
||||
pub mod announce;
|
||||
pub mod announce_sign_payload;
|
||||
pub mod delete;
|
||||
|
||||
#[derive(Debug, Args)]
|
||||
#[clap(args_conflicts_with_subcommands = true, subcommand_required = true)]
|
||||
pub struct MixnetOperatorsService {
|
||||
#[clap(subcommand)]
|
||||
pub command: MixnetOperatorsServiceCommands,
|
||||
}
|
||||
|
||||
#[allow(clippy::large_enum_variant)]
|
||||
#[derive(Debug, Subcommand)]
|
||||
pub enum MixnetOperatorsServiceCommands {
|
||||
/// Announce service provider to the world
|
||||
Announce(announce::Args),
|
||||
/// Delete entry for service provider from the directory
|
||||
Delete(delete::Args),
|
||||
/// Create base58-encoded payload required for producing valid announce signature.
|
||||
CreateServiceAnnounceSignPayload(announce_sign_payload::Args),
|
||||
}
|
||||
@@ -5,6 +5,8 @@ use clap::{Args, Subcommand};
|
||||
|
||||
pub mod query_all_gateways;
|
||||
pub mod query_all_mixnodes;
|
||||
pub mod query_all_names;
|
||||
pub mod query_all_service_providers;
|
||||
|
||||
#[derive(Debug, Args)]
|
||||
#[clap(args_conflicts_with_subcommands = true, subcommand_required = true)]
|
||||
@@ -19,4 +21,8 @@ pub enum MixnetQueryCommands {
|
||||
Mixnodes(query_all_mixnodes::Args),
|
||||
/// Query gateways
|
||||
Gateways(query_all_gateways::Args),
|
||||
/// Query announced service-providers
|
||||
ServiceProviders(query_all_service_providers::Args),
|
||||
/// Query registed names
|
||||
Names(query_all_names::Args),
|
||||
}
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::context::QueryClientWithNyxd;
|
||||
use crate::utils::show_error;
|
||||
use clap::Parser;
|
||||
use comfy_table::Table;
|
||||
use nym_validator_client::client::NymApiClientExt;
|
||||
use nym_validator_client::nym_api::error::NymAPIError;
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct Args {
|
||||
#[clap(value_parser)]
|
||||
#[clap(help = "Optionally, the registered name to display")]
|
||||
pub name: Option<String>,
|
||||
}
|
||||
|
||||
pub async fn query(args: Args, client: &QueryClientWithNyxd) {
|
||||
log::trace!("Querying all registered names");
|
||||
|
||||
match client.nym_api.get_registered_names().await {
|
||||
Ok(res) => {
|
||||
if let Some(name) = args.name {
|
||||
let name = res.names.iter().find(|name_entry| {
|
||||
name_entry.name.name.to_string().eq_ignore_ascii_case(&name)
|
||||
});
|
||||
println!(
|
||||
"{}",
|
||||
::serde_json::to_string_pretty(&name).expect("json formatting error")
|
||||
);
|
||||
} else {
|
||||
let mut table = Table::new();
|
||||
|
||||
table.set_header(vec!["Name Id", "Owner", "Nym Address", "Name"]);
|
||||
for name_entry in res.names {
|
||||
table.add_row(vec![
|
||||
name_entry.id.to_string(),
|
||||
name_entry.owner.to_string(),
|
||||
name_entry.name.address.to_string(),
|
||||
name_entry.name.name.to_string(),
|
||||
]);
|
||||
}
|
||||
|
||||
println!("The registered names in the directory are:");
|
||||
println!("{table}");
|
||||
}
|
||||
}
|
||||
Err(NymAPIError::NotFound) => {
|
||||
println!("nym-api reports no name endpoint available");
|
||||
}
|
||||
Err(e) => show_error(e),
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::context::QueryClientWithNyxd;
|
||||
use crate::utils::show_error;
|
||||
use clap::Parser;
|
||||
use comfy_table::Table;
|
||||
use nym_validator_client::client::NymApiClientExt;
|
||||
use nym_validator_client::nym_api::error::NymAPIError;
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct Args {
|
||||
#[clap(value_parser)]
|
||||
#[clap(help = "Optionally, the service provider to display")]
|
||||
pub nym_address: Option<String>,
|
||||
}
|
||||
|
||||
pub async fn query(args: Args, client: &QueryClientWithNyxd) {
|
||||
match client.nym_api.get_service_providers().await {
|
||||
Ok(res) => {
|
||||
if let Some(nym_address) = args.nym_address {
|
||||
let service = res.services.iter().find(|service| {
|
||||
service
|
||||
.service
|
||||
.nym_address
|
||||
.to_string()
|
||||
.eq_ignore_ascii_case(&nym_address)
|
||||
});
|
||||
println!(
|
||||
"{}",
|
||||
::serde_json::to_string_pretty(&service).expect("json formatting error")
|
||||
);
|
||||
} else {
|
||||
let mut table = Table::new();
|
||||
|
||||
table.set_header(vec!["Service Id", "Announcer", "Type", "Nym Address"]);
|
||||
for service in res.services {
|
||||
table.add_row(vec![
|
||||
service.service_id.to_string(),
|
||||
service.announcer.to_string(),
|
||||
service.service.service_type.to_string(),
|
||||
service.service.nym_address.to_string(),
|
||||
]);
|
||||
}
|
||||
|
||||
println!("The service providers in the directory are:");
|
||||
println!("{table}");
|
||||
}
|
||||
}
|
||||
Err(NymAPIError::NotFound) => {
|
||||
println!("nym-api reports no service provider endpoint available");
|
||||
}
|
||||
Err(e) => show_error(e),
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,7 @@ license.workspace = true
|
||||
|
||||
[dependencies]
|
||||
dirs = { version = "5.0.1", optional = true }
|
||||
handlebars = { workspace = true }
|
||||
handlebars = "3.5.5"
|
||||
log = { workspace = true }
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
toml = "0.7.4"
|
||||
|
||||
@@ -328,8 +328,4 @@ impl EpochState {
|
||||
pub fn is_dealing_exchange(&self) -> bool {
|
||||
matches!(self, EpochState::DealingExchange { .. })
|
||||
}
|
||||
|
||||
pub fn is_waiting_initialisation(&self) -> bool {
|
||||
matches!(self, EpochState::WaitingInitialisation)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,13 +11,9 @@ repository = { workspace = true }
|
||||
bs58 = { workspace = true }
|
||||
cosmwasm-std = { workspace = true }
|
||||
cosmwasm-schema = { workspace = true }
|
||||
cw-storage-plus = { workspace = true }
|
||||
schemars = { workspace = true }
|
||||
schemars = "0.8"
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
thiserror = { workspace = true }
|
||||
|
||||
[dev-dependencies]
|
||||
serde_json = { workspace = true }
|
||||
|
||||
[build-dependencies]
|
||||
vergen = { version = "=8.3.1", features = ["build", "git", "gitcl", "rustc", "cargo"] }
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use vergen::EmitBuilder;
|
||||
|
||||
fn main() {
|
||||
EmitBuilder::builder()
|
||||
.all_build()
|
||||
.rustc_semver()
|
||||
.git_branch()
|
||||
.git_commit_timestamp()
|
||||
.git_sha(false)
|
||||
.cargo_debug()
|
||||
.cargo_opt_level()
|
||||
.emit()
|
||||
.expect("failed to extract build metadata");
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user