Compare commits
102 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 499b1c7400 | |||
| 5b536eeaf6 | |||
| 45617cd218 | |||
| 3f90de1790 | |||
| e638f87729 | |||
| d86286ef54 | |||
| b73d66e073 | |||
| 378ed88714 | |||
| 3e1ea8e855 | |||
| 50191cf80b | |||
| 54d7b37f10 | |||
| 8dda5fba5f | |||
| 93f063bb01 | |||
| 376eca688a | |||
| 54cec265e6 | |||
| 20697fd5fc | |||
| a87753f1ee | |||
| 5e9d25364f | |||
| 49e1134722 | |||
| ffcc4e8fa5 | |||
| 0337c04844 | |||
| ec77f1e7b4 | |||
| 1cd42bde0b | |||
| 6606fc8cc4 | |||
| eef3405777 | |||
| 2d7957a83b | |||
| 60e8f8254e | |||
| 7066c115e5 | |||
| fb63555ab0 | |||
| 814aeb5e7c | |||
| 45bef0da68 | |||
| 060f785ff0 | |||
| a9ef20914e | |||
| 9761644d08 | |||
| b6b8ec41eb | |||
| d7d2aaff68 | |||
| e2114dd9e5 | |||
| d247c88a74 | |||
| 2fc359f58f | |||
| 0f35f5c909 | |||
| 3fdaa7bac3 | |||
| 16c3e5ff9a | |||
| 4f5d86a50c | |||
| 9d8f14ddec | |||
| 72482180b9 | |||
| d99cb96994 | |||
| 99d2a807dd | |||
| 9400140f69 | |||
| f78bb83eab | |||
| 349e95aa07 | |||
| 5cc5484297 | |||
| 8864921260 | |||
| 7608ca768f | |||
| 7fa1cdba93 | |||
| d59f05f9d4 | |||
| f819b33628 | |||
| 7d2b1ca9a8 | |||
| 08f5749887 | |||
| 3573d1e6a6 | |||
| 1015251bd9 | |||
| 0492d84ea8 | |||
| 70c1e4fd85 | |||
| 5047ed2722 | |||
| 8630cefddb | |||
| 68a1d43cbf | |||
| fedaf00375 | |||
| 7660f007c8 | |||
| 747675f52f | |||
| c7b3bd1608 | |||
| 6fc231821b | |||
| fa6efbaa2a | |||
| e9ade22b10 | |||
| 731f69acc3 | |||
| a0e55f49d4 | |||
| 7563cccf49 | |||
| 95274e3883 | |||
| c8ca174b87 | |||
| 4eccc59f6f | |||
| 56becc3a34 | |||
| 13a6f0b5ef | |||
| 4f1bac204c | |||
| f87f57bddd | |||
| c49f7f91ed | |||
| 8c8e085796 | |||
| 4bb05f3698 | |||
| 8fcea5f350 | |||
| 42739597ed | |||
| 699aa6116a | |||
| 4519bd6571 | |||
| 5083b420ec | |||
| 6f4421dc4a | |||
| 415c30fcc9 | |||
| 8e8eceb894 | |||
| 546482916d | |||
| 530d744d6d | |||
| 2e8e9a4c0a | |||
| 109de83128 | |||
| 0c36e64526 | |||
| d423cde71c | |||
| 1130d0fe3e | |||
| f53d2aa4cd | |||
| c406814886 |
@@ -26,7 +26,6 @@ jobs:
|
|||||||
runs-on: ${{ matrix.platform }}
|
runs-on: ${{ matrix.platform }}
|
||||||
env:
|
env:
|
||||||
CARGO_TERM_COLOR: always
|
CARGO_TERM_COLOR: always
|
||||||
RUSTUP_PERMIT_COPY_RENAME: 1
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
@@ -80,6 +79,7 @@ jobs:
|
|||||||
target/release/nym-socks5-client
|
target/release/nym-socks5-client
|
||||||
target/release/nym-api
|
target/release/nym-api
|
||||||
target/release/nym-network-requester
|
target/release/nym-network-requester
|
||||||
|
target/release/nym-data-observatory
|
||||||
target/release/nym-cli
|
target/release/nym-cli
|
||||||
target/release/nymvisor
|
target/release/nymvisor
|
||||||
target/release/nym-node
|
target/release/nym-node
|
||||||
@@ -97,6 +97,7 @@ jobs:
|
|||||||
cp target/release/nym-socks5-client $OUTPUT_DIR
|
cp target/release/nym-socks5-client $OUTPUT_DIR
|
||||||
cp target/release/nym-api $OUTPUT_DIR
|
cp target/release/nym-api $OUTPUT_DIR
|
||||||
cp target/release/nym-network-requester $OUTPUT_DIR
|
cp target/release/nym-network-requester $OUTPUT_DIR
|
||||||
|
cp target/release/nym-data-observatory $OUTPUT_DIR
|
||||||
cp target/release/nymvisor $OUTPUT_DIR
|
cp target/release/nymvisor $OUTPUT_DIR
|
||||||
cp target/release/nym-node $OUTPUT_DIR
|
cp target/release/nym-node $OUTPUT_DIR
|
||||||
cp target/release/nym-cli $OUTPUT_DIR
|
cp target/release/nym-cli $OUTPUT_DIR
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ jobs:
|
|||||||
runs-on: arc-ubuntu-22.04
|
runs-on: arc-ubuntu-22.04
|
||||||
env:
|
env:
|
||||||
CARGO_TERM_COLOR: always
|
CARGO_TERM_COLOR: always
|
||||||
RUSTUP_PERMIT_COPY_RENAME: 1
|
|
||||||
steps:
|
steps:
|
||||||
- name: Check out repository code
|
- name: Check out repository code
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|||||||
@@ -8,18 +8,16 @@ on:
|
|||||||
- 'explorer-api/**'
|
- 'explorer-api/**'
|
||||||
- 'gateway/**'
|
- 'gateway/**'
|
||||||
- 'integrations/**'
|
- 'integrations/**'
|
||||||
- 'nym-api/**'
|
- 'mixnode/**'
|
||||||
- 'nym-credential-proxy/**'
|
|
||||||
- 'nym-network-monitor/**'
|
|
||||||
- 'nym-node/**'
|
|
||||||
- 'nym-node-status-api/**'
|
|
||||||
- 'nym-outfox/**'
|
|
||||||
- 'nym-validator-rewarder/**'
|
|
||||||
- 'nyx-chain-watcher/**'
|
|
||||||
- 'sdk/ffi/**'
|
|
||||||
- 'sdk/rust/**'
|
- 'sdk/rust/**'
|
||||||
|
- 'sdk/lib/**'
|
||||||
- 'service-providers/**'
|
- 'service-providers/**'
|
||||||
- 'nym-browser-extension/storage/**'
|
- 'nym-network-monitor/**'
|
||||||
|
- 'nym-api/**'
|
||||||
|
- 'nym-node/**'
|
||||||
|
- 'nym-outfox/**'
|
||||||
|
- 'nym-data-observatory/**'
|
||||||
|
- 'nym-validator-rewarder/**'
|
||||||
- 'tools/**'
|
- 'tools/**'
|
||||||
- 'wasm/**'
|
- 'wasm/**'
|
||||||
- 'Cargo.toml'
|
- 'Cargo.toml'
|
||||||
@@ -37,7 +35,6 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
CARGO_TERM_COLOR: always
|
CARGO_TERM_COLOR: always
|
||||||
IPINFO_API_TOKEN: ${{ secrets.IPINFO_API_TOKEN }}
|
IPINFO_API_TOKEN: ${{ secrets.IPINFO_API_TOKEN }}
|
||||||
RUSTUP_PERMIT_COPY_RENAME: 1
|
|
||||||
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
|
||||||
@@ -55,20 +52,6 @@ jobs:
|
|||||||
override: true
|
override: true
|
||||||
components: rustfmt, clippy
|
components: rustfmt, clippy
|
||||||
|
|
||||||
# To avoid running out of disk space, skip generating debug symbols
|
|
||||||
- name: Set debug to false (unix)
|
|
||||||
if: contains(matrix.os, 'ubuntu') || contains(matrix.os, 'mac')
|
|
||||||
run: |
|
|
||||||
sed -i.bak 's/\[profile.dev\]/\[profile.dev\]\ndebug = false/' Cargo.toml
|
|
||||||
git diff
|
|
||||||
|
|
||||||
- name: Set debug to false (win)
|
|
||||||
if: contains(matrix.os, 'windows')
|
|
||||||
shell: pwsh
|
|
||||||
run: |
|
|
||||||
(Get-Content Cargo.toml) -replace '\[profile.dev\]', "`$&`ndebug = false" | Set-Content Cargo.toml
|
|
||||||
git diff
|
|
||||||
|
|
||||||
- name: Check formatting
|
- name: Check formatting
|
||||||
uses: actions-rs/cargo@v1
|
uses: actions-rs/cargo@v1
|
||||||
with:
|
with:
|
||||||
|
|||||||
@@ -9,8 +9,6 @@ on:
|
|||||||
paths:
|
paths:
|
||||||
- 'contracts/**'
|
- 'contracts/**'
|
||||||
- 'common/**'
|
- 'common/**'
|
||||||
- 'Cargo.lock'
|
|
||||||
- 'Cargo.toml'
|
|
||||||
- '.github/workflows/ci-contracts.yml'
|
- '.github/workflows/ci-contracts.yml'
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
|||||||
@@ -30,12 +30,6 @@ jobs:
|
|||||||
override: true
|
override: true
|
||||||
components: rustfmt, clippy
|
components: rustfmt, clippy
|
||||||
|
|
||||||
- name: Set debug to false
|
|
||||||
working-directory: nym-wallet
|
|
||||||
run: |
|
|
||||||
sed -i.bak '1s/^/\[profile.dev\]\ndebug = false\n\n/' Cargo.toml
|
|
||||||
git diff
|
|
||||||
|
|
||||||
- name: Build all binaries
|
- name: Build all binaries
|
||||||
uses: actions-rs/cargo@v1
|
uses: actions-rs/cargo@v1
|
||||||
with:
|
with:
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
name: ci-sdk-wasm
|
name: ci-sdk-wasm
|
||||||
|
|
||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
|
||||||
pull_request:
|
pull_request:
|
||||||
paths:
|
paths:
|
||||||
- 'wasm/**'
|
- 'wasm/**'
|
||||||
@@ -45,11 +44,6 @@ jobs:
|
|||||||
- name: Install wasm-bindgen-cli
|
- name: Install wasm-bindgen-cli
|
||||||
run: cargo install wasm-bindgen-cli
|
run: cargo install wasm-bindgen-cli
|
||||||
|
|
||||||
- name: Set debug to false
|
|
||||||
run: |
|
|
||||||
sed -i.bak 's/\[profile.dev\]/\[profile.dev\]\ndebug = false/' Cargo.toml
|
|
||||||
git diff
|
|
||||||
|
|
||||||
- name: "Build"
|
- name: "Build"
|
||||||
run: make sdk-wasm-build
|
run: make sdk-wasm-build
|
||||||
|
|
||||||
|
|||||||
@@ -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.6
|
||||||
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.6
|
||||||
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.6
|
||||||
id: get_version
|
id: get_version
|
||||||
with:
|
with:
|
||||||
cmd: yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/nym-network-monitor/Cargo.toml
|
cmd: yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/nym-network-monitor/Cargo.toml
|
||||||
|
|||||||
@@ -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.6
|
||||||
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.6
|
||||||
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.6
|
||||||
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.6
|
||||||
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.6
|
||||||
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
|
||||||
|
|||||||
-311
@@ -4,317 +4,6 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
## [2025.4-dorina-patched] (2025-03-06)
|
|
||||||
|
|
||||||
- bugfix: make sure to correctly decode response content when putting it into error message ([#5571])
|
|
||||||
- Tweak surb management to be more conservative ([#5570])
|
|
||||||
- Deserialize v5 authenticator requests ([#5568])
|
|
||||||
- chore: additional logs when attempting to load ecash keys ([#5567])
|
|
||||||
- add full response body to error message upon decoding failure ([#5566])
|
|
||||||
- hotfix: ensure we bail on merkle leaves insertion upon missing data ([#5565])
|
|
||||||
- feature: v2 authentication request (#5537) ([#5563])
|
|
||||||
- Create authenticator v5 request/response types ([#5561])
|
|
||||||
|
|
||||||
[#5571]: https://github.com/nymtech/nym/pull/5571
|
|
||||||
[#5570]: https://github.com/nymtech/nym/pull/5570
|
|
||||||
[#5568]: https://github.com/nymtech/nym/pull/5568
|
|
||||||
[#5567]: https://github.com/nymtech/nym/pull/5567
|
|
||||||
[#5566]: https://github.com/nymtech/nym/pull/5566
|
|
||||||
[#5565]: https://github.com/nymtech/nym/pull/5565
|
|
||||||
[#5563]: https://github.com/nymtech/nym/pull/5563
|
|
||||||
[#5561]: https://github.com/nymtech/nym/pull/5561
|
|
||||||
|
|
||||||
## [2025.4-dorina] (2025-03-04)
|
|
||||||
|
|
||||||
- fixed sphinx version metrics registration ([#5546])
|
|
||||||
- Feature/chain status api ([#5539])
|
|
||||||
- Add SURBs soft threshold ([#5535])
|
|
||||||
- Simplify IPR v8 ([#5532])
|
|
||||||
- Shared instance for DNS AsyncResolver ([#5523])
|
|
||||||
- merge #5512 again after reverting due to incorrect rebase ([#5520])
|
|
||||||
- cherry-pick 17d3ff2d775f61aee381d90a304ed416c08f33fc onto dorina ([#5519])
|
|
||||||
- cherry-pick 6e5d0dac1b75413c5f09122b0d953f8ec6ef48df onto dorina ([#5518])
|
|
||||||
- chore: workspace global panic preventing lints ([#5512])
|
|
||||||
- bugfix: dont query for ecash apis unless necessary when spending ticketbooks ([#5508])
|
|
||||||
- bugfix: bound check when recovering a reply SURB ([#5502])
|
|
||||||
- chore: removed all old coconut code ([#5500])
|
|
||||||
- IPR request types v8 ([#5498])
|
|
||||||
- Support static routes for HTTP requests ([#5487])
|
|
||||||
- build(deps): bump the patch-updates group across 1 directory with 3 updates ([#5482])
|
|
||||||
- added missing import to doctest ([#5480])
|
|
||||||
- adjusted TestSetup::new_complex to ensure bonded node's existence ([#5478])
|
|
||||||
- Trigger contracts CI on main workspace Cargo changes ([#5477])
|
|
||||||
- build(deps): bump http from 1.1.0 to 1.2.0 ([#5472])
|
|
||||||
- build(deps): bump utoipa-swagger-ui from 8.0.3 to 8.1.0 ([#5471])
|
|
||||||
- build(deps): bump colored from 2.1.0 to 2.2.0 ([#5470])
|
|
||||||
- build(deps): bump celes from 2.4.0 to 2.5.0 ([#5469])
|
|
||||||
- build(deps): bump the patch-updates group with 2 updates ([#5467])
|
|
||||||
- build(deps): bump elliptic from 6.5.4 to 6.6.1 in /docker/typescript_client/upload_contract ([#5463])
|
|
||||||
- Run cargo autoinherit ([#5460])
|
|
||||||
- Fix clippy::precedence ([#5457])
|
|
||||||
- Provide Interval context with node descriptor endpoints ([#5456])
|
|
||||||
- fix: update fx average rate calcs to ignore 0 values ([#5454])
|
|
||||||
- Feature/add gbp currency ([#5453])
|
|
||||||
- Add helper to extract a list of sqlite files with journal files wal/shm ([#5452])
|
|
||||||
- Add a middleware layer to the nym api allowing for data compression ([#5451])
|
|
||||||
- Condense core API functionalities and enable gzip decompression for reqwest payloads ([#5450])
|
|
||||||
- build(deps): bump uniffi_build from 0.25.3 to 0.29.0 ([#5448])
|
|
||||||
- Upgrade tower to 0.5.2 ([#5446])
|
|
||||||
- build(deps): bump hickory-proto from 0.24.2 to 0.24.3 ([#5444])
|
|
||||||
- Seedable clients ([#5440])
|
|
||||||
- build(deps): bump the patch-updates group across 1 directory with 10 updates ([#5439])
|
|
||||||
- Remove all recv_with_delay and add shutdown condition to loops in client-core ([#5435])
|
|
||||||
- Disable the test for checking the remaining bandwidth in nym-node-status-api ([#5425])
|
|
||||||
- Dz nym node stats ([#5418])
|
|
||||||
- build(deps): bump hyper from 1.4.1 to 1.6.0 ([#5416])
|
|
||||||
- build(deps): bump publicsuffix from 2.2.3 to 2.3.0 ([#5367])
|
|
||||||
- Nymnode entrypoint docker ([#5300])
|
|
||||||
|
|
||||||
[#5546]: https://github.com/nymtech/nym/pull/5546
|
|
||||||
[#5539]: https://github.com/nymtech/nym/pull/5539
|
|
||||||
[#5535]: https://github.com/nymtech/nym/pull/5535
|
|
||||||
[#5532]: https://github.com/nymtech/nym/pull/5532
|
|
||||||
[#5523]: https://github.com/nymtech/nym/pull/5523
|
|
||||||
[#5520]: https://github.com/nymtech/nym/pull/5520
|
|
||||||
[#5519]: https://github.com/nymtech/nym/pull/5519
|
|
||||||
[#5518]: https://github.com/nymtech/nym/pull/5518
|
|
||||||
[#5512]: https://github.com/nymtech/nym/pull/5512
|
|
||||||
[#5508]: https://github.com/nymtech/nym/pull/5508
|
|
||||||
[#5502]: https://github.com/nymtech/nym/pull/5502
|
|
||||||
[#5500]: https://github.com/nymtech/nym/pull/5500
|
|
||||||
[#5498]: https://github.com/nymtech/nym/pull/5498
|
|
||||||
[#5487]: https://github.com/nymtech/nym/pull/5487
|
|
||||||
[#5482]: https://github.com/nymtech/nym/pull/5482
|
|
||||||
[#5480]: https://github.com/nymtech/nym/pull/5480
|
|
||||||
[#5478]: https://github.com/nymtech/nym/pull/5478
|
|
||||||
[#5477]: https://github.com/nymtech/nym/pull/5477
|
|
||||||
[#5472]: https://github.com/nymtech/nym/pull/5472
|
|
||||||
[#5471]: https://github.com/nymtech/nym/pull/5471
|
|
||||||
[#5470]: https://github.com/nymtech/nym/pull/5470
|
|
||||||
[#5469]: https://github.com/nymtech/nym/pull/5469
|
|
||||||
[#5467]: https://github.com/nymtech/nym/pull/5467
|
|
||||||
[#5463]: https://github.com/nymtech/nym/pull/5463
|
|
||||||
[#5460]: https://github.com/nymtech/nym/pull/5460
|
|
||||||
[#5457]: https://github.com/nymtech/nym/pull/5457
|
|
||||||
[#5456]: https://github.com/nymtech/nym/pull/5456
|
|
||||||
[#5454]: https://github.com/nymtech/nym/pull/5454
|
|
||||||
[#5453]: https://github.com/nymtech/nym/pull/5453
|
|
||||||
[#5452]: https://github.com/nymtech/nym/pull/5452
|
|
||||||
[#5451]: https://github.com/nymtech/nym/pull/5451
|
|
||||||
[#5450]: https://github.com/nymtech/nym/pull/5450
|
|
||||||
[#5448]: https://github.com/nymtech/nym/pull/5448
|
|
||||||
[#5446]: https://github.com/nymtech/nym/pull/5446
|
|
||||||
[#5444]: https://github.com/nymtech/nym/pull/5444
|
|
||||||
[#5440]: https://github.com/nymtech/nym/pull/5440
|
|
||||||
[#5439]: https://github.com/nymtech/nym/pull/5439
|
|
||||||
[#5435]: https://github.com/nymtech/nym/pull/5435
|
|
||||||
[#5425]: https://github.com/nymtech/nym/pull/5425
|
|
||||||
[#5418]: https://github.com/nymtech/nym/pull/5418
|
|
||||||
[#5416]: https://github.com/nymtech/nym/pull/5416
|
|
||||||
[#5367]: https://github.com/nymtech/nym/pull/5367
|
|
||||||
[#5300]: https://github.com/nymtech/nym/pull/5300
|
|
||||||
|
|
||||||
## [2025.3-ruta] (2025-02-10)
|
|
||||||
|
|
||||||
- Push down forget me to client configs ([#5431])
|
|
||||||
- Fix statistics shutdown ([#5426])
|
|
||||||
- Make wait_for_graceful_shutdown to be pub ([#5424])
|
|
||||||
- Upgrade to thiserror 2.0 ([#5414])
|
|
||||||
- build(deps): bump the patch-updates group across 1 directory with 9 updates ([#5406])
|
|
||||||
- Relocate a validator api function ([#5401])
|
|
||||||
- Send shutdown instead of panic when reaching max fail ([#5398])
|
|
||||||
- Change Explorer URL to new smooshed nodes ([#5396])
|
|
||||||
- reduce log severity for checking topology validity ([#5395])
|
|
||||||
- MixnetClient can send ClientRequests ([#5381])
|
|
||||||
- Fix missing path triggers for CI ([#5380])
|
|
||||||
- Uncouple storage reference for bandwidth client ([#5372])
|
|
||||||
- build(deps): bump tokio from 1.40.0 to 1.43.0 ([#5370])
|
|
||||||
- DNS resolver configuration for internal HTTP client lookups ([#5355])
|
|
||||||
- Update README.md ([#5328])
|
|
||||||
- Update README.md ([#5327])
|
|
||||||
|
|
||||||
[#5431]: https://github.com/nymtech/nym/pull/5431
|
|
||||||
[#5426]: https://github.com/nymtech/nym/pull/5426
|
|
||||||
[#5424]: https://github.com/nymtech/nym/pull/5424
|
|
||||||
[#5414]: https://github.com/nymtech/nym/pull/5414
|
|
||||||
[#5406]: https://github.com/nymtech/nym/pull/5406
|
|
||||||
[#5401]: https://github.com/nymtech/nym/pull/5401
|
|
||||||
[#5398]: https://github.com/nymtech/nym/pull/5398
|
|
||||||
[#5396]: https://github.com/nymtech/nym/pull/5396
|
|
||||||
[#5395]: https://github.com/nymtech/nym/pull/5395
|
|
||||||
[#5381]: https://github.com/nymtech/nym/pull/5381
|
|
||||||
[#5380]: https://github.com/nymtech/nym/pull/5380
|
|
||||||
[#5372]: https://github.com/nymtech/nym/pull/5372
|
|
||||||
[#5370]: https://github.com/nymtech/nym/pull/5370
|
|
||||||
[#5355]: https://github.com/nymtech/nym/pull/5355
|
|
||||||
[#5328]: https://github.com/nymtech/nym/pull/5328
|
|
||||||
[#5327]: https://github.com/nymtech/nym/pull/5327
|
|
||||||
|
|
||||||
## [2025.2-hu] (2025-02-04)
|
|
||||||
|
|
||||||
- Feature/remove double spending bloomfilter ([#5417])
|
|
||||||
- HU - Downgrade harmless log message from info to debug ([#5405])
|
|
||||||
- lower default ticket verification quorum to 0.7 ([#5404])
|
|
||||||
- Downgrade harmless log message from info to debug ([#5403])
|
|
||||||
- Redirect from mixnode page to nodes page ([#5397])
|
|
||||||
- chore :update version of chain watcher and validator rewarder ([#5394])
|
|
||||||
- bugfix: correctly handle ingore epoch roles flag ([#5390])
|
|
||||||
- bugfix: terminate mixnet socket listener on shutdown ([#5389])
|
|
||||||
- feat: make client ignore dual mode nodes by default ([#5388])
|
|
||||||
- Handle ecash network errors differently ([#5378])
|
|
||||||
- Remove empty ephemeral keys ([#5376])
|
|
||||||
- fixed sql migration for adding default message timestamp ([#5374])
|
|
||||||
- Bind to [::] on nym-node for both IP versions ([#5361])
|
|
||||||
- exposed NymApiClient method for obtaining node performance history ([#5360])
|
|
||||||
- Client gateway selection ([#5358])
|
|
||||||
- chore: refresh wasm sdk ([#5353])
|
|
||||||
- chore: update indexed_db_futures ([#5347])
|
|
||||||
- build(deps): bump mikefarah/yq from 4.44.6 to 4.45.1 ([#5342])
|
|
||||||
- updated cosmrs and tendermint-rpc to their most recent versions ([#5339])
|
|
||||||
- build(deps): bump ts-rs from 10.0.0 to 10.1.0 ([#5338])
|
|
||||||
- build(deps): bump tempfile from 3.14.0 to 3.15.0 ([#5337])
|
|
||||||
- build(deps): bump the patch-updates group with 8 updates ([#5336])
|
|
||||||
- feature: introduce /load endpoint for self-reported quantised NymNode load ([#5326])
|
|
||||||
- feature: `CancellationToken`-based shutdowns ([#5325])
|
|
||||||
- Use expect in geodata test to give error message on failure ([#5314])
|
|
||||||
- feature: periodically remove stale gateway messages ([#5312])
|
|
||||||
- build(deps): bump the patch-updates group across 1 directory with 35 updates ([#5310])
|
|
||||||
- Add dependabot assignes for the root cargo ecosystem ([#5297])
|
|
||||||
- Move tun constants to network defaults ([#5286])
|
|
||||||
- Include IPINFO_API_TOKEN in nightly CI ([#5285])
|
|
||||||
- Nyx Chain Watcher ([#5274])
|
|
||||||
- bugfix: remove unnecessary arguments for nym-api swagger endpoints ([#5272])
|
|
||||||
- feature: nym topology revamp ([#5271])
|
|
||||||
- Add windows to CI builds ([#5269])
|
|
||||||
- http-api-client: deduplicate code ([#5267])
|
|
||||||
- build(deps): bump http from 1.1.0 to 1.2.0 ([#5228])
|
|
||||||
- NS API: add mixnet scraper ([#5200])
|
|
||||||
- build(deps): bump criterion from 0.4.0 to 0.5.1 ([#4911])
|
|
||||||
|
|
||||||
[#5417]: https://github.com/nymtech/nym/pull/5417
|
|
||||||
[#5405]: https://github.com/nymtech/nym/pull/5405
|
|
||||||
[#5404]: https://github.com/nymtech/nym/pull/5404
|
|
||||||
[#5403]: https://github.com/nymtech/nym/pull/5403
|
|
||||||
[#5397]: https://github.com/nymtech/nym/pull/5397
|
|
||||||
[#5394]: https://github.com/nymtech/nym/pull/5394
|
|
||||||
[#5390]: https://github.com/nymtech/nym/pull/5390
|
|
||||||
[#5389]: https://github.com/nymtech/nym/pull/5389
|
|
||||||
[#5388]: https://github.com/nymtech/nym/pull/5388
|
|
||||||
[#5378]: https://github.com/nymtech/nym/pull/5378
|
|
||||||
[#5376]: https://github.com/nymtech/nym/pull/5376
|
|
||||||
[#5374]: https://github.com/nymtech/nym/pull/5374
|
|
||||||
[#5361]: https://github.com/nymtech/nym/pull/5361
|
|
||||||
[#5360]: https://github.com/nymtech/nym/pull/5360
|
|
||||||
[#5358]: https://github.com/nymtech/nym/pull/5358
|
|
||||||
[#5353]: https://github.com/nymtech/nym/pull/5353
|
|
||||||
[#5347]: https://github.com/nymtech/nym/pull/5347
|
|
||||||
[#5342]: https://github.com/nymtech/nym/pull/5342
|
|
||||||
[#5339]: https://github.com/nymtech/nym/pull/5339
|
|
||||||
[#5338]: https://github.com/nymtech/nym/pull/5338
|
|
||||||
[#5337]: https://github.com/nymtech/nym/pull/5337
|
|
||||||
[#5336]: https://github.com/nymtech/nym/pull/5336
|
|
||||||
[#5326]: https://github.com/nymtech/nym/pull/5326
|
|
||||||
[#5325]: https://github.com/nymtech/nym/pull/5325
|
|
||||||
[#5314]: https://github.com/nymtech/nym/pull/5314
|
|
||||||
[#5312]: https://github.com/nymtech/nym/pull/5312
|
|
||||||
[#5310]: https://github.com/nymtech/nym/pull/5310
|
|
||||||
[#5297]: https://github.com/nymtech/nym/pull/5297
|
|
||||||
[#5286]: https://github.com/nymtech/nym/pull/5286
|
|
||||||
[#5285]: https://github.com/nymtech/nym/pull/5285
|
|
||||||
[#5274]: https://github.com/nymtech/nym/pull/5274
|
|
||||||
[#5272]: https://github.com/nymtech/nym/pull/5272
|
|
||||||
[#5271]: https://github.com/nymtech/nym/pull/5271
|
|
||||||
[#5269]: https://github.com/nymtech/nym/pull/5269
|
|
||||||
[#5267]: https://github.com/nymtech/nym/pull/5267
|
|
||||||
[#5228]: https://github.com/nymtech/nym/pull/5228
|
|
||||||
[#5200]: https://github.com/nymtech/nym/pull/5200
|
|
||||||
[#4911]: https://github.com/nymtech/nym/pull/4911
|
|
||||||
|
|
||||||
## [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)
|
## [2024.14-crunch] (2024-12-11)
|
||||||
|
|
||||||
- Merge/release/2024.14-crunch ([#5242])
|
- Merge/release/2024.14-crunch ([#5242])
|
||||||
|
|||||||
Generated
+1413
-2270
File diff suppressed because it is too large
Load Diff
+95
-107
@@ -48,12 +48,13 @@ members = [
|
|||||||
"common/credentials-interface",
|
"common/credentials-interface",
|
||||||
"common/crypto",
|
"common/crypto",
|
||||||
"common/dkg",
|
"common/dkg",
|
||||||
|
"common/ecash-double-spending",
|
||||||
"common/ecash-time",
|
"common/ecash-time",
|
||||||
"common/execute",
|
"common/execute",
|
||||||
"common/exit-policy",
|
"common/exit-policy",
|
||||||
"common/gateway-requests",
|
"common/gateway-requests",
|
||||||
"common/gateway-stats-storage",
|
|
||||||
"common/gateway-storage",
|
"common/gateway-storage",
|
||||||
|
"common/gateway-stats-storage",
|
||||||
"common/http-api-client",
|
"common/http-api-client",
|
||||||
"common/http-api-common",
|
"common/http-api-common",
|
||||||
"common/inclusion-probability",
|
"common/inclusion-probability",
|
||||||
@@ -66,6 +67,7 @@ members = [
|
|||||||
"common/nym-id",
|
"common/nym-id",
|
||||||
"common/nym-metrics",
|
"common/nym-metrics",
|
||||||
"common/nym_offline_compact_ecash",
|
"common/nym_offline_compact_ecash",
|
||||||
|
"common/nymcoconut",
|
||||||
"common/nymsphinx",
|
"common/nymsphinx",
|
||||||
"common/nymsphinx/acknowledgements",
|
"common/nymsphinx/acknowledgements",
|
||||||
"common/nymsphinx/addressing",
|
"common/nymsphinx/addressing",
|
||||||
@@ -91,7 +93,6 @@ members = [
|
|||||||
"common/topology",
|
"common/topology",
|
||||||
"common/tun",
|
"common/tun",
|
||||||
"common/types",
|
"common/types",
|
||||||
"common/verloc",
|
|
||||||
"common/wasm/client-core",
|
"common/wasm/client-core",
|
||||||
"common/wasm/storage",
|
"common/wasm/storage",
|
||||||
"common/wasm/utils",
|
"common/wasm/utils",
|
||||||
@@ -103,22 +104,6 @@ members = [
|
|||||||
"explorer-api/explorer-client",
|
"explorer-api/explorer-client",
|
||||||
"gateway",
|
"gateway",
|
||||||
"integrations/bity",
|
"integrations/bity",
|
||||||
"nym-api",
|
|
||||||
"nym-api/nym-api-requests",
|
|
||||||
"nym-browser-extension/storage",
|
|
||||||
"nym-credential-proxy/nym-credential-proxy",
|
|
||||||
"nym-credential-proxy/nym-credential-proxy-requests",
|
|
||||||
"nym-credential-proxy/vpn-api-lib-wasm",
|
|
||||||
"nym-network-monitor",
|
|
||||||
"nym-node",
|
|
||||||
"nym-node-status-api/nym-node-status-agent",
|
|
||||||
"nym-node-status-api/nym-node-status-api",
|
|
||||||
"nym-node-status-api/nym-node-status-client",
|
|
||||||
"nym-node/nym-node-metrics",
|
|
||||||
"nym-node/nym-node-requests",
|
|
||||||
"nym-outfox",
|
|
||||||
"nym-validator-rewarder",
|
|
||||||
"nyx-chain-watcher",
|
|
||||||
"sdk/ffi/cpp",
|
"sdk/ffi/cpp",
|
||||||
"sdk/ffi/go",
|
"sdk/ffi/go",
|
||||||
"sdk/ffi/shared",
|
"sdk/ffi/shared",
|
||||||
@@ -127,16 +112,26 @@ members = [
|
|||||||
"service-providers/common",
|
"service-providers/common",
|
||||||
"service-providers/ip-packet-router",
|
"service-providers/ip-packet-router",
|
||||||
"service-providers/network-requester",
|
"service-providers/network-requester",
|
||||||
"tools/echo-server",
|
"nym-api",
|
||||||
"tools/echo-server",
|
"nym-api/nym-api-requests",
|
||||||
"tools/internal/contract-state-importer/importer-cli",
|
"nym-browser-extension/storage",
|
||||||
"tools/internal/contract-state-importer/importer-contract",
|
"nym-credential-proxy/nym-credential-proxy",
|
||||||
"tools/internal/mixnet-connectivity-check",
|
"nym-credential-proxy/nym-credential-proxy-requests",
|
||||||
# "tools/internal/sdk-version-bump",
|
"nym-credential-proxy/vpn-api-lib-wasm",
|
||||||
|
"nym-network-monitor",
|
||||||
|
"nyx-chain-watcher",
|
||||||
|
"nym-node",
|
||||||
|
"nym-node/nym-node-requests",
|
||||||
|
"nym-node/nym-node-metrics",
|
||||||
|
"nym-node-status-api/nym-node-status-agent",
|
||||||
|
"nym-node-status-api/nym-node-status-api",
|
||||||
|
"nym-node-status-api/nym-node-status-client",
|
||||||
|
"nym-outfox",
|
||||||
|
"nym-validator-rewarder",
|
||||||
|
# "tools/echo-server",
|
||||||
"tools/internal/ssl-inject",
|
"tools/internal/ssl-inject",
|
||||||
|
# "tools/internal/sdk-version-bump",
|
||||||
"tools/internal/testnet-manager",
|
"tools/internal/testnet-manager",
|
||||||
"tools/internal/testnet-manager",
|
|
||||||
"tools/internal/testnet-manager/dkg-bypass-contract",
|
|
||||||
"tools/internal/testnet-manager/dkg-bypass-contract",
|
"tools/internal/testnet-manager/dkg-bypass-contract",
|
||||||
"tools/nym-cli",
|
"tools/nym-cli",
|
||||||
"tools/nym-id-cli",
|
"tools/nym-id-cli",
|
||||||
@@ -148,6 +143,13 @@ members = [
|
|||||||
"wasm/mix-fetch",
|
"wasm/mix-fetch",
|
||||||
"wasm/node-tester",
|
"wasm/node-tester",
|
||||||
"wasm/zknym-lib",
|
"wasm/zknym-lib",
|
||||||
|
"tools/echo-server",
|
||||||
|
"tools/internal/contract-state-importer/importer-cli",
|
||||||
|
"tools/internal/contract-state-importer/importer-contract",
|
||||||
|
"tools/internal/testnet-manager",
|
||||||
|
"tools/internal/testnet-manager/dkg-bypass-contract",
|
||||||
|
"common/verloc",
|
||||||
|
"tools/internal/mixnet-connectivity-check", "tools/internal/mixnet-check-all-gateways",
|
||||||
]
|
]
|
||||||
|
|
||||||
default-members = [
|
default-members = [
|
||||||
@@ -171,6 +173,7 @@ exclude = [
|
|||||||
"explorer",
|
"explorer",
|
||||||
"contracts",
|
"contracts",
|
||||||
"nym-wallet",
|
"nym-wallet",
|
||||||
|
"nym-vpn/ui/src-tauri",
|
||||||
"cpu-cycles",
|
"cpu-cycles",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -186,49 +189,45 @@ readme = "README.md"
|
|||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
addr = "0.15.6"
|
addr = "0.15.6"
|
||||||
aead = "0.5.2"
|
|
||||||
aes = "0.8.1"
|
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"
|
||||||
ammonia = "4"
|
aead = "0.5.2"
|
||||||
anyhow = "1.0.97"
|
anyhow = "1.0.90"
|
||||||
arc-swap = "1.7.1"
|
|
||||||
argon2 = "0.5.0"
|
argon2 = "0.5.0"
|
||||||
async-trait = "0.1.87"
|
async-trait = "0.1.83"
|
||||||
axum = "0.7.5"
|
|
||||||
axum-client-ip = "0.6.1"
|
axum-client-ip = "0.6.1"
|
||||||
|
axum = "0.7.5"
|
||||||
axum-extra = "0.9.4"
|
axum-extra = "0.9.4"
|
||||||
axum-test = "16.2.0"
|
|
||||||
base64 = "0.22.1"
|
base64 = "0.22.1"
|
||||||
base85rs = "0.1.3"
|
|
||||||
bincode = "1.3.3"
|
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.6.1"
|
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"
|
||||||
bytes = "1.7.2"
|
bytes = "1.7.2"
|
||||||
cargo_metadata = "0.18.1"
|
cargo_metadata = "0.18.1"
|
||||||
celes = "2.5.0"
|
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.40"
|
chrono = "0.4.31"
|
||||||
cipher = "0.4.3"
|
cipher = "0.4.3"
|
||||||
clap = "4.5.31"
|
clap = "4.5.20"
|
||||||
clap_complete = "4.5"
|
clap_complete = "4.5"
|
||||||
clap_complete_fig = "4.5"
|
clap_complete_fig = "4.5"
|
||||||
colored = "2.2"
|
colored = "2.0"
|
||||||
comfy-table = "7.1.4"
|
comfy-table = "7.1.1"
|
||||||
console = "0.15.11"
|
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"
|
||||||
@@ -241,60 +240,58 @@ doc-comment = "0.3"
|
|||||||
dotenvy = "0.15.6"
|
dotenvy = "0.15.6"
|
||||||
ecdsa = "0.16"
|
ecdsa = "0.16"
|
||||||
ed25519-dalek = "2.1"
|
ed25519-dalek = "2.1"
|
||||||
encoding_rs = "0.8.35"
|
|
||||||
env_logger = "0.11.6"
|
|
||||||
envy = "0.4"
|
|
||||||
etherparse = "0.13.0"
|
etherparse = "0.13.0"
|
||||||
|
envy = "0.4"
|
||||||
eyre = "0.6.9"
|
eyre = "0.6.9"
|
||||||
fastrand = "2.1.1"
|
fastrand = "2.1.1"
|
||||||
flate2 = "1.1.0"
|
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"
|
||||||
getset = "0.1.5"
|
getset = "0.1.3"
|
||||||
handlebars = "3.5.5"
|
handlebars = "3.5.5"
|
||||||
headers = "0.4.0"
|
headers = "0.4.0"
|
||||||
hex = "0.4.3"
|
hex = "0.4.3"
|
||||||
hex-literal = "0.3.3"
|
hex-literal = "0.3.3"
|
||||||
hickory-resolver = "0.24.4"
|
|
||||||
hkdf = "0.12.3"
|
hkdf = "0.12.3"
|
||||||
hmac = "0.12.1"
|
hmac = "0.12.1"
|
||||||
http = "1"
|
http = "1"
|
||||||
http-body-util = "0.1"
|
http-body-util = "0.1"
|
||||||
httpcodec = "0.2.3"
|
httpcodec = "0.2.3"
|
||||||
human-repr = "1.1.0"
|
|
||||||
humantime = "2.1.0"
|
humantime = "2.1.0"
|
||||||
humantime-serde = "1.1.1"
|
humantime-serde = "1.1.1"
|
||||||
hyper = "1.6.0"
|
human-repr = "1.1.0"
|
||||||
|
hyper = "1.4.1"
|
||||||
hyper-util = "0.1"
|
hyper-util = "0.1"
|
||||||
indicatif = "0.17.11"
|
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"
|
||||||
isocountry = "0.3.2"
|
isocountry = "0.3.2"
|
||||||
itertools = "0.14.0"
|
itertools = "0.13.0"
|
||||||
k256 = "0.13"
|
k256 = "0.13"
|
||||||
lazy_static = "1.5.0"
|
lazy_static = "1.5.0"
|
||||||
ledger-transport = "0.10.0"
|
ledger-transport = "0.10.0"
|
||||||
ledger-transport-hid = "0.10.0"
|
ledger-transport-hid = "0.10.0"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
maxminddb = "0.23.0"
|
maxminddb = "0.23.0"
|
||||||
|
rs_merkle = "1.4.2"
|
||||||
mime = "0.3.17"
|
mime = "0.3.17"
|
||||||
moka = { version = "0.12", features = ["future"] }
|
moka = { version = "0.12", features = ["future"] }
|
||||||
nix = "0.27.1"
|
nix = "0.27.1"
|
||||||
notify = "5.1.0"
|
notify = "5.1.0"
|
||||||
okapi = "0.7.0"
|
okapi = "0.7.0"
|
||||||
once_cell = "1.20.3"
|
once_cell = "1.20.2"
|
||||||
opentelemetry = "0.19.0"
|
opentelemetry = "0.19.0"
|
||||||
opentelemetry-jaeger = "0.18.0"
|
opentelemetry-jaeger = "0.18.0"
|
||||||
parking_lot = "0.12.3"
|
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.3.0"
|
publicsuffix = "2.2.3"
|
||||||
quote = "1"
|
quote = "1"
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
rand_chacha = "0.3"
|
rand_chacha = "0.3"
|
||||||
@@ -308,59 +305,55 @@ reqwest = { version = "0.12.4", default-features = false }
|
|||||||
rocket = "0.5.0"
|
rocket = "0.5.0"
|
||||||
rocket_cors = "0.6.0"
|
rocket_cors = "0.6.0"
|
||||||
rocket_okapi = "0.8.0"
|
rocket_okapi = "0.8.0"
|
||||||
rs_merkle = "1.4.2"
|
|
||||||
safer-ffi = "0.1.13"
|
safer-ffi = "0.1.13"
|
||||||
schemars = "0.8.22"
|
schemars = "0.8.21"
|
||||||
semver = "1.0.25"
|
semver = "1.0.23"
|
||||||
serde = "1.0.217"
|
serde = "1.0.211"
|
||||||
serde_bytes = "0.11.16"
|
serde_bytes = "0.11.15"
|
||||||
serde_derive = "1.0"
|
serde_derive = "1.0"
|
||||||
serde_json = "1.0.140"
|
serde_json = "1.0.132"
|
||||||
serde_json_path = "0.7.2"
|
serde_json_path = "0.7.1"
|
||||||
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"
|
||||||
sha2 = "0.10.8"
|
sha2 = "0.10.8"
|
||||||
si-scale = "0.2.3"
|
si-scale = "0.2.3"
|
||||||
sphinx-packet = "0.3.1"
|
sphinx-packet = "0.1.1"
|
||||||
sqlx = "0.7.4"
|
sqlx = "0.7.4"
|
||||||
strum = "0.26"
|
strum = "0.26"
|
||||||
strum_macros = "0.26"
|
strum_macros = "0.26"
|
||||||
subtle-encoding = "0.5"
|
subtle-encoding = "0.5"
|
||||||
syn = "1"
|
syn = "1"
|
||||||
sysinfo = "0.33.0"
|
sysinfo = "0.30.13"
|
||||||
tap = "1.0.1"
|
tap = "1.0.1"
|
||||||
tar = "0.4.44"
|
tar = "0.4.42"
|
||||||
tempfile = "3.15"
|
tempfile = "3.14"
|
||||||
thiserror = "2.0"
|
thiserror = "1.0.64"
|
||||||
time = "0.3.37"
|
time = "0.3.30"
|
||||||
tokio = "1.43"
|
tokio = "1.39"
|
||||||
tokio-postgres = "0.7"
|
tokio-stream = "0.1.16"
|
||||||
tokio-stream = "0.1.17"
|
|
||||||
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.20"
|
toml = "0.8.14"
|
||||||
tower = "0.5.2"
|
tower = "0.4.13"
|
||||||
tower-http = "0.5.2"
|
tower-http = "0.5.2"
|
||||||
tracing = "0.1.41"
|
tracing = "0.1.37"
|
||||||
tracing-log = "0.2"
|
|
||||||
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"
|
||||||
ts-rs = "10.1.0"
|
tracing-log = "0.2"
|
||||||
|
ts-rs = "10.0.0"
|
||||||
tungstenite = { version = "0.20.1", default-features = false }
|
tungstenite = { version = "0.20.1", default-features = false }
|
||||||
uniffi = "0.29.0"
|
|
||||||
uniffi_build = "0.29.0"
|
|
||||||
url = "2.5"
|
url = "2.5"
|
||||||
utoipa = "5.2"
|
utoipa = "5.2"
|
||||||
utoipa-swagger-ui = "8.1"
|
utoipa-swagger-ui = "8.0"
|
||||||
utoipauto = "0.2"
|
utoipauto = "0.2"
|
||||||
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"
|
||||||
|
|
||||||
@@ -391,26 +384,31 @@ cw4 = { version = "=1.1.2" }
|
|||||||
cw-controllers = { version = "=1.1.0" }
|
cw-controllers = { version = "=1.1.0" }
|
||||||
|
|
||||||
# cosmrs-related
|
# cosmrs-related
|
||||||
bip32 = { version = "0.5.3", default-features = false }
|
bip32 = { version = "0.5.2", default-features = false }
|
||||||
|
|
||||||
|
# temporarily using a fork again (yay.) because we need staking and slashing support (which are already on main but not released)
|
||||||
cosmrs = { version = "0.21.1" }
|
# plus response message parsing (which is, as of the time of writing this message, waiting to get merged)
|
||||||
tendermint = "0.40.0"
|
#cosmrs = { path = "../cosmos-rust-fork/cosmos-rust/cosmrs" }
|
||||||
tendermint-rpc = "0.40.0"
|
cosmrs = { git = "https://github.com/cosmos/cosmos-rust", rev = "4b1332e6d8258ac845cef71589c8d362a669675a" } # unfortuntely we need a fork by yours truly to get the staking support
|
||||||
prost = { version = "0.13", default-features = false }
|
tendermint = "0.37.0" # same version as used by cosmrs
|
||||||
|
tendermint-rpc = "0.37.0" # same version as used by cosmrs
|
||||||
|
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"
|
||||||
|
|
||||||
indexed_db_futures = "0.6.0"
|
# use a separate branch due to feature unification failures
|
||||||
js-sys = "0.3.76"
|
# this is blocked until the upstream removes outdates `wasm_bindgen` feature usage
|
||||||
|
# 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.99"
|
||||||
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
|
||||||
|
|
||||||
@@ -438,13 +436,3 @@ opt-level = 'z'
|
|||||||
[profile.release.package.mix-fetch-wasm]
|
[profile.release.package.mix-fetch-wasm]
|
||||||
# lto = true
|
# lto = true
|
||||||
opt-level = 'z'
|
opt-level = 'z'
|
||||||
|
|
||||||
[workspace.lints.clippy]
|
|
||||||
unwrap_used = "deny"
|
|
||||||
expect_used = "deny"
|
|
||||||
todo = "deny"
|
|
||||||
dbg_macro = "deny"
|
|
||||||
exit = "deny"
|
|
||||||
panic = "deny"
|
|
||||||
unimplemented = "deny"
|
|
||||||
unreachable = "deny"
|
|
||||||
@@ -13,8 +13,8 @@ The platform is composed of multiple Rust crates. Top-level executable binary cr
|
|||||||
* `nym-client` - an executable which you can build into your own applications. Use it for interacting with Nym nodes.
|
* `nym-client` - an executable which you can build into your own applications. Use it for interacting with Nym nodes.
|
||||||
* `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.app)) 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.
|
* `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").
|
||||||
-->
|
-->
|
||||||
@@ -42,10 +42,10 @@ client ───► Gateway ──┘ mix │ mix ┌─►mix ───►
|
|||||||
|
|
||||||
References for developers:
|
References for developers:
|
||||||
|
|
||||||
* [Dev Docs](https://nym.com/docs/developers)
|
* [Dev Docs](https://nymtech.net/docs/developers)
|
||||||
* [SDKs](https://nym.com/docs/developers/rust)
|
* [SDKs](https://nymtech.net/docs/developers/rust)
|
||||||
* [Network Docs](https://nym.com/docs/network)
|
* [Network Docs](https://nymtech.net/docs/network)
|
||||||
* [Release Cycle - git flow](https://nym.com/docs/operators/release-cycle)
|
* [Release Cycle - git flow](https://nymtech.net/docs/operators/release-cycle)
|
||||||
|
|
||||||
### Developer chat
|
### Developer chat
|
||||||
|
|
||||||
@@ -66,4 +66,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 Terms and Conditions can be found [here](https://nym.com/operators-validators-terms).
|
Nym Node Operators and Validators Temrs and Conditions can be found [here](https://nymtech.net/terms-and-conditions/operators/v1.0.0).
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "nym-client"
|
name = "nym-client"
|
||||||
version = "1.1.50"
|
version = "1.1.45"
|
||||||
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"
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ pub fn default_data_directory<P: AsRef<Path>>(id: P) -> PathBuf {
|
|||||||
.join(DEFAULT_DATA_DIR)
|
.join(DEFAULT_DATA_DIR)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, PartialEq, Serialize, Clone)]
|
#[derive(Debug, Deserialize, PartialEq, Serialize)]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
pub base: BaseClientConfig,
|
pub base: BaseClientConfig,
|
||||||
@@ -94,10 +94,6 @@ impl CliClientConfig for Config {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Config {
|
impl Config {
|
||||||
pub fn base(&self) -> BaseClientConfig {
|
|
||||||
self.base.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new<S: AsRef<str>>(id: S) -> Self {
|
pub fn new<S: AsRef<str>>(id: S) -> Self {
|
||||||
Config {
|
Config {
|
||||||
base: BaseClientConfig::new(id.as_ref(), env!("CARGO_PKG_VERSION")),
|
base: BaseClientConfig::new(id.as_ref(), env!("CARGO_PKG_VERSION")),
|
||||||
@@ -213,7 +209,7 @@ impl SocketType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, PartialEq, Eq, Serialize, Clone)]
|
#[derive(Debug, Deserialize, PartialEq, Eq, Serialize)]
|
||||||
#[serde(default, deny_unknown_fields)]
|
#[serde(default, deny_unknown_fields)]
|
||||||
pub struct Socket {
|
pub struct Socket {
|
||||||
pub socket_type: SocketType,
|
pub socket_type: SocketType,
|
||||||
|
|||||||
@@ -107,8 +107,5 @@ enabled = {{ debug.stats_reporting.enabled }}
|
|||||||
provider_address = '{{ debug.stats_reporting.provider_address }}'
|
provider_address = '{{ debug.stats_reporting.provider_address }}'
|
||||||
reporting_interval = '{{ debug.stats_reporting.reporting_interval }}'
|
reporting_interval = '{{ debug.stats_reporting.reporting_interval }}'
|
||||||
|
|
||||||
[debug.forget_me]
|
|
||||||
client = {{ debug.forget_me.client }}
|
|
||||||
stats = {{ debug.forget_me.stats }}
|
|
||||||
|
|
||||||
"#;
|
"#;
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ pub use nym_sphinx::addressing::clients::Recipient;
|
|||||||
|
|
||||||
pub mod config;
|
pub mod config;
|
||||||
|
|
||||||
type NativeClientBuilder = BaseClientBuilder<QueryHttpRpcNyxdClient, OnDiskPersistent>;
|
type NativeClientBuilder<'a> = BaseClientBuilder<'a, QueryHttpRpcNyxdClient, OnDiskPersistent>;
|
||||||
|
|
||||||
pub struct SocketClient {
|
pub struct SocketClient {
|
||||||
/// Client configuration options, including, among other things, packet sending rates,
|
/// Client configuration options, including, among other things, packet sending rates,
|
||||||
@@ -32,10 +32,6 @@ pub struct SocketClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl SocketClient {
|
impl SocketClient {
|
||||||
pub fn config(&self) -> Config {
|
|
||||||
self.config.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new(config: Config, custom_mixnet: Option<PathBuf>) -> Self {
|
pub fn new(config: Config, custom_mixnet: Option<PathBuf>) -> Self {
|
||||||
SocketClient {
|
SocketClient {
|
||||||
config,
|
config,
|
||||||
@@ -49,7 +45,7 @@ impl SocketClient {
|
|||||||
client_output: ClientOutput,
|
client_output: ClientOutput,
|
||||||
client_state: ClientState,
|
client_state: ClientState,
|
||||||
self_address: &Recipient,
|
self_address: &Recipient,
|
||||||
task_client: nym_task::TaskClient,
|
shutdown: nym_task::TaskClient,
|
||||||
packet_type: PacketType,
|
packet_type: PacketType,
|
||||||
) {
|
) {
|
||||||
info!("Starting websocket listener...");
|
info!("Starting websocket listener...");
|
||||||
@@ -77,15 +73,10 @@ impl SocketClient {
|
|||||||
shared_lane_queue_lengths,
|
shared_lane_queue_lengths,
|
||||||
reply_controller_sender,
|
reply_controller_sender,
|
||||||
Some(packet_type),
|
Some(packet_type),
|
||||||
task_client.fork("websocket_handler"),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
websocket::Listener::new(
|
websocket::Listener::new(config.socket.host, config.socket.listening_port)
|
||||||
config.socket.host,
|
.start(websocket_handler, shutdown);
|
||||||
config.socket.listening_port,
|
|
||||||
task_client.with_suffix("websocket_listener"),
|
|
||||||
)
|
|
||||||
.start(websocket_handler);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// blocking version of `start_socket` method. Will run forever (or until SIGINT is sent)
|
/// blocking version of `start_socket` method. Will run forever (or until SIGINT is sent)
|
||||||
@@ -117,9 +108,8 @@ impl SocketClient {
|
|||||||
let storage = self.initialise_storage().await?;
|
let storage = self.initialise_storage().await?;
|
||||||
let user_agent = nym_bin_common::bin_info!().into();
|
let user_agent = nym_bin_common::bin_info!().into();
|
||||||
|
|
||||||
let mut base_client =
|
let mut base_client = BaseClientBuilder::new(&self.config.base, storage, dkg_query_client)
|
||||||
BaseClientBuilder::new(self.config().base(), storage, dkg_query_client)
|
.with_user_agent(user_agent);
|
||||||
.with_user_agent(user_agent);
|
|
||||||
|
|
||||||
if let Some(custom_mixnet) = &self.custom_mixnet {
|
if let Some(custom_mixnet) = &self.custom_mixnet {
|
||||||
base_client = base_client.with_stored_topology(custom_mixnet)?;
|
base_client = base_client.with_stored_topology(custom_mixnet)?;
|
||||||
|
|||||||
@@ -82,7 +82,6 @@ impl From<Init> for OverrideConfig {
|
|||||||
nyxd_urls: init_config.common_args.nyxd_urls,
|
nyxd_urls: init_config.common_args.nyxd_urls,
|
||||||
enabled_credentials_mode: init_config.common_args.enabled_credentials_mode,
|
enabled_credentials_mode: init_config.common_args.enabled_credentials_mode,
|
||||||
stats_reporting_address: init_config.common_args.stats_reporting_address,
|
stats_reporting_address: init_config.common_args.stats_reporting_address,
|
||||||
forget_me: init_config.common_args.forget_me.into(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ use nym_bin_common::completions::{fig_generate, ArgShell};
|
|||||||
use nym_client::client::Recipient;
|
use nym_client::client::Recipient;
|
||||||
use nym_client_core::cli_helpers::CliClient;
|
use nym_client_core::cli_helpers::CliClient;
|
||||||
use nym_client_core::client::base_client::storage::migration_helpers::v1_1_33;
|
use nym_client_core::client::base_client::storage::migration_helpers::v1_1_33;
|
||||||
use nym_client_core::config::ForgetMe;
|
|
||||||
use nym_config::OptionalSet;
|
use nym_config::OptionalSet;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::net::IpAddr;
|
use std::net::IpAddr;
|
||||||
@@ -107,7 +106,6 @@ pub(crate) struct OverrideConfig {
|
|||||||
nyxd_urls: Option<Vec<url::Url>>,
|
nyxd_urls: Option<Vec<url::Url>>,
|
||||||
enabled_credentials_mode: Option<bool>,
|
enabled_credentials_mode: Option<bool>,
|
||||||
stats_reporting_address: Option<Recipient>,
|
stats_reporting_address: Option<Recipient>,
|
||||||
forget_me: ForgetMe,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn execute(args: Cli) -> Result<(), Box<dyn Error + Send + Sync>> {
|
pub(crate) async fn execute(args: Cli) -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
@@ -135,7 +133,6 @@ pub(crate) fn override_config(config: Config, args: OverrideConfig) -> Config {
|
|||||||
args.fastmode,
|
args.fastmode,
|
||||||
)
|
)
|
||||||
.with_base(BaseClientConfig::with_disabled_cover_traffic, args.no_cover)
|
.with_base(BaseClientConfig::with_disabled_cover_traffic, args.no_cover)
|
||||||
.with_base(BaseClientConfig::with_forget_me, args.forget_me)
|
|
||||||
.with_optional(Config::with_port, args.port)
|
.with_optional(Config::with_port, args.port)
|
||||||
.with_optional(Config::with_host, args.host)
|
.with_optional(Config::with_host, args.host)
|
||||||
.with_optional_custom_env_ext(
|
.with_optional_custom_env_ext(
|
||||||
|
|||||||
@@ -41,7 +41,6 @@ impl From<Run> for OverrideConfig {
|
|||||||
nyxd_urls: run_config.common_args.nyxd_urls,
|
nyxd_urls: run_config.common_args.nyxd_urls,
|
||||||
enabled_credentials_mode: run_config.common_args.enabled_credentials_mode,
|
enabled_credentials_mode: run_config.common_args.enabled_credentials_mode,
|
||||||
stats_reporting_address: run_config.common_args.stats_reporting_address,
|
stats_reporting_address: run_config.common_args.stats_reporting_address,
|
||||||
forget_me: run_config.common_args.forget_me.into(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ use nym_sphinx::receiver::ReconstructedMessage;
|
|||||||
use nym_task::connections::{
|
use nym_task::connections::{
|
||||||
ConnectionCommand, ConnectionCommandSender, ConnectionId, LaneQueueLengths, TransmissionLane,
|
ConnectionCommand, ConnectionCommandSender, ConnectionId, LaneQueueLengths, TransmissionLane,
|
||||||
};
|
};
|
||||||
use nym_task::TaskClient;
|
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use tokio::net::TcpStream;
|
use tokio::net::TcpStream;
|
||||||
use tokio::time::Instant;
|
use tokio::time::Instant;
|
||||||
@@ -44,11 +43,9 @@ pub(crate) struct HandlerBuilder {
|
|||||||
lane_queue_lengths: LaneQueueLengths,
|
lane_queue_lengths: LaneQueueLengths,
|
||||||
reply_controller_sender: ReplyControllerSender,
|
reply_controller_sender: ReplyControllerSender,
|
||||||
packet_type: Option<PacketType>,
|
packet_type: Option<PacketType>,
|
||||||
task_client: TaskClient,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HandlerBuilder {
|
impl HandlerBuilder {
|
||||||
#[allow(clippy::too_many_arguments)]
|
|
||||||
pub(crate) fn new(
|
pub(crate) fn new(
|
||||||
msg_input: InputMessageSender,
|
msg_input: InputMessageSender,
|
||||||
client_connection_tx: ConnectionCommandSender,
|
client_connection_tx: ConnectionCommandSender,
|
||||||
@@ -57,7 +54,6 @@ impl HandlerBuilder {
|
|||||||
lane_queue_lengths: LaneQueueLengths,
|
lane_queue_lengths: LaneQueueLengths,
|
||||||
reply_controller_sender: ReplyControllerSender,
|
reply_controller_sender: ReplyControllerSender,
|
||||||
packet_type: Option<PacketType>,
|
packet_type: Option<PacketType>,
|
||||||
task_client: TaskClient,
|
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
msg_input,
|
msg_input,
|
||||||
@@ -67,14 +63,11 @@ impl HandlerBuilder {
|
|||||||
lane_queue_lengths,
|
lane_queue_lengths,
|
||||||
reply_controller_sender,
|
reply_controller_sender,
|
||||||
packet_type,
|
packet_type,
|
||||||
task_client,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: make sure we only ever have one active handler
|
// TODO: make sure we only ever have one active handler
|
||||||
pub fn create_active_handler(&self) -> Handler {
|
pub fn create_active_handler(&self) -> Handler {
|
||||||
let mut task_client = self.task_client.fork("active_handler");
|
|
||||||
task_client.disarm();
|
|
||||||
Handler {
|
Handler {
|
||||||
msg_input: self.msg_input.clone(),
|
msg_input: self.msg_input.clone(),
|
||||||
client_connection_tx: self.client_connection_tx.clone(),
|
client_connection_tx: self.client_connection_tx.clone(),
|
||||||
@@ -85,7 +78,6 @@ impl HandlerBuilder {
|
|||||||
lane_queue_lengths: self.lane_queue_lengths.clone(),
|
lane_queue_lengths: self.lane_queue_lengths.clone(),
|
||||||
reply_controller_sender: self.reply_controller_sender.clone(),
|
reply_controller_sender: self.reply_controller_sender.clone(),
|
||||||
packet_type: self.packet_type,
|
packet_type: self.packet_type,
|
||||||
task_client,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -100,18 +92,16 @@ pub(crate) struct Handler {
|
|||||||
lane_queue_lengths: LaneQueueLengths,
|
lane_queue_lengths: LaneQueueLengths,
|
||||||
reply_controller_sender: ReplyControllerSender,
|
reply_controller_sender: ReplyControllerSender,
|
||||||
packet_type: Option<PacketType>,
|
packet_type: Option<PacketType>,
|
||||||
task_client: TaskClient,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for Handler {
|
impl Drop for Handler {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
if let Err(err) = self
|
if self
|
||||||
.buffer_requester
|
.buffer_requester
|
||||||
.unbounded_send(ReceivedBufferMessage::ReceiverDisconnect)
|
.unbounded_send(ReceivedBufferMessage::ReceiverDisconnect)
|
||||||
|
.is_err()
|
||||||
{
|
{
|
||||||
if !self.task_client.is_shutdown_poll() {
|
error!("we failed to disconnect the receiver from the buffer! presumably the shutdown procedure has been initiated!")
|
||||||
error!("failed to disconnect the receiver from the buffer: {err}");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -135,23 +125,10 @@ impl Handler {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// get the number of pending replies waiting for reply surbs
|
// get the number of pending replies waiting for reply surbs
|
||||||
let reply_queue_length = match self
|
let reply_queue_length = self
|
||||||
.reply_controller_sender
|
.reply_controller_sender
|
||||||
.get_lane_queue_length(connection_id)
|
.get_lane_queue_length(connection_id)
|
||||||
.await
|
.await;
|
||||||
{
|
|
||||||
Ok(length) => length,
|
|
||||||
Err(err) => {
|
|
||||||
if !self.task_client.is_shutdown_poll() {
|
|
||||||
error!(
|
|
||||||
"Failed to get reply queue length for connection {connection_id}: {err}"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
// We're just going to assume that the queue is empty, and I think that's okay
|
|
||||||
// during shutdown.
|
|
||||||
0
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let queue_length = base_length + reply_queue_length;
|
let queue_length = base_length + reply_queue_length;
|
||||||
|
|
||||||
@@ -191,11 +168,10 @@ impl Handler {
|
|||||||
|
|
||||||
// the ack control is now responsible for chunking, etc.
|
// the ack control is now responsible for chunking, etc.
|
||||||
let input_msg = InputMessage::new_regular(recipient, message, lane, self.packet_type);
|
let input_msg = InputMessage::new_regular(recipient, message, lane, self.packet_type);
|
||||||
if let Err(err) = self.msg_input.send(input_msg).await {
|
self.msg_input
|
||||||
if !self.task_client.is_shutdown_poll() {
|
.send(input_msg)
|
||||||
error!("Failed to send message to the input buffer: {err}");
|
.await
|
||||||
}
|
.expect("InputMessageReceiver has stopped receiving!");
|
||||||
}
|
|
||||||
|
|
||||||
// Only reply back with a `LaneQueueLength` if the sender providided a connection id
|
// Only reply back with a `LaneQueueLength` if the sender providided a connection id
|
||||||
let TransmissionLane::ConnectionId(connection_id) = lane else {
|
let TransmissionLane::ConnectionId(connection_id) = lane else {
|
||||||
@@ -224,11 +200,10 @@ impl Handler {
|
|||||||
|
|
||||||
let input_msg =
|
let input_msg =
|
||||||
InputMessage::new_anonymous(recipient, message, reply_surbs, lane, self.packet_type);
|
InputMessage::new_anonymous(recipient, message, reply_surbs, lane, self.packet_type);
|
||||||
if let Err(err) = self.msg_input.send(input_msg).await {
|
self.msg_input
|
||||||
if !self.task_client.is_shutdown_poll() {
|
.send(input_msg)
|
||||||
error!("Failed to send anonymous message to the input buffer: {err}");
|
.await
|
||||||
}
|
.expect("InputMessageReceiver has stopped receiving!");
|
||||||
}
|
|
||||||
|
|
||||||
// Only reply back with a `LaneQueueLength` if the sender providided a connection id
|
// Only reply back with a `LaneQueueLength` if the sender providided a connection id
|
||||||
let TransmissionLane::ConnectionId(connection_id) = lane else {
|
let TransmissionLane::ConnectionId(connection_id) = lane else {
|
||||||
@@ -252,11 +227,10 @@ impl Handler {
|
|||||||
});
|
});
|
||||||
|
|
||||||
let input_msg = InputMessage::new_reply(recipient_tag, message, lane, self.packet_type);
|
let input_msg = InputMessage::new_reply(recipient_tag, message, lane, self.packet_type);
|
||||||
if let Err(err) = self.msg_input.send(input_msg).await {
|
self.msg_input
|
||||||
if !self.task_client.is_shutdown_poll() {
|
.send(input_msg)
|
||||||
error!("Failed to send reply message to the input buffer: {err}");
|
.await
|
||||||
}
|
.expect("InputMessageReceiver has stopped receiving!");
|
||||||
}
|
|
||||||
|
|
||||||
// Only reply back with a `LaneQueueLength` if the sender providided a connection id
|
// Only reply back with a `LaneQueueLength` if the sender providided a connection id
|
||||||
let TransmissionLane::ConnectionId(connection_id) = lane else {
|
let TransmissionLane::ConnectionId(connection_id) = lane else {
|
||||||
@@ -271,14 +245,9 @@ impl Handler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn handle_closed_connection(&self, connection_id: u64) -> Option<ServerResponse> {
|
fn handle_closed_connection(&self, connection_id: u64) -> Option<ServerResponse> {
|
||||||
if let Err(err) = self
|
self.client_connection_tx
|
||||||
.client_connection_tx
|
|
||||||
.unbounded_send(ConnectionCommand::Close(connection_id))
|
.unbounded_send(ConnectionCommand::Close(connection_id))
|
||||||
{
|
.unwrap();
|
||||||
if !self.task_client.is_shutdown_poll() {
|
|
||||||
error!("Failed to send close connection command: {err}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -393,10 +362,11 @@ impl Handler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn listen_for_requests(&mut self, mut msg_receiver: ReconstructedMessagesReceiver) {
|
async fn listen_for_requests(
|
||||||
let mut task_client = self.task_client.fork("select");
|
&mut self,
|
||||||
task_client.disarm();
|
mut msg_receiver: ReconstructedMessagesReceiver,
|
||||||
|
mut task_client: nym_task::TaskClient,
|
||||||
|
) {
|
||||||
while !task_client.is_shutdown() {
|
while !task_client.is_shutdown() {
|
||||||
tokio::select! {
|
tokio::select! {
|
||||||
// we can either get a client request from the websocket
|
// we can either get a client request from the websocket
|
||||||
@@ -445,7 +415,15 @@ impl Handler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// consume self to make sure `drop` is called after this is done
|
// consume self to make sure `drop` is called after this is done
|
||||||
pub(crate) async fn handle_connection(mut self, socket: TcpStream) {
|
pub(crate) async fn handle_connection(
|
||||||
|
mut self,
|
||||||
|
socket: TcpStream,
|
||||||
|
mut task_client: nym_task::TaskClient,
|
||||||
|
) {
|
||||||
|
// We don't want a crash in the connection handler to trigger a shutdown of the whole
|
||||||
|
// process.
|
||||||
|
task_client.disarm();
|
||||||
|
|
||||||
let ws_stream = match accept_async(socket).await {
|
let ws_stream = match accept_async(socket).await {
|
||||||
Ok(ws_stream) => ws_stream,
|
Ok(ws_stream) => ws_stream,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
@@ -458,18 +436,14 @@ impl Handler {
|
|||||||
let (reconstructed_sender, reconstructed_receiver) = mpsc::unbounded();
|
let (reconstructed_sender, reconstructed_receiver) = mpsc::unbounded();
|
||||||
|
|
||||||
// tell the buffer to start sending stuff to us
|
// tell the buffer to start sending stuff to us
|
||||||
if let Err(err) =
|
self.buffer_requester
|
||||||
self.buffer_requester
|
.unbounded_send(ReceivedBufferMessage::ReceiverAnnounce(
|
||||||
.unbounded_send(ReceivedBufferMessage::ReceiverAnnounce(
|
reconstructed_sender,
|
||||||
reconstructed_sender,
|
))
|
||||||
))
|
.expect("the buffer request failed!");
|
||||||
{
|
|
||||||
if !self.task_client.is_shutdown_poll() {
|
|
||||||
error!("failed to announce the receiver to the buffer: {err}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.listen_for_requests(reconstructed_receiver).await;
|
self.listen_for_requests(reconstructed_receiver, task_client)
|
||||||
|
.await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
use super::handler::HandlerBuilder;
|
use super::handler::HandlerBuilder;
|
||||||
use log::*;
|
use log::*;
|
||||||
use nym_task::TaskClient;
|
|
||||||
use std::net::IpAddr;
|
use std::net::IpAddr;
|
||||||
use std::{net::SocketAddr, process, sync::Arc};
|
use std::{net::SocketAddr, process, sync::Arc};
|
||||||
use tokio::io::AsyncWriteExt;
|
use tokio::io::AsyncWriteExt;
|
||||||
@@ -23,19 +22,21 @@ impl State {
|
|||||||
pub(crate) struct Listener {
|
pub(crate) struct Listener {
|
||||||
address: SocketAddr,
|
address: SocketAddr,
|
||||||
state: State,
|
state: State,
|
||||||
task_client: TaskClient,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Listener {
|
impl Listener {
|
||||||
pub(crate) fn new(host: IpAddr, port: u16, task_client: TaskClient) -> Self {
|
pub(crate) fn new(host: IpAddr, port: u16) -> Self {
|
||||||
Listener {
|
Listener {
|
||||||
address: SocketAddr::new(host, port),
|
address: SocketAddr::new(host, port),
|
||||||
state: State::AwaitingConnection,
|
state: State::AwaitingConnection,
|
||||||
task_client,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn run(&mut self, handler: HandlerBuilder) {
|
pub(crate) async fn run(
|
||||||
|
&mut self,
|
||||||
|
handler: HandlerBuilder,
|
||||||
|
mut task_client: nym_task::TaskClient,
|
||||||
|
) {
|
||||||
let tcp_listener = match tokio::net::TcpListener::bind(self.address).await {
|
let tcp_listener = match tokio::net::TcpListener::bind(self.address).await {
|
||||||
Ok(listener) => listener,
|
Ok(listener) => listener,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
@@ -46,11 +47,11 @@ impl Listener {
|
|||||||
|
|
||||||
let notify = Arc::new(Notify::new());
|
let notify = Arc::new(Notify::new());
|
||||||
|
|
||||||
while !self.task_client.is_shutdown() {
|
loop {
|
||||||
tokio::select! {
|
tokio::select! {
|
||||||
// When the handler finishes we check if shutdown is signalled
|
// When the handler finishes we check if shutdown is signalled
|
||||||
_ = notify.notified() => {
|
_ = notify.notified() => {
|
||||||
if self.task_client.is_shutdown() {
|
if task_client.is_shutdown() {
|
||||||
log::trace!("Websocket listener: detected shutdown after connection closed");
|
log::trace!("Websocket listener: detected shutdown after connection closed");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -59,7 +60,7 @@ impl Listener {
|
|||||||
}
|
}
|
||||||
// ... but when there is no connected client at the time of shutdown being
|
// ... but when there is no connected client at the time of shutdown being
|
||||||
// signalled, we handle it here.
|
// signalled, we handle it here.
|
||||||
_ = self.task_client.recv() => {
|
_ = task_client.recv() => {
|
||||||
if !self.state.is_connected() {
|
if !self.state.is_connected() {
|
||||||
log::trace!("Not connected: shutting down");
|
log::trace!("Not connected: shutting down");
|
||||||
break;
|
break;
|
||||||
@@ -87,8 +88,9 @@ impl Listener {
|
|||||||
// hanging because the executor doesn't come back here
|
// hanging because the executor doesn't come back here
|
||||||
let notify_clone = Arc::clone(¬ify);
|
let notify_clone = Arc::clone(¬ify);
|
||||||
let fresh_handler = handler.create_active_handler();
|
let fresh_handler = handler.create_active_handler();
|
||||||
|
let task_client_handler = task_client.clone();
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
fresh_handler.handle_connection(socket).await;
|
fresh_handler.handle_connection(socket, task_client_handler).await;
|
||||||
notify_clone.notify_one();
|
notify_clone.notify_one();
|
||||||
});
|
});
|
||||||
self.state = State::Connected;
|
self.state = State::Connected;
|
||||||
@@ -102,9 +104,13 @@ impl Listener {
|
|||||||
log::debug!("Websocket listener: Exiting");
|
log::debug!("Websocket listener: Exiting");
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn start(mut self, handler: HandlerBuilder) -> JoinHandle<()> {
|
pub(crate) fn start(
|
||||||
|
mut self,
|
||||||
|
handler: HandlerBuilder,
|
||||||
|
shutdown: nym_task::TaskClient,
|
||||||
|
) -> JoinHandle<()> {
|
||||||
info!("Running websocket on {:?}", self.address.to_string());
|
info!("Running websocket on {:?}", self.address.to_string());
|
||||||
|
|
||||||
tokio::spawn(async move { self.run(handler).await })
|
tokio::spawn(async move { self.run(handler, shutdown).await })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "nym-socks5-client"
|
name = "nym-socks5-client"
|
||||||
version = "1.1.50"
|
version = "1.1.45"
|
||||||
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"
|
||||||
|
|||||||
@@ -93,7 +93,6 @@ impl From<Init> for OverrideConfig {
|
|||||||
enabled_credentials_mode: init_config.common_args.enabled_credentials_mode,
|
enabled_credentials_mode: init_config.common_args.enabled_credentials_mode,
|
||||||
outfox: false,
|
outfox: false,
|
||||||
stats_reporting_address: init_config.common_args.stats_reporting_address,
|
stats_reporting_address: init_config.common_args.stats_reporting_address,
|
||||||
forget_me: init_config.common_args.forget_me.into(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ use nym_bin_common::completions::{fig_generate, ArgShell};
|
|||||||
use nym_client_core::cli_helpers::CliClient;
|
use nym_client_core::cli_helpers::CliClient;
|
||||||
use nym_client_core::client::base_client::storage::migration_helpers::v1_1_33;
|
use nym_client_core::client::base_client::storage::migration_helpers::v1_1_33;
|
||||||
use nym_client_core::client::topology_control::geo_aware_provider::CountryGroup;
|
use nym_client_core::client::topology_control::geo_aware_provider::CountryGroup;
|
||||||
use nym_client_core::config::{ForgetMe, GroupBy, TopologyStructure};
|
use nym_client_core::config::{GroupBy, TopologyStructure};
|
||||||
use nym_config::OptionalSet;
|
use nym_config::OptionalSet;
|
||||||
use nym_sphinx::addressing::Recipient;
|
use nym_sphinx::addressing::Recipient;
|
||||||
use nym_sphinx::params::{PacketSize, PacketType};
|
use nym_sphinx::params::{PacketSize, PacketType};
|
||||||
@@ -113,7 +113,6 @@ pub(crate) struct OverrideConfig {
|
|||||||
enabled_credentials_mode: Option<bool>,
|
enabled_credentials_mode: Option<bool>,
|
||||||
outfox: bool,
|
outfox: bool,
|
||||||
stats_reporting_address: Option<Recipient>,
|
stats_reporting_address: Option<Recipient>,
|
||||||
forget_me: ForgetMe,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn execute(args: Cli) -> Result<(), Box<dyn Error + Send + Sync>> {
|
pub(crate) async fn execute(args: Cli) -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
@@ -180,7 +179,6 @@ pub(crate) fn override_config(config: Config, args: OverrideConfig) -> Config {
|
|||||||
BaseClientConfig::with_topology_structure,
|
BaseClientConfig::with_topology_structure,
|
||||||
topology_structure,
|
topology_structure,
|
||||||
)
|
)
|
||||||
.with_base(BaseClientConfig::with_forget_me, args.forget_me)
|
|
||||||
.with_optional(Config::with_anonymous_replies, args.use_anonymous_replies)
|
.with_optional(Config::with_anonymous_replies, args.use_anonymous_replies)
|
||||||
.with_optional(Config::with_port, args.port)
|
.with_optional(Config::with_port, args.port)
|
||||||
.with_optional(Config::with_ip, args.ip)
|
.with_optional(Config::with_ip, args.ip)
|
||||||
|
|||||||
@@ -65,7 +65,6 @@ impl From<Run> for OverrideConfig {
|
|||||||
enabled_credentials_mode: run_config.common_args.enabled_credentials_mode,
|
enabled_credentials_mode: run_config.common_args.enabled_credentials_mode,
|
||||||
outfox: run_config.outfox,
|
outfox: run_config.outfox,
|
||||||
stats_reporting_address: run_config.common_args.stats_reporting_address,
|
stats_reporting_address: run_config.common_args.stats_reporting_address,
|
||||||
forget_me: run_config.common_args.forget_me.into(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -113,8 +113,4 @@ enabled = {{ core.debug.stats_reporting.enabled }}
|
|||||||
provider_address = '{{ core.debug.stats_reporting.provider_address }}'
|
provider_address = '{{ core.debug.stats_reporting.provider_address }}'
|
||||||
reporting_interval = '{{ core.debug.stats_reporting.reporting_interval }}'
|
reporting_interval = '{{ core.debug.stats_reporting.reporting_interval }}'
|
||||||
|
|
||||||
[core.debug.forget_me]
|
|
||||||
client = {{ core.debug.forget_me.client }}
|
|
||||||
stats = {{ core.debug.forget_me.stats }}
|
|
||||||
|
|
||||||
"#;
|
"#;
|
||||||
|
|||||||
@@ -1,3 +1,2 @@
|
|||||||
allow-unwrap-in-tests = true
|
allow-unwrap-in-tests = true
|
||||||
allow-expect-in-tests = true
|
allow-expect-in-tests = true
|
||||||
allow-panic-in-tests = true
|
|
||||||
@@ -6,15 +6,14 @@ pub mod v1;
|
|||||||
pub mod v2;
|
pub mod v2;
|
||||||
pub mod v3;
|
pub mod v3;
|
||||||
pub mod v4;
|
pub mod v4;
|
||||||
pub mod v5;
|
|
||||||
|
|
||||||
mod error;
|
mod error;
|
||||||
mod util;
|
mod util;
|
||||||
|
|
||||||
pub use error::Error;
|
pub use error::Error;
|
||||||
pub use v5 as latest;
|
pub use v4 as latest;
|
||||||
|
|
||||||
pub const CURRENT_VERSION: u8 = 5;
|
pub const CURRENT_VERSION: u8 = 4;
|
||||||
|
|
||||||
fn make_bincode_serializer() -> impl bincode::Options {
|
fn make_bincode_serializer() -> impl bincode::Options {
|
||||||
use bincode::Options;
|
use bincode::Options;
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ use nym_sphinx::addressing::clients::Recipient;
|
|||||||
use nym_wireguard_types::PeerPublicKey;
|
use nym_wireguard_types::PeerPublicKey;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
v1, v2, v3, v4,
|
v1, v2, v3,
|
||||||
v5::{self, registration::IpPair},
|
v4::{self, registration::IpPair},
|
||||||
Error,
|
Error,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -19,7 +19,6 @@ pub enum AuthenticatorVersion {
|
|||||||
V2,
|
V2,
|
||||||
V3,
|
V3,
|
||||||
V4,
|
V4,
|
||||||
V5,
|
|
||||||
UNKNOWN,
|
UNKNOWN,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -35,8 +34,6 @@ impl From<Protocol> for AuthenticatorVersion {
|
|||||||
AuthenticatorVersion::V3
|
AuthenticatorVersion::V3
|
||||||
} else if value.version == v4::VERSION {
|
} else if value.version == v4::VERSION {
|
||||||
AuthenticatorVersion::V4
|
AuthenticatorVersion::V4
|
||||||
} else if value.version == v5::VERSION {
|
|
||||||
AuthenticatorVersion::V5
|
|
||||||
} else {
|
} else {
|
||||||
AuthenticatorVersion::UNKNOWN
|
AuthenticatorVersion::UNKNOWN
|
||||||
}
|
}
|
||||||
@@ -71,12 +68,6 @@ impl InitMessage for v4::registration::InitMessage {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InitMessage for v5::registration::InitMessage {
|
|
||||||
fn pub_key(&self) -> PeerPublicKey {
|
|
||||||
self.pub_key
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait FinalMessage {
|
pub trait FinalMessage {
|
||||||
fn pub_key(&self) -> PeerPublicKey;
|
fn pub_key(&self) -> PeerPublicKey;
|
||||||
fn verify(&self, private_key: &PrivateKey, nonce: u64) -> Result<(), Error>;
|
fn verify(&self, private_key: &PrivateKey, nonce: u64) -> Result<(), Error>;
|
||||||
@@ -147,24 +138,6 @@ impl FinalMessage for v4::registration::FinalMessage {
|
|||||||
self.gateway_client.verify(private_key, nonce)
|
self.gateway_client.verify(private_key, nonce)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn private_ips(&self) -> IpPair {
|
|
||||||
self.gateway_client.private_ips.into()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn credential(&self) -> Option<CredentialSpendingData> {
|
|
||||||
self.credential.clone()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FinalMessage for v5::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 {
|
fn private_ips(&self) -> IpPair {
|
||||||
self.gateway_client.private_ips
|
self.gateway_client.private_ips
|
||||||
}
|
}
|
||||||
@@ -209,39 +182,29 @@ impl TopUpMessage for v4::topup::TopUpMessage {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TopUpMessage for v5::topup::TopUpMessage {
|
|
||||||
fn pub_key(&self) -> PeerPublicKey {
|
|
||||||
self.pub_key
|
|
||||||
}
|
|
||||||
|
|
||||||
fn credential(&self) -> CredentialSpendingData {
|
|
||||||
self.credential.clone()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum AuthenticatorRequest {
|
pub enum AuthenticatorRequest {
|
||||||
Initial {
|
Initial {
|
||||||
msg: Box<dyn InitMessage + Send + Sync + 'static>,
|
msg: Box<dyn InitMessage + Send + Sync + 'static>,
|
||||||
protocol: Protocol,
|
protocol: Protocol,
|
||||||
reply_to: Option<Recipient>,
|
reply_to: Recipient,
|
||||||
request_id: u64,
|
request_id: u64,
|
||||||
},
|
},
|
||||||
Final {
|
Final {
|
||||||
msg: Box<dyn FinalMessage + Send + Sync + 'static>,
|
msg: Box<dyn FinalMessage + Send + Sync + 'static>,
|
||||||
protocol: Protocol,
|
protocol: Protocol,
|
||||||
reply_to: Option<Recipient>,
|
reply_to: Recipient,
|
||||||
request_id: u64,
|
request_id: u64,
|
||||||
},
|
},
|
||||||
QueryBandwidth {
|
QueryBandwidth {
|
||||||
msg: Box<dyn QueryBandwidthMessage + Send + Sync + 'static>,
|
msg: Box<dyn QueryBandwidthMessage + Send + Sync + 'static>,
|
||||||
protocol: Protocol,
|
protocol: Protocol,
|
||||||
reply_to: Option<Recipient>,
|
reply_to: Recipient,
|
||||||
request_id: u64,
|
request_id: u64,
|
||||||
},
|
},
|
||||||
TopUpBandwidth {
|
TopUpBandwidth {
|
||||||
msg: Box<dyn TopUpMessage + Send + Sync + 'static>,
|
msg: Box<dyn TopUpMessage + Send + Sync + 'static>,
|
||||||
protocol: Protocol,
|
protocol: Protocol,
|
||||||
reply_to: Option<Recipient>,
|
reply_to: Recipient,
|
||||||
request_id: u64,
|
request_id: u64,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -255,7 +218,7 @@ impl From<v1::request::AuthenticatorRequest> for AuthenticatorRequest {
|
|||||||
version: value.version,
|
version: value.version,
|
||||||
service_provider_type: ServiceProviderType::Authenticator,
|
service_provider_type: ServiceProviderType::Authenticator,
|
||||||
},
|
},
|
||||||
reply_to: Some(value.reply_to),
|
reply_to: value.reply_to,
|
||||||
request_id: value.request_id,
|
request_id: value.request_id,
|
||||||
},
|
},
|
||||||
v1::request::AuthenticatorRequestData::Final(gateway_client) => Self::Final {
|
v1::request::AuthenticatorRequestData::Final(gateway_client) => Self::Final {
|
||||||
@@ -264,7 +227,7 @@ impl From<v1::request::AuthenticatorRequest> for AuthenticatorRequest {
|
|||||||
version: value.version,
|
version: value.version,
|
||||||
service_provider_type: ServiceProviderType::Authenticator,
|
service_provider_type: ServiceProviderType::Authenticator,
|
||||||
},
|
},
|
||||||
reply_to: Some(value.reply_to),
|
reply_to: value.reply_to,
|
||||||
request_id: value.request_id,
|
request_id: value.request_id,
|
||||||
},
|
},
|
||||||
v1::request::AuthenticatorRequestData::QueryBandwidth(peer_public_key) => {
|
v1::request::AuthenticatorRequestData::QueryBandwidth(peer_public_key) => {
|
||||||
@@ -274,7 +237,7 @@ impl From<v1::request::AuthenticatorRequest> for AuthenticatorRequest {
|
|||||||
version: value.version,
|
version: value.version,
|
||||||
service_provider_type: ServiceProviderType::Authenticator,
|
service_provider_type: ServiceProviderType::Authenticator,
|
||||||
},
|
},
|
||||||
reply_to: Some(value.reply_to),
|
reply_to: value.reply_to,
|
||||||
request_id: value.request_id,
|
request_id: value.request_id,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -288,20 +251,20 @@ impl From<v2::request::AuthenticatorRequest> for AuthenticatorRequest {
|
|||||||
v2::request::AuthenticatorRequestData::Initial(init_message) => Self::Initial {
|
v2::request::AuthenticatorRequestData::Initial(init_message) => Self::Initial {
|
||||||
msg: Box::new(init_message),
|
msg: Box::new(init_message),
|
||||||
protocol: value.protocol,
|
protocol: value.protocol,
|
||||||
reply_to: Some(value.reply_to),
|
reply_to: value.reply_to,
|
||||||
request_id: value.request_id,
|
request_id: value.request_id,
|
||||||
},
|
},
|
||||||
v2::request::AuthenticatorRequestData::Final(final_message) => Self::Final {
|
v2::request::AuthenticatorRequestData::Final(final_message) => Self::Final {
|
||||||
msg: final_message,
|
msg: final_message,
|
||||||
protocol: value.protocol,
|
protocol: value.protocol,
|
||||||
reply_to: Some(value.reply_to),
|
reply_to: value.reply_to,
|
||||||
request_id: value.request_id,
|
request_id: value.request_id,
|
||||||
},
|
},
|
||||||
v2::request::AuthenticatorRequestData::QueryBandwidth(peer_public_key) => {
|
v2::request::AuthenticatorRequestData::QueryBandwidth(peer_public_key) => {
|
||||||
Self::QueryBandwidth {
|
Self::QueryBandwidth {
|
||||||
msg: Box::new(peer_public_key),
|
msg: Box::new(peer_public_key),
|
||||||
protocol: value.protocol,
|
protocol: value.protocol,
|
||||||
reply_to: Some(value.reply_to),
|
reply_to: value.reply_to,
|
||||||
request_id: value.request_id,
|
request_id: value.request_id,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -315,20 +278,20 @@ impl From<v3::request::AuthenticatorRequest> for AuthenticatorRequest {
|
|||||||
v3::request::AuthenticatorRequestData::Initial(init_message) => Self::Initial {
|
v3::request::AuthenticatorRequestData::Initial(init_message) => Self::Initial {
|
||||||
msg: Box::new(init_message),
|
msg: Box::new(init_message),
|
||||||
protocol: value.protocol,
|
protocol: value.protocol,
|
||||||
reply_to: Some(value.reply_to),
|
reply_to: value.reply_to,
|
||||||
request_id: value.request_id,
|
request_id: value.request_id,
|
||||||
},
|
},
|
||||||
v3::request::AuthenticatorRequestData::Final(final_message) => Self::Final {
|
v3::request::AuthenticatorRequestData::Final(final_message) => Self::Final {
|
||||||
msg: final_message,
|
msg: final_message,
|
||||||
protocol: value.protocol,
|
protocol: value.protocol,
|
||||||
reply_to: Some(value.reply_to),
|
reply_to: value.reply_to,
|
||||||
request_id: value.request_id,
|
request_id: value.request_id,
|
||||||
},
|
},
|
||||||
v3::request::AuthenticatorRequestData::QueryBandwidth(peer_public_key) => {
|
v3::request::AuthenticatorRequestData::QueryBandwidth(peer_public_key) => {
|
||||||
Self::QueryBandwidth {
|
Self::QueryBandwidth {
|
||||||
msg: Box::new(peer_public_key),
|
msg: Box::new(peer_public_key),
|
||||||
protocol: value.protocol,
|
protocol: value.protocol,
|
||||||
reply_to: Some(value.reply_to),
|
reply_to: value.reply_to,
|
||||||
request_id: value.request_id,
|
request_id: value.request_id,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -336,7 +299,7 @@ impl From<v3::request::AuthenticatorRequest> for AuthenticatorRequest {
|
|||||||
Self::TopUpBandwidth {
|
Self::TopUpBandwidth {
|
||||||
msg: top_up_message,
|
msg: top_up_message,
|
||||||
protocol: value.protocol,
|
protocol: value.protocol,
|
||||||
reply_to: Some(value.reply_to),
|
reply_to: value.reply_to,
|
||||||
request_id: value.request_id,
|
request_id: value.request_id,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -350,20 +313,20 @@ impl From<v4::request::AuthenticatorRequest> for AuthenticatorRequest {
|
|||||||
v4::request::AuthenticatorRequestData::Initial(init_message) => Self::Initial {
|
v4::request::AuthenticatorRequestData::Initial(init_message) => Self::Initial {
|
||||||
msg: Box::new(init_message),
|
msg: Box::new(init_message),
|
||||||
protocol: value.protocol,
|
protocol: value.protocol,
|
||||||
reply_to: Some(value.reply_to),
|
reply_to: value.reply_to,
|
||||||
request_id: value.request_id,
|
request_id: value.request_id,
|
||||||
},
|
},
|
||||||
v4::request::AuthenticatorRequestData::Final(final_message) => Self::Final {
|
v4::request::AuthenticatorRequestData::Final(final_message) => Self::Final {
|
||||||
msg: final_message,
|
msg: final_message,
|
||||||
protocol: value.protocol,
|
protocol: value.protocol,
|
||||||
reply_to: Some(value.reply_to),
|
reply_to: value.reply_to,
|
||||||
request_id: value.request_id,
|
request_id: value.request_id,
|
||||||
},
|
},
|
||||||
v4::request::AuthenticatorRequestData::QueryBandwidth(peer_public_key) => {
|
v4::request::AuthenticatorRequestData::QueryBandwidth(peer_public_key) => {
|
||||||
Self::QueryBandwidth {
|
Self::QueryBandwidth {
|
||||||
msg: Box::new(peer_public_key),
|
msg: Box::new(peer_public_key),
|
||||||
protocol: value.protocol,
|
protocol: value.protocol,
|
||||||
reply_to: Some(value.reply_to),
|
reply_to: value.reply_to,
|
||||||
request_id: value.request_id,
|
request_id: value.request_id,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -371,42 +334,7 @@ impl From<v4::request::AuthenticatorRequest> for AuthenticatorRequest {
|
|||||||
Self::TopUpBandwidth {
|
Self::TopUpBandwidth {
|
||||||
msg: top_up_message,
|
msg: top_up_message,
|
||||||
protocol: value.protocol,
|
protocol: value.protocol,
|
||||||
reply_to: Some(value.reply_to),
|
reply_to: value.reply_to,
|
||||||
request_id: value.request_id,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v5::request::AuthenticatorRequest> for AuthenticatorRequest {
|
|
||||||
fn from(value: v5::request::AuthenticatorRequest) -> Self {
|
|
||||||
match value.data {
|
|
||||||
v5::request::AuthenticatorRequestData::Initial(init_message) => Self::Initial {
|
|
||||||
msg: Box::new(init_message),
|
|
||||||
protocol: value.protocol,
|
|
||||||
reply_to: None,
|
|
||||||
request_id: value.request_id,
|
|
||||||
},
|
|
||||||
v5::request::AuthenticatorRequestData::Final(final_message) => Self::Final {
|
|
||||||
msg: final_message,
|
|
||||||
protocol: value.protocol,
|
|
||||||
reply_to: None,
|
|
||||||
request_id: value.request_id,
|
|
||||||
},
|
|
||||||
v5::request::AuthenticatorRequestData::QueryBandwidth(peer_public_key) => {
|
|
||||||
Self::QueryBandwidth {
|
|
||||||
msg: Box::new(peer_public_key),
|
|
||||||
protocol: value.protocol,
|
|
||||||
reply_to: None,
|
|
||||||
request_id: value.request_id,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
v5::request::AuthenticatorRequestData::TopUpBandwidth(top_up_message) => {
|
|
||||||
Self::TopUpBandwidth {
|
|
||||||
msg: top_up_message,
|
|
||||||
protocol: value.protocol,
|
|
||||||
reply_to: None,
|
|
||||||
request_id: value.request_id,
|
request_id: value.request_id,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 {
|
||||||
@@ -60,7 +60,7 @@ impl From<IpAddr> for IpPair {
|
|||||||
std::net::IpAddr::V4(ipv4_addr) => (ipv4_addr.octets()[2], ipv4_addr.octets()[3]),
|
std::net::IpAddr::V4(ipv4_addr) => (ipv4_addr.octets()[2], ipv4_addr.octets()[3]),
|
||||||
std::net::IpAddr::V6(ipv6_addr) => (ipv6_addr.octets()[14], ipv6_addr.octets()[15]),
|
std::net::IpAddr::V6(ipv6_addr) => (ipv6_addr.octets()[14], ipv6_addr.octets()[15]),
|
||||||
};
|
};
|
||||||
let last_bytes = ((before_last_byte as u16) << 8) | last_byte as u16;
|
let last_bytes = (before_last_byte as u16) << 8 | last_byte as u16;
|
||||||
let ipv4 = Ipv4Addr::new(
|
let ipv4 = Ipv4Addr::new(
|
||||||
WG_TUN_DEVICE_IP_ADDRESS_V4.octets()[0],
|
WG_TUN_DEVICE_IP_ADDRESS_V4.octets()[0],
|
||||||
WG_TUN_DEVICE_IP_ADDRESS_V4.octets()[1],
|
WG_TUN_DEVICE_IP_ADDRESS_V4.octets()[1],
|
||||||
|
|||||||
@@ -1,478 +0,0 @@
|
|||||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
use nym_service_provider_requests_common::{Protocol, ServiceProviderType};
|
|
||||||
|
|
||||||
use crate::{v4, v5};
|
|
||||||
|
|
||||||
impl From<v4::request::AuthenticatorRequest> for v5::request::AuthenticatorRequest {
|
|
||||||
fn from(authenticator_request: v4::request::AuthenticatorRequest) -> Self {
|
|
||||||
Self {
|
|
||||||
protocol: Protocol {
|
|
||||||
version: 5,
|
|
||||||
service_provider_type: ServiceProviderType::Authenticator,
|
|
||||||
},
|
|
||||||
data: authenticator_request.data.into(),
|
|
||||||
request_id: authenticator_request.request_id,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v4::request::AuthenticatorRequestData> for v5::request::AuthenticatorRequestData {
|
|
||||||
fn from(authenticator_request_data: v4::request::AuthenticatorRequestData) -> Self {
|
|
||||||
match authenticator_request_data {
|
|
||||||
v4::request::AuthenticatorRequestData::Initial(init_msg) => {
|
|
||||||
v5::request::AuthenticatorRequestData::Initial(init_msg.into())
|
|
||||||
}
|
|
||||||
v4::request::AuthenticatorRequestData::Final(final_msg) => {
|
|
||||||
v5::request::AuthenticatorRequestData::Final(Box::new((*final_msg).into()))
|
|
||||||
}
|
|
||||||
v4::request::AuthenticatorRequestData::QueryBandwidth(pub_key) => {
|
|
||||||
v5::request::AuthenticatorRequestData::QueryBandwidth(pub_key)
|
|
||||||
}
|
|
||||||
v4::request::AuthenticatorRequestData::TopUpBandwidth(top_up_message) => {
|
|
||||||
v5::request::AuthenticatorRequestData::TopUpBandwidth(top_up_message.into())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v4::registration::InitMessage> for v5::registration::InitMessage {
|
|
||||||
fn from(init_msg: v4::registration::InitMessage) -> Self {
|
|
||||||
Self {
|
|
||||||
pub_key: init_msg.pub_key,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v4::registration::FinalMessage> for v5::registration::FinalMessage {
|
|
||||||
fn from(final_msg: v4::registration::FinalMessage) -> Self {
|
|
||||||
Self {
|
|
||||||
gateway_client: final_msg.gateway_client.into(),
|
|
||||||
credential: final_msg.credential,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v4::registration::GatewayClient> for v5::registration::GatewayClient {
|
|
||||||
fn from(gateway_client: v4::registration::GatewayClient) -> Self {
|
|
||||||
Self {
|
|
||||||
pub_key: gateway_client.pub_key,
|
|
||||||
private_ips: gateway_client.private_ips.into(),
|
|
||||||
mac: gateway_client.mac.into(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v5::registration::GatewayClient> for v4::registration::GatewayClient {
|
|
||||||
fn from(gateway_client: v5::registration::GatewayClient) -> Self {
|
|
||||||
Self {
|
|
||||||
pub_key: gateway_client.pub_key,
|
|
||||||
private_ips: gateway_client.private_ips.into(),
|
|
||||||
mac: gateway_client.mac.into(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v4::registration::ClientMac> for v5::registration::ClientMac {
|
|
||||||
fn from(client_mac: v4::registration::ClientMac) -> Self {
|
|
||||||
Self::new((*client_mac).clone())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v5::registration::ClientMac> for v4::registration::ClientMac {
|
|
||||||
fn from(client_mac: v5::registration::ClientMac) -> Self {
|
|
||||||
Self::new((*client_mac).clone())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<Box<v4::topup::TopUpMessage>> for Box<v5::topup::TopUpMessage> {
|
|
||||||
fn from(top_up_message: Box<v4::topup::TopUpMessage>) -> Self {
|
|
||||||
Box::new(v5::topup::TopUpMessage {
|
|
||||||
pub_key: top_up_message.pub_key,
|
|
||||||
credential: top_up_message.credential,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v4::response::AuthenticatorResponse> for v5::response::AuthenticatorResponse {
|
|
||||||
fn from(value: v4::response::AuthenticatorResponse) -> Self {
|
|
||||||
Self {
|
|
||||||
protocol: Protocol {
|
|
||||||
version: 5,
|
|
||||||
service_provider_type: value.protocol.service_provider_type,
|
|
||||||
},
|
|
||||||
data: value.data.into(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v4::response::AuthenticatorResponseData> for v5::response::AuthenticatorResponseData {
|
|
||||||
fn from(authenticator_response_data: v4::response::AuthenticatorResponseData) -> Self {
|
|
||||||
match authenticator_response_data {
|
|
||||||
v4::response::AuthenticatorResponseData::PendingRegistration(pending_response) => {
|
|
||||||
v5::response::AuthenticatorResponseData::PendingRegistration(
|
|
||||||
pending_response.into(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
v4::response::AuthenticatorResponseData::Registered(registered_response) => {
|
|
||||||
v5::response::AuthenticatorResponseData::Registered(registered_response.into())
|
|
||||||
}
|
|
||||||
v4::response::AuthenticatorResponseData::RemainingBandwidth(
|
|
||||||
remaining_bandwidth_response,
|
|
||||||
) => v5::response::AuthenticatorResponseData::RemainingBandwidth(
|
|
||||||
remaining_bandwidth_response.into(),
|
|
||||||
),
|
|
||||||
v4::response::AuthenticatorResponseData::TopUpBandwidth(top_up_response) => {
|
|
||||||
v5::response::AuthenticatorResponseData::TopUpBandwidth(top_up_response.into())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v4::response::RegisteredResponse> for v5::response::RegisteredResponse {
|
|
||||||
fn from(value: v4::response::RegisteredResponse) -> Self {
|
|
||||||
Self {
|
|
||||||
request_id: value.request_id,
|
|
||||||
reply: value.reply.into(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v4::response::PendingRegistrationResponse> for v5::response::PendingRegistrationResponse {
|
|
||||||
fn from(value: v4::response::PendingRegistrationResponse) -> Self {
|
|
||||||
Self {
|
|
||||||
request_id: value.request_id,
|
|
||||||
reply: value.reply.into(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v4::registration::RegistrationData> for v5::registration::RegistrationData {
|
|
||||||
fn from(value: v4::registration::RegistrationData) -> Self {
|
|
||||||
Self {
|
|
||||||
nonce: value.nonce,
|
|
||||||
gateway_data: value.gateway_data.into(),
|
|
||||||
wg_port: value.wg_port,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v5::registration::RegistrationData> for v4::registration::RegistrationData {
|
|
||||||
fn from(value: v5::registration::RegistrationData) -> Self {
|
|
||||||
Self {
|
|
||||||
nonce: value.nonce,
|
|
||||||
gateway_data: value.gateway_data.into(),
|
|
||||||
wg_port: value.wg_port,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v4::response::RemainingBandwidthResponse> for v5::response::RemainingBandwidthResponse {
|
|
||||||
fn from(value: v4::response::RemainingBandwidthResponse) -> Self {
|
|
||||||
Self {
|
|
||||||
request_id: value.request_id,
|
|
||||||
reply: value.reply.map(Into::into),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v4::response::TopUpBandwidthResponse> for v5::response::TopUpBandwidthResponse {
|
|
||||||
fn from(value: v4::response::TopUpBandwidthResponse) -> Self {
|
|
||||||
Self {
|
|
||||||
request_id: value.request_id,
|
|
||||||
reply: value.reply.into(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v4::registration::RegistredData> for v5::registration::RegistredData {
|
|
||||||
fn from(value: v4::registration::RegistredData) -> Self {
|
|
||||||
Self {
|
|
||||||
pub_key: value.pub_key,
|
|
||||||
private_ips: value.private_ips.into(),
|
|
||||||
wg_port: value.wg_port,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v4::registration::RemainingBandwidthData> for v5::registration::RemainingBandwidthData {
|
|
||||||
fn from(value: v4::registration::RemainingBandwidthData) -> Self {
|
|
||||||
Self {
|
|
||||||
available_bandwidth: value.available_bandwidth,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v4::registration::IpPair> for v5::registration::IpPair {
|
|
||||||
fn from(value: v4::registration::IpPair) -> Self {
|
|
||||||
Self {
|
|
||||||
ipv4: value.ipv4,
|
|
||||||
ipv6: value.ipv6,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v5::registration::IpPair> for v4::registration::IpPair {
|
|
||||||
fn from(value: v5::registration::IpPair) -> Self {
|
|
||||||
Self {
|
|
||||||
ipv4: value.ipv4,
|
|
||||||
ipv6: value.ipv6,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[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},
|
|
||||||
v4,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[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, _) = v4::request::AuthenticatorRequest::new_initial_request(
|
|
||||||
v4::registration::InitMessage::new(pub_key),
|
|
||||||
reply_to,
|
|
||||||
);
|
|
||||||
let upgraded_msg = v5::request::AuthenticatorRequest::from(msg);
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
upgraded_msg.protocol,
|
|
||||||
Protocol {
|
|
||||||
version: 5,
|
|
||||||
service_provider_type: ServiceProviderType::Authenticator
|
|
||||||
}
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
upgraded_msg.data,
|
|
||||||
v5::request::AuthenticatorRequestData::Initial(v5::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 ipv6 = Ipv6Addr::from_str("fc01::a0a").unwrap();
|
|
||||||
let ips = v4::registration::IpPair::new(ipv4, ipv6);
|
|
||||||
let nonce = 42;
|
|
||||||
let gateway_client = v4::registration::GatewayClient::new(
|
|
||||||
&local_secret,
|
|
||||||
(&remote_secret).into(),
|
|
||||||
ips,
|
|
||||||
nonce,
|
|
||||||
);
|
|
||||||
let credential = Some(CredentialSpendingData::try_from_bytes(&CREDENTIAL_BYTES).unwrap());
|
|
||||||
let final_message = v4::registration::FinalMessage {
|
|
||||||
gateway_client: gateway_client.clone(),
|
|
||||||
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);
|
|
||||||
let upgraded_msg = v5::request::AuthenticatorRequest::from(msg);
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
upgraded_msg.protocol,
|
|
||||||
Protocol {
|
|
||||||
version: 5,
|
|
||||||
service_provider_type: ServiceProviderType::Authenticator
|
|
||||||
}
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
upgraded_msg.data,
|
|
||||||
v5::request::AuthenticatorRequestData::Final(Box::new(
|
|
||||||
v5::registration::FinalMessage {
|
|
||||||
gateway_client: v5::registration::GatewayClient::new(
|
|
||||||
&local_secret,
|
|
||||||
(&remote_secret).into(),
|
|
||||||
v5::registration::IpPair::new(ipv4, ipv6),
|
|
||||||
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, _) = v4::request::AuthenticatorRequest::new_query_request(pub_key, reply_to);
|
|
||||||
let upgraded_msg = v5::request::AuthenticatorRequest::from(msg);
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
upgraded_msg.protocol,
|
|
||||||
Protocol {
|
|
||||||
version: 5,
|
|
||||||
service_provider_type: ServiceProviderType::Authenticator
|
|
||||||
}
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
upgraded_msg.data,
|
|
||||||
v5::request::AuthenticatorRequestData::QueryBandwidth(pub_key)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[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 ipv6 = Ipv6Addr::from_str("fc01::a0a").unwrap();
|
|
||||||
let ips = v4::registration::IpPair::new(ipv4, ipv6);
|
|
||||||
let nonce = 42;
|
|
||||||
let wg_port = 51822;
|
|
||||||
let gateway_data = v4::registration::GatewayClient::new(
|
|
||||||
&local_secret,
|
|
||||||
(&remote_secret).into(),
|
|
||||||
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,
|
|
||||||
);
|
|
||||||
let upgraded_msg = v5::response::AuthenticatorResponse::from(msg);
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
upgraded_msg.protocol,
|
|
||||||
Protocol {
|
|
||||||
version: 5,
|
|
||||||
service_provider_type: ServiceProviderType::Authenticator
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
upgraded_msg.data,
|
|
||||||
v5::response::AuthenticatorResponseData::PendingRegistration(
|
|
||||||
v5::response::PendingRegistrationResponse {
|
|
||||||
request_id,
|
|
||||||
reply: v5::registration::RegistrationData {
|
|
||||||
nonce,
|
|
||||||
gateway_data: v5::registration::GatewayClient::new(
|
|
||||||
&local_secret,
|
|
||||||
(&remote_secret).into(),
|
|
||||||
v5::registration::IpPair::new(ipv4, ipv6),
|
|
||||||
nonce
|
|
||||||
),
|
|
||||||
wg_port
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[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 ipv6 = Ipv6Addr::from_str("fc01::a0a").unwrap();
|
|
||||||
let private_ips = v4::registration::IpPair::new(ipv4, ipv6);
|
|
||||||
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 upgraded_msg = v5::response::AuthenticatorResponse::from(msg);
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
upgraded_msg.protocol,
|
|
||||||
Protocol {
|
|
||||||
version: 5,
|
|
||||||
service_provider_type: ServiceProviderType::Authenticator
|
|
||||||
}
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
upgraded_msg.data,
|
|
||||||
v5::response::AuthenticatorResponseData::Registered(v5::response::RegisteredResponse {
|
|
||||||
request_id,
|
|
||||||
reply: v5::registration::RegistredData {
|
|
||||||
wg_port,
|
|
||||||
pub_key,
|
|
||||||
private_ips: v5::registration::IpPair::new(ipv4, ipv6)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn upgrade_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 upgraded_msg = v5::response::AuthenticatorResponse::from(msg);
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
upgraded_msg.protocol,
|
|
||||||
Protocol {
|
|
||||||
version: 5,
|
|
||||||
service_provider_type: ServiceProviderType::Authenticator
|
|
||||||
}
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
upgraded_msg.data,
|
|
||||||
v5::response::AuthenticatorResponseData::RemainingBandwidth(
|
|
||||||
v5::response::RemainingBandwidthResponse {
|
|
||||||
request_id,
|
|
||||||
reply: Some(v5::registration::RemainingBandwidthData {
|
|
||||||
available_bandwidth,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
pub mod conversion;
|
|
||||||
pub mod registration;
|
|
||||||
pub mod request;
|
|
||||||
pub mod response;
|
|
||||||
pub mod topup;
|
|
||||||
|
|
||||||
pub const VERSION: u8 = 5;
|
|
||||||
@@ -1,287 +0,0 @@
|
|||||||
// -2024 - Nym Technologies SA <contact@nymtech.net>
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
use crate::error::Error;
|
|
||||||
use base64::{engine::general_purpose, Engine};
|
|
||||||
use nym_credentials_interface::CredentialSpendingData;
|
|
||||||
use nym_network_defaults::constants::{WG_TUN_DEVICE_IP_ADDRESS_V4, WG_TUN_DEVICE_IP_ADDRESS_V6};
|
|
||||||
use nym_wireguard_types::PeerPublicKey;
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
|
|
||||||
use std::time::SystemTime;
|
|
||||||
use std::{fmt, ops::Deref, str::FromStr};
|
|
||||||
|
|
||||||
#[cfg(feature = "verify")]
|
|
||||||
use hmac::{Hmac, Mac};
|
|
||||||
#[cfg(feature = "verify")]
|
|
||||||
use nym_crypto::asymmetric::encryption::PrivateKey;
|
|
||||||
#[cfg(feature = "verify")]
|
|
||||||
use sha2::Sha256;
|
|
||||||
|
|
||||||
pub type PendingRegistrations = HashMap<PeerPublicKey, RegistrationData>;
|
|
||||||
pub type PrivateIPs = HashMap<IpPair, Taken>;
|
|
||||||
|
|
||||||
#[cfg(feature = "verify")]
|
|
||||||
pub type HmacSha256 = Hmac<Sha256>;
|
|
||||||
|
|
||||||
pub type Nonce = u64;
|
|
||||||
pub type Taken = Option<SystemTime>;
|
|
||||||
|
|
||||||
pub const BANDWIDTH_CAP_PER_DAY: u64 = 250 * 1024 * 1024 * 1024; // 250 GB
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
|
||||||
pub struct IpPair {
|
|
||||||
pub ipv4: Ipv4Addr,
|
|
||||||
pub ipv6: Ipv6Addr,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl IpPair {
|
|
||||||
pub fn new(ipv4: Ipv4Addr, ipv6: Ipv6Addr) -> Self {
|
|
||||||
IpPair { ipv4, ipv6 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<(Ipv4Addr, Ipv6Addr)> for IpPair {
|
|
||||||
fn from((ipv4, ipv6): (Ipv4Addr, Ipv6Addr)) -> Self {
|
|
||||||
IpPair { ipv4, ipv6 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for IpPair {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
write!(f, "({}, {})", self.ipv4, self.ipv6)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<IpAddr> for IpPair {
|
|
||||||
fn from(value: IpAddr) -> Self {
|
|
||||||
let (before_last_byte, last_byte) = match value {
|
|
||||||
std::net::IpAddr::V4(ipv4_addr) => (ipv4_addr.octets()[2], ipv4_addr.octets()[3]),
|
|
||||||
std::net::IpAddr::V6(ipv6_addr) => (ipv6_addr.octets()[14], ipv6_addr.octets()[15]),
|
|
||||||
};
|
|
||||||
let last_bytes = ((before_last_byte as u16) << 8) | last_byte as u16;
|
|
||||||
let ipv4 = Ipv4Addr::new(
|
|
||||||
WG_TUN_DEVICE_IP_ADDRESS_V4.octets()[0],
|
|
||||||
WG_TUN_DEVICE_IP_ADDRESS_V4.octets()[1],
|
|
||||||
before_last_byte,
|
|
||||||
last_byte,
|
|
||||||
);
|
|
||||||
let ipv6 = Ipv6Addr::new(
|
|
||||||
WG_TUN_DEVICE_IP_ADDRESS_V6.segments()[0],
|
|
||||||
WG_TUN_DEVICE_IP_ADDRESS_V6.segments()[1],
|
|
||||||
WG_TUN_DEVICE_IP_ADDRESS_V6.segments()[2],
|
|
||||||
WG_TUN_DEVICE_IP_ADDRESS_V6.segments()[3],
|
|
||||||
WG_TUN_DEVICE_IP_ADDRESS_V6.segments()[4],
|
|
||||||
WG_TUN_DEVICE_IP_ADDRESS_V6.segments()[5],
|
|
||||||
WG_TUN_DEVICE_IP_ADDRESS_V6.segments()[6],
|
|
||||||
last_bytes,
|
|
||||||
);
|
|
||||||
IpPair::new(ipv4, ipv6)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
|
|
||||||
pub struct InitMessage {
|
|
||||||
/// Base64 encoded x25519 public key
|
|
||||||
pub pub_key: PeerPublicKey,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl InitMessage {
|
|
||||||
pub fn new(pub_key: PeerPublicKey) -> Self {
|
|
||||||
InitMessage { pub_key }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
|
|
||||||
pub struct FinalMessage {
|
|
||||||
/// Gateway client data
|
|
||||||
pub gateway_client: GatewayClient,
|
|
||||||
|
|
||||||
/// Ecash credential
|
|
||||||
pub credential: Option<CredentialSpendingData>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
|
|
||||||
pub struct RegistrationData {
|
|
||||||
pub nonce: u64,
|
|
||||||
pub gateway_data: GatewayClient,
|
|
||||||
pub wg_port: u16,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
|
|
||||||
pub struct RegistredData {
|
|
||||||
pub pub_key: PeerPublicKey,
|
|
||||||
pub private_ips: IpPair,
|
|
||||||
pub wg_port: u16,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
|
|
||||||
pub struct RemainingBandwidthData {
|
|
||||||
pub available_bandwidth: i64,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 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
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
|
|
||||||
pub struct GatewayClient {
|
|
||||||
/// Base64 encoded x25519 public key
|
|
||||||
pub pub_key: PeerPublicKey,
|
|
||||||
|
|
||||||
/// Assigned private IPs (v4 and v6)
|
|
||||||
pub private_ips: IpPair,
|
|
||||||
|
|
||||||
/// Sha256 hmac on the data (alongside the prior nonce)
|
|
||||||
pub mac: ClientMac,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GatewayClient {
|
|
||||||
#[cfg(feature = "verify")]
|
|
||||||
pub fn new(
|
|
||||||
local_secret: &PrivateKey,
|
|
||||||
remote_public: x25519_dalek::PublicKey,
|
|
||||||
private_ips: IpPair,
|
|
||||||
nonce: u64,
|
|
||||||
) -> Self {
|
|
||||||
// convert from 1.0 x25519-dalek private key into 2.0 x25519-dalek
|
|
||||||
#[allow(clippy::expect_used)]
|
|
||||||
let static_secret = x25519_dalek::StaticSecret::from(local_secret.to_bytes());
|
|
||||||
let local_public: x25519_dalek::PublicKey = (&static_secret).into();
|
|
||||||
|
|
||||||
let dh = static_secret.diffie_hellman(&remote_public);
|
|
||||||
|
|
||||||
// TODO: change that to use our nym_crypto::hmac module instead
|
|
||||||
#[allow(clippy::expect_used)]
|
|
||||||
let mut mac = HmacSha256::new_from_slice(dh.as_bytes())
|
|
||||||
.expect("x25519 shared secret is always 32 bytes long");
|
|
||||||
|
|
||||||
mac.update(local_public.as_bytes());
|
|
||||||
mac.update(private_ips.to_string().as_bytes());
|
|
||||||
mac.update(&nonce.to_le_bytes());
|
|
||||||
|
|
||||||
GatewayClient {
|
|
||||||
pub_key: PeerPublicKey::new(local_public),
|
|
||||||
private_ips,
|
|
||||||
mac: ClientMac(mac.finalize().into_bytes().to_vec()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reusable secret should be gateways Wireguard PK
|
|
||||||
// Client should perform this step when generating its payload, using its own WG PK
|
|
||||||
#[cfg(feature = "verify")]
|
|
||||||
pub fn verify(&self, gateway_key: &PrivateKey, nonce: u64) -> Result<(), Error> {
|
|
||||||
// convert from 1.0 x25519-dalek private key into 2.0 x25519-dalek
|
|
||||||
#[allow(clippy::expect_used)]
|
|
||||||
let static_secret = x25519_dalek::StaticSecret::from(gateway_key.to_bytes());
|
|
||||||
|
|
||||||
let dh = static_secret.diffie_hellman(&self.pub_key);
|
|
||||||
|
|
||||||
// TODO: change that to use our nym_crypto::hmac module instead
|
|
||||||
#[allow(clippy::expect_used)]
|
|
||||||
let mut mac = HmacSha256::new_from_slice(dh.as_bytes())
|
|
||||||
.expect("x25519 shared secret is always 32 bytes long");
|
|
||||||
|
|
||||||
mac.update(self.pub_key.as_bytes());
|
|
||||||
mac.update(self.private_ips.to_string().as_bytes());
|
|
||||||
mac.update(&nonce.to_le_bytes());
|
|
||||||
|
|
||||||
mac.verify_slice(&self.mac)
|
|
||||||
.map_err(|source| Error::FailedClientMacVerification {
|
|
||||||
client: self.pub_key.to_string(),
|
|
||||||
source,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn pub_key(&self) -> PeerPublicKey {
|
|
||||||
self.pub_key
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: change the inner type into generic array of size HmacSha256::OutputSize
|
|
||||||
// TODO2: rely on our internal crypto/hmac
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
|
||||||
pub struct ClientMac(Vec<u8>);
|
|
||||||
|
|
||||||
impl fmt::Display for ClientMac {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
write!(f, "{}", general_purpose::STANDARD.encode(&self.0))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ClientMac {
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub fn new(mac: Vec<u8>) -> Self {
|
|
||||||
ClientMac(mac)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Deref for ClientMac {
|
|
||||||
type Target = Vec<u8>;
|
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
|
||||||
&self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FromStr for ClientMac {
|
|
||||||
type Err = Error;
|
|
||||||
|
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
||||||
let mac_bytes: Vec<u8> =
|
|
||||||
general_purpose::STANDARD
|
|
||||||
.decode(s)
|
|
||||||
.map_err(|source| Error::MalformedClientMac {
|
|
||||||
mac: s.to_string(),
|
|
||||||
source,
|
|
||||||
})?;
|
|
||||||
|
|
||||||
Ok(ClientMac(mac_bytes))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Serialize for ClientMac {
|
|
||||||
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
|
||||||
let encoded_key = general_purpose::STANDARD.encode(self.0.clone());
|
|
||||||
serializer.serialize_str(&encoded_key)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'de> Deserialize<'de> for ClientMac {
|
|
||||||
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
|
|
||||||
let encoded_key = String::deserialize(deserializer)?;
|
|
||||||
ClientMac::from_str(&encoded_key).map_err(serde::de::Error::custom)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
use nym_crypto::asymmetric::encryption;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn create_ip_pair() {
|
|
||||||
let ipv4: IpAddr = Ipv4Addr::from_str("10.1.10.50").unwrap().into();
|
|
||||||
let ipv6: IpAddr = Ipv6Addr::from_str("fc01::0a32").unwrap().into();
|
|
||||||
|
|
||||||
assert_eq!(IpPair::from(ipv4), IpPair::from(ipv6));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
#[cfg(feature = "verify")]
|
|
||||||
fn client_request_roundtrip() {
|
|
||||||
let mut rng = rand::thread_rng();
|
|
||||||
|
|
||||||
let gateway_key_pair = encryption::KeyPair::new(&mut rng);
|
|
||||||
let client_key_pair = encryption::KeyPair::new(&mut rng);
|
|
||||||
|
|
||||||
let nonce = 1234567890;
|
|
||||||
|
|
||||||
let client = GatewayClient::new(
|
|
||||||
client_key_pair.private_key(),
|
|
||||||
x25519_dalek::PublicKey::from(gateway_key_pair.public_key().to_bytes()),
|
|
||||||
IpPair::new("10.0.0.42".parse().unwrap(), "fc00::42".parse().unwrap()),
|
|
||||||
nonce,
|
|
||||||
);
|
|
||||||
assert!(client.verify(gateway_key_pair.private_key(), nonce).is_ok())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,132 +0,0 @@
|
|||||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
use super::{
|
|
||||||
registration::{FinalMessage, InitMessage},
|
|
||||||
topup::TopUpMessage,
|
|
||||||
};
|
|
||||||
use nym_service_provider_requests_common::{Protocol, ServiceProviderType};
|
|
||||||
use nym_wireguard_types::PeerPublicKey;
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
use crate::make_bincode_serializer;
|
|
||||||
|
|
||||||
use super::VERSION;
|
|
||||||
|
|
||||||
fn generate_random() -> u64 {
|
|
||||||
use rand::RngCore;
|
|
||||||
let mut rng = rand::rngs::OsRng;
|
|
||||||
rng.next_u64()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
||||||
pub struct AuthenticatorRequest {
|
|
||||||
pub protocol: Protocol,
|
|
||||||
pub data: AuthenticatorRequestData,
|
|
||||||
pub request_id: u64,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AuthenticatorRequest {
|
|
||||||
pub fn from_reconstructed_message(
|
|
||||||
message: &nym_sphinx::receiver::ReconstructedMessage,
|
|
||||||
) -> Result<Self, bincode::Error> {
|
|
||||||
use bincode::Options;
|
|
||||||
make_bincode_serializer().deserialize(&message.message)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new_initial_request(init_message: InitMessage) -> (Self, u64) {
|
|
||||||
let request_id = generate_random();
|
|
||||||
(
|
|
||||||
Self {
|
|
||||||
protocol: Protocol {
|
|
||||||
service_provider_type: ServiceProviderType::Authenticator,
|
|
||||||
version: VERSION,
|
|
||||||
},
|
|
||||||
data: AuthenticatorRequestData::Initial(init_message),
|
|
||||||
request_id,
|
|
||||||
},
|
|
||||||
request_id,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new_final_request(final_message: FinalMessage) -> (Self, u64) {
|
|
||||||
let request_id = generate_random();
|
|
||||||
(
|
|
||||||
Self {
|
|
||||||
protocol: Protocol {
|
|
||||||
service_provider_type: ServiceProviderType::Authenticator,
|
|
||||||
version: VERSION,
|
|
||||||
},
|
|
||||||
data: AuthenticatorRequestData::Final(Box::new(final_message)),
|
|
||||||
request_id,
|
|
||||||
},
|
|
||||||
request_id,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new_query_request(peer_public_key: PeerPublicKey) -> (Self, u64) {
|
|
||||||
let request_id = generate_random();
|
|
||||||
(
|
|
||||||
Self {
|
|
||||||
protocol: Protocol {
|
|
||||||
service_provider_type: ServiceProviderType::Authenticator,
|
|
||||||
version: VERSION,
|
|
||||||
},
|
|
||||||
data: AuthenticatorRequestData::QueryBandwidth(peer_public_key),
|
|
||||||
request_id,
|
|
||||||
},
|
|
||||||
request_id,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new_topup_request(top_up_message: TopUpMessage) -> (Self, u64) {
|
|
||||||
let request_id = generate_random();
|
|
||||||
(
|
|
||||||
Self {
|
|
||||||
protocol: Protocol {
|
|
||||||
service_provider_type: ServiceProviderType::Authenticator,
|
|
||||||
version: VERSION,
|
|
||||||
},
|
|
||||||
data: AuthenticatorRequestData::TopUpBandwidth(Box::new(top_up_message)),
|
|
||||||
request_id,
|
|
||||||
},
|
|
||||||
request_id,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn to_bytes(&self) -> Result<Vec<u8>, bincode::Error> {
|
|
||||||
use bincode::Options;
|
|
||||||
make_bincode_serializer().serialize(self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
||||||
pub enum AuthenticatorRequestData {
|
|
||||||
Initial(InitMessage),
|
|
||||||
Final(Box<FinalMessage>),
|
|
||||||
QueryBandwidth(PeerPublicKey),
|
|
||||||
TopUpBandwidth(Box<TopUpMessage>),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
use std::str::FromStr;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn check_first_bytes_protocol() {
|
|
||||||
let version = 5;
|
|
||||||
let data = AuthenticatorRequest {
|
|
||||||
protocol: Protocol {
|
|
||||||
version,
|
|
||||||
service_provider_type: ServiceProviderType::Authenticator,
|
|
||||||
},
|
|
||||||
data: AuthenticatorRequestData::Initial(InitMessage::new(
|
|
||||||
PeerPublicKey::from_str("yvNUDpT5l7W/xDhiu6HkqTHDQwbs/B3J5UrLmORl1EQ=").unwrap(),
|
|
||||||
)),
|
|
||||||
request_id: 1,
|
|
||||||
};
|
|
||||||
let bytes = *data.to_bytes().unwrap().first_chunk::<2>().unwrap();
|
|
||||||
assert_eq!(bytes, [version, ServiceProviderType::Authenticator as u8]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,132 +0,0 @@
|
|||||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
use super::registration::{RegistrationData, RegistredData, RemainingBandwidthData};
|
|
||||||
use nym_service_provider_requests_common::{Protocol, ServiceProviderType};
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
use crate::make_bincode_serializer;
|
|
||||||
|
|
||||||
use super::VERSION;
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
||||||
pub struct AuthenticatorResponse {
|
|
||||||
pub protocol: Protocol,
|
|
||||||
pub data: AuthenticatorResponseData,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AuthenticatorResponse {
|
|
||||||
pub fn new_pending_registration_success(
|
|
||||||
registration_data: RegistrationData,
|
|
||||||
request_id: u64,
|
|
||||||
) -> Self {
|
|
||||||
Self {
|
|
||||||
protocol: Protocol {
|
|
||||||
service_provider_type: ServiceProviderType::Authenticator,
|
|
||||||
version: VERSION,
|
|
||||||
},
|
|
||||||
data: AuthenticatorResponseData::PendingRegistration(PendingRegistrationResponse {
|
|
||||||
reply: registration_data,
|
|
||||||
request_id,
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new_registered(registred_data: RegistredData, request_id: u64) -> Self {
|
|
||||||
Self {
|
|
||||||
protocol: Protocol {
|
|
||||||
service_provider_type: ServiceProviderType::Authenticator,
|
|
||||||
version: VERSION,
|
|
||||||
},
|
|
||||||
data: AuthenticatorResponseData::Registered(RegisteredResponse {
|
|
||||||
reply: registred_data,
|
|
||||||
request_id,
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new_remaining_bandwidth(
|
|
||||||
remaining_bandwidth_data: Option<RemainingBandwidthData>,
|
|
||||||
request_id: u64,
|
|
||||||
) -> Self {
|
|
||||||
Self {
|
|
||||||
protocol: Protocol {
|
|
||||||
service_provider_type: ServiceProviderType::Authenticator,
|
|
||||||
version: VERSION,
|
|
||||||
},
|
|
||||||
data: AuthenticatorResponseData::RemainingBandwidth(RemainingBandwidthResponse {
|
|
||||||
reply: remaining_bandwidth_data,
|
|
||||||
request_id,
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new_topup_bandwidth(
|
|
||||||
remaining_bandwidth_data: RemainingBandwidthData,
|
|
||||||
request_id: u64,
|
|
||||||
) -> Self {
|
|
||||||
Self {
|
|
||||||
protocol: Protocol {
|
|
||||||
service_provider_type: ServiceProviderType::Authenticator,
|
|
||||||
version: VERSION,
|
|
||||||
},
|
|
||||||
data: AuthenticatorResponseData::TopUpBandwidth(TopUpBandwidthResponse {
|
|
||||||
reply: remaining_bandwidth_data,
|
|
||||||
request_id,
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn to_bytes(&self) -> Result<Vec<u8>, bincode::Error> {
|
|
||||||
use bincode::Options;
|
|
||||||
make_bincode_serializer().serialize(self)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn from_reconstructed_message(
|
|
||||||
message: &nym_sphinx::receiver::ReconstructedMessage,
|
|
||||||
) -> Result<Self, bincode::Error> {
|
|
||||||
use bincode::Options;
|
|
||||||
make_bincode_serializer().deserialize(&message.message)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn id(&self) -> Option<u64> {
|
|
||||||
match &self.data {
|
|
||||||
AuthenticatorResponseData::PendingRegistration(response) => Some(response.request_id),
|
|
||||||
AuthenticatorResponseData::Registered(response) => Some(response.request_id),
|
|
||||||
AuthenticatorResponseData::RemainingBandwidth(response) => Some(response.request_id),
|
|
||||||
AuthenticatorResponseData::TopUpBandwidth(response) => Some(response.request_id),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
||||||
pub enum AuthenticatorResponseData {
|
|
||||||
PendingRegistration(PendingRegistrationResponse),
|
|
||||||
Registered(RegisteredResponse),
|
|
||||||
RemainingBandwidth(RemainingBandwidthResponse),
|
|
||||||
TopUpBandwidth(TopUpBandwidthResponse),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
||||||
pub struct PendingRegistrationResponse {
|
|
||||||
pub request_id: u64,
|
|
||||||
pub reply: RegistrationData,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
||||||
pub struct RegisteredResponse {
|
|
||||||
pub request_id: u64,
|
|
||||||
pub reply: RegistredData,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
||||||
pub struct RemainingBandwidthResponse {
|
|
||||||
pub request_id: u64,
|
|
||||||
pub reply: Option<RemainingBandwidthData>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
||||||
pub struct TopUpBandwidthResponse {
|
|
||||||
pub request_id: u64,
|
|
||||||
pub reply: RemainingBandwidthData,
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
use nym_credentials_interface::CredentialSpendingData;
|
|
||||||
use nym_wireguard_types::PeerPublicKey;
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
|
|
||||||
pub struct TopUpMessage {
|
|
||||||
/// Base64 encoded x25519 public key
|
|
||||||
pub pub_key: PeerPublicKey,
|
|
||||||
|
|
||||||
/// Ecash credential
|
|
||||||
pub credential: CredentialSpendingData,
|
|
||||||
}
|
|
||||||
@@ -105,24 +105,26 @@ impl<C, St: Storage> BandwidthController<C, St> {
|
|||||||
async fn get_aggregate_verification_key(
|
async fn get_aggregate_verification_key(
|
||||||
&self,
|
&self,
|
||||||
epoch_id: EpochId,
|
epoch_id: EpochId,
|
||||||
ecash_apis: &mut ApiClientsWrapper<'_, C>,
|
apis: &mut ApiClientsWrapper,
|
||||||
) -> Result<VerificationKeyAuth, BandwidthControllerError>
|
) -> Result<VerificationKeyAuth, BandwidthControllerError>
|
||||||
where
|
where
|
||||||
C: DkgQueryClient + Sync + Send,
|
C: DkgQueryClient + Sync + Send,
|
||||||
<St as Storage>::StorageError: Send + Sync + 'static,
|
<St as Storage>::StorageError: Send + Sync + 'static,
|
||||||
{
|
{
|
||||||
|
let ecash_apis = apis.get_or_init(epoch_id, &self.client).await?;
|
||||||
get_aggregate_verification_key(&self.storage, epoch_id, ecash_apis).await
|
get_aggregate_verification_key(&self.storage, epoch_id, ecash_apis).await
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_coin_index_signatures(
|
async fn get_coin_index_signatures(
|
||||||
&self,
|
&self,
|
||||||
epoch_id: EpochId,
|
epoch_id: EpochId,
|
||||||
ecash_apis: &mut ApiClientsWrapper<'_, C>,
|
apis: &mut ApiClientsWrapper,
|
||||||
) -> Result<Vec<AnnotatedCoinIndexSignature>, BandwidthControllerError>
|
) -> Result<Vec<AnnotatedCoinIndexSignature>, BandwidthControllerError>
|
||||||
where
|
where
|
||||||
C: DkgQueryClient + Sync + Send,
|
C: DkgQueryClient + Sync + Send,
|
||||||
<St as Storage>::StorageError: Send + Sync + 'static,
|
<St as Storage>::StorageError: Send + Sync + 'static,
|
||||||
{
|
{
|
||||||
|
let ecash_apis = apis.get_or_init(epoch_id, &self.client).await?;
|
||||||
get_coin_index_signatures(&self.storage, epoch_id, ecash_apis).await
|
get_coin_index_signatures(&self.storage, epoch_id, ecash_apis).await
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,12 +132,13 @@ impl<C, St: Storage> BandwidthController<C, St> {
|
|||||||
&self,
|
&self,
|
||||||
epoch_id: EpochId,
|
epoch_id: EpochId,
|
||||||
expiration_date: Date,
|
expiration_date: Date,
|
||||||
ecash_apis: &mut ApiClientsWrapper<'_, C>,
|
apis: &mut ApiClientsWrapper,
|
||||||
) -> Result<Vec<AnnotatedExpirationDateSignature>, BandwidthControllerError>
|
) -> Result<Vec<AnnotatedExpirationDateSignature>, BandwidthControllerError>
|
||||||
where
|
where
|
||||||
C: DkgQueryClient + Sync + Send,
|
C: DkgQueryClient + Sync + Send,
|
||||||
<St as Storage>::StorageError: Send + Sync + 'static,
|
<St as Storage>::StorageError: Send + Sync + 'static,
|
||||||
{
|
{
|
||||||
|
let ecash_apis = apis.get_or_init(epoch_id, &self.client).await?;
|
||||||
get_expiration_date_signatures(&self.storage, epoch_id, expiration_date, ecash_apis).await
|
get_expiration_date_signatures(&self.storage, epoch_id, expiration_date, ecash_apis).await
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -151,7 +154,7 @@ impl<C, St: Storage> BandwidthController<C, St> {
|
|||||||
{
|
{
|
||||||
let epoch_id = retrieved_ticketbook.ticketbook.epoch_id();
|
let epoch_id = retrieved_ticketbook.ticketbook.epoch_id();
|
||||||
let expiration_date = retrieved_ticketbook.ticketbook.expiration_date();
|
let expiration_date = retrieved_ticketbook.ticketbook.expiration_date();
|
||||||
let mut api_clients = ApiClientsWrapper::new(&self.client, epoch_id);
|
let mut api_clients = Default::default();
|
||||||
|
|
||||||
let verification_key = self
|
let verification_key = self
|
||||||
.get_aggregate_verification_key(epoch_id, &mut api_clients)
|
.get_aggregate_verification_key(epoch_id, &mut api_clients)
|
||||||
|
|||||||
@@ -21,67 +21,30 @@ use rand::thread_rng;
|
|||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
use std::future::Future;
|
use std::future::Future;
|
||||||
|
|
||||||
pub(crate) trait EcashClientsProvider {
|
// it really doesn't need the RwLock because it's never moved across tasks,
|
||||||
async fn try_get_ecash_clients(
|
// but we need all the Send/Sync action
|
||||||
&mut self,
|
#[derive(Default)]
|
||||||
) -> Result<Vec<EcashApiClient>, BandwidthControllerError>;
|
pub(crate) struct ApiClientsWrapper(Option<Vec<EcashApiClient>>);
|
||||||
}
|
|
||||||
|
|
||||||
impl EcashClientsProvider for Vec<EcashApiClient> {
|
impl ApiClientsWrapper {
|
||||||
async fn try_get_ecash_clients(
|
pub(crate) async fn get_or_init<C>(
|
||||||
&mut self,
|
&mut self,
|
||||||
) -> Result<Vec<EcashApiClient>, BandwidthControllerError> {
|
|
||||||
Ok(self.clone())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<C> EcashClientsProvider for &mut ApiClientsWrapper<'_, C>
|
|
||||||
where
|
|
||||||
C: DkgQueryClient + Sync + Send,
|
|
||||||
{
|
|
||||||
async fn try_get_ecash_clients(
|
|
||||||
&mut self,
|
|
||||||
) -> Result<Vec<EcashApiClient>, BandwidthControllerError> {
|
|
||||||
self.clients().await
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) enum ApiClientsWrapper<'a, C> {
|
|
||||||
Uninitialised {
|
|
||||||
query_client: &'a C,
|
|
||||||
epoch_id: EpochId,
|
epoch_id: EpochId,
|
||||||
},
|
dkg_client: &C,
|
||||||
Cached {
|
) -> Result<Vec<EcashApiClient>, BandwidthControllerError>
|
||||||
clients: Vec<EcashApiClient>,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, C> ApiClientsWrapper<'a, C> {
|
|
||||||
pub(crate) fn new(query_client: &'a C, epoch_id: EpochId) -> Self {
|
|
||||||
ApiClientsWrapper::Uninitialised {
|
|
||||||
query_client,
|
|
||||||
epoch_id,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn clients(&mut self) -> Result<Vec<EcashApiClient>, BandwidthControllerError>
|
|
||||||
where
|
where
|
||||||
C: DkgQueryClient + Sync + Send,
|
C: DkgQueryClient + Sync + Send,
|
||||||
{
|
{
|
||||||
match self {
|
if let Some(cached) = &self.0 {
|
||||||
ApiClientsWrapper::Uninitialised {
|
return Ok(cached.clone());
|
||||||
query_client,
|
|
||||||
epoch_id,
|
|
||||||
} => {
|
|
||||||
let clients = all_ecash_api_clients(*query_client, *epoch_id).await?;
|
|
||||||
*self = ApiClientsWrapper::Cached {
|
|
||||||
clients: clients.clone(),
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(clients)
|
|
||||||
}
|
|
||||||
ApiClientsWrapper::Cached { clients } => Ok(clients.clone()),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let clients = all_ecash_api_clients(dkg_client, epoch_id).await?;
|
||||||
|
|
||||||
|
// technically we don't have to be cloning all the clients here, but it's way simpler than
|
||||||
|
// dealing with locking and whatnot given the performance penalty is negligible
|
||||||
|
self.0 = Some(clients.clone());
|
||||||
|
Ok(clients)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,7 +76,7 @@ where
|
|||||||
pub(crate) async fn get_aggregate_verification_key<St>(
|
pub(crate) async fn get_aggregate_verification_key<St>(
|
||||||
storage: &St,
|
storage: &St,
|
||||||
epoch_id: EpochId,
|
epoch_id: EpochId,
|
||||||
mut ecash_apis: impl EcashClientsProvider,
|
ecash_apis: Vec<EcashApiClient>,
|
||||||
) -> Result<VerificationKeyAuth, BandwidthControllerError>
|
) -> Result<VerificationKeyAuth, BandwidthControllerError>
|
||||||
where
|
where
|
||||||
St: Storage,
|
St: Storage,
|
||||||
@@ -127,8 +90,6 @@ where
|
|||||||
return Ok(stored);
|
return Ok(stored);
|
||||||
};
|
};
|
||||||
|
|
||||||
let ecash_apis = ecash_apis.try_get_ecash_clients().await?;
|
|
||||||
|
|
||||||
let master_vk = query_random_apis_until_success(
|
let master_vk = query_random_apis_until_success(
|
||||||
ecash_apis,
|
ecash_apis,
|
||||||
|api| async move { api.api_client.master_verification_key(Some(epoch_id)).await },
|
|api| async move { api.api_client.master_verification_key(Some(epoch_id)).await },
|
||||||
@@ -154,7 +115,7 @@ where
|
|||||||
pub(crate) async fn get_coin_index_signatures<St>(
|
pub(crate) async fn get_coin_index_signatures<St>(
|
||||||
storage: &St,
|
storage: &St,
|
||||||
epoch_id: EpochId,
|
epoch_id: EpochId,
|
||||||
mut ecash_apis: impl EcashClientsProvider,
|
ecash_apis: Vec<EcashApiClient>,
|
||||||
) -> Result<Vec<AnnotatedCoinIndexSignature>, BandwidthControllerError>
|
) -> Result<Vec<AnnotatedCoinIndexSignature>, BandwidthControllerError>
|
||||||
where
|
where
|
||||||
St: Storage,
|
St: Storage,
|
||||||
@@ -168,8 +129,6 @@ where
|
|||||||
return Ok(stored);
|
return Ok(stored);
|
||||||
};
|
};
|
||||||
|
|
||||||
let ecash_apis = ecash_apis.try_get_ecash_clients().await?;
|
|
||||||
|
|
||||||
let index_sigs = query_random_apis_until_success(
|
let index_sigs = query_random_apis_until_success(
|
||||||
ecash_apis,
|
ecash_apis,
|
||||||
|api| async move {
|
|api| async move {
|
||||||
@@ -200,7 +159,7 @@ pub(crate) async fn get_expiration_date_signatures<St>(
|
|||||||
storage: &St,
|
storage: &St,
|
||||||
epoch_id: EpochId,
|
epoch_id: EpochId,
|
||||||
expiration_date: Date,
|
expiration_date: Date,
|
||||||
mut ecash_apis: impl EcashClientsProvider,
|
ecash_apis: Vec<EcashApiClient>,
|
||||||
) -> Result<Vec<AnnotatedExpirationDateSignature>, BandwidthControllerError>
|
) -> Result<Vec<AnnotatedExpirationDateSignature>, BandwidthControllerError>
|
||||||
where
|
where
|
||||||
St: Storage,
|
St: Storage,
|
||||||
@@ -214,8 +173,6 @@ where
|
|||||||
return Ok(stored);
|
return Ok(stored);
|
||||||
};
|
};
|
||||||
|
|
||||||
let ecash_apis = ecash_apis.try_get_ecash_clients().await?;
|
|
||||||
|
|
||||||
let expiration_sigs = query_random_apis_until_success(
|
let expiration_sigs = query_random_apis_until_success(
|
||||||
ecash_apis,
|
ecash_apis,
|
||||||
|api| async move {
|
|api| async move {
|
||||||
|
|||||||
@@ -40,7 +40,6 @@ nym-crypto = { path = "../crypto" }
|
|||||||
nym-explorer-client = { path = "../../explorer-api/explorer-client" }
|
nym-explorer-client = { path = "../../explorer-api/explorer-client" }
|
||||||
nym-gateway-client = { path = "../client-libs/gateway-client" }
|
nym-gateway-client = { path = "../client-libs/gateway-client" }
|
||||||
nym-gateway-requests = { path = "../gateway-requests" }
|
nym-gateway-requests = { path = "../gateway-requests" }
|
||||||
nym-http-api-client = { path = "../http-api-client" }
|
|
||||||
nym-metrics = { path = "../nym-metrics" }
|
nym-metrics = { path = "../nym-metrics" }
|
||||||
nym-nonexhaustive-delayqueue = { path = "../nonexhaustive-delayqueue" }
|
nym-nonexhaustive-delayqueue = { path = "../nonexhaustive-delayqueue" }
|
||||||
nym-sphinx = { path = "../nymsphinx" }
|
nym-sphinx = { path = "../nymsphinx" }
|
||||||
|
|||||||
@@ -45,12 +45,11 @@ const DEFAULT_COVER_TRAFFIC_PRIMARY_SIZE_RATIO: f64 = 0.70;
|
|||||||
// clients/client-core/src/client/replies/reply_storage/surb_storage.rs
|
// clients/client-core/src/client/replies/reply_storage/surb_storage.rs
|
||||||
const DEFAULT_MINIMUM_REPLY_SURB_STORAGE_THRESHOLD: usize = 10;
|
const DEFAULT_MINIMUM_REPLY_SURB_STORAGE_THRESHOLD: usize = 10;
|
||||||
const DEFAULT_MAXIMUM_REPLY_SURB_STORAGE_THRESHOLD: usize = 200;
|
const DEFAULT_MAXIMUM_REPLY_SURB_STORAGE_THRESHOLD: usize = 200;
|
||||||
const DEFAULT_MINIMUM_REPLY_SURB_THRESHOLD_BUFFER: usize = 0;
|
|
||||||
|
|
||||||
// define how much to request at once
|
// define how much to request at once
|
||||||
// clients/client-core/src/client/replies/reply_controller.rs
|
// clients/client-core/src/client/replies/reply_controller.rs
|
||||||
const DEFAULT_MINIMUM_REPLY_SURB_REQUEST_SIZE: u32 = 10;
|
const DEFAULT_MINIMUM_REPLY_SURB_REQUEST_SIZE: u32 = 10;
|
||||||
const DEFAULT_MAXIMUM_REPLY_SURB_REQUEST_SIZE: u32 = 50;
|
const DEFAULT_MAXIMUM_REPLY_SURB_REQUEST_SIZE: u32 = 100;
|
||||||
|
|
||||||
const DEFAULT_MAXIMUM_ALLOWED_SURB_REQUEST_SIZE: u32 = 500;
|
const DEFAULT_MAXIMUM_ALLOWED_SURB_REQUEST_SIZE: u32 = 500;
|
||||||
|
|
||||||
@@ -146,11 +145,6 @@ impl Config {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_forget_me(mut self, forget_me: ForgetMe) -> Self {
|
|
||||||
self.debug.forget_me = forget_me;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: this should be refactored properly
|
// TODO: this should be refactored properly
|
||||||
// as of 12.09.23 the below is true (not sure how this comment will rot in the future)
|
// as of 12.09.23 the below is true (not sure how this comment will rot in the future)
|
||||||
// medium_toggle:
|
// medium_toggle:
|
||||||
@@ -523,7 +517,7 @@ impl Default for Acknowledgements {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||||
#[serde(default)]
|
#[serde(default, deny_unknown_fields)]
|
||||||
pub struct Topology {
|
pub struct Topology {
|
||||||
/// The uniform delay every which clients are querying the directory server
|
/// The uniform delay every which clients are querying the directory server
|
||||||
/// to try to obtain a compatible network topology to send sphinx packets through.
|
/// to try to obtain a compatible network topology to send sphinx packets through.
|
||||||
@@ -559,15 +553,12 @@ pub struct Topology {
|
|||||||
|
|
||||||
/// Specifies whether this client should attempt to retrieve all available network nodes
|
/// Specifies whether this client should attempt to retrieve all available network nodes
|
||||||
/// as opposed to just active mixnodes/gateways.
|
/// as opposed to just active mixnodes/gateways.
|
||||||
|
/// Useless without `ignore_epoch_roles = true`
|
||||||
pub use_extended_topology: bool,
|
pub use_extended_topology: bool,
|
||||||
|
|
||||||
/// Specifies whether this client should ignore the current epoch role of the target egress node
|
/// Specifies whether this client should ignore the current epoch role of the target egress node
|
||||||
/// when constructing the final hop packets.
|
/// when constructing the final hop packets.
|
||||||
pub ignore_egress_epoch_role: bool,
|
pub ignore_egress_epoch_role: bool,
|
||||||
|
|
||||||
/// Specifies whether this client should ignore the current epoch role of the ingress node
|
|
||||||
/// when attempting to establish new connection
|
|
||||||
pub ignore_ingress_epoch_role: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::large_enum_variant)]
|
#[allow(clippy::large_enum_variant)]
|
||||||
@@ -605,9 +596,7 @@ impl Default for Topology {
|
|||||||
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,
|
use_extended_topology: false,
|
||||||
|
ignore_egress_epoch_role: false,
|
||||||
ignore_egress_epoch_role: true,
|
|
||||||
ignore_ingress_epoch_role: true,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -622,10 +611,6 @@ pub struct ReplySurbs {
|
|||||||
/// Defines the maximum number of reply surbs the client wants to keep in its storage at any times.
|
/// Defines the maximum number of reply surbs the client wants to keep in its storage at any times.
|
||||||
pub maximum_reply_surb_storage_threshold: usize,
|
pub maximum_reply_surb_storage_threshold: usize,
|
||||||
|
|
||||||
/// Defines the soft threshold ontop of the minimum reply surb storage threshold for when the client
|
|
||||||
/// should proactively request additional reply surbs.
|
|
||||||
pub minimum_reply_surb_threshold_buffer: usize,
|
|
||||||
|
|
||||||
/// Defines the minimum number of reply surbs the client would request.
|
/// Defines the minimum number of reply surbs the client would request.
|
||||||
pub minimum_reply_surb_request_size: u32,
|
pub minimum_reply_surb_request_size: u32,
|
||||||
|
|
||||||
@@ -665,7 +650,6 @@ impl Default for ReplySurbs {
|
|||||||
ReplySurbs {
|
ReplySurbs {
|
||||||
minimum_reply_surb_storage_threshold: DEFAULT_MINIMUM_REPLY_SURB_STORAGE_THRESHOLD,
|
minimum_reply_surb_storage_threshold: DEFAULT_MINIMUM_REPLY_SURB_STORAGE_THRESHOLD,
|
||||||
maximum_reply_surb_storage_threshold: DEFAULT_MAXIMUM_REPLY_SURB_STORAGE_THRESHOLD,
|
maximum_reply_surb_storage_threshold: DEFAULT_MAXIMUM_REPLY_SURB_STORAGE_THRESHOLD,
|
||||||
minimum_reply_surb_threshold_buffer: DEFAULT_MINIMUM_REPLY_SURB_THRESHOLD_BUFFER,
|
|
||||||
minimum_reply_surb_request_size: DEFAULT_MINIMUM_REPLY_SURB_REQUEST_SIZE,
|
minimum_reply_surb_request_size: DEFAULT_MINIMUM_REPLY_SURB_REQUEST_SIZE,
|
||||||
maximum_reply_surb_request_size: DEFAULT_MAXIMUM_REPLY_SURB_REQUEST_SIZE,
|
maximum_reply_surb_request_size: DEFAULT_MAXIMUM_REPLY_SURB_REQUEST_SIZE,
|
||||||
maximum_allowed_reply_surb_request_size: DEFAULT_MAXIMUM_ALLOWED_SURB_REQUEST_SIZE,
|
maximum_allowed_reply_surb_request_size: DEFAULT_MAXIMUM_ALLOWED_SURB_REQUEST_SIZE,
|
||||||
@@ -730,9 +714,6 @@ pub struct DebugConfig {
|
|||||||
|
|
||||||
/// Defines all configuration options related to stats reporting.
|
/// Defines all configuration options related to stats reporting.
|
||||||
pub stats_reporting: StatsReporting,
|
pub stats_reporting: StatsReporting,
|
||||||
|
|
||||||
/// Defines all configuration options related to the forget me flag.
|
|
||||||
pub forget_me: ForgetMe,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DebugConfig {
|
impl DebugConfig {
|
||||||
@@ -755,69 +736,6 @@ impl Default for DebugConfig {
|
|||||||
topology: Default::default(),
|
topology: Default::default(),
|
||||||
reply_surbs: Default::default(),
|
reply_surbs: Default::default(),
|
||||||
stats_reporting: Default::default(),
|
stats_reporting: Default::default(),
|
||||||
forget_me: Default::default(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Default, Debug, Deserialize, PartialEq, Serialize, Copy)]
|
|
||||||
pub struct ForgetMe {
|
|
||||||
client: bool,
|
|
||||||
stats: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<bool> for ForgetMe {
|
|
||||||
fn from(value: bool) -> Self {
|
|
||||||
if value {
|
|
||||||
Self::new_all()
|
|
||||||
} else {
|
|
||||||
Self::new_none()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new_none() -> Self {
|
|
||||||
Self {
|
|
||||||
client: false,
|
|
||||||
stats: false,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -181,9 +181,8 @@ impl From<ConfigV5> for Config {
|
|||||||
maximum_reply_surb_age: value.debug.reply_surbs.maximum_reply_surb_age,
|
maximum_reply_surb_age: value.debug.reply_surbs.maximum_reply_surb_age,
|
||||||
maximum_reply_key_age: value.debug.reply_surbs.maximum_reply_key_age,
|
maximum_reply_key_age: value.debug.reply_surbs.maximum_reply_key_age,
|
||||||
surb_mix_hops: value.debug.reply_surbs.surb_mix_hops,
|
surb_mix_hops: value.debug.reply_surbs.surb_mix_hops,
|
||||||
..Default::default()
|
|
||||||
},
|
},
|
||||||
..Default::default()
|
stats_reporting: Default::default(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ pub mod error;
|
|||||||
mod manager;
|
mod manager;
|
||||||
mod models;
|
mod models;
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct OnDiskGatewaysDetails {
|
pub struct OnDiskGatewaysDetails {
|
||||||
manager: StorageManager,
|
manager: StorageManager,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,12 +20,12 @@ pub enum InMemStorageError {
|
|||||||
MalformedGateway(#[from] BadGateway),
|
MalformedGateway(#[from] BadGateway),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct InMemGatewaysDetails {
|
pub struct InMemGatewaysDetails {
|
||||||
inner: Arc<RwLock<InMemStorageInner>>,
|
inner: Arc<RwLock<InMemStorageInner>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
struct InMemStorageInner {
|
struct InMemStorageInner {
|
||||||
active_gateway: Option<String>,
|
active_gateway: Option<String>,
|
||||||
gateways: HashMap<String, GatewayRegistration>,
|
gateways: HashMap<String, GatewayRegistration>,
|
||||||
|
|||||||
@@ -115,12 +115,11 @@ where
|
|||||||
hardcoded_topology.entry_capable_nodes().cloned().collect()
|
hardcoded_topology.entry_capable_nodes().cloned().collect()
|
||||||
} else {
|
} else {
|
||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::thread_rng();
|
||||||
crate::init::helpers::gateways_for_init(
|
crate::init::helpers::current_gateways(
|
||||||
&mut rng,
|
&mut rng,
|
||||||
&core.client.nym_api_urls,
|
&core.client.nym_api_urls,
|
||||||
user_agent,
|
user_agent,
|
||||||
core.debug.topology.minimum_gateway_performance,
|
core.debug.topology.minimum_gateway_performance,
|
||||||
core.debug.topology.ignore_ingress_epoch_role,
|
|
||||||
)
|
)
|
||||||
.await?
|
.await?
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -93,10 +93,6 @@ pub struct CommonClientInitArgs {
|
|||||||
/// Sets the address to report statistics
|
/// Sets the address to report statistics
|
||||||
#[cfg_attr(feature = "cli", clap(long, hide = true))]
|
#[cfg_attr(feature = "cli", clap(long, hide = true))]
|
||||||
pub stats_reporting_address: Option<Recipient>,
|
pub stats_reporting_address: Option<Recipient>,
|
||||||
|
|
||||||
/// Sets the forget me flag
|
|
||||||
#[cfg_attr(feature = "cli", clap(long, hide = true, default_value_t = false))]
|
|
||||||
pub forget_me: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct InitResultsWithConfig<T> {
|
pub struct InitResultsWithConfig<T> {
|
||||||
@@ -174,12 +170,11 @@ where
|
|||||||
hardcoded_topology.entry_capable_nodes().cloned().collect()
|
hardcoded_topology.entry_capable_nodes().cloned().collect()
|
||||||
} else {
|
} else {
|
||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::thread_rng();
|
||||||
crate::init::helpers::gateways_for_init(
|
crate::init::helpers::current_gateways(
|
||||||
&mut rng,
|
&mut rng,
|
||||||
&core.client.nym_api_urls,
|
&core.client.nym_api_urls,
|
||||||
user_agent,
|
user_agent,
|
||||||
core.debug.topology.minimum_gateway_performance,
|
core.debug.topology.minimum_gateway_performance,
|
||||||
core.debug.topology.ignore_ingress_epoch_role,
|
|
||||||
)
|
)
|
||||||
.await?
|
.await?
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -61,8 +61,4 @@ pub struct CommonClientRunArgs {
|
|||||||
/// Sets the address to report statistics
|
/// Sets the address to report statistics
|
||||||
#[cfg_attr(feature = "cli", clap(long, hide = true))]
|
#[cfg_attr(feature = "cli", clap(long, hide = true))]
|
||||||
pub stats_reporting_address: Option<Recipient>,
|
pub stats_reporting_address: Option<Recipient>,
|
||||||
|
|
||||||
/// Sets the forget me flag
|
|
||||||
#[cfg_attr(feature = "cli", clap(long, hide = true, default_value_t = false))]
|
|
||||||
pub forget_me: bool,
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
// Copyright 2022-2023 - Nym Technologies SA <contact@nymtech.net>
|
// Copyright 2022-2023 - Nym Technologies SA <contact@nymtech.net>
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
use super::mix_traffic::ClientRequestSender;
|
|
||||||
use super::received_buffer::ReceivedBufferMessage;
|
use super::received_buffer::ReceivedBufferMessage;
|
||||||
use super::statistics_control::StatisticsControl;
|
use super::statistics_control::StatisticsControl;
|
||||||
use crate::client::base_client::storage::helpers::store_client_keys;
|
use crate::client::base_client::storage::helpers::store_client_keys;
|
||||||
@@ -32,15 +31,13 @@ use crate::init::{
|
|||||||
setup_gateway,
|
setup_gateway,
|
||||||
types::{GatewaySetup, InitialisationResult},
|
types::{GatewaySetup, InitialisationResult},
|
||||||
};
|
};
|
||||||
use crate::{config, spawn_future};
|
use crate::{config, spawn_future, ForgetMe};
|
||||||
use futures::channel::mpsc;
|
use futures::channel::mpsc;
|
||||||
use log::*;
|
use log::*;
|
||||||
use nym_bandwidth_controller::BandwidthController;
|
use nym_bandwidth_controller::BandwidthController;
|
||||||
use nym_client_core_config_types::ForgetMe;
|
|
||||||
use nym_client_core_gateways_storage::{GatewayDetails, GatewaysDetailsStore};
|
use nym_client_core_gateways_storage::{GatewayDetails, GatewaysDetailsStore};
|
||||||
use nym_credential_storage::storage::Storage as CredentialStorage;
|
use nym_credential_storage::storage::Storage as CredentialStorage;
|
||||||
use nym_crypto::asymmetric::{encryption, identity};
|
use nym_crypto::asymmetric::{encryption, identity};
|
||||||
use nym_crypto::hkdf::DerivationMaterial;
|
|
||||||
use nym_gateway_client::client::config::GatewayClientConfig;
|
use nym_gateway_client::client::config::GatewayClientConfig;
|
||||||
use nym_gateway_client::{
|
use nym_gateway_client::{
|
||||||
AcknowledgementReceiver, GatewayClient, GatewayConfig, MixnetMessageReceiver, PacketRouter,
|
AcknowledgementReceiver, GatewayClient, GatewayConfig, MixnetMessageReceiver, PacketRouter,
|
||||||
@@ -178,8 +175,8 @@ impl From<bool> for CredentialsToggle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct BaseClientBuilder<C, S: MixnetClientStorage> {
|
pub struct BaseClientBuilder<'a, C, S: MixnetClientStorage> {
|
||||||
config: Config,
|
config: &'a Config,
|
||||||
client_store: S,
|
client_store: S,
|
||||||
dkg_query_client: Option<C>,
|
dkg_query_client: Option<C>,
|
||||||
|
|
||||||
@@ -194,19 +191,19 @@ pub struct BaseClientBuilder<C, S: MixnetClientStorage> {
|
|||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
connection_fd_callback: Option<Arc<dyn Fn(RawFd) + Send + Sync>>,
|
connection_fd_callback: Option<Arc<dyn Fn(RawFd) + Send + Sync>>,
|
||||||
|
|
||||||
derivation_material: Option<DerivationMaterial>,
|
forget_me: ForgetMe,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C, S> BaseClientBuilder<C, S>
|
impl<'a, C, S> BaseClientBuilder<'a, C, S>
|
||||||
where
|
where
|
||||||
S: MixnetClientStorage + 'static,
|
S: MixnetClientStorage + 'static,
|
||||||
C: DkgQueryClient + Send + Sync + 'static,
|
C: DkgQueryClient + Send + Sync + 'static,
|
||||||
{
|
{
|
||||||
pub fn new(
|
pub fn new(
|
||||||
base_config: Config,
|
base_config: &'a Config,
|
||||||
client_store: S,
|
client_store: S,
|
||||||
dkg_query_client: Option<C>,
|
dkg_query_client: Option<C>,
|
||||||
) -> BaseClientBuilder<C, S> {
|
) -> BaseClientBuilder<'a, C, S> {
|
||||||
BaseClientBuilder {
|
BaseClientBuilder {
|
||||||
config: base_config,
|
config: base_config,
|
||||||
client_store,
|
client_store,
|
||||||
@@ -219,22 +216,13 @@ where
|
|||||||
setup_method: GatewaySetup::MustLoad { gateway_id: None },
|
setup_method: GatewaySetup::MustLoad { gateway_id: None },
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
connection_fd_callback: None,
|
connection_fd_callback: None,
|
||||||
derivation_material: None,
|
forget_me: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[must_use]
|
|
||||||
pub fn with_derivation_material(
|
|
||||||
mut self,
|
|
||||||
derivation_material: Option<DerivationMaterial>,
|
|
||||||
) -> Self {
|
|
||||||
self.derivation_material = derivation_material;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn with_forget_me(mut self, forget_me: &ForgetMe) -> Self {
|
pub fn with_forget_me(mut self, forget_me: &ForgetMe) -> Self {
|
||||||
self.config.debug.forget_me = *forget_me;
|
self.forget_me = forget_me.clone();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -310,7 +298,7 @@ where
|
|||||||
topology_accessor: TopologyAccessor,
|
topology_accessor: TopologyAccessor,
|
||||||
mix_tx: BatchMixMessageSender,
|
mix_tx: BatchMixMessageSender,
|
||||||
stats_tx: ClientStatsSender,
|
stats_tx: ClientStatsSender,
|
||||||
task_client: TaskClient,
|
shutdown: TaskClient,
|
||||||
) {
|
) {
|
||||||
info!("Starting loop cover traffic stream...");
|
info!("Starting loop cover traffic stream...");
|
||||||
|
|
||||||
@@ -323,10 +311,9 @@ where
|
|||||||
debug_config.traffic,
|
debug_config.traffic,
|
||||||
debug_config.cover_traffic,
|
debug_config.cover_traffic,
|
||||||
stats_tx,
|
stats_tx,
|
||||||
task_client,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
stream.start();
|
stream.start_with_shutdown(shutdown);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
@@ -341,7 +328,7 @@ where
|
|||||||
reply_controller_receiver: ReplyControllerReceiver,
|
reply_controller_receiver: ReplyControllerReceiver,
|
||||||
lane_queue_lengths: LaneQueueLengths,
|
lane_queue_lengths: LaneQueueLengths,
|
||||||
client_connection_rx: ConnectionCommandReceiver,
|
client_connection_rx: ConnectionCommandReceiver,
|
||||||
task_client: TaskClient,
|
shutdown: TaskClient,
|
||||||
packet_type: PacketType,
|
packet_type: PacketType,
|
||||||
stats_tx: ClientStatsSender,
|
stats_tx: ClientStatsSender,
|
||||||
) {
|
) {
|
||||||
@@ -359,9 +346,8 @@ where
|
|||||||
lane_queue_lengths,
|
lane_queue_lengths,
|
||||||
client_connection_rx,
|
client_connection_rx,
|
||||||
stats_tx,
|
stats_tx,
|
||||||
task_client,
|
|
||||||
)
|
)
|
||||||
.start(packet_type);
|
.start_with_shutdown(shutdown, packet_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
// buffer controlling all messages fetched from provider
|
// buffer controlling all messages fetched from provider
|
||||||
@@ -384,9 +370,8 @@ where
|
|||||||
reply_key_storage,
|
reply_key_storage,
|
||||||
reply_controller_sender,
|
reply_controller_sender,
|
||||||
metrics_reporter,
|
metrics_reporter,
|
||||||
shutdown,
|
|
||||||
);
|
);
|
||||||
controller.start()
|
controller.start_with_shutdown(shutdown)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
@@ -487,7 +472,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)?;
|
||||||
@@ -575,22 +559,15 @@ where
|
|||||||
topology_accessor: TopologyAccessor,
|
topology_accessor: TopologyAccessor,
|
||||||
local_gateway: NodeIdentity,
|
local_gateway: NodeIdentity,
|
||||||
wait_for_gateway: bool,
|
wait_for_gateway: bool,
|
||||||
mut task_client: TaskClient,
|
mut shutdown: TaskClient,
|
||||||
) -> Result<(), ClientCoreError> {
|
) -> Result<(), ClientCoreError> {
|
||||||
let topology_refresher_config =
|
let topology_refresher_config =
|
||||||
TopologyRefresherConfig::new(topology_config.topology_refresh_rate);
|
TopologyRefresherConfig::new(topology_config.topology_refresh_rate);
|
||||||
|
|
||||||
if topology_config.disable_refreshing {
|
|
||||||
// if we're not spawning the refresher, don't cause shutdown immediately
|
|
||||||
info!("The background topology refesher is not going to be started");
|
|
||||||
task_client.disarm();
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut topology_refresher = TopologyRefresher::new(
|
let mut topology_refresher = TopologyRefresher::new(
|
||||||
topology_refresher_config,
|
topology_refresher_config,
|
||||||
topology_accessor,
|
topology_accessor,
|
||||||
topology_provider,
|
topology_provider,
|
||||||
task_client,
|
|
||||||
);
|
);
|
||||||
// before returning, block entire runtime to refresh the current network view so that any
|
// before returning, block entire runtime to refresh the current network view so that any
|
||||||
// components depending on topology would see a non-empty view
|
// components depending on topology would see a non-empty view
|
||||||
@@ -631,11 +608,15 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !topology_config.disable_refreshing {
|
if topology_config.disable_refreshing {
|
||||||
|
// if we're not spawning the refresher, don't cause shutdown immediately
|
||||||
|
info!("The topology refesher is not going to be started");
|
||||||
|
shutdown.disarm();
|
||||||
|
} else {
|
||||||
// don't spawn the refresher if we don't want to be refreshing the topology.
|
// don't spawn the refresher if we don't want to be refreshing the topology.
|
||||||
// only use the initial values obtained
|
// only use the initial values obtained
|
||||||
info!("Starting topology refresher...");
|
info!("Starting topology refresher...");
|
||||||
topology_refresher.start();
|
topology_refresher.start_with_shutdown(shutdown);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -646,29 +627,30 @@ where
|
|||||||
user_agent: Option<UserAgent>,
|
user_agent: Option<UserAgent>,
|
||||||
client_stats_id: String,
|
client_stats_id: String,
|
||||||
input_sender: Sender<InputMessage>,
|
input_sender: Sender<InputMessage>,
|
||||||
task_client: TaskClient,
|
shutdown: TaskClient,
|
||||||
) -> ClientStatsSender {
|
) -> ClientStatsSender {
|
||||||
info!("Starting statistics control...");
|
info!("Starting statistics control...");
|
||||||
StatisticsControl::create_and_start(
|
StatisticsControl::create_and_start_with_shutdown(
|
||||||
config.debug.stats_reporting,
|
config.debug.stats_reporting,
|
||||||
user_agent
|
user_agent
|
||||||
.map(|u| u.application)
|
.map(|u| u.application)
|
||||||
.unwrap_or("unknown".to_string()),
|
.unwrap_or("unknown".to_string()),
|
||||||
client_stats_id,
|
client_stats_id,
|
||||||
input_sender.clone(),
|
input_sender.clone(),
|
||||||
task_client,
|
shutdown.with_suffix("controller"),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
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,
|
||||||
) -> (BatchMixMessageSender, ClientRequestSender) {
|
forget_me: ForgetMe,
|
||||||
|
) -> BatchMixMessageSender {
|
||||||
info!("Starting mix traffic controller...");
|
info!("Starting mix traffic controller...");
|
||||||
let (mix_traffic_controller, mix_tx, client_tx) =
|
let (mix_traffic_controller, mix_tx) =
|
||||||
MixTrafficController::new(gateway_transceiver, shutdown);
|
MixTrafficController::new(gateway_transceiver, forget_me);
|
||||||
mix_traffic_controller.start();
|
mix_traffic_controller.start_with_shutdown(shutdown);
|
||||||
(mix_tx, client_tx)
|
mix_tx
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: rename it as it implies the data is persistent whilst one can use InMemBackend
|
// TODO: rename it as it implies the data is persistent whilst one can use InMemBackend
|
||||||
@@ -703,7 +685,6 @@ where
|
|||||||
setup_method: GatewaySetup,
|
setup_method: GatewaySetup,
|
||||||
key_store: &S::KeyStore,
|
key_store: &S::KeyStore,
|
||||||
details_store: &S::GatewaysDetailsStore,
|
details_store: &S::GatewaysDetailsStore,
|
||||||
derivation_material: Option<DerivationMaterial>,
|
|
||||||
) -> Result<InitialisationResult, ClientCoreError>
|
) -> Result<InitialisationResult, ClientCoreError>
|
||||||
where
|
where
|
||||||
<S::KeyStore as KeyStore>::StorageError: Sync + Send,
|
<S::KeyStore as KeyStore>::StorageError: Sync + Send,
|
||||||
@@ -713,12 +694,7 @@ where
|
|||||||
if key_store.load_keys().await.is_err() {
|
if key_store.load_keys().await.is_err() {
|
||||||
info!("could not find valid client keys - a new set will be generated");
|
info!("could not find valid client keys - a new set will be generated");
|
||||||
let mut rng = OsRng;
|
let mut rng = OsRng;
|
||||||
let keys = if let Some(derivation_material) = derivation_material {
|
let keys = ClientKeys::generate_new(&mut rng);
|
||||||
ClientKeys::from_master_key(&mut rng, &derivation_material)
|
|
||||||
.map_err(|_| ClientCoreError::HkdfDerivationError {})?
|
|
||||||
} else {
|
|
||||||
ClientKeys::generate_new(&mut rng)
|
|
||||||
};
|
|
||||||
store_client_keys(keys, key_store).await?;
|
store_client_keys(keys, key_store).await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -740,7 +716,6 @@ where
|
|||||||
self.setup_method,
|
self.setup_method,
|
||||||
self.client_store.key_store(),
|
self.client_store.key_store(),
|
||||||
self.client_store.gateway_details_store(),
|
self.client_store.gateway_details_store(),
|
||||||
self.derivation_material,
|
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
@@ -797,7 +772,7 @@ where
|
|||||||
);
|
);
|
||||||
|
|
||||||
let stats_reporter = Self::start_statistics_control(
|
let stats_reporter = Self::start_statistics_control(
|
||||||
&self.config,
|
self.config,
|
||||||
self.user_agent.clone(),
|
self.user_agent.clone(),
|
||||||
generate_client_stats_id(*self_address.identity()),
|
generate_client_stats_id(*self_address.identity()),
|
||||||
input_sender.clone(),
|
input_sender.clone(),
|
||||||
@@ -823,7 +798,7 @@ where
|
|||||||
|
|
||||||
let gateway_transceiver = Self::setup_gateway_transceiver(
|
let gateway_transceiver = Self::setup_gateway_transceiver(
|
||||||
self.custom_gateway_transceiver,
|
self.custom_gateway_transceiver,
|
||||||
&self.config,
|
self.config,
|
||||||
init_res,
|
init_res,
|
||||||
bandwidth_controller,
|
bandwidth_controller,
|
||||||
&details_store,
|
&details_store,
|
||||||
@@ -857,9 +832,10 @@ where
|
|||||||
// traffic stream.
|
// traffic stream.
|
||||||
// The MixTrafficController then sends the actual traffic
|
// The MixTrafficController then sends the actual traffic
|
||||||
|
|
||||||
let (message_sender, client_request_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
|
||||||
@@ -934,8 +910,6 @@ where
|
|||||||
},
|
},
|
||||||
stats_reporter,
|
stats_reporter,
|
||||||
task_handle: shutdown,
|
task_handle: shutdown,
|
||||||
client_request_sender,
|
|
||||||
forget_me: self.config.debug.forget_me,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -947,7 +921,6 @@ pub struct BaseClient {
|
|||||||
pub client_output: ClientOutputStatus,
|
pub client_output: ClientOutputStatus,
|
||||||
pub client_state: ClientState,
|
pub client_state: ClientState,
|
||||||
pub stats_reporter: ClientStatsSender,
|
pub stats_reporter: ClientStatsSender,
|
||||||
pub client_request_sender: ClientRequestSender,
|
|
||||||
pub task_handle: TaskHandle,
|
pub task_handle: TaskHandle,
|
||||||
pub forget_me: ForgetMe,
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,8 +4,6 @@
|
|||||||
// TODO: combine those more closely. Perhaps into a single underlying store.
|
// TODO: combine those more closely. Perhaps into a single underlying store.
|
||||||
// Like for persistent, on-disk, storage, what's the point of having 3 different databases?
|
// Like for persistent, on-disk, storage, what's the point of having 3 different databases?
|
||||||
|
|
||||||
use rand::rngs::OsRng;
|
|
||||||
|
|
||||||
use crate::client::key_manager::persistence::{InMemEphemeralKeys, KeyStore};
|
use crate::client::key_manager::persistence::{InMemEphemeralKeys, KeyStore};
|
||||||
use crate::client::replies::reply_storage;
|
use crate::client::replies::reply_storage;
|
||||||
use crate::client::replies::reply_storage::ReplyStorageBackend;
|
use crate::client::replies::reply_storage::ReplyStorageBackend;
|
||||||
@@ -65,7 +63,7 @@ pub trait MixnetClientStorage {
|
|||||||
fn gateway_details_store(&self) -> &Self::GatewaysDetailsStore;
|
fn gateway_details_store(&self) -> &Self::GatewaysDetailsStore;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Default)]
|
||||||
pub struct Ephemeral {
|
pub struct Ephemeral {
|
||||||
key_store: InMemEphemeralKeys,
|
key_store: InMemEphemeralKeys,
|
||||||
reply_store: reply_storage::Empty,
|
reply_store: reply_storage::Empty,
|
||||||
@@ -73,14 +71,9 @@ pub struct Ephemeral {
|
|||||||
gateway_details_store: InMemGatewaysDetails,
|
gateway_details_store: InMemGatewaysDetails,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Ephemeral {
|
impl Ephemeral {
|
||||||
fn default() -> Self {
|
pub fn new() -> Self {
|
||||||
Ephemeral {
|
Default::default()
|
||||||
key_store: InMemEphemeralKeys::new(&mut OsRng),
|
|
||||||
reply_store: Default::default(),
|
|
||||||
credential_store: Default::default(),
|
|
||||||
gateway_details_store: Default::default(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,7 +114,6 @@ impl MixnetClientStorage for Ephemeral {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
#[cfg(all(
|
#[cfg(all(
|
||||||
not(target_arch = "wasm32"),
|
not(target_arch = "wasm32"),
|
||||||
feature = "fs-surb-storage",
|
feature = "fs-surb-storage",
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ use nym_sphinx::cover::generate_loop_cover_packet;
|
|||||||
use nym_sphinx::params::{PacketSize, PacketType};
|
use nym_sphinx::params::{PacketSize, PacketType};
|
||||||
use nym_sphinx::utils::sample_poisson_duration;
|
use nym_sphinx::utils::sample_poisson_duration;
|
||||||
use nym_statistics_common::clients::{packet_statistics::PacketStatisticsEvent, ClientStatsSender};
|
use nym_statistics_common::clients::{packet_statistics::PacketStatisticsEvent, ClientStatsSender};
|
||||||
use nym_task::TaskClient;
|
|
||||||
use rand::{rngs::OsRng, CryptoRng, Rng};
|
use rand::{rngs::OsRng, CryptoRng, Rng};
|
||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
@@ -65,8 +64,6 @@ where
|
|||||||
packet_type: PacketType,
|
packet_type: PacketType,
|
||||||
|
|
||||||
stats_tx: ClientStatsSender,
|
stats_tx: ClientStatsSender,
|
||||||
|
|
||||||
task_client: TaskClient,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<R> Stream for LoopCoverTrafficStream<R>
|
impl<R> Stream for LoopCoverTrafficStream<R>
|
||||||
@@ -113,7 +110,6 @@ impl LoopCoverTrafficStream<OsRng> {
|
|||||||
traffic_config: config::Traffic,
|
traffic_config: config::Traffic,
|
||||||
cover_config: config::CoverTraffic,
|
cover_config: config::CoverTraffic,
|
||||||
stats_tx: ClientStatsSender,
|
stats_tx: ClientStatsSender,
|
||||||
task_client: TaskClient,
|
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let rng = OsRng;
|
let rng = OsRng;
|
||||||
|
|
||||||
@@ -132,7 +128,6 @@ impl LoopCoverTrafficStream<OsRng> {
|
|||||||
secondary_packet_size: traffic_config.secondary_packet_size,
|
secondary_packet_size: traffic_config.secondary_packet_size,
|
||||||
packet_type: traffic_config.packet_type,
|
packet_type: traffic_config.packet_type,
|
||||||
stats_tx,
|
stats_tx,
|
||||||
task_client,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -180,7 +175,7 @@ impl LoopCoverTrafficStream<OsRng> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let cover_message = match generate_loop_cover_packet(
|
let cover_message = generate_loop_cover_packet(
|
||||||
&mut self.rng,
|
&mut self.rng,
|
||||||
topology_ref,
|
topology_ref,
|
||||||
&self.ack_key,
|
&self.ack_key,
|
||||||
@@ -189,15 +184,8 @@ impl LoopCoverTrafficStream<OsRng> {
|
|||||||
self.cover_traffic.loop_cover_traffic_average_delay,
|
self.cover_traffic.loop_cover_traffic_average_delay,
|
||||||
cover_traffic_packet_size,
|
cover_traffic_packet_size,
|
||||||
self.packet_type,
|
self.packet_type,
|
||||||
) {
|
)
|
||||||
Ok(cover_message) => cover_message,
|
.expect("Somehow failed to generate a loop cover message with a valid topology");
|
||||||
Err(err) => {
|
|
||||||
warn!(
|
|
||||||
"Somehow failed to generate a loop cover message with a valid topology: {err}"
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Err(err) = self.mix_tx.try_send(vec![cover_message]) {
|
if let Err(err) = self.mix_tx.try_send(vec![cover_message]) {
|
||||||
match err {
|
match err {
|
||||||
@@ -229,7 +217,7 @@ impl LoopCoverTrafficStream<OsRng> {
|
|||||||
tokio::task::yield_now().await;
|
tokio::task::yield_now().await;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn start(mut self) {
|
pub fn start_with_shutdown(mut self, mut shutdown: nym_task::TaskClient) {
|
||||||
if self.cover_traffic.disable_loop_cover_traffic_stream {
|
if self.cover_traffic.disable_loop_cover_traffic_stream {
|
||||||
// we should have never got here in the first place - the task should have never been created to begin with
|
// we should have never got here in the first place - the task should have never been created to begin with
|
||||||
// so panic and review the code that lead to this branch
|
// so panic and review the code that lead to this branch
|
||||||
@@ -243,8 +231,6 @@ impl LoopCoverTrafficStream<OsRng> {
|
|||||||
);
|
);
|
||||||
self.set_next_delay(sampled);
|
self.set_next_delay(sampled);
|
||||||
|
|
||||||
let mut shutdown = self.task_client.fork("select");
|
|
||||||
|
|
||||||
spawn_future(async move {
|
spawn_future(async move {
|
||||||
debug!("Started LoopCoverTrafficStream with graceful shutdown support");
|
debug!("Started LoopCoverTrafficStream with graceful shutdown support");
|
||||||
|
|
||||||
|
|||||||
@@ -2,10 +2,7 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
use crate::client::key_manager::persistence::KeyStore;
|
use crate::client::key_manager::persistence::KeyStore;
|
||||||
use nym_crypto::{
|
use nym_crypto::asymmetric::{encryption, identity};
|
||||||
asymmetric::{encryption, identity},
|
|
||||||
hkdf::{DerivationMaterial, InvalidLength},
|
|
||||||
};
|
|
||||||
use nym_gateway_requests::shared_key::{LegacySharedKeys, SharedGatewayKey, SharedSymmetricKey};
|
use nym_gateway_requests::shared_key::{LegacySharedKeys, SharedGatewayKey, SharedSymmetricKey};
|
||||||
use nym_sphinx::acknowledgements::AckKey;
|
use nym_sphinx::acknowledgements::AckKey;
|
||||||
use rand::{CryptoRng, RngCore};
|
use rand::{CryptoRng, RngCore};
|
||||||
@@ -13,7 +10,6 @@ use std::sync::Arc;
|
|||||||
use zeroize::ZeroizeOnDrop;
|
use zeroize::ZeroizeOnDrop;
|
||||||
|
|
||||||
pub mod persistence;
|
pub mod persistence;
|
||||||
mod test;
|
|
||||||
|
|
||||||
// Note: to support key rotation in the future, all keys will require adding an extra smart pointer,
|
// Note: to support key rotation in the future, all keys will require adding an extra smart pointer,
|
||||||
// most likely an AtomicCell, or if it doesn't work as I think it does, a Mutex. Although I think
|
// most likely an AtomicCell, or if it doesn't work as I think it does, a Mutex. Although I think
|
||||||
@@ -47,24 +43,6 @@ impl ClientKeys {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_master_key<R>(
|
|
||||||
rng: &mut R,
|
|
||||||
derivation_material: &DerivationMaterial,
|
|
||||||
) -> Result<Self, InvalidLength>
|
|
||||||
where
|
|
||||||
R: RngCore + CryptoRng,
|
|
||||||
{
|
|
||||||
let secret = derivation_material.derive_secret()?;
|
|
||||||
Ok(ClientKeys {
|
|
||||||
identity_keypair: Arc::new(identity::KeyPair::from_secret(
|
|
||||||
secret,
|
|
||||||
derivation_material.index(),
|
|
||||||
)),
|
|
||||||
encryption_keypair: Arc::new(encryption::KeyPair::new(rng)),
|
|
||||||
ack_key: Arc::new(AckKey::new(rng)),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn from_keys(
|
pub fn from_keys(
|
||||||
id_keypair: identity::KeyPair,
|
id_keypair: identity::KeyPair,
|
||||||
enc_keypair: encryption::KeyPair,
|
enc_keypair: encryption::KeyPair,
|
||||||
|
|||||||
@@ -3,9 +3,7 @@
|
|||||||
|
|
||||||
use crate::client::key_manager::ClientKeys;
|
use crate::client::key_manager::ClientKeys;
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use rand::{CryptoRng, RngCore};
|
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::sync::Arc;
|
|
||||||
use tokio::sync::Mutex;
|
use tokio::sync::Mutex;
|
||||||
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
@@ -66,7 +64,6 @@ pub enum OnDiskKeysError {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
pub struct OnDiskKeys {
|
pub struct OnDiskKeys {
|
||||||
paths: ClientKeysPaths,
|
paths: ClientKeysPaths,
|
||||||
@@ -196,20 +193,9 @@ impl KeyStore for OnDiskKeys {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Default)]
|
||||||
pub struct InMemEphemeralKeys {
|
pub struct InMemEphemeralKeys {
|
||||||
keys: Arc<Mutex<ClientKeys>>,
|
keys: Mutex<Option<ClientKeys>>,
|
||||||
}
|
|
||||||
|
|
||||||
impl InMemEphemeralKeys {
|
|
||||||
pub fn new<R>(rng: &mut R) -> Self
|
|
||||||
where
|
|
||||||
R: RngCore + CryptoRng,
|
|
||||||
{
|
|
||||||
InMemEphemeralKeys {
|
|
||||||
keys: Arc::new(Mutex::new(ClientKeys::generate_new(rng))),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, thiserror::Error)]
|
#[derive(Debug, thiserror::Error)]
|
||||||
@@ -222,11 +208,11 @@ impl KeyStore for InMemEphemeralKeys {
|
|||||||
type StorageError = EphemeralKeysError;
|
type StorageError = EphemeralKeysError;
|
||||||
|
|
||||||
async fn load_keys(&self) -> Result<ClientKeys, Self::StorageError> {
|
async fn load_keys(&self) -> Result<ClientKeys, Self::StorageError> {
|
||||||
Ok(self.keys.lock().await.clone())
|
self.keys.lock().await.clone().ok_or(EphemeralKeysError)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn store_keys(&self, keys: &ClientKeys) -> Result<(), Self::StorageError> {
|
async fn store_keys(&self, keys: &ClientKeys) -> Result<(), Self::StorageError> {
|
||||||
*self.keys.lock().await = keys.clone();
|
*self.keys.lock().await = Some(keys.clone());
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,89 +0,0 @@
|
|||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use crate::client::key_manager::ClientKeys;
|
|
||||||
use nym_crypto::hkdf::DerivationMaterial;
|
|
||||||
use rand::SeedableRng;
|
|
||||||
use rand_chacha::ChaCha20Rng;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_from_master_key_success() {
|
|
||||||
// Set up a deterministic RNG.
|
|
||||||
let seed = [33u8; 32];
|
|
||||||
let mut rng = ChaCha20Rng::from_seed(seed);
|
|
||||||
|
|
||||||
// Set up the derivation material.
|
|
||||||
let master_key = b"this is a secret master key";
|
|
||||||
let salt = b"unique-salt";
|
|
||||||
let derivation_material = DerivationMaterial::new(master_key, 0, salt);
|
|
||||||
|
|
||||||
// Generate ClientKeys from the master key.
|
|
||||||
let client_keys = ClientKeys::from_master_key(&mut rng, &derivation_material)
|
|
||||||
.expect("Failed to create client keys");
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
client_keys.identity_keypair().public_key().to_string(),
|
|
||||||
String::from("FX4Undr5LPPBA7zThWWpAKXKQTXSbW1C28PnxbCqUkU4")
|
|
||||||
);
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
client_keys.identity_keypair().private_key().to_string(),
|
|
||||||
String::from("6S3uMi2rU5SwyUUYCiMrF5qqdcYnEDMYLggBSvavVzEt")
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_from_master_key_deterministic_identity() {
|
|
||||||
// Using identical derivation material should result in the exactly same identity keypair.
|
|
||||||
let seed = [1u8; 32];
|
|
||||||
let mut rng1 = ChaCha20Rng::from_seed(seed);
|
|
||||||
let mut rng2 = ChaCha20Rng::from_seed(seed);
|
|
||||||
|
|
||||||
let master_key = b"another secret master key";
|
|
||||||
let salt = b"deterministic-salt";
|
|
||||||
let index = 7u32;
|
|
||||||
let derivation_material = DerivationMaterial::new(master_key, index, salt);
|
|
||||||
|
|
||||||
let client_keys1 = ClientKeys::from_master_key(&mut rng1, &derivation_material)
|
|
||||||
.expect("Failed to create client keys (first instance)");
|
|
||||||
let client_keys2 = ClientKeys::from_master_key(&mut rng2, &derivation_material)
|
|
||||||
.expect("Failed to create client keys (second instance)");
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
client_keys1.identity_keypair().public_key().to_string(),
|
|
||||||
client_keys2.identity_keypair().public_key().to_string()
|
|
||||||
);
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
client_keys1.identity_keypair().private_key().to_string(),
|
|
||||||
client_keys2.identity_keypair().private_key().to_string()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_from_master_key_different_indices() {
|
|
||||||
// Changing the index should yield a different identity key.
|
|
||||||
let seed = [5u8; 32];
|
|
||||||
let mut rng = ChaCha20Rng::from_seed(seed);
|
|
||||||
|
|
||||||
let master_key = b"same secret key";
|
|
||||||
let salt = b"same-salt";
|
|
||||||
|
|
||||||
let derivation_material1 = DerivationMaterial::new(master_key, 1, salt);
|
|
||||||
let derivation_material2 = DerivationMaterial::new(master_key, 2, salt);
|
|
||||||
|
|
||||||
let client_keys1 = ClientKeys::from_master_key(&mut rng, &derivation_material1)
|
|
||||||
.expect("Failed to create client keys for index 1");
|
|
||||||
let client_keys2 = ClientKeys::from_master_key(&mut rng, &derivation_material2)
|
|
||||||
.expect("Failed to create client keys for index 2");
|
|
||||||
|
|
||||||
assert_ne!(
|
|
||||||
client_keys1.identity_keypair().public_key().to_string(),
|
|
||||||
client_keys2.identity_keypair().public_key().to_string()
|
|
||||||
);
|
|
||||||
|
|
||||||
assert_ne!(
|
|
||||||
client_keys1.identity_keypair().private_key().to_string(),
|
|
||||||
client_keys2.identity_keypair().private_key().to_string()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -2,18 +2,13 @@
|
|||||||
// 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::error::ClientCoreError;
|
use crate::{spawn_future, ForgetMe};
|
||||||
use crate::spawn_future;
|
|
||||||
use log::*;
|
use log::*;
|
||||||
use nym_gateway_requests::ClientRequest;
|
use nym_gateway_requests::ClientRequest;
|
||||||
use nym_sphinx::forwarding::packet::MixPacket;
|
use nym_sphinx::forwarding::packet::MixPacket;
|
||||||
use nym_task::TaskClient;
|
|
||||||
use transceiver::ErasedGatewayError;
|
|
||||||
|
|
||||||
pub type BatchMixMessageSender = tokio::sync::mpsc::Sender<Vec<MixPacket>>;
|
pub type BatchMixMessageSender = tokio::sync::mpsc::Sender<Vec<MixPacket>>;
|
||||||
pub type BatchMixMessageReceiver = tokio::sync::mpsc::Receiver<Vec<MixPacket>>;
|
pub type BatchMixMessageReceiver = tokio::sync::mpsc::Receiver<Vec<MixPacket>>;
|
||||||
pub type ClientRequestReceiver = tokio::sync::mpsc::Receiver<ClientRequest>;
|
|
||||||
pub type ClientRequestSender = tokio::sync::mpsc::Sender<ClientRequest>;
|
|
||||||
|
|
||||||
pub mod transceiver;
|
pub mod transceiver;
|
||||||
|
|
||||||
@@ -28,73 +23,52 @@ pub struct MixTrafficController {
|
|||||||
gateway_transceiver: Box<dyn GatewayTransceiver + Send>,
|
gateway_transceiver: Box<dyn GatewayTransceiver + Send>,
|
||||||
|
|
||||||
mix_rx: BatchMixMessageReceiver,
|
mix_rx: BatchMixMessageReceiver,
|
||||||
client_rx: ClientRequestReceiver,
|
|
||||||
|
|
||||||
// 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,
|
||||||
task_client: TaskClient,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MixTrafficController {
|
impl MixTrafficController {
|
||||||
pub fn new<T>(
|
pub fn new<T>(
|
||||||
gateway_transceiver: T,
|
gateway_transceiver: T,
|
||||||
task_client: TaskClient,
|
forget_me: ForgetMe,
|
||||||
) -> (
|
) -> (MixTrafficController, BatchMixMessageSender)
|
||||||
MixTrafficController,
|
|
||||||
BatchMixMessageSender,
|
|
||||||
ClientRequestSender,
|
|
||||||
)
|
|
||||||
where
|
where
|
||||||
T: GatewayTransceiver + Send + 'static,
|
T: GatewayTransceiver + Send + 'static,
|
||||||
{
|
{
|
||||||
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);
|
||||||
|
|
||||||
let (client_sender, client_receiver) = tokio::sync::mpsc::channel(1);
|
|
||||||
|
|
||||||
(
|
(
|
||||||
MixTrafficController {
|
MixTrafficController {
|
||||||
gateway_transceiver: Box::new(gateway_transceiver),
|
gateway_transceiver: Box::new(gateway_transceiver),
|
||||||
mix_rx: message_receiver,
|
mix_rx: message_receiver,
|
||||||
client_rx: client_receiver,
|
|
||||||
consecutive_gateway_failure_count: 0,
|
consecutive_gateway_failure_count: 0,
|
||||||
task_client,
|
forget_me,
|
||||||
},
|
},
|
||||||
message_sender,
|
message_sender,
|
||||||
client_sender,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_dynamic(
|
pub fn new_dynamic(
|
||||||
gateway_transceiver: Box<dyn GatewayTransceiver + Send>,
|
gateway_transceiver: Box<dyn GatewayTransceiver + Send>,
|
||||||
task_client: TaskClient,
|
forget_me: ForgetMe,
|
||||||
) -> (
|
) -> (MixTrafficController, BatchMixMessageSender) {
|
||||||
MixTrafficController,
|
|
||||||
BatchMixMessageSender,
|
|
||||||
ClientRequestSender,
|
|
||||||
) {
|
|
||||||
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);
|
||||||
let (client_sender, client_receiver) = tokio::sync::mpsc::channel(1);
|
|
||||||
(
|
(
|
||||||
MixTrafficController {
|
MixTrafficController {
|
||||||
gateway_transceiver,
|
gateway_transceiver,
|
||||||
mix_rx: message_receiver,
|
mix_rx: message_receiver,
|
||||||
client_rx: client_receiver,
|
|
||||||
consecutive_gateway_failure_count: 0,
|
consecutive_gateway_failure_count: 0,
|
||||||
task_client,
|
forget_me,
|
||||||
},
|
},
|
||||||
message_sender,
|
message_sender,
|
||||||
client_sender,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn on_messages(
|
async fn on_messages(&mut self, mut mix_packets: Vec<MixPacket>) {
|
||||||
&mut self,
|
|
||||||
mut mix_packets: Vec<MixPacket>,
|
|
||||||
) -> Result<(), ErasedGatewayError> {
|
|
||||||
debug_assert!(!mix_packets.is_empty());
|
debug_assert!(!mix_packets.is_empty());
|
||||||
|
|
||||||
let result = if mix_packets.len() == 1 {
|
let result = if mix_packets.len() == 1 {
|
||||||
@@ -106,60 +80,64 @@ impl MixTrafficController {
|
|||||||
.await
|
.await
|
||||||
};
|
};
|
||||||
|
|
||||||
if result.is_err() {
|
match result {
|
||||||
self.consecutive_gateway_failure_count += 1;
|
Err(err) => {
|
||||||
} else {
|
error!("Failed to send sphinx packet(s) to the gateway: {err}");
|
||||||
trace!("We *might* have managed to forward sphinx packet(s) to the gateway!");
|
self.consecutive_gateway_failure_count += 1;
|
||||||
self.consecutive_gateway_failure_count = 0;
|
if self.consecutive_gateway_failure_count == MAX_FAILURE_COUNT {
|
||||||
|
// todo: in the future this should initiate a 'graceful' shutdown or try
|
||||||
|
// to reconnect?
|
||||||
|
panic!("failed to send sphinx packet to the gateway {MAX_FAILURE_COUNT} times in a row - assuming the gateway is dead. Can't do anything about it yet :(")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(_) => {
|
||||||
|
trace!("We *might* have managed to forward sphinx packet(s) to the gateway!");
|
||||||
|
self.consecutive_gateway_failure_count = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn start(mut self) {
|
pub fn start_with_shutdown(mut self, mut shutdown: nym_task::TaskClient) {
|
||||||
spawn_future(async move {
|
spawn_future(async move {
|
||||||
debug!("Started MixTrafficController with graceful shutdown support");
|
debug!("Started MixTrafficController with graceful shutdown support");
|
||||||
|
|
||||||
while !self.task_client.is_shutdown() {
|
loop {
|
||||||
tokio::select! {
|
tokio::select! {
|
||||||
mix_packets = self.mix_rx.recv() => match mix_packets {
|
mix_packets = self.mix_rx.recv() => match mix_packets {
|
||||||
Some(mix_packets) => {
|
Some(mix_packets) => {
|
||||||
if let Err(err) = self.on_messages(mix_packets).await {
|
self.on_messages(mix_packets).await;
|
||||||
error!("Failed to send sphinx packet(s) to the gateway: {err}");
|
|
||||||
if self.consecutive_gateway_failure_count == MAX_FAILURE_COUNT {
|
|
||||||
// Disconnect from the gateway. If we should try to re-connect
|
|
||||||
// is handled at a higher layer.
|
|
||||||
error!("Failed to send sphinx packet to the gateway {MAX_FAILURE_COUNT} times in a row - assuming the gateway is dead");
|
|
||||||
// Do we need to handle the embedded mixnet client case
|
|
||||||
// separately?
|
|
||||||
self.task_client.send_we_stopped(Box::new(ClientCoreError::GatewayFailedToForwardMessages));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
None => {
|
None => {
|
||||||
log::trace!("MixTrafficController: Stopping since channel closed");
|
log::trace!("MixTrafficController: Stopping since channel closed");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
client_request = self.client_rx.recv() => match client_request {
|
_ = shutdown.recv_with_delay() => {
|
||||||
Some(client_request) => {
|
|
||||||
match self.gateway_transceiver.send_client_request(client_request).await {
|
|
||||||
Ok(_) => (),
|
|
||||||
Err(e) => error!("Failed to send client request: {}", e),
|
|
||||||
};
|
|
||||||
},
|
|
||||||
None => {
|
|
||||||
log::trace!("MixTrafficController, client request channel closed");
|
|
||||||
}
|
|
||||||
},
|
|
||||||
_ = self.task_client.recv() => {
|
|
||||||
log::trace!("MixTrafficController: Received shutdown");
|
log::trace!("MixTrafficController: Received shutdown");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.task_client.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");
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -86,9 +86,7 @@ impl<G: GatewayTransceiver + ?Sized + Send> GatewayTransceiver for Box<G> {
|
|||||||
&mut self,
|
&mut self,
|
||||||
message: ClientRequest,
|
message: ClientRequest,
|
||||||
) -> Result<(), GatewayClientError> {
|
) -> Result<(), GatewayClientError> {
|
||||||
let _ = (**self).send_client_request(message.clone()).await?;
|
(**self).send_client_request(message).await
|
||||||
log::debug!("Sent client request: {:?}", message);
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -145,7 +143,14 @@ where
|
|||||||
&mut self,
|
&mut self,
|
||||||
message: ClientRequest,
|
message: ClientRequest,
|
||||||
) -> Result<(), GatewayClientError> {
|
) -> Result<(), GatewayClientError> {
|
||||||
self.gateway_client.send_client_request(message).await
|
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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+6
-15
@@ -11,7 +11,6 @@ use nym_sphinx::{
|
|||||||
acknowledgements::{identifier::recover_identifier, AckKey},
|
acknowledgements::{identifier::recover_identifier, AckKey},
|
||||||
chunking::fragment::{FragmentIdentifier, COVER_FRAG_ID},
|
chunking::fragment::{FragmentIdentifier, COVER_FRAG_ID},
|
||||||
};
|
};
|
||||||
use nym_task::TaskClient;
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
/// Module responsible for listening for any data resembling acknowledgements from the network
|
/// Module responsible for listening for any data resembling acknowledgements from the network
|
||||||
@@ -21,7 +20,6 @@ pub(super) struct AcknowledgementListener {
|
|||||||
ack_receiver: AcknowledgementReceiver,
|
ack_receiver: AcknowledgementReceiver,
|
||||||
action_sender: AckActionSender,
|
action_sender: AckActionSender,
|
||||||
stats_tx: ClientStatsSender,
|
stats_tx: ClientStatsSender,
|
||||||
task_client: TaskClient,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AcknowledgementListener {
|
impl AcknowledgementListener {
|
||||||
@@ -30,14 +28,12 @@ impl AcknowledgementListener {
|
|||||||
ack_receiver: AcknowledgementReceiver,
|
ack_receiver: AcknowledgementReceiver,
|
||||||
action_sender: AckActionSender,
|
action_sender: AckActionSender,
|
||||||
stats_tx: ClientStatsSender,
|
stats_tx: ClientStatsSender,
|
||||||
task_client: TaskClient,
|
|
||||||
) -> Self {
|
) -> Self {
|
||||||
AcknowledgementListener {
|
AcknowledgementListener {
|
||||||
ack_key,
|
ack_key,
|
||||||
ack_receiver,
|
ack_receiver,
|
||||||
action_sender,
|
action_sender,
|
||||||
stats_tx,
|
stats_tx,
|
||||||
task_client,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,14 +64,9 @@ impl AcknowledgementListener {
|
|||||||
trace!("Received {} from the mix network", frag_id);
|
trace!("Received {} from the mix network", frag_id);
|
||||||
self.stats_tx
|
self.stats_tx
|
||||||
.report(PacketStatisticsEvent::RealAckReceived(ack_content.len()).into());
|
.report(PacketStatisticsEvent::RealAckReceived(ack_content.len()).into());
|
||||||
if let Err(err) = self
|
self.action_sender
|
||||||
.action_sender
|
|
||||||
.unbounded_send(Action::new_remove(frag_id))
|
.unbounded_send(Action::new_remove(frag_id))
|
||||||
{
|
.unwrap();
|
||||||
if !self.task_client.is_shutdown_poll() {
|
|
||||||
error!("Failed to send remove action to action controller: {err}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn handle_ack_receiver_item(&mut self, item: Vec<Vec<u8>>) {
|
async fn handle_ack_receiver_item(&mut self, item: Vec<Vec<u8>>) {
|
||||||
@@ -85,10 +76,10 @@ impl AcknowledgementListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) async fn run(&mut self) {
|
pub(super) async fn run_with_shutdown(&mut self, mut shutdown: nym_task::TaskClient) {
|
||||||
debug!("Started AcknowledgementListener with graceful shutdown support");
|
debug!("Started AcknowledgementListener with graceful shutdown support");
|
||||||
|
|
||||||
while !self.task_client.is_shutdown() {
|
while !shutdown.is_shutdown() {
|
||||||
tokio::select! {
|
tokio::select! {
|
||||||
acks = self.ack_receiver.next() => match acks {
|
acks = self.ack_receiver.next() => match acks {
|
||||||
Some(acks) => self.handle_ack_receiver_item(acks).await,
|
Some(acks) => self.handle_ack_receiver_item(acks).await,
|
||||||
@@ -97,12 +88,12 @@ impl AcknowledgementListener {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
_ = self.task_client.recv() => {
|
_ = shutdown.recv_with_delay() => {
|
||||||
log::trace!("AcknowledgementListener: Received shutdown");
|
log::trace!("AcknowledgementListener: Received shutdown");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.task_client.recv_timeout().await;
|
shutdown.recv_timeout().await;
|
||||||
log::debug!("AcknowledgementListener: Exiting");
|
log::debug!("AcknowledgementListener: Exiting");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+16
-15
@@ -9,7 +9,6 @@ use log::*;
|
|||||||
use nym_nonexhaustive_delayqueue::{Expired, NonExhaustiveDelayQueue, QueueKey};
|
use nym_nonexhaustive_delayqueue::{Expired, NonExhaustiveDelayQueue, QueueKey};
|
||||||
use nym_sphinx::chunking::fragment::FragmentIdentifier;
|
use nym_sphinx::chunking::fragment::FragmentIdentifier;
|
||||||
use nym_sphinx::Delay as SphinxDelay;
|
use nym_sphinx::Delay as SphinxDelay;
|
||||||
use nym_task::TaskClient;
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
@@ -102,8 +101,6 @@ pub(super) struct ActionController {
|
|||||||
|
|
||||||
/// Channel for notifying `RetransmissionRequestListener` about expired acknowledgements.
|
/// Channel for notifying `RetransmissionRequestListener` about expired acknowledgements.
|
||||||
retransmission_sender: RetransmissionRequestSender,
|
retransmission_sender: RetransmissionRequestSender,
|
||||||
|
|
||||||
task_client: TaskClient,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ActionController {
|
impl ActionController {
|
||||||
@@ -111,7 +108,6 @@ impl ActionController {
|
|||||||
config: Config,
|
config: Config,
|
||||||
retransmission_sender: RetransmissionRequestSender,
|
retransmission_sender: RetransmissionRequestSender,
|
||||||
incoming_actions: AckActionReceiver,
|
incoming_actions: AckActionReceiver,
|
||||||
task_client: TaskClient,
|
|
||||||
) -> Self {
|
) -> Self {
|
||||||
ActionController {
|
ActionController {
|
||||||
config,
|
config,
|
||||||
@@ -119,7 +115,6 @@ impl ActionController {
|
|||||||
pending_acks_timers: NonExhaustiveDelayQueue::new(),
|
pending_acks_timers: NonExhaustiveDelayQueue::new(),
|
||||||
incoming_actions,
|
incoming_actions,
|
||||||
retransmission_sender,
|
retransmission_sender,
|
||||||
task_client,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -221,7 +216,11 @@ impl ActionController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// note: when the entry expires it's automatically removed from pending_acks_timers
|
// note: when the entry expires it's automatically removed from pending_acks_timers
|
||||||
fn handle_expired_ack_timer(&mut self, expired_ack: Expired<FragmentIdentifier>) {
|
fn handle_expired_ack_timer(
|
||||||
|
&mut self,
|
||||||
|
expired_ack: Expired<FragmentIdentifier>,
|
||||||
|
task_client: &mut nym_task::TaskClient,
|
||||||
|
) {
|
||||||
// I'm honestly not sure how to handle it, because getting it means other things in our
|
// I'm honestly not sure how to handle it, because getting it means other things in our
|
||||||
// system are already misbehaving. If we ever see this panic, then I guess we should worry
|
// system are already misbehaving. If we ever see this panic, then I guess we should worry
|
||||||
// about it. Perhaps just reschedule it at later point?
|
// about it. Perhaps just reschedule it at later point?
|
||||||
@@ -239,13 +238,15 @@ impl ActionController {
|
|||||||
// downgrading an arc and then upgrading vs cloning is difference of 30ns vs 15ns
|
// downgrading an arc and then upgrading vs cloning is difference of 30ns vs 15ns
|
||||||
// so it's literally a NO difference while it might prevent us from unnecessarily
|
// so it's literally a NO difference while it might prevent us from unnecessarily
|
||||||
// resending data (in maybe 1 in 1 million cases, but it's something)
|
// resending data (in maybe 1 in 1 million cases, but it's something)
|
||||||
if let Err(err) = self
|
if self
|
||||||
.retransmission_sender
|
.retransmission_sender
|
||||||
.unbounded_send(Arc::downgrade(pending_ack_data))
|
.unbounded_send(Arc::downgrade(pending_ack_data))
|
||||||
|
.is_err()
|
||||||
{
|
{
|
||||||
if !self.task_client.is_shutdown_poll() {
|
assert!(
|
||||||
log::error!("Failed to send pending ack for retransmission: {err}");
|
task_client.is_shutdown_poll(),
|
||||||
}
|
"Failed to send pending ack for retransmission"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// this shouldn't cause any issues but shouldn't have happened to begin with!
|
// this shouldn't cause any issues but shouldn't have happened to begin with!
|
||||||
@@ -264,10 +265,10 @@ impl ActionController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) async fn run(&mut self) {
|
pub(super) async fn run_with_shutdown(&mut self, mut shutdown: nym_task::TaskClient) {
|
||||||
debug!("Started ActionController with graceful shutdown support");
|
debug!("Started ActionController with graceful shutdown support");
|
||||||
|
|
||||||
while !self.task_client.is_shutdown() {
|
loop {
|
||||||
tokio::select! {
|
tokio::select! {
|
||||||
action = self.incoming_actions.next() => match action {
|
action = self.incoming_actions.next() => match action {
|
||||||
Some(action) => self.process_action(action),
|
Some(action) => self.process_action(action),
|
||||||
@@ -279,19 +280,19 @@ impl ActionController {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
expired_ack = self.pending_acks_timers.next() => match expired_ack {
|
expired_ack = self.pending_acks_timers.next() => match expired_ack {
|
||||||
Some(expired_ack) => self.handle_expired_ack_timer(expired_ack),
|
Some(expired_ack) => self.handle_expired_ack_timer(expired_ack, &mut shutdown),
|
||||||
None => {
|
None => {
|
||||||
log::trace!("ActionController: Stopping since ack channel closed");
|
log::trace!("ActionController: Stopping since ack channel closed");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
_ = self.task_client.recv() => {
|
_ = shutdown.recv_with_delay() => {
|
||||||
log::trace!("ActionController: Received shutdown");
|
log::trace!("ActionController: Received shutdown");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.task_client.recv_timeout().await;
|
shutdown.recv_timeout().await;
|
||||||
log::debug!("ActionController: Exiting");
|
log::debug!("ActionController: Exiting");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-15
@@ -11,7 +11,6 @@ use nym_sphinx::anonymous_replies::requests::AnonymousSenderTag;
|
|||||||
use nym_sphinx::forwarding::packet::MixPacket;
|
use nym_sphinx::forwarding::packet::MixPacket;
|
||||||
use nym_sphinx::params::PacketType;
|
use nym_sphinx::params::PacketType;
|
||||||
use nym_task::connections::TransmissionLane;
|
use nym_task::connections::TransmissionLane;
|
||||||
use nym_task::TaskClient;
|
|
||||||
use rand::{CryptoRng, Rng};
|
use rand::{CryptoRng, Rng};
|
||||||
|
|
||||||
/// Module responsible for dealing with the received messages: splitting them, creating acknowledgements,
|
/// Module responsible for dealing with the received messages: splitting them, creating acknowledgements,
|
||||||
@@ -24,7 +23,6 @@ where
|
|||||||
input_receiver: InputMessageReceiver,
|
input_receiver: InputMessageReceiver,
|
||||||
message_handler: MessageHandler<R>,
|
message_handler: MessageHandler<R>,
|
||||||
reply_controller_sender: ReplyControllerSender,
|
reply_controller_sender: ReplyControllerSender,
|
||||||
task_client: TaskClient,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<R> InputMessageListener<R>
|
impl<R> InputMessageListener<R>
|
||||||
@@ -38,13 +36,11 @@ where
|
|||||||
input_receiver: InputMessageReceiver,
|
input_receiver: InputMessageReceiver,
|
||||||
message_handler: MessageHandler<R>,
|
message_handler: MessageHandler<R>,
|
||||||
reply_controller_sender: ReplyControllerSender,
|
reply_controller_sender: ReplyControllerSender,
|
||||||
task_client: TaskClient,
|
|
||||||
) -> Self {
|
) -> Self {
|
||||||
InputMessageListener {
|
InputMessageListener {
|
||||||
input_receiver,
|
input_receiver,
|
||||||
message_handler,
|
message_handler,
|
||||||
reply_controller_sender,
|
reply_controller_sender,
|
||||||
task_client,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,14 +63,8 @@ where
|
|||||||
lane: TransmissionLane,
|
lane: TransmissionLane,
|
||||||
) {
|
) {
|
||||||
// offload reply handling to the dedicated task
|
// offload reply handling to the dedicated task
|
||||||
if let Err(err) = self
|
self.reply_controller_sender
|
||||||
.reply_controller_sender
|
|
||||||
.send_reply(recipient_tag, data, lane)
|
.send_reply(recipient_tag, data, lane)
|
||||||
{
|
|
||||||
if !self.task_client.is_shutdown_poll() {
|
|
||||||
error!("failed to send a reply - {err}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn handle_plain_message(
|
async fn handle_plain_message(
|
||||||
@@ -174,10 +164,10 @@ where
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) async fn run(&mut self) {
|
pub(super) async fn run_with_shutdown(&mut self, mut shutdown: nym_task::TaskClient) {
|
||||||
debug!("Started InputMessageListener with graceful shutdown support");
|
debug!("Started InputMessageListener with graceful shutdown support");
|
||||||
|
|
||||||
while !self.task_client.is_shutdown() {
|
while !shutdown.is_shutdown() {
|
||||||
tokio::select! {
|
tokio::select! {
|
||||||
input_msg = self.input_receiver.recv() => match input_msg {
|
input_msg = self.input_receiver.recv() => match input_msg {
|
||||||
Some(input_msg) => {
|
Some(input_msg) => {
|
||||||
@@ -188,12 +178,12 @@ where
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
_ = self.task_client.recv() => {
|
_ = shutdown.recv_with_delay() => {
|
||||||
log::trace!("InputMessageListener: Received shutdown");
|
log::trace!("InputMessageListener: Received shutdown");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.task_client.recv_timeout().await;
|
shutdown.recv_timeout().await;
|
||||||
log::debug!("InputMessageListener: Exiting");
|
log::debug!("InputMessageListener: Exiting");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+27
-18
@@ -24,7 +24,6 @@ use nym_sphinx::{
|
|||||||
Delay as SphinxDelay,
|
Delay as SphinxDelay,
|
||||||
};
|
};
|
||||||
use nym_statistics_common::clients::ClientStatsSender;
|
use nym_statistics_common::clients::ClientStatsSender;
|
||||||
use nym_task::TaskClient;
|
|
||||||
use rand::{CryptoRng, Rng};
|
use rand::{CryptoRng, Rng};
|
||||||
use std::{
|
use std::{
|
||||||
sync::{Arc, Weak},
|
sync::{Arc, Weak},
|
||||||
@@ -67,7 +66,7 @@ pub(crate) enum PacketDestination {
|
|||||||
|
|
||||||
/// Structure representing a data `Fragment` that is on-route to the specified `Recipient`
|
/// Structure representing a data `Fragment` that is on-route to the specified `Recipient`
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct PendingAcknowledgement {
|
pub(crate) struct PendingAcknowledgement {
|
||||||
message_chunk: Fragment,
|
message_chunk: Fragment,
|
||||||
delay: SphinxDelay,
|
delay: SphinxDelay,
|
||||||
destination: PacketDestination,
|
destination: PacketDestination,
|
||||||
@@ -217,7 +216,6 @@ where
|
|||||||
message_handler: MessageHandler<R>,
|
message_handler: MessageHandler<R>,
|
||||||
reply_controller_sender: ReplyControllerSender,
|
reply_controller_sender: ReplyControllerSender,
|
||||||
stats_tx: ClientStatsSender,
|
stats_tx: ClientStatsSender,
|
||||||
task_client: TaskClient,
|
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let (retransmission_tx, retransmission_rx) = mpsc::unbounded();
|
let (retransmission_tx, retransmission_rx) = mpsc::unbounded();
|
||||||
|
|
||||||
@@ -227,7 +225,6 @@ where
|
|||||||
action_config,
|
action_config,
|
||||||
retransmission_tx,
|
retransmission_tx,
|
||||||
connectors.ack_action_receiver,
|
connectors.ack_action_receiver,
|
||||||
task_client.fork("action_controller"),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// will listen for any acks coming from the network
|
// will listen for any acks coming from the network
|
||||||
@@ -236,7 +233,6 @@ where
|
|||||||
connectors.ack_receiver,
|
connectors.ack_receiver,
|
||||||
connectors.ack_action_sender.clone(),
|
connectors.ack_action_sender.clone(),
|
||||||
stats_tx,
|
stats_tx,
|
||||||
task_client.fork("acknowledgement_listener"),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// will listen for any new messages from the client
|
// will listen for any new messages from the client
|
||||||
@@ -244,7 +240,6 @@ where
|
|||||||
connectors.input_receiver,
|
connectors.input_receiver,
|
||||||
message_handler.clone(),
|
message_handler.clone(),
|
||||||
reply_controller_sender.clone(),
|
reply_controller_sender.clone(),
|
||||||
task_client.fork("input_message_listener"),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// will listen for any ack timeouts and trigger retransmission
|
// will listen for any ack timeouts and trigger retransmission
|
||||||
@@ -254,16 +249,12 @@ where
|
|||||||
message_handler,
|
message_handler,
|
||||||
retransmission_rx,
|
retransmission_rx,
|
||||||
reply_controller_sender,
|
reply_controller_sender,
|
||||||
task_client.fork("retransmission_request_listener"),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// will listen for events indicating the packet was sent through the network so that
|
// will listen for events indicating the packet was sent through the network so that
|
||||||
// the retransmission timer should be started.
|
// the retransmission timer should be started.
|
||||||
let sent_notification_listener = SentNotificationListener::new(
|
let sent_notification_listener =
|
||||||
connectors.sent_notifier,
|
SentNotificationListener::new(connectors.sent_notifier, connectors.ack_action_sender);
|
||||||
connectors.ack_action_sender,
|
|
||||||
task_client.with_suffix("sent_notification_listener"),
|
|
||||||
);
|
|
||||||
|
|
||||||
AcknowledgementController {
|
AcknowledgementController {
|
||||||
acknowledgement_listener,
|
acknowledgement_listener,
|
||||||
@@ -274,35 +265,53 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn start(self, packet_type: PacketType) {
|
pub(super) fn start_with_shutdown(
|
||||||
|
self,
|
||||||
|
shutdown: nym_task::TaskClient,
|
||||||
|
packet_type: PacketType,
|
||||||
|
) {
|
||||||
let mut acknowledgement_listener = self.acknowledgement_listener;
|
let mut acknowledgement_listener = self.acknowledgement_listener;
|
||||||
let mut input_message_listener = self.input_message_listener;
|
let mut input_message_listener = self.input_message_listener;
|
||||||
let mut retransmission_request_listener = self.retransmission_request_listener;
|
let mut retransmission_request_listener = self.retransmission_request_listener;
|
||||||
let mut sent_notification_listener = self.sent_notification_listener;
|
let mut sent_notification_listener = self.sent_notification_listener;
|
||||||
let mut action_controller = self.action_controller;
|
let mut action_controller = self.action_controller;
|
||||||
|
|
||||||
|
let shutdown_handle = shutdown.fork("acknowledgement_listener");
|
||||||
spawn_future(async move {
|
spawn_future(async move {
|
||||||
acknowledgement_listener.run().await;
|
acknowledgement_listener
|
||||||
|
.run_with_shutdown(shutdown_handle)
|
||||||
|
.await;
|
||||||
debug!("The acknowledgement listener has finished execution!");
|
debug!("The acknowledgement listener has finished execution!");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let shutdown_handle = shutdown.fork("input_message_listener");
|
||||||
spawn_future(async move {
|
spawn_future(async move {
|
||||||
input_message_listener.run().await;
|
input_message_listener
|
||||||
|
.run_with_shutdown(shutdown_handle)
|
||||||
|
.await;
|
||||||
debug!("The input listener has finished execution!");
|
debug!("The input listener has finished execution!");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let shutdown_handle = shutdown.fork("retransmission_request_listener");
|
||||||
spawn_future(async move {
|
spawn_future(async move {
|
||||||
retransmission_request_listener.run(packet_type).await;
|
retransmission_request_listener
|
||||||
|
.run_with_shutdown(shutdown_handle, packet_type)
|
||||||
|
.await;
|
||||||
debug!("The retransmission request listener has finished execution!");
|
debug!("The retransmission request listener has finished execution!");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let shutdown_handle = shutdown.fork("sent_notification_listener");
|
||||||
spawn_future(async move {
|
spawn_future(async move {
|
||||||
sent_notification_listener.run().await;
|
sent_notification_listener
|
||||||
|
.run_with_shutdown(shutdown_handle)
|
||||||
|
.await;
|
||||||
debug!("The sent notification listener has finished execution!");
|
debug!("The sent notification listener has finished execution!");
|
||||||
});
|
});
|
||||||
|
|
||||||
spawn_future(async move {
|
spawn_future(async move {
|
||||||
action_controller.run().await;
|
action_controller
|
||||||
|
.run_with_shutdown(shutdown.with_suffix("action_controller"))
|
||||||
|
.await;
|
||||||
debug!("The controller has finished execution!");
|
debug!("The controller has finished execution!");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
+17
-32
@@ -14,7 +14,7 @@ use log::*;
|
|||||||
use nym_sphinx::chunking::fragment::Fragment;
|
use nym_sphinx::chunking::fragment::Fragment;
|
||||||
use nym_sphinx::preparer::PreparedFragment;
|
use nym_sphinx::preparer::PreparedFragment;
|
||||||
use nym_sphinx::{addressing::clients::Recipient, params::PacketType};
|
use nym_sphinx::{addressing::clients::Recipient, params::PacketType};
|
||||||
use nym_task::{connections::TransmissionLane, TaskClient};
|
use nym_task::connections::TransmissionLane;
|
||||||
use rand::{CryptoRng, Rng};
|
use rand::{CryptoRng, Rng};
|
||||||
use std::sync::{Arc, Weak};
|
use std::sync::{Arc, Weak};
|
||||||
|
|
||||||
@@ -25,7 +25,6 @@ pub(super) struct RetransmissionRequestListener<R> {
|
|||||||
message_handler: MessageHandler<R>,
|
message_handler: MessageHandler<R>,
|
||||||
request_receiver: RetransmissionRequestReceiver,
|
request_receiver: RetransmissionRequestReceiver,
|
||||||
reply_controller_sender: ReplyControllerSender,
|
reply_controller_sender: ReplyControllerSender,
|
||||||
task_client: TaskClient,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<R> RetransmissionRequestListener<R>
|
impl<R> RetransmissionRequestListener<R>
|
||||||
@@ -38,7 +37,6 @@ where
|
|||||||
message_handler: MessageHandler<R>,
|
message_handler: MessageHandler<R>,
|
||||||
request_receiver: RetransmissionRequestReceiver,
|
request_receiver: RetransmissionRequestReceiver,
|
||||||
reply_controller_sender: ReplyControllerSender,
|
reply_controller_sender: ReplyControllerSender,
|
||||||
task_client: TaskClient,
|
|
||||||
) -> Self {
|
) -> Self {
|
||||||
RetransmissionRequestListener {
|
RetransmissionRequestListener {
|
||||||
maximum_retransmissions,
|
maximum_retransmissions,
|
||||||
@@ -46,7 +44,6 @@ where
|
|||||||
message_handler,
|
message_handler,
|
||||||
request_receiver,
|
request_receiver,
|
||||||
reply_controller_sender,
|
reply_controller_sender,
|
||||||
task_client,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,12 +79,9 @@ where
|
|||||||
if let Some(limit) = self.maximum_retransmissions {
|
if let Some(limit) = self.maximum_retransmissions {
|
||||||
if timed_out_ack.retransmissions >= limit {
|
if timed_out_ack.retransmissions >= limit {
|
||||||
warn!("reached maximum number of allowed retransmissions for the packet");
|
warn!("reached maximum number of allowed retransmissions for the packet");
|
||||||
if let Err(err) = self
|
self.action_sender
|
||||||
.action_sender
|
|
||||||
.unbounded_send(Action::new_remove(frag_id))
|
.unbounded_send(Action::new_remove(frag_id))
|
||||||
{
|
.unwrap();
|
||||||
error!("Failed to send remove action to the controller: {err}");
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -99,16 +93,11 @@ where
|
|||||||
} => {
|
} => {
|
||||||
// if this is retransmission for reply, offload it to the dedicated task
|
// if this is retransmission for reply, offload it to the dedicated task
|
||||||
// that deals with all the surbs
|
// that deals with all the surbs
|
||||||
if let Err(err) = self.reply_controller_sender.send_retransmission_data(
|
return self.reply_controller_sender.send_retransmission_data(
|
||||||
*recipient_tag,
|
*recipient_tag,
|
||||||
weak_timed_out_ack,
|
weak_timed_out_ack,
|
||||||
*extra_surb_request,
|
*extra_surb_request,
|
||||||
) {
|
);
|
||||||
if !self.task_client.is_shutdown_poll() {
|
|
||||||
error!("Failed to send retransmission data to the reply controller: {err}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
PacketDestination::KnownRecipient(recipient) => {
|
PacketDestination::KnownRecipient(recipient) => {
|
||||||
self.prepare_normal_retransmission_chunk(
|
self.prepare_normal_retransmission_chunk(
|
||||||
@@ -125,12 +114,9 @@ where
|
|||||||
Err(err) => {
|
Err(err) => {
|
||||||
warn!("Could not retransmit the packet - {err}");
|
warn!("Could not retransmit the packet - {err}");
|
||||||
// we NEED to start timer here otherwise we will have this guy permanently stuck in memory
|
// we NEED to start timer here otherwise we will have this guy permanently stuck in memory
|
||||||
if let Err(err) = self
|
self.action_sender
|
||||||
.action_sender
|
|
||||||
.unbounded_send(Action::new_start_timer(frag_id))
|
.unbounded_send(Action::new_start_timer(frag_id))
|
||||||
{
|
.unwrap();
|
||||||
error!("Failed to send start timer action to the controller: {err}");
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -155,14 +141,9 @@ where
|
|||||||
// is sent to the `OutQueueControl` and has gone through its internal queue
|
// is sent to the `OutQueueControl` and has gone through its internal queue
|
||||||
// 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`
|
||||||
if let Err(err) = self
|
self.action_sender
|
||||||
.action_sender
|
|
||||||
.unbounded_send(Action::new_update_pending_ack(frag_id, new_delay))
|
.unbounded_send(Action::new_update_pending_ack(frag_id, new_delay))
|
||||||
{
|
.unwrap();
|
||||||
if !self.task_client.is_shutdown_poll() {
|
|
||||||
error!("Failed to send update pending ack action to the controller: {err}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// send to `OutQueueControl` to eventually send to the mix network
|
// send to `OutQueueControl` to eventually send to the mix network
|
||||||
self.message_handler
|
self.message_handler
|
||||||
@@ -176,10 +157,14 @@ where
|
|||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) async fn run(&mut self, packet_type: PacketType) {
|
pub(super) async fn run_with_shutdown(
|
||||||
|
&mut self,
|
||||||
|
mut shutdown: nym_task::TaskClient,
|
||||||
|
packet_type: PacketType,
|
||||||
|
) {
|
||||||
debug!("Started RetransmissionRequestListener with graceful shutdown support");
|
debug!("Started RetransmissionRequestListener with graceful shutdown support");
|
||||||
|
|
||||||
while !self.task_client.is_shutdown() {
|
while !shutdown.is_shutdown() {
|
||||||
tokio::select! {
|
tokio::select! {
|
||||||
timed_out_ack = self.request_receiver.next() => match timed_out_ack {
|
timed_out_ack = self.request_receiver.next() => match timed_out_ack {
|
||||||
Some(timed_out_ack) => self.on_retransmission_request(timed_out_ack, packet_type).await,
|
Some(timed_out_ack) => self.on_retransmission_request(timed_out_ack, packet_type).await,
|
||||||
@@ -188,12 +173,12 @@ where
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
_ = self.task_client.recv() => {
|
_ = shutdown.recv() => {
|
||||||
log::trace!("RetransmissionRequestListener: Received shutdown");
|
log::trace!("RetransmissionRequestListener: Received shutdown");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.task_client.recv_timeout().await;
|
shutdown.recv_timeout().await;
|
||||||
log::debug!("RetransmissionRequestListener: Exiting");
|
log::debug!("RetransmissionRequestListener: Exiting");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-15
@@ -6,7 +6,6 @@ use super::SentPacketNotificationReceiver;
|
|||||||
use futures::StreamExt;
|
use futures::StreamExt;
|
||||||
use log::*;
|
use log::*;
|
||||||
use nym_sphinx::chunking::fragment::{FragmentIdentifier, COVER_FRAG_ID};
|
use nym_sphinx::chunking::fragment::{FragmentIdentifier, COVER_FRAG_ID};
|
||||||
use nym_task::TaskClient;
|
|
||||||
|
|
||||||
/// Module responsible for starting up retransmission timers.
|
/// Module responsible for starting up retransmission timers.
|
||||||
/// It is required because when we send our packet to the `real traffic stream` controlled
|
/// It is required because when we send our packet to the `real traffic stream` controlled
|
||||||
@@ -15,19 +14,16 @@ use nym_task::TaskClient;
|
|||||||
pub(super) struct SentNotificationListener {
|
pub(super) struct SentNotificationListener {
|
||||||
sent_notifier: SentPacketNotificationReceiver,
|
sent_notifier: SentPacketNotificationReceiver,
|
||||||
action_sender: AckActionSender,
|
action_sender: AckActionSender,
|
||||||
task_client: TaskClient,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SentNotificationListener {
|
impl SentNotificationListener {
|
||||||
pub(super) fn new(
|
pub(super) fn new(
|
||||||
sent_notifier: SentPacketNotificationReceiver,
|
sent_notifier: SentPacketNotificationReceiver,
|
||||||
action_sender: AckActionSender,
|
action_sender: AckActionSender,
|
||||||
task_client: TaskClient,
|
|
||||||
) -> Self {
|
) -> Self {
|
||||||
SentNotificationListener {
|
SentNotificationListener {
|
||||||
sent_notifier,
|
sent_notifier,
|
||||||
action_sender,
|
action_sender,
|
||||||
task_client,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,20 +32,15 @@ impl SentNotificationListener {
|
|||||||
trace!("sent off a cover message - no need to start retransmission timer!");
|
trace!("sent off a cover message - no need to start retransmission timer!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if let Err(err) = self
|
self.action_sender
|
||||||
.action_sender
|
|
||||||
.unbounded_send(Action::new_start_timer(frag_id))
|
.unbounded_send(Action::new_start_timer(frag_id))
|
||||||
{
|
.unwrap();
|
||||||
if !self.task_client.is_shutdown_poll() {
|
|
||||||
error!("Failed to send start timer action to action controller: {err}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) async fn run(&mut self) {
|
pub(super) async fn run_with_shutdown(&mut self, mut shutdown: nym_task::TaskClient) {
|
||||||
debug!("Started SentNotificationListener with graceful shutdown support");
|
debug!("Started SentNotificationListener with graceful shutdown support");
|
||||||
|
|
||||||
while !self.task_client.is_shutdown() {
|
loop {
|
||||||
tokio::select! {
|
tokio::select! {
|
||||||
frag_id = self.sent_notifier.next() => match frag_id {
|
frag_id = self.sent_notifier.next() => match frag_id {
|
||||||
Some(frag_id) => {
|
Some(frag_id) => {
|
||||||
@@ -60,13 +51,13 @@ impl SentNotificationListener {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
_ = self.task_client.recv() => {
|
_ = shutdown.recv_with_delay() => {
|
||||||
log::trace!("SentNotificationListener: Received shutdown");
|
log::trace!("SentNotificationListener: Received shutdown");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert!(self.task_client.is_shutdown_poll());
|
assert!(shutdown.is_shutdown_poll());
|
||||||
log::debug!("SentNotificationListener: Exiting");
|
log::debug!("SentNotificationListener: Exiting");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ use nym_sphinx::params::{PacketSize, PacketType};
|
|||||||
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_task::TaskClient;
|
|
||||||
use nym_topology::{NymRouteProvider, NymTopologyError};
|
use nym_topology::{NymRouteProvider, NymTopologyError};
|
||||||
use rand::{CryptoRng, Rng};
|
use rand::{CryptoRng, Rng};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
@@ -33,12 +32,10 @@ pub enum PreparationError {
|
|||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
NymTopologyError(#[from] NymTopologyError),
|
NymTopologyError(#[from] NymTopologyError),
|
||||||
|
|
||||||
#[error("message too long for a single SURB, splitting into {fragments} fragments.")]
|
#[error("The received message cannot be sent using a single reply surb. It ended up getting split into {fragments} fragments.")]
|
||||||
MessageTooLongForSingleSurb { fragments: usize },
|
MessageTooLongForSingleSurb { fragments: usize },
|
||||||
|
|
||||||
#[error(
|
#[error("Not enough reply SURBs to send the message. We have {available} available and require at least {required}.")]
|
||||||
"not enough reply SURBs to send the message, available: {available} required: {required}."
|
|
||||||
)]
|
|
||||||
NotEnoughSurbs { available: usize, required: usize },
|
NotEnoughSurbs { available: usize, required: usize },
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -152,14 +149,12 @@ pub(crate) struct MessageHandler<R> {
|
|||||||
topology_access: TopologyAccessor,
|
topology_access: TopologyAccessor,
|
||||||
reply_key_storage: SentReplyKeys,
|
reply_key_storage: SentReplyKeys,
|
||||||
tag_storage: UsedSenderTags,
|
tag_storage: UsedSenderTags,
|
||||||
task_client: TaskClient,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<R> MessageHandler<R>
|
impl<R> MessageHandler<R>
|
||||||
where
|
where
|
||||||
R: CryptoRng + Rng,
|
R: CryptoRng + Rng,
|
||||||
{
|
{
|
||||||
#[allow(clippy::too_many_arguments)]
|
|
||||||
pub(crate) fn new(
|
pub(crate) fn new(
|
||||||
config: Config,
|
config: Config,
|
||||||
rng: R,
|
rng: R,
|
||||||
@@ -168,7 +163,6 @@ where
|
|||||||
topology_access: TopologyAccessor,
|
topology_access: TopologyAccessor,
|
||||||
reply_key_storage: SentReplyKeys,
|
reply_key_storage: SentReplyKeys,
|
||||||
tag_storage: UsedSenderTags,
|
tag_storage: UsedSenderTags,
|
||||||
task_client: TaskClient,
|
|
||||||
) -> Self
|
) -> Self
|
||||||
where
|
where
|
||||||
R: Copy,
|
R: Copy,
|
||||||
@@ -189,7 +183,6 @@ where
|
|||||||
topology_access,
|
topology_access,
|
||||||
reply_key_storage,
|
reply_key_storage,
|
||||||
tag_storage,
|
tag_storage,
|
||||||
task_client,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -616,25 +609,15 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn update_ack_delay(&self, id: FragmentIdentifier, new_delay: Delay) {
|
pub(crate) fn update_ack_delay(&self, id: FragmentIdentifier, new_delay: Delay) {
|
||||||
if let Err(err) = self
|
self.action_sender
|
||||||
.action_sender
|
|
||||||
.unbounded_send(Action::UpdatePendingAck(id, new_delay))
|
.unbounded_send(Action::UpdatePendingAck(id, new_delay))
|
||||||
{
|
.expect("action control task has died")
|
||||||
if !self.task_client.is_shutdown_poll() {
|
|
||||||
error!("Failed to send update action to the controller: {err}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn insert_pending_acks(&self, pending_acks: Vec<PendingAcknowledgement>) {
|
pub(crate) fn insert_pending_acks(&self, pending_acks: Vec<PendingAcknowledgement>) {
|
||||||
if let Err(err) = self
|
self.action_sender
|
||||||
.action_sender
|
|
||||||
.unbounded_send(Action::new_insert(pending_acks))
|
.unbounded_send(Action::new_insert(pending_acks))
|
||||||
{
|
.expect("action control task has died")
|
||||||
if !self.task_client.is_shutdown_poll() {
|
|
||||||
error!("Failed to send insert action to the controller: {err}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// tells real message sender (with the poisson timer) to send this to the mix network
|
// tells real message sender (with the poisson timer) to send this to the mix network
|
||||||
@@ -643,14 +626,9 @@ where
|
|||||||
messages: Vec<RealMessage>,
|
messages: Vec<RealMessage>,
|
||||||
transmission_lane: TransmissionLane,
|
transmission_lane: TransmissionLane,
|
||||||
) {
|
) {
|
||||||
if let Err(err) = self
|
self.real_message_sender
|
||||||
.real_message_sender
|
|
||||||
.send((messages, transmission_lane))
|
.send((messages, transmission_lane))
|
||||||
.await
|
.await
|
||||||
{
|
.expect("real message receiver task (OutQueueControl) has died");
|
||||||
if !self.task_client.is_shutdown_poll() {
|
|
||||||
error!("Failed to forward messages to the real message sender: {err}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,14 +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 nym_task::TaskClient;
|
|
||||||
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;
|
||||||
@@ -148,7 +148,6 @@ impl RealMessagesController<OsRng> {
|
|||||||
lane_queue_lengths: LaneQueueLengths,
|
lane_queue_lengths: LaneQueueLengths,
|
||||||
client_connection_rx: ConnectionCommandReceiver,
|
client_connection_rx: ConnectionCommandReceiver,
|
||||||
stats_tx: ClientStatsSender,
|
stats_tx: ClientStatsSender,
|
||||||
task_client: TaskClient,
|
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let rng = OsRng;
|
let rng = OsRng;
|
||||||
|
|
||||||
@@ -179,7 +178,6 @@ impl RealMessagesController<OsRng> {
|
|||||||
topology_access.clone(),
|
topology_access.clone(),
|
||||||
reply_storage.key_storage(),
|
reply_storage.key_storage(),
|
||||||
reply_storage.tags_storage(),
|
reply_storage.tags_storage(),
|
||||||
task_client.fork("message_handler"),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
let ack_control = AcknowledgementController::new(
|
let ack_control = AcknowledgementController::new(
|
||||||
@@ -189,7 +187,6 @@ impl RealMessagesController<OsRng> {
|
|||||||
message_handler.clone(),
|
message_handler.clone(),
|
||||||
reply_controller_sender,
|
reply_controller_sender,
|
||||||
stats_tx.clone(),
|
stats_tx.clone(),
|
||||||
task_client.fork("ack_control"),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
let reply_control = ReplyController::new(
|
let reply_control = ReplyController::new(
|
||||||
@@ -197,7 +194,6 @@ impl RealMessagesController<OsRng> {
|
|||||||
message_handler,
|
message_handler,
|
||||||
reply_storage,
|
reply_storage,
|
||||||
reply_controller_receiver,
|
reply_controller_receiver,
|
||||||
task_client.fork("reply_controller"),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
let out_queue_control = OutQueueControl::new(
|
let out_queue_control = OutQueueControl::new(
|
||||||
@@ -210,7 +206,6 @@ impl RealMessagesController<OsRng> {
|
|||||||
lane_queue_lengths,
|
lane_queue_lengths,
|
||||||
client_connection_rx,
|
client_connection_rx,
|
||||||
stats_tx,
|
stats_tx,
|
||||||
task_client.with_suffix("out_queue_control"),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
RealMessagesController {
|
RealMessagesController {
|
||||||
@@ -220,20 +215,22 @@ impl RealMessagesController<OsRng> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn start(self, packet_type: PacketType) {
|
pub fn start_with_shutdown(self, shutdown: nym_task::TaskClient, packet_type: PacketType) {
|
||||||
let mut out_queue_control = self.out_queue_control;
|
let mut out_queue_control = self.out_queue_control;
|
||||||
let ack_control = self.ack_control;
|
let ack_control = self.ack_control;
|
||||||
let mut reply_control = self.reply_control;
|
let mut reply_control = self.reply_control;
|
||||||
|
|
||||||
|
let shutdown_handle = shutdown.fork("out_queue_control");
|
||||||
spawn_future(async move {
|
spawn_future(async move {
|
||||||
out_queue_control.run().await;
|
out_queue_control.run_with_shutdown(shutdown_handle).await;
|
||||||
debug!("The out queue controller has finished execution!");
|
debug!("The out queue controller has finished execution!");
|
||||||
});
|
});
|
||||||
|
let shutdown_handle = shutdown.fork("reply_control");
|
||||||
spawn_future(async move {
|
spawn_future(async move {
|
||||||
reply_control.run().await;
|
reply_control.run_with_shutdown(shutdown_handle).await;
|
||||||
debug!("The reply controller has finished execution!");
|
debug!("The reply controller has finished execution!");
|
||||||
});
|
});
|
||||||
|
|
||||||
ack_control.start(packet_type);
|
ack_control.start_with_shutdown(shutdown.with_suffix("ack_control"), packet_type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ use nym_statistics_common::clients::{packet_statistics::PacketStatisticsEvent, C
|
|||||||
use nym_task::connections::{
|
use nym_task::connections::{
|
||||||
ConnectionCommand, ConnectionCommandReceiver, ConnectionId, LaneQueueLengths, TransmissionLane,
|
ConnectionCommand, ConnectionCommandReceiver, ConnectionId, LaneQueueLengths, TransmissionLane,
|
||||||
};
|
};
|
||||||
use nym_task::TaskClient;
|
|
||||||
use rand::{CryptoRng, Rng};
|
use rand::{CryptoRng, Rng};
|
||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
@@ -118,8 +117,6 @@ where
|
|||||||
|
|
||||||
/// Channel used for sending metrics events (specifically `PacketStatistics` events) to the metrics tracker.
|
/// Channel used for sending metrics events (specifically `PacketStatistics` events) to the metrics tracker.
|
||||||
stats_tx: ClientStatsSender,
|
stats_tx: ClientStatsSender,
|
||||||
|
|
||||||
task_client: TaskClient,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@@ -179,7 +176,6 @@ where
|
|||||||
lane_queue_lengths: LaneQueueLengths,
|
lane_queue_lengths: LaneQueueLengths,
|
||||||
client_connection_rx: ConnectionCommandReceiver,
|
client_connection_rx: ConnectionCommandReceiver,
|
||||||
stats_tx: ClientStatsSender,
|
stats_tx: ClientStatsSender,
|
||||||
task_client: TaskClient,
|
|
||||||
) -> Self {
|
) -> Self {
|
||||||
OutQueueControl {
|
OutQueueControl {
|
||||||
config,
|
config,
|
||||||
@@ -194,7 +190,6 @@ where
|
|||||||
client_connection_rx,
|
client_connection_rx,
|
||||||
lane_queue_lengths,
|
lane_queue_lengths,
|
||||||
stats_tx,
|
stats_tx,
|
||||||
task_client,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -203,9 +198,7 @@ where
|
|||||||
// queues and client load rather than the required delay. So realistically we can treat
|
// queues and client load rather than the required delay. So realistically we can treat
|
||||||
// whatever is about to happen as negligible additional delay.
|
// whatever is about to happen as negligible additional delay.
|
||||||
trace!("{} is about to get sent to the mixnet", frag_id);
|
trace!("{} is about to get sent to the mixnet", frag_id);
|
||||||
if let Err(err) = self.sent_notifier.unbounded_send(frag_id) {
|
self.sent_notifier.unbounded_send(frag_id).unwrap();
|
||||||
error!("Failed to notify about sent message: {err}");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn loop_cover_message_size(&mut self) -> PacketSize {
|
fn loop_cover_message_size(&mut self) -> PacketSize {
|
||||||
@@ -278,9 +271,7 @@ where
|
|||||||
};
|
};
|
||||||
|
|
||||||
if let Err(err) = self.mix_tx.send(vec![next_message]).await {
|
if let Err(err) = self.mix_tx.send(vec![next_message]).await {
|
||||||
if !self.task_client.is_shutdown_poll() {
|
log::error!("Failed to send: {err}");
|
||||||
log::error!("Failed to send: {err}");
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
let event = if fragment_id.is_some() {
|
let event = if fragment_id.is_some() {
|
||||||
PacketStatisticsEvent::RealPacketSent(packet_size)
|
PacketStatisticsEvent::RealPacketSent(packet_size)
|
||||||
@@ -513,29 +504,21 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
fn log_status(&self, shutdown: &mut TaskClient) {
|
fn log_status(&self, shutdown: &mut nym_task::TaskClient) {
|
||||||
use crate::error::ClientCoreStatusMessage;
|
use crate::error::ClientCoreStatusMessage;
|
||||||
|
|
||||||
let packets = self.transmission_buffer.total_size();
|
let packets = self.transmission_buffer.total_size();
|
||||||
let lanes = self.transmission_buffer.lanes();
|
let backlog = self.transmission_buffer.total_size_in_bytes() as f64 / 1024.0;
|
||||||
|
let lanes = self.transmission_buffer.num_lanes();
|
||||||
let mult = self.sending_delay_controller.current_multiplier();
|
let mult = self.sending_delay_controller.current_multiplier();
|
||||||
let delay = self.current_average_message_sending_delay().as_millis();
|
let delay = self.current_average_message_sending_delay().as_millis();
|
||||||
|
|
||||||
let lane_status = lanes
|
|
||||||
.iter()
|
|
||||||
.map(|lane_name| {
|
|
||||||
let lane_length = self.transmission_buffer.lane_length(lane_name).unwrap_or(0);
|
|
||||||
format!("{lane_name:?}: {lane_length}")
|
|
||||||
})
|
|
||||||
.collect::<Vec<String>>()
|
|
||||||
.join(", ");
|
|
||||||
|
|
||||||
let status_str = if self.config.traffic.disable_main_poisson_packet_distribution {
|
let status_str = if self.config.traffic.disable_main_poisson_packet_distribution {
|
||||||
format!("Packet backlog: {lane_status}, no delay")
|
format!("Packet backlog: {backlog:.2} kiB ({packets}), {lanes} lanes, no delay")
|
||||||
} else {
|
} else {
|
||||||
format!("Packet backlog: {lane_status}, avg delay: {delay}ms ({mult})")
|
format!(
|
||||||
|
"Packet backlog: {backlog:.2} kiB ({packets}), {lanes} lanes, avg delay: {delay}ms ({mult})"
|
||||||
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
if packets > 1000 {
|
if packets > 1000 {
|
||||||
log::warn!("{status_str}");
|
log::warn!("{status_str}");
|
||||||
} else if packets > 0 {
|
} else if packets > 0 {
|
||||||
@@ -552,19 +535,17 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) async fn run(&mut self) {
|
pub(super) async fn run_with_shutdown(&mut self, mut shutdown: nym_task::TaskClient) {
|
||||||
debug!("Started OutQueueControl with graceful shutdown support");
|
debug!("Started OutQueueControl with graceful shutdown support");
|
||||||
|
|
||||||
let mut shutdown = self.task_client.fork("select");
|
|
||||||
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
{
|
{
|
||||||
let mut status_timer = tokio::time::interval(Duration::from_secs(5));
|
let mut status_timer = tokio::time::interval(Duration::from_secs(5));
|
||||||
|
|
||||||
while !shutdown.is_shutdown() {
|
loop {
|
||||||
tokio::select! {
|
tokio::select! {
|
||||||
biased;
|
biased;
|
||||||
_ = shutdown.recv() => {
|
_ = shutdown.recv_with_delay() => {
|
||||||
log::trace!("OutQueueControl: Received shutdown");
|
log::trace!("OutQueueControl: Received shutdown");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
+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,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ use nym_sphinx::message::{NymMessage, PlainMessage};
|
|||||||
use nym_sphinx::params::ReplySurbKeyDigestAlgorithm;
|
use nym_sphinx::params::ReplySurbKeyDigestAlgorithm;
|
||||||
use nym_sphinx::receiver::{MessageReceiver, MessageRecoveryError, ReconstructedMessage};
|
use nym_sphinx::receiver::{MessageReceiver, MessageRecoveryError, ReconstructedMessage};
|
||||||
use nym_statistics_common::clients::{packet_statistics::PacketStatisticsEvent, ClientStatsSender};
|
use nym_statistics_common::clients::{packet_statistics::PacketStatisticsEvent, ClientStatsSender};
|
||||||
use nym_task::TaskClient;
|
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
@@ -153,7 +152,6 @@ struct ReceivedMessagesBuffer<R: MessageReceiver> {
|
|||||||
inner: Arc<Mutex<ReceivedMessagesBufferInner<R>>>,
|
inner: Arc<Mutex<ReceivedMessagesBufferInner<R>>>,
|
||||||
reply_key_storage: SentReplyKeys,
|
reply_key_storage: SentReplyKeys,
|
||||||
reply_controller_sender: ReplyControllerSender,
|
reply_controller_sender: ReplyControllerSender,
|
||||||
task_client: TaskClient,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<R: MessageReceiver> ReceivedMessagesBuffer<R> {
|
impl<R: MessageReceiver> ReceivedMessagesBuffer<R> {
|
||||||
@@ -162,7 +160,6 @@ impl<R: MessageReceiver> ReceivedMessagesBuffer<R> {
|
|||||||
reply_key_storage: SentReplyKeys,
|
reply_key_storage: SentReplyKeys,
|
||||||
reply_controller_sender: ReplyControllerSender,
|
reply_controller_sender: ReplyControllerSender,
|
||||||
stats_tx: ClientStatsSender,
|
stats_tx: ClientStatsSender,
|
||||||
task_client: TaskClient,
|
|
||||||
) -> Self {
|
) -> Self {
|
||||||
ReceivedMessagesBuffer {
|
ReceivedMessagesBuffer {
|
||||||
inner: Arc::new(Mutex::new(ReceivedMessagesBufferInner {
|
inner: Arc::new(Mutex::new(ReceivedMessagesBufferInner {
|
||||||
@@ -175,7 +172,6 @@ impl<R: MessageReceiver> ReceivedMessagesBuffer<R> {
|
|||||||
})),
|
})),
|
||||||
reply_key_storage,
|
reply_key_storage,
|
||||||
reply_controller_sender,
|
reply_controller_sender,
|
||||||
task_client,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -261,15 +257,11 @@ impl<R: MessageReceiver> ReceivedMessagesBuffer<R> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Err(err) = self.reply_controller_sender.send_additional_surbs(
|
self.reply_controller_sender.send_additional_surbs(
|
||||||
msg.sender_tag,
|
msg.sender_tag,
|
||||||
reply_surbs,
|
reply_surbs,
|
||||||
from_surb_request,
|
from_surb_request,
|
||||||
) {
|
)
|
||||||
if !self.task_client.is_shutdown_poll() {
|
|
||||||
error!("{err}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
reconstructed
|
reconstructed
|
||||||
}
|
}
|
||||||
@@ -284,14 +276,8 @@ impl<R: MessageReceiver> ReceivedMessagesBuffer<R> {
|
|||||||
ReplyMessageContent::Data { message } => reconstructed.push(message.into()),
|
ReplyMessageContent::Data { message } => reconstructed.push(message.into()),
|
||||||
ReplyMessageContent::SurbRequest { recipient, amount } => {
|
ReplyMessageContent::SurbRequest { recipient, amount } => {
|
||||||
debug!("received request for {amount} additional reply SURBs from {recipient}");
|
debug!("received request for {amount} additional reply SURBs from {recipient}");
|
||||||
if let Err(err) = self
|
self.reply_controller_sender
|
||||||
.reply_controller_sender
|
.send_additional_surbs_request(*recipient, amount);
|
||||||
.send_additional_surbs_request(*recipient, amount)
|
|
||||||
{
|
|
||||||
if !self.task_client.is_shutdown_poll() {
|
|
||||||
error!("{err}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -413,19 +399,16 @@ pub enum ReceivedBufferMessage {
|
|||||||
struct RequestReceiver<R: MessageReceiver> {
|
struct RequestReceiver<R: MessageReceiver> {
|
||||||
received_buffer: ReceivedMessagesBuffer<R>,
|
received_buffer: ReceivedMessagesBuffer<R>,
|
||||||
query_receiver: ReceivedBufferRequestReceiver,
|
query_receiver: ReceivedBufferRequestReceiver,
|
||||||
task_client: TaskClient,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<R: MessageReceiver> RequestReceiver<R> {
|
impl<R: MessageReceiver> RequestReceiver<R> {
|
||||||
fn new(
|
fn new(
|
||||||
received_buffer: ReceivedMessagesBuffer<R>,
|
received_buffer: ReceivedMessagesBuffer<R>,
|
||||||
query_receiver: ReceivedBufferRequestReceiver,
|
query_receiver: ReceivedBufferRequestReceiver,
|
||||||
task_client: TaskClient,
|
|
||||||
) -> Self {
|
) -> Self {
|
||||||
RequestReceiver {
|
RequestReceiver {
|
||||||
received_buffer,
|
received_buffer,
|
||||||
query_receiver,
|
query_receiver,
|
||||||
task_client,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -440,12 +423,12 @@ impl<R: MessageReceiver> RequestReceiver<R> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn run(&mut self) {
|
async fn run_with_shutdown(&mut self, mut shutdown: nym_task::TaskClient) {
|
||||||
debug!("Started RequestReceiver with graceful shutdown support");
|
debug!("Started RequestReceiver with graceful shutdown support");
|
||||||
while !self.task_client.is_shutdown() {
|
while !shutdown.is_shutdown() {
|
||||||
tokio::select! {
|
tokio::select! {
|
||||||
biased;
|
biased;
|
||||||
_ = self.task_client.recv() => {
|
_ = shutdown.recv_with_delay() => {
|
||||||
log::trace!("RequestReceiver: Received shutdown");
|
log::trace!("RequestReceiver: Received shutdown");
|
||||||
}
|
}
|
||||||
request = self.query_receiver.next() => {
|
request = self.query_receiver.next() => {
|
||||||
@@ -458,7 +441,7 @@ impl<R: MessageReceiver> RequestReceiver<R> {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.task_client.recv().await;
|
shutdown.recv_timeout().await;
|
||||||
log::debug!("RequestReceiver: Exiting");
|
log::debug!("RequestReceiver: Exiting");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -466,25 +449,25 @@ impl<R: MessageReceiver> RequestReceiver<R> {
|
|||||||
struct FragmentedMessageReceiver<R: MessageReceiver> {
|
struct FragmentedMessageReceiver<R: MessageReceiver> {
|
||||||
received_buffer: ReceivedMessagesBuffer<R>,
|
received_buffer: ReceivedMessagesBuffer<R>,
|
||||||
mixnet_packet_receiver: MixnetMessageReceiver,
|
mixnet_packet_receiver: MixnetMessageReceiver,
|
||||||
task_client: TaskClient,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<R: MessageReceiver> FragmentedMessageReceiver<R> {
|
impl<R: MessageReceiver> FragmentedMessageReceiver<R> {
|
||||||
fn new(
|
fn new(
|
||||||
received_buffer: ReceivedMessagesBuffer<R>,
|
received_buffer: ReceivedMessagesBuffer<R>,
|
||||||
mixnet_packet_receiver: MixnetMessageReceiver,
|
mixnet_packet_receiver: MixnetMessageReceiver,
|
||||||
task_client: TaskClient,
|
|
||||||
) -> Self {
|
) -> Self {
|
||||||
FragmentedMessageReceiver {
|
FragmentedMessageReceiver {
|
||||||
received_buffer,
|
received_buffer,
|
||||||
mixnet_packet_receiver,
|
mixnet_packet_receiver,
|
||||||
task_client,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn run(&mut self) -> Result<(), MessageRecoveryError> {
|
async fn run_with_shutdown(
|
||||||
|
&mut self,
|
||||||
|
mut shutdown: nym_task::TaskClient,
|
||||||
|
) -> Result<(), MessageRecoveryError> {
|
||||||
debug!("Started FragmentedMessageReceiver with graceful shutdown support");
|
debug!("Started FragmentedMessageReceiver with graceful shutdown support");
|
||||||
while !self.task_client.is_shutdown() {
|
while !shutdown.is_shutdown() {
|
||||||
tokio::select! {
|
tokio::select! {
|
||||||
new_messages = self.mixnet_packet_receiver.next() => {
|
new_messages = self.mixnet_packet_receiver.next() => {
|
||||||
if let Some(new_messages) = new_messages {
|
if let Some(new_messages) = new_messages {
|
||||||
@@ -494,12 +477,12 @@ impl<R: MessageReceiver> FragmentedMessageReceiver<R> {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
_ = self.task_client.recv_with_delay() => {
|
_ = shutdown.recv_with_delay() => {
|
||||||
log::trace!("FragmentedMessageReceiver: Received shutdown");
|
log::trace!("FragmentedMessageReceiver: Received shutdown");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.task_client.recv_timeout().await;
|
shutdown.recv_timeout().await;
|
||||||
log::debug!("FragmentedMessageReceiver: Exiting");
|
log::debug!("FragmentedMessageReceiver: Exiting");
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -518,42 +501,41 @@ impl<R: MessageReceiver + Clone + Send + 'static> ReceivedMessagesBufferControll
|
|||||||
reply_key_storage: SentReplyKeys,
|
reply_key_storage: SentReplyKeys,
|
||||||
reply_controller_sender: ReplyControllerSender,
|
reply_controller_sender: ReplyControllerSender,
|
||||||
metrics_reporter: ClientStatsSender,
|
metrics_reporter: ClientStatsSender,
|
||||||
task_client: TaskClient,
|
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let received_buffer = ReceivedMessagesBuffer::new(
|
let received_buffer = ReceivedMessagesBuffer::new(
|
||||||
local_encryption_keypair,
|
local_encryption_keypair,
|
||||||
reply_key_storage,
|
reply_key_storage,
|
||||||
reply_controller_sender,
|
reply_controller_sender,
|
||||||
metrics_reporter,
|
metrics_reporter,
|
||||||
task_client.fork("received_messages_buffer"),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
ReceivedMessagesBufferController {
|
ReceivedMessagesBufferController {
|
||||||
fragmented_message_receiver: FragmentedMessageReceiver::new(
|
fragmented_message_receiver: FragmentedMessageReceiver::new(
|
||||||
received_buffer.clone(),
|
received_buffer.clone(),
|
||||||
mixnet_packet_receiver,
|
mixnet_packet_receiver,
|
||||||
task_client.fork("fragmented_message_receiver"),
|
|
||||||
),
|
|
||||||
request_receiver: RequestReceiver::new(
|
|
||||||
received_buffer,
|
|
||||||
query_receiver,
|
|
||||||
task_client.with_suffix("request_receiver"),
|
|
||||||
),
|
),
|
||||||
|
request_receiver: RequestReceiver::new(received_buffer, query_receiver),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn start(self) {
|
pub fn start_with_shutdown(self, shutdown: nym_task::TaskClient) {
|
||||||
let mut fragmented_message_receiver = self.fragmented_message_receiver;
|
let mut fragmented_message_receiver = self.fragmented_message_receiver;
|
||||||
let mut request_receiver = self.request_receiver;
|
let mut request_receiver = self.request_receiver;
|
||||||
|
|
||||||
|
let shutdown_handle = shutdown.fork("fragmented_message_receiver");
|
||||||
spawn_future(async move {
|
spawn_future(async move {
|
||||||
match fragmented_message_receiver.run().await {
|
match fragmented_message_receiver
|
||||||
|
.run_with_shutdown(shutdown_handle)
|
||||||
|
.await
|
||||||
|
{
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
Err(e) => error!("{e}"),
|
Err(e) => error!("{e}"),
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
spawn_future(async move {
|
spawn_future(async move {
|
||||||
request_receiver.run().await;
|
request_receiver
|
||||||
|
.run_with_shutdown(shutdown.with_suffix("request_receiver"))
|
||||||
|
.await;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ use nym_sphinx::anonymous_replies::requests::AnonymousSenderTag;
|
|||||||
use nym_sphinx::anonymous_replies::ReplySurb;
|
use nym_sphinx::anonymous_replies::ReplySurb;
|
||||||
use nym_sphinx::chunking::fragment::{Fragment, FragmentIdentifier};
|
use nym_sphinx::chunking::fragment::{Fragment, FragmentIdentifier};
|
||||||
use nym_task::connections::{ConnectionId, TransmissionLane};
|
use nym_task::connections::{ConnectionId, TransmissionLane};
|
||||||
use nym_task::TaskClient;
|
|
||||||
use rand::{CryptoRng, Rng};
|
use rand::{CryptoRng, Rng};
|
||||||
use std::cmp::{max, min};
|
use std::cmp::{max, min};
|
||||||
use std::collections::btree_map::Entry;
|
use std::collections::btree_map::Entry;
|
||||||
@@ -69,9 +68,6 @@ pub struct ReplyController<R> {
|
|||||||
|
|
||||||
message_handler: MessageHandler<R>,
|
message_handler: MessageHandler<R>,
|
||||||
full_reply_storage: CombinedReplyStorage,
|
full_reply_storage: CombinedReplyStorage,
|
||||||
|
|
||||||
// Listen for shutdown signals
|
|
||||||
task_client: TaskClient,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<R> ReplyController<R>
|
impl<R> ReplyController<R>
|
||||||
@@ -83,7 +79,6 @@ where
|
|||||||
message_handler: MessageHandler<R>,
|
message_handler: MessageHandler<R>,
|
||||||
full_reply_storage: CombinedReplyStorage,
|
full_reply_storage: CombinedReplyStorage,
|
||||||
request_receiver: ReplyControllerReceiver,
|
request_receiver: ReplyControllerReceiver,
|
||||||
task_client: TaskClient,
|
|
||||||
) -> Self {
|
) -> Self {
|
||||||
ReplyController {
|
ReplyController {
|
||||||
config,
|
config,
|
||||||
@@ -92,7 +87,6 @@ where
|
|||||||
pending_retransmissions: HashMap::new(),
|
pending_retransmissions: HashMap::new(),
|
||||||
message_handler,
|
message_handler,
|
||||||
full_reply_storage,
|
full_reply_storage,
|
||||||
task_client,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -102,7 +96,6 @@ where
|
|||||||
fragments: I,
|
fragments: I,
|
||||||
lane: TransmissionLane,
|
lane: TransmissionLane,
|
||||||
) {
|
) {
|
||||||
trace!("buffering pending replies for {recipient}");
|
|
||||||
self.pending_replies
|
self.pending_replies
|
||||||
.entry(*recipient)
|
.entry(*recipient)
|
||||||
.or_insert_with(TransmissionBuffer::new)
|
.or_insert_with(TransmissionBuffer::new)
|
||||||
@@ -114,7 +107,6 @@ where
|
|||||||
recipient: &AnonymousSenderTag,
|
recipient: &AnonymousSenderTag,
|
||||||
fragments: Vec<(TransmissionLane, Fragment)>,
|
fragments: Vec<(TransmissionLane, Fragment)>,
|
||||||
) {
|
) {
|
||||||
trace!("re-inserting pending replies for {recipient}");
|
|
||||||
// the buffer should ALWAYS exist at this point, if it doesn't, it's a bug...
|
// the buffer should ALWAYS exist at this point, if it doesn't, it's a bug...
|
||||||
self.pending_replies
|
self.pending_replies
|
||||||
.entry(*recipient)
|
.entry(*recipient)
|
||||||
@@ -127,7 +119,6 @@ where
|
|||||||
recipient: &AnonymousSenderTag,
|
recipient: &AnonymousSenderTag,
|
||||||
data: Vec<Arc<PendingAcknowledgement>>,
|
data: Vec<Arc<PendingAcknowledgement>>,
|
||||||
) {
|
) {
|
||||||
trace!("re-inserting pending retransmissions for {recipient}");
|
|
||||||
// the underlying entry MUST exist as we've just got data from there
|
// the underlying entry MUST exist as we've just got data from there
|
||||||
let map_entry = self
|
let map_entry = self
|
||||||
.pending_retransmissions
|
.pending_retransmissions
|
||||||
@@ -145,7 +136,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn should_request_more_surbs(&self, target: &AnonymousSenderTag) -> bool {
|
fn should_request_more_surbs(&self, target: &AnonymousSenderTag) -> bool {
|
||||||
trace!("checking if we should request more surbs from {target}");
|
trace!("checking if we should request more surbs from {:?}", target);
|
||||||
|
|
||||||
let pending_queue_size = self
|
let pending_queue_size = self
|
||||||
.pending_replies
|
.pending_replies
|
||||||
@@ -161,6 +152,11 @@ where
|
|||||||
|
|
||||||
let total_queue = pending_queue_size + retransmission_queue;
|
let total_queue = pending_queue_size + retransmission_queue;
|
||||||
|
|
||||||
|
// simple as that - there's absolutely nothing to retransmit
|
||||||
|
if total_queue == 0 {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
let available_surbs = self
|
let available_surbs = self
|
||||||
.full_reply_storage
|
.full_reply_storage
|
||||||
.surbs_storage_ref()
|
.surbs_storage_ref()
|
||||||
@@ -177,27 +173,11 @@ where
|
|||||||
.full_reply_storage
|
.full_reply_storage
|
||||||
.surbs_storage_ref()
|
.surbs_storage_ref()
|
||||||
.max_surb_threshold();
|
.max_surb_threshold();
|
||||||
let min_surbs_threshold_buffer =
|
|
||||||
self.config.reply_surbs.minimum_reply_surb_threshold_buffer;
|
|
||||||
|
|
||||||
// After clearing the queue, we want to have at least `min_surbs_threshold` surbs available
|
debug!("total queue size: {total_queue} = pending data {pending_queue_size} + pending retransmission {retransmission_queue}, available surbs: {available_surbs} pending surbs: {pending_surbs} threshold range: {min_surbs_threshold}..{max_surbs_threshold}");
|
||||||
// and reserved for requesting additional surbs, and in addition to that we also want to
|
|
||||||
// have `min_surbs_threshold_buffer` surbs available proactively.
|
|
||||||
let target_surbs_after_clearing_queue = min_surbs_threshold + min_surbs_threshold_buffer;
|
|
||||||
|
|
||||||
// Check if we have enough surbs to handle the total queue and maintain minimum thresholds
|
(pending_surbs + available_surbs) < max_surbs_threshold
|
||||||
let total_required_surbs = total_queue + target_surbs_after_clearing_queue;
|
&& (pending_surbs + available_surbs) < (total_queue + min_surbs_threshold)
|
||||||
let total_available_surbs = pending_surbs + available_surbs;
|
|
||||||
|
|
||||||
debug!("total queue size: {total_queue} = pending data {pending_queue_size} + pending retransmission {retransmission_queue}, available surbs: {available_surbs} pending surbs: {pending_surbs} threshold range: {min_surbs_threshold}..+{min_surbs_threshold_buffer}..{max_surbs_threshold}");
|
|
||||||
|
|
||||||
// We should request more surbs if:
|
|
||||||
// 1. We haven't hit the maximum surb threshold, and
|
|
||||||
// 2. We don't have enough surbs to handle the queue plus minimum thresholds
|
|
||||||
let is_below_max_threshold = total_available_surbs < max_surbs_threshold;
|
|
||||||
let is_below_required_surbs = total_available_surbs < total_required_surbs;
|
|
||||||
|
|
||||||
is_below_max_threshold && is_below_required_surbs
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn handle_send_reply(
|
async fn handle_send_reply(
|
||||||
@@ -258,10 +238,6 @@ where
|
|||||||
&recipient_tag,
|
&recipient_tag,
|
||||||
);
|
);
|
||||||
warn!("failed to send reply to {recipient_tag}: {err}");
|
warn!("failed to send reply to {recipient_tag}: {err}");
|
||||||
info!(
|
|
||||||
"buffering {no_fragments} fragments for {recipient_tag}",
|
|
||||||
no_fragments = to_send.len()
|
|
||||||
);
|
|
||||||
self.insert_pending_replies(&recipient_tag, to_send, lane);
|
self.insert_pending_replies(&recipient_tag, to_send, lane);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -269,13 +245,6 @@ where
|
|||||||
|
|
||||||
// if there's leftover data we didn't send because we didn't have enough (or any) surbs - buffer it
|
// if there's leftover data we didn't send because we didn't have enough (or any) surbs - buffer it
|
||||||
if !fragments.is_empty() {
|
if !fragments.is_empty() {
|
||||||
// Ideally we should have enough surbs above the minimum threshold to handle sending
|
|
||||||
// new replies without having to first request more surbs. That's why I'd like to log
|
|
||||||
// these cases as they might indicate a problem with the surb management.
|
|
||||||
debug!(
|
|
||||||
"buffering {no_fragments} fragments for {recipient_tag}",
|
|
||||||
no_fragments = fragments.len()
|
|
||||||
);
|
|
||||||
self.insert_pending_replies(&recipient_tag, fragments, lane);
|
self.insert_pending_replies(&recipient_tag, fragments, lane);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -290,7 +259,6 @@ where
|
|||||||
target: AnonymousSenderTag,
|
target: AnonymousSenderTag,
|
||||||
amount: u32,
|
amount: u32,
|
||||||
) -> Result<(), PreparationError> {
|
) -> Result<(), PreparationError> {
|
||||||
debug!("requesting {amount} additional reply surbs for {target}");
|
|
||||||
let reply_surb = self
|
let reply_surb = self
|
||||||
.full_reply_storage
|
.full_reply_storage
|
||||||
.surbs_storage_ref()
|
.surbs_storage_ref()
|
||||||
@@ -712,7 +680,7 @@ where
|
|||||||
// it should take into consideration the average latency, sending rate and queue size.
|
// it should take into consideration the average latency, sending rate and queue size.
|
||||||
// it should request as many surbs as it takes to saturate its sending rate before next batch arrives
|
// it should request as many surbs as it takes to saturate its sending rate before next batch arrives
|
||||||
async fn request_reply_surbs_for_queue_clearing(&mut self, target: AnonymousSenderTag) {
|
async fn request_reply_surbs_for_queue_clearing(&mut self, target: AnonymousSenderTag) {
|
||||||
trace!("requesting surbs for queue clearing");
|
trace!("requesting surbs for queues clearing");
|
||||||
|
|
||||||
let pending_queue_size = self
|
let pending_queue_size = self
|
||||||
.pending_replies
|
.pending_replies
|
||||||
@@ -726,18 +694,17 @@ where
|
|||||||
.map(|pending_queue| pending_queue.len())
|
.map(|pending_queue| pending_queue.len())
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
|
||||||
let min_surbs_buffer = self.config.reply_surbs.minimum_reply_surb_threshold_buffer as u32;
|
|
||||||
|
|
||||||
let total_queue = (pending_queue_size + retransmission_queue) as u32;
|
let total_queue = (pending_queue_size + retransmission_queue) as u32;
|
||||||
|
|
||||||
// To proactively request additional surbs, we aim to have a buffer of extra surbs in our
|
if total_queue == 0 {
|
||||||
// storage.
|
trace!("the pending queues for {:?} are already empty", target);
|
||||||
let total_queue_with_buffer = total_queue + min_surbs_buffer;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let request_size = min(
|
let request_size = min(
|
||||||
self.config.reply_surbs.maximum_reply_surb_request_size,
|
self.config.reply_surbs.maximum_reply_surb_request_size,
|
||||||
max(
|
max(
|
||||||
total_queue_with_buffer,
|
total_queue,
|
||||||
self.config.reply_surbs.minimum_reply_surb_request_size,
|
self.config.reply_surbs.minimum_reply_surb_request_size,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -746,7 +713,7 @@ where
|
|||||||
.request_additional_reply_surbs(target, request_size)
|
.request_additional_reply_surbs(target, request_size)
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
info!("{err}")
|
warn!("failed to request additional surbs... - {err}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -879,11 +846,9 @@ where
|
|||||||
// todo!()
|
// todo!()
|
||||||
// }
|
// }
|
||||||
|
|
||||||
pub(crate) async fn run(&mut self) {
|
pub(crate) async fn run_with_shutdown(&mut self, mut shutdown: nym_task::TaskClient) {
|
||||||
debug!("Started ReplyController with graceful shutdown support");
|
debug!("Started ReplyController with graceful shutdown support");
|
||||||
|
|
||||||
let mut shutdown = self.task_client.fork("select");
|
|
||||||
|
|
||||||
let polling_rate = Duration::from_secs(5);
|
let polling_rate = Duration::from_secs(5);
|
||||||
let mut stale_inspection = new_interval_stream(polling_rate);
|
let mut stale_inspection = new_interval_stream(polling_rate);
|
||||||
|
|
||||||
@@ -895,7 +860,7 @@ where
|
|||||||
while !shutdown.is_shutdown() {
|
while !shutdown.is_shutdown() {
|
||||||
tokio::select! {
|
tokio::select! {
|
||||||
biased;
|
biased;
|
||||||
_ = shutdown.recv() => {
|
_ = shutdown.recv_with_delay() => {
|
||||||
log::trace!("ReplyController: Received shutdown");
|
log::trace!("ReplyController: Received shutdown");
|
||||||
},
|
},
|
||||||
req = self.request_receiver.next() => match req {
|
req = self.request_receiver.next() => match req {
|
||||||
|
|||||||
@@ -15,27 +15,6 @@ pub(crate) fn new_control_channels() -> (ReplyControllerSender, ReplyControllerR
|
|||||||
(tx.into(), rx)
|
(tx.into(), rx)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, thiserror::Error)]
|
|
||||||
pub enum ReplyControllerSenderError {
|
|
||||||
#[error("failed to send retransmission data to reply controller")]
|
|
||||||
SendRetransmissionData(#[source] mpsc::TrySendError<ReplyControllerMessage>),
|
|
||||||
|
|
||||||
#[error("failed to send reply to reply controller")]
|
|
||||||
SendReply(#[source] mpsc::TrySendError<ReplyControllerMessage>),
|
|
||||||
|
|
||||||
#[error("failed to send additional surbs to reply controller")]
|
|
||||||
AdditionalSurbs(#[source] mpsc::TrySendError<ReplyControllerMessage>),
|
|
||||||
|
|
||||||
#[error("failed to send additional surbs request to reply controller")]
|
|
||||||
AdditionalSurbsRequest(#[source] mpsc::TrySendError<ReplyControllerMessage>),
|
|
||||||
|
|
||||||
#[error("failed to request lane queue length from reply controller")]
|
|
||||||
LaneQueueLength(#[source] mpsc::TrySendError<ReplyControllerMessage>),
|
|
||||||
|
|
||||||
#[error("response channel was dropped before we could receive the response")]
|
|
||||||
ResponseChannelDropped(#[source] oneshot::Canceled),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct ReplyControllerSender(mpsc::UnboundedSender<ReplyControllerMessage>);
|
pub struct ReplyControllerSender(mpsc::UnboundedSender<ReplyControllerMessage>);
|
||||||
|
|
||||||
@@ -51,14 +30,14 @@ impl ReplyControllerSender {
|
|||||||
recipient: AnonymousSenderTag,
|
recipient: AnonymousSenderTag,
|
||||||
timed_out_ack: Weak<PendingAcknowledgement>,
|
timed_out_ack: Weak<PendingAcknowledgement>,
|
||||||
extra_surb_request: bool,
|
extra_surb_request: bool,
|
||||||
) -> Result<(), ReplyControllerSenderError> {
|
) {
|
||||||
self.0
|
self.0
|
||||||
.unbounded_send(ReplyControllerMessage::RetransmitReply {
|
.unbounded_send(ReplyControllerMessage::RetransmitReply {
|
||||||
recipient,
|
recipient,
|
||||||
timed_out_ack,
|
timed_out_ack,
|
||||||
extra_surb_request,
|
extra_surb_request,
|
||||||
})
|
})
|
||||||
.map_err(ReplyControllerSenderError::SendRetransmissionData)
|
.expect("ReplyControllerReceiver has died!")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn send_reply(
|
pub(crate) fn send_reply(
|
||||||
@@ -66,14 +45,14 @@ impl ReplyControllerSender {
|
|||||||
recipient: AnonymousSenderTag,
|
recipient: AnonymousSenderTag,
|
||||||
message: Vec<u8>,
|
message: Vec<u8>,
|
||||||
lane: TransmissionLane,
|
lane: TransmissionLane,
|
||||||
) -> Result<(), ReplyControllerSenderError> {
|
) {
|
||||||
self.0
|
self.0
|
||||||
.unbounded_send(ReplyControllerMessage::SendReply {
|
.unbounded_send(ReplyControllerMessage::SendReply {
|
||||||
recipient,
|
recipient,
|
||||||
message,
|
message,
|
||||||
lane,
|
lane,
|
||||||
})
|
})
|
||||||
.map_err(ReplyControllerSenderError::SendReply)
|
.expect("ReplyControllerReceiver has died!")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn send_additional_surbs(
|
pub(crate) fn send_additional_surbs(
|
||||||
@@ -81,47 +60,42 @@ impl ReplyControllerSender {
|
|||||||
sender_tag: AnonymousSenderTag,
|
sender_tag: AnonymousSenderTag,
|
||||||
reply_surbs: Vec<ReplySurb>,
|
reply_surbs: Vec<ReplySurb>,
|
||||||
from_surb_request: bool,
|
from_surb_request: bool,
|
||||||
) -> Result<(), ReplyControllerSenderError> {
|
) {
|
||||||
self.0
|
self.0
|
||||||
.unbounded_send(ReplyControllerMessage::AdditionalSurbs {
|
.unbounded_send(ReplyControllerMessage::AdditionalSurbs {
|
||||||
sender_tag,
|
sender_tag,
|
||||||
reply_surbs,
|
reply_surbs,
|
||||||
from_surb_request,
|
from_surb_request,
|
||||||
})
|
})
|
||||||
.map_err(ReplyControllerSenderError::AdditionalSurbs)
|
.expect("ReplyControllerReceiver has died!")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn send_additional_surbs_request(
|
pub(crate) fn send_additional_surbs_request(&self, recipient: Recipient, amount: u32) {
|
||||||
&self,
|
|
||||||
recipient: Recipient,
|
|
||||||
amount: u32,
|
|
||||||
) -> Result<(), ReplyControllerSenderError> {
|
|
||||||
self.0
|
self.0
|
||||||
.unbounded_send(ReplyControllerMessage::AdditionalSurbsRequest {
|
.unbounded_send(ReplyControllerMessage::AdditionalSurbsRequest {
|
||||||
recipient: Box::new(recipient),
|
recipient: Box::new(recipient),
|
||||||
amount,
|
amount,
|
||||||
})
|
})
|
||||||
.map_err(ReplyControllerSenderError::AdditionalSurbsRequest)
|
.expect("ReplyControllerReceiver has died!")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_lane_queue_length(
|
pub async fn get_lane_queue_length(&self, connection_id: ConnectionId) -> usize {
|
||||||
&self,
|
|
||||||
connection_id: ConnectionId,
|
|
||||||
) -> Result<usize, ReplyControllerSenderError> {
|
|
||||||
let (response_tx, response_rx) = oneshot::channel();
|
let (response_tx, response_rx) = oneshot::channel();
|
||||||
if let Err(err) = self
|
self.0
|
||||||
.0
|
|
||||||
.unbounded_send(ReplyControllerMessage::LaneQueueLength {
|
.unbounded_send(ReplyControllerMessage::LaneQueueLength {
|
||||||
connection_id,
|
connection_id,
|
||||||
response_channel: response_tx,
|
response_channel: response_tx,
|
||||||
})
|
})
|
||||||
{
|
.expect("ReplyControllerReceiver has died!");
|
||||||
return Err(ReplyControllerSenderError::LaneQueueLength(err));
|
|
||||||
}
|
|
||||||
|
|
||||||
response_rx
|
match response_rx.await {
|
||||||
.await
|
Ok(length) => length,
|
||||||
.map_err(ReplyControllerSenderError::ResponseChannelDropped)
|
Err(_) => {
|
||||||
|
error!("The reply controller has dropped our response channel!");
|
||||||
|
// TODO: should we panic here instead? this message implies something weird and unrecoverable has happened
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -136,10 +110,7 @@ impl ReplyQueueLengths {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_lane_queue_length(
|
pub async fn get_lane_queue_length(&self, connection_id: ConnectionId) -> usize {
|
||||||
&self,
|
|
||||||
connection_id: ConnectionId,
|
|
||||||
) -> Result<usize, ReplyControllerSenderError> {
|
|
||||||
self.reply_controller_sender
|
self.reply_controller_sender
|
||||||
.get_lane_queue_length(connection_id)
|
.get_lane_queue_length(connection_id)
|
||||||
.await
|
.await
|
||||||
@@ -149,7 +120,7 @@ impl ReplyQueueLengths {
|
|||||||
pub(crate) type ReplyControllerReceiver = mpsc::UnboundedReceiver<ReplyControllerMessage>;
|
pub(crate) type ReplyControllerReceiver = mpsc::UnboundedReceiver<ReplyControllerMessage>;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum ReplyControllerMessage {
|
pub(crate) enum ReplyControllerMessage {
|
||||||
RetransmitReply {
|
RetransmitReply {
|
||||||
recipient: AnonymousSenderTag,
|
recipient: AnonymousSenderTag,
|
||||||
timed_out_ack: Weak<PendingAcknowledgement>,
|
timed_out_ack: Weak<PendingAcknowledgement>,
|
||||||
|
|||||||
@@ -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, TaskClient};
|
use nym_task::connections::TransmissionLane;
|
||||||
use std::time::Duration;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
client::inbound_messages::{InputMessage, InputMessageSender},
|
client::inbound_messages::{InputMessage, InputMessageSender},
|
||||||
@@ -51,9 +51,6 @@ pub(crate) struct StatisticsControl {
|
|||||||
|
|
||||||
/// Config for stats reporting (enabled, address, interval)
|
/// Config for stats reporting (enabled, address, interval)
|
||||||
reporting_config: StatsReporting,
|
reporting_config: StatsReporting,
|
||||||
|
|
||||||
/// Task client for listening for shutdown
|
|
||||||
task_client: TaskClient,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl StatisticsControl {
|
impl StatisticsControl {
|
||||||
@@ -62,24 +59,19 @@ impl StatisticsControl {
|
|||||||
client_type: String,
|
client_type: String,
|
||||||
client_stats_id: String,
|
client_stats_id: String,
|
||||||
report_tx: InputMessageSender,
|
report_tx: InputMessageSender,
|
||||||
task_client: TaskClient,
|
|
||||||
) -> (Self, ClientStatsSender) {
|
) -> (Self, ClientStatsSender) {
|
||||||
let (stats_tx, stats_rx) = tokio::sync::mpsc::unbounded_channel();
|
let (stats_tx, stats_rx) = tokio::sync::mpsc::unbounded_channel();
|
||||||
|
|
||||||
let stats = ClientStatsController::new(client_stats_id, client_type);
|
let stats = ClientStatsController::new(client_stats_id, client_type);
|
||||||
|
|
||||||
let mut task_client_stats_sender = task_client.fork("stats_sender");
|
|
||||||
task_client_stats_sender.disarm();
|
|
||||||
|
|
||||||
(
|
(
|
||||||
StatisticsControl {
|
StatisticsControl {
|
||||||
stats,
|
stats,
|
||||||
stats_rx,
|
stats_rx,
|
||||||
report_tx,
|
report_tx,
|
||||||
reporting_config,
|
reporting_config,
|
||||||
task_client,
|
|
||||||
},
|
},
|
||||||
ClientStatsSender::new(Some(stats_tx), task_client_stats_sender),
|
ClientStatsSender::new(Some(stats_tx)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,43 +91,16 @@ impl StatisticsControl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn run(&mut self) {
|
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"))]
|
loop {
|
||||||
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);
|
|
||||||
|
|
||||||
while !self.task_client.is_shutdown() {
|
|
||||||
tokio::select! {
|
tokio::select! {
|
||||||
biased;
|
|
||||||
_ = self.task_client.recv() => {
|
|
||||||
log::trace!("StatisticsControl: Received shutdown");
|
|
||||||
break;
|
|
||||||
},
|
|
||||||
stats_event = self.stats_rx.recv() => match stats_event {
|
stats_event = self.stats_rx.recv() => match stats_event {
|
||||||
Some(stats_event) => self.stats.handle_event(stats_event),
|
Some(stats_event) => self.stats.handle_event(stats_event),
|
||||||
None => {
|
None => {
|
||||||
@@ -143,48 +108,44 @@ 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 self.task_client);
|
self.stats.local_report(&mut task_client);
|
||||||
}
|
}
|
||||||
|
_ = task_client.recv_with_delay() => {
|
||||||
|
log::trace!("StatisticsControl: Received shutdown");
|
||||||
|
break;
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
task_client.recv_timeout().await;
|
||||||
log::debug!("StatisticsControl: Exiting");
|
log::debug!("StatisticsControl: Exiting");
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn start(mut self) {
|
pub(crate) fn start_with_shutdown(mut self, task_client: nym_task::TaskClient) {
|
||||||
spawn_future(async move {
|
spawn_future(async move {
|
||||||
self.run().await;
|
self.run_with_shutdown(task_client).await;
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn create_and_start(
|
pub(crate) fn create_and_start_with_shutdown(
|
||||||
reporting_config: StatsReporting,
|
reporting_config: StatsReporting,
|
||||||
client_type: String,
|
client_type: String,
|
||||||
client_stats_id: String,
|
client_stats_id: String,
|
||||||
report_tx: InputMessageSender,
|
report_tx: InputMessageSender,
|
||||||
task_client: TaskClient,
|
task_client: nym_task::TaskClient,
|
||||||
) -> ClientStatsSender {
|
) -> ClientStatsSender {
|
||||||
let (controller, sender) = Self::create(
|
let (controller, sender) =
|
||||||
reporting_config,
|
Self::create(reporting_config, client_type, client_stats_id, report_tx);
|
||||||
client_type,
|
controller.start_with_shutdown(task_client);
|
||||||
client_stats_id,
|
|
||||||
report_tx,
|
|
||||||
task_client,
|
|
||||||
);
|
|
||||||
controller.start();
|
|
||||||
sender
|
sender
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ pub(crate) use accessor::{TopologyAccessor, TopologyReadPermit};
|
|||||||
use futures::StreamExt;
|
use futures::StreamExt;
|
||||||
use log::*;
|
use log::*;
|
||||||
use nym_sphinx::addressing::nodes::NodeIdentity;
|
use nym_sphinx::addressing::nodes::NodeIdentity;
|
||||||
use nym_task::TaskClient;
|
|
||||||
use nym_topology::NymTopologyError;
|
use nym_topology::NymTopologyError;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
@@ -44,8 +43,6 @@ pub struct TopologyRefresher {
|
|||||||
|
|
||||||
refresh_rate: Duration,
|
refresh_rate: Duration,
|
||||||
consecutive_failure_count: usize,
|
consecutive_failure_count: usize,
|
||||||
|
|
||||||
task_client: TaskClient,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TopologyRefresher {
|
impl TopologyRefresher {
|
||||||
@@ -53,14 +50,12 @@ impl TopologyRefresher {
|
|||||||
cfg: TopologyRefresherConfig,
|
cfg: TopologyRefresherConfig,
|
||||||
topology_accessor: TopologyAccessor,
|
topology_accessor: TopologyAccessor,
|
||||||
topology_provider: Box<dyn TopologyProvider + Send + Sync>,
|
topology_provider: Box<dyn TopologyProvider + Send + Sync>,
|
||||||
task_client: TaskClient,
|
|
||||||
) -> Self {
|
) -> Self {
|
||||||
TopologyRefresher {
|
TopologyRefresher {
|
||||||
topology_provider,
|
topology_provider,
|
||||||
topology_accessor,
|
topology_accessor,
|
||||||
refresh_rate: cfg.refresh_rate,
|
refresh_rate: cfg.refresh_rate,
|
||||||
consecutive_failure_count: 0,
|
consecutive_failure_count: 0,
|
||||||
task_client,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -147,7 +142,7 @@ impl TopologyRefresher {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn start(mut self) {
|
pub fn start_with_shutdown(mut self, mut shutdown: nym_task::TaskClient) {
|
||||||
spawn_future(async move {
|
spawn_future(async move {
|
||||||
debug!("Started TopologyRefresher with graceful shutdown support");
|
debug!("Started TopologyRefresher with graceful shutdown support");
|
||||||
|
|
||||||
@@ -160,17 +155,17 @@ impl TopologyRefresher {
|
|||||||
let mut interval =
|
let mut interval =
|
||||||
gloo_timers::future::IntervalStream::new(self.refresh_rate.as_millis() as u32);
|
gloo_timers::future::IntervalStream::new(self.refresh_rate.as_millis() as u32);
|
||||||
|
|
||||||
while !self.task_client.is_shutdown() {
|
while !shutdown.is_shutdown() {
|
||||||
tokio::select! {
|
tokio::select! {
|
||||||
_ = interval.next() => {
|
_ = interval.next() => {
|
||||||
self.try_refresh().await;
|
self.try_refresh().await;
|
||||||
},
|
},
|
||||||
_ = self.task_client.recv() => {
|
_ = shutdown.recv() => {
|
||||||
log::trace!("TopologyRefresher: Received shutdown");
|
log::trace!("TopologyRefresher: Received shutdown");
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.task_client.recv_timeout().await;
|
shutdown.recv_timeout().await;
|
||||||
log::debug!("TopologyRefresher: Exiting");
|
log::debug!("TopologyRefresher: Exiting");
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,8 +58,8 @@ impl<T> TransmissionBuffer<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
pub(crate) fn lanes(&self) -> Vec<TransmissionLane> {
|
pub(crate) fn num_lanes(&self) -> usize {
|
||||||
self.buffer.keys().cloned().collect()
|
self.buffer.keys().count()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn lane_length(&self, lane: &TransmissionLane) -> Option<usize> {
|
pub(crate) fn lane_length(&self, lane: &TransmissionLane) -> Option<usize> {
|
||||||
@@ -83,7 +83,6 @@ impl<T> TransmissionBuffer<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
#[allow(unused)]
|
|
||||||
pub(crate) fn total_size_in_bytes(&self) -> usize
|
pub(crate) fn total_size_in_bytes(&self) -> usize
|
||||||
where
|
where
|
||||||
T: SizedData,
|
T: SizedData,
|
||||||
|
|||||||
@@ -36,13 +36,6 @@ pub enum ClientCoreError {
|
|||||||
#[error("no gateway with id: {0}")]
|
#[error("no gateway with id: {0}")]
|
||||||
NoGatewayWithId(String),
|
NoGatewayWithId(String),
|
||||||
|
|
||||||
#[error("Invalid URL: {0}")]
|
|
||||||
InvalidUrl(String),
|
|
||||||
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
|
||||||
#[error("resolution failed: {0}")]
|
|
||||||
ResolutionFailed(#[from] nym_http_api_client::HickoryDnsError),
|
|
||||||
|
|
||||||
#[error("no gateways on network")]
|
#[error("no gateways on network")]
|
||||||
NoGatewaysOnNetwork,
|
NoGatewaysOnNetwork,
|
||||||
|
|
||||||
@@ -103,9 +96,6 @@ pub enum ClientCoreError {
|
|||||||
#[error("timed out while trying to establish gateway connection")]
|
#[error("timed out while trying to establish gateway connection")]
|
||||||
GatewayConnectionTimeout,
|
GatewayConnectionTimeout,
|
||||||
|
|
||||||
#[error("failed to forward mix messages to gateway")]
|
|
||||||
GatewayFailedToForwardMessages,
|
|
||||||
|
|
||||||
#[error("no ping measurements for the gateway ({identity}) performed")]
|
#[error("no ping measurements for the gateway ({identity}) performed")]
|
||||||
NoGatewayMeasurements { identity: String },
|
NoGatewayMeasurements { identity: String },
|
||||||
|
|
||||||
@@ -222,9 +212,6 @@ pub enum ClientCoreError {
|
|||||||
"fresh registration with gateway {gateway_id} somehow requires an additional key upgrade!"
|
"fresh registration with gateway {gateway_id} somehow requires an additional key upgrade!"
|
||||||
)]
|
)]
|
||||||
UnexpectedKeyUpgrade { gateway_id: String },
|
UnexpectedKeyUpgrade { gateway_id: String },
|
||||||
|
|
||||||
#[error("failed to derive keys from master key")]
|
|
||||||
HkdfDerivationError {},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set of messages that the client can send to listeners via the task manager
|
/// Set of messages that the client can send to listeners via the task manager
|
||||||
|
|||||||
@@ -15,9 +15,6 @@ use std::{sync::Arc, time::Duration};
|
|||||||
use tungstenite::Message;
|
use tungstenite::Message;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
|
||||||
use crate::init::websockets::connect_async;
|
|
||||||
|
|
||||||
use nym_topology::NodeId;
|
use nym_topology::NodeId;
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
use tokio::net::TcpStream;
|
use tokio::net::TcpStream;
|
||||||
@@ -26,6 +23,8 @@ use tokio::time::sleep;
|
|||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
use tokio::time::Instant;
|
use tokio::time::Instant;
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
use tokio_tungstenite::connect_async;
|
||||||
|
#[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;
|
||||||
@@ -87,12 +86,11 @@ impl<'a, G: ConnectableGateway> GatewayWithLatency<'a, G> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn gateways_for_init<R: Rng>(
|
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,
|
minimum_performance: u8,
|
||||||
ignore_epoch_roles: bool,
|
|
||||||
) -> Result<Vec<RoutingNode>, ClientCoreError> {
|
) -> Result<Vec<RoutingNode>, ClientCoreError> {
|
||||||
let nym_api = nym_apis
|
let nym_api = nym_apis
|
||||||
.choose(rng)
|
.choose(rng)
|
||||||
@@ -110,11 +108,8 @@ pub async fn gateways_for_init<R: Rng>(
|
|||||||
|
|
||||||
log::trace!("Gateways: {:#?}", gateways);
|
log::trace!("Gateways: {:#?}", gateways);
|
||||||
|
|
||||||
// filter out gateways below minimum performance and ones that could operate as a mixnode
|
|
||||||
// (we don't want instability)
|
|
||||||
let valid_gateways = gateways
|
let valid_gateways = gateways
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|g| ignore_epoch_roles || !g.supported_roles.mixnode)
|
|
||||||
.filter(|g| g.performance.round_to_integer() >= minimum_performance)
|
.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<_>>();
|
||||||
@@ -133,7 +128,7 @@ pub async fn gateways_for_init<R: Rng>(
|
|||||||
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 {
|
||||||
Err(_elapsed) => Err(ClientCoreError::GatewayConnectionTimeout),
|
Err(_elapsed) => Err(ClientCoreError::GatewayConnectionTimeout),
|
||||||
Ok(Err(conn_failure)) => Err(conn_failure),
|
Ok(Err(conn_failure)) => Err(conn_failure.into()),
|
||||||
Ok(Ok((stream, _))) => Ok(stream),
|
Ok(Ok((stream, _))) => Ok(stream),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,8 +26,6 @@ use serde::Serialize;
|
|||||||
|
|
||||||
pub mod helpers;
|
pub mod helpers;
|
||||||
pub mod types;
|
pub mod types;
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
|
||||||
pub(crate) mod websockets;
|
|
||||||
|
|
||||||
// helpers for error wrapping
|
// helpers for error wrapping
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ use nym_topology::node::RoutingNode;
|
|||||||
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;
|
||||||
@@ -221,34 +221,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 {
|
||||||
|
|||||||
@@ -1,44 +0,0 @@
|
|||||||
use crate::error::ClientCoreError;
|
|
||||||
|
|
||||||
use nym_http_api_client::HickoryDnsResolver;
|
|
||||||
use tokio::net::TcpStream;
|
|
||||||
use tokio_tungstenite::{MaybeTlsStream, WebSocketStream};
|
|
||||||
use tungstenite::handshake::client::Response;
|
|
||||||
use url::{Host, Url};
|
|
||||||
|
|
||||||
use std::net::SocketAddr;
|
|
||||||
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
|
||||||
pub(crate) async fn connect_async(
|
|
||||||
endpoint: &str,
|
|
||||||
) -> Result<(WebSocketStream<MaybeTlsStream<TcpStream>>, Response), ClientCoreError> {
|
|
||||||
let resolver = HickoryDnsResolver::default();
|
|
||||||
let uri = Url::parse(endpoint).map_err(|_| ClientCoreError::InvalidUrl(endpoint.to_owned()))?;
|
|
||||||
let port: u16 = uri.port_or_known_default().unwrap_or(443);
|
|
||||||
|
|
||||||
let host = uri
|
|
||||||
.host()
|
|
||||||
.ok_or(ClientCoreError::InvalidUrl(endpoint.to_owned()))?;
|
|
||||||
|
|
||||||
// Get address for tcp connection, if a domain is provided use our preferred resolver rather than
|
|
||||||
// the default std resolve
|
|
||||||
let sock_addrs: Vec<SocketAddr> = match host {
|
|
||||||
Host::Ipv4(addr) => vec![SocketAddr::new(addr.into(), port)],
|
|
||||||
Host::Ipv6(addr) => vec![SocketAddr::new(addr.into(), port)],
|
|
||||||
Host::Domain(domain) => {
|
|
||||||
// Do a DNS lookup for the domain using our custom DNS resolver
|
|
||||||
resolver
|
|
||||||
.resolve_str(domain)
|
|
||||||
.await?
|
|
||||||
.into_iter()
|
|
||||||
.map(|a| SocketAddr::new(a, port))
|
|
||||||
.collect()
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let stream = TcpStream::connect(&sock_addrs[..]).await?;
|
|
||||||
|
|
||||||
tokio_tungstenite::client_async_tls(endpoint, stream)
|
|
||||||
.await
|
|
||||||
.map_err(Into::into)
|
|
||||||
}
|
|
||||||
@@ -33,3 +33,48 @@ 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ mod error;
|
|||||||
mod manager;
|
mod manager;
|
||||||
mod models;
|
mod models;
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Backend {
|
pub struct Backend {
|
||||||
temporary_old_path: Option<PathBuf>,
|
temporary_old_path: Option<PathBuf>,
|
||||||
database_path: PathBuf,
|
database_path: PathBuf,
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ pub mod fs_backend;
|
|||||||
#[error("no information provided")]
|
#[error("no information provided")]
|
||||||
pub struct UndefinedError;
|
pub struct UndefinedError;
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Empty {
|
pub struct Empty {
|
||||||
// we need to keep 'basic' metadata here to "load" the CombinedReplyStorage
|
// we need to keep 'basic' metadata here to "load" the CombinedReplyStorage
|
||||||
pub min_surb_threshold: usize,
|
pub min_surb_threshold: usize,
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ nym-credential-storage = { path = "../../credential-storage" }
|
|||||||
nym-credentials-interface = { path = "../../credentials-interface" }
|
nym-credentials-interface = { path = "../../credentials-interface" }
|
||||||
nym-crypto = { path = "../../crypto" }
|
nym-crypto = { path = "../../crypto" }
|
||||||
nym-gateway-requests = { path = "../../gateway-requests" }
|
nym-gateway-requests = { path = "../../gateway-requests" }
|
||||||
nym-http-api-client = { path = "../../http-api-client" }
|
|
||||||
nym-network-defaults = { path = "../../network-defaults" }
|
nym-network-defaults = { path = "../../network-defaults" }
|
||||||
nym-sphinx = { path = "../../nymsphinx" }
|
nym-sphinx = { path = "../../nymsphinx" }
|
||||||
nym-statistics-common = { path = "../../statistics" }
|
nym-statistics-common = { path = "../../statistics" }
|
||||||
|
|||||||
@@ -20,8 +20,8 @@ use nym_credentials_interface::TicketType;
|
|||||||
use nym_crypto::asymmetric::identity;
|
use nym_crypto::asymmetric::identity;
|
||||||
use nym_gateway_requests::registration::handshake::client_handshake;
|
use nym_gateway_requests::registration::handshake::client_handshake;
|
||||||
use nym_gateway_requests::{
|
use nym_gateway_requests::{
|
||||||
BinaryRequest, ClientControlRequest, ClientRequest, GatewayProtocolVersionExt,
|
BinaryRequest, ClientControlRequest, ClientRequest, SensitiveServerResponse, ServerResponse,
|
||||||
SensitiveServerResponse, ServerResponse, SharedGatewayKey, SharedSymmetricKey,
|
SharedGatewayKey, SharedSymmetricKey, AES_GCM_SIV_PROTOCOL_VERSION,
|
||||||
CREDENTIAL_UPDATE_V2_PROTOCOL_VERSION, CURRENT_PROTOCOL_VERSION,
|
CREDENTIAL_UPDATE_V2_PROTOCOL_VERSION, CURRENT_PROTOCOL_VERSION,
|
||||||
};
|
};
|
||||||
use nym_sphinx::forwarding::packet::MixPacket;
|
use nym_sphinx::forwarding::packet::MixPacket;
|
||||||
@@ -40,6 +40,8 @@ use url::Url;
|
|||||||
use std::os::fd::RawFd;
|
use std::os::fd::RawFd;
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
use tokio::time::sleep;
|
use tokio::time::sleep;
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
use tokio_tungstenite::connect_async;
|
||||||
|
|
||||||
#[cfg(not(unix))]
|
#[cfg(not(unix))]
|
||||||
use std::os::raw::c_int as RawFd;
|
use std::os::raw::c_int as RawFd;
|
||||||
@@ -51,11 +53,6 @@ use zeroize::Zeroizing;
|
|||||||
|
|
||||||
pub mod config;
|
pub mod config;
|
||||||
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
|
||||||
pub(crate) mod websockets;
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
|
||||||
use websockets::connect_async;
|
|
||||||
|
|
||||||
pub struct GatewayConfig {
|
pub struct GatewayConfig {
|
||||||
pub gateway_identity: identity::PublicKey,
|
pub gateway_identity: identity::PublicKey,
|
||||||
|
|
||||||
@@ -204,15 +201,23 @@ impl<C, St> GatewayClient<C, St> {
|
|||||||
"Attemting to establish connection to gateway at: {}",
|
"Attemting to establish connection to gateway at: {}",
|
||||||
self.gateway_address
|
self.gateway_address
|
||||||
);
|
);
|
||||||
let (ws_stream, _) = connect_async(
|
let ws_stream = match connect_async(&self.gateway_address).await {
|
||||||
&self.gateway_address,
|
Ok((ws_stream, _)) => ws_stream,
|
||||||
#[cfg(unix)]
|
Err(error) => {
|
||||||
self.connection_fd_callback.clone(),
|
return Err(GatewayClientError::NetworkConnectionFailed {
|
||||||
)
|
address: self.gateway_address.clone(),
|
||||||
.await?;
|
source: error,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
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(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -266,19 +271,6 @@ impl<C, St> GatewayClient<C, St> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn send_client_request(
|
|
||||||
&mut self,
|
|
||||||
message: ClientRequest,
|
|
||||||
) -> Result<(), GatewayClientError> {
|
|
||||||
if let Some(shared_key) = self.shared_key() {
|
|
||||||
let encrypted = message.encrypt(&*shared_key)?;
|
|
||||||
Box::pin(self.send_websocket_message(encrypted)).await?;
|
|
||||||
Ok(())
|
|
||||||
} else {
|
|
||||||
Err(GatewayClientError::ConnectionInInvalidState)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn read_control_response(&mut self) -> Result<ServerResponse, GatewayClientError> {
|
async fn read_control_response(&mut self) -> Result<ServerResponse, GatewayClientError> {
|
||||||
// we use the fact that all request responses are Message::Text and only pushed
|
// we use the fact that all request responses are Message::Text and only pushed
|
||||||
// sphinx packets are Message::Binary
|
// sphinx packets are Message::Binary
|
||||||
@@ -563,10 +555,28 @@ impl<C, St> GatewayClient<C, St> {
|
|||||||
Ok(zeroizing_updated_key)
|
Ok(zeroizing_updated_key)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn send_authenticate_request_and_handle_response(
|
async fn authenticate(&mut self) -> Result<(), GatewayClientError> {
|
||||||
&mut self,
|
let Some(shared_key) = self.shared_key.as_ref() else {
|
||||||
msg: ClientControlRequest,
|
return Err(GatewayClientError::NoSharedKeyAvailable);
|
||||||
) -> Result<(), GatewayClientError> {
|
};
|
||||||
|
|
||||||
|
if !self.connection.is_established() {
|
||||||
|
return Err(GatewayClientError::ConnectionNotEstablished);
|
||||||
|
}
|
||||||
|
debug!("authenticating with gateway");
|
||||||
|
|
||||||
|
let self_address = self
|
||||||
|
.local_identity
|
||||||
|
.as_ref()
|
||||||
|
.public_key()
|
||||||
|
.derive_destination_address();
|
||||||
|
|
||||||
|
let msg = ClientControlRequest::new_authenticate(
|
||||||
|
self_address,
|
||||||
|
shared_key,
|
||||||
|
self.cfg.bandwidth.require_tickets,
|
||||||
|
)?;
|
||||||
|
|
||||||
match self.send_websocket_message(msg).await? {
|
match self.send_websocket_message(msg).await? {
|
||||||
ServerResponse::Authenticate {
|
ServerResponse::Authenticate {
|
||||||
protocol_version,
|
protocol_version,
|
||||||
@@ -590,51 +600,6 @@ impl<C, St> GatewayClient<C, St> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn authenticate_v1(&mut self) -> Result<(), GatewayClientError> {
|
|
||||||
debug!("using v1 authentication");
|
|
||||||
|
|
||||||
let Some(shared_key) = self.shared_key.as_ref() else {
|
|
||||||
return Err(GatewayClientError::NoSharedKeyAvailable);
|
|
||||||
};
|
|
||||||
|
|
||||||
let self_address = self
|
|
||||||
.local_identity
|
|
||||||
.public_key()
|
|
||||||
.derive_destination_address();
|
|
||||||
|
|
||||||
let msg = ClientControlRequest::new_authenticate(
|
|
||||||
self_address,
|
|
||||||
shared_key,
|
|
||||||
self.cfg.bandwidth.require_tickets,
|
|
||||||
)?;
|
|
||||||
self.send_authenticate_request_and_handle_response(msg)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn authenticate_v2(&mut self) -> Result<(), GatewayClientError> {
|
|
||||||
debug!("using v2 authentication");
|
|
||||||
let Some(shared_key) = self.shared_key.as_ref() else {
|
|
||||||
return Err(GatewayClientError::NoSharedKeyAvailable);
|
|
||||||
};
|
|
||||||
|
|
||||||
let msg = ClientControlRequest::new_authenticate_v2(shared_key, &self.local_identity)?;
|
|
||||||
self.send_authenticate_request_and_handle_response(msg)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn authenticate(&mut self, use_v2: bool) -> Result<(), GatewayClientError> {
|
|
||||||
if !self.connection.is_established() {
|
|
||||||
return Err(GatewayClientError::ConnectionNotEstablished);
|
|
||||||
}
|
|
||||||
debug!("authenticating with gateway");
|
|
||||||
|
|
||||||
if use_v2 {
|
|
||||||
self.authenticate_v2().await
|
|
||||||
} else {
|
|
||||||
self.authenticate_v1().await
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Helper method to either call register or authenticate based on self.shared_key value
|
/// Helper method to either call register or authenticate based on self.shared_key value
|
||||||
#[instrument(skip_all,
|
#[instrument(skip_all,
|
||||||
fields(
|
fields(
|
||||||
@@ -650,25 +615,19 @@ impl<C, St> GatewayClient<C, St> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 1. check gateway's protocol version
|
// 1. check gateway's protocol version
|
||||||
let gw_protocol = match self.get_gateway_protocol().await {
|
let supports_aes_gcm_siv = match self.get_gateway_protocol().await {
|
||||||
Ok(protocol) => Some(protocol),
|
Ok(protocol) => protocol >= AES_GCM_SIV_PROTOCOL_VERSION,
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
// if we failed to send the request, it means the gateway is running the old binary,
|
// if we failed to send the request, it means the gateway is running the old binary,
|
||||||
// so it has reset our connection - we have to reconnect
|
// so it has reset our connection - we have to reconnect
|
||||||
self.establish_connection().await?;
|
self.establish_connection().await?;
|
||||||
None
|
false
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let supports_aes_gcm_siv = gw_protocol.supports_aes256_gcm_siv();
|
|
||||||
let supports_auth_v2 = gw_protocol.supports_authenticate_v2();
|
|
||||||
|
|
||||||
if !supports_aes_gcm_siv {
|
if !supports_aes_gcm_siv {
|
||||||
warn!("this gateway is on an old version that doesn't support AES256-GCM-SIV");
|
warn!("this gateway is on an old version that doesn't support AES256-GCM-SIV");
|
||||||
}
|
}
|
||||||
if !supports_auth_v2 {
|
|
||||||
warn!("this gateway is on an old version that doesn't support authentication v2")
|
|
||||||
}
|
|
||||||
|
|
||||||
if self.authenticated {
|
if self.authenticated {
|
||||||
debug!("Already authenticated");
|
debug!("Already authenticated");
|
||||||
@@ -683,7 +642,7 @@ impl<C, St> GatewayClient<C, St> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if self.shared_key.is_some() {
|
if self.shared_key.is_some() {
|
||||||
self.authenticate(supports_auth_v2).await?;
|
self.authenticate().await?;
|
||||||
|
|
||||||
if self.authenticated {
|
if self.authenticated {
|
||||||
// if we are authenticated it means we MUST have an associated shared_key
|
// if we are authenticated it means we MUST have an associated shared_key
|
||||||
@@ -1016,8 +975,7 @@ impl<C, St> GatewayClient<C, St> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// if we're reconnecting, because we lost connection, we need to re-authenticate the connection
|
// if we're reconnecting, because we lost connection, we need to re-authenticate the connection
|
||||||
self.authenticate(self.negotiated_protocol.supports_authenticate_v2())
|
self.authenticate().await?;
|
||||||
.await?;
|
|
||||||
|
|
||||||
// this call is NON-blocking
|
// this call is NON-blocking
|
||||||
self.start_listening_for_mixnet_messages()?;
|
self.start_listening_for_mixnet_messages()?;
|
||||||
@@ -1087,7 +1045,7 @@ impl GatewayClient<InitOnly, EphemeralCredentialStorage> {
|
|||||||
connection: SocketState::NotConnected,
|
connection: SocketState::NotConnected,
|
||||||
packet_router,
|
packet_router,
|
||||||
bandwidth_controller: None,
|
bandwidth_controller: None,
|
||||||
stats_reporter: ClientStatsSender::new(None, task_client.clone()),
|
stats_reporter: ClientStatsSender::new(None),
|
||||||
negotiated_protocol: None,
|
negotiated_protocol: None,
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
connection_fd_callback: None,
|
connection_fd_callback: None,
|
||||||
|
|||||||
@@ -1,88 +0,0 @@
|
|||||||
use crate::error::GatewayClientError;
|
|
||||||
|
|
||||||
use nym_http_api_client::HickoryDnsResolver;
|
|
||||||
#[cfg(unix)]
|
|
||||||
use std::{
|
|
||||||
os::fd::{AsRawFd, RawFd},
|
|
||||||
sync::Arc,
|
|
||||||
};
|
|
||||||
use tokio::net::TcpStream;
|
|
||||||
use tokio_tungstenite::{MaybeTlsStream, WebSocketStream};
|
|
||||||
use tungstenite::handshake::client::Response;
|
|
||||||
use url::{Host, Url};
|
|
||||||
|
|
||||||
use std::net::SocketAddr;
|
|
||||||
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
|
||||||
pub(crate) async fn connect_async(
|
|
||||||
endpoint: &str,
|
|
||||||
#[cfg(unix)] connection_fd_callback: Option<Arc<dyn Fn(RawFd) + Send + Sync>>,
|
|
||||||
) -> Result<(WebSocketStream<MaybeTlsStream<TcpStream>>, Response), GatewayClientError> {
|
|
||||||
use tokio::net::TcpSocket;
|
|
||||||
|
|
||||||
let resolver = HickoryDnsResolver::default();
|
|
||||||
let uri =
|
|
||||||
Url::parse(endpoint).map_err(|_| GatewayClientError::InvalidUrl(endpoint.to_owned()))?;
|
|
||||||
let port: u16 = uri.port_or_known_default().unwrap_or(443);
|
|
||||||
|
|
||||||
let host = uri
|
|
||||||
.host()
|
|
||||||
.ok_or(GatewayClientError::InvalidUrl(endpoint.to_owned()))?;
|
|
||||||
|
|
||||||
// Get address for tcp connection, if a domain is provided use our preferred resolver rather than
|
|
||||||
// the default std resolve
|
|
||||||
let sock_addrs: Vec<SocketAddr> = match host {
|
|
||||||
Host::Ipv4(addr) => vec![SocketAddr::new(addr.into(), port)],
|
|
||||||
Host::Ipv6(addr) => vec![SocketAddr::new(addr.into(), port)],
|
|
||||||
Host::Domain(domain) => {
|
|
||||||
// Do a DNS lookup for the domain using our custom DNS resolver
|
|
||||||
resolver
|
|
||||||
.resolve_str(domain)
|
|
||||||
.await?
|
|
||||||
.into_iter()
|
|
||||||
.map(|a| SocketAddr::new(a, port))
|
|
||||||
.collect()
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut stream = Err(GatewayClientError::NoEndpointForConnection {
|
|
||||||
address: endpoint.to_owned(),
|
|
||||||
});
|
|
||||||
for sock_addr in sock_addrs {
|
|
||||||
let socket = if sock_addr.is_ipv4() {
|
|
||||||
TcpSocket::new_v4()
|
|
||||||
} else {
|
|
||||||
TcpSocket::new_v6()
|
|
||||||
}
|
|
||||||
.map_err(|err| GatewayClientError::NetworkConnectionFailed {
|
|
||||||
address: endpoint.to_owned(),
|
|
||||||
source: err.into(),
|
|
||||||
})?;
|
|
||||||
|
|
||||||
#[cfg(unix)]
|
|
||||||
if let Some(callback) = connection_fd_callback.as_ref() {
|
|
||||||
callback.as_ref()(socket.as_raw_fd());
|
|
||||||
}
|
|
||||||
|
|
||||||
match socket.connect(sock_addr).await {
|
|
||||||
Ok(s) => {
|
|
||||||
stream = Ok(s);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
Err(err) => {
|
|
||||||
stream = Err(GatewayClientError::NetworkConnectionFailed {
|
|
||||||
address: endpoint.to_owned(),
|
|
||||||
source: err.into(),
|
|
||||||
});
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tokio_tungstenite::client_async_tls(endpoint, stream?)
|
|
||||||
.await
|
|
||||||
.map_err(|error| GatewayClientError::NetworkConnectionFailed {
|
|
||||||
address: endpoint.to_owned(),
|
|
||||||
source: error,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@@ -43,15 +43,8 @@ pub enum GatewayClientError {
|
|||||||
#[error("connection failed: {address}: {source}")]
|
#[error("connection failed: {address}: {source}")]
|
||||||
NetworkConnectionFailed { address: String, source: WsError },
|
NetworkConnectionFailed { address: String, source: WsError },
|
||||||
|
|
||||||
#[error("no socket address for endpoint: {address}")]
|
|
||||||
NoEndpointForConnection { address: String },
|
|
||||||
|
|
||||||
#[error("Invalid URL: {0}")]
|
#[error("Invalid URL: {0}")]
|
||||||
InvalidUrl(String),
|
InvalidURL(String),
|
||||||
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
|
||||||
#[error("resolution failed: {0}")]
|
|
||||||
ResolutionFailed(#[from] nym_http_api_client::HickoryDnsError),
|
|
||||||
|
|
||||||
#[error("No shared key was provided or obtained")]
|
#[error("No shared key was provided or obtained")]
|
||||||
NoSharedKeyAvailable,
|
NoSharedKeyAvailable,
|
||||||
|
|||||||
@@ -11,24 +11,23 @@ use crate::{
|
|||||||
use nym_api_requests::ecash::models::{
|
use nym_api_requests::ecash::models::{
|
||||||
AggregatedCoinIndicesSignatureResponse, AggregatedExpirationDateSignatureResponse,
|
AggregatedCoinIndicesSignatureResponse, AggregatedExpirationDateSignatureResponse,
|
||||||
BatchRedeemTicketsBody, EcashBatchTicketRedemptionResponse, EcashTicketVerificationResponse,
|
BatchRedeemTicketsBody, EcashBatchTicketRedemptionResponse, EcashTicketVerificationResponse,
|
||||||
IssuedTicketbooksChallengeResponse, IssuedTicketbooksForResponse, VerifyEcashTicketBody,
|
IssuedTicketbooksChallengeResponse, IssuedTicketbooksForResponse, SpentCredentialsResponse,
|
||||||
|
VerifyEcashTicketBody,
|
||||||
};
|
};
|
||||||
use nym_api_requests::ecash::{
|
use nym_api_requests::ecash::{
|
||||||
BlindSignRequestBody, BlindedSignatureResponse, PartialCoinIndicesSignatureResponse,
|
BlindSignRequestBody, BlindedSignatureResponse, PartialCoinIndicesSignatureResponse,
|
||||||
PartialExpirationDateSignatureResponse, VerificationKeyResponse,
|
PartialExpirationDateSignatureResponse, VerificationKeyResponse,
|
||||||
};
|
};
|
||||||
use nym_api_requests::models::{
|
use nym_api_requests::models::{
|
||||||
ApiHealthResponse, GatewayBondAnnotated, GatewayCoreStatusResponse,
|
ApiHealthResponse, GatewayBondAnnotated, GatewayCoreStatusResponse, MixnodeCoreStatusResponse,
|
||||||
HistoricalPerformanceResponse, 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::{NodesByAddressesResponse, SkimmedNode};
|
use nym_api_requests::nym_nodes::SkimmedNode;
|
||||||
use nym_coconut_dkg_common::types::EpochId;
|
use nym_coconut_dkg_common::types::EpochId;
|
||||||
use nym_ecash_contract_common::deposit::DepositId;
|
use nym_ecash_contract_common::deposit::DepositId;
|
||||||
use nym_http_api_client::UserAgent;
|
use nym_http_api_client::UserAgent;
|
||||||
use nym_network_defaults::NymNetworkDetails;
|
use nym_network_defaults::NymNetworkDetails;
|
||||||
use std::net::IpAddr;
|
|
||||||
use time::Date;
|
use time::Date;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
@@ -265,31 +264,6 @@ impl<C, S> Client<C, S> {
|
|||||||
Ok(self.nym_api.get_gateways_detailed_unfiltered().await?)
|
Ok(self.nym_api.get_gateways_detailed_unfiltered().await?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_full_node_performance_history(
|
|
||||||
&self,
|
|
||||||
node_id: NodeId,
|
|
||||||
) -> Result<Vec<HistoricalPerformanceResponse>, ValidatorClientError> {
|
|
||||||
// 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 history = Vec::new();
|
|
||||||
|
|
||||||
loop {
|
|
||||||
let mut res = self
|
|
||||||
.nym_api
|
|
||||||
.get_node_performance_history(node_id, Some(page), None)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
history.append(&mut res.history.data);
|
|
||||||
if history.len() < res.history.pagination.total {
|
|
||||||
page += 1
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(history)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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,
|
||||||
@@ -647,6 +621,13 @@ impl NymApiClient {
|
|||||||
.await?)
|
.await?)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[deprecated]
|
||||||
|
pub async fn spent_credentials_filter(
|
||||||
|
&self,
|
||||||
|
) -> Result<SpentCredentialsResponse, ValidatorClientError> {
|
||||||
|
Ok(self.nym_api.double_spending_filter_v1().await?)
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn partial_expiration_date_signatures(
|
pub async fn partial_expiration_date_signatures(
|
||||||
&self,
|
&self,
|
||||||
expiration_date: Option<Date>,
|
expiration_date: Option<Date>,
|
||||||
@@ -711,11 +692,4 @@ impl NymApiClient {
|
|||||||
.issued_ticketbooks_challenge(expiration_date, deposits)
|
.issued_ticketbooks_challenge(expiration_date, deposits)
|
||||||
.await?)
|
.await?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn nodes_by_addresses(
|
|
||||||
&self,
|
|
||||||
addresses: Vec<IpAddr>,
|
|
||||||
) -> Result<NodesByAddressesResponse, ValidatorClientError> {
|
|
||||||
Ok(self.nym_api.nodes_by_addresses(addresses).await?)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,12 +65,6 @@ pub enum EcashApiError {
|
|||||||
#[from]
|
#[from]
|
||||||
source: cosmrs::ErrorReport,
|
source: cosmrs::ErrorReport,
|
||||||
},
|
},
|
||||||
|
|
||||||
#[error("nym api error")]
|
|
||||||
NymApi {
|
|
||||||
#[from]
|
|
||||||
source: crate::ValidatorClientError,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryFrom<ContractVKShare> for EcashApiClient {
|
impl TryFrom<ContractVKShare> for EcashApiClient {
|
||||||
|
|||||||
@@ -13,11 +13,9 @@ 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, PerformanceHistoryResponse, RewardedSetResponse,
|
NodeRefreshBody, NymNodeDescription, RewardedSetResponse,
|
||||||
};
|
|
||||||
use nym_api_requests::nym_nodes::{
|
|
||||||
NodesByAddressesRequestBody, NodesByAddressesResponse, PaginatedCachedNodesResponse,
|
|
||||||
};
|
};
|
||||||
|
use nym_api_requests::nym_nodes::PaginatedCachedNodesResponse;
|
||||||
use nym_api_requests::pagination::PaginatedResponse;
|
use nym_api_requests::pagination::PaginatedResponse;
|
||||||
pub use nym_api_requests::{
|
pub use nym_api_requests::{
|
||||||
ecash::{
|
ecash::{
|
||||||
@@ -33,7 +31,6 @@ pub use nym_api_requests::{
|
|||||||
StakeSaturationResponse, UptimeResponse,
|
StakeSaturationResponse, UptimeResponse,
|
||||||
},
|
},
|
||||||
nym_nodes::{CachedNodesResponse, SkimmedNode},
|
nym_nodes::{CachedNodesResponse, SkimmedNode},
|
||||||
NymNetworkDetailsResponse,
|
|
||||||
};
|
};
|
||||||
pub use nym_coconut_dkg_common::types::EpochId;
|
pub use nym_coconut_dkg_common::types::EpochId;
|
||||||
use nym_contracts_common::IdentityKey;
|
use nym_contracts_common::IdentityKey;
|
||||||
@@ -42,7 +39,6 @@ pub use nym_http_api_client::Client;
|
|||||||
use nym_http_api_client::{ApiClient, NO_PARAMS};
|
use nym_http_api_client::{ApiClient, NO_PARAMS};
|
||||||
use nym_mixnet_contract_common::mixnode::MixNodeDetails;
|
use nym_mixnet_contract_common::mixnode::MixNodeDetails;
|
||||||
use nym_mixnet_contract_common::{GatewayBond, IdentityKeyRef, NodeId, NymNodeDetails};
|
use nym_mixnet_contract_common::{GatewayBond, IdentityKeyRef, NodeId, NymNodeDetails};
|
||||||
use std::net::IpAddr;
|
|
||||||
use time::format_description::BorrowedFormatItem;
|
use time::format_description::BorrowedFormatItem;
|
||||||
use time::Date;
|
use time::Date;
|
||||||
use tracing::instrument;
|
use tracing::instrument;
|
||||||
@@ -167,35 +163,6 @@ pub trait NymApiClientExt: ApiClient {
|
|||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument(level = "debug", skip_all)]
|
|
||||||
async fn get_node_performance_history(
|
|
||||||
&self,
|
|
||||||
node_id: NodeId,
|
|
||||||
page: Option<u32>,
|
|
||||||
per_page: Option<u32>,
|
|
||||||
) -> Result<PerformanceHistoryResponse, NymAPIError> {
|
|
||||||
let mut params = Vec::new();
|
|
||||||
|
|
||||||
if let Some(page) = page {
|
|
||||||
params.push(("page", page.to_string()))
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(per_page) = per_page {
|
|
||||||
params.push(("per_page", per_page.to_string()))
|
|
||||||
}
|
|
||||||
|
|
||||||
self.get_json(
|
|
||||||
&[
|
|
||||||
routes::API_VERSION,
|
|
||||||
routes::NYM_NODES_ROUTES,
|
|
||||||
routes::NYM_NODES_PERFORMANCE_HISTORY,
|
|
||||||
&*node_id.to_string(),
|
|
||||||
],
|
|
||||||
¶ms,
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tracing::instrument(level = "debug", skip_all)]
|
#[tracing::instrument(level = "debug", skip_all)]
|
||||||
async fn get_nodes_described(
|
async fn get_nodes_described(
|
||||||
&self,
|
&self,
|
||||||
@@ -212,15 +179,8 @@ pub trait NymApiClientExt: ApiClient {
|
|||||||
params.push(("per_page", per_page.to_string()))
|
params.push(("per_page", per_page.to_string()))
|
||||||
}
|
}
|
||||||
|
|
||||||
self.get_json(
|
self.get_json(&[routes::API_VERSION, "nym-nodes", "described"], ¶ms)
|
||||||
&[
|
.await
|
||||||
routes::API_VERSION,
|
|
||||||
routes::NYM_NODES_ROUTES,
|
|
||||||
routes::NYM_NODES_DESCRIBED,
|
|
||||||
],
|
|
||||||
¶ms,
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument(level = "debug", skip_all)]
|
#[tracing::instrument(level = "debug", skip_all)]
|
||||||
@@ -239,15 +199,8 @@ pub trait NymApiClientExt: ApiClient {
|
|||||||
params.push(("per_page", per_page.to_string()))
|
params.push(("per_page", per_page.to_string()))
|
||||||
}
|
}
|
||||||
|
|
||||||
self.get_json(
|
self.get_json(&[routes::API_VERSION, "nym-nodes", "bonded"], ¶ms)
|
||||||
&[
|
.await
|
||||||
routes::API_VERSION,
|
|
||||||
routes::NYM_NODES_ROUTES,
|
|
||||||
routes::NYM_NODES_BONDED,
|
|
||||||
],
|
|
||||||
¶ms,
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[deprecated]
|
#[deprecated]
|
||||||
@@ -257,7 +210,7 @@ pub trait NymApiClientExt: ApiClient {
|
|||||||
&[
|
&[
|
||||||
routes::API_VERSION,
|
routes::API_VERSION,
|
||||||
"unstable",
|
"unstable",
|
||||||
routes::NYM_NODES_ROUTES,
|
"nym-nodes",
|
||||||
"mixnodes",
|
"mixnodes",
|
||||||
"skimmed",
|
"skimmed",
|
||||||
],
|
],
|
||||||
@@ -273,7 +226,7 @@ pub trait NymApiClientExt: ApiClient {
|
|||||||
&[
|
&[
|
||||||
routes::API_VERSION,
|
routes::API_VERSION,
|
||||||
"unstable",
|
"unstable",
|
||||||
routes::NYM_NODES_ROUTES,
|
"nym-nodes",
|
||||||
"gateways",
|
"gateways",
|
||||||
"skimmed",
|
"skimmed",
|
||||||
],
|
],
|
||||||
@@ -285,11 +238,7 @@ pub trait NymApiClientExt: ApiClient {
|
|||||||
#[instrument(level = "debug", skip(self))]
|
#[instrument(level = "debug", skip(self))]
|
||||||
async fn get_rewarded_set(&self) -> Result<RewardedSetResponse, NymAPIError> {
|
async fn get_rewarded_set(&self) -> Result<RewardedSetResponse, NymAPIError> {
|
||||||
self.get_json(
|
self.get_json(
|
||||||
&[
|
&[routes::API_VERSION, "nym-nodes", "rewarded-set"],
|
||||||
routes::API_VERSION,
|
|
||||||
routes::NYM_NODES_ROUTES,
|
|
||||||
routes::NYM_NODES_REWARDED_SET,
|
|
||||||
],
|
|
||||||
NO_PARAMS,
|
NO_PARAMS,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
@@ -322,7 +271,7 @@ pub trait NymApiClientExt: ApiClient {
|
|||||||
&[
|
&[
|
||||||
routes::API_VERSION,
|
routes::API_VERSION,
|
||||||
"unstable",
|
"unstable",
|
||||||
routes::NYM_NODES_ROUTES,
|
"nym-nodes",
|
||||||
"skimmed",
|
"skimmed",
|
||||||
"entry-gateways",
|
"entry-gateways",
|
||||||
"all",
|
"all",
|
||||||
@@ -359,7 +308,7 @@ pub trait NymApiClientExt: ApiClient {
|
|||||||
&[
|
&[
|
||||||
routes::API_VERSION,
|
routes::API_VERSION,
|
||||||
"unstable",
|
"unstable",
|
||||||
routes::NYM_NODES_ROUTES,
|
"nym-nodes",
|
||||||
"skimmed",
|
"skimmed",
|
||||||
"mixnodes",
|
"mixnodes",
|
||||||
"active",
|
"active",
|
||||||
@@ -396,7 +345,7 @@ pub trait NymApiClientExt: ApiClient {
|
|||||||
&[
|
&[
|
||||||
routes::API_VERSION,
|
routes::API_VERSION,
|
||||||
"unstable",
|
"unstable",
|
||||||
routes::NYM_NODES_ROUTES,
|
"nym-nodes",
|
||||||
"skimmed",
|
"skimmed",
|
||||||
"mixnodes",
|
"mixnodes",
|
||||||
"all",
|
"all",
|
||||||
@@ -428,12 +377,7 @@ pub trait NymApiClientExt: ApiClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.get_json(
|
self.get_json(
|
||||||
&[
|
&[routes::API_VERSION, "unstable", "nym-nodes", "skimmed"],
|
||||||
routes::API_VERSION,
|
|
||||||
"unstable",
|
|
||||||
routes::NYM_NODES_ROUTES,
|
|
||||||
"skimmed",
|
|
||||||
],
|
|
||||||
¶ms,
|
¶ms,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
@@ -742,8 +686,8 @@ pub trait NymApiClientExt: ApiClient {
|
|||||||
self.get_json(
|
self.get_json(
|
||||||
&[
|
&[
|
||||||
routes::API_VERSION,
|
routes::API_VERSION,
|
||||||
routes::NYM_NODES_ROUTES,
|
"nym-nodes",
|
||||||
routes::NYM_NODES_PERFORMANCE,
|
"performance",
|
||||||
&node_id.to_string(),
|
&node_id.to_string(),
|
||||||
],
|
],
|
||||||
NO_PARAMS,
|
NO_PARAMS,
|
||||||
@@ -758,8 +702,8 @@ pub trait NymApiClientExt: ApiClient {
|
|||||||
self.get_json(
|
self.get_json(
|
||||||
&[
|
&[
|
||||||
routes::API_VERSION,
|
routes::API_VERSION,
|
||||||
routes::NYM_NODES_ROUTES,
|
"nym-nodes",
|
||||||
routes::NYM_NODES_ANNOTATION,
|
"annotation",
|
||||||
&node_id.to_string(),
|
&node_id.to_string(),
|
||||||
],
|
],
|
||||||
NO_PARAMS,
|
NO_PARAMS,
|
||||||
@@ -853,6 +797,20 @@ pub trait NymApiClientExt: ApiClient {
|
|||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[deprecated]
|
||||||
|
#[instrument(level = "debug", skip(self))]
|
||||||
|
async fn double_spending_filter_v1(&self) -> Result<SpentCredentialsResponse, NymAPIError> {
|
||||||
|
self.get_json(
|
||||||
|
&[
|
||||||
|
routes::API_VERSION,
|
||||||
|
routes::ECASH_ROUTES,
|
||||||
|
routes::DOUBLE_SPENDING_FILTER_V1,
|
||||||
|
],
|
||||||
|
NO_PARAMS,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
#[instrument(level = "debug", skip(self))]
|
#[instrument(level = "debug", skip(self))]
|
||||||
async fn partial_expiration_date_signatures(
|
async fn partial_expiration_date_signatures(
|
||||||
&self,
|
&self,
|
||||||
@@ -969,11 +927,7 @@ pub trait NymApiClientExt: ApiClient {
|
|||||||
request: &NodeRefreshBody,
|
request: &NodeRefreshBody,
|
||||||
) -> Result<(), NymAPIError> {
|
) -> Result<(), NymAPIError> {
|
||||||
self.post_json(
|
self.post_json(
|
||||||
&[
|
&[routes::API_VERSION, "nym-nodes", "refresh-described"],
|
||||||
routes::API_VERSION,
|
|
||||||
routes::NYM_NODES_ROUTES,
|
|
||||||
routes::NYM_NODES_REFRESH_DESCRIBED,
|
|
||||||
],
|
|
||||||
NO_PARAMS,
|
NO_PARAMS,
|
||||||
request,
|
request,
|
||||||
)
|
)
|
||||||
@@ -1017,32 +971,6 @@ pub trait NymApiClientExt: ApiClient {
|
|||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn nodes_by_addresses(
|
|
||||||
&self,
|
|
||||||
addresses: Vec<IpAddr>,
|
|
||||||
) -> Result<NodesByAddressesResponse, NymAPIError> {
|
|
||||||
self.post_json(
|
|
||||||
&[
|
|
||||||
routes::API_VERSION,
|
|
||||||
"unstable",
|
|
||||||
routes::NYM_NODES_ROUTES,
|
|
||||||
routes::nym_nodes::BY_ADDRESSES,
|
|
||||||
],
|
|
||||||
NO_PARAMS,
|
|
||||||
&NodesByAddressesRequestBody { addresses },
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
#[instrument(level = "debug", skip(self))]
|
|
||||||
async fn get_network_details(&self) -> Result<NymNetworkDetailsResponse, NymAPIError> {
|
|
||||||
self.get_json(
|
|
||||||
&[routes::API_VERSION, routes::NETWORK, routes::DETAILS],
|
|
||||||
NO_PARAMS,
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ pub const DETAILED: &str = "detailed";
|
|||||||
pub const DETAILED_UNFILTERED: &str = "detailed-unfiltered";
|
pub const DETAILED_UNFILTERED: &str = "detailed-unfiltered";
|
||||||
pub const ACTIVE: &str = "active";
|
pub const ACTIVE: &str = "active";
|
||||||
pub const REWARDED: &str = "rewarded";
|
pub const REWARDED: &str = "rewarded";
|
||||||
|
pub const DOUBLE_SPENDING_FILTER_V1: &str = "double-spending-filter-v1";
|
||||||
|
|
||||||
pub const ECASH_ROUTES: &str = "ecash";
|
pub const ECASH_ROUTES: &str = "ecash";
|
||||||
|
|
||||||
pub use ecash::*;
|
pub use ecash::*;
|
||||||
@@ -32,20 +34,6 @@ pub mod ecash {
|
|||||||
pub const EPOCH_ID_PARAM: &str = "epoch_id";
|
pub const EPOCH_ID_PARAM: &str = "epoch_id";
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const NYM_NODES_ROUTES: &str = "nym-nodes";
|
|
||||||
|
|
||||||
pub use nym_nodes::*;
|
|
||||||
pub mod nym_nodes {
|
|
||||||
pub const NYM_NODES_PERFORMANCE_HISTORY: &str = "performance-history";
|
|
||||||
pub const NYM_NODES_PERFORMANCE: &str = "performance";
|
|
||||||
pub const NYM_NODES_ANNOTATION: &str = "annotation";
|
|
||||||
pub const NYM_NODES_DESCRIBED: &str = "described";
|
|
||||||
pub const NYM_NODES_BONDED: &str = "bonded";
|
|
||||||
pub const NYM_NODES_REWARDED_SET: &str = "rewarded-set";
|
|
||||||
pub const NYM_NODES_REFRESH_DESCRIBED: &str = "refresh-described";
|
|
||||||
pub const BY_ADDRESSES: &str = "by-addresses";
|
|
||||||
}
|
|
||||||
|
|
||||||
pub const STATUS_ROUTES: &str = "status";
|
pub const STATUS_ROUTES: &str = "status";
|
||||||
pub const API_STATUS_ROUTES: &str = "api-status";
|
pub const API_STATUS_ROUTES: &str = "api-status";
|
||||||
pub const HEALTH: &str = "health";
|
pub const HEALTH: &str = "health";
|
||||||
@@ -66,8 +54,6 @@ pub const STAKE_SATURATION: &str = "stake-saturation";
|
|||||||
pub const INCLUSION_CHANCE: &str = "inclusion-probability";
|
pub const INCLUSION_CHANCE: &str = "inclusion-probability";
|
||||||
pub const SUBMIT_GATEWAY: &str = "submit-gateway-monitoring-results";
|
pub const SUBMIT_GATEWAY: &str = "submit-gateway-monitoring-results";
|
||||||
pub const SUBMIT_NODE: &str = "submit-node-monitoring-results";
|
pub const SUBMIT_NODE: &str = "submit-node-monitoring-results";
|
||||||
|
pub const PERFORMANCE: &str = "performance";
|
||||||
|
|
||||||
pub const SERVICE_PROVIDERS: &str = "services";
|
pub const SERVICE_PROVIDERS: &str = "services";
|
||||||
|
|
||||||
pub const DETAILS: &str = "details";
|
|
||||||
pub const NETWORK: &str = "network";
|
|
||||||
|
|||||||
-31
@@ -153,20 +153,13 @@ pub trait CosmWasmClient: TendermintRpcClient {
|
|||||||
let req = QueryAllBalancesRequest {
|
let req = QueryAllBalancesRequest {
|
||||||
address: address.to_string(),
|
address: address.to_string(),
|
||||||
pagination,
|
pagination,
|
||||||
resolve_denom: false,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut res = self
|
let mut res = self
|
||||||
.make_abci_query::<_, QueryAllBalancesResponse>(path.clone(), req)
|
.make_abci_query::<_, QueryAllBalancesResponse>(path.clone(), req)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let early_break = res.balances.is_empty();
|
|
||||||
raw_balances.append(&mut res.balances);
|
raw_balances.append(&mut res.balances);
|
||||||
|
|
||||||
if early_break {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(next_key) = next_page_key(res.pagination) {
|
if let Some(next_key) = next_page_key(res.pagination) {
|
||||||
pagination = Some(create_pagination(next_key))
|
pagination = Some(create_pagination(next_key))
|
||||||
} else {
|
} else {
|
||||||
@@ -194,13 +187,7 @@ pub trait CosmWasmClient: TendermintRpcClient {
|
|||||||
.make_abci_query::<_, QueryTotalSupplyResponse>(path.clone(), req)
|
.make_abci_query::<_, QueryTotalSupplyResponse>(path.clone(), req)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let early_break = res.supply.is_empty();
|
|
||||||
supply.append(&mut res.supply);
|
supply.append(&mut res.supply);
|
||||||
|
|
||||||
if early_break {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(next_key) = next_page_key(res.pagination) {
|
if let Some(next_key) = next_page_key(res.pagination) {
|
||||||
pagination = Some(create_pagination(next_key))
|
pagination = Some(create_pagination(next_key))
|
||||||
} else {
|
} else {
|
||||||
@@ -341,13 +328,7 @@ pub trait CosmWasmClient: TendermintRpcClient {
|
|||||||
.make_abci_query::<_, QueryCodesResponse>(path.clone(), req)
|
.make_abci_query::<_, QueryCodesResponse>(path.clone(), req)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let early_break = res.code_infos.is_empty();
|
|
||||||
raw_codes.append(&mut res.code_infos);
|
raw_codes.append(&mut res.code_infos);
|
||||||
|
|
||||||
if early_break {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(next_key) = next_page_key(res.pagination) {
|
if let Some(next_key) = next_page_key(res.pagination) {
|
||||||
pagination = Some(create_pagination(next_key))
|
pagination = Some(create_pagination(next_key))
|
||||||
} else {
|
} else {
|
||||||
@@ -392,13 +373,7 @@ pub trait CosmWasmClient: TendermintRpcClient {
|
|||||||
.make_abci_query::<_, QueryContractsByCodeResponse>(path.clone(), req)
|
.make_abci_query::<_, QueryContractsByCodeResponse>(path.clone(), req)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let early_break = res.contracts.is_empty();
|
|
||||||
raw_contracts.append(&mut res.contracts);
|
raw_contracts.append(&mut res.contracts);
|
||||||
|
|
||||||
if early_break {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(next_key) = next_page_key(res.pagination) {
|
if let Some(next_key) = next_page_key(res.pagination) {
|
||||||
pagination = Some(create_pagination(next_key))
|
pagination = Some(create_pagination(next_key))
|
||||||
} else {
|
} else {
|
||||||
@@ -454,13 +429,7 @@ pub trait CosmWasmClient: TendermintRpcClient {
|
|||||||
.make_abci_query::<_, QueryContractHistoryResponse>(path.clone(), req)
|
.make_abci_query::<_, QueryContractHistoryResponse>(path.clone(), req)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let early_break = res.entries.is_empty();
|
|
||||||
raw_entries.append(&mut res.entries);
|
raw_entries.append(&mut res.entries);
|
||||||
|
|
||||||
if early_break {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(next_key) = next_page_key(res.pagination) {
|
if let Some(next_key) = next_page_key(res.pagination) {
|
||||||
pagination = Some(create_pagination(next_key))
|
pagination = Some(create_pagination(next_key))
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ use nym_network_defaults::{ChainDetails, NymNetworkDetails};
|
|||||||
use serde::{de::DeserializeOwned, Serialize};
|
use serde::{de::DeserializeOwned, Serialize};
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use std::time::SystemTime;
|
use std::time::SystemTime;
|
||||||
|
use tendermint_rpc::endpoint::block::Response as BlockResponse;
|
||||||
use tendermint_rpc::endpoint::*;
|
use tendermint_rpc::endpoint::*;
|
||||||
use tendermint_rpc::{Error as TendermintRpcError, Order};
|
use tendermint_rpc::{Error as TendermintRpcError, Order};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
@@ -62,7 +63,6 @@ pub use cw3;
|
|||||||
pub use cw4;
|
pub use cw4;
|
||||||
pub use cw_controllers;
|
pub use cw_controllers;
|
||||||
pub use fee::{gas_price::GasPrice, GasAdjustable, GasAdjustment};
|
pub use fee::{gas_price::GasPrice, GasAdjustable, GasAdjustment};
|
||||||
pub use tendermint_rpc::endpoint::block::Response as BlockResponse;
|
|
||||||
pub use tendermint_rpc::{
|
pub use tendermint_rpc::{
|
||||||
endpoint::{tx::Response as TxResponse, validators::Response as ValidatorResponse},
|
endpoint::{tx::Response as TxResponse, validators::Response as ValidatorResponse},
|
||||||
query::Query,
|
query::Query,
|
||||||
|
|||||||
@@ -4,11 +4,9 @@
|
|||||||
use crate::rpc::TendermintRpcClient;
|
use crate::rpc::TendermintRpcClient;
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use base64::Engine;
|
use base64::Engine;
|
||||||
use cosmrs::tendermint;
|
|
||||||
use cosmrs::tendermint::{block::Height, evidence::Evidence, Hash};
|
use cosmrs::tendermint::{block::Height, evidence::Evidence, Hash};
|
||||||
use reqwest::header::HeaderMap;
|
use reqwest::header::HeaderMap;
|
||||||
use reqwest::{header, RequestBuilder};
|
use reqwest::{header, RequestBuilder};
|
||||||
use tendermint_rpc::dialect::{v0_34, v0_37, v0_38, LatestDialect};
|
|
||||||
use tendermint_rpc::{
|
use tendermint_rpc::{
|
||||||
client::CompatMode,
|
client::CompatMode,
|
||||||
dialect::{self, Dialect},
|
dialect::{self, Dialect},
|
||||||
@@ -23,21 +21,8 @@ macro_rules! perform_with_compat {
|
|||||||
($self:expr, $request:expr) => {{
|
($self:expr, $request:expr) => {{
|
||||||
let request = $request;
|
let request = $request;
|
||||||
match $self.compat {
|
match $self.compat {
|
||||||
CompatMode::V0_38 => {
|
CompatMode::V0_37 => $self.perform_v0_37(request).await,
|
||||||
$self
|
CompatMode::V0_34 => $self.perform_v0_34(request).await,
|
||||||
.perform_request_with_dialect(request, dialect::v0_38::Dialect)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
CompatMode::V0_37 => {
|
|
||||||
$self
|
|
||||||
.perform_request_with_dialect(request, dialect::v0_37::Dialect)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
CompatMode::V0_34 => {
|
|
||||||
$self
|
|
||||||
.perform_request_with_dialect(request, dialect::v0_34::Dialect)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
@@ -85,11 +70,7 @@ impl ReqwestRpcClient {
|
|||||||
.headers(headers)
|
.headers(headers)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn perform_request_with_dialect<R, S>(
|
async fn perform_request<R, S>(&self, request: R) -> Result<R::Output, Error>
|
||||||
&self,
|
|
||||||
request: R,
|
|
||||||
_dialect: S,
|
|
||||||
) -> Result<R::Output, Error>
|
|
||||||
where
|
where
|
||||||
R: SimpleRequest<S>,
|
R: SimpleRequest<S>,
|
||||||
S: Dialect,
|
S: Dialect,
|
||||||
@@ -100,25 +81,26 @@ impl ReqwestRpcClient {
|
|||||||
.send()
|
.send()
|
||||||
.await
|
.await
|
||||||
.map_err(TendermintRpcErrorMap::into_rpc_err)?;
|
.map_err(TendermintRpcErrorMap::into_rpc_err)?;
|
||||||
let response_status = response.status();
|
|
||||||
let bytes = response
|
let bytes = response
|
||||||
.bytes()
|
.bytes()
|
||||||
.await
|
.await
|
||||||
.map_err(TendermintRpcErrorMap::into_rpc_err)?;
|
.map_err(TendermintRpcErrorMap::into_rpc_err)?;
|
||||||
|
|
||||||
// Successful JSON-RPC requests are expected to return a 200 OK HTTP status.
|
|
||||||
// Otherwise, this means that the HTTP request failed as a whole,
|
|
||||||
// as opposed to the JSON-RPC request returning an error,
|
|
||||||
// and we cannot expect the response body to be a valid JSON-RPC response.
|
|
||||||
if response_status != reqwest::StatusCode::OK {
|
|
||||||
// hehe, that's so nasty but we have to somehow convert between different versions of the same lib
|
|
||||||
return Err(Error::http_request_failed(
|
|
||||||
response_status.as_u16().try_into().unwrap(),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
R::Response::from_string(bytes).map(Into::into)
|
R::Response::from_string(bytes).map(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn perform_v0_34<R>(&self, request: R) -> Result<R::Output, Error>
|
||||||
|
where
|
||||||
|
R: SimpleRequest<dialect::v0_34::Dialect>,
|
||||||
|
{
|
||||||
|
self.perform_request(request).await
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn perform_v0_37<R>(&self, request: R) -> Result<R::Output, Error>
|
||||||
|
where
|
||||||
|
R: SimpleRequest<dialect::v0_37::Dialect>,
|
||||||
|
{
|
||||||
|
self.perform_request(request).await
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trait TendermintRpcErrorMap {
|
trait TendermintRpcErrorMap {
|
||||||
@@ -138,50 +120,18 @@ impl TendermintRpcClient for ReqwestRpcClient {
|
|||||||
where
|
where
|
||||||
R: SimpleRequest,
|
R: SimpleRequest,
|
||||||
{
|
{
|
||||||
self.perform_request_with_dialect(request, LatestDialect)
|
self.perform_request(request).await
|
||||||
.await
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn block<H>(&self, height: H) -> Result<endpoint::block::Response, Error>
|
async fn block_results<H>(&self, height: H) -> Result<block_results::Response, Error>
|
||||||
where
|
where
|
||||||
H: Into<Height> + Send,
|
H: Into<Height> + Send,
|
||||||
{
|
{
|
||||||
perform_with_compat!(self, endpoint::block::Request::new(height.into()))
|
perform_with_compat!(self, block_results::Request::new(height.into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn block_by_hash(
|
async fn latest_block_results(&self) -> Result<block_results::Response, Error> {
|
||||||
&self,
|
perform_with_compat!(self, block_results::Request::default())
|
||||||
hash: tendermint::Hash,
|
|
||||||
) -> Result<endpoint::block_by_hash::Response, Error> {
|
|
||||||
perform_with_compat!(self, endpoint::block_by_hash::Request::new(hash))
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn latest_block(&self) -> Result<endpoint::block::Response, Error> {
|
|
||||||
perform_with_compat!(self, endpoint::block::Request::default())
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn block_results<H>(&self, height: H) -> Result<endpoint::block_results::Response, Error>
|
|
||||||
where
|
|
||||||
H: Into<Height> + Send,
|
|
||||||
{
|
|
||||||
perform_with_compat!(self, endpoint::block_results::Request::new(height.into()))
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn latest_block_results(&self) -> Result<endpoint::block_results::Response, Error> {
|
|
||||||
perform_with_compat!(self, endpoint::block_results::Request::default())
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn block_search(
|
|
||||||
&self,
|
|
||||||
query: Query,
|
|
||||||
page: u32,
|
|
||||||
per_page: u8,
|
|
||||||
order: Order,
|
|
||||||
) -> Result<endpoint::block_search::Response, Error> {
|
|
||||||
perform_with_compat!(
|
|
||||||
self,
|
|
||||||
endpoint::block_search::Request::new(query, page, per_page, order)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn header<H>(&self, height: H) -> Result<endpoint::header::Response, Error>
|
async fn header<H>(&self, height: H) -> Result<endpoint::header::Response, Error>
|
||||||
@@ -190,26 +140,11 @@ impl TendermintRpcClient for ReqwestRpcClient {
|
|||||||
{
|
{
|
||||||
let height = height.into();
|
let height = height.into();
|
||||||
match self.compat {
|
match self.compat {
|
||||||
CompatMode::V0_38 => {
|
CompatMode::V0_37 => self.perform(endpoint::header::Request::new(height)).await,
|
||||||
self.perform_request_with_dialect(
|
|
||||||
endpoint::header::Request::new(height),
|
|
||||||
v0_38::Dialect,
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
CompatMode::V0_37 => {
|
|
||||||
self.perform_request_with_dialect(
|
|
||||||
endpoint::header::Request::new(height),
|
|
||||||
v0_37::Dialect,
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
CompatMode::V0_34 => {
|
CompatMode::V0_34 => {
|
||||||
// Back-fill with a request to /block endpoint and
|
// Back-fill with a request to /block endpoint and
|
||||||
// taking just the header from the response.
|
// taking just the header from the response.
|
||||||
let resp = self
|
let resp = self.perform_v0_34(block::Request::new(height)).await?;
|
||||||
.perform_request_with_dialect(block::Request::new(height), v0_34::Dialect)
|
|
||||||
.await?;
|
|
||||||
Ok(resp.into())
|
Ok(resp.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -217,25 +152,12 @@ impl TendermintRpcClient for ReqwestRpcClient {
|
|||||||
|
|
||||||
async fn header_by_hash(&self, hash: Hash) -> Result<header_by_hash::Response, Error> {
|
async fn header_by_hash(&self, hash: Hash) -> Result<header_by_hash::Response, Error> {
|
||||||
match self.compat {
|
match self.compat {
|
||||||
CompatMode::V0_38 => {
|
CompatMode::V0_37 => self.perform(header_by_hash::Request::new(hash)).await,
|
||||||
self.perform_request_with_dialect(
|
|
||||||
header_by_hash::Request::new(hash),
|
|
||||||
v0_38::Dialect,
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
CompatMode::V0_37 => {
|
|
||||||
self.perform_request_with_dialect(
|
|
||||||
header_by_hash::Request::new(hash),
|
|
||||||
v0_37::Dialect,
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
CompatMode::V0_34 => {
|
CompatMode::V0_34 => {
|
||||||
// Back-fill with a request to /block_by_hash endpoint and
|
// Back-fill with a request to /block_by_hash endpoint and
|
||||||
// taking just the header from the response.
|
// taking just the header from the response.
|
||||||
let resp = self
|
let resp = self
|
||||||
.perform_request_with_dialect(block_by_hash::Request::new(hash), v0_34::Dialect)
|
.perform_v0_34(block_by_hash::Request::new(hash))
|
||||||
.await?;
|
.await?;
|
||||||
Ok(resp.into())
|
Ok(resp.into())
|
||||||
}
|
}
|
||||||
@@ -245,18 +167,8 @@ impl TendermintRpcClient for ReqwestRpcClient {
|
|||||||
/// `/broadcast_evidence`: broadcast an evidence.
|
/// `/broadcast_evidence`: broadcast an evidence.
|
||||||
async fn broadcast_evidence(&self, e: Evidence) -> Result<evidence::Response, Error> {
|
async fn broadcast_evidence(&self, e: Evidence) -> Result<evidence::Response, Error> {
|
||||||
match self.compat {
|
match self.compat {
|
||||||
CompatMode::V0_38 => {
|
CompatMode::V0_37 => self.perform(evidence::Request::new(e)).await,
|
||||||
self.perform_request_with_dialect(evidence::Request::new(e), v0_38::Dialect)
|
CompatMode::V0_34 => self.perform_v0_34(evidence::Request::new(e)).await,
|
||||||
.await
|
|
||||||
}
|
|
||||||
CompatMode::V0_37 => {
|
|
||||||
self.perform_request_with_dialect(evidence::Request::new(e), v0_37::Dialect)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
CompatMode::V0_34 => {
|
|
||||||
self.perform_request_with_dialect(evidence::Request::new(e), v0_34::Dialect)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,15 @@ pub fn in6addr_any_init() -> IpAddr {
|
|||||||
IpAddr::V6(Ipv6Addr::UNSPECIFIED)
|
IpAddr::V6(Ipv6Addr::UNSPECIFIED)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Helper for providing binding warnings if node tries to bind to any of those
|
||||||
|
pub const SPECIAL_ADDRESSES: &[IpAddr] = &[
|
||||||
|
IpAddr::V4(Ipv4Addr::LOCALHOST),
|
||||||
|
IpAddr::V4(Ipv4Addr::UNSPECIFIED),
|
||||||
|
IpAddr::V4(Ipv4Addr::BROADCAST),
|
||||||
|
IpAddr::V6(Ipv6Addr::LOCALHOST),
|
||||||
|
IpAddr::V6(Ipv6Addr::UNSPECIFIED),
|
||||||
|
];
|
||||||
|
|
||||||
// TODO: is it really part of 'Config'?
|
// TODO: is it really part of 'Config'?
|
||||||
pub trait OptionalSet {
|
pub trait OptionalSet {
|
||||||
/// If the value is available (i.e. `Some`), the provided closure is applied.
|
/// If the value is available (i.e. `Some`), the provided closure is applied.
|
||||||
|
|||||||
@@ -863,4 +863,11 @@ pub enum QueryMsg {
|
|||||||
pub struct MigrateMsg {
|
pub struct MigrateMsg {
|
||||||
pub unsafe_skip_state_updates: Option<bool>,
|
pub unsafe_skip_state_updates: Option<bool>,
|
||||||
pub vesting_contract_address: Option<String>,
|
pub vesting_contract_address: Option<String>,
|
||||||
|
pub current_nym_node_semver: String,
|
||||||
|
|
||||||
|
#[serde(default)]
|
||||||
|
pub version_score_weights: OutdatedVersionWeights,
|
||||||
|
|
||||||
|
#[serde(default)]
|
||||||
|
pub version_score_params: VersionScoreFormulaParams,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -113,10 +113,6 @@ impl Role {
|
|||||||
pub fn is_standby(&self) -> bool {
|
pub fn is_standby(&self) -> bool {
|
||||||
matches!(self, Role::Standby)
|
matches!(self, Role::Standby)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_mixnode(&self) -> bool {
|
|
||||||
matches!(self, Role::Layer1 | Role::Layer2 | Role::Layer3)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for Role {
|
impl Display for Role {
|
||||||
|
|||||||
@@ -8,81 +8,81 @@ use thiserror::Error;
|
|||||||
|
|
||||||
#[derive(Error, Debug, PartialEq)]
|
#[derive(Error, Debug, PartialEq)]
|
||||||
pub enum VestingContractError {
|
pub enum VestingContractError {
|
||||||
#[error("VESTING ({l}): {0}", l = line!())]
|
#[error("VESTING ({}): {0}", line!())]
|
||||||
Std(#[from] StdError),
|
Std(#[from] StdError),
|
||||||
|
|
||||||
#[error("VESTING: {0}")]
|
#[error("VESTING: {0}")]
|
||||||
OverflowError(#[from] OverflowError),
|
OverflowError(#[from] OverflowError),
|
||||||
|
|
||||||
#[error("VESTING ({l}): Account does not exist - {0}", l = line!())]
|
#[error("VESTING ({}): Account does not exist - {0}", line!())]
|
||||||
NoAccountForAddress(String),
|
NoAccountForAddress(String),
|
||||||
|
|
||||||
#[error("VESTING ({l}): Only admin can perform this action, {0} is not admin", l = line!())]
|
#[error("VESTING ({}): Only admin can perform this action, {0} is not admin", line!())]
|
||||||
NotAdmin(String),
|
NotAdmin(String),
|
||||||
|
|
||||||
#[error("VESTING ({l}): Balance not found for existing account ({0}), this is a bug", l = line!())]
|
#[error("VESTING ({}): Balance not found for existing account ({0}), this is a bug", line!())]
|
||||||
NoBalanceForAddress(String),
|
NoBalanceForAddress(String),
|
||||||
|
|
||||||
#[error("VESTING ({l}): Insufficient balance for address {0} -> {1}", l = line!())]
|
#[error("VESTING ({}): Insufficient balance for address {0} -> {1}", line!())]
|
||||||
InsufficientBalance(String, u128),
|
InsufficientBalance(String, u128),
|
||||||
|
|
||||||
#[error("VESTING ({l}): Insufficient spendable balance for address {0} -> {1}", l = line!())]
|
#[error("VESTING ({}): Insufficient spendable balance for address {0} -> {1}", line!())]
|
||||||
InsufficientSpendable(String, u128),
|
InsufficientSpendable(String, u128),
|
||||||
|
|
||||||
#[error(
|
#[error(
|
||||||
"VESTING ({l}):Only delegation owner can perform delegation actions, {0} is not the delegation owner"
|
"VESTING ({}):Only delegation owner can perform delegation actions, {0} is not the delegation owner"
|
||||||
, l = line!())]
|
, line!())]
|
||||||
NotDelegate(String),
|
NotDelegate(String),
|
||||||
|
|
||||||
#[error("VESTING ({l}): Total vesting amount is inprobably low -> {0}, this is likely an error", l = line!())]
|
#[error("VESTING ({}): Total vesting amount is inprobably low -> {0}, this is likely an error", line!())]
|
||||||
ImprobableVestingAmount(u128),
|
ImprobableVestingAmount(u128),
|
||||||
|
|
||||||
#[error("VESTING ({l}): Address {0} has already bonded a node", l = line!())]
|
#[error("VESTING ({}): Address {0} has already bonded a node", line!())]
|
||||||
AlreadyBonded(String),
|
AlreadyBonded(String),
|
||||||
|
|
||||||
#[error("VESTING ({l}): Received empty funds vector", l = line!())]
|
#[error("VESTING ({}): Received empty funds vector", line!())]
|
||||||
EmptyFunds,
|
EmptyFunds,
|
||||||
|
|
||||||
#[error("VESTING ({l}): Received wrong denom: {0}, expected {1}", l = line!())]
|
#[error("VESTING ({}): Received wrong denom: {0}, expected {1}", line!())]
|
||||||
WrongDenom(String, String),
|
WrongDenom(String, String),
|
||||||
|
|
||||||
#[error("VESTING ({l}): Received multiple denoms, expected 1", l = line!())]
|
#[error("VESTING ({}): Received multiple denoms, expected 1", line!())]
|
||||||
MultipleDenoms,
|
MultipleDenoms,
|
||||||
|
|
||||||
#[error("VESTING ({l}): No delegations found for account {0}, mix_identity {1}", l = line!())]
|
#[error("VESTING ({}): No delegations found for account {0}, mix_identity {1}", line!())]
|
||||||
NoSuchDelegation(Addr, NodeId),
|
NoSuchDelegation(Addr, NodeId),
|
||||||
|
|
||||||
#[error("VESTING ({l}): Only mixnet contract can perform this operation, got {0}", l = line!())]
|
#[error("VESTING ({}): Only mixnet contract can perform this operation, got {0}", line!())]
|
||||||
NotMixnetContract(Addr),
|
NotMixnetContract(Addr),
|
||||||
|
|
||||||
#[error("VESTING ({l}): Calculation underflowed", l = line!())]
|
#[error("VESTING ({}): Calculation underflowed", line!())]
|
||||||
Underflow,
|
Underflow,
|
||||||
|
|
||||||
#[error("VESTING ({l}): No bond found for account {0}", l = line!())]
|
#[error("VESTING ({}): No bond found for account {0}", line!())]
|
||||||
NoBondFound(String),
|
NoBondFound(String),
|
||||||
|
|
||||||
#[error("VESTING: Attempted to reduce mixnode bond pledge below zero! The current pledge is {current} and we attempted to reduce it by {decrease_by}.")]
|
#[error("VESTING: Attempted to reduce mixnode bond pledge below zero! The current pledge is {current} and we attempted to reduce it by {decrease_by}.")]
|
||||||
InvalidBondPledgeReduction { current: Coin, decrease_by: Coin },
|
InvalidBondPledgeReduction { current: Coin, decrease_by: Coin },
|
||||||
|
|
||||||
#[error("VESTING ({l}): Action can only be executed by account owner -> {0}", l = line!())]
|
#[error("VESTING ({}): Action can only be executed by account owner -> {0}", line!())]
|
||||||
NotOwner(String),
|
NotOwner(String),
|
||||||
|
|
||||||
#[error("VESTING ({l}): Invalid address: {0}", l = line!())]
|
#[error("VESTING ({}): Invalid address: {0}", line!())]
|
||||||
InvalidAddress(String),
|
InvalidAddress(String),
|
||||||
|
|
||||||
#[error("VESTING ({l}): Account already exists: {0}", l = line!())]
|
#[error("VESTING ({}): Account already exists: {0}", line!())]
|
||||||
AccountAlreadyExists(String),
|
AccountAlreadyExists(String),
|
||||||
|
|
||||||
#[error("VESTING ({l}): Staking account already exists: {0}", l = line!())]
|
#[error("VESTING ({}): Staking account already exists: {0}", line!())]
|
||||||
StakingAccountAlreadyExists(String),
|
StakingAccountAlreadyExists(String),
|
||||||
|
|
||||||
#[error("VESTING ({l}): Too few coins sent for vesting account creation, sent {sent}, need at least {need}", l = line!())]
|
#[error("VESTING ({}): Too few coins sent for vesting account creation, sent {sent}, need at least {need}", line!())]
|
||||||
MinVestingFunds { sent: u128, need: u128 },
|
MinVestingFunds { sent: u128, need: u128 },
|
||||||
|
|
||||||
#[error("VESTING ({l}): Maximum amount of locked coins has already been pledged: {current}, cap is {cap}", l = line!())]
|
#[error("VESTING ({}): Maximum amount of locked coins has already been pledged: {current}, cap is {cap}", line!())]
|
||||||
LockedPledgeCapReached { current: Uint128, cap: Uint128 },
|
LockedPledgeCapReached { current: Uint128, cap: Uint128 },
|
||||||
|
|
||||||
#[error("VESTING: ({l}: Account owned by {owner} has unpopulated vesting periods!", l = line!())]
|
#[error("VESTING: ({}: Account owned by {owner} has unpopulated vesting periods!", line!())]
|
||||||
UnpopulatedVestingPeriods { owner: Addr },
|
UnpopulatedVestingPeriods { owner: Addr },
|
||||||
|
|
||||||
#[error("VESTING: Vesting account associated with {0} already exists, only addresses with not existing vesting accounts can be added as staking addresses")]
|
#[error("VESTING: Vesting account associated with {0} already exists, only addresses with not existing vesting accounts can be added as staking addresses")]
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ use std::error::Error;
|
|||||||
// `SELECT total_tickets, used_tickets FROM ecash_ticketbook WHERE expiration_date >= ?`, today_date
|
// `SELECT total_tickets, used_tickets FROM ecash_ticketbook WHERE expiration_date >= ?`, today_date
|
||||||
// then for each calculate the diff total_tickets - used_tickets and multiply the result by the size of the ticket
|
// then for each calculate the diff total_tickets - used_tickets and multiply the result by the size of the ticket
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
pub trait Storage: Clone + Send + Sync {
|
pub trait Storage: Send + Sync {
|
||||||
type StorageError: Error;
|
type StorageError: Error;
|
||||||
|
|
||||||
async fn close(&self);
|
async fn close(&self);
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user