Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| bd077f0a73 |
@@ -5,28 +5,21 @@ on:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: arc-ubuntu-20.04
|
runs-on: ubuntu-20.04-16-core
|
||||||
defaults:
|
|
||||||
run:
|
|
||||||
working-directory: documentation/docs
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- name: Install Dependencies (Linux)
|
- name: Install Dependencies (Linux)
|
||||||
run: sudo apt-get update && sudo apt-get install -y build-essential curl wget libssl-dev libudev-dev squashfs-tools protobuf-compiler git python3 && sudo apt-get update --fix-missing
|
run: sudo apt-get update && sudo apt-get install -y build-essential curl wget libssl-dev libudev-dev squashfs-tools protobuf-compiler git python3 && sudo apt-get update --fix-missing
|
||||||
- name: Install pip3
|
- name: Install pip3
|
||||||
run: sudo apt install -y python3-pip
|
run: sudo apt install -y python3-pip
|
||||||
- name: Install Python3 modules
|
- name: Install Python3 modules
|
||||||
run: sudo pip3 install pandas tabulate
|
run: sudo pip3 install pandas tabulate
|
||||||
- name: Install rsync
|
- name: Install rsync
|
||||||
run: sudo apt-get install rsync
|
run: sudo apt-get install rsync
|
||||||
- uses: rlespinasse/github-slug-action@v3.x
|
- uses: rlespinasse/github-slug-action@v3.x
|
||||||
- name: Setup pnpm
|
|
||||||
uses: pnpm/action-setup@v4.0.0
|
|
||||||
with:
|
|
||||||
version: 9
|
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 20
|
node-version: 18
|
||||||
- name: Install Rust stable
|
- name: Install Rust stable
|
||||||
uses: actions-rs/toolchain@v1
|
uses: actions-rs/toolchain@v1
|
||||||
with:
|
with:
|
||||||
@@ -36,13 +29,33 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
command: build
|
command: build
|
||||||
args: --workspace --release
|
args: --workspace --release
|
||||||
|
- name: Install mdbook and plugins
|
||||||
|
run: cd documentation && ./install_mdbook_deps.sh
|
||||||
|
- name: Remove existing Nym config directory (`~/.nym/`)
|
||||||
|
run: cd documentation && ./remove_existing_config.sh
|
||||||
|
continue-on-error: false
|
||||||
|
# This is the original flow
|
||||||
|
# - name: Build all projects in documentation/ & move to ~/dist/docs/
|
||||||
|
# run: cd documentation && ./build_all_to_dist.sh
|
||||||
|
|
||||||
- name: Install project dependencies
|
# This is a workaround replacement which builds on the last working commit b332a6b55668f60988e36961f3f62a794ba82ddb and then on current branch
|
||||||
run: pnpm i
|
- name: Save current branch to ~/current_branch
|
||||||
- name: Build project
|
run: git rev-parse --abbrev-ref HEAD > ~/current_branch
|
||||||
run: pnpm run build
|
- name: Git pull, reset & switch to b332a6b55668f60988e36961f3f62a794ba82ddb
|
||||||
- name: Move files to /dist/
|
run: git pull && git reset --hard && git checkout b332a6b55668f60988e36961f3f62a794ba82ddb
|
||||||
run: ../scripts/move-to-dist.sh
|
- name: Build all projects in documentation/ & move to ~/dist/docs/ from b332a6b55668f60988e36961f3f62a794ba82ddb
|
||||||
|
run: cd documentation && ./build_all_to_dist.sh
|
||||||
|
|
||||||
|
- name: Switch to current branch
|
||||||
|
run: git checkout $echo "$(cat ~/current_branch)"
|
||||||
|
- name: Build all projects in documentation/ & move to ~/dist/docs/ on current branch
|
||||||
|
run: cd documentation && ./build_all_to_dist.sh && rm ~/current_branch
|
||||||
|
|
||||||
|
# End of replacemet
|
||||||
|
|
||||||
|
- name: Post process
|
||||||
|
run: cd documentation && ./post_process.sh
|
||||||
|
continue-on-error: false
|
||||||
|
|
||||||
- name: Create Vercel project file
|
- name: Create Vercel project file
|
||||||
uses: mobiledevops/secret-to-file-action@v1
|
uses: mobiledevops/secret-to-file-action@v1
|
||||||
@@ -86,3 +99,24 @@ jobs:
|
|||||||
run: vercel deploy --prebuilt --prod --token=${{ secrets.VERCEL_TOKEN }}
|
run: vercel deploy --prebuilt --prod --token=${{ secrets.VERCEL_TOKEN }}
|
||||||
working-directory: dist/docs
|
working-directory: dist/docs
|
||||||
continue-on-error: false
|
continue-on-error: false
|
||||||
|
|
||||||
|
- name: Matrix - Node Install
|
||||||
|
run: npm install
|
||||||
|
working-directory: .github/workflows/support-files
|
||||||
|
- name: Matrix - Send Notification
|
||||||
|
env:
|
||||||
|
NYM_NOTIFICATION_KIND: cd-docs
|
||||||
|
NYM_PROJECT_NAME: "Docs CD"
|
||||||
|
NYM_CI_WWW_BASE: "${{ secrets.NYM_CD_WWW_BASE }}"
|
||||||
|
NYM_CI_WWW_LOCATION: "${{ env.GITHUB_REF_SLUG }}"
|
||||||
|
GIT_COMMIT_MESSAGE: "${{ github.event.head_commit.message }}"
|
||||||
|
GIT_BRANCH: "${GITHUB_REF##*/}"
|
||||||
|
MATRIX_SERVER: "${{ secrets.MATRIX_SERVER }}"
|
||||||
|
MATRIX_ROOM: "${{ secrets.MATRIX_ROOM_DOCS }}"
|
||||||
|
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
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
name: ci-build-ts
|
name: ci-build-ts
|
||||||
|
|
||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
|
||||||
pull_request:
|
pull_request:
|
||||||
paths:
|
paths:
|
||||||
- "ts-packages/**"
|
- "ts-packages/**"
|
||||||
@@ -10,7 +9,7 @@ on:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: arc-ubuntu-20.04
|
runs-on: ubuntu-20.04-16-core
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- name: Install rsync
|
- name: Install rsync
|
||||||
@@ -46,3 +45,23 @@ jobs:
|
|||||||
REMOTE_USER: ${{ secrets.CI_WWW_REMOTE_USER }}
|
REMOTE_USER: ${{ secrets.CI_WWW_REMOTE_USER }}
|
||||||
TARGET: ${{ secrets.CI_WWW_REMOTE_TARGET }}/ts-${{ env.GITHUB_REF_SLUG }}-example
|
TARGET: ${{ secrets.CI_WWW_REMOTE_TARGET }}/ts-${{ env.GITHUB_REF_SLUG }}-example
|
||||||
EXCLUDE: "/dist/, /node_modules/"
|
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: ts-packages
|
||||||
|
NYM_PROJECT_NAME: "ts-packages"
|
||||||
|
NYM_CI_WWW_BASE: "${{ secrets.NYM_CI_WWW_BASE }}"
|
||||||
|
NYM_CI_WWW_LOCATION: "ts-${{ 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
|
||||||
|
|||||||
@@ -15,13 +15,30 @@ on:
|
|||||||
type: boolean
|
type: boolean
|
||||||
schedule:
|
schedule:
|
||||||
- cron: "14 0 * * *"
|
- cron: "14 0 * * *"
|
||||||
|
pull_request:
|
||||||
|
paths:
|
||||||
|
- "clients/**"
|
||||||
|
- "common/**"
|
||||||
|
- "explorer-api/**"
|
||||||
|
- "gateway/**"
|
||||||
|
- "integrations/**"
|
||||||
|
- "mixnode/**"
|
||||||
|
- "nym-api/**"
|
||||||
|
- "nym-node/**"
|
||||||
|
- "nym-outfox/**"
|
||||||
|
- "nym-validator-rewarder/**"
|
||||||
|
- "sdk/rust/nym-sdk/**"
|
||||||
|
- "service-providers/**"
|
||||||
|
- "tools/**"
|
||||||
|
- "nymvisor/**"
|
||||||
|
- ".github/workflows/ci-build-upload-binaries.yml"
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
publish-nym:
|
publish-nym:
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
platform: [ arc-ubuntu-22.04 ]
|
platform: [ arc-ubuntu-20.04 ]
|
||||||
|
|
||||||
runs-on: ${{ matrix.platform }}
|
runs-on: ${{ matrix.platform }}
|
||||||
env:
|
env:
|
||||||
@@ -39,7 +56,7 @@ jobs:
|
|||||||
echo $OUTPUT_DIR
|
echo $OUTPUT_DIR
|
||||||
|
|
||||||
- name: Install Dependencies (Linux)
|
- name: Install Dependencies (Linux)
|
||||||
run: sudo apt-get update && sudo apt-get -y install libudev-dev
|
run: sudo apt update && sudo apt install libudev-dev
|
||||||
|
|
||||||
- name: Sets env vars for tokio if set in manual dispatch inputs
|
- name: Sets env vars for tokio if set in manual dispatch inputs
|
||||||
run: |
|
run: |
|
||||||
@@ -79,7 +96,6 @@ jobs:
|
|||||||
target/release/nym-socks5-client
|
target/release/nym-socks5-client
|
||||||
target/release/nym-api
|
target/release/nym-api
|
||||||
target/release/nym-network-requester
|
target/release/nym-network-requester
|
||||||
target/release/nym-data-observatory
|
|
||||||
target/release/nym-cli
|
target/release/nym-cli
|
||||||
target/release/nymvisor
|
target/release/nymvisor
|
||||||
target/release/nym-node
|
target/release/nym-node
|
||||||
@@ -97,7 +113,6 @@ jobs:
|
|||||||
cp target/release/nym-socks5-client $OUTPUT_DIR
|
cp target/release/nym-socks5-client $OUTPUT_DIR
|
||||||
cp target/release/nym-api $OUTPUT_DIR
|
cp target/release/nym-api $OUTPUT_DIR
|
||||||
cp target/release/nym-network-requester $OUTPUT_DIR
|
cp target/release/nym-network-requester $OUTPUT_DIR
|
||||||
cp target/release/nym-data-observatory $OUTPUT_DIR
|
|
||||||
cp target/release/nymvisor $OUTPUT_DIR
|
cp target/release/nymvisor $OUTPUT_DIR
|
||||||
cp target/release/nym-node $OUTPUT_DIR
|
cp target/release/nym-node $OUTPUT_DIR
|
||||||
cp target/release/nym-cli $OUTPUT_DIR
|
cp target/release/nym-cli $OUTPUT_DIR
|
||||||
|
|||||||
@@ -1,41 +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-ubuntu-22.04
|
|
||||||
env:
|
|
||||||
CARGO_TERM_COLOR: always
|
|
||||||
steps:
|
|
||||||
- name: Check out repository code
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Install Rust toolchain
|
|
||||||
uses: actions-rs/toolchain@v1
|
|
||||||
with:
|
|
||||||
profile: minimal
|
|
||||||
toolchain: stable
|
|
||||||
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,6 @@ on:
|
|||||||
- 'nym-api/**'
|
- 'nym-api/**'
|
||||||
- 'nym-node/**'
|
- 'nym-node/**'
|
||||||
- 'nym-outfox/**'
|
- 'nym-outfox/**'
|
||||||
- 'nym-data-observatory/**'
|
|
||||||
- 'nym-validator-rewarder/**'
|
- 'nym-validator-rewarder/**'
|
||||||
- 'tools/**'
|
- 'tools/**'
|
||||||
- 'wasm/**'
|
- 'wasm/**'
|
||||||
@@ -30,7 +29,7 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
os: [ arc-ubuntu-20.04, custom-runner-mac-m1 ]
|
os: [arc-ubuntu-20.04, custom-runner-mac-m1]
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
env:
|
env:
|
||||||
CARGO_TERM_COLOR: always
|
CARGO_TERM_COLOR: always
|
||||||
@@ -57,17 +56,19 @@ jobs:
|
|||||||
command: fmt
|
command: fmt
|
||||||
args: --all -- --check
|
args: --all -- --check
|
||||||
|
|
||||||
- name: Clippy
|
|
||||||
uses: actions-rs/cargo@v1
|
|
||||||
with:
|
|
||||||
command: clippy
|
|
||||||
args: --workspace --all-targets -- -D warnings
|
|
||||||
|
|
||||||
- name: Build all binaries
|
- name: Build all binaries
|
||||||
uses: actions-rs/cargo@v1
|
uses: actions-rs/cargo@v1
|
||||||
with:
|
with:
|
||||||
command: build
|
command: build
|
||||||
|
|
||||||
|
# while disabled by default, this build ensures nothing is broken within
|
||||||
|
# `axum` feature
|
||||||
|
- name: Build with `axum` feature
|
||||||
|
uses: actions-rs/cargo@v1
|
||||||
|
with:
|
||||||
|
command: build
|
||||||
|
args: --features axum
|
||||||
|
|
||||||
- name: Build all examples
|
- name: Build all examples
|
||||||
if: contains(matrix.os, 'ubuntu')
|
if: contains(matrix.os, 'ubuntu')
|
||||||
uses: actions-rs/cargo@v1
|
uses: actions-rs/cargo@v1
|
||||||
@@ -88,3 +89,17 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
command: test
|
command: test
|
||||||
args: --workspace -- --ignored
|
args: --workspace -- --ignored
|
||||||
|
|
||||||
|
- name: Annotate with clippy checks
|
||||||
|
if: contains(matrix.os, 'ubuntu')
|
||||||
|
uses: actions-rs/clippy-check@v1
|
||||||
|
continue-on-error: true
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
args: --workspace
|
||||||
|
|
||||||
|
- name: Clippy
|
||||||
|
uses: actions-rs/cargo@v1
|
||||||
|
with:
|
||||||
|
command: clippy
|
||||||
|
args: --workspace --all-targets --features axum -- -D warnings
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ on:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
cargo-deny:
|
cargo-deny:
|
||||||
runs-on: ubuntu-latest
|
runs-on: arc-ubuntu-22.04-dind
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
checks:
|
checks:
|
||||||
@@ -18,8 +18,8 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: EmbarkStudios/cargo-deny-action@v2
|
- uses: EmbarkStudios/cargo-deny-action@v1
|
||||||
with:
|
with:
|
||||||
log-level: warn
|
log-level: warn
|
||||||
command: check ${{ matrix.checks }}
|
command: check ${{ matrix.checks }}
|
||||||
arguments: --all-features
|
argument: --all-features
|
||||||
|
|||||||
@@ -2,5 +2,9 @@
|
|||||||
{
|
{
|
||||||
"rust":"stable",
|
"rust":"stable",
|
||||||
"runOnEvent":"always"
|
"runOnEvent":"always"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rust":"beta",
|
||||||
|
"runOnEvent":"pull_request"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ on:
|
|||||||
jobs:
|
jobs:
|
||||||
check-schema:
|
check-schema:
|
||||||
name: Generate and check schema
|
name: Generate and check schema
|
||||||
runs-on: ubuntu-20.04
|
runs-on: arc-ubuntu-20.04
|
||||||
env:
|
env:
|
||||||
CARGO_TERM_COLOR: always
|
CARGO_TERM_COLOR: always
|
||||||
steps:
|
steps:
|
||||||
|
|||||||
@@ -2,6 +2,11 @@ name: ci-contracts-upload-binaries
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
pull_request:
|
||||||
|
paths:
|
||||||
|
- 'common/**'
|
||||||
|
- 'contracts/**'
|
||||||
|
- '.github/workflows/ci-contracts-upload-binaries.yml'
|
||||||
|
|
||||||
env:
|
env:
|
||||||
NETWORK: mainnet
|
NETWORK: mainnet
|
||||||
@@ -11,7 +16,7 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
platform: [ arc-ubuntu-20.04 ]
|
platform: arc-ubuntu-20.04
|
||||||
|
|
||||||
runs-on: ${{ matrix.platform }}
|
runs-on: ${{ matrix.platform }}
|
||||||
env:
|
env:
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ on:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
matrix_prep:
|
matrix_prep:
|
||||||
runs-on: ubuntu-20.04
|
runs-on: arc-ubuntu-20.04
|
||||||
outputs:
|
outputs:
|
||||||
matrix: ${{ steps.set-matrix.outputs.matrix }}
|
matrix: ${{ steps.set-matrix.outputs.matrix }}
|
||||||
steps:
|
steps:
|
||||||
|
|||||||
@@ -3,35 +3,28 @@ name: ci-docs
|
|||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
push:
|
push:
|
||||||
branches-ignore: [master]
|
branches-ignore: master
|
||||||
paths:
|
paths:
|
||||||
- "documentation/docs/**"
|
- 'documentation/docs/**'
|
||||||
- ".github/workflows/ci-docs.yml"
|
- '.github/workflows/ci-docs.yml'
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: arc-ubuntu-20.04
|
runs-on: ubuntu-20.04-16-core
|
||||||
defaults:
|
|
||||||
run:
|
|
||||||
working-directory: documentation/docs
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- name: Install Dependencies (Linux)
|
- name: Install Dependencies (Linux)
|
||||||
run: sudo apt-get update && sudo apt-get install -y build-essential curl wget libssl-dev libudev-dev squashfs-tools protobuf-compiler git python3 && sudo apt-get update --fix-missing
|
run: sudo apt-get update && sudo apt-get install -y build-essential curl wget libssl-dev libudev-dev squashfs-tools protobuf-compiler git python3 && sudo apt-get update --fix-missing
|
||||||
- name: Install pip3
|
- name: Install pip3
|
||||||
run: sudo apt install -y python3-pip
|
run: sudo apt install -y python3-pip
|
||||||
- name: Install Python3 modules
|
- name: Install Python3 modules
|
||||||
run: sudo pip3 install pandas tabulate
|
run: sudo pip3 install pandas tabulate
|
||||||
- name: Install rsync
|
- name: Install rsync
|
||||||
run: sudo apt-get install rsync
|
run: sudo apt-get install rsync
|
||||||
- uses: rlespinasse/github-slug-action@v3.x
|
- uses: rlespinasse/github-slug-action@v3.x
|
||||||
- name: Setup pnpm
|
|
||||||
uses: pnpm/action-setup@v4.0.0
|
|
||||||
with:
|
|
||||||
version: 9
|
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 20
|
node-version: 18
|
||||||
- name: Install Rust stable
|
- name: Install Rust stable
|
||||||
uses: actions-rs/toolchain@v1
|
uses: actions-rs/toolchain@v1
|
||||||
with:
|
with:
|
||||||
@@ -41,13 +34,30 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
command: build
|
command: build
|
||||||
args: --workspace --release
|
args: --workspace --release
|
||||||
|
- name: Install mdbook and plugins
|
||||||
|
run: cd documentation && ./install_mdbook_deps.sh
|
||||||
|
- name: Remove existing Nym config directory (`~/.nym/`)
|
||||||
|
run: cd documentation && ./remove_existing_config.sh
|
||||||
|
continue-on-error: false
|
||||||
|
|
||||||
- name: Install project dependencies
|
# This is the original flow
|
||||||
run: pnpm i
|
# - name: Build all projects in documentation/ & move to ~/dist/docs/
|
||||||
- name: Build project
|
# run: cd documentation && ./build_all_to_dist.sh
|
||||||
run: pnpm run build
|
|
||||||
- name: Move files to /dist/
|
# This is a workaround replacement which builds on the last working commit b332a6b55668f60988e36961f3f62a794ba82ddb and then on current branch
|
||||||
run: ../scripts/move-to-dist.sh
|
- name: Save current branch to ~/current_branch
|
||||||
|
run: git rev-parse --abbrev-ref HEAD > ~/current_branch
|
||||||
|
- name: Git pull, reset & switch to b332a6b55668f60988e36961f3f62a794ba82ddb
|
||||||
|
run: git pull && git reset --hard && git checkout b332a6b55668f60988e36961f3f62a794ba82ddb
|
||||||
|
- name: Build all projects in documentation/ & move to ~/dist/docs/ from b332a6b55668f60988e36961f3f62a794ba82ddb
|
||||||
|
run: cd documentation && ./build_all_to_dist.sh
|
||||||
|
|
||||||
|
- name: Switch to current branch
|
||||||
|
run: git checkout $echo "$(cat ~/current_branch)"
|
||||||
|
- name: Build all projects in documentation/ & move to ~/dist/docs/ on current branch
|
||||||
|
run: cd documentation && ./build_all_to_dist.sh && rm ~/current_branch
|
||||||
|
|
||||||
|
# End of replacemet
|
||||||
|
|
||||||
- name: Deploy branch to CI www
|
- name: Deploy branch to CI www
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
@@ -58,5 +68,26 @@ jobs:
|
|||||||
SOURCE: "dist/docs/"
|
SOURCE: "dist/docs/"
|
||||||
REMOTE_HOST: ${{ secrets.CI_WWW_REMOTE_HOST }}
|
REMOTE_HOST: ${{ secrets.CI_WWW_REMOTE_HOST }}
|
||||||
REMOTE_USER: ${{ secrets.CI_WWW_REMOTE_USER }}
|
REMOTE_USER: ${{ secrets.CI_WWW_REMOTE_USER }}
|
||||||
TARGET: ${{ secrets.CI_WWW_REMOTE_TARGET }}/docs-nextra-${{ env.GITHUB_REF_SLUG }}
|
TARGET: ${{ secrets.CI_WWW_REMOTE_TARGET }}/docs-${{ env.GITHUB_REF_SLUG }}
|
||||||
EXCLUDE: "/node_modules/"
|
EXCLUDE: "/node_modules/"
|
||||||
|
|
||||||
|
- name: Matrix - Node Install
|
||||||
|
run: npm install
|
||||||
|
working-directory: .github/workflows/support-files
|
||||||
|
- name: Matrix - Send Notification
|
||||||
|
env:
|
||||||
|
NYM_NOTIFICATION_KIND: ci-docs
|
||||||
|
NYM_PROJECT_NAME: "Docs CI"
|
||||||
|
NYM_CI_WWW_BASE: "${{ secrets.NYM_CI_WWW_BASE }}"
|
||||||
|
NYM_CI_WWW_LOCATION: "docs-${{ env.GITHUB_REF_SLUG }}"
|
||||||
|
GIT_COMMIT_MESSAGE: "${{ github.event.head_commit.message }}"
|
||||||
|
GIT_BRANCH: "${GITHUB_REF##*/}"
|
||||||
|
MATRIX_SERVER: "${{ secrets.MATRIX_SERVER }}"
|
||||||
|
MATRIX_ROOM: "${{ secrets.MATRIX_ROOM_DOCS }}"
|
||||||
|
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
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
name: ci-lint-typescript
|
name: ci-lint-typescript
|
||||||
|
|
||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
|
||||||
pull_request:
|
pull_request:
|
||||||
paths:
|
paths:
|
||||||
- "ts-packages/**"
|
- "ts-packages/**"
|
||||||
@@ -15,7 +14,7 @@ on:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: arc-ubuntu-20.04
|
runs-on: ubuntu-20.04-16-core
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: rlespinasse/github-slug-action@v3.x
|
- uses: rlespinasse/github-slug-action@v3.x
|
||||||
@@ -54,3 +53,24 @@ jobs:
|
|||||||
run: yarn lint
|
run: yarn lint
|
||||||
- name: Typecheck with tsc
|
- name: Typecheck with tsc
|
||||||
run: yarn tsc
|
run: yarn tsc
|
||||||
|
|
||||||
|
- name: Matrix - Node Install
|
||||||
|
run: npm install
|
||||||
|
working-directory: .github/workflows/support-files
|
||||||
|
- name: Matrix - Send Notification
|
||||||
|
env:
|
||||||
|
NYM_NOTIFICATION_KIND: ts-packages
|
||||||
|
NYM_PROJECT_NAME: "ts-packages"
|
||||||
|
NYM_CI_WWW_BASE: "${{ secrets.NYM_CI_WWW_BASE }}"
|
||||||
|
NYM_CI_WWW_LOCATION: "ts-${{ 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
|
||||||
|
|||||||
@@ -0,0 +1,39 @@
|
|||||||
|
name: ci-nym-api-tests
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
push:
|
||||||
|
paths:
|
||||||
|
- "nym-api/**"
|
||||||
|
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
working-directory: nym-api/tests
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
name: nym-api tests
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: install yarn in root
|
||||||
|
run: cd ../.. && yarn install
|
||||||
|
|
||||||
|
- name: Install npm
|
||||||
|
run: npm install
|
||||||
|
|
||||||
|
- name: Node v18
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: 18.1.0
|
||||||
|
|
||||||
|
- name: Install yarn
|
||||||
|
run: yarn install
|
||||||
|
|
||||||
|
- name: Run yarn
|
||||||
|
run: yarn
|
||||||
|
|
||||||
|
- name: Run tests
|
||||||
|
run: yarn test:sandbox
|
||||||
|
working-directory: nym-api/tests
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
name: ci-sdk-docs-typescript
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
paths:
|
||||||
|
- "sdk/typescript/**"
|
||||||
|
- "wasm/**"
|
||||||
|
- '.github/workflows/ci-sdk-docs-typescript.yml'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: custom-linux
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Install rsync
|
||||||
|
run: sudo apt-get install rsync
|
||||||
|
continue-on-error: true
|
||||||
|
- uses: rlespinasse/github-slug-action@v3.x
|
||||||
|
- uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: 18.17
|
||||||
|
- name: Install Rust stable
|
||||||
|
uses: actions-rs/toolchain@v1
|
||||||
|
with:
|
||||||
|
toolchain: stable
|
||||||
|
- name: Setup yarn
|
||||||
|
run: npm install -g yarn
|
||||||
|
|
||||||
|
- name: Set up Go
|
||||||
|
uses: actions/setup-go@v5
|
||||||
|
with:
|
||||||
|
go-version: '1.20'
|
||||||
|
|
||||||
|
- name: Install wasm-pack
|
||||||
|
run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
|
||||||
|
|
||||||
|
- name: Install wasm-opt
|
||||||
|
uses: ./.github/actions/install-wasm-opt
|
||||||
|
with:
|
||||||
|
version: '116'
|
||||||
|
|
||||||
|
- name: Build branch WASM packages
|
||||||
|
run: make sdk-wasm-build
|
||||||
|
|
||||||
|
- name: Install
|
||||||
|
run: yarn
|
||||||
|
- name: Build
|
||||||
|
run: yarn docs:prod:build
|
||||||
|
- name: Deploy branch to CI www (docs)
|
||||||
|
continue-on-error: true
|
||||||
|
uses: easingthemes/ssh-deploy@main
|
||||||
|
env:
|
||||||
|
SSH_PRIVATE_KEY: ${{ secrets.CI_WWW_SSH_PRIVATE_KEY }}
|
||||||
|
ARGS: "-rltgoDzvO --delete"
|
||||||
|
SOURCE: "dist/ts/"
|
||||||
|
REMOTE_HOST: ${{ secrets.CI_WWW_REMOTE_HOST }}
|
||||||
|
REMOTE_USER: ${{ secrets.CI_WWW_REMOTE_USER }}
|
||||||
|
TARGET: ${{ secrets.CI_WWW_REMOTE_TARGET }}/sdk-ts-docs-${{ 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: ts-packages
|
||||||
|
NYM_PROJECT_NAME: "sdk-ts-docs"
|
||||||
|
NYM_CI_WWW_BASE: "${{ secrets.NYM_CI_WWW_BASE }}/docs/sdk/typescript"
|
||||||
|
NYM_CI_WWW_LOCATION: "sdk-ts-docs-${{ 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
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
name: Hello world
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
my-job:
|
|
||||||
runs-on: arc-ubuntu-22.04
|
|
||||||
steps:
|
|
||||||
- name: my-step
|
|
||||||
run: echo "Hello World!"
|
|
||||||
@@ -4,9 +4,7 @@ on:
|
|||||||
pull_request:
|
pull_request:
|
||||||
branches:
|
branches:
|
||||||
- develop
|
- develop
|
||||||
- "release/**"
|
- 'release/**'
|
||||||
paths-ignore:
|
|
||||||
- "documentation/**"
|
|
||||||
types:
|
types:
|
||||||
- labeled
|
- labeled
|
||||||
- unlabeled
|
- unlabeled
|
||||||
|
|||||||
@@ -55,7 +55,6 @@ jobs:
|
|||||||
uses: actions-rs/toolchain@v1
|
uses: actions-rs/toolchain@v1
|
||||||
with:
|
with:
|
||||||
toolchain: stable
|
toolchain: stable
|
||||||
override: true
|
|
||||||
|
|
||||||
- name: Build all binaries
|
- name: Build all binaries
|
||||||
uses: actions-rs/cargo@v1
|
uses: actions-rs/cargo@v1
|
||||||
|
|||||||
@@ -14,14 +14,13 @@ jobs:
|
|||||||
- name: Install Rust stable
|
- name: Install Rust stable
|
||||||
uses: actions-rs/toolchain@v1
|
uses: actions-rs/toolchain@v1
|
||||||
with:
|
with:
|
||||||
toolchain: 1.77
|
toolchain: stable
|
||||||
target: wasm32-unknown-unknown
|
target: wasm32-unknown-unknown
|
||||||
override: true
|
override: true
|
||||||
|
components: rustfmt, clippy
|
||||||
|
|
||||||
- name: Install wasm-opt
|
- name: Install wasm-opt
|
||||||
uses: ./.github/actions/install-wasm-opt
|
run: cargo install --version 0.114.0 wasm-opt
|
||||||
with:
|
|
||||||
version: '114'
|
|
||||||
|
|
||||||
- name: Build release contracts
|
- name: Build release contracts
|
||||||
run: make contracts
|
run: make contracts
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ on:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
publish:
|
publish:
|
||||||
runs-on: arc-ubuntu-20.04
|
runs-on: ubuntu-20.04-16-core
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
|||||||
@@ -1,55 +0,0 @@
|
|||||||
name: Build and upload Credential Proxy container to harbor.nymte.ch
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
env:
|
|
||||||
WORKING_DIRECTORY: "nym-credential-proxy"
|
|
||||||
CONTAINER_NAME: "credential-proxy"
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build-container:
|
|
||||||
runs-on: arc-ubuntu-22.04-dind
|
|
||||||
steps:
|
|
||||||
- name: Login to Harbor
|
|
||||||
uses: docker/login-action@v3
|
|
||||||
with:
|
|
||||||
registry: harbor.nymte.ch
|
|
||||||
username: ${{ secrets.HARBOR_ROBOT_USERNAME }}
|
|
||||||
password: ${{ secrets.HARBOR_ROBOT_SECRET }}
|
|
||||||
|
|
||||||
- name: Checkout repo
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Configure git identity
|
|
||||||
run: |
|
|
||||||
git config --global user.email "lawrence@nymtech.net"
|
|
||||||
git config --global user.name "Lawrence Stalder"
|
|
||||||
|
|
||||||
- name: Get version from cargo.toml
|
|
||||||
uses: mikefarah/yq@v4.44.5
|
|
||||||
id: get_version
|
|
||||||
with:
|
|
||||||
cmd: yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/nym-credential-proxy/Cargo.toml
|
|
||||||
|
|
||||||
- name: Check if tag exists
|
|
||||||
run: |
|
|
||||||
if git rev-parse ${{ steps.get_version.outputs.value }} >/dev/null 2>&1; then
|
|
||||||
echo "Tag ${{ steps.get_version.outputs.value }} already exists"
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Remove existing tag if exists
|
|
||||||
run: |
|
|
||||||
if git rev-parse ${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.result }} >/dev/null 2>&1; then
|
|
||||||
git push --delete origin ${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.result }}
|
|
||||||
git tag -d ${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.result }}
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Create tag
|
|
||||||
run: |
|
|
||||||
git tag -a ${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.result }} -m "Version ${{ steps.get_version.outputs.result }}"
|
|
||||||
git push origin ${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.result }}
|
|
||||||
|
|
||||||
- name: BuildAndPushImageOnHarbor
|
|
||||||
run: |
|
|
||||||
docker build -f ${{ env.WORKING_DIRECTORY }}/nym-credential-proxy/Dockerfile . -t harbor.nymte.ch/nym/${{ env.CONTAINER_NAME }}:${{ steps.get_version.outputs.result }} -t harbor.nymte.ch/nym/${{ env.CONTAINER_NAME }}:latest
|
|
||||||
docker push harbor.nymte.ch/nym/${{ env.CONTAINER_NAME }} --all-tags
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
name: Build and upload Data observatory container to harbor.nymte.ch
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
env:
|
|
||||||
WORKING_DIRECTORY: "nym-data-observatory"
|
|
||||||
CONTAINER_NAME: "data-observatory"
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build-container:
|
|
||||||
runs-on: arc-ubuntu-22.04-dind
|
|
||||||
steps:
|
|
||||||
- name: Login to Harbor
|
|
||||||
uses: docker/login-action@v3
|
|
||||||
with:
|
|
||||||
registry: harbor.nymte.ch
|
|
||||||
username: ${{ secrets.HARBOR_ROBOT_USERNAME }}
|
|
||||||
password: ${{ secrets.HARBOR_ROBOT_SECRET }}
|
|
||||||
|
|
||||||
- name: Checkout repo
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Configure git identity
|
|
||||||
run: |
|
|
||||||
git config --global user.email "lawrence@nymtech.net"
|
|
||||||
git config --global user.name "Lawrence Stalder"
|
|
||||||
|
|
||||||
- name: Get version from cargo.toml
|
|
||||||
uses: mikefarah/yq@v4.44.5
|
|
||||||
id: get_version
|
|
||||||
with:
|
|
||||||
cmd: yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/Cargo.toml
|
|
||||||
|
|
||||||
- name: Check if tag exists
|
|
||||||
run: |
|
|
||||||
if git rev-parse ${{ steps.get_version.outputs.value }} >/dev/null 2>&1; then
|
|
||||||
echo "Tag ${{ steps.get_version.outputs.value }} already exists"
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Remove existing tag if exists
|
|
||||||
run: |
|
|
||||||
if git rev-parse ${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.result }} >/dev/null 2>&1; then
|
|
||||||
git push --delete origin ${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.result }}
|
|
||||||
git tag -d ${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.result }}
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Create tag
|
|
||||||
run: |
|
|
||||||
git tag -a ${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.result }} -m "Version ${{ steps.get_version.outputs.result }}"
|
|
||||||
git push origin ${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.result }}
|
|
||||||
|
|
||||||
- name: BuildAndPushImageOnHarbor
|
|
||||||
run: |
|
|
||||||
docker build -f ${{ env.WORKING_DIRECTORY }}/Dockerfile . -t harbor.nymte.ch/nym/${{ env.CONTAINER_NAME }}:${{ steps.get_version.outputs.result }} -t harbor.nymte.ch/nym/${{ env.CONTAINER_NAME }}:latest
|
|
||||||
docker push harbor.nymte.ch/nym/${{ env.CONTAINER_NAME }} --all-tags
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
name: Build and upload Network monitor container to harbor.nymte.ch
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
env:
|
|
||||||
WORKING_DIRECTORY: "."
|
|
||||||
CONTAINER_NAME: "network-monitor"
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build-container:
|
|
||||||
runs-on: arc-ubuntu-22.04-dind
|
|
||||||
steps:
|
|
||||||
- name: Login to Harbor
|
|
||||||
uses: docker/login-action@v3
|
|
||||||
with:
|
|
||||||
registry: harbor.nymte.ch
|
|
||||||
username: ${{ secrets.HARBOR_ROBOT_USERNAME }}
|
|
||||||
password: ${{ secrets.HARBOR_ROBOT_SECRET }}
|
|
||||||
|
|
||||||
- name: Checkout repo
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Configure git identity
|
|
||||||
run: |
|
|
||||||
git config --global user.email "lawrence@nymtech.net"
|
|
||||||
git config --global user.name "Lawrence Stalder"
|
|
||||||
|
|
||||||
- name: Get version from cargo.toml
|
|
||||||
uses: mikefarah/yq@v4.44.5
|
|
||||||
id: get_version
|
|
||||||
with:
|
|
||||||
cmd: yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/nym-network-monitor/Cargo.toml
|
|
||||||
|
|
||||||
- name: Remove existing tag if exists
|
|
||||||
run: |
|
|
||||||
echo "Checking if tag ${{ env.CONTAINER_NAME }}-${{ steps.get_version.outputs.result }} exists..."
|
|
||||||
if git rev-parse ${{ env.CONTAINER_NAME }}-${{ steps.get_version.outputs.result }} >/dev/null 2>&1; then
|
|
||||||
echo "Tag ${{ env.CONTAINER_NAME }}-${{ steps.get_version.outputs.result }} already exists"
|
|
||||||
git push --delete origin ${{ env.CONTAINER_NAME }}-${{ steps.get_version.outputs.result }}
|
|
||||||
git tag -d ${{ env.CONTAINER_NAME }}-${{ steps.get_version.outputs.result }}
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Create tag
|
|
||||||
run: |
|
|
||||||
git tag -a ${{ env.CONTAINER_NAME }}-${{ steps.get_version.outputs.result }} -m "Version ${{ steps.get_version.outputs.result }}"
|
|
||||||
git push origin ${{ env.CONTAINER_NAME }}-${{ steps.get_version.outputs.result }}
|
|
||||||
|
|
||||||
- name: BuildAndPushImageOnHarbor
|
|
||||||
run: |
|
|
||||||
docker build -f nym-network-monitor.dockerfile ${{ env.WORKING_DIRECTORY }} -t harbor.nymte.ch/nym/${{ env.CONTAINER_NAME }}:${{ steps.get_version.outputs.result }} -t harbor.nymte.ch/nym/${{ env.CONTAINER_NAME }}:latest
|
|
||||||
docker push harbor.nymte.ch/nym/${{ env.CONTAINER_NAME }} --all-tags
|
|
||||||
@@ -1,61 +0,0 @@
|
|||||||
name: Build and upload Node Status agent container to harbor.nymte.ch
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
inputs:
|
|
||||||
gateway_probe_git_ref:
|
|
||||||
type: string
|
|
||||||
description: Which gateway probe git ref to build the image with
|
|
||||||
|
|
||||||
env:
|
|
||||||
WORKING_DIRECTORY: "nym-node-status-agent"
|
|
||||||
CONTAINER_NAME: "node-status-agent"
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build-container:
|
|
||||||
runs-on: arc-ubuntu-22.04-dind
|
|
||||||
steps:
|
|
||||||
- name: Login to Harbor
|
|
||||||
uses: docker/login-action@v3
|
|
||||||
with:
|
|
||||||
registry: harbor.nymte.ch
|
|
||||||
username: ${{ secrets.HARBOR_ROBOT_USERNAME }}
|
|
||||||
password: ${{ secrets.HARBOR_ROBOT_SECRET }}
|
|
||||||
|
|
||||||
- name: Checkout repo
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Configure git identity
|
|
||||||
run: |
|
|
||||||
git config --global user.email "lawrence@nymtech.net"
|
|
||||||
git config --global user.name "Lawrence Stalder"
|
|
||||||
|
|
||||||
- name: Get version from cargo.toml
|
|
||||||
uses: mikefarah/yq@v4.44.5
|
|
||||||
id: get_version
|
|
||||||
with:
|
|
||||||
cmd: yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/Cargo.toml
|
|
||||||
|
|
||||||
- name: cleanup-gateway-probe-ref
|
|
||||||
id: cleanup_gateway_probe_ref
|
|
||||||
run: |
|
|
||||||
GATEWAY_PROBE_GIT_REF=${{ github.event.inputs.gateway_probe_git_ref }}
|
|
||||||
GIT_REF_SLUG="${GATEWAY_PROBE_GIT_REF//\//-}"
|
|
||||||
echo "git_ref=${GIT_REF_SLUG}" >> $GITHUB_OUTPUT
|
|
||||||
|
|
||||||
- name: Remove existing tag if exists
|
|
||||||
run: |
|
|
||||||
if git rev-parse ${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.result }}-${{ steps.cleanup_gateway_probe_ref.outputs.git_ref }} >/dev/null 2>&1; then
|
|
||||||
git push --delete origin ${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.result }}-${{ steps.cleanup_gateway_probe_ref.outputs.git_ref }}
|
|
||||||
git tag -d ${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.result }}-${{ steps.cleanup_gateway_probe_ref.outputs.git_ref }}
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Create tag
|
|
||||||
run: |
|
|
||||||
git tag -a ${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.result }}-${{ steps.cleanup_gateway_probe_ref.outputs.git_ref }} -m "Version ${{ steps.get_version.outputs.result }}-${{ steps.cleanup_gateway_probe_ref.outputs.git_ref }}"
|
|
||||||
git push origin ${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.result }}-${{ steps.cleanup_gateway_probe_ref.outputs.git_ref }}
|
|
||||||
|
|
||||||
- name: BuildAndPushImageOnHarbor
|
|
||||||
run: |
|
|
||||||
docker build --build-arg GIT_REF=${{ github.event.inputs.gateway_probe_git_ref }} -f ${{ env.WORKING_DIRECTORY }}/Dockerfile . -t harbor.nymte.ch/nym/${{ env.CONTAINER_NAME }}:${{ steps.get_version.outputs.result }}-${{ steps.cleanup_gateway_probe_ref.outputs.git_ref }}
|
|
||||||
docker push harbor.nymte.ch/nym/${{ env.CONTAINER_NAME }} --all-tags
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
name: Build and upload Node Status API container to harbor.nymte.ch
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
env:
|
|
||||||
WORKING_DIRECTORY: "nym-node-status-api"
|
|
||||||
CONTAINER_NAME: "node-status-api"
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build-container:
|
|
||||||
runs-on: arc-ubuntu-22.04-dind
|
|
||||||
steps:
|
|
||||||
- name: Login to Harbor
|
|
||||||
uses: docker/login-action@v3
|
|
||||||
with:
|
|
||||||
registry: harbor.nymte.ch
|
|
||||||
username: ${{ secrets.HARBOR_ROBOT_USERNAME }}
|
|
||||||
password: ${{ secrets.HARBOR_ROBOT_SECRET }}
|
|
||||||
|
|
||||||
- name: Checkout repo
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Configure git identity
|
|
||||||
run: |
|
|
||||||
git config --global user.email "lawrence@nymtech.net"
|
|
||||||
git config --global user.name "Lawrence Stalder"
|
|
||||||
|
|
||||||
- name: Get version from cargo.toml
|
|
||||||
uses: mikefarah/yq@v4.44.5
|
|
||||||
id: get_version
|
|
||||||
with:
|
|
||||||
cmd: yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/Cargo.toml
|
|
||||||
|
|
||||||
- name: Check if tag exists
|
|
||||||
run: |
|
|
||||||
if git rev-parse ${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.result }} >/dev/null 2>&1; then
|
|
||||||
echo "Tag ${{ steps.get_version.outputs.result }} already exists"
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Remove existing tag if exists
|
|
||||||
run: |
|
|
||||||
if git rev-parse ${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.result }} >/dev/null 2>&1; then
|
|
||||||
git push --delete origin ${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.result }}
|
|
||||||
git tag -d ${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.result }}
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Create tag
|
|
||||||
run: |
|
|
||||||
git tag -a ${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.result }} -m "Version ${{ steps.get_version.outputs.result }}"
|
|
||||||
git push origin ${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.result }}
|
|
||||||
|
|
||||||
- name: BuildAndPushImageOnHarbor
|
|
||||||
run: |
|
|
||||||
docker build -f ${{ env.WORKING_DIRECTORY }}/Dockerfile . -t harbor.nymte.ch/nym/${{ env.CONTAINER_NAME }}:${{ steps.get_version.outputs.result }} -t harbor.nymte.ch/nym/${{ env.CONTAINER_NAME }}:latest
|
|
||||||
docker push harbor.nymte.ch/nym/${{ env.CONTAINER_NAME }} --all-tags
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
name: Build and upload nym node container to harbor.nymte.ch
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
env:
|
|
||||||
WORKING_DIRECTORY: "nym-node"
|
|
||||||
CONTAINER_NAME: "nym-node"
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build-container:
|
|
||||||
runs-on: arc-ubuntu-22.04-dind
|
|
||||||
steps:
|
|
||||||
- name: Login to Harbor
|
|
||||||
uses: docker/login-action@v3
|
|
||||||
with:
|
|
||||||
registry: harbor.nymte.ch
|
|
||||||
username: ${{ secrets.HARBOR_ROBOT_USERNAME }}
|
|
||||||
password: ${{ secrets.HARBOR_ROBOT_SECRET }}
|
|
||||||
|
|
||||||
- name: Checkout repo
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Configure git identity
|
|
||||||
run: |
|
|
||||||
git config --global user.email "lawrence@nymtech.net"
|
|
||||||
git config --global user.name "Lawrence Stalder"
|
|
||||||
|
|
||||||
- name: Get version from cargo.toml
|
|
||||||
uses: mikefarah/yq@v4.44.5
|
|
||||||
id: get_version
|
|
||||||
with:
|
|
||||||
cmd: yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/Cargo.toml
|
|
||||||
|
|
||||||
- name: Check if tag exists
|
|
||||||
run: |
|
|
||||||
if git rev-parse ${{ steps.get_version.outputs.value }} >/dev/null 2>&1; then
|
|
||||||
echo "Tag ${{ steps.get_version.outputs.value }} already exists"
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Remove existing tag if exists
|
|
||||||
run: |
|
|
||||||
if git rev-parse ${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.result }} >/dev/null 2>&1; then
|
|
||||||
git push --delete origin ${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.result }}
|
|
||||||
git tag -d ${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.result }}
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Create tag
|
|
||||||
run: |
|
|
||||||
git tag -a ${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.result }} -m "Version ${{ steps.get_version.outputs.result }}"
|
|
||||||
git push origin ${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.result }}
|
|
||||||
|
|
||||||
- name: BuildAndPushImageOnHarbor
|
|
||||||
run: |
|
|
||||||
docker build -f ${{ env.WORKING_DIRECTORY }}/Dockerfile . -t harbor.nymte.ch/nym/${{ env.CONTAINER_NAME }}:${{ steps.get_version.outputs.result }} -t harbor.nymte.ch/nym/${{ env.CONTAINER_NAME }}:latest
|
|
||||||
docker push harbor.nymte.ch/nym/${{ env.CONTAINER_NAME }} --all-tags
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
name: Build and upload Validator Rewarder container to harbor.nymte.ch
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
env:
|
|
||||||
WORKING_DIRECTORY: "nym-validator-rewarder"
|
|
||||||
CONTAINER_NAME: "validator-rewarder"
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build-container:
|
|
||||||
runs-on: arc-ubuntu-22.04-dind
|
|
||||||
steps:
|
|
||||||
- name: Login to Harbor
|
|
||||||
uses: docker/login-action@v3
|
|
||||||
with:
|
|
||||||
registry: harbor.nymte.ch
|
|
||||||
username: ${{ secrets.HARBOR_ROBOT_USERNAME }}
|
|
||||||
password: ${{ secrets.HARBOR_ROBOT_SECRET }}
|
|
||||||
|
|
||||||
- name: Checkout repo
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Configure git identity
|
|
||||||
run: |
|
|
||||||
git config --global user.email "lawrence@nymtech.net"
|
|
||||||
git config --global user.name "Lawrence Stalder"
|
|
||||||
|
|
||||||
- name: Get version from cargo.toml
|
|
||||||
uses: mikefarah/yq@v4.44.5
|
|
||||||
id: get_version
|
|
||||||
with:
|
|
||||||
cmd: yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/nym-credential-proxy/Cargo.toml
|
|
||||||
|
|
||||||
- name: Remove existing tag if exists
|
|
||||||
run: |
|
|
||||||
if git rev-parse ${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.result }} >/dev/null 2>&1; then
|
|
||||||
git push --delete origin ${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.result }}
|
|
||||||
git tag -d ${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.result }}
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Create tag
|
|
||||||
run: |
|
|
||||||
git tag -a ${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.result }} -m "Version ${{ steps.get_version.outputs.result }}"
|
|
||||||
git push origin ${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.result }}
|
|
||||||
|
|
||||||
- name: BuildAndPushImageOnHarbor
|
|
||||||
run: |
|
|
||||||
docker build -f ${{ env.WORKING_DIRECTORY }}/Dockerfile . -t harbor.nymte.ch/nym/${{ env.CONTAINER_NAME }}:${{ steps.get_version.outputs.result }} -t harbor.nymte.ch/nym/${{ env.CONTAINER_NAME }}:latest
|
|
||||||
docker push harbor.nymte.ch/nym/${{ env.CONTAINER_NAME }} --all-tags
|
|
||||||
-352
@@ -4,358 +4,6 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
## [2024.13-magura-drift] (2024-11-29)
|
|
||||||
|
|
||||||
- Optimised syncing bandwidth information to storage
|
|
||||||
|
|
||||||
## [2024.13-magura-patched] (2024-11-22)
|
|
||||||
|
|
||||||
- [experimental] allow clients to change between deterministic route selection based on packet headers and a pseudorandom distribution
|
|
||||||
- Introduced a configurable limit on retransmission frequency of packets if ACKs are not received
|
|
||||||
- Filtered out invalid IP addresses on nym-api
|
|
||||||
|
|
||||||
## [2024.13-magura] (2024-11-18)
|
|
||||||
|
|
||||||
- Limit race probability ([#5145])
|
|
||||||
- bugifx: assign 'node_id' when converting from 'GatewayDetails' to 'TestNode' ([#5143])
|
|
||||||
- bugfix: make sure to assign correct node_id and identity during 'gateway_details' table migration ([#5142])
|
|
||||||
- Respond to auth messages with same version ([#5140])
|
|
||||||
- Pain/polyfill deprecated endpoints ([#5131])
|
|
||||||
- change: dont select mixnodes bonded with vested tokens into the rewarded set ([#5129])
|
|
||||||
- nym-credential-proxy-requests: reqwest use rustls-tls ([#5116])
|
|
||||||
- bugfix: preserve as much as possible of the rewarded set during migration ([#5103])
|
|
||||||
- Feature/force refresh node ([#5101])
|
|
||||||
- Add NYM_VPN_API to env files ([#5099])
|
|
||||||
- bugfix: fixed historical uptimes for nodes ([#5097])
|
|
||||||
- Remove old use of 1GB constant ([#5096])
|
|
||||||
- Graceful agent 1.1.5 ([#5093])
|
|
||||||
- Add more translations from v2 to v3 authenticator ([#5091])
|
|
||||||
- Nym node - Fix claim delegator rewards ([#5090])
|
|
||||||
- Make 250 GB/30 days for free ride mode ([#5083])
|
|
||||||
- Don't increase bandwidth two times ([#5081])
|
|
||||||
- Fix expiration date as today + 7 days ([#5076])
|
|
||||||
- Fix gateway decreasing bandwidth ([#5075])
|
|
||||||
- Allow custom http port to be reset ([#5073])
|
|
||||||
- bugfix: additional checks inside credential proxy ([#5072])
|
|
||||||
- chore: deprecated old nym-api client methods and replaced them when possible ([#5069])
|
|
||||||
- NS API with directory v2 (#5058) ([#5068])
|
|
||||||
- bugfix: credential-proxy obtain-async ([#5067])
|
|
||||||
- Allow nym node config updates ([#5066])
|
|
||||||
- bugfix: use corrext axum extractors for ecash route arguments ([#5065])
|
|
||||||
- Merge2/release/2024.13 magura ([#5063])
|
|
||||||
- bugfix/feature: added NymApiClient method to get all skimmed nodes ([#5062])
|
|
||||||
- Merge1/release/2024.13 magura ([#5061])
|
|
||||||
- added hacky routes to return nymnodes alongside legacy nodes ([#5051])
|
|
||||||
- bugfix: mark migrated gateways as rewarded in the previous epoch in case theyre in the rewarded set ([#5049])
|
|
||||||
- bugfix: adjust runtime storage migration ([#5047])
|
|
||||||
- bugfix: supersede 'cb13be27f8f61d9ae74d924e85d2e6787895eb14' by using… ([#5046])
|
|
||||||
- bugfix: restore default http port for nym-api ([#5045])
|
|
||||||
- bugfix: fix ecash handlers routes ([#5043])
|
|
||||||
- bugfix: don't assign exit gateways to standby set ([#5041])
|
|
||||||
- bugfix: make sure nym-nodes are also tested by network monitor ([#5040])
|
|
||||||
- bugfix: use bonded nym-nodes for determining initial network monitor … ([#5039])
|
|
||||||
- bugfix: make gateways insert themselves into [local] topology ([#5038])
|
|
||||||
- Pass poisson flag ([#5037])
|
|
||||||
- bugfix: use human readable roles for annotations ([#5036])
|
|
||||||
- bugfix: use old name for 'epoch_role' in SkimmedNode ([#5034])
|
|
||||||
- bugfix: make sure to use correct highest node id when assigning role ([#5032])
|
|
||||||
- feature: use axum_client_ip for attempting to extract source ip ([#5031])
|
|
||||||
- bugfix: fixed backwards incompatibility for /gateways/described endpoint ([#5030])
|
|
||||||
- bugfix: verifying signed information of legacy nodes ([#5029])
|
|
||||||
- bugfix: introduce 'LegacyPendingMixNodeChanges' that does not contain 'cost_params_change' ([#5028])
|
|
||||||
- bugfix: missing #[serde(default)] for announce port ([#5024])
|
|
||||||
- bugfix: directory v2.1 `get_all_avg_gateway_reliability_in_interval` query ([#5023])
|
|
||||||
- added 'get_all_described_nodes' to NymApiClient and adjusted return t… ([#5016])
|
|
||||||
- Reapply fixes to new branch ([#5014])
|
|
||||||
- Consume only positive bandwidth ([#5013])
|
|
||||||
- feature: adjusted ticket sizes to the agreed amounts ([#5009])
|
|
||||||
- Push private ip before inserting ([#5008])
|
|
||||||
- chore: update itertools in compact ecash ([#4994])
|
|
||||||
- feature: make accepting t&c a hard requirement for rewarded set selection ([#4993])
|
|
||||||
- Fix rustfmt in nym-credential-proxy ([#4992])
|
|
||||||
- bugfix: client memory leak ([#4991])
|
|
||||||
- Eliminate 0 bandwidth race check ([#4988])
|
|
||||||
- [DOCs;/operators]: Release notes for v2024.12 aero ([#4984])
|
|
||||||
- Add topup req constructor ([#4983])
|
|
||||||
- Fix critical issues SI86 and SI87 from Cure53 ([#4982])
|
|
||||||
- Rename nym-vpn-api to nym-credential-proxy ([#4981])
|
|
||||||
- enable global ecash routes even if api is not a signer ([#4980])
|
|
||||||
- resolve beta clippy issues in contracts ([#4978])
|
|
||||||
- Re-enable vested delegation migration ([#4977])
|
|
||||||
- feature: require reporting using nym-node binary for rewarded set selection ([#4976])
|
|
||||||
- Top up bandwidth ([#4975])
|
|
||||||
- [Product Data] Add session type based on ecash ticket received ([#4974])
|
|
||||||
- Bugfix/additional directory fixes ([#4973])
|
|
||||||
- feat: add Dockerfile for nym node ([#4972])
|
|
||||||
- chore: remove unused rocket code ([#4968])
|
|
||||||
- Import nym-vpn-api crates ([#4967])
|
|
||||||
- feature: importer-cli to correctly handle mixnet/vesting import ([#4966])
|
|
||||||
- bugfix: fix expected return type on /v1/gateways endpoint ([#4965])
|
|
||||||
- [Product Data] First step in gateway usage data collection ([#4963])
|
|
||||||
- Bump sqlx to 0.7.4 ([#4959])
|
|
||||||
- Add env feature to clap and make clap parameters available as env variables ([#4957])
|
|
||||||
- Feature/contract state tools ([#4954])
|
|
||||||
- expose authenticator address along other address in node-details ([#4953])
|
|
||||||
- Extract packet processing from mixnode-common ([#4949])
|
|
||||||
- nym-api container ([#4948])
|
|
||||||
- Ticket type storage ([#4947])
|
|
||||||
- Add "utoipa" feature to nym-node ([#4945])
|
|
||||||
- build(deps): bump the patch-updates group across 1 directory with 9 updates ([#4944])
|
|
||||||
- V2 performance monitoring feature flag ([#4943])
|
|
||||||
- Bugfix/rewarder post pruning adjustments ([#4942])
|
|
||||||
- Switch over the last set of jobs to arc runners ([#4938])
|
|
||||||
- Fix broken build after merge ([#4937])
|
|
||||||
- bugfix: correctly paginate through 'search_tx' endpoint ([#4936])
|
|
||||||
- Add more conversions for responses of authenticator messages ([#4929])
|
|
||||||
- Directory Sevices v2.1 ([#4903])
|
|
||||||
- Migrate Legacy Node (Frontend) ([#4826])
|
|
||||||
- Fix critical issues SI84 and SI85 from Cure53 ([#4758])
|
|
||||||
|
|
||||||
[#5145]: https://github.com/nymtech/nym/pull/5145
|
|
||||||
[#5143]: https://github.com/nymtech/nym/pull/5143
|
|
||||||
[#5142]: https://github.com/nymtech/nym/pull/5142
|
|
||||||
[#5140]: https://github.com/nymtech/nym/pull/5140
|
|
||||||
[#5131]: https://github.com/nymtech/nym/pull/5131
|
|
||||||
[#5129]: https://github.com/nymtech/nym/pull/5129
|
|
||||||
[#5116]: https://github.com/nymtech/nym/pull/5116
|
|
||||||
[#5103]: https://github.com/nymtech/nym/pull/5103
|
|
||||||
[#5101]: https://github.com/nymtech/nym/pull/5101
|
|
||||||
[#5099]: https://github.com/nymtech/nym/pull/5099
|
|
||||||
[#5097]: https://github.com/nymtech/nym/pull/5097
|
|
||||||
[#5096]: https://github.com/nymtech/nym/pull/5096
|
|
||||||
[#5093]: https://github.com/nymtech/nym/pull/5093
|
|
||||||
[#5091]: https://github.com/nymtech/nym/pull/5091
|
|
||||||
[#5090]: https://github.com/nymtech/nym/pull/5090
|
|
||||||
[#5083]: https://github.com/nymtech/nym/pull/5083
|
|
||||||
[#5081]: https://github.com/nymtech/nym/pull/5081
|
|
||||||
[#5076]: https://github.com/nymtech/nym/pull/5076
|
|
||||||
[#5075]: https://github.com/nymtech/nym/pull/5075
|
|
||||||
[#5073]: https://github.com/nymtech/nym/pull/5073
|
|
||||||
[#5072]: https://github.com/nymtech/nym/pull/5072
|
|
||||||
[#5069]: https://github.com/nymtech/nym/pull/5069
|
|
||||||
[#5068]: https://github.com/nymtech/nym/pull/5068
|
|
||||||
[#5067]: https://github.com/nymtech/nym/pull/5067
|
|
||||||
[#5066]: https://github.com/nymtech/nym/pull/5066
|
|
||||||
[#5065]: https://github.com/nymtech/nym/pull/5065
|
|
||||||
[#5063]: https://github.com/nymtech/nym/pull/5063
|
|
||||||
[#5062]: https://github.com/nymtech/nym/pull/5062
|
|
||||||
[#5061]: https://github.com/nymtech/nym/pull/5061
|
|
||||||
[#5051]: https://github.com/nymtech/nym/pull/5051
|
|
||||||
[#5049]: https://github.com/nymtech/nym/pull/5049
|
|
||||||
[#5047]: https://github.com/nymtech/nym/pull/5047
|
|
||||||
[#5046]: https://github.com/nymtech/nym/pull/5046
|
|
||||||
[#5045]: https://github.com/nymtech/nym/pull/5045
|
|
||||||
[#5043]: https://github.com/nymtech/nym/pull/5043
|
|
||||||
[#5041]: https://github.com/nymtech/nym/pull/5041
|
|
||||||
[#5040]: https://github.com/nymtech/nym/pull/5040
|
|
||||||
[#5039]: https://github.com/nymtech/nym/pull/5039
|
|
||||||
[#5038]: https://github.com/nymtech/nym/pull/5038
|
|
||||||
[#5037]: https://github.com/nymtech/nym/pull/5037
|
|
||||||
[#5036]: https://github.com/nymtech/nym/pull/5036
|
|
||||||
[#5034]: https://github.com/nymtech/nym/pull/5034
|
|
||||||
[#5032]: https://github.com/nymtech/nym/pull/5032
|
|
||||||
[#5031]: https://github.com/nymtech/nym/pull/5031
|
|
||||||
[#5030]: https://github.com/nymtech/nym/pull/5030
|
|
||||||
[#5029]: https://github.com/nymtech/nym/pull/5029
|
|
||||||
[#5028]: https://github.com/nymtech/nym/pull/5028
|
|
||||||
[#5024]: https://github.com/nymtech/nym/pull/5024
|
|
||||||
[#5023]: https://github.com/nymtech/nym/pull/5023
|
|
||||||
[#5016]: https://github.com/nymtech/nym/pull/5016
|
|
||||||
[#5014]: https://github.com/nymtech/nym/pull/5014
|
|
||||||
[#5013]: https://github.com/nymtech/nym/pull/5013
|
|
||||||
[#5009]: https://github.com/nymtech/nym/pull/5009
|
|
||||||
[#5008]: https://github.com/nymtech/nym/pull/5008
|
|
||||||
[#4994]: https://github.com/nymtech/nym/pull/4994
|
|
||||||
[#4993]: https://github.com/nymtech/nym/pull/4993
|
|
||||||
[#4992]: https://github.com/nymtech/nym/pull/4992
|
|
||||||
[#4991]: https://github.com/nymtech/nym/pull/4991
|
|
||||||
[#4988]: https://github.com/nymtech/nym/pull/4988
|
|
||||||
[#4984]: https://github.com/nymtech/nym/pull/4984
|
|
||||||
[#4983]: https://github.com/nymtech/nym/pull/4983
|
|
||||||
[#4982]: https://github.com/nymtech/nym/pull/4982
|
|
||||||
[#4981]: https://github.com/nymtech/nym/pull/4981
|
|
||||||
[#4980]: https://github.com/nymtech/nym/pull/4980
|
|
||||||
[#4978]: https://github.com/nymtech/nym/pull/4978
|
|
||||||
[#4977]: https://github.com/nymtech/nym/pull/4977
|
|
||||||
[#4976]: https://github.com/nymtech/nym/pull/4976
|
|
||||||
[#4975]: https://github.com/nymtech/nym/pull/4975
|
|
||||||
[#4974]: https://github.com/nymtech/nym/pull/4974
|
|
||||||
[#4973]: https://github.com/nymtech/nym/pull/4973
|
|
||||||
[#4972]: https://github.com/nymtech/nym/pull/4972
|
|
||||||
[#4968]: https://github.com/nymtech/nym/pull/4968
|
|
||||||
[#4967]: https://github.com/nymtech/nym/pull/4967
|
|
||||||
[#4966]: https://github.com/nymtech/nym/pull/4966
|
|
||||||
[#4965]: https://github.com/nymtech/nym/pull/4965
|
|
||||||
[#4963]: https://github.com/nymtech/nym/pull/4963
|
|
||||||
[#4959]: https://github.com/nymtech/nym/pull/4959
|
|
||||||
[#4957]: https://github.com/nymtech/nym/pull/4957
|
|
||||||
[#4954]: https://github.com/nymtech/nym/pull/4954
|
|
||||||
[#4953]: https://github.com/nymtech/nym/pull/4953
|
|
||||||
[#4949]: https://github.com/nymtech/nym/pull/4949
|
|
||||||
[#4948]: https://github.com/nymtech/nym/pull/4948
|
|
||||||
[#4947]: https://github.com/nymtech/nym/pull/4947
|
|
||||||
[#4945]: https://github.com/nymtech/nym/pull/4945
|
|
||||||
[#4944]: https://github.com/nymtech/nym/pull/4944
|
|
||||||
[#4943]: https://github.com/nymtech/nym/pull/4943
|
|
||||||
[#4942]: https://github.com/nymtech/nym/pull/4942
|
|
||||||
[#4938]: https://github.com/nymtech/nym/pull/4938
|
|
||||||
[#4937]: https://github.com/nymtech/nym/pull/4937
|
|
||||||
[#4936]: https://github.com/nymtech/nym/pull/4936
|
|
||||||
[#4929]: https://github.com/nymtech/nym/pull/4929
|
|
||||||
[#4903]: https://github.com/nymtech/nym/pull/4903
|
|
||||||
[#4826]: https://github.com/nymtech/nym/pull/4826
|
|
||||||
[#4758]: https://github.com/nymtech/nym/pull/4758
|
|
||||||
|
|
||||||
## [2024.12-aero] (2024-10-17)
|
|
||||||
|
|
||||||
- nym-node: don't use bloomfilters for double spending checks ([#4960])
|
|
||||||
- bugfix: replace unreachable macro with an error return ([#4958])
|
|
||||||
- [DOCs:/operators]: Update FAQ sphinx size ([#4946])
|
|
||||||
- [DOCs/operators]: Release notes v2024.11-wedel ([#4939])
|
|
||||||
- Fix handle drop ([#4934])
|
|
||||||
- Assume offline mode ([#4926])
|
|
||||||
- Make ip-packet-request VERSION pub ([#4925])
|
|
||||||
- Expose error type ([#4924])
|
|
||||||
- Fix argument to cargo-deny action ([#4922])
|
|
||||||
- Fix nymvpn.com url in mainnet defaults ([#4920])
|
|
||||||
- Check both version and type in message header ([#4918])
|
|
||||||
- Bump http-api-client default timeout to 30 sec ([#4917])
|
|
||||||
- Max/proxy ffi ([#4906])
|
|
||||||
- Data Observatory stub ([#4905])
|
|
||||||
- Fix missing duplication of modified tables ([#4904])
|
|
||||||
- Update cargo deny ([#4901])
|
|
||||||
- docs: add hostname instructions for wss ([#4900])
|
|
||||||
- build(deps): bump the patch-updates group across 1 directory with 9 updates ([#4898])
|
|
||||||
- Fix clippy for beta toolchain ([#4897])
|
|
||||||
- Remove clippy github PR annotations ([#4896])
|
|
||||||
- Fix apt install in ci-build-upload-binaries.yml ([#4894])
|
|
||||||
- Update network monitor entrypoint ([#4893])
|
|
||||||
- Update nym-vpn metapackage and replace nymvpn-x with nym-vpn-app ([#4889])
|
|
||||||
- Entry wireguard tickets ([#4888])
|
|
||||||
- Build and Push CI ([#4887])
|
|
||||||
- Feature/updated gateway registration ([#4885])
|
|
||||||
- Few fixes to NNM pre deploy ([#4883])
|
|
||||||
- Fix sql serde with enum ([#4875])
|
|
||||||
- allow clients to send stateless gateway requests without prior registration ([#4873])
|
|
||||||
- chore: remove queued migration for adding explicit admin ([#4871])
|
|
||||||
- Gateway database modifications for different modes ([#4868])
|
|
||||||
- build(deps): bump strum from 0.25.0 to 0.26.3 ([#4848])
|
|
||||||
- Use serde from workspace ([#4833])
|
|
||||||
- build(deps): bump toml from 0.5.11 to 0.8.14 ([#4805])
|
|
||||||
- Max/rust sdk stream abstraction ([#4743])
|
|
||||||
|
|
||||||
[#4960]: https://github.com/nymtech/nym/pull/4960
|
|
||||||
[#4958]: https://github.com/nymtech/nym/pull/4958
|
|
||||||
[#4946]: https://github.com/nymtech/nym/pull/4946
|
|
||||||
[#4939]: https://github.com/nymtech/nym/pull/4939
|
|
||||||
[#4934]: https://github.com/nymtech/nym/pull/4934
|
|
||||||
[#4926]: https://github.com/nymtech/nym/pull/4926
|
|
||||||
[#4925]: https://github.com/nymtech/nym/pull/4925
|
|
||||||
[#4924]: https://github.com/nymtech/nym/pull/4924
|
|
||||||
[#4922]: https://github.com/nymtech/nym/pull/4922
|
|
||||||
[#4920]: https://github.com/nymtech/nym/pull/4920
|
|
||||||
[#4918]: https://github.com/nymtech/nym/pull/4918
|
|
||||||
[#4917]: https://github.com/nymtech/nym/pull/4917
|
|
||||||
[#4906]: https://github.com/nymtech/nym/pull/4906
|
|
||||||
[#4905]: https://github.com/nymtech/nym/pull/4905
|
|
||||||
[#4904]: https://github.com/nymtech/nym/pull/4904
|
|
||||||
[#4901]: https://github.com/nymtech/nym/pull/4901
|
|
||||||
[#4900]: https://github.com/nymtech/nym/pull/4900
|
|
||||||
[#4898]: https://github.com/nymtech/nym/pull/4898
|
|
||||||
[#4897]: https://github.com/nymtech/nym/pull/4897
|
|
||||||
[#4896]: https://github.com/nymtech/nym/pull/4896
|
|
||||||
[#4894]: https://github.com/nymtech/nym/pull/4894
|
|
||||||
[#4893]: https://github.com/nymtech/nym/pull/4893
|
|
||||||
[#4889]: https://github.com/nymtech/nym/pull/4889
|
|
||||||
[#4888]: https://github.com/nymtech/nym/pull/4888
|
|
||||||
[#4887]: https://github.com/nymtech/nym/pull/4887
|
|
||||||
[#4885]: https://github.com/nymtech/nym/pull/4885
|
|
||||||
[#4883]: https://github.com/nymtech/nym/pull/4883
|
|
||||||
[#4875]: https://github.com/nymtech/nym/pull/4875
|
|
||||||
[#4873]: https://github.com/nymtech/nym/pull/4873
|
|
||||||
[#4871]: https://github.com/nymtech/nym/pull/4871
|
|
||||||
[#4868]: https://github.com/nymtech/nym/pull/4868
|
|
||||||
[#4848]: https://github.com/nymtech/nym/pull/4848
|
|
||||||
[#4833]: https://github.com/nymtech/nym/pull/4833
|
|
||||||
[#4805]: https://github.com/nymtech/nym/pull/4805
|
|
||||||
[#4743]: https://github.com/nymtech/nym/pull/4743
|
|
||||||
|
|
||||||
## [2024.11-wedel] (2024-09-23)
|
|
||||||
|
|
||||||
- Backport #4894 to fix ci ([#4899])
|
|
||||||
- Bugfix/ticketbook false double spending ([#4892])
|
|
||||||
- fix: allow updating globally stored signatures ([#4891])
|
|
||||||
- [DOCs/operators]: Document changelog for patch/2024.10-caramello ([#4886])
|
|
||||||
- [DOCs/operators]: Post release docs updates ([#4874])
|
|
||||||
- Bump defguard to github latest version ([#4872])
|
|
||||||
- chore: removed completed queued mixnet migration ([#4865])
|
|
||||||
- Disable push trigger and add missing paths in ci-build ([#4864])
|
|
||||||
- Fix linux conditional in ci-build.yml ([#4863])
|
|
||||||
- Remove golang workaround in ci-sdk-wasm ([#4858])
|
|
||||||
- Revert runner for ci-docs ([#4855])
|
|
||||||
- Move credential verification into common crate ([#4853])
|
|
||||||
- Fix test failure in ipr request size ([#4844])
|
|
||||||
- Start switching over jobs to arc-ubuntu-20.04 ([#4843])
|
|
||||||
- Use ecash credential type for bandwidth value ([#4840])
|
|
||||||
- Create nym-repo-setup debian package and nym-vpn meta package ([#4837])
|
|
||||||
- Remove serde_crate named import ([#4832])
|
|
||||||
- Run cargo autoinherit following last weeks dependabot updates ([#4831])
|
|
||||||
- revamped ticketbook serialisation and exposed additional cli methods ([#4827])
|
|
||||||
- Expose wireguard details on self described endpoint ([#4825])
|
|
||||||
- Remove unused wireguard flag from SDK ([#4823])
|
|
||||||
- Add `axum` server to `nym-api` ([#4803])
|
|
||||||
- Run cargo-autoinherit for a few new crates ([#4801])
|
|
||||||
- Update dependabot ([#4796])
|
|
||||||
- Fix clippy for unwrap_or_default ([#4783])
|
|
||||||
- Enable dependabot version upgrades for root rust workspace ([#4778])
|
|
||||||
- Persist used wireguard private IPs ([#4771])
|
|
||||||
- Avoid race on ip and registration structures ([#4766])
|
|
||||||
- docs/hotfix ([#4765])
|
|
||||||
- chore: remove repetitive words ([#4763])
|
|
||||||
- Make gateway latency check generic ([#4759])
|
|
||||||
- Remove duplicate stat count for retransmissions ([#4756])
|
|
||||||
- Update peer refresh value ([#4754])
|
|
||||||
- Remove deprecated mark_as_success and use new disarm ([#4751])
|
|
||||||
- Add get_mixnodes_described to validator_client ([#4725])
|
|
||||||
- New Network Monitor ([#4610])
|
|
||||||
|
|
||||||
[#4899]: https://github.com/nymtech/nym/pull/4899
|
|
||||||
[#4892]: https://github.com/nymtech/nym/pull/4892
|
|
||||||
[#4891]: https://github.com/nymtech/nym/pull/4891
|
|
||||||
[#4886]: https://github.com/nymtech/nym/pull/4886
|
|
||||||
[#4874]: https://github.com/nymtech/nym/pull/4874
|
|
||||||
[#4872]: https://github.com/nymtech/nym/pull/4872
|
|
||||||
[#4865]: https://github.com/nymtech/nym/pull/4865
|
|
||||||
[#4864]: https://github.com/nymtech/nym/pull/4864
|
|
||||||
[#4863]: https://github.com/nymtech/nym/pull/4863
|
|
||||||
[#4858]: https://github.com/nymtech/nym/pull/4858
|
|
||||||
[#4855]: https://github.com/nymtech/nym/pull/4855
|
|
||||||
[#4853]: https://github.com/nymtech/nym/pull/4853
|
|
||||||
[#4844]: https://github.com/nymtech/nym/pull/4844
|
|
||||||
[#4843]: https://github.com/nymtech/nym/pull/4843
|
|
||||||
[#4840]: https://github.com/nymtech/nym/pull/4840
|
|
||||||
[#4837]: https://github.com/nymtech/nym/pull/4837
|
|
||||||
[#4832]: https://github.com/nymtech/nym/pull/4832
|
|
||||||
[#4831]: https://github.com/nymtech/nym/pull/4831
|
|
||||||
[#4827]: https://github.com/nymtech/nym/pull/4827
|
|
||||||
[#4825]: https://github.com/nymtech/nym/pull/4825
|
|
||||||
[#4823]: https://github.com/nymtech/nym/pull/4823
|
|
||||||
[#4803]: https://github.com/nymtech/nym/pull/4803
|
|
||||||
[#4801]: https://github.com/nymtech/nym/pull/4801
|
|
||||||
[#4796]: https://github.com/nymtech/nym/pull/4796
|
|
||||||
[#4783]: https://github.com/nymtech/nym/pull/4783
|
|
||||||
[#4778]: https://github.com/nymtech/nym/pull/4778
|
|
||||||
[#4771]: https://github.com/nymtech/nym/pull/4771
|
|
||||||
[#4766]: https://github.com/nymtech/nym/pull/4766
|
|
||||||
[#4765]: https://github.com/nymtech/nym/pull/4765
|
|
||||||
[#4763]: https://github.com/nymtech/nym/pull/4763
|
|
||||||
[#4759]: https://github.com/nymtech/nym/pull/4759
|
|
||||||
[#4756]: https://github.com/nymtech/nym/pull/4756
|
|
||||||
[#4754]: https://github.com/nymtech/nym/pull/4754
|
|
||||||
[#4751]: https://github.com/nymtech/nym/pull/4751
|
|
||||||
[#4725]: https://github.com/nymtech/nym/pull/4725
|
|
||||||
[#4610]: https://github.com/nymtech/nym/pull/4610
|
|
||||||
|
|
||||||
## [2024.10-caramello] (2024-09-10)
|
## [2024.10-caramello] (2024-09-10)
|
||||||
|
|
||||||
- Backport 4844 and 4845 ([#4857])
|
- Backport 4844 and 4845 ([#4857])
|
||||||
|
|||||||
Generated
+823
-1623
File diff suppressed because it is too large
Load Diff
+43
-84
@@ -19,33 +19,33 @@ members = [
|
|||||||
"clients/native",
|
"clients/native",
|
||||||
"clients/native/websocket-requests",
|
"clients/native/websocket-requests",
|
||||||
"clients/socks5",
|
"clients/socks5",
|
||||||
"common/async-file-watcher",
|
|
||||||
"common/authenticator-requests",
|
"common/authenticator-requests",
|
||||||
|
"common/async-file-watcher",
|
||||||
"common/bandwidth-controller",
|
"common/bandwidth-controller",
|
||||||
"common/bin-common",
|
"common/bin-common",
|
||||||
"common/client-core",
|
"common/client-core",
|
||||||
"common/client-core/config-types",
|
"common/client-core/config-types",
|
||||||
"common/client-core/gateways-storage",
|
|
||||||
"common/client-core/surb-storage",
|
"common/client-core/surb-storage",
|
||||||
|
"common/client-core/gateways-storage",
|
||||||
"common/client-libs/gateway-client",
|
"common/client-libs/gateway-client",
|
||||||
"common/client-libs/mixnet-client",
|
"common/client-libs/mixnet-client",
|
||||||
"common/client-libs/validator-client",
|
"common/client-libs/validator-client",
|
||||||
"common/commands",
|
"common/commands",
|
||||||
"common/config",
|
"common/config",
|
||||||
"common/cosmwasm-smart-contracts/coconut-bandwidth-contract",
|
"common/cosmwasm-smart-contracts/coconut-bandwidth-contract",
|
||||||
|
"common/cosmwasm-smart-contracts/ecash-contract",
|
||||||
"common/cosmwasm-smart-contracts/coconut-dkg",
|
"common/cosmwasm-smart-contracts/coconut-dkg",
|
||||||
"common/cosmwasm-smart-contracts/contracts-common",
|
"common/cosmwasm-smart-contracts/contracts-common",
|
||||||
"common/cosmwasm-smart-contracts/ecash-contract",
|
|
||||||
"common/cosmwasm-smart-contracts/group-contract",
|
"common/cosmwasm-smart-contracts/group-contract",
|
||||||
"common/cosmwasm-smart-contracts/mixnet-contract",
|
"common/cosmwasm-smart-contracts/mixnet-contract",
|
||||||
"common/cosmwasm-smart-contracts/multisig-contract",
|
"common/cosmwasm-smart-contracts/multisig-contract",
|
||||||
"common/cosmwasm-smart-contracts/vesting-contract",
|
"common/cosmwasm-smart-contracts/vesting-contract",
|
||||||
"common/country-group",
|
"common/country-group",
|
||||||
"common/credential-storage",
|
"common/credential-storage",
|
||||||
"common/credential-utils",
|
|
||||||
"common/credential-verification",
|
|
||||||
"common/credentials",
|
"common/credentials",
|
||||||
|
"common/credential-utils",
|
||||||
"common/credentials-interface",
|
"common/credentials-interface",
|
||||||
|
"common/credential-verification",
|
||||||
"common/crypto",
|
"common/crypto",
|
||||||
"common/dkg",
|
"common/dkg",
|
||||||
"common/ecash-double-spending",
|
"common/ecash-double-spending",
|
||||||
@@ -54,21 +54,19 @@ members = [
|
|||||||
"common/exit-policy",
|
"common/exit-policy",
|
||||||
"common/gateway-requests",
|
"common/gateway-requests",
|
||||||
"common/gateway-storage",
|
"common/gateway-storage",
|
||||||
"common/gateway-stats-storage",
|
|
||||||
"common/http-api-client",
|
"common/http-api-client",
|
||||||
"common/http-api-common",
|
"common/http-api-common",
|
||||||
"common/inclusion-probability",
|
"common/inclusion-probability",
|
||||||
"common/ip-packet-requests",
|
"common/ip-packet-requests",
|
||||||
"common/ledger",
|
"common/ledger",
|
||||||
"common/mixnode-common",
|
"common/mixnode-common",
|
||||||
"common/models",
|
|
||||||
"common/network-defaults",
|
"common/network-defaults",
|
||||||
"common/node-tester-utils",
|
"common/node-tester-utils",
|
||||||
"common/nonexhaustive-delayqueue",
|
"common/nonexhaustive-delayqueue",
|
||||||
|
"common/nymcoconut",
|
||||||
|
"common/nym_offline_compact_ecash",
|
||||||
"common/nym-id",
|
"common/nym-id",
|
||||||
"common/nym-metrics",
|
"common/nym-metrics",
|
||||||
"common/nym_offline_compact_ecash",
|
|
||||||
"common/nymcoconut",
|
|
||||||
"common/nymsphinx",
|
"common/nymsphinx",
|
||||||
"common/nymsphinx/acknowledgements",
|
"common/nymsphinx/acknowledgements",
|
||||||
"common/nymsphinx/addressing",
|
"common/nymsphinx/addressing",
|
||||||
@@ -83,14 +81,11 @@ members = [
|
|||||||
"common/nyxd-scraper",
|
"common/nyxd-scraper",
|
||||||
"common/pemstore",
|
"common/pemstore",
|
||||||
"common/serde-helpers",
|
"common/serde-helpers",
|
||||||
"common/service-provider-requests-common",
|
|
||||||
"common/socks5-client-core",
|
"common/socks5-client-core",
|
||||||
"common/socks5/proxy-helpers",
|
"common/socks5/proxy-helpers",
|
||||||
"common/socks5/requests",
|
"common/socks5/requests",
|
||||||
"common/statistics",
|
|
||||||
"common/store-cipher",
|
"common/store-cipher",
|
||||||
"common/task",
|
"common/task",
|
||||||
"common/ticketbooks-merkle",
|
|
||||||
"common/topology",
|
"common/topology",
|
||||||
"common/tun",
|
"common/tun",
|
||||||
"common/types",
|
"common/types",
|
||||||
@@ -99,38 +94,27 @@ members = [
|
|||||||
"common/wasm/utils",
|
"common/wasm/utils",
|
||||||
"common/wireguard",
|
"common/wireguard",
|
||||||
"common/wireguard-types",
|
"common/wireguard-types",
|
||||||
# "documentation/autodoc",
|
|
||||||
"explorer-api",
|
"explorer-api",
|
||||||
"explorer-api/explorer-api-requests",
|
"explorer-api/explorer-api-requests",
|
||||||
"explorer-api/explorer-client",
|
"explorer-api/explorer-client",
|
||||||
"gateway",
|
"gateway",
|
||||||
"integrations/bity",
|
"integrations/bity",
|
||||||
"mixnode",
|
"mixnode",
|
||||||
"sdk/ffi/cpp",
|
|
||||||
"sdk/ffi/go",
|
|
||||||
"sdk/ffi/shared",
|
|
||||||
"sdk/lib/socks5-listener",
|
"sdk/lib/socks5-listener",
|
||||||
"sdk/rust/nym-sdk",
|
"sdk/rust/nym-sdk",
|
||||||
"service-providers/authenticator",
|
"service-providers/authenticator",
|
||||||
"service-providers/common",
|
"service-providers/common",
|
||||||
"service-providers/ip-packet-router",
|
"service-providers/ip-packet-router",
|
||||||
"service-providers/network-requester",
|
"service-providers/network-requester",
|
||||||
"nym-api",
|
|
||||||
"nym-api/nym-api-requests",
|
|
||||||
"nym-browser-extension/storage",
|
|
||||||
"nym-credential-proxy/nym-credential-proxy",
|
|
||||||
"nym-credential-proxy/nym-credential-proxy-requests",
|
|
||||||
"nym-credential-proxy/vpn-api-lib-wasm",
|
|
||||||
"nym-data-observatory",
|
|
||||||
"nym-network-monitor",
|
"nym-network-monitor",
|
||||||
|
"nym-api",
|
||||||
|
"nym-browser-extension/storage",
|
||||||
|
"nym-api/nym-api-requests",
|
||||||
"nym-node",
|
"nym-node",
|
||||||
"nym-node/nym-node-http-api",
|
"nym-node/nym-node-http-api",
|
||||||
"nym-node/nym-node-requests",
|
"nym-node/nym-node-requests",
|
||||||
"nym-node-status-api",
|
|
||||||
"nym-node-status-agent",
|
|
||||||
"nym-outfox",
|
"nym-outfox",
|
||||||
"nym-validator-rewarder",
|
"nym-validator-rewarder",
|
||||||
"tools/echo-server",
|
|
||||||
"tools/internal/ssl-inject",
|
"tools/internal/ssl-inject",
|
||||||
# "tools/internal/sdk-version-bump",
|
# "tools/internal/sdk-version-bump",
|
||||||
"tools/internal/testnet-manager",
|
"tools/internal/testnet-manager",
|
||||||
@@ -145,27 +129,17 @@ members = [
|
|||||||
"wasm/mix-fetch",
|
"wasm/mix-fetch",
|
||||||
"wasm/node-tester",
|
"wasm/node-tester",
|
||||||
"wasm/zknym-lib",
|
"wasm/zknym-lib",
|
||||||
"tools/echo-server",
|
|
||||||
"tools/internal/contract-state-importer/importer-cli",
|
|
||||||
"tools/internal/contract-state-importer/importer-contract",
|
|
||||||
"tools/internal/testnet-manager",
|
|
||||||
"tools/internal/testnet-manager/dkg-bypass-contract",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
default-members = [
|
default-members = [
|
||||||
"clients/native",
|
"clients/native",
|
||||||
"clients/socks5",
|
"clients/socks5",
|
||||||
"common/models",
|
|
||||||
"explorer-api",
|
"explorer-api",
|
||||||
"gateway",
|
"gateway",
|
||||||
"mixnode",
|
"mixnode",
|
||||||
"nym-api",
|
"nym-api",
|
||||||
"nym-credential-proxy/nym-credential-proxy",
|
|
||||||
"nym-data-observatory",
|
|
||||||
"nym-node",
|
"nym-node",
|
||||||
"nym-node-status-api",
|
|
||||||
"nym-validator-rewarder",
|
"nym-validator-rewarder",
|
||||||
"nym-node-status-api",
|
|
||||||
"service-providers/authenticator",
|
"service-providers/authenticator",
|
||||||
"service-providers/ip-packet-router",
|
"service-providers/ip-packet-router",
|
||||||
"service-providers/network-requester",
|
"service-providers/network-requester",
|
||||||
@@ -178,6 +152,7 @@ exclude = [
|
|||||||
"nym-wallet",
|
"nym-wallet",
|
||||||
"nym-vpn/ui/src-tauri",
|
"nym-vpn/ui/src-tauri",
|
||||||
"cpu-cycles",
|
"cpu-cycles",
|
||||||
|
"sdk/ffi/cpp",
|
||||||
]
|
]
|
||||||
|
|
||||||
[workspace.package]
|
[workspace.package]
|
||||||
@@ -194,24 +169,24 @@ readme = "README.md"
|
|||||||
addr = "0.15.6"
|
addr = "0.15.6"
|
||||||
aes = "0.8.1"
|
aes = "0.8.1"
|
||||||
aes-gcm = "0.10.1"
|
aes-gcm = "0.10.1"
|
||||||
aes-gcm-siv = "0.11.1"
|
anyhow = "1.0.87"
|
||||||
aead = "0.5.2"
|
|
||||||
anyhow = "1.0.90"
|
|
||||||
argon2 = "0.5.0"
|
argon2 = "0.5.0"
|
||||||
async-trait = "0.1.83"
|
async-trait = "0.1.82"
|
||||||
axum-client-ip = "0.6.1"
|
|
||||||
axum = "0.7.5"
|
axum = "0.7.5"
|
||||||
axum-extra = "0.9.4"
|
axum-extra = "0.9.3"
|
||||||
base64 = "0.22.1"
|
base64 = "0.22.1"
|
||||||
bincode = "1.3.3"
|
bincode = "1.3.3"
|
||||||
bip39 = { version = "2.0.0", features = ["zeroize"] }
|
bip39 = { version = "2.0.0", features = ["zeroize"] }
|
||||||
bit-vec = "0.7.0" # can we unify those?
|
|
||||||
|
# can we unify those?
|
||||||
|
bit-vec = "0.7.0"
|
||||||
bitvec = "1.0.0"
|
bitvec = "1.0.0"
|
||||||
|
|
||||||
blake3 = "1.5.4"
|
blake3 = "1.5.4"
|
||||||
bloomfilter = "1.0.14"
|
bloomfilter = "1.0.14"
|
||||||
bs58 = "0.5.1"
|
bs58 = "0.5.1"
|
||||||
bytecodec = "0.4.15"
|
bytecodec = "0.4.15"
|
||||||
bytes = "1.7.2"
|
bytes = "1.7.1"
|
||||||
cargo_metadata = "0.18.1"
|
cargo_metadata = "0.18.1"
|
||||||
celes = "2.4.0"
|
celes = "2.4.0"
|
||||||
cfg-if = "1.0.0"
|
cfg-if = "1.0.0"
|
||||||
@@ -219,11 +194,11 @@ chacha20 = "0.9.0"
|
|||||||
chacha20poly1305 = "0.10.1"
|
chacha20poly1305 = "0.10.1"
|
||||||
chrono = "0.4.31"
|
chrono = "0.4.31"
|
||||||
cipher = "0.4.3"
|
cipher = "0.4.3"
|
||||||
clap = "4.5.20"
|
clap = "4.5.17"
|
||||||
clap_complete = "4.5"
|
clap_complete = "4.5"
|
||||||
clap_complete_fig = "4.5"
|
clap_complete_fig = "4.5"
|
||||||
colored = "2.0"
|
colored = "2.0"
|
||||||
comfy-table = "7.1.1"
|
comfy-table = "6.0.0"
|
||||||
console = "0.15.8"
|
console = "0.15.8"
|
||||||
console-subscriber = "0.1.1"
|
console-subscriber = "0.1.1"
|
||||||
console_error_panic_hook = "0.1"
|
console_error_panic_hook = "0.1"
|
||||||
@@ -235,8 +210,7 @@ ctr = "0.9.1"
|
|||||||
cupid = "0.6.1"
|
cupid = "0.6.1"
|
||||||
curve25519-dalek = "4.1"
|
curve25519-dalek = "4.1"
|
||||||
dashmap = "5.5.3"
|
dashmap = "5.5.3"
|
||||||
# We want https://github.com/DefGuard/wireguard-rs/pull/64 , but there's no crates.io release being pushed out anymore
|
defguard_wireguard_rs = "0.4.2"
|
||||||
defguard_wireguard_rs = { git = "https://github.com/DefGuard/wireguard-rs.git", rev = "v0.4.7" }
|
|
||||||
digest = "0.10.7"
|
digest = "0.10.7"
|
||||||
dirs = "5.0"
|
dirs = "5.0"
|
||||||
doc-comment = "0.3"
|
doc-comment = "0.3"
|
||||||
@@ -244,15 +218,13 @@ dotenvy = "0.15.6"
|
|||||||
ecdsa = "0.16"
|
ecdsa = "0.16"
|
||||||
ed25519-dalek = "2.1"
|
ed25519-dalek = "2.1"
|
||||||
etherparse = "0.13.0"
|
etherparse = "0.13.0"
|
||||||
envy = "0.4"
|
|
||||||
eyre = "0.6.9"
|
eyre = "0.6.9"
|
||||||
fastrand = "2.1.1"
|
fastrand = "2.1.1"
|
||||||
flate2 = "1.0.34"
|
flate2 = "1.0.33"
|
||||||
futures = "0.3.28"
|
futures = "0.3.28"
|
||||||
futures-util = "0.3"
|
|
||||||
generic-array = "0.14.7"
|
generic-array = "0.14.7"
|
||||||
getrandom = "0.2.10"
|
getrandom = "0.2.10"
|
||||||
getset = "0.1.3"
|
getset = "0.1.1"
|
||||||
handlebars = "3.5.5"
|
handlebars = "3.5.5"
|
||||||
headers = "0.4.0"
|
headers = "0.4.0"
|
||||||
hex = "0.4.3"
|
hex = "0.4.3"
|
||||||
@@ -260,12 +232,10 @@ hex-literal = "0.3.3"
|
|||||||
hkdf = "0.12.3"
|
hkdf = "0.12.3"
|
||||||
hmac = "0.12.1"
|
hmac = "0.12.1"
|
||||||
http = "1"
|
http = "1"
|
||||||
http-body-util = "0.1"
|
|
||||||
httpcodec = "0.2.3"
|
httpcodec = "0.2.3"
|
||||||
humantime = "2.1.0"
|
humantime = "2.1.0"
|
||||||
humantime-serde = "1.1.1"
|
humantime-serde = "1.1.1"
|
||||||
hyper = "1.4.1"
|
hyper = "1.3.1"
|
||||||
hyper-util = "0.1"
|
|
||||||
indicatif = "0.17.8"
|
indicatif = "0.17.8"
|
||||||
inquire = "0.6.2"
|
inquire = "0.6.2"
|
||||||
ip_network = "0.4.1"
|
ip_network = "0.4.1"
|
||||||
@@ -273,25 +243,22 @@ ipnetwork = "0.20"
|
|||||||
isocountry = "0.3.2"
|
isocountry = "0.3.2"
|
||||||
itertools = "0.13.0"
|
itertools = "0.13.0"
|
||||||
k256 = "0.13"
|
k256 = "0.13"
|
||||||
lazy_static = "1.5.0"
|
lazy_static = "1.4.0"
|
||||||
ledger-transport = "0.10.0"
|
ledger-transport = "0.10.0"
|
||||||
ledger-transport-hid = "0.10.0"
|
ledger-transport-hid = "0.10.0"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
maxminddb = "0.23.0"
|
maxminddb = "0.23.0"
|
||||||
rs_merkle = "1.4.2"
|
|
||||||
mime = "0.3.17"
|
mime = "0.3.17"
|
||||||
moka = { version = "0.12", features = ["future"] }
|
|
||||||
nix = "0.27.1"
|
nix = "0.27.1"
|
||||||
notify = "5.1.0"
|
notify = "5.1.0"
|
||||||
okapi = "0.7.0"
|
okapi = "0.7.0"
|
||||||
once_cell = "1.20.2"
|
once_cell = "1.7.2"
|
||||||
opentelemetry = "0.19.0"
|
opentelemetry = "0.19.0"
|
||||||
opentelemetry-jaeger = "0.18.0"
|
opentelemetry-jaeger = "0.18.0"
|
||||||
parking_lot = "0.12.3"
|
parking_lot = "0.12.3"
|
||||||
pem = "0.8"
|
pem = "0.8"
|
||||||
petgraph = "0.6.5"
|
petgraph = "0.6.5"
|
||||||
pin-project = "1.1"
|
pin-project = "1.0"
|
||||||
pin-project-lite = "0.2.14"
|
|
||||||
pretty_env_logger = "0.4.0"
|
pretty_env_logger = "0.4.0"
|
||||||
publicsuffix = "2.2.3"
|
publicsuffix = "2.2.3"
|
||||||
quote = "1"
|
quote = "1"
|
||||||
@@ -307,35 +274,32 @@ reqwest = { version = "0.12.4", default-features = false }
|
|||||||
rocket = "0.5.0"
|
rocket = "0.5.0"
|
||||||
rocket_cors = "0.6.0"
|
rocket_cors = "0.6.0"
|
||||||
rocket_okapi = "0.8.0"
|
rocket_okapi = "0.8.0"
|
||||||
safer-ffi = "0.1.13"
|
safer-ffi = "0.1.12"
|
||||||
schemars = "0.8.21"
|
schemars = "0.8.21"
|
||||||
semver = "1.0.23"
|
semver = "1.0.23"
|
||||||
serde = "1.0.211"
|
serde = "1.0.210"
|
||||||
serde_bytes = "0.11.15"
|
serde_bytes = "0.11.15"
|
||||||
serde_derive = "1.0"
|
serde_derive = "1.0"
|
||||||
serde_json = "1.0.132"
|
serde_json = "1.0.128"
|
||||||
serde_json_path = "0.7.1"
|
|
||||||
serde_repr = "0.1"
|
serde_repr = "0.1"
|
||||||
serde_with = "3.9.0"
|
serde_with = "3.9.0"
|
||||||
serde_yaml = "0.9.25"
|
serde_yaml = "0.9.25"
|
||||||
sha2 = "0.10.8"
|
sha2 = "0.10.8"
|
||||||
si-scale = "0.2.3"
|
si-scale = "0.2.3"
|
||||||
sphinx-packet = "0.1.1"
|
sphinx-packet = "0.1.1"
|
||||||
sqlx = "0.7.4"
|
sqlx = "0.6.3"
|
||||||
strum = "0.26"
|
strum = "0.26"
|
||||||
strum_macros = "0.26"
|
|
||||||
subtle-encoding = "0.5"
|
subtle-encoding = "0.5"
|
||||||
syn = "1"
|
syn = "1"
|
||||||
sysinfo = "0.30.13"
|
sysinfo = "0.30.12"
|
||||||
tap = "1.0.1"
|
tap = "1.0.1"
|
||||||
tar = "0.4.42"
|
tar = "0.4.41"
|
||||||
tempfile = "3.14"
|
tempfile = "3.5.0"
|
||||||
thiserror = "1.0.64"
|
thiserror = "1.0.63"
|
||||||
time = "0.3.30"
|
time = "0.3.30"
|
||||||
tokio = "1.39"
|
tokio = "1.39"
|
||||||
tokio-stream = "0.1.16"
|
tokio-stream = "0.1.16"
|
||||||
tokio-test = "0.4.4"
|
tokio-test = "0.4.4"
|
||||||
tokio-tun = "0.11.5"
|
|
||||||
tokio-tungstenite = { version = "0.20.1" }
|
tokio-tungstenite = { version = "0.20.1" }
|
||||||
tokio-util = "0.7.12"
|
tokio-util = "0.7.12"
|
||||||
toml = "0.8.14"
|
toml = "0.8.14"
|
||||||
@@ -345,11 +309,11 @@ tracing = "0.1.37"
|
|||||||
tracing-opentelemetry = "0.19.0"
|
tracing-opentelemetry = "0.19.0"
|
||||||
tracing-subscriber = "0.3.16"
|
tracing-subscriber = "0.3.16"
|
||||||
tracing-tree = "0.2.2"
|
tracing-tree = "0.2.2"
|
||||||
tracing-log = "0.2"
|
ts-rs = "7.0.0"
|
||||||
ts-rs = "10.0.0"
|
|
||||||
tungstenite = { version = "0.20.1", default-features = false }
|
tungstenite = { version = "0.20.1", default-features = false }
|
||||||
url = "2.5"
|
url = "2.5"
|
||||||
utoipa = "4.2"
|
utoipa = "4.2"
|
||||||
|
utoipa-rapidoc = "4.0"
|
||||||
utoipa-swagger-ui = "7.1"
|
utoipa-swagger-ui = "7.1"
|
||||||
utoipauto = "0.1"
|
utoipauto = "0.1"
|
||||||
uuid = "*"
|
uuid = "*"
|
||||||
@@ -368,9 +332,9 @@ prometheus = { version = "0.13.0" }
|
|||||||
bls12_381 = { git = "https://github.com/jstuczyn/bls12_381", default-features = false, branch = "temp/experimental-serdect" }
|
bls12_381 = { git = "https://github.com/jstuczyn/bls12_381", default-features = false, branch = "temp/experimental-serdect" }
|
||||||
group = { version = "0.13.0", default-features = false }
|
group = { version = "0.13.0", default-features = false }
|
||||||
ff = { version = "0.13.0", default-features = false }
|
ff = { version = "0.13.0", default-features = false }
|
||||||
subtle = "2.5.0"
|
|
||||||
|
|
||||||
# cosmwasm-related
|
# cosmwasm-related
|
||||||
|
cosmwasm-derive = "=1.4.3"
|
||||||
cosmwasm-schema = "=1.4.3"
|
cosmwasm-schema = "=1.4.3"
|
||||||
cosmwasm-std = "=1.4.3"
|
cosmwasm-std = "=1.4.3"
|
||||||
# use 0.5.0 as that's the version used by cosmwasm-std 1.4.3
|
# use 0.5.0 as that's the version used by cosmwasm-std 1.4.3
|
||||||
@@ -407,19 +371,14 @@ indexed_db_futures = { git = "https://github.com/TiemenSch/rust-indexed-db", bra
|
|||||||
js-sys = "0.3.70"
|
js-sys = "0.3.70"
|
||||||
serde-wasm-bindgen = "0.6.5"
|
serde-wasm-bindgen = "0.6.5"
|
||||||
tsify = "0.4.5"
|
tsify = "0.4.5"
|
||||||
wasm-bindgen = "0.2.95"
|
wasm-bindgen = "0.2.93"
|
||||||
wasm-bindgen-futures = "0.4.45"
|
wasm-bindgen-futures = "0.4.43"
|
||||||
wasmtimer = "0.2.0"
|
wasmtimer = "0.2.0"
|
||||||
web-sys = "0.3.72"
|
web-sys = "0.3.70"
|
||||||
|
|
||||||
|
|
||||||
# Profile settings for individual crates
|
# Profile settings for individual crates
|
||||||
|
|
||||||
# Compile-time verified queries do quite a bit of work at compile time. Incremental
|
|
||||||
# actions like cargo check and cargo build can be significantly faster when
|
|
||||||
# using an optimized build
|
|
||||||
[profile.dev.package.sqlx-macros]
|
|
||||||
opt-level = 3
|
|
||||||
|
|
||||||
[profile.release.package.nym-socks5-listener]
|
[profile.release.package.nym-socks5-listener]
|
||||||
strip = true
|
strip = true
|
||||||
codegen-units = 1
|
codegen-units = 1
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "nym-client"
|
name = "nym-client"
|
||||||
version = "1.1.45"
|
version = "1.1.40"
|
||||||
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jędrzej Stuczyński <andrew@nymtech.net>"]
|
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jędrzej Stuczyński <andrew@nymtech.net>"]
|
||||||
description = "Implementation of the Nym Client"
|
description = "Implementation of the Nym Client"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|||||||
@@ -102,10 +102,5 @@ average_ack_delay = '{{ debug.acknowledgements.average_ack_delay }}'
|
|||||||
[debug.cover_traffic]
|
[debug.cover_traffic]
|
||||||
loop_cover_traffic_average_delay = '{{ debug.cover_traffic.loop_cover_traffic_average_delay }}'
|
loop_cover_traffic_average_delay = '{{ debug.cover_traffic.loop_cover_traffic_average_delay }}'
|
||||||
|
|
||||||
[debug.stats_reporting]
|
|
||||||
enabled = {{ debug.stats_reporting.enabled }}
|
|
||||||
provider_address = '{{ debug.stats_reporting.provider_address }}'
|
|
||||||
reporting_interval = '{{ debug.stats_reporting.reporting_interval }}'
|
|
||||||
|
|
||||||
|
|
||||||
"#;
|
"#;
|
||||||
|
|||||||
@@ -81,7 +81,6 @@ impl From<Init> for OverrideConfig {
|
|||||||
|
|
||||||
nyxd_urls: init_config.common_args.nyxd_urls,
|
nyxd_urls: init_config.common_args.nyxd_urls,
|
||||||
enabled_credentials_mode: init_config.common_args.enabled_credentials_mode,
|
enabled_credentials_mode: init_config.common_args.enabled_credentials_mode,
|
||||||
stats_reporting_address: init_config.common_args.stats_reporting_address,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ use clap::{Parser, Subcommand};
|
|||||||
use log::{error, info};
|
use log::{error, info};
|
||||||
use nym_bin_common::bin_info;
|
use nym_bin_common::bin_info;
|
||||||
use nym_bin_common::completions::{fig_generate, ArgShell};
|
use nym_bin_common::completions::{fig_generate, ArgShell};
|
||||||
use nym_client::client::Recipient;
|
|
||||||
use nym_client_core::cli_helpers::CliClient;
|
use nym_client_core::cli_helpers::CliClient;
|
||||||
use nym_client_core::client::base_client::storage::migration_helpers::v1_1_33;
|
use nym_client_core::client::base_client::storage::migration_helpers::v1_1_33;
|
||||||
use nym_config::OptionalSet;
|
use nym_config::OptionalSet;
|
||||||
@@ -105,7 +104,6 @@ pub(crate) struct OverrideConfig {
|
|||||||
no_cover: bool,
|
no_cover: bool,
|
||||||
nyxd_urls: Option<Vec<url::Url>>,
|
nyxd_urls: Option<Vec<url::Url>>,
|
||||||
enabled_credentials_mode: Option<bool>,
|
enabled_credentials_mode: Option<bool>,
|
||||||
stats_reporting_address: Option<Recipient>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn execute(args: Cli) -> Result<(), Box<dyn Error + Send + Sync>> {
|
pub(crate) async fn execute(args: Cli) -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
@@ -151,11 +149,6 @@ pub(crate) fn override_config(config: Config, args: OverrideConfig) -> Config {
|
|||||||
BaseClientConfig::with_disabled_credentials,
|
BaseClientConfig::with_disabled_credentials,
|
||||||
args.enabled_credentials_mode.map(|b| !b),
|
args.enabled_credentials_mode.map(|b| !b),
|
||||||
)
|
)
|
||||||
.with_optional_env_ext(
|
|
||||||
BaseClientConfig::with_enabled_stats_reporting_address,
|
|
||||||
args.stats_reporting_address,
|
|
||||||
nym_network_defaults::var_names::CLIENT_STATS_COLLECTION_PROVIDER,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn try_upgrade_v1_1_13_config(id: &str) -> Result<bool, ClientError> {
|
async fn try_upgrade_v1_1_13_config(id: &str) -> Result<bool, ClientError> {
|
||||||
|
|||||||
@@ -43,7 +43,6 @@ impl From<Run> for OverrideConfig {
|
|||||||
no_cover: run_config.common_args.no_cover,
|
no_cover: run_config.common_args.no_cover,
|
||||||
nyxd_urls: run_config.common_args.nyxd_urls,
|
nyxd_urls: run_config.common_args.nyxd_urls,
|
||||||
enabled_credentials_mode: run_config.common_args.enabled_credentials_mode,
|
enabled_credentials_mode: run_config.common_args.enabled_credentials_mode,
|
||||||
stats_reporting_address: run_config.common_args.stats_reporting_address,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "nym-socks5-client"
|
name = "nym-socks5-client"
|
||||||
version = "1.1.45"
|
version = "1.1.40"
|
||||||
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"]
|
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"]
|
||||||
description = "A SOCKS5 localhost proxy that converts incoming messages to Sphinx and sends them to a Nym address"
|
description = "A SOCKS5 localhost proxy that converts incoming messages to Sphinx and sends them to a Nym address"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|||||||
@@ -92,7 +92,6 @@ impl From<Init> for OverrideConfig {
|
|||||||
nyxd_urls: init_config.common_args.nyxd_urls,
|
nyxd_urls: init_config.common_args.nyxd_urls,
|
||||||
enabled_credentials_mode: init_config.common_args.enabled_credentials_mode,
|
enabled_credentials_mode: init_config.common_args.enabled_credentials_mode,
|
||||||
outfox: false,
|
outfox: false,
|
||||||
stats_reporting_address: init_config.common_args.stats_reporting_address,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ use nym_client_core::client::base_client::storage::migration_helpers::v1_1_33;
|
|||||||
use nym_client_core::client::topology_control::geo_aware_provider::CountryGroup;
|
use nym_client_core::client::topology_control::geo_aware_provider::CountryGroup;
|
||||||
use nym_client_core::config::{GroupBy, TopologyStructure};
|
use nym_client_core::config::{GroupBy, TopologyStructure};
|
||||||
use nym_config::OptionalSet;
|
use nym_config::OptionalSet;
|
||||||
use nym_sphinx::addressing::Recipient;
|
|
||||||
use nym_sphinx::params::{PacketSize, PacketType};
|
use nym_sphinx::params::{PacketSize, PacketType};
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::net::IpAddr;
|
use std::net::IpAddr;
|
||||||
@@ -112,7 +111,6 @@ pub(crate) struct OverrideConfig {
|
|||||||
nyxd_urls: Option<Vec<url::Url>>,
|
nyxd_urls: Option<Vec<url::Url>>,
|
||||||
enabled_credentials_mode: Option<bool>,
|
enabled_credentials_mode: Option<bool>,
|
||||||
outfox: bool,
|
outfox: bool,
|
||||||
stats_reporting_address: Option<Recipient>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn execute(args: Cli) -> Result<(), Box<dyn Error + Send + Sync>> {
|
pub(crate) async fn execute(args: Cli) -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
@@ -198,11 +196,6 @@ pub(crate) fn override_config(config: Config, args: OverrideConfig) -> Config {
|
|||||||
BaseClientConfig::with_disabled_credentials,
|
BaseClientConfig::with_disabled_credentials,
|
||||||
args.enabled_credentials_mode.map(|b| !b),
|
args.enabled_credentials_mode.map(|b| !b),
|
||||||
)
|
)
|
||||||
.with_optional_base_env(
|
|
||||||
BaseClientConfig::with_enabled_stats_reporting_address,
|
|
||||||
args.stats_reporting_address,
|
|
||||||
nym_network_defaults::var_names::CLIENT_STATS_COLLECTION_PROVIDER,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn try_upgrade_v1_1_13_config(id: &str) -> Result<bool, Socks5ClientError> {
|
async fn try_upgrade_v1_1_13_config(id: &str) -> Result<bool, Socks5ClientError> {
|
||||||
|
|||||||
@@ -70,7 +70,6 @@ impl From<Run> for OverrideConfig {
|
|||||||
nyxd_urls: run_config.common_args.nyxd_urls,
|
nyxd_urls: run_config.common_args.nyxd_urls,
|
||||||
enabled_credentials_mode: run_config.common_args.enabled_credentials_mode,
|
enabled_credentials_mode: run_config.common_args.enabled_credentials_mode,
|
||||||
outfox: run_config.outfox,
|
outfox: run_config.outfox,
|
||||||
stats_reporting_address: run_config.common_args.stats_reporting_address,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -108,9 +108,4 @@ average_ack_delay = '{{ core.debug.acknowledgements.average_ack_delay }}'
|
|||||||
[core.debug.cover_traffic]
|
[core.debug.cover_traffic]
|
||||||
loop_cover_traffic_average_delay = '{{ core.debug.cover_traffic.loop_cover_traffic_average_delay }}'
|
loop_cover_traffic_average_delay = '{{ core.debug.cover_traffic.loop_cover_traffic_average_delay }}'
|
||||||
|
|
||||||
[core.debug.stats_reporting]
|
|
||||||
enabled = {{ core.debug.stats_reporting.enabled }}
|
|
||||||
provider_address = '{{ core.debug.stats_reporting.provider_address }}'
|
|
||||||
reporting_interval = '{{ core.debug.stats_reporting.reporting_interval }}'
|
|
||||||
|
|
||||||
"#;
|
"#;
|
||||||
|
|||||||
@@ -9,25 +9,9 @@ edition.workspace = true
|
|||||||
license.workspace = true
|
license.workspace = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
base64 = { workspace = true }
|
|
||||||
bincode = { workspace = true }
|
bincode = { workspace = true }
|
||||||
rand = { workspace = true }
|
rand = { workspace = true }
|
||||||
serde = { workspace = true, features = ["derive"] }
|
serde = { workspace = true, features = ["derive"] }
|
||||||
thiserror = { workspace = true }
|
|
||||||
|
|
||||||
nym-credentials-interface = { path = "../credentials-interface" }
|
|
||||||
nym-crypto = { path = "../crypto", features = ["asymmetric"] }
|
|
||||||
nym-network-defaults = { path = "../network-defaults" }
|
|
||||||
nym-service-provider-requests-common = { path = "../service-provider-requests-common" }
|
|
||||||
nym-sphinx = { path = "../nymsphinx" }
|
nym-sphinx = { path = "../nymsphinx" }
|
||||||
nym-wireguard-types = { path = "../wireguard-types" }
|
nym-wireguard-types = { path = "../wireguard-types" }
|
||||||
|
|
||||||
## verify:
|
|
||||||
hmac = { workspace = true, optional = true }
|
|
||||||
sha2 = { workspace = true, optional = true }
|
|
||||||
x25519-dalek = { workspace = true, features = ["static_secrets"] }
|
|
||||||
|
|
||||||
[features]
|
|
||||||
default = ["verify"]
|
|
||||||
# this is moved to a separate feature as we really need clients to import it (especially, *cough*, wasm)
|
|
||||||
verify = ["hmac", "sha2"]
|
|
||||||
|
|||||||
@@ -1,28 +0,0 @@
|
|||||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
use thiserror::Error;
|
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
|
||||||
pub enum Error {
|
|
||||||
#[error("the provided base64-encoded client MAC ('{mac}') was malformed: {source}")]
|
|
||||||
MalformedClientMac {
|
|
||||||
mac: String,
|
|
||||||
#[source]
|
|
||||||
source: base64::DecodeError,
|
|
||||||
},
|
|
||||||
|
|
||||||
#[cfg(feature = "verify")]
|
|
||||||
#[error("failed to verify mac provided by '{client}': {source}")]
|
|
||||||
FailedClientMacVerification {
|
|
||||||
client: String,
|
|
||||||
#[source]
|
|
||||||
source: hmac::digest::MacError,
|
|
||||||
},
|
|
||||||
|
|
||||||
#[error("conversion: {0}")]
|
|
||||||
Conversion(String),
|
|
||||||
|
|
||||||
#[error("failed to serialize response packet: {source}")]
|
|
||||||
FailedToSerializeResponsePacket { source: Box<bincode::ErrorKind> },
|
|
||||||
}
|
|
||||||
@@ -1,18 +1,9 @@
|
|||||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
pub mod traits;
|
|
||||||
pub mod v1;
|
pub mod v1;
|
||||||
pub mod v2;
|
|
||||||
pub mod v3;
|
|
||||||
pub mod v4;
|
|
||||||
|
|
||||||
mod error;
|
pub const CURRENT_VERSION: u8 = 1;
|
||||||
|
|
||||||
pub use error::Error;
|
|
||||||
pub use v4 as latest;
|
|
||||||
|
|
||||||
pub const CURRENT_VERSION: u8 = 4;
|
|
||||||
|
|
||||||
fn make_bincode_serializer() -> impl bincode::Options {
|
fn make_bincode_serializer() -> impl bincode::Options {
|
||||||
use bincode::Options;
|
use bincode::Options;
|
||||||
|
|||||||
@@ -1,343 +0,0 @@
|
|||||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
use nym_credentials_interface::CredentialSpendingData;
|
|
||||||
use nym_crypto::asymmetric::x25519::PrivateKey;
|
|
||||||
use nym_service_provider_requests_common::{Protocol, ServiceProviderType};
|
|
||||||
use nym_sphinx::addressing::clients::Recipient;
|
|
||||||
use nym_wireguard_types::PeerPublicKey;
|
|
||||||
|
|
||||||
use crate::{
|
|
||||||
v1, v2, v3,
|
|
||||||
v4::{self, registration::IpPair},
|
|
||||||
Error,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
|
||||||
pub enum AuthenticatorVersion {
|
|
||||||
V1,
|
|
||||||
V2,
|
|
||||||
V3,
|
|
||||||
V4,
|
|
||||||
UNKNOWN,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<Protocol> for AuthenticatorVersion {
|
|
||||||
fn from(value: Protocol) -> Self {
|
|
||||||
if value.service_provider_type != ServiceProviderType::Authenticator {
|
|
||||||
AuthenticatorVersion::UNKNOWN
|
|
||||||
} else if value.version == v1::VERSION {
|
|
||||||
AuthenticatorVersion::V1
|
|
||||||
} else if value.version == v2::VERSION {
|
|
||||||
AuthenticatorVersion::V2
|
|
||||||
} else if value.version == v3::VERSION {
|
|
||||||
AuthenticatorVersion::V3
|
|
||||||
} else if value.version == v4::VERSION {
|
|
||||||
AuthenticatorVersion::V4
|
|
||||||
} else {
|
|
||||||
AuthenticatorVersion::UNKNOWN
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait InitMessage {
|
|
||||||
fn pub_key(&self) -> PeerPublicKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl InitMessage for v1::registration::InitMessage {
|
|
||||||
fn pub_key(&self) -> PeerPublicKey {
|
|
||||||
self.pub_key
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl InitMessage for v2::registration::InitMessage {
|
|
||||||
fn pub_key(&self) -> PeerPublicKey {
|
|
||||||
self.pub_key
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl InitMessage for v3::registration::InitMessage {
|
|
||||||
fn pub_key(&self) -> PeerPublicKey {
|
|
||||||
self.pub_key
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl InitMessage for v4::registration::InitMessage {
|
|
||||||
fn pub_key(&self) -> PeerPublicKey {
|
|
||||||
self.pub_key
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait FinalMessage {
|
|
||||||
fn pub_key(&self) -> PeerPublicKey;
|
|
||||||
fn verify(&self, private_key: &PrivateKey, nonce: u64) -> Result<(), Error>;
|
|
||||||
fn private_ips(&self) -> IpPair;
|
|
||||||
fn credential(&self) -> Option<CredentialSpendingData>;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FinalMessage for v1::GatewayClient {
|
|
||||||
fn pub_key(&self) -> PeerPublicKey {
|
|
||||||
self.pub_key
|
|
||||||
}
|
|
||||||
|
|
||||||
fn verify(&self, private_key: &PrivateKey, nonce: u64) -> Result<(), Error> {
|
|
||||||
self.verify(private_key, nonce)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn private_ips(&self) -> IpPair {
|
|
||||||
self.private_ip.into()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn credential(&self) -> Option<CredentialSpendingData> {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FinalMessage for v2::registration::FinalMessage {
|
|
||||||
fn pub_key(&self) -> PeerPublicKey {
|
|
||||||
self.gateway_client.pub_key
|
|
||||||
}
|
|
||||||
|
|
||||||
fn verify(&self, private_key: &PrivateKey, nonce: u64) -> Result<(), Error> {
|
|
||||||
self.gateway_client.verify(private_key, nonce)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn private_ips(&self) -> IpPair {
|
|
||||||
self.gateway_client.private_ip.into()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn credential(&self) -> Option<CredentialSpendingData> {
|
|
||||||
self.credential.clone()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FinalMessage for v3::registration::FinalMessage {
|
|
||||||
fn pub_key(&self) -> PeerPublicKey {
|
|
||||||
self.gateway_client.pub_key
|
|
||||||
}
|
|
||||||
|
|
||||||
fn verify(&self, private_key: &PrivateKey, nonce: u64) -> Result<(), Error> {
|
|
||||||
self.gateway_client.verify(private_key, nonce)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn private_ips(&self) -> IpPair {
|
|
||||||
self.gateway_client.private_ip.into()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn credential(&self) -> Option<CredentialSpendingData> {
|
|
||||||
self.credential.clone()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FinalMessage for v4::registration::FinalMessage {
|
|
||||||
fn pub_key(&self) -> PeerPublicKey {
|
|
||||||
self.gateway_client.pub_key
|
|
||||||
}
|
|
||||||
|
|
||||||
fn verify(&self, private_key: &PrivateKey, nonce: u64) -> Result<(), Error> {
|
|
||||||
self.gateway_client.verify(private_key, nonce)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn private_ips(&self) -> IpPair {
|
|
||||||
self.gateway_client.private_ips
|
|
||||||
}
|
|
||||||
|
|
||||||
fn credential(&self) -> Option<CredentialSpendingData> {
|
|
||||||
self.credential.clone()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait QueryBandwidthMessage {
|
|
||||||
fn pub_key(&self) -> PeerPublicKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl QueryBandwidthMessage for PeerPublicKey {
|
|
||||||
fn pub_key(&self) -> PeerPublicKey {
|
|
||||||
*self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait TopUpMessage {
|
|
||||||
fn pub_key(&self) -> PeerPublicKey;
|
|
||||||
fn credential(&self) -> CredentialSpendingData;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TopUpMessage for v3::topup::TopUpMessage {
|
|
||||||
fn pub_key(&self) -> PeerPublicKey {
|
|
||||||
self.pub_key
|
|
||||||
}
|
|
||||||
|
|
||||||
fn credential(&self) -> CredentialSpendingData {
|
|
||||||
self.credential.clone()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TopUpMessage for v4::topup::TopUpMessage {
|
|
||||||
fn pub_key(&self) -> PeerPublicKey {
|
|
||||||
self.pub_key
|
|
||||||
}
|
|
||||||
|
|
||||||
fn credential(&self) -> CredentialSpendingData {
|
|
||||||
self.credential.clone()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum AuthenticatorRequest {
|
|
||||||
Initial {
|
|
||||||
msg: Box<dyn InitMessage + Send + Sync + 'static>,
|
|
||||||
protocol: Protocol,
|
|
||||||
reply_to: Recipient,
|
|
||||||
request_id: u64,
|
|
||||||
},
|
|
||||||
Final {
|
|
||||||
msg: Box<dyn FinalMessage + Send + Sync + 'static>,
|
|
||||||
protocol: Protocol,
|
|
||||||
reply_to: Recipient,
|
|
||||||
request_id: u64,
|
|
||||||
},
|
|
||||||
QueryBandwidth {
|
|
||||||
msg: Box<dyn QueryBandwidthMessage + Send + Sync + 'static>,
|
|
||||||
protocol: Protocol,
|
|
||||||
reply_to: Recipient,
|
|
||||||
request_id: u64,
|
|
||||||
},
|
|
||||||
TopUpBandwidth {
|
|
||||||
msg: Box<dyn TopUpMessage + Send + Sync + 'static>,
|
|
||||||
protocol: Protocol,
|
|
||||||
reply_to: Recipient,
|
|
||||||
request_id: u64,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v1::request::AuthenticatorRequest> for AuthenticatorRequest {
|
|
||||||
fn from(value: v1::request::AuthenticatorRequest) -> Self {
|
|
||||||
match value.data {
|
|
||||||
v1::request::AuthenticatorRequestData::Initial(init_message) => Self::Initial {
|
|
||||||
msg: Box::new(init_message),
|
|
||||||
protocol: Protocol {
|
|
||||||
version: value.version,
|
|
||||||
service_provider_type: ServiceProviderType::Authenticator,
|
|
||||||
},
|
|
||||||
reply_to: value.reply_to,
|
|
||||||
request_id: value.request_id,
|
|
||||||
},
|
|
||||||
v1::request::AuthenticatorRequestData::Final(gateway_client) => Self::Final {
|
|
||||||
msg: Box::new(gateway_client),
|
|
||||||
protocol: Protocol {
|
|
||||||
version: value.version,
|
|
||||||
service_provider_type: ServiceProviderType::Authenticator,
|
|
||||||
},
|
|
||||||
reply_to: value.reply_to,
|
|
||||||
request_id: value.request_id,
|
|
||||||
},
|
|
||||||
v1::request::AuthenticatorRequestData::QueryBandwidth(peer_public_key) => {
|
|
||||||
Self::QueryBandwidth {
|
|
||||||
msg: Box::new(peer_public_key),
|
|
||||||
protocol: Protocol {
|
|
||||||
version: value.version,
|
|
||||||
service_provider_type: ServiceProviderType::Authenticator,
|
|
||||||
},
|
|
||||||
reply_to: value.reply_to,
|
|
||||||
request_id: value.request_id,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v2::request::AuthenticatorRequest> for AuthenticatorRequest {
|
|
||||||
fn from(value: v2::request::AuthenticatorRequest) -> Self {
|
|
||||||
match value.data {
|
|
||||||
v2::request::AuthenticatorRequestData::Initial(init_message) => Self::Initial {
|
|
||||||
msg: Box::new(init_message),
|
|
||||||
protocol: value.protocol,
|
|
||||||
reply_to: value.reply_to,
|
|
||||||
request_id: value.request_id,
|
|
||||||
},
|
|
||||||
v2::request::AuthenticatorRequestData::Final(final_message) => Self::Final {
|
|
||||||
msg: final_message,
|
|
||||||
protocol: value.protocol,
|
|
||||||
reply_to: value.reply_to,
|
|
||||||
request_id: value.request_id,
|
|
||||||
},
|
|
||||||
v2::request::AuthenticatorRequestData::QueryBandwidth(peer_public_key) => {
|
|
||||||
Self::QueryBandwidth {
|
|
||||||
msg: Box::new(peer_public_key),
|
|
||||||
protocol: value.protocol,
|
|
||||||
reply_to: value.reply_to,
|
|
||||||
request_id: value.request_id,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v3::request::AuthenticatorRequest> for AuthenticatorRequest {
|
|
||||||
fn from(value: v3::request::AuthenticatorRequest) -> Self {
|
|
||||||
match value.data {
|
|
||||||
v3::request::AuthenticatorRequestData::Initial(init_message) => Self::Initial {
|
|
||||||
msg: Box::new(init_message),
|
|
||||||
protocol: value.protocol,
|
|
||||||
reply_to: value.reply_to,
|
|
||||||
request_id: value.request_id,
|
|
||||||
},
|
|
||||||
v3::request::AuthenticatorRequestData::Final(final_message) => Self::Final {
|
|
||||||
msg: final_message,
|
|
||||||
protocol: value.protocol,
|
|
||||||
reply_to: value.reply_to,
|
|
||||||
request_id: value.request_id,
|
|
||||||
},
|
|
||||||
v3::request::AuthenticatorRequestData::QueryBandwidth(peer_public_key) => {
|
|
||||||
Self::QueryBandwidth {
|
|
||||||
msg: Box::new(peer_public_key),
|
|
||||||
protocol: value.protocol,
|
|
||||||
reply_to: value.reply_to,
|
|
||||||
request_id: value.request_id,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
v3::request::AuthenticatorRequestData::TopUpBandwidth(top_up_message) => {
|
|
||||||
Self::TopUpBandwidth {
|
|
||||||
msg: top_up_message,
|
|
||||||
protocol: value.protocol,
|
|
||||||
reply_to: value.reply_to,
|
|
||||||
request_id: value.request_id,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v4::request::AuthenticatorRequest> for AuthenticatorRequest {
|
|
||||||
fn from(value: v4::request::AuthenticatorRequest) -> Self {
|
|
||||||
match value.data {
|
|
||||||
v4::request::AuthenticatorRequestData::Initial(init_message) => Self::Initial {
|
|
||||||
msg: Box::new(init_message),
|
|
||||||
protocol: value.protocol,
|
|
||||||
reply_to: value.reply_to,
|
|
||||||
request_id: value.request_id,
|
|
||||||
},
|
|
||||||
v4::request::AuthenticatorRequestData::Final(final_message) => Self::Final {
|
|
||||||
msg: final_message,
|
|
||||||
protocol: value.protocol,
|
|
||||||
reply_to: value.reply_to,
|
|
||||||
request_id: value.request_id,
|
|
||||||
},
|
|
||||||
v4::request::AuthenticatorRequestData::QueryBandwidth(peer_public_key) => {
|
|
||||||
Self::QueryBandwidth {
|
|
||||||
msg: Box::new(peer_public_key),
|
|
||||||
protocol: value.protocol,
|
|
||||||
reply_to: value.reply_to,
|
|
||||||
request_id: value.request_id,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
v4::request::AuthenticatorRequestData::TopUpBandwidth(top_up_message) => {
|
|
||||||
Self::TopUpBandwidth {
|
|
||||||
msg: top_up_message,
|
|
||||||
protocol: value.protocol,
|
|
||||||
reply_to: value.reply_to,
|
|
||||||
request_id: value.request_id,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,13 +1,7 @@
|
|||||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
pub mod registration;
|
|
||||||
pub mod request;
|
pub mod request;
|
||||||
pub mod response;
|
pub mod response;
|
||||||
|
|
||||||
pub use registration::{ClientMac, GatewayClient, InitMessage, Nonce};
|
const VERSION: u8 = 1;
|
||||||
|
|
||||||
#[cfg(feature = "verify")]
|
|
||||||
pub use registration::HmacSha256;
|
|
||||||
|
|
||||||
pub const VERSION: u8 = 1;
|
|
||||||
|
|||||||
@@ -1,218 +0,0 @@
|
|||||||
// Copyright 2023-2024 - Nym Technologies SA <contact@nymtech.net>
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
use crate::error::Error;
|
|
||||||
use base64::{engine::general_purpose, Engine};
|
|
||||||
use nym_wireguard_types::PeerPublicKey;
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::net::IpAddr;
|
|
||||||
use std::time::SystemTime;
|
|
||||||
use std::{fmt, ops::Deref, str::FromStr};
|
|
||||||
|
|
||||||
#[cfg(feature = "verify")]
|
|
||||||
use hmac::{Hmac, Mac};
|
|
||||||
#[cfg(feature = "verify")]
|
|
||||||
use nym_crypto::asymmetric::encryption::PrivateKey;
|
|
||||||
#[cfg(feature = "verify")]
|
|
||||||
use sha2::Sha256;
|
|
||||||
|
|
||||||
pub type PendingRegistrations = HashMap<PeerPublicKey, RegistrationData>;
|
|
||||||
pub type PrivateIPs = HashMap<IpAddr, Taken>;
|
|
||||||
|
|
||||||
#[cfg(feature = "verify")]
|
|
||||||
pub type HmacSha256 = Hmac<Sha256>;
|
|
||||||
|
|
||||||
pub type Nonce = u64;
|
|
||||||
pub type Taken = Option<SystemTime>;
|
|
||||||
|
|
||||||
pub const BANDWIDTH_CAP_PER_DAY: i64 = 1024 * 1024 * 1024; // 1 GB
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
|
||||||
pub struct InitMessage {
|
|
||||||
/// Base64 encoded x25519 public key
|
|
||||||
pub pub_key: PeerPublicKey,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl InitMessage {
|
|
||||||
pub fn new(pub_key: PeerPublicKey) -> Self {
|
|
||||||
InitMessage { pub_key }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
|
||||||
pub struct RegistrationData {
|
|
||||||
pub nonce: u64,
|
|
||||||
pub gateway_data: GatewayClient,
|
|
||||||
pub wg_port: u16,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
|
||||||
pub struct RegistredData {
|
|
||||||
pub pub_key: PeerPublicKey,
|
|
||||||
pub private_ip: IpAddr,
|
|
||||||
pub wg_port: u16,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
|
||||||
pub struct RemainingBandwidthData {
|
|
||||||
pub available_bandwidth: u64,
|
|
||||||
pub suspended: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Client that wants to register sends its PublicKey bytes mac digest encrypted with a DH shared secret.
|
|
||||||
/// Gateway/Nym node can then verify pub_key payload using the same process
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
|
||||||
pub struct GatewayClient {
|
|
||||||
/// Base64 encoded x25519 public key
|
|
||||||
pub pub_key: PeerPublicKey,
|
|
||||||
|
|
||||||
/// Assigned private IP
|
|
||||||
pub private_ip: IpAddr,
|
|
||||||
|
|
||||||
/// Sha256 hmac on the data (alongside the prior nonce)
|
|
||||||
pub mac: ClientMac,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GatewayClient {
|
|
||||||
#[cfg(feature = "verify")]
|
|
||||||
pub fn new(
|
|
||||||
local_secret: &PrivateKey,
|
|
||||||
remote_public: x25519_dalek::PublicKey,
|
|
||||||
private_ip: IpAddr,
|
|
||||||
nonce: u64,
|
|
||||||
) -> Self {
|
|
||||||
// convert from 1.0 x25519-dalek private key into 2.0 x25519-dalek
|
|
||||||
#[allow(clippy::expect_used)]
|
|
||||||
let static_secret = x25519_dalek::StaticSecret::from(local_secret.to_bytes());
|
|
||||||
let local_public: x25519_dalek::PublicKey = (&static_secret).into();
|
|
||||||
|
|
||||||
let dh = static_secret.diffie_hellman(&remote_public);
|
|
||||||
|
|
||||||
// TODO: change that to use our nym_crypto::hmac module instead
|
|
||||||
#[allow(clippy::expect_used)]
|
|
||||||
let mut mac = HmacSha256::new_from_slice(dh.as_bytes())
|
|
||||||
.expect("x25519 shared secret is always 32 bytes long");
|
|
||||||
|
|
||||||
mac.update(local_public.as_bytes());
|
|
||||||
mac.update(private_ip.to_string().as_bytes());
|
|
||||||
mac.update(&nonce.to_le_bytes());
|
|
||||||
|
|
||||||
GatewayClient {
|
|
||||||
pub_key: PeerPublicKey::new(local_public),
|
|
||||||
private_ip,
|
|
||||||
mac: ClientMac(mac.finalize().into_bytes().to_vec()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reusable secret should be gateways Wireguard PK
|
|
||||||
// Client should perform this step when generating its payload, using its own WG PK
|
|
||||||
#[cfg(feature = "verify")]
|
|
||||||
pub fn verify(&self, gateway_key: &PrivateKey, nonce: u64) -> Result<(), Error> {
|
|
||||||
// convert from 1.0 x25519-dalek private key into 2.0 x25519-dalek
|
|
||||||
#[allow(clippy::expect_used)]
|
|
||||||
let static_secret = x25519_dalek::StaticSecret::from(gateway_key.to_bytes());
|
|
||||||
|
|
||||||
let dh = static_secret.diffie_hellman(&self.pub_key);
|
|
||||||
|
|
||||||
// TODO: change that to use our nym_crypto::hmac module instead
|
|
||||||
#[allow(clippy::expect_used)]
|
|
||||||
let mut mac = HmacSha256::new_from_slice(dh.as_bytes())
|
|
||||||
.expect("x25519 shared secret is always 32 bytes long");
|
|
||||||
|
|
||||||
mac.update(self.pub_key.as_bytes());
|
|
||||||
mac.update(self.private_ip.to_string().as_bytes());
|
|
||||||
mac.update(&nonce.to_le_bytes());
|
|
||||||
|
|
||||||
mac.verify_slice(&self.mac)
|
|
||||||
.map_err(|source| Error::FailedClientMacVerification {
|
|
||||||
client: self.pub_key.to_string(),
|
|
||||||
source,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn pub_key(&self) -> PeerPublicKey {
|
|
||||||
self.pub_key
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: change the inner type into generic array of size HmacSha256::OutputSize
|
|
||||||
// TODO2: rely on our internal crypto/hmac
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct ClientMac(Vec<u8>);
|
|
||||||
|
|
||||||
impl fmt::Display for ClientMac {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
write!(f, "{}", general_purpose::STANDARD.encode(&self.0))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ClientMac {
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub fn new(mac: Vec<u8>) -> Self {
|
|
||||||
ClientMac(mac)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Deref for ClientMac {
|
|
||||||
type Target = Vec<u8>;
|
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
|
||||||
&self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FromStr for ClientMac {
|
|
||||||
type Err = Error;
|
|
||||||
|
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
||||||
let mac_bytes: Vec<u8> =
|
|
||||||
general_purpose::STANDARD
|
|
||||||
.decode(s)
|
|
||||||
.map_err(|source| Error::MalformedClientMac {
|
|
||||||
mac: s.to_string(),
|
|
||||||
source,
|
|
||||||
})?;
|
|
||||||
|
|
||||||
Ok(ClientMac(mac_bytes))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Serialize for ClientMac {
|
|
||||||
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
|
||||||
let encoded_key = general_purpose::STANDARD.encode(self.0.clone());
|
|
||||||
serializer.serialize_str(&encoded_key)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'de> Deserialize<'de> for ClientMac {
|
|
||||||
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
|
|
||||||
let encoded_key = String::deserialize(deserializer)?;
|
|
||||||
ClientMac::from_str(&encoded_key).map_err(serde::de::Error::custom)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
use nym_crypto::asymmetric::encryption;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
#[cfg(feature = "verify")]
|
|
||||||
fn client_request_roundtrip() {
|
|
||||||
let mut rng = rand::thread_rng();
|
|
||||||
|
|
||||||
let gateway_key_pair = encryption::KeyPair::new(&mut rng);
|
|
||||||
let client_key_pair = encryption::KeyPair::new(&mut rng);
|
|
||||||
|
|
||||||
let nonce = 1234567890;
|
|
||||||
|
|
||||||
let client = GatewayClient::new(
|
|
||||||
client_key_pair.private_key(),
|
|
||||||
x25519_dalek::PublicKey::from(gateway_key_pair.public_key().to_bytes()),
|
|
||||||
"10.0.0.42".parse().unwrap(),
|
|
||||||
nonce,
|
|
||||||
);
|
|
||||||
assert!(client.verify(gateway_key_pair.private_key(), nonce).is_ok())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,9 +1,8 @@
|
|||||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
use super::registration::{GatewayClient, InitMessage};
|
|
||||||
use nym_sphinx::addressing::Recipient;
|
use nym_sphinx::addressing::Recipient;
|
||||||
use nym_wireguard_types::PeerPublicKey;
|
use nym_wireguard_types::{GatewayClient, InitMessage, PeerPublicKey};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::make_bincode_serializer;
|
use crate::make_bincode_serializer;
|
||||||
@@ -83,24 +82,3 @@ pub enum AuthenticatorRequestData {
|
|||||||
Final(GatewayClient),
|
Final(GatewayClient),
|
||||||
QueryBandwidth(PeerPublicKey),
|
QueryBandwidth(PeerPublicKey),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
use std::str::FromStr;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn check_first_byte_version() {
|
|
||||||
let version = 2;
|
|
||||||
let data = AuthenticatorRequest {
|
|
||||||
version,
|
|
||||||
data: AuthenticatorRequestData::Initial(InitMessage::new(
|
|
||||||
PeerPublicKey::from_str("yvNUDpT5l7W/xDhiu6HkqTHDQwbs/B3J5UrLmORl1EQ=").unwrap(),
|
|
||||||
)),
|
|
||||||
reply_to: Recipient::try_from_base58_string("D1rrpsysCGCYXy9saP8y3kmNpGtJZUXN9SvFoUcqAsM9.9Ssso1ea5NfkbMASdiseDSjTN1fSWda5SgEVjdSN4CvV@GJqd3ZxpXWSNxTfx7B1pPtswpetH4LnJdFeLeuY5KUuN").unwrap(),
|
|
||||||
request_id: 1,
|
|
||||||
};
|
|
||||||
let bytes = data.to_bytes().unwrap();
|
|
||||||
assert_eq!(*bytes.first().unwrap(), version);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
use super::registration::{RegistrationData, RegistredData, RemainingBandwidthData};
|
|
||||||
use nym_sphinx::addressing::Recipient;
|
use nym_sphinx::addressing::Recipient;
|
||||||
|
use nym_wireguard_types::registration::{RegistrationData, RegistredData, RemainingBandwidthData};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::make_bincode_serializer;
|
use crate::make_bincode_serializer;
|
||||||
|
|||||||
@@ -1,174 +0,0 @@
|
|||||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
use nym_service_provider_requests_common::{Protocol, ServiceProviderType};
|
|
||||||
|
|
||||||
use crate::{v1, v2};
|
|
||||||
|
|
||||||
impl From<v1::request::AuthenticatorRequest> for v2::request::AuthenticatorRequest {
|
|
||||||
fn from(authenticator_request: v1::request::AuthenticatorRequest) -> Self {
|
|
||||||
Self {
|
|
||||||
protocol: Protocol {
|
|
||||||
version: 2,
|
|
||||||
service_provider_type: ServiceProviderType::Authenticator,
|
|
||||||
},
|
|
||||||
data: authenticator_request.data.into(),
|
|
||||||
reply_to: authenticator_request.reply_to,
|
|
||||||
request_id: authenticator_request.request_id,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v1::request::AuthenticatorRequestData> for v2::request::AuthenticatorRequestData {
|
|
||||||
fn from(authenticator_request_data: v1::request::AuthenticatorRequestData) -> Self {
|
|
||||||
match authenticator_request_data {
|
|
||||||
v1::request::AuthenticatorRequestData::Initial(init_msg) => {
|
|
||||||
v2::request::AuthenticatorRequestData::Initial(init_msg.into())
|
|
||||||
}
|
|
||||||
v1::request::AuthenticatorRequestData::Final(gw_client) => {
|
|
||||||
v2::request::AuthenticatorRequestData::Final(gw_client.into())
|
|
||||||
}
|
|
||||||
v1::request::AuthenticatorRequestData::QueryBandwidth(pub_key) => {
|
|
||||||
v2::request::AuthenticatorRequestData::QueryBandwidth(pub_key)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v1::registration::InitMessage> for v2::registration::InitMessage {
|
|
||||||
fn from(init_msg: v1::registration::InitMessage) -> Self {
|
|
||||||
Self {
|
|
||||||
pub_key: init_msg.pub_key,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v1::registration::GatewayClient> for Box<v2::registration::FinalMessage> {
|
|
||||||
fn from(gw_client: v1::registration::GatewayClient) -> Self {
|
|
||||||
Box::new(v2::registration::FinalMessage {
|
|
||||||
gateway_client: gw_client.into(),
|
|
||||||
credential: None,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v1::registration::GatewayClient> for v2::registration::GatewayClient {
|
|
||||||
fn from(gw_client: v1::registration::GatewayClient) -> Self {
|
|
||||||
Self {
|
|
||||||
pub_key: gw_client.pub_key,
|
|
||||||
private_ip: gw_client.private_ip,
|
|
||||||
mac: gw_client.mac.into(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v2::registration::GatewayClient> for v1::registration::GatewayClient {
|
|
||||||
fn from(gw_client: v2::registration::GatewayClient) -> Self {
|
|
||||||
Self {
|
|
||||||
pub_key: gw_client.pub_key,
|
|
||||||
private_ip: gw_client.private_ip,
|
|
||||||
mac: gw_client.mac.into(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v1::registration::ClientMac> for v2::registration::ClientMac {
|
|
||||||
fn from(mac: v1::registration::ClientMac) -> Self {
|
|
||||||
Self::new(mac.to_vec())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v2::registration::ClientMac> for v1::registration::ClientMac {
|
|
||||||
fn from(mac: v2::registration::ClientMac) -> Self {
|
|
||||||
Self::new(mac.to_vec())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v2::response::AuthenticatorResponse> for v1::response::AuthenticatorResponse {
|
|
||||||
fn from(authenticator_response: v2::response::AuthenticatorResponse) -> Self {
|
|
||||||
Self {
|
|
||||||
version: authenticator_response.protocol.version,
|
|
||||||
data: authenticator_response.data.into(),
|
|
||||||
reply_to: authenticator_response.reply_to,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v2::response::AuthenticatorResponseData> for v1::response::AuthenticatorResponseData {
|
|
||||||
fn from(authenticator_response_data: v2::response::AuthenticatorResponseData) -> Self {
|
|
||||||
match authenticator_response_data {
|
|
||||||
v2::response::AuthenticatorResponseData::PendingRegistration(
|
|
||||||
pending_registration_response,
|
|
||||||
) => v1::response::AuthenticatorResponseData::PendingRegistration(
|
|
||||||
pending_registration_response.into(),
|
|
||||||
),
|
|
||||||
v2::response::AuthenticatorResponseData::Registered(registered_response) => {
|
|
||||||
v1::response::AuthenticatorResponseData::Registered(registered_response.into())
|
|
||||||
}
|
|
||||||
v2::response::AuthenticatorResponseData::RemainingBandwidth(
|
|
||||||
remaining_bandwidth_response,
|
|
||||||
) => v1::response::AuthenticatorResponseData::RemainingBandwidth(
|
|
||||||
remaining_bandwidth_response.into(),
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v2::response::PendingRegistrationResponse> for v1::response::PendingRegistrationResponse {
|
|
||||||
fn from(value: v2::response::PendingRegistrationResponse) -> Self {
|
|
||||||
Self {
|
|
||||||
request_id: value.request_id,
|
|
||||||
reply_to: value.reply_to,
|
|
||||||
reply: value.reply.into(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v2::response::RegisteredResponse> for v1::response::RegisteredResponse {
|
|
||||||
fn from(value: v2::response::RegisteredResponse) -> Self {
|
|
||||||
Self {
|
|
||||||
request_id: value.request_id,
|
|
||||||
reply_to: value.reply_to,
|
|
||||||
reply: value.reply.into(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v2::response::RemainingBandwidthResponse> for v1::response::RemainingBandwidthResponse {
|
|
||||||
fn from(value: v2::response::RemainingBandwidthResponse) -> Self {
|
|
||||||
Self {
|
|
||||||
request_id: value.request_id,
|
|
||||||
reply_to: value.reply_to,
|
|
||||||
reply: value.reply.map(Into::into),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v2::registration::RegistrationData> for v1::registration::RegistrationData {
|
|
||||||
fn from(value: v2::registration::RegistrationData) -> Self {
|
|
||||||
Self {
|
|
||||||
nonce: value.nonce,
|
|
||||||
gateway_data: value.gateway_data.into(),
|
|
||||||
wg_port: value.wg_port,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v2::registration::RegistredData> for v1::registration::RegistredData {
|
|
||||||
fn from(value: v2::registration::RegistredData) -> Self {
|
|
||||||
Self {
|
|
||||||
pub_key: value.pub_key,
|
|
||||||
private_ip: value.private_ip,
|
|
||||||
wg_port: value.wg_port,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v2::registration::RemainingBandwidthData> for v1::registration::RemainingBandwidthData {
|
|
||||||
fn from(value: v2::registration::RemainingBandwidthData) -> Self {
|
|
||||||
Self {
|
|
||||||
available_bandwidth: value.available_bandwidth as u64,
|
|
||||||
suspended: false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
pub mod conversion;
|
|
||||||
pub mod registration;
|
|
||||||
pub mod request;
|
|
||||||
pub mod response;
|
|
||||||
|
|
||||||
pub const VERSION: u8 = 2;
|
|
||||||
@@ -1,116 +0,0 @@
|
|||||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
use super::registration::{FinalMessage, InitMessage};
|
|
||||||
use nym_service_provider_requests_common::{Protocol, ServiceProviderType};
|
|
||||||
use nym_sphinx::addressing::Recipient;
|
|
||||||
use nym_wireguard_types::PeerPublicKey;
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
use crate::make_bincode_serializer;
|
|
||||||
|
|
||||||
use super::VERSION;
|
|
||||||
|
|
||||||
fn generate_random() -> u64 {
|
|
||||||
use rand::RngCore;
|
|
||||||
let mut rng = rand::rngs::OsRng;
|
|
||||||
rng.next_u64()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
|
||||||
pub struct AuthenticatorRequest {
|
|
||||||
pub protocol: Protocol,
|
|
||||||
pub data: AuthenticatorRequestData,
|
|
||||||
pub reply_to: Recipient,
|
|
||||||
pub request_id: u64,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AuthenticatorRequest {
|
|
||||||
pub fn from_reconstructed_message(
|
|
||||||
message: &nym_sphinx::receiver::ReconstructedMessage,
|
|
||||||
) -> Result<Self, bincode::Error> {
|
|
||||||
use bincode::Options;
|
|
||||||
make_bincode_serializer().deserialize(&message.message)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new_initial_request(init_message: InitMessage, reply_to: Recipient) -> (Self, u64) {
|
|
||||||
let request_id = generate_random();
|
|
||||||
(
|
|
||||||
Self {
|
|
||||||
protocol: Protocol {
|
|
||||||
service_provider_type: ServiceProviderType::Authenticator,
|
|
||||||
version: VERSION,
|
|
||||||
},
|
|
||||||
data: AuthenticatorRequestData::Initial(init_message),
|
|
||||||
reply_to,
|
|
||||||
request_id,
|
|
||||||
},
|
|
||||||
request_id,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new_final_request(final_message: FinalMessage, reply_to: Recipient) -> (Self, u64) {
|
|
||||||
let request_id = generate_random();
|
|
||||||
(
|
|
||||||
Self {
|
|
||||||
protocol: Protocol {
|
|
||||||
service_provider_type: ServiceProviderType::Authenticator,
|
|
||||||
version: VERSION,
|
|
||||||
},
|
|
||||||
data: AuthenticatorRequestData::Final(Box::new(final_message)),
|
|
||||||
reply_to,
|
|
||||||
request_id,
|
|
||||||
},
|
|
||||||
request_id,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new_query_request(peer_public_key: PeerPublicKey, reply_to: Recipient) -> (Self, u64) {
|
|
||||||
let request_id = generate_random();
|
|
||||||
(
|
|
||||||
Self {
|
|
||||||
protocol: Protocol {
|
|
||||||
service_provider_type: ServiceProviderType::Authenticator,
|
|
||||||
version: VERSION,
|
|
||||||
},
|
|
||||||
data: AuthenticatorRequestData::QueryBandwidth(peer_public_key),
|
|
||||||
reply_to,
|
|
||||||
request_id,
|
|
||||||
},
|
|
||||||
request_id,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn to_bytes(&self) -> Result<Vec<u8>, bincode::Error> {
|
|
||||||
use bincode::Options;
|
|
||||||
make_bincode_serializer().serialize(self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
|
||||||
pub enum AuthenticatorRequestData {
|
|
||||||
Initial(InitMessage),
|
|
||||||
Final(Box<FinalMessage>),
|
|
||||||
QueryBandwidth(PeerPublicKey),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
use std::str::FromStr;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn check_first_bytes_protocol() {
|
|
||||||
let version = 2;
|
|
||||||
let data = AuthenticatorRequest {
|
|
||||||
protocol: Protocol { version, service_provider_type: ServiceProviderType::Authenticator },
|
|
||||||
data: AuthenticatorRequestData::Initial(InitMessage::new(
|
|
||||||
PeerPublicKey::from_str("yvNUDpT5l7W/xDhiu6HkqTHDQwbs/B3J5UrLmORl1EQ=").unwrap(),
|
|
||||||
)),
|
|
||||||
reply_to: Recipient::try_from_base58_string("D1rrpsysCGCYXy9saP8y3kmNpGtJZUXN9SvFoUcqAsM9.9Ssso1ea5NfkbMASdiseDSjTN1fSWda5SgEVjdSN4CvV@GJqd3ZxpXWSNxTfx7B1pPtswpetH4LnJdFeLeuY5KUuN").unwrap(),
|
|
||||||
request_id: 1,
|
|
||||||
};
|
|
||||||
let bytes = *data.to_bytes().unwrap().first_chunk::<2>().unwrap();
|
|
||||||
assert_eq!(bytes, [version, ServiceProviderType::Authenticator as u8]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,129 +0,0 @@
|
|||||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
use super::registration::{RegistrationData, RegistredData, RemainingBandwidthData};
|
|
||||||
use nym_service_provider_requests_common::{Protocol, ServiceProviderType};
|
|
||||||
use nym_sphinx::addressing::Recipient;
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
use crate::make_bincode_serializer;
|
|
||||||
|
|
||||||
use super::VERSION;
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
|
||||||
pub struct AuthenticatorResponse {
|
|
||||||
pub protocol: Protocol,
|
|
||||||
pub data: AuthenticatorResponseData,
|
|
||||||
pub reply_to: Recipient,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AuthenticatorResponse {
|
|
||||||
pub fn new_pending_registration_success(
|
|
||||||
registration_data: RegistrationData,
|
|
||||||
request_id: u64,
|
|
||||||
reply_to: Recipient,
|
|
||||||
) -> Self {
|
|
||||||
Self {
|
|
||||||
protocol: Protocol {
|
|
||||||
service_provider_type: ServiceProviderType::Authenticator,
|
|
||||||
version: VERSION,
|
|
||||||
},
|
|
||||||
data: AuthenticatorResponseData::PendingRegistration(PendingRegistrationResponse {
|
|
||||||
reply: registration_data,
|
|
||||||
reply_to,
|
|
||||||
request_id,
|
|
||||||
}),
|
|
||||||
reply_to,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new_registered(
|
|
||||||
registred_data: RegistredData,
|
|
||||||
reply_to: Recipient,
|
|
||||||
request_id: u64,
|
|
||||||
) -> Self {
|
|
||||||
Self {
|
|
||||||
protocol: Protocol {
|
|
||||||
service_provider_type: ServiceProviderType::Authenticator,
|
|
||||||
version: VERSION,
|
|
||||||
},
|
|
||||||
data: AuthenticatorResponseData::Registered(RegisteredResponse {
|
|
||||||
reply: registred_data,
|
|
||||||
reply_to,
|
|
||||||
request_id,
|
|
||||||
}),
|
|
||||||
reply_to,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new_remaining_bandwidth(
|
|
||||||
remaining_bandwidth_data: Option<RemainingBandwidthData>,
|
|
||||||
reply_to: Recipient,
|
|
||||||
request_id: u64,
|
|
||||||
) -> Self {
|
|
||||||
Self {
|
|
||||||
protocol: Protocol {
|
|
||||||
service_provider_type: ServiceProviderType::Authenticator,
|
|
||||||
version: VERSION,
|
|
||||||
},
|
|
||||||
data: AuthenticatorResponseData::RemainingBandwidth(RemainingBandwidthResponse {
|
|
||||||
reply: remaining_bandwidth_data,
|
|
||||||
reply_to,
|
|
||||||
request_id,
|
|
||||||
}),
|
|
||||||
reply_to,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn recipient(&self) -> Recipient {
|
|
||||||
self.reply_to
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn to_bytes(&self) -> Result<Vec<u8>, bincode::Error> {
|
|
||||||
use bincode::Options;
|
|
||||||
make_bincode_serializer().serialize(self)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn from_reconstructed_message(
|
|
||||||
message: &nym_sphinx::receiver::ReconstructedMessage,
|
|
||||||
) -> Result<Self, bincode::Error> {
|
|
||||||
use bincode::Options;
|
|
||||||
make_bincode_serializer().deserialize(&message.message)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn id(&self) -> Option<u64> {
|
|
||||||
match &self.data {
|
|
||||||
AuthenticatorResponseData::PendingRegistration(response) => Some(response.request_id),
|
|
||||||
AuthenticatorResponseData::Registered(response) => Some(response.request_id),
|
|
||||||
AuthenticatorResponseData::RemainingBandwidth(response) => Some(response.request_id),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
|
||||||
pub enum AuthenticatorResponseData {
|
|
||||||
PendingRegistration(PendingRegistrationResponse),
|
|
||||||
Registered(RegisteredResponse),
|
|
||||||
RemainingBandwidth(RemainingBandwidthResponse),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
|
||||||
pub struct PendingRegistrationResponse {
|
|
||||||
pub request_id: u64,
|
|
||||||
pub reply_to: Recipient,
|
|
||||||
pub reply: RegistrationData,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
|
||||||
pub struct RegisteredResponse {
|
|
||||||
pub request_id: u64,
|
|
||||||
pub reply_to: Recipient,
|
|
||||||
pub reply: RegistredData,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
|
||||||
pub struct RemainingBandwidthResponse {
|
|
||||||
pub request_id: u64,
|
|
||||||
pub reply_to: Recipient,
|
|
||||||
pub reply: Option<RemainingBandwidthData>,
|
|
||||||
}
|
|
||||||
@@ -1,272 +0,0 @@
|
|||||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
use nym_service_provider_requests_common::{Protocol, ServiceProviderType};
|
|
||||||
|
|
||||||
use crate::{v2, v3};
|
|
||||||
|
|
||||||
impl From<v2::request::AuthenticatorRequest> for v3::request::AuthenticatorRequest {
|
|
||||||
fn from(authenticator_request: v2::request::AuthenticatorRequest) -> Self {
|
|
||||||
Self {
|
|
||||||
protocol: Protocol {
|
|
||||||
version: 3,
|
|
||||||
service_provider_type: ServiceProviderType::Authenticator,
|
|
||||||
},
|
|
||||||
data: authenticator_request.data.into(),
|
|
||||||
reply_to: authenticator_request.reply_to,
|
|
||||||
request_id: authenticator_request.request_id,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v2::request::AuthenticatorRequestData> for v3::request::AuthenticatorRequestData {
|
|
||||||
fn from(authenticator_request_data: v2::request::AuthenticatorRequestData) -> Self {
|
|
||||||
match authenticator_request_data {
|
|
||||||
v2::request::AuthenticatorRequestData::Initial(init_msg) => {
|
|
||||||
v3::request::AuthenticatorRequestData::Initial(init_msg.into())
|
|
||||||
}
|
|
||||||
v2::request::AuthenticatorRequestData::Final(gw_client) => {
|
|
||||||
v3::request::AuthenticatorRequestData::Final(gw_client.into())
|
|
||||||
}
|
|
||||||
v2::request::AuthenticatorRequestData::QueryBandwidth(pub_key) => {
|
|
||||||
v3::request::AuthenticatorRequestData::QueryBandwidth(pub_key)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v2::registration::InitMessage> for v3::registration::InitMessage {
|
|
||||||
fn from(init_msg: v2::registration::InitMessage) -> Self {
|
|
||||||
Self {
|
|
||||||
pub_key: init_msg.pub_key,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<Box<v2::registration::FinalMessage>> for Box<v3::registration::FinalMessage> {
|
|
||||||
fn from(gw_client: Box<v2::registration::FinalMessage>) -> Self {
|
|
||||||
Box::new(v3::registration::FinalMessage {
|
|
||||||
gateway_client: gw_client.gateway_client.into(),
|
|
||||||
credential: gw_client.credential,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v2::registration::GatewayClient> for v3::registration::GatewayClient {
|
|
||||||
fn from(gw_client: v2::registration::GatewayClient) -> Self {
|
|
||||||
Self {
|
|
||||||
pub_key: gw_client.pub_key,
|
|
||||||
private_ip: gw_client.private_ip,
|
|
||||||
mac: gw_client.mac.into(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v3::registration::GatewayClient> for v2::registration::GatewayClient {
|
|
||||||
fn from(gw_client: v3::registration::GatewayClient) -> Self {
|
|
||||||
Self {
|
|
||||||
pub_key: gw_client.pub_key,
|
|
||||||
private_ip: gw_client.private_ip,
|
|
||||||
mac: gw_client.mac.into(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v2::registration::ClientMac> for v3::registration::ClientMac {
|
|
||||||
fn from(mac: v2::registration::ClientMac) -> Self {
|
|
||||||
Self::new(mac.to_vec())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v3::registration::ClientMac> for v2::registration::ClientMac {
|
|
||||||
fn from(mac: v3::registration::ClientMac) -> Self {
|
|
||||||
Self::new(mac.to_vec())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TryFrom<v3::response::AuthenticatorResponse> for v2::response::AuthenticatorResponse {
|
|
||||||
type Error = crate::Error;
|
|
||||||
|
|
||||||
fn try_from(
|
|
||||||
authenticator_response: v3::response::AuthenticatorResponse,
|
|
||||||
) -> Result<Self, Self::Error> {
|
|
||||||
Ok(Self {
|
|
||||||
data: authenticator_response.data.try_into()?,
|
|
||||||
reply_to: authenticator_response.reply_to,
|
|
||||||
protocol: authenticator_response.protocol,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v2::response::AuthenticatorResponse> for v3::response::AuthenticatorResponse {
|
|
||||||
fn from(value: v2::response::AuthenticatorResponse) -> Self {
|
|
||||||
Self {
|
|
||||||
protocol: value.protocol,
|
|
||||||
data: value.data.into(),
|
|
||||||
reply_to: value.reply_to,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TryFrom<v3::response::AuthenticatorResponseData> for v2::response::AuthenticatorResponseData {
|
|
||||||
type Error = crate::Error;
|
|
||||||
|
|
||||||
fn try_from(
|
|
||||||
authenticator_response_data: v3::response::AuthenticatorResponseData,
|
|
||||||
) -> Result<Self, Self::Error> {
|
|
||||||
match authenticator_response_data {
|
|
||||||
v3::response::AuthenticatorResponseData::PendingRegistration(
|
|
||||||
pending_registration_response,
|
|
||||||
) => Ok(
|
|
||||||
v2::response::AuthenticatorResponseData::PendingRegistration(
|
|
||||||
pending_registration_response.into(),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
v3::response::AuthenticatorResponseData::Registered(registered_response) => Ok(
|
|
||||||
v2::response::AuthenticatorResponseData::Registered(registered_response.into()),
|
|
||||||
),
|
|
||||||
v3::response::AuthenticatorResponseData::RemainingBandwidth(
|
|
||||||
remaining_bandwidth_response,
|
|
||||||
) => Ok(v2::response::AuthenticatorResponseData::RemainingBandwidth(
|
|
||||||
remaining_bandwidth_response.into(),
|
|
||||||
)),
|
|
||||||
v3::response::AuthenticatorResponseData::TopUpBandwidth(_) => {
|
|
||||||
Err(Self::Error::Conversion(
|
|
||||||
"a v2 request couldn't produce a v3 only type of response".to_string(),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v2::response::AuthenticatorResponseData> for v3::response::AuthenticatorResponseData {
|
|
||||||
fn from(value: v2::response::AuthenticatorResponseData) -> Self {
|
|
||||||
match value {
|
|
||||||
v2::response::AuthenticatorResponseData::PendingRegistration(
|
|
||||||
pending_registration_response,
|
|
||||||
) => Self::PendingRegistration(pending_registration_response.into()),
|
|
||||||
v2::response::AuthenticatorResponseData::Registered(registered_response) => {
|
|
||||||
Self::Registered(registered_response.into())
|
|
||||||
}
|
|
||||||
v2::response::AuthenticatorResponseData::RemainingBandwidth(
|
|
||||||
remaining_bandwidth_response,
|
|
||||||
) => Self::RemainingBandwidth(remaining_bandwidth_response.into()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v3::response::PendingRegistrationResponse> for v2::response::PendingRegistrationResponse {
|
|
||||||
fn from(value: v3::response::PendingRegistrationResponse) -> Self {
|
|
||||||
Self {
|
|
||||||
request_id: value.request_id,
|
|
||||||
reply_to: value.reply_to,
|
|
||||||
reply: value.reply.into(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v2::response::PendingRegistrationResponse> for v3::response::PendingRegistrationResponse {
|
|
||||||
fn from(value: v2::response::PendingRegistrationResponse) -> Self {
|
|
||||||
Self {
|
|
||||||
request_id: value.request_id,
|
|
||||||
reply_to: value.reply_to,
|
|
||||||
reply: value.reply.into(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v3::response::RegisteredResponse> for v2::response::RegisteredResponse {
|
|
||||||
fn from(value: v3::response::RegisteredResponse) -> Self {
|
|
||||||
Self {
|
|
||||||
request_id: value.request_id,
|
|
||||||
reply_to: value.reply_to,
|
|
||||||
reply: value.reply.into(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v2::response::RegisteredResponse> for v3::response::RegisteredResponse {
|
|
||||||
fn from(value: v2::response::RegisteredResponse) -> Self {
|
|
||||||
Self {
|
|
||||||
request_id: value.request_id,
|
|
||||||
reply_to: value.reply_to,
|
|
||||||
reply: value.reply.into(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v3::response::RemainingBandwidthResponse> for v2::response::RemainingBandwidthResponse {
|
|
||||||
fn from(value: v3::response::RemainingBandwidthResponse) -> Self {
|
|
||||||
Self {
|
|
||||||
request_id: value.request_id,
|
|
||||||
reply_to: value.reply_to,
|
|
||||||
reply: value.reply.map(Into::into),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v2::response::RemainingBandwidthResponse> for v3::response::RemainingBandwidthResponse {
|
|
||||||
fn from(value: v2::response::RemainingBandwidthResponse) -> Self {
|
|
||||||
Self {
|
|
||||||
request_id: value.request_id,
|
|
||||||
reply_to: value.reply_to,
|
|
||||||
reply: value.reply.map(Into::into),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v3::registration::RegistrationData> for v2::registration::RegistrationData {
|
|
||||||
fn from(value: v3::registration::RegistrationData) -> Self {
|
|
||||||
Self {
|
|
||||||
nonce: value.nonce,
|
|
||||||
gateway_data: value.gateway_data.into(),
|
|
||||||
wg_port: value.wg_port,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v2::registration::RegistrationData> for v3::registration::RegistrationData {
|
|
||||||
fn from(value: v2::registration::RegistrationData) -> Self {
|
|
||||||
Self {
|
|
||||||
nonce: value.nonce,
|
|
||||||
gateway_data: value.gateway_data.into(),
|
|
||||||
wg_port: value.wg_port,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v3::registration::RegistredData> for v2::registration::RegistredData {
|
|
||||||
fn from(value: v3::registration::RegistredData) -> Self {
|
|
||||||
Self {
|
|
||||||
pub_key: value.pub_key,
|
|
||||||
private_ip: value.private_ip,
|
|
||||||
wg_port: value.wg_port,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v2::registration::RegistredData> for v3::registration::RegistredData {
|
|
||||||
fn from(value: v2::registration::RegistredData) -> Self {
|
|
||||||
Self {
|
|
||||||
pub_key: value.pub_key,
|
|
||||||
private_ip: value.private_ip,
|
|
||||||
wg_port: value.wg_port,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v3::registration::RemainingBandwidthData> for v2::registration::RemainingBandwidthData {
|
|
||||||
fn from(value: v3::registration::RemainingBandwidthData) -> Self {
|
|
||||||
Self {
|
|
||||||
available_bandwidth: value.available_bandwidth,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v2::registration::RemainingBandwidthData> for v3::registration::RemainingBandwidthData {
|
|
||||||
fn from(value: v2::registration::RemainingBandwidthData) -> Self {
|
|
||||||
Self {
|
|
||||||
available_bandwidth: value.available_bandwidth,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
pub mod conversion;
|
|
||||||
pub mod registration;
|
|
||||||
pub mod request;
|
|
||||||
pub mod response;
|
|
||||||
pub mod topup;
|
|
||||||
|
|
||||||
pub const VERSION: u8 = 3;
|
|
||||||
@@ -1,227 +0,0 @@
|
|||||||
// -2024 - Nym Technologies SA <contact@nymtech.net>
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
use crate::error::Error;
|
|
||||||
use base64::{engine::general_purpose, Engine};
|
|
||||||
use nym_credentials_interface::CredentialSpendingData;
|
|
||||||
use nym_wireguard_types::PeerPublicKey;
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::net::IpAddr;
|
|
||||||
use std::time::SystemTime;
|
|
||||||
use std::{fmt, ops::Deref, str::FromStr};
|
|
||||||
|
|
||||||
#[cfg(feature = "verify")]
|
|
||||||
use hmac::{Hmac, Mac};
|
|
||||||
#[cfg(feature = "verify")]
|
|
||||||
use nym_crypto::asymmetric::encryption::PrivateKey;
|
|
||||||
#[cfg(feature = "verify")]
|
|
||||||
use sha2::Sha256;
|
|
||||||
|
|
||||||
pub type PendingRegistrations = HashMap<PeerPublicKey, RegistrationData>;
|
|
||||||
pub type PrivateIPs = HashMap<IpAddr, Taken>;
|
|
||||||
|
|
||||||
#[cfg(feature = "verify")]
|
|
||||||
pub type HmacSha256 = Hmac<Sha256>;
|
|
||||||
|
|
||||||
pub type Nonce = u64;
|
|
||||||
pub type Taken = Option<SystemTime>;
|
|
||||||
|
|
||||||
pub const BANDWIDTH_CAP_PER_DAY: u64 = 250 * 1024 * 1024 * 1024; // 250 GB
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
|
||||||
pub struct InitMessage {
|
|
||||||
/// Base64 encoded x25519 public key
|
|
||||||
pub pub_key: PeerPublicKey,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl InitMessage {
|
|
||||||
pub fn new(pub_key: PeerPublicKey) -> Self {
|
|
||||||
InitMessage { pub_key }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
|
||||||
pub struct FinalMessage {
|
|
||||||
/// Gateway client data
|
|
||||||
pub gateway_client: GatewayClient,
|
|
||||||
|
|
||||||
/// Ecash credential
|
|
||||||
pub credential: Option<CredentialSpendingData>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
|
||||||
pub struct RegistrationData {
|
|
||||||
pub nonce: u64,
|
|
||||||
pub gateway_data: GatewayClient,
|
|
||||||
pub wg_port: u16,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
|
||||||
pub struct RegistredData {
|
|
||||||
pub pub_key: PeerPublicKey,
|
|
||||||
pub private_ip: IpAddr,
|
|
||||||
pub wg_port: u16,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
|
||||||
pub struct RemainingBandwidthData {
|
|
||||||
pub available_bandwidth: i64,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Client that wants to register sends its PublicKey bytes mac digest encrypted with a DH shared secret.
|
|
||||||
/// Gateway/Nym node can then verify pub_key payload using the same process
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
|
||||||
pub struct GatewayClient {
|
|
||||||
/// Base64 encoded x25519 public key
|
|
||||||
pub pub_key: PeerPublicKey,
|
|
||||||
|
|
||||||
/// Assigned private IP
|
|
||||||
pub private_ip: IpAddr,
|
|
||||||
|
|
||||||
/// Sha256 hmac on the data (alongside the prior nonce)
|
|
||||||
pub mac: ClientMac,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GatewayClient {
|
|
||||||
#[cfg(feature = "verify")]
|
|
||||||
pub fn new(
|
|
||||||
local_secret: &PrivateKey,
|
|
||||||
remote_public: x25519_dalek::PublicKey,
|
|
||||||
private_ip: IpAddr,
|
|
||||||
nonce: u64,
|
|
||||||
) -> Self {
|
|
||||||
// convert from 1.0 x25519-dalek private key into 2.0 x25519-dalek
|
|
||||||
#[allow(clippy::expect_used)]
|
|
||||||
let static_secret = x25519_dalek::StaticSecret::from(local_secret.to_bytes());
|
|
||||||
let local_public: x25519_dalek::PublicKey = (&static_secret).into();
|
|
||||||
|
|
||||||
let dh = static_secret.diffie_hellman(&remote_public);
|
|
||||||
|
|
||||||
// TODO: change that to use our nym_crypto::hmac module instead
|
|
||||||
#[allow(clippy::expect_used)]
|
|
||||||
let mut mac = HmacSha256::new_from_slice(dh.as_bytes())
|
|
||||||
.expect("x25519 shared secret is always 32 bytes long");
|
|
||||||
|
|
||||||
mac.update(local_public.as_bytes());
|
|
||||||
mac.update(private_ip.to_string().as_bytes());
|
|
||||||
mac.update(&nonce.to_le_bytes());
|
|
||||||
|
|
||||||
GatewayClient {
|
|
||||||
pub_key: PeerPublicKey::new(local_public),
|
|
||||||
private_ip,
|
|
||||||
mac: ClientMac(mac.finalize().into_bytes().to_vec()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reusable secret should be gateways Wireguard PK
|
|
||||||
// Client should perform this step when generating its payload, using its own WG PK
|
|
||||||
#[cfg(feature = "verify")]
|
|
||||||
pub fn verify(&self, gateway_key: &PrivateKey, nonce: u64) -> Result<(), Error> {
|
|
||||||
// convert from 1.0 x25519-dalek private key into 2.0 x25519-dalek
|
|
||||||
#[allow(clippy::expect_used)]
|
|
||||||
let static_secret = x25519_dalek::StaticSecret::from(gateway_key.to_bytes());
|
|
||||||
|
|
||||||
let dh = static_secret.diffie_hellman(&self.pub_key);
|
|
||||||
|
|
||||||
// TODO: change that to use our nym_crypto::hmac module instead
|
|
||||||
#[allow(clippy::expect_used)]
|
|
||||||
let mut mac = HmacSha256::new_from_slice(dh.as_bytes())
|
|
||||||
.expect("x25519 shared secret is always 32 bytes long");
|
|
||||||
|
|
||||||
mac.update(self.pub_key.as_bytes());
|
|
||||||
mac.update(self.private_ip.to_string().as_bytes());
|
|
||||||
mac.update(&nonce.to_le_bytes());
|
|
||||||
|
|
||||||
mac.verify_slice(&self.mac)
|
|
||||||
.map_err(|source| Error::FailedClientMacVerification {
|
|
||||||
client: self.pub_key.to_string(),
|
|
||||||
source,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn pub_key(&self) -> PeerPublicKey {
|
|
||||||
self.pub_key
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: change the inner type into generic array of size HmacSha256::OutputSize
|
|
||||||
// TODO2: rely on our internal crypto/hmac
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct ClientMac(Vec<u8>);
|
|
||||||
|
|
||||||
impl fmt::Display for ClientMac {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
write!(f, "{}", general_purpose::STANDARD.encode(&self.0))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ClientMac {
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub fn new(mac: Vec<u8>) -> Self {
|
|
||||||
ClientMac(mac)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Deref for ClientMac {
|
|
||||||
type Target = Vec<u8>;
|
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
|
||||||
&self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FromStr for ClientMac {
|
|
||||||
type Err = Error;
|
|
||||||
|
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
||||||
let mac_bytes: Vec<u8> =
|
|
||||||
general_purpose::STANDARD
|
|
||||||
.decode(s)
|
|
||||||
.map_err(|source| Error::MalformedClientMac {
|
|
||||||
mac: s.to_string(),
|
|
||||||
source,
|
|
||||||
})?;
|
|
||||||
|
|
||||||
Ok(ClientMac(mac_bytes))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Serialize for ClientMac {
|
|
||||||
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
|
||||||
let encoded_key = general_purpose::STANDARD.encode(self.0.clone());
|
|
||||||
serializer.serialize_str(&encoded_key)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'de> Deserialize<'de> for ClientMac {
|
|
||||||
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
|
|
||||||
let encoded_key = String::deserialize(deserializer)?;
|
|
||||||
ClientMac::from_str(&encoded_key).map_err(serde::de::Error::custom)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
use nym_crypto::asymmetric::encryption;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
#[cfg(feature = "verify")]
|
|
||||||
fn client_request_roundtrip() {
|
|
||||||
let mut rng = rand::thread_rng();
|
|
||||||
|
|
||||||
let gateway_key_pair = encryption::KeyPair::new(&mut rng);
|
|
||||||
let client_key_pair = encryption::KeyPair::new(&mut rng);
|
|
||||||
|
|
||||||
let nonce = 1234567890;
|
|
||||||
|
|
||||||
let client = GatewayClient::new(
|
|
||||||
client_key_pair.private_key(),
|
|
||||||
x25519_dalek::PublicKey::from(gateway_key_pair.public_key().to_bytes()),
|
|
||||||
"10.0.0.42".parse().unwrap(),
|
|
||||||
nonce,
|
|
||||||
);
|
|
||||||
assert!(client.verify(gateway_key_pair.private_key(), nonce).is_ok())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,136 +0,0 @@
|
|||||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
use super::{
|
|
||||||
registration::{FinalMessage, InitMessage},
|
|
||||||
topup::TopUpMessage,
|
|
||||||
};
|
|
||||||
use nym_service_provider_requests_common::{Protocol, ServiceProviderType};
|
|
||||||
use nym_sphinx::addressing::Recipient;
|
|
||||||
use nym_wireguard_types::PeerPublicKey;
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
use crate::make_bincode_serializer;
|
|
||||||
|
|
||||||
use super::VERSION;
|
|
||||||
|
|
||||||
fn generate_random() -> u64 {
|
|
||||||
use rand::RngCore;
|
|
||||||
let mut rng = rand::rngs::OsRng;
|
|
||||||
rng.next_u64()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
|
||||||
pub struct AuthenticatorRequest {
|
|
||||||
pub protocol: Protocol,
|
|
||||||
pub data: AuthenticatorRequestData,
|
|
||||||
pub reply_to: Recipient,
|
|
||||||
pub request_id: u64,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AuthenticatorRequest {
|
|
||||||
pub fn from_reconstructed_message(
|
|
||||||
message: &nym_sphinx::receiver::ReconstructedMessage,
|
|
||||||
) -> Result<Self, bincode::Error> {
|
|
||||||
use bincode::Options;
|
|
||||||
make_bincode_serializer().deserialize(&message.message)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new_initial_request(init_message: InitMessage, reply_to: Recipient) -> (Self, u64) {
|
|
||||||
let request_id = generate_random();
|
|
||||||
(
|
|
||||||
Self {
|
|
||||||
protocol: Protocol {
|
|
||||||
service_provider_type: ServiceProviderType::Authenticator,
|
|
||||||
version: VERSION,
|
|
||||||
},
|
|
||||||
data: AuthenticatorRequestData::Initial(init_message),
|
|
||||||
reply_to,
|
|
||||||
request_id,
|
|
||||||
},
|
|
||||||
request_id,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new_final_request(final_message: FinalMessage, reply_to: Recipient) -> (Self, u64) {
|
|
||||||
let request_id = generate_random();
|
|
||||||
(
|
|
||||||
Self {
|
|
||||||
protocol: Protocol {
|
|
||||||
service_provider_type: ServiceProviderType::Authenticator,
|
|
||||||
version: VERSION,
|
|
||||||
},
|
|
||||||
data: AuthenticatorRequestData::Final(Box::new(final_message)),
|
|
||||||
reply_to,
|
|
||||||
request_id,
|
|
||||||
},
|
|
||||||
request_id,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new_query_request(peer_public_key: PeerPublicKey, reply_to: Recipient) -> (Self, u64) {
|
|
||||||
let request_id = generate_random();
|
|
||||||
(
|
|
||||||
Self {
|
|
||||||
protocol: Protocol {
|
|
||||||
service_provider_type: ServiceProviderType::Authenticator,
|
|
||||||
version: VERSION,
|
|
||||||
},
|
|
||||||
data: AuthenticatorRequestData::QueryBandwidth(peer_public_key),
|
|
||||||
reply_to,
|
|
||||||
request_id,
|
|
||||||
},
|
|
||||||
request_id,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new_topup_request(top_up_message: TopUpMessage, reply_to: Recipient) -> (Self, u64) {
|
|
||||||
let request_id = generate_random();
|
|
||||||
(
|
|
||||||
Self {
|
|
||||||
protocol: Protocol {
|
|
||||||
service_provider_type: ServiceProviderType::Authenticator,
|
|
||||||
version: VERSION,
|
|
||||||
},
|
|
||||||
data: AuthenticatorRequestData::TopUpBandwidth(Box::new(top_up_message)),
|
|
||||||
reply_to,
|
|
||||||
request_id,
|
|
||||||
},
|
|
||||||
request_id,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn to_bytes(&self) -> Result<Vec<u8>, bincode::Error> {
|
|
||||||
use bincode::Options;
|
|
||||||
make_bincode_serializer().serialize(self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
|
||||||
pub enum AuthenticatorRequestData {
|
|
||||||
Initial(InitMessage),
|
|
||||||
Final(Box<FinalMessage>),
|
|
||||||
QueryBandwidth(PeerPublicKey),
|
|
||||||
TopUpBandwidth(Box<TopUpMessage>),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
use std::str::FromStr;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn check_first_bytes_protocol() {
|
|
||||||
let version = 2;
|
|
||||||
let data = AuthenticatorRequest {
|
|
||||||
protocol: Protocol { version, service_provider_type: ServiceProviderType::Authenticator },
|
|
||||||
data: AuthenticatorRequestData::Initial(InitMessage::new(
|
|
||||||
PeerPublicKey::from_str("yvNUDpT5l7W/xDhiu6HkqTHDQwbs/B3J5UrLmORl1EQ=").unwrap(),
|
|
||||||
)),
|
|
||||||
reply_to: Recipient::try_from_base58_string("D1rrpsysCGCYXy9saP8y3kmNpGtJZUXN9SvFoUcqAsM9.9Ssso1ea5NfkbMASdiseDSjTN1fSWda5SgEVjdSN4CvV@GJqd3ZxpXWSNxTfx7B1pPtswpetH4LnJdFeLeuY5KUuN").unwrap(),
|
|
||||||
request_id: 1,
|
|
||||||
};
|
|
||||||
let bytes = *data.to_bytes().unwrap().first_chunk::<2>().unwrap();
|
|
||||||
assert_eq!(bytes, [version, ServiceProviderType::Authenticator as u8]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,157 +0,0 @@
|
|||||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
use super::registration::{RegistrationData, RegistredData, RemainingBandwidthData};
|
|
||||||
use nym_service_provider_requests_common::{Protocol, ServiceProviderType};
|
|
||||||
use nym_sphinx::addressing::Recipient;
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
use crate::make_bincode_serializer;
|
|
||||||
|
|
||||||
use super::VERSION;
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
|
||||||
pub struct AuthenticatorResponse {
|
|
||||||
pub protocol: Protocol,
|
|
||||||
pub data: AuthenticatorResponseData,
|
|
||||||
pub reply_to: Recipient,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AuthenticatorResponse {
|
|
||||||
pub fn new_pending_registration_success(
|
|
||||||
registration_data: RegistrationData,
|
|
||||||
request_id: u64,
|
|
||||||
reply_to: Recipient,
|
|
||||||
) -> Self {
|
|
||||||
Self {
|
|
||||||
protocol: Protocol {
|
|
||||||
service_provider_type: ServiceProviderType::Authenticator,
|
|
||||||
version: VERSION,
|
|
||||||
},
|
|
||||||
data: AuthenticatorResponseData::PendingRegistration(PendingRegistrationResponse {
|
|
||||||
reply: registration_data,
|
|
||||||
reply_to,
|
|
||||||
request_id,
|
|
||||||
}),
|
|
||||||
reply_to,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new_registered(
|
|
||||||
registred_data: RegistredData,
|
|
||||||
reply_to: Recipient,
|
|
||||||
request_id: u64,
|
|
||||||
) -> Self {
|
|
||||||
Self {
|
|
||||||
protocol: Protocol {
|
|
||||||
service_provider_type: ServiceProviderType::Authenticator,
|
|
||||||
version: VERSION,
|
|
||||||
},
|
|
||||||
data: AuthenticatorResponseData::Registered(RegisteredResponse {
|
|
||||||
reply: registred_data,
|
|
||||||
reply_to,
|
|
||||||
request_id,
|
|
||||||
}),
|
|
||||||
reply_to,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new_remaining_bandwidth(
|
|
||||||
remaining_bandwidth_data: Option<RemainingBandwidthData>,
|
|
||||||
reply_to: Recipient,
|
|
||||||
request_id: u64,
|
|
||||||
) -> Self {
|
|
||||||
Self {
|
|
||||||
protocol: Protocol {
|
|
||||||
service_provider_type: ServiceProviderType::Authenticator,
|
|
||||||
version: VERSION,
|
|
||||||
},
|
|
||||||
data: AuthenticatorResponseData::RemainingBandwidth(RemainingBandwidthResponse {
|
|
||||||
reply: remaining_bandwidth_data,
|
|
||||||
reply_to,
|
|
||||||
request_id,
|
|
||||||
}),
|
|
||||||
reply_to,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new_topup_bandwidth(
|
|
||||||
remaining_bandwidth_data: RemainingBandwidthData,
|
|
||||||
reply_to: Recipient,
|
|
||||||
request_id: u64,
|
|
||||||
) -> Self {
|
|
||||||
Self {
|
|
||||||
protocol: Protocol {
|
|
||||||
service_provider_type: ServiceProviderType::Authenticator,
|
|
||||||
version: VERSION,
|
|
||||||
},
|
|
||||||
data: AuthenticatorResponseData::TopUpBandwidth(TopUpBandwidthResponse {
|
|
||||||
reply: remaining_bandwidth_data,
|
|
||||||
reply_to,
|
|
||||||
request_id,
|
|
||||||
}),
|
|
||||||
reply_to,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn recipient(&self) -> Recipient {
|
|
||||||
self.reply_to
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn to_bytes(&self) -> Result<Vec<u8>, bincode::Error> {
|
|
||||||
use bincode::Options;
|
|
||||||
make_bincode_serializer().serialize(self)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn from_reconstructed_message(
|
|
||||||
message: &nym_sphinx::receiver::ReconstructedMessage,
|
|
||||||
) -> Result<Self, bincode::Error> {
|
|
||||||
use bincode::Options;
|
|
||||||
make_bincode_serializer().deserialize(&message.message)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn id(&self) -> Option<u64> {
|
|
||||||
match &self.data {
|
|
||||||
AuthenticatorResponseData::PendingRegistration(response) => Some(response.request_id),
|
|
||||||
AuthenticatorResponseData::Registered(response) => Some(response.request_id),
|
|
||||||
AuthenticatorResponseData::RemainingBandwidth(response) => Some(response.request_id),
|
|
||||||
AuthenticatorResponseData::TopUpBandwidth(response) => Some(response.request_id),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
|
||||||
pub enum AuthenticatorResponseData {
|
|
||||||
PendingRegistration(PendingRegistrationResponse),
|
|
||||||
Registered(RegisteredResponse),
|
|
||||||
RemainingBandwidth(RemainingBandwidthResponse),
|
|
||||||
TopUpBandwidth(TopUpBandwidthResponse),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
|
||||||
pub struct PendingRegistrationResponse {
|
|
||||||
pub request_id: u64,
|
|
||||||
pub reply_to: Recipient,
|
|
||||||
pub reply: RegistrationData,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
|
||||||
pub struct RegisteredResponse {
|
|
||||||
pub request_id: u64,
|
|
||||||
pub reply_to: Recipient,
|
|
||||||
pub reply: RegistredData,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
|
||||||
pub struct RemainingBandwidthResponse {
|
|
||||||
pub request_id: u64,
|
|
||||||
pub reply_to: Recipient,
|
|
||||||
pub reply: Option<RemainingBandwidthData>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
|
||||||
pub struct TopUpBandwidthResponse {
|
|
||||||
pub request_id: u64,
|
|
||||||
pub reply_to: Recipient,
|
|
||||||
pub reply: RemainingBandwidthData,
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
use nym_credentials_interface::CredentialSpendingData;
|
|
||||||
use nym_wireguard_types::PeerPublicKey;
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
|
||||||
pub struct TopUpMessage {
|
|
||||||
/// Base64 encoded x25519 public key
|
|
||||||
pub pub_key: PeerPublicKey,
|
|
||||||
|
|
||||||
/// Ecash credential
|
|
||||||
pub credential: CredentialSpendingData,
|
|
||||||
}
|
|
||||||
@@ -1,232 +0,0 @@
|
|||||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
use nym_service_provider_requests_common::{Protocol, ServiceProviderType};
|
|
||||||
|
|
||||||
use crate::{v2, v3, v4};
|
|
||||||
|
|
||||||
impl From<v3::request::AuthenticatorRequest> for v4::request::AuthenticatorRequest {
|
|
||||||
fn from(authenticator_request: v3::request::AuthenticatorRequest) -> Self {
|
|
||||||
Self {
|
|
||||||
protocol: Protocol {
|
|
||||||
version: 4,
|
|
||||||
service_provider_type: ServiceProviderType::Authenticator,
|
|
||||||
},
|
|
||||||
data: authenticator_request.data.into(),
|
|
||||||
reply_to: authenticator_request.reply_to,
|
|
||||||
request_id: authenticator_request.request_id,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v3::request::AuthenticatorRequestData> for v4::request::AuthenticatorRequestData {
|
|
||||||
fn from(authenticator_request_data: v3::request::AuthenticatorRequestData) -> Self {
|
|
||||||
match authenticator_request_data {
|
|
||||||
v3::request::AuthenticatorRequestData::Initial(init_msg) => {
|
|
||||||
v4::request::AuthenticatorRequestData::Initial(init_msg.into())
|
|
||||||
}
|
|
||||||
v3::request::AuthenticatorRequestData::Final(gw_client) => {
|
|
||||||
v4::request::AuthenticatorRequestData::Final(gw_client.into())
|
|
||||||
}
|
|
||||||
v3::request::AuthenticatorRequestData::QueryBandwidth(pub_key) => {
|
|
||||||
v4::request::AuthenticatorRequestData::QueryBandwidth(pub_key)
|
|
||||||
}
|
|
||||||
v3::request::AuthenticatorRequestData::TopUpBandwidth(top_up_message) => {
|
|
||||||
v4::request::AuthenticatorRequestData::TopUpBandwidth(top_up_message.into())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v3::registration::InitMessage> for v4::registration::InitMessage {
|
|
||||||
fn from(init_msg: v3::registration::InitMessage) -> Self {
|
|
||||||
Self {
|
|
||||||
pub_key: init_msg.pub_key,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<Box<v3::registration::FinalMessage>> for Box<v4::registration::FinalMessage> {
|
|
||||||
fn from(gw_client: Box<v3::registration::FinalMessage>) -> Self {
|
|
||||||
Box::new(v4::registration::FinalMessage {
|
|
||||||
gateway_client: gw_client.gateway_client.into(),
|
|
||||||
credential: gw_client.credential,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<Box<v3::topup::TopUpMessage>> for Box<v4::topup::TopUpMessage> {
|
|
||||||
fn from(top_up_message: Box<v3::topup::TopUpMessage>) -> Self {
|
|
||||||
Box::new(v4::topup::TopUpMessage {
|
|
||||||
pub_key: top_up_message.pub_key,
|
|
||||||
credential: top_up_message.credential,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v2::registration::GatewayClient> for v4::registration::GatewayClient {
|
|
||||||
fn from(gw_client: v2::registration::GatewayClient) -> Self {
|
|
||||||
Self {
|
|
||||||
pub_key: gw_client.pub_key,
|
|
||||||
private_ips: gw_client.private_ip.into(),
|
|
||||||
mac: gw_client.mac.into(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v3::registration::GatewayClient> for v4::registration::GatewayClient {
|
|
||||||
fn from(gw_client: v3::registration::GatewayClient) -> Self {
|
|
||||||
Self {
|
|
||||||
pub_key: gw_client.pub_key,
|
|
||||||
private_ips: gw_client.private_ip.into(),
|
|
||||||
mac: gw_client.mac.into(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v4::registration::GatewayClient> for v3::registration::GatewayClient {
|
|
||||||
fn from(gw_client: v4::registration::GatewayClient) -> Self {
|
|
||||||
Self {
|
|
||||||
pub_key: gw_client.pub_key,
|
|
||||||
private_ip: gw_client.private_ips.ipv4.into(),
|
|
||||||
mac: gw_client.mac.into(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v4::registration::GatewayClient> for v2::registration::GatewayClient {
|
|
||||||
fn from(gw_client: v4::registration::GatewayClient) -> Self {
|
|
||||||
Self {
|
|
||||||
pub_key: gw_client.pub_key,
|
|
||||||
private_ip: gw_client.private_ips.ipv4.into(),
|
|
||||||
mac: gw_client.mac.into(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v2::registration::ClientMac> for v4::registration::ClientMac {
|
|
||||||
fn from(mac: v2::registration::ClientMac) -> Self {
|
|
||||||
Self::new(mac.to_vec())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v3::registration::ClientMac> for v4::registration::ClientMac {
|
|
||||||
fn from(mac: v3::registration::ClientMac) -> Self {
|
|
||||||
Self::new(mac.to_vec())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v4::registration::ClientMac> for v3::registration::ClientMac {
|
|
||||||
fn from(mac: v4::registration::ClientMac) -> Self {
|
|
||||||
Self::new(mac.to_vec())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v4::registration::ClientMac> for v2::registration::ClientMac {
|
|
||||||
fn from(mac: v4::registration::ClientMac) -> Self {
|
|
||||||
Self::new(mac.to_vec())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TryFrom<v4::response::AuthenticatorResponse> for v3::response::AuthenticatorResponse {
|
|
||||||
type Error = crate::Error;
|
|
||||||
|
|
||||||
fn try_from(
|
|
||||||
authenticator_response: v4::response::AuthenticatorResponse,
|
|
||||||
) -> Result<Self, Self::Error> {
|
|
||||||
Ok(Self {
|
|
||||||
data: authenticator_response.data.try_into()?,
|
|
||||||
reply_to: authenticator_response.reply_to,
|
|
||||||
protocol: authenticator_response.protocol,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TryFrom<v4::response::AuthenticatorResponseData> for v3::response::AuthenticatorResponseData {
|
|
||||||
type Error = crate::Error;
|
|
||||||
|
|
||||||
fn try_from(
|
|
||||||
authenticator_response_data: v4::response::AuthenticatorResponseData,
|
|
||||||
) -> Result<Self, Self::Error> {
|
|
||||||
match authenticator_response_data {
|
|
||||||
v4::response::AuthenticatorResponseData::PendingRegistration(
|
|
||||||
pending_registration_response,
|
|
||||||
) => Ok(
|
|
||||||
v3::response::AuthenticatorResponseData::PendingRegistration(
|
|
||||||
pending_registration_response.into(),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
v4::response::AuthenticatorResponseData::Registered(registered_response) => Ok(
|
|
||||||
v3::response::AuthenticatorResponseData::Registered(registered_response.into()),
|
|
||||||
),
|
|
||||||
v4::response::AuthenticatorResponseData::RemainingBandwidth(
|
|
||||||
remaining_bandwidth_response,
|
|
||||||
) => Ok(v3::response::AuthenticatorResponseData::RemainingBandwidth(
|
|
||||||
remaining_bandwidth_response.into(),
|
|
||||||
)),
|
|
||||||
v4::response::AuthenticatorResponseData::TopUpBandwidth(_) => {
|
|
||||||
Err(Self::Error::Conversion(
|
|
||||||
"a v3 request couldn't produce a v4 only type of response".to_string(),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v4::response::PendingRegistrationResponse> for v3::response::PendingRegistrationResponse {
|
|
||||||
fn from(value: v4::response::PendingRegistrationResponse) -> Self {
|
|
||||||
Self {
|
|
||||||
request_id: value.request_id,
|
|
||||||
reply_to: value.reply_to,
|
|
||||||
reply: value.reply.into(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v4::response::RegisteredResponse> for v3::response::RegisteredResponse {
|
|
||||||
fn from(value: v4::response::RegisteredResponse) -> Self {
|
|
||||||
Self {
|
|
||||||
request_id: value.request_id,
|
|
||||||
reply_to: value.reply_to,
|
|
||||||
reply: value.reply.into(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v4::response::RemainingBandwidthResponse> for v3::response::RemainingBandwidthResponse {
|
|
||||||
fn from(value: v4::response::RemainingBandwidthResponse) -> Self {
|
|
||||||
Self {
|
|
||||||
request_id: value.request_id,
|
|
||||||
reply_to: value.reply_to,
|
|
||||||
reply: value.reply.map(Into::into),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v4::registration::RegistrationData> for v3::registration::RegistrationData {
|
|
||||||
fn from(value: v4::registration::RegistrationData) -> Self {
|
|
||||||
Self {
|
|
||||||
nonce: value.nonce,
|
|
||||||
gateway_data: value.gateway_data.into(),
|
|
||||||
wg_port: value.wg_port,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v4::registration::RegistredData> for v3::registration::RegistredData {
|
|
||||||
fn from(value: v4::registration::RegistredData) -> Self {
|
|
||||||
Self {
|
|
||||||
pub_key: value.pub_key,
|
|
||||||
private_ip: value.private_ips.ipv4.into(),
|
|
||||||
wg_port: value.wg_port,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<v4::registration::RemainingBandwidthData> for v3::registration::RemainingBandwidthData {
|
|
||||||
fn from(value: v4::registration::RemainingBandwidthData) -> Self {
|
|
||||||
Self {
|
|
||||||
available_bandwidth: value.available_bandwidth,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
pub mod conversion;
|
|
||||||
pub mod registration;
|
|
||||||
pub mod request;
|
|
||||||
pub mod response;
|
|
||||||
pub mod topup;
|
|
||||||
|
|
||||||
pub const VERSION: u8 = 4;
|
|
||||||
@@ -1,287 +0,0 @@
|
|||||||
// -2024 - Nym Technologies SA <contact@nymtech.net>
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
use crate::error::Error;
|
|
||||||
use base64::{engine::general_purpose, Engine};
|
|
||||||
use nym_credentials_interface::CredentialSpendingData;
|
|
||||||
use nym_network_defaults::constants::{WG_TUN_DEVICE_IP_ADDRESS_V4, WG_TUN_DEVICE_IP_ADDRESS_V6};
|
|
||||||
use nym_wireguard_types::PeerPublicKey;
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
|
|
||||||
use std::time::SystemTime;
|
|
||||||
use std::{fmt, ops::Deref, str::FromStr};
|
|
||||||
|
|
||||||
#[cfg(feature = "verify")]
|
|
||||||
use hmac::{Hmac, Mac};
|
|
||||||
#[cfg(feature = "verify")]
|
|
||||||
use nym_crypto::asymmetric::encryption::PrivateKey;
|
|
||||||
#[cfg(feature = "verify")]
|
|
||||||
use sha2::Sha256;
|
|
||||||
|
|
||||||
pub type PendingRegistrations = HashMap<PeerPublicKey, RegistrationData>;
|
|
||||||
pub type PrivateIPs = HashMap<IpPair, Taken>;
|
|
||||||
|
|
||||||
#[cfg(feature = "verify")]
|
|
||||||
pub type HmacSha256 = Hmac<Sha256>;
|
|
||||||
|
|
||||||
pub type Nonce = u64;
|
|
||||||
pub type Taken = Option<SystemTime>;
|
|
||||||
|
|
||||||
pub const BANDWIDTH_CAP_PER_DAY: u64 = 1024 * 1024 * 1024; // 1 GB
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
|
||||||
pub struct IpPair {
|
|
||||||
pub ipv4: Ipv4Addr,
|
|
||||||
pub ipv6: Ipv6Addr,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl IpPair {
|
|
||||||
pub fn new(ipv4: Ipv4Addr, ipv6: Ipv6Addr) -> Self {
|
|
||||||
IpPair { ipv4, ipv6 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<(Ipv4Addr, Ipv6Addr)> for IpPair {
|
|
||||||
fn from((ipv4, ipv6): (Ipv4Addr, Ipv6Addr)) -> Self {
|
|
||||||
IpPair { ipv4, ipv6 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for IpPair {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
write!(f, "({}, {})", self.ipv4, self.ipv6)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<IpAddr> for IpPair {
|
|
||||||
fn from(value: IpAddr) -> Self {
|
|
||||||
let (before_last_byte, last_byte) = match value {
|
|
||||||
std::net::IpAddr::V4(ipv4_addr) => (ipv4_addr.octets()[2], ipv4_addr.octets()[3]),
|
|
||||||
std::net::IpAddr::V6(ipv6_addr) => (ipv6_addr.octets()[14], ipv6_addr.octets()[15]),
|
|
||||||
};
|
|
||||||
let last_bytes = (before_last_byte as u16) << 8 | last_byte as u16;
|
|
||||||
let ipv4 = Ipv4Addr::new(
|
|
||||||
WG_TUN_DEVICE_IP_ADDRESS_V4.octets()[0],
|
|
||||||
WG_TUN_DEVICE_IP_ADDRESS_V4.octets()[1],
|
|
||||||
before_last_byte,
|
|
||||||
last_byte,
|
|
||||||
);
|
|
||||||
let ipv6 = Ipv6Addr::new(
|
|
||||||
WG_TUN_DEVICE_IP_ADDRESS_V6.segments()[0],
|
|
||||||
WG_TUN_DEVICE_IP_ADDRESS_V6.segments()[1],
|
|
||||||
WG_TUN_DEVICE_IP_ADDRESS_V6.segments()[2],
|
|
||||||
WG_TUN_DEVICE_IP_ADDRESS_V6.segments()[3],
|
|
||||||
WG_TUN_DEVICE_IP_ADDRESS_V6.segments()[4],
|
|
||||||
WG_TUN_DEVICE_IP_ADDRESS_V6.segments()[5],
|
|
||||||
WG_TUN_DEVICE_IP_ADDRESS_V6.segments()[6],
|
|
||||||
last_bytes,
|
|
||||||
);
|
|
||||||
IpPair::new(ipv4, ipv6)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
|
||||||
pub struct InitMessage {
|
|
||||||
/// Base64 encoded x25519 public key
|
|
||||||
pub pub_key: PeerPublicKey,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl InitMessage {
|
|
||||||
pub fn new(pub_key: PeerPublicKey) -> Self {
|
|
||||||
InitMessage { pub_key }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
|
||||||
pub struct FinalMessage {
|
|
||||||
/// Gateway client data
|
|
||||||
pub gateway_client: GatewayClient,
|
|
||||||
|
|
||||||
/// Ecash credential
|
|
||||||
pub credential: Option<CredentialSpendingData>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
|
||||||
pub struct RegistrationData {
|
|
||||||
pub nonce: u64,
|
|
||||||
pub gateway_data: GatewayClient,
|
|
||||||
pub wg_port: u16,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
|
||||||
pub struct RegistredData {
|
|
||||||
pub pub_key: PeerPublicKey,
|
|
||||||
pub private_ips: IpPair,
|
|
||||||
pub wg_port: u16,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
|
||||||
pub struct RemainingBandwidthData {
|
|
||||||
pub available_bandwidth: i64,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Client that wants to register sends its PublicKey bytes mac digest encrypted with a DH shared secret.
|
|
||||||
/// Gateway/Nym node can then verify pub_key payload using the same process
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
|
||||||
pub struct GatewayClient {
|
|
||||||
/// Base64 encoded x25519 public key
|
|
||||||
pub pub_key: PeerPublicKey,
|
|
||||||
|
|
||||||
/// Assigned private IPs (v4 and v6)
|
|
||||||
pub private_ips: IpPair,
|
|
||||||
|
|
||||||
/// Sha256 hmac on the data (alongside the prior nonce)
|
|
||||||
pub mac: ClientMac,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GatewayClient {
|
|
||||||
#[cfg(feature = "verify")]
|
|
||||||
pub fn new(
|
|
||||||
local_secret: &PrivateKey,
|
|
||||||
remote_public: x25519_dalek::PublicKey,
|
|
||||||
private_ips: IpPair,
|
|
||||||
nonce: u64,
|
|
||||||
) -> Self {
|
|
||||||
// convert from 1.0 x25519-dalek private key into 2.0 x25519-dalek
|
|
||||||
#[allow(clippy::expect_used)]
|
|
||||||
let static_secret = x25519_dalek::StaticSecret::from(local_secret.to_bytes());
|
|
||||||
let local_public: x25519_dalek::PublicKey = (&static_secret).into();
|
|
||||||
|
|
||||||
let dh = static_secret.diffie_hellman(&remote_public);
|
|
||||||
|
|
||||||
// TODO: change that to use our nym_crypto::hmac module instead
|
|
||||||
#[allow(clippy::expect_used)]
|
|
||||||
let mut mac = HmacSha256::new_from_slice(dh.as_bytes())
|
|
||||||
.expect("x25519 shared secret is always 32 bytes long");
|
|
||||||
|
|
||||||
mac.update(local_public.as_bytes());
|
|
||||||
mac.update(private_ips.to_string().as_bytes());
|
|
||||||
mac.update(&nonce.to_le_bytes());
|
|
||||||
|
|
||||||
GatewayClient {
|
|
||||||
pub_key: PeerPublicKey::new(local_public),
|
|
||||||
private_ips,
|
|
||||||
mac: ClientMac(mac.finalize().into_bytes().to_vec()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reusable secret should be gateways Wireguard PK
|
|
||||||
// Client should perform this step when generating its payload, using its own WG PK
|
|
||||||
#[cfg(feature = "verify")]
|
|
||||||
pub fn verify(&self, gateway_key: &PrivateKey, nonce: u64) -> Result<(), Error> {
|
|
||||||
// convert from 1.0 x25519-dalek private key into 2.0 x25519-dalek
|
|
||||||
#[allow(clippy::expect_used)]
|
|
||||||
let static_secret = x25519_dalek::StaticSecret::from(gateway_key.to_bytes());
|
|
||||||
|
|
||||||
let dh = static_secret.diffie_hellman(&self.pub_key);
|
|
||||||
|
|
||||||
// TODO: change that to use our nym_crypto::hmac module instead
|
|
||||||
#[allow(clippy::expect_used)]
|
|
||||||
let mut mac = HmacSha256::new_from_slice(dh.as_bytes())
|
|
||||||
.expect("x25519 shared secret is always 32 bytes long");
|
|
||||||
|
|
||||||
mac.update(self.pub_key.as_bytes());
|
|
||||||
mac.update(self.private_ips.to_string().as_bytes());
|
|
||||||
mac.update(&nonce.to_le_bytes());
|
|
||||||
|
|
||||||
mac.verify_slice(&self.mac)
|
|
||||||
.map_err(|source| Error::FailedClientMacVerification {
|
|
||||||
client: self.pub_key.to_string(),
|
|
||||||
source,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn pub_key(&self) -> PeerPublicKey {
|
|
||||||
self.pub_key
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: change the inner type into generic array of size HmacSha256::OutputSize
|
|
||||||
// TODO2: rely on our internal crypto/hmac
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct ClientMac(Vec<u8>);
|
|
||||||
|
|
||||||
impl fmt::Display for ClientMac {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
write!(f, "{}", general_purpose::STANDARD.encode(&self.0))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ClientMac {
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub fn new(mac: Vec<u8>) -> Self {
|
|
||||||
ClientMac(mac)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Deref for ClientMac {
|
|
||||||
type Target = Vec<u8>;
|
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
|
||||||
&self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FromStr for ClientMac {
|
|
||||||
type Err = Error;
|
|
||||||
|
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
||||||
let mac_bytes: Vec<u8> =
|
|
||||||
general_purpose::STANDARD
|
|
||||||
.decode(s)
|
|
||||||
.map_err(|source| Error::MalformedClientMac {
|
|
||||||
mac: s.to_string(),
|
|
||||||
source,
|
|
||||||
})?;
|
|
||||||
|
|
||||||
Ok(ClientMac(mac_bytes))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Serialize for ClientMac {
|
|
||||||
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
|
||||||
let encoded_key = general_purpose::STANDARD.encode(self.0.clone());
|
|
||||||
serializer.serialize_str(&encoded_key)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'de> Deserialize<'de> for ClientMac {
|
|
||||||
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
|
|
||||||
let encoded_key = String::deserialize(deserializer)?;
|
|
||||||
ClientMac::from_str(&encoded_key).map_err(serde::de::Error::custom)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
use nym_crypto::asymmetric::encryption;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn create_ip_pair() {
|
|
||||||
let ipv4: IpAddr = Ipv4Addr::from_str("10.1.10.50").unwrap().into();
|
|
||||||
let ipv6: IpAddr = Ipv6Addr::from_str("fc01::0a32").unwrap().into();
|
|
||||||
|
|
||||||
assert_eq!(IpPair::from(ipv4), IpPair::from(ipv6));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
#[cfg(feature = "verify")]
|
|
||||||
fn client_request_roundtrip() {
|
|
||||||
let mut rng = rand::thread_rng();
|
|
||||||
|
|
||||||
let gateway_key_pair = encryption::KeyPair::new(&mut rng);
|
|
||||||
let client_key_pair = encryption::KeyPair::new(&mut rng);
|
|
||||||
|
|
||||||
let nonce = 1234567890;
|
|
||||||
|
|
||||||
let client = GatewayClient::new(
|
|
||||||
client_key_pair.private_key(),
|
|
||||||
x25519_dalek::PublicKey::from(gateway_key_pair.public_key().to_bytes()),
|
|
||||||
IpPair::new("10.0.0.42".parse().unwrap(), "fc00::42".parse().unwrap()),
|
|
||||||
nonce,
|
|
||||||
);
|
|
||||||
assert!(client.verify(gateway_key_pair.private_key(), nonce).is_ok())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,136 +0,0 @@
|
|||||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
use super::{
|
|
||||||
registration::{FinalMessage, InitMessage},
|
|
||||||
topup::TopUpMessage,
|
|
||||||
};
|
|
||||||
use nym_service_provider_requests_common::{Protocol, ServiceProviderType};
|
|
||||||
use nym_sphinx::addressing::Recipient;
|
|
||||||
use nym_wireguard_types::PeerPublicKey;
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
use crate::make_bincode_serializer;
|
|
||||||
|
|
||||||
use super::VERSION;
|
|
||||||
|
|
||||||
fn generate_random() -> u64 {
|
|
||||||
use rand::RngCore;
|
|
||||||
let mut rng = rand::rngs::OsRng;
|
|
||||||
rng.next_u64()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
|
||||||
pub struct AuthenticatorRequest {
|
|
||||||
pub protocol: Protocol,
|
|
||||||
pub data: AuthenticatorRequestData,
|
|
||||||
pub reply_to: Recipient,
|
|
||||||
pub request_id: u64,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AuthenticatorRequest {
|
|
||||||
pub fn from_reconstructed_message(
|
|
||||||
message: &nym_sphinx::receiver::ReconstructedMessage,
|
|
||||||
) -> Result<Self, bincode::Error> {
|
|
||||||
use bincode::Options;
|
|
||||||
make_bincode_serializer().deserialize(&message.message)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new_initial_request(init_message: InitMessage, reply_to: Recipient) -> (Self, u64) {
|
|
||||||
let request_id = generate_random();
|
|
||||||
(
|
|
||||||
Self {
|
|
||||||
protocol: Protocol {
|
|
||||||
service_provider_type: ServiceProviderType::Authenticator,
|
|
||||||
version: VERSION,
|
|
||||||
},
|
|
||||||
data: AuthenticatorRequestData::Initial(init_message),
|
|
||||||
reply_to,
|
|
||||||
request_id,
|
|
||||||
},
|
|
||||||
request_id,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new_final_request(final_message: FinalMessage, reply_to: Recipient) -> (Self, u64) {
|
|
||||||
let request_id = generate_random();
|
|
||||||
(
|
|
||||||
Self {
|
|
||||||
protocol: Protocol {
|
|
||||||
service_provider_type: ServiceProviderType::Authenticator,
|
|
||||||
version: VERSION,
|
|
||||||
},
|
|
||||||
data: AuthenticatorRequestData::Final(Box::new(final_message)),
|
|
||||||
reply_to,
|
|
||||||
request_id,
|
|
||||||
},
|
|
||||||
request_id,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new_query_request(peer_public_key: PeerPublicKey, reply_to: Recipient) -> (Self, u64) {
|
|
||||||
let request_id = generate_random();
|
|
||||||
(
|
|
||||||
Self {
|
|
||||||
protocol: Protocol {
|
|
||||||
service_provider_type: ServiceProviderType::Authenticator,
|
|
||||||
version: VERSION,
|
|
||||||
},
|
|
||||||
data: AuthenticatorRequestData::QueryBandwidth(peer_public_key),
|
|
||||||
reply_to,
|
|
||||||
request_id,
|
|
||||||
},
|
|
||||||
request_id,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new_topup_request(top_up_message: TopUpMessage, reply_to: Recipient) -> (Self, u64) {
|
|
||||||
let request_id = generate_random();
|
|
||||||
(
|
|
||||||
Self {
|
|
||||||
protocol: Protocol {
|
|
||||||
service_provider_type: ServiceProviderType::Authenticator,
|
|
||||||
version: VERSION,
|
|
||||||
},
|
|
||||||
data: AuthenticatorRequestData::TopUpBandwidth(Box::new(top_up_message)),
|
|
||||||
reply_to,
|
|
||||||
request_id,
|
|
||||||
},
|
|
||||||
request_id,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn to_bytes(&self) -> Result<Vec<u8>, bincode::Error> {
|
|
||||||
use bincode::Options;
|
|
||||||
make_bincode_serializer().serialize(self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
|
||||||
pub enum AuthenticatorRequestData {
|
|
||||||
Initial(InitMessage),
|
|
||||||
Final(Box<FinalMessage>),
|
|
||||||
QueryBandwidth(PeerPublicKey),
|
|
||||||
TopUpBandwidth(Box<TopUpMessage>),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
use std::str::FromStr;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn check_first_bytes_protocol() {
|
|
||||||
let version = 4;
|
|
||||||
let data = AuthenticatorRequest {
|
|
||||||
protocol: Protocol { version, service_provider_type: ServiceProviderType::Authenticator },
|
|
||||||
data: AuthenticatorRequestData::Initial(InitMessage::new(
|
|
||||||
PeerPublicKey::from_str("yvNUDpT5l7W/xDhiu6HkqTHDQwbs/B3J5UrLmORl1EQ=").unwrap(),
|
|
||||||
)),
|
|
||||||
reply_to: Recipient::try_from_base58_string("D1rrpsysCGCYXy9saP8y3kmNpGtJZUXN9SvFoUcqAsM9.9Ssso1ea5NfkbMASdiseDSjTN1fSWda5SgEVjdSN4CvV@GJqd3ZxpXWSNxTfx7B1pPtswpetH4LnJdFeLeuY5KUuN").unwrap(),
|
|
||||||
request_id: 1,
|
|
||||||
};
|
|
||||||
let bytes = *data.to_bytes().unwrap().first_chunk::<2>().unwrap();
|
|
||||||
assert_eq!(bytes, [version, ServiceProviderType::Authenticator as u8]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,157 +0,0 @@
|
|||||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
use super::registration::{RegistrationData, RegistredData, RemainingBandwidthData};
|
|
||||||
use nym_service_provider_requests_common::{Protocol, ServiceProviderType};
|
|
||||||
use nym_sphinx::addressing::Recipient;
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
use crate::make_bincode_serializer;
|
|
||||||
|
|
||||||
use super::VERSION;
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
|
||||||
pub struct AuthenticatorResponse {
|
|
||||||
pub protocol: Protocol,
|
|
||||||
pub data: AuthenticatorResponseData,
|
|
||||||
pub reply_to: Recipient,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AuthenticatorResponse {
|
|
||||||
pub fn new_pending_registration_success(
|
|
||||||
registration_data: RegistrationData,
|
|
||||||
request_id: u64,
|
|
||||||
reply_to: Recipient,
|
|
||||||
) -> Self {
|
|
||||||
Self {
|
|
||||||
protocol: Protocol {
|
|
||||||
service_provider_type: ServiceProviderType::Authenticator,
|
|
||||||
version: VERSION,
|
|
||||||
},
|
|
||||||
data: AuthenticatorResponseData::PendingRegistration(PendingRegistrationResponse {
|
|
||||||
reply: registration_data,
|
|
||||||
reply_to,
|
|
||||||
request_id,
|
|
||||||
}),
|
|
||||||
reply_to,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new_registered(
|
|
||||||
registred_data: RegistredData,
|
|
||||||
reply_to: Recipient,
|
|
||||||
request_id: u64,
|
|
||||||
) -> Self {
|
|
||||||
Self {
|
|
||||||
protocol: Protocol {
|
|
||||||
service_provider_type: ServiceProviderType::Authenticator,
|
|
||||||
version: VERSION,
|
|
||||||
},
|
|
||||||
data: AuthenticatorResponseData::Registered(RegisteredResponse {
|
|
||||||
reply: registred_data,
|
|
||||||
reply_to,
|
|
||||||
request_id,
|
|
||||||
}),
|
|
||||||
reply_to,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new_remaining_bandwidth(
|
|
||||||
remaining_bandwidth_data: Option<RemainingBandwidthData>,
|
|
||||||
reply_to: Recipient,
|
|
||||||
request_id: u64,
|
|
||||||
) -> Self {
|
|
||||||
Self {
|
|
||||||
protocol: Protocol {
|
|
||||||
service_provider_type: ServiceProviderType::Authenticator,
|
|
||||||
version: VERSION,
|
|
||||||
},
|
|
||||||
data: AuthenticatorResponseData::RemainingBandwidth(RemainingBandwidthResponse {
|
|
||||||
reply: remaining_bandwidth_data,
|
|
||||||
reply_to,
|
|
||||||
request_id,
|
|
||||||
}),
|
|
||||||
reply_to,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new_topup_bandwidth(
|
|
||||||
remaining_bandwidth_data: RemainingBandwidthData,
|
|
||||||
reply_to: Recipient,
|
|
||||||
request_id: u64,
|
|
||||||
) -> Self {
|
|
||||||
Self {
|
|
||||||
protocol: Protocol {
|
|
||||||
service_provider_type: ServiceProviderType::Authenticator,
|
|
||||||
version: VERSION,
|
|
||||||
},
|
|
||||||
data: AuthenticatorResponseData::TopUpBandwidth(TopUpBandwidthResponse {
|
|
||||||
reply: remaining_bandwidth_data,
|
|
||||||
reply_to,
|
|
||||||
request_id,
|
|
||||||
}),
|
|
||||||
reply_to,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn recipient(&self) -> Recipient {
|
|
||||||
self.reply_to
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn to_bytes(&self) -> Result<Vec<u8>, bincode::Error> {
|
|
||||||
use bincode::Options;
|
|
||||||
make_bincode_serializer().serialize(self)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn from_reconstructed_message(
|
|
||||||
message: &nym_sphinx::receiver::ReconstructedMessage,
|
|
||||||
) -> Result<Self, bincode::Error> {
|
|
||||||
use bincode::Options;
|
|
||||||
make_bincode_serializer().deserialize(&message.message)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn id(&self) -> Option<u64> {
|
|
||||||
match &self.data {
|
|
||||||
AuthenticatorResponseData::PendingRegistration(response) => Some(response.request_id),
|
|
||||||
AuthenticatorResponseData::Registered(response) => Some(response.request_id),
|
|
||||||
AuthenticatorResponseData::RemainingBandwidth(response) => Some(response.request_id),
|
|
||||||
AuthenticatorResponseData::TopUpBandwidth(response) => Some(response.request_id),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
|
||||||
pub enum AuthenticatorResponseData {
|
|
||||||
PendingRegistration(PendingRegistrationResponse),
|
|
||||||
Registered(RegisteredResponse),
|
|
||||||
RemainingBandwidth(RemainingBandwidthResponse),
|
|
||||||
TopUpBandwidth(TopUpBandwidthResponse),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
|
||||||
pub struct PendingRegistrationResponse {
|
|
||||||
pub request_id: u64,
|
|
||||||
pub reply_to: Recipient,
|
|
||||||
pub reply: RegistrationData,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
|
||||||
pub struct RegisteredResponse {
|
|
||||||
pub request_id: u64,
|
|
||||||
pub reply_to: Recipient,
|
|
||||||
pub reply: RegistredData,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
|
||||||
pub struct RemainingBandwidthResponse {
|
|
||||||
pub request_id: u64,
|
|
||||||
pub reply_to: Recipient,
|
|
||||||
pub reply: Option<RemainingBandwidthData>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
|
||||||
pub struct TopUpBandwidthResponse {
|
|
||||||
pub request_id: u64,
|
|
||||||
pub reply_to: Recipient,
|
|
||||||
pub reply: RemainingBandwidthData,
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
use nym_credentials_interface::CredentialSpendingData;
|
|
||||||
use nym_wireguard_types::PeerPublicKey;
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
|
||||||
pub struct TopUpMessage {
|
|
||||||
/// Base64 encoded x25519 public key
|
|
||||||
pub pub_key: PeerPublicKey,
|
|
||||||
|
|
||||||
/// Ecash credential
|
|
||||||
pub credential: CredentialSpendingData,
|
|
||||||
}
|
|
||||||
@@ -14,15 +14,14 @@ thiserror = { workspace = true }
|
|||||||
url = { workspace = true }
|
url = { workspace = true }
|
||||||
zeroize = { workspace = true }
|
zeroize = { workspace = true }
|
||||||
|
|
||||||
|
nym-ecash-time = { path = "../ecash-time" }
|
||||||
nym-credential-storage = { path = "../credential-storage" }
|
nym-credential-storage = { path = "../credential-storage" }
|
||||||
nym-credentials = { path = "../credentials" }
|
nym-credentials = { path = "../credentials" }
|
||||||
nym-credentials-interface = { path = "../credentials-interface" }
|
nym-credentials-interface = { path = "../credentials-interface" }
|
||||||
nym-crypto = { path = "../crypto", features = ["rand", "asymmetric", "stream_cipher", "aes", "hashing"] }
|
nym-crypto = { path = "../crypto", features = ["rand", "asymmetric", "symmetric", "aes", "hashing"] }
|
||||||
nym-ecash-contract-common = { path = "../cosmwasm-smart-contracts/ecash-contract" }
|
|
||||||
nym-ecash-time = { path = "../ecash-time" }
|
|
||||||
nym-network-defaults = { path = "../network-defaults" }
|
nym-network-defaults = { path = "../network-defaults" }
|
||||||
nym-task = { path = "../task" }
|
|
||||||
nym-validator-client = { path = "../client-libs/validator-client", default-features = false }
|
nym-validator-client = { path = "../client-libs/validator-client", default-features = false }
|
||||||
|
nym-ecash-contract-common = { path = "../cosmwasm-smart-contracts/ecash-contract" }
|
||||||
|
|
||||||
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.nym-validator-client]
|
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.nym-validator-client]
|
||||||
path = "../client-libs/validator-client"
|
path = "../client-libs/validator-client"
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ use nym_validator_client::coconut::all_ecash_api_clients;
|
|||||||
use nym_validator_client::nym_api::EpochId;
|
use nym_validator_client::nym_api::EpochId;
|
||||||
use nym_validator_client::nyxd::contract_traits::EcashSigningClient;
|
use nym_validator_client::nyxd::contract_traits::EcashSigningClient;
|
||||||
use nym_validator_client::nyxd::contract_traits::{DkgQueryClient, EcashQueryClient};
|
use nym_validator_client::nyxd::contract_traits::{DkgQueryClient, EcashQueryClient};
|
||||||
use nym_validator_client::nyxd::cosmwasm_client::ContractResponseData;
|
use nym_validator_client::nyxd::cosmwasm_client::ToSingletonContractData;
|
||||||
use nym_validator_client::EcashApiClient;
|
use nym_validator_client::EcashApiClient;
|
||||||
use rand::rngs::OsRng;
|
use rand::rngs::OsRng;
|
||||||
|
|
||||||
|
|||||||
@@ -1,25 +1,13 @@
|
|||||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
#[derive(Debug)]
|
// See other comments for other TaskStatus message enumds about abusing the Error trait when we
|
||||||
|
// should have a new trait for TaskStatus messages
|
||||||
|
#[derive(Debug, thiserror::Error)]
|
||||||
pub enum BandwidthStatusMessage {
|
pub enum BandwidthStatusMessage {
|
||||||
|
#[error("remaining bandwidth: {0}")]
|
||||||
RemainingBandwidth(i64),
|
RemainingBandwidth(i64),
|
||||||
|
|
||||||
|
#[error("no bandwidth left")]
|
||||||
NoBandwidth,
|
NoBandwidth,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::fmt::Display for BandwidthStatusMessage {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
||||||
match self {
|
|
||||||
BandwidthStatusMessage::RemainingBandwidth(b) => {
|
|
||||||
write!(f, "remaining bandwidth: {}", b)
|
|
||||||
}
|
|
||||||
BandwidthStatusMessage::NoBandwidth => write!(f, "no bandwidth left"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl nym_task::TaskStatusEvent for BandwidthStatusMessage {
|
|
||||||
fn as_any(&self) -> &dyn std::any::Any {
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ use nym_credential_storage::models::RetrievedTicketbook;
|
|||||||
use nym_credential_storage::storage::Storage;
|
use nym_credential_storage::storage::Storage;
|
||||||
use nym_credentials::ecash::bandwidth::CredentialSpendingData;
|
use nym_credentials::ecash::bandwidth::CredentialSpendingData;
|
||||||
use nym_credentials_interface::{
|
use nym_credentials_interface::{
|
||||||
AnnotatedCoinIndexSignature, AnnotatedExpirationDateSignature, TicketType, VerificationKeyAuth,
|
AnnotatedCoinIndexSignature, AnnotatedExpirationDateSignature, VerificationKeyAuth,
|
||||||
};
|
};
|
||||||
use nym_ecash_time::Date;
|
use nym_ecash_time::Date;
|
||||||
use nym_validator_client::nym_api::EpochId;
|
use nym_validator_client::nym_api::EpochId;
|
||||||
@@ -64,10 +64,9 @@ impl<C, St: Storage> BandwidthController<C, St> {
|
|||||||
BandwidthController { storage, client }
|
BandwidthController { storage, client }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tries to retrieve one of the stored, unused credentials for the given type that hasn't yet expired.
|
/// Tries to retrieve one of the stored, unused credentials that hasn't yet expired.
|
||||||
pub async fn get_next_usable_ticketbook(
|
pub async fn get_next_usable_ticketbook(
|
||||||
&self,
|
&self,
|
||||||
ticketbook_type: TicketType,
|
|
||||||
tickets: u32,
|
tickets: u32,
|
||||||
) -> Result<RetrievedTicketbook, BandwidthControllerError>
|
) -> Result<RetrievedTicketbook, BandwidthControllerError>
|
||||||
where
|
where
|
||||||
@@ -75,7 +74,7 @@ impl<C, St: Storage> BandwidthController<C, St> {
|
|||||||
{
|
{
|
||||||
let Some(ticketbook) = self
|
let Some(ticketbook) = self
|
||||||
.storage
|
.storage
|
||||||
.get_next_unspent_usable_ticketbook(ticketbook_type.to_string(), tickets)
|
.get_next_unspent_usable_ticketbook(tickets)
|
||||||
.await
|
.await
|
||||||
.map_err(BandwidthControllerError::credential_storage_error)?
|
.map_err(BandwidthControllerError::credential_storage_error)?
|
||||||
else {
|
else {
|
||||||
@@ -182,7 +181,6 @@ impl<C, St: Storage> BandwidthController<C, St> {
|
|||||||
|
|
||||||
pub async fn prepare_ecash_ticket(
|
pub async fn prepare_ecash_ticket(
|
||||||
&self,
|
&self,
|
||||||
ticketbook_type: TicketType,
|
|
||||||
provider_pk: [u8; 32],
|
provider_pk: [u8; 32],
|
||||||
tickets_to_spend: u32,
|
tickets_to_spend: u32,
|
||||||
) -> Result<PreparedCredential, BandwidthControllerError>
|
) -> Result<PreparedCredential, BandwidthControllerError>
|
||||||
@@ -190,9 +188,7 @@ impl<C, St: Storage> BandwidthController<C, St> {
|
|||||||
C: DkgQueryClient + Sync + Send,
|
C: DkgQueryClient + Sync + Send,
|
||||||
<St as Storage>::StorageError: Send + Sync + 'static,
|
<St as Storage>::StorageError: Send + Sync + 'static,
|
||||||
{
|
{
|
||||||
let retrieved_ticketbook = self
|
let retrieved_ticketbook = self.get_next_usable_ticketbook(tickets_to_spend).await?;
|
||||||
.get_next_usable_ticketbook(ticketbook_type, tickets_to_spend)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
let ticketbook_id = retrieved_ticketbook.ticketbook_id;
|
let ticketbook_id = retrieved_ticketbook.ticketbook_id;
|
||||||
let epoch_id = retrieved_ticketbook.ticketbook.epoch_id();
|
let epoch_id = retrieved_ticketbook.ticketbook.epoch_id();
|
||||||
|
|||||||
@@ -8,14 +8,14 @@ license = { workspace = true }
|
|||||||
repository = { workspace = true }
|
repository = { workspace = true }
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
const-str = { workspace = true }
|
||||||
clap = { workspace = true, features = ["derive"], optional = true }
|
clap = { workspace = true, features = ["derive"], optional = true }
|
||||||
clap_complete = { workspace = true, optional = true }
|
clap_complete = { workspace = true, optional = true }
|
||||||
clap_complete_fig = { workspace = true, optional = true }
|
clap_complete_fig = { workspace = true, optional = true }
|
||||||
const-str = { workspace = true }
|
|
||||||
log = { workspace = true }
|
log = { workspace = true }
|
||||||
pretty_env_logger = { workspace = true }
|
pretty_env_logger = { workspace = true }
|
||||||
|
semver = "0.11"
|
||||||
schemars = { workspace = true, features = ["preserve_order"], optional = true }
|
schemars = { workspace = true, features = ["preserve_order"], optional = true }
|
||||||
semver.workspace = true
|
|
||||||
serde = { workspace = true, features = ["derive"] }
|
serde = { workspace = true, features = ["derive"] }
|
||||||
serde_json = { workspace = true, optional = true }
|
serde_json = { workspace = true, optional = true }
|
||||||
|
|
||||||
@@ -45,4 +45,3 @@ tracing = [
|
|||||||
"opentelemetry",
|
"opentelemetry",
|
||||||
]
|
]
|
||||||
clap = [ "dep:clap", "dep:clap_complete", "dep:clap_complete_fig" ]
|
clap = [ "dep:clap", "dep:clap_complete", "dep:clap_complete_fig" ]
|
||||||
models = []
|
|
||||||
|
|||||||
@@ -47,7 +47,6 @@ pub fn setup_logging() {
|
|||||||
#[cfg(feature = "basic_tracing")]
|
#[cfg(feature = "basic_tracing")]
|
||||||
pub fn setup_tracing_logger() {
|
pub fn setup_tracing_logger() {
|
||||||
let log_builder = tracing_subscriber::fmt()
|
let log_builder = tracing_subscriber::fmt()
|
||||||
.with_writer(std::io::stderr)
|
|
||||||
// Use a more compact, abbreviated log format
|
// Use a more compact, abbreviated log format
|
||||||
.compact()
|
.compact()
|
||||||
// Display source code file paths
|
// Display source code file paths
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
use semver::SemVerError;
|
||||||
pub use semver::Version;
|
pub use semver::Version;
|
||||||
|
|
||||||
/// Checks if the version is minor version compatible.
|
|
||||||
///
|
|
||||||
/// Checks whether given `version` is compatible with a given semantic version requirement `req`
|
/// Checks whether given `version` is compatible with a given semantic version requirement `req`
|
||||||
/// according to major-minor semver rules. The semantic version requirement can be passed as a full,
|
/// according to major-minor semver rules. The semantic version requirement can be passed as a full,
|
||||||
/// concrete version number, because that's what we'll have in our Cargo.toml files (e.g. 0.3.2).
|
/// concrete version number, because that's what we'll have in our Cargo.toml files (e.g. 0.3.2).
|
||||||
@@ -23,7 +22,7 @@ pub fn is_minor_version_compatible(version: &str, req: &str) -> bool {
|
|||||||
expected_version.major == req_version.major && expected_version.minor == req_version.minor
|
expected_version.major == req_version.major && expected_version.minor == req_version.minor
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_version(raw_version: &str) -> Result<Version, semver::Error> {
|
pub fn parse_version(raw_version: &str) -> Result<Version, SemVerError> {
|
||||||
Version::parse(raw_version)
|
Version::parse(raw_version)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ base64 = { workspace = true }
|
|||||||
bs58 = { workspace = true }
|
bs58 = { workspace = true }
|
||||||
cfg-if = { workspace = true }
|
cfg-if = { workspace = true }
|
||||||
clap = { workspace = true, optional = true }
|
clap = { workspace = true, optional = true }
|
||||||
comfy-table = { workspace = true, optional = true }
|
comfy-table = { version = "7.1.1", optional = true }
|
||||||
futures = { workspace = true }
|
futures = { workspace = true }
|
||||||
humantime-serde = { workspace = true }
|
humantime-serde = { workspace = true }
|
||||||
log = { workspace = true }
|
log = { workspace = true }
|
||||||
@@ -43,7 +43,6 @@ nym-gateway-requests = { path = "../gateway-requests" }
|
|||||||
nym-metrics = { path = "../nym-metrics" }
|
nym-metrics = { path = "../nym-metrics" }
|
||||||
nym-nonexhaustive-delayqueue = { path = "../nonexhaustive-delayqueue" }
|
nym-nonexhaustive-delayqueue = { path = "../nonexhaustive-delayqueue" }
|
||||||
nym-sphinx = { path = "../nymsphinx" }
|
nym-sphinx = { path = "../nymsphinx" }
|
||||||
nym-statistics-common = { path = "../statistics" }
|
|
||||||
nym-pemstore = { path = "../pemstore" }
|
nym-pemstore = { path = "../pemstore" }
|
||||||
nym-topology = { path = "../topology", features = ["serializable"] }
|
nym-topology = { path = "../topology", features = ["serializable"] }
|
||||||
nym-validator-client = { path = "../client-libs/validator-client", default-features = false }
|
nym-validator-client = { path = "../client-libs/validator-client", default-features = false }
|
||||||
@@ -60,19 +59,19 @@ nym-ecash-time = { path = "../ecash-time" }
|
|||||||
|
|
||||||
### For serving prometheus metrics
|
### For serving prometheus metrics
|
||||||
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.hyper]
|
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.hyper]
|
||||||
workspace = true
|
version = "1"
|
||||||
features = ["server", "http1"]
|
features = ["server", "http1"]
|
||||||
|
|
||||||
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.http-body-util]
|
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.http-body-util]
|
||||||
workspace = true
|
version = "0.1"
|
||||||
|
|
||||||
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.hyper-util]
|
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.hyper-util]
|
||||||
workspace = true
|
version = "0.1"
|
||||||
features = ["tokio"]
|
features = ["tokio"]
|
||||||
###
|
###
|
||||||
|
|
||||||
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.tokio-stream]
|
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.tokio-stream]
|
||||||
workspace = true
|
version = "0.1.16"
|
||||||
features = ["time"]
|
features = ["time"]
|
||||||
|
|
||||||
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.tokio]
|
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.tokio]
|
||||||
@@ -111,7 +110,7 @@ path = "../wasm/utils"
|
|||||||
features = ["websocket"]
|
features = ["websocket"]
|
||||||
|
|
||||||
[target."cfg(target_arch = \"wasm32\")".dependencies.time]
|
[target."cfg(target_arch = \"wasm32\")".dependencies.time]
|
||||||
workspace = true
|
version = "0.3.17"
|
||||||
features = ["wasm-bindgen"]
|
features = ["wasm-bindgen"]
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
|||||||
@@ -23,4 +23,4 @@ nym-sphinx-addressing = { path = "../../nymsphinx/addressing" }
|
|||||||
|
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
disk-persistence = ["nym-pemstore"]
|
disk-persistence = ["nym-pemstore"]
|
||||||
@@ -2,7 +2,6 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
use nym_config::defaults::NymNetworkDetails;
|
use nym_config::defaults::NymNetworkDetails;
|
||||||
use nym_config::serde_helpers::{de_maybe_stringified, ser_maybe_stringified};
|
|
||||||
use nym_sphinx_addressing::Recipient;
|
use nym_sphinx_addressing::Recipient;
|
||||||
use nym_sphinx_params::{PacketSize, PacketType};
|
use nym_sphinx_params::{PacketSize, PacketType};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
@@ -62,11 +61,6 @@ const DEFAULT_MAXIMUM_REPLY_SURB_AGE: Duration = Duration::from_secs(12 * 60 * 6
|
|||||||
// 24 hours
|
// 24 hours
|
||||||
const DEFAULT_MAXIMUM_REPLY_KEY_AGE: Duration = Duration::from_secs(24 * 60 * 60);
|
const DEFAULT_MAXIMUM_REPLY_KEY_AGE: Duration = Duration::from_secs(24 * 60 * 60);
|
||||||
|
|
||||||
// stats reporting related
|
|
||||||
|
|
||||||
/// Time interval between reporting statistics to the given provider if it exist
|
|
||||||
const STATS_REPORT_INTERVAL_SECS: Duration = Duration::from_secs(300);
|
|
||||||
|
|
||||||
use crate::error::InvalidTrafficModeFailure;
|
use crate::error::InvalidTrafficModeFailure;
|
||||||
pub use nym_country_group::CountryGroup;
|
pub use nym_country_group::CountryGroup;
|
||||||
|
|
||||||
@@ -139,12 +133,6 @@ impl Config {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_enabled_stats_reporting_address(mut self, address: Recipient) -> Self {
|
|
||||||
self.debug.stats_reporting.provider_address = Some(address);
|
|
||||||
self.debug.stats_reporting.enabled = true; //since we are overriding the address, we assume the reporting should be enabled
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: this should be refactored properly
|
// TODO: this should be refactored properly
|
||||||
// as of 12.09.23 the below is true (not sure how this comment will rot in the future)
|
// as of 12.09.23 the below is true (not sure how this comment will rot in the future)
|
||||||
// medium_toggle:
|
// medium_toggle:
|
||||||
@@ -393,20 +381,13 @@ pub struct Traffic {
|
|||||||
/// poisson distribution.
|
/// poisson distribution.
|
||||||
pub disable_main_poisson_packet_distribution: bool,
|
pub disable_main_poisson_packet_distribution: bool,
|
||||||
|
|
||||||
/// Specify whether route selection should be determined by the packet header.
|
|
||||||
pub deterministic_route_selection: bool,
|
|
||||||
|
|
||||||
/// Specify how many times particular packet can be retransmitted
|
|
||||||
/// None - no limit
|
|
||||||
pub maximum_number_of_retransmissions: Option<u32>,
|
|
||||||
|
|
||||||
/// Specifies the packet size used for sent messages.
|
/// Specifies the packet size used for sent messages.
|
||||||
/// Do not override it unless you understand the consequences of that change.
|
/// Do not override it unless you understand the consequences of that change.
|
||||||
pub primary_packet_size: PacketSize,
|
pub primary_packet_size: PacketSize,
|
||||||
|
|
||||||
/// Specifies the optional auxiliary packet size for optimizing message streams.
|
/// Specifies the optional auxiliary packet size for optimizing message streams.
|
||||||
/// Note that its use decreases overall anonymity.
|
/// Note that its use decreases overall anonymity.
|
||||||
/// Do not set it unless you understand the consequences of that change.
|
/// Do not set it it unless you understand the consequences of that change.
|
||||||
pub secondary_packet_size: Option<PacketSize>,
|
pub secondary_packet_size: Option<PacketSize>,
|
||||||
|
|
||||||
pub packet_type: PacketType,
|
pub packet_type: PacketType,
|
||||||
@@ -431,8 +412,6 @@ impl Default for Traffic {
|
|||||||
average_packet_delay: DEFAULT_AVERAGE_PACKET_DELAY,
|
average_packet_delay: DEFAULT_AVERAGE_PACKET_DELAY,
|
||||||
message_sending_average_delay: DEFAULT_MESSAGE_STREAM_AVERAGE_DELAY,
|
message_sending_average_delay: DEFAULT_MESSAGE_STREAM_AVERAGE_DELAY,
|
||||||
disable_main_poisson_packet_distribution: false,
|
disable_main_poisson_packet_distribution: false,
|
||||||
deterministic_route_selection: false,
|
|
||||||
maximum_number_of_retransmissions: None,
|
|
||||||
primary_packet_size: PacketSize::RegularPacket,
|
primary_packet_size: PacketSize::RegularPacket,
|
||||||
secondary_packet_size: None,
|
secondary_packet_size: None,
|
||||||
packet_type: PacketType::Mix,
|
packet_type: PacketType::Mix,
|
||||||
@@ -652,34 +631,6 @@ impl Default for ReplySurbs {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
|
||||||
#[serde(default, deny_unknown_fields)]
|
|
||||||
pub struct StatsReporting {
|
|
||||||
/// Is stats reporting enabled
|
|
||||||
pub enabled: bool,
|
|
||||||
|
|
||||||
/// Address of the stats collector. If this is none, no reporting will happen, regardless of `enabled`
|
|
||||||
#[serde(
|
|
||||||
serialize_with = "ser_maybe_stringified",
|
|
||||||
deserialize_with = "de_maybe_stringified"
|
|
||||||
)]
|
|
||||||
pub provider_address: Option<Recipient>,
|
|
||||||
|
|
||||||
/// With what frequence will statistics be sent
|
|
||||||
#[serde(with = "humantime_serde")]
|
|
||||||
pub reporting_interval: Duration,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for StatsReporting {
|
|
||||||
fn default() -> Self {
|
|
||||||
StatsReporting {
|
|
||||||
enabled: true,
|
|
||||||
provider_address: None,
|
|
||||||
reporting_interval: STATS_REPORT_INTERVAL_SECS,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||||
#[serde(default, deny_unknown_fields)]
|
#[serde(default, deny_unknown_fields)]
|
||||||
pub struct DebugConfig {
|
pub struct DebugConfig {
|
||||||
@@ -700,9 +651,6 @@ pub struct DebugConfig {
|
|||||||
|
|
||||||
/// Defines all configuration options related to reply SURBs.
|
/// Defines all configuration options related to reply SURBs.
|
||||||
pub reply_surbs: ReplySurbs,
|
pub reply_surbs: ReplySurbs,
|
||||||
|
|
||||||
/// Defines all configuration options related to stats reporting.
|
|
||||||
pub stats_reporting: StatsReporting,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DebugConfig {
|
impl DebugConfig {
|
||||||
@@ -724,7 +672,6 @@ impl Default for DebugConfig {
|
|||||||
acknowledgements: Default::default(),
|
acknowledgements: Default::default(),
|
||||||
topology: Default::default(),
|
topology: Default::default(),
|
||||||
reply_surbs: Default::default(),
|
reply_surbs: Default::default(),
|
||||||
stats_reporting: Default::default(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -111,7 +111,6 @@ impl From<ConfigV5> for Config {
|
|||||||
primary_packet_size: value.debug.traffic.primary_packet_size,
|
primary_packet_size: value.debug.traffic.primary_packet_size,
|
||||||
secondary_packet_size: value.debug.traffic.secondary_packet_size,
|
secondary_packet_size: value.debug.traffic.secondary_packet_size,
|
||||||
packet_type: value.debug.traffic.packet_type,
|
packet_type: value.debug.traffic.packet_type,
|
||||||
..Default::default()
|
|
||||||
},
|
},
|
||||||
cover_traffic: CoverTraffic {
|
cover_traffic: CoverTraffic {
|
||||||
loop_cover_traffic_average_delay: value
|
loop_cover_traffic_average_delay: value
|
||||||
@@ -182,7 +181,6 @@ impl From<ConfigV5> for Config {
|
|||||||
maximum_reply_key_age: value.debug.reply_surbs.maximum_reply_key_age,
|
maximum_reply_key_age: value.debug.reply_surbs.maximum_reply_key_age,
|
||||||
surb_mix_hops: value.debug.reply_surbs.surb_mix_hops,
|
surb_mix_hops: value.debug.reply_surbs.surb_mix_hops,
|
||||||
},
|
},
|
||||||
stats_reporting: Default::default(),
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
-20
@@ -1,20 +0,0 @@
|
|||||||
{
|
|
||||||
"db_name": "SQLite",
|
|
||||||
"query": "SELECT EXISTS (SELECT 1 FROM registered_gateway WHERE gateway_id_bs58 = ?) AS 'exists'",
|
|
||||||
"describe": {
|
|
||||||
"columns": [
|
|
||||||
{
|
|
||||||
"name": "exists",
|
|
||||||
"ordinal": 0,
|
|
||||||
"type_info": "Int"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"parameters": {
|
|
||||||
"Right": 1
|
|
||||||
},
|
|
||||||
"nullable": [
|
|
||||||
null
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"hash": "06e743d143fcc4be20ca2af5e99b19f15d22fff72490473587a14cdc046fda32"
|
|
||||||
}
|
|
||||||
-44
@@ -1,44 +0,0 @@
|
|||||||
{
|
|
||||||
"db_name": "SQLite",
|
|
||||||
"query": "SELECT * FROM remote_gateway_details WHERE gateway_id_bs58 = ?",
|
|
||||||
"describe": {
|
|
||||||
"columns": [
|
|
||||||
{
|
|
||||||
"name": "gateway_id_bs58",
|
|
||||||
"ordinal": 0,
|
|
||||||
"type_info": "Text"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "gateway_owner_address",
|
|
||||||
"ordinal": 1,
|
|
||||||
"type_info": "Text"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "gateway_listener",
|
|
||||||
"ordinal": 2,
|
|
||||||
"type_info": "Text"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "derived_aes128_ctr_blake3_hmac_keys_bs58",
|
|
||||||
"ordinal": 3,
|
|
||||||
"type_info": "Text"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "derived_aes256_gcm_siv_key",
|
|
||||||
"ordinal": 4,
|
|
||||||
"type_info": "Blob"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"parameters": {
|
|
||||||
"Right": 1
|
|
||||||
},
|
|
||||||
"nullable": [
|
|
||||||
false,
|
|
||||||
true,
|
|
||||||
false,
|
|
||||||
true,
|
|
||||||
true
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"hash": "0e85ec18da67cf4e3df04ad80136571f6e920eb2290f20b1b8c5b0ab4b489985"
|
|
||||||
}
|
|
||||||
-12
@@ -1,12 +0,0 @@
|
|||||||
{
|
|
||||||
"db_name": "SQLite",
|
|
||||||
"query": "\n UPDATE remote_gateway_details\n SET\n derived_aes128_ctr_blake3_hmac_keys_bs58 = ?,\n derived_aes256_gcm_siv_key = ?\n WHERE gateway_id_bs58 = ?\n ",
|
|
||||||
"describe": {
|
|
||||||
"columns": [],
|
|
||||||
"parameters": {
|
|
||||||
"Right": 3
|
|
||||||
},
|
|
||||||
"nullable": []
|
|
||||||
},
|
|
||||||
"hash": "0f1dfb89f1eb39f4a58787af0f53a7a93afb7e4d2e54e2d38fd79d31c8575a54"
|
|
||||||
}
|
|
||||||
-12
@@ -1,12 +0,0 @@
|
|||||||
{
|
|
||||||
"db_name": "SQLite",
|
|
||||||
"query": "DELETE FROM remote_gateway_details WHERE gateway_id_bs58 = ?",
|
|
||||||
"describe": {
|
|
||||||
"columns": [],
|
|
||||||
"parameters": {
|
|
||||||
"Right": 1
|
|
||||||
},
|
|
||||||
"nullable": []
|
|
||||||
},
|
|
||||||
"hash": "1da6904e72b5abb9abf75affb13af7974d7795b4cbdba234273345fe161df233"
|
|
||||||
}
|
|
||||||
-12
@@ -1,12 +0,0 @@
|
|||||||
{
|
|
||||||
"db_name": "SQLite",
|
|
||||||
"query": "DELETE FROM custom_gateway_details WHERE gateway_id_bs58 = ?",
|
|
||||||
"describe": {
|
|
||||||
"columns": [],
|
|
||||||
"parameters": {
|
|
||||||
"Right": 1
|
|
||||||
},
|
|
||||||
"nullable": []
|
|
||||||
},
|
|
||||||
"hash": "4f78619aca933484cd67cb89a376b2a5bec1c191993ff58f0c71c03e3ef6d92d"
|
|
||||||
}
|
|
||||||
-26
@@ -1,26 +0,0 @@
|
|||||||
{
|
|
||||||
"db_name": "SQLite",
|
|
||||||
"query": "SELECT * FROM custom_gateway_details WHERE gateway_id_bs58 = ?",
|
|
||||||
"describe": {
|
|
||||||
"columns": [
|
|
||||||
{
|
|
||||||
"name": "gateway_id_bs58",
|
|
||||||
"ordinal": 0,
|
|
||||||
"type_info": "Text"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "data",
|
|
||||||
"ordinal": 1,
|
|
||||||
"type_info": "Blob"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"parameters": {
|
|
||||||
"Right": 1
|
|
||||||
},
|
|
||||||
"nullable": [
|
|
||||||
false,
|
|
||||||
true
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"hash": "54f552a9dbe95236f946ac2b6615e03504afa58e345ae16a128629d8e76f0a11"
|
|
||||||
}
|
|
||||||
-20
@@ -1,20 +0,0 @@
|
|||||||
{
|
|
||||||
"db_name": "SQLite",
|
|
||||||
"query": "SELECT gateway_id_bs58 FROM registered_gateway",
|
|
||||||
"describe": {
|
|
||||||
"columns": [
|
|
||||||
{
|
|
||||||
"name": "gateway_id_bs58",
|
|
||||||
"ordinal": 0,
|
|
||||||
"type_info": "Text"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"parameters": {
|
|
||||||
"Right": 0
|
|
||||||
},
|
|
||||||
"nullable": [
|
|
||||||
false
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"hash": "5661cf1ad8bd5ca062e855e1971a8787133ee41814bd3efdd501f9ee0c050f2b"
|
|
||||||
}
|
|
||||||
-12
@@ -1,12 +0,0 @@
|
|||||||
{
|
|
||||||
"db_name": "SQLite",
|
|
||||||
"query": "UPDATE active_gateway SET active_gateway_id_bs58 = ?",
|
|
||||||
"describe": {
|
|
||||||
"columns": [],
|
|
||||||
"parameters": {
|
|
||||||
"Right": 1
|
|
||||||
},
|
|
||||||
"nullable": []
|
|
||||||
},
|
|
||||||
"hash": "80476cf2906eb0ecf7f66c16bc5682169b87f488b6927fa67fade6bf5abf7582"
|
|
||||||
}
|
|
||||||
-12
@@ -1,12 +0,0 @@
|
|||||||
{
|
|
||||||
"db_name": "SQLite",
|
|
||||||
"query": "\n INSERT INTO registered_gateway(gateway_id_bs58, registration_timestamp, gateway_type) \n VALUES (?, ?, ?)\n ",
|
|
||||||
"describe": {
|
|
||||||
"columns": [],
|
|
||||||
"parameters": {
|
|
||||||
"Right": 3
|
|
||||||
},
|
|
||||||
"nullable": []
|
|
||||||
},
|
|
||||||
"hash": "8909fd329e7e5fb16c4989b15b3d3a12bba1569520e01f6f074178e23d6ee89e"
|
|
||||||
}
|
|
||||||
-12
@@ -1,12 +0,0 @@
|
|||||||
{
|
|
||||||
"db_name": "SQLite",
|
|
||||||
"query": "\n INSERT INTO remote_gateway_details(gateway_id_bs58, derived_aes128_ctr_blake3_hmac_keys_bs58, derived_aes256_gcm_siv_key, gateway_owner_address, gateway_listener)\n VALUES (?, ?, ?, ?, ?)\n ",
|
|
||||||
"describe": {
|
|
||||||
"columns": [],
|
|
||||||
"parameters": {
|
|
||||||
"Right": 5
|
|
||||||
},
|
|
||||||
"nullable": []
|
|
||||||
},
|
|
||||||
"hash": "a6939bea03b10cde810a9a099bd597b4f51092e30a41c4085a8f8668f039f7c0"
|
|
||||||
}
|
|
||||||
-12
@@ -1,12 +0,0 @@
|
|||||||
{
|
|
||||||
"db_name": "SQLite",
|
|
||||||
"query": "\n INSERT INTO custom_gateway_details(gateway_id_bs58, data) \n VALUES (?, ?)\n ",
|
|
||||||
"describe": {
|
|
||||||
"columns": [],
|
|
||||||
"parameters": {
|
|
||||||
"Right": 2
|
|
||||||
},
|
|
||||||
"nullable": []
|
|
||||||
},
|
|
||||||
"hash": "b059bc3688b6b7f83f47048db9897720fd4e6f3211bf74030a9638f7bf6738e4"
|
|
||||||
}
|
|
||||||
-20
@@ -1,20 +0,0 @@
|
|||||||
{
|
|
||||||
"db_name": "SQLite",
|
|
||||||
"query": "SELECT active_gateway_id_bs58 FROM active_gateway",
|
|
||||||
"describe": {
|
|
||||||
"columns": [
|
|
||||||
{
|
|
||||||
"name": "active_gateway_id_bs58",
|
|
||||||
"ordinal": 0,
|
|
||||||
"type_info": "Text"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"parameters": {
|
|
||||||
"Right": 0
|
|
||||||
},
|
|
||||||
"nullable": [
|
|
||||||
true
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"hash": "bf249752f08c283bf5942b6ff48125c24750b523cfcad1e5e9069dbf7050e2a1"
|
|
||||||
}
|
|
||||||
-12
@@ -1,12 +0,0 @@
|
|||||||
{
|
|
||||||
"db_name": "SQLite",
|
|
||||||
"query": "DELETE FROM registered_gateway WHERE gateway_id_bs58 = ?",
|
|
||||||
"describe": {
|
|
||||||
"columns": [],
|
|
||||||
"parameters": {
|
|
||||||
"Right": 1
|
|
||||||
},
|
|
||||||
"nullable": []
|
|
||||||
},
|
|
||||||
"hash": "f3ebe259e26c05ecdd33bd9085dbb91cd5046a8c9d4434cf085a4fa2ebf03e93"
|
|
||||||
}
|
|
||||||
-13
@@ -1,13 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
-- make aes128 key column nullable and add aes256 column
|
|
||||||
ALTER TABLE remote_gateway_details RENAME COLUMN derived_aes128_ctr_blake3_hmac_keys_bs58 TO derived_aes128_ctr_blake3_hmac_keys_bs58_old;
|
|
||||||
ALTER TABLE remote_gateway_details ADD COLUMN derived_aes128_ctr_blake3_hmac_keys_bs58 TEXT;
|
|
||||||
ALTER TABLE remote_gateway_details ADD COLUMN derived_aes256_gcm_siv_key BLOB;
|
|
||||||
|
|
||||||
UPDATE remote_gateway_details SET derived_aes128_ctr_blake3_hmac_keys_bs58 = derived_aes128_ctr_blake3_hmac_keys_bs58_old;
|
|
||||||
|
|
||||||
ALTER TABLE remote_gateway_details DROP COLUMN derived_aes128_ctr_blake3_hmac_keys_bs58_old;
|
|
||||||
@@ -29,10 +29,11 @@ impl StorageManager {
|
|||||||
})?;
|
})?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let opts = sqlx::sqlite::SqliteConnectOptions::new()
|
let mut opts = sqlx::sqlite::SqliteConnectOptions::new()
|
||||||
.filename(database_path)
|
.filename(database_path)
|
||||||
.create_if_missing(true)
|
.create_if_missing(true);
|
||||||
.disable_statement_logging();
|
|
||||||
|
opts.disable_statement_logging();
|
||||||
|
|
||||||
let connection_pool = sqlx::SqlitePool::connect_with(opts)
|
let connection_pool = sqlx::SqlitePool::connect_with(opts)
|
||||||
.await
|
.await
|
||||||
@@ -81,7 +82,7 @@ impl StorageManager {
|
|||||||
sqlx::query!("SELECT EXISTS (SELECT 1 FROM registered_gateway WHERE gateway_id_bs58 = ?) AS 'exists'", gateway_id)
|
sqlx::query!("SELECT EXISTS (SELECT 1 FROM registered_gateway WHERE gateway_id_bs58 = ?) AS 'exists'", gateway_id)
|
||||||
.fetch_one(&self.connection_pool)
|
.fetch_one(&self.connection_pool)
|
||||||
.await
|
.await
|
||||||
.map(|result| result.exists == Some(1))
|
.map(|result| result.exists == 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn maybe_get_registered_gateway(
|
pub(crate) async fn maybe_get_registered_gateway(
|
||||||
@@ -154,12 +155,11 @@ impl StorageManager {
|
|||||||
) -> Result<(), sqlx::Error> {
|
) -> Result<(), sqlx::Error> {
|
||||||
sqlx::query!(
|
sqlx::query!(
|
||||||
r#"
|
r#"
|
||||||
INSERT INTO remote_gateway_details(gateway_id_bs58, derived_aes128_ctr_blake3_hmac_keys_bs58, derived_aes256_gcm_siv_key, gateway_owner_address, gateway_listener)
|
INSERT INTO remote_gateway_details(gateway_id_bs58, derived_aes128_ctr_blake3_hmac_keys_bs58, gateway_owner_address, gateway_listener)
|
||||||
VALUES (?, ?, ?, ?, ?)
|
VALUES (?, ?, ?, ?)
|
||||||
"#,
|
"#,
|
||||||
remote.gateway_id_bs58,
|
remote.gateway_id_bs58,
|
||||||
remote.derived_aes128_ctr_blake3_hmac_keys_bs58,
|
remote.derived_aes128_ctr_blake3_hmac_keys_bs58,
|
||||||
remote.derived_aes256_gcm_siv_key,
|
|
||||||
remote.gateway_owner_address,
|
remote.gateway_owner_address,
|
||||||
remote.gateway_listener,
|
remote.gateway_listener,
|
||||||
)
|
)
|
||||||
@@ -168,30 +168,6 @@ impl StorageManager {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn update_remote_gateway_key(
|
|
||||||
&self,
|
|
||||||
gateway_id_bs58: &str,
|
|
||||||
derived_aes128_ctr_blake3_hmac_keys_bs58: Option<&str>,
|
|
||||||
derived_aes256_gcm_siv_key: Option<&[u8]>,
|
|
||||||
) -> Result<(), sqlx::Error> {
|
|
||||||
sqlx::query!(
|
|
||||||
r#"
|
|
||||||
UPDATE remote_gateway_details
|
|
||||||
SET
|
|
||||||
derived_aes128_ctr_blake3_hmac_keys_bs58 = ?,
|
|
||||||
derived_aes256_gcm_siv_key = ?
|
|
||||||
WHERE gateway_id_bs58 = ?
|
|
||||||
"#,
|
|
||||||
derived_aes128_ctr_blake3_hmac_keys_bs58,
|
|
||||||
derived_aes256_gcm_siv_key,
|
|
||||||
gateway_id_bs58
|
|
||||||
)
|
|
||||||
.execute(&self.connection_pool)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) async fn remove_remote_gateway_details(
|
pub(crate) async fn remove_remote_gateway_details(
|
||||||
&self,
|
&self,
|
||||||
gateway_id: &str,
|
gateway_id: &str,
|
||||||
|
|||||||
@@ -7,8 +7,7 @@ use crate::{
|
|||||||
};
|
};
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use manager::StorageManager;
|
use manager::StorageManager;
|
||||||
use nym_crypto::asymmetric::ed25519;
|
use nym_crypto::asymmetric::identity::PublicKey;
|
||||||
use nym_gateway_requests::SharedSymmetricKey;
|
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
pub mod error;
|
pub mod error;
|
||||||
@@ -68,7 +67,7 @@ impl GatewaysDetailsStore for OnDiskGatewaysDetails {
|
|||||||
Ok(registered)
|
Ok(registered)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn all_gateways_identities(&self) -> Result<Vec<ed25519::PublicKey>, Self::StorageError> {
|
async fn all_gateways_identities(&self) -> Result<Vec<PublicKey>, Self::StorageError> {
|
||||||
Ok(self
|
Ok(self
|
||||||
.manager
|
.manager
|
||||||
.registered_gateways()
|
.registered_gateways()
|
||||||
@@ -133,21 +132,6 @@ impl GatewaysDetailsStore for OnDiskGatewaysDetails {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn upgrade_stored_remote_gateway_key(
|
|
||||||
&self,
|
|
||||||
gateway_id: ed25519::PublicKey,
|
|
||||||
updated_key: &SharedSymmetricKey,
|
|
||||||
) -> Result<(), Self::StorageError> {
|
|
||||||
self.manager
|
|
||||||
.update_remote_gateway_key(
|
|
||||||
&gateway_id.to_base58_string(),
|
|
||||||
None,
|
|
||||||
Some(updated_key.as_bytes()),
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
// ideally all of those should be run under a storage tx to ensure storage consistency,
|
// ideally all of those should be run under a storage tx to ensure storage consistency,
|
||||||
// but at that point it's fine
|
// but at that point it's fine
|
||||||
async fn remove_gateway_details(&self, gateway_id: &str) -> Result<(), Self::StorageError> {
|
async fn remove_gateway_details(&self, gateway_id: &str) -> Result<(), Self::StorageError> {
|
||||||
|
|||||||
@@ -2,10 +2,8 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
use crate::types::{ActiveGateway, GatewayRegistration};
|
use crate::types::{ActiveGateway, GatewayRegistration};
|
||||||
use crate::{BadGateway, GatewayDetails, GatewaysDetailsStore};
|
use crate::{BadGateway, GatewaysDetailsStore};
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use nym_crypto::asymmetric::ed25519::PublicKey;
|
|
||||||
use nym_gateway_requests::{SharedGatewayKey, SharedSymmetricKey};
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
@@ -36,6 +34,10 @@ struct InMemStorageInner {
|
|||||||
impl GatewaysDetailsStore for InMemGatewaysDetails {
|
impl GatewaysDetailsStore for InMemGatewaysDetails {
|
||||||
type StorageError = InMemStorageError;
|
type StorageError = InMemStorageError;
|
||||||
|
|
||||||
|
async fn has_gateway_details(&self, gateway_id: &str) -> Result<bool, Self::StorageError> {
|
||||||
|
Ok(self.inner.read().await.gateways.contains_key(gateway_id))
|
||||||
|
}
|
||||||
|
|
||||||
async fn active_gateway(&self) -> Result<ActiveGateway, Self::StorageError> {
|
async fn active_gateway(&self) -> Result<ActiveGateway, Self::StorageError> {
|
||||||
let guard = self.inner.read().await;
|
let guard = self.inner.read().await;
|
||||||
|
|
||||||
@@ -66,10 +68,6 @@ impl GatewaysDetailsStore for InMemGatewaysDetails {
|
|||||||
Ok(self.inner.read().await.gateways.values().cloned().collect())
|
Ok(self.inner.read().await.gateways.values().cloned().collect())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn has_gateway_details(&self, gateway_id: &str) -> Result<bool, Self::StorageError> {
|
|
||||||
Ok(self.inner.read().await.gateways.contains_key(gateway_id))
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn load_gateway_details(
|
async fn load_gateway_details(
|
||||||
&self,
|
&self,
|
||||||
gateway_id: &str,
|
gateway_id: &str,
|
||||||
@@ -96,29 +94,6 @@ impl GatewaysDetailsStore for InMemGatewaysDetails {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn upgrade_stored_remote_gateway_key(
|
|
||||||
&self,
|
|
||||||
gateway_id: PublicKey,
|
|
||||||
updated_key: &SharedSymmetricKey,
|
|
||||||
) -> Result<(), Self::StorageError> {
|
|
||||||
let mut guard = self.inner.write().await;
|
|
||||||
|
|
||||||
#[allow(clippy::unwrap_used)]
|
|
||||||
if let Some(target) = guard.gateways.get_mut(&gateway_id.to_string()) {
|
|
||||||
let GatewayDetails::Remote(details) = &mut target.details else {
|
|
||||||
return Ok(());
|
|
||||||
};
|
|
||||||
assert_eq!(Arc::strong_count(&details.shared_key), 1);
|
|
||||||
|
|
||||||
// eh. that's nasty, but it's only ever used for ephemeral clients so should be fine for now...
|
|
||||||
details.shared_key = Arc::new(SharedGatewayKey::Current(
|
|
||||||
SharedSymmetricKey::try_from_bytes(updated_key.as_bytes()).unwrap(),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn remove_gateway_details(&self, gateway_id: &str) -> Result<(), Self::StorageError> {
|
async fn remove_gateway_details(&self, gateway_id: &str) -> Result<(), Self::StorageError> {
|
||||||
let mut guard = self.inner.write().await;
|
let mut guard = self.inner.write().await;
|
||||||
if let Some(active) = guard.active_gateway.as_ref() {
|
if let Some(active) = guard.active_gateway.as_ref() {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
use nym_crypto::asymmetric::identity::Ed25519RecoveryError;
|
use nym_crypto::asymmetric::identity::Ed25519RecoveryError;
|
||||||
use nym_gateway_requests::shared_key::SharedKeyConversionError;
|
use nym_gateway_requests::registration::handshake::shared_key::SharedKeyConversionError;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
@@ -36,9 +36,6 @@ pub enum BadGateway {
|
|||||||
source: SharedKeyConversionError,
|
source: SharedKeyConversionError,
|
||||||
},
|
},
|
||||||
|
|
||||||
#[error("could not find any valid shared keys for gateway {gateway_id}")]
|
|
||||||
MissingSharedKey { gateway_id: String },
|
|
||||||
|
|
||||||
#[error(
|
#[error(
|
||||||
"the listening address of gateway {gateway_id} ({raw_listener}) is malformed: {source}"
|
"the listening address of gateway {gateway_id} ({raw_listener}) is malformed: {source}"
|
||||||
)]
|
)]
|
||||||
|
|||||||
@@ -5,8 +5,6 @@
|
|||||||
#![warn(clippy::unwrap_used)]
|
#![warn(clippy::unwrap_used)]
|
||||||
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use nym_crypto::asymmetric::identity;
|
|
||||||
use nym_gateway_requests::SharedSymmetricKey;
|
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
|
||||||
pub mod backend;
|
pub mod backend;
|
||||||
@@ -20,6 +18,7 @@ pub use error::BadGateway;
|
|||||||
|
|
||||||
#[cfg(all(not(target_arch = "wasm32"), feature = "fs-gateways-storage"))]
|
#[cfg(all(not(target_arch = "wasm32"), feature = "fs-gateways-storage"))]
|
||||||
pub use backend::fs_backend::{error::StorageError, OnDiskGatewaysDetails};
|
pub use backend::fs_backend::{error::StorageError, OnDiskGatewaysDetails};
|
||||||
|
use nym_crypto::asymmetric::identity;
|
||||||
|
|
||||||
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
||||||
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
|
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
|
||||||
@@ -62,12 +61,6 @@ pub trait GatewaysDetailsStore {
|
|||||||
details: &GatewayRegistration,
|
details: &GatewayRegistration,
|
||||||
) -> Result<(), Self::StorageError>;
|
) -> Result<(), Self::StorageError>;
|
||||||
|
|
||||||
async fn upgrade_stored_remote_gateway_key(
|
|
||||||
&self,
|
|
||||||
gateway_id: identity::PublicKey,
|
|
||||||
updated_key: &SharedSymmetricKey,
|
|
||||||
) -> Result<(), Self::StorageError>;
|
|
||||||
|
|
||||||
/// Remove given gateway details from the underlying store.
|
/// Remove given gateway details from the underlying store.
|
||||||
async fn remove_gateway_details(&self, gateway_id: &str) -> Result<(), Self::StorageError>;
|
async fn remove_gateway_details(&self, gateway_id: &str) -> Result<(), Self::StorageError>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,10 +4,9 @@
|
|||||||
use crate::BadGateway;
|
use crate::BadGateway;
|
||||||
use cosmrs::AccountId;
|
use cosmrs::AccountId;
|
||||||
use nym_crypto::asymmetric::identity;
|
use nym_crypto::asymmetric::identity;
|
||||||
use nym_gateway_requests::shared_key::{LegacySharedKeys, SharedGatewayKey, SharedSymmetricKey};
|
use nym_gateway_requests::registration::handshake::SharedKeys;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter};
|
||||||
use std::ops::Deref;
|
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use time::OffsetDateTime;
|
use time::OffsetDateTime;
|
||||||
@@ -65,13 +64,13 @@ impl From<GatewayDetails> for GatewayRegistration {
|
|||||||
impl GatewayDetails {
|
impl GatewayDetails {
|
||||||
pub fn new_remote(
|
pub fn new_remote(
|
||||||
gateway_id: identity::PublicKey,
|
gateway_id: identity::PublicKey,
|
||||||
shared_key: Arc<SharedGatewayKey>,
|
derived_aes128_ctr_blake3_hmac_keys: Arc<SharedKeys>,
|
||||||
gateway_owner_address: Option<AccountId>,
|
gateway_owner_address: Option<AccountId>,
|
||||||
gateway_listener: Url,
|
gateway_listener: Url,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
GatewayDetails::Remote(RemoteGatewayDetails {
|
GatewayDetails::Remote(RemoteGatewayDetails {
|
||||||
gateway_id,
|
gateway_id,
|
||||||
shared_key,
|
derived_aes128_ctr_blake3_hmac_keys,
|
||||||
gateway_owner_address,
|
gateway_owner_address,
|
||||||
gateway_listener,
|
gateway_listener,
|
||||||
})
|
})
|
||||||
@@ -88,9 +87,9 @@ impl GatewayDetails {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn shared_key(&self) -> Option<&SharedGatewayKey> {
|
pub fn shared_key(&self) -> Option<&SharedKeys> {
|
||||||
match self {
|
match self {
|
||||||
GatewayDetails::Remote(details) => Some(&details.shared_key),
|
GatewayDetails::Remote(details) => Some(&details.derived_aes128_ctr_blake3_hmac_keys),
|
||||||
GatewayDetails::Custom(_) => None,
|
GatewayDetails::Custom(_) => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -168,8 +167,7 @@ pub struct RegisteredGateway {
|
|||||||
#[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))]
|
#[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))]
|
||||||
pub struct RawRemoteGatewayDetails {
|
pub struct RawRemoteGatewayDetails {
|
||||||
pub gateway_id_bs58: String,
|
pub gateway_id_bs58: String,
|
||||||
pub derived_aes128_ctr_blake3_hmac_keys_bs58: Option<String>,
|
pub derived_aes128_ctr_blake3_hmac_keys_bs58: String,
|
||||||
pub derived_aes256_gcm_siv_key: Option<Vec<u8>>,
|
|
||||||
pub gateway_owner_address: Option<String>,
|
pub gateway_owner_address: Option<String>,
|
||||||
pub gateway_listener: String,
|
pub gateway_listener: String,
|
||||||
}
|
}
|
||||||
@@ -186,35 +184,13 @@ impl TryFrom<RawRemoteGatewayDetails> for RemoteGatewayDetails {
|
|||||||
}
|
}
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let shared_key =
|
let derived_aes128_ctr_blake3_hmac_keys = Arc::new(
|
||||||
match (
|
SharedKeys::try_from_base58_string(&value.derived_aes128_ctr_blake3_hmac_keys_bs58)
|
||||||
&value.derived_aes256_gcm_siv_key,
|
.map_err(|source| BadGateway::MalformedSharedKeys {
|
||||||
&value.derived_aes128_ctr_blake3_hmac_keys_bs58,
|
gateway_id: value.gateway_id_bs58.clone(),
|
||||||
) {
|
source,
|
||||||
(None, None) => {
|
})?,
|
||||||
return Err(BadGateway::MissingSharedKey {
|
);
|
||||||
gateway_id: value.gateway_id_bs58.clone(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
(Some(aes256gcm_siv), _) => {
|
|
||||||
let current_key =
|
|
||||||
SharedSymmetricKey::try_from_bytes(aes256gcm_siv).map_err(|source| {
|
|
||||||
BadGateway::MalformedSharedKeys {
|
|
||||||
gateway_id: value.gateway_id_bs58.clone(),
|
|
||||||
source,
|
|
||||||
}
|
|
||||||
})?;
|
|
||||||
SharedGatewayKey::Current(current_key)
|
|
||||||
}
|
|
||||||
(None, Some(aes128ctr_hmac)) => {
|
|
||||||
let legacy_key = LegacySharedKeys::try_from_base58_string(aes128ctr_hmac)
|
|
||||||
.map_err(|source| BadGateway::MalformedSharedKeys {
|
|
||||||
gateway_id: value.gateway_id_bs58.clone(),
|
|
||||||
source,
|
|
||||||
})?;
|
|
||||||
SharedGatewayKey::Legacy(legacy_key)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let gateway_owner_address = value
|
let gateway_owner_address = value
|
||||||
.gateway_owner_address
|
.gateway_owner_address
|
||||||
@@ -240,7 +216,7 @@ impl TryFrom<RawRemoteGatewayDetails> for RemoteGatewayDetails {
|
|||||||
|
|
||||||
Ok(RemoteGatewayDetails {
|
Ok(RemoteGatewayDetails {
|
||||||
gateway_id,
|
gateway_id,
|
||||||
shared_key: Arc::new(shared_key),
|
derived_aes128_ctr_blake3_hmac_keys,
|
||||||
gateway_owner_address,
|
gateway_owner_address,
|
||||||
gateway_listener,
|
gateway_listener,
|
||||||
})
|
})
|
||||||
@@ -249,16 +225,11 @@ impl TryFrom<RawRemoteGatewayDetails> for RemoteGatewayDetails {
|
|||||||
|
|
||||||
impl<'a> From<&'a RemoteGatewayDetails> for RawRemoteGatewayDetails {
|
impl<'a> From<&'a RemoteGatewayDetails> for RawRemoteGatewayDetails {
|
||||||
fn from(value: &'a RemoteGatewayDetails) -> Self {
|
fn from(value: &'a RemoteGatewayDetails) -> Self {
|
||||||
let (derived_aes128_ctr_blake3_hmac_keys_bs58, derived_aes256_gcm_siv_key) =
|
|
||||||
match value.shared_key.deref() {
|
|
||||||
SharedGatewayKey::Current(key) => (None, Some(key.to_bytes())),
|
|
||||||
SharedGatewayKey::Legacy(key) => (Some(key.to_base58_string()), None),
|
|
||||||
};
|
|
||||||
|
|
||||||
RawRemoteGatewayDetails {
|
RawRemoteGatewayDetails {
|
||||||
gateway_id_bs58: value.gateway_id.to_base58_string(),
|
gateway_id_bs58: value.gateway_id.to_base58_string(),
|
||||||
derived_aes128_ctr_blake3_hmac_keys_bs58,
|
derived_aes128_ctr_blake3_hmac_keys_bs58: value
|
||||||
derived_aes256_gcm_siv_key,
|
.derived_aes128_ctr_blake3_hmac_keys
|
||||||
|
.to_base58_string(),
|
||||||
gateway_owner_address: value.gateway_owner_address.as_ref().map(|o| o.to_string()),
|
gateway_owner_address: value.gateway_owner_address.as_ref().map(|o| o.to_string()),
|
||||||
gateway_listener: value.gateway_listener.to_string(),
|
gateway_listener: value.gateway_listener.to_string(),
|
||||||
}
|
}
|
||||||
@@ -269,7 +240,9 @@ impl<'a> From<&'a RemoteGatewayDetails> for RawRemoteGatewayDetails {
|
|||||||
pub struct RemoteGatewayDetails {
|
pub struct RemoteGatewayDetails {
|
||||||
pub gateway_id: identity::PublicKey,
|
pub gateway_id: identity::PublicKey,
|
||||||
|
|
||||||
pub shared_key: Arc<SharedGatewayKey>,
|
// note: `SharedKeys` implement ZeroizeOnDrop, meaning when `RemoteGatewayDetails` is dropped,
|
||||||
|
// the keys will be zeroized
|
||||||
|
pub derived_aes128_ctr_blake3_hmac_keys: Arc<SharedKeys>,
|
||||||
|
|
||||||
pub gateway_owner_address: Option<AccountId>,
|
pub gateway_owner_address: Option<AccountId>,
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ use crate::{
|
|||||||
use log::info;
|
use log::info;
|
||||||
use nym_client_core_gateways_storage::GatewayDetails;
|
use nym_client_core_gateways_storage::GatewayDetails;
|
||||||
use nym_crypto::asymmetric::identity;
|
use nym_crypto::asymmetric::identity;
|
||||||
use nym_sphinx::addressing::Recipient;
|
|
||||||
use nym_topology::NymTopology;
|
use nym_topology::NymTopology;
|
||||||
use nym_validator_client::UserAgent;
|
use nym_validator_client::UserAgent;
|
||||||
use rand::rngs::OsRng;
|
use rand::rngs::OsRng;
|
||||||
@@ -89,10 +88,6 @@ pub struct CommonClientInitArgs {
|
|||||||
/// Disable loop cover traffic and the Poisson rate limiter (for debugging only)
|
/// Disable loop cover traffic and the Poisson rate limiter (for debugging only)
|
||||||
#[cfg_attr(feature = "cli", clap(long, hide = true))]
|
#[cfg_attr(feature = "cli", clap(long, hide = true))]
|
||||||
pub no_cover: bool,
|
pub no_cover: bool,
|
||||||
|
|
||||||
/// Sets the address to report statistics
|
|
||||||
#[cfg_attr(feature = "cli", clap(long, hide = true))]
|
|
||||||
pub stats_reporting_address: Option<Recipient>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct InitResultsWithConfig<T> {
|
pub struct InitResultsWithConfig<T> {
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
use nym_crypto::asymmetric::identity;
|
use nym_crypto::asymmetric::identity;
|
||||||
use nym_sphinx::addressing::Recipient;
|
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
#[cfg_attr(feature = "cli", derive(clap::Args))]
|
#[cfg_attr(feature = "cli", derive(clap::Args))]
|
||||||
@@ -57,8 +56,4 @@ pub struct CommonClientRunArgs {
|
|||||||
// has defined the conflict on that field itself
|
// has defined the conflict on that field itself
|
||||||
#[cfg_attr(feature = "cli", clap(long, hide = true))]
|
#[cfg_attr(feature = "cli", clap(long, hide = true))]
|
||||||
pub no_cover: bool,
|
pub no_cover: bool,
|
||||||
|
|
||||||
/// Sets the address to report statistics
|
|
||||||
#[cfg_attr(feature = "cli", clap(long, hide = true))]
|
|
||||||
pub stats_reporting_address: Option<Recipient>,
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
// Copyright 2022-2023 - Nym Technologies SA <contact@nymtech.net>
|
// Copyright 2022-2023 - Nym Technologies SA <contact@nymtech.net>
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
use super::packet_statistics_control::PacketStatisticsReporter;
|
||||||
use super::received_buffer::ReceivedBufferMessage;
|
use super::received_buffer::ReceivedBufferMessage;
|
||||||
use super::statistics_control::StatisticsControl;
|
|
||||||
use super::topology_control::geo_aware_provider::GeoAwareTopologyProvider;
|
use super::topology_control::geo_aware_provider::GeoAwareTopologyProvider;
|
||||||
use crate::client::base_client::storage::helpers::store_client_keys;
|
use crate::client::base_client::storage::helpers::store_client_keys;
|
||||||
use crate::client::base_client::storage::MixnetClientStorage;
|
use crate::client::base_client::storage::MixnetClientStorage;
|
||||||
@@ -12,6 +12,7 @@ use crate::client::key_manager::persistence::KeyStore;
|
|||||||
use crate::client::key_manager::ClientKeys;
|
use crate::client::key_manager::ClientKeys;
|
||||||
use crate::client::mix_traffic::transceiver::{GatewayReceiver, GatewayTransceiver, RemoteGateway};
|
use crate::client::mix_traffic::transceiver::{GatewayReceiver, GatewayTransceiver, RemoteGateway};
|
||||||
use crate::client::mix_traffic::{BatchMixMessageSender, MixTrafficController};
|
use crate::client::mix_traffic::{BatchMixMessageSender, MixTrafficController};
|
||||||
|
use crate::client::packet_statistics_control::PacketStatisticsControl;
|
||||||
use crate::client::real_messages_control;
|
use crate::client::real_messages_control;
|
||||||
use crate::client::real_messages_control::RealMessagesController;
|
use crate::client::real_messages_control::RealMessagesController;
|
||||||
use crate::client::received_buffer::{
|
use crate::client::received_buffer::{
|
||||||
@@ -48,8 +49,6 @@ use nym_sphinx::addressing::clients::Recipient;
|
|||||||
use nym_sphinx::addressing::nodes::NodeIdentity;
|
use nym_sphinx::addressing::nodes::NodeIdentity;
|
||||||
use nym_sphinx::params::PacketType;
|
use nym_sphinx::params::PacketType;
|
||||||
use nym_sphinx::receiver::{ReconstructedMessage, SphinxMessageReceiver};
|
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::connections::{ConnectionCommandReceiver, ConnectionCommandSender, LaneQueueLengths};
|
||||||
use nym_task::{TaskClient, TaskHandle};
|
use nym_task::{TaskClient, TaskHandle};
|
||||||
use nym_topology::provider_trait::TopologyProvider;
|
use nym_topology::provider_trait::TopologyProvider;
|
||||||
@@ -60,7 +59,6 @@ use std::fmt::Debug;
|
|||||||
use std::os::raw::c_int as RawFd;
|
use std::os::raw::c_int as RawFd;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use tokio::sync::mpsc::Sender;
|
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
#[cfg(all(
|
#[cfg(all(
|
||||||
@@ -275,7 +273,7 @@ where
|
|||||||
self_address: Recipient,
|
self_address: Recipient,
|
||||||
topology_accessor: TopologyAccessor,
|
topology_accessor: TopologyAccessor,
|
||||||
mix_tx: BatchMixMessageSender,
|
mix_tx: BatchMixMessageSender,
|
||||||
stats_tx: ClientStatsSender,
|
stats_tx: PacketStatisticsReporter,
|
||||||
shutdown: TaskClient,
|
shutdown: TaskClient,
|
||||||
) {
|
) {
|
||||||
info!("Starting loop cover traffic stream...");
|
info!("Starting loop cover traffic stream...");
|
||||||
@@ -308,7 +306,7 @@ where
|
|||||||
client_connection_rx: ConnectionCommandReceiver,
|
client_connection_rx: ConnectionCommandReceiver,
|
||||||
shutdown: TaskClient,
|
shutdown: TaskClient,
|
||||||
packet_type: PacketType,
|
packet_type: PacketType,
|
||||||
stats_tx: ClientStatsSender,
|
stats_tx: PacketStatisticsReporter,
|
||||||
) {
|
) {
|
||||||
info!("Starting real traffic stream...");
|
info!("Starting real traffic stream...");
|
||||||
|
|
||||||
@@ -337,7 +335,7 @@ where
|
|||||||
reply_key_storage: SentReplyKeys,
|
reply_key_storage: SentReplyKeys,
|
||||||
reply_controller_sender: ReplyControllerSender,
|
reply_controller_sender: ReplyControllerSender,
|
||||||
shutdown: TaskClient,
|
shutdown: TaskClient,
|
||||||
metrics_reporter: ClientStatsSender,
|
packet_statistics_control: PacketStatisticsReporter,
|
||||||
) {
|
) {
|
||||||
info!("Starting received messages buffer controller...");
|
info!("Starting received messages buffer controller...");
|
||||||
let controller: ReceivedMessagesBufferController<SphinxMessageReceiver> =
|
let controller: ReceivedMessagesBufferController<SphinxMessageReceiver> =
|
||||||
@@ -347,7 +345,7 @@ where
|
|||||||
mixnet_receiver,
|
mixnet_receiver,
|
||||||
reply_key_storage,
|
reply_key_storage,
|
||||||
reply_controller_sender,
|
reply_controller_sender,
|
||||||
metrics_reporter,
|
packet_statistics_control,
|
||||||
);
|
);
|
||||||
controller.start_with_shutdown(shutdown)
|
controller.start_with_shutdown(shutdown)
|
||||||
}
|
}
|
||||||
@@ -356,15 +354,12 @@ where
|
|||||||
config: &Config,
|
config: &Config,
|
||||||
initialisation_result: InitialisationResult,
|
initialisation_result: InitialisationResult,
|
||||||
bandwidth_controller: Option<BandwidthController<C, S::CredentialStore>>,
|
bandwidth_controller: Option<BandwidthController<C, S::CredentialStore>>,
|
||||||
details_store: &S::GatewaysDetailsStore,
|
|
||||||
packet_router: PacketRouter,
|
packet_router: PacketRouter,
|
||||||
stats_reporter: ClientStatsSender,
|
|
||||||
shutdown: TaskClient,
|
shutdown: TaskClient,
|
||||||
) -> Result<GatewayClient<C, S::CredentialStore>, ClientCoreError>
|
) -> Result<GatewayClient<C, S::CredentialStore>, ClientCoreError>
|
||||||
where
|
where
|
||||||
<S::KeyStore as KeyStore>::StorageError: Send + Sync + 'static,
|
<S::KeyStore as KeyStore>::StorageError: Send + Sync + 'static,
|
||||||
<S::CredentialStore as CredentialStorage>::StorageError: Send + Sync + 'static,
|
<S::CredentialStore as CredentialStorage>::StorageError: Send + Sync + 'static,
|
||||||
<S::GatewaysDetailsStore as GatewaysDetailsStore>::StorageError: Sync + Send,
|
|
||||||
{
|
{
|
||||||
let managed_keys = initialisation_result.client_keys;
|
let managed_keys = initialisation_result.client_keys;
|
||||||
let GatewayDetails::Remote(details) = initialisation_result.gateway_registration.details
|
let GatewayDetails::Remote(details) = initialisation_result.gateway_registration.details
|
||||||
@@ -374,12 +369,7 @@ where
|
|||||||
|
|
||||||
let mut gateway_client =
|
let mut gateway_client =
|
||||||
if let Some(existing_client) = initialisation_result.authenticated_ephemeral_client {
|
if let Some(existing_client) = initialisation_result.authenticated_ephemeral_client {
|
||||||
existing_client.upgrade(
|
existing_client.upgrade(packet_router, bandwidth_controller, shutdown)
|
||||||
packet_router,
|
|
||||||
bandwidth_controller,
|
|
||||||
stats_reporter,
|
|
||||||
shutdown,
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
let cfg = GatewayConfig::new(
|
let cfg = GatewayConfig::new(
|
||||||
details.gateway_id,
|
details.gateway_id,
|
||||||
@@ -397,77 +387,38 @@ where
|
|||||||
),
|
),
|
||||||
cfg,
|
cfg,
|
||||||
managed_keys.identity_keypair(),
|
managed_keys.identity_keypair(),
|
||||||
Some(details.shared_key),
|
Some(details.derived_aes128_ctr_blake3_hmac_keys),
|
||||||
packet_router,
|
packet_router,
|
||||||
bandwidth_controller,
|
bandwidth_controller,
|
||||||
stats_reporter,
|
|
||||||
shutdown,
|
shutdown,
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
let gateway_failure = |err| {
|
|
||||||
log::error!("Could not authenticate and start up the gateway connection - {err}");
|
|
||||||
ClientCoreError::GatewayClientError {
|
|
||||||
gateway_id: details.gateway_id.to_base58_string(),
|
|
||||||
source: err,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// the gateway client startup procedure is slightly more complicated now
|
|
||||||
// we need to:
|
|
||||||
// - perform handshake (reg or auth)
|
|
||||||
// - check for key upgrade
|
|
||||||
// - maybe perform another upgrade handshake
|
|
||||||
// - check for bandwidth
|
|
||||||
// - start background tasks
|
|
||||||
let auth_res = gateway_client
|
|
||||||
.perform_initial_authentication()
|
|
||||||
.await
|
|
||||||
.map_err(gateway_failure)?;
|
|
||||||
|
|
||||||
if auth_res.requires_key_upgrade {
|
|
||||||
// drop the shared_key arc because we don't need it and we can't hold it for the purposes of upgrade
|
|
||||||
drop(auth_res);
|
|
||||||
|
|
||||||
let updated_key = gateway_client
|
|
||||||
.upgrade_key_authenticated()
|
|
||||||
.await
|
|
||||||
.map_err(gateway_failure)?;
|
|
||||||
|
|
||||||
details_store
|
|
||||||
.upgrade_stored_remote_gateway_key(gateway_client.gateway_identity(), &updated_key)
|
|
||||||
.await.map_err(|err| {
|
|
||||||
error!("failed to store upgraded gateway key! this connection might be forever broken now: {err}");
|
|
||||||
ClientCoreError::GatewaysDetailsStoreError { source: Box::new(err) }
|
|
||||||
})?
|
|
||||||
}
|
|
||||||
|
|
||||||
gateway_client
|
gateway_client
|
||||||
.claim_initial_bandwidth()
|
.authenticate_and_start()
|
||||||
.await
|
.await
|
||||||
.map_err(gateway_failure)?;
|
.map_err(|err| {
|
||||||
gateway_client
|
log::error!("Could not authenticate and start up the gateway connection - {err}");
|
||||||
.start_listening_for_mixnet_messages()
|
ClientCoreError::GatewayClientError {
|
||||||
.map_err(gateway_failure)?;
|
gateway_id: details.gateway_id.to_base58_string(),
|
||||||
|
source: err,
|
||||||
|
}
|
||||||
|
})?;
|
||||||
|
|
||||||
Ok(gateway_client)
|
Ok(gateway_client)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::too_many_arguments)]
|
|
||||||
async fn setup_gateway_transceiver(
|
async fn setup_gateway_transceiver(
|
||||||
custom_gateway_transceiver: Option<Box<dyn GatewayTransceiver + Send>>,
|
custom_gateway_transceiver: Option<Box<dyn GatewayTransceiver + Send>>,
|
||||||
config: &Config,
|
config: &Config,
|
||||||
initialisation_result: InitialisationResult,
|
initialisation_result: InitialisationResult,
|
||||||
bandwidth_controller: Option<BandwidthController<C, S::CredentialStore>>,
|
bandwidth_controller: Option<BandwidthController<C, S::CredentialStore>>,
|
||||||
details_store: &S::GatewaysDetailsStore,
|
|
||||||
packet_router: PacketRouter,
|
packet_router: PacketRouter,
|
||||||
stats_reporter: ClientStatsSender,
|
|
||||||
mut shutdown: TaskClient,
|
mut shutdown: TaskClient,
|
||||||
) -> Result<Box<dyn GatewayTransceiver + Send>, ClientCoreError>
|
) -> Result<Box<dyn GatewayTransceiver + Send>, ClientCoreError>
|
||||||
where
|
where
|
||||||
<S::KeyStore as KeyStore>::StorageError: Send + Sync + 'static,
|
<S::KeyStore as KeyStore>::StorageError: Send + Sync + 'static,
|
||||||
<S::CredentialStore as CredentialStorage>::StorageError: Send + Sync + 'static,
|
<S::CredentialStore as CredentialStorage>::StorageError: Send + Sync + 'static,
|
||||||
<S::GatewaysDetailsStore as GatewaysDetailsStore>::StorageError: Sync + Send,
|
|
||||||
{
|
{
|
||||||
// if we have setup custom gateway sender and persisted details agree with it, return it
|
// if we have setup custom gateway sender and persisted details agree with it, return it
|
||||||
if let Some(mut custom_gateway_transceiver) = custom_gateway_transceiver {
|
if let Some(mut custom_gateway_transceiver) = custom_gateway_transceiver {
|
||||||
@@ -478,7 +429,7 @@ where
|
|||||||
{
|
{
|
||||||
Err(ClientCoreError::CustomGatewaySelectionExpected)
|
Err(ClientCoreError::CustomGatewaySelectionExpected)
|
||||||
} else {
|
} else {
|
||||||
// and make sure to invalidate the task client, so we wouldn't cause premature shutdown
|
// and make sure to invalidate the task client so we wouldn't cause premature shutdown
|
||||||
shutdown.disarm();
|
shutdown.disarm();
|
||||||
custom_gateway_transceiver.set_packet_router(packet_router)?;
|
custom_gateway_transceiver.set_packet_router(packet_router)?;
|
||||||
Ok(custom_gateway_transceiver)
|
Ok(custom_gateway_transceiver)
|
||||||
@@ -490,9 +441,7 @@ where
|
|||||||
config,
|
config,
|
||||||
initialisation_result,
|
initialisation_result,
|
||||||
bandwidth_controller,
|
bandwidth_controller,
|
||||||
details_store,
|
|
||||||
packet_router,
|
packet_router,
|
||||||
stats_reporter,
|
|
||||||
shutdown,
|
shutdown,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
@@ -598,23 +547,11 @@ where
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn start_statistics_control(
|
fn start_packet_statistics_control(shutdown: TaskClient) -> PacketStatisticsReporter {
|
||||||
config: &Config,
|
info!("Starting packet statistics control...");
|
||||||
user_agent: Option<UserAgent>,
|
let (packet_statistics_control, packet_stats_reporter) = PacketStatisticsControl::new();
|
||||||
client_stats_id: String,
|
packet_statistics_control.start_with_shutdown(shutdown);
|
||||||
input_sender: Sender<InputMessage>,
|
packet_stats_reporter
|
||||||
shutdown: TaskClient,
|
|
||||||
) -> ClientStatsSender {
|
|
||||||
info!("Starting statistics control...");
|
|
||||||
StatisticsControl::create_and_start_with_shutdown(
|
|
||||||
config.debug.stats_reporting,
|
|
||||||
user_agent
|
|
||||||
.map(|u| u.application)
|
|
||||||
.unwrap_or("unknown".to_string()),
|
|
||||||
client_stats_id,
|
|
||||||
input_sender.clone(),
|
|
||||||
shutdown.with_suffix("controller"),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn start_mix_traffic_controller(
|
fn start_mix_traffic_controller(
|
||||||
@@ -693,8 +630,7 @@ where
|
|||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let (reply_storage_backend, credential_store, details_store) =
|
let (reply_storage_backend, credential_store) = self.client_store.into_runtime_stores();
|
||||||
self.client_store.into_runtime_stores();
|
|
||||||
|
|
||||||
// channels for inter-component communication
|
// channels for inter-component communication
|
||||||
// TODO: make the channels be internally created by the relevant components
|
// TODO: make the channels be internally created by the relevant components
|
||||||
@@ -744,14 +680,6 @@ where
|
|||||||
self.user_agent.clone(),
|
self.user_agent.clone(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let stats_reporter = Self::start_statistics_control(
|
|
||||||
self.config,
|
|
||||||
self.user_agent.clone(),
|
|
||||||
generate_client_stats_id(*self_address.identity()),
|
|
||||||
input_sender.clone(),
|
|
||||||
shutdown.fork("statistics_control"),
|
|
||||||
);
|
|
||||||
|
|
||||||
// needs to be started as the first thing to block if required waiting for the gateway
|
// needs to be started as the first thing to block if required waiting for the gateway
|
||||||
Self::start_topology_refresher(
|
Self::start_topology_refresher(
|
||||||
topology_provider,
|
topology_provider,
|
||||||
@@ -763,6 +691,9 @@ where
|
|||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
let packet_stats_reporter =
|
||||||
|
Self::start_packet_statistics_control(shutdown.fork("packet_statistics_control"));
|
||||||
|
|
||||||
let gateway_packet_router = PacketRouter::new(
|
let gateway_packet_router = PacketRouter::new(
|
||||||
ack_sender,
|
ack_sender,
|
||||||
mixnet_messages_sender,
|
mixnet_messages_sender,
|
||||||
@@ -774,9 +705,7 @@ where
|
|||||||
self.config,
|
self.config,
|
||||||
init_res,
|
init_res,
|
||||||
bandwidth_controller,
|
bandwidth_controller,
|
||||||
&details_store,
|
|
||||||
gateway_packet_router,
|
gateway_packet_router,
|
||||||
stats_reporter.clone(),
|
|
||||||
shutdown.fork("gateway_transceiver"),
|
shutdown.fork("gateway_transceiver"),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
@@ -795,7 +724,7 @@ where
|
|||||||
reply_storage.key_storage(),
|
reply_storage.key_storage(),
|
||||||
reply_controller_sender.clone(),
|
reply_controller_sender.clone(),
|
||||||
shutdown.fork("received_messages_buffer"),
|
shutdown.fork("received_messages_buffer"),
|
||||||
stats_reporter.clone(),
|
packet_stats_reporter.clone(),
|
||||||
);
|
);
|
||||||
|
|
||||||
// The message_sender is the transmitter for any component generating sphinx packets
|
// The message_sender is the transmitter for any component generating sphinx packets
|
||||||
@@ -834,7 +763,7 @@ where
|
|||||||
client_connection_rx,
|
client_connection_rx,
|
||||||
shutdown.fork("real_traffic_controller"),
|
shutdown.fork("real_traffic_controller"),
|
||||||
self.config.debug.traffic.packet_type,
|
self.config.debug.traffic.packet_type,
|
||||||
stats_reporter.clone(),
|
packet_stats_reporter.clone(),
|
||||||
);
|
);
|
||||||
|
|
||||||
if !self
|
if !self
|
||||||
@@ -849,7 +778,7 @@ where
|
|||||||
self_address,
|
self_address,
|
||||||
shared_topology_accessor.clone(),
|
shared_topology_accessor.clone(),
|
||||||
message_sender,
|
message_sender,
|
||||||
stats_reporter.clone(),
|
packet_stats_reporter,
|
||||||
shutdown.fork("cover_traffic_stream"),
|
shutdown.fork("cover_traffic_stream"),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -877,7 +806,6 @@ where
|
|||||||
topology_accessor: shared_topology_accessor,
|
topology_accessor: shared_topology_accessor,
|
||||||
gateway_connection: GatewayConnection { gateway_ws_fd },
|
gateway_connection: GatewayConnection { gateway_ws_fd },
|
||||||
},
|
},
|
||||||
stats_reporter,
|
|
||||||
task_handle: shutdown,
|
task_handle: shutdown,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -889,7 +817,6 @@ pub struct BaseClient {
|
|||||||
pub client_input: ClientInputStatus,
|
pub client_input: ClientInputStatus,
|
||||||
pub client_output: ClientOutputStatus,
|
pub client_output: ClientOutputStatus,
|
||||||
pub client_state: ClientState,
|
pub client_state: ClientState,
|
||||||
pub stats_reporter: ClientStatsSender,
|
|
||||||
|
|
||||||
pub task_handle: TaskHandle,
|
pub task_handle: TaskHandle,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ pub mod v1_1_33 {
|
|||||||
use nym_client_core_gateways_storage::{
|
use nym_client_core_gateways_storage::{
|
||||||
CustomGatewayDetails, GatewayDetails, GatewayRegistration, RemoteGatewayDetails,
|
CustomGatewayDetails, GatewayDetails, GatewayRegistration, RemoteGatewayDetails,
|
||||||
};
|
};
|
||||||
use nym_gateway_requests::shared_key::LegacySharedKeys;
|
use nym_gateway_requests::registration::handshake::SharedKeys;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use sha2::{digest::Digest, Sha256};
|
use sha2::{digest::Digest, Sha256};
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
@@ -58,7 +58,7 @@ pub mod v1_1_33 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl PersistedGatewayConfig {
|
impl PersistedGatewayConfig {
|
||||||
fn verify(&self, shared_key: &LegacySharedKeys) -> bool {
|
fn verify(&self, shared_key: &SharedKeys) -> bool {
|
||||||
let key_bytes = Zeroizing::new(shared_key.to_bytes());
|
let key_bytes = Zeroizing::new(shared_key.to_bytes());
|
||||||
|
|
||||||
let mut key_hasher = Sha256::new();
|
let mut key_hasher = Sha256::new();
|
||||||
@@ -74,7 +74,7 @@ pub mod v1_1_33 {
|
|||||||
gateway_id: String,
|
gateway_id: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_shared_key<P: AsRef<Path>>(path: P) -> Result<LegacySharedKeys, ClientCoreError> {
|
fn load_shared_key<P: AsRef<Path>>(path: P) -> Result<SharedKeys, ClientCoreError> {
|
||||||
// the shared key was a simple pem file
|
// the shared key was a simple pem file
|
||||||
Ok(nym_pemstore::load_key(path)?)
|
Ok(nym_pemstore::load_key(path)?)
|
||||||
}
|
}
|
||||||
@@ -83,7 +83,7 @@ pub mod v1_1_33 {
|
|||||||
gateway_id: String,
|
gateway_id: String,
|
||||||
gateway_owner: String,
|
gateway_owner: String,
|
||||||
gateway_listener: String,
|
gateway_listener: String,
|
||||||
gateway_shared_key: LegacySharedKeys,
|
gateway_shared_key: SharedKeys,
|
||||||
) -> Result<GatewayDetails, ClientCoreError> {
|
) -> Result<GatewayDetails, ClientCoreError> {
|
||||||
Ok(GatewayDetails::Remote(RemoteGatewayDetails {
|
Ok(GatewayDetails::Remote(RemoteGatewayDetails {
|
||||||
gateway_id: gateway_id
|
gateway_id: gateway_id
|
||||||
@@ -91,7 +91,7 @@ pub mod v1_1_33 {
|
|||||||
.map_err(|err| ClientCoreError::UpgradeFailure {
|
.map_err(|err| ClientCoreError::UpgradeFailure {
|
||||||
message: format!("the stored gateway id was malformed: {err}"),
|
message: format!("the stored gateway id was malformed: {err}"),
|
||||||
})?,
|
})?,
|
||||||
shared_key: Arc::new(gateway_shared_key.into()),
|
derived_aes128_ctr_blake3_hmac_keys: Arc::new(gateway_shared_key),
|
||||||
gateway_owner_address: Some(gateway_owner.parse().map_err(|err| {
|
gateway_owner_address: Some(gateway_owner.parse().map_err(|err| {
|
||||||
ClientCoreError::UpgradeFailure {
|
ClientCoreError::UpgradeFailure {
|
||||||
message: format!("the stored gateway owner address was malformed: {err}"),
|
message: format!("the stored gateway owner address was malformed: {err}"),
|
||||||
|
|||||||
@@ -49,13 +49,7 @@ pub trait MixnetClientStorage {
|
|||||||
type CredentialStore: CredentialStorage;
|
type CredentialStore: CredentialStorage;
|
||||||
type GatewaysDetailsStore: GatewaysDetailsStore;
|
type GatewaysDetailsStore: GatewaysDetailsStore;
|
||||||
|
|
||||||
fn into_runtime_stores(
|
fn into_runtime_stores(self) -> (Self::ReplyStore, Self::CredentialStore);
|
||||||
self,
|
|
||||||
) -> (
|
|
||||||
Self::ReplyStore,
|
|
||||||
Self::CredentialStore,
|
|
||||||
Self::GatewaysDetailsStore,
|
|
||||||
);
|
|
||||||
|
|
||||||
fn key_store(&self) -> &Self::KeyStore;
|
fn key_store(&self) -> &Self::KeyStore;
|
||||||
fn reply_store(&self) -> &Self::ReplyStore;
|
fn reply_store(&self) -> &Self::ReplyStore;
|
||||||
@@ -83,18 +77,8 @@ impl MixnetClientStorage for Ephemeral {
|
|||||||
type CredentialStore = EphemeralCredentialStorage;
|
type CredentialStore = EphemeralCredentialStorage;
|
||||||
type GatewaysDetailsStore = InMemGatewaysDetails;
|
type GatewaysDetailsStore = InMemGatewaysDetails;
|
||||||
|
|
||||||
fn into_runtime_stores(
|
fn into_runtime_stores(self) -> (Self::ReplyStore, Self::CredentialStore) {
|
||||||
self,
|
(self.reply_store, self.credential_store)
|
||||||
) -> (
|
|
||||||
Self::ReplyStore,
|
|
||||||
Self::CredentialStore,
|
|
||||||
Self::GatewaysDetailsStore,
|
|
||||||
) {
|
|
||||||
(
|
|
||||||
self.reply_store,
|
|
||||||
self.credential_store,
|
|
||||||
self.gateway_details_store,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn key_store(&self) -> &Self::KeyStore {
|
fn key_store(&self) -> &Self::KeyStore {
|
||||||
@@ -184,18 +168,8 @@ impl MixnetClientStorage for OnDiskPersistent {
|
|||||||
type CredentialStore = PersistentCredentialStorage;
|
type CredentialStore = PersistentCredentialStorage;
|
||||||
type GatewaysDetailsStore = OnDiskGatewaysDetails;
|
type GatewaysDetailsStore = OnDiskGatewaysDetails;
|
||||||
|
|
||||||
fn into_runtime_stores(
|
fn into_runtime_stores(self) -> (Self::ReplyStore, Self::CredentialStore) {
|
||||||
self,
|
(self.reply_store, self.credential_store)
|
||||||
) -> (
|
|
||||||
Self::ReplyStore,
|
|
||||||
Self::CredentialStore,
|
|
||||||
Self::GatewaysDetailsStore,
|
|
||||||
) {
|
|
||||||
(
|
|
||||||
self.reply_store,
|
|
||||||
self.credential_store,
|
|
||||||
self.gateway_details_store,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn key_store(&self) -> &Self::KeyStore {
|
fn key_store(&self) -> &Self::KeyStore {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
use crate::client::mix_traffic::BatchMixMessageSender;
|
use crate::client::mix_traffic::BatchMixMessageSender;
|
||||||
|
use crate::client::packet_statistics_control::{PacketStatisticsEvent, PacketStatisticsReporter};
|
||||||
use crate::client::topology_control::TopologyAccessor;
|
use crate::client::topology_control::TopologyAccessor;
|
||||||
use crate::{config, spawn_future};
|
use crate::{config, spawn_future};
|
||||||
use futures::task::{Context, Poll};
|
use futures::task::{Context, Poll};
|
||||||
@@ -12,7 +13,6 @@ use nym_sphinx::addressing::clients::Recipient;
|
|||||||
use nym_sphinx::cover::generate_loop_cover_packet;
|
use nym_sphinx::cover::generate_loop_cover_packet;
|
||||||
use nym_sphinx::params::{PacketSize, PacketType};
|
use nym_sphinx::params::{PacketSize, PacketType};
|
||||||
use nym_sphinx::utils::sample_poisson_duration;
|
use nym_sphinx::utils::sample_poisson_duration;
|
||||||
use nym_statistics_common::clients::{packet_statistics::PacketStatisticsEvent, ClientStatsSender};
|
|
||||||
use rand::{rngs::OsRng, CryptoRng, Rng};
|
use rand::{rngs::OsRng, CryptoRng, Rng};
|
||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
@@ -63,7 +63,7 @@ where
|
|||||||
|
|
||||||
packet_type: PacketType,
|
packet_type: PacketType,
|
||||||
|
|
||||||
stats_tx: ClientStatsSender,
|
stats_tx: PacketStatisticsReporter,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<R> Stream for LoopCoverTrafficStream<R>
|
impl<R> Stream for LoopCoverTrafficStream<R>
|
||||||
@@ -109,7 +109,7 @@ impl LoopCoverTrafficStream<OsRng> {
|
|||||||
topology_access: TopologyAccessor,
|
topology_access: TopologyAccessor,
|
||||||
traffic_config: config::Traffic,
|
traffic_config: config::Traffic,
|
||||||
cover_config: config::CoverTraffic,
|
cover_config: config::CoverTraffic,
|
||||||
stats_tx: ClientStatsSender,
|
stats_tx: PacketStatisticsReporter,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let rng = OsRng;
|
let rng = OsRng;
|
||||||
|
|
||||||
@@ -198,9 +198,9 @@ impl LoopCoverTrafficStream<OsRng> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.stats_tx.report(
|
self.stats_tx.report(PacketStatisticsEvent::CoverPacketSent(
|
||||||
PacketStatisticsEvent::CoverPacketSent(cover_traffic_packet_size.size()).into(),
|
cover_traffic_packet_size.size(),
|
||||||
);
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: I'm not entirely sure whether this is really required, because I'm not 100%
|
// TODO: I'm not entirely sure whether this is really required, because I'm not 100%
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user