Compare commits
253 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0f8a8ddf7e | |||
| 3c92ce60ca | |||
| 846dbba363 | |||
| 94ab9d5466 | |||
| c78d942383 | |||
| 0b6166d20e | |||
| 6384467526 | |||
| fdd3823585 | |||
| 892a3bd826 | |||
| 59ff7d6588 | |||
| 20c4553bca | |||
| 4c38481c36 | |||
| 07680db2c7 | |||
| 59cbce50f7 | |||
| ac13ddbda8 | |||
| 67803930b6 | |||
| 7052e2e902 | |||
| cccfa76336 | |||
| a946336e67 | |||
| e5836bc1cb | |||
| f12108a7db | |||
| 70bdbce23f | |||
| e6f9b551ed | |||
| fcfa0b604e | |||
| 8b086e0239 | |||
| 6c76834b6c | |||
| 071589237b | |||
| 771ee10ba2 | |||
| 33ce05a3df | |||
| 73016ed687 | |||
| 8a5205ac4c | |||
| aaa7e317bf | |||
| f28c49e9d6 | |||
| e2ceaf48ed | |||
| 3e2137a33e | |||
| 984fa065e3 | |||
| da46ea7485 | |||
| b1bc359806 | |||
| b338644620 | |||
| 1ec0bf868b | |||
| 07842661b9 | |||
| 0cd4dd5747 | |||
| abdd960b20 | |||
| db2f3bff05 | |||
| be56c79106 | |||
| 3ccfbee834 | |||
| 942ab3c8e8 | |||
| 9ec937dd30 | |||
| 6ccc4a988a | |||
| 27890eb1a3 | |||
| fa327a1b2a | |||
| cea66c1237 | |||
| 757a89c5d7 | |||
| 1e3f531e15 | |||
| 7cc33d8df7 | |||
| 1bd0bfeee1 | |||
| f297af2a8c | |||
| d9190e5899 | |||
| a562812ad9 | |||
| 7368692629 | |||
| c185f485a7 | |||
| 6930968e88 | |||
| 8294191913 | |||
| 9b2fb45270 | |||
| cb8747abb8 | |||
| 47d37d8aed | |||
| d452932b18 | |||
| 702dfdc927 | |||
| 18e8dfe394 | |||
| 0208a84b77 | |||
| 7105bbf4b4 | |||
| 39692502df | |||
| fcefa079b0 | |||
| 371422f27b | |||
| 5541f242ff | |||
| 348e93dd70 | |||
| 7f8b7eea8c | |||
| 8760c40d46 | |||
| 8ae4b8fee2 | |||
| 4f4885fe50 | |||
| bc52db53b7 | |||
| 08d49a6f2e | |||
| 6f53192dbf | |||
| b5afb77f19 | |||
| 29714dea76 | |||
| 8fd9cee189 | |||
| 2b4a11e273 | |||
| a58b32703c | |||
| de80b4ce48 | |||
| 85a3b25be9 | |||
| 708bd71a56 | |||
| 40b886e0bd | |||
| 23c1c4bdac | |||
| 2dd8707725 | |||
| 0bb3c4b2bf | |||
| 72e8180abe | |||
| 2d5b1d577c | |||
| b5e45040ca | |||
| e420081512 | |||
| 0da4ee985b | |||
| 6d8cacc900 | |||
| 49543fcd98 | |||
| 7b80716c9a | |||
| a4a48c60ae | |||
| e027b5a1fe | |||
| 723df5584e | |||
| 2ca5155748 | |||
| 4f0cc58a11 | |||
| 2ccdfedd65 | |||
| d7ddb7592c | |||
| 7371ce3e36 | |||
| cd7bb9931e | |||
| b77dbdd87e | |||
| 83dcf3fd13 | |||
| a5c6e9d0e2 | |||
| a417411184 | |||
| 24d5e4aba9 | |||
| 6cb2fc8445 | |||
| 4ea2c3beb3 | |||
| be8c1191f3 | |||
| d969979c8c | |||
| c6fd3c8527 | |||
| 6ac4d93909 | |||
| 197a7eaec8 | |||
| f598ee2916 | |||
| b2fa6cdf8f | |||
| 97dbef155d | |||
| 9dbd91d93e | |||
| 7914cbdbb7 | |||
| 99febfb3aa | |||
| 2b00188983 | |||
| 82f270329f | |||
| 3cb17e76bd | |||
| 7b2f8a4ed1 | |||
| 438e745cb3 | |||
| 674fd511f4 | |||
| 66d85a7c0d | |||
| d12a5d754a | |||
| 3a78d62240 | |||
| 5e651b55fc | |||
| 8a6bf4a03d | |||
| 6a2f1a67ed | |||
| d56ab91a2e | |||
| 8f670f467b | |||
| d013168823 | |||
| 8dc3ba4ec3 | |||
| 712e3f5183 | |||
| 5229df47ab | |||
| 32cffed36b | |||
| 49c710e651 | |||
| 0a5227a894 | |||
| b231eb4f04 | |||
| fdd2c8fac2 | |||
| e2dd8ac743 | |||
| 8001fa7f40 | |||
| 80370b98ec | |||
| 3524089ad8 | |||
| ec7ee49282 | |||
| 653d1c2dea | |||
| b579f987b1 | |||
| 59254c92c3 | |||
| 69887921cc | |||
| e075b07632 | |||
| d32b680351 | |||
| fcd59a19be | |||
| 08b20ac2ab | |||
| 4c007669f9 | |||
| c3a8fa8d0d | |||
| d8769157fd | |||
| 7cccf3cfff | |||
| 02eec164f8 | |||
| 4f13ab1e0a | |||
| a34c7ef19f | |||
| f00b18298c | |||
| 0426adc94e | |||
| 4b4a2fe387 | |||
| 1ebb7e06c7 | |||
| 1fd17c5cb3 | |||
| ef65cf4c9e | |||
| 48dad0f16b | |||
| 93ac638765 | |||
| c6589ca92c | |||
| 03d5a87826 | |||
| 512cfd1b74 | |||
| ba0625cd97 | |||
| a2c489dc5b | |||
| 5cee248122 | |||
| 86aec84697 | |||
| 8f376d1b9b | |||
| f0ae4f4090 | |||
| 4e850f6fe0 | |||
| bd3678dd4f | |||
| 28c1637198 | |||
| 8de574ec97 | |||
| 4464d12103 | |||
| 0d9d97e31e | |||
| a7705a5f2c | |||
| 7a300bdd74 | |||
| 6569479083 | |||
| 611844b248 | |||
| 2cc9b05520 | |||
| 05b6f5e282 | |||
| a450b6f984 | |||
| 5093450004 | |||
| f6bd511599 | |||
| e5c3f39a57 | |||
| 76f999fc88 | |||
| 2fce8c7ca3 | |||
| 468bd8b5d1 | |||
| 45022b1671 | |||
| 3b3c5beae4 | |||
| 650917e216 | |||
| c02adaa019 | |||
| d01c34263a | |||
| f247e028f2 | |||
| 20fe8dd028 | |||
| 89edabf796 | |||
| bf5352906f | |||
| 8eb9999876 | |||
| c0f582b336 | |||
| 133a855e01 | |||
| 98149dde87 | |||
| 5e733a5ebf | |||
| 5647ae6a41 | |||
| 4ed9d8fb7a | |||
| a2081af603 | |||
| 5b62fd76ba | |||
| 77a34fe3bf | |||
| 630c4922ac | |||
| 6edbece3ad | |||
| 8529a3c351 | |||
| 453e1cbe70 | |||
| 94a3599b4d | |||
| a6bc54461a | |||
| 4f0c40dab7 | |||
| 3eff6e5e3b | |||
| a519f4ccb8 | |||
| a3ba3bfc5a | |||
| 988df7cff7 | |||
| 260f8e9714 | |||
| d28d0ac39e | |||
| dce4d6b34b | |||
| bc47e9a1b2 | |||
| 3b693741b2 | |||
| cb277fe487 | |||
| 8bb29f4d07 | |||
| e753f24ed1 | |||
| c7cd962627 | |||
| 00467e4440 | |||
| f3d1000472 | |||
| 597aae1a20 | |||
| 40a3cd28b7 | |||
| a4950485d1 |
@@ -6,6 +6,8 @@ on:
|
||||
jobs:
|
||||
build:
|
||||
runs-on: arc-ubuntu-22.04
|
||||
env:
|
||||
NEXT_PUBLIC_SITE_URL: https://nym.com/docs
|
||||
defaults:
|
||||
run:
|
||||
working-directory: documentation/docs
|
||||
@@ -41,6 +43,8 @@ jobs:
|
||||
run: pnpm i
|
||||
- name: Build project
|
||||
run: pnpm run build
|
||||
- name: Generate sitemap
|
||||
run: npx next-sitemap
|
||||
- name: Move files to /dist/
|
||||
run: ../scripts/move-to-dist.sh
|
||||
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
name: ci-build-vpn-api-wasm
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- 'common/**'
|
||||
- 'nym-credential-proxy/**'
|
||||
- '.github/workflows/ci-build-vpn-api-wasm.yml'
|
||||
|
||||
jobs:
|
||||
wasm:
|
||||
runs-on: arc-linux-latest
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
RUSTUP_PERMIT_COPY_RENAME: 1
|
||||
steps:
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Install Rust toolchain
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
profile: minimal
|
||||
toolchain: ${{ vars.REQUIRED_RUSTC_VERSION }}
|
||||
target: wasm32-unknown-unknown
|
||||
override: true
|
||||
components: rustfmt, clippy
|
||||
|
||||
- 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: Install wasm-bindgen-cli
|
||||
run: cargo install wasm-bindgen-cli
|
||||
|
||||
- name: "Build"
|
||||
run: make
|
||||
working-directory: nym-credential-proxy/vpn-api-lib-wasm
|
||||
@@ -16,7 +16,7 @@ jobs:
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Get version from cargo.toml
|
||||
uses: mikefarah/yq@v4.52.2
|
||||
uses: mikefarah/yq@v4.52.4
|
||||
id: get_version
|
||||
with:
|
||||
cmd: yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/Cargo.toml
|
||||
|
||||
@@ -16,7 +16,7 @@ jobs:
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Get version from cargo.toml
|
||||
uses: mikefarah/yq@v4.52.2
|
||||
uses: mikefarah/yq@v4.52.4
|
||||
id: get_version
|
||||
with:
|
||||
cmd: yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/Cargo.toml
|
||||
|
||||
@@ -48,6 +48,8 @@ jobs:
|
||||
run: pnpm i
|
||||
- name: Build project
|
||||
run: pnpm run build
|
||||
- name: Generate sitemap
|
||||
run: npx next-sitemap
|
||||
- name: Move files to /dist/
|
||||
run: ../scripts/move-to-dist.sh
|
||||
|
||||
|
||||
@@ -51,25 +51,3 @@ 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
|
||||
NYM_PROJECT_NAME: "nym-wallet"
|
||||
NYM_CI_WWW_BASE: "${{ secrets.NYM_CI_WWW_BASE }}"
|
||||
NYM_CI_WWW_LOCATION: "wallet-${{ env.GITHUB_REF_SLUG }}"
|
||||
GIT_COMMIT_MESSAGE: "${{ github.event.head_commit.message }}"
|
||||
GIT_BRANCH: "${GITHUB_REF##*/}"
|
||||
IS_SUCCESS: "${{ job.status == 'success' }}"
|
||||
MATRIX_SERVER: "${{ secrets.MATRIX_SERVER }}"
|
||||
MATRIX_ROOM: "${{ secrets.MATRIX_ROOM }}"
|
||||
MATRIX_USER_ID: "${{ secrets.MATRIX_USER_ID }}"
|
||||
MATRIX_TOKEN: "${{ secrets.MATRIX_TOKEN }}"
|
||||
MATRIX_DEVICE_ID: "${{ secrets.MATRIX_DEVICE_ID }}"
|
||||
uses: docker://keybaseio/client:stable-node
|
||||
with:
|
||||
args: .github/workflows/support-files/notifications/entry_point.sh
|
||||
|
||||
@@ -8,7 +8,7 @@ on:
|
||||
jobs:
|
||||
sonarqube:
|
||||
name: SonarQube
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: arc-linux-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
|
||||
@@ -2,16 +2,14 @@ name: nightly-build
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: '14 1 * * *'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
rust: [stable, beta]
|
||||
os: [ubuntu-22.04, windows-latest, macos-latest]
|
||||
rust: [ stable, beta ]
|
||||
os: [ ubuntu-22.04, windows-latest, macos-latest ]
|
||||
runs-on: ${{ matrix.os }}
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
@@ -93,38 +91,3 @@ jobs:
|
||||
with:
|
||||
command: clippy
|
||||
args: --workspace --all-targets -- -D warnings
|
||||
|
||||
notification:
|
||||
needs: build
|
||||
runs-on: custom-linux
|
||||
steps:
|
||||
- name: Collect jobs status
|
||||
uses: technote-space/workflow-conclusion-action@v3
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v6
|
||||
- name: install npm
|
||||
uses: actions/setup-node@v4
|
||||
if: env.WORKFLOW_CONCLUSION == 'failure'
|
||||
with:
|
||||
node-version: 20
|
||||
- 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 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
|
||||
|
||||
@@ -10,7 +10,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-22.04, macos-latest, windows-latest]
|
||||
os: [ ubuntu-22.04, macos-latest, windows-latest ]
|
||||
runs-on: ${{ matrix.os }}
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
@@ -55,38 +55,3 @@ jobs:
|
||||
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@v3
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v6
|
||||
- name: install npm
|
||||
uses: actions/setup-node@v4
|
||||
if: env.WORKFLOW_CONCLUSION == 'failure'
|
||||
with:
|
||||
node-version: 20
|
||||
- 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-wallet-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
|
||||
|
||||
@@ -24,34 +24,3 @@ jobs:
|
||||
with:
|
||||
name: report
|
||||
path: .github/workflows/support-files/notifications/deny.message
|
||||
notification:
|
||||
needs: cargo-deny
|
||||
runs-on: custom-linux
|
||||
steps:
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v6
|
||||
- name: Download report from previous job
|
||||
uses: actions/download-artifact@v7
|
||||
with:
|
||||
name: report
|
||||
path: .github/workflows/support-files/notifications
|
||||
- name: install npm
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
- name: Matrix - Node Install
|
||||
run: npm install
|
||||
working-directory: .github/workflows/support-files
|
||||
- name: Matrix - Send Notification
|
||||
env:
|
||||
NYM_NOTIFICATION_KIND: security
|
||||
NYM_PROJECT_NAME: "Daily security report"
|
||||
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
|
||||
MATRIX_SERVER: "${{ secrets.MATRIX_SERVER }}"
|
||||
MATRIX_ROOM: "${{ secrets.MATRIX_ROOM_AUDIT }}"
|
||||
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
|
||||
|
||||
@@ -9,7 +9,7 @@ on:
|
||||
|
||||
jobs:
|
||||
integration-tests:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: arc-linux-latest
|
||||
env:
|
||||
API_BASE_URL: http://localhost:8000
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ env:
|
||||
jobs:
|
||||
check-milestone:
|
||||
name: Check Milestone
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: arc-linux-latest
|
||||
steps:
|
||||
- if: github.event.pull_request.milestone == null && contains( env.LABELS, 'no-milestone' ) == false
|
||||
run: exit 1
|
||||
|
||||
@@ -36,6 +36,9 @@ jobs:
|
||||
with:
|
||||
go-version: "1.24.6"
|
||||
|
||||
- name: Update root CA certificate bundle
|
||||
run: ./wasm/mix-fetch/go-mix-conn/scripts/update-root-certs.sh
|
||||
|
||||
- name: Install dependencies
|
||||
run: yarn
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ jobs:
|
||||
git config --global user.name "Lawrence Stalder"
|
||||
|
||||
- name: Get version from cargo.toml
|
||||
uses: mikefarah/yq@v4.52.2
|
||||
uses: mikefarah/yq@v4.52.4
|
||||
id: get_version
|
||||
with:
|
||||
cmd: yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/nym-credential-proxy/Cargo.toml
|
||||
|
||||
@@ -26,7 +26,7 @@ jobs:
|
||||
git config --global user.name "Lawrence Stalder"
|
||||
|
||||
- name: Get version from cargo.toml
|
||||
uses: mikefarah/yq@v4.52.2
|
||||
uses: mikefarah/yq@v4.52.4
|
||||
id: get_version
|
||||
with:
|
||||
cmd: yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/Cargo.toml
|
||||
|
||||
@@ -26,7 +26,7 @@ jobs:
|
||||
git config --global user.name "Lawrence Stalder"
|
||||
|
||||
- name: Get version from cargo.toml
|
||||
uses: mikefarah/yq@v4.52.2
|
||||
uses: mikefarah/yq@v4.52.4
|
||||
id: get_version
|
||||
with:
|
||||
cmd: yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/nym-network-monitor/Cargo.toml
|
||||
|
||||
@@ -26,7 +26,7 @@ jobs:
|
||||
git config --global user.name "Lawrence Stalder"
|
||||
|
||||
- name: Get version from cargo.toml
|
||||
uses: mikefarah/yq@v4.52.2
|
||||
uses: mikefarah/yq@v4.52.4
|
||||
id: get_version
|
||||
with:
|
||||
cmd: yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/nym-api/Cargo.toml
|
||||
|
||||
@@ -26,7 +26,7 @@ jobs:
|
||||
git config --global user.name "Lawrence Stalder"
|
||||
|
||||
- name: Get version from cargo.toml
|
||||
uses: mikefarah/yq@v4.52.2
|
||||
uses: mikefarah/yq@v4.52.4
|
||||
id: get_version
|
||||
with:
|
||||
cmd: yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/Cargo.toml
|
||||
|
||||
@@ -26,7 +26,7 @@ jobs:
|
||||
git config --global user.name "Lawrence Stalder"
|
||||
|
||||
- name: Get version from cargo.toml
|
||||
uses: mikefarah/yq@v4.52.2
|
||||
uses: mikefarah/yq@v4.52.4
|
||||
id: get_version
|
||||
with:
|
||||
cmd: yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/Cargo.toml
|
||||
|
||||
@@ -26,7 +26,7 @@ jobs:
|
||||
git config --global user.name "Lawrence Stalder"
|
||||
|
||||
- name: Get version from cargo.toml
|
||||
uses: mikefarah/yq@v4.52.2
|
||||
uses: mikefarah/yq@v4.52.4
|
||||
id: get_version
|
||||
with:
|
||||
cmd: yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/Cargo.toml
|
||||
|
||||
@@ -26,7 +26,7 @@ jobs:
|
||||
git config --global user.name "Lawrence Stalder"
|
||||
|
||||
- name: Get version from cargo.toml
|
||||
uses: mikefarah/yq@v4.52.2
|
||||
uses: mikefarah/yq@v4.52.4
|
||||
id: get_version
|
||||
with:
|
||||
cmd: yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/Cargo.toml
|
||||
|
||||
@@ -4,51 +4,23 @@ This is a collection of scripts and files to support GitHub Actions.
|
||||
|
||||
## Sending Notifications
|
||||
|
||||
These scripts send CI notifications to Matrix by creating messages from templates and env vars passed from GitHub Actions.
|
||||
|
||||
### Adding notifications to a GitHub Action
|
||||
|
||||
```
|
||||
jobs:
|
||||
build:
|
||||
...
|
||||
- name: Notifications - Node Install
|
||||
run: npm install
|
||||
working-directory: .github/workflows/support-files/notifications
|
||||
- name: Notifications - Send
|
||||
env:
|
||||
NYM_NOTIFICATION_KIND: "my-component"
|
||||
GIT_BRANCH: "${GITHUB_REF##*/}"
|
||||
MATRIX_SERVER: "${{ secrets.MATRIX_SERVER }}"
|
||||
MATRIX_ROOM: "${{ secrets.MATRIX_ROOM }}"
|
||||
MATRIX_USER_ID: "${{ secrets.MATRIX_USER_ID }}"
|
||||
MATRIX_TOKEN: "${{ secrets.MATRIX_TOKEN }}"
|
||||
MATRIX_DEVICE_ID: "${{ secrets.MATRIX_DEVICE_ID }}"
|
||||
IS_SUCCESS: "${{ job.status == 'success' }}"
|
||||
uses: docker://keybaseio/client:stable-node
|
||||
with:
|
||||
args: .github/workflows/support-files/notifications/entry_point.sh
|
||||
```
|
||||
|
||||
Notifications are run by adding the snippet above to a GitHub Action, and:
|
||||
|
||||
1. Installing node packages needed at run time
|
||||
2. Set the env vars as required:
|
||||
- `NYM_NOTIFICATION_KIND` matches the directory in `.github/workflows/support-files/${NYM_NOTIFICATION_KIND}` to provide the templates and extra scripting in `index.js`
|
||||
- Matrix credentials, room and other env vars for the status of the build and repo
|
||||
3. Replacing the default entry point shell script on the `keybaseio/client:stable-node` docker image to run `.github/workflows/support-files/notifications/entry_point.sh`
|
||||
These scripts send CI notifications to Matrix by creating messages from templates and env vars passed from GitHub
|
||||
Actions.
|
||||
|
||||
### Running locally
|
||||
|
||||
You will need:
|
||||
|
||||
- Node 16 LTS
|
||||
- npm
|
||||
|
||||
Copy `.github/workflows/support-files/.env.example` to `.github/workflows/support-files/.env` and valid Matrix credentials.
|
||||
Copy `.github/workflows/support-files/.env.example` to `.github/workflows/support-files/.env` and valid Matrix
|
||||
credentials.
|
||||
|
||||
Then run `npm install` to get dependencies.
|
||||
|
||||
Start development mode for the notification type you want either by passing the value as an env var called `NYM_NOTIFICATION_KIND` or set the `.env` file values correctly.
|
||||
Start development mode for the notification type you want either by passing the value as an env var called
|
||||
`NYM_NOTIFICATION_KIND` or set the `.env` file values correctly.
|
||||
|
||||
```bash
|
||||
cd .github/workflows/support-files
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# pass exit codes out to GitHub Actions
|
||||
set -euxo pipefail
|
||||
|
||||
# change to the directory that contains this script
|
||||
cd "${0%/*}"
|
||||
|
||||
# run the node script
|
||||
node send_message.js
|
||||
@@ -1,126 +0,0 @@
|
||||
require('dotenv').config();
|
||||
|
||||
const { sendMatrixMessage } = require('./send_message_to_matrix');
|
||||
|
||||
let context = {
|
||||
kinds: ['nym-wallet', 'ts-packages', 'network-explorer', 'nightly', 'nym-connect','security','ci-docs','cd-docs','ci-dev','cd-dev'],
|
||||
};
|
||||
|
||||
/**
|
||||
* Validate that all required env and context vars are available
|
||||
*/
|
||||
function validateContext() {
|
||||
if (!context.env.NYM_NOTIFICATION_KIND) {
|
||||
throw new Error(
|
||||
'Please set env var NYM_NOTIFICATION_KIND with the project kind that matches a directory in ".github/workflows/support-files"',
|
||||
);
|
||||
}
|
||||
if (!context.kinds.includes(context.env.NYM_NOTIFICATION_KIND)) {
|
||||
throw new Error(`Env var NYM_NOTIFICATION_KIND is not in ${context.kinds}`);
|
||||
}
|
||||
if (!context.env.NYM_PROJECT_NAME) {
|
||||
throw new Error(
|
||||
'Please set env var NYM_PROJECT_NAME with the project name for displaying in notification messages',
|
||||
);
|
||||
}
|
||||
if (context.env.MATRIX_ROOM) {
|
||||
if (!context.env.MATRIX_SERVER) {
|
||||
throw new Error(
|
||||
'Matrix server is not defined. Please set env var MATRIX_SERVER',
|
||||
);
|
||||
}
|
||||
if (!context.env.MATRIX_USER_ID) {
|
||||
throw new Error(
|
||||
'Matrix user id is not defined. Please set env var MATRIX_USER_ID',
|
||||
);
|
||||
}
|
||||
if (!context.env.MATRIX_TOKEN) {
|
||||
throw new Error(
|
||||
'Matrix token is not defined. Please set env var MATRIX_TOKEN',
|
||||
);
|
||||
}
|
||||
if (!context.env.MATRIX_DEVICE_ID) {
|
||||
throw new Error(
|
||||
'Matrix device id is not defined. Please set env var MATRIX_DEVICE_ID',
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a context that will be available in the templates for rendering notifications
|
||||
*/
|
||||
function createTemplateContext() {
|
||||
const options = { dateStyle: 'full', timeStyle: 'long' };
|
||||
context.timestamp = new Date().toLocaleString(undefined, options);
|
||||
|
||||
// add environment to template context and validate
|
||||
context.env = process.env;
|
||||
try {
|
||||
validateContext();
|
||||
} catch (e) {
|
||||
if(process.env.SHOW_DEBUG) {
|
||||
// recursively print the context for easy debugging and rethrow the error
|
||||
console.dir({ context }, { depth: null });
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
|
||||
context.kind = context.env.NYM_NOTIFICATION_KIND;
|
||||
|
||||
if (!context.env.GIT_BRANCH_NAME) {
|
||||
context.env.GIT_BRANCH_NAME = context.env.GITHUB_REF.split('/')
|
||||
.slice(2)
|
||||
.join('/');
|
||||
}
|
||||
|
||||
context.status = process.env.IS_SUCCESS === 'true' ? 'success' : 'failure';
|
||||
}
|
||||
|
||||
/**
|
||||
* Uses the `kind` set in the context to process the context and generate a notification message
|
||||
* @returns {Promise<string>} A string notification message body
|
||||
*/
|
||||
async function processKindScript() {
|
||||
const script = require(`../${context.kind}`);
|
||||
if (!script.addToContextAndValidate) {
|
||||
throw new Error(
|
||||
`"./${context.kind}/index.js" does not export a method called "async addToContextAndValidate(context)"`,
|
||||
);
|
||||
}
|
||||
if (!script.getMessageBody) {
|
||||
throw new Error(
|
||||
`"./${context.kind}/index.js" does not export a method called "async getMessageBody(context)"`,
|
||||
);
|
||||
}
|
||||
|
||||
// call the script to modify and validate the context
|
||||
await script.addToContextAndValidate(context);
|
||||
|
||||
// let the script create a message body and return the result as a string for sending
|
||||
return await script.getMessageBody(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* The main function, as async so that await syntax is available
|
||||
*/
|
||||
async function main() {
|
||||
createTemplateContext();
|
||||
console.log(`Sending notification for kind "${context.kind}"...`);
|
||||
const messageBody = await processKindScript();
|
||||
if(process.env.SHOW_DEBUG) {
|
||||
console.log('-----------------------------------------');
|
||||
console.log(messageBody);
|
||||
console.log('-----------------------------------------');
|
||||
}
|
||||
if(context.env.MATRIX_ROOM) {
|
||||
await sendMatrixMessage(context, messageBody, context.env.MATRIX_ROOM)
|
||||
}
|
||||
if(context.env.MATRIX_ROOM_OF_SHAME && context.env.IS_SUCCESS !== 'true') {
|
||||
// when a job fails
|
||||
await sendMatrixMessage(context, messageBody, context.env.MATRIX_ROOM_OF_SHAME)
|
||||
}
|
||||
}
|
||||
|
||||
// call main function and let NodeJS handle the promise
|
||||
main();
|
||||
@@ -1,67 +0,0 @@
|
||||
const sdk = require('matrix-js-sdk');
|
||||
global.Olm = require('olm');
|
||||
const { LocalStorage } = require('node-localstorage');
|
||||
const localStorage = new LocalStorage('./scratch');
|
||||
const {
|
||||
LocalStorageCryptoStore,
|
||||
} = require('matrix-js-sdk/lib/crypto/store/localStorage-crypto-store');
|
||||
var showdown = require('showdown');
|
||||
|
||||
// hide all matrix client output
|
||||
console.error = (error) => console.log('❌ error: ', error);
|
||||
process.stderr.write = () => {};
|
||||
process.stdout.write = () => {};
|
||||
|
||||
|
||||
function createClient(context, room, message) {
|
||||
const server = context.env.MATRIX_SERVER;
|
||||
const token = context.env.MATRIX_TOKEN;
|
||||
const deviceId = context.env.MATRIX_DEVICE_ID;
|
||||
const userId = context.env.MATRIX_USER_ID;
|
||||
|
||||
const client = sdk.createClient({
|
||||
baseUrl: server,
|
||||
accessToken: token,
|
||||
userId,
|
||||
deviceId,
|
||||
sessionStore: new sdk.WebStorageSessionStore(localStorage),
|
||||
cryptoStore: new LocalStorageCryptoStore(localStorage),
|
||||
});
|
||||
|
||||
client.on('sync', async function(state, prevState, res) {
|
||||
if (state !== 'PREPARED') return;
|
||||
client.setGlobalErrorOnUnknownDevices(false);
|
||||
try {
|
||||
await client.joinRoom(room);
|
||||
await client.sendEvent(
|
||||
room,
|
||||
'm.room.message',
|
||||
{
|
||||
msgtype: 'm.text',
|
||||
format: 'org.matrix.custom.html',
|
||||
body: message,
|
||||
formatted_body: message,
|
||||
},
|
||||
'',
|
||||
);
|
||||
} catch (error) {
|
||||
console.error('Job failed: ' + error.message);
|
||||
}
|
||||
client.stopClient();
|
||||
process.exit(0);
|
||||
});
|
||||
|
||||
return client;
|
||||
}
|
||||
|
||||
async function sendMatrixMessage(contextArg, messageAsMarkdown, roomId) {
|
||||
const converter = new showdown.Converter();
|
||||
const messageAsHtml = converter.makeHtml(messageAsMarkdown);
|
||||
const client = createClient(contextArg, roomId, messageAsHtml);
|
||||
await client.initCrypto();
|
||||
await client.startClient({ initialSyncLimit: 1 });
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
sendMatrixMessage,
|
||||
};
|
||||
@@ -46,6 +46,7 @@ storybook-static
|
||||
**/.DS_Store
|
||||
cpu-cycles/libcpucycles/build
|
||||
foxyfox.env
|
||||
scratch.txt
|
||||
|
||||
.next
|
||||
ppa-private-key.b64
|
||||
@@ -76,3 +77,4 @@ CLAUDE.md
|
||||
.claude/settings.json
|
||||
|
||||
/notes
|
||||
/target-otel
|
||||
|
||||
+122
@@ -4,6 +4,128 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [2026.5-raclette] (2026-03-10)
|
||||
|
||||
- bugfix: correctly populate gateway probe LP data ([#6533])
|
||||
- chore: introduce additional prometheus metrics for registration times ([#6532])
|
||||
- bugfix: lp information to have proper snake_case on API endpoints ([#6531])
|
||||
- removed redundant LP states ([#6509])
|
||||
- chore: removed all matrix notifications from github actions ([#6495])
|
||||
- feat: Lewes Protocol with PSQv2 ([#6491])
|
||||
- build(deps): bump minimatch from 3.1.2 to 3.1.4 in /documentation/docs ([#6486])
|
||||
- build(deps): bump bn.js from 4.12.2 to 4.12.3 in /documentation/docs ([#6484])
|
||||
- build(deps): bump bn.js from 4.12.2 to 4.12.3 ([#6483])
|
||||
- build(deps): bump ajv from 8.17.1 to 8.18.0 in /clients/native/examples/js-examples/websocket ([#6478])
|
||||
- build(deps): bump ajv from 6.12.6 to 6.14.0 in /documentation/docs ([#6477])
|
||||
- build(deps): bump minimatch and glob in /documentation/scripts/post-process ([#6476])
|
||||
- build(deps): bump hono from 4.11.9 to 4.12.0 ([#6475])
|
||||
- build(deps): bump keccak from 0.1.5 to 0.1.6 ([#6472])
|
||||
- build(deps-dev): bump qs from 6.14.1 to 6.14.2 in /clients/native/examples/js-examples/websocket ([#6466])
|
||||
- build(deps): bump mikefarah/yq from 4.52.2 to 4.52.4 ([#6465])
|
||||
- Otel minimal v2 ([#6464])
|
||||
- build(deps): bump qs and express in /wasm/client/internal-dev ([#6461])
|
||||
- bugfix: restore 'latest_measurement' field for nym-node /verloc endpoint ([#6452])
|
||||
- build(deps-dev): bump webpack from 5.77.0 to 5.104.1 in /wasm/node-tester/internal-dev ([#6451])
|
||||
- Max/mixfetch concurrent test ([#6417])
|
||||
|
||||
[#6533]: https://github.com/nymtech/nym/pull/6533
|
||||
[#6532]: https://github.com/nymtech/nym/pull/6532
|
||||
[#6531]: https://github.com/nymtech/nym/pull/6531
|
||||
[#6509]: https://github.com/nymtech/nym/pull/6509
|
||||
[#6495]: https://github.com/nymtech/nym/pull/6495
|
||||
[#6491]: https://github.com/nymtech/nym/pull/6491
|
||||
[#6486]: https://github.com/nymtech/nym/pull/6486
|
||||
[#6484]: https://github.com/nymtech/nym/pull/6484
|
||||
[#6483]: https://github.com/nymtech/nym/pull/6483
|
||||
[#6478]: https://github.com/nymtech/nym/pull/6478
|
||||
[#6477]: https://github.com/nymtech/nym/pull/6477
|
||||
[#6476]: https://github.com/nymtech/nym/pull/6476
|
||||
[#6475]: https://github.com/nymtech/nym/pull/6475
|
||||
[#6472]: https://github.com/nymtech/nym/pull/6472
|
||||
[#6466]: https://github.com/nymtech/nym/pull/6466
|
||||
[#6465]: https://github.com/nymtech/nym/pull/6465
|
||||
[#6464]: https://github.com/nymtech/nym/pull/6464
|
||||
[#6461]: https://github.com/nymtech/nym/pull/6461
|
||||
[#6452]: https://github.com/nymtech/nym/pull/6452
|
||||
[#6451]: https://github.com/nymtech/nym/pull/6451
|
||||
[#6417]: https://github.com/nymtech/nym/pull/6417
|
||||
|
||||
## [2026.4-quark] (2026-02-24)
|
||||
|
||||
- Enhance CI workflow with feature inputs ([#6462])
|
||||
- Chore/revert 6433 ([#6445])
|
||||
- Lp/stateless handshake ([#6437])
|
||||
- build(deps-dev): bump webpack from 5.98.0 to 5.105.0 in /wasm/client/internal-dev ([#6435])
|
||||
- build(deps-dev): bump webpack from 5.102.1 to 5.104.1 ([#6432])
|
||||
- build(deps-dev): bump webpack from 5.98.0 to 5.105.0 in /wasm/mix-fetch/internal-dev ([#6431])
|
||||
- build(deps-dev): bump webpack from 5.94.0 to 5.104.1 in /nym-credential-proxy/vpn-api-lib-wasm/internal-dev ([#6430])
|
||||
- build(deps-dev): bump webpack from 5.77.0 to 5.104.1 in /wasm/zknym-lib/internal-dev ([#6429])
|
||||
- build(deps-dev): bump webpack from 5.76.0 to 5.105.0 in /clients/native/examples/js-examples/websocket ([#6428])
|
||||
- HTTP & DNS Improvements ([#6423])
|
||||
- Endpoint for exit GW IPs ([#6418])
|
||||
- build(deps): bump bytes from 1.6.0 to 1.11.1 in /contracts ([#6416])
|
||||
- build(deps): bump @isaacs/brace-expansion from 5.0.0 to 5.0.1 ([#6415])
|
||||
- build(deps): bump bytes from 1.11.0 to 1.11.1 ([#6414])
|
||||
- build(deps): bump mikefarah/yq from 4.50.1 to 4.52.2 ([#6407])
|
||||
- build(deps-dev): bump eslint from 8.57.1 to 9.26.0 ([#6405])
|
||||
- Update reqwest to v0.13.1 ([#6401])
|
||||
- build(deps): bump next from 15.5.9 to 16.1.5 in /documentation/docs ([#6387])
|
||||
- build(deps): bump next from 15.4.10 to 16.1.5 in /nym-node-status-api/nym-node-status-ui ([#6385])
|
||||
- build(deps): bump lodash from 4.17.21 to 4.17.23 ([#6369])
|
||||
- build(deps): bump lodash-es from 4.17.21 to 4.17.23 ([#6360])
|
||||
- build(deps-dev): bump lodash from 4.17.21 to 4.17.23 in /sdk/typescript/codegen/contract-clients ([#6359])
|
||||
- build(deps): bump lodash from 4.17.21 to 4.17.23 in /sdk/typescript/packages/nodejs-client ([#6354])
|
||||
- build(deps): bump lodash from 4.17.21 to 4.17.23 in /documentation/docs ([#6353])
|
||||
- build(deps): bump lodash from 4.17.21 to 4.17.23 in /clients/native/examples/js-examples/websocket ([#6351])
|
||||
- build(deps): bump lodash-es from 4.17.21 to 4.17.23 in /documentation/docs ([#6350])
|
||||
- build(deps): bump diff from 5.2.0 to 5.2.2 in /documentation/docs ([#6345])
|
||||
- Max/crates publishing tweaks ([#6343])
|
||||
- build(deps): bump h3 from 1.15.4 to 1.15.5 ([#6339])
|
||||
- build(deps): bump h3 from 1.15.4 to 1.15.5 in /documentation/docs ([#6332])
|
||||
- build(deps): bump undici from 6.21.3 to 6.23.0 in /documentation/docs ([#6325])
|
||||
- build(deps): bump rsa from 0.9.8 to 0.9.10 ([#6311])
|
||||
- build(deps): bump qs and express in /wasm/mix-fetch/internal-dev ([#6308])
|
||||
- build(deps): bump qs and express in /clients/native/examples/js-examples/websocket ([#6307])
|
||||
- feat: introduce on-disk cache persistance for major nym-api caches ([#6302])
|
||||
- Fix migrations in the Data Observatory ([#6271])
|
||||
|
||||
[#6462]: https://github.com/nymtech/nym/pull/6462
|
||||
[#6445]: https://github.com/nymtech/nym/pull/6445
|
||||
[#6437]: https://github.com/nymtech/nym/pull/6437
|
||||
[#6435]: https://github.com/nymtech/nym/pull/6435
|
||||
[#6432]: https://github.com/nymtech/nym/pull/6432
|
||||
[#6431]: https://github.com/nymtech/nym/pull/6431
|
||||
[#6430]: https://github.com/nymtech/nym/pull/6430
|
||||
[#6429]: https://github.com/nymtech/nym/pull/6429
|
||||
[#6428]: https://github.com/nymtech/nym/pull/6428
|
||||
[#6423]: https://github.com/nymtech/nym/pull/6423
|
||||
[#6418]: https://github.com/nymtech/nym/pull/6418
|
||||
[#6416]: https://github.com/nymtech/nym/pull/6416
|
||||
[#6415]: https://github.com/nymtech/nym/pull/6415
|
||||
[#6414]: https://github.com/nymtech/nym/pull/6414
|
||||
[#6407]: https://github.com/nymtech/nym/pull/6407
|
||||
[#6405]: https://github.com/nymtech/nym/pull/6405
|
||||
[#6401]: https://github.com/nymtech/nym/pull/6401
|
||||
[#6387]: https://github.com/nymtech/nym/pull/6387
|
||||
[#6385]: https://github.com/nymtech/nym/pull/6385
|
||||
[#6369]: https://github.com/nymtech/nym/pull/6369
|
||||
[#6360]: https://github.com/nymtech/nym/pull/6360
|
||||
[#6359]: https://github.com/nymtech/nym/pull/6359
|
||||
[#6354]: https://github.com/nymtech/nym/pull/6354
|
||||
[#6353]: https://github.com/nymtech/nym/pull/6353
|
||||
[#6351]: https://github.com/nymtech/nym/pull/6351
|
||||
[#6350]: https://github.com/nymtech/nym/pull/6350
|
||||
[#6345]: https://github.com/nymtech/nym/pull/6345
|
||||
[#6343]: https://github.com/nymtech/nym/pull/6343
|
||||
[#6339]: https://github.com/nymtech/nym/pull/6339
|
||||
[#6332]: https://github.com/nymtech/nym/pull/6332
|
||||
[#6325]: https://github.com/nymtech/nym/pull/6325
|
||||
[#6311]: https://github.com/nymtech/nym/pull/6311
|
||||
[#6308]: https://github.com/nymtech/nym/pull/6308
|
||||
[#6307]: https://github.com/nymtech/nym/pull/6307
|
||||
[#6302]: https://github.com/nymtech/nym/pull/6302
|
||||
[#6271]: https://github.com/nymtech/nym/pull/6271
|
||||
|
||||
## [2026.3-parmigiano] (2026-02-10)
|
||||
|
||||
- chore: disable LP on parmigiano branch ([#6422])
|
||||
|
||||
Generated
+1816
-1286
File diff suppressed because it is too large
Load Diff
+35
-15
@@ -74,7 +74,6 @@ members = [
|
||||
"common/nym-id",
|
||||
"common/nym-kcp",
|
||||
"common/nym-lp",
|
||||
"common/nym-lp-common",
|
||||
"common/nym-kkt",
|
||||
"common/nym-metrics",
|
||||
"common/nym_offline_compact_ecash",
|
||||
@@ -129,7 +128,6 @@ members = [
|
||||
"nym-browser-extension/storage",
|
||||
"nym-credential-proxy/nym-credential-proxy",
|
||||
"nym-credential-proxy/nym-credential-proxy-requests",
|
||||
"nym-credential-proxy/vpn-api-lib-wasm",
|
||||
"nym-data-observatory",
|
||||
"nym-ip-packet-client",
|
||||
"nym-network-monitor",
|
||||
@@ -159,8 +157,8 @@ members = [
|
||||
"tools/internal/mixnet-connectivity-check",
|
||||
# "tools/internal/sdk-version-bump",
|
||||
"tools/internal/ssl-inject",
|
||||
"tools/internal/testnet-manager",
|
||||
"tools/internal/testnet-manager/dkg-bypass-contract",
|
||||
"tools/internal/localnet-orchestrator",
|
||||
"tools/internal/localnet-orchestrator/dkg-bypass-contract",
|
||||
"tools/internal/validator-status-check",
|
||||
"tools/nym-cli",
|
||||
"tools/nym-id-cli",
|
||||
@@ -174,7 +172,9 @@ members = [
|
||||
"wasm/node-tester",
|
||||
"wasm/zknym-lib",
|
||||
"nym-gateway-probe",
|
||||
"integration-tests", "common/nym-lp-transport", "common/nym-kkt-ciphersuite",
|
||||
"integration-tests",
|
||||
"common/nym-kkt-ciphersuite",
|
||||
"common/nym-kkt-context",
|
||||
]
|
||||
|
||||
default-members = [
|
||||
@@ -191,7 +191,8 @@ default-members = [
|
||||
"service-providers/ip-packet-router",
|
||||
"service-providers/network-requester",
|
||||
"tools/nymvisor",
|
||||
"nym-registration-client"
|
||||
"nym-registration-client",
|
||||
"tools/internal/localnet-orchestrator"
|
||||
]
|
||||
|
||||
exclude = ["contracts", "nym-wallet", "cpu-cycles"]
|
||||
@@ -203,7 +204,7 @@ homepage = "https://nymtech.net"
|
||||
documentation = "https://nymtech.net"
|
||||
edition = "2024"
|
||||
license = "Apache-2.0"
|
||||
rust-version = "1.85"
|
||||
rust-version = "1.87.0"
|
||||
readme = "README.md"
|
||||
version = "1.20.4"
|
||||
|
||||
@@ -233,6 +234,7 @@ bloomfilter = "3.0.1"
|
||||
bs58 = "0.5.1"
|
||||
bytecodec = "0.4.15"
|
||||
bytes = "1.11.1"
|
||||
cargo-edit = "0.13.8"
|
||||
cargo_metadata = "0.19.2"
|
||||
celes = "2.6.0"
|
||||
cfg-if = "1.0.0"
|
||||
@@ -274,6 +276,7 @@ futures = "0.3.31"
|
||||
futures-util = "0.3"
|
||||
generic-array = "0.14.7"
|
||||
getrandom = "0.2.10"
|
||||
getrandom03 = { package = "getrandom", version = "=0.3.3" }
|
||||
glob = "0.3"
|
||||
handlebars = "3.5.5"
|
||||
hex = "0.4.3"
|
||||
@@ -309,8 +312,10 @@ nix = "0.30.1"
|
||||
notify = "5.1.0"
|
||||
num_enum = "0.7.5"
|
||||
once_cell = "1.21.3"
|
||||
opentelemetry = "0.19.0"
|
||||
opentelemetry-jaeger = "0.18.0"
|
||||
opentelemetry = "0.31.0"
|
||||
opentelemetry_sdk = "0.31.0"
|
||||
opentelemetry-otlp = "0.31.0"
|
||||
tonic = "0.14.4"
|
||||
parking_lot = "0.12.3"
|
||||
pem = "0.8"
|
||||
petgraph = "0.6.5"
|
||||
@@ -322,6 +327,7 @@ quote = "1"
|
||||
rand = "0.8.5"
|
||||
rand09 = { package = "rand", version = "=0.9.2" }
|
||||
rand_chacha = "0.3"
|
||||
rand_chacha09 = { package = "rand_chacha", version = "=0.9.0" }
|
||||
rand_core = "0.6.3"
|
||||
rand_distr = "0.4"
|
||||
rayon = "1.5.1"
|
||||
@@ -344,8 +350,8 @@ si-scale = "0.2.3"
|
||||
snow = "0.9.6"
|
||||
sphinx-packet = "=0.6.0"
|
||||
sqlx = "0.8.6"
|
||||
strum = "0.27.2"
|
||||
strum_macros = "0.27.2"
|
||||
strum = "0.28.0"
|
||||
strum_macros = "0.28.0"
|
||||
subtle-encoding = "0.5"
|
||||
syn = "2"
|
||||
sysinfo = "0.37.0"
|
||||
@@ -368,12 +374,11 @@ tower = "0.5.2"
|
||||
tower-http = "0.6.6"
|
||||
tracing = "0.1.41"
|
||||
tracing-log = "0.2"
|
||||
tracing-opentelemetry = "0.19.0"
|
||||
tracing-opentelemetry = "0.32.1"
|
||||
tracing-subscriber = "0.3.20"
|
||||
tracing-tree = "0.2.2"
|
||||
tracing-indicatif = "0.3.9"
|
||||
tracing-test = "0.2.5"
|
||||
ts-rs = "10.1.0"
|
||||
ts-rs = "12.0.1"
|
||||
tungstenite = { version = "0.20.1", default-features = false }
|
||||
typed-builder = "0.23.0"
|
||||
uniffi = "0.29.2"
|
||||
@@ -391,6 +396,17 @@ zeroize = "1.7.0"
|
||||
|
||||
prometheus = { version = "0.14.0" }
|
||||
|
||||
|
||||
# libcrux
|
||||
libcrux-kem = { git = "https://github.com/cryspen/libcrux", rev = "b17f8687b67cdcfc10b55aeecc998bbbca28f775" }
|
||||
libcrux-ecdh = { git = "https://github.com/cryspen/libcrux", rev = "b17f8687b67cdcfc10b55aeecc998bbbca28f775" }
|
||||
libcrux-curve25519 = { git = "https://github.com/cryspen/libcrux", rev = "b17f8687b67cdcfc10b55aeecc998bbbca28f775" }
|
||||
libcrux-chacha20poly1305 = { git = "https://github.com/cryspen/libcrux", rev = "b17f8687b67cdcfc10b55aeecc998bbbca28f775" }
|
||||
libcrux-psq = { git = "https://github.com/cryspen/libcrux", rev = "b17f8687b67cdcfc10b55aeecc998bbbca28f775" }
|
||||
libcrux-ml-kem = { git = "https://github.com/cryspen/libcrux", rev = "b17f8687b67cdcfc10b55aeecc998bbbca28f775" }
|
||||
libcrux-sha3 = { git = "https://github.com/cryspen/libcrux", rev = "b17f8687b67cdcfc10b55aeecc998bbbca28f775" }
|
||||
libcrux-traits = { git = "https://github.com/cryspen/libcrux", rev = "b17f8687b67cdcfc10b55aeecc998bbbca28f775" }
|
||||
|
||||
# Workspace dep definitions required by crates.io publication - we need a workspace version since `cargo workspaces` doesn't work with path imports from crate manifests
|
||||
nym-api-requests = { version = "1.20.4", path = "nym-api/nym-api-requests" }
|
||||
nym-authenticator-requests = { version = "1.20.4", path = "common/authenticator-requests" }
|
||||
@@ -425,6 +441,7 @@ nym-ecash-time = { version = "1.20.4", path = "common/ecash-time" }
|
||||
nym-exit-policy = { version = "1.20.4", path = "common/exit-policy" }
|
||||
nym-ffi-shared = { version = "1.20.4", path = "sdk/ffi/shared" }
|
||||
nym-gateway-client = { version = "1.20.4", path = "common/client-libs/gateway-client", default-features = false }
|
||||
nym-gateway-probe = { version = "1.18.0", path = "nym-gateway-probe" }
|
||||
nym-gateway-requests = { version = "1.20.4", path = "common/gateway-requests" }
|
||||
nym-gateway-storage = { version = "1.20.4", path = "common/gateway-storage" }
|
||||
nym-gateway-stats-storage = { version = "1.20.4", path = "common/gateway-stats-storage" }
|
||||
@@ -435,7 +452,10 @@ nym-http-api-common = { version = "1.20.4", path = "common/http-api-common", def
|
||||
nym-id = { version = "1.20.4", path = "common/nym-id" }
|
||||
nym-ip-packet-client = { version = "1.20.4", path = "nym-ip-packet-client" }
|
||||
nym-ip-packet-requests = { version = "1.20.4", path = "common/ip-packet-requests" }
|
||||
nym-kkt-ciphersuite = { path = "common/nym-kkt-ciphersuite" }
|
||||
nym-lp = { version = "1.20.4", path = "common/nym-lp" }
|
||||
nym-kkt = { version = "0.1.0", path = "common/nym-kkt" }
|
||||
nym-kkt-ciphersuite = { version = "1.20.4", path = "common/nym-kkt-ciphersuite" }
|
||||
nym-kkt-context = { version = "1.20.4", path = "common/nym-kkt-context" }
|
||||
nym-metrics = { version = "1.20.4", path = "common/nym-metrics" }
|
||||
nym-mixnet-client = { version = "1.20.4", path = "common/client-libs/mixnet-client" }
|
||||
nym-mixnet-contract-common = { version = "1.20.4", path = "common/cosmwasm-smart-contracts/mixnet-contract" }
|
||||
|
||||
@@ -104,11 +104,11 @@ $(eval $(call add_cargo_workspace,wallet,nym-wallet))
|
||||
sdk-wasm: sdk-wasm-build sdk-wasm-test sdk-wasm-lint
|
||||
|
||||
sdk-wasm-build:
|
||||
$(MAKE) -C nym-browser-extension/storage wasm-pack
|
||||
# $(MAKE) -C nym-browser-extension/storage wasm-pack
|
||||
$(MAKE) -C wasm/client
|
||||
$(MAKE) -C wasm/node-tester
|
||||
$(MAKE) -C wasm/mix-fetch
|
||||
$(MAKE) -C wasm/zknym-lib
|
||||
# $(MAKE) -C wasm/zknym-lib
|
||||
# $(MAKE) -C wasm/full-nym-wasm
|
||||
|
||||
# run this from npm/yarn to ensure tools are in the path, e.g. yarn build:sdk from root of repo
|
||||
@@ -119,13 +119,14 @@ sdk-typescript-build:
|
||||
yarn --cwd sdk/typescript/codegen/contract-clients build
|
||||
|
||||
# NOTE: These targets are part of the main workspace (but not as wasm32-unknown-unknown)
|
||||
WASM_CRATES = extension-storage nym-client-wasm nym-node-tester-wasm zknym-lib
|
||||
# WASM_CRATES = extension-storage nym-client-wasm nym-node-tester-wasm zknym-lib
|
||||
WASM_CRATES = nym-client-wasm nym-node-tester-wasm
|
||||
|
||||
sdk-wasm-test:
|
||||
#cargo test $(addprefix -p , $(WASM_CRATES)) --target wasm32-unknown-unknown -- -Dwarnings
|
||||
|
||||
sdk-wasm-lint:
|
||||
cargo clippy $(addprefix -p , $(WASM_CRATES)) --target wasm32-unknown-unknown -- -Dwarnings
|
||||
RUSTFLAGS='--cfg getrandom_backend="wasm_js"' cargo clippy $(addprefix -p , $(WASM_CRATES)) --target wasm32-unknown-unknown -- -Dwarnings
|
||||
$(MAKE) -C wasm/mix-fetch check-fmt
|
||||
|
||||
# Add to top-level targets
|
||||
|
||||
@@ -30,8 +30,11 @@ client ───► Gateway ──┘ mix │ mix ┌─►mix ───►
|
||||
|
||||
```
|
||||
|
||||
<!-- This is broken
|
||||
[](https://github.com/nymtech/nym/actions?query=branch%3Adevelop)
|
||||
-->
|
||||
|
||||
> This project integrates with the Midnight Network
|
||||
|
||||
### Building
|
||||
|
||||
|
||||
@@ -1,32 +1,38 @@
|
||||
---
|
||||
ansible_ssh_private_key_file: ~/.ssh/<SSH_KEY>
|
||||
|
||||
# nym_version: "v2025.21-mozzarella"
|
||||
#
|
||||
# NOTE:
|
||||
# if you want to pin Nym to a specific version instead of using the
|
||||
# latest release from GitHub in /tasks/main.yml then
|
||||
# uncomment the line above and set the tag
|
||||
|
||||
cli_url: "https://github.com/nymtech/nym/releases/download/nym-binaries-{{ nym_version }}/nym-cli"
|
||||
tunnel_manager_url: "https://github.com/nymtech/nym/raw/refs/heads/develop/scripts/nym-node-setup/network-tunnel-manager.sh"
|
||||
quic_bridge_deployment_url: "https://raw.githubusercontent.com/nymtech/nym/refs/heads/develop/scripts/nym-node-setup/quic_bridge_deployment.sh"
|
||||
|
||||
# NOTE: These values will be used globally unless overwritten per node in inventory/all
|
||||
###############################################################################
|
||||
## GLOBAL VARS
|
||||
## These values will be used globally unless overwritten per node in inventory/all
|
||||
###############################################################################
|
||||
|
||||
ansible_user: root # used for ssh, like `ssh root@nym-exit.ch-1.mynodes.net`
|
||||
email: "<EMAIL>" # used in certbot, description.toml and landing page
|
||||
website: "<WEBSITE>" # it is used in the description.toml
|
||||
description: "<NODE_PUBLIC_DESCRIPTION>" # or define per node in inventory/all
|
||||
# operator_name: "<OPERATOR_NAME>" # used in landing page if provided
|
||||
|
||||
###############################################################################
|
||||
## GLOBAL VARS
|
||||
## These values will be used globally unless overwritten per node in inventory/all
|
||||
## Set these vars only if you want them globally for all nodes
|
||||
## Per node changes in inventory/all will overwrite these global vars
|
||||
###############################################################################
|
||||
|
||||
# NOTE: Set these vars if you want them globally for all nodes
|
||||
# Per node changes in inventory/all will overwrite these global ones:
|
||||
hostname: "" # this is a fallback, keep it and setup hostname per node in inventory/all
|
||||
# moniker: "<MONIKER>" # if not setup here not in inventory/all it get's derived from the hostname
|
||||
# mode: <MODE> # entry-gateway/exit-gateway/mixnode
|
||||
# wireguard_enabled: <WIREGUARD_ENABLED> # true/false
|
||||
hostname: "" # this is a fallback, keep it and setup hostname per node in inventory/all
|
||||
|
||||
###############################################################################
|
||||
## GLOBAL PACKAGES
|
||||
## These will be installed during deployment
|
||||
###############################################################################
|
||||
|
||||
# NOTE: Possible vars to incule on landing page, etc.
|
||||
# operator_name: "<OPERATOR_NAME>"
|
||||
|
||||
packages:
|
||||
- tmux
|
||||
@@ -42,3 +48,73 @@ packages:
|
||||
- jq
|
||||
- wget
|
||||
- ufw
|
||||
|
||||
|
||||
###############################################################################
|
||||
## OPTIONAL OVERRIDES
|
||||
## All values below already have defaults in the playbook/roles
|
||||
## Uncomment only if you want to override them
|
||||
###############################################################################
|
||||
|
||||
###############################################################################
|
||||
## SYSTEM MAINTENANCE PLAYBOOK KNOBS
|
||||
###############################################################################
|
||||
|
||||
# nym_version: "v2025.21-mozzarella"
|
||||
|
||||
## NOTE:
|
||||
## if you want to pin Nym to a specific version instead of using the
|
||||
## latest release from GitHub in /tasks/main.yml then
|
||||
## uncomment the line above and set the tag
|
||||
|
||||
###############################################################################
|
||||
## SYSTEM MAINTENANCE PLAYBOOK KNOBS
|
||||
###############################################################################
|
||||
|
||||
## JOURNALD LIMITS
|
||||
|
||||
# journald_system_max_use: "100M" # max persistent journal size
|
||||
# journald_runtime_max_use: "50M" # max runtime journal size
|
||||
# journald_system_max_file_size: "25M" # max single journal file
|
||||
# journald_runtime_max_file_size: "10M" # max runtime journal file
|
||||
# journald_max_retention_sec: "3day" # retention time
|
||||
|
||||
# journald_rate_limit_interval: "30s" # rate limit window
|
||||
# journald_rate_limit_burst: "1000" # rate limit burst
|
||||
|
||||
|
||||
## NYM-NODE LOG CONTROL
|
||||
|
||||
# nymnode_log_level_max: "warning" # drop INFO logs
|
||||
# nymnode_rate_limit_interval: "30s" # per nym-node rate limit window
|
||||
# nymnode_rate_limit_burst: "200" # per nym-node rate limit burst
|
||||
|
||||
|
||||
## JOURNAL VACUUM TARGETS
|
||||
|
||||
# journal_vacuum_size: "100M"
|
||||
# journal_vacuum_time: "3days"
|
||||
|
||||
|
||||
## RSYSLOG
|
||||
|
||||
# disable_rsyslog: true
|
||||
|
||||
|
||||
## FSTRIM SCHEDULE
|
||||
|
||||
# fstrim_every_calendar: "*:0/15" # Aggressive
|
||||
# fstrim_every_calendar: "hourly" # Less aggressive
|
||||
|
||||
|
||||
## OPTIONAL CLEANUPS
|
||||
|
||||
# enable_apt_cleanup: true
|
||||
# enable_snap_cleanup: true
|
||||
|
||||
|
||||
## WRITEBACK TUNING
|
||||
|
||||
# enable_writeback_tuning: true
|
||||
# writeback_dirty_writeback_centisecs: 1500
|
||||
# writeback_dirty_expire_centisecs: 6000
|
||||
@@ -0,0 +1,38 @@
|
||||
---
|
||||
- name: Restrict logging, vacuum journals, and enable periodic trim
|
||||
hosts: all
|
||||
become: true
|
||||
gather_facts: false
|
||||
|
||||
# global knobs - override in inventory/group_vars/host_vars as needed
|
||||
vars:
|
||||
journald_system_max_use: "100M"
|
||||
journald_runtime_max_use: "50M"
|
||||
journald_system_max_file_size: "25M"
|
||||
journald_runtime_max_file_size: "10M"
|
||||
journald_max_retention_sec: "3day"
|
||||
journald_rate_limit_interval: "30s"
|
||||
journald_rate_limit_burst: "1000"
|
||||
|
||||
# per nym-node rate limit + level cap
|
||||
nymnode_log_level_max: "warning"
|
||||
nymnode_rate_limit_interval: "30s"
|
||||
nymnode_rate_limit_burst: "200"
|
||||
|
||||
# journal vacuum targets
|
||||
journal_vacuum_size: "100M"
|
||||
journal_vacuum_time: "3days"
|
||||
|
||||
# fstrim cadence (note: the systemd override uses cron-like calendar)
|
||||
fstrim_every_calendar: "*:0/15"
|
||||
|
||||
roles:
|
||||
- role: journald_limits
|
||||
- role: nymnode_logging
|
||||
- role: rsyslog_disable
|
||||
- role: journal_vacuum
|
||||
- role: classic_log_cleanup
|
||||
- role: apt_cleanup
|
||||
- role: snap_cleanup
|
||||
- role: fstrim_15min
|
||||
- role: report
|
||||
@@ -0,0 +1,21 @@
|
||||
---
|
||||
- name: Clean apt cache
|
||||
command: apt-get clean
|
||||
ignore_errors: true
|
||||
|
||||
- name: Autoremove unused packages
|
||||
command: apt-get -y autoremove
|
||||
ignore_errors: true
|
||||
|
||||
- name: Remove apt lists to reclaim space (they will be re-fetched on update)
|
||||
file:
|
||||
path: /var/lib/apt/lists
|
||||
state: absent
|
||||
ignore_errors: true
|
||||
|
||||
- name: Recreate apt lists directory
|
||||
file:
|
||||
path: /var/lib/apt/lists
|
||||
state: directory
|
||||
mode: "0755"
|
||||
ignore_errors: true
|
||||
@@ -0,0 +1,20 @@
|
||||
---
|
||||
- name: Remove classic /var/log files if present (optional)
|
||||
file:
|
||||
path: "{{ item }}"
|
||||
state: absent
|
||||
loop:
|
||||
- /var/log/syslog
|
||||
- /var/log/syslog.1
|
||||
- /var/log/kern.log
|
||||
- /var/log/kern.log.1
|
||||
- /var/log/auth.log
|
||||
- /var/log/auth.log.1
|
||||
- /var/log/ufw.log
|
||||
- /var/log/ufw.log.1
|
||||
ignore_errors: true
|
||||
|
||||
# This is best-effort and may still fail if other packages' postrotate scripts assume services exist.
|
||||
- name: Force logrotate (best-effort)
|
||||
command: "logrotate --force /etc/logrotate.conf"
|
||||
ignore_errors: true
|
||||
@@ -0,0 +1,3 @@
|
||||
---
|
||||
fstrim_timer_dropin_dir: "/etc/systemd/system/fstrim.timer.d"
|
||||
fstrim_every_calendar: "*:0/15"
|
||||
@@ -0,0 +1,31 @@
|
||||
---
|
||||
- name: Ensure systemd drop-in dir for fstrim.timer exists
|
||||
file:
|
||||
path: "{{ fstrim_timer_dropin_dir }}"
|
||||
state: directory
|
||||
mode: "0755"
|
||||
|
||||
- name: Override fstrim.timer schedule
|
||||
copy:
|
||||
dest: "{{ fstrim_timer_dropin_dir }}/override.conf"
|
||||
mode: "0644"
|
||||
content: |
|
||||
[Timer]
|
||||
OnCalendar=
|
||||
OnCalendar={{ fstrim_every_calendar }}
|
||||
Persistent=true
|
||||
RandomizedDelaySec=0
|
||||
|
||||
- name: Reload systemd after fstrim override
|
||||
systemd:
|
||||
daemon_reload: true
|
||||
|
||||
- name: Enable and start fstrim timer
|
||||
systemd:
|
||||
name: fstrim.timer
|
||||
enabled: true
|
||||
state: started
|
||||
|
||||
- name: Run fstrim now (best-effort)
|
||||
command: fstrim -av
|
||||
ignore_errors: true
|
||||
@@ -0,0 +1,3 @@
|
||||
---
|
||||
journal_vacuum_size: "100M"
|
||||
journal_vacuum_time: "3days"
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
- name: Vacuum journal to size cap (hard)
|
||||
command: "journalctl --vacuum-size={{ journal_vacuum_size }}"
|
||||
|
||||
- name: Vacuum journal older than retention window (time)
|
||||
command: "journalctl --vacuum-time={{ journal_vacuum_time }}"
|
||||
@@ -0,0 +1,8 @@
|
||||
---
|
||||
journald_system_max_use: "100M"
|
||||
journald_runtime_max_use: "50M"
|
||||
journald_system_max_file_size: "25M"
|
||||
journald_runtime_max_file_size: "10M"
|
||||
journald_max_retention_sec: "3day"
|
||||
journald_rate_limit_interval: "30s"
|
||||
journald_rate_limit_burst: "1000"
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
- name: Restart journald
|
||||
systemd:
|
||||
name: systemd-journald
|
||||
state: restarted
|
||||
@@ -0,0 +1,20 @@
|
||||
---
|
||||
- name: Configure journald limits (persistent, capped, rate-limited)
|
||||
copy:
|
||||
dest: /etc/systemd/journald.conf
|
||||
mode: "0644"
|
||||
content: |
|
||||
[Journal]
|
||||
Storage=persistent
|
||||
Compress=yes
|
||||
Seal=yes
|
||||
|
||||
SystemMaxUse={{ journald_system_max_use }}
|
||||
RuntimeMaxUse={{ journald_runtime_max_use }}
|
||||
SystemMaxFileSize={{ journald_system_max_file_size }}
|
||||
RuntimeMaxFileSize={{ journald_runtime_max_file_size }}
|
||||
MaxRetentionSec={{ journald_max_retention_sec }}
|
||||
|
||||
RateLimitIntervalSec={{ journald_rate_limit_interval }}
|
||||
RateLimitBurst={{ journald_rate_limit_burst }}
|
||||
notify: Restart journald
|
||||
@@ -0,0 +1,7 @@
|
||||
---
|
||||
nymnode_log_level_max: "warning"
|
||||
nymnode_rate_limit_interval: "30s"
|
||||
nymnode_rate_limit_burst: "200"
|
||||
nymnode_unit_name: "nym-node" # set to "nym-node.service" if your distro expects it
|
||||
nymnode_dropin_dir: "/etc/systemd/system/nym-node.service.d"
|
||||
nymnode_dropin_file: "10-logging.conf"
|
||||
@@ -0,0 +1,26 @@
|
||||
---
|
||||
- name: Ensure systemd drop-in dir for nym-node exists
|
||||
file:
|
||||
path: "{{ nymnode_dropin_dir }}"
|
||||
state: directory
|
||||
mode: "0755"
|
||||
|
||||
- name: Cap nym-node logs + apply per-unit rate limiting
|
||||
copy:
|
||||
dest: "{{ nymnode_dropin_dir }}/{{ nymnode_dropin_file }}"
|
||||
mode: "0644"
|
||||
content: |
|
||||
[Service]
|
||||
LogLevelMax={{ nymnode_log_level_max }}
|
||||
LogRateLimitIntervalSec={{ nymnode_rate_limit_interval }}
|
||||
LogRateLimitBurst={{ nymnode_rate_limit_burst }}
|
||||
|
||||
- name: Reload systemd after nym-node drop-in
|
||||
systemd:
|
||||
daemon_reload: true
|
||||
|
||||
- name: Restart nym-node to apply new logging limits (best-effort)
|
||||
systemd:
|
||||
name: "{{ nymnode_unit_name }}"
|
||||
state: restarted
|
||||
ignore_errors: true
|
||||
@@ -0,0 +1,8 @@
|
||||
---
|
||||
- name: Show journal disk usage
|
||||
command: journalctl --disk-usage
|
||||
register: journal_usage
|
||||
changed_when: false
|
||||
|
||||
- debug:
|
||||
var: journal_usage.stdout
|
||||
@@ -0,0 +1,13 @@
|
||||
---
|
||||
- name: Stop/disable rsyslog if installed (best-effort)
|
||||
systemd:
|
||||
name: rsyslog
|
||||
state: stopped
|
||||
enabled: false
|
||||
ignore_errors: true
|
||||
|
||||
- name: Remove rsyslog logrotate stanza if present (prevents logrotate failures)
|
||||
file:
|
||||
path: /etc/logrotate.d/rsyslog
|
||||
state: absent
|
||||
ignore_errors: true
|
||||
@@ -0,0 +1,10 @@
|
||||
---
|
||||
- name: Remove disabled snap revisions (best-effort)
|
||||
shell: |
|
||||
set -euo pipefail
|
||||
snap list --all | awk '/disabled/{print $1, $3}' | while read -r name rev; do
|
||||
snap remove "$name" --revision="$rev" || true
|
||||
done
|
||||
args:
|
||||
executable: /bin/bash
|
||||
ignore_errors: true
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "nym-client"
|
||||
version = "1.1.70"
|
||||
version = "1.1.72"
|
||||
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jędrzej Stuczyński <andrew@nymtech.net>"]
|
||||
description = "Implementation of the Nym Client"
|
||||
edition = "2021"
|
||||
|
||||
+12
-12
@@ -513,9 +513,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/ajv": {
|
||||
"version": "8.17.1",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz",
|
||||
"integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
|
||||
"version": "8.18.0",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz",
|
||||
"integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==",
|
||||
"dependencies": {
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
"fast-uri": "^3.0.1",
|
||||
@@ -3067,9 +3067,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/qs": {
|
||||
"version": "6.14.1",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.14.1.tgz",
|
||||
"integrity": "sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==",
|
||||
"version": "6.14.2",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.14.2.tgz",
|
||||
"integrity": "sha512-V/yCWTTF7VJ9hIh18Ugr2zhJMP01MY7c5kh4J870L7imm6/DIzBsNLTXzMwUA3yZ5b/KBqLx8Kp3uRvd7xSe3Q==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"side-channel": "^1.1.0"
|
||||
@@ -4989,9 +4989,9 @@
|
||||
}
|
||||
},
|
||||
"ajv": {
|
||||
"version": "8.17.1",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz",
|
||||
"integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
|
||||
"version": "8.18.0",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz",
|
||||
"integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==",
|
||||
"requires": {
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
"fast-uri": "^3.0.1",
|
||||
@@ -6870,9 +6870,9 @@
|
||||
}
|
||||
},
|
||||
"qs": {
|
||||
"version": "6.14.1",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.14.1.tgz",
|
||||
"integrity": "sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==",
|
||||
"version": "6.14.2",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.14.2.tgz",
|
||||
"integrity": "sha512-V/yCWTTF7VJ9hIh18Ugr2zhJMP01MY7c5kh4J870L7imm6/DIzBsNLTXzMwUA3yZ5b/KBqLx8Kp3uRvd7xSe3Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"side-channel": "^1.1.0"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "nym-socks5-client"
|
||||
version = "1.1.70"
|
||||
version = "1.1.72"
|
||||
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"
|
||||
|
||||
@@ -19,12 +19,15 @@ serde_json = { workspace = true, optional = true }
|
||||
|
||||
## tracing
|
||||
tracing-subscriber = { workspace = true, features = ["env-filter"], optional = true }
|
||||
tracing-tree = { workspace = true, optional = true }
|
||||
tracing = { workspace = true, optional = true }
|
||||
opentelemetry-jaeger = { workspace = true, features = ["rt-tokio", "collector_client", "isahc_collector_client"], optional = true }
|
||||
tracing-opentelemetry = { workspace = true, optional = true }
|
||||
utoipa = { workspace = true, optional = true }
|
||||
opentelemetry = { workspace = true, features = ["rt-tokio"], optional = true }
|
||||
opentelemetry = { workspace = true, features = ["trace"], optional = true }
|
||||
|
||||
## otel-otlp (modern OTLP export to SigNoz/any OTLP collector)
|
||||
opentelemetry_sdk = { workspace = true, features = ["trace"], optional = true }
|
||||
opentelemetry-otlp = { workspace = true, features = ["grpc-tonic", "trace", "tls-roots"], optional = true }
|
||||
tonic = { workspace = true, optional = true }
|
||||
|
||||
|
||||
[build-dependencies]
|
||||
@@ -35,13 +38,14 @@ default = []
|
||||
openapi = ["utoipa"]
|
||||
output_format = ["serde_json", "dep:clap"]
|
||||
bin_info_schema = ["schemars"]
|
||||
basic_tracing = ["dep:tracing", "tracing-subscriber"]
|
||||
tracing = [
|
||||
basic_tracing = ["dep:tracing", "dep:tracing-subscriber"]
|
||||
otel-otlp = [
|
||||
"basic_tracing",
|
||||
"tracing-tree",
|
||||
"opentelemetry-jaeger",
|
||||
"tracing-opentelemetry",
|
||||
"opentelemetry",
|
||||
"dep:opentelemetry",
|
||||
"dep:opentelemetry_sdk",
|
||||
"dep:opentelemetry-otlp",
|
||||
"dep:tracing-opentelemetry",
|
||||
"dep:tonic",
|
||||
]
|
||||
clap = ["dep:clap", "dep:clap_complete", "dep:clap_complete_fig"]
|
||||
models = []
|
||||
|
||||
@@ -4,16 +4,9 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::io::IsTerminal;
|
||||
|
||||
#[cfg(feature = "tracing")]
|
||||
pub use opentelemetry;
|
||||
#[cfg(feature = "tracing")]
|
||||
pub use opentelemetry_jaeger;
|
||||
#[cfg(feature = "tracing")]
|
||||
pub use tracing_opentelemetry;
|
||||
// Re-export tracing_subscriber for consumers that need to compose layers
|
||||
#[cfg(feature = "basic_tracing")]
|
||||
pub use tracing_subscriber;
|
||||
#[cfg(feature = "tracing")]
|
||||
pub use tracing_tree;
|
||||
|
||||
#[derive(Debug, Default, Copy, Clone, Deserialize, PartialEq, Eq, Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
@@ -69,40 +62,106 @@ pub fn setup_tracing_logger() {
|
||||
build_tracing_logger().init()
|
||||
}
|
||||
|
||||
// TODO: This has to be a macro, running it as a function does not work for the file_appender for some reason
|
||||
#[cfg(feature = "tracing")]
|
||||
#[macro_export]
|
||||
macro_rules! setup_tracing {
|
||||
($service_name: expr) => {
|
||||
use nym_bin_common::logging::tracing_subscriber::layer::SubscriberExt;
|
||||
use nym_bin_common::logging::tracing_subscriber::util::SubscriberInitExt;
|
||||
/// Initialize an OpenTelemetry tracing layer that exports spans via OTLP/gRPC.
|
||||
///
|
||||
/// This produces a layer compatible with `tracing_subscriber::registry()` that
|
||||
/// sends traces to any OTLP-compatible collector (SigNoz, Grafana Tempo, etc).
|
||||
///
|
||||
/// Returns both the tracing layer and the [`SdkTracerProvider`] so the caller
|
||||
/// can invoke [`SdkTracerProvider::shutdown`] for graceful flush on exit.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `service_name` - The service name reported to the collector (e.g. "nym-node")
|
||||
/// * `endpoint` - The OTLP/gRPC collector endpoint (e.g. "http://localhost:4317"
|
||||
/// or "https://ingest.eu.signoz.cloud:443" for SigNoz Cloud)
|
||||
/// * `ingestion_key` - Optional SigNoz Cloud ingestion key. When provided, it is
|
||||
/// sent as the `signoz-ingestion-key` gRPC metadata header on every export.
|
||||
/// * `environment` - Deployment environment label (e.g. "sandbox", "mainnet", "canary").
|
||||
/// Attached as the `deployment.environment` OTel resource attribute.
|
||||
/// * `sample_ratio` - Trace sampling ratio in 0.0..=1.0 (e.g. 0.1 = 10% of traces).
|
||||
/// Used to limit cost when exporting from many nodes; clamped to [0.0, 1.0].
|
||||
/// * `export_timeout_secs` - Timeout in seconds for each OTLP export batch. Prevents
|
||||
/// unbounded blocking if the collector is slow or unreachable.
|
||||
#[cfg(feature = "otel-otlp")]
|
||||
pub fn init_otel_layer<S>(
|
||||
service_name: &str,
|
||||
endpoint: &str,
|
||||
ingestion_key: Option<&str>,
|
||||
environment: &str,
|
||||
sample_ratio: f64,
|
||||
export_timeout_secs: u64,
|
||||
) -> Result<
|
||||
(
|
||||
tracing_opentelemetry::OpenTelemetryLayer<S, opentelemetry_sdk::trace::SdkTracer>,
|
||||
opentelemetry_sdk::trace::SdkTracerProvider,
|
||||
),
|
||||
Box<dyn std::error::Error + Send + Sync>,
|
||||
>
|
||||
where
|
||||
S: tracing::Subscriber + for<'a> tracing_subscriber::registry::LookupSpan<'a>,
|
||||
{
|
||||
use opentelemetry::trace::TracerProvider as _;
|
||||
use opentelemetry_otlp::WithExportConfig;
|
||||
use opentelemetry_otlp::WithTonicConfig;
|
||||
use opentelemetry_sdk::trace::Sampler;
|
||||
use std::time::Duration;
|
||||
|
||||
let registry = nym_bin_common::logging::tracing_subscriber::Registry::default()
|
||||
.with(nym_bin_common::logging::tracing_subscriber::EnvFilter::from_default_env())
|
||||
.with(
|
||||
nym_bin_common::logging::tracing_tree::HierarchicalLayer::new(4)
|
||||
.with_targets(true)
|
||||
.with_bracketed_fields(true),
|
||||
);
|
||||
// Validate endpoint URI early to fail with a clear message
|
||||
if !endpoint.starts_with("http://") && !endpoint.starts_with("https://") {
|
||||
return Err(format!(
|
||||
"invalid OTLP endpoint URI: {endpoint} (must start with http:// or https://)"
|
||||
)
|
||||
.into());
|
||||
}
|
||||
|
||||
let tracer = nym_bin_common::logging::opentelemetry_jaeger::new_collector_pipeline()
|
||||
.with_endpoint("http://44.199.230.10:14268/api/traces")
|
||||
.with_service_name($service_name)
|
||||
.with_isahc()
|
||||
.with_trace_config(
|
||||
nym_bin_common::logging::opentelemetry::sdk::trace::config().with_sampler(
|
||||
nym_bin_common::logging::opentelemetry::sdk::trace::Sampler::TraceIdRatioBased(
|
||||
0.1,
|
||||
),
|
||||
),
|
||||
)
|
||||
.install_batch(nym_bin_common::logging::opentelemetry::runtime::Tokio)
|
||||
.expect("Could not init tracer");
|
||||
let sample_ratio_clamped = sample_ratio.clamp(0.0, 1.0);
|
||||
|
||||
let telemetry = nym_bin_common::logging::tracing_opentelemetry::layer().with_tracer(tracer);
|
||||
let mut builder = opentelemetry_otlp::SpanExporter::builder()
|
||||
.with_tonic()
|
||||
.with_endpoint(endpoint)
|
||||
.with_timeout(Duration::from_secs(export_timeout_secs));
|
||||
|
||||
registry.with(telemetry).init();
|
||||
};
|
||||
// Explicitly configure TLS when the endpoint uses HTTPS
|
||||
if endpoint.starts_with("https://") {
|
||||
builder =
|
||||
builder.with_tls_config(tonic::transport::ClientTlsConfig::new().with_native_roots());
|
||||
}
|
||||
|
||||
if let Some(key) = ingestion_key {
|
||||
let mut metadata = tonic::metadata::MetadataMap::new();
|
||||
metadata.insert(
|
||||
"signoz-ingestion-key",
|
||||
key.parse()
|
||||
.map_err(|_| "invalid ingestion key format (value redacted)")?,
|
||||
);
|
||||
builder = builder.with_metadata(metadata);
|
||||
}
|
||||
|
||||
let exporter = builder
|
||||
.build()
|
||||
.map_err(|e| format!("failed to build OTLP exporter for endpoint {endpoint}: {e}"))?;
|
||||
|
||||
let tracer_provider = opentelemetry_sdk::trace::SdkTracerProvider::builder()
|
||||
.with_sampler(Sampler::TraceIdRatioBased(sample_ratio_clamped))
|
||||
.with_batch_exporter(exporter)
|
||||
.with_resource(
|
||||
opentelemetry_sdk::Resource::builder()
|
||||
.with_service_name(service_name.to_owned())
|
||||
.with_attribute(opentelemetry::KeyValue::new(
|
||||
"deployment.environment",
|
||||
environment.to_owned(),
|
||||
))
|
||||
.build(),
|
||||
)
|
||||
.build();
|
||||
|
||||
opentelemetry::global::set_tracer_provider(tracer_provider.clone());
|
||||
let tracer = tracer_provider.tracer(service_name.to_owned());
|
||||
|
||||
Ok((
|
||||
tracing_opentelemetry::layer().with_tracer(tracer),
|
||||
tracer_provider,
|
||||
))
|
||||
}
|
||||
|
||||
pub fn banner(crate_name: &str, crate_version: &str) -> String {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
name = "nym-client-core"
|
||||
version.workspace = true
|
||||
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"]
|
||||
edition = "2021"
|
||||
edition = "2024"
|
||||
rust-version = "1.85"
|
||||
license.workspace = true
|
||||
description = "Crate containing core client functionality and configs, used by all other Nym client implentations"
|
||||
@@ -121,6 +121,10 @@ features = ["wasm-bindgen"]
|
||||
workspace = true
|
||||
features = ["full"]
|
||||
|
||||
[target."cfg(target_arch = \"wasm32\")".dependencies.getrandom03]
|
||||
workspace = true
|
||||
features = ["wasm_js"]
|
||||
|
||||
[dev-dependencies]
|
||||
tempfile = { workspace = true }
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ const DEFAULT_MIN_MIXNODE_PERFORMANCE: u8 = 50;
|
||||
const DEFAULT_MIN_GATEWAY_PERFORMANCE: u8 = 50;
|
||||
|
||||
const DEFAULT_MAX_STARTUP_GATEWAY_WAITING_PERIOD: Duration = Duration::from_secs(70 * 60); // 70min -> full epoch (1h) + a bit of overhead
|
||||
const DEFAULT_MAX_STARTUP_TOPOLOGY_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
|
||||
@@ -555,6 +556,11 @@ pub struct Topology {
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub max_startup_gateway_waiting_period: Duration,
|
||||
|
||||
/// Defines how long the client is going to wait on startup for minimal topology to become online,
|
||||
/// before abandoning the procedure.
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub max_startup_network_waiting_period: Duration,
|
||||
|
||||
/// Specifies a minimum performance of a mixnode that is used on route construction.
|
||||
/// This setting is only applicable when `NymApi` topology is used.
|
||||
pub minimum_mixnode_performance: u8,
|
||||
@@ -583,6 +589,7 @@ impl Default for Topology {
|
||||
topology_resolution_timeout: DEFAULT_TOPOLOGY_RESOLUTION_TIMEOUT,
|
||||
disable_refreshing: false,
|
||||
max_startup_gateway_waiting_period: DEFAULT_MAX_STARTUP_GATEWAY_WAITING_PERIOD,
|
||||
max_startup_network_waiting_period: DEFAULT_MAX_STARTUP_TOPOLOGY_WAITING_PERIOD,
|
||||
minimum_mixnode_performance: DEFAULT_MIN_MIXNODE_PERFORMANCE,
|
||||
minimum_gateway_performance: DEFAULT_MIN_GATEWAY_PERFORMANCE,
|
||||
use_extended_topology: false,
|
||||
|
||||
@@ -159,6 +159,7 @@ impl From<ConfigV6> for Config {
|
||||
use_extended_topology: value.debug.topology.use_extended_topology,
|
||||
ignore_egress_epoch_role: value.debug.topology.ignore_egress_epoch_role,
|
||||
ignore_ingress_epoch_role: value.debug.topology.ignore_ingress_epoch_role,
|
||||
..Default::default()
|
||||
},
|
||||
reply_surbs: ReplySurbs {
|
||||
minimum_reply_surb_storage_threshold: value
|
||||
|
||||
@@ -160,7 +160,10 @@ where
|
||||
)
|
||||
.await?;
|
||||
} else {
|
||||
info!("registered with new gateway {} (under address {address}), but this will not be our default address", gateway_details.gateway_id);
|
||||
info!(
|
||||
"registered with new gateway {} (under address {address}), but this will not be our default address",
|
||||
gateway_details.gateway_id
|
||||
);
|
||||
}
|
||||
|
||||
Ok(GatewayInfo {
|
||||
|
||||
@@ -4,13 +4,13 @@
|
||||
use super::mix_traffic::ClientRequestSender;
|
||||
use super::received_buffer::ReceivedBufferMessage;
|
||||
use super::statistics_control::StatisticsControl;
|
||||
use crate::client::base_client::storage::helpers::store_client_keys;
|
||||
use crate::client::base_client::storage::MixnetClientStorage;
|
||||
use crate::client::base_client::storage::helpers::store_client_keys;
|
||||
use crate::client::cover_traffic_stream::LoopCoverTrafficStream;
|
||||
use crate::client::event_control::EventControl;
|
||||
use crate::client::inbound_messages::{InputMessage, InputMessageReceiver, InputMessageSender};
|
||||
use crate::client::key_manager::persistence::KeyStore;
|
||||
use crate::client::key_manager::ClientKeys;
|
||||
use crate::client::key_manager::persistence::KeyStore;
|
||||
use crate::client::mix_traffic::transceiver::{GatewayReceiver, GatewayTransceiver, RemoteGateway};
|
||||
use crate::client::mix_traffic::{BatchMixMessageSender, MixTrafficController, MixTrafficEvent};
|
||||
use crate::client::real_messages_control;
|
||||
@@ -52,12 +52,12 @@ use nym_sphinx::addressing::nodes::NodeIdentity;
|
||||
use nym_sphinx::receiver::{ReconstructedMessage, SphinxMessageReceiver};
|
||||
use nym_statistics_common::clients::ClientStatsSender;
|
||||
use nym_statistics_common::generate_client_stats_id;
|
||||
use nym_task::connections::{ConnectionCommandReceiver, ConnectionCommandSender, LaneQueueLengths};
|
||||
use nym_task::ShutdownTracker;
|
||||
use nym_topology::provider_trait::TopologyProvider;
|
||||
use nym_task::connections::{ConnectionCommandReceiver, ConnectionCommandSender, LaneQueueLengths};
|
||||
use nym_topology::HardcodedTopologyProvider;
|
||||
use nym_topology::provider_trait::TopologyProvider;
|
||||
use nym_validator_client::nym_api::NymApiClientExt;
|
||||
use nym_validator_client::{nyxd::contract_traits::DkgQueryClient, UserAgent};
|
||||
use nym_validator_client::{UserAgent, nyxd::contract_traits::DkgQueryClient};
|
||||
use rand::prelude::SliceRandom;
|
||||
use rand::rngs::OsRng;
|
||||
use rand::thread_rng;
|
||||
@@ -220,6 +220,7 @@ pub struct BaseClientBuilder<C, S: MixnetClientStorage> {
|
||||
nym_api_urls: Option<Vec<nym_network_defaults::ApiUrl>>,
|
||||
|
||||
wait_for_gateway: bool,
|
||||
wait_for_initial_topology: bool,
|
||||
custom_topology_provider: Option<Box<dyn TopologyProvider + Send + Sync>>,
|
||||
custom_gateway_transceiver: Option<Box<dyn GatewayTransceiver + Send>>,
|
||||
shutdown: Option<ShutdownTracker>,
|
||||
@@ -250,6 +251,7 @@ where
|
||||
dkg_query_client,
|
||||
nym_api_urls: None,
|
||||
wait_for_gateway: false,
|
||||
wait_for_initial_topology: false,
|
||||
custom_topology_provider: None,
|
||||
custom_gateway_transceiver: None,
|
||||
shutdown: None,
|
||||
@@ -305,6 +307,12 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn with_wait_for_initial_topology(mut self, wait_for_initial_topology: bool) -> Self {
|
||||
self.wait_for_initial_topology = wait_for_initial_topology;
|
||||
self
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn with_topology_provider(
|
||||
mut self,
|
||||
@@ -674,6 +682,7 @@ where
|
||||
topology_accessor: TopologyAccessor,
|
||||
local_gateway: NodeIdentity,
|
||||
wait_for_gateway: bool,
|
||||
wait_for_initial_topology: bool,
|
||||
shutdown_tracker: &ShutdownTracker,
|
||||
) -> Result<(), ClientCoreError> {
|
||||
let topology_refresher_config =
|
||||
@@ -694,6 +703,46 @@ where
|
||||
tracing::info!("Obtaining initial network topology");
|
||||
topology_refresher.try_refresh().await;
|
||||
|
||||
// 1. wait for the minimum topology (if applicable)
|
||||
if topology_refresher
|
||||
.ensure_topology_is_routable()
|
||||
.await
|
||||
.is_err()
|
||||
&& wait_for_initial_topology
|
||||
{
|
||||
if let Err(err) = topology_refresher
|
||||
.wait_for_initial_network(topology_config.max_startup_network_waiting_period)
|
||||
.await
|
||||
{
|
||||
tracing::error!(
|
||||
"the network did not come become online within the specified timeout: {err}"
|
||||
);
|
||||
return Err(err.into());
|
||||
}
|
||||
}
|
||||
|
||||
// 2. wait for our gateway (if applicable)
|
||||
if topology_refresher
|
||||
.ensure_contains_routable_egress(local_gateway)
|
||||
.await
|
||||
.is_err()
|
||||
&& wait_for_gateway
|
||||
{
|
||||
if let Err(err) = topology_refresher
|
||||
.wait_for_gateway(
|
||||
local_gateway,
|
||||
topology_config.max_startup_gateway_waiting_period,
|
||||
)
|
||||
.await
|
||||
{
|
||||
tracing::error!(
|
||||
"the gateway did not come back online within the specified timeout: {err}"
|
||||
);
|
||||
return Err(err.into());
|
||||
}
|
||||
}
|
||||
|
||||
// 3. check if the topology is routable (in case we were NOT waiting for it)
|
||||
if let Err(err) = topology_refresher.ensure_topology_is_routable().await {
|
||||
tracing::error!(
|
||||
"The current network topology seem to be insufficient to route any packets through \
|
||||
@@ -702,30 +751,15 @@ where
|
||||
return Err(ClientCoreError::InsufficientNetworkTopology(err));
|
||||
}
|
||||
|
||||
let gateway_wait_timeout = if wait_for_gateway {
|
||||
Some(topology_config.max_startup_gateway_waiting_period)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
// 4. check if the gateway exists (in case we were NOT waiting for it)
|
||||
if let Err(err) = topology_refresher
|
||||
.ensure_contains_routable_egress(local_gateway)
|
||||
.await
|
||||
{
|
||||
if let Some(waiting_timeout) = gateway_wait_timeout {
|
||||
if let Err(err) = topology_refresher
|
||||
.wait_for_gateway(local_gateway, waiting_timeout)
|
||||
.await
|
||||
{
|
||||
tracing::error!(
|
||||
"the gateway did not come back online within the specified timeout: {err}"
|
||||
);
|
||||
return Err(err.into());
|
||||
}
|
||||
} else {
|
||||
tracing::error!("the gateway we're supposedly connected to does not exist. We'll not be able to send any packets to ourselves: {err}");
|
||||
return Err(err.into());
|
||||
}
|
||||
tracing::error!(
|
||||
"the gateway we're supposedly connected to does not exist. We'll not be able to send any packets to ourselves: {err}"
|
||||
);
|
||||
return Err(err.into());
|
||||
}
|
||||
|
||||
if !topology_config.disable_refreshing {
|
||||
@@ -1024,6 +1058,7 @@ where
|
||||
shared_topology_accessor.clone(),
|
||||
self_address.gateway(),
|
||||
self.wait_for_gateway,
|
||||
self.wait_for_initial_topology,
|
||||
&shutdown_tracker.clone(),
|
||||
)
|
||||
.await?;
|
||||
@@ -1195,9 +1230,11 @@ mod tests {
|
||||
]);
|
||||
|
||||
assert_eq!(network_details.nym_api_urls.as_ref().unwrap().len(), 2);
|
||||
assert!(network_details.nym_api_urls.as_ref().unwrap()[1]
|
||||
.front_hosts
|
||||
.is_some());
|
||||
assert!(
|
||||
network_details.nym_api_urls.as_ref().unwrap()[1]
|
||||
.front_hosts
|
||||
.is_some()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -1210,11 +1247,13 @@ mod tests {
|
||||
|
||||
assert_eq!(api_url.url, "https://nym-frontdoor.vercel.app/api/");
|
||||
assert_eq!(api_url.front_hosts.as_ref().unwrap().len(), 2);
|
||||
assert!(api_url
|
||||
.front_hosts
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.contains(&"vercel.app".to_string()));
|
||||
assert!(
|
||||
api_url
|
||||
.front_hosts
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.contains(&"vercel.app".to_string())
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::{
|
||||
client::replies::reply_storage::{fs_backend, CombinedReplyStorage, ReplyStorageBackend},
|
||||
client::replies::reply_storage::{CombinedReplyStorage, ReplyStorageBackend, fs_backend},
|
||||
config,
|
||||
config::Config,
|
||||
error::ClientCoreError,
|
||||
@@ -10,7 +10,7 @@ use crate::{
|
||||
use nym_bandwidth_controller::BandwidthController;
|
||||
use nym_client_core_gateways_storage::OnDiskGatewaysDetails;
|
||||
use nym_credential_storage::storage::Storage as CredentialStorage;
|
||||
use nym_validator_client::{nyxd, QueryHttpRpcNyxdClient};
|
||||
use nym_validator_client::{QueryHttpRpcNyxdClient, nyxd};
|
||||
use std::{io, path::Path};
|
||||
use time::OffsetDateTime;
|
||||
use tracing::{error, info, trace};
|
||||
@@ -24,7 +24,9 @@ async fn setup_fresh_backend<P: AsRef<Path>>(
|
||||
let mut storage_backend = match fs_backend::Backend::init(db_path).await {
|
||||
Ok(backend) => backend,
|
||||
Err(err) => {
|
||||
error!("setup_fresh_backend: Failed to setup persistent storage backend for our reply needs: {err}");
|
||||
error!(
|
||||
"setup_fresh_backend: Failed to setup persistent storage backend for our reply needs: {err}"
|
||||
);
|
||||
return Err(ClientCoreError::SurbStorageError {
|
||||
source: Box::new(err),
|
||||
});
|
||||
@@ -93,7 +95,9 @@ pub async fn setup_fs_reply_surb_backend<P: AsRef<Path>>(
|
||||
match fs_backend::Backend::try_load(db_path).await {
|
||||
Ok(backend) => Ok(backend),
|
||||
Err(err) => {
|
||||
error!("setup_fs_reply_surb_backend: Failed to setup persistent storage backend for our reply needs: {err}. We're going to create a fresh database instead. This behaviour might change in the future");
|
||||
error!(
|
||||
"setup_fs_reply_surb_backend: Failed to setup persistent storage backend for our reply needs: {err}. We're going to create a fresh database instead. This behaviour might change in the future"
|
||||
);
|
||||
archive_corrupted_database(db_path).await?;
|
||||
setup_fresh_backend(db_path, surb_config).await
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::client::key_manager::persistence::KeyStore;
|
||||
use crate::client::key_manager::ClientKeys;
|
||||
use crate::client::key_manager::persistence::KeyStore;
|
||||
use crate::error::ClientCoreError;
|
||||
use nym_client_core_gateways_storage::{
|
||||
ActiveGateway, GatewayPublishedData, GatewayRegistration, GatewaysDetailsStore,
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
pub mod v1_1_33 {
|
||||
use crate::config::disk_persistence::old_v1_1_33::CommonClientPathsV1_1_33;
|
||||
use crate::config::disk_persistence::CommonClientPaths;
|
||||
use crate::config::disk_persistence::old_v1_1_33::CommonClientPathsV1_1_33;
|
||||
use crate::config::old_config_v1_1_33::OldGatewayEndpointConfigV1_1_33;
|
||||
use crate::error::ClientCoreError;
|
||||
|
||||
|
||||
@@ -11,8 +11,8 @@ use nym_sphinx::addressing::clients::Recipient;
|
||||
use nym_sphinx::cover::generate_loop_cover_packet;
|
||||
use nym_sphinx::params::{PacketSize, PacketType};
|
||||
use nym_sphinx::utils::sample_poisson_duration;
|
||||
use nym_statistics_common::clients::{packet_statistics::PacketStatisticsEvent, ClientStatsSender};
|
||||
use rand::{rngs::OsRng, CryptoRng, Rng};
|
||||
use nym_statistics_common::clients::{ClientStatsSender, packet_statistics::PacketStatisticsEvent};
|
||||
use rand::{CryptoRng, Rng, rngs::OsRng};
|
||||
use std::pin::Pin;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
@@ -20,10 +20,10 @@ use tokio::sync::mpsc::error::TrySendError;
|
||||
use tracing::*;
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
use tokio::time::{sleep, Sleep};
|
||||
use tokio::time::{Sleep, sleep};
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
use wasmtimer::tokio::{sleep, Sleep};
|
||||
use wasmtimer::tokio::{Sleep, sleep};
|
||||
|
||||
pub struct LoopCoverTrafficStream<R>
|
||||
where
|
||||
@@ -179,7 +179,9 @@ impl LoopCoverTrafficStream<OsRng> {
|
||||
) {
|
||||
Ok(topology) => topology,
|
||||
Err(err) => {
|
||||
warn!("We're not going to send any loop cover message this time, as the current topology seem to be invalid - {err}");
|
||||
warn!(
|
||||
"We're not going to send any loop cover message this time, as the current topology seem to be invalid - {err}"
|
||||
);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -15,3 +15,13 @@ pub(crate) fn get_time_now() -> Instant {
|
||||
pub(crate) fn new_interval_stream(polling_rate: Duration) -> IntervalStream {
|
||||
gloo_timers::future::IntervalStream::new(polling_rate.as_millis() as u32)
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
unsafe extern "Rust" fn __getrandom_v03_custom(
|
||||
dest: *mut u8,
|
||||
len: usize,
|
||||
) -> Result<(), getrandom03::Error> {
|
||||
let _ = dest;
|
||||
let _ = len;
|
||||
Err(getrandom03::Error::UNSUPPORTED)
|
||||
}
|
||||
|
||||
@@ -13,10 +13,10 @@ use crate::config::disk_persistence::ClientKeysPaths;
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
use nym_crypto::asymmetric::{ed25519, x25519};
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
use nym_pemstore::traits::{PemStorableKey, PemStorableKeyPair};
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
use nym_pemstore::KeyPairPath;
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
use nym_pemstore::traits::{PemStorableKey, PemStorableKeyPair};
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
use nym_sphinx::acknowledgements::AckKey;
|
||||
|
||||
// we have to define it as an async trait since wasm storage is async
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
use async_trait::async_trait;
|
||||
use nym_credential_storage::storage::Storage as CredentialStorage;
|
||||
use nym_crypto::asymmetric::ed25519;
|
||||
use nym_gateway_client::error::GatewayClientError;
|
||||
use nym_gateway_client::GatewayClient;
|
||||
use nym_gateway_client::error::GatewayClientError;
|
||||
pub use nym_gateway_client::{GatewayPacketRouter, PacketRouter};
|
||||
use nym_gateway_requests::ClientRequest;
|
||||
use nym_sphinx::forwarding::packet::MixPacket;
|
||||
|
||||
+3
-3
@@ -2,13 +2,13 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use super::action_controller::{AckActionSender, Action};
|
||||
use nym_statistics_common::clients::{packet_statistics::PacketStatisticsEvent, ClientStatsSender};
|
||||
use nym_statistics_common::clients::{ClientStatsSender, packet_statistics::PacketStatisticsEvent};
|
||||
|
||||
use futures::StreamExt;
|
||||
use nym_gateway_client::AcknowledgementReceiver;
|
||||
use nym_sphinx::{
|
||||
acknowledgements::{identifier::recover_identifier, AckKey},
|
||||
chunking::fragment::{FragmentIdentifier, COVER_FRAG_ID},
|
||||
acknowledgements::{AckKey, identifier::recover_identifier},
|
||||
chunking::fragment::{COVER_FRAG_ID, FragmentIdentifier},
|
||||
};
|
||||
use nym_task::ShutdownToken;
|
||||
use std::sync::Arc;
|
||||
|
||||
+2
-2
@@ -3,11 +3,11 @@
|
||||
|
||||
use super::PendingAcknowledgement;
|
||||
use crate::client::real_messages_control::acknowledgement_control::RetransmissionRequestSender;
|
||||
use futures::channel::mpsc;
|
||||
use futures::StreamExt;
|
||||
use futures::channel::mpsc;
|
||||
use nym_nonexhaustive_delayqueue::{Expired, NonExhaustiveDelayQueue, QueueKey};
|
||||
use nym_sphinx::chunking::fragment::FragmentIdentifier;
|
||||
use nym_sphinx::Delay as SphinxDelay;
|
||||
use nym_sphinx::chunking::fragment::FragmentIdentifier;
|
||||
use nym_task::ShutdownToken;
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
|
||||
+1
-1
@@ -9,8 +9,8 @@ use nym_sphinx::addressing::clients::Recipient;
|
||||
use nym_sphinx::anonymous_replies::requests::AnonymousSenderTag;
|
||||
use nym_sphinx::forwarding::packet::MixPacket;
|
||||
use nym_sphinx::params::PacketType;
|
||||
use nym_task::connections::TransmissionLane;
|
||||
use nym_task::ShutdownToken;
|
||||
use nym_task::connections::TransmissionLane;
|
||||
use rand::{CryptoRng, Rng};
|
||||
use tracing::*;
|
||||
|
||||
|
||||
@@ -16,10 +16,10 @@ use nym_gateway_client::AcknowledgementReceiver;
|
||||
use nym_sphinx::anonymous_replies::requests::AnonymousSenderTag;
|
||||
use nym_sphinx::params::{PacketSize, PacketType};
|
||||
use nym_sphinx::{
|
||||
Delay as SphinxDelay,
|
||||
acknowledgements::AckKey,
|
||||
addressing::clients::Recipient,
|
||||
chunking::fragment::{Fragment, FragmentIdentifier},
|
||||
Delay as SphinxDelay,
|
||||
};
|
||||
use nym_statistics_common::clients::ClientStatsSender;
|
||||
use rand::{CryptoRng, Rng};
|
||||
|
||||
+2
-2
@@ -2,8 +2,8 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use super::{
|
||||
action_controller::{AckActionSender, Action},
|
||||
PendingAcknowledgement, RetransmissionRequestReceiver,
|
||||
action_controller::{AckActionSender, Action},
|
||||
};
|
||||
use crate::client::real_messages_control::acknowledgement_control::PacketDestination;
|
||||
use crate::client::real_messages_control::message_handler::{MessageHandler, PreparationError};
|
||||
@@ -13,7 +13,7 @@ use futures::StreamExt;
|
||||
use nym_sphinx::chunking::fragment::Fragment;
|
||||
use nym_sphinx::preparer::PreparedFragment;
|
||||
use nym_sphinx::{addressing::clients::Recipient, params::PacketType};
|
||||
use nym_task::{connections::TransmissionLane, ShutdownToken};
|
||||
use nym_task::{ShutdownToken, connections::TransmissionLane};
|
||||
use rand::{CryptoRng, Rng};
|
||||
use std::sync::{Arc, Weak};
|
||||
use tracing::*;
|
||||
|
||||
+2
-2
@@ -1,10 +1,10 @@
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use super::action_controller::{AckActionSender, Action};
|
||||
use super::SentPacketNotificationReceiver;
|
||||
use super::action_controller::{AckActionSender, Action};
|
||||
use futures::StreamExt;
|
||||
use nym_sphinx::chunking::fragment::{FragmentIdentifier, COVER_FRAG_ID};
|
||||
use nym_sphinx::chunking::fragment::{COVER_FRAG_ID, FragmentIdentifier};
|
||||
use tracing::*;
|
||||
|
||||
/// Module responsible for starting up retransmission timers.
|
||||
|
||||
@@ -10,17 +10,17 @@ use crate::client::replies::reply_controller::MaxRetransmissions;
|
||||
use crate::client::replies::reply_storage::{ReceivedReplySurbsMap, SentReplyKeys, UsedSenderTags};
|
||||
use crate::client::topology_control::{TopologyAccessor, TopologyReadPermit};
|
||||
use nym_client_core_surb_storage::RetrievedReplySurb;
|
||||
use nym_sphinx::Delay;
|
||||
use nym_sphinx::acknowledgements::AckKey;
|
||||
use nym_sphinx::addressing::clients::Recipient;
|
||||
use nym_sphinx::anonymous_replies::requests::{AnonymousSenderTag, RepliableMessage, ReplyMessage};
|
||||
use nym_sphinx::anonymous_replies::ReplySurbWithKeyRotation;
|
||||
use nym_sphinx::anonymous_replies::requests::{AnonymousSenderTag, RepliableMessage, ReplyMessage};
|
||||
use nym_sphinx::chunking::fragment::{Fragment, FragmentIdentifier};
|
||||
use nym_sphinx::message::NymMessage;
|
||||
use nym_sphinx::params::{PacketSize, PacketType};
|
||||
use nym_sphinx::preparer::{MessagePreparer, PreparedFragment};
|
||||
use nym_sphinx::Delay;
|
||||
use nym_task::connections::TransmissionLane;
|
||||
use nym_task::ShutdownToken;
|
||||
use nym_task::connections::TransmissionLane;
|
||||
use nym_topology::{NymRouteProvider, NymTopologyError};
|
||||
use rand::{CryptoRng, Rng};
|
||||
use std::collections::HashMap;
|
||||
@@ -272,7 +272,9 @@ where
|
||||
let primary_count = msg.required_packets(self.config.primary_packet_size);
|
||||
let secondary_count = msg.required_packets(secondary_packet);
|
||||
|
||||
trace!("This message would require: {primary_count} primary packets or {secondary_count} secondary packets...");
|
||||
trace!(
|
||||
"This message would require: {primary_count} primary packets or {secondary_count} secondary packets..."
|
||||
);
|
||||
// if there would be no benefit in using the secondary packet - use the primary (duh)
|
||||
if primary_count <= secondary_count {
|
||||
trace!("so choosing primary for this message");
|
||||
|
||||
@@ -25,9 +25,9 @@ use nym_gateway_client::AcknowledgementReceiver;
|
||||
use nym_sphinx::acknowledgements::AckKey;
|
||||
use nym_sphinx::addressing::clients::Recipient;
|
||||
use nym_statistics_common::clients::ClientStatsSender;
|
||||
use nym_task::connections::{ConnectionCommandReceiver, LaneQueueLengths};
|
||||
use nym_task::ShutdownToken;
|
||||
use rand::{rngs::OsRng, CryptoRng, Rng};
|
||||
use nym_task::connections::{ConnectionCommandReceiver, LaneQueueLengths};
|
||||
use rand::{CryptoRng, Rng, rngs::OsRng};
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::client::replies::reply_controller::key_rotation_helpers::KeyRotationConfig;
|
||||
|
||||
@@ -17,11 +17,11 @@ use nym_sphinx::forwarding::packet::MixPacket;
|
||||
use nym_sphinx::params::PacketSize;
|
||||
use nym_sphinx::preparer::PreparedFragment;
|
||||
use nym_sphinx::utils::sample_poisson_duration;
|
||||
use nym_statistics_common::clients::{packet_statistics::PacketStatisticsEvent, ClientStatsSender};
|
||||
use nym_statistics_common::clients::{ClientStatsSender, packet_statistics::PacketStatisticsEvent};
|
||||
use nym_task::ShutdownToken;
|
||||
use nym_task::connections::{
|
||||
ConnectionCommand, ConnectionCommandReceiver, ConnectionId, LaneQueueLengths, TransmissionLane,
|
||||
};
|
||||
use nym_task::ShutdownToken;
|
||||
use rand::{CryptoRng, Rng};
|
||||
use std::pin::Pin;
|
||||
use std::sync::Arc;
|
||||
@@ -29,11 +29,11 @@ use std::time::Duration;
|
||||
use tracing::*;
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
use tokio::time::{sleep, Sleep};
|
||||
use tokio::time::{Sleep, sleep};
|
||||
|
||||
// use nym_wasm_utils::console_log;
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
use wasmtimer::tokio::{sleep, Sleep};
|
||||
use wasmtimer::tokio::{Sleep, sleep};
|
||||
mod sending_delay_controller;
|
||||
|
||||
/// Configurable parameters of the `OutQueueControl`
|
||||
@@ -230,7 +230,9 @@ where
|
||||
let (next_message, fragment_id, packet_size) = match next_message {
|
||||
StreamMessage::Cover => {
|
||||
let cover_traffic_packet_size = self.loop_cover_message_size();
|
||||
trace!("the next loop cover message will be put in a {cover_traffic_packet_size} packet");
|
||||
trace!(
|
||||
"the next loop cover message will be put in a {cover_traffic_packet_size} packet"
|
||||
);
|
||||
|
||||
// TODO for way down the line: in very rare cases (during topology update) we might have
|
||||
// to wait a really tiny bit before actually obtaining the permit hence messing with our
|
||||
@@ -244,7 +246,9 @@ where
|
||||
) {
|
||||
Ok(topology) => topology,
|
||||
Err(err) => {
|
||||
warn!("We're not going to send any loop cover message this time, as the current topology seem to be invalid - {err}");
|
||||
warn!(
|
||||
"We're not going to send any loop cover message this time, as the current topology seem to be invalid - {err}"
|
||||
);
|
||||
return;
|
||||
}
|
||||
};
|
||||
@@ -436,7 +440,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(ref mut next_delay) = &mut self.next_delay {
|
||||
if let Some(next_delay) = &mut self.next_delay {
|
||||
// it is not yet time to return a message
|
||||
if next_delay.as_mut().poll(cx).is_pending() {
|
||||
return Poll::Pending;
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::client::helpers::{get_time_now, Instant};
|
||||
use crate::client::helpers::{Instant, get_time_now};
|
||||
use std::time::Duration;
|
||||
|
||||
// The minimum time between increasing the average delay between packets. If we hit the ceiling in
|
||||
|
||||
@@ -5,20 +5,20 @@ use crate::client::helpers::get_time_now;
|
||||
use crate::client::replies::{
|
||||
reply_controller::ReplyControllerSender, reply_storage::SentReplyKeys,
|
||||
};
|
||||
use futures::StreamExt;
|
||||
use futures::channel::mpsc;
|
||||
use futures::lock::Mutex;
|
||||
use futures::StreamExt;
|
||||
use nym_crypto::asymmetric::x25519;
|
||||
use nym_crypto::Digest;
|
||||
use nym_crypto::asymmetric::x25519;
|
||||
use nym_gateway_client::MixnetMessageReceiver;
|
||||
use nym_sphinx::anonymous_replies::requests::{
|
||||
RepliableMessage, RepliableMessageContent, ReplyMessage, ReplyMessageContent,
|
||||
};
|
||||
use nym_sphinx::anonymous_replies::{encryption_key::EncryptionKeyDigest, SurbEncryptionKey};
|
||||
use nym_sphinx::anonymous_replies::{SurbEncryptionKey, encryption_key::EncryptionKeyDigest};
|
||||
use nym_sphinx::message::{NymMessage, PlainMessage};
|
||||
use nym_sphinx::params::ReplySurbKeyDigestAlgorithm;
|
||||
use nym_sphinx::receiver::{MessageReceiver, MessageRecoveryError, ReconstructedMessage};
|
||||
use nym_statistics_common::clients::{packet_statistics::PacketStatisticsEvent, ClientStatsSender};
|
||||
use nym_statistics_common::clients::{ClientStatsSender, packet_statistics::PacketStatisticsEvent};
|
||||
use nym_task::ShutdownToken;
|
||||
use std::collections::HashSet;
|
||||
use std::sync::Arc;
|
||||
@@ -78,14 +78,19 @@ impl<R: MessageReceiver> ReceivedMessagesBufferInner<R> {
|
||||
|
||||
let fragment = match self.message_receiver.recover_fragment(fragment_data) {
|
||||
Err(err) => {
|
||||
warn!("failed to recover fragment from raw data: {err}. The whole underlying message might be corrupted and unrecoverable!");
|
||||
warn!(
|
||||
"failed to recover fragment from raw data: {err}. The whole underlying message might be corrupted and unrecoverable!"
|
||||
);
|
||||
return None;
|
||||
}
|
||||
Ok(frag) => frag,
|
||||
};
|
||||
|
||||
if self.recently_reconstructed.contains(&fragment.id()) {
|
||||
debug!("Received a chunk of already re-assembled message ({:?})! It probably got here because the ack got lost", fragment.id());
|
||||
debug!(
|
||||
"Received a chunk of already re-assembled message ({:?})! It probably got here because the ack got lost",
|
||||
fragment.id()
|
||||
);
|
||||
return None;
|
||||
}
|
||||
|
||||
@@ -93,7 +98,9 @@ impl<R: MessageReceiver> ReceivedMessagesBufferInner<R> {
|
||||
match self.message_receiver.insert_new_fragment(fragment) {
|
||||
Err(err) => match err {
|
||||
MessageRecoveryError::MalformedReconstructedMessage { source, used_sets } => {
|
||||
error!("message reconstruction failed - {source}. Attempting to re-use the message sets...");
|
||||
error!(
|
||||
"message reconstruction failed - {source}. Attempting to re-use the message sets..."
|
||||
);
|
||||
// TODO: should we really insert reconstructed sets? could this be abused for some attack?
|
||||
for set_id in used_sets {
|
||||
if !self.recently_reconstructed.insert(set_id) {
|
||||
@@ -144,7 +151,9 @@ impl<R: MessageReceiver> ReceivedMessagesBufferInner<R> {
|
||||
&mut raw_fragment,
|
||||
) {
|
||||
Err(err) => {
|
||||
warn!("failed to recover fragment data: {err}. The whole underlying message might be corrupted and unrecoverable!");
|
||||
warn!(
|
||||
"failed to recover fragment data: {err}. The whole underlying message might be corrupted and unrecoverable!"
|
||||
);
|
||||
return None;
|
||||
}
|
||||
Ok(frag_data) => frag_data,
|
||||
@@ -275,7 +284,9 @@ impl<R: MessageReceiver> ReceivedMessagesBuffer<R> {
|
||||
}
|
||||
RepliableMessageContent::Heartbeat(content) => {
|
||||
let additional_reply_surbs = content.additional_reply_surbs;
|
||||
error!("received a repliable heartbeat message - we don't know how to handle it yet (and we won't know until future PRs)");
|
||||
error!(
|
||||
"received a repliable heartbeat message - we don't know how to handle it yet (and we won't know until future PRs)"
|
||||
);
|
||||
(additional_reply_surbs, false)
|
||||
}
|
||||
RepliableMessageContent::DataV2(content) => {
|
||||
@@ -304,7 +315,9 @@ impl<R: MessageReceiver> ReceivedMessagesBuffer<R> {
|
||||
}
|
||||
RepliableMessageContent::HeartbeatV2(content) => {
|
||||
let additional_reply_surbs = content.additional_reply_surbs;
|
||||
error!("received a repliable heartbeat message - we don't know how to handle it yet (and we won't know until future PRs)");
|
||||
error!(
|
||||
"received a repliable heartbeat message - we don't know how to handle it yet (and we won't know until future PRs)"
|
||||
);
|
||||
(additional_reply_surbs, false)
|
||||
}
|
||||
};
|
||||
@@ -380,7 +393,9 @@ impl<R: MessageReceiver> ReceivedMessagesBuffer<R> {
|
||||
if let Some(sender) = &inner_guard.message_sender {
|
||||
trace!("Sending reconstructed messages to announced sender");
|
||||
if let Err(err) = sender.unbounded_send(reconstructed_messages) {
|
||||
warn!("The reconstructed message receiver went offline without explicit notification (relevant error: - {err})");
|
||||
warn!(
|
||||
"The reconstructed message receiver went offline without explicit notification (relevant error: - {err})"
|
||||
);
|
||||
inner_guard.message_sender = None;
|
||||
inner_guard.messages.extend(err.into_inner());
|
||||
}
|
||||
|
||||
@@ -5,15 +5,15 @@ use crate::client::real_messages_control::acknowledgement_control::PendingAcknow
|
||||
use crate::client::real_messages_control::message_handler::{
|
||||
FragmentWithMaxRetransmissions, MessageHandler, PreparationError,
|
||||
};
|
||||
use crate::client::replies::reply_controller::key_rotation_helpers::SurbRefreshState;
|
||||
use crate::client::replies::reply_controller::Config;
|
||||
use crate::client::replies::reply_controller::key_rotation_helpers::SurbRefreshState;
|
||||
use crate::client::topology_control::TopologyAccessor;
|
||||
use crate::client::transmission_buffer::TransmissionBuffer;
|
||||
use futures::channel::oneshot;
|
||||
use nym_client_core_surb_storage::{ReceivedReplySurb, ReceivedReplySurbsMap};
|
||||
use nym_crypto::aes::cipher::crypto_common::rand_core::CryptoRng;
|
||||
use nym_sphinx::anonymous_replies::requests::AnonymousSenderTag;
|
||||
use nym_sphinx::anonymous_replies::ReplySurbWithKeyRotation;
|
||||
use nym_sphinx::anonymous_replies::requests::AnonymousSenderTag;
|
||||
use nym_sphinx::chunking::fragment::FragmentIdentifier;
|
||||
use nym_task::connections::{ConnectionId, TransmissionLane};
|
||||
use nym_topology::NymTopologyMetadata;
|
||||
@@ -50,7 +50,9 @@ impl SenderData {
|
||||
let pending_retransmissions = self.pending_retransmissions.len();
|
||||
let total_pending = pending_retransmissions + pending_replies;
|
||||
|
||||
debug!("total queue size: {total_pending} = pending data {pending_replies} + pending retransmission {pending_retransmissions}");
|
||||
debug!(
|
||||
"total queue size: {total_pending} = pending data {pending_replies} + pending retransmission {pending_retransmissions}"
|
||||
);
|
||||
|
||||
total_pending
|
||||
}
|
||||
@@ -200,7 +202,9 @@ where
|
||||
let total_required_surbs = total_queue + target_surbs_after_clearing_queue;
|
||||
let total_available_surbs = pending_surbs + available_surbs;
|
||||
|
||||
debug!("available surbs: {available_surbs} pending surbs: {pending_surbs} threshold range: {min_surbs_threshold}..+{min_surbs_threshold_buffer}..{max_surbs_threshold}");
|
||||
debug!(
|
||||
"available surbs: {available_surbs} pending surbs: {pending_surbs} threshold range: {min_surbs_threshold}..+{min_surbs_threshold_buffer}..{max_surbs_threshold}"
|
||||
);
|
||||
|
||||
// We should request more surbs if:
|
||||
// 1. We haven't hit the maximum surb threshold, and
|
||||
@@ -225,9 +229,13 @@ where
|
||||
.is_none()
|
||||
{
|
||||
// don't report it every single time
|
||||
warn!("received reply request for {recipient_tag} but we don't have any surbs stored for that recipient!");
|
||||
warn!(
|
||||
"received reply request for {recipient_tag} but we don't have any surbs stored for that recipient!"
|
||||
);
|
||||
} else {
|
||||
trace!("received reply request for {recipient_tag} but we don't have any surbs stored for that recipient!");
|
||||
trace!(
|
||||
"received reply request for {recipient_tag} but we don't have any surbs stored for that recipient!"
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -383,7 +391,9 @@ where
|
||||
let (surbs_for_reply, _) = self.surbs_storage.get_reply_surbs(&target, to_take.len());
|
||||
|
||||
let Some(surbs_for_reply) = surbs_for_reply else {
|
||||
error!("somehow different task has stolen our reply surbs! - this should have been impossible");
|
||||
error!(
|
||||
"somehow different task has stolen our reply surbs! - this should have been impossible"
|
||||
);
|
||||
self.re_insert_pending_retransmission(&target, to_take);
|
||||
return;
|
||||
};
|
||||
@@ -459,7 +469,9 @@ where
|
||||
.get_reply_surbs(&target, to_send_clone.len());
|
||||
|
||||
let Some(surbs_for_reply) = surbs_for_reply else {
|
||||
error!("somehow different task has stolen our reply surbs! - this should have been impossible");
|
||||
error!(
|
||||
"somehow different task has stolen our reply surbs! - this should have been impossible"
|
||||
);
|
||||
self.re_insert_pending_replies(&target, to_send);
|
||||
return;
|
||||
};
|
||||
@@ -543,7 +555,9 @@ where
|
||||
let ack_ref = match timed_out_ack.upgrade() {
|
||||
Some(ack) => ack,
|
||||
None => {
|
||||
debug!("we received the ack for one of the reply packets as we were putting it in the retransmission queue");
|
||||
debug!(
|
||||
"we received the ack for one of the reply packets as we were putting it in the retransmission queue"
|
||||
);
|
||||
return;
|
||||
}
|
||||
};
|
||||
@@ -657,9 +671,13 @@ where
|
||||
|
||||
// only log at higher level if it's the first time this error has occurred in a while
|
||||
if now - last_failure > time::Duration::seconds(30) {
|
||||
warn!("failed to request more surbs to clear pending queue of size {total_queue} (attempted to request: {request_size}): {err}")
|
||||
warn!(
|
||||
"failed to request more surbs to clear pending queue of size {total_queue} (attempted to request: {request_size}): {err}"
|
||||
)
|
||||
} else {
|
||||
debug!("failed to request more surbs to clear pending queue of size {total_queue} (attempted to request: {request_size}): {err}")
|
||||
debug!(
|
||||
"failed to request more surbs to clear pending queue of size {total_queue} (attempted to request: {request_size}): {err}"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -681,7 +699,10 @@ where
|
||||
.surbs_storage
|
||||
.surbs_last_received_at(pending_reply_target)
|
||||
else {
|
||||
error!("we have {} pending replies for {pending_reply_target}, but we somehow never received any reply surbs from them!", retransmission_buf.total_size());
|
||||
error!(
|
||||
"we have {} pending replies for {pending_reply_target}, but we somehow never received any reply surbs from them!",
|
||||
retransmission_buf.total_size()
|
||||
);
|
||||
to_remove.push(*pending_reply_target);
|
||||
continue;
|
||||
};
|
||||
@@ -702,7 +723,9 @@ where
|
||||
// if client is offline)
|
||||
if vals.current_clear_rerequest_counter > max_rerequests {
|
||||
to_remove.push(*pending_reply_target);
|
||||
debug!("we have reached the maximum threshold of attempting to request surbs from {pending_reply_target}. dropping the sender");
|
||||
debug!(
|
||||
"we have reached the maximum threshold of attempting to request surbs from {pending_reply_target}. dropping the sender"
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -710,7 +733,10 @@ where
|
||||
if diff > max_drop_wait {
|
||||
to_remove.push(*pending_reply_target)
|
||||
} else {
|
||||
debug!("We haven't received any surbs in {} from {pending_reply_target}. Going to explicitly ask for more", humantime::format_duration(diff.unsigned_abs()));
|
||||
debug!(
|
||||
"We haven't received any surbs in {} from {pending_reply_target}. Going to explicitly ask for more",
|
||||
humantime::format_duration(diff.unsigned_abs())
|
||||
);
|
||||
vals.increment_current_clear_rerequest_counter();
|
||||
to_request.push(*pending_reply_target);
|
||||
}
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
use crate::client::real_messages_control::acknowledgement_control::PendingAcknowledgement;
|
||||
use futures::channel::{mpsc, oneshot};
|
||||
use nym_sphinx::addressing::clients::Recipient;
|
||||
use nym_sphinx::anonymous_replies::requests::AnonymousSenderTag;
|
||||
use nym_sphinx::anonymous_replies::ReplySurbWithKeyRotation;
|
||||
use nym_sphinx::anonymous_replies::requests::AnonymousSenderTag;
|
||||
use nym_task::connections::{ConnectionId, TransmissionLane};
|
||||
use std::sync::Weak;
|
||||
|
||||
|
||||
@@ -43,7 +43,9 @@ where
|
||||
// 1. check whether we sent any surbs in the past to this recipient, otherwise
|
||||
// they have no business in asking for more
|
||||
if !self.tags_storage.exists(&recipient) {
|
||||
warn!("{recipient} asked us for reply SURBs even though we never sent them any anonymous messages before!");
|
||||
warn!(
|
||||
"{recipient} asked us for reply SURBs even though we never sent them any anonymous messages before!"
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -54,7 +56,12 @@ where
|
||||
.reply_surbs
|
||||
.maximum_allowed_reply_surb_request_size
|
||||
{
|
||||
warn!("The requested reply surb amount is larger than our maximum allowed ({amount} > {}). Lowering it to a more sane value...", self.config.reply_surbs.maximum_allowed_reply_surb_request_size);
|
||||
warn!(
|
||||
"The requested reply surb amount is larger than our maximum allowed ({amount} > {}). Lowering it to a more sane value...",
|
||||
self.config
|
||||
.reply_surbs
|
||||
.maximum_allowed_reply_surb_request_size
|
||||
);
|
||||
amount = self
|
||||
.config
|
||||
.reply_surbs
|
||||
|
||||
@@ -23,7 +23,7 @@ use nym_sphinx::addressing::Recipient;
|
||||
use nym_statistics_common::clients::{
|
||||
ClientStatsController, ClientStatsReceiver, ClientStatsSender,
|
||||
};
|
||||
use nym_task::{connections::TransmissionLane, ShutdownToken, ShutdownTracker};
|
||||
use nym_task::{ShutdownToken, ShutdownTracker, connections::TransmissionLane};
|
||||
use std::time::Duration;
|
||||
|
||||
/// Time interval between reporting statistics locally (logging/shutdown_token)
|
||||
|
||||
@@ -5,8 +5,8 @@ use nym_sphinx::addressing::clients::Recipient;
|
||||
use nym_topology::{NymRouteProvider, NymTopology, NymTopologyError, NymTopologyMetadata};
|
||||
use nym_validator_client::models::KeyRotationId;
|
||||
use std::ops::Deref;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::Arc;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use tokio::sync::{Notify, RwLock, RwLockReadGuard};
|
||||
|
||||
#[derive(Debug)]
|
||||
|
||||
@@ -63,7 +63,9 @@ impl TopologyRefresher {
|
||||
trace!("Refreshing the topology");
|
||||
|
||||
if self.topology_accessor.controlled_manually() {
|
||||
info!("topology is being controlled manually - we're going to wait until the control is released...");
|
||||
info!(
|
||||
"topology is being controlled manually - we're going to wait until the control is released..."
|
||||
);
|
||||
self.topology_accessor
|
||||
.wait_for_released_manual_control()
|
||||
.await;
|
||||
@@ -138,6 +140,35 @@ impl TopologyRefresher {
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn wait_for_initial_network(
|
||||
&mut self,
|
||||
timeout_duration: Duration,
|
||||
) -> Result<(), NymTopologyError> {
|
||||
info!(
|
||||
"going to wait for at most {timeout_duration:?} for initial network to become online"
|
||||
);
|
||||
|
||||
let deadline = sleep(timeout_duration);
|
||||
tokio::pin!(deadline);
|
||||
|
||||
loop {
|
||||
tokio::select! {
|
||||
_ = &mut deadline => {
|
||||
return Err(NymTopologyError::TimedOutWaitingForTopology)
|
||||
}
|
||||
_ = self.try_refresh() => {
|
||||
if let Err(err) = self.ensure_topology_is_routable().await {
|
||||
info!("network is still not routable...: {err}");
|
||||
} else {
|
||||
return Ok(())
|
||||
}
|
||||
|
||||
sleep(self.refresh_rate).await
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// it's perfectly fine if task is interrupted mid-refresh
|
||||
// there's no data to persist or send over
|
||||
pub async fn run(&mut self) {
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
|
||||
use async_trait::async_trait;
|
||||
use nym_mixnet_contract_common::EpochRewardedSet;
|
||||
use nym_topology::provider_trait::{ToTopologyMetadata, TopologyProvider};
|
||||
use nym_topology::NymTopology;
|
||||
use nym_topology::provider_trait::{ToTopologyMetadata, TopologyProvider};
|
||||
use nym_validator_client::nym_api::NymApiClientExt;
|
||||
use rand::prelude::SliceRandom;
|
||||
use rand::thread_rng;
|
||||
@@ -82,7 +82,9 @@ impl NymApiTopologyProvider {
|
||||
|
||||
fn use_next_nym_api(&mut self) {
|
||||
if self.nym_api_urls.len() == 1 {
|
||||
warn!("There's only a single nym API available - it won't be possible to use a different one");
|
||||
warn!(
|
||||
"There's only a single nym API available - it won't be possible to use a different one"
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -155,7 +157,10 @@ impl NymApiTopologyProvider {
|
||||
let mixnodes = mixnodes_res.nodes;
|
||||
|
||||
if !gateways_res.metadata.consistency_check(&metadata) {
|
||||
warn!("inconsistent nodes metadata between mixnodes and gateways calls! {metadata:?} and {:?}", gateways_res.metadata);
|
||||
warn!(
|
||||
"inconsistent nodes metadata between mixnodes and gateways calls! {metadata:?} and {:?}",
|
||||
gateways_res.metadata
|
||||
);
|
||||
return None;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::client::helpers::{get_time_now, Instant};
|
||||
use crate::client::helpers::{Instant, get_time_now};
|
||||
use crate::client::real_messages_control::real_traffic_stream::RealMessage;
|
||||
use nym_sphinx::chunking::fragment::Fragment;
|
||||
use nym_task::connections::TransmissionLane;
|
||||
use rand::{seq::SliceRandom, Rng};
|
||||
use rand::{Rng, seq::SliceRandom};
|
||||
use std::{
|
||||
collections::{HashMap, HashSet, VecDeque},
|
||||
time::Duration,
|
||||
|
||||
@@ -7,9 +7,9 @@ use nym_gateway_client::error::GatewayClientError;
|
||||
use nym_task::RegistryAccessError;
|
||||
use nym_topology::node::RoutingNodeError;
|
||||
use nym_topology::{NodeId, NymTopologyError};
|
||||
use nym_validator_client::ValidatorClientError;
|
||||
use nym_validator_client::nym_api::error::NymAPIError;
|
||||
use nym_validator_client::nyxd::error::NyxdError;
|
||||
use nym_validator_client::ValidatorClientError;
|
||||
use rand::distributions::WeightedError;
|
||||
use std::error::Error;
|
||||
use std::path::PathBuf;
|
||||
@@ -56,7 +56,9 @@ pub enum ClientCoreError {
|
||||
#[error("no gateways on network")]
|
||||
NoGatewaysOnNetwork,
|
||||
|
||||
#[error("there are no more new gateways on the network - it seems this client has already registered with all nodes it could have")]
|
||||
#[error(
|
||||
"there are no more new gateways on the network - it seems this client has already registered with all nodes it could have"
|
||||
)]
|
||||
NoNewGatewaysAvailable,
|
||||
|
||||
#[error("list of nym apis is empty")]
|
||||
@@ -127,7 +129,9 @@ pub enum ClientCoreError {
|
||||
#[error("unexpected exit")]
|
||||
UnexpectedExit,
|
||||
|
||||
#[error("this operation would have resulted in the gateway {gateway_id:?} key being overwritten without permission")]
|
||||
#[error(
|
||||
"this operation would have resulted in the gateway {gateway_id:?} key being overwritten without permission"
|
||||
)]
|
||||
ForbiddenGatewayKeyOverwrite { gateway_id: String },
|
||||
|
||||
#[error(
|
||||
@@ -151,7 +155,9 @@ pub enum ClientCoreError {
|
||||
#[error("attempted to obtain fresh gateway details whilst already knowing about one")]
|
||||
UnexpectedGatewayDetails,
|
||||
|
||||
#[error("the provided gateway details (for gateway {gateway_id}) do not correspond to the shared keys")]
|
||||
#[error(
|
||||
"the provided gateway details (for gateway {gateway_id}) do not correspond to the shared keys"
|
||||
)]
|
||||
MismatchedGatewayDetails { gateway_id: String },
|
||||
|
||||
#[error("unable to upgrade config file from `{current_version}`")]
|
||||
@@ -227,7 +233,9 @@ pub enum ClientCoreError {
|
||||
source: url::ParseError,
|
||||
},
|
||||
|
||||
#[error("this client (id: '{client_id}') has already been initialised before. If you want to add additional gateway, use `add-gateway` command")]
|
||||
#[error(
|
||||
"this client (id: '{client_id}') has already been initialised before. If you want to add additional gateway, use `add-gateway` command"
|
||||
)]
|
||||
AlreadyInitialised { client_id: String },
|
||||
|
||||
#[error("this client has already registered with gateway {gateway_id}")]
|
||||
|
||||
@@ -5,13 +5,13 @@ use crate::error::ClientCoreError;
|
||||
use crate::init::types::RegistrationResult;
|
||||
use futures::{SinkExt, StreamExt};
|
||||
use nym_crypto::asymmetric::ed25519;
|
||||
use nym_gateway_client::client::GatewayListeners;
|
||||
use nym_gateway_client::GatewayClient;
|
||||
use nym_gateway_client::client::GatewayListeners;
|
||||
use nym_topology::node::RoutingNode;
|
||||
use nym_validator_client::UserAgent;
|
||||
use nym_validator_client::client::{IdentityKeyRef, NymApiClientExt};
|
||||
use nym_validator_client::nym_nodes::SkimmedNodesWithMetadata;
|
||||
use nym_validator_client::UserAgent;
|
||||
use rand::{seq::SliceRandom, Rng};
|
||||
use rand::{Rng, seq::SliceRandom};
|
||||
#[cfg(unix)]
|
||||
use std::os::fd::RawFd;
|
||||
use std::{sync::Arc, time::Duration};
|
||||
@@ -28,10 +28,10 @@ use nym_wasm_utils::websocket::JSWebsocket;
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
use tokio::net::TcpStream;
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
use tokio::time::sleep;
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
use tokio::time::Instant;
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
use tokio::time::sleep;
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
use tokio_tungstenite::{MaybeTlsStream, WebSocketStream};
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
use wasmtimer::std::Instant;
|
||||
|
||||
@@ -7,8 +7,8 @@ use crate::client::base_client::storage::helpers::{
|
||||
has_gateway_details, load_active_gateway_details, load_client_keys, load_gateway_details,
|
||||
store_gateway_details, update_stored_published_data_gateway,
|
||||
};
|
||||
use crate::client::key_manager::persistence::KeyStore;
|
||||
use crate::client::key_manager::ClientKeys;
|
||||
use crate::client::key_manager::persistence::KeyStore;
|
||||
use crate::error::ClientCoreError;
|
||||
use crate::init::helpers::{
|
||||
choose_gateway_by_latency, get_specified_gateway, uniformly_random_gateway,
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
// Copyright 2023-2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::client::key_manager::persistence::KeyStore;
|
||||
use crate::client::key_manager::ClientKeys;
|
||||
use crate::client::key_manager::persistence::KeyStore;
|
||||
use crate::config::Config;
|
||||
use crate::error::ClientCoreError;
|
||||
use crate::init::{setup_gateway, use_loaded_gateway_details};
|
||||
@@ -10,8 +10,8 @@ use nym_client_core_gateways_storage::{
|
||||
GatewayRegistration, GatewaysDetailsStore, RemoteGatewayDetails,
|
||||
};
|
||||
use nym_crypto::asymmetric::ed25519;
|
||||
use nym_gateway_client::client::{GatewayListeners, InitGatewayClient};
|
||||
use nym_gateway_client::SharedSymmetricKey;
|
||||
use nym_gateway_client::client::{GatewayListeners, InitGatewayClient};
|
||||
use nym_sphinx::addressing::clients::Recipient;
|
||||
use nym_topology::node::RoutingNode;
|
||||
use nym_validator_client::client::IdentityKey;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#![allow(deprecated)] // silences clippy warning: use of deprecated associated function `nym_crypto::generic_array::GenericArray::<T, N>::clone_from_slice`: please upgrade to generic-array 1.x - TODO
|
||||
use std::future::Future;
|
||||
|
||||
#[cfg(all(
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
#![allow(deprecated)] // silences clippy warning: use of deprecated associated function `nym_crypto::generic_array::GenericArray::<T, N>::from_exact_iter`: please upgrade to generic-array 1.x - TODO
|
||||
pub use backend::*;
|
||||
pub use combined::CombinedReplyStorage;
|
||||
pub use key_storage::SentReplyKeys;
|
||||
|
||||
@@ -128,54 +128,95 @@ impl ManagedConnection {
|
||||
|
||||
async fn run(self) {
|
||||
let address = self.address;
|
||||
let reconnection_attempt = self.current_reconnection.load(Ordering::Acquire);
|
||||
let connect_start = tokio::time::Instant::now();
|
||||
let connection_fut = TcpStream::connect(address);
|
||||
|
||||
let conn = match tokio::time::timeout(self.connection_timeout, connection_fut).await {
|
||||
Ok(stream_res) => match stream_res {
|
||||
Ok(stream) => {
|
||||
debug!("Managed to establish connection to {}", self.address);
|
||||
let connect_ms = connect_start.elapsed().as_millis() as u64;
|
||||
debug!(
|
||||
peer = %address,
|
||||
connect_ms,
|
||||
"Managed to establish connection to {}", self.address
|
||||
);
|
||||
|
||||
let noise_start = tokio::time::Instant::now();
|
||||
let noise_stream =
|
||||
match upgrade_noise_initiator(stream, &self.noise_config).await {
|
||||
Ok(noise_stream) => noise_stream,
|
||||
Err(err) => {
|
||||
error!("Failed to perform Noise handshake with {address} - {err}");
|
||||
// we failed to finish the noise handshake - increase reconnection attempt
|
||||
let noise_handshake_ms = noise_start.elapsed().as_millis() as u64;
|
||||
warn!(
|
||||
event = "connection.failed.noise",
|
||||
peer = %address,
|
||||
error = %err,
|
||||
connect_ms,
|
||||
noise_handshake_ms,
|
||||
reconnection_attempt,
|
||||
exit_reason = "noise_error",
|
||||
"Failed to perform Noise initiator handshake with {address}"
|
||||
);
|
||||
self.current_reconnection.fetch_add(1, Ordering::SeqCst);
|
||||
return;
|
||||
}
|
||||
};
|
||||
// if we managed to connect AND do the noise handshake, reset the reconnection count (whatever it might have been)
|
||||
let noise_handshake_ms = noise_start.elapsed().as_millis() as u64;
|
||||
self.current_reconnection.store(0, Ordering::Release);
|
||||
debug!("Noise initiator handshake completed for {:?}", address);
|
||||
debug!(
|
||||
peer = %address,
|
||||
connect_ms,
|
||||
noise_handshake_ms,
|
||||
"Noise initiator handshake completed for {:?}", address
|
||||
);
|
||||
Framed::new(noise_stream, NymCodec)
|
||||
}
|
||||
Err(err) => {
|
||||
debug!("failed to establish connection to {address} (err: {err})",);
|
||||
let connect_ms = connect_start.elapsed().as_millis() as u64;
|
||||
warn!(
|
||||
event = "connection.failed.connect",
|
||||
peer = %address,
|
||||
error = %err,
|
||||
connect_ms,
|
||||
reconnection_attempt,
|
||||
exit_reason = "connect_error",
|
||||
"failed to establish connection to {address}"
|
||||
);
|
||||
return;
|
||||
}
|
||||
},
|
||||
Err(_) => {
|
||||
debug!(
|
||||
let connect_ms = connect_start.elapsed().as_millis() as u64;
|
||||
warn!(
|
||||
event = "connection.failed.timeout",
|
||||
peer = %address,
|
||||
timeout_ms = self.connection_timeout.as_millis() as u64,
|
||||
connect_ms,
|
||||
reconnection_attempt,
|
||||
exit_reason = "timeout",
|
||||
"failed to connect to {address} within {:?}",
|
||||
self.connection_timeout
|
||||
);
|
||||
|
||||
// we failed to connect - increase reconnection attempt
|
||||
self.current_reconnection.fetch_add(1, Ordering::SeqCst);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
// Take whatever the receiver channel produces and put it on the connection.
|
||||
// We could have as well used conn.send_all(receiver.map(Ok)), but considering we don't care
|
||||
// about neither receiver nor the connection, it doesn't matter which one gets consumed
|
||||
if let Err(err) = self.message_receiver.map(Ok).forward(conn).await {
|
||||
warn!("Failed to forward packets to {address}: {err}");
|
||||
warn!(
|
||||
event = "connection.forward_error",
|
||||
peer = %address,
|
||||
error = %err,
|
||||
exit_reason = "forward_error",
|
||||
"Failed to forward packets to {address}: {err}"
|
||||
);
|
||||
}
|
||||
|
||||
debug!(
|
||||
"connection manager to {address} is finished. Either the connection failed or mixnet client got dropped",
|
||||
peer = %address,
|
||||
exit_reason = "sender_dropped",
|
||||
"connection manager to {address} finished"
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -272,16 +313,18 @@ impl SendWithoutResponse for Client {
|
||||
trace!("Sending packet to {address}");
|
||||
|
||||
// TODO: optimisation for the future: rather than constantly using legacy encoding,
|
||||
// once we're addressing by node_id (and thus have full node info here),
|
||||
// we could simply infer supported encoding based on their version
|
||||
// use the mix packet type / flags to pick encoding per packet
|
||||
let framed_packet =
|
||||
FramedNymPacket::from_mix_packet(packet, self.config.use_legacy_packet_encoding);
|
||||
|
||||
let Some(sender) = self.active_connections.get_mut(&address) else {
|
||||
// there was never a connection to begin with
|
||||
debug!("establishing initial connection to {address}");
|
||||
// it's not a 'big' error, but we did not manage to send the packet, but queue the packet
|
||||
// for sending for as soon as the connection is created
|
||||
debug!(
|
||||
event = "mixclient.try_send",
|
||||
peer = %address,
|
||||
result = "not_connected",
|
||||
"establishing initial connection to {address}"
|
||||
);
|
||||
self.make_connection(address, framed_packet);
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::NotConnected,
|
||||
@@ -289,15 +332,24 @@ impl SendWithoutResponse for Client {
|
||||
));
|
||||
};
|
||||
|
||||
let channel_capacity = sender.channel.max_capacity();
|
||||
let channel_available = sender.channel.capacity();
|
||||
let channel_used = channel_capacity - channel_available;
|
||||
|
||||
let sending_res = sender.channel.try_send(framed_packet);
|
||||
drop(sender);
|
||||
|
||||
sending_res.map_err(|err| {
|
||||
match err {
|
||||
TrySendError::Full(_) => {
|
||||
debug!("Connection to {address} seems to not be able to handle all the traffic - dropping the current packet");
|
||||
// it's not a 'big' error, but we did not manage to send the packet
|
||||
// if the queue is full, we can't really do anything but to drop the packet
|
||||
warn!(
|
||||
event = "mixclient.try_send",
|
||||
peer = %address,
|
||||
result = "full_dropped",
|
||||
channel_capacity,
|
||||
channel_used,
|
||||
"dropping packet: connection buffer to {address} is full ({channel_used}/{channel_capacity})"
|
||||
);
|
||||
io::Error::new(
|
||||
io::ErrorKind::WouldBlock,
|
||||
"connection queue is full",
|
||||
@@ -305,11 +357,13 @@ impl SendWithoutResponse for Client {
|
||||
}
|
||||
TrySendError::Closed(dropped) => {
|
||||
debug!(
|
||||
"Connection to {address} seems to be dead. attempting to re-establish it...",
|
||||
event = "mixclient.try_send",
|
||||
peer = %address,
|
||||
result = "closed_reconnecting",
|
||||
channel_capacity,
|
||||
channel_used,
|
||||
"connection to {address} dead, attempting re-establishment"
|
||||
);
|
||||
|
||||
// it's not a 'big' error, but we did not manage to send the packet, but queue
|
||||
// it up to send it as soon as the connection is re-established
|
||||
self.make_connection(address, dropped);
|
||||
io::Error::new(
|
||||
io::ErrorKind::ConnectionAborted,
|
||||
|
||||
@@ -20,10 +20,10 @@ use nym_api_requests::ecash::{
|
||||
};
|
||||
use nym_api_requests::models::{
|
||||
ApiHealthResponse, GatewayCoreStatusResponse, HistoricalPerformanceResponse,
|
||||
MixnodeCoreStatusResponse, NymNodeDescriptionV1,
|
||||
MixnodeCoreStatusResponse, NymNodeDescriptionV1, NymNodeDescriptionV2,
|
||||
};
|
||||
use nym_api_requests::nym_nodes::{
|
||||
NodesByAddressesResponse, SemiSkimmedNodesWithMetadata, SkimmedNode, SkimmedNodesWithMetadata,
|
||||
NodesByAddressesResponse, SemiSkimmedNodesWithMetadata, SkimmedNodeV1, SkimmedNodesWithMetadata,
|
||||
};
|
||||
use nym_coconut_dkg_common::types::EpochId;
|
||||
use nym_http_api_client::UserAgent;
|
||||
@@ -273,18 +273,18 @@ impl<C, S> Client<C, S> {
|
||||
Ok(history)
|
||||
}
|
||||
|
||||
// #[deprecated(note = "use get_all_cached_described_nodes_v2 instead")]
|
||||
#[deprecated(note = "use get_all_cached_described_nodes_v2 instead")]
|
||||
pub async fn get_all_cached_described_nodes(
|
||||
&self,
|
||||
) -> Result<Vec<NymNodeDescriptionV1>, ValidatorClientError> {
|
||||
Ok(self.nym_api.get_all_described_nodes().await?)
|
||||
}
|
||||
|
||||
// pub async fn get_all_cached_described_nodes_v2(
|
||||
// &self,
|
||||
// ) -> Result<Vec<NymNodeDescriptionV2>, ValidatorClientError> {
|
||||
// Ok(self.nym_api.get_all_described_nodes_v2().await?)
|
||||
// }
|
||||
pub async fn get_all_cached_described_nodes_v2(
|
||||
&self,
|
||||
) -> Result<Vec<NymNodeDescriptionV2>, ValidatorClientError> {
|
||||
Ok(self.nym_api.get_all_described_nodes_v2().await?)
|
||||
}
|
||||
|
||||
pub async fn get_all_cached_bonded_nym_nodes(
|
||||
&self,
|
||||
@@ -354,12 +354,12 @@ impl NymApiClient {
|
||||
}
|
||||
|
||||
#[deprecated(note = "use get_all_basic_active_mixing_assigned_nodes instead")]
|
||||
pub async fn get_basic_mixnodes(&self) -> Result<Vec<SkimmedNode>, ValidatorClientError> {
|
||||
pub async fn get_basic_mixnodes(&self) -> Result<Vec<SkimmedNodeV1>, ValidatorClientError> {
|
||||
Ok(self.nym_api.get_basic_mixnodes().await?.nodes)
|
||||
}
|
||||
|
||||
#[deprecated(note = "use get_all_basic_entry_assigned_nodes instead")]
|
||||
pub async fn get_basic_gateways(&self) -> Result<Vec<SkimmedNode>, ValidatorClientError> {
|
||||
pub async fn get_basic_gateways(&self) -> Result<Vec<SkimmedNodeV1>, ValidatorClientError> {
|
||||
Ok(self.nym_api.get_basic_gateways().await?.nodes)
|
||||
}
|
||||
|
||||
@@ -372,7 +372,7 @@ impl NymApiClient {
|
||||
#[deprecated(note = "use get_all_basic_entry_assigned_nodes_with_metadata instead")]
|
||||
pub async fn get_all_basic_entry_assigned_nodes(
|
||||
&self,
|
||||
) -> Result<Vec<SkimmedNode>, ValidatorClientError> {
|
||||
) -> Result<Vec<SkimmedNodeV1>, ValidatorClientError> {
|
||||
self.get_all_basic_entry_assigned_nodes_with_metadata()
|
||||
.await
|
||||
.map(|res| res.nodes)
|
||||
@@ -389,7 +389,7 @@ impl NymApiClient {
|
||||
#[deprecated(note = "use get_all_basic_active_mixing_assigned_nodes_with_metadata instead")]
|
||||
pub async fn get_all_basic_active_mixing_assigned_nodes(
|
||||
&self,
|
||||
) -> Result<Vec<SkimmedNode>, ValidatorClientError> {
|
||||
) -> Result<Vec<SkimmedNodeV1>, ValidatorClientError> {
|
||||
self.get_all_basic_active_mixing_assigned_nodes_with_metadata()
|
||||
.await
|
||||
.map(|res| res.nodes)
|
||||
@@ -406,7 +406,7 @@ impl NymApiClient {
|
||||
#[deprecated(note = "use get_all_basic_mixing_capable_nodes_with_metadata instead")]
|
||||
pub async fn get_all_basic_mixing_capable_nodes(
|
||||
&self,
|
||||
) -> Result<Vec<SkimmedNode>, ValidatorClientError> {
|
||||
) -> Result<Vec<SkimmedNodeV1>, ValidatorClientError> {
|
||||
self.get_all_basic_mixing_capable_nodes_with_metadata()
|
||||
.await
|
||||
.map(|res| res.nodes)
|
||||
@@ -420,7 +420,7 @@ impl NymApiClient {
|
||||
|
||||
/// retrieve basic information for all bonded nodes on the network
|
||||
#[deprecated(note = "use get_all_basic_nodes_with_metadata instead")]
|
||||
pub async fn get_all_basic_nodes(&self) -> Result<Vec<SkimmedNode>, ValidatorClientError> {
|
||||
pub async fn get_all_basic_nodes(&self) -> Result<Vec<SkimmedNodeV1>, ValidatorClientError> {
|
||||
self.get_all_basic_nodes_with_metadata()
|
||||
.await
|
||||
.map(|res| res.nodes)
|
||||
@@ -473,7 +473,7 @@ impl NymApiClient {
|
||||
Ok(self.nym_api.health().await?)
|
||||
}
|
||||
|
||||
// #[deprecated(note = "use .get_all_described_nodes_v2 instead")]
|
||||
#[deprecated(note = "use .get_all_described_nodes_v2 instead")]
|
||||
pub async fn get_all_described_nodes(
|
||||
&self,
|
||||
) -> Result<Vec<NymNodeDescriptionV1>, ValidatorClientError> {
|
||||
@@ -495,29 +495,29 @@ impl NymApiClient {
|
||||
Ok(descriptions)
|
||||
}
|
||||
|
||||
// pub async fn get_all_described_nodes_v2(
|
||||
// &self,
|
||||
// ) -> Result<Vec<NymNodeDescriptionV2>, ValidatorClientError> {
|
||||
// // TODO: deal with paging in macro or some helper function or something, because it's the same pattern everywhere
|
||||
// let mut page = 0;
|
||||
// let mut descriptions = Vec::new();
|
||||
//
|
||||
// loop {
|
||||
// let mut res = self
|
||||
// .nym_api
|
||||
// .get_nodes_described_v2(Some(page), None)
|
||||
// .await?;
|
||||
//
|
||||
// descriptions.append(&mut res.data);
|
||||
// if descriptions.len() < res.pagination.total {
|
||||
// page += 1
|
||||
// } else {
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// Ok(descriptions)
|
||||
// }
|
||||
pub async fn get_all_described_nodes_v2(
|
||||
&self,
|
||||
) -> Result<Vec<NymNodeDescriptionV2>, ValidatorClientError> {
|
||||
// TODO: deal with paging in macro or some helper function or something, because it's the same pattern everywhere
|
||||
let mut page = 0;
|
||||
let mut descriptions = Vec::new();
|
||||
|
||||
loop {
|
||||
let mut res = self
|
||||
.nym_api
|
||||
.get_nodes_described_v2(Some(page), None)
|
||||
.await?;
|
||||
|
||||
descriptions.append(&mut res.data);
|
||||
if descriptions.len() < res.pagination.total {
|
||||
page += 1
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(descriptions)
|
||||
}
|
||||
|
||||
pub async fn get_all_bonded_nym_nodes(
|
||||
&self,
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
use crate::nym_api::error::NymAPIError;
|
||||
use crate::nym_api::routes::{ecash, CORE_STATUS_COUNT, SINCE_ARG};
|
||||
use crate::nym_nodes::SkimmedNodesWithMetadata;
|
||||
use crate::ValidatorClientError;
|
||||
use async_trait::async_trait;
|
||||
use nym_api_requests::ecash::models::{
|
||||
AggregatedCoinIndicesSignatureResponse, AggregatedExpirationDateSignatureResponse,
|
||||
@@ -17,14 +18,17 @@ use nym_api_requests::ecash::VerificationKeyResponse;
|
||||
use nym_api_requests::models::{
|
||||
AnnotationResponse, ApiHealthResponse, BinaryBuildInformationOwned, ChainBlocksStatusResponse,
|
||||
ChainStatusResponse, KeyRotationInfoResponse, NodePerformanceResponse, NodeRefreshBody,
|
||||
NymNodeDescriptionV1, PerformanceHistoryResponse, RewardedSetResponse,
|
||||
NymNodeDescriptionV1, NymNodeDescriptionV2, PerformanceHistoryResponse, RewardedSetResponse,
|
||||
SignerInformationResponse,
|
||||
};
|
||||
use nym_api_requests::nym_nodes::{
|
||||
NodesByAddressesRequestBody, NodesByAddressesResponse, PaginatedCachedNodesResponseV1,
|
||||
PaginatedCachedNodesResponseV2,
|
||||
};
|
||||
use nym_api_requests::pagination::PaginatedResponse;
|
||||
use nym_http_api_client::{ApiClient, NO_PARAMS};
|
||||
use nym_mixnet_contract_common::{IdentityKeyRef, NodeId, NymNodeDetails};
|
||||
use std::net::IpAddr;
|
||||
use time::format_description::BorrowedFormatItem;
|
||||
use time::Date;
|
||||
use tracing::instrument;
|
||||
|
||||
pub use nym_api_requests::{
|
||||
ecash::{
|
||||
models::SpentCredentialsResponse, BlindSignRequestBody, BlindedSignatureResponse,
|
||||
@@ -36,17 +40,14 @@ pub use nym_api_requests::{
|
||||
MixnodeCoreStatusResponse, MixnodeStatusReportResponse, MixnodeStatusResponse,
|
||||
MixnodeUptimeHistoryResponse, StakeSaturationResponse, UptimeResponse,
|
||||
},
|
||||
nym_nodes::{CachedNodesResponse, SemiSkimmedNode, SemiSkimmedNodesWithMetadata, SkimmedNode},
|
||||
nym_nodes::{
|
||||
CachedNodesResponse, NodesByAddressesRequestBody, NodesByAddressesResponse,
|
||||
PaginatedCachedNodesResponseV1, PaginatedCachedNodesResponseV2, SemiSkimmedNodeV1,
|
||||
SemiSkimmedNodeV3, SemiSkimmedNodesWithMetadata, SkimmedNodeV1,
|
||||
},
|
||||
NymNetworkDetailsResponse,
|
||||
};
|
||||
use nym_http_api_client::{ApiClient, NO_PARAMS};
|
||||
use nym_mixnet_contract_common::{IdentityKeyRef, NodeId, NymNodeDetails};
|
||||
use std::net::IpAddr;
|
||||
use time::format_description::BorrowedFormatItem;
|
||||
use time::Date;
|
||||
use tracing::instrument;
|
||||
|
||||
use crate::ValidatorClientError;
|
||||
pub use nym_coconut_dkg_common::types::EpochId;
|
||||
|
||||
pub mod error;
|
||||
@@ -117,7 +118,7 @@ pub trait NymApiClientExt: ApiClient {
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip_all)]
|
||||
// #[deprecated(note = "use .get_nodes_described_v2 instead")]
|
||||
#[deprecated(note = "use .get_nodes_described_v2 instead")]
|
||||
async fn get_nodes_described(
|
||||
&self,
|
||||
page: Option<u32>,
|
||||
@@ -144,32 +145,32 @@ pub trait NymApiClientExt: ApiClient {
|
||||
.await
|
||||
}
|
||||
|
||||
// #[tracing::instrument(level = "debug", skip_all)]
|
||||
// async fn get_nodes_described_v2(
|
||||
// &self,
|
||||
// page: Option<u32>,
|
||||
// per_page: Option<u32>,
|
||||
// ) -> Result<PaginatedResponse<NymNodeDescriptionV2>, NymAPIError> {
|
||||
// let mut params = Vec::new();
|
||||
//
|
||||
// if let Some(page) = page {
|
||||
// params.push(("page", page.to_string()))
|
||||
// }
|
||||
//
|
||||
// if let Some(per_page) = per_page {
|
||||
// params.push(("per_page", per_page.to_string()))
|
||||
// }
|
||||
//
|
||||
// self.get_json(
|
||||
// &[
|
||||
// routes::V2_API_VERSION,
|
||||
// routes::NYM_NODES_ROUTES,
|
||||
// routes::NYM_NODES_DESCRIBED,
|
||||
// ],
|
||||
// ¶ms,
|
||||
// )
|
||||
// .await
|
||||
// }
|
||||
#[tracing::instrument(level = "debug", skip_all)]
|
||||
async fn get_nodes_described_v2(
|
||||
&self,
|
||||
page: Option<u32>,
|
||||
per_page: Option<u32>,
|
||||
) -> Result<PaginatedResponse<NymNodeDescriptionV2>, NymAPIError> {
|
||||
let mut params = Vec::new();
|
||||
|
||||
if let Some(page) = page {
|
||||
params.push(("page", page.to_string()))
|
||||
}
|
||||
|
||||
if let Some(per_page) = per_page {
|
||||
params.push(("per_page", per_page.to_string()))
|
||||
}
|
||||
|
||||
self.get_json(
|
||||
&[
|
||||
routes::V2_API_VERSION,
|
||||
routes::NYM_NODES_ROUTES,
|
||||
routes::NYM_NODES_DESCRIBED,
|
||||
],
|
||||
¶ms,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn get_current_rewarded_set(&self) -> Result<RewardedSetResponse, NymAPIError> {
|
||||
self.get_rewarded_set().await
|
||||
@@ -302,8 +303,8 @@ pub trait NymApiClientExt: ApiClient {
|
||||
Ok(SkimmedNodesWithMetadata::new(nodes, metadata))
|
||||
}
|
||||
|
||||
// #[deprecated(note = "use .get_all_described_nodes_v2 instead")]
|
||||
// #[allow(deprecated)]
|
||||
#[deprecated(note = "use .get_all_described_nodes_v2 instead")]
|
||||
#[allow(deprecated)]
|
||||
async fn get_all_described_nodes(&self) -> Result<Vec<NymNodeDescriptionV1>, NymAPIError> {
|
||||
// TODO: deal with paging in macro or some helper function or something, because it's the same pattern everywhere
|
||||
let mut page = 0;
|
||||
@@ -323,24 +324,24 @@ pub trait NymApiClientExt: ApiClient {
|
||||
Ok(descriptions)
|
||||
}
|
||||
|
||||
// async fn (&self) -> Result<Vec<NymNodeDescriptionV2>, NymAPIError> {
|
||||
// // TODO: deal with paging in macro or some helper function or something, because it's the same pattern everywhere
|
||||
// let mut page = 0;
|
||||
// let mut descriptions = Vec::new();
|
||||
//
|
||||
// loop {
|
||||
// let mut res = self.get_nodes_described_v2(Some(page), None).await?;
|
||||
//
|
||||
// descriptions.append(&mut res.data);
|
||||
// if descriptions.len() < res.pagination.total {
|
||||
// page += 1
|
||||
// } else {
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// Ok(descriptions)
|
||||
// }
|
||||
async fn get_all_described_nodes_v2(&self) -> Result<Vec<NymNodeDescriptionV2>, NymAPIError> {
|
||||
// TODO: deal with paging in macro or some helper function or something, because it's the same pattern everywhere
|
||||
let mut page = 0;
|
||||
let mut descriptions = Vec::new();
|
||||
|
||||
loop {
|
||||
let mut res = self.get_nodes_described_v2(Some(page), None).await?;
|
||||
|
||||
descriptions.append(&mut res.data);
|
||||
if descriptions.len() < res.pagination.total {
|
||||
page += 1
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(descriptions)
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip_all)]
|
||||
async fn get_nym_nodes(
|
||||
@@ -390,7 +391,7 @@ pub trait NymApiClientExt: ApiClient {
|
||||
|
||||
#[deprecated]
|
||||
#[tracing::instrument(level = "debug", skip_all)]
|
||||
async fn get_basic_mixnodes(&self) -> Result<CachedNodesResponse<SkimmedNode>, NymAPIError> {
|
||||
async fn get_basic_mixnodes(&self) -> Result<CachedNodesResponse<SkimmedNodeV1>, NymAPIError> {
|
||||
self.get_json(
|
||||
&[
|
||||
routes::V1_API_VERSION,
|
||||
@@ -406,7 +407,7 @@ pub trait NymApiClientExt: ApiClient {
|
||||
|
||||
#[deprecated]
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
async fn get_basic_gateways(&self) -> Result<CachedNodesResponse<SkimmedNode>, NymAPIError> {
|
||||
async fn get_basic_gateways(&self) -> Result<CachedNodesResponse<SkimmedNodeV1>, NymAPIError> {
|
||||
self.get_json(
|
||||
&[
|
||||
routes::V1_API_VERSION,
|
||||
@@ -443,7 +444,7 @@ pub trait NymApiClientExt: ApiClient {
|
||||
page: Option<u32>,
|
||||
per_page: Option<u32>,
|
||||
use_bincode: bool,
|
||||
) -> Result<PaginatedCachedNodesResponseV1<SkimmedNode>, NymAPIError> {
|
||||
) -> Result<PaginatedCachedNodesResponseV1<SkimmedNodeV1>, NymAPIError> {
|
||||
let mut params = Vec::new();
|
||||
|
||||
if no_legacy {
|
||||
@@ -485,7 +486,7 @@ pub trait NymApiClientExt: ApiClient {
|
||||
page: Option<u32>,
|
||||
per_page: Option<u32>,
|
||||
use_bincode: bool,
|
||||
) -> Result<PaginatedCachedNodesResponseV2<SkimmedNode>, NymAPIError> {
|
||||
) -> Result<PaginatedCachedNodesResponseV2<SkimmedNodeV1>, NymAPIError> {
|
||||
let mut params = Vec::new();
|
||||
|
||||
if no_legacy {
|
||||
@@ -527,7 +528,7 @@ pub trait NymApiClientExt: ApiClient {
|
||||
page: Option<u32>,
|
||||
per_page: Option<u32>,
|
||||
use_bincode: bool,
|
||||
) -> Result<PaginatedCachedNodesResponseV1<SkimmedNode>, NymAPIError> {
|
||||
) -> Result<PaginatedCachedNodesResponseV1<SkimmedNodeV1>, NymAPIError> {
|
||||
let mut params = Vec::new();
|
||||
|
||||
if no_legacy {
|
||||
@@ -569,7 +570,7 @@ pub trait NymApiClientExt: ApiClient {
|
||||
page: Option<u32>,
|
||||
per_page: Option<u32>,
|
||||
use_bincode: bool,
|
||||
) -> Result<PaginatedCachedNodesResponseV2<SkimmedNode>, NymAPIError> {
|
||||
) -> Result<PaginatedCachedNodesResponseV2<SkimmedNodeV1>, NymAPIError> {
|
||||
let mut params = Vec::new();
|
||||
|
||||
if no_legacy {
|
||||
@@ -612,7 +613,7 @@ pub trait NymApiClientExt: ApiClient {
|
||||
page: Option<u32>,
|
||||
per_page: Option<u32>,
|
||||
use_bincode: bool,
|
||||
) -> Result<PaginatedCachedNodesResponseV1<SkimmedNode>, NymAPIError> {
|
||||
) -> Result<PaginatedCachedNodesResponseV1<SkimmedNodeV1>, NymAPIError> {
|
||||
let mut params = Vec::new();
|
||||
|
||||
if no_legacy {
|
||||
@@ -654,7 +655,7 @@ pub trait NymApiClientExt: ApiClient {
|
||||
page: Option<u32>,
|
||||
per_page: Option<u32>,
|
||||
use_bincode: bool,
|
||||
) -> Result<PaginatedCachedNodesResponseV2<SkimmedNode>, NymAPIError> {
|
||||
) -> Result<PaginatedCachedNodesResponseV2<SkimmedNodeV1>, NymAPIError> {
|
||||
let mut params = Vec::new();
|
||||
|
||||
if no_legacy {
|
||||
@@ -695,7 +696,7 @@ pub trait NymApiClientExt: ApiClient {
|
||||
page: Option<u32>,
|
||||
per_page: Option<u32>,
|
||||
use_bincode: bool,
|
||||
) -> Result<PaginatedCachedNodesResponseV1<SkimmedNode>, NymAPIError> {
|
||||
) -> Result<PaginatedCachedNodesResponseV1<SkimmedNodeV1>, NymAPIError> {
|
||||
let mut params = Vec::new();
|
||||
|
||||
if no_legacy {
|
||||
@@ -733,7 +734,7 @@ pub trait NymApiClientExt: ApiClient {
|
||||
page: Option<u32>,
|
||||
per_page: Option<u32>,
|
||||
use_bincode: bool,
|
||||
) -> Result<PaginatedCachedNodesResponseV2<SkimmedNode>, NymAPIError> {
|
||||
) -> Result<PaginatedCachedNodesResponseV2<SkimmedNodeV1>, NymAPIError> {
|
||||
let mut params = Vec::new();
|
||||
|
||||
if no_legacy {
|
||||
@@ -770,7 +771,7 @@ pub trait NymApiClientExt: ApiClient {
|
||||
no_legacy: bool,
|
||||
page: Option<u32>,
|
||||
per_page: Option<u32>,
|
||||
) -> Result<PaginatedCachedNodesResponseV2<SemiSkimmedNode>, NymAPIError> {
|
||||
) -> Result<PaginatedCachedNodesResponseV2<SemiSkimmedNodeV1>, NymAPIError> {
|
||||
let mut params = Vec::new();
|
||||
|
||||
if no_legacy {
|
||||
@@ -797,6 +798,21 @@ pub trait NymApiClientExt: ApiClient {
|
||||
.await
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
async fn get_expanded_nodes_v3(
|
||||
&self,
|
||||
use_bincode: bool,
|
||||
) -> Result<PaginatedCachedNodesResponseV2<SemiSkimmedNodeV3>, NymAPIError> {
|
||||
let mut params = Vec::new();
|
||||
|
||||
if use_bincode {
|
||||
params.push(("output", "bincode".to_string()))
|
||||
}
|
||||
|
||||
self.get_response("/v3/unstable/nym-nodes/semi-skimmed", ¶ms)
|
||||
.await
|
||||
}
|
||||
|
||||
#[deprecated]
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
async fn get_mixnode_report(
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
pub const V1_API_VERSION: &str = "v1";
|
||||
pub const V2_API_VERSION: &str = "v2";
|
||||
pub const V3_API_VERSION: &str = "v3";
|
||||
pub const MIXNODES: &str = "mixnodes";
|
||||
pub const GATEWAYS: &str = "gateways";
|
||||
pub const DESCRIBED: &str = "described";
|
||||
|
||||
+1
-1
@@ -130,7 +130,7 @@ pub trait CosmWasmClient: TendermintRpcClient {
|
||||
|
||||
let req = QueryBalanceRequest {
|
||||
address: address.to_string(),
|
||||
denom: search_denom.to_string(),
|
||||
denom: search_denom,
|
||||
};
|
||||
|
||||
let res = self
|
||||
|
||||
@@ -199,6 +199,18 @@ impl NyxdClient<HttpClient, DirectSecp256k1HdWallet> {
|
||||
let wallet = DirectSecp256k1HdWallet::checked_from_mnemonic(prefix, mnemonic)?;
|
||||
Ok(Self::connect_with_signer(config, client, wallet))
|
||||
}
|
||||
|
||||
pub fn connect_with_mnemonic_and_network_details<U>(
|
||||
endpoint: U,
|
||||
network_details: NymNetworkDetails,
|
||||
mnemonic: bip39::Mnemonic,
|
||||
) -> Result<DirectSigningHttpRpcNyxdClient, NyxdError>
|
||||
where
|
||||
U: TryInto<HttpClientUrl, Error = TendermintRpcError>,
|
||||
{
|
||||
let config = Config::try_from_nym_network_details(&network_details)?;
|
||||
Self::connect_with_mnemonic(config, endpoint, mnemonic)
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
|
||||
@@ -14,7 +14,7 @@ pub struct Args {
|
||||
}
|
||||
|
||||
pub async fn query(args: Args, client: &QueryClientWithNyxd) {
|
||||
match client.get_all_cached_described_nodes().await {
|
||||
match client.get_all_cached_described_nodes_v2().await {
|
||||
Ok(res) => match args.identity_key {
|
||||
Some(identity_key) => {
|
||||
let node = res.iter().find(|node| {
|
||||
|
||||
@@ -14,7 +14,7 @@ pub struct Args {
|
||||
}
|
||||
|
||||
pub async fn query(args: Args, client: &QueryClientWithNyxd) {
|
||||
match client.get_all_cached_described_nodes().await {
|
||||
match client.get_all_cached_described_nodes_v2().await {
|
||||
Ok(res) => match args.identity_key {
|
||||
Some(identity_key) => {
|
||||
let node = res.iter().find(|node| {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
// Copyright 2022-2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
#![allow(clippy::derivable_impls)]
|
||||
// MAX: surpressing warning for the moment, will be dealt with in a different PR (TODO)
|
||||
use cosmwasm_schema::cw_serde;
|
||||
use std::fmt::{Display, Formatter};
|
||||
use std::str::FromStr;
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
use rand::Rng;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt::Debug;
|
||||
use strum::IntoEnumIterator as _;
|
||||
use thiserror::Error;
|
||||
use time::{Date, OffsetDateTime};
|
||||
|
||||
@@ -315,6 +316,10 @@ impl TicketType {
|
||||
_ => Err(UnknownTicketType),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn exposed_iter() -> impl Iterator<Item = TicketType> {
|
||||
TicketType::iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<TicketType> for TicketTypeRepr {
|
||||
|
||||
@@ -21,10 +21,13 @@ generic-array = { workspace = true, optional = true }
|
||||
hkdf = { workspace = true, optional = true }
|
||||
hmac = { workspace = true, optional = true }
|
||||
jwt-simple = { workspace = true, optional = true }
|
||||
libcrux-psq = { workspace = true, optional = true }
|
||||
libcrux-curve25519 = { workspace = true, optional = true }
|
||||
cipher = { workspace = true, optional = true }
|
||||
x25519-dalek = { workspace = true, features = ["static_secrets"], optional = true }
|
||||
ed25519-dalek = { workspace = true, features = ["rand_core"], optional = true }
|
||||
rand = { workspace = true, optional = true }
|
||||
rand09 = { workspace = true, optional = true }
|
||||
serde_bytes = { workspace = true, optional = true }
|
||||
serde = { workspace = true, features = ["derive"], optional = true }
|
||||
sha2 = { workspace = true, optional = true }
|
||||
@@ -39,17 +42,18 @@ nym-pemstore = { workspace = true }
|
||||
[dev-dependencies]
|
||||
anyhow = { workspace = true }
|
||||
rand_chacha = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
nym-test-utils = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
|
||||
|
||||
[features]
|
||||
default = []
|
||||
aead = ["dep:aead", "aead/std", "aes-gcm-siv", "generic-array"]
|
||||
naive_jwt = ["asymmetric", "jwt-simple"]
|
||||
libcrux_x25519 = ["libcrux-psq", "libcrux-curve25519"]
|
||||
serde = ["dep:serde", "serde_bytes", "ed25519-dalek/serde", "x25519-dalek/serde"]
|
||||
asymmetric = ["x25519-dalek", "ed25519-dalek", "curve25519-dalek", "sha2", "zeroize"]
|
||||
hashing = ["blake3", "digest", "hkdf", "hmac", "generic-array", "sha2", "zeroize"]
|
||||
hashing = ["blake3", "digest", "hkdf", "hmac", "generic-array", "sha2", "zeroize", "rand09"]
|
||||
stream_cipher = ["aes", "ctr", "cipher", "generic-array"]
|
||||
sphinx = ["nym-sphinx-types", "nym-sphinx-types/sphinx"]
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user