Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 79b8b4d324 |
@@ -4,3 +4,4 @@
|
|||||||
**/node_modules
|
**/node_modules
|
||||||
**/target
|
**/target
|
||||||
dist
|
dist
|
||||||
|
documentation
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
nym-validator-rewarder/.sqlx/** diff=nodiff
|
|
||||||
@@ -31,5 +31,3 @@ updates:
|
|||||||
update-types:
|
update-types:
|
||||||
- "patch"
|
- "patch"
|
||||||
open-pull-requests-limit: 10
|
open-pull-requests-limit: 10
|
||||||
assignees:
|
|
||||||
- "octol"
|
|
||||||
|
|||||||
@@ -9,16 +9,15 @@ on:
|
|||||||
- 'gateway/**'
|
- 'gateway/**'
|
||||||
- 'integrations/**'
|
- 'integrations/**'
|
||||||
- 'mixnode/**'
|
- 'mixnode/**'
|
||||||
- 'nym-api/**'
|
|
||||||
- 'nym-data-observatory/**'
|
|
||||||
- 'nym-network-monitor/**'
|
|
||||||
- 'nym-node/**'
|
|
||||||
- 'nym-node-status-api/**'
|
|
||||||
- 'nym-outfox/**'
|
|
||||||
- 'nym-validator-rewarder/**'
|
|
||||||
- 'sdk/lib/**'
|
|
||||||
- 'sdk/rust/**'
|
- 'sdk/rust/**'
|
||||||
|
- 'sdk/lib/**'
|
||||||
- 'service-providers/**'
|
- 'service-providers/**'
|
||||||
|
- 'nym-network-monitor/**'
|
||||||
|
- 'nym-api/**'
|
||||||
|
- 'nym-node/**'
|
||||||
|
- 'nym-outfox/**'
|
||||||
|
- 'nym-data-observatory/**'
|
||||||
|
- 'nym-validator-rewarder/**'
|
||||||
- 'tools/**'
|
- 'tools/**'
|
||||||
- 'wasm/**'
|
- 'wasm/**'
|
||||||
- 'Cargo.toml'
|
- 'Cargo.toml'
|
||||||
@@ -31,11 +30,10 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
os: [ arc-ubuntu-20.04, custom-windows-11, custom-runner-mac-m1 ]
|
os: [ arc-ubuntu-20.04, custom-runner-mac-m1 ]
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
env:
|
env:
|
||||||
CARGO_TERM_COLOR: always
|
CARGO_TERM_COLOR: always
|
||||||
IPINFO_API_TOKEN: ${{ secrets.IPINFO_API_TOKEN }}
|
|
||||||
steps:
|
steps:
|
||||||
- name: Install Dependencies (Linux)
|
- 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 libudev-dev squashfs-tools protobuf-compiler
|
run: sudo apt-get update && sudo apt-get -y install libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev libudev-dev squashfs-tools protobuf-compiler
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ on:
|
|||||||
jobs:
|
jobs:
|
||||||
check-schema:
|
check-schema:
|
||||||
name: Generate and check schema
|
name: Generate and check schema
|
||||||
runs-on: ubuntu-20.04
|
runs-on: arc-ubuntu-20.04
|
||||||
env:
|
env:
|
||||||
CARGO_TERM_COLOR: always
|
CARGO_TERM_COLOR: always
|
||||||
steps:
|
steps:
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ on:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
matrix_prep:
|
matrix_prep:
|
||||||
runs-on: ubuntu-20.04
|
runs-on: arc-ubuntu-20.04
|
||||||
outputs:
|
outputs:
|
||||||
matrix: ${{ steps.set-matrix.outputs.matrix }}
|
matrix: ${{ steps.set-matrix.outputs.matrix }}
|
||||||
steps:
|
steps:
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ jobs:
|
|||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
env:
|
env:
|
||||||
CARGO_TERM_COLOR: always
|
CARGO_TERM_COLOR: always
|
||||||
IPINFO_API_TOKEN: ${{ secrets.IPINFO_API_TOKEN }}
|
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
steps:
|
steps:
|
||||||
- name: Check out repository code
|
- name: Check out repository code
|
||||||
|
|||||||
@@ -55,7 +55,6 @@ jobs:
|
|||||||
uses: actions-rs/toolchain@v1
|
uses: actions-rs/toolchain@v1
|
||||||
with:
|
with:
|
||||||
toolchain: stable
|
toolchain: stable
|
||||||
override: true
|
|
||||||
|
|
||||||
- name: Build all binaries
|
- name: Build all binaries
|
||||||
uses: actions-rs/cargo@v1
|
uses: actions-rs/cargo@v1
|
||||||
|
|||||||
@@ -14,14 +14,13 @@ jobs:
|
|||||||
- name: Install Rust stable
|
- name: Install Rust stable
|
||||||
uses: actions-rs/toolchain@v1
|
uses: actions-rs/toolchain@v1
|
||||||
with:
|
with:
|
||||||
toolchain: 1.77
|
toolchain: stable
|
||||||
target: wasm32-unknown-unknown
|
target: wasm32-unknown-unknown
|
||||||
override: true
|
override: true
|
||||||
|
components: rustfmt, clippy
|
||||||
|
|
||||||
- name: Install wasm-opt
|
- name: Install wasm-opt
|
||||||
uses: ./.github/actions/install-wasm-opt
|
run: cargo install --version 0.114.0 wasm-opt
|
||||||
with:
|
|
||||||
version: '114'
|
|
||||||
|
|
||||||
- name: Build release contracts
|
- name: Build release contracts
|
||||||
run: make contracts
|
run: make contracts
|
||||||
|
|||||||
@@ -56,6 +56,14 @@ jobs:
|
|||||||
rustup target add aarch64-linux-android \
|
rustup target add aarch64-linux-android \
|
||||||
x86_64-linux-android
|
x86_64-linux-android
|
||||||
|
|
||||||
|
- name: Build lib nym-socks5-listener
|
||||||
|
working-directory: sdk/lib/socks5-listener/
|
||||||
|
env:
|
||||||
|
RELEASE: true
|
||||||
|
RUSTFLAGS: "-C link-args=-Wl,--hash-style=gnu"
|
||||||
|
# build for arm64 and x86_64
|
||||||
|
run: ./build-android.sh aarch64 x86_64
|
||||||
|
|
||||||
- name: Build APKs (unsigned)
|
- name: Build APKs (unsigned)
|
||||||
working-directory: nym-connect/native/android
|
working-directory: nym-connect/native/android
|
||||||
env:
|
env:
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ jobs:
|
|||||||
git config --global user.name "Lawrence Stalder"
|
git config --global user.name "Lawrence Stalder"
|
||||||
|
|
||||||
- name: Get version from cargo.toml
|
- name: Get version from cargo.toml
|
||||||
uses: mikefarah/yq@v4.45.1
|
uses: mikefarah/yq@v4.44.3
|
||||||
id: get_version
|
id: get_version
|
||||||
with:
|
with:
|
||||||
cmd: yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/nym-credential-proxy/Cargo.toml
|
cmd: yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/nym-credential-proxy/Cargo.toml
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ jobs:
|
|||||||
git config --global user.name "Lawrence Stalder"
|
git config --global user.name "Lawrence Stalder"
|
||||||
|
|
||||||
- name: Get version from cargo.toml
|
- name: Get version from cargo.toml
|
||||||
uses: mikefarah/yq@v4.45.1
|
uses: mikefarah/yq@v4.44.3
|
||||||
id: get_version
|
id: get_version
|
||||||
with:
|
with:
|
||||||
cmd: yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/Cargo.toml
|
cmd: yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/Cargo.toml
|
||||||
|
|||||||
@@ -25,27 +25,31 @@ jobs:
|
|||||||
git config --global user.email "lawrence@nymtech.net"
|
git config --global user.email "lawrence@nymtech.net"
|
||||||
git config --global user.name "Lawrence Stalder"
|
git config --global user.name "Lawrence Stalder"
|
||||||
|
|
||||||
- name: Get version from cargo.toml
|
- name: Get version from package.json
|
||||||
uses: mikefarah/yq@v4.45.1
|
uses: sergeysova/jq-action@v2
|
||||||
id: get_version
|
id: get_version
|
||||||
with:
|
with:
|
||||||
cmd: yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/nym-network-monitor/Cargo.toml
|
cmd: jq -r '.version' ${{ env.WORKING_DIRECTORY }}/package.json
|
||||||
|
|
||||||
|
- name: Check if tag exists
|
||||||
|
run: |
|
||||||
|
if git rev-parse ${{ steps.get_version.outputs.value }} >/dev/null 2>&1; then
|
||||||
|
echo "Tag ${{ steps.get_version.outputs.value }} already exists"
|
||||||
|
fi
|
||||||
|
|
||||||
- name: Remove existing tag if exists
|
- name: Remove existing tag if exists
|
||||||
run: |
|
run: |
|
||||||
echo "Checking if tag ${{ env.CONTAINER_NAME }}-${{ steps.get_version.outputs.result }} exists..."
|
if git rev-parse ${{ steps.get_version.outputs.value }} >/dev/null 2>&1; then
|
||||||
if git rev-parse ${{ env.CONTAINER_NAME }}-${{ steps.get_version.outputs.result }} >/dev/null 2>&1; then
|
git push --delete origin ${{ steps.get_version.outputs.value }}
|
||||||
echo "Tag ${{ env.CONTAINER_NAME }}-${{ steps.get_version.outputs.result }} already exists"
|
git tag -d ${{ steps.get_version.outputs.value }}
|
||||||
git push --delete origin ${{ env.CONTAINER_NAME }}-${{ steps.get_version.outputs.result }}
|
|
||||||
git tag -d ${{ env.CONTAINER_NAME }}-${{ steps.get_version.outputs.result }}
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
- name: Create tag
|
- name: Create tag
|
||||||
run: |
|
run: |
|
||||||
git tag -a ${{ env.CONTAINER_NAME }}-${{ steps.get_version.outputs.result }} -m "Version ${{ steps.get_version.outputs.result }}"
|
git tag -a ${{ steps.get_version.outputs.value }} -m "Version ${{ steps.get_version.outputs.value }}"
|
||||||
git push origin ${{ env.CONTAINER_NAME }}-${{ steps.get_version.outputs.result }}
|
git push origin ${{ steps.get_version.outputs.value }}
|
||||||
|
|
||||||
- name: BuildAndPushImageOnHarbor
|
- name: BuildAndPushImageOnHarbor
|
||||||
run: |
|
run: |
|
||||||
docker build -f nym-network-monitor.dockerfile ${{ env.WORKING_DIRECTORY }} -t harbor.nymte.ch/nym/${{ env.CONTAINER_NAME }}:${{ steps.get_version.outputs.result }} -t harbor.nymte.ch/nym/${{ env.CONTAINER_NAME }}:latest
|
docker build -f nym-network-monitor.dockerfile ${{ env.WORKING_DIRECTORY }} -t harbor.nymte.ch/nym/${{ env.CONTAINER_NAME }}:${{ steps.get_version.outputs.value }} -t harbor.nymte.ch/nym/${{ env.CONTAINER_NAME }}:latest
|
||||||
docker push harbor.nymte.ch/nym/${{ env.CONTAINER_NAME }} --all-tags
|
docker push harbor.nymte.ch/nym/${{ env.CONTAINER_NAME }} --all-tags
|
||||||
@@ -8,7 +8,7 @@ on:
|
|||||||
description: Which gateway probe git ref to build the image with
|
description: Which gateway probe git ref to build the image with
|
||||||
|
|
||||||
env:
|
env:
|
||||||
WORKING_DIRECTORY: "nym-node-status-api/nym-node-status-agent"
|
WORKING_DIRECTORY: "nym-node-status-agent"
|
||||||
CONTAINER_NAME: "node-status-agent"
|
CONTAINER_NAME: "node-status-agent"
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
@@ -31,7 +31,7 @@ jobs:
|
|||||||
git config --global user.name "Lawrence Stalder"
|
git config --global user.name "Lawrence Stalder"
|
||||||
|
|
||||||
- name: Get version from cargo.toml
|
- name: Get version from cargo.toml
|
||||||
uses: mikefarah/yq@v4.45.1
|
uses: mikefarah/yq@v4.44.3
|
||||||
id: get_version
|
id: get_version
|
||||||
with:
|
with:
|
||||||
cmd: yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/Cargo.toml
|
cmd: yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/Cargo.toml
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ on:
|
|||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
env:
|
env:
|
||||||
WORKING_DIRECTORY: "nym-node-status-api/nym-node-status-api"
|
WORKING_DIRECTORY: "nym-node-status-api"
|
||||||
CONTAINER_NAME: "node-status-api"
|
CONTAINER_NAME: "node-status-api"
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
@@ -26,7 +26,7 @@ jobs:
|
|||||||
git config --global user.name "Lawrence Stalder"
|
git config --global user.name "Lawrence Stalder"
|
||||||
|
|
||||||
- name: Get version from cargo.toml
|
- name: Get version from cargo.toml
|
||||||
uses: mikefarah/yq@v4.45.1
|
uses: mikefarah/yq@v4.44.3
|
||||||
id: get_version
|
id: get_version
|
||||||
with:
|
with:
|
||||||
cmd: yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/Cargo.toml
|
cmd: yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/Cargo.toml
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ jobs:
|
|||||||
git config --global user.name "Lawrence Stalder"
|
git config --global user.name "Lawrence Stalder"
|
||||||
|
|
||||||
- name: Get version from cargo.toml
|
- name: Get version from cargo.toml
|
||||||
uses: mikefarah/yq@v4.45.1
|
uses: mikefarah/yq@v4.44.3
|
||||||
id: get_version
|
id: get_version
|
||||||
with:
|
with:
|
||||||
cmd: yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/Cargo.toml
|
cmd: yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/Cargo.toml
|
||||||
|
|||||||
@@ -1,55 +0,0 @@
|
|||||||
name: Build and upload Nyx Chain Watcher container to harbor.nymte.ch
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
env:
|
|
||||||
WORKING_DIRECTORY: "nyx-chain-watcher"
|
|
||||||
CONTAINER_NAME: "nyx-chain-watcher"
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build-container:
|
|
||||||
runs-on: arc-ubuntu-22.04-dind
|
|
||||||
steps:
|
|
||||||
- name: Login to Harbor
|
|
||||||
uses: docker/login-action@v3
|
|
||||||
with:
|
|
||||||
registry: harbor.nymte.ch
|
|
||||||
username: ${{ secrets.HARBOR_ROBOT_USERNAME }}
|
|
||||||
password: ${{ secrets.HARBOR_ROBOT_SECRET }}
|
|
||||||
|
|
||||||
- name: Checkout repo
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Configure git identity
|
|
||||||
run: |
|
|
||||||
git config --global user.email "lawrence@nymtech.net"
|
|
||||||
git config --global user.name "Lawrence Stalder"
|
|
||||||
|
|
||||||
- name: Get version from cargo.toml
|
|
||||||
uses: mikefarah/yq@v4.45.1
|
|
||||||
id: get_version
|
|
||||||
with:
|
|
||||||
cmd: yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/Cargo.toml
|
|
||||||
|
|
||||||
- name: Check if tag exists
|
|
||||||
run: |
|
|
||||||
if git rev-parse ${{ steps.get_version.outputs.value }} >/dev/null 2>&1; then
|
|
||||||
echo "Tag ${{ steps.get_version.outputs.value }} already exists"
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Remove existing tag if exists
|
|
||||||
run: |
|
|
||||||
if git rev-parse ${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.result }} >/dev/null 2>&1; then
|
|
||||||
git push --delete origin ${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.result }}
|
|
||||||
git tag -d ${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.result }}
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Create tag
|
|
||||||
run: |
|
|
||||||
git tag -a ${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.result }} -m "Version ${{ steps.get_version.outputs.result }}"
|
|
||||||
git push origin ${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.result }}
|
|
||||||
|
|
||||||
- name: BuildAndPushImageOnHarbor
|
|
||||||
run: |
|
|
||||||
docker build -f ${{ env.WORKING_DIRECTORY }}/Dockerfile . -t harbor.nymte.ch/nym/${{ env.CONTAINER_NAME }}:${{ steps.get_version.outputs.result }} -t harbor.nymte.ch/nym/${{ env.CONTAINER_NAME }}:latest
|
|
||||||
docker push harbor.nymte.ch/nym/${{ env.CONTAINER_NAME }} --all-tags
|
|
||||||
@@ -26,10 +26,10 @@ jobs:
|
|||||||
git config --global user.name "Lawrence Stalder"
|
git config --global user.name "Lawrence Stalder"
|
||||||
|
|
||||||
- name: Get version from cargo.toml
|
- name: Get version from cargo.toml
|
||||||
uses: mikefarah/yq@v4.45.1
|
uses: mikefarah/yq@v4.44.3
|
||||||
id: get_version
|
id: get_version
|
||||||
with:
|
with:
|
||||||
cmd: yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/Cargo.toml
|
cmd: yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/nym-credential-proxy/Cargo.toml
|
||||||
|
|
||||||
- name: Remove existing tag if exists
|
- name: Remove existing tag if exists
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
+1
-8
@@ -51,11 +51,4 @@ ppa-private-key.b64
|
|||||||
ppa-private-key.asc
|
ppa-private-key.asc
|
||||||
nym-network-monitor/topology.json
|
nym-network-monitor/topology.json
|
||||||
nym-network-monitor/__pycache__
|
nym-network-monitor/__pycache__
|
||||||
nym-network-monitor/*.key
|
nym-network-monitor/*.key
|
||||||
nym-network-monitor/.envrc
|
|
||||||
nym-network-monitor/.envrc
|
|
||||||
nym-api/redocly/formatted-openapi.json
|
|
||||||
|
|
||||||
|
|
||||||
*.sqlite
|
|
||||||
.build
|
|
||||||
-429
@@ -4,435 +4,6 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
## [2025.1-reeses] (2025-01-15)
|
|
||||||
|
|
||||||
- Feture/legacy alert ([#5346])
|
|
||||||
- chore: readjusted --mode behaviour to fix the regression ([#5331])
|
|
||||||
- chore: apply 1.84 linter suggestions ([#5330])
|
|
||||||
- bugfix: make sure refresh data key matches bond info ([#5329])
|
|
||||||
- reduce log severity for number of packets being delayed ([#5321])
|
|
||||||
- feat: warn users if node is run in exit mode only ([#5320])
|
|
||||||
- Bugfix/contract version assignment ([#5318])
|
|
||||||
- fixed client session histogram buckets ([#5316])
|
|
||||||
- amend 250gb limit ([#5313])
|
|
||||||
- feature: expand nym-node prometheus metrics ([#5298])
|
|
||||||
- Cherry picked #5286 ([#5287])
|
|
||||||
- Add close to credential storage ([#5283])
|
|
||||||
- feature: wireguard metrics ([#5278])
|
|
||||||
- Add PATCH support to nym-http-api-client ([#5260])
|
|
||||||
- chore: removed legacy socks5 listener ([#5259])
|
|
||||||
- bugfix: make sure to apply gateway score filtering when choosing initial node ([#5256])
|
|
||||||
- Update TS bindings ([#5255])
|
|
||||||
- Add conversion unit tests for auth msg ([#5251])
|
|
||||||
- Add control messages to GatewayTransciver ([#5247])
|
|
||||||
- Remove unneeded async function annotation ([#5246])
|
|
||||||
- bugfix: make sure to update timestamp of last batch verification to prevent double redemption ([#5239])
|
|
||||||
- Add FromStr impl for UserAgent ([#5236])
|
|
||||||
- Extend swagger docs ([#5235])
|
|
||||||
- TicketType derive Hash and Eq ([#5233])
|
|
||||||
- Add fd callback to client core ([#5230])
|
|
||||||
- Extend raw ws fd for gateway client ([#5218])
|
|
||||||
- Shipping raw metrics to PG ([#5216])
|
|
||||||
- Change sqlite journal mode to WAL ([#5213])
|
|
||||||
- Derive serialize for UserAgent ([#5210])
|
|
||||||
- Restore Location fields ([#5208])
|
|
||||||
- better date serialization ([#5207])
|
|
||||||
- Fix overflow ([#5204])
|
|
||||||
- feature: hopefully final steps of the smoosh™️ ([#5201])
|
|
||||||
- Fix overflow ([#5184])
|
|
||||||
- NS API - Gateway stats scraping ([#5180])
|
|
||||||
- introduced initial internal commands for nym-cli: ecash key and request generation ([#5174])
|
|
||||||
- Move NS client to separate package under NS API ([#5171])
|
|
||||||
- build(deps): bump micromatch from 4.0.4 to 4.0.8 in /testnet-faucet ([#4813])
|
|
||||||
|
|
||||||
[#5346]: https://github.com/nymtech/nym/pull/5346
|
|
||||||
[#5331]: https://github.com/nymtech/nym/pull/5331
|
|
||||||
[#5330]: https://github.com/nymtech/nym/pull/5330
|
|
||||||
[#5329]: https://github.com/nymtech/nym/pull/5329
|
|
||||||
[#5321]: https://github.com/nymtech/nym/pull/5321
|
|
||||||
[#5320]: https://github.com/nymtech/nym/pull/5320
|
|
||||||
[#5318]: https://github.com/nymtech/nym/pull/5318
|
|
||||||
[#5316]: https://github.com/nymtech/nym/pull/5316
|
|
||||||
[#5313]: https://github.com/nymtech/nym/pull/5313
|
|
||||||
[#5298]: https://github.com/nymtech/nym/pull/5298
|
|
||||||
[#5287]: https://github.com/nymtech/nym/pull/5287
|
|
||||||
[#5283]: https://github.com/nymtech/nym/pull/5283
|
|
||||||
[#5278]: https://github.com/nymtech/nym/pull/5278
|
|
||||||
[#5260]: https://github.com/nymtech/nym/pull/5260
|
|
||||||
[#5259]: https://github.com/nymtech/nym/pull/5259
|
|
||||||
[#5256]: https://github.com/nymtech/nym/pull/5256
|
|
||||||
[#5255]: https://github.com/nymtech/nym/pull/5255
|
|
||||||
[#5251]: https://github.com/nymtech/nym/pull/5251
|
|
||||||
[#5247]: https://github.com/nymtech/nym/pull/5247
|
|
||||||
[#5246]: https://github.com/nymtech/nym/pull/5246
|
|
||||||
[#5239]: https://github.com/nymtech/nym/pull/5239
|
|
||||||
[#5236]: https://github.com/nymtech/nym/pull/5236
|
|
||||||
[#5235]: https://github.com/nymtech/nym/pull/5235
|
|
||||||
[#5233]: https://github.com/nymtech/nym/pull/5233
|
|
||||||
[#5230]: https://github.com/nymtech/nym/pull/5230
|
|
||||||
[#5218]: https://github.com/nymtech/nym/pull/5218
|
|
||||||
[#5216]: https://github.com/nymtech/nym/pull/5216
|
|
||||||
[#5213]: https://github.com/nymtech/nym/pull/5213
|
|
||||||
[#5210]: https://github.com/nymtech/nym/pull/5210
|
|
||||||
[#5208]: https://github.com/nymtech/nym/pull/5208
|
|
||||||
[#5207]: https://github.com/nymtech/nym/pull/5207
|
|
||||||
[#5204]: https://github.com/nymtech/nym/pull/5204
|
|
||||||
[#5201]: https://github.com/nymtech/nym/pull/5201
|
|
||||||
[#5184]: https://github.com/nymtech/nym/pull/5184
|
|
||||||
[#5180]: https://github.com/nymtech/nym/pull/5180
|
|
||||||
[#5174]: https://github.com/nymtech/nym/pull/5174
|
|
||||||
[#5171]: https://github.com/nymtech/nym/pull/5171
|
|
||||||
[#4813]: https://github.com/nymtech/nym/pull/4813
|
|
||||||
|
|
||||||
## [2024.14-crunch-patched] (2024-12-17)
|
|
||||||
|
|
||||||
- Fixes an issue to allow previously registred clients to connect to latest nym-nodes
|
|
||||||
- Fixes compatibility issues between nym-nodes and older clients
|
|
||||||
|
|
||||||
## [2024.14-crunch] (2024-12-11)
|
|
||||||
|
|
||||||
- Merge/release/2024.14-crunch ([#5242])
|
|
||||||
- bugfix: added explicit openapi servers to account for route prefixes ([#5237])
|
|
||||||
- Further config score adjustments ([#5225])
|
|
||||||
- feature: remve any filtering on node semver ([#5224])
|
|
||||||
- Backport #5218 ([#5220])
|
|
||||||
- Derive serialize for UserAgent (#5210) ([#5217])
|
|
||||||
- dont consider legacy nodes for rewarded set selection ([#5215])
|
|
||||||
- introduce UNSTABLE endpoints for returning network monitor run details ([#5214])
|
|
||||||
- Nmv2 add debug config ([#5212])
|
|
||||||
- nym-api NMv1 adjustments ([#5209])
|
|
||||||
- adjusted config score penalty calculation ([#5206])
|
|
||||||
- Fix backwards compat mac generation ([#5202])
|
|
||||||
- merge crunch into develop ([#5199])
|
|
||||||
- Update Security disclosure email, public key and policy ([#5195])
|
|
||||||
- Guard storage access with cache ([#5193])
|
|
||||||
- chore: apply 1.84 linter suggestions ([#5192])
|
|
||||||
- improvement: make internal gateway clients use the same topology cache ([#5191])
|
|
||||||
- Bugfix/credential proxy sequencing ([#5187])
|
|
||||||
- Add monitor_run and testing_route indexes ([#5182])
|
|
||||||
- Add indexes to monitor run and testing route ([#5181])
|
|
||||||
- bugfix: fixed nym-node config migrations (again) ([#5179])
|
|
||||||
- bugfix: use default value for verloc config when deserialising missing values ([#5177])
|
|
||||||
- Remove peers with no allowed ip from storage ([#5175])
|
|
||||||
- Move two minor jobs to free tier github hosted runners ([#5169])
|
|
||||||
- Add support for DELETE to nym-http-api-client ([#5166])
|
|
||||||
- Fix env var name ([#5165])
|
|
||||||
- Add strum::EnumIter for TicketType ([#5164])
|
|
||||||
- Add export_to_env to NymNetworkDetails ([#5162])
|
|
||||||
- bugfix: correctly expose ecash-related data on nym-api ([#5155])
|
|
||||||
- fix: validator-rewarder GH job ([#5151])
|
|
||||||
- build(deps): bump cross-spawn from 7.0.3 to 7.0.6 in /testnet-faucet ([#5150])
|
|
||||||
- build(deps): bump mikefarah/yq from 4.44.3 to 4.44.5 ([#5149])
|
|
||||||
- start session collection for exit gateways ([#5148])
|
|
||||||
- add version to clientStatsReport ([#5147])
|
|
||||||
- update serde_json_path due to compilation issue ([#5144])
|
|
||||||
- chore: remove standalone legacy mixnode/gateway binaries ([#5135])
|
|
||||||
- [Product Data] Set up country reporting from vpn-client ([#5134])
|
|
||||||
- removed ci-nym-api-tests.yml which was running outdated (and broken) tests ([#5133])
|
|
||||||
- CI: reduce jobs running on cluster ([#5132])
|
|
||||||
- [DOCS/operators]: Release changes v2024.13-magura & Tokenomics pages v1.0 ([#5128])
|
|
||||||
- NS Agent auth with NS API ([#5127])
|
|
||||||
- [Product Data] Config deserialization bug fix ([#5126])
|
|
||||||
- bugfix: don't send empty BankMsg in ecash contract ([#5121])
|
|
||||||
- [Product data] Data consumption with ecash ticket ([#5120])
|
|
||||||
- feat: add GH workflow for nym-validator-rewarder ([#5119])
|
|
||||||
- feat: add Dockerfile and add env vars for clap arguments ([#5118])
|
|
||||||
- feature: config score ([#5117])
|
|
||||||
- [Product Data] Add stats reporting configuration in client config ([#5115])
|
|
||||||
- Correct IPv6 address generation ([#5113])
|
|
||||||
- feature: rewarding for ticketbook issuance ([#5112])
|
|
||||||
- Add granular log on nym-node ([#5111])
|
|
||||||
- Send mixnet packet stats using task client ([#5109])
|
|
||||||
- Expose time range ([#5108])
|
|
||||||
- [Product Data] Client-side stats collection ([#5107])
|
|
||||||
- chore: ecash contract migration to remove unused 'redemption_gateway_share' ([#5104])
|
|
||||||
- [Product Data] Better unique user count on gateways ([#5084])
|
|
||||||
- feat: add nym node GH workflow ([#5080])
|
|
||||||
- IPv6 support for wireguard ([#5059])
|
|
||||||
- Node Status API ([#5050])
|
|
||||||
- Authenticator CLI client mode ([#5044])
|
|
||||||
- Integrate nym-credential-proxy into workspace ([#5027])
|
|
||||||
- [Product Data] Introduce data persistence on gateways ([#5022])
|
|
||||||
- Bump the patch-updates group across 1 directory with 10 updates ([#5011])
|
|
||||||
- build(deps): bump once_cell from 1.19.0 to 1.20.2 ([#4952])
|
|
||||||
- Create TaskStatusEvent trait instead of piggybacking on Error ([#4919])
|
|
||||||
- build(deps): bump lazy_static from 1.4.0 to 1.5.0 ([#4913])
|
|
||||||
- Sync code with .env in build.rs ([#4876])
|
|
||||||
- build(deps): bump axios from 1.6.0 to 1.7.5 in /nym-api/tests ([#4790])
|
|
||||||
- Bump elliptic from 6.5.4 to 6.5.7 in /testnet-faucet ([#4768])
|
|
||||||
|
|
||||||
[#5242]: https://github.com/nymtech/nym/pull/5242
|
|
||||||
[#5237]: https://github.com/nymtech/nym/pull/5237
|
|
||||||
[#5225]: https://github.com/nymtech/nym/pull/5225
|
|
||||||
[#5224]: https://github.com/nymtech/nym/pull/5224
|
|
||||||
[#5220]: https://github.com/nymtech/nym/pull/5220
|
|
||||||
[#5217]: https://github.com/nymtech/nym/pull/5217
|
|
||||||
[#5215]: https://github.com/nymtech/nym/pull/5215
|
|
||||||
[#5214]: https://github.com/nymtech/nym/pull/5214
|
|
||||||
[#5212]: https://github.com/nymtech/nym/pull/5212
|
|
||||||
[#5209]: https://github.com/nymtech/nym/pull/5209
|
|
||||||
[#5206]: https://github.com/nymtech/nym/pull/5206
|
|
||||||
[#5202]: https://github.com/nymtech/nym/pull/5202
|
|
||||||
[#5199]: https://github.com/nymtech/nym/pull/5199
|
|
||||||
[#5195]: https://github.com/nymtech/nym/pull/5195
|
|
||||||
[#5193]: https://github.com/nymtech/nym/pull/5193
|
|
||||||
[#5192]: https://github.com/nymtech/nym/pull/5192
|
|
||||||
[#5191]: https://github.com/nymtech/nym/pull/5191
|
|
||||||
[#5187]: https://github.com/nymtech/nym/pull/5187
|
|
||||||
[#5182]: https://github.com/nymtech/nym/pull/5182
|
|
||||||
[#5181]: https://github.com/nymtech/nym/pull/5181
|
|
||||||
[#5179]: https://github.com/nymtech/nym/pull/5179
|
|
||||||
[#5177]: https://github.com/nymtech/nym/pull/5177
|
|
||||||
[#5175]: https://github.com/nymtech/nym/pull/5175
|
|
||||||
[#5169]: https://github.com/nymtech/nym/pull/5169
|
|
||||||
[#5166]: https://github.com/nymtech/nym/pull/5166
|
|
||||||
[#5165]: https://github.com/nymtech/nym/pull/5165
|
|
||||||
[#5164]: https://github.com/nymtech/nym/pull/5164
|
|
||||||
[#5162]: https://github.com/nymtech/nym/pull/5162
|
|
||||||
[#5155]: https://github.com/nymtech/nym/pull/5155
|
|
||||||
[#5151]: https://github.com/nymtech/nym/pull/5151
|
|
||||||
[#5150]: https://github.com/nymtech/nym/pull/5150
|
|
||||||
[#5149]: https://github.com/nymtech/nym/pull/5149
|
|
||||||
[#5148]: https://github.com/nymtech/nym/pull/5148
|
|
||||||
[#5147]: https://github.com/nymtech/nym/pull/5147
|
|
||||||
[#5144]: https://github.com/nymtech/nym/pull/5144
|
|
||||||
[#5135]: https://github.com/nymtech/nym/pull/5135
|
|
||||||
[#5134]: https://github.com/nymtech/nym/pull/5134
|
|
||||||
[#5133]: https://github.com/nymtech/nym/pull/5133
|
|
||||||
[#5132]: https://github.com/nymtech/nym/pull/5132
|
|
||||||
[#5128]: https://github.com/nymtech/nym/pull/5128
|
|
||||||
[#5127]: https://github.com/nymtech/nym/pull/5127
|
|
||||||
[#5126]: https://github.com/nymtech/nym/pull/5126
|
|
||||||
[#5121]: https://github.com/nymtech/nym/pull/5121
|
|
||||||
[#5120]: https://github.com/nymtech/nym/pull/5120
|
|
||||||
[#5119]: https://github.com/nymtech/nym/pull/5119
|
|
||||||
[#5118]: https://github.com/nymtech/nym/pull/5118
|
|
||||||
[#5117]: https://github.com/nymtech/nym/pull/5117
|
|
||||||
[#5115]: https://github.com/nymtech/nym/pull/5115
|
|
||||||
[#5113]: https://github.com/nymtech/nym/pull/5113
|
|
||||||
[#5112]: https://github.com/nymtech/nym/pull/5112
|
|
||||||
[#5111]: https://github.com/nymtech/nym/pull/5111
|
|
||||||
[#5109]: https://github.com/nymtech/nym/pull/5109
|
|
||||||
[#5108]: https://github.com/nymtech/nym/pull/5108
|
|
||||||
[#5107]: https://github.com/nymtech/nym/pull/5107
|
|
||||||
[#5104]: https://github.com/nymtech/nym/pull/5104
|
|
||||||
[#5084]: https://github.com/nymtech/nym/pull/5084
|
|
||||||
[#5080]: https://github.com/nymtech/nym/pull/5080
|
|
||||||
[#5059]: https://github.com/nymtech/nym/pull/5059
|
|
||||||
[#5050]: https://github.com/nymtech/nym/pull/5050
|
|
||||||
[#5044]: https://github.com/nymtech/nym/pull/5044
|
|
||||||
[#5027]: https://github.com/nymtech/nym/pull/5027
|
|
||||||
[#5022]: https://github.com/nymtech/nym/pull/5022
|
|
||||||
[#5011]: https://github.com/nymtech/nym/pull/5011
|
|
||||||
[#4952]: https://github.com/nymtech/nym/pull/4952
|
|
||||||
[#4919]: https://github.com/nymtech/nym/pull/4919
|
|
||||||
[#4913]: https://github.com/nymtech/nym/pull/4913
|
|
||||||
[#4876]: https://github.com/nymtech/nym/pull/4876
|
|
||||||
[#4790]: https://github.com/nymtech/nym/pull/4790
|
|
||||||
[#4768]: https://github.com/nymtech/nym/pull/4768
|
|
||||||
|
|
||||||
## [2024.13-magura-drift] (2024-11-29)
|
|
||||||
|
|
||||||
- Optimised syncing bandwidth information to storage
|
|
||||||
|
|
||||||
## [2024.13-magura-patched] (2024-11-22)
|
|
||||||
|
|
||||||
- [experimental] allow clients to change between deterministic route selection based on packet headers and a pseudorandom distribution
|
|
||||||
- Introduced a configurable limit on retransmission frequency of packets if ACKs are not received
|
|
||||||
- Filtered out invalid IP addresses on nym-api
|
|
||||||
|
|
||||||
## [2024.13-magura] (2024-11-18)
|
|
||||||
|
|
||||||
- Limit race probability ([#5145])
|
|
||||||
- bugifx: assign 'node_id' when converting from 'GatewayDetails' to 'TestNode' ([#5143])
|
|
||||||
- bugfix: make sure to assign correct node_id and identity during 'gateway_details' table migration ([#5142])
|
|
||||||
- Respond to auth messages with same version ([#5140])
|
|
||||||
- Pain/polyfill deprecated endpoints ([#5131])
|
|
||||||
- change: dont select mixnodes bonded with vested tokens into the rewarded set ([#5129])
|
|
||||||
- nym-credential-proxy-requests: reqwest use rustls-tls ([#5116])
|
|
||||||
- bugfix: preserve as much as possible of the rewarded set during migration ([#5103])
|
|
||||||
- Feature/force refresh node ([#5101])
|
|
||||||
- Add NYM_VPN_API to env files ([#5099])
|
|
||||||
- bugfix: fixed historical uptimes for nodes ([#5097])
|
|
||||||
- Remove old use of 1GB constant ([#5096])
|
|
||||||
- Graceful agent 1.1.5 ([#5093])
|
|
||||||
- Add more translations from v2 to v3 authenticator ([#5091])
|
|
||||||
- Nym node - Fix claim delegator rewards ([#5090])
|
|
||||||
- Make 250 GB/30 days for free ride mode ([#5083])
|
|
||||||
- Don't increase bandwidth two times ([#5081])
|
|
||||||
- Fix expiration date as today + 7 days ([#5076])
|
|
||||||
- Fix gateway decreasing bandwidth ([#5075])
|
|
||||||
- Allow custom http port to be reset ([#5073])
|
|
||||||
- bugfix: additional checks inside credential proxy ([#5072])
|
|
||||||
- chore: deprecated old nym-api client methods and replaced them when possible ([#5069])
|
|
||||||
- NS API with directory v2 (#5058) ([#5068])
|
|
||||||
- bugfix: credential-proxy obtain-async ([#5067])
|
|
||||||
- Allow nym node config updates ([#5066])
|
|
||||||
- bugfix: use corrext axum extractors for ecash route arguments ([#5065])
|
|
||||||
- Merge2/release/2024.13 magura ([#5063])
|
|
||||||
- bugfix/feature: added NymApiClient method to get all skimmed nodes ([#5062])
|
|
||||||
- Merge1/release/2024.13 magura ([#5061])
|
|
||||||
- added hacky routes to return nymnodes alongside legacy nodes ([#5051])
|
|
||||||
- bugfix: mark migrated gateways as rewarded in the previous epoch in case theyre in the rewarded set ([#5049])
|
|
||||||
- bugfix: adjust runtime storage migration ([#5047])
|
|
||||||
- bugfix: supersede 'cb13be27f8f61d9ae74d924e85d2e6787895eb14' by using… ([#5046])
|
|
||||||
- bugfix: restore default http port for nym-api ([#5045])
|
|
||||||
- bugfix: fix ecash handlers routes ([#5043])
|
|
||||||
- bugfix: don't assign exit gateways to standby set ([#5041])
|
|
||||||
- bugfix: make sure nym-nodes are also tested by network monitor ([#5040])
|
|
||||||
- bugfix: use bonded nym-nodes for determining initial network monitor … ([#5039])
|
|
||||||
- bugfix: make gateways insert themselves into [local] topology ([#5038])
|
|
||||||
- Pass poisson flag ([#5037])
|
|
||||||
- bugfix: use human readable roles for annotations ([#5036])
|
|
||||||
- bugfix: use old name for 'epoch_role' in SkimmedNode ([#5034])
|
|
||||||
- bugfix: make sure to use correct highest node id when assigning role ([#5032])
|
|
||||||
- feature: use axum_client_ip for attempting to extract source ip ([#5031])
|
|
||||||
- bugfix: fixed backwards incompatibility for /gateways/described endpoint ([#5030])
|
|
||||||
- bugfix: verifying signed information of legacy nodes ([#5029])
|
|
||||||
- bugfix: introduce 'LegacyPendingMixNodeChanges' that does not contain 'cost_params_change' ([#5028])
|
|
||||||
- bugfix: missing #[serde(default)] for announce port ([#5024])
|
|
||||||
- bugfix: directory v2.1 `get_all_avg_gateway_reliability_in_interval` query ([#5023])
|
|
||||||
- added 'get_all_described_nodes' to NymApiClient and adjusted return t… ([#5016])
|
|
||||||
- Reapply fixes to new branch ([#5014])
|
|
||||||
- Consume only positive bandwidth ([#5013])
|
|
||||||
- feature: adjusted ticket sizes to the agreed amounts ([#5009])
|
|
||||||
- Push private ip before inserting ([#5008])
|
|
||||||
- chore: update itertools in compact ecash ([#4994])
|
|
||||||
- feature: make accepting t&c a hard requirement for rewarded set selection ([#4993])
|
|
||||||
- Fix rustfmt in nym-credential-proxy ([#4992])
|
|
||||||
- bugfix: client memory leak ([#4991])
|
|
||||||
- Eliminate 0 bandwidth race check ([#4988])
|
|
||||||
- [DOCs;/operators]: Release notes for v2024.12 aero ([#4984])
|
|
||||||
- Add topup req constructor ([#4983])
|
|
||||||
- Fix critical issues SI86 and SI87 from Cure53 ([#4982])
|
|
||||||
- Rename nym-vpn-api to nym-credential-proxy ([#4981])
|
|
||||||
- enable global ecash routes even if api is not a signer ([#4980])
|
|
||||||
- resolve beta clippy issues in contracts ([#4978])
|
|
||||||
- Re-enable vested delegation migration ([#4977])
|
|
||||||
- feature: require reporting using nym-node binary for rewarded set selection ([#4976])
|
|
||||||
- Top up bandwidth ([#4975])
|
|
||||||
- [Product Data] Add session type based on ecash ticket received ([#4974])
|
|
||||||
- Bugfix/additional directory fixes ([#4973])
|
|
||||||
- feat: add Dockerfile for nym node ([#4972])
|
|
||||||
- chore: remove unused rocket code ([#4968])
|
|
||||||
- Import nym-vpn-api crates ([#4967])
|
|
||||||
- feature: importer-cli to correctly handle mixnet/vesting import ([#4966])
|
|
||||||
- bugfix: fix expected return type on /v1/gateways endpoint ([#4965])
|
|
||||||
- [Product Data] First step in gateway usage data collection ([#4963])
|
|
||||||
- Bump sqlx to 0.7.4 ([#4959])
|
|
||||||
- Add env feature to clap and make clap parameters available as env variables ([#4957])
|
|
||||||
- Feature/contract state tools ([#4954])
|
|
||||||
- expose authenticator address along other address in node-details ([#4953])
|
|
||||||
- Extract packet processing from mixnode-common ([#4949])
|
|
||||||
- nym-api container ([#4948])
|
|
||||||
- Ticket type storage ([#4947])
|
|
||||||
- Add "utoipa" feature to nym-node ([#4945])
|
|
||||||
- build(deps): bump the patch-updates group across 1 directory with 9 updates ([#4944])
|
|
||||||
- V2 performance monitoring feature flag ([#4943])
|
|
||||||
- Bugfix/rewarder post pruning adjustments ([#4942])
|
|
||||||
- Switch over the last set of jobs to arc runners ([#4938])
|
|
||||||
- Fix broken build after merge ([#4937])
|
|
||||||
- bugfix: correctly paginate through 'search_tx' endpoint ([#4936])
|
|
||||||
- Add more conversions for responses of authenticator messages ([#4929])
|
|
||||||
- Directory Sevices v2.1 ([#4903])
|
|
||||||
- Migrate Legacy Node (Frontend) ([#4826])
|
|
||||||
- Fix critical issues SI84 and SI85 from Cure53 ([#4758])
|
|
||||||
|
|
||||||
[#5145]: https://github.com/nymtech/nym/pull/5145
|
|
||||||
[#5143]: https://github.com/nymtech/nym/pull/5143
|
|
||||||
[#5142]: https://github.com/nymtech/nym/pull/5142
|
|
||||||
[#5140]: https://github.com/nymtech/nym/pull/5140
|
|
||||||
[#5131]: https://github.com/nymtech/nym/pull/5131
|
|
||||||
[#5129]: https://github.com/nymtech/nym/pull/5129
|
|
||||||
[#5116]: https://github.com/nymtech/nym/pull/5116
|
|
||||||
[#5103]: https://github.com/nymtech/nym/pull/5103
|
|
||||||
[#5101]: https://github.com/nymtech/nym/pull/5101
|
|
||||||
[#5099]: https://github.com/nymtech/nym/pull/5099
|
|
||||||
[#5097]: https://github.com/nymtech/nym/pull/5097
|
|
||||||
[#5096]: https://github.com/nymtech/nym/pull/5096
|
|
||||||
[#5093]: https://github.com/nymtech/nym/pull/5093
|
|
||||||
[#5091]: https://github.com/nymtech/nym/pull/5091
|
|
||||||
[#5090]: https://github.com/nymtech/nym/pull/5090
|
|
||||||
[#5083]: https://github.com/nymtech/nym/pull/5083
|
|
||||||
[#5081]: https://github.com/nymtech/nym/pull/5081
|
|
||||||
[#5076]: https://github.com/nymtech/nym/pull/5076
|
|
||||||
[#5075]: https://github.com/nymtech/nym/pull/5075
|
|
||||||
[#5073]: https://github.com/nymtech/nym/pull/5073
|
|
||||||
[#5072]: https://github.com/nymtech/nym/pull/5072
|
|
||||||
[#5069]: https://github.com/nymtech/nym/pull/5069
|
|
||||||
[#5068]: https://github.com/nymtech/nym/pull/5068
|
|
||||||
[#5067]: https://github.com/nymtech/nym/pull/5067
|
|
||||||
[#5066]: https://github.com/nymtech/nym/pull/5066
|
|
||||||
[#5065]: https://github.com/nymtech/nym/pull/5065
|
|
||||||
[#5063]: https://github.com/nymtech/nym/pull/5063
|
|
||||||
[#5062]: https://github.com/nymtech/nym/pull/5062
|
|
||||||
[#5061]: https://github.com/nymtech/nym/pull/5061
|
|
||||||
[#5051]: https://github.com/nymtech/nym/pull/5051
|
|
||||||
[#5049]: https://github.com/nymtech/nym/pull/5049
|
|
||||||
[#5047]: https://github.com/nymtech/nym/pull/5047
|
|
||||||
[#5046]: https://github.com/nymtech/nym/pull/5046
|
|
||||||
[#5045]: https://github.com/nymtech/nym/pull/5045
|
|
||||||
[#5043]: https://github.com/nymtech/nym/pull/5043
|
|
||||||
[#5041]: https://github.com/nymtech/nym/pull/5041
|
|
||||||
[#5040]: https://github.com/nymtech/nym/pull/5040
|
|
||||||
[#5039]: https://github.com/nymtech/nym/pull/5039
|
|
||||||
[#5038]: https://github.com/nymtech/nym/pull/5038
|
|
||||||
[#5037]: https://github.com/nymtech/nym/pull/5037
|
|
||||||
[#5036]: https://github.com/nymtech/nym/pull/5036
|
|
||||||
[#5034]: https://github.com/nymtech/nym/pull/5034
|
|
||||||
[#5032]: https://github.com/nymtech/nym/pull/5032
|
|
||||||
[#5031]: https://github.com/nymtech/nym/pull/5031
|
|
||||||
[#5030]: https://github.com/nymtech/nym/pull/5030
|
|
||||||
[#5029]: https://github.com/nymtech/nym/pull/5029
|
|
||||||
[#5028]: https://github.com/nymtech/nym/pull/5028
|
|
||||||
[#5024]: https://github.com/nymtech/nym/pull/5024
|
|
||||||
[#5023]: https://github.com/nymtech/nym/pull/5023
|
|
||||||
[#5016]: https://github.com/nymtech/nym/pull/5016
|
|
||||||
[#5014]: https://github.com/nymtech/nym/pull/5014
|
|
||||||
[#5013]: https://github.com/nymtech/nym/pull/5013
|
|
||||||
[#5009]: https://github.com/nymtech/nym/pull/5009
|
|
||||||
[#5008]: https://github.com/nymtech/nym/pull/5008
|
|
||||||
[#4994]: https://github.com/nymtech/nym/pull/4994
|
|
||||||
[#4993]: https://github.com/nymtech/nym/pull/4993
|
|
||||||
[#4992]: https://github.com/nymtech/nym/pull/4992
|
|
||||||
[#4991]: https://github.com/nymtech/nym/pull/4991
|
|
||||||
[#4988]: https://github.com/nymtech/nym/pull/4988
|
|
||||||
[#4984]: https://github.com/nymtech/nym/pull/4984
|
|
||||||
[#4983]: https://github.com/nymtech/nym/pull/4983
|
|
||||||
[#4982]: https://github.com/nymtech/nym/pull/4982
|
|
||||||
[#4981]: https://github.com/nymtech/nym/pull/4981
|
|
||||||
[#4980]: https://github.com/nymtech/nym/pull/4980
|
|
||||||
[#4978]: https://github.com/nymtech/nym/pull/4978
|
|
||||||
[#4977]: https://github.com/nymtech/nym/pull/4977
|
|
||||||
[#4976]: https://github.com/nymtech/nym/pull/4976
|
|
||||||
[#4975]: https://github.com/nymtech/nym/pull/4975
|
|
||||||
[#4974]: https://github.com/nymtech/nym/pull/4974
|
|
||||||
[#4973]: https://github.com/nymtech/nym/pull/4973
|
|
||||||
[#4972]: https://github.com/nymtech/nym/pull/4972
|
|
||||||
[#4968]: https://github.com/nymtech/nym/pull/4968
|
|
||||||
[#4967]: https://github.com/nymtech/nym/pull/4967
|
|
||||||
[#4966]: https://github.com/nymtech/nym/pull/4966
|
|
||||||
[#4965]: https://github.com/nymtech/nym/pull/4965
|
|
||||||
[#4963]: https://github.com/nymtech/nym/pull/4963
|
|
||||||
[#4959]: https://github.com/nymtech/nym/pull/4959
|
|
||||||
[#4957]: https://github.com/nymtech/nym/pull/4957
|
|
||||||
[#4954]: https://github.com/nymtech/nym/pull/4954
|
|
||||||
[#4953]: https://github.com/nymtech/nym/pull/4953
|
|
||||||
[#4949]: https://github.com/nymtech/nym/pull/4949
|
|
||||||
[#4948]: https://github.com/nymtech/nym/pull/4948
|
|
||||||
[#4947]: https://github.com/nymtech/nym/pull/4947
|
|
||||||
[#4945]: https://github.com/nymtech/nym/pull/4945
|
|
||||||
[#4944]: https://github.com/nymtech/nym/pull/4944
|
|
||||||
[#4943]: https://github.com/nymtech/nym/pull/4943
|
|
||||||
[#4942]: https://github.com/nymtech/nym/pull/4942
|
|
||||||
[#4938]: https://github.com/nymtech/nym/pull/4938
|
|
||||||
[#4937]: https://github.com/nymtech/nym/pull/4937
|
|
||||||
[#4936]: https://github.com/nymtech/nym/pull/4936
|
|
||||||
[#4929]: https://github.com/nymtech/nym/pull/4929
|
|
||||||
[#4903]: https://github.com/nymtech/nym/pull/4903
|
|
||||||
[#4826]: https://github.com/nymtech/nym/pull/4826
|
|
||||||
[#4758]: https://github.com/nymtech/nym/pull/4758
|
|
||||||
|
|
||||||
## [2024.12-aero] (2024-10-17)
|
## [2024.12-aero] (2024-10-17)
|
||||||
|
|
||||||
- nym-node: don't use bloomfilters for double spending checks ([#4960])
|
- nym-node: don't use bloomfilters for double spending checks ([#4960])
|
||||||
|
|||||||
Generated
+1024
-1342
File diff suppressed because it is too large
Load Diff
+59
-51
@@ -61,6 +61,7 @@ members = [
|
|||||||
"common/ip-packet-requests",
|
"common/ip-packet-requests",
|
||||||
"common/ledger",
|
"common/ledger",
|
||||||
"common/mixnode-common",
|
"common/mixnode-common",
|
||||||
|
"common/models",
|
||||||
"common/network-defaults",
|
"common/network-defaults",
|
||||||
"common/node-tester-utils",
|
"common/node-tester-utils",
|
||||||
"common/nonexhaustive-delayqueue",
|
"common/nonexhaustive-delayqueue",
|
||||||
@@ -98,15 +99,17 @@ members = [
|
|||||||
"common/wasm/utils",
|
"common/wasm/utils",
|
||||||
"common/wireguard",
|
"common/wireguard",
|
||||||
"common/wireguard-types",
|
"common/wireguard-types",
|
||||||
"documentation/autodoc",
|
# "documentation/autodoc",
|
||||||
"explorer-api",
|
"explorer-api",
|
||||||
"explorer-api/explorer-api-requests",
|
"explorer-api/explorer-api-requests",
|
||||||
"explorer-api/explorer-client",
|
"explorer-api/explorer-client",
|
||||||
"gateway",
|
"gateway",
|
||||||
"integrations/bity",
|
"integrations/bity",
|
||||||
|
"mixnode",
|
||||||
"sdk/ffi/cpp",
|
"sdk/ffi/cpp",
|
||||||
"sdk/ffi/go",
|
"sdk/ffi/go",
|
||||||
"sdk/ffi/shared",
|
"sdk/ffi/shared",
|
||||||
|
"sdk/lib/socks5-listener",
|
||||||
"sdk/rust/nym-sdk",
|
"sdk/rust/nym-sdk",
|
||||||
"service-providers/authenticator",
|
"service-providers/authenticator",
|
||||||
"service-providers/common",
|
"service-providers/common",
|
||||||
@@ -118,14 +121,13 @@ members = [
|
|||||||
"nym-credential-proxy/nym-credential-proxy",
|
"nym-credential-proxy/nym-credential-proxy",
|
||||||
"nym-credential-proxy/nym-credential-proxy-requests",
|
"nym-credential-proxy/nym-credential-proxy-requests",
|
||||||
"nym-credential-proxy/vpn-api-lib-wasm",
|
"nym-credential-proxy/vpn-api-lib-wasm",
|
||||||
|
"nym-data-observatory",
|
||||||
"nym-network-monitor",
|
"nym-network-monitor",
|
||||||
"nyx-chain-watcher",
|
|
||||||
"nym-node",
|
"nym-node",
|
||||||
|
"nym-node/nym-node-http-api",
|
||||||
"nym-node/nym-node-requests",
|
"nym-node/nym-node-requests",
|
||||||
"nym-node/nym-node-metrics",
|
"nym-node-status-api",
|
||||||
"nym-node-status-api/nym-node-status-agent",
|
"nym-node-status-agent",
|
||||||
"nym-node-status-api/nym-node-status-api",
|
|
||||||
"nym-node-status-api/nym-node-status-client",
|
|
||||||
"nym-outfox",
|
"nym-outfox",
|
||||||
"nym-validator-rewarder",
|
"nym-validator-rewarder",
|
||||||
"tools/echo-server",
|
"tools/echo-server",
|
||||||
@@ -148,21 +150,22 @@ members = [
|
|||||||
"tools/internal/contract-state-importer/importer-contract",
|
"tools/internal/contract-state-importer/importer-contract",
|
||||||
"tools/internal/testnet-manager",
|
"tools/internal/testnet-manager",
|
||||||
"tools/internal/testnet-manager/dkg-bypass-contract",
|
"tools/internal/testnet-manager/dkg-bypass-contract",
|
||||||
"common/verloc",
|
|
||||||
"tools/internal/mixnet-connectivity-check",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
default-members = [
|
default-members = [
|
||||||
"clients/native",
|
"clients/native",
|
||||||
"clients/socks5",
|
"clients/socks5",
|
||||||
|
"common/models",
|
||||||
"explorer-api",
|
"explorer-api",
|
||||||
|
"gateway",
|
||||||
|
"mixnode",
|
||||||
"nym-api",
|
"nym-api",
|
||||||
"nym-credential-proxy/nym-credential-proxy",
|
"nym-credential-proxy/nym-credential-proxy",
|
||||||
|
"nym-data-observatory",
|
||||||
"nym-node",
|
"nym-node",
|
||||||
"nym-node-status-api/nym-node-status-agent",
|
"nym-node-status-api",
|
||||||
"nym-node-status-api/nym-node-status-api",
|
|
||||||
"nym-validator-rewarder",
|
"nym-validator-rewarder",
|
||||||
"nyx-chain-watcher",
|
"nym-node-status-api",
|
||||||
"service-providers/authenticator",
|
"service-providers/authenticator",
|
||||||
"service-providers/ip-packet-router",
|
"service-providers/ip-packet-router",
|
||||||
"service-providers/network-requester",
|
"service-providers/network-requester",
|
||||||
@@ -193,9 +196,9 @@ aes = "0.8.1"
|
|||||||
aes-gcm = "0.10.1"
|
aes-gcm = "0.10.1"
|
||||||
aes-gcm-siv = "0.11.1"
|
aes-gcm-siv = "0.11.1"
|
||||||
aead = "0.5.2"
|
aead = "0.5.2"
|
||||||
anyhow = "1.0.95"
|
anyhow = "1.0.90"
|
||||||
argon2 = "0.5.0"
|
argon2 = "0.5.0"
|
||||||
async-trait = "0.1.85"
|
async-trait = "0.1.83"
|
||||||
axum-client-ip = "0.6.1"
|
axum-client-ip = "0.6.1"
|
||||||
axum = "0.7.5"
|
axum = "0.7.5"
|
||||||
axum-extra = "0.9.4"
|
axum-extra = "0.9.4"
|
||||||
@@ -204,7 +207,7 @@ bincode = "1.3.3"
|
|||||||
bip39 = { version = "2.0.0", features = ["zeroize"] }
|
bip39 = { version = "2.0.0", features = ["zeroize"] }
|
||||||
bit-vec = "0.7.0" # can we unify those?
|
bit-vec = "0.7.0" # can we unify those?
|
||||||
bitvec = "1.0.0"
|
bitvec = "1.0.0"
|
||||||
blake3 = "1.5.5"
|
blake3 = "1.5.4"
|
||||||
bloomfilter = "1.0.14"
|
bloomfilter = "1.0.14"
|
||||||
bs58 = "0.5.1"
|
bs58 = "0.5.1"
|
||||||
bytecodec = "0.4.15"
|
bytecodec = "0.4.15"
|
||||||
@@ -214,20 +217,20 @@ celes = "2.4.0"
|
|||||||
cfg-if = "1.0.0"
|
cfg-if = "1.0.0"
|
||||||
chacha20 = "0.9.0"
|
chacha20 = "0.9.0"
|
||||||
chacha20poly1305 = "0.10.1"
|
chacha20poly1305 = "0.10.1"
|
||||||
chrono = "0.4.39"
|
chrono = "0.4.31"
|
||||||
cipher = "0.4.3"
|
cipher = "0.4.3"
|
||||||
clap = "4.5.26"
|
clap = "4.5.20"
|
||||||
clap_complete = "4.5"
|
clap_complete = "4.5"
|
||||||
clap_complete_fig = "4.5"
|
clap_complete_fig = "4.5"
|
||||||
colored = "2.0"
|
colored = "2.0"
|
||||||
comfy-table = "7.1.3"
|
comfy-table = "7.1.1"
|
||||||
console = "0.15.10"
|
console = "0.15.8"
|
||||||
console-subscriber = "0.1.1"
|
console-subscriber = "0.1.1"
|
||||||
console_error_panic_hook = "0.1"
|
console_error_panic_hook = "0.1"
|
||||||
const-str = "0.5.6"
|
const-str = "0.5.6"
|
||||||
const_format = "0.2.34"
|
const_format = "0.2.33"
|
||||||
criterion = "0.5"
|
criterion = "0.4"
|
||||||
csv = "1.3.1"
|
csv = "1.3.0"
|
||||||
ctr = "0.9.1"
|
ctr = "0.9.1"
|
||||||
cupid = "0.6.1"
|
cupid = "0.6.1"
|
||||||
curve25519-dalek = "4.1"
|
curve25519-dalek = "4.1"
|
||||||
@@ -244,8 +247,8 @@ etherparse = "0.13.0"
|
|||||||
envy = "0.4"
|
envy = "0.4"
|
||||||
eyre = "0.6.9"
|
eyre = "0.6.9"
|
||||||
fastrand = "2.1.1"
|
fastrand = "2.1.1"
|
||||||
flate2 = "1.0.35"
|
flate2 = "1.0.34"
|
||||||
futures = "0.3.31"
|
futures = "0.3.28"
|
||||||
futures-util = "0.3"
|
futures-util = "0.3"
|
||||||
generic-array = "0.14.7"
|
generic-array = "0.14.7"
|
||||||
getrandom = "0.2.10"
|
getrandom = "0.2.10"
|
||||||
@@ -261,10 +264,9 @@ http-body-util = "0.1"
|
|||||||
httpcodec = "0.2.3"
|
httpcodec = "0.2.3"
|
||||||
humantime = "2.1.0"
|
humantime = "2.1.0"
|
||||||
humantime-serde = "1.1.1"
|
humantime-serde = "1.1.1"
|
||||||
human-repr = "1.1.0"
|
|
||||||
hyper = "1.4.1"
|
hyper = "1.4.1"
|
||||||
hyper-util = "0.1"
|
hyper-util = "0.1"
|
||||||
indicatif = "0.17.9"
|
indicatif = "0.17.8"
|
||||||
inquire = "0.6.2"
|
inquire = "0.6.2"
|
||||||
ip_network = "0.4.1"
|
ip_network = "0.4.1"
|
||||||
ipnetwork = "0.20"
|
ipnetwork = "0.20"
|
||||||
@@ -289,7 +291,7 @@ parking_lot = "0.12.3"
|
|||||||
pem = "0.8"
|
pem = "0.8"
|
||||||
petgraph = "0.6.5"
|
petgraph = "0.6.5"
|
||||||
pin-project = "1.1"
|
pin-project = "1.1"
|
||||||
pin-project-lite = "0.2.16"
|
pin-project-lite = "0.2.14"
|
||||||
pretty_env_logger = "0.4.0"
|
pretty_env_logger = "0.4.0"
|
||||||
publicsuffix = "2.2.3"
|
publicsuffix = "2.2.3"
|
||||||
quote = "1"
|
quote = "1"
|
||||||
@@ -307,12 +309,12 @@ rocket_cors = "0.6.0"
|
|||||||
rocket_okapi = "0.8.0"
|
rocket_okapi = "0.8.0"
|
||||||
safer-ffi = "0.1.13"
|
safer-ffi = "0.1.13"
|
||||||
schemars = "0.8.21"
|
schemars = "0.8.21"
|
||||||
semver = "1.0.24"
|
semver = "1.0.23"
|
||||||
serde = "1.0.217"
|
serde = "1.0.211"
|
||||||
serde_bytes = "0.11.15"
|
serde_bytes = "0.11.15"
|
||||||
serde_derive = "1.0"
|
serde_derive = "1.0"
|
||||||
serde_json = "1.0.135"
|
serde_json = "1.0.132"
|
||||||
serde_json_path = "0.7.1"
|
serde_json_path = "0.6.7"
|
||||||
serde_repr = "0.1"
|
serde_repr = "0.1"
|
||||||
serde_with = "3.9.0"
|
serde_with = "3.9.0"
|
||||||
serde_yaml = "0.9.25"
|
serde_yaml = "0.9.25"
|
||||||
@@ -326,34 +328,34 @@ subtle-encoding = "0.5"
|
|||||||
syn = "1"
|
syn = "1"
|
||||||
sysinfo = "0.30.13"
|
sysinfo = "0.30.13"
|
||||||
tap = "1.0.1"
|
tap = "1.0.1"
|
||||||
tar = "0.4.43"
|
tar = "0.4.42"
|
||||||
tempfile = "3.15"
|
tempfile = "3.5.0"
|
||||||
thiserror = "1.0.64"
|
thiserror = "1.0.64"
|
||||||
time = "0.3.37"
|
time = "0.3.30"
|
||||||
tokio = "1.39"
|
tokio = "1.39"
|
||||||
tokio-stream = "0.1.17"
|
tokio-stream = "0.1.16"
|
||||||
tokio-test = "0.4.4"
|
tokio-test = "0.4.4"
|
||||||
tokio-tun = "0.11.5"
|
tokio-tun = "0.11.5"
|
||||||
tokio-tungstenite = { version = "0.20.1" }
|
tokio-tungstenite = { version = "0.20.1" }
|
||||||
tokio-util = "0.7.13"
|
tokio-util = "0.7.12"
|
||||||
toml = "0.8.19"
|
toml = "0.8.14"
|
||||||
tower = "0.4.13"
|
tower = "0.4.13"
|
||||||
tower-http = "0.5.2"
|
tower-http = "0.5.2"
|
||||||
tracing = "0.1.41"
|
tracing = "0.1.37"
|
||||||
tracing-opentelemetry = "0.19.0"
|
tracing-opentelemetry = "0.19.0"
|
||||||
tracing-subscriber = "0.3.19"
|
tracing-subscriber = "0.3.16"
|
||||||
tracing-tree = "0.2.2"
|
tracing-tree = "0.2.2"
|
||||||
tracing-log = "0.2"
|
tracing-log = "0.2"
|
||||||
ts-rs = "10.1.0"
|
ts-rs = "10.0.0"
|
||||||
tungstenite = { version = "0.20.1", default-features = false }
|
tungstenite = { version = "0.20.1", default-features = false }
|
||||||
url = "2.5"
|
url = "2.5"
|
||||||
utoipa = "5.2"
|
utoipa = "4.2"
|
||||||
utoipa-swagger-ui = "8.0"
|
utoipa-swagger-ui = "7.1"
|
||||||
utoipauto = "0.2"
|
utoipauto = "0.1"
|
||||||
uuid = "*"
|
uuid = "*"
|
||||||
vergen = { version = "=8.3.1", default-features = false }
|
vergen = { version = "=8.3.1", default-features = false }
|
||||||
walkdir = "2"
|
walkdir = "2"
|
||||||
wasm-bindgen-test = "0.3.49"
|
wasm-bindgen-test = "0.3.43"
|
||||||
x25519-dalek = "2.0.0"
|
x25519-dalek = "2.0.0"
|
||||||
zeroize = "1.6.0"
|
zeroize = "1.6.0"
|
||||||
|
|
||||||
@@ -396,17 +398,19 @@ prost = { version = "0.12", default-features = false }
|
|||||||
|
|
||||||
# wasm-related dependencies
|
# wasm-related dependencies
|
||||||
gloo-utils = "0.2.0"
|
gloo-utils = "0.2.0"
|
||||||
gloo-net = "0.6.0"
|
gloo-net = "0.5.0"
|
||||||
|
|
||||||
# TODO: migrate to 0.6+
|
# use a separate branch due to feature unification failures
|
||||||
indexed_db_futures = "0.4.2"
|
# this is blocked until the upstream removes outdates `wasm_bindgen` feature usage
|
||||||
js-sys = "0.3.76"
|
# indexed_db_futures = "0.4.1"
|
||||||
|
indexed_db_futures = { git = "https://github.com/TiemenSch/rust-indexed-db", branch = "update-uuid" }
|
||||||
|
js-sys = "0.3.70"
|
||||||
serde-wasm-bindgen = "0.6.5"
|
serde-wasm-bindgen = "0.6.5"
|
||||||
tsify = "0.4.5"
|
tsify = "0.4.5"
|
||||||
wasm-bindgen = "0.2.99"
|
wasm-bindgen = "0.2.95"
|
||||||
wasm-bindgen-futures = "0.4.49"
|
wasm-bindgen-futures = "0.4.45"
|
||||||
wasmtimer = "0.4.1"
|
wasmtimer = "0.2.0"
|
||||||
web-sys = "0.3.76"
|
web-sys = "0.3.72"
|
||||||
|
|
||||||
# Profile settings for individual crates
|
# Profile settings for individual crates
|
||||||
|
|
||||||
@@ -416,6 +420,10 @@ web-sys = "0.3.76"
|
|||||||
[profile.dev.package.sqlx-macros]
|
[profile.dev.package.sqlx-macros]
|
||||||
opt-level = 3
|
opt-level = 3
|
||||||
|
|
||||||
|
[profile.release.package.nym-socks5-listener]
|
||||||
|
strip = true
|
||||||
|
codegen-units = 1
|
||||||
|
|
||||||
[profile.release.package.nym-client-wasm]
|
[profile.release.package.nym-client-wasm]
|
||||||
# lto = true
|
# lto = true
|
||||||
opt-level = 'z'
|
opt-level = 'z'
|
||||||
|
|||||||
@@ -1,23 +0,0 @@
|
|||||||
Boost Software License - Version 1.0 - August 17th, 2003
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person or organization
|
|
||||||
obtaining a copy of the software and accompanying documentation covered by
|
|
||||||
this license (the "Software") to use, reproduce, display, distribute,
|
|
||||||
execute, and transmit the Software, and to prepare derivative works of the
|
|
||||||
Software, and to permit third-parties to whom the Software is furnished to
|
|
||||||
do so, all subject to the following:
|
|
||||||
|
|
||||||
The copyright notices in the Software and this entire statement, including
|
|
||||||
the above license grant, this restriction and the following disclaimer,
|
|
||||||
must be included in all copies of the Software, in whole or in part, and
|
|
||||||
all derivative works of the Software, unless such copies or derivative
|
|
||||||
works are solely in the form of machine-executable object code generated by
|
|
||||||
a source language processor.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
|
||||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
|
||||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
|
||||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
DEALINGS IN THE SOFTWARE.
|
|
||||||
@@ -14,7 +14,6 @@ The platform is composed of multiple Rust crates. Top-level executable binary cr
|
|||||||
* `nym-socks5-client` - a Socks5 proxy you can run on your machine and use with existing applications.
|
* `nym-socks5-client` - a Socks5 proxy you can run on your machine and use with existing applications.
|
||||||
* `nym-explorer` - a (projected) block explorer and (existing) mixnet viewer.
|
* `nym-explorer` - a (projected) block explorer and (existing) mixnet viewer.
|
||||||
* `nym-wallet` - a desktop wallet implemented using the [Tauri](https://tauri.studio/en/docs/about/intro) framework.
|
* `nym-wallet` - a desktop wallet implemented using the [Tauri](https://tauri.studio/en/docs/about/intro) framework.
|
||||||
* `nym-cli` - a tool for interacting with the network from the CLI.
|
|
||||||
<!-- coming soon
|
<!-- coming soon
|
||||||
* `nym-network-monitor` - sends packets through the full system to check that they are working as expected, and stores node uptime histories as the basis of a rewards system ("mixmining" or "proof-of-mixing").
|
* `nym-network-monitor` - sends packets through the full system to check that they are working as expected, and stores node uptime histories as the basis of a rewards system ("mixmining" or "proof-of-mixing").
|
||||||
-->
|
-->
|
||||||
@@ -36,20 +35,24 @@ client ───► Gateway ──┘ mix │ mix ┌─►mix ───►
|
|||||||
### Building
|
### Building
|
||||||
|
|
||||||
* Platform build instructions are available on Nym [Operators Guide documentation](https://nymtech.net/operators/binaries/building-nym.html).
|
* Platform build instructions are available on Nym [Operators Guide documentation](https://nymtech.net/operators/binaries/building-nym.html).
|
||||||
* Wallet build instructions are available [here](https://github.com/nymtech/nym/tree/master/nym-wallet#installation-prerequisites---linux--mac).
|
* Wallet build instructions are available on Nym [Technical docs](https://nymtech.net/docs/wallet/desktop-wallet.html).
|
||||||
|
|
||||||
### Developing
|
### Developing
|
||||||
|
|
||||||
|
There's a [`sandbox.env`](https://github.com/nymtech/nym/envs/sandbox.env) file provided which you can rename to `.env` if you want convenient testing environment. Read more about sandbox environment in our [Operators Guide page](https://nymtech.net/operators/sandbox.html).
|
||||||
|
|
||||||
References for developers:
|
References for developers:
|
||||||
|
|
||||||
* [Dev Docs](https://nym.com/docs/developers)
|
* [Developers Portal](https://nymtech.net/developers)
|
||||||
* [SDKs](https://nym.com/docs/developers/rust)
|
* [Typescript SDKs](https://sdk.nymtech.net/)
|
||||||
* [Network Docs](https://nym.com/docs/network)
|
* [Technical Documentation - Nym network overview](https://nymtech.net/docs/)
|
||||||
* [Release Cycle - git flow](https://nym.com/docs/operators/release-cycle)
|
* [Release Cycle - git flow](https://nymtech.net/operators/release-cycle.html)
|
||||||
|
|
||||||
### Developer chat
|
### Developer chat
|
||||||
|
|
||||||
You can chat to us in the #dev channel on [Matrix](https://matrix.to/#/#dev:nymtech.chat) or on the [Nym Forum](https://forum.nymtech.net).
|
You can chat to us in two places:
|
||||||
|
* The #dev channel on [Matrix](https://matrix.to/#/#dev:nymtech.chat)
|
||||||
|
* The various developer channels on [Discord](https://nymtech.net/go/discord)
|
||||||
|
|
||||||
### Tokenomics & Rewards
|
### Tokenomics & Rewards
|
||||||
|
|
||||||
@@ -66,4 +69,4 @@ As a general approach, licensing is as follows this pattern:
|
|||||||
- libraries and components are Apache 2.0 or MIT
|
- libraries and components are Apache 2.0 or MIT
|
||||||
- documentation is Apache 2.0 or CC0-1.0
|
- documentation is Apache 2.0 or CC0-1.0
|
||||||
|
|
||||||
Nym Node Operators and Validators Temrs and Conditions can be found [here](https://nym.com/terms-and-conditions/operators/v1.0.0).
|
Nym Node Operators and Validators Temrs and Conditions can be found [here](https://nymtech.net/terms-and-conditions/operators/v1.0.0).
|
||||||
|
|||||||
+56
-68
@@ -3,23 +3,37 @@ Critical bug or security issue 💥
|
|||||||
If you're here because you're trying to figure out how to notify us of a security issue, send us a PGP encrypted email to:
|
If you're here because you're trying to figure out how to notify us of a security issue, send us a PGP encrypted email to:
|
||||||
|
|
||||||
```
|
```
|
||||||
security@nym.com
|
security@nymte.ch
|
||||||
```
|
```
|
||||||
|
|
||||||
Encrypted with our public key which is available below in plain text and also on keyservers:
|
Encrypted with our public key which is available below in plain text and also on keyservers:
|
||||||
|
|
||||||
```
|
```
|
||||||
sec rsa4096/7C3C727F05090550 2023-10-30 [SC] [expire : 2026-10-29]
|
pub rsa4096 2023-10-30 [SC] [expire : 2026-10-29]
|
||||||
24B2592E801A5AAA8666C8BA7C3C727F05090550
|
24B2592E801A5AAA8666C8BA7C3C727F05090550
|
||||||
uid [ ultime ] Security Nym Technologies <security@nym.com>
|
uid [ ultime ] Security Nym Technologies <security@nymte.ch>
|
||||||
ssb rsa4096/ACD0FBD79DC70ACC 2023-10-30 [E] [expire : 2026-10-29]
|
sub rsa4096 2023-10-30 [E] [expire : 2026-10-29]
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
The fingerprint of the key is on the second line above.
|
The fingerprint of the key is on the second line above.
|
||||||
|
|
||||||
|
If you need to chat __urgently__ to our team for a __critical__ security issue:
|
||||||
|
|
||||||
|
go to Matrix, and alert the core engineers with a private direct message:
|
||||||
|
|
||||||
|
Jedrzej Stuczynski @jstuczyn:nymtech.chat
|
||||||
|
Mark Sinclair @mark:nymtech.chat
|
||||||
|
Raphaël Walther @raphael:nymtech.chat
|
||||||
|
|
||||||
Please avoid opening public issues on GitHub that contain information about a potential security vulnerability as this makes it difficult to reduce the impact and harm of valid security issues.
|
Please avoid opening public issues on GitHub that contain information about a potential security vulnerability as this makes it difficult to reduce the impact and harm of valid security issues.
|
||||||
|
|
||||||
|
If you don't know what Matrix is, you can follow this documentation to create an account on this federation of instant messaging servers:
|
||||||
|
|
||||||
|
[Matrix for Instant Messaging](https://matrix.org/docs/chat_basics/matrix-for-im/)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
```
|
```
|
||||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||||
|
|
||||||
@@ -34,69 +48,43 @@ vMFUIzBMHOPXH16036zGyFMC1esRd2qqil4b9KtLgCOkrD1VgpjcveoA0VyMJCN6
|
|||||||
LmKTrVjwjjDMxby+d49BolRWGnCofXozXwvNQx+CYv8M2WPErTpyYoofYFtpqr7A
|
LmKTrVjwjjDMxby+d49BolRWGnCofXozXwvNQx+CYv8M2WPErTpyYoofYFtpqr7A
|
||||||
fIufc/e0+um3zoGIbHejrhsbuH9Qf+MKsI+Ng93bdDtjeHz6MEgAlsTm0qeizYpj
|
fIufc/e0+um3zoGIbHejrhsbuH9Qf+MKsI+Ng93bdDtjeHz6MEgAlsTm0qeizYpj
|
||||||
IyKZIObPmfvrAm08hFZ8JnGk+XuooF36XWbJYjCCy0bOyMw1r7ZG99TcSwARAQAB
|
IyKZIObPmfvrAm08hFZ8JnGk+XuooF36XWbJYjCCy0bOyMw1r7ZG99TcSwARAQAB
|
||||||
tCxTZWN1cml0eSBOeW0gVGVjaG5vbG9naWVzIDxzZWN1cml0eUBueW0uY29tPokC
|
tC1TZWN1cml0eSBOeW0gVGVjaG5vbG9naWVzIDxzZWN1cml0eUBueW10ZS5jaD6J
|
||||||
VAQTAQoAPhYhBCSyWS6AGlqqhmbIunw8cn8FCQVQBQJnSd5VAhsDBQkFo5qABQsJ
|
AlQEEwEKAD4WIQQkslkugBpaqoZmyLp8PHJ/BQkFUAUCZT9elwIbAwUJBaOagAUL
|
||||||
CAcDBRUKCQgLBRYCAwEAAh4BAheAAAoJEHw8cn8FCQVQPPIP/ipGz2zLAjE2dSE3
|
CQgHAwUVCgkICwUWAgMBAAIeAQIXgAAKCRB8PHJ/BQkFUL7dD/9zO73uI5VR+SWx
|
||||||
VcqOvras0DfqIL9HDm26Dg6QO2D/4YRntw0RqVyuy+zFnRUm+RZCKLPLUzbQ9Wjb
|
PFmJW+9QsPiQbVRvGwNZurctmQ2s2Pe0vHRELFeqD5oYvSx2Lequ3Ir+zn/C3kDM
|
||||||
G/Og5ttQVYQMu5eKu7OMvXkrbRo3teZFU+8IL08zIW6pyf9haxO6YMhLRy6cLYwW
|
kNs40obSL6jCBiLPkxEY0JqzPM9jZr7EjvlibWV3f6DxooRIqEyfN57I3OBGlqZE
|
||||||
0EYC6Qzn5gz3kI7VkI8fWfs2Dk4XEV3D+SVtBoF6KRxMXT6HZvpzoMSEJZBoNj8S
|
0Mx7sQuCcgau8C70DF952QhKUwXC2cmpmDKHVEEoio1xGSD4dQhGapCB32RQGtna
|
||||||
jw0TF8TFUQf49jUQbIHumukMswolrHi8a5ej8DSfNwSgz+Tt8oh5lu01kyUJiHn7
|
OGfAO9celNMvSq0Lp+aJxeACmWFY5T4/y79JPcT5vSs/yEIRmaH/fn2piwaFBsIq
|
||||||
nuHaY4Y9cHUVAOSwq/hovG52+ZE1r3aiswvle/B19o9pKeWWVvacSptGxDQagBtQ
|
gHJJMxO3740P1hF8j7KWUoUofuFaEALHBpEpjWTOj8ej1wmFlu+5F+jSVoc781Wb
|
||||||
igoNLdRvY0XN2TEyX9pOHR0AoVOxtIW11CpkKuDbQG9vPwovqJ2L6+Fh3pzHYzcI
|
ZZXu04cOBXnGTogzSxMpBe9TtLb28zd6WzFotC25KTI3pngMzXsQGLJLOwvoZKiS
|
||||||
2GIShNm/Z2SZBiUqbljJe9H4UAT/aHgMINkEG8qzUKwO42MA5HJT7YbHTR17/QSF
|
LFjPRjg1rwobmB3Q3J2W5GYSveia0CDsZGP+g87GVVf/oD2Djpa68xyVYwIYeA6T
|
||||||
Il5dhneRzmSbNcW2rdRwx/BmzrcsFJfqCt4JG/WDF293xSOjhFqQYvU4gCO+OB7o
|
3DNdS77qHiRuGiS4kWXyVjDqOICboR4uCvt09zlkBuLDdTWqWYARUvZjtjs4w/Ol
|
||||||
KXjX907XXDjS2KEJ71OGqVfk/P7BqEfQNfrLtb02TyXJAPQXHhybv23c4E7zUs9V
|
rdrBI3A88ti8fRldYaNpu17ME1ilpN44yKoJtqiWc3Tisk8eYLfx6c7FQF3PrRva
|
||||||
lMjNizzxYB96uwJb0LAB2ijzEwoP91uGT2tFjk6F08x2QiArmXUdgrv44b39Stia
|
mr7FZvhFsYML5CeNFHTEzN6Y3jjKN/60DvCfodWnWFK47Txkl8UAXGY2W9B0fWqQ
|
||||||
gJS0GYKqSzyr10xHhUuDA+GKYtcitC1TZWN1cml0eSBOeW0gVGVjaG5vbG9naWVz
|
wUVr8uLuMyyMiKbeoufi7rGOj6AMErkCDQRlP16XARAA8FGmD5J3tM1BOM1niJxZ
|
||||||
IDxzZWN1cml0eUBueW10ZS5jaD6JAjYEMAEKACAWIQQkslkugBpaqoZmyLp8PHJ/
|
JTdCauzEtxEoBL0RuqGBkR8U29sRM6DwuzjU7PwscFnBaGyU+eU73GwGkH3ozFfF
|
||||||
BQkFUAUCZ0nftQIdIAAKCRB8PHJ/BQkFUFHDEACtyNuUEjKCLAT5mSfow85PjFgo
|
tllYhQrhP/kkN+0rEO5Xi+nR+4JCFRqrf3nJXAAPfiksURMp8er1dUOY2/e1ZSoL
|
||||||
o8kHjQr/IIQ7ZbBOHeJJcrxDuypssiLh5XUjF3x5BiBfZ6vCxSb81RRwsDMp0mA1
|
tS+nzUivV8CfE+pgj/5YtGwPC+KYHLATkKkMELCrbW4UO06VWOqQsvr6kivXuJQQ
|
||||||
qzv9G8sgW0HTQUnZ9oH6CYut2NgzAnQpmuacrunm9Zy0FJ3ejbmwUY/NqK6gJkle
|
LdEAMpBlADmXFG45DmPKQzsBWUgvTwyGy3LX0nys8cgpex9BH8hhr01QmGyP469s
|
||||||
66duHKhAy7DWjj7amd0C8bPDR+PA44fI3MezDHkQNaauKZTRqd1TqH8Qk5PAl4cB
|
N3cNrtFuu8U6RAsiCD/8mlBuD3EQEU5SF0lc7kCICAZk+wElmXnimEi0TOYsbz6k
|
||||||
o5gVzeZh/U7/usvtGhazAIUF5BqK6bTmDnYopg+2x8jjwrG4+08GrttZkNjBLXeA
|
90lteicX70rA9GNeyI76H+VSOYvWpkRwaJAgUdzrAM1o9SHASq+cZ6nD85OZioQk
|
||||||
Y/2U064yMz12LPv01qqAFdZ+coRy/ps/gOQTz34/VeW0CFy7TMqs4t3vSBWTqU7w
|
DWM6+Q+sf2oen0qJnnGmUr93kJIC0PIdgrXRrtiNfeRa1Z/H0LmREyyEMoFiVivn
|
||||||
hnw/qj6cM33fdxctj6KDgJSCkZdx2fvwXgxiPqUa5+j9FlFBeD5RDAl6g6t8N1/K
|
z1vVk85Oq6Sf3ltUwvmDzuuJOtsp2Qp6+x6Snn/yKauI4uf4Cf/wKUch4r6Bwgg5
|
||||||
Xca+zNYuSZgc297q1D+mtSD1C7uJNPxoAl+Bv5KNKpsjfQ+m04++CIFtGyX22aCA
|
Dw49ky7lwlnALio4GIVoGLpLef93wWoDmp4Klyh3ZPf2nB0U91u3bHRUo7m+D7QJ
|
||||||
h2/tHwQZIXhOiMAKOoupidDVDhgxtCJ3Ps416xL0sTZfsPfg+j1Uv/Em9pzPClEl
|
98cyKtqLLzjg7szGf60pIWNWRsadYQT3bSncynqknAjOV3BCvx6/ivsnpj//QjYR
|
||||||
fX6+1O4DdSyZUQ4VsjMu/H5W/NQdbHgmqFrxQ6WX/0s5GMwO6GMDiPe8sOrwz9wD
|
HtviUAcQ1DBB6UC6q23FIs0AEQEAAYkCPAQYAQoAJhYhBCSyWS6AGlqqhmbIunw8
|
||||||
WYtyjafxXOHEZ1OjYX5gr7bGaG4oKc2btTJN0B3Phg4dStnHCNjEYccxuV3507fj
|
cn8FCQVQBQJlP16XAhsMBQkFo5qAAAoJEHw8cn8FCQVQzukP/iLxjOxT+UpPR//c
|
||||||
HnNotkpXF2nGLxy+PYkCVAQTAQoAPhYhBCSyWS6AGlqqhmbIunw8cn8FCQVQBQJl
|
prDVSLkP4pF5bmw36U07jvqpS+/KTXsxiiQleffRabOpNLcd+K1ueavyt9nnIwHH
|
||||||
P16XAhsDBQkFo5qABQsJCAcDBRUKCQgLBRYCAwEAAh4BAheAAAoJEHw8cn8FCQVQ
|
tHS9kM9A7DBw3LnpEbXki46QDCCI6niGijlLOEeAWqnocwMNTT05wVVgCtO3DQP2
|
||||||
vt0P/3M7ve4jlVH5JbE8WYlb71Cw+JBtVG8bA1m6ty2ZDazY97S8dEQsV6oPmhi9
|
MoSCcqHpXDChvOyr5d5xjYLVJhlctIMSomcVzGryjknPu0Yj/TkC/4c+m86ZWQUD
|
||||||
LHYt6q7civ7Of8LeQMyQ2zjShtIvqMIGIs+TERjQmrM8z2NmvsSO+WJtZXd/oPGi
|
HqMHQIuiEenvb62/F4c5OJIRZPEn70wdddkgJuJU3eHdHrnuhCkjCC93GQGbGj03
|
||||||
hEioTJ83nsjc4EaWpkTQzHuxC4JyBq7wLvQMX3nZCEpTBcLZyamYModUQSiKjXEZ
|
Zqos6699y6hmPeD3U5IUv8ujwZYVCCuDm8gJfrp3R6WLfeZeK9WmTVBpCzsDg3fV
|
||||||
IPh1CEZqkIHfZFAa2do4Z8A71x6U0y9KrQun5onF4AKZYVjlPj/Lv0k9xPm9Kz/I
|
hSwmOk6pp8DAq1/Dev3yRkFggCEyGK6c9b+a0CRBncl8e5Q0QQIzNiS/uExQP3h+
|
||||||
QhGZof9+famLBoUGwiqAckkzE7fvjQ/WEXyPspZShSh+4VoQAscGkSmNZM6Px6PX
|
ELJs3P0MLP+6FWhNUry09n3lnWkr1hY+v1M0GAxbfdv/tsCN1Pq/VQEz+CTqXqya
|
||||||
CYWW77kX6NJWhzvzVZtlle7Thw4FecZOiDNLEykF71O0tvbzN3pbMWi0LbkpMjem
|
ftWldOHWw6Hh+gtwxcHjG4MBOrO5oICQ3lh2hGwQ58cDgZYSK/OGgJ9BggFl1CcM
|
||||||
eAzNexAYsks7C+hkqJIsWM9GODWvChuYHdDcnZbkZhK96JrQIOxkY/6DzsZVV/+g
|
0uGC0/TRCI1zt/4y+7efSZQMZkHo7VC/3MFbp2hcNejpW+BxVuwKTunFvWK3TLhq
|
||||||
PYOOlrrzHJVjAhh4DpPcM11LvuoeJG4aJLiRZfJWMOo4gJuhHi4K+3T3OWQG4sN1
|
sSlQ5yyhqchooepsFHq9bosKFjLJC01uprBv1rinoNduOy43FbyS7JPRRspANN0R
|
||||||
NapZgBFS9mO2OzjD86Wt2sEjcDzy2Lx9GV1ho2m7XswTWKWk3jjIqgm2qJZzdOKy
|
iC2pMbWdE0ZTQaFq6tPIg058pjqi
|
||||||
Tx5gt/HpzsVAXc+tG9qavsVm+EWxgwvkJ40UdMTM3pjeOMo3/rQO8J+h1adYUrjt
|
=nqgX
|
||||||
PGSXxQBcZjZb0HR9apDBRWvy4u4zLIyIpt6i5+LusY6PoAwSuQINBGU/XpcBEADw
|
|
||||||
UaYPkne0zUE4zWeInFklN0Jq7MS3ESgEvRG6oYGRHxTb2xEzoPC7ONTs/CxwWcFo
|
|
||||||
bJT55TvcbAaQfejMV8W2WViFCuE/+SQ37SsQ7leL6dH7gkIVGqt/eclcAA9+KSxR
|
|
||||||
Eynx6vV1Q5jb97VlKgu1L6fNSK9XwJ8T6mCP/li0bA8L4pgcsBOQqQwQsKttbhQ7
|
|
||||||
TpVY6pCy+vqSK9e4lBAt0QAykGUAOZcUbjkOY8pDOwFZSC9PDIbLctfSfKzxyCl7
|
|
||||||
H0EfyGGvTVCYbI/jr2w3dw2u0W67xTpECyIIP/yaUG4PcRARTlIXSVzuQIgIBmT7
|
|
||||||
ASWZeeKYSLRM5ixvPqT3SW16JxfvSsD0Y17Ijvof5VI5i9amRHBokCBR3OsAzWj1
|
|
||||||
IcBKr5xnqcPzk5mKhCQNYzr5D6x/ah6fSomecaZSv3eQkgLQ8h2CtdGu2I195FrV
|
|
||||||
n8fQuZETLIQygWJWK+fPW9WTzk6rpJ/eW1TC+YPO64k62ynZCnr7HpKef/Ipq4ji
|
|
||||||
5/gJ//ApRyHivoHCCDkPDj2TLuXCWcAuKjgYhWgYukt5/3fBagOangqXKHdk9/ac
|
|
||||||
HRT3W7dsdFSjub4PtAn3xzIq2osvOODuzMZ/rSkhY1ZGxp1hBPdtKdzKeqScCM5X
|
|
||||||
cEK/Hr+K+yemP/9CNhEe2+JQBxDUMEHpQLqrbcUizQARAQABiQI8BBgBCgAmFiEE
|
|
||||||
JLJZLoAaWqqGZsi6fDxyfwUJBVAFAmU/XpcCGwwFCQWjmoAACgkQfDxyfwUJBVDO
|
|
||||||
6Q/+IvGM7FP5Sk9H/9ymsNVIuQ/ikXlubDfpTTuO+qlL78pNezGKJCV599Fps6k0
|
|
||||||
tx34rW55q/K32ecjAce0dL2Qz0DsMHDcuekRteSLjpAMIIjqeIaKOUs4R4Baqehz
|
|
||||||
Aw1NPTnBVWAK07cNA/YyhIJyoelcMKG87Kvl3nGNgtUmGVy0gxKiZxXMavKOSc+7
|
|
||||||
RiP9OQL/hz6bzplZBQMeowdAi6IR6e9vrb8Xhzk4khFk8SfvTB112SAm4lTd4d0e
|
|
||||||
ue6EKSMIL3cZAZsaPTdmqizrr33LqGY94PdTkhS/y6PBlhUIK4ObyAl+undHpYt9
|
|
||||||
5l4r1aZNUGkLOwODd9WFLCY6TqmnwMCrX8N6/fJGQWCAITIYrpz1v5rQJEGdyXx7
|
|
||||||
lDRBAjM2JL+4TFA/eH4Qsmzc/Qws/7oVaE1SvLT2feWdaSvWFj6/UzQYDFt92/+2
|
|
||||||
wI3U+r9VATP4JOperJp+1aV04dbDoeH6C3DFweMbgwE6s7mggJDeWHaEbBDnxwOB
|
|
||||||
lhIr84aAn0GCAWXUJwzS4YLT9NEIjXO3/jL7t59JlAxmQejtUL/cwVunaFw16Olb
|
|
||||||
4HFW7ApO6cW9YrdMuGqxKVDnLKGpyGih6mwUer1uiwoWMskLTW6msG/WuKeg1247
|
|
||||||
LjcVvJLsk9FGykA03RGILakxtZ0TRlNBoWrq08iDTnymOqI=
|
|
||||||
=QPTf
|
|
||||||
-----END PGP PUBLIC KEY BLOCK-----
|
-----END PGP PUBLIC KEY BLOCK-----
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "nym-client"
|
name = "nym-client"
|
||||||
version = "1.1.46"
|
version = "1.1.42"
|
||||||
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jędrzej Stuczyński <andrew@nymtech.net>"]
|
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jędrzej Stuczyński <andrew@nymtech.net>"]
|
||||||
description = "Implementation of the Nym Client"
|
description = "Implementation of the Nym Client"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|||||||
@@ -3,10 +3,13 @@
|
|||||||
|
|
||||||
use crate::commands::try_load_current_config;
|
use crate::commands::try_load_current_config;
|
||||||
use crate::{
|
use crate::{
|
||||||
client::SocketClient,
|
client::{config::Config, SocketClient},
|
||||||
commands::{override_config, OverrideConfig},
|
commands::{override_config, OverrideConfig},
|
||||||
|
error::ClientError,
|
||||||
};
|
};
|
||||||
use clap::Args;
|
use clap::Args;
|
||||||
|
use log::*;
|
||||||
|
use nym_bin_common::version_checker::is_minor_version_compatible;
|
||||||
use nym_client_core::cli_helpers::client_run::CommonClientRunArgs;
|
use nym_client_core::cli_helpers::client_run::CommonClientRunArgs;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::net::IpAddr;
|
use std::net::IpAddr;
|
||||||
@@ -45,12 +48,36 @@ impl From<Run> for OverrideConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// this only checks compatibility between config the binary. It does not take into consideration
|
||||||
|
// network version. It might do so in the future.
|
||||||
|
fn version_check(cfg: &Config) -> bool {
|
||||||
|
let binary_version = env!("CARGO_PKG_VERSION");
|
||||||
|
let config_version = &cfg.base.client.version;
|
||||||
|
if binary_version == config_version {
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
warn!("The native-client binary has different version than what is specified in config file! {} and {}", binary_version, config_version);
|
||||||
|
if is_minor_version_compatible(binary_version, config_version) {
|
||||||
|
info!("but they are still semver compatible. However, consider running the `upgrade` command");
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
error!("and they are semver incompatible! - please run the `upgrade` command before attempting `run` again");
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) async fn execute(args: Run) -> Result<(), Box<dyn Error + Send + Sync>> {
|
pub(crate) async fn execute(args: Run) -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
eprintln!("Starting client {}...", args.common_args.id);
|
eprintln!("Starting client {}...", args.common_args.id);
|
||||||
|
|
||||||
let mut config = try_load_current_config(&args.common_args.id).await?;
|
let mut config = try_load_current_config(&args.common_args.id).await?;
|
||||||
config = override_config(config, OverrideConfig::from(args.clone()));
|
config = override_config(config, OverrideConfig::from(args.clone()));
|
||||||
|
|
||||||
|
if !version_check(&config) {
|
||||||
|
error!("failed the local version check");
|
||||||
|
return Err(Box::new(ClientError::FailedLocalVersionCheck));
|
||||||
|
}
|
||||||
|
|
||||||
SocketClient::new(config, args.common_args.custom_mixnet)
|
SocketClient::new(config, args.common_args.custom_mixnet)
|
||||||
.run_socket_forever()
|
.run_socket_forever()
|
||||||
.await
|
.await
|
||||||
|
|||||||
@@ -17,6 +17,9 @@ pub enum ClientError {
|
|||||||
#[error("Failed to validate the loaded config")]
|
#[error("Failed to validate the loaded config")]
|
||||||
ConfigValidationFailure,
|
ConfigValidationFailure,
|
||||||
|
|
||||||
|
#[error("Failed local version check, client and config mismatch")]
|
||||||
|
FailedLocalVersionCheck,
|
||||||
|
|
||||||
#[error("Attempted to start the client in invalid socket mode")]
|
#[error("Attempted to start the client in invalid socket mode")]
|
||||||
InvalidSocketMode,
|
InvalidSocketMode,
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "nym-socks5-client"
|
name = "nym-socks5-client"
|
||||||
version = "1.1.46"
|
version = "1.1.42"
|
||||||
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"]
|
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"
|
description = "A SOCKS5 localhost proxy that converts incoming messages to Sphinx and sends them to a Nym address"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|||||||
@@ -2,8 +2,14 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
use crate::commands::try_load_current_config;
|
use crate::commands::try_load_current_config;
|
||||||
use crate::commands::{override_config, OverrideConfig};
|
use crate::config::Config;
|
||||||
|
use crate::{
|
||||||
|
commands::{override_config, OverrideConfig},
|
||||||
|
error::Socks5ClientError,
|
||||||
|
};
|
||||||
use clap::Args;
|
use clap::Args;
|
||||||
|
use log::*;
|
||||||
|
use nym_bin_common::version_checker::is_minor_version_compatible;
|
||||||
use nym_client_core::cli_helpers::client_run::CommonClientRunArgs;
|
use nym_client_core::cli_helpers::client_run::CommonClientRunArgs;
|
||||||
use nym_client_core::client::base_client::storage::OnDiskPersistent;
|
use nym_client_core::client::base_client::storage::OnDiskPersistent;
|
||||||
use nym_client_core::client::topology_control::geo_aware_provider::CountryGroup;
|
use nym_client_core::client::topology_control::geo_aware_provider::CountryGroup;
|
||||||
@@ -76,12 +82,38 @@ fn validate_country_group(s: &str) -> Result<CountryGroup, String> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// this only checks compatibility between config the binary. It does not take into consideration
|
||||||
|
// network version. It might do so in the future.
|
||||||
|
fn version_check(cfg: &Config) -> bool {
|
||||||
|
let binary_version = env!("CARGO_PKG_VERSION");
|
||||||
|
let config_version = &cfg.core.base.client.version;
|
||||||
|
if binary_version == config_version {
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
warn!(
|
||||||
|
"The socks5-client binary has different version than what is specified in config file! {binary_version} and {config_version}",
|
||||||
|
);
|
||||||
|
if is_minor_version_compatible(binary_version, config_version) {
|
||||||
|
info!("but they are still semver compatible. However, consider running the `upgrade` command");
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
error!("and they are semver incompatible! - please run the `upgrade` command before attempting `run` again");
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) async fn execute(args: Run) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
pub(crate) async fn execute(args: Run) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
||||||
eprintln!("Starting client {}...", args.common_args.id);
|
eprintln!("Starting client {}...", args.common_args.id);
|
||||||
|
|
||||||
let mut config = try_load_current_config(&args.common_args.id).await?;
|
let mut config = try_load_current_config(&args.common_args.id).await?;
|
||||||
config = override_config(config, OverrideConfig::from(args.clone()));
|
config = override_config(config, OverrideConfig::from(args.clone()));
|
||||||
|
|
||||||
|
if !version_check(&config) {
|
||||||
|
error!("failed the local version check");
|
||||||
|
return Err(Box::new(Socks5ClientError::FailedLocalVersionCheck));
|
||||||
|
}
|
||||||
|
|
||||||
let storage =
|
let storage =
|
||||||
OnDiskPersistent::from_paths(config.storage_paths.common_paths, &config.core.base.debug)
|
OnDiskPersistent::from_paths(config.storage_paths.common_paths, &config.core.base.debug)
|
||||||
.await?;
|
.await?;
|
||||||
|
|||||||
@@ -14,6 +14,9 @@ pub enum Socks5ClientError {
|
|||||||
#[error("Failed to validate the loaded config")]
|
#[error("Failed to validate the loaded config")]
|
||||||
ConfigValidationFailure,
|
ConfigValidationFailure,
|
||||||
|
|
||||||
|
#[error("Failed local version check, client and config mismatch")]
|
||||||
|
FailedLocalVersionCheck,
|
||||||
|
|
||||||
#[error("Fail to bind address")]
|
#[error("Fail to bind address")]
|
||||||
FailToBindAddress,
|
FailToBindAddress,
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,4 @@ pub enum Error {
|
|||||||
|
|
||||||
#[error("conversion: {0}")]
|
#[error("conversion: {0}")]
|
||||||
Conversion(String),
|
Conversion(String),
|
||||||
|
|
||||||
#[error("failed to serialize response packet: {source}")]
|
|
||||||
FailedToSerializeResponsePacket { source: Box<bincode::ErrorKind> },
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,12 @@
|
|||||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
pub mod traits;
|
|
||||||
pub mod v1;
|
pub mod v1;
|
||||||
pub mod v2;
|
pub mod v2;
|
||||||
pub mod v3;
|
pub mod v3;
|
||||||
pub mod v4;
|
pub mod v4;
|
||||||
|
|
||||||
mod error;
|
mod error;
|
||||||
mod util;
|
|
||||||
|
|
||||||
pub use error::Error;
|
pub use error::Error;
|
||||||
pub use v4 as latest;
|
pub use v4 as latest;
|
||||||
|
|||||||
@@ -1,343 +0,0 @@
|
|||||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
use nym_credentials_interface::CredentialSpendingData;
|
|
||||||
use nym_crypto::asymmetric::x25519::PrivateKey;
|
|
||||||
use nym_service_provider_requests_common::{Protocol, ServiceProviderType};
|
|
||||||
use nym_sphinx::addressing::clients::Recipient;
|
|
||||||
use nym_wireguard_types::PeerPublicKey;
|
|
||||||
|
|
||||||
use crate::{
|
|
||||||
v1, v2, v3,
|
|
||||||
v4::{self, registration::IpPair},
|
|
||||||
Error,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
|
||||||
pub enum AuthenticatorVersion {
|
|
||||||
V1,
|
|
||||||
V2,
|
|
||||||
V3,
|
|
||||||
V4,
|
|
||||||
UNKNOWN,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<Protocol> for AuthenticatorVersion {
|
|
||||||
fn from(value: Protocol) -> Self {
|
|
||||||
if value.service_provider_type != ServiceProviderType::Authenticator {
|
|
||||||
AuthenticatorVersion::UNKNOWN
|
|
||||||
} else if value.version == v1::VERSION {
|
|
||||||
AuthenticatorVersion::V1
|
|
||||||
} else if value.version == v2::VERSION {
|
|
||||||
AuthenticatorVersion::V2
|
|
||||||
} else if value.version == v3::VERSION {
|
|
||||||
AuthenticatorVersion::V3
|
|
||||||
} else if value.version == v4::VERSION {
|
|
||||||
AuthenticatorVersion::V4
|
|
||||||
} else {
|
|
||||||
AuthenticatorVersion::UNKNOWN
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait InitMessage {
|
|
||||||
fn pub_key(&self) -> PeerPublicKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl InitMessage for v1::registration::InitMessage {
|
|
||||||
fn pub_key(&self) -> PeerPublicKey {
|
|
||||||
self.pub_key
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl InitMessage for v2::registration::InitMessage {
|
|
||||||
fn pub_key(&self) -> PeerPublicKey {
|
|
||||||
self.pub_key
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl InitMessage for v3::registration::InitMessage {
|
|
||||||
fn pub_key(&self) -> PeerPublicKey {
|
|
||||||
self.pub_key
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl InitMessage for v4::registration::InitMessage {
|
|
||||||
fn pub_key(&self) -> PeerPublicKey {
|
|
||||||
self.pub_key
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait FinalMessage {
|
|
||||||
fn pub_key(&self) -> PeerPublicKey;
|
|
||||||
fn verify(&self, private_key: &PrivateKey, nonce: u64) -> Result<(), Error>;
|
|
||||||
fn private_ips(&self) -> IpPair;
|
|
||||||
fn credential(&self) -> Option<CredentialSpendingData>;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FinalMessage for v1::GatewayClient {
|
|
||||||
fn pub_key(&self) -> PeerPublicKey {
|
|
||||||
self.pub_key
|
|
||||||
}
|
|
||||||
|
|
||||||
fn verify(&self, private_key: &PrivateKey, nonce: u64) -> Result<(), Error> {
|
|
||||||
self.verify(private_key, nonce)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn private_ips(&self) -> IpPair {
|
|
||||||
self.private_ip.into()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn credential(&self) -> Option<CredentialSpendingData> {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FinalMessage for v2::registration::FinalMessage {
|
|
||||||
fn pub_key(&self) -> PeerPublicKey {
|
|
||||||
self.gateway_client.pub_key
|
|
||||||
}
|
|
||||||
|
|
||||||
fn verify(&self, private_key: &PrivateKey, nonce: u64) -> Result<(), Error> {
|
|
||||||
self.gateway_client.verify(private_key, nonce)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn private_ips(&self) -> IpPair {
|
|
||||||
self.gateway_client.private_ip.into()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn credential(&self) -> Option<CredentialSpendingData> {
|
|
||||||
self.credential.clone()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FinalMessage for v3::registration::FinalMessage {
|
|
||||||
fn pub_key(&self) -> PeerPublicKey {
|
|
||||||
self.gateway_client.pub_key
|
|
||||||
}
|
|
||||||
|
|
||||||
fn verify(&self, private_key: &PrivateKey, nonce: u64) -> Result<(), Error> {
|
|
||||||
self.gateway_client.verify(private_key, nonce)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn private_ips(&self) -> IpPair {
|
|
||||||
self.gateway_client.private_ip.into()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn credential(&self) -> Option<CredentialSpendingData> {
|
|
||||||
self.credential.clone()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FinalMessage for v4::registration::FinalMessage {
|
|
||||||
fn pub_key(&self) -> PeerPublicKey {
|
|
||||||
self.gateway_client.pub_key
|
|
||||||
}
|
|
||||||
|
|
||||||
fn verify(&self, private_key: &PrivateKey, nonce: u64) -> Result<(), Error> {
|
|
||||||
self.gateway_client.verify(private_key, nonce)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn private_ips(&self) -> IpPair {
|
|
||||||
self.gateway_client.private_ips
|
|
||||||
}
|
|
||||||
|
|
||||||
fn credential(&self) -> Option<CredentialSpendingData> {
|
|
||||||
self.credential.clone()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait QueryBandwidthMessage {
|
|
||||||
fn pub_key(&self) -> PeerPublicKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl QueryBandwidthMessage for PeerPublicKey {
|
|
||||||
fn pub_key(&self) -> PeerPublicKey {
|
|
||||||
*self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait TopUpMessage {
|
|
||||||
fn pub_key(&self) -> PeerPublicKey;
|
|
||||||
fn credential(&self) -> CredentialSpendingData;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TopUpMessage for v3::topup::TopUpMessage {
|
|
||||||
fn pub_key(&self) -> PeerPublicKey {
|
|
||||||
self.pub_key
|
|
||||||
}
|
|
||||||
|
|
||||||
fn credential(&self) -> CredentialSpendingData {
|
|
||||||
self.credential.clone()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TopUpMessage for v4::topup::TopUpMessage {
|
|
||||||
fn pub_key(&self) -> PeerPublicKey {
|
|
||||||
self.pub_key
|
|
||||||
}
|
|
||||||
|
|
||||||
fn credential(&self) -> CredentialSpendingData {
|
|
||||||
self.credential.clone()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum AuthenticatorRequest {
|
|
||||||
Initial {
|
|
||||||
msg: Box<dyn InitMessage + Send + Sync + 'static>,
|
|
||||||
protocol: Protocol,
|
|
||||||
reply_to: Recipient,
|
|
||||||
request_id: u64,
|
|
||||||
},
|
|
||||||
Final {
|
|
||||||
msg: Box<dyn FinalMessage + Send + Sync + 'static>,
|
|
||||||
protocol: Protocol,
|
|
||||||
reply_to: Recipient,
|
|
||||||
request_id: u64,
|
|
||||||
},
|
|
||||||
QueryBandwidth {
|
|
||||||
msg: Box<dyn QueryBandwidthMessage + Send + Sync + 'static>,
|
|
||||||
protocol: Protocol,
|
|
||||||
reply_to: Recipient,
|
|
||||||
request_id: u64,
|
|
||||||
},
|
|
||||||
TopUpBandwidth {
|
|
||||||
msg: Box<dyn TopUpMessage + Send + Sync + 'static>,
|
|
||||||
protocol: Protocol,
|
|
||||||
reply_to: Recipient,
|
|
||||||
request_id: u64,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v1::request::AuthenticatorRequest> for AuthenticatorRequest {
|
|
||||||
fn from(value: v1::request::AuthenticatorRequest) -> Self {
|
|
||||||
match value.data {
|
|
||||||
v1::request::AuthenticatorRequestData::Initial(init_message) => Self::Initial {
|
|
||||||
msg: Box::new(init_message),
|
|
||||||
protocol: Protocol {
|
|
||||||
version: value.version,
|
|
||||||
service_provider_type: ServiceProviderType::Authenticator,
|
|
||||||
},
|
|
||||||
reply_to: value.reply_to,
|
|
||||||
request_id: value.request_id,
|
|
||||||
},
|
|
||||||
v1::request::AuthenticatorRequestData::Final(gateway_client) => Self::Final {
|
|
||||||
msg: Box::new(gateway_client),
|
|
||||||
protocol: Protocol {
|
|
||||||
version: value.version,
|
|
||||||
service_provider_type: ServiceProviderType::Authenticator,
|
|
||||||
},
|
|
||||||
reply_to: value.reply_to,
|
|
||||||
request_id: value.request_id,
|
|
||||||
},
|
|
||||||
v1::request::AuthenticatorRequestData::QueryBandwidth(peer_public_key) => {
|
|
||||||
Self::QueryBandwidth {
|
|
||||||
msg: Box::new(peer_public_key),
|
|
||||||
protocol: Protocol {
|
|
||||||
version: value.version,
|
|
||||||
service_provider_type: ServiceProviderType::Authenticator,
|
|
||||||
},
|
|
||||||
reply_to: value.reply_to,
|
|
||||||
request_id: value.request_id,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v2::request::AuthenticatorRequest> for AuthenticatorRequest {
|
|
||||||
fn from(value: v2::request::AuthenticatorRequest) -> Self {
|
|
||||||
match value.data {
|
|
||||||
v2::request::AuthenticatorRequestData::Initial(init_message) => Self::Initial {
|
|
||||||
msg: Box::new(init_message),
|
|
||||||
protocol: value.protocol,
|
|
||||||
reply_to: value.reply_to,
|
|
||||||
request_id: value.request_id,
|
|
||||||
},
|
|
||||||
v2::request::AuthenticatorRequestData::Final(final_message) => Self::Final {
|
|
||||||
msg: final_message,
|
|
||||||
protocol: value.protocol,
|
|
||||||
reply_to: value.reply_to,
|
|
||||||
request_id: value.request_id,
|
|
||||||
},
|
|
||||||
v2::request::AuthenticatorRequestData::QueryBandwidth(peer_public_key) => {
|
|
||||||
Self::QueryBandwidth {
|
|
||||||
msg: Box::new(peer_public_key),
|
|
||||||
protocol: value.protocol,
|
|
||||||
reply_to: value.reply_to,
|
|
||||||
request_id: value.request_id,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v3::request::AuthenticatorRequest> for AuthenticatorRequest {
|
|
||||||
fn from(value: v3::request::AuthenticatorRequest) -> Self {
|
|
||||||
match value.data {
|
|
||||||
v3::request::AuthenticatorRequestData::Initial(init_message) => Self::Initial {
|
|
||||||
msg: Box::new(init_message),
|
|
||||||
protocol: value.protocol,
|
|
||||||
reply_to: value.reply_to,
|
|
||||||
request_id: value.request_id,
|
|
||||||
},
|
|
||||||
v3::request::AuthenticatorRequestData::Final(final_message) => Self::Final {
|
|
||||||
msg: final_message,
|
|
||||||
protocol: value.protocol,
|
|
||||||
reply_to: value.reply_to,
|
|
||||||
request_id: value.request_id,
|
|
||||||
},
|
|
||||||
v3::request::AuthenticatorRequestData::QueryBandwidth(peer_public_key) => {
|
|
||||||
Self::QueryBandwidth {
|
|
||||||
msg: Box::new(peer_public_key),
|
|
||||||
protocol: value.protocol,
|
|
||||||
reply_to: value.reply_to,
|
|
||||||
request_id: value.request_id,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
v3::request::AuthenticatorRequestData::TopUpBandwidth(top_up_message) => {
|
|
||||||
Self::TopUpBandwidth {
|
|
||||||
msg: top_up_message,
|
|
||||||
protocol: value.protocol,
|
|
||||||
reply_to: value.reply_to,
|
|
||||||
request_id: value.request_id,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v4::request::AuthenticatorRequest> for AuthenticatorRequest {
|
|
||||||
fn from(value: v4::request::AuthenticatorRequest) -> Self {
|
|
||||||
match value.data {
|
|
||||||
v4::request::AuthenticatorRequestData::Initial(init_message) => Self::Initial {
|
|
||||||
msg: Box::new(init_message),
|
|
||||||
protocol: value.protocol,
|
|
||||||
reply_to: value.reply_to,
|
|
||||||
request_id: value.request_id,
|
|
||||||
},
|
|
||||||
v4::request::AuthenticatorRequestData::Final(final_message) => Self::Final {
|
|
||||||
msg: final_message,
|
|
||||||
protocol: value.protocol,
|
|
||||||
reply_to: value.reply_to,
|
|
||||||
request_id: value.request_id,
|
|
||||||
},
|
|
||||||
v4::request::AuthenticatorRequestData::QueryBandwidth(peer_public_key) => {
|
|
||||||
Self::QueryBandwidth {
|
|
||||||
msg: Box::new(peer_public_key),
|
|
||||||
protocol: value.protocol,
|
|
||||||
reply_to: value.reply_to,
|
|
||||||
request_id: value.request_id,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
v4::request::AuthenticatorRequestData::TopUpBandwidth(top_up_message) => {
|
|
||||||
Self::TopUpBandwidth {
|
|
||||||
msg: top_up_message,
|
|
||||||
protocol: value.protocol,
|
|
||||||
reply_to: value.reply_to,
|
|
||||||
request_id: value.request_id,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
pub(crate) mod tests {
|
|
||||||
pub(crate) const CREDENTIAL_BYTES: [u8; 1245] = [
|
|
||||||
0, 0, 4, 133, 96, 179, 223, 185, 136, 23, 213, 166, 59, 203, 66, 69, 209, 181, 227, 254,
|
|
||||||
16, 102, 98, 237, 59, 119, 170, 111, 31, 194, 51, 59, 120, 17, 115, 229, 79, 91, 11, 139,
|
|
||||||
154, 2, 212, 23, 68, 70, 167, 3, 240, 54, 224, 171, 221, 1, 69, 48, 60, 118, 119, 249, 123,
|
|
||||||
35, 172, 227, 131, 96, 232, 209, 187, 123, 4, 197, 102, 90, 96, 45, 125, 135, 140, 99, 1,
|
|
||||||
151, 17, 131, 143, 157, 97, 107, 139, 232, 212, 87, 14, 115, 253, 255, 166, 167, 186, 43,
|
|
||||||
90, 96, 173, 105, 120, 40, 10, 163, 250, 224, 214, 200, 178, 4, 160, 16, 130, 59, 76, 193,
|
|
||||||
39, 240, 3, 101, 141, 209, 183, 226, 186, 207, 56, 210, 187, 7, 164, 240, 164, 205, 37, 81,
|
|
||||||
184, 214, 193, 195, 90, 205, 238, 225, 195, 104, 12, 123, 203, 57, 233, 243, 215, 145, 195,
|
|
||||||
196, 57, 38, 125, 172, 18, 47, 63, 165, 110, 219, 180, 40, 58, 116, 92, 254, 160, 98, 48,
|
|
||||||
92, 254, 232, 107, 184, 80, 234, 60, 160, 235, 249, 76, 41, 38, 165, 28, 40, 136, 74, 48,
|
|
||||||
166, 50, 245, 23, 201, 140, 101, 79, 93, 235, 128, 186, 146, 126, 180, 134, 43, 13, 186,
|
|
||||||
19, 195, 48, 168, 201, 29, 216, 95, 176, 198, 132, 188, 64, 39, 212, 150, 32, 52, 53, 38,
|
|
||||||
228, 199, 122, 226, 217, 75, 40, 191, 151, 48, 164, 242, 177, 79, 14, 122, 105, 151, 85,
|
|
||||||
88, 199, 162, 17, 96, 103, 83, 178, 128, 9, 24, 30, 74, 108, 241, 85, 240, 166, 97, 241,
|
|
||||||
85, 199, 11, 198, 226, 234, 70, 107, 145, 28, 208, 114, 51, 12, 234, 108, 101, 202, 112,
|
|
||||||
48, 185, 22, 159, 67, 109, 49, 27, 149, 90, 109, 32, 226, 112, 7, 201, 208, 209, 104, 31,
|
|
||||||
97, 134, 204, 145, 27, 181, 206, 181, 106, 32, 110, 136, 115, 249, 201, 111, 5, 245, 203,
|
|
||||||
71, 121, 169, 126, 151, 178, 236, 59, 221, 195, 48, 135, 115, 6, 50, 227, 74, 97, 107, 107,
|
|
||||||
213, 90, 2, 203, 154, 138, 47, 128, 52, 134, 128, 224, 51, 65, 240, 90, 8, 55, 175, 180,
|
|
||||||
178, 204, 206, 168, 110, 51, 57, 189, 169, 48, 169, 136, 121, 99, 51, 170, 178, 214, 74, 1,
|
|
||||||
96, 151, 167, 25, 173, 180, 171, 155, 10, 55, 142, 234, 190, 113, 90, 79, 80, 244, 71, 166,
|
|
||||||
30, 235, 113, 150, 133, 1, 218, 17, 109, 111, 223, 24, 216, 177, 41, 2, 204, 65, 221, 212,
|
|
||||||
207, 236, 144, 6, 65, 224, 55, 42, 1, 1, 161, 134, 118, 127, 111, 220, 110, 127, 240, 71,
|
|
||||||
223, 129, 12, 93, 20, 220, 60, 56, 71, 146, 184, 95, 132, 69, 28, 56, 53, 192, 213, 22,
|
|
||||||
119, 230, 152, 225, 182, 188, 163, 219, 37, 175, 247, 73, 14, 247, 38, 72, 243, 1, 48, 131,
|
|
||||||
59, 8, 13, 96, 143, 185, 127, 241, 161, 217, 24, 149, 193, 40, 16, 30, 202, 151, 28, 119,
|
|
||||||
240, 153, 101, 156, 61, 193, 72, 245, 199, 181, 12, 231, 65, 166, 67, 142, 121, 207, 202,
|
|
||||||
58, 197, 113, 188, 248, 42, 124, 105, 48, 161, 241, 55, 209, 36, 194, 27, 63, 233, 144,
|
|
||||||
189, 85, 117, 234, 9, 139, 46, 31, 206, 114, 95, 131, 29, 240, 13, 81, 142, 140, 133, 33,
|
|
||||||
30, 41, 141, 37, 80, 217, 95, 221, 76, 115, 86, 201, 165, 51, 252, 9, 28, 209, 1, 48, 150,
|
|
||||||
74, 248, 212, 187, 222, 66, 210, 3, 200, 19, 217, 171, 184, 42, 148, 53, 150, 57, 50, 6,
|
|
||||||
227, 227, 62, 49, 42, 148, 148, 157, 82, 191, 58, 24, 34, 56, 98, 120, 89, 105, 176, 85,
|
|
||||||
15, 253, 241, 41, 153, 195, 136, 1, 48, 142, 126, 213, 101, 223, 79, 133, 230, 105, 38,
|
|
||||||
161, 149, 2, 21, 136, 150, 42, 72, 218, 85, 146, 63, 223, 58, 108, 186, 183, 248, 62, 20,
|
|
||||||
47, 34, 113, 160, 177, 204, 181, 16, 24, 212, 224, 35, 84, 51, 168, 56, 136, 11, 1, 48,
|
|
||||||
135, 242, 62, 149, 230, 178, 32, 224, 119, 26, 234, 163, 237, 224, 114, 95, 112, 140, 170,
|
|
||||||
150, 96, 125, 136, 221, 180, 78, 18, 11, 12, 184, 2, 198, 217, 119, 43, 69, 4, 172, 109,
|
|
||||||
55, 183, 40, 131, 172, 161, 88, 183, 101, 1, 48, 173, 216, 22, 73, 42, 255, 211, 93, 249,
|
|
||||||
87, 159, 115, 61, 91, 55, 130, 17, 216, 60, 34, 122, 55, 8, 244, 244, 153, 151, 57, 5, 144,
|
|
||||||
178, 55, 249, 64, 211, 168, 34, 148, 56, 89, 92, 203, 70, 124, 219, 152, 253, 165, 0, 32,
|
|
||||||
203, 116, 63, 7, 240, 222, 82, 86, 11, 149, 167, 72, 224, 55, 190, 66, 201, 65, 168, 184,
|
|
||||||
96, 47, 194, 241, 168, 124, 7, 74, 214, 250, 37, 76, 32, 218, 69, 122, 103, 215, 145, 169,
|
|
||||||
24, 212, 229, 168, 106, 10, 144, 31, 13, 25, 178, 242, 250, 106, 159, 40, 48, 163, 165, 61,
|
|
||||||
130, 57, 146, 4, 73, 32, 254, 233, 125, 135, 212, 29, 111, 4, 177, 114, 15, 210, 170, 82,
|
|
||||||
108, 110, 62, 166, 81, 209, 106, 176, 156, 14, 133, 242, 60, 127, 120, 242, 28, 97, 0, 1,
|
|
||||||
32, 103, 93, 109, 89, 240, 91, 1, 84, 150, 50, 206, 157, 203, 49, 220, 120, 234, 175, 234,
|
|
||||||
150, 126, 225, 94, 163, 164, 199, 138, 114, 62, 99, 106, 112, 1, 32, 171, 40, 220, 82, 241,
|
|
||||||
203, 76, 146, 111, 139, 182, 179, 237, 182, 115, 75, 128, 201, 107, 43, 214, 0, 135, 217,
|
|
||||||
160, 68, 150, 232, 144, 114, 237, 98, 32, 30, 134, 232, 59, 93, 163, 253, 244, 13, 202, 52,
|
|
||||||
147, 168, 83, 121, 123, 95, 21, 210, 209, 225, 223, 143, 49, 10, 205, 238, 1, 22, 83, 81,
|
|
||||||
70, 1, 32, 26, 76, 6, 234, 160, 50, 139, 102, 161, 232, 155, 106, 130, 171, 226, 210, 233,
|
|
||||||
178, 85, 247, 71, 123, 55, 53, 46, 67, 148, 137, 156, 207, 208, 107, 1, 32, 102, 31, 4, 98,
|
|
||||||
110, 156, 144, 61, 229, 140, 198, 84, 196, 238, 128, 35, 131, 182, 137, 125, 241, 95, 69,
|
|
||||||
131, 170, 27, 2, 144, 75, 72, 242, 102, 3, 32, 121, 80, 45, 173, 56, 65, 218, 27, 40, 251,
|
|
||||||
197, 32, 169, 104, 123, 110, 90, 78, 153, 166, 38, 9, 129, 228, 99, 8, 1, 116, 142, 233,
|
|
||||||
162, 69, 32, 216, 169, 159, 116, 95, 12, 63, 176, 195, 6, 183, 123, 135, 75, 61, 112, 106,
|
|
||||||
83, 235, 176, 41, 27, 248, 48, 71, 165, 170, 12, 92, 103, 103, 81, 32, 58, 74, 75, 145,
|
|
||||||
192, 94, 153, 69, 80, 128, 241, 3, 16, 117, 192, 86, 161, 103, 44, 174, 211, 196, 182, 124,
|
|
||||||
55, 11, 107, 142, 49, 88, 6, 41, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
|
||||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
|
||||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 0, 37, 139, 240, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 1,
|
|
||||||
];
|
|
||||||
pub(crate) const RECIPIENT: &str = "CytBseW6yFXUMzz4SGAKdNLGR7q3sJLLYxyBGvutNEQV.4QXYyEVc5fUDjmmi8PrHN9tdUFV4PCvSJE1278cHyvoe@4sBbL1ngf1vtNqykydQKTFh26sQCw888GpUqvPvyNB4f";
|
|
||||||
}
|
|
||||||
@@ -29,7 +29,7 @@ pub type Taken = Option<SystemTime>;
|
|||||||
|
|
||||||
pub const BANDWIDTH_CAP_PER_DAY: u64 = 1024 * 1024 * 1024; // 1 GB
|
pub const BANDWIDTH_CAP_PER_DAY: u64 = 1024 * 1024 * 1024; // 1 GB
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
pub struct InitMessage {
|
pub struct InitMessage {
|
||||||
/// Base64 encoded x25519 public key
|
/// Base64 encoded x25519 public key
|
||||||
pub pub_key: PeerPublicKey,
|
pub pub_key: PeerPublicKey,
|
||||||
@@ -41,7 +41,7 @@ impl InitMessage {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
pub struct FinalMessage {
|
pub struct FinalMessage {
|
||||||
/// Gateway client data
|
/// Gateway client data
|
||||||
pub gateway_client: GatewayClient,
|
pub gateway_client: GatewayClient,
|
||||||
@@ -50,28 +50,28 @@ pub struct FinalMessage {
|
|||||||
pub credential: Option<CredentialSpendingData>,
|
pub credential: Option<CredentialSpendingData>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
pub struct RegistrationData {
|
pub struct RegistrationData {
|
||||||
pub nonce: u64,
|
pub nonce: u64,
|
||||||
pub gateway_data: GatewayClient,
|
pub gateway_data: GatewayClient,
|
||||||
pub wg_port: u16,
|
pub wg_port: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
pub struct RegistredData {
|
pub struct RegistredData {
|
||||||
pub pub_key: PeerPublicKey,
|
pub pub_key: PeerPublicKey,
|
||||||
pub private_ip: IpAddr,
|
pub private_ip: IpAddr,
|
||||||
pub wg_port: u16,
|
pub wg_port: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
pub struct RemainingBandwidthData {
|
pub struct RemainingBandwidthData {
|
||||||
pub available_bandwidth: i64,
|
pub available_bandwidth: i64,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Client that wants to register sends its PublicKey bytes mac digest encrypted with a DH shared secret.
|
/// Client that wants to register sends its PublicKey bytes mac digest encrypted with a DH shared secret.
|
||||||
/// Gateway/Nym node can then verify pub_key payload using the same process
|
/// Gateway/Nym node can then verify pub_key payload using the same process
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
pub struct GatewayClient {
|
pub struct GatewayClient {
|
||||||
/// Base64 encoded x25519 public key
|
/// Base64 encoded x25519 public key
|
||||||
pub pub_key: PeerPublicKey,
|
pub pub_key: PeerPublicKey,
|
||||||
@@ -147,7 +147,7 @@ impl GatewayClient {
|
|||||||
|
|
||||||
// TODO: change the inner type into generic array of size HmacSha256::OutputSize
|
// TODO: change the inner type into generic array of size HmacSha256::OutputSize
|
||||||
// TODO2: rely on our internal crypto/hmac
|
// TODO2: rely on our internal crypto/hmac
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct ClientMac(Vec<u8>);
|
pub struct ClientMac(Vec<u8>);
|
||||||
|
|
||||||
impl fmt::Display for ClientMac {
|
impl fmt::Display for ClientMac {
|
||||||
|
|||||||
@@ -17,6 +17,11 @@ fn generate_random() -> u64 {
|
|||||||
rng.next_u64()
|
rng.next_u64()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
|
pub struct QueryMessage {
|
||||||
|
pub pub_key: PeerPublicKey,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
pub struct AuthenticatorRequest {
|
pub struct AuthenticatorRequest {
|
||||||
pub protocol: Protocol,
|
pub protocol: Protocol,
|
||||||
@@ -65,7 +70,7 @@ impl AuthenticatorRequest {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_query_request(peer_public_key: PeerPublicKey, reply_to: Recipient) -> (Self, u64) {
|
pub fn new_query_request(query_message: QueryMessage, reply_to: Recipient) -> (Self, u64) {
|
||||||
let request_id = generate_random();
|
let request_id = generate_random();
|
||||||
(
|
(
|
||||||
Self {
|
Self {
|
||||||
@@ -73,7 +78,7 @@ impl AuthenticatorRequest {
|
|||||||
service_provider_type: ServiceProviderType::Authenticator,
|
service_provider_type: ServiceProviderType::Authenticator,
|
||||||
version: VERSION,
|
version: VERSION,
|
||||||
},
|
},
|
||||||
data: AuthenticatorRequestData::QueryBandwidth(peer_public_key),
|
data: AuthenticatorRequestData::QueryBandwidth(query_message.pub_key),
|
||||||
reply_to,
|
reply_to,
|
||||||
request_id,
|
request_id,
|
||||||
},
|
},
|
||||||
@@ -87,7 +92,7 @@ impl AuthenticatorRequest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
pub enum AuthenticatorRequestData {
|
pub enum AuthenticatorRequestData {
|
||||||
Initial(InitMessage),
|
Initial(InitMessage),
|
||||||
Final(Box<FinalMessage>),
|
Final(Box<FinalMessage>),
|
||||||
|
|||||||
@@ -100,28 +100,28 @@ impl AuthenticatorResponse {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
pub enum AuthenticatorResponseData {
|
pub enum AuthenticatorResponseData {
|
||||||
PendingRegistration(PendingRegistrationResponse),
|
PendingRegistration(PendingRegistrationResponse),
|
||||||
Registered(RegisteredResponse),
|
Registered(RegisteredResponse),
|
||||||
RemainingBandwidth(RemainingBandwidthResponse),
|
RemainingBandwidth(RemainingBandwidthResponse),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
pub struct PendingRegistrationResponse {
|
pub struct PendingRegistrationResponse {
|
||||||
pub request_id: u64,
|
pub request_id: u64,
|
||||||
pub reply_to: Recipient,
|
pub reply_to: Recipient,
|
||||||
pub reply: RegistrationData,
|
pub reply: RegistrationData,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
pub struct RegisteredResponse {
|
pub struct RegisteredResponse {
|
||||||
pub request_id: u64,
|
pub request_id: u64,
|
||||||
pub reply_to: Recipient,
|
pub reply_to: Recipient,
|
||||||
pub reply: RegistredData,
|
pub reply: RegistredData,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
pub struct RemainingBandwidthResponse {
|
pub struct RemainingBandwidthResponse {
|
||||||
pub request_id: u64,
|
pub request_id: u64,
|
||||||
pub reply_to: Recipient,
|
pub reply_to: Recipient,
|
||||||
|
|||||||
@@ -19,24 +19,6 @@ impl From<v2::request::AuthenticatorRequest> for v3::request::AuthenticatorReque
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryFrom<v3::request::AuthenticatorRequest> for v2::request::AuthenticatorRequest {
|
|
||||||
type Error = crate::Error;
|
|
||||||
|
|
||||||
fn try_from(
|
|
||||||
authenticator_request: v3::request::AuthenticatorRequest,
|
|
||||||
) -> Result<Self, Self::Error> {
|
|
||||||
Ok(Self {
|
|
||||||
protocol: Protocol {
|
|
||||||
version: 2,
|
|
||||||
service_provider_type: ServiceProviderType::Authenticator,
|
|
||||||
},
|
|
||||||
data: authenticator_request.data.try_into()?,
|
|
||||||
reply_to: authenticator_request.reply_to,
|
|
||||||
request_id: authenticator_request.request_id,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v2::request::AuthenticatorRequestData> for v3::request::AuthenticatorRequestData {
|
impl From<v2::request::AuthenticatorRequestData> for v3::request::AuthenticatorRequestData {
|
||||||
fn from(authenticator_request_data: v2::request::AuthenticatorRequestData) -> Self {
|
fn from(authenticator_request_data: v2::request::AuthenticatorRequestData) -> Self {
|
||||||
match authenticator_request_data {
|
match authenticator_request_data {
|
||||||
@@ -53,29 +35,6 @@ impl From<v2::request::AuthenticatorRequestData> for v3::request::AuthenticatorR
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryFrom<v3::request::AuthenticatorRequestData> for v2::request::AuthenticatorRequestData {
|
|
||||||
type Error = crate::Error;
|
|
||||||
|
|
||||||
fn try_from(
|
|
||||||
authenticator_request_data: v3::request::AuthenticatorRequestData,
|
|
||||||
) -> Result<Self, Self::Error> {
|
|
||||||
match authenticator_request_data {
|
|
||||||
v3::request::AuthenticatorRequestData::Initial(init_msg) => Ok(
|
|
||||||
v2::request::AuthenticatorRequestData::Initial(init_msg.into()),
|
|
||||||
),
|
|
||||||
v3::request::AuthenticatorRequestData::Final(gw_client) => Ok(
|
|
||||||
v2::request::AuthenticatorRequestData::Final(gw_client.into()),
|
|
||||||
),
|
|
||||||
v3::request::AuthenticatorRequestData::QueryBandwidth(pub_key) => Ok(
|
|
||||||
v2::request::AuthenticatorRequestData::QueryBandwidth(pub_key),
|
|
||||||
),
|
|
||||||
v3::request::AuthenticatorRequestData::TopUpBandwidth(_) => Err(
|
|
||||||
Self::Error::Conversion("no top up bandwidth variant in v2".to_string()),
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v2::registration::InitMessage> for v3::registration::InitMessage {
|
impl From<v2::registration::InitMessage> for v3::registration::InitMessage {
|
||||||
fn from(init_msg: v2::registration::InitMessage) -> Self {
|
fn from(init_msg: v2::registration::InitMessage) -> Self {
|
||||||
Self {
|
Self {
|
||||||
@@ -84,14 +43,6 @@ impl From<v2::registration::InitMessage> for v3::registration::InitMessage {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<v3::registration::InitMessage> for v2::registration::InitMessage {
|
|
||||||
fn from(init_msg: v3::registration::InitMessage) -> Self {
|
|
||||||
Self {
|
|
||||||
pub_key: init_msg.pub_key,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<Box<v2::registration::FinalMessage>> for Box<v3::registration::FinalMessage> {
|
impl From<Box<v2::registration::FinalMessage>> for Box<v3::registration::FinalMessage> {
|
||||||
fn from(gw_client: Box<v2::registration::FinalMessage>) -> Self {
|
fn from(gw_client: Box<v2::registration::FinalMessage>) -> Self {
|
||||||
Box::new(v3::registration::FinalMessage {
|
Box::new(v3::registration::FinalMessage {
|
||||||
@@ -101,15 +52,6 @@ impl From<Box<v2::registration::FinalMessage>> for Box<v3::registration::FinalMe
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Box<v3::registration::FinalMessage>> for Box<v2::registration::FinalMessage> {
|
|
||||||
fn from(gw_client: Box<v3::registration::FinalMessage>) -> Self {
|
|
||||||
Box::new(v2::registration::FinalMessage {
|
|
||||||
gateway_client: gw_client.gateway_client.into(),
|
|
||||||
credential: gw_client.credential,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v2::registration::GatewayClient> for v3::registration::GatewayClient {
|
impl From<v2::registration::GatewayClient> for v3::registration::GatewayClient {
|
||||||
fn from(gw_client: v2::registration::GatewayClient) -> Self {
|
fn from(gw_client: v2::registration::GatewayClient) -> Self {
|
||||||
Self {
|
Self {
|
||||||
@@ -151,27 +93,11 @@ impl TryFrom<v3::response::AuthenticatorResponse> for v2::response::Authenticato
|
|||||||
Ok(Self {
|
Ok(Self {
|
||||||
data: authenticator_response.data.try_into()?,
|
data: authenticator_response.data.try_into()?,
|
||||||
reply_to: authenticator_response.reply_to,
|
reply_to: authenticator_response.reply_to,
|
||||||
protocol: Protocol {
|
protocol: authenticator_response.protocol,
|
||||||
version: 2,
|
|
||||||
service_provider_type: authenticator_response.protocol.service_provider_type,
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<v2::response::AuthenticatorResponse> for v3::response::AuthenticatorResponse {
|
|
||||||
fn from(value: v2::response::AuthenticatorResponse) -> Self {
|
|
||||||
Self {
|
|
||||||
protocol: Protocol {
|
|
||||||
version: 3,
|
|
||||||
service_provider_type: value.protocol.service_provider_type,
|
|
||||||
},
|
|
||||||
data: value.data.into(),
|
|
||||||
reply_to: value.reply_to,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TryFrom<v3::response::AuthenticatorResponseData> for v2::response::AuthenticatorResponseData {
|
impl TryFrom<v3::response::AuthenticatorResponseData> for v2::response::AuthenticatorResponseData {
|
||||||
type Error = crate::Error;
|
type Error = crate::Error;
|
||||||
|
|
||||||
@@ -203,22 +129,6 @@ impl TryFrom<v3::response::AuthenticatorResponseData> for v2::response::Authenti
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<v2::response::AuthenticatorResponseData> for v3::response::AuthenticatorResponseData {
|
|
||||||
fn from(value: v2::response::AuthenticatorResponseData) -> Self {
|
|
||||||
match value {
|
|
||||||
v2::response::AuthenticatorResponseData::PendingRegistration(
|
|
||||||
pending_registration_response,
|
|
||||||
) => Self::PendingRegistration(pending_registration_response.into()),
|
|
||||||
v2::response::AuthenticatorResponseData::Registered(registered_response) => {
|
|
||||||
Self::Registered(registered_response.into())
|
|
||||||
}
|
|
||||||
v2::response::AuthenticatorResponseData::RemainingBandwidth(
|
|
||||||
remaining_bandwidth_response,
|
|
||||||
) => Self::RemainingBandwidth(remaining_bandwidth_response.into()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v3::response::PendingRegistrationResponse> for v2::response::PendingRegistrationResponse {
|
impl From<v3::response::PendingRegistrationResponse> for v2::response::PendingRegistrationResponse {
|
||||||
fn from(value: v3::response::PendingRegistrationResponse) -> Self {
|
fn from(value: v3::response::PendingRegistrationResponse) -> Self {
|
||||||
Self {
|
Self {
|
||||||
@@ -229,16 +139,6 @@ impl From<v3::response::PendingRegistrationResponse> for v2::response::PendingRe
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<v2::response::PendingRegistrationResponse> for v3::response::PendingRegistrationResponse {
|
|
||||||
fn from(value: v2::response::PendingRegistrationResponse) -> Self {
|
|
||||||
Self {
|
|
||||||
request_id: value.request_id,
|
|
||||||
reply_to: value.reply_to,
|
|
||||||
reply: value.reply.into(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v3::response::RegisteredResponse> for v2::response::RegisteredResponse {
|
impl From<v3::response::RegisteredResponse> for v2::response::RegisteredResponse {
|
||||||
fn from(value: v3::response::RegisteredResponse) -> Self {
|
fn from(value: v3::response::RegisteredResponse) -> Self {
|
||||||
Self {
|
Self {
|
||||||
@@ -249,16 +149,6 @@ impl From<v3::response::RegisteredResponse> for v2::response::RegisteredResponse
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<v2::response::RegisteredResponse> for v3::response::RegisteredResponse {
|
|
||||||
fn from(value: v2::response::RegisteredResponse) -> Self {
|
|
||||||
Self {
|
|
||||||
request_id: value.request_id,
|
|
||||||
reply_to: value.reply_to,
|
|
||||||
reply: value.reply.into(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v3::response::RemainingBandwidthResponse> for v2::response::RemainingBandwidthResponse {
|
impl From<v3::response::RemainingBandwidthResponse> for v2::response::RemainingBandwidthResponse {
|
||||||
fn from(value: v3::response::RemainingBandwidthResponse) -> Self {
|
fn from(value: v3::response::RemainingBandwidthResponse) -> Self {
|
||||||
Self {
|
Self {
|
||||||
@@ -269,16 +159,6 @@ impl From<v3::response::RemainingBandwidthResponse> for v2::response::RemainingB
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<v2::response::RemainingBandwidthResponse> for v3::response::RemainingBandwidthResponse {
|
|
||||||
fn from(value: v2::response::RemainingBandwidthResponse) -> Self {
|
|
||||||
Self {
|
|
||||||
request_id: value.request_id,
|
|
||||||
reply_to: value.reply_to,
|
|
||||||
reply: value.reply.map(Into::into),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v3::registration::RegistrationData> for v2::registration::RegistrationData {
|
impl From<v3::registration::RegistrationData> for v2::registration::RegistrationData {
|
||||||
fn from(value: v3::registration::RegistrationData) -> Self {
|
fn from(value: v3::registration::RegistrationData) -> Self {
|
||||||
Self {
|
Self {
|
||||||
@@ -289,16 +169,6 @@ impl From<v3::registration::RegistrationData> for v2::registration::Registration
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<v2::registration::RegistrationData> for v3::registration::RegistrationData {
|
|
||||||
fn from(value: v2::registration::RegistrationData) -> Self {
|
|
||||||
Self {
|
|
||||||
nonce: value.nonce,
|
|
||||||
gateway_data: value.gateway_data.into(),
|
|
||||||
wg_port: value.wg_port,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v3::registration::RegistredData> for v2::registration::RegistredData {
|
impl From<v3::registration::RegistredData> for v2::registration::RegistredData {
|
||||||
fn from(value: v3::registration::RegistredData) -> Self {
|
fn from(value: v3::registration::RegistredData) -> Self {
|
||||||
Self {
|
Self {
|
||||||
@@ -309,16 +179,6 @@ impl From<v3::registration::RegistredData> for v2::registration::RegistredData {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<v2::registration::RegistredData> for v3::registration::RegistredData {
|
|
||||||
fn from(value: v2::registration::RegistredData) -> Self {
|
|
||||||
Self {
|
|
||||||
pub_key: value.pub_key,
|
|
||||||
private_ip: value.private_ip,
|
|
||||||
wg_port: value.wg_port,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v3::registration::RemainingBandwidthData> for v2::registration::RemainingBandwidthData {
|
impl From<v3::registration::RemainingBandwidthData> for v2::registration::RemainingBandwidthData {
|
||||||
fn from(value: v3::registration::RemainingBandwidthData) -> Self {
|
fn from(value: v3::registration::RemainingBandwidthData) -> Self {
|
||||||
Self {
|
Self {
|
||||||
@@ -326,519 +186,3 @@ impl From<v3::registration::RemainingBandwidthData> for v2::registration::Remain
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<v2::registration::RemainingBandwidthData> for v3::registration::RemainingBandwidthData {
|
|
||||||
fn from(value: v2::registration::RemainingBandwidthData) -> Self {
|
|
||||||
Self {
|
|
||||||
available_bandwidth: value.available_bandwidth,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use std::{net::IpAddr, str::FromStr};
|
|
||||||
|
|
||||||
use nym_credentials_interface::CredentialSpendingData;
|
|
||||||
use nym_crypto::asymmetric::encryption::PrivateKey;
|
|
||||||
use nym_sphinx::addressing::Recipient;
|
|
||||||
use nym_wireguard_types::PeerPublicKey;
|
|
||||||
use x25519_dalek::PublicKey;
|
|
||||||
|
|
||||||
use super::*;
|
|
||||||
use crate::util::tests::{CREDENTIAL_BYTES, RECIPIENT};
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn upgrade_initial_req() {
|
|
||||||
let pub_key = PeerPublicKey::new(PublicKey::from([0; 32]));
|
|
||||||
let reply_to = Recipient::try_from_base58_string(RECIPIENT).unwrap();
|
|
||||||
|
|
||||||
let (msg, _) = v2::request::AuthenticatorRequest::new_initial_request(
|
|
||||||
v2::registration::InitMessage::new(pub_key),
|
|
||||||
reply_to,
|
|
||||||
);
|
|
||||||
let upgraded_msg = v3::request::AuthenticatorRequest::from(msg);
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
upgraded_msg.protocol,
|
|
||||||
Protocol {
|
|
||||||
version: 3,
|
|
||||||
service_provider_type: ServiceProviderType::Authenticator
|
|
||||||
}
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
upgraded_msg.data,
|
|
||||||
v3::request::AuthenticatorRequestData::Initial(v3::registration::InitMessage {
|
|
||||||
pub_key
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn downgrade_initial_req() {
|
|
||||||
let pub_key = PeerPublicKey::new(PublicKey::from([0; 32]));
|
|
||||||
let reply_to = Recipient::try_from_base58_string(RECIPIENT).unwrap();
|
|
||||||
|
|
||||||
let (msg, _) = v3::request::AuthenticatorRequest::new_initial_request(
|
|
||||||
v3::registration::InitMessage::new(pub_key),
|
|
||||||
reply_to,
|
|
||||||
);
|
|
||||||
let downgraded_msg = v2::request::AuthenticatorRequest::try_from(msg).unwrap();
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
downgraded_msg.protocol,
|
|
||||||
Protocol {
|
|
||||||
version: 2,
|
|
||||||
service_provider_type: ServiceProviderType::Authenticator
|
|
||||||
}
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
downgraded_msg.data,
|
|
||||||
v2::request::AuthenticatorRequestData::Initial(v2::registration::InitMessage {
|
|
||||||
pub_key
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn upgrade_final_req() {
|
|
||||||
let mut rng = rand::thread_rng();
|
|
||||||
|
|
||||||
let local_secret = PrivateKey::new(&mut rng);
|
|
||||||
let remote_secret = x25519_dalek::StaticSecret::random_from_rng(&mut rng);
|
|
||||||
let private_ip = IpAddr::from_str("10.10.10.10").unwrap();
|
|
||||||
let nonce = 42;
|
|
||||||
let gateway_client = v2::registration::GatewayClient::new(
|
|
||||||
&local_secret,
|
|
||||||
(&remote_secret).into(),
|
|
||||||
private_ip,
|
|
||||||
nonce,
|
|
||||||
);
|
|
||||||
let credential = Some(CredentialSpendingData::try_from_bytes(&CREDENTIAL_BYTES).unwrap());
|
|
||||||
let final_message = v2::registration::FinalMessage {
|
|
||||||
gateway_client,
|
|
||||||
credential: credential.clone(),
|
|
||||||
};
|
|
||||||
let reply_to = Recipient::try_from_base58_string(RECIPIENT).unwrap();
|
|
||||||
|
|
||||||
let (msg, _) =
|
|
||||||
v2::request::AuthenticatorRequest::new_final_request(final_message, reply_to);
|
|
||||||
let upgraded_msg = v3::request::AuthenticatorRequest::from(msg);
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
upgraded_msg.protocol,
|
|
||||||
Protocol {
|
|
||||||
version: 3,
|
|
||||||
service_provider_type: ServiceProviderType::Authenticator
|
|
||||||
}
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
upgraded_msg.data,
|
|
||||||
v3::request::AuthenticatorRequestData::Final(Box::new(
|
|
||||||
v3::registration::FinalMessage {
|
|
||||||
gateway_client: v3::registration::GatewayClient::new(
|
|
||||||
&local_secret,
|
|
||||||
(&remote_secret).into(),
|
|
||||||
private_ip,
|
|
||||||
nonce,
|
|
||||||
),
|
|
||||||
credential
|
|
||||||
}
|
|
||||||
))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn downgrade_final_req() {
|
|
||||||
let mut rng = rand::thread_rng();
|
|
||||||
|
|
||||||
let local_secret = PrivateKey::new(&mut rng);
|
|
||||||
let remote_secret = x25519_dalek::StaticSecret::random_from_rng(&mut rng);
|
|
||||||
let private_ip = IpAddr::from_str("10.10.10.10").unwrap();
|
|
||||||
let nonce = 42;
|
|
||||||
let gateway_client = v3::registration::GatewayClient::new(
|
|
||||||
&local_secret,
|
|
||||||
(&remote_secret).into(),
|
|
||||||
private_ip,
|
|
||||||
nonce,
|
|
||||||
);
|
|
||||||
let credential = Some(CredentialSpendingData::try_from_bytes(&CREDENTIAL_BYTES).unwrap());
|
|
||||||
let final_message = v3::registration::FinalMessage {
|
|
||||||
gateway_client,
|
|
||||||
credential: credential.clone(),
|
|
||||||
};
|
|
||||||
let reply_to = Recipient::try_from_base58_string(RECIPIENT).unwrap();
|
|
||||||
|
|
||||||
let (msg, _) =
|
|
||||||
v3::request::AuthenticatorRequest::new_final_request(final_message, reply_to);
|
|
||||||
let upgraded_msg = v2::request::AuthenticatorRequest::try_from(msg).unwrap();
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
upgraded_msg.protocol,
|
|
||||||
Protocol {
|
|
||||||
version: 2,
|
|
||||||
service_provider_type: ServiceProviderType::Authenticator
|
|
||||||
}
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
upgraded_msg.data,
|
|
||||||
v2::request::AuthenticatorRequestData::Final(Box::new(
|
|
||||||
v2::registration::FinalMessage {
|
|
||||||
gateway_client: v2::registration::GatewayClient::new(
|
|
||||||
&local_secret,
|
|
||||||
(&remote_secret).into(),
|
|
||||||
private_ip,
|
|
||||||
nonce,
|
|
||||||
),
|
|
||||||
credential
|
|
||||||
}
|
|
||||||
))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn upgrade_query_req() {
|
|
||||||
let pub_key = PeerPublicKey::new(PublicKey::from([0; 32]));
|
|
||||||
let reply_to = Recipient::try_from_base58_string(RECIPIENT).unwrap();
|
|
||||||
|
|
||||||
let (msg, _) = v2::request::AuthenticatorRequest::new_query_request(pub_key, reply_to);
|
|
||||||
let upgraded_msg = v3::request::AuthenticatorRequest::from(msg);
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
upgraded_msg.protocol,
|
|
||||||
Protocol {
|
|
||||||
version: 3,
|
|
||||||
service_provider_type: ServiceProviderType::Authenticator
|
|
||||||
}
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
upgraded_msg.data,
|
|
||||||
v3::request::AuthenticatorRequestData::QueryBandwidth(pub_key)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn downgrade_query_req() {
|
|
||||||
let pub_key = PeerPublicKey::new(PublicKey::from([0; 32]));
|
|
||||||
let reply_to = Recipient::try_from_base58_string(RECIPIENT).unwrap();
|
|
||||||
|
|
||||||
let (msg, _) = v3::request::AuthenticatorRequest::new_query_request(pub_key, reply_to);
|
|
||||||
let downgraded_msg = v2::request::AuthenticatorRequest::try_from(msg).unwrap();
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
downgraded_msg.protocol,
|
|
||||||
Protocol {
|
|
||||||
version: 2,
|
|
||||||
service_provider_type: ServiceProviderType::Authenticator
|
|
||||||
}
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
downgraded_msg.data,
|
|
||||||
v2::request::AuthenticatorRequestData::QueryBandwidth(pub_key)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn downgrade_topup_req() {
|
|
||||||
let pub_key = PeerPublicKey::new(PublicKey::from([0; 32]));
|
|
||||||
let credential = CredentialSpendingData::try_from_bytes(&CREDENTIAL_BYTES).unwrap();
|
|
||||||
let top_up_message = v3::topup::TopUpMessage {
|
|
||||||
pub_key,
|
|
||||||
credential,
|
|
||||||
};
|
|
||||||
let reply_to = Recipient::try_from_base58_string(RECIPIENT).unwrap();
|
|
||||||
|
|
||||||
let (msg, _) =
|
|
||||||
v3::request::AuthenticatorRequest::new_topup_request(top_up_message, reply_to);
|
|
||||||
assert!(v2::request::AuthenticatorRequest::try_from(msg).is_err());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn upgrade_pending_reg_resp() {
|
|
||||||
let mut rng = rand::thread_rng();
|
|
||||||
|
|
||||||
let local_secret = PrivateKey::new(&mut rng);
|
|
||||||
let remote_secret = x25519_dalek::StaticSecret::random_from_rng(&mut rng);
|
|
||||||
let private_ip = IpAddr::from_str("10.10.10.10").unwrap();
|
|
||||||
let nonce = 42;
|
|
||||||
let wg_port = 51822;
|
|
||||||
let gateway_data = v2::registration::GatewayClient::new(
|
|
||||||
&local_secret,
|
|
||||||
(&remote_secret).into(),
|
|
||||||
private_ip,
|
|
||||||
nonce,
|
|
||||||
);
|
|
||||||
let registration_data = v2::registration::RegistrationData {
|
|
||||||
nonce,
|
|
||||||
gateway_data,
|
|
||||||
wg_port,
|
|
||||||
};
|
|
||||||
let request_id = 123;
|
|
||||||
let reply_to = Recipient::try_from_base58_string(RECIPIENT).unwrap();
|
|
||||||
|
|
||||||
let msg = v2::response::AuthenticatorResponse::new_pending_registration_success(
|
|
||||||
registration_data,
|
|
||||||
request_id,
|
|
||||||
reply_to,
|
|
||||||
);
|
|
||||||
let upgraded_msg = v3::response::AuthenticatorResponse::from(msg);
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
upgraded_msg.protocol,
|
|
||||||
Protocol {
|
|
||||||
version: 3,
|
|
||||||
service_provider_type: ServiceProviderType::Authenticator
|
|
||||||
}
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
upgraded_msg.data,
|
|
||||||
v3::response::AuthenticatorResponseData::PendingRegistration(
|
|
||||||
v3::response::PendingRegistrationResponse {
|
|
||||||
request_id,
|
|
||||||
reply_to,
|
|
||||||
reply: v3::registration::RegistrationData {
|
|
||||||
nonce,
|
|
||||||
gateway_data: v3::registration::GatewayClient::new(
|
|
||||||
&local_secret,
|
|
||||||
(&remote_secret).into(),
|
|
||||||
private_ip,
|
|
||||||
nonce,
|
|
||||||
),
|
|
||||||
wg_port,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn downgrade_pending_reg_resp() {
|
|
||||||
let mut rng = rand::thread_rng();
|
|
||||||
|
|
||||||
let local_secret = PrivateKey::new(&mut rng);
|
|
||||||
let remote_secret = x25519_dalek::StaticSecret::random_from_rng(&mut rng);
|
|
||||||
let private_ip = IpAddr::from_str("10.10.10.10").unwrap();
|
|
||||||
let nonce = 42;
|
|
||||||
let wg_port = 51822;
|
|
||||||
let gateway_data = v3::registration::GatewayClient::new(
|
|
||||||
&local_secret,
|
|
||||||
(&remote_secret).into(),
|
|
||||||
private_ip,
|
|
||||||
nonce,
|
|
||||||
);
|
|
||||||
let registration_data = v3::registration::RegistrationData {
|
|
||||||
nonce,
|
|
||||||
gateway_data,
|
|
||||||
wg_port,
|
|
||||||
};
|
|
||||||
let request_id = 123;
|
|
||||||
let reply_to = Recipient::try_from_base58_string(RECIPIENT).unwrap();
|
|
||||||
|
|
||||||
let msg = v3::response::AuthenticatorResponse::new_pending_registration_success(
|
|
||||||
registration_data,
|
|
||||||
request_id,
|
|
||||||
reply_to,
|
|
||||||
);
|
|
||||||
let downgraded_msg = v2::response::AuthenticatorResponse::try_from(msg).unwrap();
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
downgraded_msg.protocol,
|
|
||||||
Protocol {
|
|
||||||
version: 2,
|
|
||||||
service_provider_type: ServiceProviderType::Authenticator
|
|
||||||
}
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
downgraded_msg.data,
|
|
||||||
v2::response::AuthenticatorResponseData::PendingRegistration(
|
|
||||||
v2::response::PendingRegistrationResponse {
|
|
||||||
request_id,
|
|
||||||
reply_to,
|
|
||||||
reply: v2::registration::RegistrationData {
|
|
||||||
nonce,
|
|
||||||
gateway_data: v2::registration::GatewayClient::new(
|
|
||||||
&local_secret,
|
|
||||||
(&remote_secret).into(),
|
|
||||||
private_ip,
|
|
||||||
nonce,
|
|
||||||
),
|
|
||||||
wg_port,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn upgrade_registered_resp() {
|
|
||||||
let pub_key = PeerPublicKey::new(PublicKey::from([0; 32]));
|
|
||||||
let private_ip = IpAddr::from_str("10.10.10.10").unwrap();
|
|
||||||
let wg_port = 51822;
|
|
||||||
let registred_data = v2::registration::RegistredData {
|
|
||||||
pub_key,
|
|
||||||
private_ip,
|
|
||||||
wg_port,
|
|
||||||
};
|
|
||||||
let request_id = 123;
|
|
||||||
let reply_to = Recipient::try_from_base58_string(RECIPIENT).unwrap();
|
|
||||||
|
|
||||||
let msg = v2::response::AuthenticatorResponse::new_registered(
|
|
||||||
registred_data,
|
|
||||||
reply_to,
|
|
||||||
request_id,
|
|
||||||
);
|
|
||||||
let upgraded_msg = v3::response::AuthenticatorResponse::from(msg);
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
upgraded_msg.protocol,
|
|
||||||
Protocol {
|
|
||||||
version: 3,
|
|
||||||
service_provider_type: ServiceProviderType::Authenticator
|
|
||||||
}
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
upgraded_msg.data,
|
|
||||||
v3::response::AuthenticatorResponseData::Registered(v3::response::RegisteredResponse {
|
|
||||||
request_id,
|
|
||||||
reply_to,
|
|
||||||
reply: v3::registration::RegistredData {
|
|
||||||
wg_port,
|
|
||||||
pub_key,
|
|
||||||
private_ip
|
|
||||||
}
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn downgrade_registered_resp() {
|
|
||||||
let pub_key = PeerPublicKey::new(PublicKey::from([0; 32]));
|
|
||||||
let private_ip = IpAddr::from_str("10.10.10.10").unwrap();
|
|
||||||
let wg_port = 51822;
|
|
||||||
let registred_data = v3::registration::RegistredData {
|
|
||||||
pub_key,
|
|
||||||
private_ip,
|
|
||||||
wg_port,
|
|
||||||
};
|
|
||||||
let request_id = 123;
|
|
||||||
let reply_to = Recipient::try_from_base58_string(RECIPIENT).unwrap();
|
|
||||||
|
|
||||||
let msg = v3::response::AuthenticatorResponse::new_registered(
|
|
||||||
registred_data,
|
|
||||||
reply_to,
|
|
||||||
request_id,
|
|
||||||
);
|
|
||||||
let downgraded_msg = v2::response::AuthenticatorResponse::try_from(msg).unwrap();
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
downgraded_msg.protocol,
|
|
||||||
Protocol {
|
|
||||||
version: 2,
|
|
||||||
service_provider_type: ServiceProviderType::Authenticator
|
|
||||||
}
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
downgraded_msg.data,
|
|
||||||
v2::response::AuthenticatorResponseData::Registered(v2::response::RegisteredResponse {
|
|
||||||
request_id,
|
|
||||||
reply_to,
|
|
||||||
reply: v2::registration::RegistredData {
|
|
||||||
wg_port,
|
|
||||||
pub_key,
|
|
||||||
private_ip
|
|
||||||
}
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn upgrade_remaining_bandwidth_resp() {
|
|
||||||
let available_bandwidth = 42;
|
|
||||||
let remaining_bandwidth_data = Some(v2::registration::RemainingBandwidthData {
|
|
||||||
available_bandwidth,
|
|
||||||
});
|
|
||||||
let request_id = 123;
|
|
||||||
let reply_to = Recipient::try_from_base58_string(RECIPIENT).unwrap();
|
|
||||||
|
|
||||||
let msg = v2::response::AuthenticatorResponse::new_remaining_bandwidth(
|
|
||||||
remaining_bandwidth_data,
|
|
||||||
reply_to,
|
|
||||||
request_id,
|
|
||||||
);
|
|
||||||
let upgraded_msg = v3::response::AuthenticatorResponse::from(msg);
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
upgraded_msg.protocol,
|
|
||||||
Protocol {
|
|
||||||
version: 3,
|
|
||||||
service_provider_type: ServiceProviderType::Authenticator
|
|
||||||
}
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
upgraded_msg.data,
|
|
||||||
v3::response::AuthenticatorResponseData::RemainingBandwidth(
|
|
||||||
v3::response::RemainingBandwidthResponse {
|
|
||||||
request_id,
|
|
||||||
reply_to,
|
|
||||||
reply: Some(v3::registration::RemainingBandwidthData {
|
|
||||||
available_bandwidth,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn downgrade_remaining_bandwidth_resp() {
|
|
||||||
let available_bandwidth = 42;
|
|
||||||
let remaining_bandwidth_data = Some(v3::registration::RemainingBandwidthData {
|
|
||||||
available_bandwidth,
|
|
||||||
});
|
|
||||||
let request_id = 123;
|
|
||||||
let reply_to = Recipient::try_from_base58_string(RECIPIENT).unwrap();
|
|
||||||
|
|
||||||
let msg = v3::response::AuthenticatorResponse::new_remaining_bandwidth(
|
|
||||||
remaining_bandwidth_data,
|
|
||||||
reply_to,
|
|
||||||
request_id,
|
|
||||||
);
|
|
||||||
let downgraded_msg = v2::response::AuthenticatorResponse::try_from(msg).unwrap();
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
downgraded_msg.protocol,
|
|
||||||
Protocol {
|
|
||||||
version: 2,
|
|
||||||
service_provider_type: ServiceProviderType::Authenticator
|
|
||||||
}
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
downgraded_msg.data,
|
|
||||||
v2::response::AuthenticatorResponseData::RemainingBandwidth(
|
|
||||||
v2::response::RemainingBandwidthResponse {
|
|
||||||
request_id,
|
|
||||||
reply_to,
|
|
||||||
reply: Some(v2::registration::RemainingBandwidthData {
|
|
||||||
available_bandwidth,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn downgrade_topup_resp() {
|
|
||||||
let available_bandwidth = 42;
|
|
||||||
let remaining_bandwidth_data = v3::registration::RemainingBandwidthData {
|
|
||||||
available_bandwidth,
|
|
||||||
};
|
|
||||||
let request_id = 123;
|
|
||||||
let reply_to = Recipient::try_from_base58_string(RECIPIENT).unwrap();
|
|
||||||
|
|
||||||
let msg = v3::response::AuthenticatorResponse::new_topup_bandwidth(
|
|
||||||
remaining_bandwidth_data,
|
|
||||||
reply_to,
|
|
||||||
request_id,
|
|
||||||
);
|
|
||||||
assert!(v2::response::AuthenticatorResponse::try_from(msg).is_err());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -27,9 +27,9 @@ pub type HmacSha256 = Hmac<Sha256>;
|
|||||||
pub type Nonce = u64;
|
pub type Nonce = u64;
|
||||||
pub type Taken = Option<SystemTime>;
|
pub type Taken = Option<SystemTime>;
|
||||||
|
|
||||||
pub const BANDWIDTH_CAP_PER_DAY: u64 = 250 * 1024 * 1024 * 1024; // 250 GB
|
pub const BANDWIDTH_CAP_PER_DAY: u64 = 1024 * 1024 * 1024; // 1 GB
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
pub struct InitMessage {
|
pub struct InitMessage {
|
||||||
/// Base64 encoded x25519 public key
|
/// Base64 encoded x25519 public key
|
||||||
pub pub_key: PeerPublicKey,
|
pub pub_key: PeerPublicKey,
|
||||||
@@ -41,7 +41,7 @@ impl InitMessage {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
pub struct FinalMessage {
|
pub struct FinalMessage {
|
||||||
/// Gateway client data
|
/// Gateway client data
|
||||||
pub gateway_client: GatewayClient,
|
pub gateway_client: GatewayClient,
|
||||||
@@ -50,28 +50,28 @@ pub struct FinalMessage {
|
|||||||
pub credential: Option<CredentialSpendingData>,
|
pub credential: Option<CredentialSpendingData>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
pub struct RegistrationData {
|
pub struct RegistrationData {
|
||||||
pub nonce: u64,
|
pub nonce: u64,
|
||||||
pub gateway_data: GatewayClient,
|
pub gateway_data: GatewayClient,
|
||||||
pub wg_port: u16,
|
pub wg_port: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
pub struct RegistredData {
|
pub struct RegistredData {
|
||||||
pub pub_key: PeerPublicKey,
|
pub pub_key: PeerPublicKey,
|
||||||
pub private_ip: IpAddr,
|
pub private_ip: IpAddr,
|
||||||
pub wg_port: u16,
|
pub wg_port: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
pub struct RemainingBandwidthData {
|
pub struct RemainingBandwidthData {
|
||||||
pub available_bandwidth: i64,
|
pub available_bandwidth: i64,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Client that wants to register sends its PublicKey bytes mac digest encrypted with a DH shared secret.
|
/// Client that wants to register sends its PublicKey bytes mac digest encrypted with a DH shared secret.
|
||||||
/// Gateway/Nym node can then verify pub_key payload using the same process
|
/// Gateway/Nym node can then verify pub_key payload using the same process
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
pub struct GatewayClient {
|
pub struct GatewayClient {
|
||||||
/// Base64 encoded x25519 public key
|
/// Base64 encoded x25519 public key
|
||||||
pub pub_key: PeerPublicKey,
|
pub pub_key: PeerPublicKey,
|
||||||
@@ -147,7 +147,7 @@ impl GatewayClient {
|
|||||||
|
|
||||||
// TODO: change the inner type into generic array of size HmacSha256::OutputSize
|
// TODO: change the inner type into generic array of size HmacSha256::OutputSize
|
||||||
// TODO2: rely on our internal crypto/hmac
|
// TODO2: rely on our internal crypto/hmac
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct ClientMac(Vec<u8>);
|
pub struct ClientMac(Vec<u8>);
|
||||||
|
|
||||||
impl fmt::Display for ClientMac {
|
impl fmt::Display for ClientMac {
|
||||||
|
|||||||
@@ -20,6 +20,11 @@ fn generate_random() -> u64 {
|
|||||||
rng.next_u64()
|
rng.next_u64()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
|
pub struct QueryMessage {
|
||||||
|
pub pub_key: PeerPublicKey,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
pub struct AuthenticatorRequest {
|
pub struct AuthenticatorRequest {
|
||||||
pub protocol: Protocol,
|
pub protocol: Protocol,
|
||||||
@@ -68,7 +73,7 @@ impl AuthenticatorRequest {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_query_request(peer_public_key: PeerPublicKey, reply_to: Recipient) -> (Self, u64) {
|
pub fn new_query_request(query_message: QueryMessage, reply_to: Recipient) -> (Self, u64) {
|
||||||
let request_id = generate_random();
|
let request_id = generate_random();
|
||||||
(
|
(
|
||||||
Self {
|
Self {
|
||||||
@@ -76,7 +81,7 @@ impl AuthenticatorRequest {
|
|||||||
service_provider_type: ServiceProviderType::Authenticator,
|
service_provider_type: ServiceProviderType::Authenticator,
|
||||||
version: VERSION,
|
version: VERSION,
|
||||||
},
|
},
|
||||||
data: AuthenticatorRequestData::QueryBandwidth(peer_public_key),
|
data: AuthenticatorRequestData::QueryBandwidth(query_message.pub_key),
|
||||||
reply_to,
|
reply_to,
|
||||||
request_id,
|
request_id,
|
||||||
},
|
},
|
||||||
@@ -106,7 +111,7 @@ impl AuthenticatorRequest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
pub enum AuthenticatorRequestData {
|
pub enum AuthenticatorRequestData {
|
||||||
Initial(InitMessage),
|
Initial(InitMessage),
|
||||||
Final(Box<FinalMessage>),
|
Final(Box<FinalMessage>),
|
||||||
|
|||||||
@@ -120,7 +120,7 @@ impl AuthenticatorResponse {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
pub enum AuthenticatorResponseData {
|
pub enum AuthenticatorResponseData {
|
||||||
PendingRegistration(PendingRegistrationResponse),
|
PendingRegistration(PendingRegistrationResponse),
|
||||||
Registered(RegisteredResponse),
|
Registered(RegisteredResponse),
|
||||||
@@ -128,28 +128,28 @@ pub enum AuthenticatorResponseData {
|
|||||||
TopUpBandwidth(TopUpBandwidthResponse),
|
TopUpBandwidth(TopUpBandwidthResponse),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
pub struct PendingRegistrationResponse {
|
pub struct PendingRegistrationResponse {
|
||||||
pub request_id: u64,
|
pub request_id: u64,
|
||||||
pub reply_to: Recipient,
|
pub reply_to: Recipient,
|
||||||
pub reply: RegistrationData,
|
pub reply: RegistrationData,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
pub struct RegisteredResponse {
|
pub struct RegisteredResponse {
|
||||||
pub request_id: u64,
|
pub request_id: u64,
|
||||||
pub reply_to: Recipient,
|
pub reply_to: Recipient,
|
||||||
pub reply: RegistredData,
|
pub reply: RegistredData,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
pub struct RemainingBandwidthResponse {
|
pub struct RemainingBandwidthResponse {
|
||||||
pub request_id: u64,
|
pub request_id: u64,
|
||||||
pub reply_to: Recipient,
|
pub reply_to: Recipient,
|
||||||
pub reply: Option<RemainingBandwidthData>,
|
pub reply: Option<RemainingBandwidthData>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
pub struct TopUpBandwidthResponse {
|
pub struct TopUpBandwidthResponse {
|
||||||
pub request_id: u64,
|
pub request_id: u64,
|
||||||
pub reply_to: Recipient,
|
pub reply_to: Recipient,
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ use nym_credentials_interface::CredentialSpendingData;
|
|||||||
use nym_wireguard_types::PeerPublicKey;
|
use nym_wireguard_types::PeerPublicKey;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
pub struct TopUpMessage {
|
pub struct TopUpMessage {
|
||||||
/// Base64 encoded x25519 public key
|
/// Base64 encoded x25519 public key
|
||||||
pub pub_key: PeerPublicKey,
|
pub pub_key: PeerPublicKey,
|
||||||
|
|||||||
@@ -5,80 +5,35 @@ use nym_service_provider_requests_common::{Protocol, ServiceProviderType};
|
|||||||
|
|
||||||
use crate::{v3, v4};
|
use crate::{v3, v4};
|
||||||
|
|
||||||
impl TryFrom<v3::request::AuthenticatorRequest> for v4::request::AuthenticatorRequest {
|
impl From<v3::request::AuthenticatorRequest> for v4::request::AuthenticatorRequest {
|
||||||
type Error = crate::Error;
|
fn from(authenticator_request: v3::request::AuthenticatorRequest) -> Self {
|
||||||
fn try_from(
|
Self {
|
||||||
authenticator_request: v3::request::AuthenticatorRequest,
|
|
||||||
) -> Result<Self, Self::Error> {
|
|
||||||
Ok(Self {
|
|
||||||
protocol: Protocol {
|
protocol: Protocol {
|
||||||
version: 4,
|
version: 4,
|
||||||
service_provider_type: ServiceProviderType::Authenticator,
|
service_provider_type: ServiceProviderType::Authenticator,
|
||||||
},
|
},
|
||||||
data: authenticator_request.data.try_into()?,
|
data: authenticator_request.data.into(),
|
||||||
reply_to: authenticator_request.reply_to,
|
reply_to: authenticator_request.reply_to,
|
||||||
request_id: authenticator_request.request_id,
|
request_id: authenticator_request.request_id,
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TryFrom<v4::request::AuthenticatorRequest> for v3::request::AuthenticatorRequest {
|
|
||||||
type Error = crate::Error;
|
|
||||||
fn try_from(
|
|
||||||
authenticator_request: v4::request::AuthenticatorRequest,
|
|
||||||
) -> Result<Self, Self::Error> {
|
|
||||||
Ok(Self {
|
|
||||||
protocol: Protocol {
|
|
||||||
version: 3,
|
|
||||||
service_provider_type: ServiceProviderType::Authenticator,
|
|
||||||
},
|
|
||||||
data: authenticator_request.data.try_into()?,
|
|
||||||
reply_to: authenticator_request.reply_to,
|
|
||||||
request_id: authenticator_request.request_id,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TryFrom<v3::request::AuthenticatorRequestData> for v4::request::AuthenticatorRequestData {
|
|
||||||
type Error = crate::Error;
|
|
||||||
fn try_from(
|
|
||||||
authenticator_request_data: v3::request::AuthenticatorRequestData,
|
|
||||||
) -> Result<Self, Self::Error> {
|
|
||||||
match authenticator_request_data {
|
|
||||||
v3::request::AuthenticatorRequestData::Initial(init_msg) => Ok(
|
|
||||||
v4::request::AuthenticatorRequestData::Initial(init_msg.into()),
|
|
||||||
),
|
|
||||||
v3::request::AuthenticatorRequestData::Final(_) => Err(Self::Error::Conversion(
|
|
||||||
"mac hash breaking change".to_string(),
|
|
||||||
)),
|
|
||||||
v3::request::AuthenticatorRequestData::QueryBandwidth(pub_key) => Ok(
|
|
||||||
v4::request::AuthenticatorRequestData::QueryBandwidth(pub_key),
|
|
||||||
),
|
|
||||||
v3::request::AuthenticatorRequestData::TopUpBandwidth(top_up_message) => Ok(
|
|
||||||
v4::request::AuthenticatorRequestData::TopUpBandwidth(top_up_message.into()),
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryFrom<v4::request::AuthenticatorRequestData> for v3::request::AuthenticatorRequestData {
|
impl From<v3::request::AuthenticatorRequestData> for v4::request::AuthenticatorRequestData {
|
||||||
type Error = crate::Error;
|
fn from(authenticator_request_data: v3::request::AuthenticatorRequestData) -> Self {
|
||||||
fn try_from(
|
|
||||||
authenticator_request_data: v4::request::AuthenticatorRequestData,
|
|
||||||
) -> Result<Self, Self::Error> {
|
|
||||||
match authenticator_request_data {
|
match authenticator_request_data {
|
||||||
v4::request::AuthenticatorRequestData::Initial(init_msg) => Ok(
|
v3::request::AuthenticatorRequestData::Initial(init_msg) => {
|
||||||
v3::request::AuthenticatorRequestData::Initial(init_msg.into()),
|
v4::request::AuthenticatorRequestData::Initial(init_msg.into())
|
||||||
),
|
}
|
||||||
v4::request::AuthenticatorRequestData::Final(_) => Err(Self::Error::Conversion(
|
v3::request::AuthenticatorRequestData::Final(gw_client) => {
|
||||||
"mac hash breaking change".to_string(),
|
v4::request::AuthenticatorRequestData::Final(gw_client.into())
|
||||||
)),
|
}
|
||||||
v4::request::AuthenticatorRequestData::QueryBandwidth(pub_key) => Ok(
|
v3::request::AuthenticatorRequestData::QueryBandwidth(pub_key) => {
|
||||||
v3::request::AuthenticatorRequestData::QueryBandwidth(pub_key),
|
v4::request::AuthenticatorRequestData::QueryBandwidth(pub_key)
|
||||||
),
|
}
|
||||||
v4::request::AuthenticatorRequestData::TopUpBandwidth(top_up_message) => Ok(
|
v3::request::AuthenticatorRequestData::TopUpBandwidth(top_up_message) => {
|
||||||
v3::request::AuthenticatorRequestData::TopUpBandwidth(top_up_message.into()),
|
v4::request::AuthenticatorRequestData::TopUpBandwidth(top_up_message.into())
|
||||||
),
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -91,11 +46,12 @@ impl From<v3::registration::InitMessage> for v4::registration::InitMessage {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<v4::registration::InitMessage> for v3::registration::InitMessage {
|
impl From<Box<v3::registration::FinalMessage>> for Box<v4::registration::FinalMessage> {
|
||||||
fn from(init_msg: v4::registration::InitMessage) -> Self {
|
fn from(gw_client: Box<v3::registration::FinalMessage>) -> Self {
|
||||||
Self {
|
Box::new(v4::registration::FinalMessage {
|
||||||
pub_key: init_msg.pub_key,
|
gateway_client: gw_client.gateway_client.into(),
|
||||||
}
|
credential: gw_client.credential,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,26 +64,35 @@ impl From<Box<v3::topup::TopUpMessage>> for Box<v4::topup::TopUpMessage> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Box<v4::topup::TopUpMessage>> for Box<v3::topup::TopUpMessage> {
|
impl From<v3::registration::GatewayClient> for v4::registration::GatewayClient {
|
||||||
fn from(top_up_message: Box<v4::topup::TopUpMessage>) -> Self {
|
fn from(gw_client: v3::registration::GatewayClient) -> Self {
|
||||||
Box::new(v3::topup::TopUpMessage {
|
Self {
|
||||||
pub_key: top_up_message.pub_key,
|
pub_key: gw_client.pub_key,
|
||||||
credential: top_up_message.credential,
|
private_ips: gw_client.private_ip.into(),
|
||||||
})
|
mac: gw_client.mac.into(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryFrom<v3::response::AuthenticatorResponse> for v4::response::AuthenticatorResponse {
|
impl From<v4::registration::GatewayClient> for v3::registration::GatewayClient {
|
||||||
type Error = crate::Error;
|
fn from(gw_client: v4::registration::GatewayClient) -> Self {
|
||||||
fn try_from(value: v3::response::AuthenticatorResponse) -> Result<Self, Self::Error> {
|
Self {
|
||||||
Ok(Self {
|
pub_key: gw_client.pub_key,
|
||||||
protocol: Protocol {
|
private_ip: gw_client.private_ips.ipv4.into(),
|
||||||
version: 4,
|
mac: gw_client.mac.into(),
|
||||||
service_provider_type: value.protocol.service_provider_type,
|
}
|
||||||
},
|
}
|
||||||
data: value.data.try_into()?,
|
}
|
||||||
reply_to: value.reply_to,
|
|
||||||
})
|
impl From<v3::registration::ClientMac> for v4::registration::ClientMac {
|
||||||
|
fn from(mac: v3::registration::ClientMac) -> Self {
|
||||||
|
Self::new(mac.to_vec())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<v4::registration::ClientMac> for v3::registration::ClientMac {
|
||||||
|
fn from(mac: v4::registration::ClientMac) -> Self {
|
||||||
|
Self::new(mac.to_vec())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -140,40 +105,11 @@ impl TryFrom<v4::response::AuthenticatorResponse> for v3::response::Authenticato
|
|||||||
Ok(Self {
|
Ok(Self {
|
||||||
data: authenticator_response.data.try_into()?,
|
data: authenticator_response.data.try_into()?,
|
||||||
reply_to: authenticator_response.reply_to,
|
reply_to: authenticator_response.reply_to,
|
||||||
protocol: Protocol {
|
protocol: authenticator_response.protocol,
|
||||||
version: 3,
|
|
||||||
service_provider_type: authenticator_response.protocol.service_provider_type,
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryFrom<v3::response::AuthenticatorResponseData> for v4::response::AuthenticatorResponseData {
|
|
||||||
type Error = crate::Error;
|
|
||||||
fn try_from(
|
|
||||||
authenticator_response_data: v3::response::AuthenticatorResponseData,
|
|
||||||
) -> Result<Self, Self::Error> {
|
|
||||||
match authenticator_response_data {
|
|
||||||
v3::response::AuthenticatorResponseData::PendingRegistration(_) => Err(
|
|
||||||
Self::Error::Conversion("mac hash breaking change".to_string()),
|
|
||||||
),
|
|
||||||
|
|
||||||
v3::response::AuthenticatorResponseData::Registered(registered_response) => Ok(
|
|
||||||
v4::response::AuthenticatorResponseData::Registered(registered_response.into()),
|
|
||||||
),
|
|
||||||
|
|
||||||
v3::response::AuthenticatorResponseData::RemainingBandwidth(
|
|
||||||
remaining_bandwidth_response,
|
|
||||||
) => Ok(v4::response::AuthenticatorResponseData::RemainingBandwidth(
|
|
||||||
remaining_bandwidth_response.into(),
|
|
||||||
)),
|
|
||||||
v3::response::AuthenticatorResponseData::TopUpBandwidth(top_up_response) => Ok(
|
|
||||||
v4::response::AuthenticatorResponseData::TopUpBandwidth(top_up_response.into()),
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TryFrom<v4::response::AuthenticatorResponseData> for v3::response::AuthenticatorResponseData {
|
impl TryFrom<v4::response::AuthenticatorResponseData> for v3::response::AuthenticatorResponseData {
|
||||||
type Error = crate::Error;
|
type Error = crate::Error;
|
||||||
|
|
||||||
@@ -181,10 +117,13 @@ impl TryFrom<v4::response::AuthenticatorResponseData> for v3::response::Authenti
|
|||||||
authenticator_response_data: v4::response::AuthenticatorResponseData,
|
authenticator_response_data: v4::response::AuthenticatorResponseData,
|
||||||
) -> Result<Self, Self::Error> {
|
) -> Result<Self, Self::Error> {
|
||||||
match authenticator_response_data {
|
match authenticator_response_data {
|
||||||
v4::response::AuthenticatorResponseData::PendingRegistration(_) => Err(
|
v4::response::AuthenticatorResponseData::PendingRegistration(
|
||||||
Self::Error::Conversion("mac hash breaking change".to_string()),
|
pending_registration_response,
|
||||||
|
) => Ok(
|
||||||
|
v3::response::AuthenticatorResponseData::PendingRegistration(
|
||||||
|
pending_registration_response.into(),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
v4::response::AuthenticatorResponseData::Registered(registered_response) => Ok(
|
v4::response::AuthenticatorResponseData::Registered(registered_response) => Ok(
|
||||||
v3::response::AuthenticatorResponseData::Registered(registered_response.into()),
|
v3::response::AuthenticatorResponseData::Registered(registered_response.into()),
|
||||||
),
|
),
|
||||||
@@ -202,6 +141,16 @@ impl TryFrom<v4::response::AuthenticatorResponseData> for v3::response::Authenti
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<v4::response::PendingRegistrationResponse> for v3::response::PendingRegistrationResponse {
|
||||||
|
fn from(value: v4::response::PendingRegistrationResponse) -> Self {
|
||||||
|
Self {
|
||||||
|
request_id: value.request_id,
|
||||||
|
reply_to: value.reply_to,
|
||||||
|
reply: value.reply.into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<v4::response::RegisteredResponse> for v3::response::RegisteredResponse {
|
impl From<v4::response::RegisteredResponse> for v3::response::RegisteredResponse {
|
||||||
fn from(value: v4::response::RegisteredResponse) -> Self {
|
fn from(value: v4::response::RegisteredResponse) -> Self {
|
||||||
Self {
|
Self {
|
||||||
@@ -212,26 +161,6 @@ impl From<v4::response::RegisteredResponse> for v3::response::RegisteredResponse
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<v3::response::RegisteredResponse> for v4::response::RegisteredResponse {
|
|
||||||
fn from(value: v3::response::RegisteredResponse) -> Self {
|
|
||||||
Self {
|
|
||||||
request_id: value.request_id,
|
|
||||||
reply_to: value.reply_to,
|
|
||||||
reply: value.reply.into(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v3::response::RemainingBandwidthResponse> for v4::response::RemainingBandwidthResponse {
|
|
||||||
fn from(value: v3::response::RemainingBandwidthResponse) -> Self {
|
|
||||||
Self {
|
|
||||||
request_id: value.request_id,
|
|
||||||
reply_to: value.reply_to,
|
|
||||||
reply: value.reply.map(Into::into),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v4::response::RemainingBandwidthResponse> for v3::response::RemainingBandwidthResponse {
|
impl From<v4::response::RemainingBandwidthResponse> for v3::response::RemainingBandwidthResponse {
|
||||||
fn from(value: v4::response::RemainingBandwidthResponse) -> Self {
|
fn from(value: v4::response::RemainingBandwidthResponse) -> Self {
|
||||||
Self {
|
Self {
|
||||||
@@ -242,31 +171,11 @@ impl From<v4::response::RemainingBandwidthResponse> for v3::response::RemainingB
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<v3::response::TopUpBandwidthResponse> for v4::response::TopUpBandwidthResponse {
|
impl From<v4::registration::RegistrationData> for v3::registration::RegistrationData {
|
||||||
fn from(value: v3::response::TopUpBandwidthResponse) -> Self {
|
fn from(value: v4::registration::RegistrationData) -> Self {
|
||||||
Self {
|
Self {
|
||||||
request_id: value.request_id,
|
nonce: value.nonce,
|
||||||
reply_to: value.reply_to,
|
gateway_data: value.gateway_data.into(),
|
||||||
reply: value.reply.into(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v4::response::TopUpBandwidthResponse> for v3::response::TopUpBandwidthResponse {
|
|
||||||
fn from(value: v4::response::TopUpBandwidthResponse) -> Self {
|
|
||||||
Self {
|
|
||||||
request_id: value.request_id,
|
|
||||||
reply_to: value.reply_to,
|
|
||||||
reply: value.reply.into(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v3::registration::RegistredData> for v4::registration::RegistredData {
|
|
||||||
fn from(value: v3::registration::RegistredData) -> Self {
|
|
||||||
Self {
|
|
||||||
pub_key: value.pub_key,
|
|
||||||
private_ips: value.private_ip.into(),
|
|
||||||
wg_port: value.wg_port,
|
wg_port: value.wg_port,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -282,14 +191,6 @@ impl From<v4::registration::RegistredData> for v3::registration::RegistredData {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<v3::registration::RemainingBandwidthData> for v4::registration::RemainingBandwidthData {
|
|
||||||
fn from(value: v3::registration::RemainingBandwidthData) -> Self {
|
|
||||||
Self {
|
|
||||||
available_bandwidth: value.available_bandwidth,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v4::registration::RemainingBandwidthData> for v3::registration::RemainingBandwidthData {
|
impl From<v4::registration::RemainingBandwidthData> for v3::registration::RemainingBandwidthData {
|
||||||
fn from(value: v4::registration::RemainingBandwidthData) -> Self {
|
fn from(value: v4::registration::RemainingBandwidthData) -> Self {
|
||||||
Self {
|
Self {
|
||||||
@@ -297,441 +198,3 @@ impl From<v4::registration::RemainingBandwidthData> for v3::registration::Remain
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use std::{
|
|
||||||
net::{Ipv4Addr, Ipv6Addr},
|
|
||||||
str::FromStr,
|
|
||||||
};
|
|
||||||
|
|
||||||
use nym_credentials_interface::CredentialSpendingData;
|
|
||||||
use nym_crypto::asymmetric::encryption::PrivateKey;
|
|
||||||
use nym_sphinx::addressing::Recipient;
|
|
||||||
use nym_wireguard_types::PeerPublicKey;
|
|
||||||
use x25519_dalek::PublicKey;
|
|
||||||
|
|
||||||
use super::*;
|
|
||||||
use crate::util::tests::{CREDENTIAL_BYTES, RECIPIENT};
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn upgrade_initial_req() {
|
|
||||||
let pub_key = PeerPublicKey::new(PublicKey::from([0; 32]));
|
|
||||||
let reply_to = Recipient::try_from_base58_string(RECIPIENT).unwrap();
|
|
||||||
|
|
||||||
let (msg, _) = v3::request::AuthenticatorRequest::new_initial_request(
|
|
||||||
v3::registration::InitMessage::new(pub_key),
|
|
||||||
reply_to,
|
|
||||||
);
|
|
||||||
let upgraded_msg = v4::request::AuthenticatorRequest::try_from(msg).unwrap();
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
upgraded_msg.protocol,
|
|
||||||
Protocol {
|
|
||||||
version: 4,
|
|
||||||
service_provider_type: ServiceProviderType::Authenticator
|
|
||||||
}
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
upgraded_msg.data,
|
|
||||||
v4::request::AuthenticatorRequestData::Initial(v4::registration::InitMessage {
|
|
||||||
pub_key
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn downgrade_initial_req() {
|
|
||||||
let pub_key = PeerPublicKey::new(PublicKey::from([0; 32]));
|
|
||||||
let reply_to = Recipient::try_from_base58_string(RECIPIENT).unwrap();
|
|
||||||
|
|
||||||
let (msg, _) = v4::request::AuthenticatorRequest::new_initial_request(
|
|
||||||
v4::registration::InitMessage::new(pub_key),
|
|
||||||
reply_to,
|
|
||||||
);
|
|
||||||
let downgraded_msg = v3::request::AuthenticatorRequest::try_from(msg).unwrap();
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
downgraded_msg.protocol,
|
|
||||||
Protocol {
|
|
||||||
version: 3,
|
|
||||||
service_provider_type: ServiceProviderType::Authenticator
|
|
||||||
}
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
downgraded_msg.data,
|
|
||||||
v3::request::AuthenticatorRequestData::Initial(v3::registration::InitMessage {
|
|
||||||
pub_key
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn upgrade_final_req() {
|
|
||||||
let mut rng = rand::thread_rng();
|
|
||||||
|
|
||||||
let local_secret = PrivateKey::new(&mut rng);
|
|
||||||
let remote_secret = x25519_dalek::StaticSecret::random_from_rng(&mut rng);
|
|
||||||
let ipv4 = Ipv4Addr::from_str("10.10.10.10").unwrap();
|
|
||||||
let nonce = 42;
|
|
||||||
let gateway_client = v3::registration::GatewayClient::new(
|
|
||||||
&local_secret,
|
|
||||||
(&remote_secret).into(),
|
|
||||||
ipv4.into(),
|
|
||||||
nonce,
|
|
||||||
);
|
|
||||||
let credential = Some(CredentialSpendingData::try_from_bytes(&CREDENTIAL_BYTES).unwrap());
|
|
||||||
let final_message = v3::registration::FinalMessage {
|
|
||||||
gateway_client,
|
|
||||||
credential: credential.clone(),
|
|
||||||
};
|
|
||||||
let reply_to = Recipient::try_from_base58_string(RECIPIENT).unwrap();
|
|
||||||
|
|
||||||
let (msg, _) =
|
|
||||||
v3::request::AuthenticatorRequest::new_final_request(final_message, reply_to);
|
|
||||||
assert!(v4::request::AuthenticatorRequest::try_from(msg).is_err());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn downgrade_final_req() {
|
|
||||||
let mut rng = rand::thread_rng();
|
|
||||||
|
|
||||||
let local_secret = PrivateKey::new(&mut rng);
|
|
||||||
let remote_secret = x25519_dalek::StaticSecret::random_from_rng(&mut rng);
|
|
||||||
let ipv4 = Ipv4Addr::from_str("10.10.10.10").unwrap();
|
|
||||||
let private_ips =
|
|
||||||
v4::registration::IpPair::new(ipv4, Ipv6Addr::from_str("fc01::10").unwrap());
|
|
||||||
let nonce = 42;
|
|
||||||
let gateway_client = v4::registration::GatewayClient::new(
|
|
||||||
&local_secret,
|
|
||||||
(&remote_secret).into(),
|
|
||||||
private_ips,
|
|
||||||
nonce,
|
|
||||||
);
|
|
||||||
let credential = Some(CredentialSpendingData::try_from_bytes(&CREDENTIAL_BYTES).unwrap());
|
|
||||||
let final_message = v4::registration::FinalMessage {
|
|
||||||
gateway_client,
|
|
||||||
credential: credential.clone(),
|
|
||||||
};
|
|
||||||
let reply_to = Recipient::try_from_base58_string(RECIPIENT).unwrap();
|
|
||||||
|
|
||||||
let (msg, _) =
|
|
||||||
v4::request::AuthenticatorRequest::new_final_request(final_message, reply_to);
|
|
||||||
assert!(v3::request::AuthenticatorRequest::try_from(msg).is_err());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn upgrade_query_req() {
|
|
||||||
let pub_key = PeerPublicKey::new(PublicKey::from([0; 32]));
|
|
||||||
let reply_to = Recipient::try_from_base58_string(RECIPIENT).unwrap();
|
|
||||||
|
|
||||||
let (msg, _) = v3::request::AuthenticatorRequest::new_query_request(pub_key, reply_to);
|
|
||||||
let upgraded_msg = v4::request::AuthenticatorRequest::try_from(msg).unwrap();
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
upgraded_msg.protocol,
|
|
||||||
Protocol {
|
|
||||||
version: 4,
|
|
||||||
service_provider_type: ServiceProviderType::Authenticator
|
|
||||||
}
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
upgraded_msg.data,
|
|
||||||
v4::request::AuthenticatorRequestData::QueryBandwidth(pub_key)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn downgrade_query_req() {
|
|
||||||
let pub_key = PeerPublicKey::new(PublicKey::from([0; 32]));
|
|
||||||
let reply_to = Recipient::try_from_base58_string(RECIPIENT).unwrap();
|
|
||||||
|
|
||||||
let (msg, _) = v4::request::AuthenticatorRequest::new_query_request(pub_key, reply_to);
|
|
||||||
let downgraded_msg = v3::request::AuthenticatorRequest::try_from(msg).unwrap();
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
downgraded_msg.protocol,
|
|
||||||
Protocol {
|
|
||||||
version: 3,
|
|
||||||
service_provider_type: ServiceProviderType::Authenticator
|
|
||||||
}
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
downgraded_msg.data,
|
|
||||||
v3::request::AuthenticatorRequestData::QueryBandwidth(pub_key)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn downgrade_topup_req() {
|
|
||||||
let pub_key = PeerPublicKey::new(PublicKey::from([0; 32]));
|
|
||||||
let credential = CredentialSpendingData::try_from_bytes(&CREDENTIAL_BYTES).unwrap();
|
|
||||||
let top_up_message = v4::topup::TopUpMessage {
|
|
||||||
pub_key,
|
|
||||||
credential: credential.clone(),
|
|
||||||
};
|
|
||||||
let reply_to = Recipient::try_from_base58_string(RECIPIENT).unwrap();
|
|
||||||
|
|
||||||
let (msg, _) =
|
|
||||||
v4::request::AuthenticatorRequest::new_topup_request(top_up_message, reply_to);
|
|
||||||
let downgraded_msg = v3::request::AuthenticatorRequest::try_from(msg).unwrap();
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
downgraded_msg.protocol,
|
|
||||||
Protocol {
|
|
||||||
version: 3,
|
|
||||||
service_provider_type: ServiceProviderType::Authenticator
|
|
||||||
}
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
downgraded_msg.data,
|
|
||||||
v3::request::AuthenticatorRequestData::TopUpBandwidth(Box::new(
|
|
||||||
v3::topup::TopUpMessage {
|
|
||||||
pub_key,
|
|
||||||
credential
|
|
||||||
}
|
|
||||||
))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn upgrade_pending_reg_resp() {
|
|
||||||
let mut rng = rand::thread_rng();
|
|
||||||
|
|
||||||
let local_secret = PrivateKey::new(&mut rng);
|
|
||||||
let remote_secret = x25519_dalek::StaticSecret::random_from_rng(&mut rng);
|
|
||||||
let ipv4 = Ipv4Addr::from_str("10.10.10.10").unwrap();
|
|
||||||
let nonce = 42;
|
|
||||||
let wg_port = 51822;
|
|
||||||
let gateway_data = v3::registration::GatewayClient::new(
|
|
||||||
&local_secret,
|
|
||||||
(&remote_secret).into(),
|
|
||||||
ipv4.into(),
|
|
||||||
nonce,
|
|
||||||
);
|
|
||||||
let registration_data = v3::registration::RegistrationData {
|
|
||||||
nonce,
|
|
||||||
gateway_data,
|
|
||||||
wg_port,
|
|
||||||
};
|
|
||||||
let request_id = 123;
|
|
||||||
let reply_to = Recipient::try_from_base58_string(RECIPIENT).unwrap();
|
|
||||||
|
|
||||||
let msg = v3::response::AuthenticatorResponse::new_pending_registration_success(
|
|
||||||
registration_data,
|
|
||||||
request_id,
|
|
||||||
reply_to,
|
|
||||||
);
|
|
||||||
assert!(v4::response::AuthenticatorResponse::try_from(msg).is_err());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn downgrade_pending_reg_resp() {
|
|
||||||
let mut rng = rand::thread_rng();
|
|
||||||
|
|
||||||
let local_secret = PrivateKey::new(&mut rng);
|
|
||||||
let remote_secret = x25519_dalek::StaticSecret::random_from_rng(&mut rng);
|
|
||||||
let ipv4 = Ipv4Addr::from_str("10.10.10.10").unwrap();
|
|
||||||
let private_ips =
|
|
||||||
v4::registration::IpPair::new(ipv4, Ipv6Addr::from_str("fc01::10").unwrap());
|
|
||||||
let nonce = 42;
|
|
||||||
let wg_port = 51822;
|
|
||||||
let gateway_data = v4::registration::GatewayClient::new(
|
|
||||||
&local_secret,
|
|
||||||
(&remote_secret).into(),
|
|
||||||
private_ips,
|
|
||||||
nonce,
|
|
||||||
);
|
|
||||||
let registration_data = v4::registration::RegistrationData {
|
|
||||||
nonce,
|
|
||||||
gateway_data,
|
|
||||||
wg_port,
|
|
||||||
};
|
|
||||||
let request_id = 123;
|
|
||||||
let reply_to = Recipient::try_from_base58_string(RECIPIENT).unwrap();
|
|
||||||
|
|
||||||
let msg = v4::response::AuthenticatorResponse::new_pending_registration_success(
|
|
||||||
registration_data,
|
|
||||||
request_id,
|
|
||||||
reply_to,
|
|
||||||
);
|
|
||||||
assert!(v3::response::AuthenticatorResponse::try_from(msg).is_err());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn upgrade_registered_resp() {
|
|
||||||
let pub_key = PeerPublicKey::new(PublicKey::from([0; 32]));
|
|
||||||
let ipv4 = Ipv4Addr::from_str("10.1.10.10").unwrap();
|
|
||||||
let private_ips =
|
|
||||||
v4::registration::IpPair::new(ipv4, Ipv6Addr::from_str("fc01::a0a").unwrap());
|
|
||||||
let wg_port = 51822;
|
|
||||||
let registred_data = v3::registration::RegistredData {
|
|
||||||
pub_key,
|
|
||||||
private_ip: ipv4.into(),
|
|
||||||
wg_port,
|
|
||||||
};
|
|
||||||
let request_id = 123;
|
|
||||||
let reply_to = Recipient::try_from_base58_string(RECIPIENT).unwrap();
|
|
||||||
|
|
||||||
let msg = v3::response::AuthenticatorResponse::new_registered(
|
|
||||||
registred_data,
|
|
||||||
reply_to,
|
|
||||||
request_id,
|
|
||||||
);
|
|
||||||
let upgraded_msg = v4::response::AuthenticatorResponse::try_from(msg).unwrap();
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
upgraded_msg.protocol,
|
|
||||||
Protocol {
|
|
||||||
version: 4,
|
|
||||||
service_provider_type: ServiceProviderType::Authenticator
|
|
||||||
}
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
upgraded_msg.data,
|
|
||||||
v4::response::AuthenticatorResponseData::Registered(v4::response::RegisteredResponse {
|
|
||||||
request_id,
|
|
||||||
reply_to,
|
|
||||||
reply: v4::registration::RegistredData {
|
|
||||||
wg_port,
|
|
||||||
pub_key,
|
|
||||||
private_ips
|
|
||||||
}
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn downgrade_registered_resp() {
|
|
||||||
let pub_key = PeerPublicKey::new(PublicKey::from([0; 32]));
|
|
||||||
let ipv4 = Ipv4Addr::from_str("10.10.10.10").unwrap();
|
|
||||||
let private_ips =
|
|
||||||
v4::registration::IpPair::new(ipv4, Ipv6Addr::from_str("fc01::10").unwrap());
|
|
||||||
let wg_port = 51822;
|
|
||||||
let registred_data = v4::registration::RegistredData {
|
|
||||||
pub_key,
|
|
||||||
private_ips,
|
|
||||||
wg_port,
|
|
||||||
};
|
|
||||||
let request_id = 123;
|
|
||||||
let reply_to = Recipient::try_from_base58_string(RECIPIENT).unwrap();
|
|
||||||
|
|
||||||
let msg = v4::response::AuthenticatorResponse::new_registered(
|
|
||||||
registred_data,
|
|
||||||
reply_to,
|
|
||||||
request_id,
|
|
||||||
);
|
|
||||||
let downgraded_msg = v3::response::AuthenticatorResponse::try_from(msg).unwrap();
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
downgraded_msg.protocol,
|
|
||||||
Protocol {
|
|
||||||
version: 3,
|
|
||||||
service_provider_type: ServiceProviderType::Authenticator
|
|
||||||
}
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
downgraded_msg.data,
|
|
||||||
v3::response::AuthenticatorResponseData::Registered(v3::response::RegisteredResponse {
|
|
||||||
request_id,
|
|
||||||
reply_to,
|
|
||||||
reply: v3::registration::RegistredData {
|
|
||||||
wg_port,
|
|
||||||
pub_key,
|
|
||||||
private_ip: ipv4.into()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn upgrade_remaining_bandwidth_resp() {
|
|
||||||
let available_bandwidth = 42;
|
|
||||||
let remaining_bandwidth_data = Some(v3::registration::RemainingBandwidthData {
|
|
||||||
available_bandwidth,
|
|
||||||
});
|
|
||||||
let request_id = 123;
|
|
||||||
let reply_to = Recipient::try_from_base58_string(RECIPIENT).unwrap();
|
|
||||||
|
|
||||||
let msg = v3::response::AuthenticatorResponse::new_remaining_bandwidth(
|
|
||||||
remaining_bandwidth_data,
|
|
||||||
reply_to,
|
|
||||||
request_id,
|
|
||||||
);
|
|
||||||
let upgraded_msg = v4::response::AuthenticatorResponse::try_from(msg).unwrap();
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
upgraded_msg.protocol,
|
|
||||||
Protocol {
|
|
||||||
version: 4,
|
|
||||||
service_provider_type: ServiceProviderType::Authenticator
|
|
||||||
}
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
upgraded_msg.data,
|
|
||||||
v4::response::AuthenticatorResponseData::RemainingBandwidth(
|
|
||||||
v4::response::RemainingBandwidthResponse {
|
|
||||||
request_id,
|
|
||||||
reply_to,
|
|
||||||
reply: Some(v4::registration::RemainingBandwidthData {
|
|
||||||
available_bandwidth,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn downgrade_remaining_bandwidth_resp() {
|
|
||||||
let available_bandwidth = 42;
|
|
||||||
let remaining_bandwidth_data = Some(v4::registration::RemainingBandwidthData {
|
|
||||||
available_bandwidth,
|
|
||||||
});
|
|
||||||
let request_id = 123;
|
|
||||||
let reply_to = Recipient::try_from_base58_string(RECIPIENT).unwrap();
|
|
||||||
|
|
||||||
let msg = v4::response::AuthenticatorResponse::new_remaining_bandwidth(
|
|
||||||
remaining_bandwidth_data,
|
|
||||||
reply_to,
|
|
||||||
request_id,
|
|
||||||
);
|
|
||||||
let downgraded_msg = v3::response::AuthenticatorResponse::try_from(msg).unwrap();
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
downgraded_msg.protocol,
|
|
||||||
Protocol {
|
|
||||||
version: 3,
|
|
||||||
service_provider_type: ServiceProviderType::Authenticator
|
|
||||||
}
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
downgraded_msg.data,
|
|
||||||
v3::response::AuthenticatorResponseData::RemainingBandwidth(
|
|
||||||
v3::response::RemainingBandwidthResponse {
|
|
||||||
request_id,
|
|
||||||
reply_to,
|
|
||||||
reply: Some(v3::registration::RemainingBandwidthData {
|
|
||||||
available_bandwidth,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn downgrade_topup_resp() {
|
|
||||||
let available_bandwidth = 42;
|
|
||||||
let remaining_bandwidth_data = v4::registration::RemainingBandwidthData {
|
|
||||||
available_bandwidth,
|
|
||||||
};
|
|
||||||
let request_id = 123;
|
|
||||||
let reply_to = Recipient::try_from_base58_string(RECIPIENT).unwrap();
|
|
||||||
|
|
||||||
let msg = v4::response::AuthenticatorResponse::new_topup_bandwidth(
|
|
||||||
remaining_bandwidth_data,
|
|
||||||
reply_to,
|
|
||||||
request_id,
|
|
||||||
);
|
|
||||||
assert!(v3::response::AuthenticatorResponse::try_from(msg).is_err());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ pub type HmacSha256 = Hmac<Sha256>;
|
|||||||
pub type Nonce = u64;
|
pub type Nonce = u64;
|
||||||
pub type Taken = Option<SystemTime>;
|
pub type Taken = Option<SystemTime>;
|
||||||
|
|
||||||
pub const BANDWIDTH_CAP_PER_DAY: u64 = 250 * 1024 * 1024 * 1024; // 250 GB
|
pub const BANDWIDTH_CAP_PER_DAY: u64 = 1024 * 1024 * 1024; // 1 GB
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||||
pub struct IpPair {
|
pub struct IpPair {
|
||||||
@@ -42,12 +42,6 @@ impl IpPair {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<(Ipv4Addr, Ipv6Addr)> for IpPair {
|
|
||||||
fn from((ipv4, ipv6): (Ipv4Addr, Ipv6Addr)) -> Self {
|
|
||||||
IpPair { ipv4, ipv6 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for IpPair {
|
impl fmt::Display for IpPair {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
write!(f, "({}, {})", self.ipv4, self.ipv6)
|
write!(f, "({}, {})", self.ipv4, self.ipv6)
|
||||||
@@ -81,7 +75,7 @@ impl From<IpAddr> for IpPair {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
pub struct InitMessage {
|
pub struct InitMessage {
|
||||||
/// Base64 encoded x25519 public key
|
/// Base64 encoded x25519 public key
|
||||||
pub pub_key: PeerPublicKey,
|
pub pub_key: PeerPublicKey,
|
||||||
@@ -93,7 +87,7 @@ impl InitMessage {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
pub struct FinalMessage {
|
pub struct FinalMessage {
|
||||||
/// Gateway client data
|
/// Gateway client data
|
||||||
pub gateway_client: GatewayClient,
|
pub gateway_client: GatewayClient,
|
||||||
@@ -102,28 +96,28 @@ pub struct FinalMessage {
|
|||||||
pub credential: Option<CredentialSpendingData>,
|
pub credential: Option<CredentialSpendingData>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
pub struct RegistrationData {
|
pub struct RegistrationData {
|
||||||
pub nonce: u64,
|
pub nonce: u64,
|
||||||
pub gateway_data: GatewayClient,
|
pub gateway_data: GatewayClient,
|
||||||
pub wg_port: u16,
|
pub wg_port: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
pub struct RegistredData {
|
pub struct RegistredData {
|
||||||
pub pub_key: PeerPublicKey,
|
pub pub_key: PeerPublicKey,
|
||||||
pub private_ips: IpPair,
|
pub private_ips: IpPair,
|
||||||
pub wg_port: u16,
|
pub wg_port: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
pub struct RemainingBandwidthData {
|
pub struct RemainingBandwidthData {
|
||||||
pub available_bandwidth: i64,
|
pub available_bandwidth: i64,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Client that wants to register sends its PublicKey bytes mac digest encrypted with a DH shared secret.
|
/// Client that wants to register sends its PublicKey bytes mac digest encrypted with a DH shared secret.
|
||||||
/// Gateway/Nym node can then verify pub_key payload using the same process
|
/// Gateway/Nym node can then verify pub_key payload using the same process
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
pub struct GatewayClient {
|
pub struct GatewayClient {
|
||||||
/// Base64 encoded x25519 public key
|
/// Base64 encoded x25519 public key
|
||||||
pub pub_key: PeerPublicKey,
|
pub pub_key: PeerPublicKey,
|
||||||
@@ -199,7 +193,7 @@ impl GatewayClient {
|
|||||||
|
|
||||||
// TODO: change the inner type into generic array of size HmacSha256::OutputSize
|
// TODO: change the inner type into generic array of size HmacSha256::OutputSize
|
||||||
// TODO2: rely on our internal crypto/hmac
|
// TODO2: rely on our internal crypto/hmac
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct ClientMac(Vec<u8>);
|
pub struct ClientMac(Vec<u8>);
|
||||||
|
|
||||||
impl fmt::Display for ClientMac {
|
impl fmt::Display for ClientMac {
|
||||||
|
|||||||
@@ -20,7 +20,12 @@ fn generate_random() -> u64 {
|
|||||||
rng.next_u64()
|
rng.next_u64()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
|
pub struct QueryMessage {
|
||||||
|
pub pub_key: PeerPublicKey,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
pub struct AuthenticatorRequest {
|
pub struct AuthenticatorRequest {
|
||||||
pub protocol: Protocol,
|
pub protocol: Protocol,
|
||||||
pub data: AuthenticatorRequestData,
|
pub data: AuthenticatorRequestData,
|
||||||
@@ -68,7 +73,7 @@ impl AuthenticatorRequest {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_query_request(peer_public_key: PeerPublicKey, reply_to: Recipient) -> (Self, u64) {
|
pub fn new_query_request(query_message: QueryMessage, reply_to: Recipient) -> (Self, u64) {
|
||||||
let request_id = generate_random();
|
let request_id = generate_random();
|
||||||
(
|
(
|
||||||
Self {
|
Self {
|
||||||
@@ -76,7 +81,7 @@ impl AuthenticatorRequest {
|
|||||||
service_provider_type: ServiceProviderType::Authenticator,
|
service_provider_type: ServiceProviderType::Authenticator,
|
||||||
version: VERSION,
|
version: VERSION,
|
||||||
},
|
},
|
||||||
data: AuthenticatorRequestData::QueryBandwidth(peer_public_key),
|
data: AuthenticatorRequestData::QueryBandwidth(query_message.pub_key),
|
||||||
reply_to,
|
reply_to,
|
||||||
request_id,
|
request_id,
|
||||||
},
|
},
|
||||||
@@ -106,7 +111,7 @@ impl AuthenticatorRequest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
pub enum AuthenticatorRequestData {
|
pub enum AuthenticatorRequestData {
|
||||||
Initial(InitMessage),
|
Initial(InitMessage),
|
||||||
Final(Box<FinalMessage>),
|
Final(Box<FinalMessage>),
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ use crate::make_bincode_serializer;
|
|||||||
|
|
||||||
use super::VERSION;
|
use super::VERSION;
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
pub struct AuthenticatorResponse {
|
pub struct AuthenticatorResponse {
|
||||||
pub protocol: Protocol,
|
pub protocol: Protocol,
|
||||||
pub data: AuthenticatorResponseData,
|
pub data: AuthenticatorResponseData,
|
||||||
@@ -120,7 +120,7 @@ impl AuthenticatorResponse {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
pub enum AuthenticatorResponseData {
|
pub enum AuthenticatorResponseData {
|
||||||
PendingRegistration(PendingRegistrationResponse),
|
PendingRegistration(PendingRegistrationResponse),
|
||||||
Registered(RegisteredResponse),
|
Registered(RegisteredResponse),
|
||||||
@@ -128,28 +128,28 @@ pub enum AuthenticatorResponseData {
|
|||||||
TopUpBandwidth(TopUpBandwidthResponse),
|
TopUpBandwidth(TopUpBandwidthResponse),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
pub struct PendingRegistrationResponse {
|
pub struct PendingRegistrationResponse {
|
||||||
pub request_id: u64,
|
pub request_id: u64,
|
||||||
pub reply_to: Recipient,
|
pub reply_to: Recipient,
|
||||||
pub reply: RegistrationData,
|
pub reply: RegistrationData,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
pub struct RegisteredResponse {
|
pub struct RegisteredResponse {
|
||||||
pub request_id: u64,
|
pub request_id: u64,
|
||||||
pub reply_to: Recipient,
|
pub reply_to: Recipient,
|
||||||
pub reply: RegistredData,
|
pub reply: RegistredData,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
pub struct RemainingBandwidthResponse {
|
pub struct RemainingBandwidthResponse {
|
||||||
pub request_id: u64,
|
pub request_id: u64,
|
||||||
pub reply_to: Recipient,
|
pub reply_to: Recipient,
|
||||||
pub reply: Option<RemainingBandwidthData>,
|
pub reply: Option<RemainingBandwidthData>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
pub struct TopUpBandwidthResponse {
|
pub struct TopUpBandwidthResponse {
|
||||||
pub request_id: u64,
|
pub request_id: u64,
|
||||||
pub reply_to: Recipient,
|
pub reply_to: Recipient,
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ use nym_credentials_interface::CredentialSpendingData;
|
|||||||
use nym_wireguard_types::PeerPublicKey;
|
use nym_wireguard_types::PeerPublicKey;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
pub struct TopUpMessage {
|
pub struct TopUpMessage {
|
||||||
/// Base64 encoded x25519 public key
|
/// Base64 encoded x25519 public key
|
||||||
pub pub_key: PeerPublicKey,
|
pub pub_key: PeerPublicKey,
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ use nym_validator_client::coconut::all_ecash_api_clients;
|
|||||||
use nym_validator_client::nym_api::EpochId;
|
use nym_validator_client::nym_api::EpochId;
|
||||||
use nym_validator_client::nyxd::contract_traits::EcashSigningClient;
|
use nym_validator_client::nyxd::contract_traits::EcashSigningClient;
|
||||||
use nym_validator_client::nyxd::contract_traits::{DkgQueryClient, EcashQueryClient};
|
use nym_validator_client::nyxd::contract_traits::{DkgQueryClient, EcashQueryClient};
|
||||||
use nym_validator_client::nyxd::cosmwasm_client::ContractResponseData;
|
use nym_validator_client::nyxd::cosmwasm_client::ToSingletonContractData;
|
||||||
use nym_validator_client::EcashApiClient;
|
use nym_validator_client::EcashApiClient;
|
||||||
use rand::rngs::OsRng;
|
use rand::rngs::OsRng;
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ const-str = { workspace = true }
|
|||||||
log = { workspace = true }
|
log = { workspace = true }
|
||||||
pretty_env_logger = { workspace = true }
|
pretty_env_logger = { workspace = true }
|
||||||
schemars = { workspace = true, features = ["preserve_order"], optional = true }
|
schemars = { workspace = true, features = ["preserve_order"], optional = true }
|
||||||
|
semver.workspace = true
|
||||||
serde = { workspace = true, features = ["derive"] }
|
serde = { workspace = true, features = ["derive"] }
|
||||||
serde_json = { workspace = true, optional = true }
|
serde_json = { workspace = true, optional = true }
|
||||||
|
|
||||||
@@ -43,5 +44,5 @@ tracing = [
|
|||||||
"tracing-opentelemetry",
|
"tracing-opentelemetry",
|
||||||
"opentelemetry",
|
"opentelemetry",
|
||||||
]
|
]
|
||||||
clap = ["dep:clap", "dep:clap_complete", "dep:clap_complete_fig"]
|
clap = [ "dep:clap", "dep:clap_complete", "dep:clap_complete_fig" ]
|
||||||
models = []
|
models = []
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
pub mod build_information;
|
pub mod build_information;
|
||||||
pub mod logging;
|
pub mod logging;
|
||||||
|
pub mod version_checker;
|
||||||
|
|
||||||
#[cfg(feature = "clap")]
|
#[cfg(feature = "clap")]
|
||||||
pub mod completions;
|
pub mod completions;
|
||||||
|
|||||||
@@ -47,7 +47,6 @@ pub fn setup_logging() {
|
|||||||
#[cfg(feature = "basic_tracing")]
|
#[cfg(feature = "basic_tracing")]
|
||||||
pub fn setup_tracing_logger() {
|
pub fn setup_tracing_logger() {
|
||||||
let log_builder = tracing_subscriber::fmt()
|
let log_builder = tracing_subscriber::fmt()
|
||||||
.with_writer(std::io::stderr)
|
|
||||||
// Use a more compact, abbreviated log format
|
// Use a more compact, abbreviated log format
|
||||||
.compact()
|
.compact()
|
||||||
// Display source code file paths
|
// Display source code file paths
|
||||||
|
|||||||
@@ -0,0 +1,78 @@
|
|||||||
|
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
pub use semver::Version;
|
||||||
|
|
||||||
|
/// Checks if the version is minor version compatible.
|
||||||
|
///
|
||||||
|
/// Checks whether given `version` is compatible with a given semantic version requirement `req`
|
||||||
|
/// according to major-minor semver rules. The semantic version requirement can be passed as a full,
|
||||||
|
/// concrete version number, because that's what we'll have in our Cargo.toml files (e.g. 0.3.2).
|
||||||
|
/// The patch number in the requirement gets dropped and replaced with a wildcard (0.3.*) as all
|
||||||
|
/// minor versions should be compatible with each other.
|
||||||
|
pub fn is_minor_version_compatible(version: &str, req: &str) -> bool {
|
||||||
|
let expected_version = match Version::parse(version) {
|
||||||
|
Ok(v) => v,
|
||||||
|
Err(_) => return false,
|
||||||
|
};
|
||||||
|
let req_version = match Version::parse(req) {
|
||||||
|
Ok(v) => v,
|
||||||
|
Err(_) => return false,
|
||||||
|
};
|
||||||
|
|
||||||
|
expected_version.major == req_version.major && expected_version.minor == req_version.minor
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parse_version(raw_version: &str) -> Result<Version, semver::Error> {
|
||||||
|
Version::parse(raw_version)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn version_0_3_0_is_compatible_with_requirement_0_3_x() {
|
||||||
|
assert!(is_minor_version_compatible("0.3.0", "0.3.2"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn version_0_3_1_is_compatible_with_minimum_requirement_0_3_x() {
|
||||||
|
assert!(is_minor_version_compatible("0.3.1", "0.3.2"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn version_0_3_2_is_compatible_with_minimum_requirement_0_3_x() {
|
||||||
|
assert!(is_minor_version_compatible("0.3.2", "0.3.0"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn version_0_2_0_is_not_compatible_with_requirement_0_3_x() {
|
||||||
|
assert!(!is_minor_version_compatible("0.2.0", "0.3.2"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn version_0_4_0_is_not_compatible_with_requirement_0_3_x() {
|
||||||
|
assert!(!is_minor_version_compatible("0.4.0", "0.3.2"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn version_1_3_2_is_not_compatible_with_requirement_0_3_x() {
|
||||||
|
assert!(!is_minor_version_compatible("1.3.2", "0.3.2"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn version_0_4_0_rc_1_is_compatible_with_version_0_4_0_rc_1() {
|
||||||
|
assert!(is_minor_version_compatible("0.4.0-rc.1", "0.4.0-rc.1"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn returns_false_on_foo_version() {
|
||||||
|
assert!(!is_minor_version_compatible("foo", "0.3.2"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn returns_false_on_bar_version() {
|
||||||
|
assert!(!is_minor_version_compatible("0.3.2", "bar"));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,7 +3,7 @@ name = "nym-client-core"
|
|||||||
version = "1.1.15"
|
version = "1.1.15"
|
||||||
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"]
|
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"]
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
rust-version = "1.76"
|
rust-version = "1.70"
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
@@ -45,8 +45,7 @@ nym-nonexhaustive-delayqueue = { path = "../nonexhaustive-delayqueue" }
|
|||||||
nym-sphinx = { path = "../nymsphinx" }
|
nym-sphinx = { path = "../nymsphinx" }
|
||||||
nym-statistics-common = { path = "../statistics" }
|
nym-statistics-common = { path = "../statistics" }
|
||||||
nym-pemstore = { path = "../pemstore" }
|
nym-pemstore = { path = "../pemstore" }
|
||||||
nym-topology = { path = "../topology", features = ["persistence"] }
|
nym-topology = { path = "../topology", features = ["serializable"] }
|
||||||
nym-mixnet-client = { path = "../client-libs/mixnet-client", default-features = false }
|
|
||||||
nym-validator-client = { path = "../client-libs/validator-client", default-features = false }
|
nym-validator-client = { path = "../client-libs/validator-client", default-features = false }
|
||||||
nym-task = { path = "../task" }
|
nym-task = { path = "../task" }
|
||||||
nym-credentials-interface = { path = "../credentials-interface" }
|
nym-credentials-interface = { path = "../credentials-interface" }
|
||||||
|
|||||||
@@ -393,20 +393,13 @@ pub struct Traffic {
|
|||||||
/// poisson distribution.
|
/// poisson distribution.
|
||||||
pub disable_main_poisson_packet_distribution: bool,
|
pub disable_main_poisson_packet_distribution: bool,
|
||||||
|
|
||||||
/// Specify whether route selection should be determined by the packet header.
|
|
||||||
pub deterministic_route_selection: bool,
|
|
||||||
|
|
||||||
/// Specify how many times particular packet can be retransmitted
|
|
||||||
/// None - no limit
|
|
||||||
pub maximum_number_of_retransmissions: Option<u32>,
|
|
||||||
|
|
||||||
/// Specifies the packet size used for sent messages.
|
/// Specifies the packet size used for sent messages.
|
||||||
/// Do not override it unless you understand the consequences of that change.
|
/// Do not override it unless you understand the consequences of that change.
|
||||||
pub primary_packet_size: PacketSize,
|
pub primary_packet_size: PacketSize,
|
||||||
|
|
||||||
/// Specifies the optional auxiliary packet size for optimizing message streams.
|
/// Specifies the optional auxiliary packet size for optimizing message streams.
|
||||||
/// Note that its use decreases overall anonymity.
|
/// Note that its use decreases overall anonymity.
|
||||||
/// Do not set it unless you understand the consequences of that change.
|
/// Do not set it it unless you understand the consequences of that change.
|
||||||
pub secondary_packet_size: Option<PacketSize>,
|
pub secondary_packet_size: Option<PacketSize>,
|
||||||
|
|
||||||
pub packet_type: PacketType,
|
pub packet_type: PacketType,
|
||||||
@@ -431,8 +424,6 @@ impl Default for Traffic {
|
|||||||
average_packet_delay: DEFAULT_AVERAGE_PACKET_DELAY,
|
average_packet_delay: DEFAULT_AVERAGE_PACKET_DELAY,
|
||||||
message_sending_average_delay: DEFAULT_MESSAGE_STREAM_AVERAGE_DELAY,
|
message_sending_average_delay: DEFAULT_MESSAGE_STREAM_AVERAGE_DELAY,
|
||||||
disable_main_poisson_packet_distribution: false,
|
disable_main_poisson_packet_distribution: false,
|
||||||
deterministic_route_selection: false,
|
|
||||||
maximum_number_of_retransmissions: None,
|
|
||||||
primary_packet_size: PacketSize::RegularPacket,
|
primary_packet_size: PacketSize::RegularPacket,
|
||||||
secondary_packet_size: None,
|
secondary_packet_size: None,
|
||||||
packet_type: PacketType::Mix,
|
packet_type: PacketType::Mix,
|
||||||
@@ -550,15 +541,6 @@ pub struct Topology {
|
|||||||
/// Specifies a minimum performance of a gateway that is used on route construction.
|
/// Specifies a minimum performance of a gateway that is used on route construction.
|
||||||
/// This setting is only applicable when `NymApi` topology is used.
|
/// This setting is only applicable when `NymApi` topology is used.
|
||||||
pub minimum_gateway_performance: u8,
|
pub minimum_gateway_performance: u8,
|
||||||
|
|
||||||
/// Specifies whether this client should attempt to retrieve all available network nodes
|
|
||||||
/// as opposed to just active mixnodes/gateways.
|
|
||||||
/// Useless without `ignore_epoch_roles = true`
|
|
||||||
pub use_extended_topology: bool,
|
|
||||||
|
|
||||||
/// Specifies whether this client should ignore the current epoch role of the target egress node
|
|
||||||
/// when constructing the final hop packets.
|
|
||||||
pub ignore_egress_epoch_role: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::large_enum_variant)]
|
#[allow(clippy::large_enum_variant)]
|
||||||
@@ -595,8 +577,6 @@ impl Default for Topology {
|
|||||||
topology_structure: TopologyStructure::default(),
|
topology_structure: TopologyStructure::default(),
|
||||||
minimum_mixnode_performance: DEFAULT_MIN_MIXNODE_PERFORMANCE,
|
minimum_mixnode_performance: DEFAULT_MIN_MIXNODE_PERFORMANCE,
|
||||||
minimum_gateway_performance: DEFAULT_MIN_GATEWAY_PERFORMANCE,
|
minimum_gateway_performance: DEFAULT_MIN_GATEWAY_PERFORMANCE,
|
||||||
use_extended_topology: false,
|
|
||||||
ignore_egress_epoch_role: false,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -111,7 +111,6 @@ impl From<ConfigV5> for Config {
|
|||||||
primary_packet_size: value.debug.traffic.primary_packet_size,
|
primary_packet_size: value.debug.traffic.primary_packet_size,
|
||||||
secondary_packet_size: value.debug.traffic.secondary_packet_size,
|
secondary_packet_size: value.debug.traffic.secondary_packet_size,
|
||||||
packet_type: value.debug.traffic.packet_type,
|
packet_type: value.debug.traffic.packet_type,
|
||||||
..Default::default()
|
|
||||||
},
|
},
|
||||||
cover_traffic: CoverTraffic {
|
cover_traffic: CoverTraffic {
|
||||||
loop_cover_traffic_average_delay: value
|
loop_cover_traffic_average_delay: value
|
||||||
|
|||||||
@@ -8,10 +8,7 @@ use crate::{
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
use log::{debug, error};
|
use log::{debug, error};
|
||||||
use sqlx::{
|
use sqlx::ConnectOptions;
|
||||||
sqlite::{SqliteAutoVacuum, SqliteSynchronous},
|
|
||||||
ConnectOptions,
|
|
||||||
};
|
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
@@ -33,9 +30,6 @@ impl StorageManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let opts = sqlx::sqlite::SqliteConnectOptions::new()
|
let opts = sqlx::sqlite::SqliteConnectOptions::new()
|
||||||
.journal_mode(sqlx::sqlite::SqliteJournalMode::Wal)
|
|
||||||
.synchronous(SqliteSynchronous::Normal)
|
|
||||||
.auto_vacuum(SqliteAutoVacuum::Incremental)
|
|
||||||
.filename(database_path)
|
.filename(database_path)
|
||||||
.create_if_missing(true)
|
.create_if_missing(true)
|
||||||
.disable_statement_logging();
|
.disable_statement_logging();
|
||||||
@@ -116,7 +110,7 @@ impl StorageManager {
|
|||||||
) -> Result<(), sqlx::Error> {
|
) -> Result<(), sqlx::Error> {
|
||||||
sqlx::query!(
|
sqlx::query!(
|
||||||
r#"
|
r#"
|
||||||
INSERT INTO registered_gateway(gateway_id_bs58, registration_timestamp, gateway_type)
|
INSERT INTO registered_gateway(gateway_id_bs58, registration_timestamp, gateway_type)
|
||||||
VALUES (?, ?, ?)
|
VALUES (?, ?, ?)
|
||||||
"#,
|
"#,
|
||||||
registered_gateway.gateway_id_bs58,
|
registered_gateway.gateway_id_bs58,
|
||||||
@@ -230,7 +224,7 @@ impl StorageManager {
|
|||||||
) -> Result<(), sqlx::Error> {
|
) -> Result<(), sqlx::Error> {
|
||||||
sqlx::query!(
|
sqlx::query!(
|
||||||
r#"
|
r#"
|
||||||
INSERT INTO custom_gateway_details(gateway_id_bs58, data)
|
INSERT INTO custom_gateway_details(gateway_id_bs58, data)
|
||||||
VALUES (?, ?)
|
VALUES (?, ?)
|
||||||
"#,
|
"#,
|
||||||
custom.gateway_id_bs58,
|
custom.gateway_id_bs58,
|
||||||
|
|||||||
@@ -112,23 +112,18 @@ where
|
|||||||
source,
|
source,
|
||||||
}
|
}
|
||||||
})?;
|
})?;
|
||||||
hardcoded_topology.entry_capable_nodes().cloned().collect()
|
hardcoded_topology.get_gateways()
|
||||||
} else {
|
} else {
|
||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::thread_rng();
|
||||||
crate::init::helpers::current_gateways(
|
crate::init::helpers::current_gateways(&mut rng, &core.client.nym_api_urls, user_agent)
|
||||||
&mut rng,
|
.await?
|
||||||
&core.client.nym_api_urls,
|
|
||||||
user_agent,
|
|
||||||
core.debug.topology.minimum_gateway_performance,
|
|
||||||
)
|
|
||||||
.await?
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// since we're registering with a brand new gateway,
|
// since we're registering with a brand new gateway,
|
||||||
// make sure the list of available gateways doesn't overlap the list of known gateways
|
// make sure the list of available gateways doesn't overlap the list of known gateways
|
||||||
let available_gateways = available_gateways
|
let available_gateways = available_gateways
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter(|g| !registered_gateways.contains(&g.identity()))
|
.filter(|g| !registered_gateways.contains(g.identity()))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
if available_gateways.is_empty() {
|
if available_gateways.is_empty() {
|
||||||
|
|||||||
@@ -167,16 +167,11 @@ where
|
|||||||
source,
|
source,
|
||||||
}
|
}
|
||||||
})?;
|
})?;
|
||||||
hardcoded_topology.entry_capable_nodes().cloned().collect()
|
hardcoded_topology.get_gateways()
|
||||||
} else {
|
} else {
|
||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::thread_rng();
|
||||||
crate::init::helpers::current_gateways(
|
crate::init::helpers::current_gateways(&mut rng, &core.client.nym_api_urls, user_agent)
|
||||||
&mut rng,
|
.await?
|
||||||
&core.client.nym_api_urls,
|
|
||||||
user_agent,
|
|
||||||
core.debug.topology.minimum_gateway_performance,
|
|
||||||
)
|
|
||||||
.await?
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let gateway_setup = GatewaySetup::New {
|
let gateway_setup = GatewaySetup::New {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
use super::received_buffer::ReceivedBufferMessage;
|
use super::received_buffer::ReceivedBufferMessage;
|
||||||
use super::statistics_control::StatisticsControl;
|
use super::statistics_control::StatisticsControl;
|
||||||
|
use super::topology_control::geo_aware_provider::GeoAwareTopologyProvider;
|
||||||
use crate::client::base_client::storage::helpers::store_client_keys;
|
use crate::client::base_client::storage::helpers::store_client_keys;
|
||||||
use crate::client::base_client::storage::MixnetClientStorage;
|
use crate::client::base_client::storage::MixnetClientStorage;
|
||||||
use crate::client::cover_traffic_stream::LoopCoverTrafficStream;
|
use crate::client::cover_traffic_stream::LoopCoverTrafficStream;
|
||||||
@@ -23,7 +24,7 @@ use crate::client::replies::reply_storage::{
|
|||||||
};
|
};
|
||||||
use crate::client::topology_control::nym_api_provider::NymApiTopologyProvider;
|
use crate::client::topology_control::nym_api_provider::NymApiTopologyProvider;
|
||||||
use crate::client::topology_control::{
|
use crate::client::topology_control::{
|
||||||
TopologyAccessor, TopologyRefresher, TopologyRefresherConfig,
|
nym_api_provider, TopologyAccessor, TopologyRefresher, TopologyRefresherConfig,
|
||||||
};
|
};
|
||||||
use crate::config::{Config, DebugConfig};
|
use crate::config::{Config, DebugConfig};
|
||||||
use crate::error::ClientCoreError;
|
use crate::error::ClientCoreError;
|
||||||
@@ -31,7 +32,7 @@ use crate::init::{
|
|||||||
setup_gateway,
|
setup_gateway,
|
||||||
types::{GatewaySetup, InitialisationResult},
|
types::{GatewaySetup, InitialisationResult},
|
||||||
};
|
};
|
||||||
use crate::{config, spawn_future, ForgetMe};
|
use crate::{config, spawn_future};
|
||||||
use futures::channel::mpsc;
|
use futures::channel::mpsc;
|
||||||
use log::*;
|
use log::*;
|
||||||
use nym_bandwidth_controller::BandwidthController;
|
use nym_bandwidth_controller::BandwidthController;
|
||||||
@@ -187,11 +188,6 @@ pub struct BaseClientBuilder<'a, C, S: MixnetClientStorage> {
|
|||||||
user_agent: Option<UserAgent>,
|
user_agent: Option<UserAgent>,
|
||||||
|
|
||||||
setup_method: GatewaySetup,
|
setup_method: GatewaySetup,
|
||||||
|
|
||||||
#[cfg(unix)]
|
|
||||||
connection_fd_callback: Option<Arc<dyn Fn(RawFd) + Send + Sync>>,
|
|
||||||
|
|
||||||
forget_me: ForgetMe,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, C, S> BaseClientBuilder<'a, C, S>
|
impl<'a, C, S> BaseClientBuilder<'a, C, S>
|
||||||
@@ -214,18 +210,9 @@ where
|
|||||||
shutdown: None,
|
shutdown: None,
|
||||||
user_agent: None,
|
user_agent: None,
|
||||||
setup_method: GatewaySetup::MustLoad { gateway_id: None },
|
setup_method: GatewaySetup::MustLoad { gateway_id: None },
|
||||||
#[cfg(unix)]
|
|
||||||
connection_fd_callback: None,
|
|
||||||
forget_me: Default::default(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[must_use]
|
|
||||||
pub fn with_forget_me(mut self, forget_me: &ForgetMe) -> Self {
|
|
||||||
self.forget_me = forget_me.clone();
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn with_gateway_setup(mut self, setup: GatewaySetup) -> Self {
|
pub fn with_gateway_setup(mut self, setup: GatewaySetup) -> Self {
|
||||||
self.setup_method = setup;
|
self.setup_method = setup;
|
||||||
@@ -274,15 +261,6 @@ where
|
|||||||
Ok(self)
|
Ok(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(unix)]
|
|
||||||
pub fn with_connection_fd_callback(
|
|
||||||
mut self,
|
|
||||||
callback: Arc<dyn Fn(RawFd) + Send + Sync>,
|
|
||||||
) -> Self {
|
|
||||||
self.connection_fd_callback = Some(callback);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
// note: do **NOT** make this method public as its only valid usage is from within `start_base`
|
// note: do **NOT** make this method public as its only valid usage is from within `start_base`
|
||||||
// because it relies on the crypto keys being already loaded
|
// because it relies on the crypto keys being already loaded
|
||||||
fn mix_address(details: &InitialisationResult) -> Recipient {
|
fn mix_address(details: &InitialisationResult) -> Recipient {
|
||||||
@@ -374,7 +352,6 @@ where
|
|||||||
controller.start_with_shutdown(shutdown)
|
controller.start_with_shutdown(shutdown)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::too_many_arguments)]
|
|
||||||
async fn start_gateway_client(
|
async fn start_gateway_client(
|
||||||
config: &Config,
|
config: &Config,
|
||||||
initialisation_result: InitialisationResult,
|
initialisation_result: InitialisationResult,
|
||||||
@@ -382,7 +359,6 @@ where
|
|||||||
details_store: &S::GatewaysDetailsStore,
|
details_store: &S::GatewaysDetailsStore,
|
||||||
packet_router: PacketRouter,
|
packet_router: PacketRouter,
|
||||||
stats_reporter: ClientStatsSender,
|
stats_reporter: ClientStatsSender,
|
||||||
#[cfg(unix)] connection_fd_callback: Option<Arc<dyn Fn(RawFd) + Send + Sync>>,
|
|
||||||
shutdown: TaskClient,
|
shutdown: TaskClient,
|
||||||
) -> Result<GatewayClient<C, S::CredentialStore>, ClientCoreError>
|
) -> Result<GatewayClient<C, S::CredentialStore>, ClientCoreError>
|
||||||
where
|
where
|
||||||
@@ -425,8 +401,6 @@ where
|
|||||||
packet_router,
|
packet_router,
|
||||||
bandwidth_controller,
|
bandwidth_controller,
|
||||||
stats_reporter,
|
stats_reporter,
|
||||||
#[cfg(unix)]
|
|
||||||
connection_fd_callback,
|
|
||||||
shutdown,
|
shutdown,
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
@@ -463,8 +437,8 @@ where
|
|||||||
details_store
|
details_store
|
||||||
.upgrade_stored_remote_gateway_key(gateway_client.gateway_identity(), &updated_key)
|
.upgrade_stored_remote_gateway_key(gateway_client.gateway_identity(), &updated_key)
|
||||||
.await.map_err(|err| {
|
.await.map_err(|err| {
|
||||||
error!("failed to store upgraded gateway key! this connection might be forever broken now: {err}");
|
error!("failed to store upgraded gateway key! this connection might be forever broken now: {err}");
|
||||||
ClientCoreError::GatewaysDetailsStoreError { source: Box::new(err) }
|
ClientCoreError::GatewaysDetailsStoreError { source: Box::new(err) }
|
||||||
})?
|
})?
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -472,7 +446,6 @@ where
|
|||||||
.claim_initial_bandwidth()
|
.claim_initial_bandwidth()
|
||||||
.await
|
.await
|
||||||
.map_err(gateway_failure)?;
|
.map_err(gateway_failure)?;
|
||||||
|
|
||||||
gateway_client
|
gateway_client
|
||||||
.start_listening_for_mixnet_messages()
|
.start_listening_for_mixnet_messages()
|
||||||
.map_err(gateway_failure)?;
|
.map_err(gateway_failure)?;
|
||||||
@@ -489,7 +462,6 @@ where
|
|||||||
details_store: &S::GatewaysDetailsStore,
|
details_store: &S::GatewaysDetailsStore,
|
||||||
packet_router: PacketRouter,
|
packet_router: PacketRouter,
|
||||||
stats_reporter: ClientStatsSender,
|
stats_reporter: ClientStatsSender,
|
||||||
#[cfg(unix)] connection_fd_callback: Option<Arc<dyn Fn(RawFd) + Send + Sync>>,
|
|
||||||
mut shutdown: TaskClient,
|
mut shutdown: TaskClient,
|
||||||
) -> Result<Box<dyn GatewayTransceiver + Send>, ClientCoreError>
|
) -> Result<Box<dyn GatewayTransceiver + Send>, ClientCoreError>
|
||||||
where
|
where
|
||||||
@@ -521,8 +493,6 @@ where
|
|||||||
details_store,
|
details_store,
|
||||||
packet_router,
|
packet_router,
|
||||||
stats_reporter,
|
stats_reporter,
|
||||||
#[cfg(unix)]
|
|
||||||
connection_fd_callback,
|
|
||||||
shutdown,
|
shutdown,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
@@ -539,15 +509,20 @@ where
|
|||||||
// if no custom provider was ... provided ..., create one using nym-api
|
// 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 config_topology.topology_structure {
|
||||||
config::TopologyStructure::NymApi => Box::new(NymApiTopologyProvider::new(
|
config::TopologyStructure::NymApi => Box::new(NymApiTopologyProvider::new(
|
||||||
config_topology,
|
nym_api_provider::Config {
|
||||||
|
min_mixnode_performance: config_topology.minimum_mixnode_performance,
|
||||||
|
min_gateway_performance: config_topology.minimum_gateway_performance,
|
||||||
|
},
|
||||||
nym_api_urls,
|
nym_api_urls,
|
||||||
|
env!("CARGO_PKG_VERSION").to_string(),
|
||||||
user_agent,
|
user_agent,
|
||||||
)),
|
)),
|
||||||
config::TopologyStructure::GeoAware(group_by) => {
|
config::TopologyStructure::GeoAware(group_by) => {
|
||||||
warn!("using deprecated 'GeoAware' topology provider - this option will be removed very soon");
|
Box::new(GeoAwareTopologyProvider::new(
|
||||||
|
nym_api_urls,
|
||||||
#[allow(deprecated)]
|
env!("CARGO_PKG_VERSION").to_string(),
|
||||||
Box::new(crate::client::topology_control::GeoAwareTopologyProvider::new(nym_api_urls, group_by))
|
group_by,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -558,7 +533,7 @@ where
|
|||||||
topology_provider: Box<dyn TopologyProvider + Send + Sync>,
|
topology_provider: Box<dyn TopologyProvider + Send + Sync>,
|
||||||
topology_config: config::Topology,
|
topology_config: config::Topology,
|
||||||
topology_accessor: TopologyAccessor,
|
topology_accessor: TopologyAccessor,
|
||||||
local_gateway: NodeIdentity,
|
local_gateway: &NodeIdentity,
|
||||||
wait_for_gateway: bool,
|
wait_for_gateway: bool,
|
||||||
mut shutdown: TaskClient,
|
mut shutdown: TaskClient,
|
||||||
) -> Result<(), ClientCoreError> {
|
) -> Result<(), ClientCoreError> {
|
||||||
@@ -590,7 +565,7 @@ where
|
|||||||
};
|
};
|
||||||
|
|
||||||
if let Err(err) = topology_refresher
|
if let Err(err) = topology_refresher
|
||||||
.ensure_contains_routable_egress(local_gateway)
|
.ensure_contains_gateway(local_gateway)
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
if let Some(waiting_timeout) = gateway_wait_timeout {
|
if let Some(waiting_timeout) = gateway_wait_timeout {
|
||||||
@@ -645,11 +620,9 @@ where
|
|||||||
fn start_mix_traffic_controller(
|
fn start_mix_traffic_controller(
|
||||||
gateway_transceiver: Box<dyn GatewayTransceiver + Send>,
|
gateway_transceiver: Box<dyn GatewayTransceiver + Send>,
|
||||||
shutdown: TaskClient,
|
shutdown: TaskClient,
|
||||||
forget_me: ForgetMe,
|
|
||||||
) -> BatchMixMessageSender {
|
) -> BatchMixMessageSender {
|
||||||
info!("Starting mix traffic controller...");
|
info!("Starting mix traffic controller...");
|
||||||
let (mix_traffic_controller, mix_tx) =
|
let (mix_traffic_controller, mix_tx) = MixTrafficController::new(gateway_transceiver);
|
||||||
MixTrafficController::new(gateway_transceiver, forget_me);
|
|
||||||
mix_traffic_controller.start_with_shutdown(shutdown);
|
mix_traffic_controller.start_with_shutdown(shutdown);
|
||||||
mix_tx
|
mix_tx
|
||||||
}
|
}
|
||||||
@@ -740,8 +713,7 @@ where
|
|||||||
|
|
||||||
// channels responsible for controlling ack messages
|
// channels responsible for controlling ack messages
|
||||||
let (ack_sender, ack_receiver) = mpsc::unbounded();
|
let (ack_sender, ack_receiver) = mpsc::unbounded();
|
||||||
let shared_topology_accessor =
|
let shared_topology_accessor = TopologyAccessor::new();
|
||||||
TopologyAccessor::new(self.config.debug.topology.ignore_egress_epoch_role);
|
|
||||||
|
|
||||||
// Shutdown notifier for signalling tasks to stop
|
// Shutdown notifier for signalling tasks to stop
|
||||||
let shutdown = self
|
let shutdown = self
|
||||||
@@ -805,8 +777,6 @@ where
|
|||||||
&details_store,
|
&details_store,
|
||||||
gateway_packet_router,
|
gateway_packet_router,
|
||||||
stats_reporter.clone(),
|
stats_reporter.clone(),
|
||||||
#[cfg(unix)]
|
|
||||||
self.connection_fd_callback,
|
|
||||||
shutdown.fork("gateway_transceiver"),
|
shutdown.fork("gateway_transceiver"),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
@@ -832,11 +802,9 @@ where
|
|||||||
// that are to be sent to the mixnet. They are used by cover traffic stream and real
|
// that are to be sent to the mixnet. They are used by cover traffic stream and real
|
||||||
// traffic stream.
|
// traffic stream.
|
||||||
// The MixTrafficController then sends the actual traffic
|
// The MixTrafficController then sends the actual traffic
|
||||||
|
|
||||||
let message_sender = Self::start_mix_traffic_controller(
|
let message_sender = Self::start_mix_traffic_controller(
|
||||||
gateway_transceiver,
|
gateway_transceiver,
|
||||||
shutdown.fork("mix_traffic_controller"),
|
shutdown.fork("mix_traffic_controller"),
|
||||||
self.forget_me,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// Channels that the websocket listener can use to signal downstream to the real traffic
|
// Channels that the websocket listener can use to signal downstream to the real traffic
|
||||||
|
|||||||
@@ -163,7 +163,6 @@ impl LoopCoverTrafficStream<OsRng> {
|
|||||||
// poisson delay, but is it really a problem?
|
// poisson delay, but is it really a problem?
|
||||||
let topology_permit = self.topology_access.get_read_permit().await;
|
let topology_permit = self.topology_access.get_read_permit().await;
|
||||||
// the ack is sent back to ourselves (and then ignored)
|
// the ack is sent back to ourselves (and then ignored)
|
||||||
|
|
||||||
let topology_ref = match topology_permit.try_get_valid_topology_ref(
|
let topology_ref = match topology_permit.try_get_valid_topology_ref(
|
||||||
&self.our_full_destination,
|
&self.our_full_destination,
|
||||||
Some(&self.our_full_destination),
|
Some(&self.our_full_destination),
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ pub enum InputMessage {
|
|||||||
recipient: Recipient,
|
recipient: Recipient,
|
||||||
data: Vec<u8>,
|
data: Vec<u8>,
|
||||||
lane: TransmissionLane,
|
lane: TransmissionLane,
|
||||||
|
mix_hops: Option<u8>,
|
||||||
},
|
},
|
||||||
|
|
||||||
/// Creates a message used for a duplex anonymous communication where the recipient
|
/// Creates a message used for a duplex anonymous communication where the recipient
|
||||||
@@ -43,6 +44,7 @@ pub enum InputMessage {
|
|||||||
data: Vec<u8>,
|
data: Vec<u8>,
|
||||||
reply_surbs: u32,
|
reply_surbs: u32,
|
||||||
lane: TransmissionLane,
|
lane: TransmissionLane,
|
||||||
|
mix_hops: Option<u8>,
|
||||||
},
|
},
|
||||||
|
|
||||||
/// Attempt to use our internally received and stored `ReplySurb` to send the message back
|
/// Attempt to use our internally received and stored `ReplySurb` to send the message back
|
||||||
@@ -92,6 +94,29 @@ impl InputMessage {
|
|||||||
recipient,
|
recipient,
|
||||||
data,
|
data,
|
||||||
lane,
|
lane,
|
||||||
|
mix_hops: None,
|
||||||
|
};
|
||||||
|
if let Some(packet_type) = packet_type {
|
||||||
|
InputMessage::new_wrapper(message, packet_type)
|
||||||
|
} else {
|
||||||
|
message
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// IMHO `new_regular` should take `mix_hops: Option<u8>` as an argument instead of creating
|
||||||
|
// this function, but that would potentially break backwards compatibility with the current API
|
||||||
|
pub fn new_regular_with_custom_hops(
|
||||||
|
recipient: Recipient,
|
||||||
|
data: Vec<u8>,
|
||||||
|
lane: TransmissionLane,
|
||||||
|
packet_type: Option<PacketType>,
|
||||||
|
mix_hops: Option<u8>,
|
||||||
|
) -> Self {
|
||||||
|
let message = InputMessage::Regular {
|
||||||
|
recipient,
|
||||||
|
data,
|
||||||
|
lane,
|
||||||
|
mix_hops,
|
||||||
};
|
};
|
||||||
if let Some(packet_type) = packet_type {
|
if let Some(packet_type) = packet_type {
|
||||||
InputMessage::new_wrapper(message, packet_type)
|
InputMessage::new_wrapper(message, packet_type)
|
||||||
@@ -112,6 +137,7 @@ impl InputMessage {
|
|||||||
data,
|
data,
|
||||||
reply_surbs,
|
reply_surbs,
|
||||||
lane,
|
lane,
|
||||||
|
mix_hops: None,
|
||||||
};
|
};
|
||||||
if let Some(packet_type) = packet_type {
|
if let Some(packet_type) = packet_type {
|
||||||
InputMessage::new_wrapper(message, packet_type)
|
InputMessage::new_wrapper(message, packet_type)
|
||||||
@@ -128,12 +154,14 @@ impl InputMessage {
|
|||||||
reply_surbs: u32,
|
reply_surbs: u32,
|
||||||
lane: TransmissionLane,
|
lane: TransmissionLane,
|
||||||
packet_type: Option<PacketType>,
|
packet_type: Option<PacketType>,
|
||||||
|
mix_hops: Option<u8>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let message = InputMessage::Anonymous {
|
let message = InputMessage::Anonymous {
|
||||||
recipient,
|
recipient,
|
||||||
data,
|
data,
|
||||||
reply_surbs,
|
reply_surbs,
|
||||||
lane,
|
lane,
|
||||||
|
mix_hops,
|
||||||
};
|
};
|
||||||
if let Some(packet_type) = packet_type {
|
if let Some(packet_type) = packet_type {
|
||||||
InputMessage::new_wrapper(message, packet_type)
|
InputMessage::new_wrapper(message, packet_type)
|
||||||
|
|||||||
@@ -2,9 +2,8 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
use crate::client::mix_traffic::transceiver::GatewayTransceiver;
|
use crate::client::mix_traffic::transceiver::GatewayTransceiver;
|
||||||
use crate::{spawn_future, ForgetMe};
|
use crate::spawn_future;
|
||||||
use log::*;
|
use log::*;
|
||||||
use nym_gateway_requests::ClientRequest;
|
|
||||||
use nym_sphinx::forwarding::packet::MixPacket;
|
use nym_sphinx::forwarding::packet::MixPacket;
|
||||||
|
|
||||||
pub type BatchMixMessageSender = tokio::sync::mpsc::Sender<Vec<MixPacket>>;
|
pub type BatchMixMessageSender = tokio::sync::mpsc::Sender<Vec<MixPacket>>;
|
||||||
@@ -27,14 +26,10 @@ pub struct MixTrafficController {
|
|||||||
// TODO: this is temporary work-around.
|
// TODO: this is temporary work-around.
|
||||||
// in long run `gateway_client` will be moved away from `MixTrafficController` anyway.
|
// in long run `gateway_client` will be moved away from `MixTrafficController` anyway.
|
||||||
consecutive_gateway_failure_count: usize,
|
consecutive_gateway_failure_count: usize,
|
||||||
forget_me: ForgetMe,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MixTrafficController {
|
impl MixTrafficController {
|
||||||
pub fn new<T>(
|
pub fn new<T>(gateway_transceiver: T) -> (MixTrafficController, BatchMixMessageSender)
|
||||||
gateway_transceiver: T,
|
|
||||||
forget_me: ForgetMe,
|
|
||||||
) -> (MixTrafficController, BatchMixMessageSender)
|
|
||||||
where
|
where
|
||||||
T: GatewayTransceiver + Send + 'static,
|
T: GatewayTransceiver + Send + 'static,
|
||||||
{
|
{
|
||||||
@@ -45,7 +40,6 @@ impl MixTrafficController {
|
|||||||
gateway_transceiver: Box::new(gateway_transceiver),
|
gateway_transceiver: Box::new(gateway_transceiver),
|
||||||
mix_rx: message_receiver,
|
mix_rx: message_receiver,
|
||||||
consecutive_gateway_failure_count: 0,
|
consecutive_gateway_failure_count: 0,
|
||||||
forget_me,
|
|
||||||
},
|
},
|
||||||
message_sender,
|
message_sender,
|
||||||
)
|
)
|
||||||
@@ -53,7 +47,6 @@ impl MixTrafficController {
|
|||||||
|
|
||||||
pub fn new_dynamic(
|
pub fn new_dynamic(
|
||||||
gateway_transceiver: Box<dyn GatewayTransceiver + Send>,
|
gateway_transceiver: Box<dyn GatewayTransceiver + Send>,
|
||||||
forget_me: ForgetMe,
|
|
||||||
) -> (MixTrafficController, BatchMixMessageSender) {
|
) -> (MixTrafficController, BatchMixMessageSender) {
|
||||||
let (message_sender, message_receiver) =
|
let (message_sender, message_receiver) =
|
||||||
tokio::sync::mpsc::channel(MIX_MESSAGE_RECEIVER_BUFFER_SIZE);
|
tokio::sync::mpsc::channel(MIX_MESSAGE_RECEIVER_BUFFER_SIZE);
|
||||||
@@ -62,7 +55,6 @@ impl MixTrafficController {
|
|||||||
gateway_transceiver,
|
gateway_transceiver,
|
||||||
mix_rx: message_receiver,
|
mix_rx: message_receiver,
|
||||||
consecutive_gateway_failure_count: 0,
|
consecutive_gateway_failure_count: 0,
|
||||||
forget_me,
|
|
||||||
},
|
},
|
||||||
message_sender,
|
message_sender,
|
||||||
)
|
)
|
||||||
@@ -119,27 +111,7 @@ impl MixTrafficController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
shutdown.recv_timeout().await;
|
shutdown.recv_timeout().await;
|
||||||
|
|
||||||
if self.forget_me.any() {
|
|
||||||
log::info!("Sending forget me request to the gateway");
|
|
||||||
match self
|
|
||||||
.gateway_transceiver
|
|
||||||
.send_client_request(ClientRequest::ForgetMe {
|
|
||||||
client: self.forget_me.client(),
|
|
||||||
stats: self.forget_me.stats(),
|
|
||||||
})
|
|
||||||
.await
|
|
||||||
{
|
|
||||||
Ok(_) => {
|
|
||||||
log::info!("Successfully sent forget me request to the gateway");
|
|
||||||
}
|
|
||||||
Err(err) => {
|
|
||||||
log::error!("Failed to send forget me request to the gateway: {err}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
log::debug!("MixTrafficController: Exiting");
|
log::debug!("MixTrafficController: Exiting");
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,10 +5,8 @@ use async_trait::async_trait;
|
|||||||
use log::{debug, error};
|
use log::{debug, error};
|
||||||
use nym_credential_storage::storage::Storage as CredentialStorage;
|
use nym_credential_storage::storage::Storage as CredentialStorage;
|
||||||
use nym_crypto::asymmetric::identity;
|
use nym_crypto::asymmetric::identity;
|
||||||
use nym_gateway_client::error::GatewayClientError;
|
|
||||||
use nym_gateway_client::GatewayClient;
|
use nym_gateway_client::GatewayClient;
|
||||||
pub use nym_gateway_client::{GatewayPacketRouter, PacketRouter};
|
pub use nym_gateway_client::{GatewayPacketRouter, PacketRouter};
|
||||||
use nym_gateway_requests::ClientRequest;
|
|
||||||
use nym_sphinx::forwarding::packet::MixPacket;
|
use nym_sphinx::forwarding::packet::MixPacket;
|
||||||
use nym_validator_client::nyxd::contract_traits::DkgQueryClient;
|
use nym_validator_client::nyxd::contract_traits::DkgQueryClient;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
@@ -16,7 +14,7 @@ use std::os::raw::c_int as RawFd;
|
|||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
use futures::channel::oneshot;
|
use futures::channel::{mpsc, oneshot};
|
||||||
|
|
||||||
// we need to type erase the error type since we can't have dynamic associated types alongside dynamic dispatch
|
// we need to type erase the error type since we can't have dynamic associated types alongside dynamic dispatch
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
@@ -28,14 +26,9 @@ fn erase_err<E: std::error::Error + Send + Sync + 'static>(err: E) -> ErasedGate
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// This combines combines the functionalities of being able to send and receive mix packets.
|
/// This combines combines the functionalities of being able to send and receive mix packets.
|
||||||
#[async_trait]
|
|
||||||
pub trait GatewayTransceiver: GatewaySender + GatewayReceiver {
|
pub trait GatewayTransceiver: GatewaySender + GatewayReceiver {
|
||||||
fn gateway_identity(&self) -> identity::PublicKey;
|
fn gateway_identity(&self) -> identity::PublicKey;
|
||||||
fn ws_fd(&self) -> Option<RawFd>;
|
fn ws_fd(&self) -> Option<RawFd>;
|
||||||
async fn send_client_request(
|
|
||||||
&mut self,
|
|
||||||
message: ClientRequest,
|
|
||||||
) -> Result<(), GatewayClientError>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This trait defines the functionality of sending `MixPacket` into the mixnet,
|
/// This trait defines the functionality of sending `MixPacket` into the mixnet,
|
||||||
@@ -72,7 +65,6 @@ pub trait GatewayReceiver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// to allow for dynamic dispatch
|
// to allow for dynamic dispatch
|
||||||
#[async_trait]
|
|
||||||
impl<G: GatewayTransceiver + ?Sized + Send> GatewayTransceiver for Box<G> {
|
impl<G: GatewayTransceiver + ?Sized + Send> GatewayTransceiver for Box<G> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn gateway_identity(&self) -> identity::PublicKey {
|
fn gateway_identity(&self) -> identity::PublicKey {
|
||||||
@@ -81,13 +73,6 @@ impl<G: GatewayTransceiver + ?Sized + Send> GatewayTransceiver for Box<G> {
|
|||||||
fn ws_fd(&self) -> Option<RawFd> {
|
fn ws_fd(&self) -> Option<RawFd> {
|
||||||
(**self).ws_fd()
|
(**self).ws_fd()
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn send_client_request(
|
|
||||||
&mut self,
|
|
||||||
message: ClientRequest,
|
|
||||||
) -> Result<(), GatewayClientError> {
|
|
||||||
(**self).send_client_request(message).await
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
||||||
@@ -106,6 +91,7 @@ impl<G: GatewaySender + ?Sized + Send> GatewaySender for Box<G> {
|
|||||||
(**self).batch_send_mix_packets(packets).await
|
(**self).batch_send_mix_packets(packets).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<G: GatewayReceiver + ?Sized> GatewayReceiver for Box<G> {
|
impl<G: GatewayReceiver + ?Sized> GatewayReceiver for Box<G> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn set_packet_router(&mut self, packet_router: PacketRouter) -> Result<(), ErasedGatewayError> {
|
fn set_packet_router(&mut self, packet_router: PacketRouter) -> Result<(), ErasedGatewayError> {
|
||||||
@@ -125,7 +111,6 @@ impl<C, St> RemoteGateway<C, St> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
|
||||||
impl<C, St> GatewayTransceiver for RemoteGateway<C, St>
|
impl<C, St> GatewayTransceiver for RemoteGateway<C, St>
|
||||||
where
|
where
|
||||||
C: DkgQueryClient + Send + Sync,
|
C: DkgQueryClient + Send + Sync,
|
||||||
@@ -138,20 +123,6 @@ where
|
|||||||
fn ws_fd(&self) -> Option<RawFd> {
|
fn ws_fd(&self) -> Option<RawFd> {
|
||||||
self.gateway_client.ws_fd()
|
self.gateway_client.ws_fd()
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn send_client_request(
|
|
||||||
&mut self,
|
|
||||||
message: ClientRequest,
|
|
||||||
) -> Result<(), GatewayClientError> {
|
|
||||||
if let Some(shared_key) = self.gateway_client.shared_key() {
|
|
||||||
self.gateway_client
|
|
||||||
.send_websocket_message(message.encrypt(&*shared_key)?)
|
|
||||||
.await?;
|
|
||||||
Ok(())
|
|
||||||
} else {
|
|
||||||
Err(GatewayClientError::ConnectionInInvalidState)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
||||||
@@ -199,7 +170,7 @@ pub struct LocalGateway {
|
|||||||
|
|
||||||
// 'sender' part
|
// 'sender' part
|
||||||
/// Channel responsible for taking mix packets and forwarding them further into the further mixnet layers.
|
/// Channel responsible for taking mix packets and forwarding them further into the further mixnet layers.
|
||||||
packet_forwarder: nym_mixnet_client::forwarder::MixForwardingSender,
|
packet_forwarder: mpsc::UnboundedSender<MixPacket>,
|
||||||
|
|
||||||
// 'receiver' part
|
// 'receiver' part
|
||||||
packet_router_tx: Option<oneshot::Sender<PacketRouter>>,
|
packet_router_tx: Option<oneshot::Sender<PacketRouter>>,
|
||||||
@@ -209,7 +180,7 @@ pub struct LocalGateway {
|
|||||||
impl LocalGateway {
|
impl LocalGateway {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
local_identity: identity::PublicKey,
|
local_identity: identity::PublicKey,
|
||||||
packet_forwarder: nym_mixnet_client::forwarder::MixForwardingSender,
|
packet_forwarder: mpsc::UnboundedSender<MixPacket>,
|
||||||
packet_router_tx: oneshot::Sender<PacketRouter>,
|
packet_router_tx: oneshot::Sender<PacketRouter>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
LocalGateway {
|
LocalGateway {
|
||||||
@@ -224,7 +195,6 @@ impl LocalGateway {
|
|||||||
mod nonwasm_sealed {
|
mod nonwasm_sealed {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[async_trait]
|
|
||||||
impl GatewayTransceiver for LocalGateway {
|
impl GatewayTransceiver for LocalGateway {
|
||||||
fn gateway_identity(&self) -> identity::PublicKey {
|
fn gateway_identity(&self) -> identity::PublicKey {
|
||||||
self.local_identity
|
self.local_identity
|
||||||
@@ -232,20 +202,14 @@ mod nonwasm_sealed {
|
|||||||
fn ws_fd(&self) -> Option<RawFd> {
|
fn ws_fd(&self) -> Option<RawFd> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn send_client_request(
|
|
||||||
&mut self,
|
|
||||||
_message: ClientRequest,
|
|
||||||
) -> Result<(), GatewayClientError> {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl GatewaySender for LocalGateway {
|
impl GatewaySender for LocalGateway {
|
||||||
async fn send_mix_packet(&mut self, packet: MixPacket) -> Result<(), ErasedGatewayError> {
|
async fn send_mix_packet(&mut self, packet: MixPacket) -> Result<(), ErasedGatewayError> {
|
||||||
self.packet_forwarder
|
self.packet_forwarder
|
||||||
.forward_packet(packet)
|
.unbounded_send(packet)
|
||||||
|
.map_err(|err| err.into_send_error())
|
||||||
.map_err(erase_err)
|
.map_err(erase_err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -306,7 +270,6 @@ impl GatewaySender for MockGateway {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
|
||||||
impl GatewayTransceiver for MockGateway {
|
impl GatewayTransceiver for MockGateway {
|
||||||
fn gateway_identity(&self) -> identity::PublicKey {
|
fn gateway_identity(&self) -> identity::PublicKey {
|
||||||
self.dummy_identity
|
self.dummy_identity
|
||||||
@@ -314,11 +277,4 @@ impl GatewayTransceiver for MockGateway {
|
|||||||
fn ws_fd(&self) -> Option<RawFd> {
|
fn ws_fd(&self) -> Option<RawFd> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn send_client_request(
|
|
||||||
&mut self,
|
|
||||||
_message: ClientRequest,
|
|
||||||
) -> Result<(), GatewayClientError> {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-12
@@ -30,8 +30,7 @@ pub(crate) enum Action {
|
|||||||
InsertPending(Vec<PendingAcknowledgement>),
|
InsertPending(Vec<PendingAcknowledgement>),
|
||||||
|
|
||||||
/// Removes given `PendingAcknowledgement` from the 'shared' state. Also cancels the retransmission timer.
|
/// Removes given `PendingAcknowledgement` from the 'shared' state. Also cancels the retransmission timer.
|
||||||
/// Initiated by `AcknowledgementListener` upon receiving the acknowledgement. Also by `RetransmissionRequestListener`
|
/// Initiated by `AcknowledgementListener`
|
||||||
/// upon deciding to abandon the data.
|
|
||||||
RemovePending(FragmentIdentifier),
|
RemovePending(FragmentIdentifier),
|
||||||
|
|
||||||
/// Starts the retransmission timer on given `PendingAcknowledgement` with the `Duration` based on
|
/// Starts the retransmission timer on given `PendingAcknowledgement` with the `Duration` based on
|
||||||
@@ -42,7 +41,7 @@ pub(crate) enum Action {
|
|||||||
|
|
||||||
/// Updates the expected delay of given `PendingAcknowledgement` with the new provided `SphinxDelay`.
|
/// Updates the expected delay of given `PendingAcknowledgement` with the new provided `SphinxDelay`.
|
||||||
/// Initiated by `RetransmissionRequestListener`
|
/// Initiated by `RetransmissionRequestListener`
|
||||||
UpdatePendingAck(FragmentIdentifier, SphinxDelay),
|
UpdateDelay(FragmentIdentifier, SphinxDelay),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Action {
|
impl Action {
|
||||||
@@ -58,8 +57,8 @@ impl Action {
|
|||||||
Action::StartTimer(frag_id)
|
Action::StartTimer(frag_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn new_update_pending_ack(frag_id: FragmentIdentifier, delay: SphinxDelay) -> Self {
|
pub(crate) fn new_update_delay(frag_id: FragmentIdentifier, delay: SphinxDelay) -> Self {
|
||||||
Action::UpdatePendingAck(frag_id, delay)
|
Action::UpdateDelay(frag_id, delay)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -136,7 +135,7 @@ impl ActionController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn handle_start_timer(&mut self, frag_id: FragmentIdentifier) {
|
fn handle_start_timer(&mut self, frag_id: FragmentIdentifier) {
|
||||||
trace!("{frag_id} is starting its timer");
|
trace!("{} is starting its timer", frag_id);
|
||||||
|
|
||||||
if let Some((pending_ack_data, queue_key)) = self.pending_acks_data.get_mut(&frag_id) {
|
if let Some((pending_ack_data, queue_key)) = self.pending_acks_data.get_mut(&frag_id) {
|
||||||
// the fact that this branch is now POSSIBLE is a sign of a need to refactor this whole
|
// the fact that this branch is now POSSIBLE is a sign of a need to refactor this whole
|
||||||
@@ -194,7 +193,7 @@ impl ActionController {
|
|||||||
|
|
||||||
// initiated basically as a first step of retransmission. At first data has its delay updated
|
// initiated basically as a first step of retransmission. At first data has its delay updated
|
||||||
// (as new sphinx packet was created with new expected delivery time)
|
// (as new sphinx packet was created with new expected delivery time)
|
||||||
fn handle_update_pending_ack(&mut self, frag_id: FragmentIdentifier, delay: SphinxDelay) {
|
fn handle_update_delay(&mut self, frag_id: FragmentIdentifier, delay: SphinxDelay) {
|
||||||
trace!("{} is updating its delay", frag_id);
|
trace!("{} is updating its delay", frag_id);
|
||||||
// TODO: is it possible to solve this without either locking or temporarily removing the value?
|
// TODO: is it possible to solve this without either locking or temporarily removing the value?
|
||||||
if let Some((pending_ack_data, queue_key)) = self.pending_acks_data.remove(&frag_id) {
|
if let Some((pending_ack_data, queue_key)) = self.pending_acks_data.remove(&frag_id) {
|
||||||
@@ -203,7 +202,7 @@ impl ActionController {
|
|||||||
// reference to this Arc. HOWEVER, before the Action was pushed onto the queue, the reference
|
// reference to this Arc. HOWEVER, before the Action was pushed onto the queue, the reference
|
||||||
// was dropped hence this unwrap is safe.
|
// was dropped hence this unwrap is safe.
|
||||||
let mut inner_data = Arc::try_unwrap(pending_ack_data).unwrap();
|
let mut inner_data = Arc::try_unwrap(pending_ack_data).unwrap();
|
||||||
inner_data.update_retransmitted(delay);
|
inner_data.update_delay(delay);
|
||||||
|
|
||||||
self.pending_acks_data
|
self.pending_acks_data
|
||||||
.insert(frag_id, (Arc::new(inner_data), queue_key));
|
.insert(frag_id, (Arc::new(inner_data), queue_key));
|
||||||
@@ -226,7 +225,7 @@ impl ActionController {
|
|||||||
// about it. Perhaps just reschedule it at later point?
|
// about it. Perhaps just reschedule it at later point?
|
||||||
let frag_id = expired_ack.into_inner();
|
let frag_id = expired_ack.into_inner();
|
||||||
|
|
||||||
trace!("{frag_id} has expired");
|
trace!("{} has expired", frag_id);
|
||||||
|
|
||||||
if let Some((pending_ack_data, queue_key)) = self.pending_acks_data.get_mut(&frag_id) {
|
if let Some((pending_ack_data, queue_key)) = self.pending_acks_data.get_mut(&frag_id) {
|
||||||
if queue_key.is_none() {
|
if queue_key.is_none() {
|
||||||
@@ -259,9 +258,7 @@ impl ActionController {
|
|||||||
Action::InsertPending(pending_acks) => self.handle_insert(pending_acks),
|
Action::InsertPending(pending_acks) => self.handle_insert(pending_acks),
|
||||||
Action::RemovePending(frag_id) => self.handle_remove(frag_id),
|
Action::RemovePending(frag_id) => self.handle_remove(frag_id),
|
||||||
Action::StartTimer(frag_id) => self.handle_start_timer(frag_id),
|
Action::StartTimer(frag_id) => self.handle_start_timer(frag_id),
|
||||||
Action::UpdatePendingAck(frag_id, delay) => {
|
Action::UpdateDelay(frag_id, delay) => self.handle_update_delay(frag_id, delay),
|
||||||
self.handle_update_pending_ack(frag_id, delay)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+35
-8
@@ -73,10 +73,11 @@ where
|
|||||||
content: Vec<u8>,
|
content: Vec<u8>,
|
||||||
lane: TransmissionLane,
|
lane: TransmissionLane,
|
||||||
packet_type: PacketType,
|
packet_type: PacketType,
|
||||||
|
mix_hops: Option<u8>,
|
||||||
) {
|
) {
|
||||||
if let Err(err) = self
|
if let Err(err) = self
|
||||||
.message_handler
|
.message_handler
|
||||||
.try_send_plain_message(recipient, content, lane, packet_type)
|
.try_send_plain_message(recipient, content, lane, packet_type, mix_hops)
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
warn!("failed to send a plain message - {err}")
|
warn!("failed to send a plain message - {err}")
|
||||||
@@ -90,10 +91,18 @@ where
|
|||||||
reply_surbs: u32,
|
reply_surbs: u32,
|
||||||
lane: TransmissionLane,
|
lane: TransmissionLane,
|
||||||
packet_type: PacketType,
|
packet_type: PacketType,
|
||||||
|
mix_hops: Option<u8>,
|
||||||
) {
|
) {
|
||||||
if let Err(err) = self
|
if let Err(err) = self
|
||||||
.message_handler
|
.message_handler
|
||||||
.try_send_message_with_reply_surbs(recipient, content, reply_surbs, lane, packet_type)
|
.try_send_message_with_reply_surbs(
|
||||||
|
recipient,
|
||||||
|
content,
|
||||||
|
reply_surbs,
|
||||||
|
lane,
|
||||||
|
packet_type,
|
||||||
|
mix_hops,
|
||||||
|
)
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
warn!("failed to send a repliable message - {err}")
|
warn!("failed to send a repliable message - {err}")
|
||||||
@@ -106,8 +115,9 @@ where
|
|||||||
recipient,
|
recipient,
|
||||||
data,
|
data,
|
||||||
lane,
|
lane,
|
||||||
|
mix_hops,
|
||||||
} => {
|
} => {
|
||||||
self.handle_plain_message(recipient, data, lane, PacketType::Mix)
|
self.handle_plain_message(recipient, data, lane, PacketType::Mix, mix_hops)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
InputMessage::Anonymous {
|
InputMessage::Anonymous {
|
||||||
@@ -115,9 +125,17 @@ where
|
|||||||
data,
|
data,
|
||||||
reply_surbs,
|
reply_surbs,
|
||||||
lane,
|
lane,
|
||||||
|
mix_hops,
|
||||||
} => {
|
} => {
|
||||||
self.handle_repliable_message(recipient, data, reply_surbs, lane, PacketType::Mix)
|
self.handle_repliable_message(
|
||||||
.await
|
recipient,
|
||||||
|
data,
|
||||||
|
reply_surbs,
|
||||||
|
lane,
|
||||||
|
PacketType::Mix,
|
||||||
|
mix_hops,
|
||||||
|
)
|
||||||
|
.await
|
||||||
}
|
}
|
||||||
InputMessage::Reply {
|
InputMessage::Reply {
|
||||||
recipient_tag,
|
recipient_tag,
|
||||||
@@ -135,8 +153,9 @@ where
|
|||||||
recipient,
|
recipient,
|
||||||
data,
|
data,
|
||||||
lane,
|
lane,
|
||||||
|
mix_hops,
|
||||||
} => {
|
} => {
|
||||||
self.handle_plain_message(recipient, data, lane, packet_type)
|
self.handle_plain_message(recipient, data, lane, packet_type, mix_hops)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
InputMessage::Anonymous {
|
InputMessage::Anonymous {
|
||||||
@@ -144,9 +163,17 @@ where
|
|||||||
data,
|
data,
|
||||||
reply_surbs,
|
reply_surbs,
|
||||||
lane,
|
lane,
|
||||||
|
mix_hops,
|
||||||
} => {
|
} => {
|
||||||
self.handle_repliable_message(recipient, data, reply_surbs, lane, packet_type)
|
self.handle_repliable_message(
|
||||||
.await
|
recipient,
|
||||||
|
data,
|
||||||
|
reply_surbs,
|
||||||
|
lane,
|
||||||
|
packet_type,
|
||||||
|
mix_hops,
|
||||||
|
)
|
||||||
|
.await
|
||||||
}
|
}
|
||||||
InputMessage::Reply {
|
InputMessage::Reply {
|
||||||
recipient_tag,
|
recipient_tag,
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ pub(crate) struct PendingAcknowledgement {
|
|||||||
message_chunk: Fragment,
|
message_chunk: Fragment,
|
||||||
delay: SphinxDelay,
|
delay: SphinxDelay,
|
||||||
destination: PacketDestination,
|
destination: PacketDestination,
|
||||||
retransmissions: u32,
|
mix_hops: Option<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PendingAcknowledgement {
|
impl PendingAcknowledgement {
|
||||||
@@ -79,12 +79,13 @@ impl PendingAcknowledgement {
|
|||||||
message_chunk: Fragment,
|
message_chunk: Fragment,
|
||||||
delay: SphinxDelay,
|
delay: SphinxDelay,
|
||||||
recipient: Recipient,
|
recipient: Recipient,
|
||||||
|
mix_hops: Option<u8>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
PendingAcknowledgement {
|
PendingAcknowledgement {
|
||||||
message_chunk,
|
message_chunk,
|
||||||
delay,
|
delay,
|
||||||
destination: PacketDestination::KnownRecipient(recipient.into()),
|
destination: PacketDestination::KnownRecipient(recipient.into()),
|
||||||
retransmissions: 0,
|
mix_hops,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,7 +102,9 @@ impl PendingAcknowledgement {
|
|||||||
recipient_tag,
|
recipient_tag,
|
||||||
extra_surb_request,
|
extra_surb_request,
|
||||||
},
|
},
|
||||||
retransmissions: 0,
|
// Messages sent using SURBs are using the number of mix hops set by the recipient when
|
||||||
|
// they provided the SURBs, so it doesn't make sense to include it here.
|
||||||
|
mix_hops: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,9 +116,8 @@ impl PendingAcknowledgement {
|
|||||||
self.message_chunk.clone()
|
self.message_chunk.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_retransmitted(&mut self, new_delay: SphinxDelay) {
|
fn update_delay(&mut self, new_delay: SphinxDelay) {
|
||||||
self.delay = new_delay;
|
self.delay = new_delay;
|
||||||
self.retransmissions += 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -161,9 +163,6 @@ impl AcknowledgementControllerConnectors {
|
|||||||
|
|
||||||
/// Configurable parameters of the `AcknowledgementController`
|
/// Configurable parameters of the `AcknowledgementController`
|
||||||
pub(super) struct Config {
|
pub(super) struct Config {
|
||||||
/// Specify how many times particular packet can be retransmitted
|
|
||||||
maximum_retransmissions: Option<u32>,
|
|
||||||
|
|
||||||
/// Given ack timeout in the form a * BASE_DELAY + b, it specifies the additive part `b`
|
/// Given ack timeout in the form a * BASE_DELAY + b, it specifies the additive part `b`
|
||||||
ack_wait_addition: Duration,
|
ack_wait_addition: Duration,
|
||||||
|
|
||||||
@@ -175,13 +174,8 @@ pub(super) struct Config {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Config {
|
impl Config {
|
||||||
pub(super) fn new(
|
pub(super) fn new(ack_wait_addition: Duration, ack_wait_multiplier: f64) -> Self {
|
||||||
maximum_retransmissions: Option<u32>,
|
|
||||||
ack_wait_addition: Duration,
|
|
||||||
ack_wait_multiplier: f64,
|
|
||||||
) -> Self {
|
|
||||||
Config {
|
Config {
|
||||||
maximum_retransmissions,
|
|
||||||
ack_wait_addition,
|
ack_wait_addition,
|
||||||
ack_wait_multiplier,
|
ack_wait_multiplier,
|
||||||
packet_size: Default::default(),
|
packet_size: Default::default(),
|
||||||
@@ -244,7 +238,6 @@ where
|
|||||||
|
|
||||||
// will listen for any ack timeouts and trigger retransmission
|
// will listen for any ack timeouts and trigger retransmission
|
||||||
let retransmission_request_listener = RetransmissionRequestListener::new(
|
let retransmission_request_listener = RetransmissionRequestListener::new(
|
||||||
config.maximum_retransmissions,
|
|
||||||
connectors.ack_action_sender.clone(),
|
connectors.ack_action_sender.clone(),
|
||||||
message_handler,
|
message_handler,
|
||||||
retransmission_rx,
|
retransmission_rx,
|
||||||
|
|||||||
+11
-17
@@ -20,7 +20,6 @@ use std::sync::{Arc, Weak};
|
|||||||
|
|
||||||
// responsible for packet retransmission upon fired timer
|
// responsible for packet retransmission upon fired timer
|
||||||
pub(super) struct RetransmissionRequestListener<R> {
|
pub(super) struct RetransmissionRequestListener<R> {
|
||||||
maximum_retransmissions: Option<u32>,
|
|
||||||
action_sender: AckActionSender,
|
action_sender: AckActionSender,
|
||||||
message_handler: MessageHandler<R>,
|
message_handler: MessageHandler<R>,
|
||||||
request_receiver: RetransmissionRequestReceiver,
|
request_receiver: RetransmissionRequestReceiver,
|
||||||
@@ -32,14 +31,12 @@ where
|
|||||||
R: CryptoRng + Rng,
|
R: CryptoRng + Rng,
|
||||||
{
|
{
|
||||||
pub(super) fn new(
|
pub(super) fn new(
|
||||||
maximum_retransmissions: Option<u32>,
|
|
||||||
action_sender: AckActionSender,
|
action_sender: AckActionSender,
|
||||||
message_handler: MessageHandler<R>,
|
message_handler: MessageHandler<R>,
|
||||||
request_receiver: RetransmissionRequestReceiver,
|
request_receiver: RetransmissionRequestReceiver,
|
||||||
reply_controller_sender: ReplyControllerSender,
|
reply_controller_sender: ReplyControllerSender,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
RetransmissionRequestListener {
|
RetransmissionRequestListener {
|
||||||
maximum_retransmissions,
|
|
||||||
action_sender,
|
action_sender,
|
||||||
message_handler,
|
message_handler,
|
||||||
request_receiver,
|
request_receiver,
|
||||||
@@ -52,12 +49,18 @@ where
|
|||||||
packet_recipient: Recipient,
|
packet_recipient: Recipient,
|
||||||
chunk_data: Fragment,
|
chunk_data: Fragment,
|
||||||
packet_type: PacketType,
|
packet_type: PacketType,
|
||||||
|
mix_hops: Option<u8>,
|
||||||
) -> Result<PreparedFragment, PreparationError> {
|
) -> Result<PreparedFragment, PreparationError> {
|
||||||
debug!("retransmitting normal packet...");
|
debug!("retransmitting normal packet...");
|
||||||
|
|
||||||
// TODO: Figure out retransmission packet type signaling
|
// TODO: Figure out retransmission packet type signaling
|
||||||
self.message_handler
|
self.message_handler
|
||||||
.try_prepare_single_chunk_for_sending(packet_recipient, chunk_data, packet_type)
|
.try_prepare_single_chunk_for_sending(
|
||||||
|
packet_recipient,
|
||||||
|
chunk_data,
|
||||||
|
packet_type,
|
||||||
|
mix_hops,
|
||||||
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,18 +77,6 @@ where
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let frag_id = timed_out_ack.message_chunk.fragment_identifier();
|
|
||||||
|
|
||||||
if let Some(limit) = self.maximum_retransmissions {
|
|
||||||
if timed_out_ack.retransmissions >= limit {
|
|
||||||
warn!("reached maximum number of allowed retransmissions for the packet");
|
|
||||||
self.action_sender
|
|
||||||
.unbounded_send(Action::new_remove(frag_id))
|
|
||||||
.unwrap();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let maybe_prepared_fragment = match &timed_out_ack.destination {
|
let maybe_prepared_fragment = match &timed_out_ack.destination {
|
||||||
PacketDestination::Anonymous {
|
PacketDestination::Anonymous {
|
||||||
recipient_tag,
|
recipient_tag,
|
||||||
@@ -104,11 +95,14 @@ where
|
|||||||
**recipient,
|
**recipient,
|
||||||
timed_out_ack.message_chunk.clone(),
|
timed_out_ack.message_chunk.clone(),
|
||||||
packet_type,
|
packet_type,
|
||||||
|
timed_out_ack.mix_hops,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let frag_id = timed_out_ack.message_chunk.fragment_identifier();
|
||||||
|
|
||||||
let prepared_fragment = match maybe_prepared_fragment {
|
let prepared_fragment = match maybe_prepared_fragment {
|
||||||
Ok(prepared_fragment) => prepared_fragment,
|
Ok(prepared_fragment) => prepared_fragment,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
@@ -142,7 +136,7 @@ where
|
|||||||
// with the additional poisson delay.
|
// with the additional poisson delay.
|
||||||
// And since Actions are executed in order `UpdateTimer` will HAVE TO be executed before `StartTimer`
|
// And since Actions are executed in order `UpdateTimer` will HAVE TO be executed before `StartTimer`
|
||||||
self.action_sender
|
self.action_sender
|
||||||
.unbounded_send(Action::new_update_pending_ack(frag_id, new_delay))
|
.unbounded_send(Action::new_update_delay(frag_id, new_delay))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
// send to `OutQueueControl` to eventually send to the mix network
|
// send to `OutQueueControl` to eventually send to the mix network
|
||||||
|
|||||||
@@ -15,11 +15,11 @@ use nym_sphinx::anonymous_replies::requests::{AnonymousSenderTag, RepliableMessa
|
|||||||
use nym_sphinx::anonymous_replies::{ReplySurb, SurbEncryptionKey};
|
use nym_sphinx::anonymous_replies::{ReplySurb, SurbEncryptionKey};
|
||||||
use nym_sphinx::chunking::fragment::{Fragment, FragmentIdentifier};
|
use nym_sphinx::chunking::fragment::{Fragment, FragmentIdentifier};
|
||||||
use nym_sphinx::message::NymMessage;
|
use nym_sphinx::message::NymMessage;
|
||||||
use nym_sphinx::params::{PacketSize, PacketType};
|
use nym_sphinx::params::{PacketSize, PacketType, DEFAULT_NUM_MIX_HOPS};
|
||||||
use nym_sphinx::preparer::{MessagePreparer, PreparedFragment};
|
use nym_sphinx::preparer::{MessagePreparer, PreparedFragment};
|
||||||
use nym_sphinx::Delay;
|
use nym_sphinx::Delay;
|
||||||
use nym_task::connections::TransmissionLane;
|
use nym_task::connections::TransmissionLane;
|
||||||
use nym_topology::{NymRouteProvider, NymTopologyError};
|
use nym_topology::{NymTopology, NymTopologyError};
|
||||||
use rand::{CryptoRng, Rng};
|
use rand::{CryptoRng, Rng};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
@@ -91,15 +91,16 @@ pub(crate) struct Config {
|
|||||||
/// and surb-based are going to be sent.
|
/// and surb-based are going to be sent.
|
||||||
sender_address: Recipient,
|
sender_address: Recipient,
|
||||||
|
|
||||||
/// Specify whether route selection should be determined by the packet header.
|
|
||||||
deterministic_route_selection: bool,
|
|
||||||
|
|
||||||
/// Average delay a data packet is going to get delay at a single mixnode.
|
/// Average delay a data packet is going to get delay at a single mixnode.
|
||||||
average_packet_delay: Duration,
|
average_packet_delay: Duration,
|
||||||
|
|
||||||
/// Average delay an acknowledgement packet is going to get delay at a single mixnode.
|
/// Average delay an acknowledgement packet is going to get delay at a single mixnode.
|
||||||
average_ack_delay: Duration,
|
average_ack_delay: Duration,
|
||||||
|
|
||||||
|
/// Number of mix hops each packet ('real' message, ack, reply) is expected to take.
|
||||||
|
/// Note that it does not include gateway hops.
|
||||||
|
num_mix_hops: u8,
|
||||||
|
|
||||||
/// Primary predefined packet size used for the encapsulated messages.
|
/// Primary predefined packet size used for the encapsulated messages.
|
||||||
primary_packet_size: PacketSize,
|
primary_packet_size: PacketSize,
|
||||||
|
|
||||||
@@ -113,19 +114,25 @@ impl Config {
|
|||||||
sender_address: Recipient,
|
sender_address: Recipient,
|
||||||
average_packet_delay: Duration,
|
average_packet_delay: Duration,
|
||||||
average_ack_delay: Duration,
|
average_ack_delay: Duration,
|
||||||
deterministic_route_selection: bool,
|
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Config {
|
Config {
|
||||||
ack_key,
|
ack_key,
|
||||||
sender_address,
|
sender_address,
|
||||||
deterministic_route_selection,
|
|
||||||
average_packet_delay,
|
average_packet_delay,
|
||||||
average_ack_delay,
|
average_ack_delay,
|
||||||
|
num_mix_hops: DEFAULT_NUM_MIX_HOPS,
|
||||||
primary_packet_size: PacketSize::default(),
|
primary_packet_size: PacketSize::default(),
|
||||||
secondary_packet_size: None,
|
secondary_packet_size: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Allows setting non-default number of expected mix hops in the network.
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub fn with_mix_hops(mut self, hops: u8) -> Self {
|
||||||
|
self.num_mix_hops = hops;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
/// Allows setting non-default size of the sphinx packets sent out.
|
/// Allows setting non-default size of the sphinx packets sent out.
|
||||||
pub fn with_custom_primary_packet_size(mut self, packet_size: PacketSize) -> Self {
|
pub fn with_custom_primary_packet_size(mut self, packet_size: PacketSize) -> Self {
|
||||||
self.primary_packet_size = packet_size;
|
self.primary_packet_size = packet_size;
|
||||||
@@ -169,11 +176,12 @@ where
|
|||||||
{
|
{
|
||||||
let message_preparer = MessagePreparer::new(
|
let message_preparer = MessagePreparer::new(
|
||||||
rng,
|
rng,
|
||||||
config.deterministic_route_selection,
|
|
||||||
config.sender_address,
|
config.sender_address,
|
||||||
config.average_packet_delay,
|
config.average_packet_delay,
|
||||||
config.average_ack_delay,
|
config.average_ack_delay,
|
||||||
);
|
)
|
||||||
|
.with_mix_hops(config.num_mix_hops);
|
||||||
|
|
||||||
MessageHandler {
|
MessageHandler {
|
||||||
config,
|
config,
|
||||||
rng,
|
rng,
|
||||||
@@ -202,7 +210,7 @@ where
|
|||||||
fn get_topology<'a>(
|
fn get_topology<'a>(
|
||||||
&self,
|
&self,
|
||||||
permit: &'a TopologyReadPermit<'a>,
|
permit: &'a TopologyReadPermit<'a>,
|
||||||
) -> Result<&'a NymRouteProvider, PreparationError> {
|
) -> Result<&'a NymTopology, PreparationError> {
|
||||||
match permit.try_get_valid_topology_ref(&self.config.sender_address, None) {
|
match permit.try_get_valid_topology_ref(&self.config.sender_address, None) {
|
||||||
Ok(topology_ref) => Ok(topology_ref),
|
Ok(topology_ref) => Ok(topology_ref),
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
@@ -219,8 +227,9 @@ where
|
|||||||
return self.config.primary_packet_size;
|
return self.config.primary_packet_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
let primary_count = msg.required_packets(self.config.primary_packet_size);
|
let primary_count =
|
||||||
let secondary_count = msg.required_packets(secondary_packet);
|
msg.required_packets(self.config.primary_packet_size, self.config.num_mix_hops);
|
||||||
|
let secondary_count = msg.required_packets(secondary_packet, self.config.num_mix_hops);
|
||||||
|
|
||||||
trace!("This message would require: {primary_count} primary packets or {secondary_count} secondary packets...");
|
trace!("This message would require: {primary_count} primary packets or {secondary_count} secondary packets...");
|
||||||
// if there would be no benefit in using the secondary packet - use the primary (duh)
|
// if there would be no benefit in using the secondary packet - use the primary (duh)
|
||||||
@@ -409,9 +418,10 @@ where
|
|||||||
message: Vec<u8>,
|
message: Vec<u8>,
|
||||||
lane: TransmissionLane,
|
lane: TransmissionLane,
|
||||||
packet_type: PacketType,
|
packet_type: PacketType,
|
||||||
|
mix_hops: Option<u8>,
|
||||||
) -> Result<(), PreparationError> {
|
) -> Result<(), PreparationError> {
|
||||||
let message = NymMessage::new_plain(message);
|
let message = NymMessage::new_plain(message);
|
||||||
self.try_split_and_send_non_reply_message(message, recipient, lane, packet_type)
|
self.try_split_and_send_non_reply_message(message, recipient, lane, packet_type, mix_hops)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -421,6 +431,7 @@ where
|
|||||||
recipient: Recipient,
|
recipient: Recipient,
|
||||||
lane: TransmissionLane,
|
lane: TransmissionLane,
|
||||||
packet_type: PacketType,
|
packet_type: PacketType,
|
||||||
|
mix_hops: Option<u8>,
|
||||||
) -> Result<(), PreparationError> {
|
) -> Result<(), PreparationError> {
|
||||||
debug!("Sending non-reply message with packet type {packet_type}");
|
debug!("Sending non-reply message with packet type {packet_type}");
|
||||||
// TODO: I really dislike existence of this assertion, it implies code has to be re-organised
|
// TODO: I really dislike existence of this assertion, it implies code has to be re-organised
|
||||||
@@ -453,6 +464,7 @@ where
|
|||||||
&self.config.ack_key,
|
&self.config.ack_key,
|
||||||
&recipient,
|
&recipient,
|
||||||
packet_type,
|
packet_type,
|
||||||
|
mix_hops,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let real_message = RealMessage::new(
|
let real_message = RealMessage::new(
|
||||||
@@ -460,7 +472,8 @@ where
|
|||||||
Some(fragment.fragment_identifier()),
|
Some(fragment.fragment_identifier()),
|
||||||
);
|
);
|
||||||
let delay = prepared_fragment.total_delay;
|
let delay = prepared_fragment.total_delay;
|
||||||
let pending_ack = PendingAcknowledgement::new_known(fragment, delay, recipient);
|
let pending_ack =
|
||||||
|
PendingAcknowledgement::new_known(fragment, delay, recipient, mix_hops);
|
||||||
|
|
||||||
real_messages.push(real_message);
|
real_messages.push(real_message);
|
||||||
pending_acks.push(pending_ack);
|
pending_acks.push(pending_ack);
|
||||||
@@ -477,6 +490,7 @@ where
|
|||||||
recipient: Recipient,
|
recipient: Recipient,
|
||||||
amount: u32,
|
amount: u32,
|
||||||
packet_type: PacketType,
|
packet_type: PacketType,
|
||||||
|
mix_hops: Option<u8>,
|
||||||
) -> Result<(), PreparationError> {
|
) -> Result<(), PreparationError> {
|
||||||
debug!("Sending additional reply SURBs with packet type {packet_type}");
|
debug!("Sending additional reply SURBs with packet type {packet_type}");
|
||||||
let sender_tag = self.get_or_create_sender_tag(&recipient);
|
let sender_tag = self.get_or_create_sender_tag(&recipient);
|
||||||
@@ -493,6 +507,7 @@ where
|
|||||||
recipient,
|
recipient,
|
||||||
TransmissionLane::AdditionalReplySurbs,
|
TransmissionLane::AdditionalReplySurbs,
|
||||||
packet_type,
|
packet_type,
|
||||||
|
mix_hops,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
@@ -509,6 +524,7 @@ where
|
|||||||
num_reply_surbs: u32,
|
num_reply_surbs: u32,
|
||||||
lane: TransmissionLane,
|
lane: TransmissionLane,
|
||||||
packet_type: PacketType,
|
packet_type: PacketType,
|
||||||
|
mix_hops: Option<u8>,
|
||||||
) -> Result<(), SurbWrappedPreparationError> {
|
) -> Result<(), SurbWrappedPreparationError> {
|
||||||
debug!("Sending message with reply SURBs with packet type {packet_type}");
|
debug!("Sending message with reply SURBs with packet type {packet_type}");
|
||||||
let sender_tag = self.get_or_create_sender_tag(&recipient);
|
let sender_tag = self.get_or_create_sender_tag(&recipient);
|
||||||
@@ -519,7 +535,7 @@ where
|
|||||||
let message =
|
let message =
|
||||||
NymMessage::new_repliable(RepliableMessage::new_data(message, sender_tag, reply_surbs));
|
NymMessage::new_repliable(RepliableMessage::new_data(message, sender_tag, reply_surbs));
|
||||||
|
|
||||||
self.try_split_and_send_non_reply_message(message, recipient, lane, packet_type)
|
self.try_split_and_send_non_reply_message(message, recipient, lane, packet_type, mix_hops)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
log::trace!("storing {} reply keys", reply_keys.len());
|
log::trace!("storing {} reply keys", reply_keys.len());
|
||||||
@@ -533,18 +549,23 @@ where
|
|||||||
recipient: Recipient,
|
recipient: Recipient,
|
||||||
chunk: Fragment,
|
chunk: Fragment,
|
||||||
packet_type: PacketType,
|
packet_type: PacketType,
|
||||||
|
mix_hops: Option<u8>,
|
||||||
) -> Result<PreparedFragment, PreparationError> {
|
) -> Result<PreparedFragment, PreparationError> {
|
||||||
debug!("Sending single chunk with packet type {packet_type}");
|
debug!("Sending single chunk with packet type {packet_type}");
|
||||||
let topology_permit = self.topology_access.get_read_permit().await;
|
let topology_permit = self.topology_access.get_read_permit().await;
|
||||||
let topology = self.get_topology(&topology_permit)?;
|
let topology = self.get_topology(&topology_permit)?;
|
||||||
|
|
||||||
let prepared_fragment = self.message_preparer.prepare_chunk_for_sending(
|
let prepared_fragment = self
|
||||||
chunk,
|
.message_preparer
|
||||||
topology,
|
.prepare_chunk_for_sending(
|
||||||
&self.config.ack_key,
|
chunk,
|
||||||
&recipient,
|
topology,
|
||||||
packet_type,
|
&self.config.ack_key,
|
||||||
)?;
|
&recipient,
|
||||||
|
packet_type,
|
||||||
|
mix_hops,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
Ok(prepared_fragment)
|
Ok(prepared_fragment)
|
||||||
}
|
}
|
||||||
@@ -597,20 +618,23 @@ where
|
|||||||
Err(err) => return Err(err.return_surbs(vec![reply_surb])),
|
Err(err) => return Err(err.return_surbs(vec![reply_surb])),
|
||||||
};
|
};
|
||||||
|
|
||||||
let prepared_fragment = self.message_preparer.prepare_reply_chunk_for_sending(
|
let prepared_fragment = self
|
||||||
chunk,
|
.message_preparer
|
||||||
topology,
|
.prepare_reply_chunk_for_sending(
|
||||||
&self.config.ack_key,
|
chunk,
|
||||||
reply_surb,
|
topology,
|
||||||
PacketType::Mix,
|
&self.config.ack_key,
|
||||||
)?;
|
reply_surb,
|
||||||
|
PacketType::Mix,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
Ok(prepared_fragment)
|
Ok(prepared_fragment)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn update_ack_delay(&self, id: FragmentIdentifier, new_delay: Delay) {
|
pub(crate) fn update_ack_delay(&self, id: FragmentIdentifier, new_delay: Delay) {
|
||||||
self.action_sender
|
self.action_sender
|
||||||
.unbounded_send(Action::UpdatePendingAck(id, new_delay))
|
.unbounded_send(Action::UpdateDelay(id, new_delay))
|
||||||
.expect("action control task has died")
|
.expect("action control task has died")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,12 +9,10 @@ use self::{
|
|||||||
acknowledgement_control::AcknowledgementController, real_traffic_stream::OutQueueControl,
|
acknowledgement_control::AcknowledgementController, real_traffic_stream::OutQueueControl,
|
||||||
};
|
};
|
||||||
use crate::client::real_messages_control::message_handler::MessageHandler;
|
use crate::client::real_messages_control::message_handler::MessageHandler;
|
||||||
use crate::client::replies::reply_controller;
|
|
||||||
use crate::client::replies::reply_controller::{
|
use crate::client::replies::reply_controller::{
|
||||||
ReplyController, ReplyControllerReceiver, ReplyControllerSender,
|
ReplyController, ReplyControllerReceiver, ReplyControllerSender,
|
||||||
};
|
};
|
||||||
use crate::client::replies::reply_storage::CombinedReplyStorage;
|
use crate::client::replies::reply_storage::CombinedReplyStorage;
|
||||||
use crate::config;
|
|
||||||
use crate::{
|
use crate::{
|
||||||
client::{
|
client::{
|
||||||
inbound_messages::InputMessageReceiver, mix_traffic::BatchMixMessageSender,
|
inbound_messages::InputMessageReceiver, mix_traffic::BatchMixMessageSender,
|
||||||
@@ -29,13 +27,16 @@ use nym_gateway_client::AcknowledgementReceiver;
|
|||||||
use nym_sphinx::acknowledgements::AckKey;
|
use nym_sphinx::acknowledgements::AckKey;
|
||||||
use nym_sphinx::addressing::clients::Recipient;
|
use nym_sphinx::addressing::clients::Recipient;
|
||||||
use nym_sphinx::params::PacketType;
|
use nym_sphinx::params::PacketType;
|
||||||
use nym_statistics_common::clients::ClientStatsSender;
|
|
||||||
use nym_task::connections::{ConnectionCommandReceiver, LaneQueueLengths};
|
use nym_task::connections::{ConnectionCommandReceiver, LaneQueueLengths};
|
||||||
use rand::{rngs::OsRng, CryptoRng, Rng};
|
use rand::{rngs::OsRng, CryptoRng, Rng};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use crate::client::replies::reply_controller;
|
||||||
|
use crate::config;
|
||||||
pub(crate) use acknowledgement_control::{AckActionSender, Action};
|
pub(crate) use acknowledgement_control::{AckActionSender, Action};
|
||||||
|
|
||||||
|
use nym_statistics_common::clients::ClientStatsSender;
|
||||||
|
|
||||||
pub(crate) mod acknowledgement_control;
|
pub(crate) mod acknowledgement_control;
|
||||||
pub(crate) mod message_handler;
|
pub(crate) mod message_handler;
|
||||||
pub(crate) mod real_traffic_stream;
|
pub(crate) mod real_traffic_stream;
|
||||||
@@ -64,7 +65,6 @@ pub struct Config {
|
|||||||
impl<'a> From<&'a Config> for acknowledgement_control::Config {
|
impl<'a> From<&'a Config> for acknowledgement_control::Config {
|
||||||
fn from(cfg: &'a Config) -> Self {
|
fn from(cfg: &'a Config) -> Self {
|
||||||
acknowledgement_control::Config::new(
|
acknowledgement_control::Config::new(
|
||||||
cfg.traffic.maximum_number_of_retransmissions,
|
|
||||||
cfg.acks.ack_wait_addition,
|
cfg.acks.ack_wait_addition,
|
||||||
cfg.acks.ack_wait_multiplier,
|
cfg.acks.ack_wait_multiplier,
|
||||||
)
|
)
|
||||||
@@ -97,7 +97,6 @@ impl<'a> From<&'a Config> for message_handler::Config {
|
|||||||
cfg.self_recipient,
|
cfg.self_recipient,
|
||||||
cfg.traffic.average_packet_delay,
|
cfg.traffic.average_packet_delay,
|
||||||
cfg.acks.average_ack_delay,
|
cfg.acks.average_ack_delay,
|
||||||
cfg.traffic.deterministic_route_selection,
|
|
||||||
)
|
)
|
||||||
.with_custom_primary_packet_size(cfg.traffic.primary_packet_size)
|
.with_custom_primary_packet_size(cfg.traffic.primary_packet_size)
|
||||||
.with_custom_secondary_packet_size(cfg.traffic.secondary_packet_size)
|
.with_custom_secondary_packet_size(cfg.traffic.secondary_packet_size)
|
||||||
|
|||||||
@@ -230,7 +230,6 @@ where
|
|||||||
// poisson delay, but is it really a problem?
|
// poisson delay, but is it really a problem?
|
||||||
let topology_permit = self.topology_access.get_read_permit().await;
|
let topology_permit = self.topology_access.get_read_permit().await;
|
||||||
// the ack is sent back to ourselves (and then ignored)
|
// the ack is sent back to ourselves (and then ignored)
|
||||||
|
|
||||||
let topology_ref = match topology_permit.try_get_valid_topology_ref(
|
let topology_ref = match topology_permit.try_get_valid_topology_ref(
|
||||||
&self.config.our_full_destination,
|
&self.config.our_full_destination,
|
||||||
Some(&self.config.our_full_destination),
|
Some(&self.config.our_full_destination),
|
||||||
|
|||||||
+1
-4
@@ -70,10 +70,7 @@ impl SendingDelayController {
|
|||||||
lower_bound,
|
lower_bound,
|
||||||
multiplier_elevated_counter: 0,
|
multiplier_elevated_counter: 0,
|
||||||
time_when_logged_about_elevated_multiplier: now
|
time_when_logged_about_elevated_multiplier: now
|
||||||
.checked_sub(Duration::from_secs(
|
- Duration::from_secs(INTERVAL_BETWEEN_WARNING_ABOUT_ELEVATED_MULTIPLIER_SECS),
|
||||||
INTERVAL_BETWEEN_WARNING_ABOUT_ELEVATED_MULTIPLIER_SECS,
|
|
||||||
))
|
|
||||||
.unwrap_or(now),
|
|
||||||
time_when_changed: now,
|
time_when_changed: now,
|
||||||
time_when_backpressure_detected: now,
|
time_when_backpressure_detected: now,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -516,6 +516,7 @@ where
|
|||||||
recipient,
|
recipient,
|
||||||
to_send,
|
to_send,
|
||||||
nym_sphinx::params::PacketType::Mix,
|
nym_sphinx::params::PacketType::Mix,
|
||||||
|
self.config.reply_surbs.surb_mix_hops,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -16,14 +16,14 @@
|
|||||||
#![warn(clippy::todo)]
|
#![warn(clippy::todo)]
|
||||||
#![warn(clippy::dbg_macro)]
|
#![warn(clippy::dbg_macro)]
|
||||||
|
|
||||||
use futures::StreamExt;
|
use std::time::Duration;
|
||||||
|
|
||||||
use nym_client_core_config_types::StatsReporting;
|
use nym_client_core_config_types::StatsReporting;
|
||||||
use nym_sphinx::addressing::Recipient;
|
use nym_sphinx::addressing::Recipient;
|
||||||
use nym_statistics_common::clients::{
|
use nym_statistics_common::clients::{
|
||||||
ClientStatsController, ClientStatsReceiver, ClientStatsSender,
|
ClientStatsController, ClientStatsReceiver, ClientStatsSender,
|
||||||
};
|
};
|
||||||
use nym_task::connections::TransmissionLane;
|
use nym_task::connections::TransmissionLane;
|
||||||
use std::time::Duration;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
client::inbound_messages::{InputMessage, InputMessageSender},
|
client::inbound_messages::{InputMessage, InputMessageSender},
|
||||||
@@ -94,32 +94,10 @@ impl StatisticsControl {
|
|||||||
async fn run_with_shutdown(&mut self, mut task_client: nym_task::TaskClient) {
|
async fn run_with_shutdown(&mut self, mut task_client: nym_task::TaskClient) {
|
||||||
log::debug!("Started StatisticsControl with graceful shutdown support");
|
log::debug!("Started StatisticsControl with graceful shutdown support");
|
||||||
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
let mut stats_report_interval =
|
||||||
let mut stats_report_interval = tokio_stream::wrappers::IntervalStream::new(
|
tokio::time::interval(self.reporting_config.reporting_interval);
|
||||||
tokio::time::interval(self.reporting_config.reporting_interval),
|
let mut local_report_interval = tokio::time::interval(LOCAL_REPORT_INTERVAL);
|
||||||
);
|
let mut snapshot_interval = tokio::time::interval(SNAPSHOT_INTERVAL);
|
||||||
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
|
||||||
let mut local_report_interval = tokio_stream::wrappers::IntervalStream::new(
|
|
||||||
tokio::time::interval(LOCAL_REPORT_INTERVAL),
|
|
||||||
);
|
|
||||||
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
|
||||||
let mut snapshot_interval =
|
|
||||||
tokio_stream::wrappers::IntervalStream::new(tokio::time::interval(SNAPSHOT_INTERVAL));
|
|
||||||
|
|
||||||
#[cfg(target_arch = "wasm32")]
|
|
||||||
let mut stats_report_interval = gloo_timers::future::IntervalStream::new(
|
|
||||||
self.reporting_config.reporting_interval.as_millis() as u32,
|
|
||||||
);
|
|
||||||
|
|
||||||
#[cfg(target_arch = "wasm32")]
|
|
||||||
let mut local_report_interval =
|
|
||||||
gloo_timers::future::IntervalStream::new(LOCAL_REPORT_INTERVAL.as_millis() as u32);
|
|
||||||
|
|
||||||
#[cfg(target_arch = "wasm32")]
|
|
||||||
let mut snapshot_interval =
|
|
||||||
gloo_timers::future::IntervalStream::new(SNAPSHOT_INTERVAL.as_millis() as u32);
|
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
tokio::select! {
|
tokio::select! {
|
||||||
@@ -130,20 +108,16 @@ impl StatisticsControl {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
_ = snapshot_interval.next() => {
|
_ = snapshot_interval.tick() => {
|
||||||
self.stats.snapshot();
|
self.stats.snapshot();
|
||||||
}
|
}
|
||||||
_ = stats_report_interval.next() => {
|
_ = stats_report_interval.tick(), if self.reporting_config.enabled && self.reporting_config.provider_address.is_some() => {
|
||||||
let Some(recipient) = self.reporting_config.provider_address else {
|
// SAFTEY : this branch executes only if reporting is not none, so unwrapp is fine
|
||||||
continue
|
#[allow(clippy::unwrap_used)]
|
||||||
};
|
self.report_stats(self.reporting_config.provider_address.unwrap()).await;
|
||||||
|
|
||||||
if self.reporting_config.enabled {
|
|
||||||
self.report_stats(recipient).await;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = local_report_interval.next() => {
|
_ = local_report_interval.tick() => {
|
||||||
self.stats.local_report(&mut task_client);
|
self.stats.local_report(&mut task_client);
|
||||||
}
|
}
|
||||||
_ = task_client.recv_with_delay() => {
|
_ = task_client.recv_with_delay() => {
|
||||||
|
|||||||
@@ -2,7 +2,8 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
use nym_sphinx::addressing::clients::Recipient;
|
use nym_sphinx::addressing::clients::Recipient;
|
||||||
use nym_topology::{NymRouteProvider, NymTopology, NymTopologyError};
|
use nym_sphinx::params::DEFAULT_NUM_MIX_HOPS;
|
||||||
|
use nym_topology::{NymTopology, NymTopologyError};
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
@@ -16,36 +17,29 @@ pub struct TopologyAccessorInner {
|
|||||||
// few seconds, while reads are needed every single packet generated.
|
// few seconds, while reads are needed every single packet generated.
|
||||||
// However, proper benchmarks will be needed to determine if `RwLock` is indeed a better
|
// However, proper benchmarks will be needed to determine if `RwLock` is indeed a better
|
||||||
// approach than a `Mutex`
|
// approach than a `Mutex`
|
||||||
topology: RwLock<NymRouteProvider>,
|
topology: RwLock<Option<NymTopology>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TopologyAccessorInner {
|
impl TopologyAccessorInner {
|
||||||
fn new(initial: NymRouteProvider) -> Self {
|
fn new() -> Self {
|
||||||
TopologyAccessorInner {
|
TopologyAccessorInner {
|
||||||
controlled_manually: AtomicBool::new(false),
|
controlled_manually: AtomicBool::new(false),
|
||||||
released_manual_control: Notify::new(),
|
released_manual_control: Notify::new(),
|
||||||
topology: RwLock::new(initial),
|
topology: RwLock::new(None),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn update(&self, new: Option<NymTopology>) {
|
async fn update(&self, new: Option<NymTopology>) {
|
||||||
let mut guard = self.topology.write().await;
|
*self.topology.write().await = new;
|
||||||
|
|
||||||
match new {
|
|
||||||
Some(updated) => {
|
|
||||||
guard.update(updated);
|
|
||||||
}
|
|
||||||
None => guard.clear_topology(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct TopologyReadPermit<'a> {
|
pub struct TopologyReadPermit<'a> {
|
||||||
permit: RwLockReadGuard<'a, NymRouteProvider>,
|
permit: RwLockReadGuard<'a, Option<NymTopology>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Deref for TopologyReadPermit<'_> {
|
impl<'a> Deref for TopologyReadPermit<'a> {
|
||||||
type Target = NymRouteProvider;
|
type Target = Option<NymTopology>;
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
&self.permit
|
&self.permit
|
||||||
@@ -59,31 +53,43 @@ impl<'a> TopologyReadPermit<'a> {
|
|||||||
&'a self,
|
&'a self,
|
||||||
ack_recipient: &Recipient,
|
ack_recipient: &Recipient,
|
||||||
packet_recipient: Option<&Recipient>,
|
packet_recipient: Option<&Recipient>,
|
||||||
) -> Result<&'a NymRouteProvider, NymTopologyError> {
|
) -> Result<&'a NymTopology, NymTopologyError> {
|
||||||
let route_provider = self.permit.deref();
|
|
||||||
let topology = &route_provider.topology;
|
|
||||||
|
|
||||||
// 1. Have we managed to get anything from the refresher, i.e. have the nym-api queries gone through?
|
// 1. Have we managed to get anything from the refresher, i.e. have the nym-api queries gone through?
|
||||||
topology.ensure_not_empty()?;
|
let topology = self
|
||||||
|
.permit
|
||||||
|
.as_ref()
|
||||||
|
.ok_or(NymTopologyError::EmptyNetworkTopology)?;
|
||||||
|
|
||||||
// 2. does the topology have a node on each mixing layer?
|
// 2. does it have any mixnode at all?
|
||||||
topology.ensure_minimally_routable()?;
|
// 3. does it have any gateways at all?
|
||||||
|
// 4. does it have a mixnode on each layer?
|
||||||
|
topology.ensure_can_construct_path_through(DEFAULT_NUM_MIX_HOPS)?;
|
||||||
|
|
||||||
// 3. does it contain OUR gateway (so that we could create an ack packet)?
|
// 5. does it contain OUR gateway (so that we could create an ack packet)?
|
||||||
let _ = route_provider.egress_by_identity(ack_recipient.gateway())?;
|
if !topology.gateway_exists(ack_recipient.gateway()) {
|
||||||
|
return Err(NymTopologyError::NonExistentGatewayError {
|
||||||
// 4. for our target recipient, does it contain THEIR gateway (so that we send anything over?)
|
identity_key: ack_recipient.gateway().to_base58_string(),
|
||||||
if let Some(recipient) = packet_recipient {
|
});
|
||||||
let _ = route_provider.egress_by_identity(recipient.gateway())?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(route_provider)
|
// 6. for our target recipient, does it contain THEIR gateway (so that we could create
|
||||||
|
if let Some(recipient) = packet_recipient {
|
||||||
|
if !topology.gateway_exists(recipient.gateway()) {
|
||||||
|
return Err(NymTopologyError::NonExistentGatewayError {
|
||||||
|
identity_key: recipient.gateway().to_base58_string(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(topology)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> From<RwLockReadGuard<'a, NymRouteProvider>> for TopologyReadPermit<'a> {
|
impl<'a> From<RwLockReadGuard<'a, Option<NymTopology>>> for TopologyReadPermit<'a> {
|
||||||
fn from(permit: RwLockReadGuard<'a, NymRouteProvider>) -> Self {
|
fn from(read_permit: RwLockReadGuard<'a, Option<NymTopology>>) -> Self {
|
||||||
TopologyReadPermit { permit }
|
TopologyReadPermit {
|
||||||
|
permit: read_permit,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,11 +99,9 @@ pub struct TopologyAccessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl TopologyAccessor {
|
impl TopologyAccessor {
|
||||||
pub fn new(ignore_egress_epoch_roles: bool) -> Self {
|
pub fn new() -> Self {
|
||||||
TopologyAccessor {
|
TopologyAccessor {
|
||||||
inner: Arc::new(TopologyAccessorInner::new(NymRouteProvider::new_empty(
|
inner: Arc::new(TopologyAccessorInner::new()),
|
||||||
ignore_egress_epoch_roles,
|
|
||||||
))),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -117,21 +121,8 @@ impl TopologyAccessor {
|
|||||||
self.inner.released_manual_control.notified().await
|
self.inner.released_manual_control.notified().await
|
||||||
}
|
}
|
||||||
|
|
||||||
#[deprecated(note = "use .current_route_provider instead")]
|
|
||||||
pub async fn current_topology(&self) -> Option<NymTopology> {
|
pub async fn current_topology(&self) -> Option<NymTopology> {
|
||||||
self.current_route_provider()
|
self.inner.topology.read().await.clone()
|
||||||
.await
|
|
||||||
.as_ref()
|
|
||||||
.map(|p| p.topology.clone())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn current_route_provider(&self) -> Option<RwLockReadGuard<NymRouteProvider>> {
|
|
||||||
let provider = self.inner.topology.read().await;
|
|
||||||
if provider.topology.is_empty() {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
Some(provider)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn manually_change_topology(&self, new_topology: NymTopology) {
|
pub async fn manually_change_topology(&self, new_topology: NymTopology) {
|
||||||
@@ -149,11 +140,15 @@ impl TopologyAccessor {
|
|||||||
// only used by the client at startup to get a slightly more reasonable error message
|
// only used by the client at startup to get a slightly more reasonable error message
|
||||||
// (currently displays as unused because health checker is disabled due to required changes)
|
// (currently displays as unused because health checker is disabled due to required changes)
|
||||||
pub async fn ensure_is_routable(&self) -> Result<(), NymTopologyError> {
|
pub async fn ensure_is_routable(&self) -> Result<(), NymTopologyError> {
|
||||||
self.inner
|
match self.inner.topology.read().await.deref() {
|
||||||
.topology
|
None => Err(NymTopologyError::EmptyNetworkTopology),
|
||||||
.read()
|
Some(ref topology) => topology.ensure_can_construct_path_through(DEFAULT_NUM_MIX_HOPS),
|
||||||
.await
|
}
|
||||||
.topology
|
}
|
||||||
.ensure_minimally_routable()
|
}
|
||||||
|
|
||||||
|
impl Default for TopologyAccessor {
|
||||||
|
fn default() -> Self {
|
||||||
|
TopologyAccessor::new()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ use log::{debug, error};
|
|||||||
use nym_explorer_client::{ExplorerClient, PrettyDetailedMixNodeBond};
|
use nym_explorer_client::{ExplorerClient, PrettyDetailedMixNodeBond};
|
||||||
use nym_network_defaults::var_names::EXPLORER_API;
|
use nym_network_defaults::var_names::EXPLORER_API;
|
||||||
use nym_topology::{
|
use nym_topology::{
|
||||||
|
nym_topology_from_basic_info,
|
||||||
provider_trait::{async_trait, TopologyProvider},
|
provider_trait::{async_trait, TopologyProvider},
|
||||||
NymTopology,
|
NymTopology,
|
||||||
};
|
};
|
||||||
@@ -14,6 +15,8 @@ use url::Url;
|
|||||||
|
|
||||||
pub use nym_country_group::CountryGroup;
|
pub use nym_country_group::CountryGroup;
|
||||||
|
|
||||||
|
const MIN_NODES_PER_LAYER: usize = 1;
|
||||||
|
|
||||||
fn create_explorer_client() -> Option<ExplorerClient> {
|
fn create_explorer_client() -> Option<ExplorerClient> {
|
||||||
let Ok(explorer_api_url) = std::env::var(EXPLORER_API) else {
|
let Ok(explorer_api_url) = std::env::var(EXPLORER_API) else {
|
||||||
error!("Missing EXPLORER_API");
|
error!("Missing EXPLORER_API");
|
||||||
@@ -60,22 +63,37 @@ fn log_mixnode_distribution(mixnodes: &HashMap<CountryGroup, Vec<NodeId>>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn check_layer_integrity(topology: NymTopology) -> Result<(), ()> {
|
fn check_layer_integrity(topology: NymTopology) -> Result<(), ()> {
|
||||||
if topology.ensure_minimally_routable().is_err() {
|
let mixes = topology.mixes();
|
||||||
|
if mixes.keys().len() < 3 {
|
||||||
error!("Layer is missing in topology!");
|
error!("Layer is missing in topology!");
|
||||||
return Err(());
|
return Err(());
|
||||||
}
|
}
|
||||||
|
for (layer, mixnodes) in mixes {
|
||||||
|
debug!("Layer {:?} has {} mixnodes", layer, mixnodes.len());
|
||||||
|
if mixnodes.len() < MIN_NODES_PER_LAYER {
|
||||||
|
error!(
|
||||||
|
"There are only {} mixnodes in layer {:?}",
|
||||||
|
mixnodes.len(),
|
||||||
|
layer
|
||||||
|
);
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[deprecated(note = "use NymApiTopologyProvider instead as explorer API will soon be removed")]
|
|
||||||
pub struct GeoAwareTopologyProvider {
|
pub struct GeoAwareTopologyProvider {
|
||||||
validator_client: nym_validator_client::client::NymApiClient,
|
validator_client: nym_validator_client::client::NymApiClient,
|
||||||
filter_on: GroupBy,
|
filter_on: GroupBy,
|
||||||
|
client_version: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(deprecated)]
|
|
||||||
impl GeoAwareTopologyProvider {
|
impl GeoAwareTopologyProvider {
|
||||||
pub fn new(mut nym_api_urls: Vec<Url>, filter_on: GroupBy) -> GeoAwareTopologyProvider {
|
pub fn new(
|
||||||
|
mut nym_api_urls: Vec<Url>,
|
||||||
|
client_version: String,
|
||||||
|
filter_on: GroupBy,
|
||||||
|
) -> GeoAwareTopologyProvider {
|
||||||
log::info!(
|
log::info!(
|
||||||
"Creating geo-aware topology provider with filter on {}",
|
"Creating geo-aware topology provider with filter on {}",
|
||||||
filter_on
|
filter_on
|
||||||
@@ -87,22 +105,14 @@ impl GeoAwareTopologyProvider {
|
|||||||
nym_api_urls[0].clone(),
|
nym_api_urls[0].clone(),
|
||||||
),
|
),
|
||||||
filter_on,
|
filter_on,
|
||||||
|
client_version,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_topology(&self) -> Option<NymTopology> {
|
async fn get_topology(&self) -> Option<NymTopology> {
|
||||||
let rewarded_set = self
|
|
||||||
.validator_client
|
|
||||||
.get_current_rewarded_set()
|
|
||||||
.await
|
|
||||||
.inspect_err(|err| error!("failed to get current rewarded set: {err}"))
|
|
||||||
.ok()?;
|
|
||||||
|
|
||||||
let mut topology = NymTopology::new_empty(rewarded_set);
|
|
||||||
|
|
||||||
let mixnodes = match self
|
let mixnodes = match self
|
||||||
.validator_client
|
.validator_client
|
||||||
.get_all_basic_active_mixing_assigned_nodes()
|
.get_all_basic_active_mixing_assigned_nodes(Some(self.client_version.clone()))
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
@@ -114,7 +124,7 @@ impl GeoAwareTopologyProvider {
|
|||||||
|
|
||||||
let gateways = match self
|
let gateways = match self
|
||||||
.validator_client
|
.validator_client
|
||||||
.get_all_basic_entry_assigned_nodes()
|
.get_all_basic_entry_assigned_nodes(Some(self.client_version.clone()))
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
@@ -183,8 +193,7 @@ impl GeoAwareTopologyProvider {
|
|||||||
.filter(|m| filtered_mixnode_ids.contains(&m.node_id))
|
.filter(|m| filtered_mixnode_ids.contains(&m.node_id))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
topology.add_skimmed_nodes(&mixnodes);
|
let topology = nym_topology_from_basic_info(&mixnodes, &gateways);
|
||||||
topology.add_skimmed_nodes(&gateways);
|
|
||||||
|
|
||||||
// TODO: return real error type
|
// TODO: return real error type
|
||||||
check_layer_integrity(topology.clone()).ok()?;
|
check_layer_integrity(topology.clone()).ok()?;
|
||||||
@@ -193,7 +202,6 @@ impl GeoAwareTopologyProvider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(deprecated)]
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl TopologyProvider for GeoAwareTopologyProvider {
|
impl TopologyProvider for GeoAwareTopologyProvider {
|
||||||
@@ -203,7 +211,6 @@ impl TopologyProvider for GeoAwareTopologyProvider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(deprecated)]
|
|
||||||
#[cfg(target_arch = "wasm32")]
|
#[cfg(target_arch = "wasm32")]
|
||||||
#[async_trait(?Send)]
|
#[async_trait(?Send)]
|
||||||
impl TopologyProvider for GeoAwareTopologyProvider {
|
impl TopologyProvider for GeoAwareTopologyProvider {
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ mod accessor;
|
|||||||
pub mod geo_aware_provider;
|
pub mod geo_aware_provider;
|
||||||
pub mod nym_api_provider;
|
pub mod nym_api_provider;
|
||||||
|
|
||||||
#[allow(deprecated)]
|
|
||||||
pub use geo_aware_provider::GeoAwareTopologyProvider;
|
pub use geo_aware_provider::GeoAwareTopologyProvider;
|
||||||
pub use nym_api_provider::{Config as NymApiTopologyProviderConfig, NymApiTopologyProvider};
|
pub use nym_api_provider::{Config as NymApiTopologyProviderConfig, NymApiTopologyProvider};
|
||||||
pub use nym_topology::provider_trait::TopologyProvider;
|
pub use nym_topology::provider_trait::TopologyProvider;
|
||||||
@@ -28,7 +27,7 @@ pub use nym_topology::provider_trait::TopologyProvider;
|
|||||||
const MAX_FAILURE_COUNT: usize = 10;
|
const MAX_FAILURE_COUNT: usize = 10;
|
||||||
|
|
||||||
pub struct TopologyRefresherConfig {
|
pub struct TopologyRefresherConfig {
|
||||||
pub refresh_rate: Duration,
|
refresh_rate: Duration,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TopologyRefresherConfig {
|
impl TopologyRefresherConfig {
|
||||||
@@ -97,24 +96,28 @@ impl TopologyRefresher {
|
|||||||
self.topology_accessor.ensure_is_routable().await
|
self.topology_accessor.ensure_is_routable().await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn ensure_contains_routable_egress(
|
pub async fn ensure_contains_gateway(
|
||||||
&self,
|
&self,
|
||||||
egress: NodeIdentity,
|
gateway: &NodeIdentity,
|
||||||
) -> Result<(), NymTopologyError> {
|
) -> Result<(), NymTopologyError> {
|
||||||
let topology = self
|
let topology = self
|
||||||
.topology_accessor
|
.topology_accessor
|
||||||
.current_route_provider()
|
.current_topology()
|
||||||
.await
|
.await
|
||||||
.ok_or(NymTopologyError::EmptyNetworkTopology)?;
|
.ok_or(NymTopologyError::EmptyNetworkTopology)?;
|
||||||
|
|
||||||
let _ = topology.egress_by_identity(egress)?;
|
if !topology.gateway_exists(gateway) {
|
||||||
|
return Err(NymTopologyError::NonExistentGatewayError {
|
||||||
|
identity_key: gateway.to_base58_string(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn wait_for_gateway(
|
pub async fn wait_for_gateway(
|
||||||
&mut self,
|
&mut self,
|
||||||
gateway: NodeIdentity,
|
gateway: &NodeIdentity,
|
||||||
timeout_duration: Duration,
|
timeout_duration: Duration,
|
||||||
) -> Result<(), NymTopologyError> {
|
) -> Result<(), NymTopologyError> {
|
||||||
info!(
|
info!(
|
||||||
@@ -132,7 +135,7 @@ impl TopologyRefresher {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
_ = self.try_refresh() => {
|
_ = self.try_refresh() => {
|
||||||
if self.ensure_contains_routable_egress(gateway).await.is_ok() {
|
if self.ensure_contains_gateway(gateway).await.is_ok() {
|
||||||
return Ok(())
|
return Ok(())
|
||||||
}
|
}
|
||||||
info!("gateway '{gateway}' is still not online...");
|
info!("gateway '{gateway}' is still not online...");
|
||||||
|
|||||||
@@ -4,51 +4,47 @@
|
|||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use log::{debug, error, warn};
|
use log::{debug, error, warn};
|
||||||
use nym_topology::provider_trait::TopologyProvider;
|
use nym_topology::provider_trait::TopologyProvider;
|
||||||
use nym_topology::NymTopology;
|
use nym_topology::{NymTopology, NymTopologyError};
|
||||||
use nym_validator_client::UserAgent;
|
use nym_validator_client::UserAgent;
|
||||||
use rand::prelude::SliceRandom;
|
use rand::prelude::SliceRandom;
|
||||||
use rand::thread_rng;
|
use rand::thread_rng;
|
||||||
use std::cmp::min;
|
|
||||||
use url::Url;
|
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;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
pub min_mixnode_performance: u8,
|
pub min_mixnode_performance: u8,
|
||||||
pub min_gateway_performance: u8,
|
pub min_gateway_performance: u8,
|
||||||
pub use_extended_topology: bool,
|
|
||||||
pub ignore_egress_epoch_role: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<nym_client_core_config_types::Topology> for Config {
|
impl Default for Config {
|
||||||
fn from(value: nym_client_core_config_types::Topology) -> Self {
|
fn default() -> Self {
|
||||||
|
// old values that decided on blacklist membership
|
||||||
Config {
|
Config {
|
||||||
min_mixnode_performance: value.minimum_mixnode_performance,
|
min_mixnode_performance: DEFAULT_MIN_MIXNODE_PERFORMANCE,
|
||||||
min_gateway_performance: value.minimum_gateway_performance,
|
min_gateway_performance: DEFAULT_MIN_GATEWAY_PERFORMANCE,
|
||||||
use_extended_topology: value.use_extended_topology,
|
|
||||||
ignore_egress_epoch_role: value.ignore_egress_epoch_role,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Config {
|
|
||||||
// if we're using 'extended' topology, filter the nodes based on the lowest set performance
|
|
||||||
fn min_node_performance(&self) -> u8 {
|
|
||||||
min(self.min_mixnode_performance, self.min_gateway_performance)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct NymApiTopologyProvider {
|
pub struct NymApiTopologyProvider {
|
||||||
config: Config,
|
config: Config,
|
||||||
|
|
||||||
validator_client: nym_validator_client::client::NymApiClient,
|
validator_client: nym_validator_client::client::NymApiClient,
|
||||||
nym_api_urls: Vec<Url>,
|
nym_api_urls: Vec<Url>,
|
||||||
|
|
||||||
|
client_version: String,
|
||||||
currently_used_api: usize,
|
currently_used_api: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NymApiTopologyProvider {
|
impl NymApiTopologyProvider {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
config: impl Into<Config>,
|
config: Config,
|
||||||
mut nym_api_urls: Vec<Url>,
|
mut nym_api_urls: Vec<Url>,
|
||||||
|
client_version: String,
|
||||||
user_agent: Option<UserAgent>,
|
user_agent: Option<UserAgent>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
nym_api_urls.shuffle(&mut thread_rng());
|
nym_api_urls.shuffle(&mut thread_rng());
|
||||||
@@ -63,9 +59,10 @@ impl NymApiTopologyProvider {
|
|||||||
};
|
};
|
||||||
|
|
||||||
NymApiTopologyProvider {
|
NymApiTopologyProvider {
|
||||||
config: config.into(),
|
config,
|
||||||
validator_client,
|
validator_client,
|
||||||
nym_api_urls,
|
nym_api_urls,
|
||||||
|
client_version,
|
||||||
currently_used_api: 0,
|
currently_used_api: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -81,69 +78,70 @@ impl NymApiTopologyProvider {
|
|||||||
.change_nym_api(self.nym_api_urls[self.currently_used_api].clone())
|
.change_nym_api(self.nym_api_urls[self.currently_used_api].clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Verifies whether nodes a reasonably distributed among all mix layers.
|
||||||
|
///
|
||||||
|
/// In ideal world we would have 33% nodes on layer 1, 33% on layer 2 and 33% on layer 3.
|
||||||
|
/// However, this is a rather unrealistic expectation, instead we check whether there exists
|
||||||
|
/// a layer with more than 66% of nodes or with fewer than 15% and if so, we trigger a failure.
|
||||||
|
///
|
||||||
|
/// # Arguments
|
||||||
|
///
|
||||||
|
/// * `topology`: active topology constructed from validator api data
|
||||||
|
fn check_layer_distribution(
|
||||||
|
&self,
|
||||||
|
active_topology: &NymTopology,
|
||||||
|
) -> Result<(), NymTopologyError> {
|
||||||
|
let lower_threshold = 0.15;
|
||||||
|
let upper_threshold = 0.66;
|
||||||
|
active_topology.ensure_even_layer_distribution(lower_threshold, upper_threshold)
|
||||||
|
}
|
||||||
|
|
||||||
async fn get_current_compatible_topology(&mut self) -> Option<NymTopology> {
|
async fn get_current_compatible_topology(&mut self) -> Option<NymTopology> {
|
||||||
let rewarded_set = self
|
let mixnodes = match self
|
||||||
.validator_client
|
.validator_client
|
||||||
.get_current_rewarded_set()
|
.get_all_basic_active_mixing_assigned_nodes(Some(self.client_version.clone()))
|
||||||
.await
|
.await
|
||||||
.inspect_err(|err| error!("failed to get current rewarded set: {err}"))
|
{
|
||||||
.ok()?;
|
Err(err) => {
|
||||||
|
error!("failed to get network mixnodes - {err}");
|
||||||
let mut topology = NymTopology::new_empty(rewarded_set);
|
return None;
|
||||||
|
}
|
||||||
if self.config.use_extended_topology {
|
Ok(mixes) => mixes,
|
||||||
let all_nodes = self
|
|
||||||
.validator_client
|
|
||||||
.get_all_basic_nodes()
|
|
||||||
.await
|
|
||||||
.inspect_err(|err| error!("failed to get network nodes: {err}"))
|
|
||||||
.ok()?;
|
|
||||||
|
|
||||||
debug!(
|
|
||||||
"there are {} nodes on the network (before filtering)",
|
|
||||||
all_nodes.len()
|
|
||||||
);
|
|
||||||
topology.add_additional_nodes(all_nodes.iter().filter(|n| {
|
|
||||||
n.performance.round_to_integer() >= self.config.min_node_performance()
|
|
||||||
}));
|
|
||||||
} else {
|
|
||||||
// if we're not using extended topology, we're only getting active set mixnodes and gateways
|
|
||||||
|
|
||||||
let mixnodes = self
|
|
||||||
.validator_client
|
|
||||||
.get_all_basic_active_mixing_assigned_nodes()
|
|
||||||
.await
|
|
||||||
.inspect_err(|err| error!("failed to get network mixnodes: {err}"))
|
|
||||||
.ok()?;
|
|
||||||
|
|
||||||
// TODO: we really should be getting ACTIVE gateways only
|
|
||||||
let gateways = self
|
|
||||||
.validator_client
|
|
||||||
.get_all_basic_entry_assigned_nodes()
|
|
||||||
.await
|
|
||||||
.inspect_err(|err| error!("failed to get network gateways: {err}"))
|
|
||||||
.ok()?;
|
|
||||||
|
|
||||||
debug!(
|
|
||||||
"there are {} mixnodes and {} gateways in total (before performance filtering)",
|
|
||||||
mixnodes.len(),
|
|
||||||
gateways.len()
|
|
||||||
);
|
|
||||||
|
|
||||||
topology.add_additional_nodes(mixnodes.iter().filter(|m| {
|
|
||||||
m.performance.round_to_integer() >= self.config.min_mixnode_performance
|
|
||||||
}));
|
|
||||||
topology.add_additional_nodes(gateways.iter().filter(|m| {
|
|
||||||
m.performance.round_to_integer() >= self.config.min_gateway_performance
|
|
||||||
}));
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if !topology.is_minimally_routable() {
|
let gateways = match self
|
||||||
error!("the current filtered active topology can't be used to construct any packets");
|
.validator_client
|
||||||
return None;
|
.get_all_basic_entry_assigned_nodes(Some(self.client_version.clone()))
|
||||||
}
|
.await
|
||||||
|
{
|
||||||
|
Err(err) => {
|
||||||
|
error!("failed to get network gateways - {err}");
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
Ok(gateways) => gateways,
|
||||||
|
};
|
||||||
|
|
||||||
Some(topology)
|
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
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
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}");
|
||||||
|
self.use_next_nym_api();
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(topology)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -152,11 +150,7 @@ impl NymApiTopologyProvider {
|
|||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl TopologyProvider for NymApiTopologyProvider {
|
impl TopologyProvider for NymApiTopologyProvider {
|
||||||
async fn get_new_topology(&mut self) -> Option<NymTopology> {
|
async fn get_new_topology(&mut self) -> Option<NymTopology> {
|
||||||
let Some(topology) = self.get_current_compatible_topology().await else {
|
self.get_current_compatible_topology().await
|
||||||
self.use_next_nym_api();
|
|
||||||
return None;
|
|
||||||
};
|
|
||||||
Some(topology)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,10 +158,6 @@ impl TopologyProvider for NymApiTopologyProvider {
|
|||||||
#[async_trait(?Send)]
|
#[async_trait(?Send)]
|
||||||
impl TopologyProvider for NymApiTopologyProvider {
|
impl TopologyProvider for NymApiTopologyProvider {
|
||||||
async fn get_new_topology(&mut self) -> Option<NymTopology> {
|
async fn get_new_topology(&mut self) -> Option<NymTopology> {
|
||||||
let Some(topology) = self.get_current_compatible_topology().await else {
|
self.get_current_compatible_topology().await
|
||||||
self.use_next_nym_api();
|
|
||||||
return None;
|
|
||||||
};
|
|
||||||
Some(topology)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,8 +4,8 @@
|
|||||||
use crate::client::mix_traffic::transceiver::ErasedGatewayError;
|
use crate::client::mix_traffic::transceiver::ErasedGatewayError;
|
||||||
use nym_crypto::asymmetric::identity::Ed25519RecoveryError;
|
use nym_crypto::asymmetric::identity::Ed25519RecoveryError;
|
||||||
use nym_gateway_client::error::GatewayClientError;
|
use nym_gateway_client::error::GatewayClientError;
|
||||||
use nym_topology::node::RoutingNodeError;
|
use nym_topology::gateway::GatewayConversionError;
|
||||||
use nym_topology::{NodeId, NymTopologyError};
|
use nym_topology::NymTopologyError;
|
||||||
use nym_validator_client::ValidatorClientError;
|
use nym_validator_client::ValidatorClientError;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
@@ -74,10 +74,10 @@ pub enum ClientCoreError {
|
|||||||
#[error("the gateway id is invalid - {0}")]
|
#[error("the gateway id is invalid - {0}")]
|
||||||
UnableToCreatePublicKeyFromGatewayId(Ed25519RecoveryError),
|
UnableToCreatePublicKeyFromGatewayId(Ed25519RecoveryError),
|
||||||
|
|
||||||
#[error("the node is malformed: {source}")]
|
#[error("The gateway is malformed: {source}")]
|
||||||
MalformedGateway {
|
MalformedGateway {
|
||||||
#[from]
|
#[from]
|
||||||
source: Box<RoutingNodeError>,
|
source: GatewayConversionError,
|
||||||
},
|
},
|
||||||
|
|
||||||
#[error("failed to establish connection to gateway: {source}")]
|
#[error("failed to establish connection to gateway: {source}")]
|
||||||
@@ -159,9 +159,6 @@ pub enum ClientCoreError {
|
|||||||
#[error("the specified gateway '{gateway}' does not support the wss protocol")]
|
#[error("the specified gateway '{gateway}' does not support the wss protocol")]
|
||||||
UnsupportedWssProtocol { gateway: String },
|
UnsupportedWssProtocol { gateway: String },
|
||||||
|
|
||||||
#[error("node {id} ({identity}) does not support mixnet entry mode")]
|
|
||||||
UnsupportedEntry { id: NodeId, identity: String },
|
|
||||||
|
|
||||||
#[error(
|
#[error(
|
||||||
"failed to load custom topology using path '{}'. detailed message: {source}", file_path.display()
|
"failed to load custom topology using path '{}'. detailed message: {source}", file_path.display()
|
||||||
)]
|
)]
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ use futures::{SinkExt, StreamExt};
|
|||||||
use log::{debug, info, trace, warn};
|
use log::{debug, info, trace, warn};
|
||||||
use nym_crypto::asymmetric::identity;
|
use nym_crypto::asymmetric::identity;
|
||||||
use nym_gateway_client::GatewayClient;
|
use nym_gateway_client::GatewayClient;
|
||||||
use nym_topology::node::RoutingNode;
|
use nym_topology::{gateway, mix};
|
||||||
use nym_validator_client::client::IdentityKeyRef;
|
use nym_validator_client::client::IdentityKeyRef;
|
||||||
use nym_validator_client::UserAgent;
|
use nym_validator_client::UserAgent;
|
||||||
use rand::{seq::SliceRandom, Rng};
|
use rand::{seq::SliceRandom, Rng};
|
||||||
@@ -15,7 +15,6 @@ use std::{sync::Arc, time::Duration};
|
|||||||
use tungstenite::Message;
|
use tungstenite::Message;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
use nym_topology::NodeId;
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
use tokio::net::TcpStream;
|
use tokio::net::TcpStream;
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
@@ -26,6 +25,7 @@ use tokio::time::Instant;
|
|||||||
use tokio_tungstenite::connect_async;
|
use tokio_tungstenite::connect_async;
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
use tokio_tungstenite::{MaybeTlsStream, WebSocketStream};
|
use tokio_tungstenite::{MaybeTlsStream, WebSocketStream};
|
||||||
|
|
||||||
#[cfg(target_arch = "wasm32")]
|
#[cfg(target_arch = "wasm32")]
|
||||||
use wasm_utils::websocket::JSWebsocket;
|
use wasm_utils::websocket::JSWebsocket;
|
||||||
#[cfg(target_arch = "wasm32")]
|
#[cfg(target_arch = "wasm32")]
|
||||||
@@ -48,30 +48,22 @@ const PING_TIMEOUT: Duration = Duration::from_millis(1000);
|
|||||||
|
|
||||||
// The abstraction that some of these helpers use
|
// The abstraction that some of these helpers use
|
||||||
pub trait ConnectableGateway {
|
pub trait ConnectableGateway {
|
||||||
fn node_id(&self) -> NodeId;
|
fn identity(&self) -> &identity::PublicKey;
|
||||||
fn identity(&self) -> identity::PublicKey;
|
fn clients_address(&self) -> String;
|
||||||
fn clients_address(&self, prefer_ipv6: bool) -> Option<String>;
|
|
||||||
fn is_wss(&self) -> bool;
|
fn is_wss(&self) -> bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ConnectableGateway for RoutingNode {
|
impl ConnectableGateway for gateway::LegacyNode {
|
||||||
fn node_id(&self) -> NodeId {
|
fn identity(&self) -> &identity::PublicKey {
|
||||||
self.node_id
|
self.identity()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn identity(&self) -> identity::PublicKey {
|
fn clients_address(&self) -> String {
|
||||||
self.identity_key
|
self.clients_address()
|
||||||
}
|
|
||||||
|
|
||||||
fn clients_address(&self, prefer_ipv6: bool) -> Option<String> {
|
|
||||||
self.ws_entry_address(prefer_ipv6)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_wss(&self) -> bool {
|
fn is_wss(&self) -> bool {
|
||||||
self.entry
|
self.clients_wss_port.is_some()
|
||||||
.as_ref()
|
|
||||||
.map(|e| e.clients_wss_port.is_some())
|
|
||||||
.unwrap_or_default()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,8 +82,7 @@ pub async fn current_gateways<R: Rng>(
|
|||||||
rng: &mut R,
|
rng: &mut R,
|
||||||
nym_apis: &[Url],
|
nym_apis: &[Url],
|
||||||
user_agent: Option<UserAgent>,
|
user_agent: Option<UserAgent>,
|
||||||
minimum_performance: u8,
|
) -> Result<Vec<gateway::LegacyNode>, ClientCoreError> {
|
||||||
) -> Result<Vec<RoutingNode>, ClientCoreError> {
|
|
||||||
let nym_api = nym_apis
|
let nym_api = nym_apis
|
||||||
.choose(rng)
|
.choose(rng)
|
||||||
.ok_or(ClientCoreError::ListOfNymApisIsEmpty)?;
|
.ok_or(ClientCoreError::ListOfNymApisIsEmpty)?;
|
||||||
@@ -103,27 +94,44 @@ pub async fn current_gateways<R: Rng>(
|
|||||||
|
|
||||||
log::debug!("Fetching list of gateways from: {nym_api}");
|
log::debug!("Fetching list of gateways from: {nym_api}");
|
||||||
|
|
||||||
let gateways = client.get_all_basic_entry_assigned_nodes().await?;
|
let gateways = client.get_all_basic_entry_assigned_nodes(None).await?;
|
||||||
info!("nym api reports {} gateways", gateways.len());
|
log::debug!("Found {} gateways", gateways.len());
|
||||||
|
|
||||||
log::trace!("Gateways: {:#?}", gateways);
|
log::trace!("Gateways: {:#?}", gateways);
|
||||||
|
|
||||||
let valid_gateways = gateways
|
let valid_gateways = gateways
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|g| g.performance.round_to_integer() >= minimum_performance)
|
|
||||||
.filter_map(|gateway| gateway.try_into().ok())
|
.filter_map(|gateway| gateway.try_into().ok())
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<gateway::LegacyNode>>();
|
||||||
log::debug!("After checking validity: {}", valid_gateways.len());
|
log::debug!("After checking validity: {}", valid_gateways.len());
|
||||||
log::trace!("Valid gateways: {:#?}", valid_gateways);
|
log::trace!("Valid gateways: {:#?}", valid_gateways);
|
||||||
|
|
||||||
log::info!(
|
log::info!("nym-api reports {} valid gateways", valid_gateways.len());
|
||||||
"and {} after validity and performance filtering",
|
|
||||||
valid_gateways.len()
|
|
||||||
);
|
|
||||||
|
|
||||||
Ok(valid_gateways)
|
Ok(valid_gateways)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn current_mixnodes<R: Rng>(
|
||||||
|
rng: &mut R,
|
||||||
|
nym_apis: &[Url],
|
||||||
|
) -> Result<Vec<mix::LegacyNode>, ClientCoreError> {
|
||||||
|
let nym_api = nym_apis
|
||||||
|
.choose(rng)
|
||||||
|
.ok_or(ClientCoreError::ListOfNymApisIsEmpty)?;
|
||||||
|
let client = nym_validator_client::client::NymApiClient::new(nym_api.clone());
|
||||||
|
|
||||||
|
log::trace!("Fetching list of mixnodes from: {nym_api}");
|
||||||
|
|
||||||
|
let mixnodes = client
|
||||||
|
.get_all_basic_active_mixing_assigned_nodes(None)
|
||||||
|
.await?;
|
||||||
|
let valid_mixnodes = mixnodes
|
||||||
|
.iter()
|
||||||
|
.filter_map(|mixnode| mixnode.try_into().ok())
|
||||||
|
.collect::<Vec<mix::LegacyNode>>();
|
||||||
|
|
||||||
|
Ok(valid_mixnodes)
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
async fn connect(endpoint: &str) -> Result<WsConn, ClientCoreError> {
|
async fn connect(endpoint: &str) -> Result<WsConn, ClientCoreError> {
|
||||||
match tokio::time::timeout(CONN_TIMEOUT, connect_async(endpoint)).await {
|
match tokio::time::timeout(CONN_TIMEOUT, connect_async(endpoint)).await {
|
||||||
@@ -142,12 +150,7 @@ async fn measure_latency<G>(gateway: &G) -> Result<GatewayWithLatency<G>, Client
|
|||||||
where
|
where
|
||||||
G: ConnectableGateway,
|
G: ConnectableGateway,
|
||||||
{
|
{
|
||||||
let Some(addr) = gateway.clients_address(false) else {
|
let addr = gateway.clients_address();
|
||||||
return Err(ClientCoreError::UnsupportedEntry {
|
|
||||||
id: gateway.node_id(),
|
|
||||||
identity: gateway.identity().to_string(),
|
|
||||||
});
|
|
||||||
};
|
|
||||||
trace!(
|
trace!(
|
||||||
"establishing connection to {} ({addr})...",
|
"establishing connection to {} ({addr})...",
|
||||||
gateway.identity(),
|
gateway.identity(),
|
||||||
@@ -203,7 +206,7 @@ where
|
|||||||
Ok(GatewayWithLatency::new(gateway, avg))
|
Ok(GatewayWithLatency::new(gateway, avg))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn choose_gateway_by_latency<R: Rng, G: ConnectableGateway + Clone>(
|
pub async fn choose_gateway_by_latency<'a, R: Rng, G: ConnectableGateway + Clone>(
|
||||||
rng: &mut R,
|
rng: &mut R,
|
||||||
gateways: &[G],
|
gateways: &[G],
|
||||||
must_use_tls: bool,
|
must_use_tls: bool,
|
||||||
@@ -218,7 +221,7 @@ pub async fn choose_gateway_by_latency<R: Rng, G: ConnectableGateway + Clone>(
|
|||||||
let gateways_with_latency = Arc::new(tokio::sync::Mutex::new(Vec::new()));
|
let gateways_with_latency = Arc::new(tokio::sync::Mutex::new(Vec::new()));
|
||||||
futures::stream::iter(gateways)
|
futures::stream::iter(gateways)
|
||||||
.for_each_concurrent(CONCURRENT_GATEWAYS_MEASURED, |gateway| async {
|
.for_each_concurrent(CONCURRENT_GATEWAYS_MEASURED, |gateway| async {
|
||||||
let id = gateway.identity();
|
let id = *gateway.identity();
|
||||||
trace!("measuring latency to {id}...");
|
trace!("measuring latency to {id}...");
|
||||||
match measure_latency(gateway).await {
|
match measure_latency(gateway).await {
|
||||||
Ok(with_latency) => {
|
Ok(with_latency) => {
|
||||||
@@ -265,9 +268,9 @@ fn filter_by_tls<G: ConnectableGateway>(
|
|||||||
|
|
||||||
pub(super) fn uniformly_random_gateway<R: Rng>(
|
pub(super) fn uniformly_random_gateway<R: Rng>(
|
||||||
rng: &mut R,
|
rng: &mut R,
|
||||||
gateways: &[RoutingNode],
|
gateways: &[gateway::LegacyNode],
|
||||||
must_use_tls: bool,
|
must_use_tls: bool,
|
||||||
) -> Result<RoutingNode, ClientCoreError> {
|
) -> Result<gateway::LegacyNode, ClientCoreError> {
|
||||||
filter_by_tls(gateways, must_use_tls)?
|
filter_by_tls(gateways, must_use_tls)?
|
||||||
.choose(rng)
|
.choose(rng)
|
||||||
.ok_or(ClientCoreError::NoGatewaysOnNetwork)
|
.ok_or(ClientCoreError::NoGatewaysOnNetwork)
|
||||||
@@ -276,9 +279,9 @@ pub(super) fn uniformly_random_gateway<R: Rng>(
|
|||||||
|
|
||||||
pub(super) fn get_specified_gateway(
|
pub(super) fn get_specified_gateway(
|
||||||
gateway_identity: IdentityKeyRef,
|
gateway_identity: IdentityKeyRef,
|
||||||
gateways: &[RoutingNode],
|
gateways: &[gateway::LegacyNode],
|
||||||
must_use_tls: bool,
|
must_use_tls: bool,
|
||||||
) -> Result<RoutingNode, ClientCoreError> {
|
) -> Result<gateway::LegacyNode, ClientCoreError> {
|
||||||
log::debug!("Requesting specified gateway: {}", gateway_identity);
|
log::debug!("Requesting specified gateway: {}", gateway_identity);
|
||||||
let user_gateway = identity::PublicKey::from_base58_string(gateway_identity)
|
let user_gateway = identity::PublicKey::from_base58_string(gateway_identity)
|
||||||
.map_err(ClientCoreError::UnableToCreatePublicKeyFromGatewayId)?;
|
.map_err(ClientCoreError::UnableToCreatePublicKeyFromGatewayId)?;
|
||||||
@@ -288,14 +291,7 @@ pub(super) fn get_specified_gateway(
|
|||||||
.find(|gateway| gateway.identity_key == user_gateway)
|
.find(|gateway| gateway.identity_key == user_gateway)
|
||||||
.ok_or_else(|| ClientCoreError::NoGatewayWithId(gateway_identity.to_string()))?;
|
.ok_or_else(|| ClientCoreError::NoGatewayWithId(gateway_identity.to_string()))?;
|
||||||
|
|
||||||
let Some(entry_details) = gateway.entry.as_ref() else {
|
if must_use_tls && gateway.clients_wss_port.is_none() {
|
||||||
return Err(ClientCoreError::UnsupportedEntry {
|
|
||||||
id: gateway.node_id,
|
|
||||||
identity: gateway.identity().to_string(),
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
if must_use_tls && entry_details.clients_wss_port.is_none() {
|
|
||||||
return Err(ClientCoreError::UnsupportedWssProtocol {
|
return Err(ClientCoreError::UnsupportedWssProtocol {
|
||||||
gateway: gateway_identity.to_string(),
|
gateway: gateway_identity.to_string(),
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ use crate::init::types::{
|
|||||||
use nym_client_core_gateways_storage::GatewaysDetailsStore;
|
use nym_client_core_gateways_storage::GatewaysDetailsStore;
|
||||||
use nym_client_core_gateways_storage::{GatewayDetails, GatewayRegistration};
|
use nym_client_core_gateways_storage::{GatewayDetails, GatewayRegistration};
|
||||||
use nym_gateway_client::client::InitGatewayClient;
|
use nym_gateway_client::client::InitGatewayClient;
|
||||||
use nym_topology::node::RoutingNode;
|
use nym_topology::gateway;
|
||||||
use rand::rngs::OsRng;
|
use rand::rngs::OsRng;
|
||||||
use rand::{CryptoRng, RngCore};
|
use rand::{CryptoRng, RngCore};
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
@@ -50,7 +50,7 @@ async fn setup_new_gateway<K, D>(
|
|||||||
key_store: &K,
|
key_store: &K,
|
||||||
details_store: &D,
|
details_store: &D,
|
||||||
selection_specification: GatewaySelectionSpecification,
|
selection_specification: GatewaySelectionSpecification,
|
||||||
available_gateways: Vec<RoutingNode>,
|
available_gateways: Vec<gateway::LegacyNode>,
|
||||||
) -> Result<InitialisationResult, ClientCoreError>
|
) -> Result<InitialisationResult, ClientCoreError>
|
||||||
where
|
where
|
||||||
K: KeyStore,
|
K: KeyStore,
|
||||||
|
|||||||
@@ -13,11 +13,11 @@ use nym_crypto::asymmetric::identity;
|
|||||||
use nym_gateway_client::client::InitGatewayClient;
|
use nym_gateway_client::client::InitGatewayClient;
|
||||||
use nym_gateway_requests::shared_key::SharedGatewayKey;
|
use nym_gateway_requests::shared_key::SharedGatewayKey;
|
||||||
use nym_sphinx::addressing::clients::Recipient;
|
use nym_sphinx::addressing::clients::Recipient;
|
||||||
use nym_topology::node::RoutingNode;
|
use nym_topology::gateway;
|
||||||
use nym_validator_client::client::IdentityKey;
|
use nym_validator_client::client::IdentityKey;
|
||||||
use nym_validator_client::nyxd::AccountId;
|
use nym_validator_client::nyxd::AccountId;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use std::fmt::{Debug, Display};
|
use std::fmt::Display;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use time::OffsetDateTime;
|
use time::OffsetDateTime;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
@@ -38,23 +38,16 @@ pub enum SelectedGateway {
|
|||||||
|
|
||||||
impl SelectedGateway {
|
impl SelectedGateway {
|
||||||
pub fn from_topology_node(
|
pub fn from_topology_node(
|
||||||
node: RoutingNode,
|
node: gateway::LegacyNode,
|
||||||
must_use_tls: bool,
|
must_use_tls: bool,
|
||||||
) -> Result<Self, ClientCoreError> {
|
) -> Result<Self, ClientCoreError> {
|
||||||
// for now, let's use 'old' behaviour, if you want to change it, you can pass it up the enum stack yourself : )
|
|
||||||
let prefer_ipv6 = false;
|
|
||||||
|
|
||||||
let gateway_listener = if must_use_tls {
|
let gateway_listener = if must_use_tls {
|
||||||
node.ws_entry_address_tls()
|
node.clients_address_tls()
|
||||||
.ok_or(ClientCoreError::UnsupportedWssProtocol {
|
.ok_or(ClientCoreError::UnsupportedWssProtocol {
|
||||||
gateway: node.identity_key.to_base58_string(),
|
gateway: node.identity_key.to_base58_string(),
|
||||||
})?
|
})?
|
||||||
} else {
|
} else {
|
||||||
node.ws_entry_address(prefer_ipv6)
|
node.clients_address()
|
||||||
.ok_or(ClientCoreError::UnsupportedEntry {
|
|
||||||
id: node.node_id,
|
|
||||||
identity: node.identity_key.to_base58_string(),
|
|
||||||
})?
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let gateway_listener =
|
let gateway_listener =
|
||||||
@@ -207,7 +200,7 @@ pub enum GatewaySetup {
|
|||||||
specification: GatewaySelectionSpecification,
|
specification: GatewaySelectionSpecification,
|
||||||
|
|
||||||
// TODO: seems to be a bit inefficient to pass them by value
|
// TODO: seems to be a bit inefficient to pass them by value
|
||||||
available_gateways: Vec<RoutingNode>,
|
available_gateways: Vec<gateway::LegacyNode>,
|
||||||
},
|
},
|
||||||
|
|
||||||
ReuseConnection {
|
ReuseConnection {
|
||||||
@@ -221,34 +214,6 @@ pub enum GatewaySetup {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Debug for GatewaySetup {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
||||||
match self {
|
|
||||||
GatewaySetup::MustLoad { gateway_id } => f
|
|
||||||
.debug_struct("GatewaySetup::MustLoad")
|
|
||||||
.field("gateway_id", gateway_id)
|
|
||||||
.finish(),
|
|
||||||
GatewaySetup::New {
|
|
||||||
specification,
|
|
||||||
available_gateways,
|
|
||||||
} => f
|
|
||||||
.debug_struct("GatewaySetup::New")
|
|
||||||
.field("specification", specification)
|
|
||||||
.field("available_gateways", available_gateways)
|
|
||||||
.field("gateways", specification)
|
|
||||||
.finish(),
|
|
||||||
GatewaySetup::ReuseConnection {
|
|
||||||
gateway_details, ..
|
|
||||||
} => f
|
|
||||||
.debug_struct("GatewaySetup::ReuseConnection")
|
|
||||||
.field("authenticated_ephemeral_client", &"***")
|
|
||||||
.field("gateway_details", gateway_details)
|
|
||||||
.field("client_keys", &"***")
|
|
||||||
.finish(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GatewaySetup {
|
impl GatewaySetup {
|
||||||
pub fn try_reuse_connection(init_res: InitialisationResult) -> Result<Self, ClientCoreError> {
|
pub fn try_reuse_connection(init_res: InitialisationResult) -> Result<Self, ClientCoreError> {
|
||||||
if let Some(authenticated_ephemeral_client) = init_res.authenticated_ephemeral_client {
|
if let Some(authenticated_ephemeral_client) = init_res.authenticated_ephemeral_client {
|
||||||
|
|||||||
@@ -14,7 +14,8 @@ pub mod error;
|
|||||||
pub mod init;
|
pub mod init;
|
||||||
|
|
||||||
pub use nym_topology::{
|
pub use nym_topology::{
|
||||||
HardcodedTopologyProvider, NymRouteProvider, NymTopology, NymTopologyError, TopologyProvider,
|
HardcodedTopologyProvider, NymTopology, NymTopologyError, SerializableNymTopology,
|
||||||
|
SerializableTopologyError, TopologyProvider,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(target_arch = "wasm32")]
|
#[cfg(target_arch = "wasm32")]
|
||||||
@@ -33,48 +34,3 @@ where
|
|||||||
{
|
{
|
||||||
tokio::spawn(future);
|
tokio::spawn(future);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Default, Debug)]
|
|
||||||
pub struct ForgetMe {
|
|
||||||
client: bool,
|
|
||||||
stats: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ForgetMe {
|
|
||||||
pub fn new_all() -> Self {
|
|
||||||
Self {
|
|
||||||
client: true,
|
|
||||||
stats: true,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new_client() -> Self {
|
|
||||||
Self {
|
|
||||||
client: true,
|
|
||||||
stats: false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new_stats() -> Self {
|
|
||||||
Self {
|
|
||||||
client: false,
|
|
||||||
stats: true,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new(client: bool, stats: bool) -> Self {
|
|
||||||
Self { client, stats }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn any(&self) -> bool {
|
|
||||||
self.client || self.stats
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn client(&self) -> bool {
|
|
||||||
self.client
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn stats(&self) -> bool {
|
|
||||||
self.stats
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -9,10 +9,7 @@ use crate::backend::fs_backend::{
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
use log::{error, info};
|
use log::{error, info};
|
||||||
use sqlx::{
|
use sqlx::ConnectOptions;
|
||||||
sqlite::{SqliteAutoVacuum, SqliteSynchronous},
|
|
||||||
ConnectOptions,
|
|
||||||
};
|
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
@@ -34,9 +31,6 @@ impl StorageManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let opts = sqlx::sqlite::SqliteConnectOptions::new()
|
let opts = sqlx::sqlite::SqliteConnectOptions::new()
|
||||||
.journal_mode(sqlx::sqlite::SqliteJournalMode::Wal)
|
|
||||||
.synchronous(SqliteSynchronous::Normal)
|
|
||||||
.auto_vacuum(SqliteAutoVacuum::Incremental)
|
|
||||||
.filename(database_path)
|
.filename(database_path)
|
||||||
.create_if_missing(fresh)
|
.create_if_missing(fresh)
|
||||||
.disable_statement_logging();
|
.disable_statement_logging();
|
||||||
|
|||||||
@@ -87,10 +87,8 @@ impl ClientBandwidth {
|
|||||||
|
|
||||||
if remaining < 0 {
|
if remaining < 0 {
|
||||||
tracing::warn!("OUT OF BANDWIDTH. remaining: {remaining_bi2}");
|
tracing::warn!("OUT OF BANDWIDTH. remaining: {remaining_bi2}");
|
||||||
} else if remaining < 1_000_000 {
|
|
||||||
tracing::info!("remaining bandwidth: {remaining_bi2}");
|
|
||||||
} else {
|
} else {
|
||||||
tracing::debug!("remaining bandwidth: {remaining_bi2}");
|
tracing::info!("remaining bandwidth: {remaining_bi2}");
|
||||||
}
|
}
|
||||||
|
|
||||||
self.inner
|
self.inner
|
||||||
|
|||||||
@@ -101,10 +101,6 @@ pub struct GatewayClient<C, St = EphemeralCredentialStorage> {
|
|||||||
// currently unused (but populated)
|
// currently unused (but populated)
|
||||||
negotiated_protocol: Option<u8>,
|
negotiated_protocol: Option<u8>,
|
||||||
|
|
||||||
// Callback on the fd as soon as the connection has been established
|
|
||||||
#[cfg(unix)]
|
|
||||||
connection_fd_callback: Option<Arc<dyn Fn(RawFd) + Send + Sync>>,
|
|
||||||
|
|
||||||
/// Listen to shutdown messages and send notifications back to the task manager
|
/// Listen to shutdown messages and send notifications back to the task manager
|
||||||
task_client: TaskClient,
|
task_client: TaskClient,
|
||||||
}
|
}
|
||||||
@@ -120,7 +116,6 @@ impl<C, St> GatewayClient<C, St> {
|
|||||||
packet_router: PacketRouter,
|
packet_router: PacketRouter,
|
||||||
bandwidth_controller: Option<BandwidthController<C, St>>,
|
bandwidth_controller: Option<BandwidthController<C, St>>,
|
||||||
stats_reporter: ClientStatsSender,
|
stats_reporter: ClientStatsSender,
|
||||||
#[cfg(unix)] connection_fd_callback: Option<Arc<dyn Fn(RawFd) + Send + Sync>>,
|
|
||||||
task_client: TaskClient,
|
task_client: TaskClient,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
GatewayClient {
|
GatewayClient {
|
||||||
@@ -136,8 +131,6 @@ impl<C, St> GatewayClient<C, St> {
|
|||||||
bandwidth_controller,
|
bandwidth_controller,
|
||||||
stats_reporter,
|
stats_reporter,
|
||||||
negotiated_protocol: None,
|
negotiated_protocol: None,
|
||||||
#[cfg(unix)]
|
|
||||||
connection_fd_callback,
|
|
||||||
task_client,
|
task_client,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -146,10 +139,6 @@ impl<C, St> GatewayClient<C, St> {
|
|||||||
self.gateway_identity
|
self.gateway_identity
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn shared_key(&self) -> Option<Arc<SharedGatewayKey>> {
|
|
||||||
self.shared_key.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn ws_fd(&self) -> Option<RawFd> {
|
pub fn ws_fd(&self) -> Option<RawFd> {
|
||||||
match &self.connection {
|
match &self.connection {
|
||||||
SocketState::Available(conn) => ws_fd(conn.as_ref()),
|
SocketState::Available(conn) => ws_fd(conn.as_ref()),
|
||||||
@@ -212,12 +201,6 @@ impl<C, St> GatewayClient<C, St> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
self.connection = SocketState::Available(Box::new(ws_stream));
|
self.connection = SocketState::Available(Box::new(ws_stream));
|
||||||
|
|
||||||
#[cfg(unix)]
|
|
||||||
if let (Some(callback), Some(fd)) = (self.connection_fd_callback.as_ref(), self.ws_fd()) {
|
|
||||||
callback.as_ref()(fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -324,7 +307,7 @@ impl<C, St> GatewayClient<C, St> {
|
|||||||
|
|
||||||
// If we want to send a message (with response), we need to have a full control over the socket,
|
// If we want to send a message (with response), we need to have a full control over the socket,
|
||||||
// as we need to be able to write the request and read the subsequent response
|
// as we need to be able to write the request and read the subsequent response
|
||||||
pub async fn send_websocket_message(
|
async fn send_websocket_message(
|
||||||
&mut self,
|
&mut self,
|
||||||
msg: impl Into<Message>,
|
msg: impl Into<Message>,
|
||||||
) -> Result<ServerResponse, GatewayClientError> {
|
) -> Result<ServerResponse, GatewayClientError> {
|
||||||
@@ -425,7 +408,7 @@ impl<C, St> GatewayClient<C, St> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Some(_) => {
|
Some(_) => {
|
||||||
debug!("the gateway is using exactly the same (or older) protocol version as we are. We're good to continue!");
|
info!("the gateway is using exactly the same (or older) protocol version as we are. We're good to continue!");
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1009,6 +992,24 @@ impl<C, St> GatewayClient<C, St> {
|
|||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[deprecated(note = "this method does not deal with upgraded keys for legacy clients")]
|
||||||
|
pub async fn authenticate_and_start(
|
||||||
|
&mut self,
|
||||||
|
) -> Result<AuthenticationResponse, GatewayClientError>
|
||||||
|
where
|
||||||
|
C: DkgQueryClient + Send + Sync,
|
||||||
|
St: CredentialStorage,
|
||||||
|
<St as CredentialStorage>::StorageError: Send + Sync + 'static,
|
||||||
|
{
|
||||||
|
let shared_key = self.perform_initial_authentication().await?;
|
||||||
|
self.claim_initial_bandwidth().await?;
|
||||||
|
|
||||||
|
// this call is NON-blocking
|
||||||
|
self.start_listening_for_mixnet_messages()?;
|
||||||
|
|
||||||
|
Ok(shared_key)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// type alias for an ease of use
|
// type alias for an ease of use
|
||||||
@@ -1047,8 +1048,6 @@ impl GatewayClient<InitOnly, EphemeralCredentialStorage> {
|
|||||||
bandwidth_controller: None,
|
bandwidth_controller: None,
|
||||||
stats_reporter: ClientStatsSender::new(None),
|
stats_reporter: ClientStatsSender::new(None),
|
||||||
negotiated_protocol: None,
|
negotiated_protocol: None,
|
||||||
#[cfg(unix)]
|
|
||||||
connection_fd_callback: None,
|
|
||||||
task_client,
|
task_client,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1079,8 +1078,6 @@ impl GatewayClient<InitOnly, EphemeralCredentialStorage> {
|
|||||||
bandwidth_controller,
|
bandwidth_controller,
|
||||||
stats_reporter,
|
stats_reporter,
|
||||||
negotiated_protocol: self.negotiated_protocol,
|
negotiated_protocol: self.negotiated_protocol,
|
||||||
#[cfg(unix)]
|
|
||||||
connection_fd_callback: self.connection_fd_callback,
|
|
||||||
task_client,
|
task_client,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,8 +46,7 @@ pub(crate) fn ws_fd(_conn: &WsConn) -> Option<RawFd> {
|
|||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
match _conn.get_ref() {
|
match _conn.get_ref() {
|
||||||
MaybeTlsStream::Plain(stream) => Some(stream.as_raw_fd()),
|
MaybeTlsStream::Plain(stream) => Some(stream.as_raw_fd()),
|
||||||
MaybeTlsStream::Rustls(tls_stream) => Some(tls_stream.as_raw_fd()),
|
&_ => None,
|
||||||
_ => None,
|
|
||||||
}
|
}
|
||||||
#[cfg(not(unix))]
|
#[cfg(not(unix))]
|
||||||
None
|
None
|
||||||
@@ -111,11 +110,6 @@ impl PartiallyDelegatedRouter {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if self.stream_return.is_canceled() {
|
|
||||||
// nothing to do, receiver has been dropped
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let return_res = match ret {
|
let return_res = match ret {
|
||||||
Err(err) => self.stream_return.send(Err(err)),
|
Err(err) => self.stream_return.send(Err(err)),
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
|
|||||||
@@ -8,17 +8,11 @@ license.workspace = true
|
|||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
dashmap = { workspace = true }
|
|
||||||
futures = { workspace = true }
|
futures = { workspace = true }
|
||||||
tracing = { workspace = true }
|
log = { workspace = true }
|
||||||
tokio = { workspace = true, features = ["time", "sync"] }
|
tokio = { workspace = true, features = ["time", "net", "rt"] }
|
||||||
tokio-util = { workspace = true, features = ["codec"], optional = true }
|
tokio-util = { workspace = true, features = ["codec"] }
|
||||||
tokio-stream = { workspace = true }
|
|
||||||
|
|
||||||
# internal
|
# internal
|
||||||
nym-sphinx = { path = "../../nymsphinx" }
|
nym-sphinx = { path = "../../nymsphinx" }
|
||||||
nym-task = { path = "../../task", optional = true }
|
nym-task = { path = "../../task" }
|
||||||
|
|
||||||
[features]
|
|
||||||
default = ["client"]
|
|
||||||
client = ["tokio-util", "nym-task", "tokio/net", "tokio/rt"]
|
|
||||||
|
|||||||
@@ -1,33 +1,30 @@
|
|||||||
// Copyright 2021-2024 - Nym Technologies SA <contact@nymtech.net>
|
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
use dashmap::DashMap;
|
use futures::channel::mpsc;
|
||||||
use futures::StreamExt;
|
use futures::StreamExt;
|
||||||
|
use log::*;
|
||||||
use nym_sphinx::addressing::nodes::NymNodeRoutingAddress;
|
use nym_sphinx::addressing::nodes::NymNodeRoutingAddress;
|
||||||
use nym_sphinx::framing::codec::NymCodec;
|
use nym_sphinx::framing::codec::NymCodec;
|
||||||
use nym_sphinx::framing::packet::FramedNymPacket;
|
use nym_sphinx::framing::packet::FramedNymPacket;
|
||||||
use nym_sphinx::params::PacketType;
|
use nym_sphinx::params::PacketType;
|
||||||
use nym_sphinx::NymPacket;
|
use nym_sphinx::NymPacket;
|
||||||
|
use std::collections::HashMap;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
use std::ops::Deref;
|
use std::sync::atomic::{AtomicU32, Ordering};
|
||||||
use std::sync::atomic::{AtomicU32, AtomicUsize, Ordering};
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use tokio::net::TcpStream;
|
use tokio::net::TcpStream;
|
||||||
use tokio::sync::mpsc;
|
|
||||||
use tokio::sync::mpsc::error::TrySendError;
|
|
||||||
use tokio::time::sleep;
|
use tokio::time::sleep;
|
||||||
use tokio_stream::wrappers::ReceiverStream;
|
|
||||||
use tokio_util::codec::Framed;
|
use tokio_util::codec::Framed;
|
||||||
use tracing::*;
|
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
initial_reconnection_backoff: Duration,
|
initial_reconnection_backoff: Duration,
|
||||||
maximum_reconnection_backoff: Duration,
|
maximum_reconnection_backoff: Duration,
|
||||||
initial_connection_timeout: Duration,
|
initial_connection_timeout: Duration,
|
||||||
maximum_connection_buffer_size: usize,
|
maximum_connection_buffer_size: usize,
|
||||||
|
use_legacy_version: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Config {
|
impl Config {
|
||||||
@@ -36,12 +33,14 @@ impl Config {
|
|||||||
maximum_reconnection_backoff: Duration,
|
maximum_reconnection_backoff: Duration,
|
||||||
initial_connection_timeout: Duration,
|
initial_connection_timeout: Duration,
|
||||||
maximum_connection_buffer_size: usize,
|
maximum_connection_buffer_size: usize,
|
||||||
|
use_legacy_version: bool,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Config {
|
Config {
|
||||||
initial_reconnection_backoff,
|
initial_reconnection_backoff,
|
||||||
maximum_reconnection_backoff,
|
maximum_reconnection_backoff,
|
||||||
initial_connection_timeout,
|
initial_connection_timeout,
|
||||||
maximum_connection_buffer_size,
|
maximum_connection_buffer_size,
|
||||||
|
use_legacy_version,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -58,37 +57,11 @@ pub trait SendWithoutResponse {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct Client {
|
pub struct Client {
|
||||||
active_connections: ActiveConnections,
|
conn_new: HashMap<NymNodeRoutingAddress, ConnectionSender>,
|
||||||
connections_count: Arc<AtomicUsize>,
|
|
||||||
config: Config,
|
config: Config,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Clone)]
|
struct ConnectionSender {
|
||||||
pub struct ActiveConnections {
|
|
||||||
inner: Arc<DashMap<NymNodeRoutingAddress, ConnectionSender>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ActiveConnections {
|
|
||||||
pub fn pending_packets(&self) -> usize {
|
|
||||||
self.inner
|
|
||||||
.iter()
|
|
||||||
.map(|sender| {
|
|
||||||
let max_capacity = sender.channel.max_capacity();
|
|
||||||
let capacity = sender.channel.capacity();
|
|
||||||
max_capacity - capacity
|
|
||||||
})
|
|
||||||
.sum()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Deref for ActiveConnections {
|
|
||||||
type Target = DashMap<NymNodeRoutingAddress, ConnectionSender>;
|
|
||||||
fn deref(&self) -> &Self::Target {
|
|
||||||
&self.inner
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct ConnectionSender {
|
|
||||||
channel: mpsc::Sender<FramedNymPacket>,
|
channel: mpsc::Sender<FramedNymPacket>,
|
||||||
current_reconnection_attempt: Arc<AtomicU32>,
|
current_reconnection_attempt: Arc<AtomicU32>,
|
||||||
}
|
}
|
||||||
@@ -102,53 +75,46 @@ impl ConnectionSender {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ManagedConnection {
|
impl Client {
|
||||||
address: SocketAddr,
|
pub fn new(config: Config) -> Client {
|
||||||
message_receiver: ReceiverStream<FramedNymPacket>,
|
Client {
|
||||||
connection_timeout: Duration,
|
conn_new: HashMap::new(),
|
||||||
current_reconnection: Arc<AtomicU32>,
|
config,
|
||||||
}
|
|
||||||
|
|
||||||
impl ManagedConnection {
|
|
||||||
fn new(
|
|
||||||
address: SocketAddr,
|
|
||||||
message_receiver: mpsc::Receiver<FramedNymPacket>,
|
|
||||||
connection_timeout: Duration,
|
|
||||||
current_reconnection: Arc<AtomicU32>,
|
|
||||||
) -> Self {
|
|
||||||
ManagedConnection {
|
|
||||||
address,
|
|
||||||
message_receiver: ReceiverStream::new(message_receiver),
|
|
||||||
connection_timeout,
|
|
||||||
current_reconnection,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn run(self) {
|
async fn manage_connection(
|
||||||
let address = self.address;
|
address: SocketAddr,
|
||||||
|
receiver: mpsc::Receiver<FramedNymPacket>,
|
||||||
|
connection_timeout: Duration,
|
||||||
|
current_reconnection: &AtomicU32,
|
||||||
|
) {
|
||||||
let connection_fut = TcpStream::connect(address);
|
let connection_fut = TcpStream::connect(address);
|
||||||
|
|
||||||
let conn = match tokio::time::timeout(self.connection_timeout, connection_fut).await {
|
let conn = match tokio::time::timeout(connection_timeout, connection_fut).await {
|
||||||
Ok(stream_res) => match stream_res {
|
Ok(stream_res) => match stream_res {
|
||||||
Ok(stream) => {
|
Ok(stream) => {
|
||||||
debug!("Managed to establish connection to {}", self.address);
|
debug!("Managed to establish connection to {}", address);
|
||||||
// if we managed to connect, reset the reconnection count (whatever it might have been)
|
// if we managed to connect, reset the reconnection count (whatever it might have been)
|
||||||
self.current_reconnection.store(0, Ordering::Release);
|
current_reconnection.store(0, Ordering::Release);
|
||||||
Framed::new(stream, NymCodec)
|
Framed::new(stream, NymCodec)
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
debug!("failed to establish connection to {address} (err: {err})",);
|
debug!(
|
||||||
|
"failed to establish connection to {} (err: {})",
|
||||||
|
address, err
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
debug!(
|
debug!(
|
||||||
"failed to connect to {address} within {:?}",
|
"failed to connect to {} within {:?}",
|
||||||
self.connection_timeout
|
address, connection_timeout
|
||||||
);
|
);
|
||||||
|
|
||||||
// we failed to connect - increase reconnection attempt
|
// we failed to connect - increase reconnection attempt
|
||||||
self.current_reconnection.fetch_add(1, Ordering::SeqCst);
|
current_reconnection.fetch_add(1, Ordering::SeqCst);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -156,28 +122,15 @@ impl ManagedConnection {
|
|||||||
// Take whatever the receiver channel produces and put it on the connection.
|
// Take whatever the receiver channel produces and put it on the connection.
|
||||||
// We could have as well used conn.send_all(receiver.map(Ok)), but considering we don't care
|
// We could have as well used conn.send_all(receiver.map(Ok)), but considering we don't care
|
||||||
// about neither receiver nor the connection, it doesn't matter which one gets consumed
|
// about neither receiver nor the connection, it doesn't matter which one gets consumed
|
||||||
if let Err(err) = self.message_receiver.map(Ok).forward(conn).await {
|
if let Err(err) = receiver.map(Ok).forward(conn).await {
|
||||||
warn!("Failed to forward packets to {address}: {err}");
|
warn!("Failed to forward packets to {} - {err}", address);
|
||||||
}
|
}
|
||||||
|
|
||||||
debug!(
|
debug!(
|
||||||
"connection manager to {address} is finished. Either the connection failed or mixnet client got dropped",
|
"connection manager to {} is finished. Either the connection failed or mixnet client got dropped",
|
||||||
|
address
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl Client {
|
|
||||||
pub fn new(config: Config, connections_count: Arc<AtomicUsize>) -> Client {
|
|
||||||
Client {
|
|
||||||
active_connections: Default::default(),
|
|
||||||
connections_count,
|
|
||||||
config,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn active_connections(&self) -> ActiveConnections {
|
|
||||||
self.active_connections.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// If we're trying to reconnect, determine how long we should wait.
|
/// If we're trying to reconnect, determine how long we should wait.
|
||||||
fn determine_backoff(&self, current_attempt: u32) -> Option<Duration> {
|
fn determine_backoff(&self, current_attempt: u32) -> Option<Duration> {
|
||||||
@@ -197,7 +150,7 @@ impl Client {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn make_connection(&mut self, address: NymNodeRoutingAddress, pending_packet: FramedNymPacket) {
|
fn make_connection(&mut self, address: NymNodeRoutingAddress, pending_packet: FramedNymPacket) {
|
||||||
let (sender, receiver) = mpsc::channel(self.config.maximum_connection_buffer_size);
|
let (mut sender, receiver) = mpsc::channel(self.config.maximum_connection_buffer_size);
|
||||||
|
|
||||||
// this CAN'T fail because we just created the channel which has a non-zero capacity
|
// this CAN'T fail because we just created the channel which has a non-zero capacity
|
||||||
if self.config.maximum_connection_buffer_size > 0 {
|
if self.config.maximum_connection_buffer_size > 0 {
|
||||||
@@ -205,16 +158,15 @@ impl Client {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// if we already tried to connect to `address` before, grab the current attempt count
|
// if we already tried to connect to `address` before, grab the current attempt count
|
||||||
let current_reconnection_attempt =
|
let current_reconnection_attempt = if let Some(existing) = self.conn_new.get_mut(&address) {
|
||||||
if let Some(mut existing) = self.active_connections.get_mut(&address) {
|
existing.channel = sender;
|
||||||
existing.channel = sender;
|
Arc::clone(&existing.current_reconnection_attempt)
|
||||||
Arc::clone(&existing.current_reconnection_attempt)
|
} else {
|
||||||
} else {
|
let new_entry = ConnectionSender::new(sender);
|
||||||
let new_entry = ConnectionSender::new(sender);
|
let current_attempt = Arc::clone(&new_entry.current_reconnection_attempt);
|
||||||
let current_attempt = Arc::clone(&new_entry.current_reconnection_attempt);
|
self.conn_new.insert(address, new_entry);
|
||||||
self.active_connections.insert(address, new_entry);
|
current_attempt
|
||||||
current_attempt
|
};
|
||||||
};
|
|
||||||
|
|
||||||
// load the actual value.
|
// load the actual value.
|
||||||
let reconnection_attempt = current_reconnection_attempt.load(Ordering::Acquire);
|
let reconnection_attempt = current_reconnection_attempt.load(Ordering::Acquire);
|
||||||
@@ -223,7 +175,6 @@ impl Client {
|
|||||||
// copy the value before moving into another task
|
// copy the value before moving into another task
|
||||||
let initial_connection_timeout = self.config.initial_connection_timeout;
|
let initial_connection_timeout = self.config.initial_connection_timeout;
|
||||||
|
|
||||||
let connections_count = self.connections_count.clone();
|
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
// before executing the manager, wait for what was specified, if anything
|
// before executing the manager, wait for what was specified, if anything
|
||||||
if let Some(backoff) = backoff {
|
if let Some(backoff) = backoff {
|
||||||
@@ -231,16 +182,13 @@ impl Client {
|
|||||||
sleep(backoff).await;
|
sleep(backoff).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
connections_count.fetch_add(1, Ordering::SeqCst);
|
Self::manage_connection(
|
||||||
ManagedConnection::new(
|
|
||||||
address.into(),
|
address.into(),
|
||||||
receiver,
|
receiver,
|
||||||
initial_connection_timeout,
|
initial_connection_timeout,
|
||||||
current_reconnection_attempt,
|
¤t_reconnection_attempt,
|
||||||
)
|
)
|
||||||
.run()
|
.await
|
||||||
.await;
|
|
||||||
connections_count.fetch_sub(1, Ordering::SeqCst);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -252,50 +200,53 @@ impl SendWithoutResponse for Client {
|
|||||||
packet: NymPacket,
|
packet: NymPacket,
|
||||||
packet_type: PacketType,
|
packet_type: PacketType,
|
||||||
) -> io::Result<()> {
|
) -> io::Result<()> {
|
||||||
trace!("Sending packet to {address:?}");
|
trace!("Sending packet to {:?}", address);
|
||||||
let framed_packet = FramedNymPacket::new(packet, packet_type);
|
let framed_packet =
|
||||||
|
FramedNymPacket::new(packet, packet_type, self.config.use_legacy_version);
|
||||||
|
|
||||||
let Some(sender) = self.active_connections.get_mut(&address) else {
|
if let Some(sender) = self.conn_new.get_mut(&address) {
|
||||||
|
if let Err(err) = sender.channel.try_send(framed_packet) {
|
||||||
|
if err.is_full() {
|
||||||
|
debug!("Connection to {} seems to not be able to handle all the traffic - dropping the current packet", address);
|
||||||
|
// it's not a 'big' error, but we did not manage to send the packet
|
||||||
|
// if the queue is full, we can't really do anything but to drop the packet
|
||||||
|
Err(io::Error::new(
|
||||||
|
io::ErrorKind::WouldBlock,
|
||||||
|
"connection queue is full",
|
||||||
|
))
|
||||||
|
} else if err.is_disconnected() {
|
||||||
|
debug!(
|
||||||
|
"Connection to {} seems to be dead. attempting to re-establish it...",
|
||||||
|
address
|
||||||
|
);
|
||||||
|
// it's not a 'big' error, but we did not manage to send the packet, but queue
|
||||||
|
// it up to send it as soon as the connection is re-established
|
||||||
|
self.make_connection(address, err.into_inner());
|
||||||
|
Err(io::Error::new(
|
||||||
|
io::ErrorKind::ConnectionAborted,
|
||||||
|
"reconnection attempt is in progress",
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
// this can't really happen, but let's safe-guard against it in case something changes in futures library
|
||||||
|
Err(io::Error::new(
|
||||||
|
io::ErrorKind::Other,
|
||||||
|
"unknown connection buffer error",
|
||||||
|
))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
} else {
|
||||||
// there was never a connection to begin with
|
// there was never a connection to begin with
|
||||||
debug!("establishing initial connection to {}", address);
|
debug!("establishing initial connection to {}", address);
|
||||||
// it's not a 'big' error, but we did not manage to send the packet, but queue the packet
|
// it's not a 'big' error, but we did not manage to send the packet, but queue the packet
|
||||||
// for sending for as soon as the connection is created
|
// for sending for as soon as the connection is created
|
||||||
self.make_connection(address, framed_packet);
|
self.make_connection(address, framed_packet);
|
||||||
return Err(io::Error::new(
|
Err(io::Error::new(
|
||||||
io::ErrorKind::NotConnected,
|
io::ErrorKind::NotConnected,
|
||||||
"connection is in progress",
|
"connection is in progress",
|
||||||
));
|
))
|
||||||
};
|
}
|
||||||
|
|
||||||
let sending_res = sender.channel.try_send(framed_packet);
|
|
||||||
drop(sender);
|
|
||||||
|
|
||||||
sending_res.map_err(|err| {
|
|
||||||
match err {
|
|
||||||
TrySendError::Full(_) => {
|
|
||||||
debug!("Connection to {address} seems to not be able to handle all the traffic - dropping the current packet");
|
|
||||||
// it's not a 'big' error, but we did not manage to send the packet
|
|
||||||
// if the queue is full, we can't really do anything but to drop the packet
|
|
||||||
io::Error::new(
|
|
||||||
io::ErrorKind::WouldBlock,
|
|
||||||
"connection queue is full",
|
|
||||||
)
|
|
||||||
}
|
|
||||||
TrySendError::Closed(dropped) => {
|
|
||||||
debug!(
|
|
||||||
"Connection to {address} seems to be dead. attempting to re-establish it...",
|
|
||||||
);
|
|
||||||
|
|
||||||
// it's not a 'big' error, but we did not manage to send the packet, but queue
|
|
||||||
// it up to send it as soon as the connection is re-established
|
|
||||||
self.make_connection(address, dropped);
|
|
||||||
io::Error::new(
|
|
||||||
io::ErrorKind::ConnectionAborted,
|
|
||||||
"reconnection attempt is in progress",
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} )
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -304,15 +255,13 @@ mod tests {
|
|||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
fn dummy_client() -> Client {
|
fn dummy_client() -> Client {
|
||||||
Client::new(
|
Client::new(Config {
|
||||||
Config {
|
initial_reconnection_backoff: Duration::from_millis(10_000),
|
||||||
initial_reconnection_backoff: Duration::from_millis(10_000),
|
maximum_reconnection_backoff: Duration::from_millis(300_000),
|
||||||
maximum_reconnection_backoff: Duration::from_millis(300_000),
|
initial_connection_timeout: Duration::from_millis(1_500),
|
||||||
initial_connection_timeout: Duration::from_millis(1_500),
|
maximum_connection_buffer_size: 128,
|
||||||
maximum_connection_buffer_size: 128,
|
use_legacy_version: false,
|
||||||
},
|
})
|
||||||
Default::default(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
@@ -1,72 +1,77 @@
|
|||||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
use crate::client::{Client, Config, SendWithoutResponse};
|
||||||
use futures::channel::mpsc;
|
use futures::channel::mpsc;
|
||||||
use futures::channel::mpsc::SendError;
|
use futures::StreamExt;
|
||||||
|
use log::*;
|
||||||
use nym_sphinx::forwarding::packet::MixPacket;
|
use nym_sphinx::forwarding::packet::MixPacket;
|
||||||
use tokio::time::Instant;
|
use std::time::Duration;
|
||||||
|
|
||||||
pub fn mix_forwarding_channels() -> (MixForwardingSender, MixForwardingReceiver) {
|
pub type MixForwardingSender = mpsc::UnboundedSender<MixPacket>;
|
||||||
let (tx, rx) = mpsc::unbounded();
|
type MixForwardingReceiver = mpsc::UnboundedReceiver<MixPacket>;
|
||||||
(tx.into(), rx)
|
|
||||||
|
/// A specialisation of client such that it forwards any received packets on the channel into the
|
||||||
|
/// mix network immediately, i.e. will not try to listen for any responses.
|
||||||
|
pub struct PacketForwarder {
|
||||||
|
mixnet_client: Client,
|
||||||
|
packet_receiver: MixForwardingReceiver,
|
||||||
|
shutdown: nym_task::TaskClient,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
impl PacketForwarder {
|
||||||
pub struct MixForwardingSender(mpsc::UnboundedSender<PacketToForward>);
|
pub fn new(
|
||||||
|
initial_reconnection_backoff: Duration,
|
||||||
|
maximum_reconnection_backoff: Duration,
|
||||||
|
initial_connection_timeout: Duration,
|
||||||
|
maximum_connection_buffer_size: usize,
|
||||||
|
use_legacy_version: bool,
|
||||||
|
shutdown: nym_task::TaskClient,
|
||||||
|
) -> (PacketForwarder, MixForwardingSender) {
|
||||||
|
let client_config = Config::new(
|
||||||
|
initial_reconnection_backoff,
|
||||||
|
maximum_reconnection_backoff,
|
||||||
|
initial_connection_timeout,
|
||||||
|
maximum_connection_buffer_size,
|
||||||
|
use_legacy_version,
|
||||||
|
);
|
||||||
|
|
||||||
impl From<mpsc::UnboundedSender<PacketToForward>> for MixForwardingSender {
|
let (packet_sender, packet_receiver) = mpsc::unbounded();
|
||||||
fn from(tx: mpsc::UnboundedSender<PacketToForward>) -> Self {
|
|
||||||
MixForwardingSender(tx)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl MixForwardingSender {
|
(
|
||||||
pub fn forward_packet(&self, packet: impl Into<PacketToForward>) -> Result<(), SendError> {
|
PacketForwarder {
|
||||||
self.0
|
mixnet_client: Client::new(client_config),
|
||||||
.unbounded_send(packet.into())
|
packet_receiver,
|
||||||
.map_err(|err| err.into_send_error())
|
shutdown,
|
||||||
|
},
|
||||||
|
packet_sender,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::len_without_is_empty)]
|
pub async fn run(&mut self) {
|
||||||
pub fn len(&self) -> usize {
|
while !self.shutdown.is_shutdown() {
|
||||||
self.0.len()
|
tokio::select! {
|
||||||
}
|
biased;
|
||||||
}
|
_ = self.shutdown.recv() => {
|
||||||
|
log::trace!("PacketForwarder: Received shutdown");
|
||||||
|
}
|
||||||
|
Some(mix_packet) = self.packet_receiver.next() => {
|
||||||
|
trace!("Going to forward packet to {}", mix_packet.next_hop());
|
||||||
|
|
||||||
pub type MixForwardingReceiver = mpsc::UnboundedReceiver<PacketToForward>;
|
let next_hop = mix_packet.next_hop();
|
||||||
|
let packet_type = mix_packet.packet_type();
|
||||||
|
let packet = mix_packet.into_packet();
|
||||||
|
// we don't care about responses, we just want to fire packets
|
||||||
|
// as quickly as possible
|
||||||
|
|
||||||
pub struct PacketToForward {
|
if let Err(err) =
|
||||||
pub packet: MixPacket,
|
self.mixnet_client
|
||||||
pub forward_delay_target: Option<Instant>,
|
.send_without_response(next_hop, packet, packet_type)
|
||||||
}
|
{
|
||||||
|
debug!("failed to forward the packet - {err}")
|
||||||
impl From<MixPacket> for PacketToForward {
|
}
|
||||||
fn from(packet: MixPacket) -> Self {
|
}
|
||||||
PacketToForward::new_no_delay(packet)
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<(MixPacket, Option<Instant>)> for PacketToForward {
|
|
||||||
fn from((packet, delay_until): (MixPacket, Option<Instant>)) -> Self {
|
|
||||||
PacketToForward::new(packet, delay_until)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<(MixPacket, Instant)> for PacketToForward {
|
|
||||||
fn from((packet, delay_until): (MixPacket, Instant)) -> Self {
|
|
||||||
PacketToForward::new(packet, Some(delay_until))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PacketToForward {
|
|
||||||
pub fn new(packet: MixPacket, forward_delay_target: Option<Instant>) -> Self {
|
|
||||||
PacketToForward {
|
|
||||||
packet,
|
|
||||||
forward_delay_target,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_no_delay(packet: MixPacket) -> Self {
|
|
||||||
Self::new(packet, None)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
#[cfg(feature = "client")]
|
|
||||||
pub mod client;
|
pub mod client;
|
||||||
pub mod forwarder;
|
pub mod forwarder;
|
||||||
|
|
||||||
#[cfg(feature = "client")]
|
|
||||||
pub use client::{Client, Config, SendWithoutResponse};
|
pub use client::{Client, Config, SendWithoutResponse};
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
|
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
pub use crate::nym_api::NymApiClientExt;
|
||||||
use crate::nyxd::{self, NyxdClient};
|
use crate::nyxd::{self, NyxdClient};
|
||||||
use crate::signing::direct_wallet::DirectSecp256k1HdWallet;
|
use crate::signing::direct_wallet::DirectSecp256k1HdWallet;
|
||||||
use crate::signing::signer::{NoSigner, OfflineSigner};
|
use crate::signing::signer::{NoSigner, OfflineSigner};
|
||||||
@@ -19,8 +20,8 @@ use nym_api_requests::ecash::{
|
|||||||
PartialExpirationDateSignatureResponse, VerificationKeyResponse,
|
PartialExpirationDateSignatureResponse, VerificationKeyResponse,
|
||||||
};
|
};
|
||||||
use nym_api_requests::models::{
|
use nym_api_requests::models::{
|
||||||
ApiHealthResponse, GatewayBondAnnotated, GatewayCoreStatusResponse, MixnodeCoreStatusResponse,
|
ApiHealthResponse, GatewayCoreStatusResponse, MixnodeCoreStatusResponse, MixnodeStatusResponse,
|
||||||
MixnodeStatusResponse, NymNodeDescription, RewardEstimationResponse, StakeSaturationResponse,
|
NymNodeDescription, RewardEstimationResponse, StakeSaturationResponse,
|
||||||
};
|
};
|
||||||
use nym_api_requests::models::{LegacyDescribedGateway, MixNodeBondAnnotated};
|
use nym_api_requests::models::{LegacyDescribedGateway, MixNodeBondAnnotated};
|
||||||
use nym_api_requests::nym_nodes::SkimmedNode;
|
use nym_api_requests::nym_nodes::SkimmedNode;
|
||||||
@@ -31,11 +32,10 @@ use nym_network_defaults::NymNetworkDetails;
|
|||||||
use time::Date;
|
use time::Date;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
pub use crate::nym_api::NymApiClientExt;
|
|
||||||
use nym_mixnet_contract_common::EpochRewardedSet;
|
|
||||||
pub use nym_mixnet_contract_common::{
|
pub use nym_mixnet_contract_common::{
|
||||||
mixnode::MixNodeDetails, GatewayBond, IdentityKey, IdentityKeyRef, NodeId, NymNodeDetails,
|
mixnode::MixNodeDetails, GatewayBond, IdentityKey, IdentityKeyRef, NodeId, NymNodeDetails,
|
||||||
};
|
};
|
||||||
|
|
||||||
// re-export the type to not break existing imports
|
// re-export the type to not break existing imports
|
||||||
pub use crate::coconut::EcashApiClient;
|
pub use crate::coconut::EcashApiClient;
|
||||||
|
|
||||||
@@ -257,13 +257,6 @@ impl<C, S> Client<C, S> {
|
|||||||
Ok(self.nym_api.get_gateways().await?)
|
Ok(self.nym_api.get_gateways().await?)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[deprecated]
|
|
||||||
pub async fn get_cached_gateways_detailed_unfiltered(
|
|
||||||
&self,
|
|
||||||
) -> Result<Vec<GatewayBondAnnotated>, ValidatorClientError> {
|
|
||||||
Ok(self.nym_api.get_gateways_detailed_unfiltered().await?)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: combine with NymApiClient...
|
// TODO: combine with NymApiClient...
|
||||||
pub async fn get_all_cached_described_nodes(
|
pub async fn get_all_cached_described_nodes(
|
||||||
&self,
|
&self,
|
||||||
@@ -339,10 +332,10 @@ impl NymApiClient {
|
|||||||
NymApiClient { nym_api }
|
NymApiClient { nym_api }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_with_user_agent(api_url: Url, user_agent: impl Into<UserAgent>) -> Self {
|
pub fn new_with_user_agent(api_url: Url, user_agent: UserAgent) -> Self {
|
||||||
let nym_api = nym_api::Client::builder::<_, ValidatorClientError>(api_url)
|
let nym_api = nym_api::Client::builder::<_, ValidatorClientError>(api_url)
|
||||||
.expect("invalid api url")
|
.expect("invalid api url")
|
||||||
.with_user_agent(user_agent.into())
|
.with_user_agent(user_agent)
|
||||||
.build::<ValidatorClientError>()
|
.build::<ValidatorClientError>()
|
||||||
.expect("failed to build nym api client");
|
.expect("failed to build nym api client");
|
||||||
|
|
||||||
@@ -358,23 +351,34 @@ impl NymApiClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[deprecated(note = "use get_all_basic_active_mixing_assigned_nodes instead")]
|
#[deprecated(note = "use get_all_basic_active_mixing_assigned_nodes instead")]
|
||||||
pub async fn get_basic_mixnodes(&self) -> Result<Vec<SkimmedNode>, ValidatorClientError> {
|
pub async fn get_basic_mixnodes(
|
||||||
Ok(self.nym_api.get_basic_mixnodes().await?.nodes)
|
&self,
|
||||||
|
semver_compatibility: Option<String>,
|
||||||
|
) -> Result<Vec<SkimmedNode>, ValidatorClientError> {
|
||||||
|
Ok(self
|
||||||
|
.nym_api
|
||||||
|
.get_basic_mixnodes(semver_compatibility)
|
||||||
|
.await?
|
||||||
|
.nodes)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[deprecated(note = "use get_all_basic_entry_assigned_nodes instead")]
|
#[deprecated(note = "use get_all_basic_entry_assigned_nodes instead")]
|
||||||
pub async fn get_basic_gateways(&self) -> Result<Vec<SkimmedNode>, ValidatorClientError> {
|
pub async fn get_basic_gateways(
|
||||||
Ok(self.nym_api.get_basic_gateways().await?.nodes)
|
&self,
|
||||||
}
|
semver_compatibility: Option<String>,
|
||||||
|
) -> Result<Vec<SkimmedNode>, ValidatorClientError> {
|
||||||
pub async fn get_current_rewarded_set(&self) -> Result<EpochRewardedSet, ValidatorClientError> {
|
Ok(self
|
||||||
Ok(self.nym_api.get_rewarded_set().await?.into())
|
.nym_api
|
||||||
|
.get_basic_gateways(semver_compatibility)
|
||||||
|
.await?
|
||||||
|
.nodes)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// retrieve basic information for nodes are capable of operating as an entry gateway
|
/// retrieve basic information for nodes are capable of operating as an entry gateway
|
||||||
/// this includes legacy gateways and nym-nodes
|
/// this includes legacy gateways and nym-nodes
|
||||||
pub async fn get_all_basic_entry_assigned_nodes(
|
pub async fn get_all_basic_entry_assigned_nodes(
|
||||||
&self,
|
&self,
|
||||||
|
semver_compatibility: Option<String>,
|
||||||
) -> Result<Vec<SkimmedNode>, ValidatorClientError> {
|
) -> Result<Vec<SkimmedNode>, ValidatorClientError> {
|
||||||
// TODO: deal with paging in macro or some helper function or something, because it's the same pattern everywhere
|
// TODO: deal with paging in macro or some helper function or something, because it's the same pattern everywhere
|
||||||
let mut page = 0;
|
let mut page = 0;
|
||||||
@@ -383,7 +387,12 @@ impl NymApiClient {
|
|||||||
loop {
|
loop {
|
||||||
let mut res = self
|
let mut res = self
|
||||||
.nym_api
|
.nym_api
|
||||||
.get_basic_entry_assigned_nodes(false, Some(page), None)
|
.get_basic_entry_assigned_nodes(
|
||||||
|
semver_compatibility.clone(),
|
||||||
|
false,
|
||||||
|
Some(page),
|
||||||
|
None,
|
||||||
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
nodes.append(&mut res.nodes.data);
|
nodes.append(&mut res.nodes.data);
|
||||||
@@ -401,6 +410,7 @@ impl NymApiClient {
|
|||||||
/// this includes legacy mixnodes and nym-nodes
|
/// this includes legacy mixnodes and nym-nodes
|
||||||
pub async fn get_all_basic_active_mixing_assigned_nodes(
|
pub async fn get_all_basic_active_mixing_assigned_nodes(
|
||||||
&self,
|
&self,
|
||||||
|
semver_compatibility: Option<String>,
|
||||||
) -> Result<Vec<SkimmedNode>, ValidatorClientError> {
|
) -> Result<Vec<SkimmedNode>, ValidatorClientError> {
|
||||||
// TODO: deal with paging in macro or some helper function or something, because it's the same pattern everywhere
|
// TODO: deal with paging in macro or some helper function or something, because it's the same pattern everywhere
|
||||||
let mut page = 0;
|
let mut page = 0;
|
||||||
@@ -409,7 +419,12 @@ impl NymApiClient {
|
|||||||
loop {
|
loop {
|
||||||
let mut res = self
|
let mut res = self
|
||||||
.nym_api
|
.nym_api
|
||||||
.get_basic_active_mixing_assigned_nodes(false, Some(page), None)
|
.get_basic_active_mixing_assigned_nodes(
|
||||||
|
semver_compatibility.clone(),
|
||||||
|
false,
|
||||||
|
Some(page),
|
||||||
|
None,
|
||||||
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
nodes.append(&mut res.nodes.data);
|
nodes.append(&mut res.nodes.data);
|
||||||
@@ -427,6 +442,7 @@ impl NymApiClient {
|
|||||||
/// this includes legacy mixnodes and nym-nodes
|
/// this includes legacy mixnodes and nym-nodes
|
||||||
pub async fn get_all_basic_mixing_capable_nodes(
|
pub async fn get_all_basic_mixing_capable_nodes(
|
||||||
&self,
|
&self,
|
||||||
|
semver_compatibility: Option<String>,
|
||||||
) -> Result<Vec<SkimmedNode>, ValidatorClientError> {
|
) -> Result<Vec<SkimmedNode>, ValidatorClientError> {
|
||||||
// TODO: deal with paging in macro or some helper function or something, because it's the same pattern everywhere
|
// TODO: deal with paging in macro or some helper function or something, because it's the same pattern everywhere
|
||||||
let mut page = 0;
|
let mut page = 0;
|
||||||
@@ -435,7 +451,12 @@ impl NymApiClient {
|
|||||||
loop {
|
loop {
|
||||||
let mut res = self
|
let mut res = self
|
||||||
.nym_api
|
.nym_api
|
||||||
.get_basic_mixing_capable_nodes(false, Some(page), None)
|
.get_basic_mixing_capable_nodes(
|
||||||
|
semver_compatibility.clone(),
|
||||||
|
false,
|
||||||
|
Some(page),
|
||||||
|
None,
|
||||||
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
nodes.append(&mut res.nodes.data);
|
nodes.append(&mut res.nodes.data);
|
||||||
@@ -450,7 +471,10 @@ impl NymApiClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// retrieve basic information for all bonded nodes on the network
|
/// retrieve basic information for all bonded nodes on the network
|
||||||
pub async fn get_all_basic_nodes(&self) -> Result<Vec<SkimmedNode>, ValidatorClientError> {
|
pub async fn get_all_basic_nodes(
|
||||||
|
&self,
|
||||||
|
semver_compatibility: Option<String>,
|
||||||
|
) -> Result<Vec<SkimmedNode>, ValidatorClientError> {
|
||||||
// TODO: deal with paging in macro or some helper function or something, because it's the same pattern everywhere
|
// TODO: deal with paging in macro or some helper function or something, because it's the same pattern everywhere
|
||||||
let mut page = 0;
|
let mut page = 0;
|
||||||
let mut nodes = Vec::new();
|
let mut nodes = Vec::new();
|
||||||
@@ -458,7 +482,7 @@ impl NymApiClient {
|
|||||||
loop {
|
loop {
|
||||||
let mut res = self
|
let mut res = self
|
||||||
.nym_api
|
.nym_api
|
||||||
.get_basic_nodes(false, Some(page), None)
|
.get_basic_nodes(semver_compatibility.clone(), false, Some(page), None)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
nodes.append(&mut res.nodes.data);
|
nodes.append(&mut res.nodes.data);
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ use nym_api_requests::ecash::models::{
|
|||||||
use nym_api_requests::ecash::VerificationKeyResponse;
|
use nym_api_requests::ecash::VerificationKeyResponse;
|
||||||
use nym_api_requests::models::{
|
use nym_api_requests::models::{
|
||||||
AnnotationResponse, ApiHealthResponse, LegacyDescribedMixNode, NodePerformanceResponse,
|
AnnotationResponse, ApiHealthResponse, LegacyDescribedMixNode, NodePerformanceResponse,
|
||||||
NodeRefreshBody, NymNodeDescription, RewardedSetResponse,
|
NymNodeDescription,
|
||||||
};
|
};
|
||||||
use nym_api_requests::nym_nodes::PaginatedCachedNodesResponse;
|
use nym_api_requests::nym_nodes::PaginatedCachedNodesResponse;
|
||||||
use nym_api_requests::pagination::PaginatedResponse;
|
use nym_api_requests::pagination::PaginatedResponse;
|
||||||
@@ -102,23 +102,6 @@ pub trait NymApiClientExt: ApiClient {
|
|||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
#[deprecated]
|
|
||||||
#[instrument(level = "debug", skip(self))]
|
|
||||||
async fn get_gateways_detailed_unfiltered(
|
|
||||||
&self,
|
|
||||||
) -> Result<Vec<GatewayBondAnnotated>, NymAPIError> {
|
|
||||||
self.get_json(
|
|
||||||
&[
|
|
||||||
routes::API_VERSION,
|
|
||||||
routes::STATUS,
|
|
||||||
routes::GATEWAYS,
|
|
||||||
routes::DETAILED_UNFILTERED,
|
|
||||||
],
|
|
||||||
NO_PARAMS,
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
#[deprecated]
|
#[deprecated]
|
||||||
#[instrument(level = "debug", skip(self))]
|
#[instrument(level = "debug", skip(self))]
|
||||||
async fn get_mixnodes_detailed_unfiltered(
|
async fn get_mixnodes_detailed_unfiltered(
|
||||||
@@ -205,7 +188,16 @@ pub trait NymApiClientExt: ApiClient {
|
|||||||
|
|
||||||
#[deprecated]
|
#[deprecated]
|
||||||
#[tracing::instrument(level = "debug", skip_all)]
|
#[tracing::instrument(level = "debug", skip_all)]
|
||||||
async fn get_basic_mixnodes(&self) -> Result<CachedNodesResponse<SkimmedNode>, NymAPIError> {
|
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(
|
self.get_json(
|
||||||
&[
|
&[
|
||||||
routes::API_VERSION,
|
routes::API_VERSION,
|
||||||
@@ -214,14 +206,23 @@ pub trait NymApiClientExt: ApiClient {
|
|||||||
"mixnodes",
|
"mixnodes",
|
||||||
"skimmed",
|
"skimmed",
|
||||||
],
|
],
|
||||||
NO_PARAMS,
|
¶ms,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
#[deprecated]
|
#[deprecated]
|
||||||
#[instrument(level = "debug", skip(self))]
|
#[instrument(level = "debug", skip(self))]
|
||||||
async fn get_basic_gateways(&self) -> Result<CachedNodesResponse<SkimmedNode>, NymAPIError> {
|
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(
|
self.get_json(
|
||||||
&[
|
&[
|
||||||
routes::API_VERSION,
|
routes::API_VERSION,
|
||||||
@@ -230,16 +231,7 @@ pub trait NymApiClientExt: ApiClient {
|
|||||||
"gateways",
|
"gateways",
|
||||||
"skimmed",
|
"skimmed",
|
||||||
],
|
],
|
||||||
NO_PARAMS,
|
¶ms,
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
#[instrument(level = "debug", skip(self))]
|
|
||||||
async fn get_rewarded_set(&self) -> Result<RewardedSetResponse, NymAPIError> {
|
|
||||||
self.get_json(
|
|
||||||
&[routes::API_VERSION, "nym-nodes", "rewarded-set"],
|
|
||||||
NO_PARAMS,
|
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@@ -249,12 +241,17 @@ pub trait NymApiClientExt: ApiClient {
|
|||||||
#[instrument(level = "debug", skip(self))]
|
#[instrument(level = "debug", skip(self))]
|
||||||
async fn get_basic_entry_assigned_nodes(
|
async fn get_basic_entry_assigned_nodes(
|
||||||
&self,
|
&self,
|
||||||
|
semver_compatibility: Option<String>,
|
||||||
no_legacy: bool,
|
no_legacy: bool,
|
||||||
page: Option<u32>,
|
page: Option<u32>,
|
||||||
per_page: Option<u32>,
|
per_page: Option<u32>,
|
||||||
) -> Result<PaginatedCachedNodesResponse<SkimmedNode>, NymAPIError> {
|
) -> Result<PaginatedCachedNodesResponse<SkimmedNode>, NymAPIError> {
|
||||||
let mut params = Vec::new();
|
let mut params = Vec::new();
|
||||||
|
|
||||||
|
if let Some(arg) = &semver_compatibility {
|
||||||
|
params.push(("semver_compatibility", arg.clone()))
|
||||||
|
}
|
||||||
|
|
||||||
if no_legacy {
|
if no_legacy {
|
||||||
params.push(("no_legacy", "true".to_string()))
|
params.push(("no_legacy", "true".to_string()))
|
||||||
}
|
}
|
||||||
@@ -286,12 +283,17 @@ pub trait NymApiClientExt: ApiClient {
|
|||||||
#[instrument(level = "debug", skip(self))]
|
#[instrument(level = "debug", skip(self))]
|
||||||
async fn get_basic_active_mixing_assigned_nodes(
|
async fn get_basic_active_mixing_assigned_nodes(
|
||||||
&self,
|
&self,
|
||||||
|
semver_compatibility: Option<String>,
|
||||||
no_legacy: bool,
|
no_legacy: bool,
|
||||||
page: Option<u32>,
|
page: Option<u32>,
|
||||||
per_page: Option<u32>,
|
per_page: Option<u32>,
|
||||||
) -> Result<PaginatedCachedNodesResponse<SkimmedNode>, NymAPIError> {
|
) -> Result<PaginatedCachedNodesResponse<SkimmedNode>, NymAPIError> {
|
||||||
let mut params = Vec::new();
|
let mut params = Vec::new();
|
||||||
|
|
||||||
|
if let Some(arg) = &semver_compatibility {
|
||||||
|
params.push(("semver_compatibility", arg.clone()))
|
||||||
|
}
|
||||||
|
|
||||||
if no_legacy {
|
if no_legacy {
|
||||||
params.push(("no_legacy", "true".to_string()))
|
params.push(("no_legacy", "true".to_string()))
|
||||||
}
|
}
|
||||||
@@ -323,12 +325,17 @@ pub trait NymApiClientExt: ApiClient {
|
|||||||
#[instrument(level = "debug", skip(self))]
|
#[instrument(level = "debug", skip(self))]
|
||||||
async fn get_basic_mixing_capable_nodes(
|
async fn get_basic_mixing_capable_nodes(
|
||||||
&self,
|
&self,
|
||||||
|
semver_compatibility: Option<String>,
|
||||||
no_legacy: bool,
|
no_legacy: bool,
|
||||||
page: Option<u32>,
|
page: Option<u32>,
|
||||||
per_page: Option<u32>,
|
per_page: Option<u32>,
|
||||||
) -> Result<PaginatedCachedNodesResponse<SkimmedNode>, NymAPIError> {
|
) -> Result<PaginatedCachedNodesResponse<SkimmedNode>, NymAPIError> {
|
||||||
let mut params = Vec::new();
|
let mut params = Vec::new();
|
||||||
|
|
||||||
|
if let Some(arg) = &semver_compatibility {
|
||||||
|
params.push(("semver_compatibility", arg.clone()))
|
||||||
|
}
|
||||||
|
|
||||||
if no_legacy {
|
if no_legacy {
|
||||||
params.push(("no_legacy", "true".to_string()))
|
params.push(("no_legacy", "true".to_string()))
|
||||||
}
|
}
|
||||||
@@ -358,12 +365,17 @@ pub trait NymApiClientExt: ApiClient {
|
|||||||
#[instrument(level = "debug", skip(self))]
|
#[instrument(level = "debug", skip(self))]
|
||||||
async fn get_basic_nodes(
|
async fn get_basic_nodes(
|
||||||
&self,
|
&self,
|
||||||
|
semver_compatibility: Option<String>,
|
||||||
no_legacy: bool,
|
no_legacy: bool,
|
||||||
page: Option<u32>,
|
page: Option<u32>,
|
||||||
per_page: Option<u32>,
|
per_page: Option<u32>,
|
||||||
) -> Result<PaginatedCachedNodesResponse<SkimmedNode>, NymAPIError> {
|
) -> Result<PaginatedCachedNodesResponse<SkimmedNode>, NymAPIError> {
|
||||||
let mut params = Vec::new();
|
let mut params = Vec::new();
|
||||||
|
|
||||||
|
if let Some(arg) = &semver_compatibility {
|
||||||
|
params.push(("semver_compatibility", arg.clone()))
|
||||||
|
}
|
||||||
|
|
||||||
if no_legacy {
|
if no_legacy {
|
||||||
params.push(("no_legacy", "true".to_string()))
|
params.push(("no_legacy", "true".to_string()))
|
||||||
}
|
}
|
||||||
@@ -683,32 +695,16 @@ pub trait NymApiClientExt: ApiClient {
|
|||||||
&self,
|
&self,
|
||||||
node_id: NodeId,
|
node_id: NodeId,
|
||||||
) -> Result<NodePerformanceResponse, NymAPIError> {
|
) -> Result<NodePerformanceResponse, NymAPIError> {
|
||||||
self.get_json(
|
self.get_json_from(format!("/v1/nym-nodes/performance/{node_id}"))
|
||||||
&[
|
.await
|
||||||
routes::API_VERSION,
|
|
||||||
"nym-nodes",
|
|
||||||
"performance",
|
|
||||||
&node_id.to_string(),
|
|
||||||
],
|
|
||||||
NO_PARAMS,
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_node_annotation(
|
async fn get_node_annotation(
|
||||||
&self,
|
&self,
|
||||||
node_id: NodeId,
|
node_id: NodeId,
|
||||||
) -> Result<AnnotationResponse, NymAPIError> {
|
) -> Result<AnnotationResponse, NymAPIError> {
|
||||||
self.get_json(
|
self.get_json_from(format!("/v1/nym-nodes/annotation/{node_id}"))
|
||||||
&[
|
.await
|
||||||
routes::API_VERSION,
|
|
||||||
"nym-nodes",
|
|
||||||
"annotation",
|
|
||||||
&node_id.to_string(),
|
|
||||||
],
|
|
||||||
NO_PARAMS,
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[deprecated]
|
#[deprecated]
|
||||||
@@ -921,20 +917,6 @@ pub trait NymApiClientExt: ApiClient {
|
|||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "debug", skip(self))]
|
|
||||||
async fn force_refresh_describe_cache(
|
|
||||||
&self,
|
|
||||||
request: &NodeRefreshBody,
|
|
||||||
) -> Result<(), NymAPIError> {
|
|
||||||
self.post_json(
|
|
||||||
&[routes::API_VERSION, "nym-nodes", "refresh-described"],
|
|
||||||
NO_PARAMS,
|
|
||||||
request,
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
#[instrument(level = "debug", skip(self))]
|
|
||||||
async fn issued_ticketbooks_for(
|
async fn issued_ticketbooks_for(
|
||||||
&self,
|
&self,
|
||||||
expiration_date: Date,
|
expiration_date: Date,
|
||||||
@@ -951,7 +933,6 @@ pub trait NymApiClientExt: ApiClient {
|
|||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "debug", skip(self))]
|
|
||||||
async fn issued_ticketbooks_challenge(
|
async fn issued_ticketbooks_challenge(
|
||||||
&self,
|
&self,
|
||||||
expiration_date: Date,
|
expiration_date: Date,
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ impl Div<GasPrice> for Coin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Div<GasPrice> for &Coin {
|
impl<'a> Div<GasPrice> for &'a Coin {
|
||||||
type Output = Gas;
|
type Output = Gas;
|
||||||
|
|
||||||
fn div(self, rhs: GasPrice) -> Self::Output {
|
fn div(self, rhs: GasPrice) -> Self::Output {
|
||||||
|
|||||||
+20
-48
@@ -10,10 +10,10 @@ use cosmrs::AccountId;
|
|||||||
use nym_contracts_common::signing::Nonce;
|
use nym_contracts_common::signing::Nonce;
|
||||||
use nym_mixnet_contract_common::gateway::{PreassignedGatewayIdsResponse, PreassignedId};
|
use nym_mixnet_contract_common::gateway::{PreassignedGatewayIdsResponse, PreassignedId};
|
||||||
use nym_mixnet_contract_common::nym_node::{
|
use nym_mixnet_contract_common::nym_node::{
|
||||||
EpochAssignmentResponse, NodeDetailsByIdentityResponse, NodeDetailsResponse,
|
EpochAssignmentResponse, NodeDetailsByIdentityResponse, NodeOwnershipResponse,
|
||||||
NodeOwnershipResponse, NodeRewardingDetailsResponse, PagedNymNodeBondsResponse,
|
NodeRewardingDetailsResponse, PagedNymNodeBondsResponse, PagedNymNodeDetailsResponse,
|
||||||
PagedNymNodeDetailsResponse, PagedUnbondedNymNodesResponse, Role, RolesMetadataResponse,
|
PagedUnbondedNymNodesResponse, Role, RolesMetadataResponse, StakeSaturationResponse,
|
||||||
StakeSaturationResponse, UnbondedNodeResponse, UnbondedNymNode,
|
UnbondedNodeResponse, UnbondedNymNode,
|
||||||
};
|
};
|
||||||
use nym_mixnet_contract_common::reward_params::WorkFactor;
|
use nym_mixnet_contract_common::reward_params::WorkFactor;
|
||||||
use nym_mixnet_contract_common::{
|
use nym_mixnet_contract_common::{
|
||||||
@@ -26,11 +26,10 @@ use nym_mixnet_contract_common::{
|
|||||||
reward_params::{Performance, RewardingParams},
|
reward_params::{Performance, RewardingParams},
|
||||||
rewarding::{EstimatedCurrentEpochRewardResponse, PendingRewardResponse},
|
rewarding::{EstimatedCurrentEpochRewardResponse, PendingRewardResponse},
|
||||||
ContractBuildInformation, ContractState, ContractStateParams, CurrentIntervalResponse,
|
ContractBuildInformation, ContractState, ContractStateParams, CurrentIntervalResponse,
|
||||||
CurrentNymNodeVersionResponse, Delegation, EpochEventId, EpochRewardedSet, EpochStatus,
|
Delegation, EpochEventId, EpochStatus, GatewayBond, GatewayBondResponse,
|
||||||
GatewayBond, GatewayBondResponse, GatewayOwnershipResponse, HistoricalNymNodeVersionEntry,
|
GatewayOwnershipResponse, IdentityKey, IdentityKeyRef, IntervalEventId, MixNodeBond,
|
||||||
IdentityKey, IdentityKeyRef, IntervalEventId, MixNodeBond, MixNodeDetails,
|
MixNodeDetails, MixOwnershipResponse, MixnodeDetailsByIdentityResponse, MixnodeDetailsResponse,
|
||||||
MixOwnershipResponse, MixnodeDetailsByIdentityResponse, MixnodeDetailsResponse, NodeId,
|
NodeId, NumberOfPendingEventsResponse, NymNodeBond, NymNodeDetails,
|
||||||
NumberOfPendingEventsResponse, NymNodeBond, NymNodeDetails, NymNodeVersionHistoryResponse,
|
|
||||||
PagedAllDelegationsResponse, PagedDelegatorDelegationsResponse, PagedGatewayResponse,
|
PagedAllDelegationsResponse, PagedDelegatorDelegationsResponse, PagedGatewayResponse,
|
||||||
PagedMixnodeBondsResponse, PagedNodeDelegationsResponse, PendingEpochEvent,
|
PagedMixnodeBondsResponse, PagedNodeDelegationsResponse, PendingEpochEvent,
|
||||||
PendingEpochEventResponse, PendingEpochEventsResponse, PendingIntervalEvent,
|
PendingEpochEventResponse, PendingEpochEventsResponse, PendingIntervalEvent,
|
||||||
@@ -72,22 +71,6 @@ pub trait MixnetQueryClient {
|
|||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_nym_node_version_history_paged(
|
|
||||||
&self,
|
|
||||||
start_after: Option<u32>,
|
|
||||||
limit: Option<u32>,
|
|
||||||
) -> Result<NymNodeVersionHistoryResponse, NyxdError> {
|
|
||||||
self.query_mixnet_contract(MixnetQueryMsg::GetNymNodeVersionHistory { limit, start_after })
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn get_current_nym_node_version(
|
|
||||||
&self,
|
|
||||||
) -> Result<CurrentNymNodeVersionResponse, NyxdError> {
|
|
||||||
self.query_mixnet_contract(MixnetQueryMsg::GetCurrentNymNodeVersion {})
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn get_mixnet_contract_state(&self) -> Result<ContractState, NyxdError> {
|
async fn get_mixnet_contract_state(&self) -> Result<ContractState, NyxdError> {
|
||||||
self.query_mixnet_contract(MixnetQueryMsg::GetState {})
|
self.query_mixnet_contract(MixnetQueryMsg::GetState {})
|
||||||
.await
|
.await
|
||||||
@@ -328,7 +311,10 @@ pub trait MixnetQueryClient {
|
|||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_nymnode_details(&self, node_id: NodeId) -> Result<NodeDetailsResponse, NyxdError> {
|
async fn get_nymnode_details(
|
||||||
|
&self,
|
||||||
|
node_id: NodeId,
|
||||||
|
) -> Result<NodeOwnershipResponse, NyxdError> {
|
||||||
self.query_mixnet_contract(MixnetQueryMsg::GetNymNodeDetails { node_id })
|
self.query_mixnet_contract(MixnetQueryMsg::GetNymNodeDetails { node_id })
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@@ -655,12 +641,6 @@ pub trait PagedMixnetQueryClient: MixnetQueryClient {
|
|||||||
) -> Result<Vec<PendingIntervalEvent>, NyxdError> {
|
) -> Result<Vec<PendingIntervalEvent>, NyxdError> {
|
||||||
collect_paged!(self, get_pending_interval_events_paged, events)
|
collect_paged!(self, get_pending_interval_events_paged, events)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_full_nym_node_version_history(
|
|
||||||
&self,
|
|
||||||
) -> Result<Vec<HistoricalNymNodeVersionEntry>, NyxdError> {
|
|
||||||
collect_paged!(self, get_nym_node_version_history_paged, history)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
@@ -670,7 +650,7 @@ impl<T> PagedMixnetQueryClient for T where T: MixnetQueryClient {}
|
|||||||
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
||||||
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
|
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
|
||||||
pub trait MixnetQueryClientExt: MixnetQueryClient {
|
pub trait MixnetQueryClientExt: MixnetQueryClient {
|
||||||
async fn get_rewarded_set(&self) -> Result<EpochRewardedSet, NyxdError> {
|
async fn get_rewarded_set(&self) -> Result<RewardedSet, NyxdError> {
|
||||||
let error_response = |message| Err(NyxdError::extension_query_failure("mixnet", message));
|
let error_response = |message| Err(NyxdError::extension_query_failure("mixnet", message));
|
||||||
|
|
||||||
let metadata = self.get_rewarded_set_metadata().await?;
|
let metadata = self.get_rewarded_set_metadata().await?;
|
||||||
@@ -711,16 +691,13 @@ pub trait MixnetQueryClientExt: MixnetQueryClient {
|
|||||||
return error_response("the nodes assigned for 'standby' returned unexpected epoch_id");
|
return error_response("the nodes assigned for 'standby' returned unexpected epoch_id");
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(EpochRewardedSet {
|
Ok(RewardedSet {
|
||||||
epoch_id: expected_epoch_id,
|
entry_gateways: entry.nodes,
|
||||||
assignment: RewardedSet {
|
exit_gateways: exit.nodes,
|
||||||
entry_gateways: entry.nodes,
|
layer1: layer1.nodes,
|
||||||
exit_gateways: exit.nodes,
|
layer2: layer2.nodes,
|
||||||
layer1: layer1.nodes,
|
layer3: layer3.nodes,
|
||||||
layer2: layer2.nodes,
|
standby: standby.nodes,
|
||||||
layer3: layer3.nodes,
|
|
||||||
standby: standby.nodes,
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -750,7 +727,6 @@ where
|
|||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::nyxd::contract_traits::tests::IgnoreValue;
|
use crate::nyxd::contract_traits::tests::IgnoreValue;
|
||||||
use nym_mixnet_contract_common::QueryMsg;
|
|
||||||
|
|
||||||
// it's enough that this compiles and clippy is happy about it
|
// it's enough that this compiles and clippy is happy about it
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
@@ -951,10 +927,6 @@ mod tests {
|
|||||||
MixnetQueryMsg::GetRewardedSetMetadata {} => {
|
MixnetQueryMsg::GetRewardedSetMetadata {} => {
|
||||||
client.get_rewarded_set_metadata().ignore()
|
client.get_rewarded_set_metadata().ignore()
|
||||||
}
|
}
|
||||||
QueryMsg::GetCurrentNymNodeVersion {} => client.get_current_nym_node_version().ignore(),
|
|
||||||
QueryMsg::GetNymNodeVersionHistory { limit, start_after } => client
|
|
||||||
.get_nym_node_version_history_paged(start_after, limit)
|
|
||||||
.ignore(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,44 +13,6 @@ use tracing::error;
|
|||||||
|
|
||||||
pub use cosmrs::abci::MsgResponse;
|
pub use cosmrs::abci::MsgResponse;
|
||||||
|
|
||||||
pub fn parse_singleton_u32_from_contract_response(b: Vec<u8>) -> Result<u32, NyxdError> {
|
|
||||||
if b.len() != 4 {
|
|
||||||
return Err(NyxdError::MalformedResponseData {
|
|
||||||
got: b.len(),
|
|
||||||
expected: 4,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
Ok(u32::from_be_bytes([b[0], b[1], b[2], b[3]]))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn parse_singleton_u64_from_contract_response(b: Vec<u8>) -> Result<u64, NyxdError> {
|
|
||||||
if b.len() != 8 {
|
|
||||||
return Err(NyxdError::MalformedResponseData {
|
|
||||||
got: b.len(),
|
|
||||||
expected: 8,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
Ok(u64::from_be_bytes([
|
|
||||||
b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7],
|
|
||||||
]))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct ParsedContractResponse {
|
|
||||||
pub message_index: usize,
|
|
||||||
pub response: Vec<u8>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ParsedContractResponse {
|
|
||||||
pub fn parse_singleton_u32_contract_data(self) -> Result<u32, NyxdError> {
|
|
||||||
parse_singleton_u32_from_contract_response(self.response)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn parse_singleton_u64_contract_data(self) -> Result<u64, NyxdError> {
|
|
||||||
parse_singleton_u64_from_contract_response(self.response)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn parse_msg_responses(data: Bytes) -> Vec<MsgResponse> {
|
pub fn parse_msg_responses(data: Bytes) -> Vec<MsgResponse> {
|
||||||
// it seems that currently, on wasmd 0.43 + tendermint-rs 0.37 + cosmrs 0.17.0-pre
|
// it seems that currently, on wasmd 0.43 + tendermint-rs 0.37 + cosmrs 0.17.0-pre
|
||||||
// the data is left in undecoded base64 form, but I'd imagine this might change so if the decoding fails,
|
// the data is left in undecoded base64 form, but I'd imagine this might change so if the decoding fails,
|
||||||
@@ -72,25 +34,35 @@ pub fn parse_msg_responses(data: Bytes) -> Vec<MsgResponse> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// requires there's a single response message
|
// requires there's a single response message
|
||||||
pub trait ContractResponseData: Sized {
|
pub trait ToSingletonContractData: Sized {
|
||||||
fn parse_singleton_u32_contract_data(&self) -> Result<u32, NyxdError> {
|
fn parse_singleton_u32_contract_data(&self) -> Result<u32, NyxdError> {
|
||||||
let b = self.to_singleton_contract_data()?;
|
let b = self.to_singleton_contract_data()?;
|
||||||
parse_singleton_u32_from_contract_response(b)
|
if b.len() != 4 {
|
||||||
|
return Err(NyxdError::MalformedResponseData {
|
||||||
|
got: b.len(),
|
||||||
|
expected: 4,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Ok(u32::from_be_bytes([b[0], b[1], b[2], b[3]]))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_singleton_u64_contract_data(&self) -> Result<u64, NyxdError> {
|
fn parse_singleton_u64_contract_data(&self) -> Result<u64, NyxdError> {
|
||||||
let b = self.to_singleton_contract_data()?;
|
let b = self.to_singleton_contract_data()?;
|
||||||
parse_singleton_u64_from_contract_response(b)
|
if b.len() != 8 {
|
||||||
|
return Err(NyxdError::MalformedResponseData {
|
||||||
|
got: b.len(),
|
||||||
|
expected: 8,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Ok(u64::from_be_bytes([
|
||||||
|
b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7],
|
||||||
|
]))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_singleton_contract_data(&self) -> Result<Vec<u8>, NyxdError>;
|
fn to_singleton_contract_data(&self) -> Result<Vec<u8>, NyxdError>;
|
||||||
|
|
||||||
fn to_unchecked_contract_data(&self) -> Result<Vec<Vec<u8>>, NyxdError>;
|
|
||||||
|
|
||||||
fn to_contract_data(&self) -> Result<Vec<ParsedContractResponse>, NyxdError>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ContractResponseData for ExecuteResult {
|
impl ToSingletonContractData for ExecuteResult {
|
||||||
fn to_singleton_contract_data(&self) -> Result<Vec<u8>, NyxdError> {
|
fn to_singleton_contract_data(&self) -> Result<Vec<u8>, NyxdError> {
|
||||||
if self.msg_responses.len() != 1 {
|
if self.msg_responses.len() != 1 {
|
||||||
return Err(NyxdError::UnexpectedNumberOfMsgResponses {
|
return Err(NyxdError::UnexpectedNumberOfMsgResponses {
|
||||||
@@ -100,30 +72,6 @@ impl ContractResponseData for ExecuteResult {
|
|||||||
|
|
||||||
self.msg_responses[0].to_contract_response_data()
|
self.msg_responses[0].to_contract_response_data()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_unchecked_contract_data(&self) -> Result<Vec<Vec<u8>>, NyxdError> {
|
|
||||||
self.msg_responses
|
|
||||||
.iter()
|
|
||||||
.map(ToContractResponseData::to_contract_response_data)
|
|
||||||
.collect()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn to_contract_data(&self) -> Result<Vec<ParsedContractResponse>, NyxdError> {
|
|
||||||
let mut response = Vec::new();
|
|
||||||
|
|
||||||
for (message_index, msg) in self.msg_responses.iter().enumerate() {
|
|
||||||
// unfortunately `Name` trait has not been derived for `MsgExecuteContractResponse`,
|
|
||||||
// so we have to make an explicit string comparison instead
|
|
||||||
if msg.type_url == "/cosmwasm.wasm.v1.MsgExecuteContractResponse" {
|
|
||||||
response.push(ParsedContractResponse {
|
|
||||||
message_index,
|
|
||||||
response: msg.to_contract_response_data()?,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(response)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait ToContractResponseData: Sized {
|
pub trait ToContractResponseData: Sized {
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ use tendermint_rpc::endpoint::*;
|
|||||||
use tendermint_rpc::query::Query;
|
use tendermint_rpc::query::Query;
|
||||||
use tendermint_rpc::{Error as TendermintRpcError, Order, Paging, SimpleRequest};
|
use tendermint_rpc::{Error as TendermintRpcError, Order, Paging, SimpleRequest};
|
||||||
|
|
||||||
pub use helpers::{ContractResponseData, ToContractResponseData};
|
pub use helpers::{ToContractResponseData, ToSingletonContractData};
|
||||||
|
|
||||||
#[cfg(feature = "http-client")]
|
#[cfg(feature = "http-client")]
|
||||||
use crate::http_client;
|
use crate::http_client;
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ pub struct GasPrice {
|
|||||||
pub denom: String,
|
pub denom: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Mul<Gas> for &GasPrice {
|
impl<'a> Mul<Gas> for &'a GasPrice {
|
||||||
type Output = Coin;
|
type Output = Coin;
|
||||||
|
|
||||||
fn mul(self, gas_limit: Gas) -> Self::Output {
|
fn mul(self, gas_limit: Gas) -> Self::Output {
|
||||||
|
|||||||
@@ -98,13 +98,6 @@ impl DirectSecp256k1HdWallet {
|
|||||||
Ok((private_key, public_key))
|
Ok((private_key, public_key))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn derive_extended_private_key(
|
|
||||||
&self,
|
|
||||||
hd_path: &DerivationPath,
|
|
||||||
) -> Result<XPrv, DirectSecp256k1HdWalletError> {
|
|
||||||
Ok(XPrv::derive_from_path(self.seed, hd_path)?)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn try_derive_accounts(&self) -> Result<Vec<AccountData>, DirectSecp256k1HdWalletError> {
|
pub fn try_derive_accounts(&self) -> Result<Vec<AccountData>, DirectSecp256k1HdWalletError> {
|
||||||
let mut accounts = Vec::with_capacity(self.accounts.len());
|
let mut accounts = Vec::with_capacity(self.accounts.len());
|
||||||
for derivation_info in &self.accounts {
|
for derivation_info in &self.accounts {
|
||||||
|
|||||||
@@ -48,7 +48,6 @@ nym-vesting-contract-common = { path = "../cosmwasm-smart-contracts/vesting-cont
|
|||||||
nym-coconut-dkg-common = { path = "../cosmwasm-smart-contracts/coconut-dkg" }
|
nym-coconut-dkg-common = { path = "../cosmwasm-smart-contracts/coconut-dkg" }
|
||||||
nym-multisig-contract-common = { path = "../cosmwasm-smart-contracts/multisig-contract" }
|
nym-multisig-contract-common = { path = "../cosmwasm-smart-contracts/multisig-contract" }
|
||||||
nym-ecash-contract-common = { path = "../cosmwasm-smart-contracts/ecash-contract" }
|
nym-ecash-contract-common = { path = "../cosmwasm-smart-contracts/ecash-contract" }
|
||||||
nym-ecash-time = { path = "../../common/ecash-time" }
|
|
||||||
nym-sphinx = { path = "../../common/nymsphinx" }
|
nym-sphinx = { path = "../../common/nymsphinx" }
|
||||||
nym-client-core = { path = "../../common/client-core" }
|
nym-client-core = { path = "../../common/client-core" }
|
||||||
nym-config = { path = "../../common/config" }
|
nym-config = { path = "../../common/config" }
|
||||||
@@ -57,7 +56,6 @@ nym-credentials-interface = { path = "../../common/credentials-interface" }
|
|||||||
nym-credential-storage = { path = "../../common/credential-storage" }
|
nym-credential-storage = { path = "../../common/credential-storage" }
|
||||||
nym-credential-utils = { path = "../../common/credential-utils" }
|
nym-credential-utils = { path = "../../common/credential-utils" }
|
||||||
nym-id = { path = "../nym-id" }
|
nym-id = { path = "../nym-id" }
|
||||||
nym-credential-proxy-requests = { path = "../../nym-credential-proxy/nym-credential-proxy-requests" }
|
|
||||||
|
|
||||||
nym-pemstore = { path = "../../common/pemstore", version = "0.3.0" }
|
nym-pemstore = { path = "../../common/pemstore", version = "0.3.0" }
|
||||||
nym-types = { path = "../../common/types" }
|
nym-types = { path = "../../common/types" }
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user