Compare commits
428 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 87a188ca06 | |||
| 4d0898c633 | |||
| d984d085a7 | |||
| 2e22cad074 | |||
| 17708cdf92 | |||
| a9c56ef9ac | |||
| 724420f97c | |||
| 0a48fa6172 | |||
| 5c8749a2e1 | |||
| 18d9d807f2 | |||
| 3a7393d316 | |||
| 6ce5f707c6 | |||
| 766a1d4497 | |||
| 35c83f0a31 | |||
| 01dd4a7972 | |||
| c2e335557e | |||
| 40e1cbc7a9 | |||
| c133e0e88b | |||
| 5b716633de | |||
| 834538300d | |||
| bd0d70f7cd | |||
| 979485c582 | |||
| d95f66bd90 | |||
| 906dfb2fb0 | |||
| 7daa726626 | |||
| 067f492ad6 | |||
| ed73ec9ce6 | |||
| 61606630bd | |||
| 2d3deeb424 | |||
| 3827dc357d | |||
| a70e9e23d3 | |||
| dc59149a5d | |||
| e418c7587a | |||
| 33339c085d | |||
| 863f329106 | |||
| 314a37cabe | |||
| 917f391948 | |||
| 0b4deda621 | |||
| d01867ca8d | |||
| 502c63b291 | |||
| a4e674c98b | |||
| 7f97f13799 | |||
| b975d08342 | |||
| 8e44f9f07f | |||
| 85604e8305 | |||
| 8461d085a5 | |||
| af9f6e5ca0 | |||
| a9ae2017f5 | |||
| 09ebe7f9e9 | |||
| b72915c224 | |||
| add3e864e3 | |||
| 578c9b0567 | |||
| 8f6f696f36 | |||
| e9165763b6 | |||
| 6c1149708b | |||
| aaf6931d78 | |||
| 97804f2fe5 | |||
| 802d9b69ca | |||
| 7313857bc8 | |||
| 779174ada5 | |||
| 8771c1dfa6 | |||
| 329ad83fc0 | |||
| aea5872ad0 | |||
| 9e9abd74d7 | |||
| 3832508af7 | |||
| 69a4e33b17 | |||
| 83385421ff | |||
| ec53b570dc | |||
| ebcc658f98 | |||
| 6a155721c6 | |||
| 1bb8b3a3ec | |||
| 8d1a16eb02 | |||
| 8d10cf70e9 | |||
| e32df10b4d | |||
| d1660c01e6 | |||
| 14378b1db9 | |||
| 35bbf5fd84 | |||
| c374a4935a | |||
| 513f4f652d | |||
| 82b9425ca6 | |||
| 615e98b166 | |||
| b11f6c6c70 | |||
| 2f5e8e0bcd | |||
| 812a8782b4 | |||
| 089c47cce7 | |||
| 833114372a | |||
| a7b57d7e58 | |||
| 84e10a654c | |||
| d724f94319 | |||
| d0692a567a | |||
| 2ae38b9e49 | |||
| ef5990658a | |||
| 658dec8299 | |||
| 447352b8d6 | |||
| d6bb0979d0 | |||
| eb59615c56 | |||
| 07c908c497 | |||
| 6de0c4ce92 | |||
| fa1d47e941 | |||
| 05d8b31e51 | |||
| 692fbf1392 | |||
| 44ec6d6bc8 | |||
| 0de4aea77b | |||
| a7cd8efc04 | |||
| 56aad75220 | |||
| e2f2ab89ec | |||
| 4d09b6f2e5 | |||
| 6d47046a38 | |||
| b9339b8f0c | |||
| 43a7360399 | |||
| 5f9f7f0fac | |||
| df0e2fe489 | |||
| 5cfd09cd99 | |||
| bc33cc4c8d | |||
| a31597aca9 | |||
| 378229b04e | |||
| fec196c097 | |||
| 1d7ffc1bb6 | |||
| 0caa627960 | |||
| d6b3d7fc0a | |||
| 40b4670d80 | |||
| ac273480f8 | |||
| 79603d61d7 | |||
| e8e9a70ef4 | |||
| 0c52ee89c8 | |||
| f324d45721 | |||
| 470e88f46c | |||
| 42a5016822 | |||
| 579cff358d | |||
| f95dda0f2f | |||
| fc666fb984 | |||
| 1264fd9bfb | |||
| 3e8451f292 | |||
| 53f4582202 | |||
| c7c6dcab65 | |||
| 3422c49e85 | |||
| deee0b8e14 | |||
| 3ac58e0c49 | |||
| 7243cb57b5 | |||
| 0276bd7b0b | |||
| 457759bb57 | |||
| de0f8ee2d3 | |||
| ebf97ece9b | |||
| 50a55f4bfb | |||
| 4ee5c6457b | |||
| d7b5fce7aa | |||
| c3d9c1131b | |||
| 5bdfb1ba5c | |||
| 94e51f0047 | |||
| f313e95e2f | |||
| 2b13ac99b4 | |||
| ef220882d4 | |||
| 59e26178ee | |||
| 0d420fb0a5 | |||
| fce195fdba | |||
| 554b1eb022 | |||
| e52bd918fb | |||
| 9d82d6d111 | |||
| 3593631e4a | |||
| 5b67403fb9 | |||
| 3a528d3b89 | |||
| 466bb97bc7 | |||
| 0d78416454 | |||
| 8ba58ba11e | |||
| be16fddc75 | |||
| e9bb9792ab | |||
| a7d6cba11d | |||
| f5846d5bc2 | |||
| 88d4a9b111 | |||
| d7779df1b7 | |||
| a67ff33054 | |||
| 61badfdcfe | |||
| 19dfbeb2b4 | |||
| 9f13616c24 | |||
| 7fcc188041 | |||
| b8c8d33c94 | |||
| 02909c03dd | |||
| d8c84cc4d6 | |||
| adbe0392ca | |||
| 3c6567ae64 | |||
| 11262836d2 | |||
| f26fd5384d | |||
| 085103b333 | |||
| 574f7f1abd | |||
| 31e161604a | |||
| e4e349bea8 | |||
| 6391b7ed3a | |||
| c225511f95 | |||
| 4eedbb235a | |||
| 548b8717b2 | |||
| a215b3d0bf | |||
| 03d5a133eb | |||
| b323c62a6e | |||
| 8384a411df | |||
| c56ebd9ceb | |||
| b081b20a83 | |||
| 866d547745 | |||
| 64e3f066a7 | |||
| 62520c9308 | |||
| e65d455c91 | |||
| 9b9c82a02a | |||
| 1a38a2503e | |||
| 318f293983 | |||
| 5f2aba19c2 | |||
| 814ee45b4d | |||
| 56ed915626 | |||
| 2de8f8bc21 | |||
| f04cb6f6a6 | |||
| 4c67f01efb | |||
| b69c2e1e94 | |||
| d27e3b49db | |||
| ac12455f97 | |||
| 0b92a59f1a | |||
| 474eff67fa | |||
| 1c6db86259 | |||
| 4a1ce8154a | |||
| e126c1f7f1 | |||
| 31772019cd | |||
| aca98ab04f | |||
| f925c6caf0 | |||
| 5369e5eab9 | |||
| 2e634c59a7 | |||
| d7383d74f3 | |||
| 9a62581272 | |||
| ebb8e4ef19 | |||
| a0057eb223 | |||
| 39195d79f5 | |||
| ede5ffaffc | |||
| ed16505137 | |||
| 03bec90b83 | |||
| add57b2c14 | |||
| e98d60d7ce | |||
| 927ca8970c | |||
| 47d222b13d | |||
| f47650d6c8 | |||
| 3b2481e5a5 | |||
| de47982585 | |||
| fafad41230 | |||
| 79df17710d | |||
| e039ea843c | |||
| e898f202b7 | |||
| ca75fec048 | |||
| 87aab4e31e | |||
| 370a4a3a03 | |||
| 9b6b2117dd | |||
| ea90d7b558 | |||
| 52e06a7eb4 | |||
| e6250fa312 | |||
| 6d9e6a0f38 | |||
| c8331f4cad | |||
| d5a2fc7b3a | |||
| 6559fadf7f | |||
| b68f02be6a | |||
| 3f6acbfd66 | |||
| a830881ba5 | |||
| a3a234b41b | |||
| 8730a84a8e | |||
| 5bdda911a9 | |||
| 419e16eb31 | |||
| dcc663891a | |||
| 9c85dc022d | |||
| 5b4e386b21 | |||
| f4e4f262ae | |||
| 75c81b3206 | |||
| b7657e488b | |||
| 546054615a | |||
| 6d4ba18d86 | |||
| 899a2bfc8a | |||
| 57096bd86e | |||
| 3049abf4f1 | |||
| 1dc42df59c | |||
| e2b85c91df | |||
| 796a7fba0a | |||
| fbcf44eeb9 | |||
| e594630314 | |||
| f4785099c2 | |||
| 9c2595d9ef | |||
| b04d3ba376 | |||
| 5ad1f0b61a | |||
| b2dfdda210 | |||
| 41ef3a26f5 | |||
| bae1b488de | |||
| 40cf2c441a | |||
| 34871b14b3 | |||
| c14b010f9e | |||
| 04f75e7e48 | |||
| 866dcd1e39 | |||
| a8526d698e | |||
| 3f5e0cdb1f | |||
| 96239a7812 | |||
| 762cfb8709 | |||
| 9835ad3396 | |||
| f73a3ac932 | |||
| 5af4d8d862 | |||
| 2c81195e79 | |||
| 4a9066fb6b | |||
| 86cc600ea3 | |||
| 459b109b5c | |||
| 08b6be93c4 | |||
| f0d3d41a1f | |||
| 9a42cab16d | |||
| 970db22702 | |||
| 2c7df5766c | |||
| 7ca2559f99 | |||
| b9dcafa04f | |||
| 260a7de083 | |||
| 51ca727ff2 | |||
| 84db9f6bcd | |||
| 660463908d | |||
| 0be844e015 | |||
| efa6e7d7c7 | |||
| 33c783bb7c | |||
| 16059211b9 | |||
| bb6c920767 | |||
| 8c4df963c9 | |||
| af737596ca | |||
| af2c4f50b6 | |||
| 02ed64557d | |||
| 38dabd8d0d | |||
| d9de5cfa33 | |||
| bdfbfde463 | |||
| 5179f38ad2 | |||
| f4e9abcd22 | |||
| 46ebd84b02 | |||
| d8d2f99a18 | |||
| cd3ec5f3bd | |||
| 32a16ef025 | |||
| 6af4e44f55 | |||
| 3cddc594b4 | |||
| d11aaed392 | |||
| 1bead28150 | |||
| 735bed5cd7 | |||
| 12e0d34885 | |||
| 43af3b8a3b | |||
| 8ff96b11c9 | |||
| df453158d6 | |||
| abeeadb661 | |||
| 752fe7fa0f | |||
| c5ec682088 | |||
| 58a569cd26 | |||
| 2e767a2586 | |||
| dc772d8759 | |||
| 9e70c7a32d | |||
| ba5e86e842 | |||
| b7313656e9 | |||
| 2eb695088f | |||
| eb612d47c0 | |||
| 2ba7b26e5d | |||
| 4cd0f7b56f | |||
| 600bf42a95 | |||
| 748e3e4248 | |||
| 8cf1b6427a | |||
| 7a888c6fdf | |||
| 9a9bb89d89 | |||
| 4cc14ddcc4 | |||
| 2dbf9d97cb | |||
| 91b6f3cc3e | |||
| 84cccffcbd | |||
| 7de346cf89 | |||
| d6c40aee01 | |||
| af16b3f059 | |||
| b1cde0716e | |||
| 45bcdb03d8 | |||
| 0841b8701d | |||
| 7ae228d8f4 | |||
| 916d33c8c0 | |||
| 9b4b2d1a46 | |||
| aef0a52c4b | |||
| 44682b5ef0 | |||
| f282ffd8a6 | |||
| dfbeb8b1f8 | |||
| fc06fe39a2 | |||
| caa94c142f | |||
| 1a5c54084e | |||
| 49d203e18d | |||
| 51c9b012e2 | |||
| 50b1175622 | |||
| 29ee5984fb | |||
| e542b25ffc | |||
| 516d3f04cf | |||
| 9225e0a630 | |||
| 08c09781c7 | |||
| 36a4d96f34 | |||
| 139c911350 | |||
| c92de832e4 | |||
| d9d62195cb | |||
| da9115d51b | |||
| bfddc1e4c1 | |||
| 080d75204e | |||
| 1367cad99d | |||
| 4f6d65ab95 | |||
| 4292d8ac03 | |||
| dcb6de2421 | |||
| 1f5ed41bb3 | |||
| 091e98aa74 | |||
| 0e38126fc5 | |||
| ecbe192a88 | |||
| f0ee49788c | |||
| d2ff3cb88d | |||
| 873d15a5e1 | |||
| 53792cc839 | |||
| 415ef1bf13 | |||
| edfe29b738 | |||
| a4f6426bf9 | |||
| 0870911b3c | |||
| 9f23887cc0 | |||
| 8ab269fa05 | |||
| 7b75f22a8e | |||
| ca0449e03d | |||
| 224e63d275 | |||
| 3d77283056 | |||
| 7cc473005b | |||
| f874284850 | |||
| 7b6077ba64 | |||
| 0d4188785b | |||
| 86c05267c2 | |||
| b4865520a4 | |||
| f52ebfb9c3 | |||
| 6ca2a3c539 | |||
| 717c9066d6 | |||
| 2760a17323 | |||
| 4e9f1bc0ed | |||
| d35023d14b | |||
| 400aa6ba6d | |||
| 2ba74ae120 | |||
| 9a4293a5b9 | |||
| cdddb44099 | |||
| d511aac301 |
+1
-11
@@ -14,7 +14,6 @@
|
|||||||
# contracts
|
# contracts
|
||||||
/contracts/mixnet @durch @jstuczyn
|
/contracts/mixnet @durch @jstuczyn
|
||||||
/contracts/vesting @durch @jstuczyn
|
/contracts/vesting @durch @jstuczyn
|
||||||
/contracts/service-provider-directory @octol
|
|
||||||
|
|
||||||
# crypto code
|
# crypto code
|
||||||
/common/crypto/ @jstuczyn
|
/common/crypto/ @jstuczyn
|
||||||
@@ -22,14 +21,5 @@
|
|||||||
/common/dkg/ @jstuczyn
|
/common/dkg/ @jstuczyn
|
||||||
/common/nymsphinx/ @jstuczyn
|
/common/nymsphinx/ @jstuczyn
|
||||||
|
|
||||||
# rust sdk
|
|
||||||
/sdk/rust/ @octol
|
|
||||||
|
|
||||||
# nym-connect (rust)
|
|
||||||
/nym-connect/desktop/src-tauri/ @octol
|
|
||||||
|
|
||||||
# nym-wallet (rust)
|
|
||||||
/nym-wallet/src-tauri/ @octol
|
|
||||||
|
|
||||||
# documentation
|
# documentation
|
||||||
/documentation @mfahampshire
|
/documentation @mfahampshire
|
||||||
|
|||||||
+3
-3
@@ -415,9 +415,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/undici": {
|
"node_modules/undici": {
|
||||||
"version": "5.28.5",
|
"version": "5.29.0",
|
||||||
"resolved": "https://registry.npmjs.org/undici/-/undici-5.28.5.tgz",
|
"resolved": "https://registry.npmjs.org/undici/-/undici-5.29.0.tgz",
|
||||||
"integrity": "sha512-zICwjrDrcrUE0pyyJc1I2QzBkLM8FINsgOrt6WjA+BgajVq9Nxu2PbFFXUrAggLfDXlZGZBVZYw7WNV5KiBiBA==",
|
"integrity": "sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fastify/busboy": "^2.0.0"
|
"@fastify/busboy": "^2.0.0"
|
||||||
|
|||||||
@@ -31,5 +31,3 @@ updates:
|
|||||||
update-types:
|
update-types:
|
||||||
- "patch"
|
- "patch"
|
||||||
open-pull-requests-limit: 10
|
open-pull-requests-limit: 10
|
||||||
assignees:
|
|
||||||
- "octol"
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ jobs:
|
|||||||
run: sudo apt-get install -y rsync
|
run: sudo apt-get install -y rsync
|
||||||
- uses: rlespinasse/github-slug-action@v3.x
|
- uses: rlespinasse/github-slug-action@v3.x
|
||||||
- name: Setup pnpm
|
- name: Setup pnpm
|
||||||
uses: pnpm/action-setup@v4.0.0
|
uses: pnpm/action-setup@v4.1.0
|
||||||
with:
|
with:
|
||||||
version: 9
|
version: 9
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
|
|||||||
@@ -38,15 +38,14 @@ jobs:
|
|||||||
rm -rf ci-builds || true
|
rm -rf ci-builds || true
|
||||||
mkdir -p $OUTPUT_DIR
|
mkdir -p $OUTPUT_DIR
|
||||||
echo $OUTPUT_DIR
|
echo $OUTPUT_DIR
|
||||||
|
|
||||||
- name: Install Dependencies (Linux)
|
- name: Install Dependencies (Linux)
|
||||||
run: sudo apt-get update && sudo apt-get -y install libudev-dev
|
run: sudo apt-get update && sudo apt-get -y install libudev-dev
|
||||||
|
|
||||||
- name: Sets env vars for tokio if set in manual dispatch inputs
|
- name: Sets env vars for tokio if set in manual dispatch inputs
|
||||||
run: |
|
|
||||||
echo 'RUSTFLAGS="--cfg tokio_unstable"' >> $GITHUB_ENV
|
|
||||||
if: github.event_name == 'workflow_dispatch' && inputs.add_tokio_unstable == true
|
if: github.event_name == 'workflow_dispatch' && inputs.add_tokio_unstable == true
|
||||||
|
run: |
|
||||||
|
echo "RUSTFLAGS=--cfg tokio_unstable" >> $GITHUB_ENV
|
||||||
|
echo "CARGO_FEATURES=--features tokio-console" >> $GITHUB_ENV
|
||||||
- name: Install Rust stable
|
- name: Install Rust stable
|
||||||
uses: actions-rs/toolchain@v1
|
uses: actions-rs/toolchain@v1
|
||||||
with:
|
with:
|
||||||
@@ -103,7 +102,6 @@ jobs:
|
|||||||
if [ ${{ github.event_name == 'workflow_dispatch' && inputs.enable_deb == true }} = true ]; then
|
if [ ${{ github.event_name == 'workflow_dispatch' && inputs.enable_deb == true }} = true ]; then
|
||||||
cp target/debian/*.deb $OUTPUT_DIR
|
cp target/debian/*.deb $OUTPUT_DIR
|
||||||
fi
|
fi
|
||||||
|
|
||||||
- name: Deploy branch to CI www
|
- name: Deploy branch to CI www
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
uses: easingthemes/ssh-deploy@main
|
uses: easingthemes/ssh-deploy@main
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ on:
|
|||||||
paths:
|
paths:
|
||||||
- 'clients/**'
|
- 'clients/**'
|
||||||
- 'common/**'
|
- 'common/**'
|
||||||
- 'explorer-api/**'
|
|
||||||
- 'gateway/**'
|
- 'gateway/**'
|
||||||
- 'integrations/**'
|
- 'integrations/**'
|
||||||
- 'nym-api/**'
|
- 'nym-api/**'
|
||||||
@@ -13,6 +12,7 @@ on:
|
|||||||
- 'nym-network-monitor/**'
|
- 'nym-network-monitor/**'
|
||||||
- 'nym-node/**'
|
- 'nym-node/**'
|
||||||
- 'nym-node-status-api/**'
|
- 'nym-node-status-api/**'
|
||||||
|
- 'nym-statistics-api/**'
|
||||||
- 'nym-outfox/**'
|
- 'nym-outfox/**'
|
||||||
- 'nym-validator-rewarder/**'
|
- 'nym-validator-rewarder/**'
|
||||||
- 'nyx-chain-watcher/**'
|
- 'nyx-chain-watcher/**'
|
||||||
@@ -38,7 +38,7 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
os: [ arc-ubuntu-22.04, custom-windows-11, custom-runner-mac-m1 ]
|
os: [ arc-linux-latest, custom-windows-11, custom-macos-15 ]
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
env:
|
env:
|
||||||
CARGO_TERM_COLOR: always
|
CARGO_TERM_COLOR: always
|
||||||
@@ -46,9 +46,9 @@ jobs:
|
|||||||
RUSTUP_PERMIT_COPY_RENAME: 1
|
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 cmake
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
if: contains(matrix.os, 'ubuntu')
|
if: contains(matrix.os, 'linux')
|
||||||
|
|
||||||
- name: Check out repository code
|
- name: Check out repository code
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
@@ -63,7 +63,7 @@ jobs:
|
|||||||
|
|
||||||
# To avoid running out of disk space, skip generating debug symbols
|
# To avoid running out of disk space, skip generating debug symbols
|
||||||
- name: Set debug to false (unix)
|
- name: Set debug to false (unix)
|
||||||
if: contains(matrix.os, 'ubuntu') || contains(matrix.os, 'mac')
|
if: contains(matrix.os, 'linux') || contains(matrix.os, 'mac')
|
||||||
run: |
|
run: |
|
||||||
sed -i.bak 's/\[profile.dev\]/\[profile.dev\]\ndebug = false/' Cargo.toml
|
sed -i.bak 's/\[profile.dev\]/\[profile.dev\]\ndebug = false/' Cargo.toml
|
||||||
git diff
|
git diff
|
||||||
@@ -93,21 +93,23 @@ jobs:
|
|||||||
command: build
|
command: build
|
||||||
|
|
||||||
- name: Build all examples
|
- name: Build all examples
|
||||||
if: contains(matrix.os, 'ubuntu')
|
if: contains(matrix.os, 'linux')
|
||||||
uses: actions-rs/cargo@v1
|
uses: actions-rs/cargo@v1
|
||||||
with:
|
with:
|
||||||
command: build
|
command: build
|
||||||
args: --workspace --examples
|
args: --workspace --examples
|
||||||
|
|
||||||
- name: Run all tests
|
- name: Run all tests
|
||||||
if: contains(matrix.os, 'ubuntu')
|
if: contains(matrix.os, 'linux')
|
||||||
uses: actions-rs/cargo@v1
|
uses: actions-rs/cargo@v1
|
||||||
|
env:
|
||||||
|
NYM_API: https://sandbox-nym-api1.nymtech.net/api
|
||||||
with:
|
with:
|
||||||
command: test
|
command: test
|
||||||
args: --workspace
|
args: --workspace
|
||||||
|
|
||||||
- name: Run expensive tests
|
- name: Run expensive tests
|
||||||
if: (github.ref == 'refs/heads/develop' || github.event.pull_request.base.ref == 'develop' || github.event.pull_request.base.ref == 'master') && contains(matrix.os, 'ubuntu')
|
if: (github.ref == 'refs/heads/develop' || github.event.pull_request.base.ref == 'develop' || github.event.pull_request.base.ref == 'master') && contains(matrix.os, 'linux')
|
||||||
uses: actions-rs/cargo@v1
|
uses: actions-rs/cargo@v1
|
||||||
with:
|
with:
|
||||||
command: test
|
command: test
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ jobs:
|
|||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Get version from cargo.toml
|
- name: Get version from cargo.toml
|
||||||
uses: mikefarah/yq@v4.45.1
|
uses: mikefarah/yq@v4.45.4
|
||||||
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
|
||||||
@@ -44,8 +44,10 @@ jobs:
|
|||||||
echo "Tag is empty"
|
echo "Tag is empty"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
# first, list all tags for logging purposes
|
||||||
curl -su ${{ secrets.HARBOR_ROBOT_USERNAME }}:${{ secrets.HARBOR_ROBOT_SECRET }} "$registry/v2/$repo_name/tags/list" | jq
|
curl -su ${{ secrets.HARBOR_ROBOT_USERNAME }}:${{ secrets.HARBOR_ROBOT_SECRET }} "$registry/v2/$repo_name/tags/list" | jq
|
||||||
exists=$(curl -su ${{ secrets.HARBOR_ROBOT_USERNAME }}:${{ secrets.HARBOR_ROBOT_SECRET }} "$registry/v2/$repo_name/tags/list" | jq --arg tag $TAG '.tags | contains([$tag])' )
|
# check if there's a matching tag
|
||||||
|
exists=$(curl -su ${{ secrets.HARBOR_ROBOT_USERNAME }}:${{ secrets.HARBOR_ROBOT_SECRET }} "$registry/v2/$repo_name/tags/list" | jq -r --arg tag "$TAG" 'any(.tags[]; . == $tag)' )
|
||||||
if [[ $exists = "true" ]]; then
|
if [[ $exists = "true" ]]; then
|
||||||
echo "Version '$TAG' defined in Cargo.toml ALREADY EXISTS as tag in harbor repo"
|
echo "Version '$TAG' defined in Cargo.toml ALREADY EXISTS as tag in harbor repo"
|
||||||
exit 1
|
exit 1
|
||||||
@@ -53,5 +55,5 @@ jobs:
|
|||||||
echo "Version '$TAG' doesn't exist on the remote"
|
echo "Version '$TAG' doesn't exist on the remote"
|
||||||
else
|
else
|
||||||
echo "Unknown output '$exists'"
|
echo "Unknown output '$exists'"
|
||||||
exit 1
|
exit 2
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -0,0 +1,59 @@
|
|||||||
|
name: ci-check-nym-stats-api-version
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
paths:
|
||||||
|
- "nym-statistics-api/**"
|
||||||
|
|
||||||
|
env:
|
||||||
|
WORKING_DIRECTORY: "nym-statistics-api"
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
check-if-tag-exists:
|
||||||
|
runs-on: arc-ubuntu-22.04-dind
|
||||||
|
steps:
|
||||||
|
- name: Checkout repo
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Get version from cargo.toml
|
||||||
|
uses: mikefarah/yq@v4.45.4
|
||||||
|
id: get_version
|
||||||
|
with:
|
||||||
|
cmd: yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/Cargo.toml
|
||||||
|
|
||||||
|
- name: Check if git tag exists
|
||||||
|
run: |
|
||||||
|
TAG=${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.result }}
|
||||||
|
if [[ -z "$TAG" ]]; then
|
||||||
|
echo "Tag is empty"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
git ls-remote --tags origin | awk '{print $2}'
|
||||||
|
if git ls-remote --tags origin | awk '{print $2}' | grep -q "refs/tags/$TAG$" ; then
|
||||||
|
echo "Tag '$TAG' ALREADY EXISTS on the remote"
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
echo "Tag '$TAG' does not exist on the remote"
|
||||||
|
fi
|
||||||
|
- name: Check if harbor tag exists
|
||||||
|
run: |
|
||||||
|
TAG=${{ steps.get_version.outputs.result }}
|
||||||
|
registry=https://harbor.nymte.ch
|
||||||
|
repo_name=nym/nym-statistics-api
|
||||||
|
if [[ -z $TAG ]]; then
|
||||||
|
echo "Tag is empty"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
# first, list all tags for logging purposes
|
||||||
|
curl -su ${{ secrets.HARBOR_ROBOT_USERNAME }}:${{ secrets.HARBOR_ROBOT_SECRET }} "$registry/v2/$repo_name/tags/list" | jq
|
||||||
|
# check if there's a matching tag
|
||||||
|
exists=$(curl -su ${{ secrets.HARBOR_ROBOT_USERNAME }}:${{ secrets.HARBOR_ROBOT_SECRET }} "$registry/v2/$repo_name/tags/list" | jq -r --arg tag "$TAG" 'any(.tags[]; . == $tag)' )
|
||||||
|
if [[ $exists = "true" ]]; then
|
||||||
|
echo "Version '$TAG' defined in Cargo.toml ALREADY EXISTS as tag in harbor repo"
|
||||||
|
exit 1
|
||||||
|
elif [[ $exists = "false" ]]; then
|
||||||
|
echo "Version '$TAG' doesn't exist on the remote"
|
||||||
|
else
|
||||||
|
echo "Unknown output '$exists'"
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
@@ -31,31 +31,26 @@ jobs:
|
|||||||
- name: Install Rust stable
|
- name: Install Rust stable
|
||||||
uses: actions-rs/toolchain@v1
|
uses: actions-rs/toolchain@v1
|
||||||
with:
|
with:
|
||||||
|
toolchain: stable
|
||||||
target: wasm32-unknown-unknown
|
target: wasm32-unknown-unknown
|
||||||
override: true
|
override: true
|
||||||
|
|
||||||
- name: Install wasm-opt
|
|
||||||
uses: ./.github/actions/install-wasm-opt
|
|
||||||
with:
|
|
||||||
version: '114'
|
|
||||||
|
|
||||||
- name: Install cosmwasm-check
|
- name: Install cosmwasm-check
|
||||||
run: cargo install cosmwasm-check
|
run: cargo install cosmwasm-check
|
||||||
|
|
||||||
- name: Build release contracts
|
- name: Build release contracts
|
||||||
run: make contracts
|
run: make publish-contracts
|
||||||
|
|
||||||
- name: Prepare build output
|
- name: Prepare build output
|
||||||
shell: bash
|
shell: bash
|
||||||
env:
|
env:
|
||||||
OUTPUT_DIR: ci-contract-builds/${{ github.ref_name }}
|
OUTPUT_DIR: ci-contract-builds/${{ github.ref_name }}
|
||||||
run: |
|
run: |
|
||||||
cp contracts/target/wasm32-unknown-unknown/release/mixnet_contract.wasm $OUTPUT_DIR
|
find contracts/artifacts -maxdepth 1 -type f -name '*.wasm' -exec cp {} $OUTPUT_DIR \;
|
||||||
cp contracts/target/wasm32-unknown-unknown/release/vesting_contract.wasm $OUTPUT_DIR
|
# Also include the optimizer-generated checksums if present
|
||||||
cp contracts/target/wasm32-unknown-unknown/release/nym_coconut_dkg.wasm $OUTPUT_DIR
|
if [ -f contracts/artifacts/checksums.txt ]; then
|
||||||
cp contracts/target/wasm32-unknown-unknown/release/cw3_flex_multisig.wasm $OUTPUT_DIR
|
cp contracts/artifacts/checksums.txt $OUTPUT_DIR
|
||||||
cp contracts/target/wasm32-unknown-unknown/release/cw4_group.wasm $OUTPUT_DIR
|
fi
|
||||||
cp contracts/target/wasm32-unknown-unknown/release/nym_ecash.wasm $OUTPUT_DIR
|
|
||||||
|
|
||||||
- name: Deploy branch to CI www
|
- name: Deploy branch to CI www
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ jobs:
|
|||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
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
|
||||||
|
|
||||||
@@ -27,7 +28,8 @@ jobs:
|
|||||||
uses: actions-rs/toolchain@v1
|
uses: actions-rs/toolchain@v1
|
||||||
with:
|
with:
|
||||||
profile: minimal
|
profile: minimal
|
||||||
toolchain: stable
|
# pinned due to issues building contracts
|
||||||
|
toolchain: 1.86.0
|
||||||
target: wasm32-unknown-unknown
|
target: wasm32-unknown-unknown
|
||||||
override: true
|
override: true
|
||||||
components: rustfmt, clippy
|
components: rustfmt, clippy
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ jobs:
|
|||||||
run: sudo apt-get install -y rsync
|
run: sudo apt-get install -y rsync
|
||||||
- uses: rlespinasse/github-slug-action@v3.x
|
- uses: rlespinasse/github-slug-action@v3.x
|
||||||
- name: Setup pnpm
|
- name: Setup pnpm
|
||||||
uses: pnpm/action-setup@v4.0.0
|
uses: pnpm/action-setup@v4.1.0
|
||||||
with:
|
with:
|
||||||
version: 9
|
version: 9
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
|
|||||||
@@ -16,8 +16,12 @@ jobs:
|
|||||||
CARGO_TERM_COLOR: always
|
CARGO_TERM_COLOR: always
|
||||||
RUSTUP_PERMIT_COPY_RENAME: 1
|
RUSTUP_PERMIT_COPY_RENAME: 1
|
||||||
steps:
|
steps:
|
||||||
- name: Install Dependencies (Linux)
|
- name: Install system dependencies
|
||||||
run: sudo apt-get update && sudo apt-get -y install libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev squashfs-tools
|
run: |
|
||||||
|
sudo apt-get update && sudo apt-get install -y libdbus-1-dev libmnl-dev libnftnl-dev \
|
||||||
|
libwebkit2gtk-4.1-dev build-essential curl wget libssl-dev jq \
|
||||||
|
libgtk-3-dev squashfs-tools libayatana-appindicator3-dev make libfuse2 unzip librsvg2-dev file \
|
||||||
|
libsoup-3.0-dev libjavascriptcoregtk-4.1-dev
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
|
|
||||||
- name: Check out repository code
|
- name: Check out repository code
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
name: Run SonarQube Scan
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- develop
|
||||||
|
# pull_request:
|
||||||
|
# types: [opened, synchronize, reopened]
|
||||||
|
jobs:
|
||||||
|
sonarqube:
|
||||||
|
name: SonarQube
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
|
||||||
|
- name: SonarQube Scan
|
||||||
|
uses: SonarSource/sonarqube-scan-action@v5
|
||||||
|
env:
|
||||||
|
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
name: Integration Tests
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
paths:
|
||||||
|
- "nym-api/**"
|
||||||
|
- "tests/**"
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
integration-tests:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
API_BASE_URL: http://localhost:8000
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Install Rust
|
||||||
|
uses: actions-rs/toolchain@v1
|
||||||
|
with:
|
||||||
|
toolchain: stable
|
||||||
|
override: true
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: sudo apt-get update && sudo apt-get install -y pkg-config libssl-dev
|
||||||
|
|
||||||
|
- name: Build nym-api
|
||||||
|
run: cargo build --package nym-api
|
||||||
|
|
||||||
|
- name: Run nym-api in the background
|
||||||
|
run: |
|
||||||
|
./target/debug/nym-api &
|
||||||
|
|
||||||
|
- name: Wait for nym-api to come alive
|
||||||
|
run: |
|
||||||
|
for i in {1..20}; do
|
||||||
|
curl -sSf http://localhost:8000/v1/status/config-score-details && break
|
||||||
|
echo "Waiting for nym-api to start..."
|
||||||
|
sleep 2
|
||||||
|
done
|
||||||
|
|
||||||
|
- name: Run integration tests
|
||||||
|
env:
|
||||||
|
NYM_API: https://sandbox-nym-api1.nymtech.net/api
|
||||||
|
run: cargo test --test public-api-tests -- --nocapture
|
||||||
@@ -20,8 +20,10 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
platform: [custom-ubuntu-22.04]
|
include:
|
||||||
runs-on: ${{ matrix.platform }}
|
- os: arc-ubuntu-22.04
|
||||||
|
target: x86_64-unknown-linux-gnu
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
|
||||||
outputs:
|
outputs:
|
||||||
release_id: ${{ steps.create-release.outputs.id }}
|
release_id: ${{ steps.create-release.outputs.id }}
|
||||||
@@ -54,7 +56,7 @@ jobs:
|
|||||||
- name: Install Rust stable
|
- name: Install Rust stable
|
||||||
uses: actions-rs/toolchain@v1
|
uses: actions-rs/toolchain@v1
|
||||||
with:
|
with:
|
||||||
toolchain: stable
|
toolchain: 1.86.0
|
||||||
override: true
|
override: true
|
||||||
|
|
||||||
- name: Build all binaries
|
- name: Build all binaries
|
||||||
@@ -68,7 +70,6 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
name: my-artifact
|
name: my-artifact
|
||||||
path: |
|
path: |
|
||||||
target/release/explorer-api
|
|
||||||
target/release/nym-client
|
target/release/nym-client
|
||||||
target/release/nym-socks5-client
|
target/release/nym-socks5-client
|
||||||
target/release/nym-api
|
target/release/nym-api
|
||||||
@@ -77,14 +78,13 @@ jobs:
|
|||||||
target/release/nymvisor
|
target/release/nymvisor
|
||||||
target/release/nym-node
|
target/release/nym-node
|
||||||
retention-days: 30
|
retention-days: 30
|
||||||
|
|
||||||
- id: create-release
|
- id: create-release
|
||||||
name: Upload to release based on tag name
|
name: Upload to release based on tag name
|
||||||
uses: softprops/action-gh-release@v2
|
uses: softprops/action-gh-release@da05d552573ad5aba039eaac05058a918a7bf631
|
||||||
if: github.event_name == 'release'
|
if: github.event_name == 'release'
|
||||||
with:
|
with:
|
||||||
files: |
|
files: |
|
||||||
target/release/explorer-api
|
|
||||||
target/release/nym-client
|
target/release/nym-client
|
||||||
target/release/nym-socks5-client
|
target/release/nym-socks5-client
|
||||||
target/release/nym-api
|
target/release/nym-api
|
||||||
|
|||||||
@@ -18,11 +18,7 @@ jobs:
|
|||||||
runs-on: ${{ matrix.platform }}
|
runs-on: ${{ matrix.platform }}
|
||||||
|
|
||||||
outputs:
|
outputs:
|
||||||
release_id: ${{ steps.create-release.outputs.id }}
|
release_tag: ${{ github.ref_name }}
|
||||||
release_date: ${{ fromJSON(steps.create-release.outputs.assets)[0].created_at }}
|
|
||||||
version: ${{ steps.release-info.outputs.version }}
|
|
||||||
filename: ${{ steps.release-info.outputs.filename }}
|
|
||||||
file_hash: ${{ steps.release-info.outputs.file_hash }}
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
@@ -33,10 +29,16 @@ jobs:
|
|||||||
node-version: 21
|
node-version: 21
|
||||||
|
|
||||||
- name: Install Rust stable
|
- name: Install Rust stable
|
||||||
uses: actions-rs/toolchain@v1
|
uses: dtolnay/rust-toolchain@stable
|
||||||
with:
|
with:
|
||||||
toolchain: stable
|
toolchain: stable
|
||||||
|
|
||||||
|
- name: Add Rust target for x86_64-apple-darwin
|
||||||
|
run: rustup target add x86_64-apple-darwin
|
||||||
|
|
||||||
|
- name: Set Cargo build target to x86_64
|
||||||
|
run: echo "CARGO_BUILD_TARGET=x86_64-apple-darwin" >> $GITHUB_ENV
|
||||||
|
|
||||||
- name: Install the Apple developer certificate for code signing
|
- name: Install the Apple developer certificate for code signing
|
||||||
env:
|
env:
|
||||||
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
|
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
|
||||||
@@ -66,12 +68,6 @@ jobs:
|
|||||||
fileName: '.env'
|
fileName: '.env'
|
||||||
encodedString: ${{ secrets.WALLET_ADMIN_ADDRESS }}
|
encodedString: ${{ secrets.WALLET_ADMIN_ADDRESS }}
|
||||||
|
|
||||||
- name: Add Rust target for x86_64-apple-darwin
|
|
||||||
run: rustup target add x86_64-apple-darwin
|
|
||||||
|
|
||||||
- name: Set Cargo build target to x86_64
|
|
||||||
run: echo "CARGO_BUILD_TARGET=x86_64-apple-darwin" >> $GITHUB_ENV
|
|
||||||
|
|
||||||
- name: Yarn cache clean
|
- name: Yarn cache clean
|
||||||
shell: bash
|
shell: bash
|
||||||
run: cd .. && yarn cache clean
|
run: cd .. && yarn cache clean
|
||||||
@@ -94,10 +90,22 @@ jobs:
|
|||||||
APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_IDENTITY_ID }}
|
APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_IDENTITY_ID }}
|
||||||
APPLE_ID: ${{ secrets.APPLE_ID }}
|
APPLE_ID: ${{ secrets.APPLE_ID }}
|
||||||
APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
|
APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
|
||||||
TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
|
# Tauri v2 specific environment variables
|
||||||
TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
|
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
|
||||||
|
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
|
||||||
|
TAURI_NOTARIZATION_USERNAME: ${{ secrets.APPLE_ID }}
|
||||||
|
TAURI_NOTARIZATION_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
|
||||||
|
TAURI_NOTARIZATION_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
||||||
run: |
|
run: |
|
||||||
yarn build-macx86
|
yarn build-macx86
|
||||||
|
|
||||||
|
- name: Create app tarball
|
||||||
|
run: |
|
||||||
|
# Navigate to where the app bundle is and create the tarball
|
||||||
|
cd target/x86_64-apple-darwin/release/bundle/macos
|
||||||
|
echo "Creating tarball from app bundle"
|
||||||
|
tar -czf nym-wallet.app.tar.gz NymWallet.app
|
||||||
|
cd -
|
||||||
|
|
||||||
- name: Upload Artifact
|
- name: Upload Artifact
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
@@ -120,22 +128,10 @@ jobs:
|
|||||||
nym-wallet/target/x86_64-apple-darwin/release/bundle/dmg/*.dmg
|
nym-wallet/target/x86_64-apple-darwin/release/bundle/dmg/*.dmg
|
||||||
nym-wallet/target/x86_64-apple-darwin/release/bundle/macos/*.app.tar.gz*
|
nym-wallet/target/x86_64-apple-darwin/release/bundle/macos/*.app.tar.gz*
|
||||||
|
|
||||||
- name: Deploy artifacts to CI www
|
|
||||||
continue-on-error: true
|
|
||||||
uses: easingthemes/ssh-deploy@main
|
|
||||||
env:
|
|
||||||
SSH_PRIVATE_KEY: ${{ secrets.CI_WWW_SSH_PRIVATE_KEY }}
|
|
||||||
ARGS: "-avzr"
|
|
||||||
SOURCE: "nym-wallet/target/x86_64-apple-darwin/release/bundle/macos/nym-wallet.app.tar.gz"
|
|
||||||
REMOTE_HOST: ${{ secrets.CI_WWW_REMOTE_HOST }}
|
|
||||||
REMOTE_USER: ${{ secrets.CI_WWW_REMOTE_USER }}
|
|
||||||
TARGET: ${{ secrets.CI_WWW_REMOTE_TARGET }}/builds/${{ github.ref_name }}/nym-wallet
|
|
||||||
EXCLUDE: "/dist/, /node_modules/"
|
|
||||||
|
|
||||||
push-release-data:
|
push-release-data:
|
||||||
if: ${{ (startsWith(github.ref, 'refs/tags/nym-wallet-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }}
|
if: ${{ (startsWith(github.ref, 'refs/tags/nym-wallet-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }}
|
||||||
uses: ./.github/workflows/release-calculate-hash.yml
|
uses: ./.github/workflows/release-calculate-hash.yml
|
||||||
needs: publish-tauri
|
needs: publish-tauri
|
||||||
with:
|
with:
|
||||||
release_tag: ${{ github.ref_name }}
|
release_tag: ${{ needs.publish-tauri.outputs.release_tag || github.ref_name }}
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
@@ -3,71 +3,108 @@ on:
|
|||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
release:
|
release:
|
||||||
types: [created]
|
types: [created]
|
||||||
|
|
||||||
defaults:
|
defaults:
|
||||||
run:
|
run:
|
||||||
working-directory: nym-wallet
|
working-directory: nym-wallet
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
publish-tauri:
|
publish-tauri:
|
||||||
if: ${{ (startsWith(github.ref, 'refs/tags/nym-wallet-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }}
|
if: ${{ (startsWith(github.ref, 'refs/tags/nym-wallet-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }}
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
platform: [custom-ubuntu-22.04]
|
platform: [ubuntu-22.04]
|
||||||
runs-on: ${{ matrix.platform }}
|
runs-on: ${{ matrix.platform }}
|
||||||
|
|
||||||
outputs:
|
outputs:
|
||||||
release_id: ${{ steps.create-release.outputs.id }}
|
release_tag: ${{ github.ref_name }}
|
||||||
release_date: ${{ fromJSON(steps.create-release.outputs.assets)[0].created_at }}
|
|
||||||
version: ${{ steps.release-info.outputs.version }}
|
|
||||||
filename: ${{ steps.release-info.outputs.filename }}
|
|
||||||
file_hash: ${{ steps.release-info.outputs.file_hash }}
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Tauri dependencies
|
- name: Install system dependencies
|
||||||
run: >
|
run: |
|
||||||
sudo apt-get update &&
|
sudo apt-get update && sudo apt-get install -y libdbus-1-dev libmnl-dev libnftnl-dev \
|
||||||
sudo apt-get install -y webkit2gtk-4.0
|
libwebkit2gtk-4.1-dev build-essential curl wget libssl-dev jq \
|
||||||
continue-on-error: true
|
libgtk-3-dev squashfs-tools libayatana-appindicator3-dev make libfuse2 unzip librsvg2-dev file \
|
||||||
|
libsoup-3.0-dev libjavascriptcoregtk-4.1-dev
|
||||||
|
|
||||||
- name: Node
|
- name: Node
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 21
|
node-version: 21
|
||||||
|
cache: 'yarn'
|
||||||
|
|
||||||
- name: Install Rust stable
|
- name: Install Rust stable
|
||||||
uses: actions-rs/toolchain@v1
|
uses: dtolnay/rust-toolchain@stable
|
||||||
with:
|
with:
|
||||||
toolchain: stable
|
toolchain: stable
|
||||||
|
|
||||||
- name: Install project dependencies
|
- name: Install project dependencies
|
||||||
shell: bash
|
shell: bash
|
||||||
run: cd .. && yarn --network-timeout 100000
|
run: cd .. && yarn --network-timeout 100000
|
||||||
|
|
||||||
- name: Install app dependencies
|
- name: Install app dependencies
|
||||||
run: yarn
|
run: yarn
|
||||||
|
|
||||||
- name: Create env file
|
- name: Create env file
|
||||||
uses: timheuer/base64-to-file@v1.2
|
uses: timheuer/base64-to-file@v1.2
|
||||||
with:
|
with:
|
||||||
fileName: '.env'
|
fileName: '.env'
|
||||||
encodedString: ${{ secrets.WALLET_ADMIN_ADDRESS }}
|
encodedString: ${{ secrets.WALLET_ADMIN_ADDRESS }}
|
||||||
|
|
||||||
- name: Build app
|
- name: Build app
|
||||||
run: yarn build
|
run: yarn build
|
||||||
env:
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
|
TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
|
||||||
TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
|
TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
|
||||||
|
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
|
||||||
|
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
|
||||||
|
|
||||||
|
- name: Check bundle directory
|
||||||
|
run: |
|
||||||
|
echo "Checking bundle directory structure"
|
||||||
|
ls -la target/release/bundle || echo "Bundle directory not found"
|
||||||
|
if [ -d "target/release/bundle/appimage" ]; then
|
||||||
|
echo "AppImage bundle directory exists, checking contents:"
|
||||||
|
ls -la target/release/bundle/appimage
|
||||||
|
else
|
||||||
|
echo "AppImage bundle directory not found, checking alternatives:"
|
||||||
|
find target/release/bundle -type d -name "*appimage*" -o -name "*AppImage*" || echo "No AppImage directories found"
|
||||||
|
find target/release/bundle -name "*.AppImage" -o -name "*.appimage" || echo "No AppImage files found"
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Create AppImage tarball if needed
|
||||||
|
run: |
|
||||||
|
# Find the AppImage file
|
||||||
|
APPIMAGE_FILE=$(find target/release/bundle -name "*.AppImage" | head -n 1)
|
||||||
|
if [ -n "$APPIMAGE_FILE" ]; then
|
||||||
|
echo "Found AppImage file: $APPIMAGE_FILE"
|
||||||
|
APPIMAGE_DIR=$(dirname "$APPIMAGE_FILE")
|
||||||
|
APPIMAGE_NAME=$(basename "$APPIMAGE_FILE")
|
||||||
|
|
||||||
|
# Create tarball if it doesn't exist
|
||||||
|
if [ ! -f "${APPIMAGE_FILE}.tar.gz" ]; then
|
||||||
|
echo "Creating tarball for $APPIMAGE_NAME"
|
||||||
|
cd "$APPIMAGE_DIR"
|
||||||
|
tar -czf "${APPIMAGE_NAME}.tar.gz" "$APPIMAGE_NAME"
|
||||||
|
cd -
|
||||||
|
echo "Created tarball: ${APPIMAGE_FILE}.tar.gz"
|
||||||
|
else
|
||||||
|
echo "Tarball already exists: ${APPIMAGE_FILE}.tar.gz"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "WARNING: No AppImage file found!"
|
||||||
|
fi
|
||||||
|
|
||||||
- name: Upload Artifact
|
- name: Upload Artifact
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: nym-wallet_1.0.0_amd64.AppImage.tar.gz
|
name: nym-wallet-appimage.tar.gz
|
||||||
path: nym-wallet/target/release/bundle/appimage/nym-wallet*.AppImage.tar.gz
|
path: |
|
||||||
|
nym-wallet/target/release/bundle/appimage/*.AppImage.tar.gz
|
||||||
|
nym-wallet/target/release/bundle/*/nym-wallet*.AppImage.tar.gz
|
||||||
retention-days: 30
|
retention-days: 30
|
||||||
|
|
||||||
- id: create-release
|
- id: create-release
|
||||||
name: Upload to release based on tag name
|
name: Upload to release based on tag name
|
||||||
uses: softprops/action-gh-release@v2
|
uses: softprops/action-gh-release@v2
|
||||||
@@ -75,24 +112,26 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
files: |
|
files: |
|
||||||
nym-wallet/target/release/bundle/appimage/*.AppImage
|
nym-wallet/target/release/bundle/appimage/*.AppImage
|
||||||
nym-wallet/target/release/bundle/appimage/*.AppImage.tar.gz*
|
nym-wallet/target/release/bundle/appimage/*.AppImage.tar.gz
|
||||||
|
nym-wallet/target/release/bundle/*/nym-wallet*.AppImage
|
||||||
- name: Deploy artifacts to CI www
|
nym-wallet/target/release/bundle/*/nym-wallet*.AppImage.tar.gz
|
||||||
continue-on-error: true
|
|
||||||
uses: easingthemes/ssh-deploy@main
|
- name: Find AppImage tarball path for deployment
|
||||||
env:
|
id: find-appimage
|
||||||
SSH_PRIVATE_KEY: ${{ secrets.CI_WWW_SSH_PRIVATE_KEY }}
|
run: |
|
||||||
ARGS: "-avzr"
|
APPIMAGE_TARBALL=$(find target/release/bundle -name "*.AppImage.tar.gz" | head -n 1)
|
||||||
SOURCE: "nym-wallet/target/release/bundle/appimage/nym-wallet*.AppImage.tar.gz"
|
if [ -n "$APPIMAGE_TARBALL" ]; then
|
||||||
REMOTE_HOST: ${{ secrets.CI_WWW_REMOTE_HOST }}
|
echo "Found AppImage tarball: $APPIMAGE_TARBALL"
|
||||||
REMOTE_USER: ${{ secrets.CI_WWW_REMOTE_USER }}
|
echo "appimage_path=$APPIMAGE_TARBALL" >> $GITHUB_OUTPUT
|
||||||
TARGET: ${{ secrets.CI_WWW_REMOTE_TARGET }}/builds/${{ github.ref_name }}/nym-wallet
|
else
|
||||||
EXCLUDE: "/dist/, /node_modules/"
|
echo "WARNING: No AppImage tarball found for deployment!"
|
||||||
|
echo "appimage_path=target/release/bundle/appimage/nym-wallet*.AppImage.tar.gz" >> $GITHUB_OUTPUT
|
||||||
|
fi
|
||||||
|
|
||||||
push-release-data:
|
push-release-data:
|
||||||
if: ${{ (startsWith(github.ref, 'refs/tags/nym-wallet-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }}
|
if: ${{ (startsWith(github.ref, 'refs/tags/nym-wallet-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }}
|
||||||
uses: ./.github/workflows/release-calculate-hash.yml
|
uses: ./.github/workflows/release-calculate-hash.yml
|
||||||
needs: publish-tauri
|
needs: publish-tauri
|
||||||
with:
|
with:
|
||||||
release_tag: ${{ github.ref_name }}
|
release_tag: ${{ needs.publish-tauri.outputs.release_tag || github.ref_name }}
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
@@ -1,6 +1,12 @@
|
|||||||
name: publish-nym-wallet-win11
|
name: publish-nym-wallet-win11
|
||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
sign:
|
||||||
|
description: "Sign this build using SSL.com. Signing is billed per signature so be careful"
|
||||||
|
required: false
|
||||||
|
type: boolean
|
||||||
|
default: true
|
||||||
release:
|
release:
|
||||||
types: [created]
|
types: [created]
|
||||||
|
|
||||||
@@ -18,53 +24,61 @@ jobs:
|
|||||||
runs-on: ${{ matrix.platform }}
|
runs-on: ${{ matrix.platform }}
|
||||||
|
|
||||||
outputs:
|
outputs:
|
||||||
release_id: ${{ steps.create-release.outputs.id }}
|
release_tag: ${{ github.ref_name }}
|
||||||
release_date: ${{ fromJSON(steps.create-release.outputs.assets)[0].created_at }}
|
|
||||||
version: ${{ steps.release-info.outputs.version }}
|
|
||||||
filename: ${{ steps.release-info.outputs.filename }}
|
|
||||||
file_hash: ${{ steps.release-info.outputs.file_hash }}
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Clean up first
|
|
||||||
continue-on-error: true
|
|
||||||
working-directory: .
|
|
||||||
run: |
|
|
||||||
cd ..
|
|
||||||
del /s /q /A:H nym
|
|
||||||
rmdir /s /q nym
|
|
||||||
|
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Import signing certificate
|
- name: Install Rust stable
|
||||||
env:
|
uses: dtolnay/rust-toolchain@stable
|
||||||
WINDOWS_CERTIFICATE: ${{ secrets.WINDOWS_CERTIFICATE }}
|
with:
|
||||||
WINDOWS_CERTIFICATE_PASSWORD: ${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }}
|
toolchain: stable
|
||||||
run: |
|
|
||||||
New-Item -ItemType directory -Path certificate
|
- name: Setup MSBuild.exe
|
||||||
Set-Content -Path certificate/tempCert.txt -Value $env:WINDOWS_CERTIFICATE
|
uses: microsoft/setup-msbuild@v2
|
||||||
certutil -decode certificate/tempCert.txt certificate/certificate.pfx
|
|
||||||
Remove-Item -path certificate -include tempCert.txt
|
|
||||||
Import-PfxCertificate -FilePath certificate/certificate.pfx -CertStoreLocation Cert:\CurrentUser\My -Password (ConvertTo-SecureString -String $env:WINDOWS_CERTIFICATE_PASSWORD -Force -AsPlainText)
|
|
||||||
|
|
||||||
- name: Node
|
- name: Node
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 21
|
node-version: 21
|
||||||
|
|
||||||
- name: Install Rust stable
|
- name: Download EV CodeSignTool from ssl.com
|
||||||
uses: actions-rs/toolchain@v1
|
working-directory: nym-wallet/src-tauri
|
||||||
with:
|
if: ${{ inputs.sign }}
|
||||||
toolchain: stable
|
shell: bash
|
||||||
|
run: |
|
||||||
- name: Create env file
|
curl -L0 https://www.ssl.com/download/codesigntool-for-linux-and-macos/ -o codesigntool.zip
|
||||||
uses: timheuer/base64-to-file@v1.2
|
unzip codesigntool.zip
|
||||||
with:
|
- name: Get EV certificate credential id
|
||||||
fileName: '.env'
|
working-directory: nym-wallet/src-tauri
|
||||||
encodedString: ${{ secrets.WALLET_ADMIN_ADDRESS }}
|
if: ${{ inputs.sign }}
|
||||||
|
id: get_credential_ids
|
||||||
- name: Install Yarn
|
shell: bash
|
||||||
run: npm install -g yarn
|
run: |
|
||||||
|
echo "SSL_COM_CREDENTIAL_ID=$(./CodeSignTool.sh get_credential_ids -username=${{ secrets.SSL_COM_USERNAME }} -password=${{ secrets.SSL_COM_PASSWORD }} | sed -n '1!p' | sed 's/- //')" >> "$GITHUB_OUTPUT"
|
||||||
|
- name: Add custom sign command to tauri.conf.json
|
||||||
|
working-directory: nym-wallet/src-tauri
|
||||||
|
if: ${{ inputs.sign }}
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
yq eval --inplace '.bundle.windows +=
|
||||||
|
{
|
||||||
|
"signCommand": {
|
||||||
|
"cmd": "C:\Program Files\Git\bin\bash.EXE",
|
||||||
|
"args": [
|
||||||
|
"/c/actions-runner/_work/nym/nym/nym-wallet/src-tauri/CodeSignTool.sh",
|
||||||
|
"sign",
|
||||||
|
"-username ${{ secrets.SSL_COM_USERNAME }}",
|
||||||
|
"-password ${{ secrets.SSL_COM_PASSWORD }}",
|
||||||
|
"-credential_id ${{ steps.get_credential_ids.outputs.SSL_COM_CREDENTIAL_ID }}",
|
||||||
|
"-totp_secret ${{ secrets.SSL_COM_TOTP_SECRET }}",
|
||||||
|
"-program_name NymWallet",
|
||||||
|
"-input_file_path",
|
||||||
|
"%1",
|
||||||
|
"-override"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}' tauri.conf.json
|
||||||
- name: Install project dependencies
|
- name: Install project dependencies
|
||||||
shell: bash
|
shell: bash
|
||||||
run: cd .. && yarn --network-timeout 100000
|
run: cd .. && yarn --network-timeout 100000
|
||||||
@@ -77,18 +91,50 @@ jobs:
|
|||||||
shell: bash
|
shell: bash
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
ENABLE_CODE_SIGNING: ${{ secrets.WINDOWS_CERTIFICATE }}
|
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
|
||||||
WINDOWS_CERTIFICATE: ${{ secrets.WINDOWS_CERTIFICATE }}
|
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
|
||||||
WINDOWS_CERTIFICATE_PASSWORD: ${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }}
|
SSL_COM_USERNAME: ${{ inputs.sign && secrets.SSL_COM_USERNAME }}
|
||||||
TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
|
SSL_COM_PASSWORD: ${{ inputs.sign && secrets.SSL_COM_PASSWORD }}
|
||||||
TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
|
SSL_COM_CREDENTIAL_ID: ${{ inputs.sign && steps.get_credential_ids.outputs.SSL_COM_CREDENTIAL_ID }}
|
||||||
run: yarn build
|
SSL_COM_TOTP_SECRET: ${{ inputs.sign && secrets.SSL_COM_TOTP_SECRET }}
|
||||||
|
run: |
|
||||||
|
echo "Starting build process..."
|
||||||
|
yarn build
|
||||||
|
|
||||||
|
- name: Check bundle directory
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
echo "Checking bundle directory structure"
|
||||||
|
|
||||||
|
# Check standard location
|
||||||
|
if [ -d "target/release/bundle" ]; then
|
||||||
|
echo "Found bundle directory at standard location"
|
||||||
|
ls -la target/release/bundle || echo "Failed to list bundle directory"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check src-tauri location
|
||||||
|
if [ -d "src-tauri/target/release/bundle" ]; then
|
||||||
|
echo "Found bundle directory in src-tauri"
|
||||||
|
ls -la src-tauri/target/release/bundle || echo "Failed to list src-tauri bundle directory"
|
||||||
|
|
||||||
|
# Use this path for future steps
|
||||||
|
echo "BUNDLE_PATH=src-tauri/target/release/bundle" >> $GITHUB_ENV
|
||||||
|
else
|
||||||
|
echo "Using standard bundle path"
|
||||||
|
echo "BUNDLE_PATH=target/release/bundle" >> $GITHUB_ENV
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check for MSI files in any location
|
||||||
|
find . -name "*.msi" -type f
|
||||||
|
|
||||||
- name: Upload Artifact
|
- name: Upload Artifact
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: nym-wallet_1.0.0_x64_en-US.msi
|
name: nym-wallet.msi
|
||||||
path: nym-wallet/target/release/bundle/msi/nym-wallet_1.*.msi
|
path: |
|
||||||
|
nym-wallet/${{ env.BUNDLE_PATH }}/msi/*.msi
|
||||||
|
nym-wallet/${{ env.BUNDLE_PATH }}/*/nym-wallet*.msi
|
||||||
|
nym-wallet/src-tauri/target/release/bundle/msi/*.msi
|
||||||
retention-days: 30
|
retention-days: 30
|
||||||
|
|
||||||
- id: create-release
|
- id: create-release
|
||||||
@@ -97,25 +143,28 @@ jobs:
|
|||||||
if: github.event_name == 'release'
|
if: github.event_name == 'release'
|
||||||
with:
|
with:
|
||||||
files: |
|
files: |
|
||||||
nym-wallet/target/release/bundle/msi/*.msi
|
nym-wallet/${{ env.BUNDLE_PATH }}/msi/*.msi
|
||||||
nym-wallet/target/release/bundle/msi/*.msi.zip*
|
nym-wallet/${{ env.BUNDLE_PATH }}/msi/*.msi.zip*
|
||||||
|
nym-wallet/${{ env.BUNDLE_PATH }}/*/nym-wallet*.msi
|
||||||
- name: Deploy artifacts to CI www
|
nym-wallet/src-tauri/target/release/bundle/msi/*.msi
|
||||||
continue-on-error: true
|
|
||||||
uses: easingthemes/ssh-deploy@main
|
- name: Find MSI path for deployment
|
||||||
env:
|
id: find-msi
|
||||||
SSH_PRIVATE_KEY: ${{ secrets.CI_WWW_SSH_PRIVATE_KEY }}
|
shell: bash
|
||||||
ARGS: "-avzr"
|
run: |
|
||||||
SOURCE: "nym-wallet/target/release/bundle/msi/nym-wallet_1.*.msi"
|
MSI_FILE=$(find . -name "*.msi" -type f | head -n 1)
|
||||||
REMOTE_HOST: ${{ secrets.CI_WWW_REMOTE_HOST }}
|
if [ -n "$MSI_FILE" ]; then
|
||||||
REMOTE_USER: ${{ secrets.CI_WWW_REMOTE_USER }}
|
echo "Found MSI file: $MSI_FILE"
|
||||||
TARGET: ${{ secrets.CI_WWW_REMOTE_TARGET }}/builds/${{ github.ref_name }}/nym-wallet
|
echo "msi_path=$MSI_FILE" >> $GITHUB_OUTPUT
|
||||||
EXCLUDE: "/dist/, /node_modules/"
|
else
|
||||||
|
echo "WARNING: No MSI file found for deployment!"
|
||||||
|
echo "msi_path=${{ env.BUNDLE_PATH }}/msi/nym-wallet*.msi" >> $GITHUB_OUTPUT
|
||||||
|
fi
|
||||||
|
|
||||||
push-release-data:
|
push-release-data:
|
||||||
if: ${{ (startsWith(github.ref, 'refs/tags/nym-wallet-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }}
|
if: ${{ (startsWith(github.ref, 'refs/tags/nym-wallet-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }}
|
||||||
uses: ./.github/workflows/release-calculate-hash.yml
|
uses: ./.github/workflows/release-calculate-hash.yml
|
||||||
needs: publish-tauri
|
needs: publish-tauri
|
||||||
with:
|
with:
|
||||||
release_tag: ${{ github.ref_name }}
|
release_tag: ${{ needs.publish-tauri.outputs.release_tag || github.ref_name }}
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
@@ -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.45.4
|
||||||
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.45.4
|
||||||
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.45.4
|
||||||
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
|
||||||
|
|||||||
@@ -5,8 +5,15 @@ on:
|
|||||||
inputs:
|
inputs:
|
||||||
gateway_probe_git_ref:
|
gateway_probe_git_ref:
|
||||||
type: string
|
type: string
|
||||||
|
default: nym-vpn-core-v1.4.0
|
||||||
|
required: true
|
||||||
description: Which gateway probe git ref to build the image with
|
description: Which gateway probe git ref to build the image with
|
||||||
|
release_image:
|
||||||
|
description: 'Tag image as a release'
|
||||||
|
required: true
|
||||||
|
default: false
|
||||||
|
type: boolean
|
||||||
|
|
||||||
env:
|
env:
|
||||||
WORKING_DIRECTORY: "nym-node-status-api/nym-node-status-agent"
|
WORKING_DIRECTORY: "nym-node-status-api/nym-node-status-agent"
|
||||||
CONTAINER_NAME: "node-status-agent"
|
CONTAINER_NAME: "node-status-agent"
|
||||||
@@ -31,10 +38,10 @@ jobs:
|
|||||||
git config --global user.name "Lawrence Stalder"
|
git config --global user.name "Lawrence Stalder"
|
||||||
|
|
||||||
- name: Get version from cargo.toml
|
- name: Get version from cargo.toml
|
||||||
uses: mikefarah/yq@v4.45.1
|
|
||||||
id: get_version
|
id: get_version
|
||||||
with:
|
run: |
|
||||||
cmd: yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/Cargo.toml
|
VERSION=$(yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/Cargo.toml)
|
||||||
|
echo "result=$VERSION" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
- name: cleanup-gateway-probe-ref
|
- name: cleanup-gateway-probe-ref
|
||||||
id: cleanup_gateway_probe_ref
|
id: cleanup_gateway_probe_ref
|
||||||
@@ -43,19 +50,35 @@ jobs:
|
|||||||
GIT_REF_SLUG="${GATEWAY_PROBE_GIT_REF//\//-}"
|
GIT_REF_SLUG="${GATEWAY_PROBE_GIT_REF//\//-}"
|
||||||
echo "git_ref=${GIT_REF_SLUG}" >> $GITHUB_OUTPUT
|
echo "git_ref=${GIT_REF_SLUG}" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
- name: Remove existing tag if exists
|
- name: Set GIT_TAG variable
|
||||||
run: |
|
run: echo "GIT_TAG=${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.result }}-${{ steps.cleanup_gateway_probe_ref.outputs.git_ref }}" >> $GITHUB_ENV
|
||||||
if git rev-parse ${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.result }}-${{ steps.cleanup_gateway_probe_ref.outputs.git_ref }} >/dev/null 2>&1; then
|
|
||||||
git push --delete origin ${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.result }}-${{ steps.cleanup_gateway_probe_ref.outputs.git_ref }}
|
|
||||||
git tag -d ${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.result }}-${{ steps.cleanup_gateway_probe_ref.outputs.git_ref }}
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Create tag
|
- name: Initialize RELEASE_TAG
|
||||||
run: |
|
run: echo "RELEASE_TAG=" >> $GITHUB_ENV
|
||||||
git tag -a ${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.result }}-${{ steps.cleanup_gateway_probe_ref.outputs.git_ref }} -m "Version ${{ steps.get_version.outputs.result }}-${{ steps.cleanup_gateway_probe_ref.outputs.git_ref }}"
|
|
||||||
git push origin ${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.result }}-${{ steps.cleanup_gateway_probe_ref.outputs.git_ref }}
|
- name: Set RELEASE_TAG for release
|
||||||
|
if: github.event.inputs.release_image == 'true'
|
||||||
|
run: echo "RELEASE_TAG=golden-" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: Set IMAGE_NAME_AND_TAGS variable
|
||||||
|
run: echo "IMAGE_NAME_AND_TAGS=${{ env.CONTAINER_NAME }}:${{ env.RELEASE_TAG }}${{ steps.get_version.outputs.result }}-${{ steps.cleanup_gateway_probe_ref.outputs.git_ref }}" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: New env vars
|
||||||
|
run: echo "RELEASE_TAG='$RELEASE_TAG' GIT_TAG='$GIT_TAG' IMAGE_NAME_AND_TAGS='$IMAGE_NAME_AND_TAGS'"
|
||||||
|
|
||||||
|
# - name: Remove existing tag if exists
|
||||||
|
# run: |
|
||||||
|
# if git rev-parse $${{ env.GIT_TAG }} >/dev/null 2>&1; then
|
||||||
|
# git push --delete origin $${{ env.GIT_TAG }}
|
||||||
|
# git tag -d $${{ env.GIT_TAG }}
|
||||||
|
# fi
|
||||||
|
|
||||||
|
# - name: Create tag
|
||||||
|
# run: |
|
||||||
|
# git tag -a $${{ env.GIT_TAG }} -m "Version ${{ steps.get_version.outputs.result }}-${{ steps.cleanup_gateway_probe_ref.outputs.git_ref }}"
|
||||||
|
# git push origin $${{ env.GIT_TAG }}
|
||||||
|
|
||||||
- name: BuildAndPushImageOnHarbor
|
- name: BuildAndPushImageOnHarbor
|
||||||
run: |
|
run: |
|
||||||
docker build --build-arg GIT_REF=${{ github.event.inputs.gateway_probe_git_ref }} -f ${{ env.WORKING_DIRECTORY }}/Dockerfile . -t harbor.nymte.ch/nym/${{ env.CONTAINER_NAME }}:${{ steps.get_version.outputs.result }}-${{ steps.cleanup_gateway_probe_ref.outputs.git_ref }}
|
docker build --build-arg GIT_REF=${{ github.event.inputs.gateway_probe_git_ref }} -f ${{ env.WORKING_DIRECTORY }}/Dockerfile . -t harbor.nymte.ch/nym/${{ env.IMAGE_NAME_AND_TAGS }}
|
||||||
docker push harbor.nymte.ch/nym/${{ env.CONTAINER_NAME }} --all-tags
|
docker push harbor.nymte.ch/nym/${{ env.CONTAINER_NAME }} --all-tags
|
||||||
|
|||||||
@@ -1,7 +1,13 @@
|
|||||||
name: Build and upload Node Status API container to harbor.nymte.ch
|
name: Build and upload Node Status API container to harbor.nymte.ch
|
||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
release_image:
|
||||||
|
description: 'Tag image as a release'
|
||||||
|
required: true
|
||||||
|
default: false
|
||||||
|
type: boolean
|
||||||
|
|
||||||
env:
|
env:
|
||||||
WORKING_DIRECTORY: "nym-node-status-api/nym-node-status-api"
|
WORKING_DIRECTORY: "nym-node-status-api/nym-node-status-api"
|
||||||
CONTAINER_NAME: "node-status-api"
|
CONTAINER_NAME: "node-status-api"
|
||||||
@@ -26,30 +32,39 @@ 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
|
|
||||||
id: get_version
|
id: get_version
|
||||||
with:
|
|
||||||
cmd: yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/Cargo.toml
|
|
||||||
|
|
||||||
- name: Check if tag exists
|
|
||||||
run: |
|
run: |
|
||||||
if git rev-parse ${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.result }} >/dev/null 2>&1; then
|
yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/Cargo.toml
|
||||||
echo "Tag ${{ steps.get_version.outputs.result }} already exists"
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Remove existing tag if exists
|
- name: Set GIT_TAG variable
|
||||||
run: |
|
run: echo "GIT_TAG=${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.result }}" >> $GITHUB_ENV
|
||||||
if git rev-parse ${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.result }} >/dev/null 2>&1; then
|
|
||||||
git push --delete origin ${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.result }}
|
|
||||||
git tag -d ${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.result }}
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Create tag
|
- name: Set RELEASE_TAG variable
|
||||||
run: |
|
if: github.event.inputs.release_image == 'true'
|
||||||
git tag -a ${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.result }} -m "Version ${{ steps.get_version.outputs.result }}"
|
run: echo "RELEASE_TAG=golden-" >> $GITHUB_ENV
|
||||||
git push origin ${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.result }}
|
|
||||||
|
- name: Set IMAGE_NAME_AND_TAGS variable
|
||||||
|
run: echo "IMAGE_NAME_AND_TAGS=${{ env.CONTAINER_NAME }}:${{ env.RELEASE_TAG }}${{ steps.get_version.outputs.result }}" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: New env vars
|
||||||
|
run: echo "RELEASE_TAG='$RELEASE_TAG' GIT_TAG='$GIT_TAG' IMAGE_NAME_AND_TAGS='$IMAGE_NAME_AND_TAGS'"
|
||||||
|
|
||||||
|
# - name: Remove existing tag if exists, then create
|
||||||
|
# run: |
|
||||||
|
# if git rev-parse "$GIT_TAG" >/dev/null 2>&1; then
|
||||||
|
# echo "Tag '$GIT_TAG' already exists, deleting"
|
||||||
|
# git push --delete origin "$GIT_TAG"
|
||||||
|
# git tag -d "$GIT_TAG"
|
||||||
|
# echo "Tag '$GIT_TAG' deleted"
|
||||||
|
# else
|
||||||
|
# echo "Tag '$GIT_TAG' does not exist, creating it"
|
||||||
|
# git tag -a $GIT_TAG -m "Version ${{ steps.get_version.outputs.result }}"
|
||||||
|
# git push origin $GIT_TAG
|
||||||
|
# echo "Tag '$GIT_TAG' created"
|
||||||
|
# fi
|
||||||
|
|
||||||
- name: BuildAndPushImageOnHarbor
|
- name: BuildAndPushImageOnHarbor
|
||||||
run: |
|
run: |
|
||||||
docker build -f ${{ env.WORKING_DIRECTORY }}/Dockerfile . -t harbor.nymte.ch/nym/${{ env.CONTAINER_NAME }}:${{ steps.get_version.outputs.result }} -t harbor.nymte.ch/nym/${{ env.CONTAINER_NAME }}:latest
|
docker build -f ${{ env.WORKING_DIRECTORY }}/Dockerfile . -t harbor.nymte.ch/nym/${{ env.IMAGE_NAME_AND_TAGS }} -t harbor.nymte.ch/nym/${{ env.CONTAINER_NAME }}:latest
|
||||||
docker push harbor.nymte.ch/nym/${{ env.CONTAINER_NAME }} --all-tags
|
docker push harbor.nymte.ch/nym/${{ env.CONTAINER_NAME }} --all-tags
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
name: Build and upload Nym APU container to harbor.nymte.ch
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
env:
|
||||||
|
WORKING_DIRECTORY: "."
|
||||||
|
CONTAINER_NAME: "nym-api"
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-container:
|
||||||
|
runs-on: arc-ubuntu-22.04-dind
|
||||||
|
steps:
|
||||||
|
- name: Login to Harbor
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: harbor.nymte.ch
|
||||||
|
username: ${{ secrets.HARBOR_ROBOT_USERNAME }}
|
||||||
|
password: ${{ secrets.HARBOR_ROBOT_SECRET }}
|
||||||
|
|
||||||
|
- name: Checkout repo
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Configure git identity
|
||||||
|
run: |
|
||||||
|
git config --global user.email "lawrence@nymtech.net"
|
||||||
|
git config --global user.name "Lawrence Stalder"
|
||||||
|
|
||||||
|
- name: Get version from cargo.toml
|
||||||
|
uses: mikefarah/yq@v4.45.4
|
||||||
|
id: get_version
|
||||||
|
with:
|
||||||
|
cmd: yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/nym-api/Cargo.toml
|
||||||
|
|
||||||
|
- name: Remove existing tag if exists
|
||||||
|
run: |
|
||||||
|
echo "Checking if tag ${{ env.CONTAINER_NAME }}-${{ steps.get_version.outputs.result }} exists..."
|
||||||
|
if git rev-parse ${{ env.CONTAINER_NAME }}-${{ steps.get_version.outputs.result }} >/dev/null 2>&1; then
|
||||||
|
echo "Tag ${{ env.CONTAINER_NAME }}-${{ steps.get_version.outputs.result }} already exists"
|
||||||
|
git push --delete origin ${{ env.CONTAINER_NAME }}-${{ steps.get_version.outputs.result }}
|
||||||
|
git tag -d ${{ env.CONTAINER_NAME }}-${{ steps.get_version.outputs.result }}
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Create tag
|
||||||
|
run: |
|
||||||
|
git tag -a ${{ env.CONTAINER_NAME }}-${{ steps.get_version.outputs.result }} -m "Version ${{ steps.get_version.outputs.result }}"
|
||||||
|
git push origin ${{ env.CONTAINER_NAME }}-${{ steps.get_version.outputs.result }}
|
||||||
|
|
||||||
|
- name: BuildAndPushImageOnHarbor
|
||||||
|
run: |
|
||||||
|
docker build -f nym-api.dockerfile ${{ env.WORKING_DIRECTORY }} -t harbor.nymte.ch/nym/${{ env.CONTAINER_NAME }}:${{ steps.get_version.outputs.result }} -t harbor.nymte.ch/nym/${{ env.CONTAINER_NAME }}:latest
|
||||||
|
docker push harbor.nymte.ch/nym/${{ env.CONTAINER_NAME }} --all-tags
|
||||||
@@ -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.45.4
|
||||||
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
|
||||||
|
|||||||
@@ -0,0 +1,42 @@
|
|||||||
|
name: Build and upload Nym Statistics API container to harbor.nymte.ch
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
env:
|
||||||
|
WORKING_DIRECTORY: "nym-statistics-api"
|
||||||
|
CONTAINER_NAME: "nym-statistics-api"
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-container:
|
||||||
|
runs-on: arc-ubuntu-22.04-dind
|
||||||
|
steps:
|
||||||
|
- name: Login to Harbor
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: harbor.nymte.ch
|
||||||
|
username: ${{ secrets.HARBOR_ROBOT_USERNAME }}
|
||||||
|
password: ${{ secrets.HARBOR_ROBOT_SECRET }}
|
||||||
|
|
||||||
|
- name: Checkout repo
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Configure git identity
|
||||||
|
run: |
|
||||||
|
git config --global user.email "lawrence@nymtech.net"
|
||||||
|
git config --global user.name "Lawrence Stalder"
|
||||||
|
|
||||||
|
- name: Get version from cargo.toml
|
||||||
|
uses: mikefarah/yq@v4.45.4
|
||||||
|
id: get_version
|
||||||
|
with:
|
||||||
|
cmd: yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/Cargo.toml
|
||||||
|
|
||||||
|
- name: Create tag
|
||||||
|
run: |
|
||||||
|
git tag -a ${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.result }} -m "Version ${{ steps.get_version.outputs.result }}"
|
||||||
|
git push origin ${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.result }}
|
||||||
|
|
||||||
|
- name: BuildAndPushImageOnHarbor
|
||||||
|
run: |
|
||||||
|
docker build -f ${{ env.WORKING_DIRECTORY }}/Dockerfile . -t harbor.nymte.ch/nym/${{ env.CONTAINER_NAME }}:${{ steps.get_version.outputs.result }} -t harbor.nymte.ch/nym/${{ env.CONTAINER_NAME }}:latest
|
||||||
|
docker push harbor.nymte.ch/nym/${{ env.CONTAINER_NAME }} --all-tags
|
||||||
@@ -26,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.45.4
|
||||||
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.45.4
|
||||||
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
|
||||||
|
|||||||
+5
-1
@@ -35,12 +35,13 @@ validator-api/keypair
|
|||||||
contracts/mixnet/code_id
|
contracts/mixnet/code_id
|
||||||
contracts/mixnet/Justfile
|
contracts/mixnet/Justfile
|
||||||
contracts/mixnet/Makefile
|
contracts/mixnet/Makefile
|
||||||
|
artifacts
|
||||||
|
contracts/artifacts
|
||||||
validator-config
|
validator-config
|
||||||
*.patch
|
*.patch
|
||||||
validator-api-config.toml
|
validator-api-config.toml
|
||||||
dist
|
dist
|
||||||
storybook-static
|
storybook-static
|
||||||
envs/qwerty.env
|
|
||||||
.parcel-cache
|
.parcel-cache
|
||||||
**/.DS_Store
|
**/.DS_Store
|
||||||
cpu-cycles/libcpucycles/build
|
cpu-cycles/libcpucycles/build
|
||||||
@@ -59,3 +60,6 @@ nym-api/redocly/formatted-openapi.json
|
|||||||
|
|
||||||
*.sqlite
|
*.sqlite
|
||||||
.build
|
.build
|
||||||
|
|
||||||
|
**/settings.sql
|
||||||
|
**/enter_db.sh
|
||||||
|
|||||||
+302
@@ -4,6 +4,308 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
## [2025.15-gruyere] (2025-08-20)
|
||||||
|
|
||||||
|
- Migrate strum to 0.27.2 ([#5960])
|
||||||
|
- WG exit policy scripts update ([#5921])
|
||||||
|
- Make DNS Resolver fallback optional ([#5920])
|
||||||
|
- nym-node debug command to reset providers db ([#5914])
|
||||||
|
- basic zulip client for sending messages ([#5913])
|
||||||
|
- chore: allow compatibility with 'CDLA-Permissive-2.0' ([#5910])
|
||||||
|
- feat: ecash liveness check ([#5890])
|
||||||
|
- Remove old free credential handle ([#5864])
|
||||||
|
|
||||||
|
[#5960]: https://github.com/nymtech/nym/pull/5960
|
||||||
|
[#5921]: https://github.com/nymtech/nym/pull/5921
|
||||||
|
[#5920]: https://github.com/nymtech/nym/pull/5920
|
||||||
|
[#5914]: https://github.com/nymtech/nym/pull/5914
|
||||||
|
[#5913]: https://github.com/nymtech/nym/pull/5913
|
||||||
|
[#5910]: https://github.com/nymtech/nym/pull/5910
|
||||||
|
[#5890]: https://github.com/nymtech/nym/pull/5890
|
||||||
|
[#5864]: https://github.com/nymtech/nym/pull/5864
|
||||||
|
|
||||||
|
## [2025.14-feta] (2025-08-05)
|
||||||
|
|
||||||
|
- chore: nym node tokio console ([#5909])
|
||||||
|
- Feature/dkg snapshot epoch ([#5900])
|
||||||
|
- Feature/dkg epoch dealers query ([#5899])
|
||||||
|
- sqlx-pool-guard: allocate more memory on windows ([#5896])
|
||||||
|
- Support mnemonic in the NS agent ([#5883])
|
||||||
|
- Allow PG database backend ([#5880])
|
||||||
|
|
||||||
|
[#5909]: https://github.com/nymtech/nym/pull/5909
|
||||||
|
[#5900]: https://github.com/nymtech/nym/pull/5900
|
||||||
|
[#5899]: https://github.com/nymtech/nym/pull/5899
|
||||||
|
[#5896]: https://github.com/nymtech/nym/pull/5896
|
||||||
|
[#5883]: https://github.com/nymtech/nym/pull/5883
|
||||||
|
[#5880]: https://github.com/nymtech/nym/pull/5880
|
||||||
|
|
||||||
|
## [2025.13-emmental] (2025-07-22)
|
||||||
|
|
||||||
|
- fix: don't allow mixnode running in exit mode ([#5898])
|
||||||
|
- fix contract build process in Makefile ([#5892])
|
||||||
|
- bugfix: ignore 'Send' responses when claiming bandwidth ([#5884])
|
||||||
|
- Update push-node-status-agent.yaml ([#5882])
|
||||||
|
- listen for shutdown signals during nym-node startup ([#5879])
|
||||||
|
- feat: forbid running mixnode + entry on the same node ([#5878])
|
||||||
|
- chore: 1.88 clippy ([#5877])
|
||||||
|
- Batch SQL writes for packet stats ([#5874])
|
||||||
|
- fix the broken link ([#5873])
|
||||||
|
- Set busy_timeout in sqlx ([#5872])
|
||||||
|
- feat: basic performance contract integration [within Nym API] ([#5871])
|
||||||
|
- scraper bugfix: ignore precommits from missing validators ([#5867])
|
||||||
|
- Return true remaining ([#5866])
|
||||||
|
- Make Mix hops optional for Mixnet Client SURBs ([#5861])
|
||||||
|
- Check gateway supported versions ([#5860])
|
||||||
|
- Add build info endpoints ([#5857])
|
||||||
|
- Clear out screaming logs ([#5856])
|
||||||
|
- fix removal of qa env ([#5855])
|
||||||
|
- Use display when printing paths ([#5853])
|
||||||
|
- feat: initial performance contract ([#5833])
|
||||||
|
- Security patches for the `dkg` crate ([#5828])
|
||||||
|
- HTTP Discovery objects & network defaults ([#5814])
|
||||||
|
|
||||||
|
[#5898]: https://github.com/nymtech/nym/pull/5898
|
||||||
|
[#5892]: https://github.com/nymtech/nym/pull/5892
|
||||||
|
[#5884]: https://github.com/nymtech/nym/pull/5884
|
||||||
|
[#5882]: https://github.com/nymtech/nym/pull/5882
|
||||||
|
[#5879]: https://github.com/nymtech/nym/pull/5879
|
||||||
|
[#5878]: https://github.com/nymtech/nym/pull/5878
|
||||||
|
[#5877]: https://github.com/nymtech/nym/pull/5877
|
||||||
|
[#5874]: https://github.com/nymtech/nym/pull/5874
|
||||||
|
[#5873]: https://github.com/nymtech/nym/pull/5873
|
||||||
|
[#5872]: https://github.com/nymtech/nym/pull/5872
|
||||||
|
[#5871]: https://github.com/nymtech/nym/pull/5871
|
||||||
|
[#5867]: https://github.com/nymtech/nym/pull/5867
|
||||||
|
[#5866]: https://github.com/nymtech/nym/pull/5866
|
||||||
|
[#5861]: https://github.com/nymtech/nym/pull/5861
|
||||||
|
[#5860]: https://github.com/nymtech/nym/pull/5860
|
||||||
|
[#5857]: https://github.com/nymtech/nym/pull/5857
|
||||||
|
[#5856]: https://github.com/nymtech/nym/pull/5856
|
||||||
|
[#5855]: https://github.com/nymtech/nym/pull/5855
|
||||||
|
[#5853]: https://github.com/nymtech/nym/pull/5853
|
||||||
|
[#5833]: https://github.com/nymtech/nym/pull/5833
|
||||||
|
[#5828]: https://github.com/nymtech/nym/pull/5828
|
||||||
|
[#5814]: https://github.com/nymtech/nym/pull/5814
|
||||||
|
|
||||||
|
## [2025.12-dolcelatte] (2025-07-07)
|
||||||
|
|
||||||
|
- bugfix: key-rotation + reply SURBs ([#5876])
|
||||||
|
- Bugfix/backwards compat ([#5865])
|
||||||
|
- bugfix: allow gateways to permit authentication from v4 clients ([#5862])
|
||||||
|
- fixed client route for obtaining v2 list of gateways ([#5859])
|
||||||
|
- Updated browser extension piece removal ([#5849])
|
||||||
|
- Remove/old env references ([#5848])
|
||||||
|
- Remove qa env ([#5847])
|
||||||
|
- remove not used old mock-api ([#5845])
|
||||||
|
- remove bity dir ([#5844])
|
||||||
|
- build(deps-dev): bump webpack-dev-server from 4.13.2 to 5.2.1 in /wasm/mix-fetch/internal-dev ([#5843])
|
||||||
|
- Amended the buy section ([#5841])
|
||||||
|
- Removing test-net faucet ([#5840])
|
||||||
|
- Feature/node status dvpn directory ([#5829])
|
||||||
|
- build(deps-dev): bump webpack-dev-server from 4.15.2 to 5.2.1 in /nym-credential-proxy/vpn-api-lib-wasm/internal-dev ([#5826])
|
||||||
|
- bugfix: fix swapped total and circulating supplies ([#5822])
|
||||||
|
- build(deps): bump tar-fs from 3.0.8 to 3.0.9 in /sdk/typescript/tests/integration-tests/mix-fetch ([#5821])
|
||||||
|
- Url scheme warning log ([#5819])
|
||||||
|
- chore: adjust heuristic for wireguard peer activity ([#5818])
|
||||||
|
- Use the same client bandwidth for top up ([#5813])
|
||||||
|
- Replace chrono with time in NS API ([#5811])
|
||||||
|
- build(deps-dev): bump http-proxy-middleware from 2.0.4 to 2.0.9 in /clients/native/examples/js-examples/websocket ([#5810])
|
||||||
|
- build(deps): bump tokio from 1.44.2 to 1.45.1 ([#5798])
|
||||||
|
- Close sqlite pool before moving or reopening databases ([#5796])
|
||||||
|
- HTTP Client Retries, Fallbacks, and Redirects ([#5789])
|
||||||
|
- feat: key rotation ([#5777])
|
||||||
|
- build(deps): bump next from 14.2.15 to 14.2.26 in /documentation/docs ([#5772])
|
||||||
|
- build(deps): bump undici from 5.28.5 to 5.29.0 in /.github/actions/nym-hash-releases/src ([#5771])
|
||||||
|
- build(deps): bump cargo_metadata from 0.18.1 to 0.19.2 ([#5765])
|
||||||
|
- build(deps): bump tempfile from 3.19.1 to 3.20.0 ([#5764])
|
||||||
|
- [Feature] Noise XKpsk3 integration (2025 version) ([#5692])
|
||||||
|
- feature: nympool contract ([#5464])
|
||||||
|
- chore: fixed typo in API endpoint parameter ([#5449])
|
||||||
|
|
||||||
|
[#5876]: https://github.com/nymtech/nym/pull/5876
|
||||||
|
[#5865]: https://github.com/nymtech/nym/pull/5865
|
||||||
|
[#5862]: https://github.com/nymtech/nym/pull/5862
|
||||||
|
[#5859]: https://github.com/nymtech/nym/pull/5859
|
||||||
|
[#5849]: https://github.com/nymtech/nym/pull/5849
|
||||||
|
[#5848]: https://github.com/nymtech/nym/pull/5848
|
||||||
|
[#5847]: https://github.com/nymtech/nym/pull/5847
|
||||||
|
[#5845]: https://github.com/nymtech/nym/pull/5845
|
||||||
|
[#5844]: https://github.com/nymtech/nym/pull/5844
|
||||||
|
[#5843]: https://github.com/nymtech/nym/pull/5843
|
||||||
|
[#5841]: https://github.com/nymtech/nym/pull/5841
|
||||||
|
[#5840]: https://github.com/nymtech/nym/pull/5840
|
||||||
|
[#5829]: https://github.com/nymtech/nym/pull/5829
|
||||||
|
[#5826]: https://github.com/nymtech/nym/pull/5826
|
||||||
|
[#5822]: https://github.com/nymtech/nym/pull/5822
|
||||||
|
[#5821]: https://github.com/nymtech/nym/pull/5821
|
||||||
|
[#5819]: https://github.com/nymtech/nym/pull/5819
|
||||||
|
[#5818]: https://github.com/nymtech/nym/pull/5818
|
||||||
|
[#5813]: https://github.com/nymtech/nym/pull/5813
|
||||||
|
[#5811]: https://github.com/nymtech/nym/pull/5811
|
||||||
|
[#5810]: https://github.com/nymtech/nym/pull/5810
|
||||||
|
[#5798]: https://github.com/nymtech/nym/pull/5798
|
||||||
|
[#5796]: https://github.com/nymtech/nym/pull/5796
|
||||||
|
[#5789]: https://github.com/nymtech/nym/pull/5789
|
||||||
|
[#5777]: https://github.com/nymtech/nym/pull/5777
|
||||||
|
[#5772]: https://github.com/nymtech/nym/pull/5772
|
||||||
|
[#5771]: https://github.com/nymtech/nym/pull/5771
|
||||||
|
[#5765]: https://github.com/nymtech/nym/pull/5765
|
||||||
|
[#5764]: https://github.com/nymtech/nym/pull/5764
|
||||||
|
[#5692]: https://github.com/nymtech/nym/pull/5692
|
||||||
|
[#5464]: https://github.com/nymtech/nym/pull/5464
|
||||||
|
[#5449]: https://github.com/nymtech/nym/pull/5449
|
||||||
|
|
||||||
|
## [2025.11-cheddar] (2025-06-10)
|
||||||
|
|
||||||
|
- No autoremoval of peers ([#5831])
|
||||||
|
- Set cached storage counters to 0 ([#5812])
|
||||||
|
- hack: temporarily use next.config.js instead of next.config.ts ([#5805])
|
||||||
|
- chore: resolve 1.87 clippy warnings ([#5802])
|
||||||
|
- Nym Statistics API ([#5800])
|
||||||
|
- QoL: RequestPath trait for http-api-client ([#5788])
|
||||||
|
- Fix contains ticketbook function that always returned true ([#5787])
|
||||||
|
- swap a decode into a fromrow to please future postgres feature ([#5785])
|
||||||
|
- Make address cache configurable ([#5784])
|
||||||
|
- Track wireguard credential retries ([#5783])
|
||||||
|
|
||||||
|
[#5831]: https://github.com/nymtech/nym/pull/5831
|
||||||
|
[#5812]: https://github.com/nymtech/nym/pull/5812
|
||||||
|
[#5805]: https://github.com/nymtech/nym/pull/5805
|
||||||
|
[#5802]: https://github.com/nymtech/nym/pull/5802
|
||||||
|
[#5800]: https://github.com/nymtech/nym/pull/5800
|
||||||
|
[#5788]: https://github.com/nymtech/nym/pull/5788
|
||||||
|
[#5787]: https://github.com/nymtech/nym/pull/5787
|
||||||
|
[#5785]: https://github.com/nymtech/nym/pull/5785
|
||||||
|
[#5784]: https://github.com/nymtech/nym/pull/5784
|
||||||
|
[#5783]: https://github.com/nymtech/nym/pull/5783
|
||||||
|
|
||||||
|
## [2025.10-brie] (2025-05-27)
|
||||||
|
|
||||||
|
- Backport PR 5779 ([#5801])
|
||||||
|
- Expanded Accept Encoding for `reqwest` ([#5779])
|
||||||
|
- Teach HttpClientError how to report its status code and timeout ([#5770])
|
||||||
|
- Skip refreshing the topology on startup as we already have an initial set ([#5768])
|
||||||
|
- Fetch the topology from the nym-api concurrently ([#5767])
|
||||||
|
- feat: use bincode by default in NymApiClient + remove feature-lock ([#5761])
|
||||||
|
- Instrument create_request ([#5760])
|
||||||
|
- Add node_bonded field to delegations ([#5759])
|
||||||
|
- build(deps): bump mikefarah/yq from 4.45.1 to 4.45.4 ([#5758])
|
||||||
|
- Raw route submissions ([#5756])
|
||||||
|
- feat: expires header for `/active` nym-api responses ([#5755])
|
||||||
|
- Decrease default average packet delay to 15 ms ([#5754])
|
||||||
|
- build(deps): bump the patch-updates group across 1 directory with 12 updates ([#5753])
|
||||||
|
- Remove pretty_env_logger and switch remaining crates to use tracing ([#5749])
|
||||||
|
- Update pretty_env_logger to latest to not depend on unmaintained crate atty ([#5748])
|
||||||
|
- Upgrade prometheus crate to fix security warning ([#5747])
|
||||||
|
- Downgrade deranged crate to 0.4.0 ([#5746])
|
||||||
|
- feat: nym-api bincode + yaml support ([#5745])
|
||||||
|
- fix parallel feature in ecash crate with send + sync ([#5744])
|
||||||
|
- Remove old test directory - Update validator docker ([#5743])
|
||||||
|
- [Feature] `RememberMe` is the new don't `ForgetMe` ([#5742])
|
||||||
|
- build(deps): bump ammonia from 4.0.0 to 4.1.0 ([#5739])
|
||||||
|
- build(deps): bump base-x from 3.0.9 to 3.0.11 in /testnet-faucet ([#5737])
|
||||||
|
- build(deps): bump http-proxy-middleware from 2.0.8 to 2.0.9 ([#5730])
|
||||||
|
|
||||||
|
[#5801]: https://github.com/nymtech/nym/pull/5801
|
||||||
|
[#5779]: https://github.com/nymtech/nym/pull/5779
|
||||||
|
[#5770]: https://github.com/nymtech/nym/pull/5770
|
||||||
|
[#5768]: https://github.com/nymtech/nym/pull/5768
|
||||||
|
[#5767]: https://github.com/nymtech/nym/pull/5767
|
||||||
|
[#5761]: https://github.com/nymtech/nym/pull/5761
|
||||||
|
[#5760]: https://github.com/nymtech/nym/pull/5760
|
||||||
|
[#5759]: https://github.com/nymtech/nym/pull/5759
|
||||||
|
[#5758]: https://github.com/nymtech/nym/pull/5758
|
||||||
|
[#5756]: https://github.com/nymtech/nym/pull/5756
|
||||||
|
[#5755]: https://github.com/nymtech/nym/pull/5755
|
||||||
|
[#5754]: https://github.com/nymtech/nym/pull/5754
|
||||||
|
[#5753]: https://github.com/nymtech/nym/pull/5753
|
||||||
|
[#5749]: https://github.com/nymtech/nym/pull/5749
|
||||||
|
[#5748]: https://github.com/nymtech/nym/pull/5748
|
||||||
|
[#5747]: https://github.com/nymtech/nym/pull/5747
|
||||||
|
[#5746]: https://github.com/nymtech/nym/pull/5746
|
||||||
|
[#5745]: https://github.com/nymtech/nym/pull/5745
|
||||||
|
[#5744]: https://github.com/nymtech/nym/pull/5744
|
||||||
|
[#5743]: https://github.com/nymtech/nym/pull/5743
|
||||||
|
[#5742]: https://github.com/nymtech/nym/pull/5742
|
||||||
|
[#5739]: https://github.com/nymtech/nym/pull/5739
|
||||||
|
[#5737]: https://github.com/nymtech/nym/pull/5737
|
||||||
|
[#5730]: https://github.com/nymtech/nym/pull/5730
|
||||||
|
|
||||||
|
## [2025.9-appenzeller] (2025-05-13)
|
||||||
|
|
||||||
|
- build(deps): bump clap from 4.5.36 to 4.5.37 in the patch-updates group ([#5722])
|
||||||
|
- build(deps): bump golang.org/x/net from 0.36.0 to 0.38.0 in /wasm/mix-fetch/go-mix-conn ([#5720])
|
||||||
|
- build(deps-dev): bump http-proxy-middleware from 2.0.6 to 2.0.9 in /wasm/client/internal-dev ([#5719])
|
||||||
|
- Add /account/{address} ([#5673])
|
||||||
|
- Add contains ticketbook data db query ([#5670])
|
||||||
|
|
||||||
|
[#5722]: https://github.com/nymtech/nym/pull/5722
|
||||||
|
[#5720]: https://github.com/nymtech/nym/pull/5720
|
||||||
|
[#5719]: https://github.com/nymtech/nym/pull/5719
|
||||||
|
[#5673]: https://github.com/nymtech/nym/pull/5673
|
||||||
|
[#5670]: https://github.com/nymtech/nym/pull/5670
|
||||||
|
|
||||||
|
## [2025.8-tourist] (2025-04-29)
|
||||||
|
|
||||||
|
- add reserved byte to reply surb serialisation ([#5731])
|
||||||
|
- Remove inactive peers ([#5721])
|
||||||
|
- Update Hickory DNS "0.24.4" to "0.25" ([#5709])
|
||||||
|
- build(deps): bump the patch-updates group across 1 directory with 7 updates ([#5708])
|
||||||
|
- Peer handle should die more gracefully ([#5704])
|
||||||
|
- build(deps): bump crossbeam-channel from 0.5.14 to 0.5.15 ([#5702])
|
||||||
|
- build(deps): bump actions/checkout from 3 to 4 ([#5700])
|
||||||
|
- Feature/updated sphinx payload keys ([#5698])
|
||||||
|
- Bump the nym-vpn deb metapackage to 1.0 ([#5697])
|
||||||
|
- Make mix hops optional for Mixnet Client ([#5696])
|
||||||
|
- build(deps): bump tokio from 1.44.1 to 1.44.2 ([#5693])
|
||||||
|
- Feature/replay protection ([#5682])
|
||||||
|
- Adding fresh nym-api tests and workflow ([#5659])
|
||||||
|
- build(deps): bump next from 14.2.21 to 14.2.25 ([#5655])
|
||||||
|
- build(deps): bump pnpm/action-setup from 4.0.0 to 4.1.0 ([#5436])
|
||||||
|
|
||||||
|
[#5731]: https://github.com/nymtech/nym/pull/5731
|
||||||
|
[#5721]: https://github.com/nymtech/nym/pull/5721
|
||||||
|
[#5709]: https://github.com/nymtech/nym/pull/5709
|
||||||
|
[#5708]: https://github.com/nymtech/nym/pull/5708
|
||||||
|
[#5704]: https://github.com/nymtech/nym/pull/5704
|
||||||
|
[#5702]: https://github.com/nymtech/nym/pull/5702
|
||||||
|
[#5700]: https://github.com/nymtech/nym/pull/5700
|
||||||
|
[#5698]: https://github.com/nymtech/nym/pull/5698
|
||||||
|
[#5697]: https://github.com/nymtech/nym/pull/5697
|
||||||
|
[#5696]: https://github.com/nymtech/nym/pull/5696
|
||||||
|
[#5693]: https://github.com/nymtech/nym/pull/5693
|
||||||
|
[#5682]: https://github.com/nymtech/nym/pull/5682
|
||||||
|
[#5659]: https://github.com/nymtech/nym/pull/5659
|
||||||
|
[#5655]: https://github.com/nymtech/nym/pull/5655
|
||||||
|
[#5436]: https://github.com/nymtech/nym/pull/5436
|
||||||
|
|
||||||
|
## [2025.7-tex] (2025-04-14)
|
||||||
|
|
||||||
|
- Expand /v3/nym-nodes with geodata ([#5686])
|
||||||
|
- chore: clippy for 1.86 ([#5685])
|
||||||
|
- Featrure: Bash scripts to init and configure VMs conveniently and update docs ([#5681])
|
||||||
|
- Update node versions in CI ([#5677])
|
||||||
|
- build(deps): bump the patch-updates group across 1 directory with 8 updates ([#5668])
|
||||||
|
- Update log crate ([#5667])
|
||||||
|
- Minor fixes involving key cloning and hashing ([#5664])
|
||||||
|
- mix throughput tester ([#5661])
|
||||||
|
- build(deps): bump blake3 from 1.6.1 to 1.7.0 ([#5658])
|
||||||
|
- build(deps): bump elliptic from 6.5.5 to 6.6.1 ([#5483])
|
||||||
|
- Move all workflows on ubuntu-20 to ubuntu-22 ([#5455])
|
||||||
|
|
||||||
|
[#5686]: https://github.com/nymtech/nym/pull/5686
|
||||||
|
[#5685]: https://github.com/nymtech/nym/pull/5685
|
||||||
|
[#5681]: https://github.com/nymtech/nym/pull/5681
|
||||||
|
[#5677]: https://github.com/nymtech/nym/pull/5677
|
||||||
|
[#5668]: https://github.com/nymtech/nym/pull/5668
|
||||||
|
[#5667]: https://github.com/nymtech/nym/pull/5667
|
||||||
|
[#5664]: https://github.com/nymtech/nym/pull/5664
|
||||||
|
[#5661]: https://github.com/nymtech/nym/pull/5661
|
||||||
|
[#5658]: https://github.com/nymtech/nym/pull/5658
|
||||||
|
[#5483]: https://github.com/nymtech/nym/pull/5483
|
||||||
|
[#5455]: https://github.com/nymtech/nym/pull/5455
|
||||||
|
|
||||||
## [2025.6-chuckles] (2025-03-31)
|
## [2025.6-chuckles] (2025-03-31)
|
||||||
|
|
||||||
- Remove Google public DNS ([#5660])
|
- Remove Google public DNS ([#5660])
|
||||||
|
|||||||
@@ -0,0 +1,686 @@
|
|||||||
|
# CLAUDE.md
|
||||||
|
|
||||||
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||||
|
|
||||||
|
## Project Overview
|
||||||
|
|
||||||
|
Nym is a privacy platform that uses mixnet technology to protect against metadata surveillance. The platform consists of several key components:
|
||||||
|
- Mixnet nodes (mixnodes) for packet mixing
|
||||||
|
- Gateways (entry/exit points for the network)
|
||||||
|
- Clients for interacting with the network
|
||||||
|
- Network monitoring tools
|
||||||
|
- Validators for network consensus
|
||||||
|
- Various service providers and integrations
|
||||||
|
|
||||||
|
## Build Commands
|
||||||
|
|
||||||
|
### Rust Components
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Default build (debug)
|
||||||
|
cargo build
|
||||||
|
|
||||||
|
# Release build
|
||||||
|
cargo build --release
|
||||||
|
|
||||||
|
# Build a specific package
|
||||||
|
cargo build -p <package-name>
|
||||||
|
|
||||||
|
# Build main components
|
||||||
|
make build
|
||||||
|
|
||||||
|
# Build release versions of main binaries and contracts
|
||||||
|
make build-release
|
||||||
|
|
||||||
|
# Build specific binaries
|
||||||
|
make build-nym-cli
|
||||||
|
cargo build -p nym-node --release
|
||||||
|
cargo build -p nym-api --release
|
||||||
|
```
|
||||||
|
|
||||||
|
### Testing
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Run clippy, unit tests, and formatting
|
||||||
|
make test
|
||||||
|
|
||||||
|
# Run all tests including slow tests
|
||||||
|
make test-all
|
||||||
|
|
||||||
|
# Run clippy on all workspaces
|
||||||
|
make clippy
|
||||||
|
|
||||||
|
# Run unit tests for a specific package
|
||||||
|
cargo test -p <package-name>
|
||||||
|
|
||||||
|
# Run only expensive/ignored tests
|
||||||
|
cargo test --workspace -- --ignored
|
||||||
|
|
||||||
|
# Run API tests
|
||||||
|
dotenv -f envs/sandbox.env -- cargo test --test public-api-tests
|
||||||
|
|
||||||
|
# Run tests with specific log level
|
||||||
|
RUST_LOG=debug cargo test -p <package-name>
|
||||||
|
|
||||||
|
# Run specific test scripts
|
||||||
|
./nym-node/tests/test_apis.sh
|
||||||
|
./scripts/wireguard-exit-policy/exit-policy-tests.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
### Linting and Formatting
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Run rustfmt on all code
|
||||||
|
make fmt
|
||||||
|
|
||||||
|
# Check formatting without modifying
|
||||||
|
cargo fmt --all -- --check
|
||||||
|
|
||||||
|
# Run clippy with all targets
|
||||||
|
cargo clippy --workspace --all-targets -- -D warnings
|
||||||
|
|
||||||
|
# TypeScript linting
|
||||||
|
yarn lint
|
||||||
|
yarn lint:fix
|
||||||
|
yarn types:lint:fix
|
||||||
|
|
||||||
|
# Check dependencies for security/licensing issues
|
||||||
|
cargo deny check
|
||||||
|
```
|
||||||
|
|
||||||
|
### WASM Components
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Build all WASM components
|
||||||
|
make sdk-wasm-build
|
||||||
|
|
||||||
|
# Build TypeScript SDK
|
||||||
|
yarn build:sdk
|
||||||
|
npx lerna run --scope @nymproject/sdk build --stream
|
||||||
|
|
||||||
|
# Build and test WASM components
|
||||||
|
make sdk-wasm
|
||||||
|
|
||||||
|
# Build specific WASM packages
|
||||||
|
cd wasm/client && make
|
||||||
|
cd wasm/mix-fetch && make
|
||||||
|
cd wasm/node-tester && make
|
||||||
|
```
|
||||||
|
|
||||||
|
### Contract Development
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Build all contracts
|
||||||
|
make contracts
|
||||||
|
|
||||||
|
# Build contracts in release mode
|
||||||
|
make build-release-contracts
|
||||||
|
|
||||||
|
# Generate contract schemas
|
||||||
|
make contract-schema
|
||||||
|
|
||||||
|
# Run wasm-opt on contracts
|
||||||
|
make wasm-opt-contracts
|
||||||
|
|
||||||
|
# Check contracts with cosmwasm-check
|
||||||
|
make cosmwasm-check-contracts
|
||||||
|
```
|
||||||
|
|
||||||
|
### Running Components
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Run nym-node as a mixnode
|
||||||
|
cargo run -p nym-node -- run --mode mixnode
|
||||||
|
|
||||||
|
# Run nym-node as a gateway
|
||||||
|
cargo run -p nym-node -- run --mode gateway
|
||||||
|
|
||||||
|
# Run the network monitor
|
||||||
|
cargo run -p nym-network-monitor
|
||||||
|
|
||||||
|
# Run the API server
|
||||||
|
cargo run -p nym-api
|
||||||
|
|
||||||
|
# Run with specific environment
|
||||||
|
dotenv -f envs/sandbox.env -- cargo run -p nym-api
|
||||||
|
|
||||||
|
# Start a local network
|
||||||
|
./scripts/localnet_start.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
The Nym platform consists of various components organized as a monorepo:
|
||||||
|
|
||||||
|
1. **Core Mixnet Infrastructure**:
|
||||||
|
- `nym-node`: Core binary supporting mixnode and gateway modes
|
||||||
|
- `common/nymsphinx`: Implementation of the Sphinx packet format
|
||||||
|
- `common/topology`: Network topology management
|
||||||
|
- `common/types`: Shared data types across components
|
||||||
|
|
||||||
|
2. **Network Monitoring**:
|
||||||
|
- `nym-network-monitor`: Monitors the network's reliability and performance
|
||||||
|
- `nym-api`: API server for network stats and monitoring data
|
||||||
|
- Metrics tracking for nodes, routes, and overall network health
|
||||||
|
|
||||||
|
3. **Client Implementations**:
|
||||||
|
- `clients/native`: Native Rust client implementation
|
||||||
|
- `clients/socks5`: SOCKS5 proxy client for standard applications
|
||||||
|
- `wasm`: WebAssembly client implementations (for browsers)
|
||||||
|
- `nym-connect`: Desktop and mobile clients
|
||||||
|
|
||||||
|
4. **Blockchain & Smart Contracts**:
|
||||||
|
- `common/cosmwasm-smart-contracts`: Smart contract implementations
|
||||||
|
- `contracts`: CosmWasm contracts for the Nym network
|
||||||
|
- `common/ledger`: Blockchain integration
|
||||||
|
|
||||||
|
5. **Utilities & Tools**:
|
||||||
|
- `tools`: Various CLI tools and utilities
|
||||||
|
- `sdk`: SDKs for different languages and platforms
|
||||||
|
- `documentation`: Documentation generation and management
|
||||||
|
|
||||||
|
## Packet System
|
||||||
|
|
||||||
|
Nym uses a modified Sphinx packet format for its mixnet:
|
||||||
|
|
||||||
|
1. **Message Chunking**:
|
||||||
|
- Messages are divided into "sets" and "fragments"
|
||||||
|
- Each fragment fits in a single Sphinx packet
|
||||||
|
- The `common/nymsphinx/chunking` module handles message fragmentation
|
||||||
|
|
||||||
|
2. **Routing**:
|
||||||
|
- Packets traverse through 3 layers of mixnodes
|
||||||
|
- Routing information is encrypted in layers (onion routing)
|
||||||
|
- The final gateway receives and processes the messages
|
||||||
|
|
||||||
|
3. **Monitoring**:
|
||||||
|
- Monitoring system tracks packet delivery through the network
|
||||||
|
- Routes are analyzed for reliability statistics
|
||||||
|
- Node performance metrics are collected
|
||||||
|
|
||||||
|
## Network Protocol
|
||||||
|
|
||||||
|
Nym implements the Loopix mixnet design with several key privacy features:
|
||||||
|
|
||||||
|
1. **Continuous-time Mixing**:
|
||||||
|
- Each mixnode delays messages independently with an exponential distribution
|
||||||
|
- This creates random reordering of packets, destroying timing correlations
|
||||||
|
- Offers better anonymity properties than batch mixing approaches
|
||||||
|
|
||||||
|
2. **Cover Traffic**:
|
||||||
|
- Clients and nodes generate dummy "loop" packets that circulate through the network
|
||||||
|
- These packets are indistinguishable from real traffic
|
||||||
|
- Creates a baseline level of traffic that hides actual communication patterns
|
||||||
|
- Provides unobservability (hiding when and how much real traffic is being sent)
|
||||||
|
|
||||||
|
3. **Stratified Network Architecture**:
|
||||||
|
- Traffic flows through Entry Gateway → 3 Mixnode Layers → Exit Gateway
|
||||||
|
- Path selection is independent per-message (unlike Tor)
|
||||||
|
- Each node connects only to adjacent layers
|
||||||
|
|
||||||
|
4. **Anonymous Replies**:
|
||||||
|
- Single-Use Reply Blocks (SURBs) allow receiving messages without revealing identity
|
||||||
|
- Enables bidirectional communication while maintaining privacy
|
||||||
|
|
||||||
|
## Network Monitoring Architecture
|
||||||
|
|
||||||
|
The network monitoring system is a core component that measures mixnet reliability:
|
||||||
|
|
||||||
|
1. The `nym-network-monitor` sends test packets through the network
|
||||||
|
2. These packets follow predefined routes through multiple mixnodes
|
||||||
|
3. Metrics are collected about:
|
||||||
|
- Successful and failed packet deliveries
|
||||||
|
- Node reliability (percentage of successful packet handling)
|
||||||
|
- Route reliability (which specific route combinations work best)
|
||||||
|
4. Results are stored in the database and used by `nym-api` to:
|
||||||
|
- Present node performance statistics
|
||||||
|
- Determine network rewards
|
||||||
|
- Provide route selection guidance to clients
|
||||||
|
|
||||||
|
In the current branch, metrics collection is being enhanced with a fanout approach to submit to multiple API endpoints.
|
||||||
|
|
||||||
|
## Development Environment
|
||||||
|
|
||||||
|
### Required Dependencies
|
||||||
|
|
||||||
|
- Rust toolchain (stable, 1.80+)
|
||||||
|
- Node.js (v20+) and yarn for TypeScript components
|
||||||
|
- SQLite for local database development
|
||||||
|
- PostgreSQL for API database (optional, for full API functionality)
|
||||||
|
- CosmWasm tools for contract development
|
||||||
|
- For building contracts: `wasm-opt` tool from `binaryen`
|
||||||
|
- Python 3.8+ for some scripts
|
||||||
|
- Docker (optional, for containerized development)
|
||||||
|
- protoc (Protocol Buffers compiler) for some components
|
||||||
|
|
||||||
|
### Environment Configurations
|
||||||
|
|
||||||
|
The `envs/` directory contains pre-configured environments:
|
||||||
|
|
||||||
|
#### Available Environments
|
||||||
|
|
||||||
|
- **`local.env`**: Local development environment
|
||||||
|
- Points to local services (localhost)
|
||||||
|
- Uses test mnemonics and keys
|
||||||
|
- Ideal for testing without external dependencies
|
||||||
|
|
||||||
|
- **`sandbox.env`**: Sandbox test network
|
||||||
|
- Public test network with real nodes
|
||||||
|
- Test tokens available from faucet
|
||||||
|
- Contract addresses for sandbox deployment
|
||||||
|
- API: https://sandbox-nym-api1.nymtech.net
|
||||||
|
|
||||||
|
- **`mainnet.env`**: Production mainnet
|
||||||
|
- Real network with real tokens
|
||||||
|
- Production contract addresses
|
||||||
|
- API: https://validator.nymtech.net
|
||||||
|
- Use with caution!
|
||||||
|
|
||||||
|
- **`canary.env`**: Canary deployment
|
||||||
|
- Pre-release testing environment
|
||||||
|
- Tests new features before mainnet
|
||||||
|
|
||||||
|
- **`mainnet-local-api.env`**: Hybrid environment
|
||||||
|
- Uses mainnet contracts but local API
|
||||||
|
- Useful for API development against mainnet data
|
||||||
|
|
||||||
|
#### Key Environment Variables
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Network configuration
|
||||||
|
NETWORK_NAME=sandbox # Network identifier
|
||||||
|
BECH32_PREFIX=n # Address prefix (n for sandbox, n for mainnet)
|
||||||
|
NYM_API=https://sandbox-nym-api1.nymtech.net/api
|
||||||
|
NYXD=https://rpc.sandbox.nymtech.net
|
||||||
|
NYM_API_NETWORK=sandbox
|
||||||
|
|
||||||
|
# Contract addresses (network-specific)
|
||||||
|
MIXNET_CONTRACT_ADDRESS=n1xr3rq8yvd7qplsw5yx90ftsr2zdhg4e9z60h5duusgxpv72hud3sjkxkav
|
||||||
|
VESTING_CONTRACT_ADDRESS=n1unyuj8qnmygvzuex3dwmg9yzt9alhvyeat0uu0jedg2wj33efl5qackslz
|
||||||
|
# ... other contract addresses
|
||||||
|
|
||||||
|
# Mnemonic for testing (NEVER use in production)
|
||||||
|
MNEMONIC="clutch captain shoe salt awake harvest setup primary inmate ugly among become"
|
||||||
|
|
||||||
|
# API Keys and tokens
|
||||||
|
IPINFO_API_TOKEN=your_token_here
|
||||||
|
AUTHENTICATOR_PASSWORD=password_here
|
||||||
|
|
||||||
|
# Logging
|
||||||
|
RUST_LOG=info # Options: error, warn, info, debug, trace
|
||||||
|
RUST_BACKTRACE=1 # Enable backtraces
|
||||||
|
|
||||||
|
# Database
|
||||||
|
DATABASE_URL=postgresql://user:pass@localhost/nym_api
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Using Environment Files
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Load environment and run command
|
||||||
|
dotenv -f envs/sandbox.env -- cargo run -p nym-api
|
||||||
|
|
||||||
|
# Export to shell
|
||||||
|
source envs/sandbox.env
|
||||||
|
|
||||||
|
# Use with make targets
|
||||||
|
dotenv -f envs/sandbox.env -- make run-api-tests
|
||||||
|
```
|
||||||
|
|
||||||
|
## Initial Setup
|
||||||
|
|
||||||
|
### First Time Setup
|
||||||
|
|
||||||
|
1. **Install Prerequisites**
|
||||||
|
```bash
|
||||||
|
# Install Rust
|
||||||
|
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
|
||||||
|
|
||||||
|
# Install Node.js and yarn
|
||||||
|
# Via nvm (recommended):
|
||||||
|
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash
|
||||||
|
nvm install 20
|
||||||
|
npm install -g yarn
|
||||||
|
|
||||||
|
# Install build tools
|
||||||
|
# Ubuntu/Debian:
|
||||||
|
sudo apt-get install build-essential pkg-config libssl-dev protobuf-compiler libpq-dev
|
||||||
|
|
||||||
|
# macOS:
|
||||||
|
brew install protobuf postgresql
|
||||||
|
|
||||||
|
# Install wasm-opt for contract builds
|
||||||
|
npm install -g wasm-opt
|
||||||
|
|
||||||
|
# Add wasm target for Rust
|
||||||
|
rustup target add wasm32-unknown-unknown
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Clone and Setup Repository**
|
||||||
|
```bash
|
||||||
|
git clone https://github.com/nymtech/nym.git
|
||||||
|
cd nym/nym
|
||||||
|
|
||||||
|
# Install JavaScript dependencies
|
||||||
|
yarn install
|
||||||
|
|
||||||
|
# Build the project
|
||||||
|
make build
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Database Setup (Optional, for API development)**
|
||||||
|
```bash
|
||||||
|
# Install PostgreSQL
|
||||||
|
# Create database
|
||||||
|
createdb nym_api
|
||||||
|
|
||||||
|
# Run migrations (from nym-api directory)
|
||||||
|
cd nym-api
|
||||||
|
sqlx migrate run
|
||||||
|
```
|
||||||
|
|
||||||
|
### Quick Start
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Run a mixnode locally
|
||||||
|
dotenv -f envs/sandbox.env -- cargo run -p nym-node -- run --mode mixnode --id my-mixnode
|
||||||
|
|
||||||
|
# Run a gateway locally
|
||||||
|
dotenv -f envs/sandbox.env -- cargo run -p nym-node -- run --mode gateway --id my-gateway
|
||||||
|
|
||||||
|
# Run the API server
|
||||||
|
dotenv -f envs/sandbox.env -- cargo run -p nym-api
|
||||||
|
|
||||||
|
# Run a client
|
||||||
|
cargo run -p nym-client -- init --id my-client
|
||||||
|
cargo run -p nym-client -- run --id my-client
|
||||||
|
```
|
||||||
|
|
||||||
|
## CI/CD Pipeline
|
||||||
|
|
||||||
|
The project uses GitHub Actions for CI/CD with several key workflows:
|
||||||
|
|
||||||
|
1. **Build and Test**:
|
||||||
|
- `ci-build.yml`: Main build workflow for Rust components
|
||||||
|
- Tests are run on multiple platforms (Linux, Windows, macOS)
|
||||||
|
- Includes formatting check (rustfmt) and linting (clippy)
|
||||||
|
|
||||||
|
2. **Release Process**:
|
||||||
|
- Binary artifacts are published on release tags
|
||||||
|
- Multiple platform builds are created
|
||||||
|
|
||||||
|
3. **Documentation**:
|
||||||
|
- Documentation is automatically built and deployed
|
||||||
|
|
||||||
|
## Database Structure
|
||||||
|
|
||||||
|
The system uses SQLite databases with tables like:
|
||||||
|
- `mixnode_status`: Status information about mixnodes
|
||||||
|
- `gateway_status`: Status information about gateways
|
||||||
|
- `routes`: Route performance information (success/failure of specific paths)
|
||||||
|
- `monitor_run`: Information about monitoring test runs
|
||||||
|
|
||||||
|
## Development Workflows
|
||||||
|
|
||||||
|
### Running a Node
|
||||||
|
|
||||||
|
To run the mixnode or gateway:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Run nym-node as a mixnode with specified identity
|
||||||
|
cargo run -p nym-node -- run --mode mixnode --id my-mixnode
|
||||||
|
|
||||||
|
# Run nym-node as a gateway
|
||||||
|
cargo run -p nym-node -- run --mode gateway --id my-gateway
|
||||||
|
```
|
||||||
|
|
||||||
|
### Configuration
|
||||||
|
|
||||||
|
Nodes can be configured with files in various locations:
|
||||||
|
- Command-line arguments
|
||||||
|
- Environment variables
|
||||||
|
- `.env` files specified with `--config-env-file`
|
||||||
|
|
||||||
|
### Monitoring
|
||||||
|
|
||||||
|
To monitor the health of your node:
|
||||||
|
- View logs for real-time information
|
||||||
|
- Use the node's HTTP API for status information
|
||||||
|
- Check the explorer for public node statistics
|
||||||
|
|
||||||
|
## Common Libraries
|
||||||
|
|
||||||
|
- `common/types`: Shared data types across all components
|
||||||
|
- `common/crypto`: Cryptographic primitives and wrappers
|
||||||
|
- `common/client-core`: Core client functionality
|
||||||
|
- `common/gateway-client`: Client-gateway communication
|
||||||
|
- `common/task`: Task management and concurrency utilities
|
||||||
|
- `common/nymsphinx`: Sphinx packet implementation for mixnet
|
||||||
|
- `common/topology`: Network topology management
|
||||||
|
- `common/credentials`: Credential system for privacy-preserving authentication
|
||||||
|
- `common/bandwidth-controller`: Bandwidth management and accounting
|
||||||
|
|
||||||
|
## Code Conventions
|
||||||
|
|
||||||
|
- Error handling: Use anyhow/thiserror for structured error handling
|
||||||
|
- Logging: Use the tracing framework for logging and diagnostics
|
||||||
|
- State management: Generally use Tokio/futures for async code
|
||||||
|
- Configuration: Use the config crate and env vars with defaults
|
||||||
|
- Database: Use sqlx for type-safe database queries
|
||||||
|
- Follow clippy recommendations and rustfmt formatting
|
||||||
|
- Use semantic commit messages: feat, fix, docs, refactor, test, chore
|
||||||
|
|
||||||
|
## When Making Changes
|
||||||
|
|
||||||
|
- Run `make test` before submitting PRs
|
||||||
|
- Follow Rust naming conventions
|
||||||
|
- Use `clippy` to check for common issues
|
||||||
|
- Update SQLx query caches when modifying DB queries: `cargo sqlx prepare`
|
||||||
|
- Consider backward compatibility for protocol changes
|
||||||
|
- Use lefthook pre-commit hooks for TypeScript formatting
|
||||||
|
- Run `cargo deny check` to verify dependency compliance
|
||||||
|
- Test against both sandbox and local environments when possible
|
||||||
|
- Update relevant documentation and CHANGELOG.md
|
||||||
|
|
||||||
|
## Development Tools
|
||||||
|
|
||||||
|
### Useful Cargo Commands
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check for outdated dependencies
|
||||||
|
cargo outdated
|
||||||
|
|
||||||
|
# Analyze binary size
|
||||||
|
cargo bloat --release -p nym-node
|
||||||
|
|
||||||
|
# Generate dependency graph
|
||||||
|
cargo tree -p nym-api
|
||||||
|
|
||||||
|
# Run with instrumentation
|
||||||
|
cargo run --features profiling -p nym-node
|
||||||
|
|
||||||
|
# Check for security advisories
|
||||||
|
cargo audit
|
||||||
|
```
|
||||||
|
|
||||||
|
### Database Tools
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# SQLx CLI for migrations
|
||||||
|
cargo install sqlx-cli
|
||||||
|
|
||||||
|
# Create new migration
|
||||||
|
cd nym-api && sqlx migrate add <migration_name>
|
||||||
|
|
||||||
|
# Prepare query metadata for offline compilation
|
||||||
|
cargo sqlx prepare --workspace
|
||||||
|
|
||||||
|
# View database schema
|
||||||
|
./nym-api/enter_db.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
### Development Scripts
|
||||||
|
|
||||||
|
- `scripts/build_topology.py`: Generate network topology files
|
||||||
|
- `scripts/node_api_check.py`: Verify node API endpoints
|
||||||
|
- `scripts/network_tunnel_manager.sh`: Manage network tunnels
|
||||||
|
- `scripts/localnet_start.sh`: Start a local test network
|
||||||
|
- Various deployment scripts in `deployment/` for different environments
|
||||||
|
|
||||||
|
## Debugging
|
||||||
|
|
||||||
|
- Enable more verbose logging with the RUST_LOG environment variable:
|
||||||
|
```
|
||||||
|
RUST_LOG=debug,nym_node=trace cargo run -p nym-node -- run --mode mixnode
|
||||||
|
```
|
||||||
|
- Use the HTTP API endpoints for status information
|
||||||
|
- Check monitoring data in the database for network performance metrics
|
||||||
|
- For complex issues, use tracing tools to follow packet flow
|
||||||
|
- Enable backtraces: `RUST_BACKTRACE=full`
|
||||||
|
- For WASM debugging: Use browser developer tools with source maps
|
||||||
|
|
||||||
|
## Deployment and Advanced Configurations
|
||||||
|
|
||||||
|
### Deployment Structure
|
||||||
|
|
||||||
|
The `deployment/` directory contains Ansible playbooks and configurations for various deployment scenarios:
|
||||||
|
|
||||||
|
- **`aws/`**: AWS-specific deployment configurations
|
||||||
|
- **`mixnode/`**: Mixnode deployment playbooks
|
||||||
|
- **`gateway/`**: Gateway deployment playbooks
|
||||||
|
- **`validator/`**: Validator node deployment
|
||||||
|
- **`sandbox-v2/`**: Complete sandbox environment setup
|
||||||
|
- **`big-dipper-2/`**: Block explorer deployment
|
||||||
|
|
||||||
|
### Sandbox V2 Deployment
|
||||||
|
|
||||||
|
The sandbox-v2 deployment (`deployment/sandbox-v2/`) provides a complete test environment:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Key playbooks:
|
||||||
|
- deploy.yaml # Main deployment orchestrator
|
||||||
|
- deploy-mixnodes.yaml # Deploy mixnodes
|
||||||
|
- deploy-gateways.yaml # Deploy gateways
|
||||||
|
- deploy-validators.yaml # Deploy validator nodes
|
||||||
|
- deploy-nym-api.yaml # Deploy API services
|
||||||
|
```
|
||||||
|
|
||||||
|
### Custom Environment Setup
|
||||||
|
|
||||||
|
To create a custom environment:
|
||||||
|
|
||||||
|
1. Copy an existing env file: `cp envs/sandbox.env envs/custom.env`
|
||||||
|
2. Modify the network endpoints and contract addresses
|
||||||
|
3. Update the `NETWORK_NAME` to your identifier
|
||||||
|
4. Set appropriate mnemonics and keys (use fresh ones for production!)
|
||||||
|
|
||||||
|
### Contract Addresses
|
||||||
|
|
||||||
|
Contract addresses are network-specific and defined in environment files:
|
||||||
|
- Mixnet contract: Manages mixnode/gateway registry
|
||||||
|
- Vesting contract: Handles token vesting schedules
|
||||||
|
- Coconut contracts: Privacy-preserving credentials
|
||||||
|
- Name service: Human-readable address mapping
|
||||||
|
- Ecash contract: Electronic cash functionality
|
||||||
|
|
||||||
|
### Local Network Setup
|
||||||
|
|
||||||
|
For a completely local network:
|
||||||
|
```bash
|
||||||
|
# Start local chain
|
||||||
|
./scripts/localnet_start.sh
|
||||||
|
|
||||||
|
# Deploy contracts
|
||||||
|
cd contracts
|
||||||
|
make deploy-local
|
||||||
|
|
||||||
|
# Start nodes with local config
|
||||||
|
dotenv -f envs/local.env -- cargo run -p nym-node -- run --mode mixnode
|
||||||
|
```
|
||||||
|
|
||||||
|
## Common Issues and Troubleshooting
|
||||||
|
|
||||||
|
### Database Issues
|
||||||
|
|
||||||
|
- When modifying database queries, you must update SQLx query caches:
|
||||||
|
```bash
|
||||||
|
cargo sqlx prepare
|
||||||
|
```
|
||||||
|
- If you see SQLx errors about missing query files, this is likely the cause
|
||||||
|
- For "database is locked" errors with SQLite, ensure only one process accesses the DB
|
||||||
|
- For PostgreSQL connection issues, verify DATABASE_URL and that the server is running
|
||||||
|
|
||||||
|
### API Connection Issues
|
||||||
|
|
||||||
|
- Check the environment variables pointing to the APIs (NYM_API, NYXD)
|
||||||
|
- Verify network connectivity and API health endpoints
|
||||||
|
- For authentication issues, check node keys and credentials
|
||||||
|
- Common endpoints to verify:
|
||||||
|
- API health: `$NYM_API/health`
|
||||||
|
- Chain status: `$NYXD/status`
|
||||||
|
- Contract info: `$NYXD/cosmwasm/wasm/v1/contract/$CONTRACT_ADDRESS`
|
||||||
|
|
||||||
|
### Build Problems
|
||||||
|
|
||||||
|
- Clean dependencies with `cargo clean` for a fresh build
|
||||||
|
- Check for compatible Rust version (1.80+ recommended)
|
||||||
|
- For smart contract builds, ensure wasm-opt is installed: `npm install -g wasm-opt`
|
||||||
|
- For cross-compilation issues, check target-specific dependencies
|
||||||
|
- WASM build issues: Ensure wasm32-unknown-unknown target is installed:
|
||||||
|
```bash
|
||||||
|
rustup target add wasm32-unknown-unknown
|
||||||
|
```
|
||||||
|
- For "cannot find -lpq" errors, install PostgreSQL development files:
|
||||||
|
```bash
|
||||||
|
# Ubuntu/Debian
|
||||||
|
sudo apt-get install libpq-dev
|
||||||
|
# macOS
|
||||||
|
brew install postgresql
|
||||||
|
```
|
||||||
|
|
||||||
|
### Environment Issues
|
||||||
|
|
||||||
|
- Contract address mismatches: Ensure you're using the correct environment file
|
||||||
|
- "Account sequence mismatch": The account nonce is out of sync, wait and retry
|
||||||
|
- Token decimal issues: Sandbox uses different decimal places than mainnet
|
||||||
|
- API version mismatches: Ensure your local API version matches the network
|
||||||
|
- "Insufficient funds": Get test tokens from faucet (sandbox) or check balance
|
||||||
|
- Gateway/mixnode bonding issues: Verify minimum stake requirements
|
||||||
|
|
||||||
|
## Working with Routes and Monitoring
|
||||||
|
|
||||||
|
1. Route monitoring metrics are stored in a `routes` table with:
|
||||||
|
- Layer node IDs (layer1, layer2, layer3, gw)
|
||||||
|
- Success flag (boolean)
|
||||||
|
- Timestamp
|
||||||
|
|
||||||
|
2. To analyze routes:
|
||||||
|
- Check `NetworkAccount` and `AccountingRoute` in `nym-network-monitor/src/accounting.rs`
|
||||||
|
- View monitoring logic in `common/nymsphinx/chunking/monitoring.rs`
|
||||||
|
- Observe how routes are submitted to the database in the `submit_accounting_routes_to_db` function
|
||||||
|
|
||||||
|
## Performance Optimization
|
||||||
|
|
||||||
|
### Profiling and Benchmarking
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Run benchmarks
|
||||||
|
cargo bench -p nym-node
|
||||||
|
|
||||||
|
# Profile with perf (Linux)
|
||||||
|
cargo build --release --features profiling
|
||||||
|
perf record --call-graph=dwarf ./target/release/nym-node run --mode mixnode
|
||||||
|
perf report
|
||||||
|
|
||||||
|
# Generate flamegraph
|
||||||
|
cargo install flamegraph
|
||||||
|
cargo flamegraph --bin nym-node -- run --mode mixnode
|
||||||
|
```
|
||||||
|
|
||||||
|
### Common Performance Considerations
|
||||||
|
|
||||||
|
- Use bounded channels for backpressure
|
||||||
|
- Batch database operations where possible
|
||||||
|
- Monitor memory usage with `RUST_LOG=nym_node::metrics=debug`
|
||||||
|
- Use connection pooling for database connections
|
||||||
|
- Consider using `jemalloc` for better memory allocation performance
|
||||||
Generated
+1755
-1455
File diff suppressed because it is too large
Load Diff
+57
-50
@@ -33,13 +33,16 @@ members = [
|
|||||||
"common/commands",
|
"common/commands",
|
||||||
"common/config",
|
"common/config",
|
||||||
"common/cosmwasm-smart-contracts/coconut-dkg",
|
"common/cosmwasm-smart-contracts/coconut-dkg",
|
||||||
"common/cosmwasm-smart-contracts/contracts-common", "common/cosmwasm-smart-contracts/easy_addr",
|
"common/cosmwasm-smart-contracts/contracts-common",
|
||||||
|
"common/cosmwasm-smart-contracts/contracts-common-testing",
|
||||||
|
"common/cosmwasm-smart-contracts/easy_addr",
|
||||||
"common/cosmwasm-smart-contracts/ecash-contract",
|
"common/cosmwasm-smart-contracts/ecash-contract",
|
||||||
"common/cosmwasm-smart-contracts/group-contract",
|
"common/cosmwasm-smart-contracts/group-contract",
|
||||||
"common/cosmwasm-smart-contracts/mixnet-contract",
|
"common/cosmwasm-smart-contracts/mixnet-contract",
|
||||||
"common/cosmwasm-smart-contracts/multisig-contract",
|
"common/cosmwasm-smart-contracts/multisig-contract",
|
||||||
|
"common/cosmwasm-smart-contracts/nym-performance-contract",
|
||||||
|
"common/cosmwasm-smart-contracts/nym-pool-contract",
|
||||||
"common/cosmwasm-smart-contracts/vesting-contract",
|
"common/cosmwasm-smart-contracts/vesting-contract",
|
||||||
"common/country-group",
|
|
||||||
"common/credential-storage",
|
"common/credential-storage",
|
||||||
"common/credential-utils",
|
"common/credential-utils",
|
||||||
"common/credential-verification",
|
"common/credential-verification",
|
||||||
@@ -47,6 +50,8 @@ members = [
|
|||||||
"common/credentials-interface",
|
"common/credentials-interface",
|
||||||
"common/crypto",
|
"common/crypto",
|
||||||
"common/dkg",
|
"common/dkg",
|
||||||
|
"common/ecash-signer-check",
|
||||||
|
"common/ecash-signer-check-types",
|
||||||
"common/ecash-time",
|
"common/ecash-time",
|
||||||
"common/execute",
|
"common/execute",
|
||||||
"common/exit-policy",
|
"common/exit-policy",
|
||||||
@@ -65,6 +70,8 @@ members = [
|
|||||||
"common/nym-id",
|
"common/nym-id",
|
||||||
"common/nym-metrics",
|
"common/nym-metrics",
|
||||||
"common/nym_offline_compact_ecash",
|
"common/nym_offline_compact_ecash",
|
||||||
|
"common/nymnoise",
|
||||||
|
"common/nymnoise/keys",
|
||||||
"common/nymsphinx",
|
"common/nymsphinx",
|
||||||
"common/nymsphinx/acknowledgements",
|
"common/nymsphinx/acknowledgements",
|
||||||
"common/nymsphinx/addressing",
|
"common/nymsphinx/addressing",
|
||||||
@@ -85,7 +92,7 @@ members = [
|
|||||||
"common/socks5/requests",
|
"common/socks5/requests",
|
||||||
"common/statistics",
|
"common/statistics",
|
||||||
"common/store-cipher",
|
"common/store-cipher",
|
||||||
"common/task",
|
"common/task", "common/test-utils",
|
||||||
"common/ticketbooks-merkle",
|
"common/ticketbooks-merkle",
|
||||||
"common/topology",
|
"common/topology",
|
||||||
"common/tun",
|
"common/tun",
|
||||||
@@ -95,13 +102,14 @@ members = [
|
|||||||
"common/wasm/storage",
|
"common/wasm/storage",
|
||||||
"common/wasm/utils",
|
"common/wasm/utils",
|
||||||
"common/wireguard",
|
"common/wireguard",
|
||||||
|
"common/wireguard-private-metadata/client",
|
||||||
|
"common/wireguard-private-metadata/server",
|
||||||
|
"common/wireguard-private-metadata/shared",
|
||||||
|
"common/wireguard-private-metadata/tests",
|
||||||
"common/wireguard-types",
|
"common/wireguard-types",
|
||||||
|
"common/zulip-client",
|
||||||
"documentation/autodoc",
|
"documentation/autodoc",
|
||||||
# "explorer-api",
|
|
||||||
# "explorer-api/explorer-api-requests",
|
|
||||||
# "explorer-api/explorer-client",
|
|
||||||
"gateway",
|
"gateway",
|
||||||
"integrations/bity",
|
|
||||||
"nym-api",
|
"nym-api",
|
||||||
"nym-api/nym-api-requests",
|
"nym-api/nym-api-requests",
|
||||||
"nym-browser-extension/storage",
|
"nym-browser-extension/storage",
|
||||||
@@ -116,17 +124,17 @@ members = [
|
|||||||
"nym-node/nym-node-metrics",
|
"nym-node/nym-node-metrics",
|
||||||
"nym-node/nym-node-requests",
|
"nym-node/nym-node-requests",
|
||||||
"nym-outfox",
|
"nym-outfox",
|
||||||
|
"nym-statistics-api",
|
||||||
"nym-validator-rewarder",
|
"nym-validator-rewarder",
|
||||||
"nyx-chain-watcher",
|
"nyx-chain-watcher",
|
||||||
"sdk/ffi/cpp",
|
"sdk/ffi/cpp",
|
||||||
"sdk/ffi/go",
|
"sdk/ffi/go",
|
||||||
"sdk/ffi/shared",
|
"sdk/ffi/shared",
|
||||||
"sdk/rust/nym-sdk",
|
"sdk/rust/nym-sdk",
|
||||||
"service-providers/authenticator",
|
|
||||||
"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",
|
"sqlx-pool-guard",
|
||||||
"tools/echo-server",
|
"tools/echo-server",
|
||||||
"tools/internal/contract-state-importer/importer-cli",
|
"tools/internal/contract-state-importer/importer-cli",
|
||||||
"tools/internal/contract-state-importer/importer-contract",
|
"tools/internal/contract-state-importer/importer-contract",
|
||||||
@@ -136,7 +144,7 @@ members = [
|
|||||||
"tools/internal/testnet-manager",
|
"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/internal/validator-status-check",
|
"tools/internal/validator-status-check",
|
||||||
"tools/nym-cli",
|
"tools/nym-cli",
|
||||||
"tools/nym-id-cli",
|
"tools/nym-id-cli",
|
||||||
"tools/nym-nr-query",
|
"tools/nym-nr-query",
|
||||||
@@ -157,20 +165,15 @@ default-members = [
|
|||||||
"nym-node",
|
"nym-node",
|
||||||
"nym-node-status-api/nym-node-status-agent",
|
"nym-node-status-api/nym-node-status-agent",
|
||||||
"nym-node-status-api/nym-node-status-api",
|
"nym-node-status-api/nym-node-status-api",
|
||||||
|
"nym-statistics-api",
|
||||||
"nym-validator-rewarder",
|
"nym-validator-rewarder",
|
||||||
"nyx-chain-watcher",
|
"nyx-chain-watcher",
|
||||||
"service-providers/authenticator",
|
|
||||||
"service-providers/ip-packet-router",
|
"service-providers/ip-packet-router",
|
||||||
"service-providers/network-requester",
|
"service-providers/network-requester",
|
||||||
"tools/nymvisor",
|
"tools/nymvisor",
|
||||||
]
|
]
|
||||||
|
|
||||||
exclude = [
|
exclude = ["explorer", "contracts", "nym-wallet", "cpu-cycles"]
|
||||||
"explorer",
|
|
||||||
"contracts",
|
|
||||||
"nym-wallet",
|
|
||||||
"cpu-cycles",
|
|
||||||
]
|
|
||||||
|
|
||||||
[workspace.package]
|
[workspace.package]
|
||||||
authors = ["Nym Technologies SA"]
|
authors = ["Nym Technologies SA"]
|
||||||
@@ -189,7 +192,7 @@ 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"
|
ammonia = "4"
|
||||||
anyhow = "1.0.97"
|
anyhow = "1.0.98"
|
||||||
arc-swap = "1.7.1"
|
arc-swap = "1.7.1"
|
||||||
argon2 = "0.5.0"
|
argon2 = "0.5.0"
|
||||||
async-trait = "0.1.88"
|
async-trait = "0.1.88"
|
||||||
@@ -204,24 +207,24 @@ 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.7.0"
|
blake3 = "1.7.0"
|
||||||
bloomfilter = "1.0.14"
|
bloomfilter = "3.0.1"
|
||||||
bs58 = "0.5.1"
|
bs58 = "0.5.1"
|
||||||
bytecodec = "0.4.15"
|
bytecodec = "0.4.15"
|
||||||
bytes = "1.10.1"
|
bytes = "1.10.1"
|
||||||
cargo_metadata = "0.18.1"
|
cargo_metadata = "0.19.2"
|
||||||
celes = "2.6.0"
|
celes = "2.6.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.41"
|
||||||
cipher = "0.4.3"
|
cipher = "0.4.3"
|
||||||
clap = "4.5.34"
|
clap = "4.5.38"
|
||||||
clap_complete = "4.5"
|
clap_complete = "4.5"
|
||||||
clap_complete_fig = "4.5"
|
clap_complete_fig = "4.5"
|
||||||
colored = "2.2"
|
colored = "2.2"
|
||||||
comfy-table = "7.1.4"
|
comfy-table = "7.1.4"
|
||||||
console = "0.15.11"
|
console = "0.15.11"
|
||||||
console-subscriber = "0.1.1"
|
console-subscriber = "0.4.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.34"
|
||||||
@@ -237,15 +240,16 @@ digest = "0.10.7"
|
|||||||
dirs = "5.0"
|
dirs = "5.0"
|
||||||
doc-comment = "0.3"
|
doc-comment = "0.3"
|
||||||
dotenvy = "0.15.6"
|
dotenvy = "0.15.6"
|
||||||
|
dyn-clone = "1.0.19"
|
||||||
ecdsa = "0.16"
|
ecdsa = "0.16"
|
||||||
ed25519-dalek = "2.1"
|
ed25519-dalek = "2.1"
|
||||||
encoding_rs = "0.8.35"
|
encoding_rs = "0.8.35"
|
||||||
env_logger = "0.11.7"
|
env_logger = "0.11.8"
|
||||||
envy = "0.4"
|
envy = "0.4"
|
||||||
etherparse = "0.13.0"
|
etherparse = "0.13.0"
|
||||||
eyre = "0.6.9"
|
eyre = "0.6.9"
|
||||||
fastrand = "2.1.1"
|
fastrand = "2.1.1"
|
||||||
flate2 = "1.1.0"
|
flate2 = "1.1.1"
|
||||||
futures = "0.3.31"
|
futures = "0.3.31"
|
||||||
futures-util = "0.3"
|
futures-util = "0.3"
|
||||||
generic-array = "0.14.7"
|
generic-array = "0.14.7"
|
||||||
@@ -255,7 +259,7 @@ 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"
|
hickory-resolver = "0.25"
|
||||||
hkdf = "0.12.3"
|
hkdf = "0.12.3"
|
||||||
hmac = "0.12.1"
|
hmac = "0.12.1"
|
||||||
http = "1"
|
http = "1"
|
||||||
@@ -270,7 +274,6 @@ indicatif = "0.17.11"
|
|||||||
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"
|
|
||||||
itertools = "0.14.0"
|
itertools = "0.14.0"
|
||||||
k256 = "0.13"
|
k256 = "0.13"
|
||||||
lazy_static = "1.5.0"
|
lazy_static = "1.5.0"
|
||||||
@@ -291,8 +294,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.16"
|
||||||
pretty_env_logger = "0.4.0"
|
|
||||||
publicsuffix = "2.3.0"
|
publicsuffix = "2.3.0"
|
||||||
|
proc_pidinfo = "0.1.3"
|
||||||
quote = "1"
|
quote = "1"
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
rand_chacha = "0.3"
|
rand_chacha = "0.3"
|
||||||
@@ -303,9 +306,6 @@ rand_seeder = "0.2.3"
|
|||||||
rayon = "1.5.1"
|
rayon = "1.5.1"
|
||||||
regex = "1.10.6"
|
regex = "1.10.6"
|
||||||
reqwest = { version = "0.12.15", default-features = false }
|
reqwest = { version = "0.12.15", default-features = false }
|
||||||
rocket = "0.5.0"
|
|
||||||
rocket_cors = "0.6.0"
|
|
||||||
rocket_okapi = "0.8.0"
|
|
||||||
rs_merkle = "1.5.0"
|
rs_merkle = "1.5.0"
|
||||||
safer-ffi = "0.1.13"
|
safer-ffi = "0.1.13"
|
||||||
schemars = "0.8.22"
|
schemars = "0.8.22"
|
||||||
@@ -318,28 +318,29 @@ serde_json_path = "0.7.2"
|
|||||||
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.9"
|
||||||
si-scale = "0.2.3"
|
si-scale = "0.2.3"
|
||||||
sphinx-packet = "=0.3.2"
|
snow = "0.9.6"
|
||||||
sqlx = "0.7.4"
|
sphinx-packet = "=0.6.0"
|
||||||
strum = "0.26"
|
sqlx = "0.8.6"
|
||||||
strum_macros = "0.26"
|
strum = "0.27.2"
|
||||||
|
strum_macros = "0.27.2"
|
||||||
subtle-encoding = "0.5"
|
subtle-encoding = "0.5"
|
||||||
syn = "1"
|
syn = "1"
|
||||||
sysinfo = "0.33.0"
|
sysinfo = "0.37.0"
|
||||||
tap = "1.0.1"
|
tap = "1.0.1"
|
||||||
tar = "0.4.44"
|
tar = "0.4.44"
|
||||||
tempfile = "3.19"
|
tempfile = "3.20"
|
||||||
thiserror = "2.0"
|
thiserror = "2.0"
|
||||||
time = "0.3.41"
|
time = "0.3.41"
|
||||||
tokio = "1.44"
|
tokio = "1.45"
|
||||||
tokio-postgres = "0.7"
|
tokio-postgres = "0.7"
|
||||||
tokio-stream = "0.1.17"
|
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.14"
|
tokio-util = "0.7.15"
|
||||||
toml = "0.8.20"
|
toml = "0.8.22"
|
||||||
tower = "0.5.2"
|
tower = "0.5.2"
|
||||||
tower-http = "0.5.2"
|
tower-http = "0.5.2"
|
||||||
tracing = "0.1.41"
|
tracing = "0.1.41"
|
||||||
@@ -350,7 +351,7 @@ tracing-tree = "0.2.2"
|
|||||||
tracing-indicatif = "0.3.9"
|
tracing-indicatif = "0.3.9"
|
||||||
ts-rs = "10.1.0"
|
ts-rs = "10.1.0"
|
||||||
tungstenite = { version = "0.20.1", default-features = false }
|
tungstenite = { version = "0.20.1", default-features = false }
|
||||||
uniffi = "0.29.1"
|
uniffi = "0.29.2"
|
||||||
uniffi_build = "0.29.0"
|
uniffi_build = "0.29.0"
|
||||||
url = "2.5"
|
url = "2.5"
|
||||||
utoipa = "5.2"
|
utoipa = "5.2"
|
||||||
@@ -359,11 +360,10 @@ 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"
|
|
||||||
x25519-dalek = "2.0.0"
|
x25519-dalek = "2.0.0"
|
||||||
zeroize = "1.7.0"
|
zeroize = "1.7.0"
|
||||||
|
|
||||||
prometheus = { version = "0.13.0" }
|
prometheus = { version = "0.14.0" }
|
||||||
|
|
||||||
# coconut/DKG related
|
# coconut/DKG related
|
||||||
# unfortunately until https://github.com/zkcrypto/bls12_381/issues/10 is resolved, we have to rely on the fork
|
# unfortunately until https://github.com/zkcrypto/bls12_381/issues/10 is resolved, we have to rely on the fork
|
||||||
@@ -377,9 +377,6 @@ subtle = "2.5.0"
|
|||||||
# cosmwasm-related
|
# cosmwasm-related
|
||||||
cosmwasm-schema = "=2.2.2"
|
cosmwasm-schema = "=2.2.2"
|
||||||
cosmwasm-std = "=2.2.2"
|
cosmwasm-std = "=2.2.2"
|
||||||
# use 1.0.1 as that's the version used by cosmwasm-std 2.2.1
|
|
||||||
# (and ideally we don't want to pull the same dependency twice)
|
|
||||||
serde-json-wasm = "=1.0.1"
|
|
||||||
# same version as used by cosmwasm
|
# same version as used by cosmwasm
|
||||||
cw-utils = "=2.0.0"
|
cw-utils = "=2.0.0"
|
||||||
cw-storage-plus = "=2.0.0"
|
cw-storage-plus = "=2.0.0"
|
||||||
@@ -387,29 +384,36 @@ cw2 = { version = "=2.0.0" }
|
|||||||
cw3 = { version = "=2.0.0" }
|
cw3 = { version = "=2.0.0" }
|
||||||
cw4 = { version = "=2.0.0" }
|
cw4 = { version = "=2.0.0" }
|
||||||
cw-controllers = { version = "=2.0.0" }
|
cw-controllers = { version = "=2.0.0" }
|
||||||
|
cw-multi-test = "=2.3.2"
|
||||||
|
|
||||||
# cosmrs-related
|
# cosmrs-related
|
||||||
bip32 = { version = "0.5.3", default-features = false }
|
bip32 = { version = "0.5.3", default-features = false }
|
||||||
|
|
||||||
|
|
||||||
cosmrs = { version = "0.21.1" }
|
cosmrs = { version = "0.21.1" }
|
||||||
tendermint = "0.40.0"
|
tendermint = "0.40.4"
|
||||||
tendermint-rpc = "0.40.0"
|
tendermint-rpc = "0.40.4"
|
||||||
prost = { version = "0.13", default-features = false }
|
prost = { version = "0.13", 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.6.0"
|
||||||
|
|
||||||
indexed_db_futures = "0.6.1"
|
indexed_db_futures = "0.6.4"
|
||||||
js-sys = "0.3.76"
|
js-sys = "0.3.76"
|
||||||
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.49"
|
||||||
|
wasm-bindgen-test = "0.3.49"
|
||||||
wasmtimer = "0.4.1"
|
wasmtimer = "0.4.1"
|
||||||
web-sys = "0.3.76"
|
web-sys = "0.3.76"
|
||||||
|
|
||||||
|
|
||||||
|
# for local development:
|
||||||
|
#[patch.crates-io]
|
||||||
|
#sphinx-packet = { path = "../sphinx" }
|
||||||
|
|
||||||
# Profile settings for individual crates
|
# Profile settings for individual crates
|
||||||
|
|
||||||
# Compile-time verified queries do quite a bit of work at compile time. Incremental
|
# Compile-time verified queries do quite a bit of work at compile time. Incremental
|
||||||
@@ -437,6 +441,9 @@ opt-level = 'z'
|
|||||||
# lto = true
|
# lto = true
|
||||||
opt-level = 'z'
|
opt-level = 'z'
|
||||||
|
|
||||||
|
[workspace.lints.rust]
|
||||||
|
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(tokio_unstable)'] }
|
||||||
|
|
||||||
[workspace.lints.clippy]
|
[workspace.lints.clippy]
|
||||||
unwrap_used = "deny"
|
unwrap_used = "deny"
|
||||||
expect_used = "deny"
|
expect_used = "deny"
|
||||||
|
|||||||
@@ -12,7 +12,11 @@ help:
|
|||||||
@echo " clippy: run clippy for all workspaces"
|
@echo " clippy: run clippy for all workspaces"
|
||||||
@echo " test: run clippy, unit tests, and formatting."
|
@echo " test: run clippy, unit tests, and formatting."
|
||||||
@echo " test-all: like test, but also includes the expensive tests"
|
@echo " test-all: like test, but also includes the expensive tests"
|
||||||
@echo " deb: build debian packages
|
@echo " deb: build debian packages"
|
||||||
|
@echo ""
|
||||||
|
@echo "Contract building targets:"
|
||||||
|
@echo " contracts: build contracts for development (includes wasm-opt)"
|
||||||
|
@echo " publish-contracts: build contracts using Docker optimizer (deterministic)"
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
# Meta targets
|
# Meta targets
|
||||||
@@ -130,25 +134,69 @@ cargo-test: sdk-wasm-test
|
|||||||
clippy: sdk-wasm-lint
|
clippy: sdk-wasm-lint
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
# Build contracts ready for deploy
|
# Build CosmWasm contracts (deterministic docker build)
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
CONTRACTS=vesting_contract mixnet_contract nym_ecash cw3_flex_multisig cw4_group nym_coconut_dkg
|
|
||||||
CONTRACTS_WASM=$(addsuffix .wasm, $(CONTRACTS))
|
|
||||||
CONTRACTS_OUT_DIR=contracts/target/wasm32-unknown-unknown/release
|
|
||||||
|
|
||||||
contracts: build-release-contracts wasm-opt-contracts cosmwasm-check-contracts
|
WASM_CONTRACT_DIR := contracts/target/wasm32-unknown-unknown/release
|
||||||
|
# Find every direct contract folder that contains a Cargo.toml
|
||||||
|
CONTRACT_DIRS := $(shell find contracts -type f -name Cargo.toml \( ! -path "contracts/Cargo.toml" \) | grep -v integration-tests | xargs -n1 dirname | sort -u)
|
||||||
|
|
||||||
|
CONTRACTS_OUT_DIR = contracts/artifacts
|
||||||
|
|
||||||
|
# Build all contracts via the official CosmWasm optimizer image (one invocation per contract)
|
||||||
|
# See : https://github.com/CosmWasm/optimizer?tab=readme-ov-file#contracts-excluded-from-workspace
|
||||||
|
# The optimizer ships separate multi-arch images. ARM builds are *not* bit-for-bit identical to the
|
||||||
|
# canonical x86_64 build (see README notice in CosmWasm/optimizer). For reproducible artefacts we
|
||||||
|
# therefore always run the amd64 variant by default.
|
||||||
|
# Override with :
|
||||||
|
# $ COSMWASM_OPTIMIZER_IMAGE=cosmwasm/optimizer-arm64:0.17.0 make contracts-publish
|
||||||
|
#
|
||||||
|
COSMWASM_OPTIMIZER_IMAGE ?= cosmwasm/optimizer:0.17.0
|
||||||
|
COSMWASM_OPTIMIZER_PLATFORM ?= linux/amd64
|
||||||
|
|
||||||
|
# Ensure clean build environment and run the optimizer
|
||||||
|
optimize-contracts:
|
||||||
|
@rm -rf artifacts 2>/dev/null || true
|
||||||
|
@echo "=== Ensuring clean build environment"
|
||||||
|
docker volume rm nym_contracts_cache 2>/dev/null || true
|
||||||
|
docker volume rm registry_cache 2>/dev/null || true
|
||||||
|
@for DIR in $(CONTRACT_DIRS); do \
|
||||||
|
echo "=== Optimizing $${DIR}"; \
|
||||||
|
docker run --rm --platform $(COSMWASM_OPTIMIZER_PLATFORM) \
|
||||||
|
-v $(CURDIR):/code \
|
||||||
|
--mount type=volume,source=nym_contracts_cache,target=/target \
|
||||||
|
--mount type=volume,source=registry_cache,target=/usr/local/cargo/registry \
|
||||||
|
-e CARGO_BUILD_INCREMENTAL=false \
|
||||||
|
-e RUSTFLAGS="-C target-cpu=generic -C debuginfo=0" \
|
||||||
|
-e SOURCE_DATE_EPOCH=1 \
|
||||||
|
$(COSMWASM_OPTIMIZER_IMAGE) $${DIR}; \
|
||||||
|
done
|
||||||
|
@mkdir -p $(CONTRACTS_OUT_DIR)
|
||||||
|
@cp artifacts/*.wasm $(CONTRACTS_OUT_DIR)/ 2>/dev/null || true
|
||||||
|
|
||||||
|
@cd $(CONTRACTS_OUT_DIR) && sha256sum *.wasm > checksums.txt
|
||||||
|
# Cleanup temporary artefacts directory
|
||||||
|
@rm -rf artifacts 2>/dev/null || true
|
||||||
|
|
||||||
wasm-opt-contracts:
|
wasm-opt-contracts:
|
||||||
for contract in $(CONTRACTS_WASM); do \
|
@for WASM in $(WASM_CONTRACT_DIR)/*.wasm; do \
|
||||||
wasm-opt --signext-lowering -Os $(CONTRACTS_OUT_DIR)/$$contract -o $(CONTRACTS_OUT_DIR)/$$contract; \
|
echo "Running wasm-opt on $$WASM"; \
|
||||||
|
wasm-opt --signext-lowering -Os $$WASM -o $$WASM ; \
|
||||||
done
|
done
|
||||||
|
|
||||||
cosmwasm-check-contracts:
|
cosmwasm-check-contracts:
|
||||||
for contract in $(CONTRACTS_WASM); do \
|
@for WASM in $(WASM_CONTRACT_DIR)/*.wasm; do \
|
||||||
cosmwasm-check $(CONTRACTS_OUT_DIR)/$$contract; \
|
echo "Checking $$WASM"; \
|
||||||
|
cosmwasm-check $$WASM ; \
|
||||||
done
|
done
|
||||||
|
|
||||||
|
# Default development build
|
||||||
|
contracts: build-release-contracts wasm-opt-contracts cosmwasm-check-contracts
|
||||||
|
|
||||||
|
# Publishing build used by CI – deterministic Docker optimiser
|
||||||
|
publish-contracts: optimize-contracts cosmwasm-check-contracts
|
||||||
|
|
||||||
# Consider adding 's' to make plural consistent (beware: used in github workflow)
|
# Consider adding 's' to make plural consistent (beware: used in github workflow)
|
||||||
contract-schema:
|
contract-schema:
|
||||||
$(MAKE) -C contracts schema
|
$(MAKE) -C contracts schema
|
||||||
@@ -168,8 +216,9 @@ generate-typescript:
|
|||||||
cd tools/ts-rs-cli && cargo run && cd ../..
|
cd tools/ts-rs-cli && cargo run && cd ../..
|
||||||
yarn types:lint:fix
|
yarn types:lint:fix
|
||||||
|
|
||||||
|
# Run the integration tests for public nym-api endpoints
|
||||||
run-api-tests:
|
run-api-tests:
|
||||||
cd nym-api/tests/functional_test && yarn test:qa
|
dotenv -f envs/sandbox.env -- cargo test --test public-api-tests
|
||||||
|
|
||||||
# Build debian package, and update PPA
|
# Build debian package, and update PPA
|
||||||
deb-cli: build-nym-cli
|
deb-cli: build-nym-cli
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "nym-client"
|
name = "nym-client"
|
||||||
version = "1.1.52"
|
version = "1.1.62"
|
||||||
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"
|
||||||
@@ -46,6 +46,7 @@ nym-bandwidth-controller = { path = "../../common/bandwidth-controller" }
|
|||||||
nym-bin-common = { path = "../../common/bin-common", features = [
|
nym-bin-common = { path = "../../common/bin-common", features = [
|
||||||
"output_format",
|
"output_format",
|
||||||
"clap",
|
"clap",
|
||||||
|
"basic_tracing",
|
||||||
] }
|
] }
|
||||||
nym-client-core = { path = "../../common/client-core", features = [
|
nym-client-core = { path = "../../common/client-core", features = [
|
||||||
"fs-credentials-storage",
|
"fs-credentials-storage",
|
||||||
|
|||||||
@@ -2048,10 +2048,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/http-proxy-middleware": {
|
"node_modules/http-proxy-middleware": {
|
||||||
"version": "2.0.4",
|
"version": "2.0.9",
|
||||||
"resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.9.tgz",
|
||||||
"integrity": "sha512-m/4FxX17SUvz4lJ5WPXOHDUuCwIqXLfLHs1s0uZ3oYjhoXlx9csYxaOa0ElDEJ+h8Q4iJ1s+lTMbiCa4EXIJqg==",
|
"integrity": "sha512-c1IyJYLYppU574+YI7R4QyX2ystMtVXZwIdzazUIPIJsHuWNd+mho2j+bKoHftndicGj9yh+xjd+l0yj7VeT1Q==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/http-proxy": "^1.17.8",
|
"@types/http-proxy": "^1.17.8",
|
||||||
"http-proxy": "^1.18.1",
|
"http-proxy": "^1.18.1",
|
||||||
@@ -6095,9 +6096,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"http-proxy-middleware": {
|
"http-proxy-middleware": {
|
||||||
"version": "2.0.4",
|
"version": "2.0.9",
|
||||||
"resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.9.tgz",
|
||||||
"integrity": "sha512-m/4FxX17SUvz4lJ5WPXOHDUuCwIqXLfLHs1s0uZ3oYjhoXlx9csYxaOa0ElDEJ+h8Q4iJ1s+lTMbiCa4EXIJqg==",
|
"integrity": "sha512-c1IyJYLYppU574+YI7R4QyX2ystMtVXZwIdzazUIPIJsHuWNd+mho2j+bKoHftndicGj9yh+xjd+l0yj7VeT1Q==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@types/http-proxy": "^1.17.8",
|
"@types/http-proxy": "^1.17.8",
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ pub mod old_config_v1_1_13;
|
|||||||
pub mod old_config_v1_1_20;
|
pub mod old_config_v1_1_20;
|
||||||
pub mod old_config_v1_1_20_2;
|
pub mod old_config_v1_1_20_2;
|
||||||
pub mod old_config_v1_1_33;
|
pub mod old_config_v1_1_33;
|
||||||
|
pub mod old_config_v1_1_54;
|
||||||
mod persistence;
|
mod persistence;
|
||||||
mod template;
|
mod template;
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
use crate::client::config::persistence::ClientPaths;
|
use crate::client::config::persistence::ClientPaths;
|
||||||
use crate::client::config::{default_config_filepath, Config, Socket, SocketType};
|
use crate::client::config::{default_config_filepath, Socket, SocketType};
|
||||||
use crate::error::ClientError;
|
use crate::error::ClientError;
|
||||||
use nym_bin_common::logging::LoggingSettings;
|
use nym_bin_common::logging::LoggingSettings;
|
||||||
use nym_client_core::config::disk_persistence::old_v1_1_33::CommonClientPathsV1_1_33;
|
use nym_client_core::config::disk_persistence::old_v1_1_33::CommonClientPathsV1_1_33;
|
||||||
@@ -14,6 +14,8 @@ use std::io;
|
|||||||
use std::net::{IpAddr, Ipv4Addr};
|
use std::net::{IpAddr, Ipv4Addr};
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
|
use super::old_config_v1_1_54::ConfigV1_1_54;
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, PartialEq, Eq, Serialize, Clone)]
|
#[derive(Debug, Deserialize, PartialEq, Eq, Serialize, Clone)]
|
||||||
pub struct ClientPathsV1_1_33 {
|
pub struct ClientPathsV1_1_33 {
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
@@ -33,6 +35,21 @@ pub struct ConfigV1_1_33 {
|
|||||||
pub logging: LoggingSettings,
|
pub logging: LoggingSettings,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl TryFrom<ConfigV1_1_33> for ConfigV1_1_54 {
|
||||||
|
type Error = ClientError;
|
||||||
|
|
||||||
|
fn try_from(value: ConfigV1_1_33) -> Result<Self, Self::Error> {
|
||||||
|
Ok(ConfigV1_1_54 {
|
||||||
|
base: value.base.into(),
|
||||||
|
socket: value.socket.into(),
|
||||||
|
storage_paths: ClientPaths {
|
||||||
|
common_paths: value.storage_paths.common_paths.upgrade_default()?,
|
||||||
|
},
|
||||||
|
logging: value.logging,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl ConfigV1_1_33 {
|
impl ConfigV1_1_33 {
|
||||||
pub fn read_from_toml_file<P: AsRef<Path>>(path: P) -> io::Result<Self> {
|
pub fn read_from_toml_file<P: AsRef<Path>>(path: P) -> io::Result<Self> {
|
||||||
read_config_from_toml_file(path)
|
read_config_from_toml_file(path)
|
||||||
@@ -41,17 +58,6 @@ impl ConfigV1_1_33 {
|
|||||||
pub fn read_from_default_path<P: AsRef<Path>>(id: P) -> io::Result<Self> {
|
pub fn read_from_default_path<P: AsRef<Path>>(id: P) -> io::Result<Self> {
|
||||||
Self::read_from_toml_file(default_config_filepath(id))
|
Self::read_from_toml_file(default_config_filepath(id))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn try_upgrade(self) -> Result<Config, ClientError> {
|
|
||||||
Ok(Config {
|
|
||||||
base: self.base.into(),
|
|
||||||
socket: self.socket.into(),
|
|
||||||
storage_paths: ClientPaths {
|
|
||||||
common_paths: self.storage_paths.common_paths.upgrade_default()?,
|
|
||||||
},
|
|
||||||
logging: self.logging,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, PartialEq, Eq, Serialize, Clone, Copy)]
|
#[derive(Debug, Deserialize, PartialEq, Eq, Serialize, Clone, Copy)]
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
use std::{io, path::Path};
|
||||||
|
|
||||||
|
use nym_bin_common::logging::LoggingSettings;
|
||||||
|
use nym_client_core::config::old_config_v1_1_54::ConfigV1_1_54 as BaseConfigV1_1_54;
|
||||||
|
use nym_config::read_config_from_toml_file;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use crate::error::ClientError;
|
||||||
|
|
||||||
|
use super::{default_config_filepath, persistence::ClientPaths, Config, Socket};
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, PartialEq, Serialize, Clone)]
|
||||||
|
pub struct ConfigV1_1_54 {
|
||||||
|
#[serde(flatten)]
|
||||||
|
pub base: BaseConfigV1_1_54,
|
||||||
|
|
||||||
|
pub socket: Socket,
|
||||||
|
|
||||||
|
pub storage_paths: ClientPaths,
|
||||||
|
|
||||||
|
pub logging: LoggingSettings,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ConfigV1_1_54 {
|
||||||
|
pub fn read_from_toml_file<P: AsRef<Path>>(path: P) -> io::Result<Self> {
|
||||||
|
read_config_from_toml_file(path)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_from_default_path<P: AsRef<Path>>(id: P) -> io::Result<Self> {
|
||||||
|
Self::read_from_toml_file(default_config_filepath(id))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn try_upgrade(self) -> Result<Config, ClientError> {
|
||||||
|
Ok(Config {
|
||||||
|
base: self.base.into(),
|
||||||
|
socket: self.socket,
|
||||||
|
storage_paths: self.storage_paths,
|
||||||
|
logging: self.logging,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -92,10 +92,6 @@ host = '{{ socket.host }}'
|
|||||||
|
|
||||||
[debug]
|
[debug]
|
||||||
|
|
||||||
[debug.traffic]
|
|
||||||
average_packet_delay = '{{ debug.traffic.average_packet_delay }}'
|
|
||||||
message_sending_average_delay = '{{ debug.traffic.message_sending_average_delay }}'
|
|
||||||
|
|
||||||
[debug.acknowledgements]
|
[debug.acknowledgements]
|
||||||
average_ack_delay = '{{ debug.acknowledgements.average_ack_delay }}'
|
average_ack_delay = '{{ debug.acknowledgements.average_ack_delay }}'
|
||||||
|
|
||||||
|
|||||||
@@ -111,7 +111,7 @@ impl SocketClient {
|
|||||||
let dkg_query_client = if self.config.base.client.disabled_credentials_mode {
|
let dkg_query_client = if self.config.base.client.disabled_credentials_mode {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some(default_query_dkg_client_from_config(&self.config.base))
|
Some(default_query_dkg_client_from_config(&self.config.base)?)
|
||||||
};
|
};
|
||||||
|
|
||||||
let storage = self.initialise_storage().await?;
|
let storage = self.initialise_storage().await?;
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ use crate::client::config::old_config_v1_1_13::OldConfigV1_1_13;
|
|||||||
use crate::client::config::old_config_v1_1_20::ConfigV1_1_20;
|
use crate::client::config::old_config_v1_1_20::ConfigV1_1_20;
|
||||||
use crate::client::config::old_config_v1_1_20_2::ConfigV1_1_20_2;
|
use crate::client::config::old_config_v1_1_20_2::ConfigV1_1_20_2;
|
||||||
use crate::client::config::old_config_v1_1_33::ConfigV1_1_33;
|
use crate::client::config::old_config_v1_1_33::ConfigV1_1_33;
|
||||||
|
use crate::client::config::old_config_v1_1_54::ConfigV1_1_54;
|
||||||
use crate::client::config::{BaseClientConfig, Config};
|
use crate::client::config::{BaseClientConfig, Config};
|
||||||
use crate::commands::ecash::Ecash;
|
use crate::commands::ecash::Ecash;
|
||||||
use crate::error::ClientError;
|
use crate::error::ClientError;
|
||||||
@@ -177,7 +178,8 @@ async fn try_upgrade_v1_1_13_config(id: &str) -> Result<bool, ClientError> {
|
|||||||
let updated_step2: ConfigV1_1_20_2 = updated_step1.into();
|
let updated_step2: ConfigV1_1_20_2 = updated_step1.into();
|
||||||
let (updated_step3, gateway_config) = updated_step2.upgrade()?;
|
let (updated_step3, gateway_config) = updated_step2.upgrade()?;
|
||||||
let old_paths = updated_step3.storage_paths.clone();
|
let old_paths = updated_step3.storage_paths.clone();
|
||||||
let updated = updated_step3.try_upgrade()?;
|
let updated_step4: ConfigV1_1_54 = updated_step3.try_into()?;
|
||||||
|
let updated = updated_step4.try_upgrade()?;
|
||||||
|
|
||||||
v1_1_33::migrate_gateway_details(
|
v1_1_33::migrate_gateway_details(
|
||||||
&old_paths.common_paths,
|
&old_paths.common_paths,
|
||||||
@@ -205,7 +207,8 @@ async fn try_upgrade_v1_1_20_config(id: &str) -> Result<bool, ClientError> {
|
|||||||
let updated_step1: ConfigV1_1_20_2 = old_config.into();
|
let updated_step1: ConfigV1_1_20_2 = old_config.into();
|
||||||
let (updated_step2, gateway_config) = updated_step1.upgrade()?;
|
let (updated_step2, gateway_config) = updated_step1.upgrade()?;
|
||||||
let old_paths = updated_step2.storage_paths.clone();
|
let old_paths = updated_step2.storage_paths.clone();
|
||||||
let updated = updated_step2.try_upgrade()?;
|
let updated_step3: ConfigV1_1_54 = updated_step2.try_into()?;
|
||||||
|
let updated = updated_step3.try_upgrade()?;
|
||||||
|
|
||||||
v1_1_33::migrate_gateway_details(
|
v1_1_33::migrate_gateway_details(
|
||||||
&old_paths.common_paths,
|
&old_paths.common_paths,
|
||||||
@@ -229,7 +232,8 @@ async fn try_upgrade_v1_1_20_2_config(id: &str) -> Result<bool, ClientError> {
|
|||||||
|
|
||||||
let (updated_step1, gateway_config) = old_config.upgrade()?;
|
let (updated_step1, gateway_config) = old_config.upgrade()?;
|
||||||
let old_paths = updated_step1.storage_paths.clone();
|
let old_paths = updated_step1.storage_paths.clone();
|
||||||
let updated = updated_step1.try_upgrade()?;
|
let updated_step2: ConfigV1_1_54 = updated_step1.try_into()?;
|
||||||
|
let updated = updated_step2.try_upgrade()?;
|
||||||
|
|
||||||
v1_1_33::migrate_gateway_details(
|
v1_1_33::migrate_gateway_details(
|
||||||
&old_paths.common_paths,
|
&old_paths.common_paths,
|
||||||
@@ -252,7 +256,8 @@ async fn try_upgrade_v1_1_33_config(id: &str) -> Result<bool, ClientError> {
|
|||||||
info!("It is going to get updated to the current specification.");
|
info!("It is going to get updated to the current specification.");
|
||||||
|
|
||||||
let old_paths = old_config.storage_paths.clone();
|
let old_paths = old_config.storage_paths.clone();
|
||||||
let updated = old_config.try_upgrade()?;
|
let updated_step1: ConfigV1_1_54 = old_config.try_into()?;
|
||||||
|
let updated = updated_step1.try_upgrade()?;
|
||||||
|
|
||||||
v1_1_33::migrate_gateway_details(
|
v1_1_33::migrate_gateway_details(
|
||||||
&old_paths.common_paths,
|
&old_paths.common_paths,
|
||||||
@@ -265,6 +270,22 @@ async fn try_upgrade_v1_1_33_config(id: &str) -> Result<bool, ClientError> {
|
|||||||
Ok(true)
|
Ok(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn try_upgrade_v1_1_54_config(id: &str) -> Result<bool, ClientError> {
|
||||||
|
// explicitly load it as v1.1.54 (which is incompatible with the current one, i.e. +1.1.55)
|
||||||
|
let Ok(old_config) = ConfigV1_1_54::read_from_default_path(id) else {
|
||||||
|
// if we failed to load it, there might have been nothing to upgrade
|
||||||
|
// or maybe it was an even older file. in either way. just ignore it and carry on with our day
|
||||||
|
return Ok(false);
|
||||||
|
};
|
||||||
|
info!("It seems the client is using <= v1.1.54 config template.");
|
||||||
|
info!("It is going to get updated to the current specification.");
|
||||||
|
|
||||||
|
let updated = old_config.try_upgrade()?;
|
||||||
|
|
||||||
|
updated.save_to_default_location()?;
|
||||||
|
Ok(true)
|
||||||
|
}
|
||||||
|
|
||||||
async fn try_upgrade_config(id: &str) -> Result<(), ClientError> {
|
async fn try_upgrade_config(id: &str) -> Result<(), ClientError> {
|
||||||
if try_upgrade_v1_1_13_config(id).await? {
|
if try_upgrade_v1_1_13_config(id).await? {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
@@ -278,6 +299,9 @@ async fn try_upgrade_config(id: &str) -> Result<(), ClientError> {
|
|||||||
if try_upgrade_v1_1_33_config(id).await? {
|
if try_upgrade_v1_1_33_config(id).await? {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
if try_upgrade_v1_1_54_config(id).await? {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
|
||||||
use clap::{crate_name, crate_version, Parser};
|
use clap::{crate_name, crate_version, Parser};
|
||||||
use nym_bin_common::logging::{maybe_print_banner, setup_logging};
|
use nym_bin_common::logging::{maybe_print_banner, setup_tracing_logger};
|
||||||
use nym_network_defaults::setup_env;
|
use nym_network_defaults::setup_env;
|
||||||
|
|
||||||
pub mod client;
|
pub mod client;
|
||||||
@@ -20,7 +20,7 @@ async fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
|
|||||||
if !args.no_banner {
|
if !args.no_banner {
|
||||||
maybe_print_banner(crate_name!(), crate_version!());
|
maybe_print_banner(crate_name!(), crate_version!());
|
||||||
}
|
}
|
||||||
setup_logging();
|
setup_tracing_logger();
|
||||||
|
|
||||||
if let Err(err) = commands::execute(args).await {
|
if let Err(err) = commands::execute(args).await {
|
||||||
log::error!("{err}");
|
log::error!("{err}");
|
||||||
|
|||||||
@@ -318,7 +318,7 @@ impl Handler {
|
|||||||
|
|
||||||
async fn handle_text_message(&mut self, msg: String) -> Option<WsMessage> {
|
async fn handle_text_message(&mut self, msg: String) -> Option<WsMessage> {
|
||||||
debug!("Handling text message request");
|
debug!("Handling text message request");
|
||||||
trace!("Content: {:?}", msg);
|
trace!("Content: {msg:?}");
|
||||||
|
|
||||||
self.received_response_type = ReceivedResponseType::Text;
|
self.received_response_type = ReceivedResponseType::Text;
|
||||||
let client_request = ClientRequest::try_from_text(msg);
|
let client_request = ClientRequest::try_from_text(msg);
|
||||||
|
|||||||
@@ -68,9 +68,9 @@ impl Listener {
|
|||||||
new_conn = tcp_listener.accept() => {
|
new_conn = tcp_listener.accept() => {
|
||||||
match new_conn {
|
match new_conn {
|
||||||
Ok((mut socket, remote_addr)) => {
|
Ok((mut socket, remote_addr)) => {
|
||||||
debug!("Received connection from {:?}", remote_addr);
|
debug!("Received connection from {remote_addr:?}");
|
||||||
if self.state.is_connected() {
|
if self.state.is_connected() {
|
||||||
warn!("Tried to open a duplicate websocket connection. The request came from {}", remote_addr);
|
warn!("Tried to open a duplicate websocket connection. The request came from {remote_addr}");
|
||||||
// if we've already got a connection, don't allow another one
|
// if we've already got a connection, don't allow another one
|
||||||
// while we only ever want to accept a single connection, we don't want
|
// while we only ever want to accept a single connection, we don't want
|
||||||
// to leave clients hanging (and also allow for reconnection if it somehow
|
// to leave clients hanging (and also allow for reconnection if it somehow
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "nym-socks5-client"
|
name = "nym-socks5-client"
|
||||||
version = "1.1.52"
|
version = "1.1.62"
|
||||||
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"
|
||||||
@@ -27,6 +27,7 @@ zeroize = { workspace = true }
|
|||||||
nym-bin-common = { path = "../../common/bin-common", features = [
|
nym-bin-common = { path = "../../common/bin-common", features = [
|
||||||
"output_format",
|
"output_format",
|
||||||
"clap",
|
"clap",
|
||||||
|
"basic_tracing",
|
||||||
] }
|
] }
|
||||||
nym-client-core = { path = "../../common/client-core", features = [
|
nym-client-core = { path = "../../common/client-core", features = [
|
||||||
"fs-credentials-storage",
|
"fs-credentials-storage",
|
||||||
|
|||||||
@@ -87,7 +87,6 @@ impl From<Init> for OverrideConfig {
|
|||||||
use_anonymous_replies: init_config.use_reply_surbs,
|
use_anonymous_replies: init_config.use_reply_surbs,
|
||||||
fastmode: init_config.common_args.fastmode,
|
fastmode: init_config.common_args.fastmode,
|
||||||
no_cover: init_config.common_args.no_cover,
|
no_cover: init_config.common_args.no_cover,
|
||||||
geo_routing: None,
|
|
||||||
medium_toggle: false,
|
medium_toggle: false,
|
||||||
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,
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ use crate::config::old_config_v1_1_20::ConfigV1_1_20;
|
|||||||
use crate::config::old_config_v1_1_20_2::ConfigV1_1_20_2;
|
use crate::config::old_config_v1_1_20_2::ConfigV1_1_20_2;
|
||||||
use crate::config::old_config_v1_1_30::ConfigV1_1_30;
|
use crate::config::old_config_v1_1_30::ConfigV1_1_30;
|
||||||
use crate::config::old_config_v1_1_33::ConfigV1_1_33;
|
use crate::config::old_config_v1_1_33::ConfigV1_1_33;
|
||||||
|
use crate::config::old_config_v1_1_54::ConfigV1_1_54;
|
||||||
use crate::config::{BaseClientConfig, Config};
|
use crate::config::{BaseClientConfig, Config};
|
||||||
use crate::error::Socks5ClientError;
|
use crate::error::Socks5ClientError;
|
||||||
use clap::CommandFactory;
|
use clap::CommandFactory;
|
||||||
@@ -16,8 +17,7 @@ use nym_bin_common::bin_info;
|
|||||||
use nym_bin_common::completions::{fig_generate, ArgShell};
|
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::config::ForgetMe;
|
||||||
use nym_client_core::config::{ForgetMe, 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};
|
||||||
@@ -107,7 +107,6 @@ pub(crate) struct OverrideConfig {
|
|||||||
use_anonymous_replies: Option<bool>,
|
use_anonymous_replies: Option<bool>,
|
||||||
fastmode: bool,
|
fastmode: bool,
|
||||||
no_cover: bool,
|
no_cover: bool,
|
||||||
geo_routing: Option<CountryGroup>,
|
|
||||||
medium_toggle: bool,
|
medium_toggle: bool,
|
||||||
nyxd_urls: Option<Vec<url::Url>>,
|
nyxd_urls: Option<Vec<url::Url>>,
|
||||||
enabled_credentials_mode: Option<bool>,
|
enabled_credentials_mode: Option<bool>,
|
||||||
@@ -138,21 +137,6 @@ pub(crate) fn override_config(config: Config, args: OverrideConfig) -> Config {
|
|||||||
let secondary_packet_size = args.medium_toggle.then_some(PacketSize::ExtendedPacket16);
|
let secondary_packet_size = args.medium_toggle.then_some(PacketSize::ExtendedPacket16);
|
||||||
let no_per_hop_delays = args.medium_toggle;
|
let no_per_hop_delays = args.medium_toggle;
|
||||||
|
|
||||||
let topology_structure = if args.medium_toggle {
|
|
||||||
// Use the location of the network-requester
|
|
||||||
let address = config
|
|
||||||
.core
|
|
||||||
.socks5
|
|
||||||
.provider_mix_address
|
|
||||||
.parse()
|
|
||||||
.expect("failed to parse provider mix address");
|
|
||||||
TopologyStructure::GeoAware(GroupBy::NymAddress(address))
|
|
||||||
} else if let Some(code) = args.geo_routing {
|
|
||||||
TopologyStructure::GeoAware(GroupBy::CountryGroup(code))
|
|
||||||
} else {
|
|
||||||
TopologyStructure::default()
|
|
||||||
};
|
|
||||||
|
|
||||||
let packet_type = if args.outfox {
|
let packet_type = if args.outfox {
|
||||||
PacketType::Outfox
|
PacketType::Outfox
|
||||||
} else {
|
} else {
|
||||||
@@ -176,10 +160,6 @@ pub(crate) fn override_config(config: Config, args: OverrideConfig) -> Config {
|
|||||||
// NOTE: see comment above about the order of the other disble cover traffic config
|
// NOTE: see comment above about the order of the other disble cover traffic config
|
||||||
.with_base(BaseClientConfig::with_disabled_cover_traffic, args.no_cover)
|
.with_base(BaseClientConfig::with_disabled_cover_traffic, args.no_cover)
|
||||||
.with_base(BaseClientConfig::with_packet_type, packet_type)
|
.with_base(BaseClientConfig::with_packet_type, packet_type)
|
||||||
.with_base(
|
|
||||||
BaseClientConfig::with_topology_structure,
|
|
||||||
topology_structure,
|
|
||||||
)
|
|
||||||
.with_base(BaseClientConfig::with_forget_me, args.forget_me)
|
.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)
|
||||||
@@ -225,15 +205,16 @@ async fn try_upgrade_v1_1_13_config(id: &str) -> Result<bool, Socks5ClientError>
|
|||||||
let old_paths = updated_step3.storage_paths.clone();
|
let old_paths = updated_step3.storage_paths.clone();
|
||||||
|
|
||||||
let updated_step4: ConfigV1_1_33 = updated_step3.into();
|
let updated_step4: ConfigV1_1_33 = updated_step3.into();
|
||||||
let updated = updated_step4.try_upgrade()?;
|
let updated_step5: ConfigV1_1_54 = updated_step4.try_into()?;
|
||||||
|
|
||||||
v1_1_33::migrate_gateway_details(
|
v1_1_33::migrate_gateway_details(
|
||||||
&old_paths.common_paths,
|
&old_paths.common_paths,
|
||||||
&updated.storage_paths.common_paths,
|
&updated_step5.storage_paths.common_paths,
|
||||||
Some(gateway_config),
|
Some(gateway_config),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
let updated = updated_step5.try_upgrade()?;
|
||||||
updated.save_to_default_location()?;
|
updated.save_to_default_location()?;
|
||||||
Ok(true)
|
Ok(true)
|
||||||
}
|
}
|
||||||
@@ -255,15 +236,16 @@ async fn try_upgrade_v1_1_20_config(id: &str) -> Result<bool, Socks5ClientError>
|
|||||||
let old_paths = updated_step2.storage_paths.clone();
|
let old_paths = updated_step2.storage_paths.clone();
|
||||||
|
|
||||||
let updated_step3: ConfigV1_1_33 = updated_step2.into();
|
let updated_step3: ConfigV1_1_33 = updated_step2.into();
|
||||||
let updated = updated_step3.try_upgrade()?;
|
let updated_step4: ConfigV1_1_54 = updated_step3.try_into()?;
|
||||||
|
|
||||||
v1_1_33::migrate_gateway_details(
|
v1_1_33::migrate_gateway_details(
|
||||||
&old_paths.common_paths,
|
&old_paths.common_paths,
|
||||||
&updated.storage_paths.common_paths,
|
&updated_step4.storage_paths.common_paths,
|
||||||
Some(gateway_config),
|
Some(gateway_config),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
let updated = updated_step4.try_upgrade()?;
|
||||||
updated.save_to_default_location()?;
|
updated.save_to_default_location()?;
|
||||||
Ok(true)
|
Ok(true)
|
||||||
}
|
}
|
||||||
@@ -282,15 +264,17 @@ async fn try_upgrade_v1_1_20_2_config(id: &str) -> Result<bool, Socks5ClientErro
|
|||||||
let old_paths = updated_step1.storage_paths.clone();
|
let old_paths = updated_step1.storage_paths.clone();
|
||||||
|
|
||||||
let updated_step2: ConfigV1_1_33 = updated_step1.into();
|
let updated_step2: ConfigV1_1_33 = updated_step1.into();
|
||||||
let updated = updated_step2.try_upgrade()?;
|
let updated_step3: ConfigV1_1_54 = updated_step2.try_into()?;
|
||||||
|
|
||||||
v1_1_33::migrate_gateway_details(
|
v1_1_33::migrate_gateway_details(
|
||||||
&old_paths.common_paths,
|
&old_paths.common_paths,
|
||||||
&updated.storage_paths.common_paths,
|
&updated_step3.storage_paths.common_paths,
|
||||||
Some(gateway_config),
|
Some(gateway_config),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
let updated = updated_step3.try_upgrade()?;
|
||||||
|
|
||||||
updated.save_to_default_location()?;
|
updated.save_to_default_location()?;
|
||||||
Ok(true)
|
Ok(true)
|
||||||
}
|
}
|
||||||
@@ -308,15 +292,16 @@ async fn try_upgrade_v1_1_30_config(id: &str) -> Result<bool, Socks5ClientError>
|
|||||||
let old_paths = old_config.storage_paths.clone();
|
let old_paths = old_config.storage_paths.clone();
|
||||||
|
|
||||||
let updated_step1: ConfigV1_1_33 = old_config.into();
|
let updated_step1: ConfigV1_1_33 = old_config.into();
|
||||||
let updated = updated_step1.try_upgrade()?;
|
let updated_step2: ConfigV1_1_54 = updated_step1.try_into()?;
|
||||||
|
|
||||||
v1_1_33::migrate_gateway_details(
|
v1_1_33::migrate_gateway_details(
|
||||||
&old_paths.common_paths,
|
&old_paths.common_paths,
|
||||||
&updated.storage_paths.common_paths,
|
&updated_step2.storage_paths.common_paths,
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
let updated = updated_step2.try_upgrade()?;
|
||||||
updated.save_to_default_location()?;
|
updated.save_to_default_location()?;
|
||||||
Ok(true)
|
Ok(true)
|
||||||
}
|
}
|
||||||
@@ -333,15 +318,32 @@ async fn try_upgrade_v1_1_33_config(id: &str) -> Result<bool, Socks5ClientError>
|
|||||||
|
|
||||||
let old_paths = old_config.storage_paths.clone();
|
let old_paths = old_config.storage_paths.clone();
|
||||||
|
|
||||||
let updated = old_config.try_upgrade()?;
|
let updated_step1: ConfigV1_1_54 = old_config.try_into()?;
|
||||||
|
|
||||||
v1_1_33::migrate_gateway_details(
|
v1_1_33::migrate_gateway_details(
|
||||||
&old_paths.common_paths,
|
&old_paths.common_paths,
|
||||||
&updated.storage_paths.common_paths,
|
&updated_step1.storage_paths.common_paths,
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
let updated = updated_step1.try_upgrade()?;
|
||||||
|
updated.save_to_default_location()?;
|
||||||
|
Ok(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn try_upgrade_v1_1_54_config(id: &str) -> Result<bool, Socks5ClientError> {
|
||||||
|
// explicitly load it as v1.1.54 (which is incompatible with the current one, i.e. +1.1.55)
|
||||||
|
let Ok(old_config) = ConfigV1_1_54::read_from_default_path(id) else {
|
||||||
|
// if we failed to load it, there might have been nothing to upgrade
|
||||||
|
// or maybe it was an even older file. in either way. just ignore it and carry on with our day
|
||||||
|
return Ok(false);
|
||||||
|
};
|
||||||
|
info!("It seems the client is using <= v1.1.54 config template.");
|
||||||
|
info!("It is going to get updated to the current specification.");
|
||||||
|
|
||||||
|
let updated = old_config.try_upgrade()?;
|
||||||
|
|
||||||
updated.save_to_default_location()?;
|
updated.save_to_default_location()?;
|
||||||
Ok(true)
|
Ok(true)
|
||||||
}
|
}
|
||||||
@@ -362,6 +364,9 @@ async fn try_upgrade_config(id: &str) -> Result<(), Socks5ClientError> {
|
|||||||
if try_upgrade_v1_1_33_config(id).await? {
|
if try_upgrade_v1_1_33_config(id).await? {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
if try_upgrade_v1_1_54_config(id).await? {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ use crate::commands::{override_config, OverrideConfig};
|
|||||||
use clap::Args;
|
use clap::Args;
|
||||||
use nym_client_core::cli_helpers::client_run::CommonClientRunArgs;
|
use nym_client_core::cli_helpers::client_run::CommonClientRunArgs;
|
||||||
use nym_client_core::client::base_client::storage::OnDiskPersistent;
|
use nym_client_core::client::base_client::storage::OnDiskPersistent;
|
||||||
use nym_client_core::client::topology_control::geo_aware_provider::CountryGroup;
|
|
||||||
use nym_socks5_client_core::NymClient;
|
use nym_socks5_client_core::NymClient;
|
||||||
use nym_sphinx::addressing::clients::Recipient;
|
use nym_sphinx::addressing::clients::Recipient;
|
||||||
use std::net::IpAddr;
|
use std::net::IpAddr;
|
||||||
@@ -37,10 +36,6 @@ pub(crate) struct Run {
|
|||||||
#[clap(long)]
|
#[clap(long)]
|
||||||
host: Option<IpAddr>,
|
host: Option<IpAddr>,
|
||||||
|
|
||||||
/// Set geo-aware mixnode selection when sending mixnet traffic, for experiments only.
|
|
||||||
#[clap(long, hide = true, value_parser = validate_country_group, group="routing")]
|
|
||||||
geo_routing: Option<CountryGroup>,
|
|
||||||
|
|
||||||
/// Enable medium mixnet traffic, for experiments only.
|
/// Enable medium mixnet traffic, for experiments only.
|
||||||
/// This includes things like disabling cover traffic, no per hop delays, etc.
|
/// This includes things like disabling cover traffic, no per hop delays, etc.
|
||||||
#[clap(long, hide = true)]
|
#[clap(long, hide = true)]
|
||||||
@@ -59,7 +54,6 @@ impl From<Run> for OverrideConfig {
|
|||||||
use_anonymous_replies: run_config.use_anonymous_replies,
|
use_anonymous_replies: run_config.use_anonymous_replies,
|
||||||
fastmode: run_config.common_args.fastmode,
|
fastmode: run_config.common_args.fastmode,
|
||||||
no_cover: run_config.common_args.no_cover,
|
no_cover: run_config.common_args.no_cover,
|
||||||
geo_routing: run_config.geo_routing,
|
|
||||||
medium_toggle: run_config.medium_toggle,
|
medium_toggle: run_config.medium_toggle,
|
||||||
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,
|
||||||
@@ -70,13 +64,6 @@ impl From<Run> for OverrideConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn validate_country_group(s: &str) -> Result<CountryGroup, String> {
|
|
||||||
match s.parse() {
|
|
||||||
Ok(cg) => Ok(cg),
|
|
||||||
Err(_) => Err(format!("failed to parse country group: {}", s)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) async fn execute(args: Run) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
pub(crate) async fn execute(args: Run) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
||||||
eprintln!("Starting client {}...", args.common_args.id);
|
eprintln!("Starting client {}...", args.common_args.id);
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ pub mod old_config_v1_1_20;
|
|||||||
pub mod old_config_v1_1_20_2;
|
pub mod old_config_v1_1_20_2;
|
||||||
pub mod old_config_v1_1_30;
|
pub mod old_config_v1_1_30;
|
||||||
pub mod old_config_v1_1_33;
|
pub mod old_config_v1_1_33;
|
||||||
|
pub mod old_config_v1_1_54;
|
||||||
mod persistence;
|
mod persistence;
|
||||||
mod template;
|
mod template;
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
use crate::config::{default_config_filepath, Config, SocksClientPaths};
|
use crate::config::{default_config_filepath, SocksClientPaths};
|
||||||
use crate::error::Socks5ClientError;
|
use crate::error::Socks5ClientError;
|
||||||
use nym_bin_common::logging::LoggingSettings;
|
use nym_bin_common::logging::LoggingSettings;
|
||||||
use nym_client_core::config::disk_persistence::old_v1_1_33::CommonClientPathsV1_1_33;
|
use nym_client_core::config::disk_persistence::old_v1_1_33::CommonClientPathsV1_1_33;
|
||||||
@@ -11,6 +11,8 @@ use serde::{Deserialize, Serialize};
|
|||||||
use std::io;
|
use std::io;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
|
use super::old_config_v1_1_54::ConfigV1_1_54;
|
||||||
|
|
||||||
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
|
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
|
||||||
pub struct SocksClientPathsV1_1_33 {
|
pub struct SocksClientPathsV1_1_33 {
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
@@ -28,6 +30,20 @@ pub struct ConfigV1_1_33 {
|
|||||||
pub logging: LoggingSettings,
|
pub logging: LoggingSettings,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl TryFrom<ConfigV1_1_33> for ConfigV1_1_54 {
|
||||||
|
type Error = Socks5ClientError;
|
||||||
|
|
||||||
|
fn try_from(value: ConfigV1_1_33) -> Result<Self, Self::Error> {
|
||||||
|
Ok(ConfigV1_1_54 {
|
||||||
|
core: value.core.into(),
|
||||||
|
storage_paths: SocksClientPaths {
|
||||||
|
common_paths: value.storage_paths.common_paths.upgrade_default()?,
|
||||||
|
},
|
||||||
|
logging: value.logging,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl ConfigV1_1_33 {
|
impl ConfigV1_1_33 {
|
||||||
pub fn read_from_toml_file<P: AsRef<Path>>(path: P) -> io::Result<Self> {
|
pub fn read_from_toml_file<P: AsRef<Path>>(path: P) -> io::Result<Self> {
|
||||||
read_config_from_toml_file(path)
|
read_config_from_toml_file(path)
|
||||||
@@ -36,14 +52,4 @@ impl ConfigV1_1_33 {
|
|||||||
pub fn read_from_default_path<P: AsRef<Path>>(id: P) -> io::Result<Self> {
|
pub fn read_from_default_path<P: AsRef<Path>>(id: P) -> io::Result<Self> {
|
||||||
Self::read_from_toml_file(default_config_filepath(id))
|
Self::read_from_toml_file(default_config_filepath(id))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn try_upgrade(self) -> Result<Config, Socks5ClientError> {
|
|
||||||
Ok(Config {
|
|
||||||
core: self.core.into(),
|
|
||||||
storage_paths: SocksClientPaths {
|
|
||||||
common_paths: self.storage_paths.common_paths.upgrade_default()?,
|
|
||||||
},
|
|
||||||
logging: self.logging,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,39 @@
|
|||||||
|
use std::{io, path::Path};
|
||||||
|
|
||||||
|
use nym_bin_common::logging::LoggingSettings;
|
||||||
|
use nym_config::read_config_from_toml_file;
|
||||||
|
use nym_socks5_client_core::config::old_config_v1_1_54::ConfigV1_1_54 as CoreConfigV1_1_54;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use crate::config::Config;
|
||||||
|
use crate::error::Socks5ClientError;
|
||||||
|
|
||||||
|
use super::{default_config_filepath, SocksClientPaths};
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
|
pub struct ConfigV1_1_54 {
|
||||||
|
pub core: CoreConfigV1_1_54,
|
||||||
|
|
||||||
|
pub storage_paths: SocksClientPaths,
|
||||||
|
|
||||||
|
pub logging: LoggingSettings,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ConfigV1_1_54 {
|
||||||
|
pub fn read_from_toml_file<P: AsRef<Path>>(path: P) -> io::Result<Self> {
|
||||||
|
read_config_from_toml_file(path)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_from_default_path<P: AsRef<Path>>(id: P) -> io::Result<Self> {
|
||||||
|
Self::read_from_toml_file(default_config_filepath(id))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn try_upgrade(self) -> Result<Config, Socks5ClientError> {
|
||||||
|
Ok(Config {
|
||||||
|
core: self.core.into(),
|
||||||
|
storage_paths: self.storage_paths,
|
||||||
|
logging: self.logging,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -98,10 +98,6 @@ send_anonymously = {{ core.socks5.send_anonymously }}
|
|||||||
|
|
||||||
[core.debug]
|
[core.debug]
|
||||||
|
|
||||||
[core.debug.traffic]
|
|
||||||
average_packet_delay = '{{ core.debug.traffic.average_packet_delay }}'
|
|
||||||
message_sending_average_delay = '{{ core.debug.traffic.message_sending_average_delay }}'
|
|
||||||
|
|
||||||
[core.debug.acknowledgements]
|
[core.debug.acknowledgements]
|
||||||
average_ack_delay = '{{ core.debug.acknowledgements.average_ack_delay }}'
|
average_ack_delay = '{{ core.debug.acknowledgements.average_ack_delay }}'
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
|
||||||
use clap::{crate_name, crate_version, Parser};
|
use clap::{crate_name, crate_version, Parser};
|
||||||
use nym_bin_common::logging::{maybe_print_banner, setup_logging};
|
use nym_bin_common::logging::{maybe_print_banner, setup_tracing_logger};
|
||||||
use nym_network_defaults::setup_env;
|
use nym_network_defaults::setup_env;
|
||||||
|
|
||||||
mod commands;
|
mod commands;
|
||||||
@@ -19,7 +19,7 @@ async fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
|
|||||||
if !args.no_banner {
|
if !args.no_banner {
|
||||||
maybe_print_banner(crate_name!(), crate_version!());
|
maybe_print_banner(crate_name!(), crate_version!());
|
||||||
}
|
}
|
||||||
setup_logging();
|
setup_tracing_logger();
|
||||||
|
|
||||||
if let Err(err) = commands::execute(args).await {
|
if let Err(err) = commands::execute(args).await {
|
||||||
log::error!("{err}");
|
log::error!("{err}");
|
||||||
|
|||||||
@@ -137,7 +137,7 @@ impl AsyncFileWatcher {
|
|||||||
log::error!("the file watcher receiver has been dropped!");
|
log::error!("the file watcher receiver has been dropped!");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log::debug!("will not propagate information about {:?}", event);
|
log::debug!("will not propagate information about {event:?}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ use std::{fmt, ops::Deref, str::FromStr};
|
|||||||
#[cfg(feature = "verify")]
|
#[cfg(feature = "verify")]
|
||||||
use hmac::{Hmac, Mac};
|
use hmac::{Hmac, Mac};
|
||||||
#[cfg(feature = "verify")]
|
#[cfg(feature = "verify")]
|
||||||
use nym_crypto::asymmetric::encryption::{PrivateKey, PublicKey};
|
use nym_crypto::asymmetric::x25519::{PrivateKey, PublicKey};
|
||||||
#[cfg(feature = "verify")]
|
#[cfg(feature = "verify")]
|
||||||
use sha2::Sha256;
|
use sha2::Sha256;
|
||||||
|
|
||||||
@@ -108,7 +108,7 @@ impl GatewayClient {
|
|||||||
#[cfg(feature = "verify")]
|
#[cfg(feature = "verify")]
|
||||||
pub fn verify(&self, gateway_key: &PrivateKey, nonce: u64) -> Result<(), Error> {
|
pub fn verify(&self, gateway_key: &PrivateKey, nonce: u64) -> Result<(), Error> {
|
||||||
// use gateways key as a ref to an x25519_dalek key
|
// use gateways key as a ref to an x25519_dalek key
|
||||||
let dh = (gateway_key.as_ref()).diffie_hellman(&self.pub_key);
|
let dh = gateway_key.inner().diffie_hellman(&self.pub_key);
|
||||||
|
|
||||||
// TODO: change that to use our nym_crypto::hmac module instead
|
// TODO: change that to use our nym_crypto::hmac module instead
|
||||||
#[allow(clippy::expect_used)]
|
#[allow(clippy::expect_used)]
|
||||||
@@ -190,15 +190,15 @@ impl<'de> Deserialize<'de> for ClientMac {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use nym_crypto::asymmetric::encryption;
|
use nym_crypto::asymmetric::x25519;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(feature = "verify")]
|
#[cfg(feature = "verify")]
|
||||||
fn client_request_roundtrip() {
|
fn client_request_roundtrip() {
|
||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::thread_rng();
|
||||||
|
|
||||||
let gateway_key_pair = encryption::KeyPair::new(&mut rng);
|
let gateway_key_pair = x25519::KeyPair::new(&mut rng);
|
||||||
let client_key_pair = encryption::KeyPair::new(&mut rng);
|
let client_key_pair = x25519::KeyPair::new(&mut rng);
|
||||||
|
|
||||||
let nonce = 1234567890;
|
let nonce = 1234567890;
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ use std::{fmt, ops::Deref, str::FromStr};
|
|||||||
#[cfg(feature = "verify")]
|
#[cfg(feature = "verify")]
|
||||||
use hmac::{Hmac, Mac};
|
use hmac::{Hmac, Mac};
|
||||||
#[cfg(feature = "verify")]
|
#[cfg(feature = "verify")]
|
||||||
use nym_crypto::asymmetric::encryption::{PrivateKey, PublicKey};
|
use nym_crypto::asymmetric::x25519::{PrivateKey, PublicKey};
|
||||||
#[cfg(feature = "verify")]
|
#[cfg(feature = "verify")]
|
||||||
use sha2::Sha256;
|
use sha2::Sha256;
|
||||||
|
|
||||||
@@ -117,7 +117,7 @@ impl GatewayClient {
|
|||||||
#[cfg(feature = "verify")]
|
#[cfg(feature = "verify")]
|
||||||
pub fn verify(&self, gateway_key: &PrivateKey, nonce: u64) -> Result<(), Error> {
|
pub fn verify(&self, gateway_key: &PrivateKey, nonce: u64) -> Result<(), Error> {
|
||||||
// use gateways key as a ref to an x25519_dalek key
|
// use gateways key as a ref to an x25519_dalek key
|
||||||
let dh = (gateway_key.as_ref()).diffie_hellman(&self.pub_key);
|
let dh = gateway_key.inner().diffie_hellman(&self.pub_key);
|
||||||
|
|
||||||
// TODO: change that to use our nym_crypto::hmac module instead
|
// TODO: change that to use our nym_crypto::hmac module instead
|
||||||
#[allow(clippy::expect_used)]
|
#[allow(clippy::expect_used)]
|
||||||
@@ -199,15 +199,15 @@ impl<'de> Deserialize<'de> for ClientMac {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use nym_crypto::asymmetric::encryption;
|
use nym_crypto::asymmetric::x25519;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(feature = "verify")]
|
#[cfg(feature = "verify")]
|
||||||
fn client_request_roundtrip() {
|
fn client_request_roundtrip() {
|
||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::thread_rng();
|
||||||
|
|
||||||
let gateway_key_pair = encryption::KeyPair::new(&mut rng);
|
let gateway_key_pair = x25519::KeyPair::new(&mut rng);
|
||||||
let client_key_pair = encryption::KeyPair::new(&mut rng);
|
let client_key_pair = x25519::KeyPair::new(&mut rng);
|
||||||
|
|
||||||
let nonce = 1234567890;
|
let nonce = 1234567890;
|
||||||
|
|
||||||
|
|||||||
@@ -340,7 +340,7 @@ mod tests {
|
|||||||
use std::{net::IpAddr, str::FromStr};
|
use std::{net::IpAddr, str::FromStr};
|
||||||
|
|
||||||
use nym_credentials_interface::CredentialSpendingData;
|
use nym_credentials_interface::CredentialSpendingData;
|
||||||
use nym_crypto::asymmetric::encryption::PrivateKey;
|
use nym_crypto::asymmetric::x25519::PrivateKey;
|
||||||
use nym_sphinx::addressing::Recipient;
|
use nym_sphinx::addressing::Recipient;
|
||||||
use nym_wireguard_types::PeerPublicKey;
|
use nym_wireguard_types::PeerPublicKey;
|
||||||
use x25519_dalek::PublicKey;
|
use x25519_dalek::PublicKey;
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ use std::{fmt, ops::Deref, str::FromStr};
|
|||||||
#[cfg(feature = "verify")]
|
#[cfg(feature = "verify")]
|
||||||
use hmac::{Hmac, Mac};
|
use hmac::{Hmac, Mac};
|
||||||
#[cfg(feature = "verify")]
|
#[cfg(feature = "verify")]
|
||||||
use nym_crypto::asymmetric::encryption::{PrivateKey, PublicKey};
|
use nym_crypto::asymmetric::x25519::{PrivateKey, PublicKey};
|
||||||
#[cfg(feature = "verify")]
|
#[cfg(feature = "verify")]
|
||||||
use sha2::Sha256;
|
use sha2::Sha256;
|
||||||
|
|
||||||
@@ -117,7 +117,7 @@ impl GatewayClient {
|
|||||||
#[cfg(feature = "verify")]
|
#[cfg(feature = "verify")]
|
||||||
pub fn verify(&self, gateway_key: &PrivateKey, nonce: u64) -> Result<(), Error> {
|
pub fn verify(&self, gateway_key: &PrivateKey, nonce: u64) -> Result<(), Error> {
|
||||||
// use gateways key as a ref to an x25519_dalek key
|
// use gateways key as a ref to an x25519_dalek key
|
||||||
let dh = (gateway_key.as_ref()).diffie_hellman(&self.pub_key);
|
let dh = gateway_key.inner().diffie_hellman(&self.pub_key);
|
||||||
|
|
||||||
// TODO: change that to use our nym_crypto::hmac module instead
|
// TODO: change that to use our nym_crypto::hmac module instead
|
||||||
#[allow(clippy::expect_used)]
|
#[allow(clippy::expect_used)]
|
||||||
@@ -199,15 +199,15 @@ impl<'de> Deserialize<'de> for ClientMac {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use nym_crypto::asymmetric::encryption;
|
use nym_crypto::asymmetric::x25519;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(feature = "verify")]
|
#[cfg(feature = "verify")]
|
||||||
fn client_request_roundtrip() {
|
fn client_request_roundtrip() {
|
||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::thread_rng();
|
||||||
|
|
||||||
let gateway_key_pair = encryption::KeyPair::new(&mut rng);
|
let gateway_key_pair = x25519::KeyPair::new(&mut rng);
|
||||||
let client_key_pair = encryption::KeyPair::new(&mut rng);
|
let client_key_pair = x25519::KeyPair::new(&mut rng);
|
||||||
|
|
||||||
let nonce = 1234567890;
|
let nonce = 1234567890;
|
||||||
|
|
||||||
|
|||||||
@@ -306,7 +306,7 @@ mod tests {
|
|||||||
};
|
};
|
||||||
|
|
||||||
use nym_credentials_interface::CredentialSpendingData;
|
use nym_credentials_interface::CredentialSpendingData;
|
||||||
use nym_crypto::asymmetric::encryption::PrivateKey;
|
use nym_crypto::asymmetric::x25519::PrivateKey;
|
||||||
use nym_sphinx::addressing::Recipient;
|
use nym_sphinx::addressing::Recipient;
|
||||||
use nym_wireguard_types::PeerPublicKey;
|
use nym_wireguard_types::PeerPublicKey;
|
||||||
use x25519_dalek::PublicKey;
|
use x25519_dalek::PublicKey;
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ use std::{fmt, ops::Deref, str::FromStr};
|
|||||||
#[cfg(feature = "verify")]
|
#[cfg(feature = "verify")]
|
||||||
use hmac::{Hmac, Mac};
|
use hmac::{Hmac, Mac};
|
||||||
#[cfg(feature = "verify")]
|
#[cfg(feature = "verify")]
|
||||||
use nym_crypto::asymmetric::encryption::{PrivateKey, PublicKey};
|
use nym_crypto::asymmetric::x25519::{PrivateKey, PublicKey};
|
||||||
#[cfg(feature = "verify")]
|
#[cfg(feature = "verify")]
|
||||||
use sha2::Sha256;
|
use sha2::Sha256;
|
||||||
|
|
||||||
@@ -169,7 +169,7 @@ impl GatewayClient {
|
|||||||
#[cfg(feature = "verify")]
|
#[cfg(feature = "verify")]
|
||||||
pub fn verify(&self, gateway_key: &PrivateKey, nonce: u64) -> Result<(), Error> {
|
pub fn verify(&self, gateway_key: &PrivateKey, nonce: u64) -> Result<(), Error> {
|
||||||
// use gateways key as a ref to an x25519_dalek key
|
// use gateways key as a ref to an x25519_dalek key
|
||||||
let dh = (gateway_key.as_ref()).diffie_hellman(&self.pub_key);
|
let dh = gateway_key.inner().diffie_hellman(&self.pub_key);
|
||||||
|
|
||||||
// TODO: change that to use our nym_crypto::hmac module instead
|
// TODO: change that to use our nym_crypto::hmac module instead
|
||||||
#[allow(clippy::expect_used)]
|
#[allow(clippy::expect_used)]
|
||||||
@@ -251,7 +251,7 @@ impl<'de> Deserialize<'de> for ClientMac {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use nym_crypto::asymmetric::encryption;
|
use nym_crypto::asymmetric::x25519;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn create_ip_pair() {
|
fn create_ip_pair() {
|
||||||
@@ -266,8 +266,8 @@ mod tests {
|
|||||||
fn client_request_roundtrip() {
|
fn client_request_roundtrip() {
|
||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::thread_rng();
|
||||||
|
|
||||||
let gateway_key_pair = encryption::KeyPair::new(&mut rng);
|
let gateway_key_pair = x25519::KeyPair::new(&mut rng);
|
||||||
let client_key_pair = encryption::KeyPair::new(&mut rng);
|
let client_key_pair = x25519::KeyPair::new(&mut rng);
|
||||||
|
|
||||||
let nonce = 1234567890;
|
let nonce = 1234567890;
|
||||||
|
|
||||||
|
|||||||
@@ -230,7 +230,7 @@ mod tests {
|
|||||||
};
|
};
|
||||||
|
|
||||||
use nym_credentials_interface::CredentialSpendingData;
|
use nym_credentials_interface::CredentialSpendingData;
|
||||||
use nym_crypto::asymmetric::encryption::PrivateKey;
|
use nym_crypto::asymmetric::x25519::PrivateKey;
|
||||||
use nym_sphinx::addressing::Recipient;
|
use nym_sphinx::addressing::Recipient;
|
||||||
use nym_wireguard_types::PeerPublicKey;
|
use nym_wireguard_types::PeerPublicKey;
|
||||||
use x25519_dalek::PublicKey;
|
use x25519_dalek::PublicKey;
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ use std::{fmt, ops::Deref, str::FromStr};
|
|||||||
#[cfg(feature = "verify")]
|
#[cfg(feature = "verify")]
|
||||||
use hmac::{Hmac, Mac};
|
use hmac::{Hmac, Mac};
|
||||||
#[cfg(feature = "verify")]
|
#[cfg(feature = "verify")]
|
||||||
use nym_crypto::asymmetric::encryption::{PrivateKey, PublicKey};
|
use nym_crypto::asymmetric::x25519::{PrivateKey, PublicKey};
|
||||||
#[cfg(feature = "verify")]
|
#[cfg(feature = "verify")]
|
||||||
use sha2::Sha256;
|
use sha2::Sha256;
|
||||||
|
|
||||||
@@ -28,8 +28,6 @@ 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
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||||
pub struct IpPair {
|
pub struct IpPair {
|
||||||
pub ipv4: Ipv4Addr,
|
pub ipv4: Ipv4Addr,
|
||||||
@@ -169,7 +167,7 @@ impl GatewayClient {
|
|||||||
#[cfg(feature = "verify")]
|
#[cfg(feature = "verify")]
|
||||||
pub fn verify(&self, gateway_key: &PrivateKey, nonce: u64) -> Result<(), Error> {
|
pub fn verify(&self, gateway_key: &PrivateKey, nonce: u64) -> Result<(), Error> {
|
||||||
// use gateways key as a ref to an x25519_dalek key
|
// use gateways key as a ref to an x25519_dalek key
|
||||||
let dh = (gateway_key.as_ref()).diffie_hellman(&self.pub_key);
|
let dh = gateway_key.inner().diffie_hellman(&self.pub_key);
|
||||||
|
|
||||||
// TODO: change that to use our nym_crypto::hmac module instead
|
// TODO: change that to use our nym_crypto::hmac module instead
|
||||||
#[allow(clippy::expect_used)]
|
#[allow(clippy::expect_used)]
|
||||||
@@ -251,7 +249,7 @@ impl<'de> Deserialize<'de> for ClientMac {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use nym_crypto::asymmetric::encryption;
|
use nym_crypto::asymmetric::x25519;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn create_ip_pair() {
|
fn create_ip_pair() {
|
||||||
@@ -266,8 +264,8 @@ mod tests {
|
|||||||
fn client_request_roundtrip() {
|
fn client_request_roundtrip() {
|
||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::thread_rng();
|
||||||
|
|
||||||
let gateway_key_pair = encryption::KeyPair::new(&mut rng);
|
let gateway_key_pair = x25519::KeyPair::new(&mut rng);
|
||||||
let client_key_pair = encryption::KeyPair::new(&mut rng);
|
let client_key_pair = x25519::KeyPair::new(&mut rng);
|
||||||
|
|
||||||
let nonce = 1234567890;
|
let nonce = 1234567890;
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ use nym_credentials::ecash::bandwidth::IssuanceTicketBook;
|
|||||||
use nym_credentials::ecash::utils::obtain_aggregate_wallet;
|
use nym_credentials::ecash::utils::obtain_aggregate_wallet;
|
||||||
use nym_credentials::IssuedTicketBook;
|
use nym_credentials::IssuedTicketBook;
|
||||||
use nym_credentials_interface::TicketType;
|
use nym_credentials_interface::TicketType;
|
||||||
use nym_crypto::asymmetric::identity;
|
use nym_crypto::asymmetric::ed25519;
|
||||||
use nym_ecash_time::{ecash_default_expiration_date, Date};
|
use nym_ecash_time::{ecash_default_expiration_date, Date};
|
||||||
use nym_validator_client::coconut::all_ecash_api_clients;
|
use nym_validator_client::coconut::all_ecash_api_clients;
|
||||||
use nym_validator_client::nym_api::EpochId;
|
use nym_validator_client::nym_api::EpochId;
|
||||||
@@ -31,7 +31,7 @@ where
|
|||||||
C: EcashSigningClient + EcashQueryClient + Sync,
|
C: EcashSigningClient + EcashQueryClient + Sync,
|
||||||
{
|
{
|
||||||
let mut rng = OsRng;
|
let mut rng = OsRng;
|
||||||
let signing_key = identity::PrivateKey::new(&mut rng);
|
let signing_key = ed25519::PrivateKey::new(&mut rng);
|
||||||
let expiration = expiration.unwrap_or_else(ecash_default_expiration_date);
|
let expiration = expiration.unwrap_or_else(ecash_default_expiration_date);
|
||||||
|
|
||||||
let deposit_amount = client.get_required_deposit_amount().await?;
|
let deposit_amount = client.get_required_deposit_amount().await?;
|
||||||
|
|||||||
@@ -4,8 +4,8 @@
|
|||||||
use nym_credential_storage::error::StorageError;
|
use nym_credential_storage::error::StorageError;
|
||||||
use nym_credentials::error::Error as CredentialsError;
|
use nym_credentials::error::Error as CredentialsError;
|
||||||
use nym_credentials_interface::CompactEcashError;
|
use nym_credentials_interface::CompactEcashError;
|
||||||
use nym_crypto::asymmetric::encryption::KeyRecoveryError;
|
use nym_crypto::asymmetric::ed25519::Ed25519RecoveryError;
|
||||||
use nym_crypto::asymmetric::identity::Ed25519RecoveryError;
|
use nym_crypto::asymmetric::x25519::KeyRecoveryError;
|
||||||
use nym_validator_client::coconut::EcashApiError;
|
use nym_validator_client::coconut::EcashApiError;
|
||||||
use nym_validator_client::error::ValidatorClientError;
|
use nym_validator_client::error::ValidatorClientError;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ impl std::fmt::Display for BandwidthStatusMessage {
|
|||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
BandwidthStatusMessage::RemainingBandwidth(b) => {
|
BandwidthStatusMessage::RemainingBandwidth(b) => {
|
||||||
write!(f, "remaining bandwidth: {}", b)
|
write!(f, "remaining bandwidth: {b}")
|
||||||
}
|
}
|
||||||
BandwidthStatusMessage::NoBandwidth => write!(f, "no bandwidth left"),
|
BandwidthStatusMessage::NoBandwidth => write!(f, "no bandwidth left"),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -207,7 +207,7 @@ where
|
|||||||
<St as Storage>::StorageError: Send + Sync + 'static,
|
<St as Storage>::StorageError: Send + Sync + 'static,
|
||||||
{
|
{
|
||||||
if let Some(stored) = storage
|
if let Some(stored) = storage
|
||||||
.get_expiration_date_signatures(expiration_date)
|
.get_expiration_date_signatures(expiration_date, epoch_id)
|
||||||
.await
|
.await
|
||||||
.map_err(BandwidthControllerError::credential_storage_error)?
|
.map_err(BandwidthControllerError::credential_storage_error)?
|
||||||
{
|
{
|
||||||
@@ -220,7 +220,7 @@ where
|
|||||||
ecash_apis,
|
ecash_apis,
|
||||||
|api| async move {
|
|api| async move {
|
||||||
api.api_client
|
api.api_client
|
||||||
.global_expiration_date_signatures(Some(expiration_date))
|
.global_expiration_date_signatures(Some(expiration_date), Some(epoch_id))
|
||||||
.await
|
.await
|
||||||
},
|
},
|
||||||
format!("aggregated coin index signatures for date {expiration_date}"),
|
format!("aggregated coin index signatures for date {expiration_date}"),
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ clap_complete = { workspace = true, optional = true }
|
|||||||
clap_complete_fig = { workspace = true, optional = true }
|
clap_complete_fig = { workspace = true, optional = true }
|
||||||
const-str = { workspace = true }
|
const-str = { workspace = true }
|
||||||
log = { workspace = true }
|
log = { workspace = true }
|
||||||
pretty_env_logger = { workspace = true }
|
|
||||||
schemars = { workspace = true, features = ["preserve_order"], optional = true }
|
schemars = { workspace = true, features = ["preserve_order"], optional = true }
|
||||||
serde = { workspace = true, features = ["derive"] }
|
serde = { workspace = true, features = ["derive"] }
|
||||||
serde_json = { workspace = true, optional = true }
|
serde_json = { workspace = true, optional = true }
|
||||||
|
|||||||
@@ -21,29 +21,6 @@ pub struct LoggingSettings {
|
|||||||
// well, we need to implement something here at some point...
|
// well, we need to implement something here at some point...
|
||||||
}
|
}
|
||||||
|
|
||||||
// I'd argue we should start transitioning from `log` to `tracing`
|
|
||||||
pub fn setup_logging() {
|
|
||||||
let mut log_builder = pretty_env_logger::formatted_timed_builder();
|
|
||||||
if let Ok(s) = ::std::env::var("RUST_LOG") {
|
|
||||||
log_builder.parse_filters(&s);
|
|
||||||
} else {
|
|
||||||
// default to 'Info'
|
|
||||||
log_builder.filter(None, log::LevelFilter::Info);
|
|
||||||
}
|
|
||||||
|
|
||||||
log_builder
|
|
||||||
.filter_module("hyper", log::LevelFilter::Warn)
|
|
||||||
.filter_module("tokio_reactor", log::LevelFilter::Warn)
|
|
||||||
.filter_module("reqwest", log::LevelFilter::Warn)
|
|
||||||
.filter_module("mio", log::LevelFilter::Warn)
|
|
||||||
.filter_module("want", log::LevelFilter::Warn)
|
|
||||||
.filter_module("tungstenite", log::LevelFilter::Warn)
|
|
||||||
.filter_module("tokio_tungstenite", log::LevelFilter::Warn)
|
|
||||||
.filter_module("handlebars", log::LevelFilter::Warn)
|
|
||||||
.filter_module("sled", log::LevelFilter::Warn)
|
|
||||||
.init();
|
|
||||||
}
|
|
||||||
|
|
||||||
// don't call init so that we could attach additional layers
|
// don't call init so that we could attach additional layers
|
||||||
#[cfg(feature = "basic_tracing")]
|
#[cfg(feature = "basic_tracing")]
|
||||||
pub fn build_tracing_logger() -> impl tracing_subscriber::layer::SubscriberExt {
|
pub fn build_tracing_logger() -> impl tracing_subscriber::layer::SubscriberExt {
|
||||||
|
|||||||
@@ -12,42 +12,36 @@ license.workspace = true
|
|||||||
async-trait = { workspace = true }
|
async-trait = { workspace = true }
|
||||||
base64 = { workspace = true }
|
base64 = { workspace = true }
|
||||||
bs58 = { workspace = true }
|
bs58 = { workspace = true }
|
||||||
cfg-if = { workspace = true }
|
|
||||||
clap = { workspace = true, optional = true }
|
clap = { workspace = true, optional = true }
|
||||||
|
cfg-if = { workspace = true }
|
||||||
comfy-table = { workspace = true, optional = true }
|
comfy-table = { workspace = true, optional = true }
|
||||||
futures = { workspace = true }
|
futures = { workspace = true }
|
||||||
humantime-serde = { workspace = true }
|
humantime = { workspace = true }
|
||||||
log = { workspace = true }
|
|
||||||
rand = { workspace = true }
|
rand = { workspace = true }
|
||||||
rand_chacha = { workspace = true }
|
rand_chacha = { workspace = true }
|
||||||
serde = { workspace = true, features = ["derive"] }
|
serde = { workspace = true, features = ["derive"] }
|
||||||
serde_json = { workspace = true }
|
serde_json = { workspace = true }
|
||||||
sha2 = { workspace = true }
|
sha2 = { workspace = true }
|
||||||
si-scale = { workspace = true }
|
si-scale = { workspace = true }
|
||||||
tap = { workspace = true }
|
|
||||||
thiserror = { workspace = true }
|
thiserror = { workspace = true }
|
||||||
url = { workspace = true, features = ["serde"] }
|
url = { workspace = true, features = ["serde"] }
|
||||||
tokio = { workspace = true, features = ["macros"] }
|
|
||||||
time = { workspace = true }
|
time = { workspace = true }
|
||||||
|
tokio = { workspace = true, features = ["sync", "macros"] }
|
||||||
|
tracing = { workspace = true }
|
||||||
zeroize = { workspace = true }
|
zeroize = { workspace = true }
|
||||||
|
|
||||||
# internal
|
# internal
|
||||||
nym-id = { path = "../nym-id" }
|
nym-id = { path = "../nym-id" }
|
||||||
nym-bandwidth-controller = { path = "../bandwidth-controller" }
|
nym-bandwidth-controller = { path = "../bandwidth-controller" }
|
||||||
nym-config = { path = "../config" }
|
|
||||||
nym-country-group = { path = "../country-group" }
|
|
||||||
nym-crypto = { path = "../crypto" }
|
nym-crypto = { path = "../crypto" }
|
||||||
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-http-api-client = { path = "../http-api-client" }
|
||||||
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" }
|
||||||
nym-statistics-common = { path = "../statistics" }
|
nym-statistics-common = { path = "../statistics" }
|
||||||
nym-pemstore = { path = "../pemstore" }
|
nym-pemstore = { path = "../pemstore" }
|
||||||
nym-topology = { path = "../topology", features = ["persistence"] }
|
nym-topology = { path = "../topology", features = ["persistence"] }
|
||||||
nym-mixnet-client = { path = "../client-libs/mixnet-client", default-features = false }
|
|
||||||
nym-validator-client = { path = "../client-libs/validator-client", default-features = false }
|
nym-validator-client = { path = "../client-libs/validator-client", default-features = false }
|
||||||
nym-task = { path = "../task" }
|
nym-task = { path = "../task" }
|
||||||
nym-credentials-interface = { path = "../credentials-interface" }
|
nym-credentials-interface = { path = "../credentials-interface" }
|
||||||
@@ -60,6 +54,9 @@ nym-client-core-surb-storage = { path = "./surb-storage" }
|
|||||||
nym-client-core-gateways-storage = { path = "./gateways-storage" }
|
nym-client-core-gateways-storage = { path = "./gateways-storage" }
|
||||||
nym-ecash-time = { path = "../ecash-time" }
|
nym-ecash-time = { path = "../ecash-time" }
|
||||||
|
|
||||||
|
[target."cfg(not(target_arch = \"wasm32\"))".dependencies]
|
||||||
|
nym-mixnet-client = { path = "../client-libs/mixnet-client", default-features = false }
|
||||||
|
|
||||||
### For serving prometheus metrics
|
### For serving prometheus metrics
|
||||||
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.hyper]
|
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.hyper]
|
||||||
workspace = true
|
workspace = true
|
||||||
@@ -127,3 +124,6 @@ fs-surb-storage = ["nym-client-core-surb-storage/fs-surb-storage"]
|
|||||||
fs-gateways-storage = ["nym-client-core-gateways-storage/fs-gateways-storage"]
|
fs-gateways-storage = ["nym-client-core-gateways-storage/fs-gateways-storage"]
|
||||||
wasm = ["nym-gateway-client/wasm"]
|
wasm = ["nym-gateway-client/wasm"]
|
||||||
metrics-server = []
|
metrics-server = []
|
||||||
|
|
||||||
|
[lints]
|
||||||
|
workspace = true
|
||||||
|
|||||||
@@ -14,12 +14,12 @@ url = { workspace = true, features = ["serde"] }
|
|||||||
|
|
||||||
nym-config = { path = "../../config" }
|
nym-config = { path = "../../config" }
|
||||||
|
|
||||||
nym-country-group = { path = "../../country-group" }
|
|
||||||
nym-pemstore = { path = "../../pemstore", optional = true }
|
nym-pemstore = { path = "../../pemstore", optional = true }
|
||||||
|
|
||||||
# those are pulling so many deps T.T
|
# those are pulling so many deps T.T
|
||||||
nym-sphinx-params = { path = "../../nymsphinx/params" }
|
nym-sphinx-params = { path = "../../nymsphinx/params" }
|
||||||
nym-sphinx-addressing = { path = "../../nymsphinx/addressing" }
|
nym-sphinx-addressing = { path = "../../nymsphinx/addressing" }
|
||||||
|
nym-statistics-common = { path = "../../statistics" }
|
||||||
|
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ use nym_config::defaults::NymNetworkDetails;
|
|||||||
use nym_config::serde_helpers::{de_maybe_stringified, ser_maybe_stringified};
|
use nym_config::serde_helpers::{de_maybe_stringified, ser_maybe_stringified};
|
||||||
use nym_sphinx_addressing::Recipient;
|
use nym_sphinx_addressing::Recipient;
|
||||||
use nym_sphinx_params::{PacketSize, PacketType};
|
use nym_sphinx_params::{PacketSize, PacketType};
|
||||||
|
use nym_statistics_common::types::SessionType;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
@@ -22,7 +23,7 @@ const DEFAULT_ACK_WAIT_MULTIPLIER: f64 = 1.5;
|
|||||||
const DEFAULT_ACK_WAIT_ADDITION: Duration = Duration::from_millis(1_500);
|
const DEFAULT_ACK_WAIT_ADDITION: Duration = Duration::from_millis(1_500);
|
||||||
const DEFAULT_LOOP_COVER_STREAM_AVERAGE_DELAY: Duration = Duration::from_millis(200);
|
const DEFAULT_LOOP_COVER_STREAM_AVERAGE_DELAY: Duration = Duration::from_millis(200);
|
||||||
const DEFAULT_MESSAGE_STREAM_AVERAGE_DELAY: Duration = Duration::from_millis(20);
|
const DEFAULT_MESSAGE_STREAM_AVERAGE_DELAY: Duration = Duration::from_millis(20);
|
||||||
const DEFAULT_AVERAGE_PACKET_DELAY: Duration = Duration::from_millis(50);
|
const DEFAULT_AVERAGE_PACKET_DELAY: Duration = Duration::from_millis(15);
|
||||||
const DEFAULT_TOPOLOGY_REFRESH_RATE: Duration = Duration::from_secs(5 * 60); // every 5min
|
const DEFAULT_TOPOLOGY_REFRESH_RATE: Duration = Duration::from_secs(5 * 60); // every 5min
|
||||||
const DEFAULT_TOPOLOGY_RESOLUTION_TIMEOUT: Duration = Duration::from_millis(5_000);
|
const DEFAULT_TOPOLOGY_RESOLUTION_TIMEOUT: Duration = Duration::from_millis(5_000);
|
||||||
|
|
||||||
@@ -56,20 +57,17 @@ const DEFAULT_MAXIMUM_ALLOWED_SURB_REQUEST_SIZE: u32 = 500;
|
|||||||
|
|
||||||
const DEFAULT_MAXIMUM_REPLY_SURB_REREQUEST_WAITING_PERIOD: Duration = Duration::from_secs(10);
|
const DEFAULT_MAXIMUM_REPLY_SURB_REREQUEST_WAITING_PERIOD: Duration = Duration::from_secs(10);
|
||||||
const DEFAULT_MAXIMUM_REPLY_SURB_DROP_WAITING_PERIOD: Duration = Duration::from_secs(5 * 60);
|
const DEFAULT_MAXIMUM_REPLY_SURB_DROP_WAITING_PERIOD: Duration = Duration::from_secs(5 * 60);
|
||||||
|
const DEFAULT_MAXIMUM_REPLY_SURB_REREQUESTS: usize = 5;
|
||||||
// 12 hours
|
|
||||||
const DEFAULT_MAXIMUM_REPLY_SURB_AGE: Duration = Duration::from_secs(12 * 60 * 60);
|
|
||||||
|
|
||||||
// 24 hours
|
// 24 hours
|
||||||
const DEFAULT_MAXIMUM_REPLY_KEY_AGE: Duration = Duration::from_secs(24 * 60 * 60);
|
const DEFAULT_MAXIMUM_REPLY_KEY_AGE: Duration = Duration::from_secs(24 * 60 * 60);
|
||||||
|
|
||||||
// stats reporting related
|
// stats reporting related
|
||||||
|
|
||||||
/// Time interval between reporting statistics to the given provider if it exist
|
/// Time interval between reporting statistics to the given provider if it exists
|
||||||
const STATS_REPORT_INTERVAL_SECS: Duration = Duration::from_secs(300);
|
const STATS_REPORT_INTERVAL_SECS: Duration = Duration::from_secs(300);
|
||||||
|
|
||||||
use crate::error::InvalidTrafficModeFailure;
|
use crate::error::InvalidTrafficModeFailure;
|
||||||
pub use nym_country_group::CountryGroup;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
|
#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
|
||||||
#[serde(deny_unknown_fields)]
|
#[serde(deny_unknown_fields)]
|
||||||
@@ -258,15 +256,6 @@ impl Config {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_topology_structure(mut self, topology_structure: TopologyStructure) -> Self {
|
|
||||||
self.set_topology_structure(topology_structure);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_topology_structure(&mut self, topology_structure: TopologyStructure) {
|
|
||||||
self.debug.topology.topology_structure = topology_structure;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn with_no_per_hop_delays(mut self, no_per_hop_delays: bool) -> Self {
|
pub fn with_no_per_hop_delays(mut self, no_per_hop_delays: bool) -> Self {
|
||||||
if no_per_hop_delays {
|
if no_per_hop_delays {
|
||||||
self.set_no_per_hop_delays()
|
self.set_no_per_hop_delays()
|
||||||
@@ -385,14 +374,12 @@ pub struct Traffic {
|
|||||||
/// sent packet is going to be delayed at any given mix node.
|
/// sent packet is going to be delayed at any given mix node.
|
||||||
/// So for a packet going through three mix nodes, on average, it will take three times this value
|
/// So for a packet going through three mix nodes, on average, it will take three times this value
|
||||||
/// until the packet reaches its destination.
|
/// until the packet reaches its destination.
|
||||||
#[serde(with = "humantime_serde")]
|
|
||||||
pub average_packet_delay: Duration,
|
pub average_packet_delay: Duration,
|
||||||
|
|
||||||
/// The parameter of Poisson distribution determining how long, on average,
|
/// The parameter of Poisson distribution determining how long, on average,
|
||||||
/// it is going to take another 'real traffic stream' message to be sent.
|
/// it is going to take another 'real traffic stream' message to be sent.
|
||||||
/// If no real packets are available and cover traffic is enabled,
|
/// If no real packets are available and cover traffic is enabled,
|
||||||
/// a loop cover message is sent instead in order to preserve the rate.
|
/// a loop cover message is sent instead in order to preserve the rate.
|
||||||
#[serde(with = "humantime_serde")]
|
|
||||||
pub message_sending_average_delay: Duration,
|
pub message_sending_average_delay: Duration,
|
||||||
|
|
||||||
/// Controls whether the main packet stream constantly produces packets according to the predefined
|
/// Controls whether the main packet stream constantly produces packets according to the predefined
|
||||||
@@ -415,7 +402,24 @@ pub struct Traffic {
|
|||||||
/// Do not set it unless you understand the consequences of that change.
|
/// Do not set it unless you understand the consequences of that change.
|
||||||
pub secondary_packet_size: Option<PacketSize>,
|
pub secondary_packet_size: Option<PacketSize>,
|
||||||
|
|
||||||
|
/// Specify whether any constructed sphinx packets should use the legacy format,
|
||||||
|
/// where the payload keys are explicitly attached rather than using the seeds
|
||||||
|
/// this affects any forward packets, acks and reply surbs
|
||||||
|
/// this flag should remain disabled until sufficient number of nodes on the network has upgraded
|
||||||
|
/// and support updated format.
|
||||||
|
/// in the case of reply surbs, the recipient must also understand the new encoding
|
||||||
|
pub use_legacy_sphinx_format: bool,
|
||||||
|
|
||||||
pub packet_type: PacketType,
|
pub packet_type: PacketType,
|
||||||
|
|
||||||
|
/// Indicates whether to mix hops or not. If mix hops are enabled, traffic
|
||||||
|
/// will be routed as usual, to the entry gateway, through three mix nodes, egressing
|
||||||
|
/// through the exit gateway. If mix hops are disabled, traffic will be routed directly
|
||||||
|
/// from the entry gateway to the exit gateway, bypassing the mix nodes.
|
||||||
|
///
|
||||||
|
/// This overrides the `use_legacy_sphinx_format` setting as reduced mix hops
|
||||||
|
/// requires use of the updated SURB packet format.
|
||||||
|
pub disable_mix_hops: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Traffic {
|
impl Traffic {
|
||||||
@@ -442,6 +446,11 @@ impl Default for Traffic {
|
|||||||
primary_packet_size: PacketSize::RegularPacket,
|
primary_packet_size: PacketSize::RegularPacket,
|
||||||
secondary_packet_size: None,
|
secondary_packet_size: None,
|
||||||
packet_type: PacketType::Mix,
|
packet_type: PacketType::Mix,
|
||||||
|
|
||||||
|
// we should use the legacy format until sufficient number of nodes understand the
|
||||||
|
// improved encoding
|
||||||
|
use_legacy_sphinx_format: true,
|
||||||
|
disable_mix_hops: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -546,9 +555,6 @@ pub struct Topology {
|
|||||||
#[serde(with = "humantime_serde")]
|
#[serde(with = "humantime_serde")]
|
||||||
pub max_startup_gateway_waiting_period: Duration,
|
pub max_startup_gateway_waiting_period: Duration,
|
||||||
|
|
||||||
/// Specifies the mixnode topology to be used for sending packets.
|
|
||||||
pub topology_structure: TopologyStructure,
|
|
||||||
|
|
||||||
/// Specifies a minimum performance of a mixnode that is used on route construction.
|
/// Specifies a minimum performance of a mixnode that is used on route construction.
|
||||||
/// This setting is only applicable when `NymApi` topology is used.
|
/// This setting is only applicable when `NymApi` topology is used.
|
||||||
pub minimum_mixnode_performance: u8,
|
pub minimum_mixnode_performance: u8,
|
||||||
@@ -570,30 +576,6 @@ pub struct Topology {
|
|||||||
pub ignore_ingress_epoch_role: bool,
|
pub ignore_ingress_epoch_role: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::large_enum_variant)]
|
|
||||||
#[derive(Default, Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
|
||||||
pub enum TopologyStructure {
|
|
||||||
#[default]
|
|
||||||
NymApi,
|
|
||||||
GeoAware(GroupBy),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(clippy::large_enum_variant)]
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
|
||||||
pub enum GroupBy {
|
|
||||||
CountryGroup(CountryGroup),
|
|
||||||
NymAddress(Recipient),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl std::fmt::Display for GroupBy {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
||||||
match self {
|
|
||||||
GroupBy::CountryGroup(group) => write!(f, "group: {group}"),
|
|
||||||
GroupBy::NymAddress(address) => write!(f, "address: {address}"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for Topology {
|
impl Default for Topology {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Topology {
|
Topology {
|
||||||
@@ -601,7 +583,6 @@ impl Default for Topology {
|
|||||||
topology_resolution_timeout: DEFAULT_TOPOLOGY_RESOLUTION_TIMEOUT,
|
topology_resolution_timeout: DEFAULT_TOPOLOGY_RESOLUTION_TIMEOUT,
|
||||||
disable_refreshing: false,
|
disable_refreshing: false,
|
||||||
max_startup_gateway_waiting_period: DEFAULT_MAX_STARTUP_GATEWAY_WAITING_PERIOD,
|
max_startup_gateway_waiting_period: DEFAULT_MAX_STARTUP_GATEWAY_WAITING_PERIOD,
|
||||||
topology_structure: TopologyStructure::default(),
|
|
||||||
minimum_mixnode_performance: DEFAULT_MIN_MIXNODE_PERFORMANCE,
|
minimum_mixnode_performance: DEFAULT_MIN_MIXNODE_PERFORMANCE,
|
||||||
minimum_gateway_performance: DEFAULT_MIN_GATEWAY_PERFORMANCE,
|
minimum_gateway_performance: DEFAULT_MIN_GATEWAY_PERFORMANCE,
|
||||||
use_extended_topology: false,
|
use_extended_topology: false,
|
||||||
@@ -645,10 +626,9 @@ pub struct ReplySurbs {
|
|||||||
#[serde(with = "humantime_serde")]
|
#[serde(with = "humantime_serde")]
|
||||||
pub maximum_reply_surb_drop_waiting_period: Duration,
|
pub maximum_reply_surb_drop_waiting_period: Duration,
|
||||||
|
|
||||||
/// Defines maximum amount of time given reply surb is going to be valid for.
|
/// Defines maximum number of times the client is going to re-request reply surbs
|
||||||
/// This is going to be superseded by key rotation once implemented.
|
/// for clearing pending messages before giving up after making no progress.
|
||||||
#[serde(with = "humantime_serde")]
|
pub maximum_reply_surbs_rerequests: usize,
|
||||||
pub maximum_reply_surb_age: Duration,
|
|
||||||
|
|
||||||
/// Defines maximum amount of time given reply key is going to be valid for.
|
/// Defines maximum amount of time given reply key is going to be valid for.
|
||||||
/// This is going to be superseded by key rotation once implemented.
|
/// This is going to be superseded by key rotation once implemented.
|
||||||
@@ -658,9 +638,6 @@ pub struct ReplySurbs {
|
|||||||
/// Specifies the number of mixnet hops the packet should go through. If not specified, then
|
/// Specifies the number of mixnet hops the packet should go through. If not specified, then
|
||||||
/// the default value is used.
|
/// the default value is used.
|
||||||
pub surb_mix_hops: Option<u8>,
|
pub surb_mix_hops: Option<u8>,
|
||||||
|
|
||||||
/// Specifies if we should reset all the sender tags on startup
|
|
||||||
pub fresh_sender_tags: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for ReplySurbs {
|
impl Default for ReplySurbs {
|
||||||
@@ -675,10 +652,9 @@ impl Default for ReplySurbs {
|
|||||||
maximum_reply_surb_rerequest_waiting_period:
|
maximum_reply_surb_rerequest_waiting_period:
|
||||||
DEFAULT_MAXIMUM_REPLY_SURB_REREQUEST_WAITING_PERIOD,
|
DEFAULT_MAXIMUM_REPLY_SURB_REREQUEST_WAITING_PERIOD,
|
||||||
maximum_reply_surb_drop_waiting_period: DEFAULT_MAXIMUM_REPLY_SURB_DROP_WAITING_PERIOD,
|
maximum_reply_surb_drop_waiting_period: DEFAULT_MAXIMUM_REPLY_SURB_DROP_WAITING_PERIOD,
|
||||||
maximum_reply_surb_age: DEFAULT_MAXIMUM_REPLY_SURB_AGE,
|
maximum_reply_surbs_rerequests: DEFAULT_MAXIMUM_REPLY_SURB_REREQUESTS,
|
||||||
maximum_reply_key_age: DEFAULT_MAXIMUM_REPLY_KEY_AGE,
|
maximum_reply_key_age: DEFAULT_MAXIMUM_REPLY_KEY_AGE,
|
||||||
surb_mix_hops: None,
|
surb_mix_hops: None,
|
||||||
fresh_sender_tags: false,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -737,6 +713,9 @@ pub struct DebugConfig {
|
|||||||
|
|
||||||
/// Defines all configuration options related to the forget me flag.
|
/// Defines all configuration options related to the forget me flag.
|
||||||
pub forget_me: ForgetMe,
|
pub forget_me: ForgetMe,
|
||||||
|
|
||||||
|
/// Defines all configuration options related to the remember me flag.
|
||||||
|
pub remember_me: RememberMe,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DebugConfig {
|
impl DebugConfig {
|
||||||
@@ -760,6 +739,7 @@ impl Default for DebugConfig {
|
|||||||
reply_surbs: Default::default(),
|
reply_surbs: Default::default(),
|
||||||
stats_reporting: Default::default(),
|
stats_reporting: Default::default(),
|
||||||
forget_me: Default::default(),
|
forget_me: Default::default(),
|
||||||
|
remember_me: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -825,3 +805,57 @@ impl ForgetMe {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Default, Debug, Deserialize, PartialEq, Serialize, Copy)]
|
||||||
|
pub struct RememberMe {
|
||||||
|
/// Signal that this client should be accounted for in the stats
|
||||||
|
stats: bool,
|
||||||
|
|
||||||
|
/// Type of the session to remember, if it should be remembered
|
||||||
|
session_type: SessionType,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RememberMe {
|
||||||
|
pub fn new_vpn() -> Self {
|
||||||
|
Self {
|
||||||
|
stats: true,
|
||||||
|
session_type: SessionType::Vpn,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_mixnet() -> Self {
|
||||||
|
Self {
|
||||||
|
stats: true,
|
||||||
|
session_type: SessionType::Mixnet,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_native() -> Self {
|
||||||
|
Self {
|
||||||
|
stats: true,
|
||||||
|
session_type: SessionType::Native,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new(stats: bool, session_type: SessionType) -> Self {
|
||||||
|
Self {
|
||||||
|
stats,
|
||||||
|
session_type,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_none() -> Self {
|
||||||
|
Self {
|
||||||
|
stats: false,
|
||||||
|
session_type: SessionType::Unknown,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn session_type(&self) -> SessionType {
|
||||||
|
self.session_type
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn stats(&self) -> bool {
|
||||||
|
self.stats
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ pub mod v2;
|
|||||||
pub mod v3;
|
pub mod v3;
|
||||||
pub mod v4;
|
pub mod v4;
|
||||||
pub mod v5;
|
pub mod v5;
|
||||||
|
pub mod v6;
|
||||||
|
|
||||||
// aliases for backwards compatibility
|
// aliases for backwards compatibility
|
||||||
pub use v1 as old_config_v1_1_13;
|
pub use v1 as old_config_v1_1_13;
|
||||||
@@ -13,3 +14,4 @@ pub use v2 as old_config_v1_1_20;
|
|||||||
pub use v3 as old_config_v1_1_20_2;
|
pub use v3 as old_config_v1_1_20_2;
|
||||||
pub use v4 as old_config_v1_1_30;
|
pub use v4 as old_config_v1_1_30;
|
||||||
pub use v5 as old_config_v1_1_33;
|
pub use v5 as old_config_v1_1_33;
|
||||||
|
pub use v6 as old_config_v1_1_54;
|
||||||
|
|||||||
@@ -2,10 +2,9 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
use crate::old::v5::{
|
use crate::old::v5::{
|
||||||
AcknowledgementsV5, ClientV5, ConfigV5, CoverTrafficV5, DebugConfigV5, GatewayConnectionV5,
|
AcknowledgementsV5, ClientV5, ConfigV5, CountryGroupV5, CoverTrafficV5, DebugConfigV5,
|
||||||
GroupByV5, ReplySurbsV5, TopologyStructureV5, TopologyV5, TrafficV5,
|
GatewayConnectionV5, GroupByV5, ReplySurbsV5, TopologyStructureV5, TopologyV5, TrafficV5,
|
||||||
};
|
};
|
||||||
use crate::CountryGroup;
|
|
||||||
use nym_sphinx_addressing::Recipient;
|
use nym_sphinx_addressing::Recipient;
|
||||||
use nym_sphinx_params::{PacketSize, PacketType};
|
use nym_sphinx_params::{PacketSize, PacketType};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
@@ -369,31 +368,47 @@ impl From<TopologyStructureV4> for TopologyStructureV5 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Hash, PartialEq, Eq, Serialize, Deserialize, Debug)]
|
||||||
|
pub enum CountryGroupV4 {
|
||||||
|
Europe,
|
||||||
|
NorthAmerica,
|
||||||
|
SouthAmerica,
|
||||||
|
Oceania,
|
||||||
|
Asia,
|
||||||
|
Africa,
|
||||||
|
Unknown,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<CountryGroupV4> for CountryGroupV5 {
|
||||||
|
fn from(value: CountryGroupV4) -> Self {
|
||||||
|
match value {
|
||||||
|
CountryGroupV4::Europe => CountryGroupV5::Europe,
|
||||||
|
CountryGroupV4::NorthAmerica => CountryGroupV5::NorthAmerica,
|
||||||
|
CountryGroupV4::SouthAmerica => CountryGroupV5::SouthAmerica,
|
||||||
|
CountryGroupV4::Oceania => CountryGroupV5::Oceania,
|
||||||
|
CountryGroupV4::Asia => CountryGroupV5::Asia,
|
||||||
|
CountryGroupV4::Africa => CountryGroupV5::Africa,
|
||||||
|
CountryGroupV4::Unknown => CountryGroupV5::Unknown,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(clippy::large_enum_variant)]
|
#[allow(clippy::large_enum_variant)]
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
pub enum GroupByV4 {
|
pub enum GroupByV4 {
|
||||||
CountryGroup(CountryGroup),
|
CountryGroup(CountryGroupV4),
|
||||||
NymAddress(Recipient),
|
NymAddress(Recipient),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<GroupByV4> for GroupByV5 {
|
impl From<GroupByV4> for GroupByV5 {
|
||||||
fn from(value: GroupByV4) -> Self {
|
fn from(value: GroupByV4) -> Self {
|
||||||
match value {
|
match value {
|
||||||
GroupByV4::CountryGroup(country) => GroupByV5::CountryGroup(country),
|
GroupByV4::CountryGroup(country) => GroupByV5::CountryGroup(country.into()),
|
||||||
GroupByV4::NymAddress(addr) => GroupByV5::NymAddress(addr),
|
GroupByV4::NymAddress(addr) => GroupByV5::NymAddress(addr),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::fmt::Display for GroupByV4 {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
||||||
match self {
|
|
||||||
GroupByV4::CountryGroup(group) => write!(f, "group: {}", group),
|
|
||||||
GroupByV4::NymAddress(address) => write!(f, "address: {}", address),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for TopologyV4 {
|
impl Default for TopologyV4 {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
TopologyV4 {
|
TopologyV4 {
|
||||||
|
|||||||
@@ -1,16 +1,14 @@
|
|||||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
use crate::{
|
|
||||||
Acknowledgements, Client, Config, CountryGroup, CoverTraffic, DebugConfig, GatewayConnection,
|
|
||||||
GroupBy, ReplySurbs, Topology, TopologyStructure, Traffic,
|
|
||||||
};
|
|
||||||
use nym_sphinx_addressing::Recipient;
|
use nym_sphinx_addressing::Recipient;
|
||||||
use nym_sphinx_params::{PacketSize, PacketType};
|
use nym_sphinx_params::{PacketSize, PacketType};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
|
use super::v6::*;
|
||||||
|
|
||||||
// 'DEBUG'
|
// 'DEBUG'
|
||||||
const DEFAULT_ACK_WAIT_MULTIPLIER: f64 = 1.5;
|
const DEFAULT_ACK_WAIT_MULTIPLIER: f64 = 1.5;
|
||||||
|
|
||||||
@@ -87,18 +85,18 @@ pub struct ConfigV5 {
|
|||||||
pub debug: DebugConfigV5,
|
pub debug: DebugConfigV5,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<ConfigV5> for Config {
|
impl From<ConfigV5> for ConfigV6 {
|
||||||
fn from(value: ConfigV5) -> Self {
|
fn from(value: ConfigV5) -> Self {
|
||||||
Config {
|
ConfigV6 {
|
||||||
client: Client {
|
client: ClientV6 {
|
||||||
version: value.client.version,
|
version: value.client.version,
|
||||||
id: value.client.id,
|
id: value.client.id,
|
||||||
disabled_credentials_mode: value.client.disabled_credentials_mode,
|
disabled_credentials_mode: value.client.disabled_credentials_mode,
|
||||||
nyxd_urls: value.client.nyxd_urls,
|
nyxd_urls: value.client.nyxd_urls,
|
||||||
nym_api_urls: value.client.nym_api_urls,
|
nym_api_urls: value.client.nym_api_urls,
|
||||||
},
|
},
|
||||||
debug: DebugConfig {
|
debug: DebugConfigV6 {
|
||||||
traffic: Traffic {
|
traffic: TrafficV6 {
|
||||||
average_packet_delay: value.debug.traffic.average_packet_delay,
|
average_packet_delay: value.debug.traffic.average_packet_delay,
|
||||||
message_sending_average_delay: value
|
message_sending_average_delay: value
|
||||||
.debug
|
.debug
|
||||||
@@ -113,7 +111,7 @@ impl From<ConfigV5> for Config {
|
|||||||
packet_type: value.debug.traffic.packet_type,
|
packet_type: value.debug.traffic.packet_type,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
cover_traffic: CoverTraffic {
|
cover_traffic: CoverTrafficV6 {
|
||||||
loop_cover_traffic_average_delay: value
|
loop_cover_traffic_average_delay: value
|
||||||
.debug
|
.debug
|
||||||
.cover_traffic
|
.cover_traffic
|
||||||
@@ -127,18 +125,18 @@ impl From<ConfigV5> for Config {
|
|||||||
.cover_traffic
|
.cover_traffic
|
||||||
.disable_loop_cover_traffic_stream,
|
.disable_loop_cover_traffic_stream,
|
||||||
},
|
},
|
||||||
gateway_connection: GatewayConnection {
|
gateway_connection: GatewayConnectionV6 {
|
||||||
gateway_response_timeout: value
|
gateway_response_timeout: value
|
||||||
.debug
|
.debug
|
||||||
.gateway_connection
|
.gateway_connection
|
||||||
.gateway_response_timeout,
|
.gateway_response_timeout,
|
||||||
},
|
},
|
||||||
acknowledgements: Acknowledgements {
|
acknowledgements: AcknowledgementsV6 {
|
||||||
average_ack_delay: value.debug.acknowledgements.average_ack_delay,
|
average_ack_delay: value.debug.acknowledgements.average_ack_delay,
|
||||||
ack_wait_multiplier: value.debug.acknowledgements.ack_wait_multiplier,
|
ack_wait_multiplier: value.debug.acknowledgements.ack_wait_multiplier,
|
||||||
ack_wait_addition: value.debug.acknowledgements.ack_wait_addition,
|
ack_wait_addition: value.debug.acknowledgements.ack_wait_addition,
|
||||||
},
|
},
|
||||||
topology: Topology {
|
topology: TopologyV6 {
|
||||||
topology_refresh_rate: value.debug.topology.topology_refresh_rate,
|
topology_refresh_rate: value.debug.topology.topology_refresh_rate,
|
||||||
topology_resolution_timeout: value.debug.topology.topology_resolution_timeout,
|
topology_resolution_timeout: value.debug.topology.topology_resolution_timeout,
|
||||||
disable_refreshing: value.debug.topology.disable_refreshing,
|
disable_refreshing: value.debug.topology.disable_refreshing,
|
||||||
@@ -146,10 +144,9 @@ impl From<ConfigV5> for Config {
|
|||||||
.debug
|
.debug
|
||||||
.topology
|
.topology
|
||||||
.max_startup_gateway_waiting_period,
|
.max_startup_gateway_waiting_period,
|
||||||
topology_structure: value.debug.topology.topology_structure.into(),
|
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
reply_surbs: ReplySurbs {
|
reply_surbs: ReplySurbsV6 {
|
||||||
minimum_reply_surb_storage_threshold: value
|
minimum_reply_surb_storage_threshold: value
|
||||||
.debug
|
.debug
|
||||||
.reply_surbs
|
.reply_surbs
|
||||||
@@ -372,40 +369,24 @@ pub enum TopologyStructureV5 {
|
|||||||
GeoAware(GroupByV5),
|
GeoAware(GroupByV5),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<TopologyStructureV5> for TopologyStructure {
|
#[derive(Copy, Clone, Hash, PartialEq, Eq, Serialize, Deserialize, Debug)]
|
||||||
fn from(value: TopologyStructureV5) -> Self {
|
pub enum CountryGroupV5 {
|
||||||
match value {
|
Europe,
|
||||||
TopologyStructureV5::NymApi => TopologyStructure::NymApi,
|
NorthAmerica,
|
||||||
TopologyStructureV5::GeoAware(group_by) => TopologyStructure::GeoAware(group_by.into()),
|
SouthAmerica,
|
||||||
}
|
Oceania,
|
||||||
}
|
Asia,
|
||||||
|
Africa,
|
||||||
|
Unknown,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::large_enum_variant)]
|
#[allow(clippy::large_enum_variant)]
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
pub enum GroupByV5 {
|
pub enum GroupByV5 {
|
||||||
CountryGroup(CountryGroup),
|
CountryGroup(CountryGroupV5),
|
||||||
NymAddress(Recipient),
|
NymAddress(Recipient),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<GroupByV5> for GroupBy {
|
|
||||||
fn from(value: GroupByV5) -> Self {
|
|
||||||
match value {
|
|
||||||
GroupByV5::CountryGroup(country) => GroupBy::CountryGroup(country),
|
|
||||||
GroupByV5::NymAddress(addr) => GroupBy::NymAddress(addr),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl std::fmt::Display for GroupByV5 {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
||||||
match self {
|
|
||||||
GroupByV5::CountryGroup(group) => write!(f, "group: {}", group),
|
|
||||||
GroupByV5::NymAddress(address) => write!(f, "address: {}", address),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for TopologyV5 {
|
impl Default for TopologyV5 {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
TopologyV5 {
|
TopologyV5 {
|
||||||
|
|||||||
@@ -0,0 +1,622 @@
|
|||||||
|
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
Acknowledgements, Client, Config, CoverTraffic, DebugConfig, ForgetMe, GatewayConnection,
|
||||||
|
RememberMe, ReplySurbs, StatsReporting, Topology, Traffic,
|
||||||
|
};
|
||||||
|
use nym_config::serde_helpers::{de_maybe_stringified, ser_maybe_stringified};
|
||||||
|
use nym_sphinx_addressing::Recipient;
|
||||||
|
use nym_sphinx_params::{PacketSize, PacketType};
|
||||||
|
use nym_statistics_common::types::SessionType;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::time::Duration;
|
||||||
|
use url::Url;
|
||||||
|
|
||||||
|
// 'DEBUG'
|
||||||
|
const DEFAULT_ACK_WAIT_MULTIPLIER: f64 = 1.5;
|
||||||
|
|
||||||
|
const DEFAULT_ACK_WAIT_ADDITION: Duration = Duration::from_millis(1_500);
|
||||||
|
const DEFAULT_LOOP_COVER_STREAM_AVERAGE_DELAY: Duration = Duration::from_millis(200);
|
||||||
|
const DEFAULT_MESSAGE_STREAM_AVERAGE_DELAY: Duration = Duration::from_millis(20);
|
||||||
|
const DEFAULT_AVERAGE_PACKET_DELAY: Duration = Duration::from_millis(15);
|
||||||
|
const DEFAULT_TOPOLOGY_REFRESH_RATE: Duration = Duration::from_secs(5 * 60); // every 5min
|
||||||
|
const DEFAULT_TOPOLOGY_RESOLUTION_TIMEOUT: Duration = Duration::from_millis(5_000);
|
||||||
|
|
||||||
|
// the same values as our current (10.06.24) blacklist
|
||||||
|
const DEFAULT_MIN_MIXNODE_PERFORMANCE: u8 = 50;
|
||||||
|
const DEFAULT_MIN_GATEWAY_PERFORMANCE: u8 = 50;
|
||||||
|
|
||||||
|
const DEFAULT_MAX_STARTUP_GATEWAY_WAITING_PERIOD: Duration = Duration::from_secs(70 * 60); // 70min -> full epoch (1h) + a bit of overhead
|
||||||
|
|
||||||
|
// Set this to a high value for now, so that we don't risk sporadic timeouts that might cause
|
||||||
|
// bought bandwidth tokens to not have time to be spent; Once we remove the gateway from the
|
||||||
|
// bandwidth bridging protocol, we can come back to a smaller timeout value
|
||||||
|
const DEFAULT_GATEWAY_RESPONSE_TIMEOUT: Duration = Duration::from_secs(5 * 60);
|
||||||
|
|
||||||
|
const DEFAULT_COVER_TRAFFIC_PRIMARY_SIZE_RATIO: f64 = 0.70;
|
||||||
|
|
||||||
|
// reply-surbs related:
|
||||||
|
|
||||||
|
// define when to request
|
||||||
|
// clients/client-core/src/client/replies/reply_storage/surb_storage.rs
|
||||||
|
const DEFAULT_MINIMUM_REPLY_SURB_STORAGE_THRESHOLD: usize = 10;
|
||||||
|
const DEFAULT_MAXIMUM_REPLY_SURB_STORAGE_THRESHOLD: usize = 200;
|
||||||
|
const DEFAULT_MINIMUM_REPLY_SURB_THRESHOLD_BUFFER: usize = 0;
|
||||||
|
|
||||||
|
// define how much to request at once
|
||||||
|
// clients/client-core/src/client/replies/reply_controller.rs
|
||||||
|
const DEFAULT_MINIMUM_REPLY_SURB_REQUEST_SIZE: u32 = 10;
|
||||||
|
const DEFAULT_MAXIMUM_REPLY_SURB_REQUEST_SIZE: u32 = 50;
|
||||||
|
|
||||||
|
const DEFAULT_MAXIMUM_ALLOWED_SURB_REQUEST_SIZE: u32 = 500;
|
||||||
|
|
||||||
|
const DEFAULT_MAXIMUM_REPLY_SURB_REREQUEST_WAITING_PERIOD: Duration = Duration::from_secs(10);
|
||||||
|
const DEFAULT_MAXIMUM_REPLY_SURB_DROP_WAITING_PERIOD: Duration = Duration::from_secs(5 * 60);
|
||||||
|
|
||||||
|
// 12 hours
|
||||||
|
const DEFAULT_MAXIMUM_REPLY_SURB_AGE: Duration = Duration::from_secs(12 * 60 * 60);
|
||||||
|
|
||||||
|
// 24 hours
|
||||||
|
const DEFAULT_MAXIMUM_REPLY_KEY_AGE: Duration = Duration::from_secs(24 * 60 * 60);
|
||||||
|
|
||||||
|
// stats reporting related
|
||||||
|
|
||||||
|
/// Time interval between reporting statistics to the given provider if it exists
|
||||||
|
const STATS_REPORT_INTERVAL_SECS: Duration = Duration::from_secs(300);
|
||||||
|
|
||||||
|
// aliases for backwards compatibility
|
||||||
|
pub type ConfigV1_1_54 = ConfigV6;
|
||||||
|
pub type ClientV1_1_54 = ClientV6;
|
||||||
|
pub type DebugConfigV1_1_54 = DebugConfigV6;
|
||||||
|
|
||||||
|
pub type TrafficV1_1_54 = TrafficV6;
|
||||||
|
pub type CoverTrafficV1_1_54 = CoverTrafficV6;
|
||||||
|
pub type GatewayConnectionV1_1_54 = GatewayConnectionV6;
|
||||||
|
pub type AcknowledgementsV1_1_54 = AcknowledgementsV6;
|
||||||
|
pub type TopologyV1_1_54 = TopologyV6;
|
||||||
|
pub type ReplySurbsV1_1_54 = ReplySurbsV6;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
|
pub struct ConfigV6 {
|
||||||
|
pub client: ClientV6,
|
||||||
|
|
||||||
|
#[serde(default)]
|
||||||
|
pub debug: DebugConfigV6,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ConfigV6> for Config {
|
||||||
|
fn from(value: ConfigV6) -> Self {
|
||||||
|
Config {
|
||||||
|
client: Client {
|
||||||
|
version: value.client.version,
|
||||||
|
id: value.client.id,
|
||||||
|
disabled_credentials_mode: value.client.disabled_credentials_mode,
|
||||||
|
nyxd_urls: value.client.nyxd_urls,
|
||||||
|
nym_api_urls: value.client.nym_api_urls,
|
||||||
|
},
|
||||||
|
debug: DebugConfig {
|
||||||
|
traffic: Traffic {
|
||||||
|
average_packet_delay: DEFAULT_AVERAGE_PACKET_DELAY,
|
||||||
|
message_sending_average_delay: value
|
||||||
|
.debug
|
||||||
|
.traffic
|
||||||
|
.message_sending_average_delay,
|
||||||
|
disable_main_poisson_packet_distribution: value
|
||||||
|
.debug
|
||||||
|
.traffic
|
||||||
|
.disable_main_poisson_packet_distribution,
|
||||||
|
primary_packet_size: value.debug.traffic.primary_packet_size,
|
||||||
|
secondary_packet_size: value.debug.traffic.secondary_packet_size,
|
||||||
|
packet_type: value.debug.traffic.packet_type,
|
||||||
|
deterministic_route_selection: value
|
||||||
|
.debug
|
||||||
|
.traffic
|
||||||
|
.deterministic_route_selection,
|
||||||
|
maximum_number_of_retransmissions: value
|
||||||
|
.debug
|
||||||
|
.traffic
|
||||||
|
.maximum_number_of_retransmissions,
|
||||||
|
use_legacy_sphinx_format: value.debug.traffic.use_legacy_sphinx_format,
|
||||||
|
disable_mix_hops: value.debug.traffic.disable_mix_hops,
|
||||||
|
},
|
||||||
|
cover_traffic: CoverTraffic {
|
||||||
|
loop_cover_traffic_average_delay: value
|
||||||
|
.debug
|
||||||
|
.cover_traffic
|
||||||
|
.loop_cover_traffic_average_delay,
|
||||||
|
cover_traffic_primary_size_ratio: value
|
||||||
|
.debug
|
||||||
|
.cover_traffic
|
||||||
|
.cover_traffic_primary_size_ratio,
|
||||||
|
disable_loop_cover_traffic_stream: value
|
||||||
|
.debug
|
||||||
|
.cover_traffic
|
||||||
|
.disable_loop_cover_traffic_stream,
|
||||||
|
},
|
||||||
|
gateway_connection: GatewayConnection {
|
||||||
|
gateway_response_timeout: value
|
||||||
|
.debug
|
||||||
|
.gateway_connection
|
||||||
|
.gateway_response_timeout,
|
||||||
|
},
|
||||||
|
acknowledgements: Acknowledgements {
|
||||||
|
average_ack_delay: value.debug.acknowledgements.average_ack_delay,
|
||||||
|
ack_wait_multiplier: value.debug.acknowledgements.ack_wait_multiplier,
|
||||||
|
ack_wait_addition: value.debug.acknowledgements.ack_wait_addition,
|
||||||
|
},
|
||||||
|
topology: Topology {
|
||||||
|
topology_refresh_rate: value.debug.topology.topology_refresh_rate,
|
||||||
|
topology_resolution_timeout: value.debug.topology.topology_resolution_timeout,
|
||||||
|
disable_refreshing: value.debug.topology.disable_refreshing,
|
||||||
|
max_startup_gateway_waiting_period: value
|
||||||
|
.debug
|
||||||
|
.topology
|
||||||
|
.max_startup_gateway_waiting_period,
|
||||||
|
minimum_mixnode_performance: value.debug.topology.minimum_mixnode_performance,
|
||||||
|
minimum_gateway_performance: value.debug.topology.minimum_gateway_performance,
|
||||||
|
use_extended_topology: value.debug.topology.use_extended_topology,
|
||||||
|
ignore_egress_epoch_role: value.debug.topology.ignore_egress_epoch_role,
|
||||||
|
ignore_ingress_epoch_role: value.debug.topology.ignore_ingress_epoch_role,
|
||||||
|
},
|
||||||
|
reply_surbs: ReplySurbs {
|
||||||
|
minimum_reply_surb_storage_threshold: value
|
||||||
|
.debug
|
||||||
|
.reply_surbs
|
||||||
|
.minimum_reply_surb_storage_threshold,
|
||||||
|
maximum_reply_surb_storage_threshold: value
|
||||||
|
.debug
|
||||||
|
.reply_surbs
|
||||||
|
.maximum_reply_surb_storage_threshold,
|
||||||
|
minimum_reply_surb_request_size: value
|
||||||
|
.debug
|
||||||
|
.reply_surbs
|
||||||
|
.minimum_reply_surb_request_size,
|
||||||
|
maximum_reply_surb_request_size: value
|
||||||
|
.debug
|
||||||
|
.reply_surbs
|
||||||
|
.maximum_reply_surb_request_size,
|
||||||
|
maximum_allowed_reply_surb_request_size: value
|
||||||
|
.debug
|
||||||
|
.reply_surbs
|
||||||
|
.maximum_allowed_reply_surb_request_size,
|
||||||
|
maximum_reply_surb_rerequest_waiting_period: value
|
||||||
|
.debug
|
||||||
|
.reply_surbs
|
||||||
|
.maximum_reply_surb_rerequest_waiting_period,
|
||||||
|
maximum_reply_surb_drop_waiting_period: value
|
||||||
|
.debug
|
||||||
|
.reply_surbs
|
||||||
|
.maximum_reply_surb_drop_waiting_period,
|
||||||
|
maximum_reply_key_age: value.debug.reply_surbs.maximum_reply_key_age,
|
||||||
|
surb_mix_hops: value.debug.reply_surbs.surb_mix_hops,
|
||||||
|
minimum_reply_surb_threshold_buffer: value
|
||||||
|
.debug
|
||||||
|
.reply_surbs
|
||||||
|
.minimum_reply_surb_threshold_buffer,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
stats_reporting: StatsReporting {
|
||||||
|
enabled: value.debug.stats_reporting.enabled,
|
||||||
|
provider_address: value.debug.stats_reporting.provider_address,
|
||||||
|
reporting_interval: value.debug.stats_reporting.reporting_interval,
|
||||||
|
},
|
||||||
|
forget_me: ForgetMe {
|
||||||
|
client: value.debug.forget_me.client,
|
||||||
|
stats: value.debug.forget_me.stats,
|
||||||
|
},
|
||||||
|
remember_me: RememberMe {
|
||||||
|
stats: value.debug.remember_me.stats,
|
||||||
|
session_type: value.debug.remember_me.session_type.into(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
|
||||||
|
// note: the deny_unknown_fields is VITAL here to allow upgrades from v1.1.20_2
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
|
pub struct ClientV6 {
|
||||||
|
/// Version of the client for which this configuration was created.
|
||||||
|
pub version: String,
|
||||||
|
|
||||||
|
/// ID specifies the human readable ID of this particular client.
|
||||||
|
pub id: String,
|
||||||
|
|
||||||
|
/// Indicates whether this client is running in a disabled credentials mode, thus attempting
|
||||||
|
/// to claim bandwidth without presenting bandwidth credentials.
|
||||||
|
// TODO: this should be moved to `debug.gateway_connection`
|
||||||
|
#[serde(default)]
|
||||||
|
pub disabled_credentials_mode: bool,
|
||||||
|
|
||||||
|
/// Addresses to nyxd validators via which the client can communicate with the chain.
|
||||||
|
#[serde(alias = "validator_urls")]
|
||||||
|
pub nyxd_urls: Vec<Url>,
|
||||||
|
|
||||||
|
/// Addresses to APIs running on validator from which the client gets the view of the network.
|
||||||
|
#[serde(alias = "validator_api_urls")]
|
||||||
|
pub nym_api_urls: Vec<Url>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||||
|
#[serde(default, deny_unknown_fields)]
|
||||||
|
pub struct TrafficV6 {
|
||||||
|
/// The parameter of Poisson distribution determining how long, on average,
|
||||||
|
/// sent packet is going to be delayed at any given mix node.
|
||||||
|
/// So for a packet going through three mix nodes, on average, it will take three times this value
|
||||||
|
/// until the packet reaches its destination.
|
||||||
|
#[serde(with = "humantime_serde")]
|
||||||
|
pub average_packet_delay: Duration,
|
||||||
|
|
||||||
|
/// The parameter of Poisson distribution determining how long, on average,
|
||||||
|
/// it is going to take another 'real traffic stream' message to be sent.
|
||||||
|
/// If no real packets are available and cover traffic is enabled,
|
||||||
|
/// a loop cover message is sent instead in order to preserve the rate.
|
||||||
|
#[serde(with = "humantime_serde")]
|
||||||
|
pub message_sending_average_delay: Duration,
|
||||||
|
|
||||||
|
/// Controls whether the main packet stream constantly produces packets according to the predefined
|
||||||
|
/// poisson distribution.
|
||||||
|
pub disable_main_poisson_packet_distribution: bool,
|
||||||
|
|
||||||
|
/// Specify whether route selection should be determined by the packet header.
|
||||||
|
pub deterministic_route_selection: bool,
|
||||||
|
|
||||||
|
/// Specify how many times particular packet can be retransmitted
|
||||||
|
/// None - no limit
|
||||||
|
pub maximum_number_of_retransmissions: Option<u32>,
|
||||||
|
|
||||||
|
/// Specifies the packet size used for sent messages.
|
||||||
|
/// Do not override it unless you understand the consequences of that change.
|
||||||
|
pub primary_packet_size: PacketSize,
|
||||||
|
|
||||||
|
/// Specifies the optional auxiliary packet size for optimizing message streams.
|
||||||
|
/// Note that its use decreases overall anonymity.
|
||||||
|
/// Do not set it unless you understand the consequences of that change.
|
||||||
|
pub secondary_packet_size: Option<PacketSize>,
|
||||||
|
|
||||||
|
/// Specify whether any constructed sphinx packets should use the legacy format,
|
||||||
|
/// where the payload keys are explicitly attached rather than using the seeds
|
||||||
|
/// this affects any forward packets, acks and reply surbs
|
||||||
|
/// this flag should remain disabled until sufficient number of nodes on the network has upgraded
|
||||||
|
/// and support updated format.
|
||||||
|
/// in the case of reply surbs, the recipient must also understand the new encoding
|
||||||
|
pub use_legacy_sphinx_format: bool,
|
||||||
|
|
||||||
|
pub packet_type: PacketType,
|
||||||
|
|
||||||
|
/// Indicates whether to mix hops or not. If mix hops are enabled, traffic
|
||||||
|
/// will be routed as usual, to the entry gateway, through three mix nodes, egressing
|
||||||
|
/// through the exit gateway. If mix hops are disabled, traffic will be routed directly
|
||||||
|
/// from the entry gateway to the exit gateway, bypassing the mix nodes.
|
||||||
|
pub disable_mix_hops: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for TrafficV6 {
|
||||||
|
fn default() -> Self {
|
||||||
|
TrafficV6 {
|
||||||
|
average_packet_delay: DEFAULT_AVERAGE_PACKET_DELAY,
|
||||||
|
message_sending_average_delay: DEFAULT_MESSAGE_STREAM_AVERAGE_DELAY,
|
||||||
|
disable_main_poisson_packet_distribution: false,
|
||||||
|
deterministic_route_selection: false,
|
||||||
|
maximum_number_of_retransmissions: None,
|
||||||
|
primary_packet_size: PacketSize::RegularPacket,
|
||||||
|
secondary_packet_size: None,
|
||||||
|
packet_type: PacketType::Mix,
|
||||||
|
|
||||||
|
// we should use the legacy format until sufficient number of nodes understand the
|
||||||
|
// improved encoding
|
||||||
|
use_legacy_sphinx_format: true,
|
||||||
|
disable_mix_hops: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||||
|
#[serde(default, deny_unknown_fields)]
|
||||||
|
pub struct CoverTrafficV6 {
|
||||||
|
/// The parameter of Poisson distribution determining how long, on average,
|
||||||
|
/// it is going to take for another loop cover traffic message to be sent.
|
||||||
|
#[serde(with = "humantime_serde")]
|
||||||
|
pub loop_cover_traffic_average_delay: Duration,
|
||||||
|
|
||||||
|
/// Specifies the ratio of `primary_packet_size` to `secondary_packet_size` used in cover traffic.
|
||||||
|
/// Only applicable if `secondary_packet_size` is enabled.
|
||||||
|
pub cover_traffic_primary_size_ratio: f64,
|
||||||
|
|
||||||
|
/// Controls whether the dedicated loop cover traffic stream should be enabled.
|
||||||
|
/// (and sending packets, on average, every [Self::loop_cover_traffic_average_delay])
|
||||||
|
pub disable_loop_cover_traffic_stream: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for CoverTrafficV6 {
|
||||||
|
fn default() -> Self {
|
||||||
|
CoverTrafficV6 {
|
||||||
|
loop_cover_traffic_average_delay: DEFAULT_LOOP_COVER_STREAM_AVERAGE_DELAY,
|
||||||
|
cover_traffic_primary_size_ratio: DEFAULT_COVER_TRAFFIC_PRIMARY_SIZE_RATIO,
|
||||||
|
disable_loop_cover_traffic_stream: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||||
|
#[serde(default, deny_unknown_fields)]
|
||||||
|
pub struct GatewayConnectionV6 {
|
||||||
|
/// How long we're willing to wait for a response to a message sent to the gateway,
|
||||||
|
/// before giving up on it.
|
||||||
|
#[serde(with = "humantime_serde")]
|
||||||
|
pub gateway_response_timeout: Duration,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for GatewayConnectionV6 {
|
||||||
|
fn default() -> Self {
|
||||||
|
GatewayConnectionV6 {
|
||||||
|
gateway_response_timeout: DEFAULT_GATEWAY_RESPONSE_TIMEOUT,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||||
|
#[serde(default, deny_unknown_fields)]
|
||||||
|
pub struct AcknowledgementsV6 {
|
||||||
|
/// The parameter of Poisson distribution determining how long, on average,
|
||||||
|
/// sent acknowledgement is going to be delayed at any given mix node.
|
||||||
|
/// So for an ack going through three mix nodes, on average, it will take three times this value
|
||||||
|
/// until the packet reaches its destination.
|
||||||
|
#[serde(with = "humantime_serde")]
|
||||||
|
pub average_ack_delay: Duration,
|
||||||
|
|
||||||
|
/// Value multiplied with the expected round trip time of an acknowledgement packet before
|
||||||
|
/// it is assumed it was lost and retransmission of the data packet happens.
|
||||||
|
/// In an ideal network with 0 latency, this value would have been 1.
|
||||||
|
pub ack_wait_multiplier: f64,
|
||||||
|
|
||||||
|
/// Value added to the expected round trip time of an acknowledgement packet before
|
||||||
|
/// it is assumed it was lost and retransmission of the data packet happens.
|
||||||
|
/// In an ideal network with 0 latency, this value would have been 0.
|
||||||
|
#[serde(with = "humantime_serde")]
|
||||||
|
pub ack_wait_addition: Duration,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for AcknowledgementsV6 {
|
||||||
|
fn default() -> Self {
|
||||||
|
AcknowledgementsV6 {
|
||||||
|
average_ack_delay: DEFAULT_AVERAGE_PACKET_DELAY,
|
||||||
|
ack_wait_multiplier: DEFAULT_ACK_WAIT_MULTIPLIER,
|
||||||
|
ack_wait_addition: DEFAULT_ACK_WAIT_ADDITION,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||||
|
#[serde(default, deny_unknown_fields)]
|
||||||
|
pub struct TopologyV6 {
|
||||||
|
/// The uniform delay every which clients are querying the directory server
|
||||||
|
/// to try to obtain a compatible network topology to send sphinx packets through.
|
||||||
|
#[serde(with = "humantime_serde")]
|
||||||
|
pub topology_refresh_rate: Duration,
|
||||||
|
|
||||||
|
/// During topology refresh, test packets are sent through every single possible network
|
||||||
|
/// path. This timeout determines waiting period until it is decided that the packet
|
||||||
|
/// did not reach its destination.
|
||||||
|
#[serde(with = "humantime_serde")]
|
||||||
|
pub topology_resolution_timeout: Duration,
|
||||||
|
|
||||||
|
/// Specifies whether the client should not refresh the network topology after obtaining
|
||||||
|
/// the first valid instance.
|
||||||
|
/// Supersedes `topology_refresh_rate_ms`.
|
||||||
|
pub disable_refreshing: bool,
|
||||||
|
|
||||||
|
/// Defines how long the client is going to wait on startup for its gateway to come online,
|
||||||
|
/// before abandoning the procedure.
|
||||||
|
#[serde(with = "humantime_serde")]
|
||||||
|
pub max_startup_gateway_waiting_period: Duration,
|
||||||
|
|
||||||
|
/// Specifies a minimum performance of a mixnode that is used on route construction.
|
||||||
|
/// This setting is only applicable when `NymApi` topology is used.
|
||||||
|
pub minimum_mixnode_performance: u8,
|
||||||
|
|
||||||
|
/// Specifies a minimum performance of a gateway that is used on route construction.
|
||||||
|
/// This setting is only applicable when `NymApi` topology is used.
|
||||||
|
pub minimum_gateway_performance: u8,
|
||||||
|
|
||||||
|
/// Specifies whether this client should attempt to retrieve all available network nodes
|
||||||
|
/// as opposed to just active mixnodes/gateways.
|
||||||
|
pub use_extended_topology: bool,
|
||||||
|
|
||||||
|
/// Specifies whether this client should ignore the current epoch role of the target egress node
|
||||||
|
/// when constructing the final hop packets.
|
||||||
|
pub ignore_egress_epoch_role: bool,
|
||||||
|
|
||||||
|
/// 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,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for TopologyV6 {
|
||||||
|
fn default() -> Self {
|
||||||
|
TopologyV6 {
|
||||||
|
topology_refresh_rate: DEFAULT_TOPOLOGY_REFRESH_RATE,
|
||||||
|
topology_resolution_timeout: DEFAULT_TOPOLOGY_RESOLUTION_TIMEOUT,
|
||||||
|
disable_refreshing: false,
|
||||||
|
max_startup_gateway_waiting_period: DEFAULT_MAX_STARTUP_GATEWAY_WAITING_PERIOD,
|
||||||
|
minimum_mixnode_performance: DEFAULT_MIN_MIXNODE_PERFORMANCE,
|
||||||
|
minimum_gateway_performance: DEFAULT_MIN_GATEWAY_PERFORMANCE,
|
||||||
|
use_extended_topology: false,
|
||||||
|
|
||||||
|
ignore_egress_epoch_role: true,
|
||||||
|
ignore_ingress_epoch_role: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||||
|
#[serde(default, deny_unknown_fields)]
|
||||||
|
pub struct ReplySurbsV6 {
|
||||||
|
/// Defines the minimum number of reply surbs the client wants to keep in its storage at all times.
|
||||||
|
/// It can only allow to go below that value if its to request additional reply surbs.
|
||||||
|
pub minimum_reply_surb_storage_threshold: usize,
|
||||||
|
|
||||||
|
/// Defines the maximum number of reply surbs the client wants to keep in its storage at any times.
|
||||||
|
pub maximum_reply_surb_storage_threshold: usize,
|
||||||
|
|
||||||
|
/// Defines the 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.
|
||||||
|
pub minimum_reply_surb_request_size: u32,
|
||||||
|
|
||||||
|
/// Defines the maximum number of reply surbs the client would request.
|
||||||
|
pub maximum_reply_surb_request_size: u32,
|
||||||
|
|
||||||
|
/// Defines the maximum number of reply surbs a remote party is allowed to request from this client at once.
|
||||||
|
pub maximum_allowed_reply_surb_request_size: u32,
|
||||||
|
|
||||||
|
/// Defines maximum amount of time the client is going to wait for reply surbs before explicitly asking
|
||||||
|
/// for more even though in theory they wouldn't need to.
|
||||||
|
#[serde(with = "humantime_serde")]
|
||||||
|
pub maximum_reply_surb_rerequest_waiting_period: Duration,
|
||||||
|
|
||||||
|
/// Defines maximum amount of time the client is going to wait for reply surbs before
|
||||||
|
/// deciding it's never going to get them and would drop all pending messages
|
||||||
|
#[serde(with = "humantime_serde")]
|
||||||
|
pub maximum_reply_surb_drop_waiting_period: Duration,
|
||||||
|
|
||||||
|
/// Defines maximum amount of time given reply surb is going to be valid for.
|
||||||
|
/// This is going to be superseded by key rotation once implemented.
|
||||||
|
#[serde(with = "humantime_serde")]
|
||||||
|
pub maximum_reply_surb_age: Duration,
|
||||||
|
|
||||||
|
/// Defines maximum amount of time given reply key is going to be valid for.
|
||||||
|
/// This is going to be superseded by key rotation once implemented.
|
||||||
|
#[serde(with = "humantime_serde")]
|
||||||
|
pub maximum_reply_key_age: Duration,
|
||||||
|
|
||||||
|
/// Specifies the number of mixnet hops the packet should go through. If not specified, then
|
||||||
|
/// the default value is used.
|
||||||
|
pub surb_mix_hops: Option<u8>,
|
||||||
|
|
||||||
|
/// Specifies if we should reset all the sender tags on startup
|
||||||
|
pub fresh_sender_tags: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for ReplySurbsV6 {
|
||||||
|
fn default() -> Self {
|
||||||
|
ReplySurbsV6 {
|
||||||
|
minimum_reply_surb_storage_threshold: DEFAULT_MINIMUM_REPLY_SURB_STORAGE_THRESHOLD,
|
||||||
|
maximum_reply_surb_storage_threshold: DEFAULT_MAXIMUM_REPLY_SURB_STORAGE_THRESHOLD,
|
||||||
|
minimum_reply_surb_threshold_buffer: DEFAULT_MINIMUM_REPLY_SURB_THRESHOLD_BUFFER,
|
||||||
|
minimum_reply_surb_request_size: DEFAULT_MINIMUM_REPLY_SURB_REQUEST_SIZE,
|
||||||
|
maximum_reply_surb_request_size: DEFAULT_MAXIMUM_REPLY_SURB_REQUEST_SIZE,
|
||||||
|
maximum_allowed_reply_surb_request_size: DEFAULT_MAXIMUM_ALLOWED_SURB_REQUEST_SIZE,
|
||||||
|
maximum_reply_surb_rerequest_waiting_period:
|
||||||
|
DEFAULT_MAXIMUM_REPLY_SURB_REREQUEST_WAITING_PERIOD,
|
||||||
|
maximum_reply_surb_drop_waiting_period: DEFAULT_MAXIMUM_REPLY_SURB_DROP_WAITING_PERIOD,
|
||||||
|
maximum_reply_surb_age: DEFAULT_MAXIMUM_REPLY_SURB_AGE,
|
||||||
|
maximum_reply_key_age: DEFAULT_MAXIMUM_REPLY_KEY_AGE,
|
||||||
|
surb_mix_hops: None,
|
||||||
|
fresh_sender_tags: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||||
|
#[serde(default, deny_unknown_fields)]
|
||||||
|
pub struct DebugConfigV6 {
|
||||||
|
/// Defines all configuration options related to traffic streams.
|
||||||
|
pub traffic: TrafficV6,
|
||||||
|
|
||||||
|
/// Defines all configuration options related to cover traffic stream(s).
|
||||||
|
pub cover_traffic: CoverTrafficV6,
|
||||||
|
|
||||||
|
/// Defines all configuration options related to the gateway connection.
|
||||||
|
pub gateway_connection: GatewayConnectionV6,
|
||||||
|
|
||||||
|
/// Defines all configuration options related to acknowledgements, such as delays or wait timeouts.
|
||||||
|
pub acknowledgements: AcknowledgementsV6,
|
||||||
|
|
||||||
|
/// Defines all configuration options related topology, such as refresh rates or timeouts.
|
||||||
|
pub topology: TopologyV6,
|
||||||
|
|
||||||
|
/// Defines all configuration options related to reply SURBs.
|
||||||
|
pub reply_surbs: ReplySurbsV6,
|
||||||
|
|
||||||
|
/// Defines all configuration options related to stats reporting.
|
||||||
|
pub stats_reporting: StatsReportingV6,
|
||||||
|
|
||||||
|
/// Defines all configuration options related to the forget me flag.
|
||||||
|
pub forget_me: ForgetMeV6,
|
||||||
|
|
||||||
|
/// Defines all configuration options related to the remember me flag.
|
||||||
|
pub remember_me: RememberMeV6,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||||
|
#[serde(default, deny_unknown_fields)]
|
||||||
|
pub struct StatsReportingV6 {
|
||||||
|
/// Is stats reporting enabled
|
||||||
|
pub enabled: bool,
|
||||||
|
|
||||||
|
/// Address of the stats collector. If this is none, no reporting will happen, regardless of `enabled`
|
||||||
|
#[serde(
|
||||||
|
serialize_with = "ser_maybe_stringified",
|
||||||
|
deserialize_with = "de_maybe_stringified"
|
||||||
|
)]
|
||||||
|
pub provider_address: Option<Recipient>,
|
||||||
|
|
||||||
|
/// With what frequence will statistics be sent
|
||||||
|
#[serde(with = "humantime_serde")]
|
||||||
|
pub reporting_interval: Duration,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for StatsReportingV6 {
|
||||||
|
fn default() -> Self {
|
||||||
|
StatsReportingV6 {
|
||||||
|
enabled: true,
|
||||||
|
provider_address: None,
|
||||||
|
reporting_interval: STATS_REPORT_INTERVAL_SECS,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Default, Debug, Deserialize, PartialEq, Serialize, Copy)]
|
||||||
|
pub struct ForgetMeV6 {
|
||||||
|
client: bool,
|
||||||
|
stats: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Default, Debug, Deserialize, PartialEq, Serialize, Copy)]
|
||||||
|
pub struct RememberMeV6 {
|
||||||
|
/// Signal that this client should be accounted for in the stats
|
||||||
|
stats: bool,
|
||||||
|
|
||||||
|
/// Type of the session to remember, if it should be remembered
|
||||||
|
session_type: SessionTypeV6,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq, Copy, Clone, Serialize, Deserialize, Default, Debug)]
|
||||||
|
pub enum SessionTypeV6 {
|
||||||
|
Vpn,
|
||||||
|
Mixnet,
|
||||||
|
Wasm,
|
||||||
|
Native,
|
||||||
|
Socks5,
|
||||||
|
#[default]
|
||||||
|
Unknown,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<SessionTypeV6> for SessionType {
|
||||||
|
fn from(value: SessionTypeV6) -> Self {
|
||||||
|
match value {
|
||||||
|
SessionTypeV6::Vpn => Self::Vpn,
|
||||||
|
SessionTypeV6::Mixnet => Self::Mixnet,
|
||||||
|
SessionTypeV6::Wasm => Self::Wasm,
|
||||||
|
SessionTypeV6::Native => Self::Native,
|
||||||
|
SessionTypeV6::Socks5 => Self::Socks5,
|
||||||
|
SessionTypeV6::Unknown => Self::Unknown,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,11 +9,11 @@ license.workspace = true
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
async-trait.workspace = true
|
async-trait.workspace = true
|
||||||
cosmrs.workspace = true
|
cosmrs.workspace = true
|
||||||
log.workspace = true
|
|
||||||
serde = { workspace = true, features = ["derive"] }
|
serde = { workspace = true, features = ["derive"] }
|
||||||
thiserror.workspace = true
|
thiserror.workspace = true
|
||||||
time.workspace = true
|
time.workspace = true
|
||||||
tokio = { workspace = true, features = ["sync"] }
|
tokio = { workspace = true, features = ["sync"] }
|
||||||
|
tracing.workspace = true
|
||||||
url.workspace = true
|
url.workspace = true
|
||||||
zeroize = { workspace = true, features = ["zeroize_derive"] }
|
zeroize = { workspace = true, features = ["zeroize_derive"] }
|
||||||
|
|
||||||
|
|||||||
@@ -2,8 +2,7 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
use crate::BadGateway;
|
use crate::BadGateway;
|
||||||
use std::io;
|
use std::{io, path::PathBuf};
|
||||||
use std::path::PathBuf;
|
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
@@ -19,7 +18,6 @@ pub enum StorageError {
|
|||||||
|
|
||||||
#[error("failed to perform sqlx migration: {source}")]
|
#[error("failed to perform sqlx migration: {source}")]
|
||||||
MigrationError {
|
MigrationError {
|
||||||
#[source]
|
|
||||||
#[from]
|
#[from]
|
||||||
source: sqlx::migrate::MigrateError,
|
source: sqlx::migrate::MigrateError,
|
||||||
},
|
},
|
||||||
@@ -32,7 +30,6 @@ pub enum StorageError {
|
|||||||
|
|
||||||
#[error("failed to run the SQL query: {source}")]
|
#[error("failed to run the SQL query: {source}")]
|
||||||
QueryError {
|
QueryError {
|
||||||
#[source]
|
|
||||||
#[from]
|
#[from]
|
||||||
source: sqlx::error::Error,
|
source: sqlx::error::Error,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -7,12 +7,12 @@ use crate::{
|
|||||||
RawActiveGateway, RawCustomGatewayDetails, RawRegisteredGateway, RawRemoteGatewayDetails,
|
RawActiveGateway, RawCustomGatewayDetails, RawRegisteredGateway, RawRemoteGatewayDetails,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use log::{debug, error};
|
|
||||||
use sqlx::{
|
use sqlx::{
|
||||||
sqlite::{SqliteAutoVacuum, SqliteSynchronous},
|
sqlite::{SqliteAutoVacuum, SqliteSynchronous},
|
||||||
ConnectOptions,
|
ConnectOptions,
|
||||||
};
|
};
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
use tracing::{debug, error};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct StorageManager {
|
pub struct StorageManager {
|
||||||
@@ -87,7 +87,7 @@ impl StorageManager {
|
|||||||
sqlx::query!("SELECT EXISTS (SELECT 1 FROM registered_gateway WHERE gateway_id_bs58 = ?) AS 'exists'", gateway_id)
|
sqlx::query!("SELECT EXISTS (SELECT 1 FROM registered_gateway WHERE gateway_id_bs58 = ?) AS 'exists'", gateway_id)
|
||||||
.fetch_one(&self.connection_pool)
|
.fetch_one(&self.connection_pool)
|
||||||
.await
|
.await
|
||||||
.map(|result| result.exists == Some(1))
|
.map(|result| result.exists == 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn maybe_get_registered_gateway(
|
pub(crate) async fn maybe_get_registered_gateway(
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
use nym_crypto::asymmetric::identity::Ed25519RecoveryError;
|
use nym_crypto::asymmetric::ed25519::Ed25519RecoveryError;
|
||||||
use nym_gateway_requests::shared_key::SharedKeyConversionError;
|
use nym_gateway_requests::shared_key::SharedKeyConversionError;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
#![warn(clippy::unwrap_used)]
|
#![warn(clippy::unwrap_used)]
|
||||||
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use nym_crypto::asymmetric::identity;
|
use nym_crypto::asymmetric::ed25519;
|
||||||
use nym_gateway_requests::SharedSymmetricKey;
|
use nym_gateway_requests::SharedSymmetricKey;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
|
||||||
@@ -36,9 +36,7 @@ pub trait GatewaysDetailsStore {
|
|||||||
async fn all_gateways(&self) -> Result<Vec<GatewayRegistration>, Self::StorageError>;
|
async fn all_gateways(&self) -> Result<Vec<GatewayRegistration>, Self::StorageError>;
|
||||||
|
|
||||||
/// Return identity keys of all registered gateways.
|
/// Return identity keys of all registered gateways.
|
||||||
async fn all_gateways_identities(
|
async fn all_gateways_identities(&self) -> Result<Vec<ed25519::PublicKey>, Self::StorageError> {
|
||||||
&self,
|
|
||||||
) -> Result<Vec<identity::PublicKey>, Self::StorageError> {
|
|
||||||
Ok(self
|
Ok(self
|
||||||
.all_gateways()
|
.all_gateways()
|
||||||
.await?
|
.await?
|
||||||
@@ -64,7 +62,7 @@ pub trait GatewaysDetailsStore {
|
|||||||
|
|
||||||
async fn upgrade_stored_remote_gateway_key(
|
async fn upgrade_stored_remote_gateway_key(
|
||||||
&self,
|
&self,
|
||||||
gateway_id: identity::PublicKey,
|
gateway_id: ed25519::PublicKey,
|
||||||
updated_key: &SharedSymmetricKey,
|
updated_key: &SharedSymmetricKey,
|
||||||
) -> Result<(), Self::StorageError>;
|
) -> Result<(), Self::StorageError>;
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
use crate::BadGateway;
|
use crate::BadGateway;
|
||||||
use cosmrs::AccountId;
|
use cosmrs::AccountId;
|
||||||
use nym_crypto::asymmetric::identity;
|
use nym_crypto::asymmetric::ed25519;
|
||||||
use nym_gateway_requests::shared_key::{LegacySharedKeys, SharedGatewayKey, SharedSymmetricKey};
|
use nym_gateway_requests::shared_key::{LegacySharedKeys, SharedGatewayKey, SharedSymmetricKey};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter};
|
||||||
@@ -29,7 +29,7 @@ pub struct GatewayRegistration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl GatewayRegistration {
|
impl GatewayRegistration {
|
||||||
pub fn gateway_id(&self) -> identity::PublicKey {
|
pub fn gateway_id(&self) -> ed25519::PublicKey {
|
||||||
self.details.gateway_id()
|
self.details.gateway_id()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -64,7 +64,7 @@ impl From<GatewayDetails> for GatewayRegistration {
|
|||||||
|
|
||||||
impl GatewayDetails {
|
impl GatewayDetails {
|
||||||
pub fn new_remote(
|
pub fn new_remote(
|
||||||
gateway_id: identity::PublicKey,
|
gateway_id: ed25519::PublicKey,
|
||||||
shared_key: Arc<SharedGatewayKey>,
|
shared_key: Arc<SharedGatewayKey>,
|
||||||
gateway_owner_address: Option<AccountId>,
|
gateway_owner_address: Option<AccountId>,
|
||||||
gateway_listener: Url,
|
gateway_listener: Url,
|
||||||
@@ -77,11 +77,11 @@ impl GatewayDetails {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_custom(gateway_id: identity::PublicKey, data: Option<Vec<u8>>) -> Self {
|
pub fn new_custom(gateway_id: ed25519::PublicKey, data: Option<Vec<u8>>) -> Self {
|
||||||
GatewayDetails::Custom(CustomGatewayDetails { gateway_id, data })
|
GatewayDetails::Custom(CustomGatewayDetails { gateway_id, data })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn gateway_id(&self) -> identity::PublicKey {
|
pub fn gateway_id(&self) -> ed25519::PublicKey {
|
||||||
match self {
|
match self {
|
||||||
GatewayDetails::Remote(details) => details.gateway_id,
|
GatewayDetails::Remote(details) => details.gateway_id,
|
||||||
GatewayDetails::Custom(details) => details.gateway_id,
|
GatewayDetails::Custom(details) => details.gateway_id,
|
||||||
@@ -157,7 +157,7 @@ pub struct RawRegisteredGateway {
|
|||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub struct RegisteredGateway {
|
pub struct RegisteredGateway {
|
||||||
pub gateway_id: identity::PublicKey,
|
pub gateway_id: ed25519::PublicKey,
|
||||||
|
|
||||||
pub registration_timestamp: OffsetDateTime,
|
pub registration_timestamp: OffsetDateTime,
|
||||||
|
|
||||||
@@ -179,7 +179,7 @@ impl TryFrom<RawRemoteGatewayDetails> for RemoteGatewayDetails {
|
|||||||
|
|
||||||
fn try_from(value: RawRemoteGatewayDetails) -> Result<Self, Self::Error> {
|
fn try_from(value: RawRemoteGatewayDetails) -> Result<Self, Self::Error> {
|
||||||
let gateway_id =
|
let gateway_id =
|
||||||
identity::PublicKey::from_base58_string(&value.gateway_id_bs58).map_err(|source| {
|
ed25519::PublicKey::from_base58_string(&value.gateway_id_bs58).map_err(|source| {
|
||||||
BadGateway::MalformedGatewayIdentity {
|
BadGateway::MalformedGatewayIdentity {
|
||||||
gateway_id: value.gateway_id_bs58.clone(),
|
gateway_id: value.gateway_id_bs58.clone(),
|
||||||
source,
|
source,
|
||||||
@@ -267,7 +267,7 @@ impl<'a> From<&'a RemoteGatewayDetails> for RawRemoteGatewayDetails {
|
|||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct RemoteGatewayDetails {
|
pub struct RemoteGatewayDetails {
|
||||||
pub gateway_id: identity::PublicKey,
|
pub gateway_id: ed25519::PublicKey,
|
||||||
|
|
||||||
pub shared_key: Arc<SharedGatewayKey>,
|
pub shared_key: Arc<SharedGatewayKey>,
|
||||||
|
|
||||||
@@ -288,7 +288,7 @@ impl TryFrom<RawCustomGatewayDetails> for CustomGatewayDetails {
|
|||||||
|
|
||||||
fn try_from(value: RawCustomGatewayDetails) -> Result<Self, Self::Error> {
|
fn try_from(value: RawCustomGatewayDetails) -> Result<Self, Self::Error> {
|
||||||
let gateway_id =
|
let gateway_id =
|
||||||
identity::PublicKey::from_base58_string(&value.gateway_id_bs58).map_err(|source| {
|
ed25519::PublicKey::from_base58_string(&value.gateway_id_bs58).map_err(|source| {
|
||||||
BadGateway::MalformedGatewayIdentity {
|
BadGateway::MalformedGatewayIdentity {
|
||||||
gateway_id: value.gateway_id_bs58.clone(),
|
gateway_id: value.gateway_id_bs58.clone(),
|
||||||
source,
|
source,
|
||||||
@@ -314,12 +314,12 @@ impl<'a> From<&'a CustomGatewayDetails> for RawCustomGatewayDetails {
|
|||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct CustomGatewayDetails {
|
pub struct CustomGatewayDetails {
|
||||||
pub gateway_id: identity::PublicKey,
|
pub gateway_id: ed25519::PublicKey,
|
||||||
pub data: Option<Vec<u8>>,
|
pub data: Option<Vec<u8>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CustomGatewayDetails {
|
impl CustomGatewayDetails {
|
||||||
pub fn new(gateway_id: identity::PublicKey) -> CustomGatewayDetails {
|
pub fn new(gateway_id: ed25519::PublicKey) -> CustomGatewayDetails {
|
||||||
Self {
|
Self {
|
||||||
gateway_id,
|
gateway_id,
|
||||||
data: None,
|
data: None,
|
||||||
|
|||||||
@@ -12,12 +12,12 @@ use crate::{
|
|||||||
error::ClientCoreError,
|
error::ClientCoreError,
|
||||||
init::types::{GatewaySelectionSpecification, GatewaySetup},
|
init::types::{GatewaySelectionSpecification, GatewaySetup},
|
||||||
};
|
};
|
||||||
use log::info;
|
|
||||||
use nym_client_core_gateways_storage::GatewayDetails;
|
use nym_client_core_gateways_storage::GatewayDetails;
|
||||||
use nym_crypto::asymmetric::identity;
|
use nym_crypto::asymmetric::ed25519;
|
||||||
use nym_topology::NymTopology;
|
use nym_topology::NymTopology;
|
||||||
use nym_validator_client::UserAgent;
|
use nym_validator_client::UserAgent;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
use tracing::info;
|
||||||
|
|
||||||
#[cfg_attr(feature = "cli", derive(clap::Args))]
|
#[cfg_attr(feature = "cli", derive(clap::Args))]
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
@@ -29,7 +29,7 @@ pub struct CommonClientAddGatewayArgs {
|
|||||||
/// Explicitly specify id of the gateway to register with.
|
/// Explicitly specify id of the gateway to register with.
|
||||||
/// If unspecified, a random gateway will be chosen instead.
|
/// If unspecified, a random gateway will be chosen instead.
|
||||||
#[cfg_attr(feature = "cli", clap(long, alias = "gateway"))]
|
#[cfg_attr(feature = "cli", clap(long, alias = "gateway"))]
|
||||||
pub gateway_id: Option<identity::PublicKey>,
|
pub gateway_id: Option<ed25519::PublicKey>,
|
||||||
|
|
||||||
/// Specifies whether the client will attempt to enforce tls connection to the desired gateway.
|
/// Specifies whether the client will attempt to enforce tls connection to the desired gateway.
|
||||||
#[cfg_attr(feature = "cli", clap(long))]
|
#[cfg_attr(feature = "cli", clap(long))]
|
||||||
@@ -81,14 +81,14 @@ where
|
|||||||
|
|
||||||
// Attempt to use a user-provided gateway, if possible
|
// Attempt to use a user-provided gateway, if possible
|
||||||
let user_chosen_gateway_id = common_args.gateway_id;
|
let user_chosen_gateway_id = common_args.gateway_id;
|
||||||
log::debug!("User chosen gateway id: {user_chosen_gateway_id:?}");
|
tracing::debug!("User chosen gateway id: {user_chosen_gateway_id:?}");
|
||||||
|
|
||||||
let selection_spec = GatewaySelectionSpecification::new(
|
let selection_spec = GatewaySelectionSpecification::new(
|
||||||
user_chosen_gateway_id.map(|id| id.to_base58_string()),
|
user_chosen_gateway_id.map(|id| id.to_base58_string()),
|
||||||
Some(common_args.latency_based_selection),
|
Some(common_args.latency_based_selection),
|
||||||
common_args.force_tls_gateway,
|
common_args.force_tls_gateway,
|
||||||
);
|
);
|
||||||
log::debug!("Gateway selection specification: {selection_spec:?}");
|
tracing::debug!("Gateway selection specification: {selection_spec:?}");
|
||||||
|
|
||||||
let registered_gateways = get_all_registered_identities(&details_store).await?;
|
let registered_gateways = get_all_registered_identities(&details_store).await?;
|
||||||
|
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ where
|
|||||||
Some(data) => data,
|
Some(data) => data,
|
||||||
None => {
|
None => {
|
||||||
// SAFETY: one of those arguments must have been set
|
// SAFETY: one of those arguments must have been set
|
||||||
|
#[allow(clippy::unwrap_used)]
|
||||||
fs::read(common_args.signatures_path.unwrap())?
|
fs::read(common_args.signatures_path.unwrap())?
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ where
|
|||||||
Some(data) => data,
|
Some(data) => data,
|
||||||
None => {
|
None => {
|
||||||
// SAFETY: one of those arguments must have been set
|
// SAFETY: one of those arguments must have been set
|
||||||
|
#[allow(clippy::unwrap_used)]
|
||||||
fs::read(common_args.credential_path.unwrap())?
|
fs::read(common_args.credential_path.unwrap())?
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ where
|
|||||||
Some(data) => data,
|
Some(data) => data,
|
||||||
None => {
|
None => {
|
||||||
// SAFETY: one of those arguments must have been set
|
// SAFETY: one of those arguments must have been set
|
||||||
|
#[allow(clippy::unwrap_used)]
|
||||||
fs::read(common_args.signatures_path.unwrap())?
|
fs::read(common_args.signatures_path.unwrap())?
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ where
|
|||||||
Some(data) => data,
|
Some(data) => data,
|
||||||
None => {
|
None => {
|
||||||
// SAFETY: one of those arguments must have been set
|
// SAFETY: one of those arguments must have been set
|
||||||
|
#[allow(clippy::unwrap_used)]
|
||||||
fs::read(common_args.key_path.unwrap())?
|
fs::read(common_args.key_path.unwrap())?
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -12,14 +12,14 @@ use crate::{
|
|||||||
},
|
},
|
||||||
init::types::{GatewaySelectionSpecification, GatewaySetup, InitResults},
|
init::types::{GatewaySelectionSpecification, GatewaySetup, InitResults},
|
||||||
};
|
};
|
||||||
use log::info;
|
|
||||||
use nym_client_core_gateways_storage::GatewayDetails;
|
use nym_client_core_gateways_storage::GatewayDetails;
|
||||||
use nym_crypto::asymmetric::identity;
|
use nym_crypto::asymmetric::ed25519;
|
||||||
use nym_sphinx::addressing::Recipient;
|
use nym_sphinx::addressing::Recipient;
|
||||||
use nym_topology::NymTopology;
|
use nym_topology::NymTopology;
|
||||||
use nym_validator_client::UserAgent;
|
use nym_validator_client::UserAgent;
|
||||||
use rand::rngs::OsRng;
|
use rand::rngs::OsRng;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
use tracing::info;
|
||||||
|
|
||||||
// we can suppress this warning (as suggested by linter itself) since we're only using it in our own code
|
// we can suppress this warning (as suggested by linter itself) since we're only using it in our own code
|
||||||
#[allow(async_fn_in_trait)]
|
#[allow(async_fn_in_trait)]
|
||||||
@@ -42,7 +42,7 @@ pub struct CommonClientInitArgs {
|
|||||||
|
|
||||||
/// Id of the gateway we are going to connect to.
|
/// Id of the gateway we are going to connect to.
|
||||||
#[cfg_attr(feature = "cli", clap(long))]
|
#[cfg_attr(feature = "cli", clap(long))]
|
||||||
pub gateway: Option<identity::PublicKey>,
|
pub gateway: Option<ed25519::PublicKey>,
|
||||||
|
|
||||||
/// Specifies whether the client will attempt to enforce tls connection to the desired gateway.
|
/// Specifies whether the client will attempt to enforce tls connection to the desired gateway.
|
||||||
#[cfg_attr(feature = "cli", clap(long))]
|
#[cfg_attr(feature = "cli", clap(long))]
|
||||||
@@ -130,23 +130,23 @@ where
|
|||||||
|
|
||||||
// Attempt to use a user-provided gateway, if possible
|
// Attempt to use a user-provided gateway, if possible
|
||||||
let user_chosen_gateway_id = common_args.gateway;
|
let user_chosen_gateway_id = common_args.gateway;
|
||||||
log::debug!("User chosen gateway id: {user_chosen_gateway_id:?}");
|
tracing::debug!("User chosen gateway id: {user_chosen_gateway_id:?}");
|
||||||
|
|
||||||
let selection_spec = GatewaySelectionSpecification::new(
|
let selection_spec = GatewaySelectionSpecification::new(
|
||||||
user_chosen_gateway_id.map(|id| id.to_base58_string()),
|
user_chosen_gateway_id.map(|id| id.to_base58_string()),
|
||||||
Some(common_args.latency_based_selection),
|
Some(common_args.latency_based_selection),
|
||||||
common_args.force_tls_gateway,
|
common_args.force_tls_gateway,
|
||||||
);
|
);
|
||||||
log::debug!("Gateway selection specification: {selection_spec:?}");
|
tracing::debug!("Gateway selection specification: {selection_spec:?}");
|
||||||
|
|
||||||
// Load and potentially override config
|
// Load and potentially override config
|
||||||
log::debug!("Init arguments: {init_args:#?}");
|
tracing::debug!("Init arguments: {init_args:#?}");
|
||||||
let config = C::construct_config(&init_args);
|
let config = C::construct_config(&init_args);
|
||||||
log::debug!("Constructed config: {config:#?}");
|
tracing::debug!("Constructed config: {config:#?}");
|
||||||
let paths = config.common_paths();
|
let paths = config.common_paths();
|
||||||
let core = config.core_config();
|
let core = config.core_config();
|
||||||
|
|
||||||
log::info!(
|
tracing::info!(
|
||||||
"Using nym-api: {}",
|
"Using nym-api: {}",
|
||||||
core.client
|
core.client
|
||||||
.nym_api_urls
|
.nym_api_urls
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
use nym_crypto::asymmetric::identity;
|
use nym_crypto::asymmetric::ed25519;
|
||||||
use nym_sphinx::addressing::Recipient;
|
use nym_sphinx::addressing::Recipient;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
@@ -15,7 +15,7 @@ pub struct CommonClientRunArgs {
|
|||||||
/// Id of the gateway we want to connect to. If overridden, it is user's responsibility to
|
/// Id of the gateway we want to connect to. If overridden, it is user's responsibility to
|
||||||
/// ensure prior registration happened
|
/// ensure prior registration happened
|
||||||
#[cfg_attr(feature = "cli", clap(long))]
|
#[cfg_attr(feature = "cli", clap(long))]
|
||||||
pub gateway: Option<identity::PublicKey>,
|
pub gateway: Option<ed25519::PublicKey>,
|
||||||
|
|
||||||
/// Comma separated list of rest endpoints of the nyxd validators
|
/// Comma separated list of rest endpoints of the nyxd validators
|
||||||
#[cfg_attr(
|
#[cfg_attr(
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
use crate::cli_helpers::{CliClient, CliClientConfig};
|
use crate::cli_helpers::{CliClient, CliClientConfig};
|
||||||
use crate::client::base_client::non_wasm_helpers::setup_fs_gateways_storage;
|
use crate::client::base_client::non_wasm_helpers::setup_fs_gateways_storage;
|
||||||
use crate::client::base_client::storage::helpers::set_active_gateway;
|
use crate::client::base_client::storage::helpers::set_active_gateway;
|
||||||
use nym_crypto::asymmetric::identity;
|
use nym_crypto::asymmetric::ed25519;
|
||||||
|
|
||||||
#[cfg_attr(feature = "cli", derive(clap::Args))]
|
#[cfg_attr(feature = "cli", derive(clap::Args))]
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
@@ -15,7 +15,7 @@ pub struct CommonClientSwitchGatewaysArgs {
|
|||||||
|
|
||||||
/// Id of the gateway we want to switch to.
|
/// Id of the gateway we want to switch to.
|
||||||
#[cfg_attr(feature = "cli", clap(long))]
|
#[cfg_attr(feature = "cli", clap(long))]
|
||||||
pub gateway_id: identity::PublicKey,
|
pub gateway_id: ed25519::PublicKey,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn switch_gateway<C, A>(args: A) -> Result<(), C::Error>
|
pub async fn switch_gateway<C, A>(args: A) -> Result<(), C::Error>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
use nym_crypto::asymmetric::identity;
|
use nym_crypto::asymmetric::ed25519;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter};
|
||||||
use time::OffsetDateTime;
|
use time::OffsetDateTime;
|
||||||
@@ -10,7 +10,7 @@ use url::Url;
|
|||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
pub struct GatewayInfo {
|
pub struct GatewayInfo {
|
||||||
pub registration: OffsetDateTime,
|
pub registration: OffsetDateTime,
|
||||||
pub identity: identity::PublicKey,
|
pub identity: ed25519::PublicKey,
|
||||||
pub active: bool,
|
pub active: bool,
|
||||||
|
|
||||||
pub typ: String,
|
pub typ: String,
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ use crate::client::received_buffer::{
|
|||||||
ReceivedBufferRequestReceiver, ReceivedBufferRequestSender, ReceivedMessagesBufferController,
|
ReceivedBufferRequestReceiver, ReceivedBufferRequestSender, ReceivedMessagesBufferController,
|
||||||
};
|
};
|
||||||
use crate::client::replies::reply_controller;
|
use crate::client::replies::reply_controller;
|
||||||
|
use crate::client::replies::reply_controller::key_rotation_helpers::KeyRotationConfig;
|
||||||
use crate::client::replies::reply_controller::{ReplyControllerReceiver, ReplyControllerSender};
|
use crate::client::replies::reply_controller::{ReplyControllerReceiver, ReplyControllerSender};
|
||||||
use crate::client::replies::reply_storage::{
|
use crate::client::replies::reply_storage::{
|
||||||
CombinedReplyStorage, PersistentReplyStorage, ReplyStorageBackend, SentReplyKeys,
|
CombinedReplyStorage, PersistentReplyStorage, ReplyStorageBackend, SentReplyKeys,
|
||||||
@@ -34,12 +35,11 @@ use crate::init::{
|
|||||||
};
|
};
|
||||||
use crate::{config, spawn_future};
|
use crate::{config, spawn_future};
|
||||||
use futures::channel::mpsc;
|
use futures::channel::mpsc;
|
||||||
use log::*;
|
|
||||||
use nym_bandwidth_controller::BandwidthController;
|
use nym_bandwidth_controller::BandwidthController;
|
||||||
use nym_client_core_config_types::ForgetMe;
|
use nym_client_core_config_types::{ForgetMe, RememberMe};
|
||||||
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::{ed25519, x25519};
|
||||||
use nym_crypto::hkdf::DerivationMaterial;
|
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::{
|
||||||
@@ -56,13 +56,18 @@ use nym_task::connections::{ConnectionCommandReceiver, ConnectionCommandSender,
|
|||||||
use nym_task::{TaskClient, TaskHandle};
|
use nym_task::{TaskClient, TaskHandle};
|
||||||
use nym_topology::provider_trait::TopologyProvider;
|
use nym_topology::provider_trait::TopologyProvider;
|
||||||
use nym_topology::HardcodedTopologyProvider;
|
use nym_topology::HardcodedTopologyProvider;
|
||||||
use nym_validator_client::{nyxd::contract_traits::DkgQueryClient, UserAgent};
|
use nym_validator_client::nym_api::NymApiClientExt;
|
||||||
|
use nym_validator_client::{nyxd::contract_traits::DkgQueryClient, NymApiClient, UserAgent};
|
||||||
|
use rand::prelude::SliceRandom;
|
||||||
use rand::rngs::OsRng;
|
use rand::rngs::OsRng;
|
||||||
|
use rand::thread_rng;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use std::os::raw::c_int as RawFd;
|
use std::os::raw::c_int as RawFd;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
use time::OffsetDateTime;
|
||||||
use tokio::sync::mpsc::Sender;
|
use tokio::sync::mpsc::Sender;
|
||||||
|
use tracing::*;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
#[cfg(all(
|
#[cfg(all(
|
||||||
@@ -130,9 +135,11 @@ pub enum ClientInputStatus {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ClientInputStatus {
|
impl ClientInputStatus {
|
||||||
|
#[allow(clippy::panic)]
|
||||||
pub fn register_producer(&mut self) -> ClientInput {
|
pub fn register_producer(&mut self) -> ClientInput {
|
||||||
match std::mem::replace(self, ClientInputStatus::Connected) {
|
match std::mem::replace(self, ClientInputStatus::Connected) {
|
||||||
ClientInputStatus::AwaitingProducer { client_input } => client_input,
|
ClientInputStatus::AwaitingProducer { client_input } => client_input,
|
||||||
|
// critical failure implying misuse of software
|
||||||
ClientInputStatus::Connected => panic!("producer was already registered before"),
|
ClientInputStatus::Connected => panic!("producer was already registered before"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -144,9 +151,11 @@ pub enum ClientOutputStatus {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ClientOutputStatus {
|
impl ClientOutputStatus {
|
||||||
|
#[allow(clippy::panic)]
|
||||||
pub fn register_consumer(&mut self) -> ClientOutput {
|
pub fn register_consumer(&mut self) -> ClientOutput {
|
||||||
match std::mem::replace(self, ClientOutputStatus::Connected) {
|
match std::mem::replace(self, ClientOutputStatus::Connected) {
|
||||||
ClientOutputStatus::AwaitingConsumer { client_output } => client_output,
|
ClientOutputStatus::AwaitingConsumer { client_output } => client_output,
|
||||||
|
// critical failure implying misuse of software
|
||||||
ClientOutputStatus::Connected => panic!("consumer was already registered before"),
|
ClientOutputStatus::Connected => panic!("consumer was already registered before"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -238,6 +247,12 @@ where
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn with_remember_me(mut self, remember_me: &RememberMe) -> Self {
|
||||||
|
self.config.debug.remember_me = *remember_me;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn with_gateway_setup(mut self, setup: GatewaySetup) -> Self {
|
pub fn with_gateway_setup(mut self, setup: GatewaySetup) -> Self {
|
||||||
self.setup_method = setup;
|
self.setup_method = setup;
|
||||||
@@ -332,6 +347,7 @@ where
|
|||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
fn start_real_traffic_controller(
|
fn start_real_traffic_controller(
|
||||||
controller_config: real_messages_control::Config,
|
controller_config: real_messages_control::Config,
|
||||||
|
key_rotation_config: KeyRotationConfig,
|
||||||
topology_accessor: TopologyAccessor,
|
topology_accessor: TopologyAccessor,
|
||||||
ack_receiver: AcknowledgementReceiver,
|
ack_receiver: AcknowledgementReceiver,
|
||||||
input_receiver: InputMessageReceiver,
|
input_receiver: InputMessageReceiver,
|
||||||
@@ -349,6 +365,7 @@ where
|
|||||||
|
|
||||||
RealMessagesController::new(
|
RealMessagesController::new(
|
||||||
controller_config,
|
controller_config,
|
||||||
|
key_rotation_config,
|
||||||
ack_receiver,
|
ack_receiver,
|
||||||
input_receiver,
|
input_receiver,
|
||||||
mix_sender,
|
mix_sender,
|
||||||
@@ -367,7 +384,7 @@ where
|
|||||||
// buffer controlling all messages fetched from provider
|
// buffer controlling all messages fetched from provider
|
||||||
// required so that other components would be able to use them (say the websocket)
|
// required so that other components would be able to use them (say the websocket)
|
||||||
fn start_received_messages_buffer_controller(
|
fn start_received_messages_buffer_controller(
|
||||||
local_encryption_keypair: Arc<encryption::KeyPair>,
|
local_encryption_keypair: Arc<x25519::KeyPair>,
|
||||||
query_receiver: ReceivedBufferRequestReceiver,
|
query_receiver: ReceivedBufferRequestReceiver,
|
||||||
mixnet_receiver: MixnetMessageReceiver,
|
mixnet_receiver: MixnetMessageReceiver,
|
||||||
reply_key_storage: SentReplyKeys,
|
reply_key_storage: SentReplyKeys,
|
||||||
@@ -447,10 +464,10 @@ where
|
|||||||
};
|
};
|
||||||
|
|
||||||
let gateway_failure = |err| {
|
let gateway_failure = |err| {
|
||||||
log::error!("Could not authenticate and start up the gateway connection - {err}");
|
tracing::error!("Could not authenticate and start up the gateway connection - {err}");
|
||||||
ClientCoreError::GatewayClientError {
|
ClientCoreError::GatewayClientError {
|
||||||
gateway_id: details.gateway_id.to_base58_string(),
|
gateway_id: details.gateway_id.to_base58_string(),
|
||||||
source: err,
|
source: Box::new(err),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -549,21 +566,15 @@ where
|
|||||||
custom_provider: Option<Box<dyn TopologyProvider + Send + Sync>>,
|
custom_provider: Option<Box<dyn TopologyProvider + Send + Sync>>,
|
||||||
config_topology: config::Topology,
|
config_topology: config::Topology,
|
||||||
nym_api_urls: Vec<Url>,
|
nym_api_urls: Vec<Url>,
|
||||||
user_agent: Option<UserAgent>,
|
nym_api_client: NymApiClient,
|
||||||
) -> Box<dyn TopologyProvider + Send + Sync> {
|
) -> Box<dyn TopologyProvider + Send + Sync> {
|
||||||
// if no custom provider was ... provided ..., create one using nym-api
|
// if no custom provider was ... provided ..., create one using nym-api
|
||||||
custom_provider.unwrap_or_else(|| match config_topology.topology_structure {
|
custom_provider.unwrap_or_else(|| {
|
||||||
config::TopologyStructure::NymApi => Box::new(NymApiTopologyProvider::new(
|
Box::new(NymApiTopologyProvider::new(
|
||||||
config_topology,
|
config_topology,
|
||||||
nym_api_urls,
|
nym_api_urls,
|
||||||
user_agent,
|
nym_api_client,
|
||||||
)),
|
))
|
||||||
config::TopologyStructure::GeoAware(group_by) => {
|
|
||||||
warn!("using deprecated 'GeoAware' topology provider - this option will be removed very soon");
|
|
||||||
|
|
||||||
#[allow(deprecated)]
|
|
||||||
Box::new(crate::client::topology_control::GeoAwareTopologyProvider::new(nym_api_urls, group_by))
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -598,7 +609,7 @@ where
|
|||||||
topology_refresher.try_refresh().await;
|
topology_refresher.try_refresh().await;
|
||||||
|
|
||||||
if let Err(err) = topology_refresher.ensure_topology_is_routable().await {
|
if let Err(err) = topology_refresher.ensure_topology_is_routable().await {
|
||||||
log::error!(
|
tracing::error!(
|
||||||
"The current network topology seem to be insufficient to route any packets through \
|
"The current network topology seem to be insufficient to route any packets through \
|
||||||
- check if enough nodes and a gateway are online - source: {err}"
|
- check if enough nodes and a gateway are online - source: {err}"
|
||||||
);
|
);
|
||||||
@@ -674,27 +685,40 @@ where
|
|||||||
// 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
|
||||||
async fn setup_persistent_reply_storage(
|
async fn setup_persistent_reply_storage(
|
||||||
backend: S::ReplyStore,
|
backend: S::ReplyStore,
|
||||||
|
key_rotation_config: KeyRotationConfig,
|
||||||
shutdown: TaskClient,
|
shutdown: TaskClient,
|
||||||
) -> Result<CombinedReplyStorage, ClientCoreError>
|
) -> Result<CombinedReplyStorage, ClientCoreError>
|
||||||
where
|
where
|
||||||
<S::ReplyStore as ReplyStorageBackend>::StorageError: Sync + Send,
|
<S::ReplyStore as ReplyStorageBackend>::StorageError: Sync + Send,
|
||||||
S::ReplyStore: Send + Sync,
|
S::ReplyStore: Send + Sync,
|
||||||
{
|
{
|
||||||
log::trace!("Setup persistent reply storage");
|
tracing::trace!("Setup persistent reply storage");
|
||||||
|
let now = OffsetDateTime::now_utc();
|
||||||
|
let expected_current_key_rotation_start =
|
||||||
|
key_rotation_config.expected_current_key_rotation_start(now);
|
||||||
|
// time of the start of one epoch BEFORE the CURRENT rotation has begun
|
||||||
|
// this indicates the starting time of when packets with the current keys might have been constructed
|
||||||
|
// (i.e. any surbs OLDER than that MUST BE invalid)
|
||||||
|
let prior_epoch_start =
|
||||||
|
expected_current_key_rotation_start - key_rotation_config.epoch_duration;
|
||||||
|
|
||||||
let persistent_storage = PersistentReplyStorage::new(backend);
|
let persistent_storage = PersistentReplyStorage::new(backend);
|
||||||
let mem_store = persistent_storage
|
let mem_store = persistent_storage
|
||||||
.load_state_from_backend()
|
.load_state_from_backend(prior_epoch_start)
|
||||||
.await
|
.await
|
||||||
.map_err(|err| ClientCoreError::SurbStorageError {
|
.map_err(|err| ClientCoreError::SurbStorageError {
|
||||||
source: Box::new(err),
|
source: Box::new(err),
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let store_clone = mem_store.clone();
|
let store_clone = mem_store.clone();
|
||||||
spawn_future(async move {
|
spawn_future!(
|
||||||
persistent_storage
|
async move {
|
||||||
.flush_on_shutdown(store_clone, shutdown)
|
persistent_storage
|
||||||
.await
|
.flush_on_shutdown(store_clone, shutdown)
|
||||||
});
|
.await
|
||||||
|
},
|
||||||
|
"PersistentReplyStorage::flush_on_shutdown"
|
||||||
|
);
|
||||||
|
|
||||||
Ok(mem_store)
|
Ok(mem_store)
|
||||||
}
|
}
|
||||||
@@ -715,7 +739,7 @@ where
|
|||||||
let mut rng = OsRng;
|
let mut rng = OsRng;
|
||||||
let keys = if let Some(derivation_material) = derivation_material {
|
let keys = if let Some(derivation_material) = derivation_material {
|
||||||
ClientKeys::from_master_key(&mut rng, &derivation_material)
|
ClientKeys::from_master_key(&mut rng, &derivation_material)
|
||||||
.map_err(|_| ClientCoreError::HkdfDerivationError {})?
|
.map_err(|_| ClientCoreError::HkdfDerivationError)?
|
||||||
} else {
|
} else {
|
||||||
ClientKeys::generate_new(&mut rng)
|
ClientKeys::generate_new(&mut rng)
|
||||||
};
|
};
|
||||||
@@ -725,6 +749,23 @@ where
|
|||||||
setup_gateway(setup_method, key_store, details_store).await
|
setup_gateway(setup_method, key_store, details_store).await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn construct_nym_api_client(config: &Config, user_agent: Option<UserAgent>) -> NymApiClient {
|
||||||
|
let mut nym_api_urls = config.get_nym_api_endpoints();
|
||||||
|
nym_api_urls.shuffle(&mut thread_rng());
|
||||||
|
|
||||||
|
if let Some(user_agent) = user_agent {
|
||||||
|
NymApiClient::new_with_user_agent(nym_api_urls[0].clone(), user_agent)
|
||||||
|
} else {
|
||||||
|
NymApiClient::new(nym_api_urls[0].clone())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn determine_key_rotation_state(
|
||||||
|
client: &NymApiClient,
|
||||||
|
) -> Result<KeyRotationConfig, ClientCoreError> {
|
||||||
|
Ok(client.nym_api.get_key_rotation_info().await?.into())
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn start_base(mut self) -> Result<BaseClient, ClientCoreError>
|
pub async fn start_base(mut self) -> Result<BaseClient, ClientCoreError>
|
||||||
where
|
where
|
||||||
S::ReplyStore: Send + Sync,
|
S::ReplyStore: Send + Sync,
|
||||||
@@ -789,11 +830,14 @@ where
|
|||||||
.dkg_query_client
|
.dkg_query_client
|
||||||
.map(|client| BandwidthController::new(credential_store, client));
|
.map(|client| BandwidthController::new(credential_store, client));
|
||||||
|
|
||||||
|
let nym_api_client = Self::construct_nym_api_client(&self.config, self.user_agent.clone());
|
||||||
|
let key_rotation_config = Self::determine_key_rotation_state(&nym_api_client).await?;
|
||||||
|
|
||||||
let topology_provider = Self::setup_topology_provider(
|
let topology_provider = Self::setup_topology_provider(
|
||||||
self.custom_topology_provider.take(),
|
self.custom_topology_provider.take(),
|
||||||
self.config.debug.topology,
|
self.config.debug.topology,
|
||||||
self.config.get_nym_api_endpoints(),
|
self.config.get_nym_api_endpoints(),
|
||||||
self.user_agent.clone(),
|
nym_api_client,
|
||||||
);
|
);
|
||||||
|
|
||||||
let stats_reporter = Self::start_statistics_control(
|
let stats_reporter = Self::start_statistics_control(
|
||||||
@@ -838,6 +882,7 @@ where
|
|||||||
|
|
||||||
let reply_storage = Self::setup_persistent_reply_storage(
|
let reply_storage = Self::setup_persistent_reply_storage(
|
||||||
reply_storage_backend,
|
reply_storage_backend,
|
||||||
|
key_rotation_config,
|
||||||
shutdown.fork("persistent_reply_storage"),
|
shutdown.fork("persistent_reply_storage"),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
@@ -878,6 +923,7 @@ where
|
|||||||
|
|
||||||
Self::start_real_traffic_controller(
|
Self::start_real_traffic_controller(
|
||||||
controller_config,
|
controller_config,
|
||||||
|
key_rotation_config,
|
||||||
shared_topology_accessor.clone(),
|
shared_topology_accessor.clone(),
|
||||||
ack_receiver,
|
ack_receiver,
|
||||||
input_receiver,
|
input_receiver,
|
||||||
@@ -936,13 +982,14 @@ where
|
|||||||
task_handle: shutdown,
|
task_handle: shutdown,
|
||||||
client_request_sender,
|
client_request_sender,
|
||||||
forget_me: self.config.debug.forget_me,
|
forget_me: self.config.debug.forget_me,
|
||||||
|
remember_me: self.config.debug.remember_me,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct BaseClient {
|
pub struct BaseClient {
|
||||||
pub address: Recipient,
|
pub address: Recipient,
|
||||||
pub identity_keys: Arc<identity::KeyPair>,
|
pub identity_keys: Arc<ed25519::KeyPair>,
|
||||||
pub client_input: ClientInputStatus,
|
pub client_input: ClientInputStatus,
|
||||||
pub client_output: ClientOutputStatus,
|
pub client_output: ClientOutputStatus,
|
||||||
pub client_state: ClientState,
|
pub client_state: ClientState,
|
||||||
@@ -950,4 +997,5 @@ pub struct BaseClient {
|
|||||||
pub client_request_sender: ClientRequestSender,
|
pub client_request_sender: ClientRequestSender,
|
||||||
pub task_handle: TaskHandle,
|
pub task_handle: TaskHandle,
|
||||||
pub forget_me: ForgetMe,
|
pub forget_me: ForgetMe,
|
||||||
|
pub remember_me: RememberMe,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,32 +1,30 @@
|
|||||||
// Copyright 2022-2024 - Nym Technologies SA <contact@nymtech.net>
|
// Copyright 2022-2024 - Nym Technologies SA <contact@nymtech.net>
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
use crate::client::replies::reply_storage::{
|
use crate::{
|
||||||
fs_backend, CombinedReplyStorage, ReplyStorageBackend,
|
client::replies::reply_storage::{fs_backend, CombinedReplyStorage, ReplyStorageBackend},
|
||||||
|
config,
|
||||||
|
config::Config,
|
||||||
|
error::ClientCoreError,
|
||||||
};
|
};
|
||||||
use crate::config;
|
|
||||||
use crate::config::Config;
|
|
||||||
use crate::error::ClientCoreError;
|
|
||||||
use log::{error, info, trace};
|
|
||||||
use nym_bandwidth_controller::BandwidthController;
|
use nym_bandwidth_controller::BandwidthController;
|
||||||
use nym_client_core_gateways_storage::OnDiskGatewaysDetails;
|
use nym_client_core_gateways_storage::OnDiskGatewaysDetails;
|
||||||
use nym_credential_storage::storage::Storage as CredentialStorage;
|
use nym_credential_storage::storage::Storage as CredentialStorage;
|
||||||
use nym_validator_client::nyxd;
|
use nym_validator_client::{nyxd, QueryHttpRpcNyxdClient};
|
||||||
use nym_validator_client::QueryHttpRpcNyxdClient;
|
use std::{io, path::Path};
|
||||||
use std::path::Path;
|
|
||||||
use std::{fs, io};
|
|
||||||
use time::OffsetDateTime;
|
use time::OffsetDateTime;
|
||||||
|
use tracing::{error, info, trace};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
async fn setup_fresh_backend<P: AsRef<Path>>(
|
async fn setup_fresh_backend<P: AsRef<Path>>(
|
||||||
db_path: P,
|
db_path: P,
|
||||||
surb_config: &config::ReplySurbs,
|
surb_config: &config::ReplySurbs,
|
||||||
) -> Result<fs_backend::Backend, ClientCoreError> {
|
) -> Result<fs_backend::Backend, ClientCoreError> {
|
||||||
info!("creating fresh surb database");
|
info!("Creating fresh surb database");
|
||||||
let mut storage_backend = match fs_backend::Backend::init(db_path).await {
|
let mut storage_backend = match fs_backend::Backend::init(db_path).await {
|
||||||
Ok(backend) => backend,
|
Ok(backend) => backend,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
error!("failed to setup persistent storage backend for our reply needs: {err}");
|
error!("setup_fresh_backend: Failed to setup persistent storage backend for our reply needs: {err}");
|
||||||
return Err(ClientCoreError::SurbStorageError {
|
return Err(ClientCoreError::SurbStorageError {
|
||||||
source: Box::new(err),
|
source: Box::new(err),
|
||||||
});
|
});
|
||||||
@@ -40,14 +38,15 @@ async fn setup_fresh_backend<P: AsRef<Path>>(
|
|||||||
surb_config.minimum_reply_surb_storage_threshold,
|
surb_config.minimum_reply_surb_storage_threshold,
|
||||||
surb_config.maximum_reply_surb_storage_threshold,
|
surb_config.maximum_reply_surb_storage_threshold,
|
||||||
);
|
);
|
||||||
storage_backend
|
match storage_backend.init_fresh(&mem_store).await {
|
||||||
.init_fresh(&mem_store)
|
Ok(()) => Ok(storage_backend),
|
||||||
.await
|
Err(err) => {
|
||||||
.map_err(|err| ClientCoreError::SurbStorageError {
|
storage_backend.shutdown().await;
|
||||||
source: Box::new(err),
|
Err(ClientCoreError::SurbStorageError {
|
||||||
})?;
|
source: Box::new(err),
|
||||||
|
})
|
||||||
Ok(storage_backend)
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// fn setup_inactive_backend(surb_config: &config::ReplySurbs) -> fs_backend::Backend {
|
// fn setup_inactive_backend(surb_config: &config::ReplySurbs) -> fs_backend::Backend {
|
||||||
@@ -58,12 +57,11 @@ async fn setup_fresh_backend<P: AsRef<Path>>(
|
|||||||
// )
|
// )
|
||||||
// }
|
// }
|
||||||
|
|
||||||
fn archive_corrupted_database<P: AsRef<Path>>(db_path: P) -> io::Result<()> {
|
async fn archive_corrupted_database<P: AsRef<Path>>(db_path: P) -> io::Result<()> {
|
||||||
let db_path = db_path.as_ref();
|
let db_path = db_path.as_ref();
|
||||||
debug_assert!(db_path.exists());
|
debug_assert!(db_path.exists());
|
||||||
|
|
||||||
let now = OffsetDateTime::now_utc().unix_timestamp();
|
let now = OffsetDateTime::now_utc().unix_timestamp();
|
||||||
|
|
||||||
let suffix = format!("_{now}.corrupted");
|
let suffix = format!("_{now}.corrupted");
|
||||||
|
|
||||||
let new_extension =
|
let new_extension =
|
||||||
@@ -72,11 +70,15 @@ fn archive_corrupted_database<P: AsRef<Path>>(db_path: P) -> io::Result<()> {
|
|||||||
} else {
|
} else {
|
||||||
suffix
|
suffix
|
||||||
};
|
};
|
||||||
|
let renamed = db_path.with_extension(new_extension);
|
||||||
|
|
||||||
let mut renamed = db_path.to_owned();
|
tokio::fs::rename(db_path, &renamed).await.inspect_err(|_| {
|
||||||
renamed.set_extension(new_extension);
|
error!(
|
||||||
|
"Failed to rename corrupt database file: {} to {}",
|
||||||
fs::rename(db_path, renamed)
|
db_path.display(),
|
||||||
|
renamed.display()
|
||||||
|
);
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn setup_fs_reply_surb_backend<P: AsRef<Path>>(
|
pub async fn setup_fs_reply_surb_backend<P: AsRef<Path>>(
|
||||||
@@ -87,13 +89,12 @@ pub async fn setup_fs_reply_surb_backend<P: AsRef<Path>>(
|
|||||||
// the existing one
|
// the existing one
|
||||||
let db_path = db_path.as_ref();
|
let db_path = db_path.as_ref();
|
||||||
if db_path.exists() {
|
if db_path.exists() {
|
||||||
info!("loading existing surb database");
|
info!("Loading existing surb database");
|
||||||
match fs_backend::Backend::try_load(db_path, surb_config.fresh_sender_tags).await {
|
match fs_backend::Backend::try_load(db_path).await {
|
||||||
Ok(backend) => Ok(backend),
|
Ok(backend) => Ok(backend),
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
error!("failed to setup persistent storage backend for our reply needs: {err}. We're going to create a fresh database instead. This behaviour might change in the future");
|
error!("setup_fs_reply_surb_backend: Failed to setup persistent storage backend for our reply needs: {err}. We're going to create a fresh database instead. This behaviour might change in the future");
|
||||||
|
archive_corrupted_database(db_path).await?;
|
||||||
archive_corrupted_database(db_path)?;
|
|
||||||
setup_fresh_backend(db_path, surb_config).await
|
setup_fresh_backend(db_path, surb_config).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -113,41 +114,32 @@ pub async fn setup_fs_gateways_storage<P: AsRef<Path>>(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_bandwidth_controller<St: CredentialStorage>(
|
|
||||||
config: &Config,
|
|
||||||
storage: St,
|
|
||||||
) -> BandwidthController<QueryHttpRpcNyxdClient, St> {
|
|
||||||
let nyxd_url = config
|
|
||||||
.get_validator_endpoints()
|
|
||||||
.pop()
|
|
||||||
.expect("No nyxd validator endpoint provided");
|
|
||||||
|
|
||||||
create_bandwidth_controller_with_urls(nyxd_url, storage)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn create_bandwidth_controller_with_urls<St: CredentialStorage>(
|
pub fn create_bandwidth_controller_with_urls<St: CredentialStorage>(
|
||||||
nyxd_url: Url,
|
nyxd_url: Url,
|
||||||
storage: St,
|
storage: St,
|
||||||
) -> BandwidthController<QueryHttpRpcNyxdClient, St> {
|
) -> Result<BandwidthController<QueryHttpRpcNyxdClient, St>, ClientCoreError> {
|
||||||
let client = default_query_dkg_client(nyxd_url);
|
let client = default_query_dkg_client(nyxd_url)?;
|
||||||
|
|
||||||
BandwidthController::new(storage, client)
|
Ok(BandwidthController::new(storage, client))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn default_query_dkg_client_from_config(config: &Config) -> QueryHttpRpcNyxdClient {
|
pub fn default_query_dkg_client_from_config(
|
||||||
|
config: &Config,
|
||||||
|
) -> Result<QueryHttpRpcNyxdClient, ClientCoreError> {
|
||||||
let nyxd_url = config
|
let nyxd_url = config
|
||||||
.get_validator_endpoints()
|
.get_validator_endpoints()
|
||||||
.pop()
|
.pop()
|
||||||
.expect("No nyxd validator endpoint provided");
|
.ok_or(ClientCoreError::RpcClientMissingUrl)?;
|
||||||
|
|
||||||
default_query_dkg_client(nyxd_url)
|
default_query_dkg_client(nyxd_url)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn default_query_dkg_client(nyxd_url: Url) -> QueryHttpRpcNyxdClient {
|
pub fn default_query_dkg_client(nyxd_url: Url) -> Result<QueryHttpRpcNyxdClient, ClientCoreError> {
|
||||||
let details = nym_network_defaults::NymNetworkDetails::new_from_env();
|
let details = nym_network_defaults::NymNetworkDetails::new_from_env();
|
||||||
let client_config = nyxd::Config::try_from_nym_network_details(&details)
|
let client_config = nyxd::Config::try_from_nym_network_details(&details)
|
||||||
.expect("failed to construct validator client config");
|
.map_err(|source| ClientCoreError::InvalidNetworkDetails { source })?;
|
||||||
// overwrite env configuration with config URLs
|
// overwrite env configuration with config URLs
|
||||||
|
|
||||||
QueryHttpRpcNyxdClient::connect(client_config, nyxd_url.as_str())
|
QueryHttpRpcNyxdClient::connect(client_config, nyxd_url.as_str())
|
||||||
.expect("Could not construct query client")
|
.map_err(|source| ClientCoreError::RpcClientCreationFailure { source })
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ use crate::client::key_manager::persistence::KeyStore;
|
|||||||
use crate::client::key_manager::ClientKeys;
|
use crate::client::key_manager::ClientKeys;
|
||||||
use crate::error::ClientCoreError;
|
use crate::error::ClientCoreError;
|
||||||
use nym_client_core_gateways_storage::{ActiveGateway, GatewayRegistration, GatewaysDetailsStore};
|
use nym_client_core_gateways_storage::{ActiveGateway, GatewayRegistration, GatewaysDetailsStore};
|
||||||
use nym_crypto::asymmetric::identity;
|
use nym_crypto::asymmetric::ed25519;
|
||||||
|
|
||||||
// helpers for error wrapping
|
// helpers for error wrapping
|
||||||
pub async fn set_active_gateway<D>(
|
pub async fn set_active_gateway<D>(
|
||||||
@@ -26,7 +26,7 @@ where
|
|||||||
|
|
||||||
pub async fn get_active_gateway_identity<D>(
|
pub async fn get_active_gateway_identity<D>(
|
||||||
details_store: &D,
|
details_store: &D,
|
||||||
) -> Result<Option<identity::PublicKey>, ClientCoreError>
|
) -> Result<Option<ed25519::PublicKey>, ClientCoreError>
|
||||||
where
|
where
|
||||||
D: GatewaysDetailsStore,
|
D: GatewaysDetailsStore,
|
||||||
D::StorageError: Send + Sync + 'static,
|
D::StorageError: Send + Sync + 'static,
|
||||||
@@ -42,7 +42,7 @@ where
|
|||||||
|
|
||||||
pub async fn get_all_registered_identities<D>(
|
pub async fn get_all_registered_identities<D>(
|
||||||
details_store: &D,
|
details_store: &D,
|
||||||
) -> Result<Vec<identity::PublicKey>, ClientCoreError>
|
) -> Result<Vec<ed25519::PublicKey>, ClientCoreError>
|
||||||
where
|
where
|
||||||
D: GatewaysDetailsStore + Sync,
|
D: GatewaysDetailsStore + Sync,
|
||||||
D::StorageError: Send + Sync + 'static,
|
D::StorageError: Send + Sync + 'static,
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ use crate::client::topology_control::TopologyAccessor;
|
|||||||
use crate::{config, spawn_future};
|
use crate::{config, spawn_future};
|
||||||
use futures::task::{Context, Poll};
|
use futures::task::{Context, Poll};
|
||||||
use futures::{Future, Stream, StreamExt};
|
use futures::{Future, Stream, StreamExt};
|
||||||
use log::*;
|
|
||||||
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::cover::generate_loop_cover_packet;
|
use nym_sphinx::cover::generate_loop_cover_packet;
|
||||||
@@ -19,6 +18,7 @@ use std::pin::Pin;
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use tokio::sync::mpsc::error::TrySendError;
|
use tokio::sync::mpsc::error::TrySendError;
|
||||||
|
use tracing::*;
|
||||||
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
use tokio::time::{sleep, Sleep};
|
use tokio::time::{sleep, Sleep};
|
||||||
@@ -62,6 +62,10 @@ where
|
|||||||
/// Optional secondary predefined packet size used for the loop cover messages.
|
/// Optional secondary predefined packet size used for the loop cover messages.
|
||||||
secondary_packet_size: Option<PacketSize>,
|
secondary_packet_size: Option<PacketSize>,
|
||||||
|
|
||||||
|
/// Specify whether any constructed packets should use the legacy format,
|
||||||
|
/// where the payload keys are explicitly attached rather than using the seeds
|
||||||
|
use_legacy_sphinx_format: bool,
|
||||||
|
|
||||||
packet_type: PacketType,
|
packet_type: PacketType,
|
||||||
|
|
||||||
stats_tx: ClientStatsSender,
|
stats_tx: ClientStatsSender,
|
||||||
@@ -130,6 +134,7 @@ impl LoopCoverTrafficStream<OsRng> {
|
|||||||
topology_access,
|
topology_access,
|
||||||
primary_packet_size: traffic_config.primary_packet_size,
|
primary_packet_size: traffic_config.primary_packet_size,
|
||||||
secondary_packet_size: traffic_config.secondary_packet_size,
|
secondary_packet_size: traffic_config.secondary_packet_size,
|
||||||
|
use_legacy_sphinx_format: traffic_config.use_legacy_sphinx_format,
|
||||||
packet_type: traffic_config.packet_type,
|
packet_type: traffic_config.packet_type,
|
||||||
stats_tx,
|
stats_tx,
|
||||||
task_client,
|
task_client,
|
||||||
@@ -182,6 +187,7 @@ impl LoopCoverTrafficStream<OsRng> {
|
|||||||
|
|
||||||
let cover_message = match generate_loop_cover_packet(
|
let cover_message = match generate_loop_cover_packet(
|
||||||
&mut self.rng,
|
&mut self.rng,
|
||||||
|
self.use_legacy_sphinx_format,
|
||||||
topology_ref,
|
topology_ref,
|
||||||
&self.ack_key,
|
&self.ack_key,
|
||||||
&self.our_full_destination,
|
&self.our_full_destination,
|
||||||
@@ -204,10 +210,10 @@ impl LoopCoverTrafficStream<OsRng> {
|
|||||||
TrySendError::Full(_) => {
|
TrySendError::Full(_) => {
|
||||||
// This isn't a problem, if the channel is full means we're already sending the
|
// This isn't a problem, if the channel is full means we're already sending the
|
||||||
// max amount of messages downstream can handle.
|
// max amount of messages downstream can handle.
|
||||||
log::debug!("Failed to send cover message - channel full");
|
tracing::debug!("Failed to send cover message - channel full");
|
||||||
}
|
}
|
||||||
TrySendError::Closed(_) => {
|
TrySendError::Closed(_) => {
|
||||||
log::warn!("Failed to send cover message - channel closed");
|
tracing::warn!("Failed to send cover message - channel closed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -229,6 +235,7 @@ impl LoopCoverTrafficStream<OsRng> {
|
|||||||
tokio::task::yield_now().await;
|
tokio::task::yield_now().await;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::panic)]
|
||||||
pub fn start(mut self) {
|
pub fn start(mut self) {
|
||||||
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
|
||||||
@@ -245,27 +252,30 @@ impl LoopCoverTrafficStream<OsRng> {
|
|||||||
|
|
||||||
let mut shutdown = self.task_client.fork("select");
|
let mut shutdown = self.task_client.fork("select");
|
||||||
|
|
||||||
spawn_future(async move {
|
spawn_future!(
|
||||||
debug!("Started LoopCoverTrafficStream with graceful shutdown support");
|
async move {
|
||||||
|
debug!("Started LoopCoverTrafficStream with graceful shutdown support");
|
||||||
|
|
||||||
while !shutdown.is_shutdown() {
|
while !shutdown.is_shutdown() {
|
||||||
tokio::select! {
|
tokio::select! {
|
||||||
biased;
|
biased;
|
||||||
_ = shutdown.recv() => {
|
_ = shutdown.recv() => {
|
||||||
log::trace!("LoopCoverTrafficStream: Received shutdown");
|
tracing::trace!("LoopCoverTrafficStream: Received shutdown");
|
||||||
}
|
}
|
||||||
next = self.next() => {
|
next = self.next() => {
|
||||||
if next.is_some() {
|
if next.is_some() {
|
||||||
self.on_new_message().await;
|
self.on_new_message().await;
|
||||||
} else {
|
} else {
|
||||||
log::trace!("LoopCoverTrafficStream: Stopping since channel closed");
|
tracing::trace!("LoopCoverTrafficStream: Stopping since channel closed");
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
shutdown.recv_timeout().await;
|
||||||
shutdown.recv_timeout().await;
|
tracing::debug!("LoopCoverTrafficStream: Exiting");
|
||||||
log::debug!("LoopCoverTrafficStream: Exiting");
|
},
|
||||||
})
|
"LoopCoverTrafficStream"
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -135,7 +135,9 @@ impl InputMessage {
|
|||||||
recipient_tag,
|
recipient_tag,
|
||||||
data,
|
data,
|
||||||
lane,
|
lane,
|
||||||
max_retransmissions: None,
|
// \/ set it to SOME sane default so that if we run out of surbs and constantly
|
||||||
|
// fail to request more, we wouldn't be stuck in limbo
|
||||||
|
max_retransmissions: Some(10),
|
||||||
};
|
};
|
||||||
if let Some(packet_type) = packet_type {
|
if let Some(packet_type) = packet_type {
|
||||||
InputMessage::new_wrapper(message, packet_type)
|
InputMessage::new_wrapper(message, packet_type)
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
use crate::client::key_manager::persistence::KeyStore;
|
use crate::client::key_manager::persistence::KeyStore;
|
||||||
use nym_crypto::{
|
use nym_crypto::{
|
||||||
asymmetric::{encryption, identity},
|
asymmetric::{ed25519, x25519},
|
||||||
hkdf::{DerivationMaterial, InvalidLength},
|
hkdf::{DerivationMaterial, InvalidLength},
|
||||||
};
|
};
|
||||||
use nym_gateway_requests::shared_key::{LegacySharedKeys, SharedGatewayKey, SharedSymmetricKey};
|
use nym_gateway_requests::shared_key::{LegacySharedKeys, SharedGatewayKey, SharedSymmetricKey};
|
||||||
@@ -25,10 +25,10 @@ mod test;
|
|||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct ClientKeys {
|
pub struct ClientKeys {
|
||||||
/// identity key associated with the client instance.
|
/// identity key associated with the client instance.
|
||||||
identity_keypair: Arc<identity::KeyPair>,
|
identity_keypair: Arc<ed25519::KeyPair>,
|
||||||
|
|
||||||
/// encryption key associated with the client instance.
|
/// encryption key associated with the client instance.
|
||||||
encryption_keypair: Arc<encryption::KeyPair>,
|
encryption_keypair: Arc<x25519::KeyPair>,
|
||||||
|
|
||||||
/// key used for producing and processing acknowledgement packets.
|
/// key used for producing and processing acknowledgement packets.
|
||||||
ack_key: Arc<AckKey>,
|
ack_key: Arc<AckKey>,
|
||||||
@@ -41,8 +41,8 @@ impl ClientKeys {
|
|||||||
R: RngCore + CryptoRng,
|
R: RngCore + CryptoRng,
|
||||||
{
|
{
|
||||||
ClientKeys {
|
ClientKeys {
|
||||||
identity_keypair: Arc::new(identity::KeyPair::new(rng)),
|
identity_keypair: Arc::new(ed25519::KeyPair::new(rng)),
|
||||||
encryption_keypair: Arc::new(encryption::KeyPair::new(rng)),
|
encryption_keypair: Arc::new(x25519::KeyPair::new(rng)),
|
||||||
ack_key: Arc::new(AckKey::new(rng)),
|
ack_key: Arc::new(AckKey::new(rng)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -56,18 +56,18 @@ impl ClientKeys {
|
|||||||
{
|
{
|
||||||
let secret = derivation_material.derive_secret()?;
|
let secret = derivation_material.derive_secret()?;
|
||||||
Ok(ClientKeys {
|
Ok(ClientKeys {
|
||||||
identity_keypair: Arc::new(identity::KeyPair::from_secret(
|
identity_keypair: Arc::new(ed25519::KeyPair::from_secret(
|
||||||
secret,
|
secret,
|
||||||
derivation_material.index(),
|
derivation_material.index(),
|
||||||
)),
|
)),
|
||||||
encryption_keypair: Arc::new(encryption::KeyPair::new(rng)),
|
encryption_keypair: Arc::new(x25519::KeyPair::new(rng)),
|
||||||
ack_key: Arc::new(AckKey::new(rng)),
|
ack_key: Arc::new(AckKey::new(rng)),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_keys(
|
pub fn from_keys(
|
||||||
id_keypair: identity::KeyPair,
|
id_keypair: ed25519::KeyPair,
|
||||||
enc_keypair: encryption::KeyPair,
|
enc_keypair: x25519::KeyPair,
|
||||||
ack_key: AckKey,
|
ack_key: AckKey,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
@@ -85,13 +85,13 @@ impl ClientKeys {
|
|||||||
store.store_keys(self).await
|
store.store_keys(self).await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets an atomically reference counted pointer to [`identity::KeyPair`].
|
/// Gets an atomically reference counted pointer to [`ed25519::KeyPair`].
|
||||||
pub fn identity_keypair(&self) -> Arc<identity::KeyPair> {
|
pub fn identity_keypair(&self) -> Arc<ed25519::KeyPair> {
|
||||||
Arc::clone(&self.identity_keypair)
|
Arc::clone(&self.identity_keypair)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets an atomically reference counted pointer to [`encryption::KeyPair`].
|
/// Gets an atomically reference counted pointer to [`x25519::KeyPair`].
|
||||||
pub fn encryption_keypair(&self) -> Arc<encryption::KeyPair> {
|
pub fn encryption_keypair(&self) -> Arc<x25519::KeyPair> {
|
||||||
Arc::clone(&self.encryption_keypair)
|
Arc::clone(&self.encryption_keypair)
|
||||||
}
|
}
|
||||||
/// Gets an atomically reference counted pointer to [`AckKey`].
|
/// Gets an atomically reference counted pointer to [`AckKey`].
|
||||||
@@ -103,8 +103,8 @@ impl ClientKeys {
|
|||||||
fn _assert_keys_zeroize_on_drop() {
|
fn _assert_keys_zeroize_on_drop() {
|
||||||
fn _assert_zeroize_on_drop<T: ZeroizeOnDrop>() {}
|
fn _assert_zeroize_on_drop<T: ZeroizeOnDrop>() {}
|
||||||
|
|
||||||
_assert_zeroize_on_drop::<identity::KeyPair>();
|
_assert_zeroize_on_drop::<ed25519::KeyPair>();
|
||||||
_assert_zeroize_on_drop::<encryption::KeyPair>();
|
_assert_zeroize_on_drop::<x25519::KeyPair>();
|
||||||
_assert_zeroize_on_drop::<AckKey>();
|
_assert_zeroize_on_drop::<AckKey>();
|
||||||
_assert_zeroize_on_drop::<LegacySharedKeys>();
|
_assert_zeroize_on_drop::<LegacySharedKeys>();
|
||||||
_assert_zeroize_on_drop::<SharedSymmetricKey>();
|
_assert_zeroize_on_drop::<SharedSymmetricKey>();
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ use tokio::sync::Mutex;
|
|||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
use crate::config::disk_persistence::ClientKeysPaths;
|
use crate::config::disk_persistence::ClientKeysPaths;
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
use nym_crypto::asymmetric::{encryption, identity};
|
use nym_crypto::asymmetric::{ed25519, x25519};
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
use nym_pemstore::traits::{PemStorableKey, PemStorableKeyPair};
|
use nym_pemstore::traits::{PemStorableKey, PemStorableKeyPair};
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
@@ -86,13 +86,13 @@ impl OnDiskKeys {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub fn load_encryption_keypair(&self) -> Result<encryption::KeyPair, OnDiskKeysError> {
|
pub fn load_encryption_keypair(&self) -> Result<x25519::KeyPair, OnDiskKeysError> {
|
||||||
let encryption_paths = self.paths.encryption_key_pair_path();
|
let encryption_paths = self.paths.encryption_key_pair_path();
|
||||||
self.load_keypair(encryption_paths, "encryption")
|
self.load_keypair(encryption_paths, "encryption")
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub fn load_identity_keypair(&self) -> Result<identity::KeyPair, OnDiskKeysError> {
|
pub fn load_identity_keypair(&self) -> Result<ed25519::KeyPair, OnDiskKeysError> {
|
||||||
let identity_paths = self.paths.identity_key_pair_path();
|
let identity_paths = self.paths.identity_key_pair_path();
|
||||||
self.load_keypair(identity_paths, "identity")
|
self.load_keypair(identity_paths, "identity")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,10 +4,10 @@
|
|||||||
use crate::client::mix_traffic::transceiver::GatewayTransceiver;
|
use crate::client::mix_traffic::transceiver::GatewayTransceiver;
|
||||||
use crate::error::ClientCoreError;
|
use crate::error::ClientCoreError;
|
||||||
use crate::spawn_future;
|
use crate::spawn_future;
|
||||||
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 nym_task::TaskClient;
|
||||||
|
use tracing::*;
|
||||||
use transceiver::ErasedGatewayError;
|
use transceiver::ErasedGatewayError;
|
||||||
|
|
||||||
pub type BatchMixMessageSender = tokio::sync::mpsc::Sender<Vec<MixPacket>>;
|
pub type BatchMixMessageSender = tokio::sync::mpsc::Sender<Vec<MixPacket>>;
|
||||||
@@ -96,72 +96,93 @@ impl MixTrafficController {
|
|||||||
mut mix_packets: Vec<MixPacket>,
|
mut mix_packets: Vec<MixPacket>,
|
||||||
) -> Result<(), ErasedGatewayError> {
|
) -> Result<(), ErasedGatewayError> {
|
||||||
debug_assert!(!mix_packets.is_empty());
|
debug_assert!(!mix_packets.is_empty());
|
||||||
|
let send_future = if mix_packets.len() == 1 {
|
||||||
let result = if mix_packets.len() == 1 {
|
// SAFETY: we just checked we have one packet
|
||||||
|
#[allow(clippy::unwrap_used)]
|
||||||
let mix_packet = mix_packets.pop().unwrap();
|
let mix_packet = mix_packets.pop().unwrap();
|
||||||
self.gateway_transceiver.send_mix_packet(mix_packet).await
|
self.gateway_transceiver.send_mix_packet(mix_packet)
|
||||||
} else {
|
} else {
|
||||||
self.gateway_transceiver
|
self.gateway_transceiver.batch_send_mix_packets(mix_packets)
|
||||||
.batch_send_mix_packets(mix_packets)
|
|
||||||
.await
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if result.is_err() {
|
tokio::select! {
|
||||||
self.consecutive_gateway_failure_count += 1;
|
biased;
|
||||||
} else {
|
_ = self.task_client.recv() => {
|
||||||
trace!("We *might* have managed to forward sphinx packet(s) to the gateway!");
|
trace!("received shutdown while handling messages");
|
||||||
self.consecutive_gateway_failure_count = 0;
|
Ok(())
|
||||||
}
|
}
|
||||||
|
result = send_future => {
|
||||||
|
if result.is_err() {
|
||||||
|
self.consecutive_gateway_failure_count += 1;
|
||||||
|
} else {
|
||||||
|
trace!("We *might* have managed to forward sphinx packet(s) to the gateway!");
|
||||||
|
self.consecutive_gateway_failure_count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
result
|
result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn on_client_request(&mut self, client_request: ClientRequest) {
|
||||||
|
tokio::select! {
|
||||||
|
biased;
|
||||||
|
_ = self.task_client.recv() => {
|
||||||
|
trace!("received shutdown while handling client request");
|
||||||
|
}
|
||||||
|
result = self.gateway_transceiver.send_client_request(client_request) => {
|
||||||
|
if let Err(err) = result {
|
||||||
|
error!("Failed to send client request: {err}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn start(mut self) {
|
pub fn start(mut self) {
|
||||||
spawn_future(async move {
|
spawn_future!(
|
||||||
debug!("Started MixTrafficController with graceful shutdown support");
|
async move {
|
||||||
|
debug!("Started MixTrafficController with graceful shutdown support");
|
||||||
while !self.task_client.is_shutdown() {
|
while !self.task_client.is_shutdown() {
|
||||||
tokio::select! {
|
tokio::select! {
|
||||||
mix_packets = self.mix_rx.recv() => match mix_packets {
|
biased;
|
||||||
Some(mix_packets) => {
|
_ = self.task_client.recv() => {
|
||||||
if let Err(err) = self.on_messages(mix_packets).await {
|
tracing::trace!("MixTrafficController: Received shutdown");
|
||||||
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 => {
|
|
||||||
log::trace!("MixTrafficController: Stopping since channel closed");
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
},
|
mix_packets = self.mix_rx.recv() => match mix_packets {
|
||||||
client_request = self.client_rx.recv() => match client_request {
|
Some(mix_packets) => {
|
||||||
Some(client_request) => {
|
if let Err(err) = self.on_messages(mix_packets).await {
|
||||||
match self.gateway_transceiver.send_client_request(client_request).await {
|
error!("Failed to send sphinx packet(s) to the gateway: {err}");
|
||||||
Ok(_) => (),
|
if self.consecutive_gateway_failure_count == MAX_FAILURE_COUNT {
|
||||||
Err(e) => error!("Failed to send client request: {}", e),
|
// 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 => {
|
||||||
|
tracing::trace!("MixTrafficController: Stopping since channel closed");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
client_request = self.client_rx.recv() => match client_request {
|
||||||
|
Some(client_request) => {
|
||||||
|
self.on_client_request(client_request).await;
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
tracing::trace!("MixTrafficController, client request channel closed");
|
||||||
|
}
|
||||||
},
|
},
|
||||||
None => {
|
|
||||||
log::trace!("MixTrafficController, client request channel closed");
|
|
||||||
}
|
|
||||||
},
|
|
||||||
_ = self.task_client.recv() => {
|
|
||||||
log::trace!("MixTrafficController: Received shutdown");
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
self.task_client.recv_timeout().await;
|
||||||
self.task_client.recv_timeout().await;
|
tracing::debug!("MixTrafficController: Exiting");
|
||||||
|
},
|
||||||
log::debug!("MixTrafficController: Exiting");
|
"MixTrafficController"
|
||||||
});
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,9 +2,8 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use log::{debug, error};
|
|
||||||
use nym_credential_storage::storage::Storage as CredentialStorage;
|
use nym_credential_storage::storage::Storage as CredentialStorage;
|
||||||
use nym_crypto::asymmetric::identity;
|
use nym_crypto::asymmetric::ed25519;
|
||||||
use nym_gateway_client::error::GatewayClientError;
|
use nym_gateway_client::error::GatewayClientError;
|
||||||
use nym_gateway_client::GatewayClient;
|
use nym_gateway_client::GatewayClient;
|
||||||
pub use nym_gateway_client::{GatewayPacketRouter, PacketRouter};
|
pub use nym_gateway_client::{GatewayPacketRouter, PacketRouter};
|
||||||
@@ -14,6 +13,7 @@ use nym_validator_client::nyxd::contract_traits::DkgQueryClient;
|
|||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use std::os::raw::c_int as RawFd;
|
use std::os::raw::c_int as RawFd;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
use tracing::{debug, error};
|
||||||
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
use futures::channel::oneshot;
|
use futures::channel::oneshot;
|
||||||
@@ -27,10 +27,10 @@ fn erase_err<E: std::error::Error + Send + Sync + 'static>(err: E) -> ErasedGate
|
|||||||
ErasedGatewayError(Box::new(err))
|
ErasedGatewayError(Box::new(err))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This combines combines the functionalities of being able to send and receive mix packets.
|
/// This combines the functionalities of being able to send and receive mix packets.
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
pub trait GatewayTransceiver: GatewaySender + GatewayReceiver {
|
pub trait GatewayTransceiver: GatewaySender + GatewayReceiver {
|
||||||
fn gateway_identity(&self) -> identity::PublicKey;
|
fn gateway_identity(&self) -> ed25519::PublicKey;
|
||||||
fn ws_fd(&self) -> Option<RawFd>;
|
fn ws_fd(&self) -> Option<RawFd>;
|
||||||
async fn send_client_request(
|
async fn send_client_request(
|
||||||
&mut self,
|
&mut self,
|
||||||
@@ -75,7 +75,7 @@ pub trait GatewayReceiver {
|
|||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl<G: GatewayTransceiver + ?Sized + Send> GatewayTransceiver for Box<G> {
|
impl<G: GatewayTransceiver + ?Sized + Send> GatewayTransceiver for Box<G> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn gateway_identity(&self) -> identity::PublicKey {
|
fn gateway_identity(&self) -> ed25519::PublicKey {
|
||||||
(**self).gateway_identity()
|
(**self).gateway_identity()
|
||||||
}
|
}
|
||||||
fn ws_fd(&self) -> Option<RawFd> {
|
fn ws_fd(&self) -> Option<RawFd> {
|
||||||
@@ -87,7 +87,7 @@ impl<G: GatewayTransceiver + ?Sized + Send> GatewayTransceiver for Box<G> {
|
|||||||
message: ClientRequest,
|
message: ClientRequest,
|
||||||
) -> Result<(), GatewayClientError> {
|
) -> Result<(), GatewayClientError> {
|
||||||
let _ = (**self).send_client_request(message.clone()).await?;
|
let _ = (**self).send_client_request(message.clone()).await?;
|
||||||
log::debug!("Sent client request: {:?}", message);
|
tracing::debug!("Sent client request: {:?}", message);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -134,7 +134,7 @@ where
|
|||||||
St: CredentialStorage,
|
St: CredentialStorage,
|
||||||
<St as CredentialStorage>::StorageError: Send + Sync + 'static,
|
<St as CredentialStorage>::StorageError: Send + Sync + 'static,
|
||||||
{
|
{
|
||||||
fn gateway_identity(&self) -> identity::PublicKey {
|
fn gateway_identity(&self) -> ed25519::PublicKey {
|
||||||
self.gateway_client.gateway_identity()
|
self.gateway_client.gateway_identity()
|
||||||
}
|
}
|
||||||
fn ws_fd(&self) -> Option<RawFd> {
|
fn ws_fd(&self) -> Option<RawFd> {
|
||||||
@@ -190,7 +190,7 @@ pub enum LocalGatewayError {
|
|||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
pub struct LocalGateway {
|
pub struct LocalGateway {
|
||||||
/// Identity of the locally managed gateway
|
/// Identity of the locally managed gateway
|
||||||
local_identity: identity::PublicKey,
|
local_identity: ed25519::PublicKey,
|
||||||
|
|
||||||
// 'sender' part
|
// 'sender' part
|
||||||
/// Channel responsible for taking mix packets and forwarding them further into the further mixnet layers.
|
/// Channel responsible for taking mix packets and forwarding them further into the further mixnet layers.
|
||||||
@@ -203,7 +203,7 @@ pub struct LocalGateway {
|
|||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
impl LocalGateway {
|
impl LocalGateway {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
local_identity: identity::PublicKey,
|
local_identity: ed25519::PublicKey,
|
||||||
packet_forwarder: nym_mixnet_client::forwarder::MixForwardingSender,
|
packet_forwarder: nym_mixnet_client::forwarder::MixForwardingSender,
|
||||||
packet_router_tx: oneshot::Sender<PacketRouter>,
|
packet_router_tx: oneshot::Sender<PacketRouter>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
@@ -221,7 +221,7 @@ mod nonwasm_sealed {
|
|||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl GatewayTransceiver for LocalGateway {
|
impl GatewayTransceiver for LocalGateway {
|
||||||
fn gateway_identity(&self) -> identity::PublicKey {
|
fn gateway_identity(&self) -> ed25519::PublicKey {
|
||||||
self.local_identity
|
self.local_identity
|
||||||
}
|
}
|
||||||
fn ws_fd(&self) -> Option<RawFd> {
|
fn ws_fd(&self) -> Option<RawFd> {
|
||||||
@@ -263,12 +263,14 @@ mod nonwasm_sealed {
|
|||||||
|
|
||||||
// if we ever decided to start writing unit tests... : )
|
// if we ever decided to start writing unit tests... : )
|
||||||
pub struct MockGateway {
|
pub struct MockGateway {
|
||||||
dummy_identity: identity::PublicKey,
|
dummy_identity: ed25519::PublicKey,
|
||||||
packet_router: Option<PacketRouter>,
|
packet_router: Option<PacketRouter>,
|
||||||
sent: Vec<MixPacket>,
|
sent: Vec<MixPacket>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for MockGateway {
|
impl Default for MockGateway {
|
||||||
|
// test code
|
||||||
|
#[allow(clippy::unwrap_used)]
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
MockGateway {
|
MockGateway {
|
||||||
dummy_identity: "3ebjp1Fb9hdcS1AR6AZihgeJiMHkB5jjJUsvqNnfQwU7"
|
dummy_identity: "3ebjp1Fb9hdcS1AR6AZihgeJiMHkB5jjJUsvqNnfQwU7"
|
||||||
@@ -303,7 +305,7 @@ impl GatewaySender for MockGateway {
|
|||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl GatewayTransceiver for MockGateway {
|
impl GatewayTransceiver for MockGateway {
|
||||||
fn gateway_identity(&self) -> identity::PublicKey {
|
fn gateway_identity(&self) -> ed25519::PublicKey {
|
||||||
self.dummy_identity
|
self.dummy_identity
|
||||||
}
|
}
|
||||||
fn ws_fd(&self) -> Option<RawFd> {
|
fn ws_fd(&self) -> Option<RawFd> {
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user