Compare commits
563 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b7f445a330 | |||
| 360c7fda57 | |||
| 2cbb2d8327 | |||
| 808e3f0562 | |||
| f0dade3c5b | |||
| 0a3c2b3cca | |||
| ac66906980 | |||
| afd9f823d8 | |||
| d818448848 | |||
| a9a1ba2847 | |||
| 2708c0ce10 | |||
| bb3e9b3d4e | |||
| e624f42ad5 | |||
| 7da83397dd | |||
| 26d0b4b159 | |||
| b74490dc50 | |||
| 8113095ff5 | |||
| 8339d6ab49 | |||
| f037b2ae68 | |||
| 2a4c1d96a4 | |||
| ed04ddf1c4 | |||
| 34b5d66df6 | |||
| 0a1a5c25f7 | |||
| 6bdba7046f | |||
| 428d91a536 | |||
| 88e0eaafcb | |||
| dd19cabf15 | |||
| 4ec08da36d | |||
| 16c59d95d3 | |||
| e6f76380f6 | |||
| 6961ecae55 | |||
| dd814c067c | |||
| 666d5945b9 | |||
| ecebf6e84c | |||
| 4663d39505 | |||
| 81a7d7b001 | |||
| 2c0a561cd5 | |||
| d187d252fb | |||
| 4026dc8eef | |||
| c02453b2d1 | |||
| f1a5a0ccd7 | |||
| f9a4ca5a22 | |||
| ee99843b51 | |||
| 05e349cf37 | |||
| 8d51cd1afd | |||
| a2fd78963c | |||
| 59d43e1acd | |||
| 354c529cea | |||
| 435a60aee9 | |||
| a1c9b9b4bb | |||
| 457d1e8615 | |||
| 05eb05643f | |||
| 3d82f84e1d | |||
| c7b3999dcf | |||
| 8336bb0009 | |||
| 4cb0231acf | |||
| 3715860a47 | |||
| 5b2e4158bd | |||
| 2ddd34f343 | |||
| 564cbadc6e | |||
| 5a9920edb8 | |||
| 0e312f66ea | |||
| 8ca2ef28e6 | |||
| 0cd0139307 | |||
| 0041b4a7a7 | |||
| caa18f1661 | |||
| 946ced541c | |||
| fd0c4c2623 | |||
| 9f57ea4309 | |||
| 4c7a30a16d | |||
| 8029136251 | |||
| 2a3d898da1 | |||
| 0dd1f3ac2b | |||
| 2edd704e39 | |||
| e936ba1d26 | |||
| d6a9f4c549 | |||
| 2934d24e53 | |||
| aa65b96ef2 | |||
| b5bb3f36bf | |||
| 9f5c225cf9 | |||
| f0864adfe6 | |||
| 532fea38d5 | |||
| 83eb0cbf54 | |||
| 58e0330f4f | |||
| 11e01335c2 | |||
| aa8accfbf8 | |||
| efc83bdc1a | |||
| f623a9967c | |||
| 5395eebaef | |||
| 7ffe4dd1d8 | |||
| 1d292d4688 | |||
| dd04d4ea46 | |||
| 3620cc9df0 | |||
| b06d6ff412 | |||
| 6088c835a3 | |||
| 9113658a42 | |||
| d09503edf4 | |||
| 09124dafac | |||
| a2ede72798 | |||
| 61296b58e9 | |||
| e3f3c5620d | |||
| c656b3968b | |||
| 41f9b9b340 | |||
| 7d12b91bbd | |||
| 2960a4c48e | |||
| 4a84274055 | |||
| c34d89165c | |||
| f1b0a60b34 | |||
| abef9c9768 | |||
| c4b227f66e | |||
| 2389d7e62f | |||
| f5e16cda5e | |||
| 7ea415c082 | |||
| 90bfeb3dd2 | |||
| f8666cec45 | |||
| f6e5892de7 | |||
| 6d2d8ce149 | |||
| d38139be66 | |||
| 46d1ef7892 | |||
| 72bad6bb38 | |||
| 66fd484bd5 | |||
| a1328c96cf | |||
| 18aa4707a4 | |||
| dadfc412f2 | |||
| 3746975b14 | |||
| 2c90229fce | |||
| b461645d3d | |||
| f7f8b9b898 | |||
| 880d2d4edd | |||
| 7bc81a91c5 | |||
| 4ce652af95 | |||
| 8142e5c84c | |||
| 4efe712fc5 | |||
| 03f754cde4 | |||
| 8f53f095fb | |||
| a0c667927c | |||
| 0cc090038b | |||
| af32fe4022 | |||
| eb2ac7630a | |||
| 189fd0ece4 | |||
| b6ccab79d2 | |||
| 93cc281abc | |||
| 1f83b6f4e8 | |||
| 5a96ef4ffe | |||
| dea3f7d4b3 | |||
| 40b2729a01 | |||
| 91f383d5ac | |||
| 268588daac | |||
| c0aff70b37 | |||
| 410ef85165 | |||
| 4af376cb33 | |||
| 66f012c70e | |||
| 198739a126 | |||
| 85a0a3d8b5 | |||
| 789525c35b | |||
| 7ad5ff7770 | |||
| bf56696adc | |||
| 193ea34efc | |||
| 9c0ca32033 | |||
| 76e49476a6 | |||
| 6d30ede01e | |||
| 02459f5d53 | |||
| 4c2c738bba | |||
| 9f2bff2d16 | |||
| ec8c67e67d | |||
| 41bbbed704 | |||
| a7f9cb7db0 | |||
| 14961d231e | |||
| 881602bd9b | |||
| ba48b71b23 | |||
| c1f2bf4f27 | |||
| 43bd1ba419 | |||
| 807e7e588f | |||
| 9d678b4f8a | |||
| 462c15887e | |||
| 60b1c1208a | |||
| 756aca36ad | |||
| 90c40b76f5 | |||
| 71a409cc0d | |||
| 6beb77e464 | |||
| 5f5ac4449c | |||
| bb0fb71a21 | |||
| 833a1b118e | |||
| 22dbdf0cd2 | |||
| 7e6a4c073f | |||
| 50c994d2ed | |||
| d151b907d1 | |||
| 77aa58083d | |||
| 13aeca9c88 | |||
| 3689b6df1a | |||
| d64613006c | |||
| 1582c13f62 | |||
| 554010b5cb | |||
| 60912ff8ef | |||
| a9c40e76dc | |||
| e9a0c6f8d0 | |||
| bcfea21501 | |||
| 52736881db | |||
| c85ac8e54d | |||
| c4be55e824 | |||
| e62f5833e0 | |||
| d073442cfe | |||
| ba803943d8 | |||
| 6e9eb26e27 | |||
| a4bb4ec6c5 | |||
| 72553623a7 | |||
| 30165c10af | |||
| caf33095d6 | |||
| 0173bc748b | |||
| b9088a8dda | |||
| 01605534f7 | |||
| 082886ab19 | |||
| 9a592df4f0 | |||
| 2334109721 | |||
| bc21fa3a7e | |||
| aa7dd1ecf9 | |||
| 6122817ab6 | |||
| c667bb91c7 | |||
| 9b93b30aed | |||
| 79d9ddd463 | |||
| ca512ca1ad | |||
| 0f05f6e1ee | |||
| 06e656840a | |||
| 48391d2252 | |||
| e5ef62d7e7 | |||
| 1a6334f548 | |||
| 8cf0b3adae | |||
| d0e51df59a | |||
| 50da1b1606 | |||
| df010ef304 | |||
| 41caad4dbf | |||
| 11e3836599 | |||
| 4262e2e2f6 | |||
| 610f7e88ca | |||
| 05a39aa5f5 | |||
| 784ee5ace8 | |||
| 73fe7ebec7 | |||
| 7da2ce362d | |||
| f28e0b529e | |||
| 6e9a588c1a | |||
| f3442c6964 | |||
| 241169140e | |||
| 143036c2a2 | |||
| 043437a0c3 | |||
| 1370192823 | |||
| 07037341c5 | |||
| 5406396c3c | |||
| bd50119152 | |||
| d941d92571 | |||
| 06a96fa74a | |||
| 7129de4373 | |||
| 14d0d5dcbb | |||
| 37958ccb4e | |||
| 7e16920358 | |||
| 5df5918176 | |||
| a10ebf342b | |||
| 0e906b1a3d | |||
| b072a080ae | |||
| eb7305e31c | |||
| 4b23cd94fd | |||
| 04fdc1dc60 | |||
| 27810d473d | |||
| d1160350b2 | |||
| 5d8c5224ed | |||
| e38b8fd419 | |||
| 19a0fb3f38 | |||
| ebe693e591 | |||
| 6fbb6539ef | |||
| 199817bed0 | |||
| 5ce2e21abc | |||
| f2383b5cb0 | |||
| 99c972e880 | |||
| b169b6b438 | |||
| 47d0c0ffa2 | |||
| 3307e7e0fc | |||
| 70d0aabbc1 | |||
| b83e756650 | |||
| b10aa52eca | |||
| 9e33454dc2 | |||
| b056a97c8b | |||
| a088d64d57 | |||
| 7c5183700e | |||
| 00ca4d2afa | |||
| cf234ecf82 | |||
| b48dc0b38a | |||
| 0294febd63 | |||
| 5fcaacc39a | |||
| 30000126d1 | |||
| 00179d563b | |||
| 4a4b0ab7e0 | |||
| b3c7801f73 | |||
| 4716d278ce | |||
| f6f2cd7e17 | |||
| 2084095773 | |||
| aa02f33add | |||
| da9d743f39 | |||
| 5ef48b92fa | |||
| 49cf33f6d7 | |||
| 65d93b2b18 | |||
| a17d36fd89 | |||
| d33967f60c | |||
| cfef1f8325 | |||
| 8270204c7e | |||
| a209b87a41 | |||
| ffb4457427 | |||
| 6c436024f7 | |||
| acbfdd7bbf | |||
| 8c1fb28216 | |||
| bef4a92e99 | |||
| d95f0e6f54 | |||
| 9d1adf9884 | |||
| 31740f70e3 | |||
| c3d62b2a6a | |||
| 64f89f9980 | |||
| 84f6459598 | |||
| 49dcc7e894 | |||
| 361532830c | |||
| ef1a453b9d | |||
| 3fdd89035b | |||
| 1aad2a3a7a | |||
| fa3277e18b | |||
| 3d5a3ad958 | |||
| 722486ca68 | |||
| 96d1861955 | |||
| f9e5a1159d | |||
| 4e994f2b92 | |||
| 1c8685681e | |||
| a65da367a3 | |||
| e61281e25e | |||
| 0801b3c6f8 | |||
| 0ff512f373 | |||
| d47f7afbf6 | |||
| 1f66670cc3 | |||
| 515054f1c6 | |||
| 76d4036883 | |||
| 0d21f2f39d | |||
| a5fa5dc05c | |||
| e3fd26ca4e | |||
| 8139fcfe74 | |||
| 86fe4d1c1b | |||
| 6abeb9e3ca | |||
| d3ce3794b0 | |||
| 89746e7dfe | |||
| 700cd16641 | |||
| b72649e296 | |||
| e9449b9135 | |||
| caff2aa9d2 | |||
| 6eac899167 | |||
| ba4ade1750 | |||
| b131de3bea | |||
| a618668b63 | |||
| 71e9fa178d | |||
| 67f13be3f7 | |||
| af89261992 | |||
| d94a0454ae | |||
| 15af551139 | |||
| 0347a2bd89 | |||
| b26f70eb6a | |||
| bd10b17272 | |||
| 7b3a8d5bcd | |||
| 0e1548db72 | |||
| 2806931ca1 | |||
| 732720c306 | |||
| 58792e53de | |||
| 8c54ebb6d1 | |||
| 50e03d08bf | |||
| b4229d22d5 | |||
| 4533834177 | |||
| 42d3c3eec5 | |||
| 56e4b13e63 | |||
| 26217f53ae | |||
| d79eda40a4 | |||
| f4a17ac698 | |||
| 11e0b085d5 | |||
| 7df87a9c22 | |||
| 6b674fb53e | |||
| e7e68dafb5 | |||
| d5cabb10d6 | |||
| cd425412cc | |||
| 7cafd25036 | |||
| 4b68f8b725 | |||
| e2d816defb | |||
| d80333c819 | |||
| 4d8d40f288 | |||
| 1e13dc542d | |||
| d103cefed2 | |||
| ddd7c7058c | |||
| bbb6919bf1 | |||
| c3ffadf53f | |||
| c41872d5a4 | |||
| b5ca5b4417 | |||
| 6bff864444 | |||
| a0e3978927 | |||
| 735751b0d4 | |||
| bf500948b2 | |||
| 85d172e54a | |||
| d9f088f36e | |||
| 396112bc8b | |||
| 9ba2b28654 | |||
| 89fad5c667 | |||
| 474c496226 | |||
| 8bd497ae09 | |||
| 107cec39f4 | |||
| 6a9b9cd0dd | |||
| f328f3fa9e | |||
| 21a2b5f320 | |||
| 29dd931289 | |||
| bbfb1f4346 | |||
| ee02583cd2 | |||
| 4141a7844f | |||
| 1de86f7ad7 | |||
| 833502ee35 | |||
| 9095da1e10 | |||
| b5eb8e94f4 | |||
| 8377c17838 | |||
| af018180d2 | |||
| 5102fe9797 | |||
| 188e766106 | |||
| 5729123dd1 | |||
| 1935df960b | |||
| c39fd49b1f | |||
| bc6634fb6f | |||
| 09941eb741 | |||
| 2fc0d51377 | |||
| 1e1b69c3b5 | |||
| 82070b4ccb | |||
| 829296c0bb | |||
| c3571e53d9 | |||
| 7a8c9317bc | |||
| 11ca9dd34e | |||
| 3e48b8db92 | |||
| 38377ca776 | |||
| 529ad0e146 | |||
| d14337b9db | |||
| 855ae2fe78 | |||
| e328898971 | |||
| 72a6de18ae | |||
| 52dc25b0ea | |||
| a6180a54bf | |||
| f9971fbc8d | |||
| 0c7df5bd22 | |||
| 96a925c040 | |||
| 20bc1e9caf | |||
| 2ae61ae79f | |||
| 53ab49cdd0 | |||
| e341a37dd3 | |||
| e6ca58b7c8 | |||
| 8a3959b1e1 | |||
| 4ebeada604 | |||
| 6a43b95e5e | |||
| 7ebb39c401 | |||
| 66aff5bf2d | |||
| 15e029c380 | |||
| a17df31eaa | |||
| fa60c83691 | |||
| e4dda5e541 | |||
| c598082335 | |||
| 2e0cc8fa5f | |||
| b3caa7e28d | |||
| 9a30708bea | |||
| dd5d13ce91 | |||
| 30bfc24386 | |||
| 3a86e9ecb7 | |||
| 80fb3066e8 | |||
| 977338d1ba | |||
| d5d889727d | |||
| 93d4f91008 | |||
| c053dc5903 | |||
| da847b6ee8 | |||
| 0fea2e09ae | |||
| 751e3f739a | |||
| 01b3204a49 | |||
| f5808fab83 | |||
| 48e698d080 | |||
| 022687526a | |||
| 3a624070ad | |||
| 2e5a7c3912 | |||
| 78f0633669 | |||
| 8fa54c4ad5 | |||
| 7e07724085 | |||
| 42f0337e7f | |||
| 7cab3d58a8 | |||
| 495f2eb543 | |||
| 0baaa2f847 | |||
| 4adf922b3f | |||
| f3dfbeb2b7 | |||
| 6619aed3b7 | |||
| 422b9a3a86 | |||
| 618d0bdd34 | |||
| aec136edc8 | |||
| 88fa090e23 | |||
| 988fb174fc | |||
| 8961d19fb8 | |||
| 627ebf4614 | |||
| 03099493aa | |||
| f8c3f784c8 | |||
| 42fe861fbc | |||
| a0ca5fcf55 | |||
| 938e5ba19c | |||
| 962d43ba3f | |||
| cd5888636c | |||
| 305a374917 | |||
| 02a74aa448 | |||
| f86cb859a7 | |||
| 4bf7096ee7 | |||
| 4b830ce38b | |||
| 65125b5f1e | |||
| 281c94c6b2 | |||
| 160ffbbcdd | |||
| a6dc10ceec | |||
| 81edbab511 | |||
| 272909d250 | |||
| 91f1552a88 | |||
| 4aa7d08e65 | |||
| 587f500a0c | |||
| 98898054c3 | |||
| 4753766d16 | |||
| 502acd5b20 | |||
| d569bf6b09 | |||
| bfdf9942f0 | |||
| 63d2ed2fec | |||
| 9627fa0500 | |||
| 7938c41fcf | |||
| f3fa86deb4 | |||
| 3cdfcfff2c | |||
| 1412ca8fdd | |||
| 611a945a3b | |||
| 7d3e2f9870 | |||
| f08521a705 | |||
| 3be06f813e | |||
| 2c8187eb6c | |||
| 82c107f7ad | |||
| 3f5ec9e7be | |||
| ea606857c2 | |||
| a12c733b01 | |||
| f9063a298b | |||
| edc100e67e | |||
| e381e9e37f | |||
| 1abcad05c1 | |||
| ffcfa9435f | |||
| 52d5eb444b | |||
| b5cc7b8e49 | |||
| 180927bcac | |||
| 078365c467 | |||
| 85938113b7 | |||
| 0f38f35aba | |||
| 0a7826d286 | |||
| e02eae8fb3 | |||
| fe4870199e | |||
| 3d506cfa01 | |||
| 393d348306 | |||
| 3ce936edac | |||
| 3b634fe64e | |||
| 12a058d91b | |||
| 95f0dd8979 | |||
| 02dfd775a9 | |||
| 82d6d203f0 | |||
| d180f7063c | |||
| 70f5d476f2 | |||
| 445f3b0adb | |||
| 42836b3e0e | |||
| 7c2318a096 | |||
| 1b4bf74107 |
@@ -0,0 +1,37 @@
|
||||
name: 'Install wasm-opt'
|
||||
description: 'Installs wasm-opt from binaryen'
|
||||
inputs:
|
||||
version:
|
||||
description: 'Version of wasm-opt to install'
|
||||
default: '116'
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- name: Check platform compatibility
|
||||
run: |
|
||||
if [[ "$(uname)" != "Linux" ]]; then
|
||||
echo "Error: This action is only compatible with Linux."
|
||||
exit 1
|
||||
fi
|
||||
shell: bash
|
||||
|
||||
- name: Download wasm-opt
|
||||
run: |
|
||||
set -e
|
||||
SOURCE="https://github.com/WebAssembly/binaryen/releases/download/version_${{ inputs.version }}/binaryen-version_${{ inputs.version }}-x86_64-linux.tar.gz"
|
||||
TEMP_ARCHIVE="$RUNNER_TEMP/binaryen-version_${{ inputs.version }}-x86_64-linux.tar.gz"
|
||||
curl -L -o "$TEMP_ARCHIVE" "$SOURCE"
|
||||
tar -xvzf $TEMP_ARCHIVE -C $RUNNER_TEMP
|
||||
echo "$RUNNER_TEMP/binaryen-version_${{ inputs.version }}/bin" >> $GITHUB_PATH
|
||||
shell: bash
|
||||
id: install-binary
|
||||
|
||||
- name: Verify installation
|
||||
run: |
|
||||
if ! command -v wasm-opt &> /dev/null; then
|
||||
echo "Error: wasm-opt binary was not installed successfully."
|
||||
exit 1
|
||||
fi
|
||||
shell: bash
|
||||
id: verify-installation
|
||||
|
||||
+5
-5
@@ -1,16 +1,16 @@
|
||||
name: Build and upload binaries to artifact storage
|
||||
name: build-upload-binaries
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
inputs:
|
||||
add_tokio_unstable:
|
||||
description: 'True to add RUSTFLAGS="--cfg tokio_unstable"'
|
||||
required: true
|
||||
default: false
|
||||
type: boolean
|
||||
|
||||
type: boolean
|
||||
|
||||
env:
|
||||
NETWORK: mainnet
|
||||
NETWORK: mainnet
|
||||
|
||||
jobs:
|
||||
publish-nym:
|
||||
@@ -1,15 +1,14 @@
|
||||
name: CD docs
|
||||
name: cd-docs
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches: master
|
||||
paths:
|
||||
- 'documentation/docs/**'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: custom-runner-linux
|
||||
runs-on: custom-linux
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Install rsync
|
||||
@@ -26,7 +25,7 @@ jobs:
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: build
|
||||
args: --workspace --release --all
|
||||
args: --workspace --release
|
||||
- name: Install mdbook
|
||||
run: (test -x $HOME/.cargo/bin/mdbook || cargo install --vers "^0.4.33" mdbook)
|
||||
- name: Install mdbook plugins
|
||||
@@ -39,30 +38,6 @@ jobs:
|
||||
run: cd documentation && ./build_all_to_dist.sh
|
||||
continue-on-error: false
|
||||
|
||||
- name: Deploy branch master to dev
|
||||
continue-on-error: true
|
||||
uses: easingthemes/ssh-deploy@main
|
||||
env:
|
||||
SSH_PRIVATE_KEY: ${{ secrets.CD_WWW_SSH_PRIVATE_KEY }}
|
||||
ARGS: "-rltgoDzvO --delete"
|
||||
SOURCE: "dist/docs/"
|
||||
REMOTE_HOST: ${{ secrets.CD_WWW_REMOTE_HOST_DEV }}
|
||||
REMOTE_USER: ${{ secrets.CD_WWW_REMOTE_USER }}
|
||||
TARGET: ${{ secrets.CD_WWW_REMOTE_TARGET }}/
|
||||
EXCLUDE: "/node_modules/"
|
||||
|
||||
- name: Deploy branch master to prod
|
||||
if: github.ref == 'refs/heads/master'
|
||||
uses: easingthemes/ssh-deploy@main
|
||||
env:
|
||||
SSH_PRIVATE_KEY: ${{ secrets.CD_WWW_SSH_PRIVATE_KEY }}
|
||||
ARGS: "-rltgoDzvO --delete"
|
||||
SOURCE: "dist/docs/"
|
||||
REMOTE_HOST: ${{ secrets.CD_WWW_REMOTE_HOST_PROD }}
|
||||
REMOTE_USER: ${{ secrets.CD_WWW_REMOTE_USER }}
|
||||
TARGET: ${{ secrets.CD_WWW_REMOTE_TARGET }}/
|
||||
EXCLUDE: "/node_modules/"
|
||||
|
||||
- name: Post process
|
||||
run: cd documentation && ./post_process.sh
|
||||
continue-on-error: false
|
||||
|
||||
+7
-7
@@ -1,4 +1,4 @@
|
||||
name: Run config checks on all binaries
|
||||
name: ci-binary-config-checker
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
@@ -31,8 +31,8 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
platform: [custom-runner-linux]
|
||||
|
||||
platform: [custom-linux]
|
||||
|
||||
runs-on: ${{ matrix.platform }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
@@ -45,12 +45,12 @@ jobs:
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
|
||||
|
||||
- name: Branch name
|
||||
run: echo running on branch ${GITHUB_REF##*/}
|
||||
|
||||
|
||||
- name: Run tests against binaries
|
||||
run: ./build_and_run.sh ${{ github.head_ref || github.ref_name }}
|
||||
working-directory: tests/
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
name: ci-build-ts
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
paths:
|
||||
- 'ts-packages/**'
|
||||
- "ts-packages/**"
|
||||
- "sdk/typescript/**"
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: custom-runner-linux
|
||||
runs-on: ubuntu-20.04-16-core
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Install rsync
|
||||
@@ -20,7 +21,7 @@ jobs:
|
||||
- name: Setup yarn
|
||||
run: npm install -g yarn
|
||||
- name: Build
|
||||
run: yarn && yarn build && yarn build:ci
|
||||
run: yarn && yarn build && yarn build:ci:storybook
|
||||
- name: Deploy branch to CI www (storybook)
|
||||
continue-on-error: true
|
||||
uses: easingthemes/ssh-deploy@main
|
||||
|
||||
@@ -2,20 +2,6 @@ name: ci-build-upload-binaries
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
paths:
|
||||
- 'clients/**'
|
||||
- 'common/**'
|
||||
- 'explorer-api/**'
|
||||
- 'gateway/**'
|
||||
- 'integrations/**'
|
||||
- 'mixnode/**'
|
||||
- 'sdk/rust/nym-sdk/**'
|
||||
- 'service-providers/**'
|
||||
- 'nym-api/**'
|
||||
- 'nym-outfox/**'
|
||||
- 'tools/nym-cli/**'
|
||||
- 'tools/ts-rs-cli/**'
|
||||
pull_request:
|
||||
paths:
|
||||
- 'clients/**'
|
||||
@@ -31,9 +17,6 @@ on:
|
||||
- 'tools/nym-cli/**'
|
||||
- 'tools/ts-rs-cli/**'
|
||||
|
||||
env:
|
||||
NETWORK: mainnet
|
||||
|
||||
jobs:
|
||||
publish-nym:
|
||||
strategy:
|
||||
@@ -44,8 +27,6 @@ jobs:
|
||||
runs-on: ${{ matrix.platform }}
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
# a push event from the origin repo, or a PR from external repo
|
||||
if: ${{ github.event_name == 'push' || github.event.pull_request.head.repo.full_name != 'nymtech/nym' }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
@@ -59,8 +40,7 @@ jobs:
|
||||
echo $OUTPUT_DIR
|
||||
|
||||
- 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
|
||||
continue-on-error: true
|
||||
run: sudo apt update && sudo apt install libudev-dev
|
||||
|
||||
- name: Install Rust stable
|
||||
uses: actions-rs/toolchain@v1
|
||||
|
||||
@@ -48,9 +48,6 @@ jobs:
|
||||
runs-on: ${{ matrix.os }}
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
# Enable sccache via environment variable
|
||||
# env:
|
||||
# RUSTC_WRAPPER: /home/ubuntu/.cargo/bin/sccache
|
||||
steps:
|
||||
- name: Install Dependencies (Linux)
|
||||
run: sudo apt-get update && sudo apt-get -y install libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev libudev-dev squashfs-tools protobuf-compiler
|
||||
@@ -78,29 +75,28 @@ jobs:
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: build
|
||||
# Enable wireguard by default on linux only
|
||||
args: --workspace --features wireguard
|
||||
args: --workspace
|
||||
|
||||
- name: Build all examples
|
||||
if: matrix.os == 'custom-linux'
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: build
|
||||
args: --workspace --examples --features wireguard
|
||||
args: --workspace --examples
|
||||
|
||||
- name: Run all tests
|
||||
if: matrix.os == 'custom-linux'
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: test
|
||||
args: --workspace --features wireguard
|
||||
args: --workspace
|
||||
|
||||
- name: Run expensive tests
|
||||
if: (github.ref == 'refs/heads/develop' || github.event.pull_request.base.ref == 'develop' || github.event.pull_request.base.ref == 'master') && matrix.os == 'custom-linux'
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: test
|
||||
args: --workspace --features wireguard -- --ignored
|
||||
args: --workspace -- --ignored
|
||||
|
||||
- name: Annotate with clippy checks
|
||||
if: matrix.os == 'custom-linux'
|
||||
@@ -108,10 +104,10 @@ jobs:
|
||||
continue-on-error: true
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
args: --workspace --features wireguard
|
||||
args: --workspace
|
||||
|
||||
- name: Clippy
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: clippy
|
||||
args: --workspace --all-targets --features wireguard -- -D warnings
|
||||
args: --workspace --all-targets -- -D warnings
|
||||
|
||||
@@ -2,10 +2,6 @@ name: ci-contracts-schema
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
paths:
|
||||
- 'contracts/**'
|
||||
- 'common/**'
|
||||
pull_request:
|
||||
paths:
|
||||
- 'contracts/**'
|
||||
@@ -14,7 +10,7 @@ on:
|
||||
jobs:
|
||||
check-schema:
|
||||
name: Generate and check schema
|
||||
runs-on: custom-runner-linux
|
||||
runs-on: custom-linux
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
steps:
|
||||
|
||||
@@ -2,10 +2,6 @@ name: ci-contracts-upload-binaries
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
paths:
|
||||
- 'common/**'
|
||||
- 'contracts/**'
|
||||
pull_request:
|
||||
paths:
|
||||
- 'common/**'
|
||||
@@ -24,8 +20,6 @@ jobs:
|
||||
runs-on: ${{ matrix.platform }}
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
# a push event from the origin repo, or a PR from external repo
|
||||
if: ${{ github.event_name == 'push' || github.event.pull_request.head.repo.full_name != 'nymtech/nym' }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
@@ -38,19 +32,17 @@ jobs:
|
||||
mkdir -p $OUTPUT_DIR
|
||||
echo $OUTPUT_DIR
|
||||
|
||||
- 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
|
||||
continue-on-error: true
|
||||
|
||||
- name: Install Rust stable
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: 1.69.0
|
||||
toolchain: stable
|
||||
target: wasm32-unknown-unknown
|
||||
override: true
|
||||
|
||||
- name: Install wasm-opt
|
||||
run: cargo install --version 0.112.0 wasm-opt
|
||||
uses: ./.github/actions/install-wasm-opt
|
||||
with:
|
||||
version: '114'
|
||||
|
||||
- name: Build release contracts
|
||||
run: make contracts
|
||||
|
||||
@@ -9,7 +9,7 @@ on:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: custom-runner-linux
|
||||
runs-on: custom-linux
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Install rsync
|
||||
@@ -26,17 +26,22 @@ jobs:
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: build
|
||||
args: --workspace --release --all
|
||||
args: --workspace --release
|
||||
- name: Install mdbook
|
||||
run: (test -x $HOME/.cargo/bin/mdbook || cargo install --vers "^0.4.33" mdbook)
|
||||
run: (test -x $HOME/.cargo/bin/mdbook || cargo install --vers "^0.4.35" mdbook)
|
||||
- name: Install mdbook plugins
|
||||
run: |
|
||||
cargo install --vers "=0.2.2" mdbook-variables && cargo install \
|
||||
--vers "^1.8.0" mdbook-admonish && cargo install --vers \
|
||||
--vers "^1.8.0" mdbook-admonish --force && cargo install --vers \
|
||||
"^0.1.2" mdbook-last-changed && cargo install --vers "^0.1.2" mdbook-theme \
|
||||
&& cargo install --vers "^0.7.7" mdbook-linkcheck
|
||||
&& cargo install --vers "^0.7.7" mdbook-linkcheck \
|
||||
# && cd documentation \
|
||||
# && mdbook-admonish install dev-portal \
|
||||
# && mdbook-admonish install docs \
|
||||
# && mdbook-admonish install operators
|
||||
|
||||
- name: Build all projects in documentation/ & move to ~/dist/docs/
|
||||
run: cd documentation && ./build_all_to_dist.sh
|
||||
run: cd documentation && ./build_all_to_dist.sh
|
||||
continue-on-error: false
|
||||
- name: Deploy branch to CI www
|
||||
continue-on-error: true
|
||||
|
||||
@@ -1,15 +1,6 @@
|
||||
name: ci-lint-typescript
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- "ts-packages/**"
|
||||
- "sdk/typescript/**"
|
||||
- "nym-connect/desktop/src/**"
|
||||
- "nym-connect/desktop/package.json"
|
||||
- "nym-wallet/src/**"
|
||||
- "nym-wallet/package.json"
|
||||
- "explorer/**"
|
||||
pull_request:
|
||||
paths:
|
||||
- "ts-packages/**"
|
||||
@@ -22,7 +13,7 @@ on:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: custom-runner-linux
|
||||
runs-on: ubuntu-20.04-16-core
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: rlespinasse/github-slug-action@v3.x
|
||||
@@ -37,9 +28,15 @@ jobs:
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
|
||||
- name: Install wasm-pack
|
||||
run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
|
||||
|
||||
- name: Install wasm-opt
|
||||
uses: ./.github/actions/install-wasm-opt
|
||||
with:
|
||||
version: '116'
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
@@ -49,7 +46,7 @@ jobs:
|
||||
run: yarn
|
||||
|
||||
- name: Build packages
|
||||
run: yarn build:ci:sdk
|
||||
run: yarn build:ci
|
||||
|
||||
- name: Lint
|
||||
run: yarn lint
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
name: CI for Nym API Tests
|
||||
name: ci-nym-api-tests
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
@@ -16,10 +16,10 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
|
||||
- name: Install npm
|
||||
run: npm install
|
||||
|
||||
|
||||
- name: Node v18
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
@@ -1,16 +1,6 @@
|
||||
name: ci-nym-connect-desktop-rust
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- "nym-connect/desktop/src-tauri/**"
|
||||
- "nym-connect/desktop/src-tauri/Cargo.toml"
|
||||
- "clients/client-core/**"
|
||||
- "clients/socks5/**"
|
||||
- "common/**"
|
||||
- "gateway/gateway-requests/**"
|
||||
- "contracts/vesting/**"
|
||||
- "nym-api/nym-api-requests/**"
|
||||
pull_request:
|
||||
paths:
|
||||
- "nym-connect/desktop/src-tauri/**"
|
||||
@@ -27,8 +17,6 @@ jobs:
|
||||
runs-on: [self-hosted, custom-linux]
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
# env:
|
||||
# RUSTC_WRAPPER: /home/ubuntu/.cargo/bin/sccache
|
||||
steps:
|
||||
- name: Install Dependencies (Linux)
|
||||
run: sudo apt-get update && sudo apt-get -y install libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev squashfs-tools libayatana-appindicator3-dev
|
||||
@@ -45,6 +33,12 @@ jobs:
|
||||
override: true
|
||||
components: rustfmt, clippy
|
||||
|
||||
- name: Check formatting
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: fmt
|
||||
args: --manifest-path nym-connect/desktop/Cargo.toml --all -- --check
|
||||
|
||||
- name: Build all binaries
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
@@ -57,12 +51,6 @@ jobs:
|
||||
command: test
|
||||
args: --manifest-path nym-connect/desktop/Cargo.toml --workspace
|
||||
|
||||
- name: Check formatting
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: fmt
|
||||
args: --manifest-path nym-connect/desktop/Cargo.toml --all -- --check
|
||||
|
||||
- uses: actions-rs/clippy-check@v1
|
||||
name: Clippy checks
|
||||
continue-on-error: true
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
name: ci-nym-connect-desktop
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
paths:
|
||||
- 'nym-connect/desktop/**'
|
||||
|
||||
@@ -11,7 +11,7 @@ defaults:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: custom-runner-linux
|
||||
runs-on: custom-linux
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Install rsync
|
||||
|
||||
@@ -12,7 +12,7 @@ defaults:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: custom-runner-linux
|
||||
runs-on: custom-linux
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Install rsync
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
name: ci-nym-vpn-ui-js
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
paths:
|
||||
- 'nym-vpn/ui/src/**'
|
||||
- 'nym-vpn/ui/package.json'
|
||||
- 'nym-vpn/ui/index.html'
|
||||
|
||||
jobs:
|
||||
check:
|
||||
runs-on: custom-linux
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
- name: Install Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18
|
||||
- name: Install Yarn
|
||||
run: npm install -g yarn
|
||||
- name: Install dependencies
|
||||
working-directory: nym-vpn/ui
|
||||
run: yarn
|
||||
- name: Type-check
|
||||
working-directory: nym-vpn/ui
|
||||
run: yarn typecheck
|
||||
- name: Check lint
|
||||
working-directory: nym-vpn/ui
|
||||
run: yarn lint
|
||||
- name: Check formatting
|
||||
working-directory: nym-vpn/ui
|
||||
run: yarn fmt:check
|
||||
# - name: Run tests
|
||||
# working-directory: nym-vpn/ui
|
||||
# run: yarn test
|
||||
- name: Check build
|
||||
working-directory: nym-vpn/ui
|
||||
run: yarn build
|
||||
@@ -0,0 +1,63 @@
|
||||
name: ci-nym-vpn-ui-rust
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
paths:
|
||||
- 'nym-vpn/ui/src-tauri/**'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: custom-linux
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
CARGOTOML_PATH: ./nym-vpn/ui/src-tauri/Cargo.toml
|
||||
steps:
|
||||
- name: Install Dependencies (Linux)
|
||||
run: sudo apt-get update && sudo apt-get -y install libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev squashfs-tools libayatana-appindicator3-dev
|
||||
continue-on-error: true
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install rust toolchain
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
profile: minimal
|
||||
toolchain: stable
|
||||
override: true
|
||||
components: rustfmt, clippy
|
||||
|
||||
- name: Prepare build
|
||||
run: mkdir nym-vpn/ui/dist
|
||||
|
||||
- name: Build
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: build
|
||||
args: --manifest-path ${{ env.CARGOTOML_PATH }} --lib --features custom-protocol
|
||||
|
||||
# - name: Run all tests
|
||||
# uses: actions-rs/cargo@v1
|
||||
# with:
|
||||
# command: test
|
||||
# args: --manifest-path ${{ env.CARGOTOML_PATH }}
|
||||
|
||||
- name: Check formatting
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: fmt
|
||||
args: --manifest-path ${{ env.CARGOTOML_PATH }} --all -- --check
|
||||
|
||||
- name: Annotate with clippy checks
|
||||
uses: actions-rs/clippy-check@v1
|
||||
continue-on-error: true
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
args: --manifest-path ${{ env.CARGOTOML_PATH }} --all-features
|
||||
|
||||
- name: Clippy
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: clippy
|
||||
args: --manifest-path ${{ env.CARGOTOML_PATH }} --all-features --all-targets -- -D warnings
|
||||
@@ -19,8 +19,6 @@ jobs:
|
||||
runs-on: [ self-hosted, custom-linux ]
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
# env:
|
||||
# RUSTC_WRAPPER: /home/ubuntu/.cargo/bin/sccache
|
||||
steps:
|
||||
- name: Install Dependencies (Linux)
|
||||
run: sudo apt-get update && sudo apt-get -y install libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev squashfs-tools
|
||||
|
||||
@@ -1,35 +1,44 @@
|
||||
name: Nym Wallet Storybook
|
||||
name: ci-nym-wallet-storybook
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
paths:
|
||||
- 'nym-wallet/**'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: custom-runner-linux
|
||||
runs-on: custom-linux
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Install rsync
|
||||
run: sudo apt-get install rsync
|
||||
continue-on-error: true
|
||||
|
||||
- uses: rlespinasse/github-slug-action@v3.x
|
||||
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18
|
||||
|
||||
- name: Setup yarn
|
||||
run: npm install -g yarn
|
||||
|
||||
- name: Install Rust stable
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
|
||||
- name: Install wasm-pack
|
||||
run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
|
||||
run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
|
||||
|
||||
- name: Build dependencies
|
||||
run: yarn && yarn build
|
||||
|
||||
- name: Build storybook
|
||||
run: yarn storybook:build
|
||||
working-directory: ./nym-wallet
|
||||
|
||||
- name: Deploy branch to CI www (storybook)
|
||||
continue-on-error: true
|
||||
uses: easingthemes/ssh-deploy@main
|
||||
@@ -41,9 +50,11 @@ jobs:
|
||||
REMOTE_USER: ${{ secrets.CI_WWW_REMOTE_USER }}
|
||||
TARGET: ${{ secrets.CI_WWW_REMOTE_TARGET }}/wallet-${{ env.GITHUB_REF_SLUG }}
|
||||
EXCLUDE: "/dist/, /node_modules/"
|
||||
|
||||
- name: Matrix - Node Install
|
||||
run: npm install
|
||||
working-directory: .github/workflows/support-files
|
||||
|
||||
- name: Matrix - Send Notification
|
||||
env:
|
||||
NYM_NOTIFICATION_KIND: nym-wallet
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
name: ci-sdk-docs-typescript
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- "sdk/typescript/**"
|
||||
- "wasm/**"
|
||||
pull_request:
|
||||
paths:
|
||||
- "sdk/typescript/**"
|
||||
@@ -12,7 +8,7 @@ on:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: custom-runner-linux
|
||||
runs-on: custom-linux
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Install rsync
|
||||
@@ -34,6 +30,14 @@ jobs:
|
||||
with:
|
||||
go-version: '1.20'
|
||||
|
||||
- name: Install wasm-pack
|
||||
run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
|
||||
|
||||
- name: Install wasm-opt
|
||||
uses: ./.github/actions/install-wasm-opt
|
||||
with:
|
||||
version: '116'
|
||||
|
||||
- name: Build branch WASM packages
|
||||
run: make sdk-wasm-build
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ on:
|
||||
|
||||
jobs:
|
||||
wasm:
|
||||
runs-on: [custom-runner-linux]
|
||||
runs-on: [custom-linux]
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
steps:
|
||||
@@ -18,7 +18,7 @@ jobs:
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18
|
||||
|
||||
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
profile: minimal
|
||||
@@ -32,12 +32,13 @@ jobs:
|
||||
with:
|
||||
go-version: '1.20'
|
||||
|
||||
|
||||
- name: Install wasm-pack
|
||||
run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
|
||||
|
||||
- name: Install wasm-opt
|
||||
run: cargo install wasm-opt
|
||||
uses: ./.github/actions/install-wasm-opt
|
||||
with:
|
||||
version: '116'
|
||||
|
||||
- name: Install wasm-bindgen-cli
|
||||
run: cargo install wasm-bindgen-cli
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
name: Greetings
|
||||
name: greetings
|
||||
|
||||
on: [pull_request_target, issues]
|
||||
|
||||
|
||||
@@ -4,26 +4,26 @@ on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: '14 1 * * *'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
rust: [stable, beta]
|
||||
os: [custom-linux, windows10, custom-runner-mac-m1]
|
||||
os: [ubuntu-20.04, windows-latest, macos-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
continue-on-error: true
|
||||
steps:
|
||||
- name: Install Dependencies (Linux)
|
||||
run: sudo apt-get update && sudo apt-get install -y build-essential curl wget libssl-dev libudev-dev squashfs-tools protobuf-compiler
|
||||
continue-on-error: true
|
||||
if: matrix.os == 'custom-linux'
|
||||
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Install Dependencies (Linux)
|
||||
run: sudo apt-get update && sudo apt-get install -y build-essential curl wget libssl-dev libudev-dev squashfs-tools protobuf-compiler
|
||||
if: matrix.os == 'ubuntu-20.04'
|
||||
|
||||
- name: Install Rust toolchain
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
@@ -32,6 +32,12 @@ jobs:
|
||||
override: true
|
||||
components: rustfmt, clippy
|
||||
|
||||
- name: Install Protoc
|
||||
uses: arduino/setup-protoc@v2
|
||||
if: matrix.os == 'macos-latest' || matrix.os == 'windows-latest'
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Check formatting
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
@@ -42,13 +48,27 @@ jobs:
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: build
|
||||
args: --workspace
|
||||
args: --release --workspace
|
||||
|
||||
- name: Build examples
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: build
|
||||
args: --workspace --examples
|
||||
args: --release --workspace --examples
|
||||
|
||||
# To avoid running out of disk space, skip generating debug symbols
|
||||
- name: Set debug to false (unix)
|
||||
if: matrix.os == 'ubuntu-20.04' || matrix.os == 'macos-latest'
|
||||
run: |
|
||||
sed -i.bak 's/\[profile.dev\]/\[profile.dev\]\ndebug = false/' Cargo.toml
|
||||
git diff
|
||||
|
||||
- name: Set debug to false (win)
|
||||
if: matrix.os == 'windows-latest'
|
||||
shell: pwsh
|
||||
run: |
|
||||
(Get-Content Cargo.toml) -replace '\[profile.dev\]', "`$&`ndebug = false" | Set-Content Cargo.toml
|
||||
git diff
|
||||
|
||||
- name: Run unit tests
|
||||
uses: actions-rs/cargo@v1
|
||||
@@ -62,6 +82,11 @@ jobs:
|
||||
command: test
|
||||
args: --workspace -- --ignored
|
||||
|
||||
- name: Clean
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: clean
|
||||
|
||||
- name: Clippy
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
@@ -70,7 +95,7 @@ jobs:
|
||||
|
||||
notification:
|
||||
needs: build
|
||||
runs-on: custom-runner-linux
|
||||
runs-on: custom-linux
|
||||
steps:
|
||||
- name: Collect jobs status
|
||||
uses: technote-space/workflow-conclusion-action@v2
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
name: nightly-nym-connect-desktop-build
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: '14 1 * * *'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-20.04, macos-latest, windows-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
MANIFEST_PATH: --manifest-path nym-connect/desktop/Cargo.toml
|
||||
continue-on-error: true
|
||||
steps:
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Install Dependencies (Linux)
|
||||
run: sudo apt-get update && sudo apt-get install -y libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev squashfs-tools
|
||||
if: matrix.os == 'ubuntu-20.04'
|
||||
|
||||
- name: Install rust toolchain
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
profile: minimal
|
||||
toolchain: stable
|
||||
override: true
|
||||
components: rustfmt, clippy
|
||||
|
||||
- name: Check formatting
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: fmt
|
||||
args: ${{ env.MANIFEST_PATH }} --all -- --check
|
||||
|
||||
- name: Build
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: build
|
||||
args: ${{ env.MANIFEST_PATH }} --release --workspace
|
||||
|
||||
- name: Unit tests
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: test
|
||||
args: ${{ env.MANIFEST_PATH }} --workspace
|
||||
|
||||
- name: Clippy
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: clippy
|
||||
args: ${{ env.MANIFEST_PATH }} --workspace --all-targets -- -D warnings
|
||||
|
||||
notification:
|
||||
needs: build
|
||||
runs-on: custom-linux
|
||||
steps:
|
||||
- name: Collect jobs status
|
||||
uses: technote-space/workflow-conclusion-action@v2
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v3
|
||||
- name: install npm
|
||||
uses: actions/setup-node@v3
|
||||
if: env.WORKFLOW_CONCLUSION == 'failure'
|
||||
with:
|
||||
node-version: 18
|
||||
- name: Matrix - Node Install
|
||||
if: env.WORKFLOW_CONCLUSION == 'failure'
|
||||
run: npm install
|
||||
working-directory: .github/workflows/support-files
|
||||
- name: Matrix - Send Notification
|
||||
if: env.WORKFLOW_CONCLUSION == 'failure'
|
||||
env:
|
||||
NYM_NOTIFICATION_KIND: nightly
|
||||
NYM_PROJECT_NAME: "nym-connect-desktop-nightly-build"
|
||||
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
|
||||
GIT_COMMIT_MESSAGE: "${{ github.event.head_commit.message }}"
|
||||
GIT_BRANCH: "${GITHUB_REF##*/}"
|
||||
IS_SUCCESS: "${{ env.WORKFLOW_CONCLUSION == 'success' }}"
|
||||
MATRIX_SERVER: "${{ secrets.MATRIX_SERVER }}"
|
||||
MATRIX_ROOM: "${{ secrets.MATRIX_ROOM_NIGHTLY }}"
|
||||
MATRIX_USER_ID: "${{ secrets.MATRIX_USER_ID }}"
|
||||
MATRIX_TOKEN: "${{ secrets.MATRIX_TOKEN }}"
|
||||
MATRIX_DEVICE_ID: "${{ secrets.MATRIX_DEVICE_ID }}"
|
||||
uses: docker://keybaseio/client:stable-node
|
||||
with:
|
||||
args: .github/workflows/support-files/notifications/entry_point.sh
|
||||
@@ -5,27 +5,24 @@ on:
|
||||
schedule:
|
||||
- cron: '14 1 * * *'
|
||||
|
||||
defaults:
|
||||
run:
|
||||
working-directory: nym-wallet
|
||||
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [custom-ubuntu-20.04, macos-latest, windows10]
|
||||
os: [ubuntu-20.04, macos-latest, windows-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
MANIFEST_PATH: --manifest-path nym-wallet/Cargo.toml
|
||||
continue-on-error: true
|
||||
steps:
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Install Dependencies (Linux)
|
||||
run: sudo apt-get update && sudo apt-get install -y libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev libudev-dev squashfs-tools protobuf-compiler
|
||||
if: matrix.os == 'custom-linux'
|
||||
run: sudo apt-get update && sudo apt-get install -y libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev squashfs-tools
|
||||
if: matrix.os == 'ubuntu-20.04'
|
||||
|
||||
- name: Install rust toolchain
|
||||
uses: actions-rs/toolchain@v1
|
||||
@@ -39,36 +36,29 @@ jobs:
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: fmt
|
||||
args: --all -- --check
|
||||
args: ${{ env.MANIFEST_PATH }} --all -- --check
|
||||
|
||||
- name: Build
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: build
|
||||
args: --workspace
|
||||
args: ${{ env.MANIFEST_PATH }} --release --workspace
|
||||
|
||||
- name: Unit tests
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: test
|
||||
args: --workspace
|
||||
|
||||
- name: Annotate with clippy warnings
|
||||
uses: actions-rs/clippy-check@v1
|
||||
continue-on-error: true
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
args: --workspace
|
||||
args: ${{ env.MANIFEST_PATH }} --workspace
|
||||
|
||||
- name: Clippy
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: clippy
|
||||
args: --workspace --all-targets -- -D warnings
|
||||
args: ${{ env.MANIFEST_PATH }} --workspace --all-targets -- -D warnings
|
||||
|
||||
notification:
|
||||
needs: build
|
||||
runs-on: custom-runner-linux
|
||||
runs-on: custom-linux
|
||||
steps:
|
||||
- name: Collect jobs status
|
||||
uses: technote-space/workflow-conclusion-action@v2
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
name: Daily security audit
|
||||
name: nightly-security-audit
|
||||
|
||||
on:
|
||||
schedule:
|
||||
@@ -26,7 +26,7 @@ jobs:
|
||||
path: .github/workflows/support-files/notifications/deny.message
|
||||
notification:
|
||||
needs: cargo-deny
|
||||
runs-on: custom-runner-linux
|
||||
runs-on: custom-linux
|
||||
steps:
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v2
|
||||
|
||||
@@ -14,7 +14,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
platform: [macos-latest]
|
||||
platform: [macos-12-large]
|
||||
runs-on: ${{ matrix.platform }}
|
||||
|
||||
outputs:
|
||||
|
||||
@@ -14,13 +14,13 @@ jobs:
|
||||
- name: Install Rust stable
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: 1.69.0
|
||||
toolchain: stable
|
||||
target: wasm32-unknown-unknown
|
||||
override: true
|
||||
components: rustfmt, clippy
|
||||
|
||||
- name: Install wasm-opt
|
||||
run: cargo install --version 0.112.0 wasm-opt
|
||||
run: cargo install --version 0.114.0 wasm-opt
|
||||
|
||||
- name: Build release contracts
|
||||
run: make contracts
|
||||
|
||||
@@ -14,7 +14,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
platform: [macos-latest]
|
||||
platform: [macos-12-large]
|
||||
runs-on: ${{ matrix.platform }}
|
||||
|
||||
outputs:
|
||||
@@ -39,6 +39,7 @@ jobs:
|
||||
env:
|
||||
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
|
||||
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
|
||||
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
||||
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
|
||||
run: |
|
||||
# create variables
|
||||
@@ -73,6 +74,7 @@ jobs:
|
||||
ENABLE_CODE_SIGNING: ${{ secrets.APPLE_CERTIFICATE }}
|
||||
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
|
||||
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
|
||||
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
||||
APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_IDENTITY_ID }}
|
||||
APPLE_ID: ${{ secrets.APPLE_ID }}
|
||||
APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
name: Nyms5 Android
|
||||
name: publish-nyms5-android-apk
|
||||
# unsigned APKs only, supported archs:
|
||||
# - arm64-v8a (arm64)
|
||||
# - x86_64
|
||||
@@ -94,7 +94,7 @@ jobs:
|
||||
gh-release:
|
||||
name: Publish APK (GH release)
|
||||
needs: build
|
||||
runs-on: custom-runner-linux
|
||||
runs-on: custom-linux
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
@@ -4,7 +4,7 @@ on:
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
runs-on: [custom-ubuntu-20.04]
|
||||
runs-on: ubuntu-20.04-16-core
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
@@ -12,7 +12,7 @@ jobs:
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
registry-url: "https://registry.npmjs.org"
|
||||
|
||||
- name: Setup yarn
|
||||
run: npm install -g yarn
|
||||
@@ -25,6 +25,19 @@ jobs:
|
||||
- name: Install wasm-pack
|
||||
run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
|
||||
|
||||
- name: Install wasm-opt
|
||||
run: cargo install wasm-opt
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: "1.20"
|
||||
|
||||
- name: Install TinyGo
|
||||
uses: acifani/setup-tinygo@v1
|
||||
with:
|
||||
tinygo-version: "0.27.0"
|
||||
|
||||
- name: Install dependencies
|
||||
run: yarn
|
||||
|
||||
|
||||
+36
-3
@@ -3,9 +3,42 @@
|
||||
Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [Unreleased]
|
||||
- add client registry to Gateway ([#3955])
|
||||
- add HTTP API to Gateway ([#3955])
|
||||
- add `/client/<pub-key>`, `clients` and `register` routes to the gateway ([#3955])
|
||||
|
||||
## [2023.4-galaxy] (2023-11-07)
|
||||
|
||||
- DRY up client cli ([#4077])
|
||||
- [mixnode] replace rocket with axum ([#4071])
|
||||
- incorporate the nym node HTTP api into the mixnode ([#4070])
|
||||
- replaced '--disable-sign-ext' with '--signext-lowering' when running wasm-opt ([#3896])
|
||||
|
||||
[#4077]: https://github.com/nymtech/nym/pull/4077
|
||||
[#4071]: https://github.com/nymtech/nym/pull/4071
|
||||
[#4070]: https://github.com/nymtech/nym/issues/4070
|
||||
[#3896]: https://github.com/nymtech/nym/pull/3896
|
||||
|
||||
## [2023.3-kinder] (2023-10-31)
|
||||
|
||||
- suppress error output ([#4056])
|
||||
- Update frontend type for current vesting period ([#4042])
|
||||
- re-exported additional types for tx queries ([#4036])
|
||||
- fixed fmt::Display impl for GatewayNetworkRequesterDetails ([#4033])
|
||||
- Add exit node policy from TorNull and Tor Exit Node Policy ([#4024])
|
||||
- basic self-described api for gateways to dynamically announce its details + nym-api aggregation ([#4017])
|
||||
- use saturating sub in case outfox is not enabled ([#3986])
|
||||
- Fix sorting for mixnodes and gateways ([#3985])
|
||||
- Gateway client registry and api routes ([#3955])
|
||||
- Feature/configurable socks5 bind address ([#3992])
|
||||
|
||||
[#4056]: https://github.com/nymtech/nym/pull/4056
|
||||
[#4042]: https://github.com/nymtech/nym/pull/4042
|
||||
[#4036]: https://github.com/nymtech/nym/pull/4036
|
||||
[#4033]: https://github.com/nymtech/nym/pull/4033
|
||||
[#4024]: https://github.com/nymtech/nym/issues/4024
|
||||
[#4017]: https://github.com/nymtech/nym/issues/4017
|
||||
[#3986]: https://github.com/nymtech/nym/pull/3986
|
||||
[#3985]: https://github.com/nymtech/nym/pull/3985
|
||||
[#3955]: https://github.com/nymtech/nym/pull/3955
|
||||
[#3992]: https://github.com/nymtech/nym/pull/3992
|
||||
|
||||
## [2023.1-milka] (2023-09-24)
|
||||
|
||||
|
||||
Generated
+312
-114
@@ -799,18 +799,6 @@ dependencies = [
|
||||
"tower-service",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "axum-macros"
|
||||
version = "0.3.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cdca6a10ecad987bda04e95606ef85a5417dcaac1a78455242d72e031e2b6b62"
|
||||
dependencies = [
|
||||
"heck 0.4.1",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.38",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "backtrace"
|
||||
version = "0.3.69"
|
||||
@@ -1170,7 +1158,7 @@ checksum = "f769ab9e8c1652d78dd0b3ec59cdaa1e2bcb3b6b39f6681b256abcdbe101cc14"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cargo_metadata",
|
||||
"clap 4.4.6",
|
||||
"clap 4.4.7",
|
||||
"concolor-control",
|
||||
"crates-index",
|
||||
"dirs-next",
|
||||
@@ -1405,9 +1393,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.4.6"
|
||||
version = "4.4.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d04704f56c2cde07f43e8e2c154b43f216dc5c92fc98ada720177362f953b956"
|
||||
checksum = "ac495e00dcec98c83465d5ad66c5c4fabd652fd6686e7c6269b117e729a6f17b"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
"clap_derive",
|
||||
@@ -1415,13 +1403,13 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.4.6"
|
||||
version = "4.4.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0e231faeaca65ebd1ea3c737966bf858971cd38c3849107aa3ea7de90a804e45"
|
||||
checksum = "c77ed9a32a62e6ca27175d00d29d05ca32e396ea1eb5fb01d8256b669cec7663"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
"clap_lex 0.5.1",
|
||||
"clap_lex 0.6.0",
|
||||
"strsim",
|
||||
"terminal_size",
|
||||
]
|
||||
@@ -1432,7 +1420,7 @@ version = "4.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e3ae8ba90b9d8b007efe66e55e48fb936272f5ca00349b5b0e89877520d35ea7"
|
||||
dependencies = [
|
||||
"clap 4.4.6",
|
||||
"clap 4.4.7",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1441,15 +1429,15 @@ version = "4.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "29bdbe21a263b628f83fcbeac86a4416a1d588c7669dd41473bc4149e4e7d2f1"
|
||||
dependencies = [
|
||||
"clap 4.4.6",
|
||||
"clap 4.4.7",
|
||||
"clap_complete",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "4.4.2"
|
||||
version = "4.4.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0862016ff20d69b84ef8247369fabf5c008a7417002411897d40ee1f4532b873"
|
||||
checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442"
|
||||
dependencies = [
|
||||
"heck 0.4.1",
|
||||
"proc-macro2",
|
||||
@@ -1468,9 +1456,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap_lex"
|
||||
version = "0.5.1"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cd7cc57abe963c6d3b9d8be5b06ba7c8957a930305ca90304f24ef040aa6f961"
|
||||
checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1"
|
||||
|
||||
[[package]]
|
||||
name = "cloudabi"
|
||||
@@ -2329,7 +2317,7 @@ dependencies = [
|
||||
"hashbrown 0.14.1",
|
||||
"lock_api",
|
||||
"once_cell",
|
||||
"parking_lot_core 0.9.8",
|
||||
"parking_lot_core 0.9.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2883,7 +2871,7 @@ dependencies = [
|
||||
"bytes",
|
||||
"cfg-if",
|
||||
"chrono",
|
||||
"clap 4.4.6",
|
||||
"clap 4.4.7",
|
||||
"config",
|
||||
"digest 0.10.7",
|
||||
"dirs 5.0.1",
|
||||
@@ -2914,7 +2902,7 @@ dependencies = [
|
||||
"unsigned-varint",
|
||||
"utoipa",
|
||||
"utoipa-swagger-ui",
|
||||
"uuid 1.4.1",
|
||||
"uuid 1.5.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2950,10 +2938,10 @@ checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0"
|
||||
|
||||
[[package]]
|
||||
name = "explorer-api"
|
||||
version = "1.1.30"
|
||||
version = "1.1.31"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"clap 4.4.6",
|
||||
"clap 4.4.7",
|
||||
"dotenvy",
|
||||
"humantime-serde",
|
||||
"isocountry",
|
||||
@@ -3006,7 +2994,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "extension-storage"
|
||||
version = "1.2.0-rc.10"
|
||||
version = "1.2.4-rc.2"
|
||||
dependencies = [
|
||||
"bip39",
|
||||
"console_error_panic_hook",
|
||||
@@ -3867,6 +3855,20 @@ dependencies = [
|
||||
"itoa",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "http-api-client"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"reqwest",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"thiserror",
|
||||
"tracing",
|
||||
"url",
|
||||
"wasmtimer",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "http-body"
|
||||
version = "0.4.5"
|
||||
@@ -3878,6 +3880,12 @@ dependencies = [
|
||||
"pin-project-lite 0.2.13",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "http-range-header"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "add0ab9360ddbd88cfeb3bd9574a1d85cfdfa14db10b3e21d3700dbc4328758f"
|
||||
|
||||
[[package]]
|
||||
name = "httparse"
|
||||
version = "1.8.0"
|
||||
@@ -4013,16 +4021,16 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "iana-time-zone"
|
||||
version = "0.1.57"
|
||||
version = "0.1.58"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2fad5b825842d2b38bd206f3e81d6957625fd7f0a361e345c30e01a0ae2dd613"
|
||||
checksum = "8326b86b6cff230b97d0d312a6c40a60726df3332e721f72a1b035f451663b20"
|
||||
dependencies = [
|
||||
"android_system_properties",
|
||||
"core-foundation-sys",
|
||||
"iana-time-zone-haiku",
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
"windows 0.48.0",
|
||||
"windows-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4104,7 +4112,7 @@ checksum = "bfbcff6ae46750b15cc594bfd277b188cbddcfdc1817848f97f03f26f8625b9e"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"js-sys",
|
||||
"uuid 1.4.1",
|
||||
"uuid 1.5.0",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
"web-sys",
|
||||
@@ -4274,6 +4282,15 @@ version = "2.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "28b29a3cd74f0f4598934efe3aeba42bae0eb4680554128851ebbecb02af14e6"
|
||||
|
||||
[[package]]
|
||||
name = "ipnetwork"
|
||||
version = "0.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b8eca9f51da27bc908ef3dd85c21e1bbba794edaf94d7841e37356275b82d31e"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ipnetwork"
|
||||
version = "0.18.0"
|
||||
@@ -5361,9 +5378,9 @@ checksum = "e34f76eb3611940e0e7d53a9aaa4e6a3151f69541a282fd0dad5571420c53ff1"
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
version = "0.4.10"
|
||||
version = "0.4.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16"
|
||||
checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45"
|
||||
dependencies = [
|
||||
"autocfg 1.1.0",
|
||||
"scopeguard",
|
||||
@@ -5551,15 +5568,17 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mix-fetch-wasm"
|
||||
version = "1.2.0-rc.10"
|
||||
version = "1.2.4-rc.2"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"futures",
|
||||
"http-api-client",
|
||||
"js-sys",
|
||||
"nym-bin-common",
|
||||
"nym-ordered-buffer",
|
||||
"nym-service-providers-common",
|
||||
"nym-socks5-requests",
|
||||
"rand 0.7.3",
|
||||
"reqwest",
|
||||
"serde",
|
||||
"serde-wasm-bindgen",
|
||||
"thiserror",
|
||||
@@ -5942,7 +5961,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nym-api"
|
||||
version = "1.1.31"
|
||||
version = "1.1.32"
|
||||
dependencies = [
|
||||
"actix-web",
|
||||
"anyhow",
|
||||
@@ -5952,7 +5971,7 @@ dependencies = [
|
||||
"bs58 0.4.0",
|
||||
"cfg-if",
|
||||
"chrono",
|
||||
"clap 4.4.6",
|
||||
"clap 4.4.7",
|
||||
"console-subscriber",
|
||||
"cosmwasm-std",
|
||||
"cw-utils",
|
||||
@@ -5986,6 +6005,7 @@ dependencies = [
|
||||
"nym-mixnet-contract-common",
|
||||
"nym-multisig-contract-common",
|
||||
"nym-name-service-common",
|
||||
"nym-node-requests",
|
||||
"nym-node-tester-utils",
|
||||
"nym-pemstore",
|
||||
"nym-service-provider-directory-common",
|
||||
@@ -5996,7 +6016,6 @@ dependencies = [
|
||||
"nym-vesting-contract-common",
|
||||
"okapi",
|
||||
"pin-project",
|
||||
"pretty_env_logger",
|
||||
"rand 0.7.3",
|
||||
"rand 0.8.5",
|
||||
"reqwest",
|
||||
@@ -6016,7 +6035,7 @@ dependencies = [
|
||||
"tokio-stream",
|
||||
"ts-rs",
|
||||
"url",
|
||||
"uuid 1.4.1",
|
||||
"uuid 1.5.0",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
@@ -6030,6 +6049,7 @@ dependencies = [
|
||||
"getset",
|
||||
"nym-coconut-interface",
|
||||
"nym-mixnet-contract-common",
|
||||
"nym-node-requests",
|
||||
"schemars",
|
||||
"serde",
|
||||
"ts-rs",
|
||||
@@ -6056,19 +6076,21 @@ name = "nym-bin-common"
|
||||
version = "0.6.0"
|
||||
dependencies = [
|
||||
"atty",
|
||||
"clap 4.4.6",
|
||||
"clap 4.4.7",
|
||||
"clap_complete",
|
||||
"clap_complete_fig",
|
||||
"log",
|
||||
"opentelemetry",
|
||||
"opentelemetry-jaeger",
|
||||
"pretty_env_logger",
|
||||
"schemars",
|
||||
"semver 0.11.0",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tracing-opentelemetry",
|
||||
"tracing-subscriber",
|
||||
"tracing-tree",
|
||||
"utoipa",
|
||||
"vergen",
|
||||
]
|
||||
|
||||
@@ -6089,13 +6111,13 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nym-cli"
|
||||
version = "1.1.30"
|
||||
version = "1.1.31"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"base64 0.13.1",
|
||||
"bip39",
|
||||
"bs58 0.4.0",
|
||||
"clap 4.4.6",
|
||||
"clap 4.4.7",
|
||||
"clap_complete",
|
||||
"clap_complete_fig",
|
||||
"dotenvy",
|
||||
@@ -6120,7 +6142,7 @@ dependencies = [
|
||||
"bip39",
|
||||
"bs58 0.4.0",
|
||||
"cfg-if",
|
||||
"clap 4.4.6",
|
||||
"clap 4.4.7",
|
||||
"comfy-table",
|
||||
"cosmrs",
|
||||
"cosmwasm-std",
|
||||
@@ -6162,9 +6184,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nym-client"
|
||||
version = "1.1.30"
|
||||
version = "1.1.31"
|
||||
dependencies = [
|
||||
"clap 4.4.6",
|
||||
"clap 4.4.7",
|
||||
"dirs 4.0.0",
|
||||
"futures",
|
||||
"lazy_static",
|
||||
@@ -6203,6 +6225,7 @@ dependencies = [
|
||||
"async-trait",
|
||||
"base64 0.21.4",
|
||||
"cfg-if",
|
||||
"clap 4.4.7",
|
||||
"dashmap",
|
||||
"dirs 4.0.0",
|
||||
"futures",
|
||||
@@ -6247,11 +6270,12 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nym-client-wasm"
|
||||
version = "1.2.0-rc.10"
|
||||
version = "1.2.4-rc.2"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"futures",
|
||||
"js-sys",
|
||||
"nym-bin-common",
|
||||
"nym-node-tester-utils",
|
||||
"nym-node-tester-wasm",
|
||||
"rand 0.7.3",
|
||||
@@ -6465,6 +6489,18 @@ dependencies = [
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nym-exit-policy"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"reqwest",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"thiserror",
|
||||
"tracing",
|
||||
"utoipa",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nym-explorer-api-requests"
|
||||
version = "0.1.0"
|
||||
@@ -6492,26 +6528,22 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nym-gateway"
|
||||
version = "1.1.30"
|
||||
version = "1.1.31"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
"atty",
|
||||
"axum",
|
||||
"axum-macros",
|
||||
"base64 0.21.4",
|
||||
"bip39",
|
||||
"bs58 0.4.0",
|
||||
"clap 4.4.6",
|
||||
"clap 4.4.7",
|
||||
"colored",
|
||||
"dashmap",
|
||||
"dirs 4.0.0",
|
||||
"dotenvy",
|
||||
"fastrand 2.0.1",
|
||||
"futures",
|
||||
"hmac 0.12.1",
|
||||
"humantime-serde",
|
||||
"hyper",
|
||||
"ipnetwork 0.16.0",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"nym-api-requests",
|
||||
@@ -6521,10 +6553,12 @@ dependencies = [
|
||||
"nym-credentials",
|
||||
"nym-crypto",
|
||||
"nym-gateway-requests",
|
||||
"nym-ip-packet-router",
|
||||
"nym-mixnet-client",
|
||||
"nym-mixnode-common",
|
||||
"nym-network-defaults",
|
||||
"nym-network-requester",
|
||||
"nym-node",
|
||||
"nym-pemstore",
|
||||
"nym-sphinx",
|
||||
"nym-statistics-common",
|
||||
@@ -6538,7 +6572,6 @@ dependencies = [
|
||||
"rand 0.8.5",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sha2 0.10.8",
|
||||
"sqlx 0.5.13",
|
||||
"subtle-encoding",
|
||||
"thiserror",
|
||||
@@ -6548,7 +6581,6 @@ dependencies = [
|
||||
"tokio-util",
|
||||
"tower",
|
||||
"url",
|
||||
"x25519-dalek 2.0.0",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
@@ -6616,21 +6648,6 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nym-http-requests"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bytecodec",
|
||||
"bytes",
|
||||
"http",
|
||||
"httpcodec",
|
||||
"nym-ordered-buffer",
|
||||
"nym-service-providers-common",
|
||||
"nym-socks5-requests",
|
||||
"thiserror",
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nym-inclusion-probability"
|
||||
version = "0.1.0"
|
||||
@@ -6640,6 +6657,33 @@ dependencies = [
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nym-ip-packet-router"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"etherparse",
|
||||
"futures",
|
||||
"log",
|
||||
"nym-bin-common",
|
||||
"nym-client-core",
|
||||
"nym-config",
|
||||
"nym-exit-policy",
|
||||
"nym-network-requester",
|
||||
"nym-sdk",
|
||||
"nym-service-providers-common",
|
||||
"nym-sphinx",
|
||||
"nym-task",
|
||||
"nym-wireguard",
|
||||
"nym-wireguard-types",
|
||||
"reqwest",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tap",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nym-mixnet-client"
|
||||
version = "0.1.0"
|
||||
@@ -6675,12 +6719,13 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nym-mixnode"
|
||||
version = "1.1.31"
|
||||
version = "1.1.33"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"axum",
|
||||
"bs58 0.4.0",
|
||||
"cfg-if",
|
||||
"clap 4.4.6",
|
||||
"clap 4.4.7",
|
||||
"colored",
|
||||
"cpu-cycles",
|
||||
"cupid",
|
||||
@@ -6695,6 +6740,7 @@ dependencies = [
|
||||
"nym-crypto",
|
||||
"nym-mixnet-client",
|
||||
"nym-mixnode-common",
|
||||
"nym-node",
|
||||
"nym-nonexhaustive-delayqueue",
|
||||
"nym-pemstore",
|
||||
"nym-sphinx",
|
||||
@@ -6707,10 +6753,10 @@ dependencies = [
|
||||
"opentelemetry",
|
||||
"pretty_env_logger",
|
||||
"rand 0.7.3",
|
||||
"rocket",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sysinfo",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
"tokio-util",
|
||||
"toml 0.5.11",
|
||||
@@ -6793,13 +6839,13 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nym-network-requester"
|
||||
version = "1.1.30"
|
||||
version = "1.1.31"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-file-watcher",
|
||||
"async-trait",
|
||||
"bs58 0.4.0",
|
||||
"clap 4.4.6",
|
||||
"clap 4.4.7",
|
||||
"dirs 4.0.0",
|
||||
"futures",
|
||||
"humantime-serde",
|
||||
@@ -6812,6 +6858,7 @@ dependencies = [
|
||||
"nym-config",
|
||||
"nym-credential-storage",
|
||||
"nym-crypto",
|
||||
"nym-exit-policy",
|
||||
"nym-network-defaults",
|
||||
"nym-ordered-buffer",
|
||||
"nym-sdk",
|
||||
@@ -6840,7 +6887,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nym-network-statistics"
|
||||
version = "1.1.30"
|
||||
version = "1.1.31"
|
||||
dependencies = [
|
||||
"dirs 4.0.0",
|
||||
"log",
|
||||
@@ -6855,6 +6902,58 @@ dependencies = [
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nym-node"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"axum",
|
||||
"bytes",
|
||||
"colored",
|
||||
"dashmap",
|
||||
"fastrand 2.0.1",
|
||||
"hmac 0.12.1",
|
||||
"hyper",
|
||||
"ipnetwork 0.16.0",
|
||||
"mime",
|
||||
"nym-config",
|
||||
"nym-crypto",
|
||||
"nym-node-requests",
|
||||
"nym-task",
|
||||
"nym-wireguard-types",
|
||||
"rand 0.7.3",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_yaml",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
"tower",
|
||||
"tower-http",
|
||||
"tracing",
|
||||
"utoipa",
|
||||
"utoipa-swagger-ui",
|
||||
"x25519-dalek 2.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nym-node-requests"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"base64 0.21.4",
|
||||
"http-api-client",
|
||||
"nym-bin-common",
|
||||
"nym-crypto",
|
||||
"nym-exit-policy",
|
||||
"nym-wireguard-types",
|
||||
"schemars",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
"utoipa",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nym-node-tester-utils"
|
||||
version = "0.1.0"
|
||||
@@ -6876,7 +6975,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nym-node-tester-wasm"
|
||||
version = "1.2.0-rc.10"
|
||||
version = "1.2.4-rc.2"
|
||||
dependencies = [
|
||||
"futures",
|
||||
"js-sys",
|
||||
@@ -6909,7 +7008,7 @@ name = "nym-nr-query"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap 4.4.6",
|
||||
"clap 4.4.7",
|
||||
"log",
|
||||
"nym-bin-common",
|
||||
"nym-network-defaults",
|
||||
@@ -7032,9 +7131,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nym-socks5-client"
|
||||
version = "1.1.30"
|
||||
version = "1.1.31"
|
||||
dependencies = [
|
||||
"clap 4.4.6",
|
||||
"clap 4.4.7",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"nym-bin-common",
|
||||
@@ -7137,6 +7236,7 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"bincode",
|
||||
"log",
|
||||
"nym-exit-policy",
|
||||
"nym-service-providers-common",
|
||||
"nym-sphinx-addressing",
|
||||
"serde",
|
||||
@@ -7344,6 +7444,7 @@ dependencies = [
|
||||
"async-trait",
|
||||
"bs58 0.4.0",
|
||||
"log",
|
||||
"nym-api-requests",
|
||||
"nym-bin-common",
|
||||
"nym-config",
|
||||
"nym-crypto",
|
||||
@@ -7365,13 +7466,16 @@ dependencies = [
|
||||
name = "nym-types"
|
||||
version = "1.0.0"
|
||||
dependencies = [
|
||||
"base64 0.21.4",
|
||||
"cosmrs",
|
||||
"cosmwasm-std",
|
||||
"eyre",
|
||||
"itertools 0.10.5",
|
||||
"hmac 0.12.1",
|
||||
"itertools 0.11.0",
|
||||
"log",
|
||||
"nym-coconut-interface",
|
||||
"nym-config",
|
||||
"nym-crypto",
|
||||
"nym-mixnet-contract-common",
|
||||
"nym-validator-client",
|
||||
"nym-vesting-contract-common",
|
||||
@@ -7379,11 +7483,13 @@ dependencies = [
|
||||
"schemars",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"strum 0.23.0",
|
||||
"sha2 0.10.8",
|
||||
"strum 0.25.0",
|
||||
"tempfile",
|
||||
"thiserror",
|
||||
"ts-rs",
|
||||
"url",
|
||||
"x25519-dalek 2.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -7404,6 +7510,7 @@ dependencies = [
|
||||
"eyre",
|
||||
"flate2",
|
||||
"futures",
|
||||
"http-api-client",
|
||||
"itertools 0.10.5",
|
||||
"log",
|
||||
"nym-api-requests",
|
||||
@@ -7468,15 +7575,6 @@ dependencies = [
|
||||
"ts-rs",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nym-wasm-sdk"
|
||||
version = "1.2.0-rc.10"
|
||||
dependencies = [
|
||||
"mix-fetch-wasm",
|
||||
"nym-client-wasm",
|
||||
"nym-node-tester-wasm",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nym-wireguard"
|
||||
version = "0.1.0"
|
||||
@@ -7492,12 +7590,33 @@ dependencies = [
|
||||
"ip_network_table",
|
||||
"log",
|
||||
"nym-task",
|
||||
"nym-wireguard-types",
|
||||
"rand 0.8.5",
|
||||
"serde",
|
||||
"tap",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
"tokio-tun",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nym-wireguard-types"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"base64 0.21.4",
|
||||
"boringtun",
|
||||
"dashmap",
|
||||
"hmac 0.12.1",
|
||||
"nym-crypto",
|
||||
"rand 0.7.3",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sha2 0.10.8",
|
||||
"thiserror",
|
||||
"utoipa",
|
||||
"x25519-dalek 2.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.32.1"
|
||||
@@ -7774,9 +7893,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "parking"
|
||||
version = "2.1.1"
|
||||
version = "2.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e52c774a4c39359c1d1c52e43f73dd91a75a614652c825408eec30c95a9b2067"
|
||||
checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae"
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
@@ -7796,7 +7915,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
|
||||
dependencies = [
|
||||
"lock_api",
|
||||
"parking_lot_core 0.9.8",
|
||||
"parking_lot_core 0.9.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -7815,13 +7934,13 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot_core"
|
||||
version = "0.9.8"
|
||||
version = "0.9.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447"
|
||||
checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"redox_syscall 0.3.5",
|
||||
"redox_syscall 0.4.1",
|
||||
"smallvec",
|
||||
"windows-targets 0.48.5",
|
||||
]
|
||||
@@ -8702,6 +8821,15 @@ dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_users"
|
||||
version = "0.4.3"
|
||||
@@ -8779,13 +8907,13 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.10.1"
|
||||
version = "1.10.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aaac441002f822bc9705a681810a4dd2963094b9ca0ddc41cb963a4c189189ea"
|
||||
checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-automata 0.4.2",
|
||||
"regex-automata 0.4.3",
|
||||
"regex-syntax 0.8.2",
|
||||
]
|
||||
|
||||
@@ -8800,9 +8928,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "regex-automata"
|
||||
version = "0.4.2"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5011c7e263a695dc8ca064cddb722af1be54e517a280b12a5356f98366899e5d"
|
||||
checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
@@ -9314,9 +9442,9 @@ checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741"
|
||||
|
||||
[[package]]
|
||||
name = "safer-ffi"
|
||||
version = "0.1.3"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e9c1d19b288ca9898cd421c7b105fb7269918a7f8e9253a991e228981ca421ad"
|
||||
checksum = "395ace5aff9629c7268ca8255aceb945525b2cb644015f3caec5131a6a537c11"
|
||||
dependencies = [
|
||||
"inventory",
|
||||
"libc",
|
||||
@@ -9331,9 +9459,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "safer_ffi-proc_macros"
|
||||
version = "0.1.3"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2d7a04caa3ca2224f5ea4ddd850e2629c3b36b2b83621f87a8303bf41020110"
|
||||
checksum = "9255504d5467bae9e07d58b8de446ba6739b29bf72e1fa35b2387e30d29dcbfe"
|
||||
dependencies = [
|
||||
"macro_rules_attribute",
|
||||
"prettyplease",
|
||||
@@ -9423,7 +9551,7 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cargo-edit",
|
||||
"clap 4.4.6",
|
||||
"clap 4.4.7",
|
||||
"semver 1.0.20",
|
||||
"serde",
|
||||
"serde_json",
|
||||
@@ -9667,6 +9795,19 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_yaml"
|
||||
version = "0.9.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a49e178e4452f45cb61d0cd8cebc1b0fafd3e41929e996cef79aa3aca91f574"
|
||||
dependencies = [
|
||||
"indexmap 2.0.2",
|
||||
"itoa",
|
||||
"ryu",
|
||||
"serde",
|
||||
"unsafe-libyaml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha-1"
|
||||
version = "0.9.8"
|
||||
@@ -10172,7 +10313,7 @@ name = "ssl-inject"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap 4.4.6",
|
||||
"clap 4.4.7",
|
||||
"hex",
|
||||
"tokio",
|
||||
]
|
||||
@@ -10233,6 +10374,15 @@ version = "0.24.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f"
|
||||
|
||||
[[package]]
|
||||
name = "strum"
|
||||
version = "0.25.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125"
|
||||
dependencies = [
|
||||
"strum_macros 0.25.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "strum_macros"
|
||||
version = "0.23.1"
|
||||
@@ -10259,6 +10409,19 @@ dependencies = [
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "strum_macros"
|
||||
version = "0.25.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "23dc1fa9ac9c169a78ba62f0b841814b7abae11bdd047b9c58f893439e309ea0"
|
||||
dependencies = [
|
||||
"heck 0.4.1",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"rustversion",
|
||||
"syn 2.0.38",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "stun"
|
||||
version = "0.4.4"
|
||||
@@ -10779,7 +10942,9 @@ checksum = "212d5dcb2a1ce06d81107c3d0ffa3121fe974b73f068c8282cb1c32328113b6c"
|
||||
dependencies = [
|
||||
"futures-util",
|
||||
"log",
|
||||
"native-tls",
|
||||
"tokio",
|
||||
"tokio-native-tls",
|
||||
"tungstenite",
|
||||
]
|
||||
|
||||
@@ -10940,6 +11105,31 @@ dependencies = [
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tower-http"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "61c5bb1d698276a2443e5ecfabc1008bf15a36c12e6a7176e7bf089ea9131140"
|
||||
dependencies = [
|
||||
"bitflags 2.4.1",
|
||||
"bytes",
|
||||
"futures-core",
|
||||
"futures-util",
|
||||
"http",
|
||||
"http-body",
|
||||
"http-range-header",
|
||||
"httpdate",
|
||||
"mime",
|
||||
"mime_guess",
|
||||
"percent-encoding",
|
||||
"pin-project-lite 0.2.13",
|
||||
"tokio",
|
||||
"tokio-util",
|
||||
"tower-layer",
|
||||
"tower-service",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tower-layer"
|
||||
version = "0.3.2"
|
||||
@@ -11207,6 +11397,7 @@ dependencies = [
|
||||
"http",
|
||||
"httparse",
|
||||
"log",
|
||||
"native-tls",
|
||||
"rand 0.8.5",
|
||||
"sha1",
|
||||
"thiserror",
|
||||
@@ -11369,6 +11560,12 @@ dependencies = [
|
||||
"subtle 2.4.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unsafe-libyaml"
|
||||
version = "0.2.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f28467d3e1d3c6586d8f25fa243f544f5800fec42d97032474e17222c2b75cfa"
|
||||
|
||||
[[package]]
|
||||
name = "unsigned-varint"
|
||||
version = "0.7.2"
|
||||
@@ -11478,6 +11675,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "84614caa239fb25b2bb373a52859ffd94605ceb256eeb1d63436325cf81e3653"
|
||||
dependencies = [
|
||||
"actix-web",
|
||||
"axum",
|
||||
"mime_guess",
|
||||
"regex",
|
||||
"rust-embed",
|
||||
@@ -11495,9 +11693,9 @@ checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7"
|
||||
|
||||
[[package]]
|
||||
name = "uuid"
|
||||
version = "1.4.1"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "79daa5ed5740825c40b389c5e50312b9c86df53fccd33f281df655642b43869d"
|
||||
checksum = "88ad59a7560b41a70d191093a945f0b87bc1deeda46fb237479708a1d6b6cdfc"
|
||||
dependencies = [
|
||||
"getrandom 0.2.10",
|
||||
"serde",
|
||||
@@ -11940,7 +12138,7 @@ dependencies = [
|
||||
"tokio",
|
||||
"turn",
|
||||
"url",
|
||||
"uuid 1.4.1",
|
||||
"uuid 1.5.0",
|
||||
"waitgroup",
|
||||
"webrtc-mdns",
|
||||
"webrtc-util",
|
||||
|
||||
+19
-5
@@ -46,7 +46,8 @@ members = [
|
||||
"common/crypto",
|
||||
"common/dkg",
|
||||
"common/execute",
|
||||
"common/http-requests",
|
||||
"common/exit-policy",
|
||||
"common/http-api-client",
|
||||
"common/inclusion-probability",
|
||||
"common/ledger",
|
||||
"common/mixnode-common",
|
||||
@@ -78,6 +79,7 @@ members = [
|
||||
"common/wasm/storage",
|
||||
"common/wasm/utils",
|
||||
"common/wireguard",
|
||||
"common/wireguard-types",
|
||||
"explorer-api",
|
||||
"explorer-api/explorer-api-requests",
|
||||
"explorer-api/explorer-client",
|
||||
@@ -88,11 +90,14 @@ members = [
|
||||
"sdk/lib/socks5-listener",
|
||||
"sdk/rust/nym-sdk",
|
||||
"service-providers/common",
|
||||
"service-providers/ip-packet-router",
|
||||
"service-providers/network-requester",
|
||||
"service-providers/network-statistics",
|
||||
"nym-api",
|
||||
"nym-browser-extension/storage",
|
||||
"nym-api/nym-api-requests",
|
||||
"nym-node",
|
||||
"nym-node/nym-node-requests",
|
||||
"nym-outfox",
|
||||
"tools/internal/ssl-inject",
|
||||
"tools/internal/sdk-version-bump",
|
||||
@@ -100,7 +105,7 @@ members = [
|
||||
"tools/nym-nr-query",
|
||||
"tools/ts-rs-cli",
|
||||
"wasm/client",
|
||||
"wasm/full-nym-wasm",
|
||||
# "wasm/full-nym-wasm",
|
||||
"wasm/mix-fetch",
|
||||
"wasm/node-tester",
|
||||
]
|
||||
@@ -116,7 +121,7 @@ default-members = [
|
||||
"explorer-api",
|
||||
]
|
||||
|
||||
exclude = ["explorer", "contracts", "nym-wallet", "nym-connect/mobile/src-tauri", "nym-connect/desktop", "cpu-cycles"]
|
||||
exclude = ["explorer", "contracts", "nym-wallet", "nym-connect/mobile/src-tauri", "nym-connect/desktop", "nym-vpn/ui/src-tauri", "cpu-cycles"]
|
||||
|
||||
[workspace.package]
|
||||
authors = ["Nym Technologies SA"]
|
||||
@@ -129,7 +134,11 @@ license = "Apache-2.0"
|
||||
[workspace.dependencies]
|
||||
anyhow = "1.0.71"
|
||||
async-trait = "0.1.68"
|
||||
axum = "0.6.20"
|
||||
base64 = "0.21.4"
|
||||
bip39 = { version = "2.0.0", features = ["zeroize"] }
|
||||
boringtun = { git = "https://github.com/cloudflare/boringtun", rev = "e1d6360d6ab4529fc942a078e4c54df107abe2ba" }
|
||||
clap = "4.4.7"
|
||||
cfg-if = "1.0.0"
|
||||
cosmwasm-derive = "=1.3.0"
|
||||
cosmwasm-schema = "=1.3.0"
|
||||
@@ -151,22 +160,27 @@ dotenvy = "0.15.6"
|
||||
futures = "0.3.28"
|
||||
generic-array = "0.14.7"
|
||||
getrandom = "0.2.10"
|
||||
hyper = "0.14.27"
|
||||
k256 = "0.13"
|
||||
lazy_static = "1.4.0"
|
||||
log = "0.4"
|
||||
once_cell = "1.7.2"
|
||||
parking_lot = "0.12.1"
|
||||
rand = "0.8.5"
|
||||
reqwest = "0.11.18"
|
||||
reqwest = "0.11.22"
|
||||
schemars = "0.8.1"
|
||||
serde = "1.0.152"
|
||||
serde_json = "1.0.91"
|
||||
tap = "1.0.1"
|
||||
tendermint-rpc = "0.32" # same version as used by cosmrs
|
||||
thiserror = "1.0.38"
|
||||
thiserror = "1.0.48"
|
||||
tokio = "1.24.1"
|
||||
tokio-tungstenite = "0.20.1"
|
||||
tracing = "0.1.37"
|
||||
tungstenite = { version = "0.20.1", default-features = false }
|
||||
ts-rs = "7.0.0"
|
||||
utoipa = "3.5.0"
|
||||
utoipa-swagger-ui = "3.1.5"
|
||||
url = "2.4"
|
||||
zeroize = "1.6.0"
|
||||
|
||||
|
||||
@@ -93,10 +93,6 @@ $(eval $(call add_cargo_workspace,contracts,contracts,--lib --target wasm32-unkn
|
||||
$(eval $(call add_cargo_workspace,wallet,nym-wallet))
|
||||
$(eval $(call add_cargo_workspace,connect,nym-connect/desktop))
|
||||
|
||||
# OVERRIDE: wasm-opt fails if the binary has been built with the latest rustc.
|
||||
# Pin to the last working version.
|
||||
contracts_BUILD_RELEASE_TOOLCHAIN := +1.69.0
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# SDK
|
||||
# -----------------------------------------------------------------------------
|
||||
@@ -108,7 +104,7 @@ sdk-wasm-build:
|
||||
$(MAKE) -C wasm/client
|
||||
$(MAKE) -C wasm/node-tester
|
||||
$(MAKE) -C wasm/mix-fetch
|
||||
$(MAKE) -C wasm/full-nym-wasm
|
||||
#$(MAKE) -C wasm/full-nym-wasm
|
||||
|
||||
# run this from npm/yarn to ensure tools are in the path, e.g. yarn build:sdk from root of repo
|
||||
sdk-typescript-build:
|
||||
@@ -118,7 +114,7 @@ sdk-typescript-build:
|
||||
yarn --cwd sdk/typescript/codegen/contract-clients build
|
||||
|
||||
# NOTE: These targets are part of the main workspace (but not as wasm32-unknown-unknown)
|
||||
WASM_CRATES = extension-storage nym-client-wasm nym-node-tester-wasm nym-wasm-sdk
|
||||
WASM_CRATES = extension-storage nym-client-wasm nym-node-tester-wasm
|
||||
|
||||
sdk-wasm-test:
|
||||
#cargo test $(addprefix -p , $(WASM_CRATES)) --target wasm32-unknown-unknown -- -Dwarnings
|
||||
@@ -144,7 +140,7 @@ contracts: build-release-contracts wasm-opt-contracts
|
||||
|
||||
wasm-opt-contracts:
|
||||
for contract in $(CONTRACTS_WASM); do \
|
||||
wasm-opt --disable-sign-ext -Os $(CONTRACTS_OUT_DIR)/$$contract -o $(CONTRACTS_OUT_DIR)/$$contract; \
|
||||
wasm-opt --signext-lowering -Os $(CONTRACTS_OUT_DIR)/$$contract -o $(CONTRACTS_OUT_DIR)/$$contract; \
|
||||
done
|
||||
|
||||
# Consider adding 's' to make plural consistent (beware: used in github workflow)
|
||||
|
||||
@@ -50,10 +50,10 @@ Node, node operator and delegator rewards are determined according to the princi
|
||||
|<img src="https://render.githubusercontent.com/render/math?math=\lambda_{i}#gh-light-mode-only"><img src="https://render.githubusercontent.com/render/math?math=\color{white}\lambda_{i}#gh-dark-mode-only">|ratio of stake operator has pledged to their node to the token circulating supply.
|
||||
|<img src="https://render.githubusercontent.com/render/math?math=\omega_{i}#gh-light-mode-only"><img src="https://render.githubusercontent.com/render/math?math=\color{white}\omega_{i}#gh-dark-mode-only">|fraction of total effort undertaken by node `i`, set to `1/k`.
|
||||
|<img src="https://render.githubusercontent.com/render/math?math=k#gh-light-mode-only"><img src="https://render.githubusercontent.com/render/math?math=\color{white}k#gh-dark-mode-only">|number of nodes stakeholders are incentivised to create, set by the validators, a matter of governance. Currently determined by the `reward set` size, and set to 720 in testnet Sandbox.
|
||||
|<img src="https://render.githubusercontent.com/render/math?math=\alpha#gh-light-mode-only"><img src="https://render.githubusercontent.com/render/math?math=\color{white}\alpha#gh-dark-mode-only">|Sybil attack resistance parameter - the higher this parameter is set the stronger the reduction in competitiveness gets for a Sybil attacker.
|
||||
|<img src="https://render.githubusercontent.com/render/math?math=PM_{i}#gh-light-mode-only"><img src="https://render.githubusercontent.com/render/math?math=\color{white}PM_{i}#gh-dark-mode-only">|declared profit margin of operator `i`, defaults to 10% in.
|
||||
|<img src="https://render.githubusercontent.com/render/math?math=\alpha#gh-light-mode-only"><img src="https://render.githubusercontent.com/render/math?math=\color{white}\alpha#gh-dark-mode-only">|A Sybil attack resistance parameter - the higher this parameter is set, the stronger the reduction in competitiveness for a Sybil attacker.
|
||||
|<img src="https://render.githubusercontent.com/render/math?math=PM_{i}#gh-light-mode-only"><img src="https://render.githubusercontent.com/render/math?math=\color{white}PM_{i}#gh-dark-mode-only">|declared profit margin of operator `i`, defaults to 10%.
|
||||
|<img src="https://render.githubusercontent.com/render/math?math=PF_{i}#gh-light-mode-only"><img src="https://render.githubusercontent.com/render/math?math=\color{white}PF_{i}#gh-dark-mode-only">|uptime of node `i`, scaled to 0 - 1, for the rewarding epoch
|
||||
|<img src="https://render.githubusercontent.com/render/math?math=PP_{i}#gh-light-mode-only"><img src="https://render.githubusercontent.com/render/math?math=\color{white}PP_{i}#gh-dark-mode-only">|cost of operating node `i` for the duration of the rewarding epoch, set to 40 NYMT.
|
||||
|<img src="https://render.githubusercontent.com/render/math?math=PP_{i}#gh-light-mode-only"><img src="https://render.githubusercontent.com/render/math?math=\color{white}PP_{i}#gh-dark-mode-only">|cost of operating node `i` for the duration of the rewarding epoch, set to 40 NYMs.
|
||||
|
||||
Node reward for node `i` is determined as:
|
||||
|
||||
|
||||
+85
-5
@@ -1,10 +1,90 @@
|
||||
Critical bug or security issue 💥
|
||||
|
||||
If you're here because you're trying to figure out how to notify us of a security issue, go to Discord, and alert the core engineers:
|
||||
If you're here because you're trying to figure out how to notify us of a security issue, send us a PGP encrypted email to:
|
||||
|
||||
Dave Hrycyszyn futurechimp#5430
|
||||
Jedrzej Stuczynski "Jedrzej | Nym#5666"
|
||||
Fran Arbanas | franarbanas#0995
|
||||
Mark Sinclair | marknym#8088
|
||||
```
|
||||
security@nymte.ch
|
||||
```
|
||||
|
||||
Encrypted with our public key which is available below in plain text and also on keyservers:
|
||||
|
||||
```
|
||||
pub rsa4096 2023-10-30 [SC] [expire : 2026-10-29]
|
||||
24B2592E801A5AAA8666C8BA7C3C727F05090550
|
||||
uid [ ultime ] Security Nym Technologies <security@nymte.ch>
|
||||
sub rsa4096 2023-10-30 [E] [expire : 2026-10-29]
|
||||
|
||||
```
|
||||
|
||||
The fingerprint of the key is on the second line above.
|
||||
|
||||
If you need to chat __urgently__ to our team for a __critical__ security issue:
|
||||
|
||||
go to Matrix, and alert the core engineers with a private direct message:
|
||||
|
||||
Jedrzej Stuczynski @jstuczyn:nymtech.chat
|
||||
Mark Sinclair @mark:nymtech.chat
|
||||
Raphaël Walther @raphael:nymtech.chat
|
||||
|
||||
Please avoid opening public issues on GitHub that contain information about a potential security vulnerability as this makes it difficult to reduce the impact and harm of valid security issues.
|
||||
|
||||
If you don't know what Matrix is, you can follow this documentation to create an account on this federation of instant messaging servers:
|
||||
|
||||
[Matrix for Instant Messaging](https://matrix.org/docs/chat_basics/matrix-for-im/)
|
||||
|
||||
|
||||
|
||||
```
|
||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
mQINBGU/XpcBEAC+ykz0yxn8FferjEBooptXlOH/v/28aa0Nv8DfImTgj9BNY5cR
|
||||
UdLk+Wa3CSXQVE7PIsi0egEjAMfyxPEywbvPlgklW4XAKDVUCf3gxpQNN47VuVgV
|
||||
VwrN0VBurhhIKoEw9daO6A0P44+6nmXGIfUulCr4fMxYq82SOooog/j5w0/LfITu
|
||||
rQXxVABLkXHGN/NGf4BE52QI/ppeXWoshlNVU1wdZIIYWwte+9ukikWpN+LYfJUR
|
||||
ybtyCjQ4Gdf8ap1GmkKHmAru24wbUuFsBWGVgHsXAwYlKxyiNGR9YwgAxmFk6vNf
|
||||
1PqKGO3i4erx5X/+mzylzNbFlCqFuksZRyUSDZvQ8fxkm8ra1zWbO38eOTp8Vhgg
|
||||
SKfRTzOKeZYURZicJPxmEIfA88U4tx+YWJ54YWT/gERZkjIJL5mzIuY9UulVvKUM
|
||||
vMFUIzBMHOPXH16036zGyFMC1esRd2qqil4b9KtLgCOkrD1VgpjcveoA0VyMJCN6
|
||||
LmKTrVjwjjDMxby+d49BolRWGnCofXozXwvNQx+CYv8M2WPErTpyYoofYFtpqr7A
|
||||
fIufc/e0+um3zoGIbHejrhsbuH9Qf+MKsI+Ng93bdDtjeHz6MEgAlsTm0qeizYpj
|
||||
IyKZIObPmfvrAm08hFZ8JnGk+XuooF36XWbJYjCCy0bOyMw1r7ZG99TcSwARAQAB
|
||||
tC1TZWN1cml0eSBOeW0gVGVjaG5vbG9naWVzIDxzZWN1cml0eUBueW10ZS5jaD6J
|
||||
AlQEEwEKAD4WIQQkslkugBpaqoZmyLp8PHJ/BQkFUAUCZT9elwIbAwUJBaOagAUL
|
||||
CQgHAwUVCgkICwUWAgMBAAIeAQIXgAAKCRB8PHJ/BQkFUL7dD/9zO73uI5VR+SWx
|
||||
PFmJW+9QsPiQbVRvGwNZurctmQ2s2Pe0vHRELFeqD5oYvSx2Lequ3Ir+zn/C3kDM
|
||||
kNs40obSL6jCBiLPkxEY0JqzPM9jZr7EjvlibWV3f6DxooRIqEyfN57I3OBGlqZE
|
||||
0Mx7sQuCcgau8C70DF952QhKUwXC2cmpmDKHVEEoio1xGSD4dQhGapCB32RQGtna
|
||||
OGfAO9celNMvSq0Lp+aJxeACmWFY5T4/y79JPcT5vSs/yEIRmaH/fn2piwaFBsIq
|
||||
gHJJMxO3740P1hF8j7KWUoUofuFaEALHBpEpjWTOj8ej1wmFlu+5F+jSVoc781Wb
|
||||
ZZXu04cOBXnGTogzSxMpBe9TtLb28zd6WzFotC25KTI3pngMzXsQGLJLOwvoZKiS
|
||||
LFjPRjg1rwobmB3Q3J2W5GYSveia0CDsZGP+g87GVVf/oD2Djpa68xyVYwIYeA6T
|
||||
3DNdS77qHiRuGiS4kWXyVjDqOICboR4uCvt09zlkBuLDdTWqWYARUvZjtjs4w/Ol
|
||||
rdrBI3A88ti8fRldYaNpu17ME1ilpN44yKoJtqiWc3Tisk8eYLfx6c7FQF3PrRva
|
||||
mr7FZvhFsYML5CeNFHTEzN6Y3jjKN/60DvCfodWnWFK47Txkl8UAXGY2W9B0fWqQ
|
||||
wUVr8uLuMyyMiKbeoufi7rGOj6AMErkCDQRlP16XARAA8FGmD5J3tM1BOM1niJxZ
|
||||
JTdCauzEtxEoBL0RuqGBkR8U29sRM6DwuzjU7PwscFnBaGyU+eU73GwGkH3ozFfF
|
||||
tllYhQrhP/kkN+0rEO5Xi+nR+4JCFRqrf3nJXAAPfiksURMp8er1dUOY2/e1ZSoL
|
||||
tS+nzUivV8CfE+pgj/5YtGwPC+KYHLATkKkMELCrbW4UO06VWOqQsvr6kivXuJQQ
|
||||
LdEAMpBlADmXFG45DmPKQzsBWUgvTwyGy3LX0nys8cgpex9BH8hhr01QmGyP469s
|
||||
N3cNrtFuu8U6RAsiCD/8mlBuD3EQEU5SF0lc7kCICAZk+wElmXnimEi0TOYsbz6k
|
||||
90lteicX70rA9GNeyI76H+VSOYvWpkRwaJAgUdzrAM1o9SHASq+cZ6nD85OZioQk
|
||||
DWM6+Q+sf2oen0qJnnGmUr93kJIC0PIdgrXRrtiNfeRa1Z/H0LmREyyEMoFiVivn
|
||||
z1vVk85Oq6Sf3ltUwvmDzuuJOtsp2Qp6+x6Snn/yKauI4uf4Cf/wKUch4r6Bwgg5
|
||||
Dw49ky7lwlnALio4GIVoGLpLef93wWoDmp4Klyh3ZPf2nB0U91u3bHRUo7m+D7QJ
|
||||
98cyKtqLLzjg7szGf60pIWNWRsadYQT3bSncynqknAjOV3BCvx6/ivsnpj//QjYR
|
||||
HtviUAcQ1DBB6UC6q23FIs0AEQEAAYkCPAQYAQoAJhYhBCSyWS6AGlqqhmbIunw8
|
||||
cn8FCQVQBQJlP16XAhsMBQkFo5qAAAoJEHw8cn8FCQVQzukP/iLxjOxT+UpPR//c
|
||||
prDVSLkP4pF5bmw36U07jvqpS+/KTXsxiiQleffRabOpNLcd+K1ueavyt9nnIwHH
|
||||
tHS9kM9A7DBw3LnpEbXki46QDCCI6niGijlLOEeAWqnocwMNTT05wVVgCtO3DQP2
|
||||
MoSCcqHpXDChvOyr5d5xjYLVJhlctIMSomcVzGryjknPu0Yj/TkC/4c+m86ZWQUD
|
||||
HqMHQIuiEenvb62/F4c5OJIRZPEn70wdddkgJuJU3eHdHrnuhCkjCC93GQGbGj03
|
||||
Zqos6699y6hmPeD3U5IUv8ujwZYVCCuDm8gJfrp3R6WLfeZeK9WmTVBpCzsDg3fV
|
||||
hSwmOk6pp8DAq1/Dev3yRkFggCEyGK6c9b+a0CRBncl8e5Q0QQIzNiS/uExQP3h+
|
||||
ELJs3P0MLP+6FWhNUry09n3lnWkr1hY+v1M0GAxbfdv/tsCN1Pq/VQEz+CTqXqya
|
||||
ftWldOHWw6Hh+gtwxcHjG4MBOrO5oICQ3lh2hGwQ58cDgZYSK/OGgJ9BggFl1CcM
|
||||
0uGC0/TRCI1zt/4y+7efSZQMZkHo7VC/3MFbp2hcNejpW+BxVuwKTunFvWK3TLhq
|
||||
sSlQ5yyhqchooepsFHq9bosKFjLJC01uprBv1rinoNduOy43FbyS7JPRRspANN0R
|
||||
iC2pMbWdE0ZTQaFq6tPIg058pjqi
|
||||
=nqgX
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
||||
```
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "nym-client"
|
||||
version = "1.1.30"
|
||||
version = "1.1.31"
|
||||
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jędrzej Stuczyński <andrew@nymtech.net>"]
|
||||
description = "Implementation of the Nym Client"
|
||||
edition = "2021"
|
||||
@@ -20,7 +20,7 @@ futures = { workspace = true } # bunch of futures stuff, however, now that I thi
|
||||
# and the single instance of abortable we have should really be refactored anyway
|
||||
url = { workspace = true }
|
||||
|
||||
clap = { version = "4.0", features = ["cargo", "derive"] }
|
||||
clap = { workspace = true, features = ["cargo", "derive"] }
|
||||
dirs = "4.0"
|
||||
lazy_static = "1.4.0"
|
||||
log = { workspace = true } # self explanatory
|
||||
@@ -36,7 +36,7 @@ tokio-tungstenite = { workspace = true }
|
||||
## internal
|
||||
nym-bandwidth-controller = { path = "../../common/bandwidth-controller" }
|
||||
nym-bin-common = { path = "../../common/bin-common", features = ["output_format"] }
|
||||
nym-client-core = { path = "../../common/client-core", features = ["fs-surb-storage"] }
|
||||
nym-client-core = { path = "../../common/client-core", features = ["fs-surb-storage", "cli"] }
|
||||
nym-coconut-interface = { path = "../../common/coconut-interface" }
|
||||
nym-config = { path = "../../common/config" }
|
||||
nym-credential-storage = { path = "../../common/credential-storage" }
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
use crate::client::config::persistence::ClientPaths;
|
||||
use crate::client::config::template::CONFIG_TEMPLATE;
|
||||
use nym_bin_common::logging::LoggingSettings;
|
||||
use nym_client_core::cli_helpers::client_init::ClientConfig;
|
||||
use nym_client_core::config::disk_persistence::CommonClientPaths;
|
||||
use nym_config::defaults::DEFAULT_WEBSOCKET_LISTENING_PORT;
|
||||
use nym_config::{
|
||||
must_get_home, read_config_from_toml_file, save_formatted_config_to_file, NymConfigTemplate,
|
||||
@@ -72,6 +74,24 @@ impl NymConfigTemplate for Config {
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientConfig for Config {
|
||||
fn common_paths(&self) -> &CommonClientPaths {
|
||||
&self.storage_paths.common_paths
|
||||
}
|
||||
|
||||
fn core_config(&self) -> &BaseClientConfig {
|
||||
&self.base
|
||||
}
|
||||
|
||||
fn default_store_location(&self) -> PathBuf {
|
||||
self.default_location()
|
||||
}
|
||||
|
||||
fn save_to<P: AsRef<Path>>(&self, path: P) -> io::Result<()> {
|
||||
save_formatted_config_to_file(self, path)
|
||||
}
|
||||
}
|
||||
|
||||
impl Config {
|
||||
pub fn new<S: AsRef<str>>(id: S) -> Self {
|
||||
Config {
|
||||
|
||||
@@ -11,6 +11,7 @@ use crate::{
|
||||
use nym_bin_common::logging::LoggingSettings;
|
||||
use nym_client_core::config::disk_persistence::old_v1_1_20_2::CommonClientPathsV1_1_20_2;
|
||||
use nym_client_core::config::old_config_v1_1_20_2::ConfigV1_1_20_2 as BaseConfigV1_1_20_2;
|
||||
use nym_client_core::config::old_config_v1_1_30::ConfigV1_1_30 as BaseConfigV1_1_30;
|
||||
use nym_client_core::config::GatewayEndpointConfig;
|
||||
use nym_config::read_config_from_toml_file;
|
||||
use nym_network_defaults::DEFAULT_WEBSOCKET_LISTENING_PORT;
|
||||
@@ -51,7 +52,7 @@ impl ConfigV1_1_20_2 {
|
||||
pub fn upgrade(self) -> Result<(Config, GatewayEndpointConfig), ClientError> {
|
||||
let gateway_details = self.base.client.gateway_endpoint.clone().into();
|
||||
let config = Config {
|
||||
base: self.base.into(),
|
||||
base: BaseConfigV1_1_30::from(self.base).into(),
|
||||
socket: self.socket.into(),
|
||||
storage_paths: ClientPaths {
|
||||
common_paths: self.storage_paths.common_paths.upgrade_default()?,
|
||||
|
||||
@@ -12,55 +12,49 @@ use crate::{
|
||||
};
|
||||
use clap::Args;
|
||||
use nym_bin_common::output_format::OutputFormat;
|
||||
use nym_client_core::client::base_client::storage::gateway_details::OnDiskGatewayDetails;
|
||||
use nym_client_core::client::key_manager::persistence::OnDiskKeys;
|
||||
use nym_client_core::config::GatewayEndpointConfig;
|
||||
use nym_client_core::error::ClientCoreError;
|
||||
use nym_client_core::init::helpers::current_gateways;
|
||||
use nym_client_core::init::types::{GatewayDetails, GatewaySelectionSpecification, GatewaySetup};
|
||||
use nym_crypto::asymmetric::identity;
|
||||
use nym_sphinx::addressing::clients::Recipient;
|
||||
use nym_topology::NymTopology;
|
||||
use nym_client_core::cli_helpers::client_init::{
|
||||
initialise_client, CommonClientInitArgs, InitResultsWithConfig, InitialisableClient,
|
||||
};
|
||||
use serde::Serialize;
|
||||
use std::fmt::Display;
|
||||
use std::fs;
|
||||
use std::net::IpAddr;
|
||||
use std::path::PathBuf;
|
||||
use std::{fs, io};
|
||||
use tap::TapFallible;
|
||||
|
||||
struct NativeClientInit;
|
||||
|
||||
impl InitialisableClient for NativeClientInit {
|
||||
const NAME: &'static str = "native";
|
||||
type Error = ClientError;
|
||||
type InitArgs = Init;
|
||||
type Config = Config;
|
||||
|
||||
fn try_upgrade_outdated_config(id: &str) -> Result<(), Self::Error> {
|
||||
try_upgrade_config(id)
|
||||
}
|
||||
|
||||
fn initialise_storage_paths(id: &str) -> Result<(), Self::Error> {
|
||||
fs::create_dir_all(default_data_directory(id))?;
|
||||
fs::create_dir_all(default_config_directory(id))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn default_config_path(id: &str) -> PathBuf {
|
||||
default_config_filepath(id)
|
||||
}
|
||||
|
||||
fn construct_config(init_args: &Self::InitArgs) -> Self::Config {
|
||||
override_config(
|
||||
Config::new(&init_args.common_args.id),
|
||||
OverrideConfig::from(init_args.clone()),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Args, Clone)]
|
||||
pub(crate) struct Init {
|
||||
/// Id of the nym-mixnet-client we want to create config for.
|
||||
#[clap(long)]
|
||||
id: String,
|
||||
|
||||
/// Id of the gateway we are going to connect to.
|
||||
#[clap(long)]
|
||||
gateway: Option<identity::PublicKey>,
|
||||
|
||||
/// Specifies whether the new gateway should be determined based by latency as opposed to being chosen
|
||||
/// uniformly.
|
||||
#[clap(long, conflicts_with = "gateway")]
|
||||
latency_based_selection: bool,
|
||||
|
||||
/// Force register gateway. WARNING: this will overwrite any existing keys for the given id,
|
||||
/// potentially causing loss of access.
|
||||
#[clap(long)]
|
||||
force_register_gateway: bool,
|
||||
|
||||
/// Comma separated list of rest endpoints of the nyxd validators
|
||||
#[clap(long, alias = "nyxd_validators", value_delimiter = ',', hide = true)]
|
||||
nyxd_urls: Option<Vec<url::Url>>,
|
||||
|
||||
/// Comma separated list of rest endpoints of the API validators
|
||||
#[clap(
|
||||
long,
|
||||
alias = "api_validators",
|
||||
value_delimiter = ',',
|
||||
group = "network"
|
||||
)]
|
||||
// the alias here is included for backwards compatibility (1.1.4 and before)
|
||||
nym_apis: Option<Vec<url::Url>>,
|
||||
#[command(flatten)]
|
||||
common_args: CommonClientInitArgs,
|
||||
|
||||
/// Whether to not start the websocket
|
||||
#[clap(long)]
|
||||
@@ -74,40 +68,28 @@ pub(crate) struct Init {
|
||||
#[clap(long)]
|
||||
host: Option<IpAddr>,
|
||||
|
||||
/// Path to .json file containing custom network specification.
|
||||
#[clap(long, group = "network", hide = true)]
|
||||
custom_mixnet: Option<PathBuf>,
|
||||
|
||||
/// Mostly debug-related option to increase default traffic rate so that you would not need to
|
||||
/// modify config post init
|
||||
#[clap(long, hide = true)]
|
||||
fastmode: bool,
|
||||
|
||||
/// Disable loop cover traffic and the Poisson rate limiter (for debugging only)
|
||||
#[clap(long, hide = true)]
|
||||
no_cover: bool,
|
||||
|
||||
/// Set this client to work in a enabled credentials mode that would attempt to use gateway
|
||||
/// with bandwidth credential requirement.
|
||||
#[clap(long, hide = true)]
|
||||
enabled_credentials_mode: Option<bool>,
|
||||
|
||||
#[clap(short, long, default_value_t = OutputFormat::default())]
|
||||
output: OutputFormat,
|
||||
}
|
||||
|
||||
impl AsRef<CommonClientInitArgs> for Init {
|
||||
fn as_ref(&self) -> &CommonClientInitArgs {
|
||||
&self.common_args
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Init> for OverrideConfig {
|
||||
fn from(init_config: Init) -> Self {
|
||||
OverrideConfig {
|
||||
nym_apis: init_config.nym_apis,
|
||||
nym_apis: init_config.common_args.nym_apis,
|
||||
disable_socket: init_config.disable_socket,
|
||||
port: init_config.port,
|
||||
host: init_config.host,
|
||||
fastmode: init_config.fastmode,
|
||||
no_cover: init_config.no_cover,
|
||||
fastmode: init_config.common_args.fastmode,
|
||||
no_cover: init_config.common_args.no_cover,
|
||||
|
||||
nyxd_urls: init_config.nyxd_urls,
|
||||
enabled_credentials_mode: init_config.enabled_credentials_mode,
|
||||
nyxd_urls: init_config.common_args.nyxd_urls,
|
||||
enabled_credentials_mode: init_config.common_args.enabled_credentials_mode,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -121,15 +103,11 @@ pub struct InitResults {
|
||||
}
|
||||
|
||||
impl InitResults {
|
||||
fn new(config: &Config, address: &Recipient, gateway: &GatewayEndpointConfig) -> Self {
|
||||
fn new(res: InitResultsWithConfig<Config>) -> Self {
|
||||
Self {
|
||||
client_core: nym_client_core::init::types::InitResults::new(
|
||||
&config.base,
|
||||
address,
|
||||
gateway,
|
||||
),
|
||||
client_listening_port: config.socket.listening_port,
|
||||
client_address: address.to_string(),
|
||||
client_address: res.init_results.address.to_string(),
|
||||
client_core: res.init_results,
|
||||
client_listening_port: res.config.socket.listening_port,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -142,97 +120,14 @@ impl Display for InitResults {
|
||||
}
|
||||
}
|
||||
|
||||
fn init_paths(id: &str) -> io::Result<()> {
|
||||
fs::create_dir_all(default_data_directory(id))?;
|
||||
fs::create_dir_all(default_config_directory(id))
|
||||
}
|
||||
|
||||
pub(crate) async fn execute(args: Init) -> Result<(), ClientError> {
|
||||
eprintln!("Initialising client...");
|
||||
|
||||
let id = &args.id;
|
||||
let output = args.output;
|
||||
let res = initialise_client::<NativeClientInit>(args).await?;
|
||||
|
||||
let already_init = if default_config_filepath(id).exists() {
|
||||
// in case we're using old config, try to upgrade it
|
||||
// (if we're using the current version, it's a no-op)
|
||||
try_upgrade_config(id)?;
|
||||
eprintln!("Client \"{id}\" was already initialised before");
|
||||
true
|
||||
} else {
|
||||
init_paths(id)?;
|
||||
false
|
||||
};
|
||||
|
||||
// Usually you only register with the gateway on the first init, however you can force
|
||||
// re-registering if wanted.
|
||||
let user_wants_force_register = args.force_register_gateway;
|
||||
if user_wants_force_register {
|
||||
eprintln!("Instructed to force registering gateway. This will overwrite keys!");
|
||||
}
|
||||
|
||||
// If the client was already initialized, don't generate new keys and don't re-register with
|
||||
// the gateway (because this would create a new shared key).
|
||||
// Unless the user really wants to.
|
||||
let register_gateway = !already_init || user_wants_force_register;
|
||||
|
||||
// Attempt to use a user-provided gateway, if possible
|
||||
let user_chosen_gateway_id = args.gateway;
|
||||
let selection_spec = GatewaySelectionSpecification::new(
|
||||
user_chosen_gateway_id.map(|id| id.to_base58_string()),
|
||||
Some(args.latency_based_selection),
|
||||
false,
|
||||
);
|
||||
|
||||
// Load and potentially override config
|
||||
let config = override_config(Config::new(id), OverrideConfig::from(args.clone()));
|
||||
|
||||
// Setup gateway by either registering a new one, or creating a new config from the selected
|
||||
// one but with keys kept, or reusing the gateway configuration.
|
||||
let key_store = OnDiskKeys::new(config.storage_paths.common_paths.keys.clone());
|
||||
let details_store =
|
||||
OnDiskGatewayDetails::new(&config.storage_paths.common_paths.gateway_details);
|
||||
|
||||
let available_gateways = if let Some(hardcoded_topology) = args
|
||||
.custom_mixnet
|
||||
.map(NymTopology::new_from_file)
|
||||
.transpose()?
|
||||
{
|
||||
// hardcoded_topology
|
||||
hardcoded_topology.get_gateways()
|
||||
} else {
|
||||
let mut rng = rand::thread_rng();
|
||||
current_gateways(&mut rng, &config.base.client.nym_api_urls).await?
|
||||
};
|
||||
|
||||
let gateway_setup = GatewaySetup::New {
|
||||
specification: selection_spec,
|
||||
available_gateways,
|
||||
overwrite_data: register_gateway,
|
||||
};
|
||||
|
||||
let init_details =
|
||||
nym_client_core::init::setup_gateway(gateway_setup, &key_store, &details_store)
|
||||
.await
|
||||
.tap_err(|err| eprintln!("Failed to setup gateway\nError: {err}"))?;
|
||||
|
||||
let config_save_location = config.default_location();
|
||||
config.save_to_default_location().tap_err(|_| {
|
||||
log::error!("Failed to save the config file");
|
||||
})?;
|
||||
eprintln!(
|
||||
"Saved configuration file to {}",
|
||||
config_save_location.display()
|
||||
);
|
||||
|
||||
let address = init_details.client_address()?;
|
||||
|
||||
eprintln!("Client configuration completed.\n");
|
||||
|
||||
let GatewayDetails::Configured(gateway_details) = init_details.gateway_details else {
|
||||
return Err(ClientCoreError::UnexpectedPersistedCustomGatewayDetails)?;
|
||||
};
|
||||
let init_results = InitResults::new(&config, &address, &gateway_details);
|
||||
println!("{}", args.output.format(&init_results));
|
||||
let init_results = InitResults::new(res);
|
||||
println!("{}", output.format(&init_results));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -10,35 +10,14 @@ use crate::{
|
||||
use clap::Args;
|
||||
use log::*;
|
||||
use nym_bin_common::version_checker::is_minor_version_compatible;
|
||||
use nym_crypto::asymmetric::identity;
|
||||
use nym_client_core::cli_helpers::client_run::CommonClientRunArgs;
|
||||
use std::error::Error;
|
||||
use std::net::IpAddr;
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[derive(Args, Clone)]
|
||||
pub(crate) struct Run {
|
||||
/// Id of the nym-mixnet-client we want to run.
|
||||
#[clap(long)]
|
||||
id: String,
|
||||
|
||||
/// Comma separated list of rest endpoints of the nyxd validators
|
||||
#[clap(long, alias = "nyxd_validators", value_delimiter = ',', hide = true)]
|
||||
nyxd_urls: Option<Vec<url::Url>>,
|
||||
|
||||
/// Comma separated list of rest endpoints of the API validators
|
||||
#[clap(
|
||||
long,
|
||||
alias = "api_validators",
|
||||
value_delimiter = ',',
|
||||
group = "network"
|
||||
)]
|
||||
// the alias here is included for backwards compatibility (1.1.4 and before)
|
||||
nym_apis: Option<Vec<url::Url>>,
|
||||
|
||||
/// Id of the gateway we want to connect to. If overridden, it is user's responsibility to
|
||||
/// ensure prior registration happened
|
||||
#[clap(long)]
|
||||
gateway: Option<identity::PublicKey>,
|
||||
#[command(flatten)]
|
||||
common_args: CommonClientRunArgs,
|
||||
|
||||
/// Whether to not start the websocket
|
||||
#[clap(long)]
|
||||
@@ -51,37 +30,19 @@ pub(crate) struct Run {
|
||||
/// Ip for the socket (if applicable) to listen for requests.
|
||||
#[clap(long)]
|
||||
host: Option<IpAddr>,
|
||||
|
||||
/// Path to .json file containing custom network specification.
|
||||
#[clap(long, group = "network", hide = true)]
|
||||
custom_mixnet: Option<PathBuf>,
|
||||
|
||||
/// Mostly debug-related option to increase default traffic rate so that you would not need to
|
||||
/// modify config post init
|
||||
#[clap(long, hide = true)]
|
||||
fastmode: bool,
|
||||
|
||||
/// Disable loop cover traffic and the Poisson rate limiter (for debugging only)
|
||||
#[clap(long, hide = true)]
|
||||
no_cover: bool,
|
||||
|
||||
/// Set this client to work in a enabled credentials mode that would attempt to use gateway
|
||||
/// with bandwidth credential requirement.
|
||||
#[clap(long, hide = true)]
|
||||
enabled_credentials_mode: Option<bool>,
|
||||
}
|
||||
|
||||
impl From<Run> for OverrideConfig {
|
||||
fn from(run_config: Run) -> Self {
|
||||
OverrideConfig {
|
||||
nym_apis: run_config.nym_apis,
|
||||
nym_apis: run_config.common_args.nym_apis,
|
||||
disable_socket: run_config.disable_socket,
|
||||
port: run_config.port,
|
||||
host: run_config.host,
|
||||
fastmode: run_config.fastmode,
|
||||
no_cover: run_config.no_cover,
|
||||
nyxd_urls: run_config.nyxd_urls,
|
||||
enabled_credentials_mode: run_config.enabled_credentials_mode,
|
||||
fastmode: run_config.common_args.fastmode,
|
||||
no_cover: run_config.common_args.no_cover,
|
||||
nyxd_urls: run_config.common_args.nyxd_urls,
|
||||
enabled_credentials_mode: run_config.common_args.enabled_credentials_mode,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -106,9 +67,9 @@ fn version_check(cfg: &Config) -> bool {
|
||||
}
|
||||
|
||||
pub(crate) async fn execute(args: Run) -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||
eprintln!("Starting client {}...", args.id);
|
||||
eprintln!("Starting client {}...", args.common_args.id);
|
||||
|
||||
let mut config = try_load_current_config(&args.id)?;
|
||||
let mut config = try_load_current_config(&args.common_args.id)?;
|
||||
config = override_config(config, OverrideConfig::from(args.clone()));
|
||||
|
||||
if !version_check(&config) {
|
||||
@@ -116,7 +77,7 @@ pub(crate) async fn execute(args: Run) -> Result<(), Box<dyn Error + Send + Sync
|
||||
return Err(Box::new(ClientError::FailedLocalVersionCheck));
|
||||
}
|
||||
|
||||
SocketClient::new(config, args.custom_mixnet)
|
||||
SocketClient::new(config, args.common_args.custom_mixnet)
|
||||
.run_socket_forever()
|
||||
.await
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
[package]
|
||||
name = "nym-socks5-client"
|
||||
version = "1.1.30"
|
||||
version = "1.1.31"
|
||||
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"]
|
||||
description = "A SOCKS5 localhost proxy that converts incoming messages to Sphinx and sends them to a Nym address"
|
||||
edition = "2021"
|
||||
rust-version = "1.56"
|
||||
|
||||
[dependencies]
|
||||
clap = { version = "4.0", features = ["cargo", "derive"] }
|
||||
clap = { workspace = true, features = ["cargo", "derive"] }
|
||||
lazy_static = "1.4.0"
|
||||
log = { workspace = true }
|
||||
pretty_env_logger = "0.4"
|
||||
@@ -21,7 +21,7 @@ url = { workspace = true }
|
||||
|
||||
# internal
|
||||
nym-bin-common = { path = "../../common/bin-common", features = ["output_format"] }
|
||||
nym-client-core = { path = "../../common/client-core", features = ["fs-surb-storage"] }
|
||||
nym-client-core = { path = "../../common/client-core", features = ["fs-surb-storage", "cli"] }
|
||||
nym-coconut-interface = { path = "../../common/coconut-interface" }
|
||||
nym-config = { path = "../../common/config" }
|
||||
nym-credentials = { path = "../../common/credentials" }
|
||||
|
||||
@@ -11,26 +11,50 @@ use crate::{
|
||||
};
|
||||
use clap::Args;
|
||||
use nym_bin_common::output_format::OutputFormat;
|
||||
use nym_client_core::client::base_client::storage::gateway_details::OnDiskGatewayDetails;
|
||||
use nym_client_core::client::key_manager::persistence::OnDiskKeys;
|
||||
use nym_client_core::config::GatewayEndpointConfig;
|
||||
use nym_client_core::error::ClientCoreError;
|
||||
use nym_client_core::init::helpers::current_gateways;
|
||||
use nym_client_core::init::types::{GatewayDetails, GatewaySelectionSpecification, GatewaySetup};
|
||||
use nym_crypto::asymmetric::identity;
|
||||
use nym_client_core::cli_helpers::client_init::{
|
||||
initialise_client, CommonClientInitArgs, InitResultsWithConfig, InitialisableClient,
|
||||
};
|
||||
use nym_sphinx::addressing::clients::Recipient;
|
||||
use nym_topology::NymTopology;
|
||||
use serde::Serialize;
|
||||
use std::fmt::Display;
|
||||
use std::fs;
|
||||
use std::net::{IpAddr, SocketAddr};
|
||||
use std::path::PathBuf;
|
||||
use std::{fs, io};
|
||||
use tap::TapFallible;
|
||||
|
||||
struct Socks5ClientInit;
|
||||
|
||||
impl InitialisableClient for Socks5ClientInit {
|
||||
const NAME: &'static str = "socks5";
|
||||
type Error = Socks5ClientError;
|
||||
type InitArgs = Init;
|
||||
type Config = Config;
|
||||
|
||||
fn try_upgrade_outdated_config(id: &str) -> Result<(), Self::Error> {
|
||||
try_upgrade_config(id)
|
||||
}
|
||||
|
||||
fn initialise_storage_paths(id: &str) -> Result<(), Self::Error> {
|
||||
fs::create_dir_all(default_data_directory(id))?;
|
||||
fs::create_dir_all(default_config_directory(id))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn default_config_path(id: &str) -> PathBuf {
|
||||
default_config_filepath(id)
|
||||
}
|
||||
|
||||
fn construct_config(init_args: &Self::InitArgs) -> Self::Config {
|
||||
override_config(
|
||||
Config::new(&init_args.common_args.id, &init_args.provider.to_string()),
|
||||
OverrideConfig::from(init_args.clone()),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Args, Clone)]
|
||||
pub(crate) struct Init {
|
||||
/// Id of the nym-mixnet-client we want to create config for.
|
||||
#[clap(long)]
|
||||
id: String,
|
||||
#[command(flatten)]
|
||||
common_args: CommonClientInitArgs,
|
||||
|
||||
/// Address of the socks5 provider to send messages to.
|
||||
#[clap(long)]
|
||||
@@ -45,72 +69,37 @@ pub(crate) struct Init {
|
||||
#[clap(long, alias = "use_anonymous_sender_tag")]
|
||||
use_reply_surbs: Option<bool>,
|
||||
|
||||
/// Id of the gateway we are going to connect to.
|
||||
#[clap(long)]
|
||||
gateway: Option<identity::PublicKey>,
|
||||
|
||||
/// Specifies whether the new gateway should be determined based by latency as opposed to being chosen
|
||||
/// uniformly.
|
||||
#[clap(long, conflicts_with = "gateway")]
|
||||
latency_based_selection: bool,
|
||||
|
||||
/// Force register gateway. WARNING: this will overwrite any existing keys for the given id,
|
||||
/// potentially causing loss of access.
|
||||
#[clap(long)]
|
||||
force_register_gateway: bool,
|
||||
|
||||
/// Comma separated list of rest endpoints of the nyxd validators
|
||||
#[clap(long, alias = "nyxd_validators", value_delimiter = ',', hide = true)]
|
||||
nyxd_urls: Option<Vec<url::Url>>,
|
||||
|
||||
/// Comma separated list of rest endpoints of the API validators
|
||||
#[clap(
|
||||
long,
|
||||
alias = "api_validators",
|
||||
value_delimiter = ',',
|
||||
group = "network"
|
||||
)]
|
||||
// the alias here is included for backwards compatibility (1.1.4 and before)
|
||||
nym_apis: Option<Vec<url::Url>>,
|
||||
|
||||
/// Port for the socket to listen on in all subsequent runs
|
||||
#[clap(short, long)]
|
||||
port: Option<u16>,
|
||||
|
||||
/// Path to .json file containing custom network specification.
|
||||
#[clap(long, group = "network", hide = true)]
|
||||
custom_mixnet: Option<PathBuf>,
|
||||
|
||||
/// Mostly debug-related option to increase default traffic rate so that you would not need to
|
||||
/// modify config post init
|
||||
#[clap(long, hide = true)]
|
||||
fastmode: bool,
|
||||
|
||||
/// Disable loop cover traffic and the Poisson rate limiter (for debugging only)
|
||||
#[clap(long, hide = true)]
|
||||
no_cover: bool,
|
||||
|
||||
/// Set this client to work in a enabled credentials mode that would attempt to use gateway
|
||||
/// with bandwidth credential requirement.
|
||||
#[clap(long, hide = true)]
|
||||
enabled_credentials_mode: Option<bool>,
|
||||
/// The custom host on which the socks5 client will be listening for requests
|
||||
#[clap(long)]
|
||||
host: Option<IpAddr>,
|
||||
|
||||
#[clap(short, long, default_value_t = OutputFormat::default())]
|
||||
output: OutputFormat,
|
||||
}
|
||||
|
||||
impl AsRef<CommonClientInitArgs> for Init {
|
||||
fn as_ref(&self) -> &CommonClientInitArgs {
|
||||
&self.common_args
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Init> for OverrideConfig {
|
||||
fn from(init_config: Init) -> Self {
|
||||
OverrideConfig {
|
||||
nym_apis: init_config.nym_apis,
|
||||
nym_apis: init_config.common_args.nym_apis,
|
||||
ip: init_config.host,
|
||||
port: init_config.port,
|
||||
use_anonymous_replies: init_config.use_reply_surbs,
|
||||
fastmode: init_config.fastmode,
|
||||
no_cover: init_config.no_cover,
|
||||
fastmode: init_config.common_args.fastmode,
|
||||
no_cover: init_config.common_args.no_cover,
|
||||
geo_routing: None,
|
||||
medium_toggle: false,
|
||||
nyxd_urls: init_config.nyxd_urls,
|
||||
enabled_credentials_mode: init_config.enabled_credentials_mode,
|
||||
nyxd_urls: init_config.common_args.nyxd_urls,
|
||||
enabled_credentials_mode: init_config.common_args.enabled_credentials_mode,
|
||||
outfox: false,
|
||||
}
|
||||
}
|
||||
@@ -120,20 +109,16 @@ impl From<Init> for OverrideConfig {
|
||||
pub struct InitResults {
|
||||
#[serde(flatten)]
|
||||
client_core: nym_client_core::init::types::InitResults,
|
||||
socks5_listening_port: u16,
|
||||
socks5_listening_address: SocketAddr,
|
||||
client_address: String,
|
||||
}
|
||||
|
||||
impl InitResults {
|
||||
fn new(config: &Config, address: &Recipient, gateway: &GatewayEndpointConfig) -> Self {
|
||||
fn new(res: InitResultsWithConfig<Config>) -> Self {
|
||||
Self {
|
||||
client_core: nym_client_core::init::types::InitResults::new(
|
||||
&config.core.base,
|
||||
address,
|
||||
gateway,
|
||||
),
|
||||
socks5_listening_port: config.core.socks5.listening_port,
|
||||
client_address: address.to_string(),
|
||||
client_address: res.init_results.address.to_string(),
|
||||
client_core: res.init_results,
|
||||
socks5_listening_address: res.config.core.socks5.bind_adddress,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -141,106 +126,23 @@ impl InitResults {
|
||||
impl Display for InitResults {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
writeln!(f, "{}", self.client_core)?;
|
||||
writeln!(f, "SOCKS5 listening port: {}", self.socks5_listening_port)?;
|
||||
writeln!(
|
||||
f,
|
||||
"SOCKS5 listening address: {}",
|
||||
self.socks5_listening_address
|
||||
)?;
|
||||
write!(f, "Address of this client: {}", self.client_address)
|
||||
}
|
||||
}
|
||||
|
||||
fn init_paths(id: &str) -> io::Result<()> {
|
||||
fs::create_dir_all(default_data_directory(id))?;
|
||||
fs::create_dir_all(default_config_directory(id))
|
||||
}
|
||||
|
||||
pub(crate) async fn execute(args: Init) -> Result<(), Socks5ClientError> {
|
||||
eprintln!("Initialising client...");
|
||||
|
||||
let id = &args.id;
|
||||
let provider_address = &args.provider;
|
||||
let output = args.output;
|
||||
let res = initialise_client::<Socks5ClientInit>(args).await?;
|
||||
|
||||
let already_init = if default_config_filepath(id).exists() {
|
||||
// in case we're using old config, try to upgrade it
|
||||
// (if we're using the current version, it's a no-op)
|
||||
try_upgrade_config(id)?;
|
||||
eprintln!("SOCKS5 client \"{id}\" was already initialised before");
|
||||
true
|
||||
} else {
|
||||
init_paths(id)?;
|
||||
false
|
||||
};
|
||||
|
||||
// Usually you only register with the gateway on the first init, however you can force
|
||||
// re-registering if wanted.
|
||||
let user_wants_force_register = args.force_register_gateway;
|
||||
if user_wants_force_register {
|
||||
eprintln!("Instructed to force registering gateway. This might overwrite keys!");
|
||||
}
|
||||
|
||||
// If the client was already initialized, don't generate new keys and don't re-register with
|
||||
// the gateway (because this would create a new shared key).
|
||||
// Unless the user really wants to.
|
||||
let register_gateway = !already_init || user_wants_force_register;
|
||||
|
||||
// Attempt to use a user-provided gateway, if possible
|
||||
let user_chosen_gateway_id = args.gateway;
|
||||
let selection_spec = GatewaySelectionSpecification::new(
|
||||
user_chosen_gateway_id.map(|id| id.to_base58_string()),
|
||||
Some(args.latency_based_selection),
|
||||
false,
|
||||
);
|
||||
|
||||
// Load and potentially override config
|
||||
let config = override_config(
|
||||
Config::new(id, &provider_address.to_string()),
|
||||
OverrideConfig::from(args.clone()),
|
||||
);
|
||||
|
||||
// Setup gateway by either registering a new one, or creating a new config from the selected
|
||||
// one but with keys kept, or reusing the gateway configuration.
|
||||
let key_store = OnDiskKeys::new(config.storage_paths.common_paths.keys.clone());
|
||||
let details_store =
|
||||
OnDiskGatewayDetails::new(&config.storage_paths.common_paths.gateway_details);
|
||||
|
||||
let available_gateways = if let Some(hardcoded_topology) = args
|
||||
.custom_mixnet
|
||||
.map(NymTopology::new_from_file)
|
||||
.transpose()?
|
||||
{
|
||||
// hardcoded_topology
|
||||
hardcoded_topology.get_gateways()
|
||||
} else {
|
||||
let mut rng = rand::thread_rng();
|
||||
current_gateways(&mut rng, &config.core.base.client.nym_api_urls).await?
|
||||
};
|
||||
|
||||
let gateway_setup = GatewaySetup::New {
|
||||
specification: selection_spec,
|
||||
available_gateways,
|
||||
overwrite_data: register_gateway,
|
||||
};
|
||||
|
||||
let init_details =
|
||||
nym_client_core::init::setup_gateway(gateway_setup, &key_store, &details_store)
|
||||
.await
|
||||
.tap_err(|err| eprintln!("Failed to setup gateway\nError: {err}"))?;
|
||||
|
||||
// TODO: ask the service provider we specified for its interface version and set it in the config
|
||||
|
||||
let config_save_location = config.default_location();
|
||||
config.save_to_default_location().tap_err(|_| {
|
||||
log::error!("Failed to save the config file");
|
||||
})?;
|
||||
eprintln!(
|
||||
"Saved configuration file to {}",
|
||||
config_save_location.display()
|
||||
);
|
||||
|
||||
let address = init_details.client_address()?;
|
||||
|
||||
let GatewayDetails::Configured(gateway_details) = init_details.gateway_details else {
|
||||
return Err(ClientCoreError::UnexpectedPersistedCustomGatewayDetails)?;
|
||||
};
|
||||
let init_results = InitResults::new(&config, &address, &gateway_details);
|
||||
println!("{}", args.output.format(&init_results));
|
||||
let init_results = InitResults::new(res);
|
||||
println!("{}", output.format(&init_results));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
use crate::config::old_config_v1_1_13::OldConfigV1_1_13;
|
||||
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::{BaseClientConfig, Config};
|
||||
use crate::config::old_config_v1_1_30::ConfigV1_1_30;
|
||||
use crate::config::{BaseClientConfig, Config, SocksClientPaths};
|
||||
use crate::error::Socks5ClientError;
|
||||
use clap::CommandFactory;
|
||||
use clap::{Parser, Subcommand};
|
||||
@@ -22,6 +23,7 @@ use nym_client_core::error::ClientCoreError;
|
||||
use nym_config::OptionalSet;
|
||||
use nym_sphinx::params::{PacketSize, PacketType};
|
||||
use std::error::Error;
|
||||
use std::net::IpAddr;
|
||||
|
||||
pub(crate) mod build_info;
|
||||
pub mod init;
|
||||
@@ -72,6 +74,7 @@ pub(crate) enum Commands {
|
||||
// Configuration that can be overridden.
|
||||
pub(crate) struct OverrideConfig {
|
||||
nym_apis: Option<Vec<url::Url>>,
|
||||
ip: Option<IpAddr>,
|
||||
port: Option<u16>,
|
||||
use_anonymous_replies: Option<bool>,
|
||||
fastmode: bool,
|
||||
@@ -145,6 +148,7 @@ pub(crate) fn override_config(config: Config, args: OverrideConfig) -> Config {
|
||||
)
|
||||
.with_optional(Config::with_anonymous_replies, args.use_anonymous_replies)
|
||||
.with_optional(Config::with_port, args.port)
|
||||
.with_optional(Config::with_ip, args.ip)
|
||||
.with_optional_base_custom_env(
|
||||
BaseClientConfig::with_custom_nym_apis,
|
||||
args.nym_apis,
|
||||
@@ -164,12 +168,11 @@ pub(crate) fn override_config(config: Config, args: OverrideConfig) -> Config {
|
||||
}
|
||||
|
||||
fn persist_gateway_details(
|
||||
config: &Config,
|
||||
storage_paths: &SocksClientPaths,
|
||||
details: GatewayEndpointConfig,
|
||||
) -> Result<(), Socks5ClientError> {
|
||||
let details_store =
|
||||
OnDiskGatewayDetails::new(&config.storage_paths.common_paths.gateway_details);
|
||||
let keys_store = OnDiskKeys::new(config.storage_paths.common_paths.keys.clone());
|
||||
let details_store = OnDiskGatewayDetails::new(&storage_paths.common_paths.gateway_details);
|
||||
let keys_store = OnDiskKeys::new(storage_paths.common_paths.keys.clone());
|
||||
let shared_keys = keys_store.ephemeral_load_gateway_keys().map_err(|source| {
|
||||
Socks5ClientError::ClientCoreError(ClientCoreError::KeyStoreError {
|
||||
source: Box::new(source),
|
||||
@@ -199,9 +202,10 @@ fn try_upgrade_v1_1_13_config(id: &str) -> Result<bool, Socks5ClientError> {
|
||||
|
||||
let updated_step1: ConfigV1_1_20 = old_config.into();
|
||||
let updated_step2: ConfigV1_1_20_2 = updated_step1.into();
|
||||
let (updated, gateway_config) = updated_step2.upgrade()?;
|
||||
persist_gateway_details(&updated, gateway_config)?;
|
||||
let (updated_step3, gateway_config) = updated_step2.upgrade()?;
|
||||
persist_gateway_details(&updated_step3.storage_paths, gateway_config)?;
|
||||
|
||||
let updated: Config = updated_step3.into();
|
||||
updated.save_to_default_location()?;
|
||||
Ok(true)
|
||||
}
|
||||
@@ -219,9 +223,10 @@ fn try_upgrade_v1_1_20_config(id: &str) -> Result<bool, Socks5ClientError> {
|
||||
info!("It is going to get updated to the current specification.");
|
||||
|
||||
let updated_step1: ConfigV1_1_20_2 = old_config.into();
|
||||
let (updated, gateway_config) = updated_step1.upgrade()?;
|
||||
persist_gateway_details(&updated, gateway_config)?;
|
||||
let (updated_step2, gateway_config) = updated_step1.upgrade()?;
|
||||
persist_gateway_details(&updated_step2.storage_paths, gateway_config)?;
|
||||
|
||||
let updated: Config = updated_step2.into();
|
||||
updated.save_to_default_location()?;
|
||||
Ok(true)
|
||||
}
|
||||
@@ -236,9 +241,25 @@ fn try_upgrade_v1_1_20_2_config(id: &str) -> Result<bool, Socks5ClientError> {
|
||||
info!("It seems the client is using <= v1.1.20_2 config template.");
|
||||
info!("It is going to get updated to the current specification.");
|
||||
|
||||
let (updated, gateway_config) = old_config.upgrade()?;
|
||||
persist_gateway_details(&updated, gateway_config)?;
|
||||
let (updated_step1, gateway_config) = old_config.upgrade()?;
|
||||
persist_gateway_details(&updated_step1.storage_paths, gateway_config)?;
|
||||
|
||||
let updated: Config = updated_step1.into();
|
||||
updated.save_to_default_location()?;
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
fn try_upgrade_v1_1_30_config(id: &str) -> Result<bool, Socks5ClientError> {
|
||||
// explicitly load it as v1.1.30 (which is incompatible with the current one, i.e. +1.1.31)
|
||||
let Ok(old_config) = ConfigV1_1_30::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.30 config template.");
|
||||
info!("It is going to get updated to the current specification.");
|
||||
|
||||
let updated: Config = old_config.into();
|
||||
updated.save_to_default_location()?;
|
||||
Ok(true)
|
||||
}
|
||||
@@ -253,6 +274,9 @@ fn try_upgrade_config(id: &str) -> Result<(), Socks5ClientError> {
|
||||
if try_upgrade_v1_1_20_2_config(id)? {
|
||||
return Ok(());
|
||||
}
|
||||
if try_upgrade_v1_1_30_config(id)? {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -10,18 +10,17 @@ use crate::{
|
||||
use clap::Args;
|
||||
use log::*;
|
||||
use nym_bin_common::version_checker::is_minor_version_compatible;
|
||||
use nym_client_core::cli_helpers::client_run::CommonClientRunArgs;
|
||||
use nym_client_core::client::base_client::storage::OnDiskPersistent;
|
||||
use nym_client_core::client::topology_control::geo_aware_provider::CountryGroup;
|
||||
use nym_crypto::asymmetric::identity;
|
||||
use nym_socks5_client_core::NymClient;
|
||||
use nym_sphinx::addressing::clients::Recipient;
|
||||
use std::path::PathBuf;
|
||||
use std::net::IpAddr;
|
||||
|
||||
#[derive(Args, Clone)]
|
||||
pub(crate) struct Run {
|
||||
/// Id of the nym-mixnet-client we want to run.
|
||||
#[clap(long)]
|
||||
id: String,
|
||||
#[command(flatten)]
|
||||
common_args: CommonClientRunArgs,
|
||||
|
||||
/// Specifies whether this client is going to use an anonymous sender tag for communication with the service provider.
|
||||
/// While this is going to hide its actual address information, it will make the actual communication
|
||||
@@ -36,35 +35,13 @@ pub(crate) struct Run {
|
||||
#[clap(long)]
|
||||
provider: Option<Recipient>,
|
||||
|
||||
/// Id of the gateway we want to connect to. If overridden, it is user's responsibility to
|
||||
/// ensure prior registration happened
|
||||
#[clap(long)]
|
||||
gateway: Option<identity::PublicKey>,
|
||||
|
||||
/// Comma separated list of rest endpoints of the nyxd validators
|
||||
#[clap(long, alias = "nyxd_validators", value_delimiter = ',', hide = true)]
|
||||
nyxd_urls: Option<Vec<url::Url>>,
|
||||
|
||||
/// Comma separated list of rest endpoints of the Nym APIs
|
||||
#[clap(long, value_delimiter = ',', group = "network")]
|
||||
nym_apis: Option<Vec<url::Url>>,
|
||||
|
||||
/// Port for the socket to listen on
|
||||
#[clap(short, long)]
|
||||
port: Option<u16>,
|
||||
|
||||
/// Path to .json file containing custom network specification.
|
||||
#[clap(long, group = "network", group = "routing", hide = true)]
|
||||
custom_mixnet: Option<PathBuf>,
|
||||
|
||||
/// Mostly debug-related option to increase default traffic rate so that you would not need to
|
||||
/// modify config post init
|
||||
#[clap(long, hide = true)]
|
||||
fastmode: bool,
|
||||
|
||||
/// Disable loop cover traffic and the Poisson rate limiter (for debugging only)
|
||||
#[clap(long, hide = true)]
|
||||
no_cover: bool,
|
||||
/// The custom host on which the socks5 client will be listening for requests
|
||||
#[clap(long)]
|
||||
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")]
|
||||
@@ -75,11 +52,6 @@ pub(crate) struct Run {
|
||||
#[clap(long, hide = true)]
|
||||
medium_toggle: bool,
|
||||
|
||||
/// Set this client to work in a enabled credentials mode that would attempt to use gateway
|
||||
/// with bandwidth credential requirement.
|
||||
#[clap(long, hide = true)]
|
||||
enabled_credentials_mode: Option<bool>,
|
||||
|
||||
#[clap(long, hide = true, action)]
|
||||
outfox: bool,
|
||||
}
|
||||
@@ -87,15 +59,16 @@ pub(crate) struct Run {
|
||||
impl From<Run> for OverrideConfig {
|
||||
fn from(run_config: Run) -> Self {
|
||||
OverrideConfig {
|
||||
nym_apis: run_config.nym_apis,
|
||||
nym_apis: run_config.common_args.nym_apis,
|
||||
ip: run_config.host,
|
||||
port: run_config.port,
|
||||
use_anonymous_replies: run_config.use_anonymous_replies,
|
||||
fastmode: run_config.fastmode,
|
||||
no_cover: run_config.no_cover,
|
||||
fastmode: run_config.common_args.fastmode,
|
||||
no_cover: run_config.common_args.no_cover,
|
||||
geo_routing: run_config.geo_routing,
|
||||
medium_toggle: run_config.medium_toggle,
|
||||
nyxd_urls: run_config.nyxd_urls,
|
||||
enabled_credentials_mode: run_config.enabled_credentials_mode,
|
||||
nyxd_urls: run_config.common_args.nyxd_urls,
|
||||
enabled_credentials_mode: run_config.common_args.enabled_credentials_mode,
|
||||
outfox: run_config.outfox,
|
||||
}
|
||||
}
|
||||
@@ -130,9 +103,9 @@ fn version_check(cfg: &Config) -> bool {
|
||||
}
|
||||
|
||||
pub(crate) async fn execute(args: Run) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
||||
eprintln!("Starting client {}...", args.id);
|
||||
eprintln!("Starting client {}...", args.common_args.id);
|
||||
|
||||
let mut config = try_load_current_config(&args.id)?;
|
||||
let mut config = try_load_current_config(&args.common_args.id)?;
|
||||
config = override_config(config, OverrideConfig::from(args.clone()));
|
||||
|
||||
if !version_check(&config) {
|
||||
@@ -143,7 +116,7 @@ pub(crate) async fn execute(args: Run) -> Result<(), Box<dyn std::error::Error +
|
||||
let storage =
|
||||
OnDiskPersistent::from_paths(config.storage_paths.common_paths, &config.core.base.debug)
|
||||
.await?;
|
||||
NymClient::new(config.core, storage, args.custom_mixnet)
|
||||
NymClient::new(config.core, storage, args.common_args.custom_mixnet)
|
||||
.run_forever()
|
||||
.await
|
||||
}
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::config::persistence::SocksClientPaths;
|
||||
use crate::config::template::CONFIG_TEMPLATE;
|
||||
use nym_bin_common::logging::LoggingSettings;
|
||||
use nym_client_core::cli_helpers::client_init::ClientConfig;
|
||||
use nym_client_core::config::disk_persistence::CommonClientPaths;
|
||||
use nym_config::{
|
||||
must_get_home, read_config_from_toml_file, save_formatted_config_to_file, NymConfigTemplate,
|
||||
DEFAULT_CONFIG_DIR, DEFAULT_CONFIG_FILENAME, DEFAULT_DATA_DIR, NYM_DIR,
|
||||
@@ -11,15 +12,18 @@ use nym_config::{
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt::Debug;
|
||||
use std::io;
|
||||
use std::net::IpAddr;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::str::FromStr;
|
||||
|
||||
pub use crate::config::persistence::SocksClientPaths;
|
||||
pub use nym_client_core::config::Config as BaseClientConfig;
|
||||
pub use nym_socks5_client_core::config::Config as CoreConfig;
|
||||
|
||||
pub mod old_config_v1_1_13;
|
||||
pub mod old_config_v1_1_20;
|
||||
pub mod old_config_v1_1_20_2;
|
||||
pub mod old_config_v1_1_30;
|
||||
mod persistence;
|
||||
mod template;
|
||||
|
||||
@@ -67,6 +71,24 @@ impl NymConfigTemplate for Config {
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientConfig for Config {
|
||||
fn common_paths(&self) -> &CommonClientPaths {
|
||||
&self.storage_paths.common_paths
|
||||
}
|
||||
|
||||
fn core_config(&self) -> &BaseClientConfig {
|
||||
&self.core.base
|
||||
}
|
||||
|
||||
fn default_store_location(&self) -> PathBuf {
|
||||
self.default_location()
|
||||
}
|
||||
|
||||
fn save_to<P: AsRef<Path>>(&self, path: P) -> io::Result<()> {
|
||||
save_formatted_config_to_file(self, path)
|
||||
}
|
||||
}
|
||||
|
||||
impl Config {
|
||||
pub fn new<S: AsRef<str>>(id: S, provider_mix_address: S) -> Self {
|
||||
Config {
|
||||
@@ -102,8 +124,15 @@ impl Config {
|
||||
self.core.validate()
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn with_port(mut self, port: u16) -> Self {
|
||||
self.core.socks5.listening_port = port;
|
||||
self.core = self.core.with_port(port);
|
||||
self
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn with_ip(mut self, ip: IpAddr) -> Self {
|
||||
self.core = self.core.with_ip(ip);
|
||||
self
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::config::old_config_v1_1_30::ConfigV1_1_30;
|
||||
use crate::{
|
||||
config::{default_config_filepath, persistence::SocksClientPaths, Config},
|
||||
config::{default_config_filepath, persistence::SocksClientPaths},
|
||||
error::Socks5ClientError,
|
||||
};
|
||||
|
||||
use nym_bin_common::logging::LoggingSettings;
|
||||
use nym_client_core::config::disk_persistence::old_v1_1_20_2::CommonClientPathsV1_1_20_2;
|
||||
use nym_client_core::config::GatewayEndpointConfig;
|
||||
@@ -43,9 +43,9 @@ impl ConfigV1_1_20_2 {
|
||||
|
||||
// in this upgrade, gateway endpoint configuration was moved out of the config file,
|
||||
// so its returned to be stored elsewhere.
|
||||
pub fn upgrade(self) -> Result<(Config, GatewayEndpointConfig), Socks5ClientError> {
|
||||
pub fn upgrade(self) -> Result<(ConfigV1_1_30, GatewayEndpointConfig), Socks5ClientError> {
|
||||
let gateway_details = self.core.base.client.gateway_endpoint.clone().into();
|
||||
let config = Config {
|
||||
let config = ConfigV1_1_30 {
|
||||
core: self.core.into(),
|
||||
storage_paths: SocksClientPaths {
|
||||
common_paths: self.storage_paths.common_paths.upgrade_default()?,
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::config::persistence::SocksClientPaths;
|
||||
use crate::config::{default_config_filepath, Config};
|
||||
use nym_bin_common::logging::LoggingSettings;
|
||||
use nym_config::read_config_from_toml_file;
|
||||
use nym_socks5_client_core::config::old_config_v1_1_30::ConfigV1_1_30 as CoreConfigV1_1_30;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::io;
|
||||
use std::path::Path;
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct ConfigV1_1_30 {
|
||||
pub core: CoreConfigV1_1_30,
|
||||
|
||||
// I'm leaving a landmine here for when the paths actually do change the next time,
|
||||
// but propagating the change right now (in ALL clients) would be such a hassle...,
|
||||
// so sorry for the next person looking at it : )
|
||||
pub storage_paths: SocksClientPaths,
|
||||
|
||||
pub logging: LoggingSettings,
|
||||
}
|
||||
|
||||
impl From<ConfigV1_1_30> for Config {
|
||||
fn from(value: ConfigV1_1_30) -> Self {
|
||||
Config {
|
||||
core: value.core.into(),
|
||||
storage_paths: value.storage_paths,
|
||||
logging: LoggingSettings::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ConfigV1_1_30 {
|
||||
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))
|
||||
}
|
||||
}
|
||||
@@ -75,8 +75,9 @@ gateway_details = '{{ storage_paths.gateway_details }}'
|
||||
# The mix address of the provider to which all requests are going to be sent.
|
||||
provider_mix_address = '{{ core.socks5.provider_mix_address }}'
|
||||
|
||||
# The port on which the client will be listening for incoming requests
|
||||
listening_port = {{ core.socks5.listening_port }}
|
||||
# The address on which the client will be listening for incoming requests
|
||||
# (default: 127.0.0.1:1080)
|
||||
bind_adddress = '{{ core.socks5.bind_adddress }}'
|
||||
|
||||
# Specifies whether this client is going to use an anonymous sender tag for communication with the service provider.
|
||||
# While this is going to hide its actual address information, it will make the actual communication
|
||||
|
||||
@@ -8,7 +8,7 @@ edition = "2021"
|
||||
[dependencies]
|
||||
bip39 = { workspace = true }
|
||||
rand = "0.7.3"
|
||||
thiserror = "1.0"
|
||||
thiserror = { workspace = true }
|
||||
url = { workspace = true }
|
||||
|
||||
nym-coconut-interface = { path = "../coconut-interface" }
|
||||
|
||||
@@ -9,12 +9,13 @@ repository = { workspace = true }
|
||||
|
||||
[dependencies]
|
||||
atty = "0.2"
|
||||
clap = { version = "4.0", features = ["derive"] }
|
||||
clap = { workspace = true, features = ["derive"] }
|
||||
clap_complete = "4.0"
|
||||
clap_complete_fig = "4.0"
|
||||
log = { workspace = true }
|
||||
pretty_env_logger = "0.4.0"
|
||||
semver = "0.11"
|
||||
schemars = { workspace = true, features = ["preserve_order"], optional = true }
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
serde_json = { workspace = true, optional = true }
|
||||
|
||||
@@ -29,6 +30,7 @@ opentelemetry-jaeger = { version = "0.18.0", optional = true, features = [
|
||||
"isahc_collector_client",
|
||||
] }
|
||||
tracing-opentelemetry = { version = "0.19.0", optional = true }
|
||||
utoipa = { workspace = true, optional = true }
|
||||
opentelemetry = { version = "0.19.0", optional = true, features = ["rt-tokio"] }
|
||||
|
||||
|
||||
@@ -42,7 +44,9 @@ vergen = { version = "=7.4.3", default-features = false, features = [
|
||||
|
||||
[features]
|
||||
default = []
|
||||
openapi = ["utoipa"]
|
||||
output_format = ["serde_json"]
|
||||
bin_info_schema = ["schemars"]
|
||||
tracing = [
|
||||
"tracing-subscriber",
|
||||
"tracing-tree",
|
||||
|
||||
@@ -81,6 +81,8 @@ impl BinaryBuildInformation {
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "bin_info_schema", derive(schemars::JsonSchema))]
|
||||
pub struct BinaryBuildInformationOwned {
|
||||
/// Provides the name of the binary, i.e. the content of `CARGO_PKG_NAME` environmental variable.
|
||||
pub binary_name: String,
|
||||
|
||||
@@ -11,6 +11,7 @@ rust-version = "1.66"
|
||||
async-trait = { workspace = true }
|
||||
base64 = "0.21.2"
|
||||
cfg-if = "1.0.0"
|
||||
clap = { workspace = true, optional = true }
|
||||
dashmap = { workspace = true }
|
||||
dirs = "4.0"
|
||||
futures = { workspace = true }
|
||||
@@ -92,6 +93,7 @@ sqlx = { version = "0.6.2", features = ["runtime-tokio-rustls", "sqlite", "macro
|
||||
|
||||
[features]
|
||||
default = []
|
||||
cli = ["clap"]
|
||||
fs-surb-storage = ["sqlx"]
|
||||
wasm = ["nym-gateway-client/wasm"]
|
||||
|
||||
|
||||
@@ -0,0 +1,210 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::config::disk_persistence::CommonClientPaths;
|
||||
use crate::error::ClientCoreError;
|
||||
use crate::{
|
||||
client::{
|
||||
base_client::storage::gateway_details::OnDiskGatewayDetails,
|
||||
key_manager::persistence::OnDiskKeys,
|
||||
},
|
||||
init::types::{GatewayDetails, GatewaySelectionSpecification, GatewaySetup, InitResults},
|
||||
};
|
||||
use log::info;
|
||||
use nym_crypto::asymmetric::identity;
|
||||
use nym_topology::NymTopology;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
pub trait InitialisableClient {
|
||||
const NAME: &'static str;
|
||||
type Error: From<ClientCoreError>;
|
||||
type InitArgs: AsRef<CommonClientInitArgs>;
|
||||
type Config: ClientConfig;
|
||||
|
||||
fn try_upgrade_outdated_config(id: &str) -> Result<(), Self::Error>;
|
||||
|
||||
fn initialise_storage_paths(id: &str) -> Result<(), Self::Error>;
|
||||
|
||||
fn default_config_path(id: &str) -> PathBuf;
|
||||
|
||||
fn construct_config(init_args: &Self::InitArgs) -> Self::Config;
|
||||
}
|
||||
|
||||
pub trait ClientConfig {
|
||||
fn common_paths(&self) -> &CommonClientPaths;
|
||||
|
||||
fn core_config(&self) -> &crate::config::Config;
|
||||
|
||||
fn default_store_location(&self) -> PathBuf;
|
||||
|
||||
fn save_to<P: AsRef<Path>>(&self, path: P) -> std::io::Result<()>;
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "cli", derive(clap::Args))]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct CommonClientInitArgs {
|
||||
/// Id of client we want to create config for.
|
||||
#[cfg_attr(feature = "cli", clap(long))]
|
||||
pub id: String,
|
||||
|
||||
/// Id of the gateway we are going to connect to.
|
||||
#[cfg_attr(feature = "cli", clap(long))]
|
||||
pub gateway: Option<identity::PublicKey>,
|
||||
|
||||
/// Specifies whether the new gateway should be determined based by latency as opposed to being chosen
|
||||
/// uniformly.
|
||||
#[cfg_attr(feature = "cli", clap(long, conflicts_with = "gateway"))]
|
||||
pub latency_based_selection: bool,
|
||||
|
||||
/// Force register gateway. WARNING: this will overwrite any existing keys for the given id,
|
||||
/// potentially causing loss of access.
|
||||
#[cfg_attr(feature = "cli", clap(long))]
|
||||
pub force_register_gateway: bool,
|
||||
|
||||
/// Comma separated list of rest endpoints of the nyxd validators
|
||||
#[cfg_attr(
|
||||
feature = "cli",
|
||||
clap(long, alias = "nyxd_validators", value_delimiter = ',', hide = true)
|
||||
)]
|
||||
pub nyxd_urls: Option<Vec<url::Url>>,
|
||||
|
||||
/// Comma separated list of rest endpoints of the API validators
|
||||
#[cfg_attr(
|
||||
feature = "cli",
|
||||
clap(
|
||||
long,
|
||||
alias = "api_validators",
|
||||
value_delimiter = ',',
|
||||
group = "network"
|
||||
)
|
||||
)]
|
||||
pub nym_apis: Option<Vec<url::Url>>,
|
||||
|
||||
/// Path to .json file containing custom network specification.
|
||||
#[cfg_attr(feature = "cli", clap(long, group = "network", hide = true))]
|
||||
pub custom_mixnet: Option<PathBuf>,
|
||||
|
||||
/// Set this client to work in a enabled credentials mode that would attempt to use gateway
|
||||
/// with bandwidth credential requirement.
|
||||
#[cfg_attr(feature = "cli", clap(long, hide = true))]
|
||||
pub enabled_credentials_mode: Option<bool>,
|
||||
|
||||
/// Mostly debug-related option to increase default traffic rate so that you would not need to
|
||||
/// modify config post init
|
||||
#[cfg_attr(feature = "cli", clap(long, hide = true))]
|
||||
pub fastmode: bool,
|
||||
|
||||
/// Disable loop cover traffic and the Poisson rate limiter (for debugging only)
|
||||
#[cfg_attr(feature = "cli", clap(long, hide = true))]
|
||||
pub no_cover: bool,
|
||||
}
|
||||
|
||||
pub struct InitResultsWithConfig<T> {
|
||||
pub config: T,
|
||||
pub init_results: InitResults,
|
||||
}
|
||||
|
||||
pub async fn initialise_client<C>(
|
||||
init_args: C::InitArgs,
|
||||
) -> Result<InitResultsWithConfig<C::Config>, C::Error>
|
||||
where
|
||||
C: InitialisableClient,
|
||||
{
|
||||
info!("initialising {} client", C::NAME);
|
||||
|
||||
let common_args = init_args.as_ref();
|
||||
let id = &common_args.id;
|
||||
|
||||
let already_init = if C::default_config_path(id).exists() {
|
||||
// in case we're using old config, try to upgrade it
|
||||
// (if we're using the current version, it's a no-op)
|
||||
C::try_upgrade_outdated_config(id)?;
|
||||
eprintln!("{} client \"{id}\" was already initialised before", C::NAME);
|
||||
true
|
||||
} else {
|
||||
C::initialise_storage_paths(id)?;
|
||||
false
|
||||
};
|
||||
|
||||
// Usually you only register with the gateway on the first init, however you can force
|
||||
// re-registering if wanted.
|
||||
let user_wants_force_register = common_args.force_register_gateway;
|
||||
if user_wants_force_register {
|
||||
eprintln!("Instructed to force registering gateway. This might overwrite keys!");
|
||||
}
|
||||
|
||||
// If the client was already initialized, don't generate new keys and don't re-register with
|
||||
// the gateway (because this would create a new shared key).
|
||||
// Unless the user really wants to.
|
||||
let register_gateway = !already_init || user_wants_force_register;
|
||||
|
||||
// Attempt to use a user-provided gateway, if possible
|
||||
let user_chosen_gateway_id = common_args.gateway;
|
||||
let selection_spec = GatewaySelectionSpecification::new(
|
||||
user_chosen_gateway_id.map(|id| id.to_base58_string()),
|
||||
Some(common_args.latency_based_selection),
|
||||
false,
|
||||
);
|
||||
|
||||
// Load and potentially override config
|
||||
let config = C::construct_config(&init_args);
|
||||
let paths = config.common_paths();
|
||||
let core = config.core_config();
|
||||
|
||||
// Setup gateway by either registering a new one, or creating a new config from the selected
|
||||
// one but with keys kept, or reusing the gateway configuration.
|
||||
let key_store = OnDiskKeys::new(paths.keys.clone());
|
||||
let details_store = OnDiskGatewayDetails::new(&paths.gateway_details);
|
||||
|
||||
let available_gateways = if let Some(custom_mixnet) = common_args.custom_mixnet.as_ref() {
|
||||
let hardcoded_topology = NymTopology::new_from_file(custom_mixnet).map_err(|source| {
|
||||
ClientCoreError::CustomTopologyLoadFailure {
|
||||
file_path: custom_mixnet.clone(),
|
||||
source,
|
||||
}
|
||||
})?;
|
||||
hardcoded_topology.get_gateways()
|
||||
} else {
|
||||
let mut rng = rand::thread_rng();
|
||||
crate::init::helpers::current_gateways(&mut rng, &core.client.nym_api_urls).await?
|
||||
};
|
||||
|
||||
let gateway_setup = GatewaySetup::New {
|
||||
specification: selection_spec,
|
||||
available_gateways,
|
||||
overwrite_data: register_gateway,
|
||||
};
|
||||
|
||||
let init_details =
|
||||
crate::init::setup_gateway(gateway_setup, &key_store, &details_store).await?;
|
||||
|
||||
// TODO: ask the service provider we specified for its interface version and set it in the config
|
||||
|
||||
let config_save_location = config.default_store_location();
|
||||
if let Err(err) = config.save_to(&config_save_location) {
|
||||
return Err(ClientCoreError::ConfigSaveFailure {
|
||||
typ: C::NAME.to_string(),
|
||||
id: id.to_string(),
|
||||
path: config_save_location,
|
||||
source: err,
|
||||
}
|
||||
.into());
|
||||
}
|
||||
|
||||
eprintln!(
|
||||
"Saved configuration file to {}",
|
||||
config_save_location.display()
|
||||
);
|
||||
|
||||
let address = init_details.client_address()?;
|
||||
|
||||
let GatewayDetails::Configured(gateway_details) = init_details.gateway_details else {
|
||||
return Err(ClientCoreError::UnexpectedPersistedCustomGatewayDetails)?;
|
||||
};
|
||||
let init_results = InitResults::new(config.core_config(), address, &gateway_details);
|
||||
|
||||
Ok(InitResultsWithConfig {
|
||||
config,
|
||||
init_results,
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use nym_crypto::asymmetric::identity;
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[cfg_attr(feature = "cli", derive(clap::Args))]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct CommonClientRunArgs {
|
||||
/// Id of client we want to create config for.
|
||||
#[cfg_attr(feature = "cli", clap(long))]
|
||||
pub id: String,
|
||||
|
||||
/// Id of the gateway we want to connect to. If overridden, it is user's responsibility to
|
||||
/// ensure prior registration happened
|
||||
#[cfg_attr(feature = "cli", clap(long))]
|
||||
pub gateway: Option<identity::PublicKey>,
|
||||
|
||||
/// Comma separated list of rest endpoints of the nyxd validators
|
||||
#[cfg_attr(
|
||||
feature = "cli",
|
||||
clap(long, alias = "nyxd_validators", value_delimiter = ',', hide = true)
|
||||
)]
|
||||
pub nyxd_urls: Option<Vec<url::Url>>,
|
||||
|
||||
/// Comma separated list of rest endpoints of the API validators
|
||||
#[cfg_attr(
|
||||
feature = "cli",
|
||||
clap(
|
||||
long,
|
||||
alias = "api_validators",
|
||||
value_delimiter = ',',
|
||||
group = "network"
|
||||
)
|
||||
)]
|
||||
pub nym_apis: Option<Vec<url::Url>>,
|
||||
|
||||
/// Path to .json file containing custom network specification.
|
||||
#[cfg_attr(feature = "cli", clap(long, group = "network", hide = true))]
|
||||
pub custom_mixnet: Option<PathBuf>,
|
||||
|
||||
/// Set this client to work in a enabled credentials mode that would attempt to use gateway
|
||||
/// with bandwidth credential requirement.
|
||||
#[cfg_attr(feature = "cli", clap(long, hide = true))]
|
||||
pub enabled_credentials_mode: Option<bool>,
|
||||
|
||||
/// Mostly debug-related option to increase default traffic rate so that you would not need to
|
||||
/// modify config post init
|
||||
// note: we removed the 'conflicts_with = medium_toggle', but that's fine since NR
|
||||
// has defined the conflict on that field itself
|
||||
#[cfg_attr(feature = "cli", clap(long, hide = true))]
|
||||
pub fastmode: bool,
|
||||
|
||||
/// Disable loop cover traffic and the Poisson rate limiter (for debugging only)
|
||||
// note: we removed the 'conflicts_with = medium_toggle', but that's fine since NR
|
||||
// has defined the conflict on that field itself
|
||||
#[cfg_attr(feature = "cli", clap(long, hide = true))]
|
||||
pub no_cover: bool,
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
pub mod client_init;
|
||||
pub mod client_run;
|
||||
@@ -69,7 +69,7 @@ impl NymApiTopologyProvider {
|
||||
Ok(mixes) => mixes,
|
||||
};
|
||||
|
||||
let gateways = match self.validator_client.get_cached_gateways().await {
|
||||
let gateways = match self.validator_client.get_cached_described_gateways().await {
|
||||
Err(err) => {
|
||||
error!("failed to get network gateways - {err}");
|
||||
return None;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::{client::topology_control::geo_aware_provider::CountryGroup, error::ClientCoreError};
|
||||
use nym_config::defaults::NymNetworkDetails;
|
||||
use nym_crypto::asymmetric::identity;
|
||||
use nym_gateway_client::client::GatewayConfig;
|
||||
@@ -12,7 +13,6 @@ use serde::{Deserialize, Serialize};
|
||||
use std::time::Duration;
|
||||
use url::Url;
|
||||
|
||||
use crate::{client::topology_control::geo_aware_provider::CountryGroup, error::ClientCoreError};
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
@@ -20,6 +20,7 @@ pub mod disk_persistence;
|
||||
pub mod old_config_v1_1_13;
|
||||
pub mod old_config_v1_1_20;
|
||||
pub mod old_config_v1_1_20_2;
|
||||
pub mod old_config_v1_1_30;
|
||||
|
||||
// 'DEBUG'
|
||||
const DEFAULT_ACK_WAIT_MULTIPLIER: f64 = 1.5;
|
||||
@@ -280,29 +281,24 @@ impl GatewayEndpointConfig {
|
||||
.map_err(ClientCoreError::UnableToCreatePublicKeyFromGatewayId)
|
||||
}
|
||||
|
||||
pub fn from_node(node: nym_topology::gateway::Node, use_tls: bool) -> Self {
|
||||
// TODO: in the future this shall return a Result and explicit `use_tls` will be removed in favour of the tls info being available on the struct
|
||||
if use_tls {
|
||||
Self::from_topology_node_tls(node)
|
||||
pub fn from_node(
|
||||
node: nym_topology::gateway::Node,
|
||||
must_use_tls: bool,
|
||||
) -> Result<Self, ClientCoreError> {
|
||||
let gateway_listener = if must_use_tls {
|
||||
node.clients_address_tls()
|
||||
.ok_or(ClientCoreError::UnsupportedWssProtocol {
|
||||
gateway: node.identity_key.to_base58_string(),
|
||||
})?
|
||||
} else {
|
||||
Self::from_topology_node_no_tls(node)
|
||||
}
|
||||
}
|
||||
node.clients_address()
|
||||
};
|
||||
|
||||
pub fn from_topology_node_no_tls(node: nym_topology::gateway::Node) -> Self {
|
||||
GatewayEndpointConfig {
|
||||
Ok(GatewayEndpointConfig {
|
||||
gateway_id: node.identity_key.to_base58_string(),
|
||||
gateway_listener: node.clients_address(),
|
||||
gateway_listener,
|
||||
gateway_owner: node.owner,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_topology_node_tls(node: nym_topology::gateway::Node) -> Self {
|
||||
GatewayEndpointConfig {
|
||||
gateway_id: node.identity_key.to_base58_string(),
|
||||
gateway_listener: node.clients_address_tls(),
|
||||
gateway_owner: node.owner,
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::config::{
|
||||
Acknowledgements, Client, Config, CoverTraffic, DebugConfig, GatewayConnection,
|
||||
GatewayEndpointConfig, ReplySurbs, Topology, Traffic,
|
||||
use crate::config::old_config_v1_1_30::{
|
||||
AcknowledgementsV1_1_30, ClientV1_1_30, ConfigV1_1_30, CoverTrafficV1_1_30, DebugConfigV1_1_30,
|
||||
GatewayConnectionV1_1_30, ReplySurbsV1_1_30, TopologyV1_1_30, TrafficV1_1_30,
|
||||
};
|
||||
use crate::config::GatewayEndpointConfig;
|
||||
use nym_sphinx::params::{PacketSize, PacketType};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::time::Duration;
|
||||
@@ -58,9 +59,9 @@ pub struct ConfigV1_1_20_2 {
|
||||
pub debug: DebugConfigV1_1_20_2,
|
||||
}
|
||||
|
||||
impl From<ConfigV1_1_20_2> for Config {
|
||||
impl From<ConfigV1_1_20_2> for ConfigV1_1_30 {
|
||||
fn from(value: ConfigV1_1_20_2) -> Self {
|
||||
Config {
|
||||
ConfigV1_1_30 {
|
||||
client: value.client.into(),
|
||||
debug: value.debug.into(),
|
||||
}
|
||||
@@ -107,9 +108,9 @@ pub struct ClientV1_1_20_2 {
|
||||
pub gateway_endpoint: GatewayEndpointConfigV1_1_20_2,
|
||||
}
|
||||
|
||||
impl From<ClientV1_1_20_2> for Client {
|
||||
impl From<ClientV1_1_20_2> for ClientV1_1_30 {
|
||||
fn from(value: ClientV1_1_20_2) -> Self {
|
||||
Client {
|
||||
ClientV1_1_30 {
|
||||
version: value.version,
|
||||
id: value.id,
|
||||
disabled_credentials_mode: value.disabled_credentials_mode,
|
||||
@@ -132,9 +133,9 @@ pub struct TrafficV1_1_20_2 {
|
||||
pub packet_type: PacketType,
|
||||
}
|
||||
|
||||
impl From<TrafficV1_1_20_2> for Traffic {
|
||||
impl From<TrafficV1_1_20_2> for TrafficV1_1_30 {
|
||||
fn from(value: TrafficV1_1_20_2) -> Self {
|
||||
Traffic {
|
||||
TrafficV1_1_30 {
|
||||
average_packet_delay: value.average_packet_delay,
|
||||
message_sending_average_delay: value.message_sending_average_delay,
|
||||
disable_main_poisson_packet_distribution: value
|
||||
@@ -168,9 +169,9 @@ pub struct CoverTrafficV1_1_20_2 {
|
||||
pub disable_loop_cover_traffic_stream: bool,
|
||||
}
|
||||
|
||||
impl From<CoverTrafficV1_1_20_2> for CoverTraffic {
|
||||
impl From<CoverTrafficV1_1_20_2> for CoverTrafficV1_1_30 {
|
||||
fn from(value: CoverTrafficV1_1_20_2) -> Self {
|
||||
CoverTraffic {
|
||||
CoverTrafficV1_1_30 {
|
||||
loop_cover_traffic_average_delay: value.loop_cover_traffic_average_delay,
|
||||
cover_traffic_primary_size_ratio: value.cover_traffic_primary_size_ratio,
|
||||
disable_loop_cover_traffic_stream: value.disable_loop_cover_traffic_stream,
|
||||
@@ -195,9 +196,9 @@ pub struct GatewayConnectionV1_1_20_2 {
|
||||
pub gateway_response_timeout: Duration,
|
||||
}
|
||||
|
||||
impl From<GatewayConnectionV1_1_20_2> for GatewayConnection {
|
||||
impl From<GatewayConnectionV1_1_20_2> for GatewayConnectionV1_1_30 {
|
||||
fn from(value: GatewayConnectionV1_1_20_2) -> Self {
|
||||
GatewayConnection {
|
||||
GatewayConnectionV1_1_30 {
|
||||
gateway_response_timeout: value.gateway_response_timeout,
|
||||
}
|
||||
}
|
||||
@@ -221,9 +222,9 @@ pub struct AcknowledgementsV1_1_20_2 {
|
||||
pub ack_wait_addition: Duration,
|
||||
}
|
||||
|
||||
impl From<AcknowledgementsV1_1_20_2> for Acknowledgements {
|
||||
impl From<AcknowledgementsV1_1_20_2> for AcknowledgementsV1_1_30 {
|
||||
fn from(value: AcknowledgementsV1_1_20_2) -> Self {
|
||||
Acknowledgements {
|
||||
AcknowledgementsV1_1_30 {
|
||||
average_ack_delay: value.average_ack_delay,
|
||||
ack_wait_multiplier: value.ack_wait_multiplier,
|
||||
ack_wait_addition: value.ack_wait_addition,
|
||||
@@ -261,9 +262,9 @@ impl Default for TopologyV1_1_20_2 {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<TopologyV1_1_20_2> for Topology {
|
||||
impl From<TopologyV1_1_20_2> for TopologyV1_1_30 {
|
||||
fn from(value: TopologyV1_1_20_2) -> Self {
|
||||
Topology {
|
||||
TopologyV1_1_30 {
|
||||
topology_refresh_rate: value.topology_refresh_rate,
|
||||
topology_resolution_timeout: value.topology_resolution_timeout,
|
||||
disable_refreshing: value.disable_refreshing,
|
||||
@@ -307,9 +308,9 @@ impl Default for ReplySurbsV1_1_20_2 {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ReplySurbsV1_1_20_2> for ReplySurbs {
|
||||
impl From<ReplySurbsV1_1_20_2> for ReplySurbsV1_1_30 {
|
||||
fn from(value: ReplySurbsV1_1_20_2) -> Self {
|
||||
ReplySurbs {
|
||||
ReplySurbsV1_1_30 {
|
||||
minimum_reply_surb_storage_threshold: value.minimum_reply_surb_storage_threshold,
|
||||
maximum_reply_surb_storage_threshold: value.maximum_reply_surb_storage_threshold,
|
||||
minimum_reply_surb_request_size: value.minimum_reply_surb_request_size,
|
||||
@@ -335,9 +336,9 @@ pub struct DebugConfigV1_1_20_2 {
|
||||
pub reply_surbs: ReplySurbsV1_1_20_2,
|
||||
}
|
||||
|
||||
impl From<DebugConfigV1_1_20_2> for DebugConfig {
|
||||
impl From<DebugConfigV1_1_20_2> for DebugConfigV1_1_30 {
|
||||
fn from(value: DebugConfigV1_1_20_2) -> Self {
|
||||
DebugConfig {
|
||||
DebugConfigV1_1_30 {
|
||||
traffic: value.traffic.into(),
|
||||
cover_traffic: value.cover_traffic.into(),
|
||||
gateway_connection: value.gateway_connection.into(),
|
||||
|
||||
@@ -0,0 +1,472 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::client::topology_control::geo_aware_provider::CountryGroup;
|
||||
use crate::config::{
|
||||
Acknowledgements, Client, Config, CoverTraffic, DebugConfig, GatewayConnection, GroupBy,
|
||||
ReplySurbs, Topology, TopologyStructure, Traffic,
|
||||
};
|
||||
use nym_sphinx::{
|
||||
addressing::clients::Recipient,
|
||||
params::{PacketSize, PacketType},
|
||||
};
|
||||
use 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(50);
|
||||
const DEFAULT_TOPOLOGY_REFRESH_RATE: Duration = Duration::from_secs(5 * 60); // every 5min
|
||||
const DEFAULT_TOPOLOGY_RESOLUTION_TIMEOUT: Duration = Duration::from_millis(5_000);
|
||||
const DEFAULT_MAX_STARTUP_GATEWAY_WAITING_PERIOD: Duration = Duration::from_secs(70 * 60); // 70min -> full epoch (1h) + a bit of overhead
|
||||
|
||||
// Set this to a high value for now, so that we don't risk sporadic timeouts that might cause
|
||||
// bought bandwidth tokens to not have time to be spent; Once we remove the gateway from the
|
||||
// bandwidth bridging protocol, we can come back to a smaller timeout value
|
||||
const DEFAULT_GATEWAY_RESPONSE_TIMEOUT: Duration = Duration::from_secs(5 * 60);
|
||||
|
||||
const DEFAULT_COVER_TRAFFIC_PRIMARY_SIZE_RATIO: f64 = 0.70;
|
||||
|
||||
// reply-surbs related:
|
||||
|
||||
// define when to request
|
||||
// clients/client-core/src/client/replies/reply_storage/surb_storage.rs
|
||||
const DEFAULT_MINIMUM_REPLY_SURB_STORAGE_THRESHOLD: usize = 10;
|
||||
const DEFAULT_MAXIMUM_REPLY_SURB_STORAGE_THRESHOLD: usize = 200;
|
||||
|
||||
// define how much to request at once
|
||||
// clients/client-core/src/client/replies/reply_controller.rs
|
||||
const DEFAULT_MINIMUM_REPLY_SURB_REQUEST_SIZE: u32 = 10;
|
||||
const DEFAULT_MAXIMUM_REPLY_SURB_REQUEST_SIZE: u32 = 100;
|
||||
|
||||
const DEFAULT_MAXIMUM_ALLOWED_SURB_REQUEST_SIZE: u32 = 500;
|
||||
|
||||
const DEFAULT_MAXIMUM_REPLY_SURB_REREQUEST_WAITING_PERIOD: Duration = Duration::from_secs(10);
|
||||
const DEFAULT_MAXIMUM_REPLY_SURB_DROP_WAITING_PERIOD: Duration = Duration::from_secs(5 * 60);
|
||||
|
||||
// 12 hours
|
||||
const DEFAULT_MAXIMUM_REPLY_SURB_AGE: Duration = Duration::from_secs(12 * 60 * 60);
|
||||
|
||||
// 24 hours
|
||||
const DEFAULT_MAXIMUM_REPLY_KEY_AGE: Duration = Duration::from_secs(24 * 60 * 60);
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct ConfigV1_1_30 {
|
||||
pub client: ClientV1_1_30,
|
||||
|
||||
#[serde(default)]
|
||||
pub debug: DebugConfigV1_1_30,
|
||||
}
|
||||
|
||||
impl From<ConfigV1_1_30> for Config {
|
||||
fn from(value: ConfigV1_1_30) -> 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: value.debug.traffic.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,
|
||||
},
|
||||
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,
|
||||
topology_structure: value.debug.topology.topology_structure.into(),
|
||||
},
|
||||
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_surb_age: value.debug.reply_surbs.maximum_reply_surb_age,
|
||||
maximum_reply_key_age: value.debug.reply_surbs.maximum_reply_key_age,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[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 ClientV1_1_30 {
|
||||
/// 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 TrafficV1_1_30 {
|
||||
/// The parameter of Poisson distribution determining how long, on average,
|
||||
/// sent packet is going to be delayed at any given mix node.
|
||||
/// So for a packet going through three mix nodes, on average, it will take three times this value
|
||||
/// until the packet reaches its destination.
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub average_packet_delay: Duration,
|
||||
|
||||
/// The parameter of Poisson distribution determining how long, on average,
|
||||
/// it is going to take another 'real traffic stream' message to be sent.
|
||||
/// If no real packets are available and cover traffic is enabled,
|
||||
/// a loop cover message is sent instead in order to preserve the rate.
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub message_sending_average_delay: Duration,
|
||||
|
||||
/// Controls whether the main packet stream constantly produces packets according to the predefined
|
||||
/// poisson distribution.
|
||||
pub disable_main_poisson_packet_distribution: bool,
|
||||
|
||||
/// Specifies the packet size used for sent messages.
|
||||
/// Do not override it unless you understand the consequences of that change.
|
||||
pub primary_packet_size: PacketSize,
|
||||
|
||||
/// Specifies the optional auxiliary packet size for optimizing message streams.
|
||||
/// Note that its use decreases overall anonymity.
|
||||
/// Do not set it it unless you understand the consequences of that change.
|
||||
pub secondary_packet_size: Option<PacketSize>,
|
||||
|
||||
pub packet_type: PacketType,
|
||||
}
|
||||
|
||||
impl Default for TrafficV1_1_30 {
|
||||
fn default() -> Self {
|
||||
TrafficV1_1_30 {
|
||||
average_packet_delay: DEFAULT_AVERAGE_PACKET_DELAY,
|
||||
message_sending_average_delay: DEFAULT_MESSAGE_STREAM_AVERAGE_DELAY,
|
||||
disable_main_poisson_packet_distribution: false,
|
||||
primary_packet_size: PacketSize::RegularPacket,
|
||||
secondary_packet_size: None,
|
||||
packet_type: PacketType::Mix,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default, deny_unknown_fields)]
|
||||
pub struct CoverTrafficV1_1_30 {
|
||||
/// The parameter of Poisson distribution determining how long, on average,
|
||||
/// it is going to take for another loop cover traffic message to be sent.
|
||||
#[serde(with = "humantime_serde")]
|
||||
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 CoverTrafficV1_1_30 {
|
||||
fn default() -> Self {
|
||||
CoverTrafficV1_1_30 {
|
||||
loop_cover_traffic_average_delay: DEFAULT_LOOP_COVER_STREAM_AVERAGE_DELAY,
|
||||
cover_traffic_primary_size_ratio: DEFAULT_COVER_TRAFFIC_PRIMARY_SIZE_RATIO,
|
||||
disable_loop_cover_traffic_stream: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default, deny_unknown_fields)]
|
||||
pub struct GatewayConnectionV1_1_30 {
|
||||
/// How long we're willing to wait for a response to a message sent to the gateway,
|
||||
/// before giving up on it.
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub gateway_response_timeout: Duration,
|
||||
}
|
||||
|
||||
impl Default for GatewayConnectionV1_1_30 {
|
||||
fn default() -> Self {
|
||||
GatewayConnectionV1_1_30 {
|
||||
gateway_response_timeout: DEFAULT_GATEWAY_RESPONSE_TIMEOUT,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default, deny_unknown_fields)]
|
||||
pub struct AcknowledgementsV1_1_30 {
|
||||
/// The parameter of Poisson distribution determining how long, on average,
|
||||
/// sent acknowledgement is going to be delayed at any given mix node.
|
||||
/// So for an ack going through three mix nodes, on average, it will take three times this value
|
||||
/// 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 AcknowledgementsV1_1_30 {
|
||||
fn default() -> Self {
|
||||
AcknowledgementsV1_1_30 {
|
||||
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 TopologyV1_1_30 {
|
||||
/// The uniform delay every which clients are querying the directory server
|
||||
/// to try to obtain a compatible network topology to send sphinx packets through.
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub topology_refresh_rate: Duration,
|
||||
|
||||
/// During topology refresh, test packets are sent through every single possible network
|
||||
/// path. This timeout determines waiting period until it is decided that the packet
|
||||
/// did not reach its destination.
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub topology_resolution_timeout: Duration,
|
||||
|
||||
/// Specifies whether the client should not refresh the network topology after obtaining
|
||||
/// the first valid instance.
|
||||
/// Supersedes `topology_refresh_rate_ms`.
|
||||
pub disable_refreshing: bool,
|
||||
|
||||
/// Defines how long the client is going to wait on startup for its gateway to come online,
|
||||
/// before abandoning the procedure.
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub max_startup_gateway_waiting_period: Duration,
|
||||
|
||||
/// Specifies the mixnode topology to be used for sending packets.
|
||||
pub topology_structure: TopologyStructureV1_1_30,
|
||||
}
|
||||
|
||||
#[allow(clippy::large_enum_variant)]
|
||||
#[derive(Default, Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub enum TopologyStructureV1_1_30 {
|
||||
#[default]
|
||||
NymApi,
|
||||
GeoAware(GroupByV1_1_30),
|
||||
}
|
||||
|
||||
impl From<TopologyStructureV1_1_30> for TopologyStructure {
|
||||
fn from(value: TopologyStructureV1_1_30) -> Self {
|
||||
match value {
|
||||
TopologyStructureV1_1_30::NymApi => TopologyStructure::NymApi,
|
||||
TopologyStructureV1_1_30::GeoAware(group_by) => {
|
||||
TopologyStructure::GeoAware(group_by.into())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::large_enum_variant)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub enum GroupByV1_1_30 {
|
||||
CountryGroup(CountryGroup),
|
||||
NymAddress(Recipient),
|
||||
}
|
||||
|
||||
impl From<GroupByV1_1_30> for GroupBy {
|
||||
fn from(value: GroupByV1_1_30) -> Self {
|
||||
match value {
|
||||
GroupByV1_1_30::CountryGroup(country) => GroupBy::CountryGroup(country),
|
||||
GroupByV1_1_30::NymAddress(addr) => GroupBy::NymAddress(addr),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for GroupByV1_1_30 {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
GroupByV1_1_30::CountryGroup(group) => write!(f, "group: {}", group),
|
||||
GroupByV1_1_30::NymAddress(address) => write!(f, "address: {}", address),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for TopologyV1_1_30 {
|
||||
fn default() -> Self {
|
||||
TopologyV1_1_30 {
|
||||
topology_refresh_rate: DEFAULT_TOPOLOGY_REFRESH_RATE,
|
||||
topology_resolution_timeout: DEFAULT_TOPOLOGY_RESOLUTION_TIMEOUT,
|
||||
disable_refreshing: false,
|
||||
max_startup_gateway_waiting_period: DEFAULT_MAX_STARTUP_GATEWAY_WAITING_PERIOD,
|
||||
topology_structure: TopologyStructureV1_1_30::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default, deny_unknown_fields)]
|
||||
pub struct ReplySurbsV1_1_30 {
|
||||
/// Defines the minimum number of reply surbs the client wants to keep in its storage at all times.
|
||||
/// It can only allow to go below that value if its to request additional reply surbs.
|
||||
pub minimum_reply_surb_storage_threshold: usize,
|
||||
|
||||
/// Defines the maximum number of reply surbs the client wants to keep in its storage at any times.
|
||||
pub maximum_reply_surb_storage_threshold: usize,
|
||||
|
||||
/// Defines the minimum number of reply surbs the client would request.
|
||||
pub minimum_reply_surb_request_size: u32,
|
||||
|
||||
/// Defines the maximum number of reply surbs the client would request.
|
||||
pub maximum_reply_surb_request_size: u32,
|
||||
|
||||
/// Defines the maximum number of reply surbs a remote party is allowed to request from this client at once.
|
||||
pub maximum_allowed_reply_surb_request_size: u32,
|
||||
|
||||
/// Defines maximum amount of time the client is going to wait for reply surbs before explicitly asking
|
||||
/// for more even though in theory they wouldn't need to.
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub maximum_reply_surb_rerequest_waiting_period: Duration,
|
||||
|
||||
/// Defines maximum amount of time the client is going to wait for reply surbs before
|
||||
/// deciding it's never going to get them and would drop all pending messages
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub maximum_reply_surb_drop_waiting_period: Duration,
|
||||
|
||||
/// Defines maximum amount of time given reply surb is going to be valid for.
|
||||
/// This is going to be superseded by key rotation once implemented.
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub maximum_reply_surb_age: Duration,
|
||||
|
||||
/// Defines maximum amount of time given reply key is going to be valid for.
|
||||
/// This is going to be superseded by key rotation once implemented.
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub maximum_reply_key_age: Duration,
|
||||
}
|
||||
|
||||
impl Default for ReplySurbsV1_1_30 {
|
||||
fn default() -> Self {
|
||||
ReplySurbsV1_1_30 {
|
||||
minimum_reply_surb_storage_threshold: DEFAULT_MINIMUM_REPLY_SURB_STORAGE_THRESHOLD,
|
||||
maximum_reply_surb_storage_threshold: DEFAULT_MAXIMUM_REPLY_SURB_STORAGE_THRESHOLD,
|
||||
minimum_reply_surb_request_size: DEFAULT_MINIMUM_REPLY_SURB_REQUEST_SIZE,
|
||||
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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default, deny_unknown_fields)]
|
||||
pub struct DebugConfigV1_1_30 {
|
||||
/// Defines all configuration options related to traffic streams.
|
||||
pub traffic: TrafficV1_1_30,
|
||||
|
||||
/// Defines all configuration options related to cover traffic stream(s).
|
||||
pub cover_traffic: CoverTrafficV1_1_30,
|
||||
|
||||
/// Defines all configuration options related to the gateway connection.
|
||||
pub gateway_connection: GatewayConnectionV1_1_30,
|
||||
|
||||
/// Defines all configuration options related to acknowledgements, such as delays or wait timeouts.
|
||||
pub acknowledgements: AcknowledgementsV1_1_30,
|
||||
|
||||
/// Defines all configuration options related topology, such as refresh rates or timeouts.
|
||||
pub topology: TopologyV1_1_30,
|
||||
|
||||
/// Defines all configuration options related to reply SURBs.
|
||||
pub reply_surbs: ReplySurbsV1_1_30,
|
||||
}
|
||||
@@ -8,6 +8,7 @@ use nym_topology::gateway::GatewayConversionError;
|
||||
use nym_topology::NymTopologyError;
|
||||
use nym_validator_client::ValidatorClientError;
|
||||
use std::error::Error;
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
pub enum ClientCoreError {
|
||||
@@ -126,6 +127,32 @@ pub enum ClientCoreError {
|
||||
|
||||
#[error("this client has performed gateway initialisation in another session")]
|
||||
NoInitClientPresent,
|
||||
|
||||
#[error("there are no gateways supporting the wss protocol available")]
|
||||
NoWssGateways,
|
||||
|
||||
#[error("the specified gateway '{gateway}' does not support the wss protocol")]
|
||||
UnsupportedWssProtocol { gateway: String },
|
||||
|
||||
#[error(
|
||||
"failed to load custom topology using path '{}'. detailed message: {source}", file_path.display()
|
||||
)]
|
||||
CustomTopologyLoadFailure {
|
||||
file_path: PathBuf,
|
||||
#[source]
|
||||
source: std::io::Error,
|
||||
},
|
||||
|
||||
#[error(
|
||||
"failed to save config file for client-{typ} id {id} using path '{}'. detailed message: {source}", path.display()
|
||||
)]
|
||||
ConfigSaveFailure {
|
||||
typ: String,
|
||||
id: String,
|
||||
path: PathBuf,
|
||||
#[source]
|
||||
source: std::io::Error,
|
||||
},
|
||||
}
|
||||
|
||||
/// Set of messages that the client can send to listeners via the task manager
|
||||
|
||||
@@ -67,7 +67,7 @@ pub async fn current_gateways<R: Rng>(
|
||||
|
||||
log::trace!("Fetching list of gateways from: {nym_api}");
|
||||
|
||||
let gateways = client.get_cached_gateways().await?;
|
||||
let gateways = client.get_cached_described_gateways().await?;
|
||||
let valid_gateways = gateways
|
||||
.into_iter()
|
||||
.filter_map(|gateway| gateway.try_into().ok())
|
||||
@@ -174,7 +174,10 @@ async fn measure_latency(gateway: &gateway::Node) -> Result<GatewayWithLatency,
|
||||
pub async fn choose_gateway_by_latency<R: Rng>(
|
||||
rng: &mut R,
|
||||
gateways: &[gateway::Node],
|
||||
must_use_tls: bool,
|
||||
) -> Result<gateway::Node, ClientCoreError> {
|
||||
let gateways = filter_by_tls(gateways, must_use_tls)?;
|
||||
|
||||
info!(
|
||||
"choosing gateway by latency, pinging {} gateways ...",
|
||||
gateways.len()
|
||||
@@ -210,28 +213,57 @@ pub async fn choose_gateway_by_latency<R: Rng>(
|
||||
Ok(chosen.gateway.clone())
|
||||
}
|
||||
|
||||
fn filter_by_tls(
|
||||
gateways: &[gateway::Node],
|
||||
must_use_tls: bool,
|
||||
) -> Result<Vec<&gateway::Node>, ClientCoreError> {
|
||||
if must_use_tls {
|
||||
let filtered = gateways
|
||||
.iter()
|
||||
.filter(|g| g.clients_wss_port.is_some())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
if filtered.is_empty() {
|
||||
return Err(ClientCoreError::NoWssGateways);
|
||||
}
|
||||
|
||||
Ok(filtered)
|
||||
} else {
|
||||
Ok(gateways.iter().collect())
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn uniformly_random_gateway<R: Rng>(
|
||||
rng: &mut R,
|
||||
gateways: &[gateway::Node],
|
||||
must_use_tls: bool,
|
||||
) -> Result<gateway::Node, ClientCoreError> {
|
||||
gateways
|
||||
filter_by_tls(gateways, must_use_tls)?
|
||||
.choose(rng)
|
||||
.ok_or(ClientCoreError::NoGatewaysOnNetwork)
|
||||
.cloned()
|
||||
.map(|&r| r.clone())
|
||||
}
|
||||
|
||||
pub(super) fn get_specified_gateway(
|
||||
gateway_identity: IdentityKeyRef,
|
||||
gateways: &[gateway::Node],
|
||||
must_use_tls: bool,
|
||||
) -> Result<gateway::Node, ClientCoreError> {
|
||||
let user_gateway = identity::PublicKey::from_base58_string(gateway_identity)
|
||||
.map_err(ClientCoreError::UnableToCreatePublicKeyFromGatewayId)?;
|
||||
|
||||
gateways
|
||||
let gateway = gateways
|
||||
.iter()
|
||||
.find(|gateway| gateway.identity_key == user_gateway)
|
||||
.ok_or_else(|| ClientCoreError::NoGatewayWithId(gateway_identity.to_string()))
|
||||
.cloned()
|
||||
.ok_or_else(|| ClientCoreError::NoGatewayWithId(gateway_identity.to_string()))?;
|
||||
|
||||
if must_use_tls && gateway.clients_wss_port.is_none() {
|
||||
return Err(ClientCoreError::UnsupportedWssProtocol {
|
||||
gateway: gateway_identity.to_string(),
|
||||
});
|
||||
}
|
||||
|
||||
Ok(gateway.clone())
|
||||
}
|
||||
|
||||
pub(super) async fn register_with_gateway(
|
||||
|
||||
@@ -108,19 +108,20 @@ where
|
||||
|
||||
let gateway_details = match selection_specification {
|
||||
GatewaySelectionSpecification::UniformRemote { must_use_tls } => {
|
||||
let gateway = uniformly_random_gateway(&mut rng, &available_gateways)?;
|
||||
GatewayDetails::Configured(GatewayEndpointConfig::from_node(gateway, must_use_tls))
|
||||
let gateway = uniformly_random_gateway(&mut rng, &available_gateways, must_use_tls)?;
|
||||
GatewayDetails::Configured(GatewayEndpointConfig::from_node(gateway, must_use_tls)?)
|
||||
}
|
||||
GatewaySelectionSpecification::RemoteByLatency { must_use_tls } => {
|
||||
let gateway = choose_gateway_by_latency(&mut rng, &available_gateways).await?;
|
||||
GatewayDetails::Configured(GatewayEndpointConfig::from_node(gateway, must_use_tls))
|
||||
let gateway =
|
||||
choose_gateway_by_latency(&mut rng, &available_gateways, must_use_tls).await?;
|
||||
GatewayDetails::Configured(GatewayEndpointConfig::from_node(gateway, must_use_tls)?)
|
||||
}
|
||||
GatewaySelectionSpecification::Specified {
|
||||
must_use_tls,
|
||||
identity,
|
||||
} => {
|
||||
let gateway = get_specified_gateway(&identity, &available_gateways)?;
|
||||
GatewayDetails::Configured(GatewayEndpointConfig::from_node(gateway, must_use_tls))
|
||||
let gateway = get_specified_gateway(&identity, &available_gateways, must_use_tls)?;
|
||||
GatewayDetails::Configured(GatewayEndpointConfig::from_node(gateway, must_use_tls)?)
|
||||
}
|
||||
GatewaySelectionSpecification::Custom {
|
||||
gateway_identity,
|
||||
|
||||
@@ -296,16 +296,17 @@ impl<T> GatewaySetup<T> {
|
||||
/// Struct describing the results of the client initialization procedure.
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct InitResults {
|
||||
version: String,
|
||||
id: String,
|
||||
identity_key: String,
|
||||
encryption_key: String,
|
||||
gateway_id: String,
|
||||
gateway_listener: String,
|
||||
pub version: String,
|
||||
pub id: String,
|
||||
pub identity_key: String,
|
||||
pub encryption_key: String,
|
||||
pub gateway_id: String,
|
||||
pub gateway_listener: String,
|
||||
pub address: Recipient,
|
||||
}
|
||||
|
||||
impl InitResults {
|
||||
pub fn new(config: &Config, address: &Recipient, gateway: &GatewayEndpointConfig) -> Self {
|
||||
pub fn new(config: &Config, address: Recipient, gateway: &GatewayEndpointConfig) -> Self {
|
||||
Self {
|
||||
version: config.client.version.clone(),
|
||||
id: config.client.id.clone(),
|
||||
@@ -313,6 +314,7 @@ impl InitResults {
|
||||
encryption_key: address.encryption_key().to_base58_string(),
|
||||
gateway_id: gateway.gateway_id.clone(),
|
||||
gateway_listener: gateway.gateway_listener.clone(),
|
||||
address,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
use std::future::Future;
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
pub mod cli_helpers;
|
||||
pub mod client;
|
||||
pub mod config;
|
||||
pub mod error;
|
||||
|
||||
@@ -45,6 +45,9 @@ features = ["net", "sync", "time"]
|
||||
|
||||
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.tokio-tungstenite]
|
||||
workspace = true
|
||||
# the choice of this particular tls feature was arbitrary;
|
||||
# if you reckon a different one would be more appropriate, feel free to change it
|
||||
features = ["native-tls"]
|
||||
|
||||
# wasm-only dependencies
|
||||
[target."cfg(target_arch = \"wasm32\")".dependencies.wasm-bindgen]
|
||||
|
||||
@@ -74,7 +74,7 @@ impl PartiallyDelegated {
|
||||
|
||||
fn route_socket_messages(
|
||||
ws_msgs: Vec<Message>,
|
||||
packet_router: &mut PacketRouter,
|
||||
packet_router: &PacketRouter,
|
||||
shared_key: &SharedKeys,
|
||||
) -> Result<(), GatewayClientError> {
|
||||
let plaintexts = Self::recover_received_plaintexts(ws_msgs, shared_key);
|
||||
@@ -97,7 +97,6 @@ impl PartiallyDelegated {
|
||||
let mixnet_receiver_future = async move {
|
||||
let mut notify_receiver = notify_receiver;
|
||||
let mut chunk_stream = (&mut stream).ready_chunks(8);
|
||||
let mut packet_router = packet_router;
|
||||
|
||||
let ret_err = loop {
|
||||
tokio::select! {
|
||||
@@ -115,7 +114,7 @@ impl PartiallyDelegated {
|
||||
Ok(msgs) => msgs
|
||||
};
|
||||
|
||||
if let Err(err) = Self::route_socket_messages(ws_msgs, &mut packet_router, shared_key.as_ref()) {
|
||||
if let Err(err) = Self::route_socket_messages(ws_msgs, &packet_router, shared_key.as_ref()) {
|
||||
log::warn!("Route socket messages failed: {err}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,7 +42,9 @@ pub trait GatewayPacketRouter {
|
||||
}
|
||||
|
||||
n if n
|
||||
== PacketSize::OutfoxRegularPacket.plaintext_size() - outfox_ack_overhead =>
|
||||
== PacketSize::OutfoxRegularPacket
|
||||
.plaintext_size()
|
||||
.saturating_sub(outfox_ack_overhead) =>
|
||||
{
|
||||
trace!("received regular outfox packet");
|
||||
received_messages.push(received_packet);
|
||||
|
||||
@@ -24,6 +24,7 @@ nym-service-provider-directory-common = { path = "../../cosmwasm-smart-contracts
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
serde_json = { workspace = true }
|
||||
reqwest = { workspace = true, features = ["json"] }
|
||||
http-api-client = { path = "../../../common/http-api-client"}
|
||||
thiserror = { workspace = true }
|
||||
log = { workspace = true }
|
||||
url = { workspace = true, features = ["serde"] }
|
||||
|
||||
@@ -9,7 +9,7 @@ use nym_validator_client::nyxd::contract_traits::{
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
setup_env(Some("../../../envs/qa-qwerty.env"));
|
||||
setup_env(Some("../../../envs/qa.env"));
|
||||
let network_details = NymNetworkDetails::new_from_env();
|
||||
let config =
|
||||
nym_validator_client::Config::try_from_nym_network_details(&network_details).unwrap();
|
||||
|
||||
@@ -9,7 +9,7 @@ use nym_validator_client::nyxd::contract_traits::{
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
setup_env(Some("../../../envs/qa-qwerty.env"));
|
||||
setup_env(Some("../../../envs/qa.env"));
|
||||
let network_details = NymNetworkDetails::new_from_env();
|
||||
let config =
|
||||
nym_validator_client::Config::try_from_nym_network_details(&network_details).unwrap();
|
||||
|
||||
@@ -11,7 +11,7 @@ use crate::{
|
||||
use nym_api_requests::coconut::{
|
||||
BlindSignRequestBody, BlindedSignatureResponse, VerifyCredentialBody, VerifyCredentialResponse,
|
||||
};
|
||||
use nym_api_requests::models::MixNodeBondAnnotated;
|
||||
use nym_api_requests::models::{DescribedGateway, MixNodeBondAnnotated};
|
||||
use nym_api_requests::models::{
|
||||
GatewayCoreStatusResponse, MixnodeCoreStatusResponse, MixnodeStatusResponse,
|
||||
RewardEstimationResponse, StakeSaturationResponse,
|
||||
@@ -19,6 +19,7 @@ use nym_api_requests::models::{
|
||||
use nym_network_defaults::NymNetworkDetails;
|
||||
use url::Url;
|
||||
|
||||
pub use crate::nym_api::NymApiClientExt;
|
||||
pub use nym_mixnet_contract_common::{
|
||||
mixnode::MixNodeDetails, GatewayBond, IdentityKey, IdentityKeyRef, MixId,
|
||||
};
|
||||
@@ -147,7 +148,7 @@ impl Client<ReqwestRpcClient> {
|
||||
|
||||
impl<C> Client<C> {
|
||||
pub fn new_with_rpc_client(config: Config, rpc_client: C) -> Self {
|
||||
let nym_api_client = nym_api::Client::new(config.api_url.clone());
|
||||
let nym_api_client = nym_api::Client::new(config.api_url.clone(), None);
|
||||
|
||||
Client {
|
||||
nym_api: nym_api_client,
|
||||
@@ -161,7 +162,7 @@ impl<C, S> Client<C, S> {
|
||||
where
|
||||
S: OfflineSigner,
|
||||
{
|
||||
let nym_api_client = nym_api::Client::new(config.api_url.clone());
|
||||
let nym_api_client = nym_api::Client::new(config.api_url.clone(), None);
|
||||
|
||||
Client {
|
||||
nym_api: nym_api_client,
|
||||
@@ -177,7 +178,7 @@ impl<C, S> Client<C, S> {
|
||||
}
|
||||
|
||||
pub fn change_nym_api(&mut self, new_endpoint: Url) {
|
||||
self.nym_api.change_url(new_endpoint)
|
||||
self.nym_api.change_base_url(new_endpoint)
|
||||
}
|
||||
|
||||
pub async fn get_cached_mixnodes(&self) -> Result<Vec<MixNodeDetails>, ValidatorClientError> {
|
||||
@@ -241,7 +242,7 @@ pub struct NymApiClient {
|
||||
|
||||
impl NymApiClient {
|
||||
pub fn new(api_url: Url) -> Self {
|
||||
let nym_api = nym_api::Client::new(api_url);
|
||||
let nym_api = nym_api::Client::new(api_url, None);
|
||||
|
||||
NymApiClient { nym_api }
|
||||
}
|
||||
@@ -251,7 +252,7 @@ impl NymApiClient {
|
||||
}
|
||||
|
||||
pub fn change_nym_api(&mut self, new_endpoint: Url) {
|
||||
self.nym_api.change_url(new_endpoint);
|
||||
self.nym_api.change_base_url(new_endpoint);
|
||||
}
|
||||
|
||||
pub async fn get_cached_active_mixnodes(
|
||||
@@ -274,6 +275,12 @@ impl NymApiClient {
|
||||
Ok(self.nym_api.get_gateways().await?)
|
||||
}
|
||||
|
||||
pub async fn get_cached_described_gateways(
|
||||
&self,
|
||||
) -> Result<Vec<DescribedGateway>, ValidatorClientError> {
|
||||
Ok(self.nym_api.get_gateways_described().await?)
|
||||
}
|
||||
|
||||
pub async fn get_gateway_core_status_count(
|
||||
&self,
|
||||
identity: IdentityKeyRef<'_>,
|
||||
|
||||
@@ -1,20 +1,7 @@
|
||||
// Copyright 2022-2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use http_api_client::HttpClientError;
|
||||
use nym_api_requests::models::RequestError;
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum NymAPIError {
|
||||
#[error("There was an issue with the REST request - {source}")]
|
||||
ReqwestClientError {
|
||||
#[from]
|
||||
source: reqwest::Error,
|
||||
},
|
||||
|
||||
#[error("Not found")]
|
||||
NotFound,
|
||||
|
||||
#[error("Request failed with error message - {0}")]
|
||||
GenericRequestFailure(String),
|
||||
|
||||
#[error("The nym API has failed to resolve our request. It returned status code {status} and additional error message: {}", error.message())]
|
||||
ApiRequestFailure { status: u16, error: RequestError },
|
||||
}
|
||||
pub type NymAPIError = HttpClientError<RequestError>;
|
||||
|
||||
@@ -3,140 +3,38 @@
|
||||
|
||||
use crate::nym_api::error::NymAPIError;
|
||||
use crate::nym_api::routes::{CORE_STATUS_COUNT, SINCE_ARG};
|
||||
use async_trait::async_trait;
|
||||
use http_api_client::{ApiClient, NO_PARAMS};
|
||||
use nym_api_requests::coconut::{
|
||||
BlindSignRequestBody, BlindedSignatureResponse, VerifyCredentialBody, VerifyCredentialResponse,
|
||||
};
|
||||
use nym_api_requests::models::{
|
||||
ComputeRewardEstParam, GatewayBondAnnotated, GatewayCoreStatusResponse,
|
||||
ComputeRewardEstParam, DescribedGateway, GatewayBondAnnotated, GatewayCoreStatusResponse,
|
||||
GatewayStatusReportResponse, GatewayUptimeHistoryResponse, InclusionProbabilityResponse,
|
||||
MixNodeBondAnnotated, MixnodeCoreStatusResponse, MixnodeStatusReportResponse,
|
||||
MixnodeStatusResponse, MixnodeUptimeHistoryResponse, RequestError, RewardEstimationResponse,
|
||||
MixnodeStatusResponse, MixnodeUptimeHistoryResponse, RewardEstimationResponse,
|
||||
StakeSaturationResponse, UptimeResponse,
|
||||
};
|
||||
use nym_mixnet_contract_common::mixnode::MixNodeDetails;
|
||||
use nym_mixnet_contract_common::{GatewayBond, IdentityKeyRef, MixId};
|
||||
use nym_name_service_common::response::NamesListResponse;
|
||||
use nym_service_provider_directory_common::response::ServicesListResponse;
|
||||
use reqwest::{Response, StatusCode};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use url::Url;
|
||||
|
||||
pub mod error;
|
||||
pub mod routes;
|
||||
|
||||
type PathSegments<'a> = &'a [&'a str];
|
||||
type Params<'a, K, V> = &'a [(K, V)];
|
||||
pub use http_api_client::Client;
|
||||
|
||||
const NO_PARAMS: Params<'_, &'_ str, &'_ str> = &[];
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Client {
|
||||
url: Url,
|
||||
reqwest_client: reqwest::Client,
|
||||
}
|
||||
|
||||
impl Client {
|
||||
pub fn new(url: Url) -> Self {
|
||||
let reqwest_client = reqwest::Client::new();
|
||||
Self {
|
||||
url,
|
||||
reqwest_client,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn change_url(&mut self, new_url: Url) {
|
||||
self.url = new_url
|
||||
}
|
||||
|
||||
pub fn current_url(&self) -> &Url {
|
||||
&self.url
|
||||
}
|
||||
|
||||
async fn send_get_request<K, V>(
|
||||
&self,
|
||||
path: PathSegments<'_>,
|
||||
params: Params<'_, K, V>,
|
||||
) -> Result<Response, NymAPIError>
|
||||
where
|
||||
K: AsRef<str>,
|
||||
V: AsRef<str>,
|
||||
{
|
||||
let url = create_api_url(&self.url, path, params);
|
||||
Ok(self.reqwest_client.get(url).send().await?)
|
||||
}
|
||||
|
||||
async fn query_nym_api<T, K, V>(
|
||||
&self,
|
||||
path: PathSegments<'_>,
|
||||
params: Params<'_, K, V>,
|
||||
) -> Result<T, NymAPIError>
|
||||
where
|
||||
for<'a> T: Deserialize<'a>,
|
||||
K: AsRef<str>,
|
||||
V: AsRef<str>,
|
||||
{
|
||||
let res = self.send_get_request(path, params).await?;
|
||||
if res.status().is_success() {
|
||||
Ok(res.json().await?)
|
||||
} else if res.status() == StatusCode::NOT_FOUND {
|
||||
Err(NymAPIError::NotFound)
|
||||
} else {
|
||||
Err(NymAPIError::GenericRequestFailure(res.text().await?))
|
||||
}
|
||||
}
|
||||
|
||||
// This works for endpoints returning Result<Json<T>, ErrorResponse>
|
||||
async fn query_nym_api_fallible<T, K, V>(
|
||||
&self,
|
||||
path: PathSegments<'_>,
|
||||
params: Params<'_, K, V>,
|
||||
) -> Result<T, NymAPIError>
|
||||
where
|
||||
for<'a> T: Deserialize<'a>,
|
||||
K: AsRef<str>,
|
||||
V: AsRef<str>,
|
||||
{
|
||||
let res = self.send_get_request(path, params).await?;
|
||||
let status = res.status();
|
||||
if res.status().is_success() {
|
||||
Ok(res.json().await?)
|
||||
} else {
|
||||
let request_error: RequestError = res.json().await?;
|
||||
Err(NymAPIError::ApiRequestFailure {
|
||||
status: status.as_u16(),
|
||||
error: request_error,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
async fn post_nym_api<B, T, K, V>(
|
||||
&self,
|
||||
path: PathSegments<'_>,
|
||||
params: Params<'_, K, V>,
|
||||
json_body: &B,
|
||||
) -> Result<T, NymAPIError>
|
||||
where
|
||||
B: Serialize + ?Sized,
|
||||
for<'a> T: Deserialize<'a>,
|
||||
K: AsRef<str>,
|
||||
V: AsRef<str>,
|
||||
{
|
||||
let url = create_api_url(&self.url, path, params);
|
||||
let response = self.reqwest_client.post(url).json(json_body).send().await?;
|
||||
if response.status().is_success() {
|
||||
Ok(response.json().await?)
|
||||
} else {
|
||||
Err(NymAPIError::GenericRequestFailure(response.text().await?))
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn get_mixnodes(&self) -> Result<Vec<MixNodeDetails>, NymAPIError> {
|
||||
self.query_nym_api(&[routes::API_VERSION, routes::MIXNODES], NO_PARAMS)
|
||||
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
||||
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
|
||||
pub trait NymApiClientExt: ApiClient {
|
||||
async fn get_mixnodes(&self) -> Result<Vec<MixNodeDetails>, NymAPIError> {
|
||||
self.get_json(&[routes::API_VERSION, routes::MIXNODES], NO_PARAMS)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn get_mixnodes_detailed(&self) -> Result<Vec<MixNodeBondAnnotated>, NymAPIError> {
|
||||
self.query_nym_api(
|
||||
async fn get_mixnodes_detailed(&self) -> Result<Vec<MixNodeBondAnnotated>, NymAPIError> {
|
||||
self.get_json(
|
||||
&[
|
||||
routes::API_VERSION,
|
||||
routes::STATUS,
|
||||
@@ -148,8 +46,8 @@ impl Client {
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn get_gateways_detailed(&self) -> Result<Vec<GatewayBondAnnotated>, NymAPIError> {
|
||||
self.query_nym_api(
|
||||
async fn get_gateways_detailed(&self) -> Result<Vec<GatewayBondAnnotated>, NymAPIError> {
|
||||
self.get_json(
|
||||
&[
|
||||
routes::API_VERSION,
|
||||
routes::STATUS,
|
||||
@@ -161,10 +59,10 @@ impl Client {
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn get_mixnodes_detailed_unfiltered(
|
||||
async fn get_mixnodes_detailed_unfiltered(
|
||||
&self,
|
||||
) -> Result<Vec<MixNodeBondAnnotated>, NymAPIError> {
|
||||
self.query_nym_api(
|
||||
self.get_json(
|
||||
&[
|
||||
routes::API_VERSION,
|
||||
routes::STATUS,
|
||||
@@ -176,23 +74,29 @@ impl Client {
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn get_gateways(&self) -> Result<Vec<GatewayBond>, NymAPIError> {
|
||||
self.query_nym_api(&[routes::API_VERSION, routes::GATEWAYS], NO_PARAMS)
|
||||
async fn get_gateways(&self) -> Result<Vec<GatewayBond>, NymAPIError> {
|
||||
self.get_json(&[routes::API_VERSION, routes::GATEWAYS], NO_PARAMS)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn get_active_mixnodes(&self) -> Result<Vec<MixNodeDetails>, NymAPIError> {
|
||||
self.query_nym_api(
|
||||
async fn get_gateways_described(&self) -> Result<Vec<DescribedGateway>, NymAPIError> {
|
||||
self.get_json(
|
||||
&[routes::API_VERSION, routes::GATEWAYS, routes::DESCRIBED],
|
||||
NO_PARAMS,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn get_active_mixnodes(&self) -> Result<Vec<MixNodeDetails>, NymAPIError> {
|
||||
self.get_json(
|
||||
&[routes::API_VERSION, routes::MIXNODES, routes::ACTIVE],
|
||||
NO_PARAMS,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn get_active_mixnodes_detailed(
|
||||
&self,
|
||||
) -> Result<Vec<MixNodeBondAnnotated>, NymAPIError> {
|
||||
self.query_nym_api(
|
||||
async fn get_active_mixnodes_detailed(&self) -> Result<Vec<MixNodeBondAnnotated>, NymAPIError> {
|
||||
self.get_json(
|
||||
&[
|
||||
routes::API_VERSION,
|
||||
routes::STATUS,
|
||||
@@ -205,19 +109,19 @@ impl Client {
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn get_rewarded_mixnodes(&self) -> Result<Vec<MixNodeDetails>, NymAPIError> {
|
||||
self.query_nym_api(
|
||||
async fn get_rewarded_mixnodes(&self) -> Result<Vec<MixNodeDetails>, NymAPIError> {
|
||||
self.get_json(
|
||||
&[routes::API_VERSION, routes::MIXNODES, routes::REWARDED],
|
||||
NO_PARAMS,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn get_mixnode_report(
|
||||
async fn get_mixnode_report(
|
||||
&self,
|
||||
mix_id: MixId,
|
||||
) -> Result<MixnodeStatusReportResponse, NymAPIError> {
|
||||
self.query_nym_api(
|
||||
self.get_json(
|
||||
&[
|
||||
routes::API_VERSION,
|
||||
routes::STATUS,
|
||||
@@ -230,11 +134,11 @@ impl Client {
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn get_gateway_report(
|
||||
async fn get_gateway_report(
|
||||
&self,
|
||||
identity: IdentityKeyRef<'_>,
|
||||
) -> Result<GatewayStatusReportResponse, NymAPIError> {
|
||||
self.query_nym_api(
|
||||
self.get_json(
|
||||
&[
|
||||
routes::API_VERSION,
|
||||
routes::STATUS,
|
||||
@@ -247,11 +151,11 @@ impl Client {
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn get_mixnode_history(
|
||||
async fn get_mixnode_history(
|
||||
&self,
|
||||
mix_id: MixId,
|
||||
) -> Result<MixnodeUptimeHistoryResponse, NymAPIError> {
|
||||
self.query_nym_api(
|
||||
self.get_json(
|
||||
&[
|
||||
routes::API_VERSION,
|
||||
routes::STATUS,
|
||||
@@ -264,11 +168,11 @@ impl Client {
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn get_gateway_history(
|
||||
async fn get_gateway_history(
|
||||
&self,
|
||||
identity: IdentityKeyRef<'_>,
|
||||
) -> Result<GatewayUptimeHistoryResponse, NymAPIError> {
|
||||
self.query_nym_api(
|
||||
self.get_json(
|
||||
&[
|
||||
routes::API_VERSION,
|
||||
routes::STATUS,
|
||||
@@ -281,10 +185,10 @@ impl Client {
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn get_rewarded_mixnodes_detailed(
|
||||
async fn get_rewarded_mixnodes_detailed(
|
||||
&self,
|
||||
) -> Result<Vec<MixNodeBondAnnotated>, NymAPIError> {
|
||||
self.query_nym_api(
|
||||
self.get_json(
|
||||
&[
|
||||
routes::API_VERSION,
|
||||
routes::STATUS,
|
||||
@@ -297,13 +201,13 @@ impl Client {
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn get_gateway_core_status_count(
|
||||
async fn get_gateway_core_status_count(
|
||||
&self,
|
||||
identity: IdentityKeyRef<'_>,
|
||||
since: Option<i64>,
|
||||
) -> Result<GatewayCoreStatusResponse, NymAPIError> {
|
||||
if let Some(since) = since {
|
||||
self.query_nym_api(
|
||||
self.get_json(
|
||||
&[
|
||||
routes::API_VERSION,
|
||||
routes::STATUS_ROUTES,
|
||||
@@ -315,7 +219,7 @@ impl Client {
|
||||
)
|
||||
.await
|
||||
} else {
|
||||
self.query_nym_api(
|
||||
self.get_json(
|
||||
&[
|
||||
routes::API_VERSION,
|
||||
routes::STATUS_ROUTES,
|
||||
@@ -328,13 +232,13 @@ impl Client {
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn get_mixnode_core_status_count(
|
||||
async fn get_mixnode_core_status_count(
|
||||
&self,
|
||||
mix_id: MixId,
|
||||
since: Option<i64>,
|
||||
) -> Result<MixnodeCoreStatusResponse, NymAPIError> {
|
||||
if let Some(since) = since {
|
||||
self.query_nym_api(
|
||||
self.get_json(
|
||||
&[
|
||||
routes::API_VERSION,
|
||||
routes::STATUS_ROUTES,
|
||||
@@ -346,7 +250,7 @@ impl Client {
|
||||
)
|
||||
.await
|
||||
} else {
|
||||
self.query_nym_api(
|
||||
self.get_json(
|
||||
&[
|
||||
routes::API_VERSION,
|
||||
routes::STATUS_ROUTES,
|
||||
@@ -360,11 +264,11 @@ impl Client {
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn get_mixnode_status(
|
||||
async fn get_mixnode_status(
|
||||
&self,
|
||||
mix_id: MixId,
|
||||
) -> Result<MixnodeStatusResponse, NymAPIError> {
|
||||
self.query_nym_api(
|
||||
self.get_json(
|
||||
&[
|
||||
routes::API_VERSION,
|
||||
routes::STATUS_ROUTES,
|
||||
@@ -377,11 +281,11 @@ impl Client {
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn get_mixnode_reward_estimation(
|
||||
async fn get_mixnode_reward_estimation(
|
||||
&self,
|
||||
mix_id: MixId,
|
||||
) -> Result<RewardEstimationResponse, NymAPIError> {
|
||||
self.query_nym_api_fallible(
|
||||
self.get_json(
|
||||
&[
|
||||
routes::API_VERSION,
|
||||
routes::STATUS_ROUTES,
|
||||
@@ -394,12 +298,12 @@ impl Client {
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn compute_mixnode_reward_estimation(
|
||||
async fn compute_mixnode_reward_estimation(
|
||||
&self,
|
||||
mix_id: MixId,
|
||||
request_body: &ComputeRewardEstParam,
|
||||
) -> Result<RewardEstimationResponse, NymAPIError> {
|
||||
self.post_nym_api(
|
||||
self.post_json(
|
||||
&[
|
||||
routes::API_VERSION,
|
||||
routes::STATUS_ROUTES,
|
||||
@@ -413,11 +317,11 @@ impl Client {
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn get_mixnode_stake_saturation(
|
||||
async fn get_mixnode_stake_saturation(
|
||||
&self,
|
||||
mix_id: MixId,
|
||||
) -> Result<StakeSaturationResponse, NymAPIError> {
|
||||
self.query_nym_api_fallible(
|
||||
self.get_json(
|
||||
&[
|
||||
routes::API_VERSION,
|
||||
routes::STATUS_ROUTES,
|
||||
@@ -430,11 +334,11 @@ impl Client {
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn get_mixnode_inclusion_probability(
|
||||
async fn get_mixnode_inclusion_probability(
|
||||
&self,
|
||||
mix_id: MixId,
|
||||
) -> Result<InclusionProbabilityResponse, NymAPIError> {
|
||||
self.query_nym_api_fallible(
|
||||
self.get_json(
|
||||
&[
|
||||
routes::API_VERSION,
|
||||
routes::STATUS_ROUTES,
|
||||
@@ -447,11 +351,8 @@ impl Client {
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn get_mixnode_avg_uptime(
|
||||
&self,
|
||||
mix_id: MixId,
|
||||
) -> Result<UptimeResponse, NymAPIError> {
|
||||
self.query_nym_api_fallible(
|
||||
async fn get_mixnode_avg_uptime(&self, mix_id: MixId) -> Result<UptimeResponse, NymAPIError> {
|
||||
self.get_json(
|
||||
&[
|
||||
routes::API_VERSION,
|
||||
routes::STATUS_ROUTES,
|
||||
@@ -464,11 +365,11 @@ impl Client {
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn blind_sign(
|
||||
async fn blind_sign(
|
||||
&self,
|
||||
request_body: &BlindSignRequestBody,
|
||||
) -> Result<BlindedSignatureResponse, NymAPIError> {
|
||||
self.post_nym_api(
|
||||
self.post_json(
|
||||
&[
|
||||
routes::API_VERSION,
|
||||
routes::COCONUT_ROUTES,
|
||||
@@ -481,11 +382,11 @@ impl Client {
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn verify_bandwidth_credential(
|
||||
async fn verify_bandwidth_credential(
|
||||
&self,
|
||||
request_body: &VerifyCredentialBody,
|
||||
) -> Result<VerifyCredentialResponse, NymAPIError> {
|
||||
self.post_nym_api(
|
||||
self.post_json(
|
||||
&[
|
||||
routes::API_VERSION,
|
||||
routes::COCONUT_ROUTES,
|
||||
@@ -498,118 +399,20 @@ impl Client {
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn get_service_providers(&self) -> Result<ServicesListResponse, NymAPIError> {
|
||||
async fn get_service_providers(&self) -> Result<ServicesListResponse, NymAPIError> {
|
||||
log::trace!("Getting service providers");
|
||||
self.query_nym_api(&[routes::API_VERSION, routes::SERVICE_PROVIDERS], NO_PARAMS)
|
||||
self.get_json(&[routes::API_VERSION, routes::SERVICE_PROVIDERS], NO_PARAMS)
|
||||
.await
|
||||
}
|
||||
|
||||
//pub async fn get_registered_names(&self) -> Result<Vec<NameEntry>, NymAPIError> {
|
||||
pub async fn get_registered_names(&self) -> Result<NamesListResponse, NymAPIError> {
|
||||
//async fn get_registered_names(&self) -> Result<Vec<NameEntry>, NymAPIError> {
|
||||
async fn get_registered_names(&self) -> Result<NamesListResponse, NymAPIError> {
|
||||
log::trace!("Getting registered names");
|
||||
self.query_nym_api(&[routes::API_VERSION, routes::REGISTERED_NAMES], NO_PARAMS)
|
||||
self.get_json(&[routes::API_VERSION, routes::REGISTERED_NAMES], NO_PARAMS)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
// utility function that should solve the double slash problem in validator API forever.
|
||||
fn create_api_url<K: AsRef<str>, V: AsRef<str>>(
|
||||
base: &Url,
|
||||
segments: PathSegments<'_>,
|
||||
params: Params<'_, K, V>,
|
||||
) -> Url {
|
||||
let mut url = base.clone();
|
||||
let mut path_segments = url
|
||||
.path_segments_mut()
|
||||
.expect("provided validator url does not have a base!");
|
||||
for segment in segments {
|
||||
let segment = segment.strip_prefix('/').unwrap_or(segment);
|
||||
let segment = segment.strip_suffix('/').unwrap_or(segment);
|
||||
|
||||
path_segments.push(segment);
|
||||
}
|
||||
// I don't understand why compiler couldn't figure out that it's no longer used
|
||||
// and can be dropped
|
||||
drop(path_segments);
|
||||
|
||||
if !params.is_empty() {
|
||||
url.query_pairs_mut().extend_pairs(params);
|
||||
}
|
||||
|
||||
url
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn creating_api_path() {
|
||||
let base_url: Url = "http://foomp.com".parse().unwrap();
|
||||
|
||||
// works with 1 segment
|
||||
assert_eq!(
|
||||
"http://foomp.com/foo",
|
||||
create_api_url(&base_url, &["foo"], NO_PARAMS).as_str()
|
||||
);
|
||||
|
||||
// works with 2 segments
|
||||
assert_eq!(
|
||||
"http://foomp.com/foo/bar",
|
||||
create_api_url(&base_url, &["foo", "bar"], NO_PARAMS).as_str()
|
||||
);
|
||||
|
||||
// works with leading slash
|
||||
assert_eq!(
|
||||
"http://foomp.com/foo",
|
||||
create_api_url(&base_url, &["/foo"], NO_PARAMS).as_str()
|
||||
);
|
||||
assert_eq!(
|
||||
"http://foomp.com/foo/bar",
|
||||
create_api_url(&base_url, &["/foo", "bar"], NO_PARAMS).as_str()
|
||||
);
|
||||
assert_eq!(
|
||||
"http://foomp.com/foo/bar",
|
||||
create_api_url(&base_url, &["foo", "/bar"], NO_PARAMS).as_str()
|
||||
);
|
||||
|
||||
// works with trailing slash
|
||||
assert_eq!(
|
||||
"http://foomp.com/foo",
|
||||
create_api_url(&base_url, &["foo/"], NO_PARAMS).as_str()
|
||||
);
|
||||
assert_eq!(
|
||||
"http://foomp.com/foo/bar",
|
||||
create_api_url(&base_url, &["foo/", "bar"], NO_PARAMS).as_str()
|
||||
);
|
||||
assert_eq!(
|
||||
"http://foomp.com/foo/bar",
|
||||
create_api_url(&base_url, &["foo", "bar/"], NO_PARAMS).as_str()
|
||||
);
|
||||
|
||||
// works with both leading and trailing slash
|
||||
assert_eq!(
|
||||
"http://foomp.com/foo",
|
||||
create_api_url(&base_url, &["/foo/"], NO_PARAMS).as_str()
|
||||
);
|
||||
assert_eq!(
|
||||
"http://foomp.com/foo/bar",
|
||||
create_api_url(&base_url, &["/foo/", "/bar/"], NO_PARAMS).as_str()
|
||||
);
|
||||
|
||||
// adds params
|
||||
assert_eq!(
|
||||
"http://foomp.com/foo/bar?foomp=baz",
|
||||
create_api_url(&base_url, &["foo", "bar"], &[("foomp", "baz")]).as_str()
|
||||
);
|
||||
assert_eq!(
|
||||
"http://foomp.com/foo/bar?arg1=val1&arg2=val2",
|
||||
create_api_url(
|
||||
&base_url,
|
||||
&["/foo/", "/bar/"],
|
||||
&[("arg1", "val1"), ("arg2", "val2")]
|
||||
)
|
||||
.as_str()
|
||||
);
|
||||
}
|
||||
}
|
||||
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
||||
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
|
||||
impl NymApiClientExt for Client {}
|
||||
|
||||
@@ -6,6 +6,7 @@ use nym_network_defaults::NYM_API_VERSION;
|
||||
pub const API_VERSION: &str = NYM_API_VERSION;
|
||||
pub const MIXNODES: &str = "mixnodes";
|
||||
pub const GATEWAYS: &str = "gateways";
|
||||
pub const DESCRIBED: &str = "described";
|
||||
|
||||
pub const DETAILED: &str = "detailed";
|
||||
pub const DETAILED_UNFILTERED: &str = "detailed-unfiltered";
|
||||
|
||||
+1
-1
@@ -8,6 +8,7 @@ use crate::nyxd::cosmwasm_client::types::{
|
||||
Account, CodeDetails, Contract, ContractCodeId, SequenceResponse, SimulateResponse,
|
||||
};
|
||||
use crate::nyxd::error::NyxdError;
|
||||
use crate::nyxd::Query;
|
||||
use crate::rpc::TendermintRpcClient;
|
||||
use async_trait::async_trait;
|
||||
use cosmrs::cosmwasm::{CodeInfoResponse, ContractCodeHistoryEntry};
|
||||
@@ -35,7 +36,6 @@ use std::convert::TryFrom;
|
||||
use std::time::Duration;
|
||||
use tendermint_rpc::{
|
||||
endpoint::{block::Response as BlockResponse, broadcast, tx::Response as TxResponse},
|
||||
query::Query,
|
||||
Order,
|
||||
};
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ use crate::{DirectSigningReqwestRpcNyxdClient, QueryReqwestRpcNyxdClient, Reqwes
|
||||
use async_trait::async_trait;
|
||||
use cosmrs::cosmwasm;
|
||||
use cosmrs::tendermint::{abci, evidence::Evidence, Genesis};
|
||||
use cosmrs::tx::{Msg, Raw, SignDoc};
|
||||
use cosmrs::tx::{Raw, SignDoc};
|
||||
use cosmwasm_std::Addr;
|
||||
use nym_network_defaults::{ChainDetails, NymNetworkDetails};
|
||||
use serde::{de::DeserializeOwned, Serialize};
|
||||
@@ -39,6 +39,7 @@ pub use cosmrs::tendermint::block::Height;
|
||||
pub use cosmrs::tendermint::hash::{self, Algorithm, Hash};
|
||||
pub use cosmrs::tendermint::validator::Info as TendermintValidatorInfo;
|
||||
pub use cosmrs::tendermint::Time as TendermintTime;
|
||||
pub use cosmrs::tx::Msg;
|
||||
pub use cosmrs::tx::{self};
|
||||
pub use cosmrs::Coin as CosmosCoin;
|
||||
pub use cosmrs::Gas;
|
||||
@@ -47,6 +48,7 @@ pub use cosmwasm_std::Coin as CosmWasmCoin;
|
||||
pub use fee::{gas_price::GasPrice, GasAdjustable, GasAdjustment};
|
||||
pub use tendermint_rpc::{
|
||||
endpoint::{tx::Response as TxResponse, validators::Response as ValidatorResponse},
|
||||
query::Query,
|
||||
Paging,
|
||||
};
|
||||
pub use tendermint_rpc::{Request, Response, SimpleRequest};
|
||||
@@ -57,7 +59,6 @@ use crate::http_client;
|
||||
use crate::{DirectSigningHttpRpcNyxdClient, QueryHttpRpcNyxdClient};
|
||||
#[cfg(feature = "http-client")]
|
||||
use cosmrs::rpc::{HttpClient, HttpClientUrl};
|
||||
use tendermint_rpc::query::Query;
|
||||
|
||||
pub mod coin;
|
||||
pub mod contract_traits;
|
||||
|
||||
@@ -8,6 +8,6 @@ description = "Crutch library until there is proper SerDe support for coconut st
|
||||
bs58 = "0.4.0"
|
||||
getset = "0.1.1"
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
thiserror = "1"
|
||||
thiserror = { workspace = true }
|
||||
|
||||
nym-coconut = {path = "../nymcoconut" }
|
||||
|
||||
@@ -11,7 +11,7 @@ bip39 = { workspace = true }
|
||||
bs58 = "0.4"
|
||||
comfy-table = "6.0.0"
|
||||
cfg-if = "1.0.0"
|
||||
clap = { version = "4.0", features = ["derive"] }
|
||||
clap = { workspace = true, features = ["derive"] }
|
||||
cw-utils = { workspace = true }
|
||||
handlebars = "3.0.1"
|
||||
humantime-serde = "1.0"
|
||||
|
||||
@@ -60,7 +60,7 @@ pub async fn init(args: Args, client: SigningClient, network_details: &NymNetwor
|
||||
// by default we make ourselves an admin, let me know if you don't like that behaviour
|
||||
let opts = Some(InstantiateOptions {
|
||||
funds,
|
||||
admin: Some(args.admin.unwrap_or_else(|| client.address().clone())),
|
||||
admin: Some(args.admin.unwrap_or_else(|| client.address())),
|
||||
});
|
||||
|
||||
let msg: serde_json::Value =
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
use clap::{Args, Subcommand};
|
||||
|
||||
pub mod update_config;
|
||||
pub mod update_cost_params;
|
||||
pub mod vesting_update_config;
|
||||
|
||||
#[derive(Debug, Args)]
|
||||
@@ -20,7 +21,5 @@ pub enum MixnetOperatorsMixnodeSettingsCommands {
|
||||
/// Update mixnode configuration for a mixnode bonded with locked tokens
|
||||
VestingUpdateConfig(vesting_update_config::Args),
|
||||
/// Update mixnode cost parameters
|
||||
UpdateCostParameters,
|
||||
/// Update mixnode cost parameters for a mixnode bonded with locked tokens
|
||||
VestingUpdateCostParameters,
|
||||
UpdateCostParameters(update_cost_params::Args),
|
||||
}
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::context::SigningClient;
|
||||
use clap::Parser;
|
||||
use cosmwasm_std::Uint128;
|
||||
use log::info;
|
||||
use nym_mixnet_contract_common::{MixNodeCostParams, Percent};
|
||||
use nym_validator_client::nyxd::contract_traits::MixnetSigningClient;
|
||||
use nym_validator_client::nyxd::CosmWasmCoin;
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct Args {
|
||||
#[clap(
|
||||
long,
|
||||
help = "input your profit margin as follows; (so it would be 10, rather than 0.1)"
|
||||
)]
|
||||
pub profit_margin_percent: Option<u8>,
|
||||
|
||||
#[clap(
|
||||
long,
|
||||
help = "operating cost in current DENOMINATION (so it would be 'unym', rather than 'nym')"
|
||||
)]
|
||||
pub interval_operating_cost: Option<u128>,
|
||||
}
|
||||
|
||||
pub async fn update_cost_params(args: Args, client: SigningClient) {
|
||||
let denom = client.current_chain_details().mix_denom.base.as_str();
|
||||
|
||||
let cost_params = MixNodeCostParams {
|
||||
profit_margin_percent: Percent::from_percentage_value(
|
||||
args.profit_margin_percent.unwrap_or(10) as u64,
|
||||
)
|
||||
.unwrap(),
|
||||
interval_operating_cost: CosmWasmCoin {
|
||||
denom: denom.into(),
|
||||
amount: Uint128::new(args.interval_operating_cost.unwrap_or(40_000_000)),
|
||||
},
|
||||
};
|
||||
|
||||
info!("Starting mixnode params updating!");
|
||||
let res = client
|
||||
.update_mixnode_cost_params(cost_params, None)
|
||||
.await
|
||||
.expect("failed to update cost params");
|
||||
|
||||
info!("Cost params result: {:?}", res)
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use clap::Parser;
|
||||
use comfy_table::Table;
|
||||
|
||||
use crate::context::QueryClientWithNyxd;
|
||||
use crate::utils::{pretty_cosmwasm_coin, show_error};
|
||||
use clap::Parser;
|
||||
use comfy_table::Table;
|
||||
use nym_validator_client::client::NymApiClientExt;
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct Args {
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use clap::Parser;
|
||||
use comfy_table::Table;
|
||||
|
||||
use crate::context::QueryClientWithNyxd;
|
||||
use crate::utils::{pretty_decimal_with_denom, show_error};
|
||||
use clap::Parser;
|
||||
use comfy_table::Table;
|
||||
use nym_validator_client::client::NymApiClientExt;
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct Args {
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use clap::Parser;
|
||||
use comfy_table::Table;
|
||||
use nym_validator_client::nym_api::error::NymAPIError;
|
||||
|
||||
use crate::context::QueryClientWithNyxd;
|
||||
use crate::utils::show_error;
|
||||
use clap::Parser;
|
||||
use comfy_table::Table;
|
||||
use nym_validator_client::client::NymApiClientExt;
|
||||
use nym_validator_client::nym_api::error::NymAPIError;
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct Args {
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use clap::Parser;
|
||||
use comfy_table::Table;
|
||||
use nym_validator_client::nym_api::error::NymAPIError;
|
||||
|
||||
use crate::context::QueryClientWithNyxd;
|
||||
use crate::utils::show_error;
|
||||
use clap::Parser;
|
||||
use comfy_table::Table;
|
||||
use nym_validator_client::client::NymApiClientExt;
|
||||
use nym_validator_client::nym_api::error::NymAPIError;
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct Args {
|
||||
|
||||
@@ -15,6 +15,7 @@ pub use toml::de::Error as TomlDeError;
|
||||
pub mod defaults;
|
||||
pub mod helpers;
|
||||
pub mod legacy_helpers;
|
||||
pub mod serde_helpers;
|
||||
|
||||
pub const NYM_DIR: &str = ".nym";
|
||||
pub const DEFAULT_NYM_APIS_DIR: &str = "nym-api";
|
||||
@@ -24,12 +25,20 @@ pub const DEFAULT_CONFIG_FILENAME: &str = "config.toml";
|
||||
|
||||
#[cfg(feature = "dirs")]
|
||||
pub fn must_get_home() -> PathBuf {
|
||||
dirs::home_dir().expect("Failed to evaluate $HOME value")
|
||||
if let Some(home_dir) = std::env::var_os("NYM_HOME_DIR") {
|
||||
home_dir.into()
|
||||
} else {
|
||||
dirs::home_dir().expect("Failed to evaluate $HOME value")
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "dirs")]
|
||||
pub fn may_get_home() -> Option<PathBuf> {
|
||||
dirs::home_dir()
|
||||
if let Some(home_dir) = std::env::var_os("NYM_HOME_DIR") {
|
||||
Some(home_dir.into())
|
||||
} else {
|
||||
dirs::home_dir()
|
||||
}
|
||||
}
|
||||
|
||||
pub trait NymConfigTemplate: Serialize {
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use serde::{Deserialize, Deserializer};
|
||||
use std::fmt::Display;
|
||||
use std::path::PathBuf;
|
||||
use std::str::FromStr;
|
||||
|
||||
pub fn de_maybe_stringified<'de, D, T, E>(deserializer: D) -> Result<Option<T>, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
T: FromStr<Err = E>,
|
||||
E: Display,
|
||||
{
|
||||
let raw = String::deserialize(deserializer)?;
|
||||
if raw.is_empty() {
|
||||
Ok(None)
|
||||
} else {
|
||||
Ok(Some(raw.parse().map_err(serde::de::Error::custom)?))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn de_maybe_string<'de, D>(deserializer: D) -> Result<Option<String>, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
de_maybe_stringified(deserializer)
|
||||
}
|
||||
|
||||
pub fn de_maybe_path<'de, D>(deserializer: D) -> Result<Option<PathBuf>, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
de_maybe_stringified(deserializer)
|
||||
}
|
||||
|
||||
pub fn de_maybe_port<'de, D>(deserializer: D) -> Result<Option<u16>, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let port = u16::deserialize(deserializer)?;
|
||||
if port == 0 {
|
||||
Ok(None)
|
||||
} else {
|
||||
Ok(Some(port))
|
||||
}
|
||||
}
|
||||
@@ -18,7 +18,7 @@ serde_repr = "0.1"
|
||||
|
||||
# we still have to preserve that import for `JsonSchema` for `Layer` type (since we can't use cw_serde macro due to custom serde impl)
|
||||
schemars = "0.8"
|
||||
thiserror = "1.0"
|
||||
thiserror = { workspace = true }
|
||||
contracts-common = { path = "../contracts-common", package = "nym-contracts-common", version = "0.5.0" }
|
||||
serde-json-wasm = { workspace = true }
|
||||
humantime-serde = "1.1.1"
|
||||
|
||||
@@ -14,4 +14,4 @@ cosmwasm-schema = { workspace = true }
|
||||
cosmwasm-std = { workspace = true }
|
||||
schemars = "0.8"
|
||||
serde = { version = "1.0.103", default-features = false, features = ["derive"] }
|
||||
thiserror = { version = "1.0.23" }
|
||||
thiserror = { workspace = true }
|
||||
|
||||
@@ -14,7 +14,7 @@ cw2 = { workspace = true, optional = true }
|
||||
mixnet-contract-common = { path = "../mixnet-contract", package = "nym-mixnet-contract-common", version = "0.6.0" }
|
||||
contracts-common = { path = "../contracts-common", package = "nym-contracts-common", version = "0.5.0" }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
thiserror = "1.0"
|
||||
thiserror = { workspace = true }
|
||||
ts-rs = { workspace = true, optional = true}
|
||||
|
||||
[features]
|
||||
|
||||
@@ -9,7 +9,7 @@ edition = "2021"
|
||||
async-trait = { workspace = true }
|
||||
|
||||
log = { workspace = true }
|
||||
thiserror = "1.0"
|
||||
thiserror = { workspace = true }
|
||||
tokio = { version = "1.24.1", features = ["sync"]}
|
||||
|
||||
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.sqlx]
|
||||
|
||||
@@ -23,7 +23,7 @@ rand = { version = "0.7.3", features = ["wasm-bindgen"], optional = true }
|
||||
serde_bytes = { version = "0.11.6", optional = true }
|
||||
serde_crate = { version = "1.0", optional = true, default_features = false, features = ["derive"], package = "serde" }
|
||||
subtle-encoding = { version = "0.5", features = ["bech32-preview"]}
|
||||
thiserror = "1.0.37"
|
||||
thiserror = { workspace = true }
|
||||
zeroize = { workspace = true, optional = true, features = ["zeroize_derive"] }
|
||||
|
||||
# internal
|
||||
|
||||
@@ -145,8 +145,12 @@ impl PublicKey {
|
||||
Self::from_bytes(&bytes)
|
||||
}
|
||||
|
||||
pub fn verify(&self, message: &[u8], signature: &Signature) -> Result<(), SignatureError> {
|
||||
self.0.verify(message, &signature.0)
|
||||
pub fn verify<M: AsRef<[u8]>>(
|
||||
&self,
|
||||
message: M,
|
||||
signature: &Signature,
|
||||
) -> Result<(), SignatureError> {
|
||||
self.0.verify(message.as_ref(), &signature.0)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -239,16 +243,16 @@ impl PrivateKey {
|
||||
Self::from_bytes(&bytes)
|
||||
}
|
||||
|
||||
pub fn sign(&self, message: &[u8]) -> Signature {
|
||||
pub fn sign<M: AsRef<[u8]>>(&self, message: M) -> Signature {
|
||||
let expanded_secret_key = ed25519_dalek::ExpandedSecretKey::from(&self.0);
|
||||
let public_key: PublicKey = self.into();
|
||||
let sig = expanded_secret_key.sign(message, &public_key.0);
|
||||
let sig = expanded_secret_key.sign(message.as_ref(), &public_key.0);
|
||||
Signature(sig)
|
||||
}
|
||||
|
||||
/// Signs text with the provided Ed25519 private key, returning a base58 signature
|
||||
pub fn sign_text(&self, text: &str) -> String {
|
||||
let signature_bytes = self.sign(text.as_ref()).to_bytes();
|
||||
let signature_bytes = self.sign(text).to_bytes();
|
||||
bs58::encode(signature_bytes).into_string()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,10 +21,10 @@ rand = { version = "0.8.5", default-features = false}
|
||||
rand_chacha = "0.3"
|
||||
rand_core = "0.6.3"
|
||||
sha2 = "0.9"
|
||||
serde = "1.0"
|
||||
serde = { workspace = true }
|
||||
serde_derive = "1.0"
|
||||
thiserror = "1.0"
|
||||
zeroize = { version = "1.4", features = ["zeroize_derive"] }
|
||||
thiserror = { workspace = true }
|
||||
zeroize = { workspace = true, features = ["zeroize_derive"] }
|
||||
|
||||
nym-pemstore = { path = "../pemstore" }
|
||||
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
[package]
|
||||
name = "nym-exit-policy"
|
||||
version = "0.1.0"
|
||||
authors.workspace = true
|
||||
repository.workspace = true
|
||||
homepage.workspace = true
|
||||
documentation.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
thiserror = { workspace = true }
|
||||
tracing = { workspace = true }
|
||||
|
||||
# feature-specific dependencies:
|
||||
|
||||
## client feature
|
||||
reqwest = { workspace = true, optional = true }
|
||||
|
||||
## openapi feature
|
||||
serde_json = { workspace = true, optional = true }
|
||||
utoipa = { workspace = true, optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
serde_json = { workspace = true }
|
||||
|
||||
[features]
|
||||
default = []
|
||||
client = ["reqwest"]
|
||||
openapi = ["utoipa", "serde_json"]
|
||||
@@ -0,0 +1,10 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::policy::PolicyError;
|
||||
use crate::ExitPolicy;
|
||||
use reqwest::IntoUrl;
|
||||
|
||||
pub async fn get_exit_policy(url: impl IntoUrl) -> Result<ExitPolicy, PolicyError> {
|
||||
ExitPolicy::parse_from_torrc(reqwest::get(url).await?.text().await?)
|
||||
}
|
||||
@@ -0,0 +1,233 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
pub mod policy;
|
||||
|
||||
#[cfg(feature = "client")]
|
||||
pub mod client;
|
||||
|
||||
pub use crate::policy::{
|
||||
AddressPolicy, AddressPolicyAction, AddressPolicyRule, AddressPortPattern, PolicyError,
|
||||
PortRange,
|
||||
};
|
||||
|
||||
pub(crate) const EXIT_POLICY_FIELD_NAME: &str = "ExitPolicy";
|
||||
const COMMENT_CHAR: char = '#';
|
||||
|
||||
pub type ExitPolicy = AddressPolicy;
|
||||
|
||||
pub fn parse_exit_policy<S: AsRef<str>>(exit_policy: S) -> Result<ExitPolicy, PolicyError> {
|
||||
let rules = exit_policy
|
||||
.as_ref()
|
||||
.lines()
|
||||
.map(|maybe_rule| {
|
||||
if let Some(comment_start) = maybe_rule.find(COMMENT_CHAR) {
|
||||
&maybe_rule[..comment_start]
|
||||
} else {
|
||||
maybe_rule
|
||||
}
|
||||
.trim()
|
||||
})
|
||||
.filter(|maybe_rule| !maybe_rule.is_empty())
|
||||
.map(parse_address_policy_rule)
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
|
||||
Ok(AddressPolicy { rules })
|
||||
}
|
||||
|
||||
pub fn format_exit_policy(policy: &ExitPolicy) -> String {
|
||||
policy
|
||||
.rules
|
||||
.iter()
|
||||
.map(|rule| format!("{EXIT_POLICY_FIELD_NAME} {rule}"))
|
||||
.fold(String::new(), |accumulator, rule| {
|
||||
accumulator + &rule + "\n"
|
||||
})
|
||||
.trim_end()
|
||||
.to_string()
|
||||
}
|
||||
|
||||
fn parse_address_policy_rule(rule: &str) -> Result<AddressPolicyRule, PolicyError> {
|
||||
// each exit policy rule must begin with 'ExitPolicy' followed by the actual rule
|
||||
rule.strip_prefix(EXIT_POLICY_FIELD_NAME)
|
||||
.ok_or(PolicyError::NoExitPolicyPrefix {
|
||||
entry: rule.to_string(),
|
||||
})?
|
||||
.trim()
|
||||
.parse()
|
||||
}
|
||||
|
||||
// for each line, ignore everything after the comment
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::policy::AddressPolicyAction::{Accept, Accept6, Reject, Reject6};
|
||||
use crate::policy::{AddressPortPattern, IpPattern, PortRange};
|
||||
|
||||
#[test]
|
||||
fn parsing_policy() {
|
||||
let sample = r#"
|
||||
ExitPolicy reject 1.2.3.4/32:*#comment
|
||||
ExitPolicy reject 1.2.3.5:* #comment
|
||||
ExitPolicy reject 1.2.3.6/16:*
|
||||
ExitPolicy reject 1.2.3.6/16:123-456 # comment
|
||||
|
||||
ExitPolicy accept *:53 # DNS
|
||||
|
||||
# random comment
|
||||
|
||||
ExitPolicy accept6 *6:119
|
||||
ExitPolicy accept *4:120
|
||||
ExitPolicy reject6 [FC00::]/7:*
|
||||
|
||||
#ExitPolicy accept *:8080 #and another comment here
|
||||
|
||||
ExitPolicy reject FE80:0000:0000:0000:0202:B3FF:FE1E:8329:*
|
||||
ExitPolicy reject FE80:0000:0000:0000:0202:B3FF:FE1E:8328:1234
|
||||
ExitPolicy reject FE80:0000:0000:0000:0202:B3FF:FE1E:8328/64:1235
|
||||
|
||||
#another comment
|
||||
#ExitPolicy accept *:8080
|
||||
|
||||
ExitPolicy reject *:*
|
||||
"#;
|
||||
|
||||
let res = parse_exit_policy(sample).unwrap();
|
||||
|
||||
let mut expected = AddressPolicy::new();
|
||||
|
||||
// ExitPolicy reject 1.2.3.4/32:*#comment
|
||||
expected.push(
|
||||
Reject,
|
||||
AddressPortPattern {
|
||||
ip_pattern: IpPattern::V4 {
|
||||
addr_prefix: "1.2.3.4".parse().unwrap(),
|
||||
mask: 32,
|
||||
},
|
||||
ports: PortRange::new_all(),
|
||||
},
|
||||
);
|
||||
|
||||
// ExitPolicy reject 1.2.3.5:* #comment
|
||||
expected.push(
|
||||
Reject,
|
||||
AddressPortPattern {
|
||||
ip_pattern: IpPattern::V4 {
|
||||
addr_prefix: "1.2.3.5".parse().unwrap(),
|
||||
mask: 32,
|
||||
},
|
||||
ports: PortRange::new_all(),
|
||||
},
|
||||
);
|
||||
|
||||
// ExitPolicy reject 1.2.3.6/16:*
|
||||
expected.push(
|
||||
Reject,
|
||||
AddressPortPattern {
|
||||
ip_pattern: IpPattern::V4 {
|
||||
addr_prefix: "1.2.3.6".parse().unwrap(),
|
||||
mask: 16,
|
||||
},
|
||||
ports: PortRange::new_all(),
|
||||
},
|
||||
);
|
||||
|
||||
// ExitPolicy reject 1.2.3.6/16:123-456
|
||||
expected.push(
|
||||
Reject,
|
||||
AddressPortPattern {
|
||||
ip_pattern: IpPattern::V4 {
|
||||
addr_prefix: "1.2.3.6".parse().unwrap(),
|
||||
mask: 16,
|
||||
},
|
||||
ports: PortRange::new(123, 456).unwrap(),
|
||||
},
|
||||
);
|
||||
|
||||
// ExitPolicy accept *:53
|
||||
expected.push(
|
||||
Accept,
|
||||
AddressPortPattern {
|
||||
ip_pattern: IpPattern::Star,
|
||||
ports: PortRange::new_singleton(53),
|
||||
},
|
||||
);
|
||||
|
||||
// ExitPolicy accept6 *6:119
|
||||
expected.push(
|
||||
Accept6,
|
||||
AddressPortPattern {
|
||||
ip_pattern: IpPattern::V6Star,
|
||||
ports: PortRange::new_singleton(119),
|
||||
},
|
||||
);
|
||||
|
||||
// ExitPolicy accept *4:120
|
||||
expected.push(
|
||||
Accept,
|
||||
AddressPortPattern {
|
||||
ip_pattern: IpPattern::V4Star,
|
||||
ports: PortRange::new_singleton(120),
|
||||
},
|
||||
);
|
||||
|
||||
// ExitPolicy reject6 [FC00::]/7:*
|
||||
expected.push(
|
||||
Reject6,
|
||||
AddressPortPattern {
|
||||
ip_pattern: IpPattern::V6 {
|
||||
addr_prefix: "FC00::".parse().unwrap(),
|
||||
mask: 7,
|
||||
},
|
||||
ports: PortRange::new_all(),
|
||||
},
|
||||
);
|
||||
|
||||
// ExitPolicy FE80:0000:0000:0000:0202:B3FF:FE1E:8329:*
|
||||
expected.push(
|
||||
Reject,
|
||||
AddressPortPattern {
|
||||
ip_pattern: IpPattern::V6 {
|
||||
addr_prefix: "FE80:0000:0000:0000:0202:B3FF:FE1E:8329".parse().unwrap(),
|
||||
mask: 128,
|
||||
},
|
||||
ports: PortRange::new_all(),
|
||||
},
|
||||
);
|
||||
|
||||
// ExitPolicy FE80:0000:0000:0000:0202:B3FF:FE1E:8328:1234
|
||||
expected.push(
|
||||
Reject,
|
||||
AddressPortPattern {
|
||||
ip_pattern: IpPattern::V6 {
|
||||
addr_prefix: "FE80:0000:0000:0000:0202:B3FF:FE1E:8328".parse().unwrap(),
|
||||
mask: 128,
|
||||
},
|
||||
ports: PortRange::new_singleton(1234),
|
||||
},
|
||||
);
|
||||
|
||||
// ExitPolicy FE80:0000:0000:0000:0202:B3FF:FE1E:8328/64:1235
|
||||
expected.push(
|
||||
Reject,
|
||||
AddressPortPattern {
|
||||
ip_pattern: IpPattern::V6 {
|
||||
addr_prefix: "FE80:0000:0000:0000:0202:B3FF:FE1E:8328".parse().unwrap(),
|
||||
mask: 64,
|
||||
},
|
||||
ports: PortRange::new_singleton(1235),
|
||||
},
|
||||
);
|
||||
|
||||
expected.push(
|
||||
Reject,
|
||||
AddressPortPattern {
|
||||
ip_pattern: IpPattern::Star,
|
||||
ports: PortRange::new_all(),
|
||||
},
|
||||
);
|
||||
|
||||
assert_eq!(res, expected)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,726 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
//! Implements address policies, based on a series of accept/reject
|
||||
//! rules.
|
||||
|
||||
use crate::policy::error::PolicyError;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt::{Display, Formatter};
|
||||
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr};
|
||||
use std::str::FromStr;
|
||||
use tracing::trace;
|
||||
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
|
||||
#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum AddressPolicyAction {
|
||||
/// A rule that accepts matching address:port combinations on IPv4 and IPv6.
|
||||
Accept,
|
||||
|
||||
/// A rule that rejects matching address:port combinations on IPv4 and IPv6.
|
||||
Reject,
|
||||
|
||||
/// A rule that accepts matching address:port combinations on IPv6 only.
|
||||
Accept6,
|
||||
|
||||
/// A rule that rejects matching address:port combinations on IPv6 only.
|
||||
Reject6,
|
||||
}
|
||||
|
||||
impl AddressPolicyAction {
|
||||
pub fn is_accept(&self) -> bool {
|
||||
matches!(
|
||||
self,
|
||||
AddressPolicyAction::Accept | AddressPolicyAction::Accept6
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for AddressPolicyAction {
|
||||
type Err = PolicyError;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s {
|
||||
"accept" => Ok(AddressPolicyAction::Accept),
|
||||
"reject" => Ok(AddressPolicyAction::Reject),
|
||||
"accept6" => Ok(AddressPolicyAction::Accept6),
|
||||
"reject6" => Ok(AddressPolicyAction::Reject6),
|
||||
other => Err(PolicyError::InvalidPolicyAction {
|
||||
action: other.to_string(),
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for AddressPolicyAction {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
AddressPolicyAction::Accept => write!(f, "accept"),
|
||||
AddressPolicyAction::Reject => write!(f, "reject"),
|
||||
AddressPolicyAction::Accept6 => write!(f, "accept6"),
|
||||
AddressPolicyAction::Reject6 => write!(f, "reject6"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A sequence of rules that are applied to an address:port until one
|
||||
/// matches.
|
||||
///
|
||||
/// Each rule is of the form "accept(6) PATTERN" or "reject(6) PATTERN",
|
||||
/// where every pattern describes a set of addresses and ports.
|
||||
/// Address sets are given as a prefix of 0-128 bits that the address
|
||||
/// must have; port sets are given as a low-bound and high-bound that
|
||||
/// the target port might lie between.
|
||||
///
|
||||
/// An example IPv4 policy might be:
|
||||
///
|
||||
/// ```text
|
||||
/// reject *:25
|
||||
/// reject 127.0.0.0/8:*
|
||||
/// reject 192.168.0.0/16:*
|
||||
/// accept *:80
|
||||
/// accept *:443
|
||||
/// accept *:9000-65535
|
||||
/// reject *:*
|
||||
/// ```
|
||||
#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "openapi", aliases(ExitPolicy))]
|
||||
pub struct AddressPolicy {
|
||||
/// A list of rules to apply to find out whether an address is
|
||||
/// contained by this policy.
|
||||
///
|
||||
/// The rules apply in order; the first one to match determines
|
||||
/// whether the address is accepted or rejected.
|
||||
pub(crate) rules: Vec<AddressPolicyRule>,
|
||||
}
|
||||
|
||||
impl AddressPolicy {
|
||||
/// Create a new AddressPolicy that matches nothing.
|
||||
pub const fn new() -> Self {
|
||||
AddressPolicy { rules: Vec::new() }
|
||||
}
|
||||
|
||||
/// Create a new AddressPolicy that matches everything.
|
||||
pub fn new_open() -> Self {
|
||||
AddressPolicy {
|
||||
rules: vec![AddressPolicyRule::new(
|
||||
AddressPolicyAction::Accept,
|
||||
AddressPortPattern {
|
||||
ip_pattern: IpPattern::Star,
|
||||
ports: PortRange::new_all(),
|
||||
},
|
||||
)],
|
||||
}
|
||||
}
|
||||
|
||||
/// Check whether this AddressPolicy matches all patterns.
|
||||
pub fn is_open(&self) -> bool {
|
||||
if self.rules.len() != 1 {
|
||||
return false;
|
||||
}
|
||||
|
||||
let rule = &self.rules[0];
|
||||
|
||||
rule.action == AddressPolicyAction::Accept
|
||||
&& rule.pattern.ip_pattern == IpPattern::Star
|
||||
&& rule.pattern.ports.is_all()
|
||||
}
|
||||
|
||||
/// Attempts to parse the AddressPolicy out of raw torrc representation.
|
||||
pub fn parse_from_torrc<S: AsRef<str>>(raw: S) -> Result<Self, PolicyError> {
|
||||
crate::parse_exit_policy(raw)
|
||||
}
|
||||
|
||||
/// Formats the AddressPolicy with torrc representation
|
||||
pub fn format_as_torrc(&self) -> String {
|
||||
crate::format_exit_policy(self)
|
||||
}
|
||||
|
||||
/// Apply this policy to an address:port combination
|
||||
///
|
||||
/// We do this by applying each rule in sequence, until one
|
||||
/// matches.
|
||||
///
|
||||
/// Returns None if no rule matches.
|
||||
pub fn allows(&self, addr: &IpAddr, port: u16) -> Option<bool> {
|
||||
self.rules
|
||||
.iter()
|
||||
.find(|rule| rule.pattern.matches(addr, port))
|
||||
.map(|rule| {
|
||||
trace!("'{addr}:{port}' is covered by rule '{rule}'");
|
||||
rule.action.is_accept()
|
||||
})
|
||||
}
|
||||
|
||||
/// As allows, but accept a SocketAddr.
|
||||
pub fn allows_sockaddr(&self, addr: &SocketAddr) -> Option<bool> {
|
||||
self.allows(&addr.ip(), addr.port())
|
||||
}
|
||||
|
||||
/// Add a new rule to this policy.
|
||||
///
|
||||
/// The newly added rule is applied _after_ all previous rules.
|
||||
/// It matches all addresses and ports covered by AddressPortPattern.
|
||||
///
|
||||
/// If accept is true, the rule is to accept addresses that match;
|
||||
/// if accept is false, the rule rejects such addresses.
|
||||
pub fn push(&mut self, action: AddressPolicyAction, pattern: AddressPortPattern) {
|
||||
self.rules.push(AddressPolicyRule { action, pattern })
|
||||
}
|
||||
|
||||
/// As push, but accepts a AddressPolicyRule.
|
||||
pub fn push_rule(&mut self, rule: AddressPolicyRule) {
|
||||
self.rules.push(rule)
|
||||
}
|
||||
}
|
||||
|
||||
/// A single rule in an address policy.
|
||||
///
|
||||
/// Contains a pattern, what to do with things that match it.
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
|
||||
pub struct AddressPolicyRule {
|
||||
/// What do we do with items that match the pattern?
|
||||
action: AddressPolicyAction,
|
||||
|
||||
/// What pattern are we trying to match?
|
||||
pattern: AddressPortPattern,
|
||||
}
|
||||
|
||||
impl FromStr for AddressPolicyRule {
|
||||
type Err = PolicyError;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
// split on the first space, i.e. separation between the action and the pattern
|
||||
let Some((action, pattern)) = s.split_once(' ') else {
|
||||
return Err(PolicyError::MalformedAddressPolicy { raw: s.to_string() });
|
||||
};
|
||||
|
||||
Ok(AddressPolicyRule {
|
||||
action: action.parse()?,
|
||||
pattern: pattern.parse()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl AddressPolicyRule {
|
||||
pub fn new(action: AddressPolicyAction, pattern: AddressPortPattern) -> Self {
|
||||
AddressPolicyRule { action, pattern }
|
||||
}
|
||||
}
|
||||
impl Display for AddressPolicyRule {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{} {}", self.action, self.pattern)
|
||||
}
|
||||
}
|
||||
|
||||
/// A pattern that may or may not match an address and port.
|
||||
///
|
||||
/// Each AddrPortPattern has an IP pattern, which matches a set of
|
||||
/// addresses by prefix, and a port pattern, which matches a range of
|
||||
/// ports.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use nym_exit_policy::policy::AddressPortPattern;
|
||||
/// use std::net::{IpAddr,Ipv4Addr};
|
||||
/// let localhost = IpAddr::V4(Ipv4Addr::new(127,3,4,5));
|
||||
/// let not_localhost = IpAddr::V4(Ipv4Addr::new(192,0,2,16));
|
||||
/// let pat: AddressPortPattern = "127.0.0.0/8:*".parse().unwrap();
|
||||
///
|
||||
/// assert!(pat.matches(&localhost, 22));
|
||||
/// assert!(!pat.matches(¬_localhost, 22));
|
||||
/// ```
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
|
||||
pub struct AddressPortPattern {
|
||||
/// A pattern to match somewhere between zero and all IP addresses.
|
||||
#[serde(with = "stringified_ip_pattern")]
|
||||
#[cfg_attr(feature = "openapi", schema(example = "1.2.3.6/16", value_type = String))]
|
||||
pub(crate) ip_pattern: IpPattern,
|
||||
|
||||
/// A pattern to match a range of ports.
|
||||
pub(crate) ports: PortRange,
|
||||
}
|
||||
|
||||
mod stringified_ip_pattern {
|
||||
use super::IpPattern;
|
||||
use serde::{Deserialize, Deserializer, Serializer};
|
||||
use std::str::FromStr;
|
||||
|
||||
pub fn serialize<S: Serializer>(pattern: &IpPattern, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
serializer.serialize_str(&pattern.to_string())
|
||||
}
|
||||
|
||||
pub fn deserialize<'de, D: Deserializer<'de>>(deserializer: D) -> Result<IpPattern, D::Error> {
|
||||
let s = <String>::deserialize(deserializer)?;
|
||||
IpPattern::from_str(&s).map_err(serde::de::Error::custom)
|
||||
}
|
||||
}
|
||||
|
||||
impl AddressPortPattern {
|
||||
/// Return true iff this pattern matches a given address and port.
|
||||
pub fn matches(&self, addr: &IpAddr, port: u16) -> bool {
|
||||
self.ip_pattern.matches(addr) && self.ports.contains(port)
|
||||
}
|
||||
|
||||
/// As matches, but accept a SocketAddr.
|
||||
pub fn matches_sockaddr(&self, addr: &SocketAddr) -> bool {
|
||||
self.matches(&addr.ip(), addr.port())
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for AddressPortPattern {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{}:{}", self.ip_pattern, self.ports)
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for AddressPortPattern {
|
||||
type Err = PolicyError;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, PolicyError> {
|
||||
let last_colon = s
|
||||
.rfind(':')
|
||||
.ok_or(PolicyError::MalformedAddressPortPattern { raw: s.to_string() })?;
|
||||
|
||||
// doesn't have enough chars to cover the port, even if its a wildcard
|
||||
if s.len() < last_colon + 2 {
|
||||
return Err(PolicyError::MalformedAddressPortPattern { raw: s.to_string() });
|
||||
}
|
||||
|
||||
let ip_pattern = s[..last_colon].parse()?;
|
||||
let ports = s[last_colon + 1..].parse()?;
|
||||
|
||||
Ok(AddressPortPattern { ip_pattern, ports })
|
||||
}
|
||||
}
|
||||
|
||||
/// A pattern that matches one or more IP addresses.
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub enum IpPattern {
|
||||
/// Match all addresses.
|
||||
Star,
|
||||
|
||||
/// Match all IPv4 addresses.
|
||||
V4Star,
|
||||
|
||||
/// Match all IPv6 addresses.
|
||||
V6Star,
|
||||
|
||||
/// Match all IPv4 addresses beginning with a given prefix and mask.
|
||||
V4 { addr_prefix: Ipv4Addr, mask: u8 },
|
||||
|
||||
/// Match all IPv6 addresses beginning with a given prefix and mask.
|
||||
V6 { addr_prefix: Ipv6Addr, mask: u8 },
|
||||
}
|
||||
|
||||
impl IpPattern {
|
||||
/// Construct an IpPattern that matches the first `mask` bits of `addr`.
|
||||
fn from_addr_and_mask(address: IpAddr, target_mask: u8) -> Result<Self, PolicyError> {
|
||||
match (address, target_mask) {
|
||||
(IpAddr::V4(_), 0) => Ok(IpPattern::V4Star),
|
||||
(IpAddr::V6(_), 0) => Ok(IpPattern::V6Star),
|
||||
(IpAddr::V4(addr_prefix), mask) if mask <= 32 => {
|
||||
Ok(IpPattern::V4 { addr_prefix, mask })
|
||||
}
|
||||
(IpAddr::V6(addr_prefix), mask) if mask <= 128 => {
|
||||
Ok(IpPattern::V6 { addr_prefix, mask })
|
||||
}
|
||||
(addr, mask) => {
|
||||
if addr.is_ipv4() {
|
||||
Err(PolicyError::InvalidIpV4Mask { mask })
|
||||
} else {
|
||||
Err(PolicyError::InvalidIpV6Mask { mask })
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Return true iff `addr` is matched by this pattern.
|
||||
fn matches(&self, addr: &IpAddr) -> bool {
|
||||
match (self, addr) {
|
||||
(IpPattern::Star, _) => true,
|
||||
(IpPattern::V4Star, IpAddr::V4(_)) => true,
|
||||
(IpPattern::V6Star, IpAddr::V6(_)) => true,
|
||||
(IpPattern::V4 { addr_prefix, mask }, IpAddr::V4(addr)) => {
|
||||
let p1 = u32::from_be_bytes(addr_prefix.octets());
|
||||
let p2 = u32::from_be_bytes(addr.octets());
|
||||
|
||||
let shift = 32 - mask;
|
||||
(p1 >> shift) == (p2 >> shift)
|
||||
}
|
||||
(IpPattern::V6 { addr_prefix, mask }, IpAddr::V6(addr)) => {
|
||||
let p1 = u128::from_be_bytes(addr_prefix.octets());
|
||||
let p2 = u128::from_be_bytes(addr.octets());
|
||||
|
||||
let shift = 128 - mask;
|
||||
(p1 >> shift) == (p2 >> shift)
|
||||
}
|
||||
(_, _) => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for IpPattern {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
IpPattern::Star => write!(f, "*"),
|
||||
IpPattern::V4Star => write!(f, "*4"),
|
||||
IpPattern::V6Star => write!(f, "*6"),
|
||||
IpPattern::V4 { addr_prefix, mask } => {
|
||||
write!(f, "{addr_prefix}/{mask}")
|
||||
}
|
||||
IpPattern::V6 { addr_prefix, mask } => {
|
||||
write!(f, "{addr_prefix}/{mask}")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Helper: try to parse a plain ipv4 address, or an IPv6 address
|
||||
/// wrapped in brackets.
|
||||
fn parse_addr(s: &str) -> Result<IpAddr, PolicyError> {
|
||||
if s.starts_with('[') && s.ends_with(']') {
|
||||
Ipv6Addr::from_str(&s[1..s.len() - 1]).map(IpAddr::V6)
|
||||
} else {
|
||||
IpAddr::from_str(s)
|
||||
}
|
||||
.map_err(|source| PolicyError::MalformedIpAddress {
|
||||
addr: s.to_string(),
|
||||
source,
|
||||
})
|
||||
}
|
||||
|
||||
/// Helper: try to parse a port making sure it's non-zero
|
||||
fn parse_port(s: &str) -> Result<u16, PolicyError> {
|
||||
let port = s
|
||||
.parse::<u16>()
|
||||
.map_err(|_| PolicyError::InvalidPort { raw: s.to_string() })?;
|
||||
|
||||
if port == 0 {
|
||||
Err(PolicyError::InvalidPort {
|
||||
raw: port.to_string(),
|
||||
})
|
||||
} else {
|
||||
Ok(port)
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for IpPattern {
|
||||
type Err = PolicyError;
|
||||
fn from_str(s: &str) -> Result<Self, PolicyError> {
|
||||
let (ip_s, mask_s) = match s.find('/') {
|
||||
Some(slash_idx) => (&s[..slash_idx], Some(&s[slash_idx + 1..])),
|
||||
None => (s, None),
|
||||
};
|
||||
|
||||
match (ip_s, mask_s) {
|
||||
// '*' patterns
|
||||
("*", Some(m)) => Err(PolicyError::MaskWithStar {
|
||||
mask: m.to_string(),
|
||||
}),
|
||||
("*", None) => Ok(IpPattern::Star),
|
||||
|
||||
// '*4' patterns
|
||||
("*4", Some(m)) => Err(PolicyError::MaskWithV4Star {
|
||||
mask: m.to_string(),
|
||||
}),
|
||||
("*4", None) => Ok(IpPattern::V4Star),
|
||||
|
||||
// '*6' patterns
|
||||
("*6", Some(m)) => Err(PolicyError::MaskWithV6Star {
|
||||
mask: m.to_string(),
|
||||
}),
|
||||
("*6", None) => Ok(IpPattern::V6Star),
|
||||
|
||||
(s, Some(m)) => {
|
||||
let a: IpAddr = parse_addr(s)?;
|
||||
let m: u8 = m.parse().map_err(|_| PolicyError::InvalidMask {
|
||||
mask: m.to_string(),
|
||||
})?;
|
||||
IpPattern::from_addr_and_mask(a, m)
|
||||
}
|
||||
(s, None) => {
|
||||
let a: IpAddr = parse_addr(s)?;
|
||||
let m = if a.is_ipv4() { 32 } else { 128 };
|
||||
IpPattern::from_addr_and_mask(a, m)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A PortRange is a set of consecutively numbered TCP or UDP ports.
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// use nym_exit_policy::policy::PortRange;
|
||||
///
|
||||
/// let r: PortRange = "22-8000".parse().unwrap();
|
||||
/// assert!(r.contains(128));
|
||||
/// assert!(r.contains(22));
|
||||
/// assert!(r.contains(8000));
|
||||
///
|
||||
/// assert!(! r.contains(21));
|
||||
/// assert!(! r.contains(8001));
|
||||
/// ```
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
|
||||
pub struct PortRange {
|
||||
/// The first port in this range.
|
||||
#[cfg_attr(feature = "openapi", schema(example = 80))]
|
||||
pub start: u16,
|
||||
|
||||
/// The last port in this range.
|
||||
#[cfg_attr(feature = "openapi", schema(example = 81))]
|
||||
pub end: u16,
|
||||
}
|
||||
|
||||
impl PortRange {
|
||||
/// Create a new port range spanning from start to end, asserting that
|
||||
/// the correct invariants hold.
|
||||
fn new_unchecked(start: u16, end: u16) -> Self {
|
||||
assert_ne!(start, 0);
|
||||
assert!(start <= end);
|
||||
|
||||
PortRange { start, end }
|
||||
}
|
||||
|
||||
/// Create a port range containing all ports.
|
||||
pub fn new_all() -> Self {
|
||||
PortRange::new_unchecked(1, 65535)
|
||||
}
|
||||
|
||||
/// Create a new PortRange.
|
||||
///
|
||||
/// The Portrange contains all ports between `start` and `end` inclusive.
|
||||
///
|
||||
/// Returns None if lo is greater than end, or if either is zero.
|
||||
pub const fn new(start: u16, end: u16) -> Option<Self> {
|
||||
if start != 0 && start <= end {
|
||||
Some(PortRange { start, end })
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a new singleton PortRange.
|
||||
pub const fn new_singleton(value: u16) -> Self {
|
||||
PortRange {
|
||||
start: value,
|
||||
end: value,
|
||||
}
|
||||
}
|
||||
|
||||
/// Return true if a port is in this range.
|
||||
pub fn contains(&self, port: u16) -> bool {
|
||||
self.start <= port && port <= self.end
|
||||
}
|
||||
|
||||
/// Return true if this range contains all ports.
|
||||
pub fn is_all(&self) -> bool {
|
||||
self.start == 1 && self.end == 65535
|
||||
}
|
||||
}
|
||||
|
||||
/// A PortRange is displayed as a number if it contains a single port,
|
||||
/// and as a start point and end point separated by a dash if it contains
|
||||
/// more than one port.
|
||||
impl Display for PortRange {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
if self.is_all() {
|
||||
write!(f, "*")
|
||||
} else if self.start == self.end {
|
||||
write!(f, "{}", self.start)
|
||||
} else {
|
||||
write!(f, "{}-{}", self.start, self.end)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for PortRange {
|
||||
type Err = PolicyError;
|
||||
fn from_str(s: &str) -> Result<Self, PolicyError> {
|
||||
// check is if it's a star range
|
||||
if s == "*" {
|
||||
return Ok(PortRange::new_all());
|
||||
}
|
||||
|
||||
if let Some(pos) = s.find('-') {
|
||||
// This is a range; parse each part
|
||||
let start = parse_port(&s[..pos])?;
|
||||
let end = parse_port(&s[pos + 1..])?;
|
||||
PortRange::new(start, end).ok_or(PolicyError::InvalidRange { start, end })
|
||||
} else {
|
||||
// There was no hyphen, so try to parse this range as a singleton.
|
||||
let value = parse_port(s)?;
|
||||
Ok(PortRange::new_singleton(value))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_bad_rules() {
|
||||
fn check(s: &str) {
|
||||
assert!(s.parse::<AddressPortPattern>().is_err());
|
||||
}
|
||||
|
||||
check("marzipan:80");
|
||||
check("1.2.3.4:90-80");
|
||||
check("1.2.3.4/100:8888");
|
||||
check("[1.2.3.4]/16:80");
|
||||
check("[::1]/130:8888");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rule_matches() {
|
||||
fn check(address: &str, yes: &[&str], no: &[&str]) {
|
||||
use std::net::SocketAddr;
|
||||
let policy = address.parse::<AddressPortPattern>().unwrap();
|
||||
for s in yes {
|
||||
let sa = s.parse::<SocketAddr>().unwrap();
|
||||
assert!(policy.matches_sockaddr(&sa));
|
||||
}
|
||||
for s in no {
|
||||
let sa = s.parse::<SocketAddr>().unwrap();
|
||||
assert!(!policy.matches_sockaddr(&sa));
|
||||
}
|
||||
}
|
||||
|
||||
check(
|
||||
"1.2.3.4/16:80",
|
||||
&["1.2.3.4:80", "1.2.44.55:80"],
|
||||
&["9.9.9.9:80", "1.3.3.4:80", "1.2.3.4:81"],
|
||||
);
|
||||
check(
|
||||
"*:443-8000",
|
||||
&["1.2.3.4:443", "[::1]:500"],
|
||||
&["9.0.0.0:80", "[::1]:80"],
|
||||
);
|
||||
check(
|
||||
"[face::]/8:80",
|
||||
&["[fab0::7]:80"],
|
||||
&["[dd00::]:80", "[face::7]:443"],
|
||||
);
|
||||
|
||||
check("0.0.0.0/0:*", &["127.0.0.1:80"], &["[f00b::]:80"]);
|
||||
check("[::]/0:*", &["[f00b::]:80"], &["127.0.0.1:80"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_policy_matches() -> Result<(), PolicyError> {
|
||||
let mut policy = AddressPolicy::default();
|
||||
policy.push(AddressPolicyAction::Accept, "*:443".parse()?);
|
||||
policy.push(AddressPolicyAction::Accept, "[::1]:80".parse()?);
|
||||
policy.push(AddressPolicyAction::Reject, "*:80".parse()?);
|
||||
|
||||
let policy = policy; // drop mut
|
||||
assert!(policy
|
||||
.allows_sockaddr(&"[::6]:443".parse().unwrap())
|
||||
.unwrap());
|
||||
assert!(policy
|
||||
.allows_sockaddr(&"127.0.0.1:443".parse().unwrap())
|
||||
.unwrap());
|
||||
assert!(policy
|
||||
.allows_sockaddr(&"[::1]:80".parse().unwrap())
|
||||
.unwrap());
|
||||
assert!(!policy
|
||||
.allows_sockaddr(&"[::2]:80".parse().unwrap())
|
||||
.unwrap());
|
||||
assert!(!policy
|
||||
.allows_sockaddr(&"127.0.0.1:80".parse().unwrap())
|
||||
.unwrap());
|
||||
assert!(policy
|
||||
.allows_sockaddr(&"127.0.0.1:66".parse().unwrap())
|
||||
.is_none());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_portrange() {
|
||||
assert_eq!(
|
||||
"1-100".parse::<PortRange>().unwrap(),
|
||||
PortRange::new(1, 100).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
"01-100".parse::<PortRange>().unwrap(),
|
||||
PortRange::new(1, 100).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
"1-65535".parse::<PortRange>().unwrap(),
|
||||
PortRange::new_all()
|
||||
);
|
||||
assert_eq!(
|
||||
"10-30".parse::<PortRange>().unwrap(),
|
||||
PortRange::new(10, 30).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
"9001".parse::<PortRange>().unwrap(),
|
||||
PortRange::new(9001, 9001).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
"9001-9001".parse::<PortRange>().unwrap(),
|
||||
PortRange::new(9001, 9001).unwrap()
|
||||
);
|
||||
assert_eq!("*".parse::<PortRange>().unwrap(), PortRange::new_all());
|
||||
|
||||
assert!("hello".parse::<PortRange>().is_err());
|
||||
assert!("0".parse::<PortRange>().is_err());
|
||||
assert!("65536".parse::<PortRange>().is_err());
|
||||
assert!("65537".parse::<PortRange>().is_err());
|
||||
assert!("1-2-3".parse::<PortRange>().is_err());
|
||||
assert!("10-5".parse::<PortRange>().is_err());
|
||||
assert!("1-".parse::<PortRange>().is_err());
|
||||
assert!("-2".parse::<PortRange>().is_err());
|
||||
assert!("-".parse::<PortRange>().is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_portrange() {
|
||||
assert!(PortRange::new_all().is_all());
|
||||
assert!(!PortRange::new(2, 65535).unwrap().is_all());
|
||||
|
||||
assert!(PortRange::new_all().contains(1));
|
||||
assert!(PortRange::new_all().contains(65535));
|
||||
assert!(PortRange::new_all().contains(7777));
|
||||
|
||||
assert!(PortRange::new(20, 30).unwrap().contains(20));
|
||||
assert!(PortRange::new(20, 30).unwrap().contains(25));
|
||||
assert!(PortRange::new(20, 30).unwrap().contains(30));
|
||||
assert!(!PortRange::new(20, 30).unwrap().contains(19));
|
||||
assert!(!PortRange::new(20, 30).unwrap().contains(31));
|
||||
}
|
||||
|
||||
// this test exists due to manually implemented 'stringified_ip_pattern' on 'AddressPortPattern'
|
||||
#[test]
|
||||
fn policy_serde_json_roundtrip() {
|
||||
let policy = AddressPolicy::parse_from_torrc(
|
||||
r#"
|
||||
ExitPolicy reject 1.2.3.4/32:*
|
||||
ExitPolicy reject 1.2.3.5:*
|
||||
ExitPolicy reject 1.2.3.6/16:*
|
||||
ExitPolicy reject 1.2.3.6/16:123-456
|
||||
ExitPolicy accept *:53
|
||||
ExitPolicy accept6 *6:119
|
||||
ExitPolicy accept *4:120
|
||||
ExitPolicy reject6 [FC00::]/7:*
|
||||
ExitPolicy reject FE80:0000:0000:0000:0202:B3FF:FE1E:8329:*
|
||||
ExitPolicy reject FE80:0000:0000:0000:0202:B3FF:FE1E:8328:1234
|
||||
ExitPolicy reject FE80:0000:0000:0000:0202:B3FF:FE1E:8328/64:1235
|
||||
ExitPolicy reject *:*"#,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let json = serde_json::to_string(&policy).unwrap();
|
||||
let recovered: AddressPolicy = serde_json::from_str(&json).unwrap();
|
||||
|
||||
assert_eq!(recovered, policy);
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user