Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 59ebfbf50f | |||
| bb1b2a75dd | |||
| da3cbe095b |
+11
-1
@@ -14,6 +14,7 @@
|
|||||||
# contracts
|
# contracts
|
||||||
/contracts/mixnet @durch @jstuczyn
|
/contracts/mixnet @durch @jstuczyn
|
||||||
/contracts/vesting @durch @jstuczyn
|
/contracts/vesting @durch @jstuczyn
|
||||||
|
/contracts/service-provider-directory @octol
|
||||||
|
|
||||||
# crypto code
|
# crypto code
|
||||||
/common/crypto/ @jstuczyn
|
/common/crypto/ @jstuczyn
|
||||||
@@ -21,5 +22,14 @@
|
|||||||
/common/dkg/ @jstuczyn
|
/common/dkg/ @jstuczyn
|
||||||
/common/nymsphinx/ @jstuczyn
|
/common/nymsphinx/ @jstuczyn
|
||||||
|
|
||||||
|
# rust sdk
|
||||||
|
/sdk/rust/ @octol
|
||||||
|
|
||||||
|
# nym-connect (rust)
|
||||||
|
/nym-connect/desktop/src-tauri/ @octol
|
||||||
|
|
||||||
|
# nym-wallet (rust)
|
||||||
|
/nym-wallet/src-tauri/ @octol
|
||||||
|
|
||||||
# documentation
|
# documentation
|
||||||
/documentation @mfahampshire
|
/documentation @mfahampshire
|
||||||
@@ -31,3 +31,5 @@ updates:
|
|||||||
update-types:
|
update-types:
|
||||||
- "patch"
|
- "patch"
|
||||||
open-pull-requests-limit: 10
|
open-pull-requests-limit: 10
|
||||||
|
assignees:
|
||||||
|
- "octol"
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ jobs:
|
|||||||
run: sudo apt-get install -y rsync
|
run: sudo apt-get install -y rsync
|
||||||
- uses: rlespinasse/github-slug-action@v3.x
|
- uses: rlespinasse/github-slug-action@v3.x
|
||||||
- name: Setup pnpm
|
- name: Setup pnpm
|
||||||
uses: pnpm/action-setup@v4.1.0
|
uses: pnpm/action-setup@v4.0.0
|
||||||
with:
|
with:
|
||||||
version: 9
|
version: 9
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
|
|||||||
@@ -102,8 +102,6 @@ jobs:
|
|||||||
- name: Run all tests
|
- name: Run all tests
|
||||||
if: contains(matrix.os, 'ubuntu')
|
if: contains(matrix.os, 'ubuntu')
|
||||||
uses: actions-rs/cargo@v1
|
uses: actions-rs/cargo@v1
|
||||||
env:
|
|
||||||
NYM_API: https://sandbox-nym-api1.nymtech.net/api
|
|
||||||
with:
|
with:
|
||||||
command: test
|
command: test
|
||||||
args: --workspace
|
args: --workspace
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ jobs:
|
|||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Get version from cargo.toml
|
- name: Get version from cargo.toml
|
||||||
uses: mikefarah/yq@v4.45.4
|
uses: mikefarah/yq@v4.45.1
|
||||||
id: get_version
|
id: get_version
|
||||||
with:
|
with:
|
||||||
cmd: yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/Cargo.toml
|
cmd: yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/Cargo.toml
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ jobs:
|
|||||||
run: sudo apt-get install -y rsync
|
run: sudo apt-get install -y rsync
|
||||||
- uses: rlespinasse/github-slug-action@v3.x
|
- uses: rlespinasse/github-slug-action@v3.x
|
||||||
- name: Setup pnpm
|
- name: Setup pnpm
|
||||||
uses: pnpm/action-setup@v4.1.0
|
uses: pnpm/action-setup@v4.0.0
|
||||||
with:
|
with:
|
||||||
version: 9
|
version: 9
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
|
|||||||
@@ -16,12 +16,8 @@ jobs:
|
|||||||
CARGO_TERM_COLOR: always
|
CARGO_TERM_COLOR: always
|
||||||
RUSTUP_PERMIT_COPY_RENAME: 1
|
RUSTUP_PERMIT_COPY_RENAME: 1
|
||||||
steps:
|
steps:
|
||||||
- name: Install system dependencies
|
- name: Install Dependencies (Linux)
|
||||||
run: |
|
run: sudo apt-get update && sudo apt-get -y install libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev squashfs-tools
|
||||||
sudo apt-get update && sudo apt-get install -y libdbus-1-dev libmnl-dev libnftnl-dev \
|
|
||||||
libwebkit2gtk-4.1-dev build-essential curl wget libssl-dev jq \
|
|
||||||
libgtk-3-dev squashfs-tools libayatana-appindicator3-dev make libfuse2 unzip librsvg2-dev file \
|
|
||||||
libsoup-3.0-dev libjavascriptcoregtk-4.1-dev
|
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
|
|
||||||
- name: Check out repository code
|
- name: Check out repository code
|
||||||
|
|||||||
@@ -1,47 +0,0 @@
|
|||||||
name: Integration Tests
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
paths:
|
|
||||||
- "nym-api/**"
|
|
||||||
- "tests/**"
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
integration-tests:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
env:
|
|
||||||
API_BASE_URL: http://localhost:8000
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout code
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Install Rust
|
|
||||||
uses: actions-rs/toolchain@v1
|
|
||||||
with:
|
|
||||||
toolchain: stable
|
|
||||||
override: true
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: sudo apt-get update && sudo apt-get install -y pkg-config libssl-dev
|
|
||||||
|
|
||||||
- name: Build nym-api
|
|
||||||
run: cargo build --package nym-api
|
|
||||||
|
|
||||||
- name: Run nym-api in the background
|
|
||||||
run: |
|
|
||||||
./target/debug/nym-api &
|
|
||||||
|
|
||||||
- name: Wait for nym-api to come alive
|
|
||||||
run: |
|
|
||||||
for i in {1..20}; do
|
|
||||||
curl -sSf http://localhost:8000/v1/status/config-score-details && break
|
|
||||||
echo "Waiting for nym-api to start..."
|
|
||||||
sleep 2
|
|
||||||
done
|
|
||||||
|
|
||||||
- name: Run integration tests
|
|
||||||
env:
|
|
||||||
NYM_API: https://sandbox-nym-api1.nymtech.net/api
|
|
||||||
run: cargo test --test public-api-tests -- --nocapture
|
|
||||||
@@ -19,7 +19,9 @@ jobs:
|
|||||||
if: ${{ (startsWith(github.ref, 'refs/tags/nym-binaries-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }}
|
if: ${{ (startsWith(github.ref, 'refs/tags/nym-binaries-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }}
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
runs-on: arc-ubuntu-22.04
|
matrix:
|
||||||
|
platform: [custom-ubuntu-22.04]
|
||||||
|
runs-on: ${{ matrix.platform }}
|
||||||
|
|
||||||
outputs:
|
outputs:
|
||||||
release_id: ${{ steps.create-release.outputs.id }}
|
release_id: ${{ steps.create-release.outputs.id }}
|
||||||
|
|||||||
@@ -18,7 +18,11 @@ jobs:
|
|||||||
runs-on: ${{ matrix.platform }}
|
runs-on: ${{ matrix.platform }}
|
||||||
|
|
||||||
outputs:
|
outputs:
|
||||||
release_tag: ${{ github.ref_name }}
|
release_id: ${{ steps.create-release.outputs.id }}
|
||||||
|
release_date: ${{ fromJSON(steps.create-release.outputs.assets)[0].created_at }}
|
||||||
|
version: ${{ steps.release-info.outputs.version }}
|
||||||
|
filename: ${{ steps.release-info.outputs.filename }}
|
||||||
|
file_hash: ${{ steps.release-info.outputs.file_hash }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
@@ -29,16 +33,10 @@ jobs:
|
|||||||
node-version: 21
|
node-version: 21
|
||||||
|
|
||||||
- name: Install Rust stable
|
- name: Install Rust stable
|
||||||
uses: dtolnay/rust-toolchain@stable
|
uses: actions-rs/toolchain@v1
|
||||||
with:
|
with:
|
||||||
toolchain: stable
|
toolchain: stable
|
||||||
|
|
||||||
- name: Add Rust target for x86_64-apple-darwin
|
|
||||||
run: rustup target add x86_64-apple-darwin
|
|
||||||
|
|
||||||
- name: Set Cargo build target to x86_64
|
|
||||||
run: echo "CARGO_BUILD_TARGET=x86_64-apple-darwin" >> $GITHUB_ENV
|
|
||||||
|
|
||||||
- name: Install the Apple developer certificate for code signing
|
- name: Install the Apple developer certificate for code signing
|
||||||
env:
|
env:
|
||||||
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
|
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
|
||||||
@@ -68,6 +66,12 @@ jobs:
|
|||||||
fileName: '.env'
|
fileName: '.env'
|
||||||
encodedString: ${{ secrets.WALLET_ADMIN_ADDRESS }}
|
encodedString: ${{ secrets.WALLET_ADMIN_ADDRESS }}
|
||||||
|
|
||||||
|
- name: Add Rust target for x86_64-apple-darwin
|
||||||
|
run: rustup target add x86_64-apple-darwin
|
||||||
|
|
||||||
|
- name: Set Cargo build target to x86_64
|
||||||
|
run: echo "CARGO_BUILD_TARGET=x86_64-apple-darwin" >> $GITHUB_ENV
|
||||||
|
|
||||||
- name: Yarn cache clean
|
- name: Yarn cache clean
|
||||||
shell: bash
|
shell: bash
|
||||||
run: cd .. && yarn cache clean
|
run: cd .. && yarn cache clean
|
||||||
@@ -90,22 +94,10 @@ jobs:
|
|||||||
APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_IDENTITY_ID }}
|
APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_IDENTITY_ID }}
|
||||||
APPLE_ID: ${{ secrets.APPLE_ID }}
|
APPLE_ID: ${{ secrets.APPLE_ID }}
|
||||||
APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
|
APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
|
||||||
# Tauri v2 specific environment variables
|
TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
|
||||||
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
|
TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
|
||||||
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
|
|
||||||
TAURI_NOTARIZATION_USERNAME: ${{ secrets.APPLE_ID }}
|
|
||||||
TAURI_NOTARIZATION_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
|
|
||||||
TAURI_NOTARIZATION_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
|
||||||
run: |
|
run: |
|
||||||
yarn build-macx86
|
yarn build-macx86
|
||||||
|
|
||||||
- name: Create app tarball
|
|
||||||
run: |
|
|
||||||
# Navigate to where the app bundle is and create the tarball
|
|
||||||
cd target/x86_64-apple-darwin/release/bundle/macos
|
|
||||||
echo "Creating tarball from app bundle"
|
|
||||||
tar -czf nym-wallet.app.tar.gz NymWallet.app
|
|
||||||
cd -
|
|
||||||
|
|
||||||
- name: Upload Artifact
|
- name: Upload Artifact
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
@@ -128,10 +120,22 @@ jobs:
|
|||||||
nym-wallet/target/x86_64-apple-darwin/release/bundle/dmg/*.dmg
|
nym-wallet/target/x86_64-apple-darwin/release/bundle/dmg/*.dmg
|
||||||
nym-wallet/target/x86_64-apple-darwin/release/bundle/macos/*.app.tar.gz*
|
nym-wallet/target/x86_64-apple-darwin/release/bundle/macos/*.app.tar.gz*
|
||||||
|
|
||||||
|
- name: Deploy artifacts to CI www
|
||||||
|
continue-on-error: true
|
||||||
|
uses: easingthemes/ssh-deploy@main
|
||||||
|
env:
|
||||||
|
SSH_PRIVATE_KEY: ${{ secrets.CI_WWW_SSH_PRIVATE_KEY }}
|
||||||
|
ARGS: "-avzr"
|
||||||
|
SOURCE: "nym-wallet/target/x86_64-apple-darwin/release/bundle/macos/nym-wallet.app.tar.gz"
|
||||||
|
REMOTE_HOST: ${{ secrets.CI_WWW_REMOTE_HOST }}
|
||||||
|
REMOTE_USER: ${{ secrets.CI_WWW_REMOTE_USER }}
|
||||||
|
TARGET: ${{ secrets.CI_WWW_REMOTE_TARGET }}/builds/${{ github.ref_name }}/nym-wallet
|
||||||
|
EXCLUDE: "/dist/, /node_modules/"
|
||||||
|
|
||||||
push-release-data:
|
push-release-data:
|
||||||
if: ${{ (startsWith(github.ref, 'refs/tags/nym-wallet-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }}
|
if: ${{ (startsWith(github.ref, 'refs/tags/nym-wallet-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }}
|
||||||
uses: ./.github/workflows/release-calculate-hash.yml
|
uses: ./.github/workflows/release-calculate-hash.yml
|
||||||
needs: publish-tauri
|
needs: publish-tauri
|
||||||
with:
|
with:
|
||||||
release_tag: ${{ needs.publish-tauri.outputs.release_tag || github.ref_name }}
|
release_tag: ${{ github.ref_name }}
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
|
|||||||
@@ -3,108 +3,71 @@ on:
|
|||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
release:
|
release:
|
||||||
types: [created]
|
types: [created]
|
||||||
|
|
||||||
defaults:
|
defaults:
|
||||||
run:
|
run:
|
||||||
working-directory: nym-wallet
|
working-directory: nym-wallet
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
publish-tauri:
|
publish-tauri:
|
||||||
if: ${{ (startsWith(github.ref, 'refs/tags/nym-wallet-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }}
|
if: ${{ (startsWith(github.ref, 'refs/tags/nym-wallet-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }}
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
platform: [ubuntu-22.04]
|
platform: [custom-ubuntu-22.04]
|
||||||
runs-on: ${{ matrix.platform }}
|
runs-on: ${{ matrix.platform }}
|
||||||
|
|
||||||
outputs:
|
outputs:
|
||||||
release_tag: ${{ github.ref_name }}
|
release_id: ${{ steps.create-release.outputs.id }}
|
||||||
|
release_date: ${{ fromJSON(steps.create-release.outputs.assets)[0].created_at }}
|
||||||
|
version: ${{ steps.release-info.outputs.version }}
|
||||||
|
filename: ${{ steps.release-info.outputs.filename }}
|
||||||
|
file_hash: ${{ steps.release-info.outputs.file_hash }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Install system dependencies
|
- name: Tauri dependencies
|
||||||
run: |
|
run: >
|
||||||
sudo apt-get update && sudo apt-get install -y libdbus-1-dev libmnl-dev libnftnl-dev \
|
sudo apt-get update &&
|
||||||
libwebkit2gtk-4.1-dev build-essential curl wget libssl-dev jq \
|
sudo apt-get install -y webkit2gtk-4.0
|
||||||
libgtk-3-dev squashfs-tools libayatana-appindicator3-dev make libfuse2 unzip librsvg2-dev file \
|
continue-on-error: true
|
||||||
libsoup-3.0-dev libjavascriptcoregtk-4.1-dev
|
|
||||||
|
|
||||||
- name: Node
|
- name: Node
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 21
|
node-version: 21
|
||||||
cache: 'yarn'
|
|
||||||
|
|
||||||
- name: Install Rust stable
|
- name: Install Rust stable
|
||||||
uses: dtolnay/rust-toolchain@stable
|
uses: actions-rs/toolchain@v1
|
||||||
with:
|
with:
|
||||||
toolchain: stable
|
toolchain: stable
|
||||||
|
|
||||||
- name: Install project dependencies
|
- name: Install project dependencies
|
||||||
shell: bash
|
shell: bash
|
||||||
run: cd .. && yarn --network-timeout 100000
|
run: cd .. && yarn --network-timeout 100000
|
||||||
|
|
||||||
- name: Install app dependencies
|
- name: Install app dependencies
|
||||||
run: yarn
|
run: yarn
|
||||||
|
|
||||||
- name: Create env file
|
- name: Create env file
|
||||||
uses: timheuer/base64-to-file@v1.2
|
uses: timheuer/base64-to-file@v1.2
|
||||||
with:
|
with:
|
||||||
fileName: '.env'
|
fileName: '.env'
|
||||||
encodedString: ${{ secrets.WALLET_ADMIN_ADDRESS }}
|
encodedString: ${{ secrets.WALLET_ADMIN_ADDRESS }}
|
||||||
|
|
||||||
- name: Build app
|
- name: Build app
|
||||||
run: yarn build
|
run: yarn build
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
|
TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
|
||||||
TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
|
TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
|
||||||
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
|
|
||||||
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
|
|
||||||
|
|
||||||
- name: Check bundle directory
|
|
||||||
run: |
|
|
||||||
echo "Checking bundle directory structure"
|
|
||||||
ls -la target/release/bundle || echo "Bundle directory not found"
|
|
||||||
if [ -d "target/release/bundle/appimage" ]; then
|
|
||||||
echo "AppImage bundle directory exists, checking contents:"
|
|
||||||
ls -la target/release/bundle/appimage
|
|
||||||
else
|
|
||||||
echo "AppImage bundle directory not found, checking alternatives:"
|
|
||||||
find target/release/bundle -type d -name "*appimage*" -o -name "*AppImage*" || echo "No AppImage directories found"
|
|
||||||
find target/release/bundle -name "*.AppImage" -o -name "*.appimage" || echo "No AppImage files found"
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Create AppImage tarball if needed
|
|
||||||
run: |
|
|
||||||
# Find the AppImage file
|
|
||||||
APPIMAGE_FILE=$(find target/release/bundle -name "*.AppImage" | head -n 1)
|
|
||||||
if [ -n "$APPIMAGE_FILE" ]; then
|
|
||||||
echo "Found AppImage file: $APPIMAGE_FILE"
|
|
||||||
APPIMAGE_DIR=$(dirname "$APPIMAGE_FILE")
|
|
||||||
APPIMAGE_NAME=$(basename "$APPIMAGE_FILE")
|
|
||||||
|
|
||||||
# Create tarball if it doesn't exist
|
|
||||||
if [ ! -f "${APPIMAGE_FILE}.tar.gz" ]; then
|
|
||||||
echo "Creating tarball for $APPIMAGE_NAME"
|
|
||||||
cd "$APPIMAGE_DIR"
|
|
||||||
tar -czf "${APPIMAGE_NAME}.tar.gz" "$APPIMAGE_NAME"
|
|
||||||
cd -
|
|
||||||
echo "Created tarball: ${APPIMAGE_FILE}.tar.gz"
|
|
||||||
else
|
|
||||||
echo "Tarball already exists: ${APPIMAGE_FILE}.tar.gz"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
echo "WARNING: No AppImage file found!"
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Upload Artifact
|
- name: Upload Artifact
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: nym-wallet-appimage.tar.gz
|
name: nym-wallet_1.0.0_amd64.AppImage.tar.gz
|
||||||
path: |
|
path: nym-wallet/target/release/bundle/appimage/nym-wallet*.AppImage.tar.gz
|
||||||
nym-wallet/target/release/bundle/appimage/*.AppImage.tar.gz
|
|
||||||
nym-wallet/target/release/bundle/*/nym-wallet*.AppImage.tar.gz
|
|
||||||
retention-days: 30
|
retention-days: 30
|
||||||
|
|
||||||
- id: create-release
|
- id: create-release
|
||||||
name: Upload to release based on tag name
|
name: Upload to release based on tag name
|
||||||
uses: softprops/action-gh-release@v2
|
uses: softprops/action-gh-release@v2
|
||||||
@@ -112,26 +75,24 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
files: |
|
files: |
|
||||||
nym-wallet/target/release/bundle/appimage/*.AppImage
|
nym-wallet/target/release/bundle/appimage/*.AppImage
|
||||||
nym-wallet/target/release/bundle/appimage/*.AppImage.tar.gz
|
nym-wallet/target/release/bundle/appimage/*.AppImage.tar.gz*
|
||||||
nym-wallet/target/release/bundle/*/nym-wallet*.AppImage
|
|
||||||
nym-wallet/target/release/bundle/*/nym-wallet*.AppImage.tar.gz
|
- name: Deploy artifacts to CI www
|
||||||
|
continue-on-error: true
|
||||||
- name: Find AppImage tarball path for deployment
|
uses: easingthemes/ssh-deploy@main
|
||||||
id: find-appimage
|
env:
|
||||||
run: |
|
SSH_PRIVATE_KEY: ${{ secrets.CI_WWW_SSH_PRIVATE_KEY }}
|
||||||
APPIMAGE_TARBALL=$(find target/release/bundle -name "*.AppImage.tar.gz" | head -n 1)
|
ARGS: "-avzr"
|
||||||
if [ -n "$APPIMAGE_TARBALL" ]; then
|
SOURCE: "nym-wallet/target/release/bundle/appimage/nym-wallet*.AppImage.tar.gz"
|
||||||
echo "Found AppImage tarball: $APPIMAGE_TARBALL"
|
REMOTE_HOST: ${{ secrets.CI_WWW_REMOTE_HOST }}
|
||||||
echo "appimage_path=$APPIMAGE_TARBALL" >> $GITHUB_OUTPUT
|
REMOTE_USER: ${{ secrets.CI_WWW_REMOTE_USER }}
|
||||||
else
|
TARGET: ${{ secrets.CI_WWW_REMOTE_TARGET }}/builds/${{ github.ref_name }}/nym-wallet
|
||||||
echo "WARNING: No AppImage tarball found for deployment!"
|
EXCLUDE: "/dist/, /node_modules/"
|
||||||
echo "appimage_path=target/release/bundle/appimage/nym-wallet*.AppImage.tar.gz" >> $GITHUB_OUTPUT
|
|
||||||
fi
|
|
||||||
|
|
||||||
push-release-data:
|
push-release-data:
|
||||||
if: ${{ (startsWith(github.ref, 'refs/tags/nym-wallet-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }}
|
if: ${{ (startsWith(github.ref, 'refs/tags/nym-wallet-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }}
|
||||||
uses: ./.github/workflows/release-calculate-hash.yml
|
uses: ./.github/workflows/release-calculate-hash.yml
|
||||||
needs: publish-tauri
|
needs: publish-tauri
|
||||||
with:
|
with:
|
||||||
release_tag: ${{ needs.publish-tauri.outputs.release_tag || github.ref_name }}
|
release_tag: ${{ github.ref_name }}
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
|
|||||||
@@ -1,12 +1,6 @@
|
|||||||
name: publish-nym-wallet-win11
|
name: publish-nym-wallet-win11
|
||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
inputs:
|
|
||||||
sign:
|
|
||||||
description: "Sign this build using SSL.com. Signing is billed per signature so be careful"
|
|
||||||
required: false
|
|
||||||
type: boolean
|
|
||||||
default: true
|
|
||||||
release:
|
release:
|
||||||
types: [created]
|
types: [created]
|
||||||
|
|
||||||
@@ -24,61 +18,53 @@ jobs:
|
|||||||
runs-on: ${{ matrix.platform }}
|
runs-on: ${{ matrix.platform }}
|
||||||
|
|
||||||
outputs:
|
outputs:
|
||||||
release_tag: ${{ github.ref_name }}
|
release_id: ${{ steps.create-release.outputs.id }}
|
||||||
|
release_date: ${{ fromJSON(steps.create-release.outputs.assets)[0].created_at }}
|
||||||
|
version: ${{ steps.release-info.outputs.version }}
|
||||||
|
filename: ${{ steps.release-info.outputs.filename }}
|
||||||
|
file_hash: ${{ steps.release-info.outputs.file_hash }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
|
- name: Clean up first
|
||||||
|
continue-on-error: true
|
||||||
|
working-directory: .
|
||||||
|
run: |
|
||||||
|
cd ..
|
||||||
|
del /s /q /A:H nym
|
||||||
|
rmdir /s /q nym
|
||||||
|
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Install Rust stable
|
- name: Import signing certificate
|
||||||
uses: dtolnay/rust-toolchain@stable
|
env:
|
||||||
with:
|
WINDOWS_CERTIFICATE: ${{ secrets.WINDOWS_CERTIFICATE }}
|
||||||
toolchain: stable
|
WINDOWS_CERTIFICATE_PASSWORD: ${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }}
|
||||||
|
run: |
|
||||||
- name: Setup MSBuild.exe
|
New-Item -ItemType directory -Path certificate
|
||||||
uses: microsoft/setup-msbuild@v2
|
Set-Content -Path certificate/tempCert.txt -Value $env:WINDOWS_CERTIFICATE
|
||||||
|
certutil -decode certificate/tempCert.txt certificate/certificate.pfx
|
||||||
|
Remove-Item -path certificate -include tempCert.txt
|
||||||
|
Import-PfxCertificate -FilePath certificate/certificate.pfx -CertStoreLocation Cert:\CurrentUser\My -Password (ConvertTo-SecureString -String $env:WINDOWS_CERTIFICATE_PASSWORD -Force -AsPlainText)
|
||||||
|
|
||||||
- name: Node
|
- name: Node
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 21
|
node-version: 21
|
||||||
|
|
||||||
- name: Download EV CodeSignTool from ssl.com
|
- name: Install Rust stable
|
||||||
working-directory: nym-wallet/src-tauri
|
uses: actions-rs/toolchain@v1
|
||||||
if: ${{ inputs.sign }}
|
with:
|
||||||
shell: bash
|
toolchain: stable
|
||||||
run: |
|
|
||||||
curl -L0 https://www.ssl.com/download/codesigntool-for-linux-and-macos/ -o codesigntool.zip
|
- name: Create env file
|
||||||
unzip codesigntool.zip
|
uses: timheuer/base64-to-file@v1.2
|
||||||
- name: Get EV certificate credential id
|
with:
|
||||||
working-directory: nym-wallet/src-tauri
|
fileName: '.env'
|
||||||
if: ${{ inputs.sign }}
|
encodedString: ${{ secrets.WALLET_ADMIN_ADDRESS }}
|
||||||
id: get_credential_ids
|
|
||||||
shell: bash
|
- name: Install Yarn
|
||||||
run: |
|
run: npm install -g yarn
|
||||||
echo "SSL_COM_CREDENTIAL_ID=$(./CodeSignTool.sh get_credential_ids -username=${{ secrets.SSL_COM_USERNAME }} -password=${{ secrets.SSL_COM_PASSWORD }} | sed -n '1!p' | sed 's/- //')" >> "$GITHUB_OUTPUT"
|
|
||||||
- name: Add custom sign command to tauri.conf.json
|
|
||||||
working-directory: nym-wallet/src-tauri
|
|
||||||
if: ${{ inputs.sign }}
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
yq eval --inplace '.bundle.windows +=
|
|
||||||
{
|
|
||||||
"signCommand": {
|
|
||||||
"cmd": "C:\Program Files\Git\bin\bash.EXE",
|
|
||||||
"args": [
|
|
||||||
"/c/actions-runner/_work/nym/nym/nym-wallet/src-tauri/CodeSignTool.sh",
|
|
||||||
"sign",
|
|
||||||
"-username ${{ secrets.SSL_COM_USERNAME }}",
|
|
||||||
"-password ${{ secrets.SSL_COM_PASSWORD }}",
|
|
||||||
"-credential_id ${{ steps.get_credential_ids.outputs.SSL_COM_CREDENTIAL_ID }}",
|
|
||||||
"-totp_secret ${{ secrets.SSL_COM_TOTP_SECRET }}",
|
|
||||||
"-program_name NymWallet",
|
|
||||||
"-input_file_path",
|
|
||||||
"%1",
|
|
||||||
"-override"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}' tauri.conf.json
|
|
||||||
- name: Install project dependencies
|
- name: Install project dependencies
|
||||||
shell: bash
|
shell: bash
|
||||||
run: cd .. && yarn --network-timeout 100000
|
run: cd .. && yarn --network-timeout 100000
|
||||||
@@ -91,50 +77,18 @@ jobs:
|
|||||||
shell: bash
|
shell: bash
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
|
ENABLE_CODE_SIGNING: ${{ secrets.WINDOWS_CERTIFICATE }}
|
||||||
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
|
WINDOWS_CERTIFICATE: ${{ secrets.WINDOWS_CERTIFICATE }}
|
||||||
SSL_COM_USERNAME: ${{ inputs.sign && secrets.SSL_COM_USERNAME }}
|
WINDOWS_CERTIFICATE_PASSWORD: ${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }}
|
||||||
SSL_COM_PASSWORD: ${{ inputs.sign && secrets.SSL_COM_PASSWORD }}
|
TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
|
||||||
SSL_COM_CREDENTIAL_ID: ${{ inputs.sign && steps.get_credential_ids.outputs.SSL_COM_CREDENTIAL_ID }}
|
TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
|
||||||
SSL_COM_TOTP_SECRET: ${{ inputs.sign && secrets.SSL_COM_TOTP_SECRET }}
|
run: yarn build
|
||||||
run: |
|
|
||||||
echo "Starting build process..."
|
|
||||||
yarn build
|
|
||||||
|
|
||||||
- name: Check bundle directory
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
echo "Checking bundle directory structure"
|
|
||||||
|
|
||||||
# Check standard location
|
|
||||||
if [ -d "target/release/bundle" ]; then
|
|
||||||
echo "Found bundle directory at standard location"
|
|
||||||
ls -la target/release/bundle || echo "Failed to list bundle directory"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check src-tauri location
|
|
||||||
if [ -d "src-tauri/target/release/bundle" ]; then
|
|
||||||
echo "Found bundle directory in src-tauri"
|
|
||||||
ls -la src-tauri/target/release/bundle || echo "Failed to list src-tauri bundle directory"
|
|
||||||
|
|
||||||
# Use this path for future steps
|
|
||||||
echo "BUNDLE_PATH=src-tauri/target/release/bundle" >> $GITHUB_ENV
|
|
||||||
else
|
|
||||||
echo "Using standard bundle path"
|
|
||||||
echo "BUNDLE_PATH=target/release/bundle" >> $GITHUB_ENV
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check for MSI files in any location
|
|
||||||
find . -name "*.msi" -type f
|
|
||||||
|
|
||||||
- name: Upload Artifact
|
- name: Upload Artifact
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: nym-wallet.msi
|
name: nym-wallet_1.0.0_x64_en-US.msi
|
||||||
path: |
|
path: nym-wallet/target/release/bundle/msi/nym-wallet_1.*.msi
|
||||||
nym-wallet/${{ env.BUNDLE_PATH }}/msi/*.msi
|
|
||||||
nym-wallet/${{ env.BUNDLE_PATH }}/*/nym-wallet*.msi
|
|
||||||
nym-wallet/src-tauri/target/release/bundle/msi/*.msi
|
|
||||||
retention-days: 30
|
retention-days: 30
|
||||||
|
|
||||||
- id: create-release
|
- id: create-release
|
||||||
@@ -143,28 +97,25 @@ jobs:
|
|||||||
if: github.event_name == 'release'
|
if: github.event_name == 'release'
|
||||||
with:
|
with:
|
||||||
files: |
|
files: |
|
||||||
nym-wallet/${{ env.BUNDLE_PATH }}/msi/*.msi
|
nym-wallet/target/release/bundle/msi/*.msi
|
||||||
nym-wallet/${{ env.BUNDLE_PATH }}/msi/*.msi.zip*
|
nym-wallet/target/release/bundle/msi/*.msi.zip*
|
||||||
nym-wallet/${{ env.BUNDLE_PATH }}/*/nym-wallet*.msi
|
|
||||||
nym-wallet/src-tauri/target/release/bundle/msi/*.msi
|
- name: Deploy artifacts to CI www
|
||||||
|
continue-on-error: true
|
||||||
- name: Find MSI path for deployment
|
uses: easingthemes/ssh-deploy@main
|
||||||
id: find-msi
|
env:
|
||||||
shell: bash
|
SSH_PRIVATE_KEY: ${{ secrets.CI_WWW_SSH_PRIVATE_KEY }}
|
||||||
run: |
|
ARGS: "-avzr"
|
||||||
MSI_FILE=$(find . -name "*.msi" -type f | head -n 1)
|
SOURCE: "nym-wallet/target/release/bundle/msi/nym-wallet_1.*.msi"
|
||||||
if [ -n "$MSI_FILE" ]; then
|
REMOTE_HOST: ${{ secrets.CI_WWW_REMOTE_HOST }}
|
||||||
echo "Found MSI file: $MSI_FILE"
|
REMOTE_USER: ${{ secrets.CI_WWW_REMOTE_USER }}
|
||||||
echo "msi_path=$MSI_FILE" >> $GITHUB_OUTPUT
|
TARGET: ${{ secrets.CI_WWW_REMOTE_TARGET }}/builds/${{ github.ref_name }}/nym-wallet
|
||||||
else
|
EXCLUDE: "/dist/, /node_modules/"
|
||||||
echo "WARNING: No MSI file found for deployment!"
|
|
||||||
echo "msi_path=${{ env.BUNDLE_PATH }}/msi/nym-wallet*.msi" >> $GITHUB_OUTPUT
|
|
||||||
fi
|
|
||||||
|
|
||||||
push-release-data:
|
push-release-data:
|
||||||
if: ${{ (startsWith(github.ref, 'refs/tags/nym-wallet-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }}
|
if: ${{ (startsWith(github.ref, 'refs/tags/nym-wallet-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }}
|
||||||
uses: ./.github/workflows/release-calculate-hash.yml
|
uses: ./.github/workflows/release-calculate-hash.yml
|
||||||
needs: publish-tauri
|
needs: publish-tauri
|
||||||
with:
|
with:
|
||||||
release_tag: ${{ needs.publish-tauri.outputs.release_tag || github.ref_name }}
|
release_tag: ${{ github.ref_name }}
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ jobs:
|
|||||||
git config --global user.name "Lawrence Stalder"
|
git config --global user.name "Lawrence Stalder"
|
||||||
|
|
||||||
- name: Get version from cargo.toml
|
- name: Get version from cargo.toml
|
||||||
uses: mikefarah/yq@v4.45.4
|
uses: mikefarah/yq@v4.45.1
|
||||||
id: get_version
|
id: get_version
|
||||||
with:
|
with:
|
||||||
cmd: yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/nym-credential-proxy/Cargo.toml
|
cmd: yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/nym-credential-proxy/Cargo.toml
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ jobs:
|
|||||||
git config --global user.name "Lawrence Stalder"
|
git config --global user.name "Lawrence Stalder"
|
||||||
|
|
||||||
- name: Get version from cargo.toml
|
- name: Get version from cargo.toml
|
||||||
uses: mikefarah/yq@v4.45.4
|
uses: mikefarah/yq@v4.45.1
|
||||||
id: get_version
|
id: get_version
|
||||||
with:
|
with:
|
||||||
cmd: yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/Cargo.toml
|
cmd: yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/Cargo.toml
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ jobs:
|
|||||||
git config --global user.name "Lawrence Stalder"
|
git config --global user.name "Lawrence Stalder"
|
||||||
|
|
||||||
- name: Get version from cargo.toml
|
- name: Get version from cargo.toml
|
||||||
uses: mikefarah/yq@v4.45.4
|
uses: mikefarah/yq@v4.45.1
|
||||||
id: get_version
|
id: get_version
|
||||||
with:
|
with:
|
||||||
cmd: yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/nym-network-monitor/Cargo.toml
|
cmd: yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/nym-network-monitor/Cargo.toml
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ jobs:
|
|||||||
git config --global user.name "Lawrence Stalder"
|
git config --global user.name "Lawrence Stalder"
|
||||||
|
|
||||||
- name: Get version from cargo.toml
|
- name: Get version from cargo.toml
|
||||||
uses: mikefarah/yq@v4.45.4
|
uses: mikefarah/yq@v4.45.1
|
||||||
id: get_version
|
id: get_version
|
||||||
with:
|
with:
|
||||||
cmd: yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/Cargo.toml
|
cmd: yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/Cargo.toml
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ jobs:
|
|||||||
git config --global user.name "Lawrence Stalder"
|
git config --global user.name "Lawrence Stalder"
|
||||||
|
|
||||||
- name: Get version from cargo.toml
|
- name: Get version from cargo.toml
|
||||||
uses: mikefarah/yq@v4.45.4
|
uses: mikefarah/yq@v4.45.1
|
||||||
id: get_version
|
id: get_version
|
||||||
with:
|
with:
|
||||||
cmd: yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/Cargo.toml
|
cmd: yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/Cargo.toml
|
||||||
|
|||||||
@@ -1,51 +0,0 @@
|
|||||||
name: Build and upload Nym APU container to harbor.nymte.ch
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
env:
|
|
||||||
WORKING_DIRECTORY: "."
|
|
||||||
CONTAINER_NAME: "nym-api"
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build-container:
|
|
||||||
runs-on: arc-ubuntu-22.04-dind
|
|
||||||
steps:
|
|
||||||
- name: Login to Harbor
|
|
||||||
uses: docker/login-action@v3
|
|
||||||
with:
|
|
||||||
registry: harbor.nymte.ch
|
|
||||||
username: ${{ secrets.HARBOR_ROBOT_USERNAME }}
|
|
||||||
password: ${{ secrets.HARBOR_ROBOT_SECRET }}
|
|
||||||
|
|
||||||
- name: Checkout repo
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Configure git identity
|
|
||||||
run: |
|
|
||||||
git config --global user.email "lawrence@nymtech.net"
|
|
||||||
git config --global user.name "Lawrence Stalder"
|
|
||||||
|
|
||||||
- name: Get version from cargo.toml
|
|
||||||
uses: mikefarah/yq@v4.45.4
|
|
||||||
id: get_version
|
|
||||||
with:
|
|
||||||
cmd: yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/nym-api/Cargo.toml
|
|
||||||
|
|
||||||
- name: Remove existing tag if exists
|
|
||||||
run: |
|
|
||||||
echo "Checking if tag ${{ env.CONTAINER_NAME }}-${{ steps.get_version.outputs.result }} exists..."
|
|
||||||
if git rev-parse ${{ env.CONTAINER_NAME }}-${{ steps.get_version.outputs.result }} >/dev/null 2>&1; then
|
|
||||||
echo "Tag ${{ env.CONTAINER_NAME }}-${{ steps.get_version.outputs.result }} already exists"
|
|
||||||
git push --delete origin ${{ env.CONTAINER_NAME }}-${{ steps.get_version.outputs.result }}
|
|
||||||
git tag -d ${{ env.CONTAINER_NAME }}-${{ steps.get_version.outputs.result }}
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Create tag
|
|
||||||
run: |
|
|
||||||
git tag -a ${{ env.CONTAINER_NAME }}-${{ steps.get_version.outputs.result }} -m "Version ${{ steps.get_version.outputs.result }}"
|
|
||||||
git push origin ${{ env.CONTAINER_NAME }}-${{ steps.get_version.outputs.result }}
|
|
||||||
|
|
||||||
- name: BuildAndPushImageOnHarbor
|
|
||||||
run: |
|
|
||||||
docker build -f nym-api.dockerfile ${{ env.WORKING_DIRECTORY }} -t harbor.nymte.ch/nym/${{ env.CONTAINER_NAME }}:${{ steps.get_version.outputs.result }} -t harbor.nymte.ch/nym/${{ env.CONTAINER_NAME }}:latest
|
|
||||||
docker push harbor.nymte.ch/nym/${{ env.CONTAINER_NAME }} --all-tags
|
|
||||||
@@ -26,7 +26,7 @@ jobs:
|
|||||||
git config --global user.name "Lawrence Stalder"
|
git config --global user.name "Lawrence Stalder"
|
||||||
|
|
||||||
- name: Get version from cargo.toml
|
- name: Get version from cargo.toml
|
||||||
uses: mikefarah/yq@v4.45.4
|
uses: mikefarah/yq@v4.45.1
|
||||||
id: get_version
|
id: get_version
|
||||||
with:
|
with:
|
||||||
cmd: yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/Cargo.toml
|
cmd: yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/Cargo.toml
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ jobs:
|
|||||||
git config --global user.name "Lawrence Stalder"
|
git config --global user.name "Lawrence Stalder"
|
||||||
|
|
||||||
- name: Get version from cargo.toml
|
- name: Get version from cargo.toml
|
||||||
uses: mikefarah/yq@v4.45.4
|
uses: mikefarah/yq@v4.45.1
|
||||||
id: get_version
|
id: get_version
|
||||||
with:
|
with:
|
||||||
cmd: yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/Cargo.toml
|
cmd: yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/Cargo.toml
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ jobs:
|
|||||||
git config --global user.name "Lawrence Stalder"
|
git config --global user.name "Lawrence Stalder"
|
||||||
|
|
||||||
- name: Get version from cargo.toml
|
- name: Get version from cargo.toml
|
||||||
uses: mikefarah/yq@v4.45.4
|
uses: mikefarah/yq@v4.45.1
|
||||||
id: get_version
|
id: get_version
|
||||||
with:
|
with:
|
||||||
cmd: yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/Cargo.toml
|
cmd: yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/Cargo.toml
|
||||||
|
|||||||
@@ -59,7 +59,3 @@ nym-api/redocly/formatted-openapi.json
|
|||||||
|
|
||||||
*.sqlite
|
*.sqlite
|
||||||
.build
|
.build
|
||||||
|
|
||||||
**/settings.sql
|
|
||||||
**/enter_db.sh
|
|
||||||
CLAUDE.md
|
|
||||||
@@ -4,80 +4,6 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
## [2025.9-appenzeller] (2025-05-13)
|
|
||||||
|
|
||||||
- build(deps): bump clap from 4.5.36 to 4.5.37 in the patch-updates group ([#5722])
|
|
||||||
- build(deps): bump golang.org/x/net from 0.36.0 to 0.38.0 in /wasm/mix-fetch/go-mix-conn ([#5720])
|
|
||||||
- build(deps-dev): bump http-proxy-middleware from 2.0.6 to 2.0.9 in /wasm/client/internal-dev ([#5719])
|
|
||||||
- Add /account/{address} ([#5673])
|
|
||||||
- Add contains ticketbook data db query ([#5670])
|
|
||||||
|
|
||||||
[#5722]: https://github.com/nymtech/nym/pull/5722
|
|
||||||
[#5720]: https://github.com/nymtech/nym/pull/5720
|
|
||||||
[#5719]: https://github.com/nymtech/nym/pull/5719
|
|
||||||
[#5673]: https://github.com/nymtech/nym/pull/5673
|
|
||||||
[#5670]: https://github.com/nymtech/nym/pull/5670
|
|
||||||
|
|
||||||
## [2025.8-tourist] (2025-04-29)
|
|
||||||
|
|
||||||
- add reserved byte to reply surb serialisation ([#5731])
|
|
||||||
- Remove inactive peers ([#5721])
|
|
||||||
- Update Hickory DNS "0.24.4" to "0.25" ([#5709])
|
|
||||||
- build(deps): bump the patch-updates group across 1 directory with 7 updates ([#5708])
|
|
||||||
- Peer handle should die more gracefully ([#5704])
|
|
||||||
- build(deps): bump crossbeam-channel from 0.5.14 to 0.5.15 ([#5702])
|
|
||||||
- build(deps): bump actions/checkout from 3 to 4 ([#5700])
|
|
||||||
- Feature/updated sphinx payload keys ([#5698])
|
|
||||||
- Bump the nym-vpn deb metapackage to 1.0 ([#5697])
|
|
||||||
- Make mix hops optional for Mixnet Client ([#5696])
|
|
||||||
- build(deps): bump tokio from 1.44.1 to 1.44.2 ([#5693])
|
|
||||||
- Feature/replay protection ([#5682])
|
|
||||||
- Adding fresh nym-api tests and workflow ([#5659])
|
|
||||||
- build(deps): bump next from 14.2.21 to 14.2.25 ([#5655])
|
|
||||||
- build(deps): bump pnpm/action-setup from 4.0.0 to 4.1.0 ([#5436])
|
|
||||||
|
|
||||||
[#5731]: https://github.com/nymtech/nym/pull/5731
|
|
||||||
[#5721]: https://github.com/nymtech/nym/pull/5721
|
|
||||||
[#5709]: https://github.com/nymtech/nym/pull/5709
|
|
||||||
[#5708]: https://github.com/nymtech/nym/pull/5708
|
|
||||||
[#5704]: https://github.com/nymtech/nym/pull/5704
|
|
||||||
[#5702]: https://github.com/nymtech/nym/pull/5702
|
|
||||||
[#5700]: https://github.com/nymtech/nym/pull/5700
|
|
||||||
[#5698]: https://github.com/nymtech/nym/pull/5698
|
|
||||||
[#5697]: https://github.com/nymtech/nym/pull/5697
|
|
||||||
[#5696]: https://github.com/nymtech/nym/pull/5696
|
|
||||||
[#5693]: https://github.com/nymtech/nym/pull/5693
|
|
||||||
[#5682]: https://github.com/nymtech/nym/pull/5682
|
|
||||||
[#5659]: https://github.com/nymtech/nym/pull/5659
|
|
||||||
[#5655]: https://github.com/nymtech/nym/pull/5655
|
|
||||||
[#5436]: https://github.com/nymtech/nym/pull/5436
|
|
||||||
|
|
||||||
## [2025.7-tex] (2025-04-14)
|
|
||||||
|
|
||||||
- Expand /v3/nym-nodes with geodata ([#5686])
|
|
||||||
- chore: clippy for 1.86 ([#5685])
|
|
||||||
- Featrure: Bash scripts to init and configure VMs conveniently and update docs ([#5681])
|
|
||||||
- Update node versions in CI ([#5677])
|
|
||||||
- build(deps): bump the patch-updates group across 1 directory with 8 updates ([#5668])
|
|
||||||
- Update log crate ([#5667])
|
|
||||||
- Minor fixes involving key cloning and hashing ([#5664])
|
|
||||||
- mix throughput tester ([#5661])
|
|
||||||
- build(deps): bump blake3 from 1.6.1 to 1.7.0 ([#5658])
|
|
||||||
- build(deps): bump elliptic from 6.5.5 to 6.6.1 ([#5483])
|
|
||||||
- Move all workflows on ubuntu-20 to ubuntu-22 ([#5455])
|
|
||||||
|
|
||||||
[#5686]: https://github.com/nymtech/nym/pull/5686
|
|
||||||
[#5685]: https://github.com/nymtech/nym/pull/5685
|
|
||||||
[#5681]: https://github.com/nymtech/nym/pull/5681
|
|
||||||
[#5677]: https://github.com/nymtech/nym/pull/5677
|
|
||||||
[#5668]: https://github.com/nymtech/nym/pull/5668
|
|
||||||
[#5667]: https://github.com/nymtech/nym/pull/5667
|
|
||||||
[#5664]: https://github.com/nymtech/nym/pull/5664
|
|
||||||
[#5661]: https://github.com/nymtech/nym/pull/5661
|
|
||||||
[#5658]: https://github.com/nymtech/nym/pull/5658
|
|
||||||
[#5483]: https://github.com/nymtech/nym/pull/5483
|
|
||||||
[#5455]: https://github.com/nymtech/nym/pull/5455
|
|
||||||
|
|
||||||
## [2025.6-chuckles] (2025-03-31)
|
## [2025.6-chuckles] (2025-03-31)
|
||||||
|
|
||||||
- Remove Google public DNS ([#5660])
|
- Remove Google public DNS ([#5660])
|
||||||
|
|||||||
Generated
+1037
-1117
File diff suppressed because it is too large
Load Diff
+32
-22
@@ -39,6 +39,7 @@ members = [
|
|||||||
"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/credential-storage",
|
"common/credential-storage",
|
||||||
"common/credential-utils",
|
"common/credential-utils",
|
||||||
"common/credential-verification",
|
"common/credential-verification",
|
||||||
@@ -96,6 +97,9 @@ members = [
|
|||||||
"common/wireguard",
|
"common/wireguard",
|
||||||
"common/wireguard-types",
|
"common/wireguard-types",
|
||||||
"documentation/autodoc",
|
"documentation/autodoc",
|
||||||
|
# "explorer-api",
|
||||||
|
# "explorer-api/explorer-api-requests",
|
||||||
|
# "explorer-api/explorer-client",
|
||||||
"gateway",
|
"gateway",
|
||||||
"integrations/bity",
|
"integrations/bity",
|
||||||
"nym-api",
|
"nym-api",
|
||||||
@@ -123,6 +127,7 @@ members = [
|
|||||||
"service-providers/ip-packet-router",
|
"service-providers/ip-packet-router",
|
||||||
"service-providers/network-requester",
|
"service-providers/network-requester",
|
||||||
"tools/echo-server",
|
"tools/echo-server",
|
||||||
|
"tools/echo-server",
|
||||||
"tools/internal/contract-state-importer/importer-cli",
|
"tools/internal/contract-state-importer/importer-cli",
|
||||||
"tools/internal/contract-state-importer/importer-contract",
|
"tools/internal/contract-state-importer/importer-contract",
|
||||||
"tools/internal/mixnet-connectivity-check",
|
"tools/internal/mixnet-connectivity-check",
|
||||||
@@ -160,7 +165,12 @@ default-members = [
|
|||||||
"tools/nymvisor",
|
"tools/nymvisor",
|
||||||
]
|
]
|
||||||
|
|
||||||
exclude = ["explorer", "contracts", "nym-wallet", "cpu-cycles"]
|
exclude = [
|
||||||
|
"explorer",
|
||||||
|
"contracts",
|
||||||
|
"nym-wallet",
|
||||||
|
"cpu-cycles",
|
||||||
|
]
|
||||||
|
|
||||||
[workspace.package]
|
[workspace.package]
|
||||||
authors = ["Nym Technologies SA"]
|
authors = ["Nym Technologies SA"]
|
||||||
@@ -179,7 +189,7 @@ aes = "0.8.1"
|
|||||||
aes-gcm = "0.10.1"
|
aes-gcm = "0.10.1"
|
||||||
aes-gcm-siv = "0.11.1"
|
aes-gcm-siv = "0.11.1"
|
||||||
ammonia = "4"
|
ammonia = "4"
|
||||||
anyhow = "1.0.98"
|
anyhow = "1.0.97"
|
||||||
arc-swap = "1.7.1"
|
arc-swap = "1.7.1"
|
||||||
argon2 = "0.5.0"
|
argon2 = "0.5.0"
|
||||||
async-trait = "0.1.88"
|
async-trait = "0.1.88"
|
||||||
@@ -194,7 +204,7 @@ bip39 = { version = "2.0.0", features = ["zeroize"] }
|
|||||||
bit-vec = "0.7.0" # can we unify those?
|
bit-vec = "0.7.0" # can we unify those?
|
||||||
bitvec = "1.0.0"
|
bitvec = "1.0.0"
|
||||||
blake3 = "1.7.0"
|
blake3 = "1.7.0"
|
||||||
bloomfilter = "3.0.1"
|
bloomfilter = "1.0.14"
|
||||||
bs58 = "0.5.1"
|
bs58 = "0.5.1"
|
||||||
bytecodec = "0.4.15"
|
bytecodec = "0.4.15"
|
||||||
bytes = "1.10.1"
|
bytes = "1.10.1"
|
||||||
@@ -203,9 +213,9 @@ celes = "2.6.0"
|
|||||||
cfg-if = "1.0.0"
|
cfg-if = "1.0.0"
|
||||||
chacha20 = "0.9.0"
|
chacha20 = "0.9.0"
|
||||||
chacha20poly1305 = "0.10.1"
|
chacha20poly1305 = "0.10.1"
|
||||||
chrono = "0.4.41"
|
chrono = "0.4.40"
|
||||||
cipher = "0.4.3"
|
cipher = "0.4.3"
|
||||||
clap = "4.5.38"
|
clap = "4.5.34"
|
||||||
clap_complete = "4.5"
|
clap_complete = "4.5"
|
||||||
clap_complete_fig = "4.5"
|
clap_complete_fig = "4.5"
|
||||||
colored = "2.2"
|
colored = "2.2"
|
||||||
@@ -230,12 +240,12 @@ dotenvy = "0.15.6"
|
|||||||
ecdsa = "0.16"
|
ecdsa = "0.16"
|
||||||
ed25519-dalek = "2.1"
|
ed25519-dalek = "2.1"
|
||||||
encoding_rs = "0.8.35"
|
encoding_rs = "0.8.35"
|
||||||
env_logger = "0.11.8"
|
env_logger = "0.11.7"
|
||||||
envy = "0.4"
|
envy = "0.4"
|
||||||
etherparse = "0.13.0"
|
etherparse = "0.13.0"
|
||||||
eyre = "0.6.9"
|
eyre = "0.6.9"
|
||||||
fastrand = "2.1.1"
|
fastrand = "2.1.1"
|
||||||
flate2 = "1.1.1"
|
flate2 = "1.1.0"
|
||||||
futures = "0.3.31"
|
futures = "0.3.31"
|
||||||
futures-util = "0.3"
|
futures-util = "0.3"
|
||||||
generic-array = "0.14.7"
|
generic-array = "0.14.7"
|
||||||
@@ -245,7 +255,7 @@ handlebars = "3.5.5"
|
|||||||
headers = "0.4.0"
|
headers = "0.4.0"
|
||||||
hex = "0.4.3"
|
hex = "0.4.3"
|
||||||
hex-literal = "0.3.3"
|
hex-literal = "0.3.3"
|
||||||
hickory-resolver = "0.25"
|
hickory-resolver = "0.24.4"
|
||||||
hkdf = "0.12.3"
|
hkdf = "0.12.3"
|
||||||
hmac = "0.12.1"
|
hmac = "0.12.1"
|
||||||
http = "1"
|
http = "1"
|
||||||
@@ -260,6 +270,7 @@ indicatif = "0.17.11"
|
|||||||
inquire = "0.6.2"
|
inquire = "0.6.2"
|
||||||
ip_network = "0.4.1"
|
ip_network = "0.4.1"
|
||||||
ipnetwork = "0.20"
|
ipnetwork = "0.20"
|
||||||
|
isocountry = "0.3.2"
|
||||||
itertools = "0.14.0"
|
itertools = "0.14.0"
|
||||||
k256 = "0.13"
|
k256 = "0.13"
|
||||||
lazy_static = "1.5.0"
|
lazy_static = "1.5.0"
|
||||||
@@ -280,6 +291,7 @@ pem = "0.8"
|
|||||||
petgraph = "0.6.5"
|
petgraph = "0.6.5"
|
||||||
pin-project = "1.1"
|
pin-project = "1.1"
|
||||||
pin-project-lite = "0.2.16"
|
pin-project-lite = "0.2.16"
|
||||||
|
pretty_env_logger = "0.4.0"
|
||||||
publicsuffix = "2.3.0"
|
publicsuffix = "2.3.0"
|
||||||
quote = "1"
|
quote = "1"
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
@@ -291,6 +303,9 @@ rand_seeder = "0.2.3"
|
|||||||
rayon = "1.5.1"
|
rayon = "1.5.1"
|
||||||
regex = "1.10.6"
|
regex = "1.10.6"
|
||||||
reqwest = { version = "0.12.15", default-features = false }
|
reqwest = { version = "0.12.15", default-features = false }
|
||||||
|
rocket = "0.5.0"
|
||||||
|
rocket_cors = "0.6.0"
|
||||||
|
rocket_okapi = "0.8.0"
|
||||||
rs_merkle = "1.5.0"
|
rs_merkle = "1.5.0"
|
||||||
safer-ffi = "0.1.13"
|
safer-ffi = "0.1.13"
|
||||||
schemars = "0.8.22"
|
schemars = "0.8.22"
|
||||||
@@ -303,9 +318,9 @@ serde_json_path = "0.7.2"
|
|||||||
serde_repr = "0.1"
|
serde_repr = "0.1"
|
||||||
serde_with = "3.9.0"
|
serde_with = "3.9.0"
|
||||||
serde_yaml = "0.9.25"
|
serde_yaml = "0.9.25"
|
||||||
sha2 = "0.10.9"
|
sha2 = "0.10.8"
|
||||||
si-scale = "0.2.3"
|
si-scale = "0.2.3"
|
||||||
sphinx-packet = "=0.6.0"
|
sphinx-packet = "=0.3.2"
|
||||||
sqlx = "0.7.4"
|
sqlx = "0.7.4"
|
||||||
strum = "0.26"
|
strum = "0.26"
|
||||||
strum_macros = "0.26"
|
strum_macros = "0.26"
|
||||||
@@ -323,8 +338,8 @@ tokio-stream = "0.1.17"
|
|||||||
tokio-test = "0.4.4"
|
tokio-test = "0.4.4"
|
||||||
tokio-tun = "0.11.5"
|
tokio-tun = "0.11.5"
|
||||||
tokio-tungstenite = { version = "0.20.1" }
|
tokio-tungstenite = { version = "0.20.1" }
|
||||||
tokio-util = "0.7.15"
|
tokio-util = "0.7.14"
|
||||||
toml = "0.8.22"
|
toml = "0.8.20"
|
||||||
tower = "0.5.2"
|
tower = "0.5.2"
|
||||||
tower-http = "0.5.2"
|
tower-http = "0.5.2"
|
||||||
tracing = "0.1.41"
|
tracing = "0.1.41"
|
||||||
@@ -335,7 +350,7 @@ tracing-tree = "0.2.2"
|
|||||||
tracing-indicatif = "0.3.9"
|
tracing-indicatif = "0.3.9"
|
||||||
ts-rs = "10.1.0"
|
ts-rs = "10.1.0"
|
||||||
tungstenite = { version = "0.20.1", default-features = false }
|
tungstenite = { version = "0.20.1", default-features = false }
|
||||||
uniffi = "0.29.2"
|
uniffi = "0.29.1"
|
||||||
uniffi_build = "0.29.0"
|
uniffi_build = "0.29.0"
|
||||||
url = "2.5"
|
url = "2.5"
|
||||||
utoipa = "5.2"
|
utoipa = "5.2"
|
||||||
@@ -348,7 +363,7 @@ wasm-bindgen-test = "0.3.49"
|
|||||||
x25519-dalek = "2.0.0"
|
x25519-dalek = "2.0.0"
|
||||||
zeroize = "1.7.0"
|
zeroize = "1.7.0"
|
||||||
|
|
||||||
prometheus = { version = "0.14.0" }
|
prometheus = { version = "0.13.0" }
|
||||||
|
|
||||||
# coconut/DKG related
|
# coconut/DKG related
|
||||||
# unfortunately until https://github.com/zkcrypto/bls12_381/issues/10 is resolved, we have to rely on the fork
|
# unfortunately until https://github.com/zkcrypto/bls12_381/issues/10 is resolved, we have to rely on the fork
|
||||||
@@ -378,15 +393,15 @@ bip32 = { version = "0.5.3", default-features = false }
|
|||||||
|
|
||||||
|
|
||||||
cosmrs = { version = "0.21.1" }
|
cosmrs = { version = "0.21.1" }
|
||||||
tendermint = "0.40.4"
|
tendermint = "0.40.0"
|
||||||
tendermint-rpc = "0.40.4"
|
tendermint-rpc = "0.40.0"
|
||||||
prost = { version = "0.13", default-features = false }
|
prost = { version = "0.13", default-features = false }
|
||||||
|
|
||||||
# wasm-related dependencies
|
# wasm-related dependencies
|
||||||
gloo-utils = "0.2.0"
|
gloo-utils = "0.2.0"
|
||||||
gloo-net = "0.6.0"
|
gloo-net = "0.6.0"
|
||||||
|
|
||||||
indexed_db_futures = "0.6.4"
|
indexed_db_futures = "0.6.1"
|
||||||
js-sys = "0.3.76"
|
js-sys = "0.3.76"
|
||||||
serde-wasm-bindgen = "0.6.5"
|
serde-wasm-bindgen = "0.6.5"
|
||||||
tsify = "0.4.5"
|
tsify = "0.4.5"
|
||||||
@@ -395,11 +410,6 @@ wasm-bindgen-futures = "0.4.49"
|
|||||||
wasmtimer = "0.4.1"
|
wasmtimer = "0.4.1"
|
||||||
web-sys = "0.3.76"
|
web-sys = "0.3.76"
|
||||||
|
|
||||||
|
|
||||||
# for local development:
|
|
||||||
#[patch.crates-io]
|
|
||||||
#sphinx-packet = { path = "../sphinx" }
|
|
||||||
|
|
||||||
# Profile settings for individual crates
|
# Profile settings for individual crates
|
||||||
|
|
||||||
# Compile-time verified queries do quite a bit of work at compile time. Incremental
|
# Compile-time verified queries do quite a bit of work at compile time. Incremental
|
||||||
|
|||||||
@@ -168,9 +168,8 @@ generate-typescript:
|
|||||||
cd tools/ts-rs-cli && cargo run && cd ../..
|
cd tools/ts-rs-cli && cargo run && cd ../..
|
||||||
yarn types:lint:fix
|
yarn types:lint:fix
|
||||||
|
|
||||||
# Run the integration tests for public nym-api endpoints
|
|
||||||
run-api-tests:
|
run-api-tests:
|
||||||
dotenv -f envs/sandbox.env -- cargo test --test public-api-tests
|
cd nym-api/tests/functional_test && yarn test:qa
|
||||||
|
|
||||||
# Build debian package, and update PPA
|
# Build debian package, and update PPA
|
||||||
deb-cli: build-nym-cli
|
deb-cli: build-nym-cli
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "nym-client"
|
name = "nym-client"
|
||||||
version = "1.1.55"
|
version = "1.1.52"
|
||||||
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jędrzej Stuczyński <andrew@nymtech.net>"]
|
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jędrzej Stuczyński <andrew@nymtech.net>"]
|
||||||
description = "Implementation of the Nym Client"
|
description = "Implementation of the Nym Client"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
@@ -46,7 +46,6 @@ nym-bandwidth-controller = { path = "../../common/bandwidth-controller" }
|
|||||||
nym-bin-common = { path = "../../common/bin-common", features = [
|
nym-bin-common = { path = "../../common/bin-common", features = [
|
||||||
"output_format",
|
"output_format",
|
||||||
"clap",
|
"clap",
|
||||||
"basic_tracing",
|
|
||||||
] }
|
] }
|
||||||
nym-client-core = { path = "../../common/client-core", features = [
|
nym-client-core = { path = "../../common/client-core", features = [
|
||||||
"fs-credentials-storage",
|
"fs-credentials-storage",
|
||||||
|
|||||||
@@ -25,7 +25,6 @@ pub mod old_config_v1_1_13;
|
|||||||
pub mod old_config_v1_1_20;
|
pub mod old_config_v1_1_20;
|
||||||
pub mod old_config_v1_1_20_2;
|
pub mod old_config_v1_1_20_2;
|
||||||
pub mod old_config_v1_1_33;
|
pub mod old_config_v1_1_33;
|
||||||
pub mod old_config_v1_1_54;
|
|
||||||
mod persistence;
|
mod persistence;
|
||||||
mod template;
|
mod template;
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
use crate::client::config::persistence::ClientPaths;
|
use crate::client::config::persistence::ClientPaths;
|
||||||
use crate::client::config::{default_config_filepath, Socket, SocketType};
|
use crate::client::config::{default_config_filepath, Config, Socket, SocketType};
|
||||||
use crate::error::ClientError;
|
use crate::error::ClientError;
|
||||||
use nym_bin_common::logging::LoggingSettings;
|
use nym_bin_common::logging::LoggingSettings;
|
||||||
use nym_client_core::config::disk_persistence::old_v1_1_33::CommonClientPathsV1_1_33;
|
use nym_client_core::config::disk_persistence::old_v1_1_33::CommonClientPathsV1_1_33;
|
||||||
@@ -14,8 +14,6 @@ use std::io;
|
|||||||
use std::net::{IpAddr, Ipv4Addr};
|
use std::net::{IpAddr, Ipv4Addr};
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
use super::old_config_v1_1_54::ConfigV1_1_54;
|
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, PartialEq, Eq, Serialize, Clone)]
|
#[derive(Debug, Deserialize, PartialEq, Eq, Serialize, Clone)]
|
||||||
pub struct ClientPathsV1_1_33 {
|
pub struct ClientPathsV1_1_33 {
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
@@ -35,21 +33,6 @@ pub struct ConfigV1_1_33 {
|
|||||||
pub logging: LoggingSettings,
|
pub logging: LoggingSettings,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryFrom<ConfigV1_1_33> for ConfigV1_1_54 {
|
|
||||||
type Error = ClientError;
|
|
||||||
|
|
||||||
fn try_from(value: ConfigV1_1_33) -> Result<Self, Self::Error> {
|
|
||||||
Ok(ConfigV1_1_54 {
|
|
||||||
base: value.base.into(),
|
|
||||||
socket: value.socket.into(),
|
|
||||||
storage_paths: ClientPaths {
|
|
||||||
common_paths: value.storage_paths.common_paths.upgrade_default()?,
|
|
||||||
},
|
|
||||||
logging: value.logging,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ConfigV1_1_33 {
|
impl ConfigV1_1_33 {
|
||||||
pub fn read_from_toml_file<P: AsRef<Path>>(path: P) -> io::Result<Self> {
|
pub fn read_from_toml_file<P: AsRef<Path>>(path: P) -> io::Result<Self> {
|
||||||
read_config_from_toml_file(path)
|
read_config_from_toml_file(path)
|
||||||
@@ -58,6 +41,17 @@ impl ConfigV1_1_33 {
|
|||||||
pub fn read_from_default_path<P: AsRef<Path>>(id: P) -> io::Result<Self> {
|
pub fn read_from_default_path<P: AsRef<Path>>(id: P) -> io::Result<Self> {
|
||||||
Self::read_from_toml_file(default_config_filepath(id))
|
Self::read_from_toml_file(default_config_filepath(id))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn try_upgrade(self) -> Result<Config, ClientError> {
|
||||||
|
Ok(Config {
|
||||||
|
base: self.base.into(),
|
||||||
|
socket: self.socket.into(),
|
||||||
|
storage_paths: ClientPaths {
|
||||||
|
common_paths: self.storage_paths.common_paths.upgrade_default()?,
|
||||||
|
},
|
||||||
|
logging: self.logging,
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, PartialEq, Eq, Serialize, Clone, Copy)]
|
#[derive(Debug, Deserialize, PartialEq, Eq, Serialize, Clone, Copy)]
|
||||||
|
|||||||
@@ -1,41 +0,0 @@
|
|||||||
use std::{io, path::Path};
|
|
||||||
|
|
||||||
use nym_bin_common::logging::LoggingSettings;
|
|
||||||
use nym_client_core::config::old_config_v1_1_54::ConfigV1_1_54 as BaseConfigV1_1_54;
|
|
||||||
use nym_config::read_config_from_toml_file;
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
use crate::error::ClientError;
|
|
||||||
|
|
||||||
use super::{default_config_filepath, persistence::ClientPaths, Config, Socket};
|
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, PartialEq, Serialize, Clone)]
|
|
||||||
pub struct ConfigV1_1_54 {
|
|
||||||
#[serde(flatten)]
|
|
||||||
pub base: BaseConfigV1_1_54,
|
|
||||||
|
|
||||||
pub socket: Socket,
|
|
||||||
|
|
||||||
pub storage_paths: ClientPaths,
|
|
||||||
|
|
||||||
pub logging: LoggingSettings,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ConfigV1_1_54 {
|
|
||||||
pub fn read_from_toml_file<P: AsRef<Path>>(path: P) -> io::Result<Self> {
|
|
||||||
read_config_from_toml_file(path)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn read_from_default_path<P: AsRef<Path>>(id: P) -> io::Result<Self> {
|
|
||||||
Self::read_from_toml_file(default_config_filepath(id))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn try_upgrade(self) -> Result<Config, ClientError> {
|
|
||||||
Ok(Config {
|
|
||||||
base: self.base.into(),
|
|
||||||
socket: self.socket,
|
|
||||||
storage_paths: self.storage_paths,
|
|
||||||
logging: self.logging,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -92,6 +92,10 @@ host = '{{ socket.host }}'
|
|||||||
|
|
||||||
[debug]
|
[debug]
|
||||||
|
|
||||||
|
[debug.traffic]
|
||||||
|
average_packet_delay = '{{ debug.traffic.average_packet_delay }}'
|
||||||
|
message_sending_average_delay = '{{ debug.traffic.message_sending_average_delay }}'
|
||||||
|
|
||||||
[debug.acknowledgements]
|
[debug.acknowledgements]
|
||||||
average_ack_delay = '{{ debug.acknowledgements.average_ack_delay }}'
|
average_ack_delay = '{{ debug.acknowledgements.average_ack_delay }}'
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ use crate::client::config::old_config_v1_1_13::OldConfigV1_1_13;
|
|||||||
use crate::client::config::old_config_v1_1_20::ConfigV1_1_20;
|
use crate::client::config::old_config_v1_1_20::ConfigV1_1_20;
|
||||||
use crate::client::config::old_config_v1_1_20_2::ConfigV1_1_20_2;
|
use crate::client::config::old_config_v1_1_20_2::ConfigV1_1_20_2;
|
||||||
use crate::client::config::old_config_v1_1_33::ConfigV1_1_33;
|
use crate::client::config::old_config_v1_1_33::ConfigV1_1_33;
|
||||||
use crate::client::config::old_config_v1_1_54::ConfigV1_1_54;
|
|
||||||
use crate::client::config::{BaseClientConfig, Config};
|
use crate::client::config::{BaseClientConfig, Config};
|
||||||
use crate::commands::ecash::Ecash;
|
use crate::commands::ecash::Ecash;
|
||||||
use crate::error::ClientError;
|
use crate::error::ClientError;
|
||||||
@@ -178,8 +177,7 @@ async fn try_upgrade_v1_1_13_config(id: &str) -> Result<bool, ClientError> {
|
|||||||
let updated_step2: ConfigV1_1_20_2 = updated_step1.into();
|
let updated_step2: ConfigV1_1_20_2 = updated_step1.into();
|
||||||
let (updated_step3, gateway_config) = updated_step2.upgrade()?;
|
let (updated_step3, gateway_config) = updated_step2.upgrade()?;
|
||||||
let old_paths = updated_step3.storage_paths.clone();
|
let old_paths = updated_step3.storage_paths.clone();
|
||||||
let updated_step4: ConfigV1_1_54 = updated_step3.try_into()?;
|
let updated = updated_step3.try_upgrade()?;
|
||||||
let updated = updated_step4.try_upgrade()?;
|
|
||||||
|
|
||||||
v1_1_33::migrate_gateway_details(
|
v1_1_33::migrate_gateway_details(
|
||||||
&old_paths.common_paths,
|
&old_paths.common_paths,
|
||||||
@@ -207,8 +205,7 @@ async fn try_upgrade_v1_1_20_config(id: &str) -> Result<bool, ClientError> {
|
|||||||
let updated_step1: ConfigV1_1_20_2 = old_config.into();
|
let updated_step1: ConfigV1_1_20_2 = old_config.into();
|
||||||
let (updated_step2, gateway_config) = updated_step1.upgrade()?;
|
let (updated_step2, gateway_config) = updated_step1.upgrade()?;
|
||||||
let old_paths = updated_step2.storage_paths.clone();
|
let old_paths = updated_step2.storage_paths.clone();
|
||||||
let updated_step3: ConfigV1_1_54 = updated_step2.try_into()?;
|
let updated = updated_step2.try_upgrade()?;
|
||||||
let updated = updated_step3.try_upgrade()?;
|
|
||||||
|
|
||||||
v1_1_33::migrate_gateway_details(
|
v1_1_33::migrate_gateway_details(
|
||||||
&old_paths.common_paths,
|
&old_paths.common_paths,
|
||||||
@@ -232,8 +229,7 @@ async fn try_upgrade_v1_1_20_2_config(id: &str) -> Result<bool, ClientError> {
|
|||||||
|
|
||||||
let (updated_step1, gateway_config) = old_config.upgrade()?;
|
let (updated_step1, gateway_config) = old_config.upgrade()?;
|
||||||
let old_paths = updated_step1.storage_paths.clone();
|
let old_paths = updated_step1.storage_paths.clone();
|
||||||
let updated_step2: ConfigV1_1_54 = updated_step1.try_into()?;
|
let updated = updated_step1.try_upgrade()?;
|
||||||
let updated = updated_step2.try_upgrade()?;
|
|
||||||
|
|
||||||
v1_1_33::migrate_gateway_details(
|
v1_1_33::migrate_gateway_details(
|
||||||
&old_paths.common_paths,
|
&old_paths.common_paths,
|
||||||
@@ -256,8 +252,7 @@ async fn try_upgrade_v1_1_33_config(id: &str) -> Result<bool, ClientError> {
|
|||||||
info!("It is going to get updated to the current specification.");
|
info!("It is going to get updated to the current specification.");
|
||||||
|
|
||||||
let old_paths = old_config.storage_paths.clone();
|
let old_paths = old_config.storage_paths.clone();
|
||||||
let updated_step1: ConfigV1_1_54 = old_config.try_into()?;
|
let updated = old_config.try_upgrade()?;
|
||||||
let updated = updated_step1.try_upgrade()?;
|
|
||||||
|
|
||||||
v1_1_33::migrate_gateway_details(
|
v1_1_33::migrate_gateway_details(
|
||||||
&old_paths.common_paths,
|
&old_paths.common_paths,
|
||||||
@@ -270,22 +265,6 @@ async fn try_upgrade_v1_1_33_config(id: &str) -> Result<bool, ClientError> {
|
|||||||
Ok(true)
|
Ok(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn try_upgrade_v1_1_54_config(id: &str) -> Result<bool, ClientError> {
|
|
||||||
// explicitly load it as v1.1.54 (which is incompatible with the current one, i.e. +1.1.55)
|
|
||||||
let Ok(old_config) = ConfigV1_1_54::read_from_default_path(id) else {
|
|
||||||
// if we failed to load it, there might have been nothing to upgrade
|
|
||||||
// or maybe it was an even older file. in either way. just ignore it and carry on with our day
|
|
||||||
return Ok(false);
|
|
||||||
};
|
|
||||||
info!("It seems the client is using <= v1.1.54 config template.");
|
|
||||||
info!("It is going to get updated to the current specification.");
|
|
||||||
|
|
||||||
let updated = old_config.try_upgrade()?;
|
|
||||||
|
|
||||||
updated.save_to_default_location()?;
|
|
||||||
Ok(true)
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn try_upgrade_config(id: &str) -> Result<(), ClientError> {
|
async fn try_upgrade_config(id: &str) -> Result<(), ClientError> {
|
||||||
if try_upgrade_v1_1_13_config(id).await? {
|
if try_upgrade_v1_1_13_config(id).await? {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
@@ -299,9 +278,6 @@ async fn try_upgrade_config(id: &str) -> Result<(), ClientError> {
|
|||||||
if try_upgrade_v1_1_33_config(id).await? {
|
if try_upgrade_v1_1_33_config(id).await? {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
if try_upgrade_v1_1_54_config(id).await? {
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
|
||||||
use clap::{crate_name, crate_version, Parser};
|
use clap::{crate_name, crate_version, Parser};
|
||||||
use nym_bin_common::logging::{maybe_print_banner, setup_tracing_logger};
|
use nym_bin_common::logging::{maybe_print_banner, setup_logging};
|
||||||
use nym_network_defaults::setup_env;
|
use nym_network_defaults::setup_env;
|
||||||
|
|
||||||
pub mod client;
|
pub mod client;
|
||||||
@@ -20,7 +20,7 @@ async fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
|
|||||||
if !args.no_banner {
|
if !args.no_banner {
|
||||||
maybe_print_banner(crate_name!(), crate_version!());
|
maybe_print_banner(crate_name!(), crate_version!());
|
||||||
}
|
}
|
||||||
setup_tracing_logger();
|
setup_logging();
|
||||||
|
|
||||||
if let Err(err) = commands::execute(args).await {
|
if let Err(err) = commands::execute(args).await {
|
||||||
log::error!("{err}");
|
log::error!("{err}");
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "nym-socks5-client"
|
name = "nym-socks5-client"
|
||||||
version = "1.1.55"
|
version = "1.1.52"
|
||||||
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"]
|
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"]
|
||||||
description = "A SOCKS5 localhost proxy that converts incoming messages to Sphinx and sends them to a Nym address"
|
description = "A SOCKS5 localhost proxy that converts incoming messages to Sphinx and sends them to a Nym address"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
@@ -27,7 +27,6 @@ zeroize = { workspace = true }
|
|||||||
nym-bin-common = { path = "../../common/bin-common", features = [
|
nym-bin-common = { path = "../../common/bin-common", features = [
|
||||||
"output_format",
|
"output_format",
|
||||||
"clap",
|
"clap",
|
||||||
"basic_tracing",
|
|
||||||
] }
|
] }
|
||||||
nym-client-core = { path = "../../common/client-core", features = [
|
nym-client-core = { path = "../../common/client-core", features = [
|
||||||
"fs-credentials-storage",
|
"fs-credentials-storage",
|
||||||
|
|||||||
@@ -87,6 +87,7 @@ impl From<Init> for OverrideConfig {
|
|||||||
use_anonymous_replies: init_config.use_reply_surbs,
|
use_anonymous_replies: init_config.use_reply_surbs,
|
||||||
fastmode: init_config.common_args.fastmode,
|
fastmode: init_config.common_args.fastmode,
|
||||||
no_cover: init_config.common_args.no_cover,
|
no_cover: init_config.common_args.no_cover,
|
||||||
|
geo_routing: None,
|
||||||
medium_toggle: false,
|
medium_toggle: false,
|
||||||
nyxd_urls: init_config.common_args.nyxd_urls,
|
nyxd_urls: init_config.common_args.nyxd_urls,
|
||||||
enabled_credentials_mode: init_config.common_args.enabled_credentials_mode,
|
enabled_credentials_mode: init_config.common_args.enabled_credentials_mode,
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ use crate::config::old_config_v1_1_20::ConfigV1_1_20;
|
|||||||
use crate::config::old_config_v1_1_20_2::ConfigV1_1_20_2;
|
use crate::config::old_config_v1_1_20_2::ConfigV1_1_20_2;
|
||||||
use crate::config::old_config_v1_1_30::ConfigV1_1_30;
|
use crate::config::old_config_v1_1_30::ConfigV1_1_30;
|
||||||
use crate::config::old_config_v1_1_33::ConfigV1_1_33;
|
use crate::config::old_config_v1_1_33::ConfigV1_1_33;
|
||||||
use crate::config::old_config_v1_1_54::ConfigV1_1_54;
|
|
||||||
use crate::config::{BaseClientConfig, Config};
|
use crate::config::{BaseClientConfig, Config};
|
||||||
use crate::error::Socks5ClientError;
|
use crate::error::Socks5ClientError;
|
||||||
use clap::CommandFactory;
|
use clap::CommandFactory;
|
||||||
@@ -17,7 +16,8 @@ use nym_bin_common::bin_info;
|
|||||||
use nym_bin_common::completions::{fig_generate, ArgShell};
|
use nym_bin_common::completions::{fig_generate, ArgShell};
|
||||||
use nym_client_core::cli_helpers::CliClient;
|
use nym_client_core::cli_helpers::CliClient;
|
||||||
use nym_client_core::client::base_client::storage::migration_helpers::v1_1_33;
|
use nym_client_core::client::base_client::storage::migration_helpers::v1_1_33;
|
||||||
use nym_client_core::config::ForgetMe;
|
use nym_client_core::client::topology_control::geo_aware_provider::CountryGroup;
|
||||||
|
use nym_client_core::config::{ForgetMe, GroupBy, TopologyStructure};
|
||||||
use nym_config::OptionalSet;
|
use nym_config::OptionalSet;
|
||||||
use nym_sphinx::addressing::Recipient;
|
use nym_sphinx::addressing::Recipient;
|
||||||
use nym_sphinx::params::{PacketSize, PacketType};
|
use nym_sphinx::params::{PacketSize, PacketType};
|
||||||
@@ -107,6 +107,7 @@ pub(crate) struct OverrideConfig {
|
|||||||
use_anonymous_replies: Option<bool>,
|
use_anonymous_replies: Option<bool>,
|
||||||
fastmode: bool,
|
fastmode: bool,
|
||||||
no_cover: bool,
|
no_cover: bool,
|
||||||
|
geo_routing: Option<CountryGroup>,
|
||||||
medium_toggle: bool,
|
medium_toggle: bool,
|
||||||
nyxd_urls: Option<Vec<url::Url>>,
|
nyxd_urls: Option<Vec<url::Url>>,
|
||||||
enabled_credentials_mode: Option<bool>,
|
enabled_credentials_mode: Option<bool>,
|
||||||
@@ -137,6 +138,21 @@ pub(crate) fn override_config(config: Config, args: OverrideConfig) -> Config {
|
|||||||
let secondary_packet_size = args.medium_toggle.then_some(PacketSize::ExtendedPacket16);
|
let secondary_packet_size = args.medium_toggle.then_some(PacketSize::ExtendedPacket16);
|
||||||
let no_per_hop_delays = args.medium_toggle;
|
let no_per_hop_delays = args.medium_toggle;
|
||||||
|
|
||||||
|
let topology_structure = if args.medium_toggle {
|
||||||
|
// Use the location of the network-requester
|
||||||
|
let address = config
|
||||||
|
.core
|
||||||
|
.socks5
|
||||||
|
.provider_mix_address
|
||||||
|
.parse()
|
||||||
|
.expect("failed to parse provider mix address");
|
||||||
|
TopologyStructure::GeoAware(GroupBy::NymAddress(address))
|
||||||
|
} else if let Some(code) = args.geo_routing {
|
||||||
|
TopologyStructure::GeoAware(GroupBy::CountryGroup(code))
|
||||||
|
} else {
|
||||||
|
TopologyStructure::default()
|
||||||
|
};
|
||||||
|
|
||||||
let packet_type = if args.outfox {
|
let packet_type = if args.outfox {
|
||||||
PacketType::Outfox
|
PacketType::Outfox
|
||||||
} else {
|
} else {
|
||||||
@@ -160,6 +176,10 @@ pub(crate) fn override_config(config: Config, args: OverrideConfig) -> Config {
|
|||||||
// NOTE: see comment above about the order of the other disble cover traffic config
|
// NOTE: see comment above about the order of the other disble cover traffic config
|
||||||
.with_base(BaseClientConfig::with_disabled_cover_traffic, args.no_cover)
|
.with_base(BaseClientConfig::with_disabled_cover_traffic, args.no_cover)
|
||||||
.with_base(BaseClientConfig::with_packet_type, packet_type)
|
.with_base(BaseClientConfig::with_packet_type, packet_type)
|
||||||
|
.with_base(
|
||||||
|
BaseClientConfig::with_topology_structure,
|
||||||
|
topology_structure,
|
||||||
|
)
|
||||||
.with_base(BaseClientConfig::with_forget_me, args.forget_me)
|
.with_base(BaseClientConfig::with_forget_me, args.forget_me)
|
||||||
.with_optional(Config::with_anonymous_replies, args.use_anonymous_replies)
|
.with_optional(Config::with_anonymous_replies, args.use_anonymous_replies)
|
||||||
.with_optional(Config::with_port, args.port)
|
.with_optional(Config::with_port, args.port)
|
||||||
@@ -205,16 +225,15 @@ async fn try_upgrade_v1_1_13_config(id: &str) -> Result<bool, Socks5ClientError>
|
|||||||
let old_paths = updated_step3.storage_paths.clone();
|
let old_paths = updated_step3.storage_paths.clone();
|
||||||
|
|
||||||
let updated_step4: ConfigV1_1_33 = updated_step3.into();
|
let updated_step4: ConfigV1_1_33 = updated_step3.into();
|
||||||
let updated_step5: ConfigV1_1_54 = updated_step4.try_into()?;
|
let updated = updated_step4.try_upgrade()?;
|
||||||
|
|
||||||
v1_1_33::migrate_gateway_details(
|
v1_1_33::migrate_gateway_details(
|
||||||
&old_paths.common_paths,
|
&old_paths.common_paths,
|
||||||
&updated_step5.storage_paths.common_paths,
|
&updated.storage_paths.common_paths,
|
||||||
Some(gateway_config),
|
Some(gateway_config),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let updated = updated_step5.try_upgrade()?;
|
|
||||||
updated.save_to_default_location()?;
|
updated.save_to_default_location()?;
|
||||||
Ok(true)
|
Ok(true)
|
||||||
}
|
}
|
||||||
@@ -236,16 +255,15 @@ async fn try_upgrade_v1_1_20_config(id: &str) -> Result<bool, Socks5ClientError>
|
|||||||
let old_paths = updated_step2.storage_paths.clone();
|
let old_paths = updated_step2.storage_paths.clone();
|
||||||
|
|
||||||
let updated_step3: ConfigV1_1_33 = updated_step2.into();
|
let updated_step3: ConfigV1_1_33 = updated_step2.into();
|
||||||
let updated_step4: ConfigV1_1_54 = updated_step3.try_into()?;
|
let updated = updated_step3.try_upgrade()?;
|
||||||
|
|
||||||
v1_1_33::migrate_gateway_details(
|
v1_1_33::migrate_gateway_details(
|
||||||
&old_paths.common_paths,
|
&old_paths.common_paths,
|
||||||
&updated_step4.storage_paths.common_paths,
|
&updated.storage_paths.common_paths,
|
||||||
Some(gateway_config),
|
Some(gateway_config),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let updated = updated_step4.try_upgrade()?;
|
|
||||||
updated.save_to_default_location()?;
|
updated.save_to_default_location()?;
|
||||||
Ok(true)
|
Ok(true)
|
||||||
}
|
}
|
||||||
@@ -264,17 +282,15 @@ async fn try_upgrade_v1_1_20_2_config(id: &str) -> Result<bool, Socks5ClientErro
|
|||||||
let old_paths = updated_step1.storage_paths.clone();
|
let old_paths = updated_step1.storage_paths.clone();
|
||||||
|
|
||||||
let updated_step2: ConfigV1_1_33 = updated_step1.into();
|
let updated_step2: ConfigV1_1_33 = updated_step1.into();
|
||||||
let updated_step3: ConfigV1_1_54 = updated_step2.try_into()?;
|
let updated = updated_step2.try_upgrade()?;
|
||||||
|
|
||||||
v1_1_33::migrate_gateway_details(
|
v1_1_33::migrate_gateway_details(
|
||||||
&old_paths.common_paths,
|
&old_paths.common_paths,
|
||||||
&updated_step3.storage_paths.common_paths,
|
&updated.storage_paths.common_paths,
|
||||||
Some(gateway_config),
|
Some(gateway_config),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let updated = updated_step3.try_upgrade()?;
|
|
||||||
|
|
||||||
updated.save_to_default_location()?;
|
updated.save_to_default_location()?;
|
||||||
Ok(true)
|
Ok(true)
|
||||||
}
|
}
|
||||||
@@ -292,16 +308,15 @@ async fn try_upgrade_v1_1_30_config(id: &str) -> Result<bool, Socks5ClientError>
|
|||||||
let old_paths = old_config.storage_paths.clone();
|
let old_paths = old_config.storage_paths.clone();
|
||||||
|
|
||||||
let updated_step1: ConfigV1_1_33 = old_config.into();
|
let updated_step1: ConfigV1_1_33 = old_config.into();
|
||||||
let updated_step2: ConfigV1_1_54 = updated_step1.try_into()?;
|
let updated = updated_step1.try_upgrade()?;
|
||||||
|
|
||||||
v1_1_33::migrate_gateway_details(
|
v1_1_33::migrate_gateway_details(
|
||||||
&old_paths.common_paths,
|
&old_paths.common_paths,
|
||||||
&updated_step2.storage_paths.common_paths,
|
&updated.storage_paths.common_paths,
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let updated = updated_step2.try_upgrade()?;
|
|
||||||
updated.save_to_default_location()?;
|
updated.save_to_default_location()?;
|
||||||
Ok(true)
|
Ok(true)
|
||||||
}
|
}
|
||||||
@@ -318,32 +333,15 @@ async fn try_upgrade_v1_1_33_config(id: &str) -> Result<bool, Socks5ClientError>
|
|||||||
|
|
||||||
let old_paths = old_config.storage_paths.clone();
|
let old_paths = old_config.storage_paths.clone();
|
||||||
|
|
||||||
let updated_step1: ConfigV1_1_54 = old_config.try_into()?;
|
let updated = old_config.try_upgrade()?;
|
||||||
|
|
||||||
v1_1_33::migrate_gateway_details(
|
v1_1_33::migrate_gateway_details(
|
||||||
&old_paths.common_paths,
|
&old_paths.common_paths,
|
||||||
&updated_step1.storage_paths.common_paths,
|
&updated.storage_paths.common_paths,
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let updated = updated_step1.try_upgrade()?;
|
|
||||||
updated.save_to_default_location()?;
|
|
||||||
Ok(true)
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn try_upgrade_v1_1_54_config(id: &str) -> Result<bool, Socks5ClientError> {
|
|
||||||
// explicitly load it as v1.1.54 (which is incompatible with the current one, i.e. +1.1.55)
|
|
||||||
let Ok(old_config) = ConfigV1_1_54::read_from_default_path(id) else {
|
|
||||||
// if we failed to load it, there might have been nothing to upgrade
|
|
||||||
// or maybe it was an even older file. in either way. just ignore it and carry on with our day
|
|
||||||
return Ok(false);
|
|
||||||
};
|
|
||||||
info!("It seems the client is using <= v1.1.54 config template.");
|
|
||||||
info!("It is going to get updated to the current specification.");
|
|
||||||
|
|
||||||
let updated = old_config.try_upgrade()?;
|
|
||||||
|
|
||||||
updated.save_to_default_location()?;
|
updated.save_to_default_location()?;
|
||||||
Ok(true)
|
Ok(true)
|
||||||
}
|
}
|
||||||
@@ -364,9 +362,6 @@ async fn try_upgrade_config(id: &str) -> Result<(), Socks5ClientError> {
|
|||||||
if try_upgrade_v1_1_33_config(id).await? {
|
if try_upgrade_v1_1_33_config(id).await? {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
if try_upgrade_v1_1_54_config(id).await? {
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ use crate::commands::{override_config, OverrideConfig};
|
|||||||
use clap::Args;
|
use clap::Args;
|
||||||
use nym_client_core::cli_helpers::client_run::CommonClientRunArgs;
|
use nym_client_core::cli_helpers::client_run::CommonClientRunArgs;
|
||||||
use nym_client_core::client::base_client::storage::OnDiskPersistent;
|
use nym_client_core::client::base_client::storage::OnDiskPersistent;
|
||||||
|
use nym_client_core::client::topology_control::geo_aware_provider::CountryGroup;
|
||||||
use nym_socks5_client_core::NymClient;
|
use nym_socks5_client_core::NymClient;
|
||||||
use nym_sphinx::addressing::clients::Recipient;
|
use nym_sphinx::addressing::clients::Recipient;
|
||||||
use std::net::IpAddr;
|
use std::net::IpAddr;
|
||||||
@@ -36,6 +37,10 @@ pub(crate) struct Run {
|
|||||||
#[clap(long)]
|
#[clap(long)]
|
||||||
host: Option<IpAddr>,
|
host: Option<IpAddr>,
|
||||||
|
|
||||||
|
/// Set geo-aware mixnode selection when sending mixnet traffic, for experiments only.
|
||||||
|
#[clap(long, hide = true, value_parser = validate_country_group, group="routing")]
|
||||||
|
geo_routing: Option<CountryGroup>,
|
||||||
|
|
||||||
/// Enable medium mixnet traffic, for experiments only.
|
/// Enable medium mixnet traffic, for experiments only.
|
||||||
/// This includes things like disabling cover traffic, no per hop delays, etc.
|
/// This includes things like disabling cover traffic, no per hop delays, etc.
|
||||||
#[clap(long, hide = true)]
|
#[clap(long, hide = true)]
|
||||||
@@ -54,6 +59,7 @@ impl From<Run> for OverrideConfig {
|
|||||||
use_anonymous_replies: run_config.use_anonymous_replies,
|
use_anonymous_replies: run_config.use_anonymous_replies,
|
||||||
fastmode: run_config.common_args.fastmode,
|
fastmode: run_config.common_args.fastmode,
|
||||||
no_cover: run_config.common_args.no_cover,
|
no_cover: run_config.common_args.no_cover,
|
||||||
|
geo_routing: run_config.geo_routing,
|
||||||
medium_toggle: run_config.medium_toggle,
|
medium_toggle: run_config.medium_toggle,
|
||||||
nyxd_urls: run_config.common_args.nyxd_urls,
|
nyxd_urls: run_config.common_args.nyxd_urls,
|
||||||
enabled_credentials_mode: run_config.common_args.enabled_credentials_mode,
|
enabled_credentials_mode: run_config.common_args.enabled_credentials_mode,
|
||||||
@@ -64,6 +70,13 @@ impl From<Run> for OverrideConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn validate_country_group(s: &str) -> Result<CountryGroup, String> {
|
||||||
|
match s.parse() {
|
||||||
|
Ok(cg) => Ok(cg),
|
||||||
|
Err(_) => Err(format!("failed to parse country group: {}", s)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) async fn execute(args: Run) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
pub(crate) async fn execute(args: Run) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
||||||
eprintln!("Starting client {}...", args.common_args.id);
|
eprintln!("Starting client {}...", args.common_args.id);
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,6 @@ pub mod old_config_v1_1_20;
|
|||||||
pub mod old_config_v1_1_20_2;
|
pub mod old_config_v1_1_20_2;
|
||||||
pub mod old_config_v1_1_30;
|
pub mod old_config_v1_1_30;
|
||||||
pub mod old_config_v1_1_33;
|
pub mod old_config_v1_1_33;
|
||||||
pub mod old_config_v1_1_54;
|
|
||||||
mod persistence;
|
mod persistence;
|
||||||
mod template;
|
mod template;
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
use crate::config::{default_config_filepath, SocksClientPaths};
|
use crate::config::{default_config_filepath, Config, SocksClientPaths};
|
||||||
use crate::error::Socks5ClientError;
|
use crate::error::Socks5ClientError;
|
||||||
use nym_bin_common::logging::LoggingSettings;
|
use nym_bin_common::logging::LoggingSettings;
|
||||||
use nym_client_core::config::disk_persistence::old_v1_1_33::CommonClientPathsV1_1_33;
|
use nym_client_core::config::disk_persistence::old_v1_1_33::CommonClientPathsV1_1_33;
|
||||||
@@ -11,8 +11,6 @@ use serde::{Deserialize, Serialize};
|
|||||||
use std::io;
|
use std::io;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
use super::old_config_v1_1_54::ConfigV1_1_54;
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
|
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
|
||||||
pub struct SocksClientPathsV1_1_33 {
|
pub struct SocksClientPathsV1_1_33 {
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
@@ -30,20 +28,6 @@ pub struct ConfigV1_1_33 {
|
|||||||
pub logging: LoggingSettings,
|
pub logging: LoggingSettings,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryFrom<ConfigV1_1_33> for ConfigV1_1_54 {
|
|
||||||
type Error = Socks5ClientError;
|
|
||||||
|
|
||||||
fn try_from(value: ConfigV1_1_33) -> Result<Self, Self::Error> {
|
|
||||||
Ok(ConfigV1_1_54 {
|
|
||||||
core: value.core.into(),
|
|
||||||
storage_paths: SocksClientPaths {
|
|
||||||
common_paths: value.storage_paths.common_paths.upgrade_default()?,
|
|
||||||
},
|
|
||||||
logging: value.logging,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ConfigV1_1_33 {
|
impl ConfigV1_1_33 {
|
||||||
pub fn read_from_toml_file<P: AsRef<Path>>(path: P) -> io::Result<Self> {
|
pub fn read_from_toml_file<P: AsRef<Path>>(path: P) -> io::Result<Self> {
|
||||||
read_config_from_toml_file(path)
|
read_config_from_toml_file(path)
|
||||||
@@ -52,4 +36,14 @@ impl ConfigV1_1_33 {
|
|||||||
pub fn read_from_default_path<P: AsRef<Path>>(id: P) -> io::Result<Self> {
|
pub fn read_from_default_path<P: AsRef<Path>>(id: P) -> io::Result<Self> {
|
||||||
Self::read_from_toml_file(default_config_filepath(id))
|
Self::read_from_toml_file(default_config_filepath(id))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn try_upgrade(self) -> Result<Config, Socks5ClientError> {
|
||||||
|
Ok(Config {
|
||||||
|
core: self.core.into(),
|
||||||
|
storage_paths: SocksClientPaths {
|
||||||
|
common_paths: self.storage_paths.common_paths.upgrade_default()?,
|
||||||
|
},
|
||||||
|
logging: self.logging,
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,39 +0,0 @@
|
|||||||
use std::{io, path::Path};
|
|
||||||
|
|
||||||
use nym_bin_common::logging::LoggingSettings;
|
|
||||||
use nym_config::read_config_from_toml_file;
|
|
||||||
use nym_socks5_client_core::config::old_config_v1_1_54::ConfigV1_1_54 as CoreConfigV1_1_54;
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
use crate::config::Config;
|
|
||||||
use crate::error::Socks5ClientError;
|
|
||||||
|
|
||||||
use super::{default_config_filepath, SocksClientPaths};
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
|
|
||||||
#[serde(deny_unknown_fields)]
|
|
||||||
pub struct ConfigV1_1_54 {
|
|
||||||
pub core: CoreConfigV1_1_54,
|
|
||||||
|
|
||||||
pub storage_paths: SocksClientPaths,
|
|
||||||
|
|
||||||
pub logging: LoggingSettings,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ConfigV1_1_54 {
|
|
||||||
pub fn read_from_toml_file<P: AsRef<Path>>(path: P) -> io::Result<Self> {
|
|
||||||
read_config_from_toml_file(path)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn read_from_default_path<P: AsRef<Path>>(id: P) -> io::Result<Self> {
|
|
||||||
Self::read_from_toml_file(default_config_filepath(id))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn try_upgrade(self) -> Result<Config, Socks5ClientError> {
|
|
||||||
Ok(Config {
|
|
||||||
core: self.core.into(),
|
|
||||||
storage_paths: self.storage_paths,
|
|
||||||
logging: self.logging,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -98,6 +98,10 @@ send_anonymously = {{ core.socks5.send_anonymously }}
|
|||||||
|
|
||||||
[core.debug]
|
[core.debug]
|
||||||
|
|
||||||
|
[core.debug.traffic]
|
||||||
|
average_packet_delay = '{{ core.debug.traffic.average_packet_delay }}'
|
||||||
|
message_sending_average_delay = '{{ core.debug.traffic.message_sending_average_delay }}'
|
||||||
|
|
||||||
[core.debug.acknowledgements]
|
[core.debug.acknowledgements]
|
||||||
average_ack_delay = '{{ core.debug.acknowledgements.average_ack_delay }}'
|
average_ack_delay = '{{ core.debug.acknowledgements.average_ack_delay }}'
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
|
||||||
use clap::{crate_name, crate_version, Parser};
|
use clap::{crate_name, crate_version, Parser};
|
||||||
use nym_bin_common::logging::{maybe_print_banner, setup_tracing_logger};
|
use nym_bin_common::logging::{maybe_print_banner, setup_logging};
|
||||||
use nym_network_defaults::setup_env;
|
use nym_network_defaults::setup_env;
|
||||||
|
|
||||||
mod commands;
|
mod commands;
|
||||||
@@ -19,7 +19,7 @@ async fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
|
|||||||
if !args.no_banner {
|
if !args.no_banner {
|
||||||
maybe_print_banner(crate_name!(), crate_version!());
|
maybe_print_banner(crate_name!(), crate_version!());
|
||||||
}
|
}
|
||||||
setup_tracing_logger();
|
setup_logging();
|
||||||
|
|
||||||
if let Err(err) = commands::execute(args).await {
|
if let Err(err) = commands::execute(args).await {
|
||||||
log::error!("{err}");
|
log::error!("{err}");
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ use std::{fmt, ops::Deref, str::FromStr};
|
|||||||
#[cfg(feature = "verify")]
|
#[cfg(feature = "verify")]
|
||||||
use hmac::{Hmac, Mac};
|
use hmac::{Hmac, Mac};
|
||||||
#[cfg(feature = "verify")]
|
#[cfg(feature = "verify")]
|
||||||
use nym_crypto::asymmetric::x25519::{PrivateKey, PublicKey};
|
use nym_crypto::asymmetric::encryption::{PrivateKey, PublicKey};
|
||||||
#[cfg(feature = "verify")]
|
#[cfg(feature = "verify")]
|
||||||
use sha2::Sha256;
|
use sha2::Sha256;
|
||||||
|
|
||||||
@@ -190,15 +190,15 @@ impl<'de> Deserialize<'de> for ClientMac {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use nym_crypto::asymmetric::x25519;
|
use nym_crypto::asymmetric::encryption;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(feature = "verify")]
|
#[cfg(feature = "verify")]
|
||||||
fn client_request_roundtrip() {
|
fn client_request_roundtrip() {
|
||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::thread_rng();
|
||||||
|
|
||||||
let gateway_key_pair = x25519::KeyPair::new(&mut rng);
|
let gateway_key_pair = encryption::KeyPair::new(&mut rng);
|
||||||
let client_key_pair = x25519::KeyPair::new(&mut rng);
|
let client_key_pair = encryption::KeyPair::new(&mut rng);
|
||||||
|
|
||||||
let nonce = 1234567890;
|
let nonce = 1234567890;
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ use std::{fmt, ops::Deref, str::FromStr};
|
|||||||
#[cfg(feature = "verify")]
|
#[cfg(feature = "verify")]
|
||||||
use hmac::{Hmac, Mac};
|
use hmac::{Hmac, Mac};
|
||||||
#[cfg(feature = "verify")]
|
#[cfg(feature = "verify")]
|
||||||
use nym_crypto::asymmetric::x25519::{PrivateKey, PublicKey};
|
use nym_crypto::asymmetric::encryption::{PrivateKey, PublicKey};
|
||||||
#[cfg(feature = "verify")]
|
#[cfg(feature = "verify")]
|
||||||
use sha2::Sha256;
|
use sha2::Sha256;
|
||||||
|
|
||||||
@@ -199,15 +199,15 @@ impl<'de> Deserialize<'de> for ClientMac {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use nym_crypto::asymmetric::x25519;
|
use nym_crypto::asymmetric::encryption;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(feature = "verify")]
|
#[cfg(feature = "verify")]
|
||||||
fn client_request_roundtrip() {
|
fn client_request_roundtrip() {
|
||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::thread_rng();
|
||||||
|
|
||||||
let gateway_key_pair = x25519::KeyPair::new(&mut rng);
|
let gateway_key_pair = encryption::KeyPair::new(&mut rng);
|
||||||
let client_key_pair = x25519::KeyPair::new(&mut rng);
|
let client_key_pair = encryption::KeyPair::new(&mut rng);
|
||||||
|
|
||||||
let nonce = 1234567890;
|
let nonce = 1234567890;
|
||||||
|
|
||||||
|
|||||||
@@ -340,7 +340,7 @@ mod tests {
|
|||||||
use std::{net::IpAddr, str::FromStr};
|
use std::{net::IpAddr, str::FromStr};
|
||||||
|
|
||||||
use nym_credentials_interface::CredentialSpendingData;
|
use nym_credentials_interface::CredentialSpendingData;
|
||||||
use nym_crypto::asymmetric::x25519::PrivateKey;
|
use nym_crypto::asymmetric::encryption::PrivateKey;
|
||||||
use nym_sphinx::addressing::Recipient;
|
use nym_sphinx::addressing::Recipient;
|
||||||
use nym_wireguard_types::PeerPublicKey;
|
use nym_wireguard_types::PeerPublicKey;
|
||||||
use x25519_dalek::PublicKey;
|
use x25519_dalek::PublicKey;
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ use std::{fmt, ops::Deref, str::FromStr};
|
|||||||
#[cfg(feature = "verify")]
|
#[cfg(feature = "verify")]
|
||||||
use hmac::{Hmac, Mac};
|
use hmac::{Hmac, Mac};
|
||||||
#[cfg(feature = "verify")]
|
#[cfg(feature = "verify")]
|
||||||
use nym_crypto::asymmetric::x25519::{PrivateKey, PublicKey};
|
use nym_crypto::asymmetric::encryption::{PrivateKey, PublicKey};
|
||||||
#[cfg(feature = "verify")]
|
#[cfg(feature = "verify")]
|
||||||
use sha2::Sha256;
|
use sha2::Sha256;
|
||||||
|
|
||||||
@@ -199,15 +199,15 @@ impl<'de> Deserialize<'de> for ClientMac {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use nym_crypto::asymmetric::x25519;
|
use nym_crypto::asymmetric::encryption;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(feature = "verify")]
|
#[cfg(feature = "verify")]
|
||||||
fn client_request_roundtrip() {
|
fn client_request_roundtrip() {
|
||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::thread_rng();
|
||||||
|
|
||||||
let gateway_key_pair = x25519::KeyPair::new(&mut rng);
|
let gateway_key_pair = encryption::KeyPair::new(&mut rng);
|
||||||
let client_key_pair = x25519::KeyPair::new(&mut rng);
|
let client_key_pair = encryption::KeyPair::new(&mut rng);
|
||||||
|
|
||||||
let nonce = 1234567890;
|
let nonce = 1234567890;
|
||||||
|
|
||||||
|
|||||||
@@ -306,7 +306,7 @@ mod tests {
|
|||||||
};
|
};
|
||||||
|
|
||||||
use nym_credentials_interface::CredentialSpendingData;
|
use nym_credentials_interface::CredentialSpendingData;
|
||||||
use nym_crypto::asymmetric::x25519::PrivateKey;
|
use nym_crypto::asymmetric::encryption::PrivateKey;
|
||||||
use nym_sphinx::addressing::Recipient;
|
use nym_sphinx::addressing::Recipient;
|
||||||
use nym_wireguard_types::PeerPublicKey;
|
use nym_wireguard_types::PeerPublicKey;
|
||||||
use x25519_dalek::PublicKey;
|
use x25519_dalek::PublicKey;
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ use std::{fmt, ops::Deref, str::FromStr};
|
|||||||
#[cfg(feature = "verify")]
|
#[cfg(feature = "verify")]
|
||||||
use hmac::{Hmac, Mac};
|
use hmac::{Hmac, Mac};
|
||||||
#[cfg(feature = "verify")]
|
#[cfg(feature = "verify")]
|
||||||
use nym_crypto::asymmetric::x25519::{PrivateKey, PublicKey};
|
use nym_crypto::asymmetric::encryption::{PrivateKey, PublicKey};
|
||||||
#[cfg(feature = "verify")]
|
#[cfg(feature = "verify")]
|
||||||
use sha2::Sha256;
|
use sha2::Sha256;
|
||||||
|
|
||||||
@@ -251,7 +251,7 @@ impl<'de> Deserialize<'de> for ClientMac {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use nym_crypto::asymmetric::x25519;
|
use nym_crypto::asymmetric::encryption;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn create_ip_pair() {
|
fn create_ip_pair() {
|
||||||
@@ -266,8 +266,8 @@ mod tests {
|
|||||||
fn client_request_roundtrip() {
|
fn client_request_roundtrip() {
|
||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::thread_rng();
|
||||||
|
|
||||||
let gateway_key_pair = x25519::KeyPair::new(&mut rng);
|
let gateway_key_pair = encryption::KeyPair::new(&mut rng);
|
||||||
let client_key_pair = x25519::KeyPair::new(&mut rng);
|
let client_key_pair = encryption::KeyPair::new(&mut rng);
|
||||||
|
|
||||||
let nonce = 1234567890;
|
let nonce = 1234567890;
|
||||||
|
|
||||||
|
|||||||
@@ -230,7 +230,7 @@ mod tests {
|
|||||||
};
|
};
|
||||||
|
|
||||||
use nym_credentials_interface::CredentialSpendingData;
|
use nym_credentials_interface::CredentialSpendingData;
|
||||||
use nym_crypto::asymmetric::x25519::PrivateKey;
|
use nym_crypto::asymmetric::encryption::PrivateKey;
|
||||||
use nym_sphinx::addressing::Recipient;
|
use nym_sphinx::addressing::Recipient;
|
||||||
use nym_wireguard_types::PeerPublicKey;
|
use nym_wireguard_types::PeerPublicKey;
|
||||||
use x25519_dalek::PublicKey;
|
use x25519_dalek::PublicKey;
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ use std::{fmt, ops::Deref, str::FromStr};
|
|||||||
#[cfg(feature = "verify")]
|
#[cfg(feature = "verify")]
|
||||||
use hmac::{Hmac, Mac};
|
use hmac::{Hmac, Mac};
|
||||||
#[cfg(feature = "verify")]
|
#[cfg(feature = "verify")]
|
||||||
use nym_crypto::asymmetric::x25519::{PrivateKey, PublicKey};
|
use nym_crypto::asymmetric::encryption::{PrivateKey, PublicKey};
|
||||||
#[cfg(feature = "verify")]
|
#[cfg(feature = "verify")]
|
||||||
use sha2::Sha256;
|
use sha2::Sha256;
|
||||||
|
|
||||||
@@ -251,7 +251,7 @@ impl<'de> Deserialize<'de> for ClientMac {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use nym_crypto::asymmetric::x25519;
|
use nym_crypto::asymmetric::encryption;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn create_ip_pair() {
|
fn create_ip_pair() {
|
||||||
@@ -266,8 +266,8 @@ mod tests {
|
|||||||
fn client_request_roundtrip() {
|
fn client_request_roundtrip() {
|
||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::thread_rng();
|
||||||
|
|
||||||
let gateway_key_pair = x25519::KeyPair::new(&mut rng);
|
let gateway_key_pair = encryption::KeyPair::new(&mut rng);
|
||||||
let client_key_pair = x25519::KeyPair::new(&mut rng);
|
let client_key_pair = encryption::KeyPair::new(&mut rng);
|
||||||
|
|
||||||
let nonce = 1234567890;
|
let nonce = 1234567890;
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ use nym_credentials::ecash::bandwidth::IssuanceTicketBook;
|
|||||||
use nym_credentials::ecash::utils::obtain_aggregate_wallet;
|
use nym_credentials::ecash::utils::obtain_aggregate_wallet;
|
||||||
use nym_credentials::IssuedTicketBook;
|
use nym_credentials::IssuedTicketBook;
|
||||||
use nym_credentials_interface::TicketType;
|
use nym_credentials_interface::TicketType;
|
||||||
use nym_crypto::asymmetric::ed25519;
|
use nym_crypto::asymmetric::identity;
|
||||||
use nym_ecash_time::{ecash_default_expiration_date, Date};
|
use nym_ecash_time::{ecash_default_expiration_date, Date};
|
||||||
use nym_validator_client::coconut::all_ecash_api_clients;
|
use nym_validator_client::coconut::all_ecash_api_clients;
|
||||||
use nym_validator_client::nym_api::EpochId;
|
use nym_validator_client::nym_api::EpochId;
|
||||||
@@ -31,7 +31,7 @@ where
|
|||||||
C: EcashSigningClient + EcashQueryClient + Sync,
|
C: EcashSigningClient + EcashQueryClient + Sync,
|
||||||
{
|
{
|
||||||
let mut rng = OsRng;
|
let mut rng = OsRng;
|
||||||
let signing_key = ed25519::PrivateKey::new(&mut rng);
|
let signing_key = identity::PrivateKey::new(&mut rng);
|
||||||
let expiration = expiration.unwrap_or_else(ecash_default_expiration_date);
|
let expiration = expiration.unwrap_or_else(ecash_default_expiration_date);
|
||||||
|
|
||||||
let deposit_amount = client.get_required_deposit_amount().await?;
|
let deposit_amount = client.get_required_deposit_amount().await?;
|
||||||
|
|||||||
@@ -4,8 +4,8 @@
|
|||||||
use nym_credential_storage::error::StorageError;
|
use nym_credential_storage::error::StorageError;
|
||||||
use nym_credentials::error::Error as CredentialsError;
|
use nym_credentials::error::Error as CredentialsError;
|
||||||
use nym_credentials_interface::CompactEcashError;
|
use nym_credentials_interface::CompactEcashError;
|
||||||
use nym_crypto::asymmetric::ed25519::Ed25519RecoveryError;
|
use nym_crypto::asymmetric::encryption::KeyRecoveryError;
|
||||||
use nym_crypto::asymmetric::x25519::KeyRecoveryError;
|
use nym_crypto::asymmetric::identity::Ed25519RecoveryError;
|
||||||
use nym_validator_client::coconut::EcashApiError;
|
use nym_validator_client::coconut::EcashApiError;
|
||||||
use nym_validator_client::error::ValidatorClientError;
|
use nym_validator_client::error::ValidatorClientError;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ clap_complete = { workspace = true, optional = true }
|
|||||||
clap_complete_fig = { workspace = true, optional = true }
|
clap_complete_fig = { workspace = true, optional = true }
|
||||||
const-str = { workspace = true }
|
const-str = { workspace = true }
|
||||||
log = { workspace = true }
|
log = { workspace = true }
|
||||||
|
pretty_env_logger = { workspace = true }
|
||||||
schemars = { workspace = true, features = ["preserve_order"], optional = true }
|
schemars = { workspace = true, features = ["preserve_order"], optional = true }
|
||||||
serde = { workspace = true, features = ["derive"] }
|
serde = { workspace = true, features = ["derive"] }
|
||||||
serde_json = { workspace = true, optional = true }
|
serde_json = { workspace = true, optional = true }
|
||||||
|
|||||||
@@ -21,6 +21,29 @@ pub struct LoggingSettings {
|
|||||||
// well, we need to implement something here at some point...
|
// well, we need to implement something here at some point...
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// I'd argue we should start transitioning from `log` to `tracing`
|
||||||
|
pub fn setup_logging() {
|
||||||
|
let mut log_builder = pretty_env_logger::formatted_timed_builder();
|
||||||
|
if let Ok(s) = ::std::env::var("RUST_LOG") {
|
||||||
|
log_builder.parse_filters(&s);
|
||||||
|
} else {
|
||||||
|
// default to 'Info'
|
||||||
|
log_builder.filter(None, log::LevelFilter::Info);
|
||||||
|
}
|
||||||
|
|
||||||
|
log_builder
|
||||||
|
.filter_module("hyper", log::LevelFilter::Warn)
|
||||||
|
.filter_module("tokio_reactor", log::LevelFilter::Warn)
|
||||||
|
.filter_module("reqwest", log::LevelFilter::Warn)
|
||||||
|
.filter_module("mio", log::LevelFilter::Warn)
|
||||||
|
.filter_module("want", log::LevelFilter::Warn)
|
||||||
|
.filter_module("tungstenite", log::LevelFilter::Warn)
|
||||||
|
.filter_module("tokio_tungstenite", log::LevelFilter::Warn)
|
||||||
|
.filter_module("handlebars", log::LevelFilter::Warn)
|
||||||
|
.filter_module("sled", log::LevelFilter::Warn)
|
||||||
|
.init();
|
||||||
|
}
|
||||||
|
|
||||||
// don't call init so that we could attach additional layers
|
// don't call init so that we could attach additional layers
|
||||||
#[cfg(feature = "basic_tracing")]
|
#[cfg(feature = "basic_tracing")]
|
||||||
pub fn build_tracing_logger() -> impl tracing_subscriber::layer::SubscriberExt {
|
pub fn build_tracing_logger() -> impl tracing_subscriber::layer::SubscriberExt {
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ license.workspace = true
|
|||||||
async-trait = { workspace = true }
|
async-trait = { workspace = true }
|
||||||
base64 = { workspace = true }
|
base64 = { workspace = true }
|
||||||
bs58 = { workspace = true }
|
bs58 = { workspace = true }
|
||||||
|
cfg-if = { workspace = true }
|
||||||
clap = { workspace = true, optional = true }
|
clap = { workspace = true, optional = true }
|
||||||
comfy-table = { workspace = true, optional = true }
|
comfy-table = { workspace = true, optional = true }
|
||||||
futures = { workspace = true }
|
futures = { workspace = true }
|
||||||
@@ -23,18 +24,20 @@ serde = { workspace = true, features = ["derive"] }
|
|||||||
serde_json = { workspace = true }
|
serde_json = { workspace = true }
|
||||||
sha2 = { workspace = true }
|
sha2 = { workspace = true }
|
||||||
si-scale = { workspace = true }
|
si-scale = { workspace = true }
|
||||||
|
tap = { workspace = true }
|
||||||
thiserror = { workspace = true }
|
thiserror = { workspace = true }
|
||||||
url = { workspace = true, features = ["serde"] }
|
url = { workspace = true, features = ["serde"] }
|
||||||
tokio = { workspace = true, features = ["macros"] }
|
tokio = { workspace = true, features = ["macros"] }
|
||||||
time = { workspace = true }
|
time = { workspace = true }
|
||||||
tracing = { workspace = true }
|
|
||||||
zeroize = { workspace = true }
|
zeroize = { workspace = true }
|
||||||
|
|
||||||
# internal
|
# internal
|
||||||
nym-id = { path = "../nym-id" }
|
nym-id = { path = "../nym-id" }
|
||||||
nym-bandwidth-controller = { path = "../bandwidth-controller" }
|
nym-bandwidth-controller = { path = "../bandwidth-controller" }
|
||||||
nym-config = { path = "../config" }
|
nym-config = { path = "../config" }
|
||||||
|
nym-country-group = { path = "../country-group" }
|
||||||
nym-crypto = { path = "../crypto" }
|
nym-crypto = { path = "../crypto" }
|
||||||
|
nym-explorer-client = { path = "../../explorer-api/explorer-client" }
|
||||||
nym-gateway-client = { path = "../client-libs/gateway-client" }
|
nym-gateway-client = { path = "../client-libs/gateway-client" }
|
||||||
nym-gateway-requests = { path = "../gateway-requests" }
|
nym-gateway-requests = { path = "../gateway-requests" }
|
||||||
nym-http-api-client = { path = "../http-api-client" }
|
nym-http-api-client = { path = "../http-api-client" }
|
||||||
|
|||||||
@@ -14,12 +14,12 @@ url = { workspace = true, features = ["serde"] }
|
|||||||
|
|
||||||
nym-config = { path = "../../config" }
|
nym-config = { path = "../../config" }
|
||||||
|
|
||||||
|
nym-country-group = { path = "../../country-group" }
|
||||||
nym-pemstore = { path = "../../pemstore", optional = true }
|
nym-pemstore = { path = "../../pemstore", optional = true }
|
||||||
|
|
||||||
# those are pulling so many deps T.T
|
# those are pulling so many deps T.T
|
||||||
nym-sphinx-params = { path = "../../nymsphinx/params" }
|
nym-sphinx-params = { path = "../../nymsphinx/params" }
|
||||||
nym-sphinx-addressing = { path = "../../nymsphinx/addressing" }
|
nym-sphinx-addressing = { path = "../../nymsphinx/addressing" }
|
||||||
nym-statistics-common = { path = "../../statistics" }
|
|
||||||
|
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ use nym_config::defaults::NymNetworkDetails;
|
|||||||
use nym_config::serde_helpers::{de_maybe_stringified, ser_maybe_stringified};
|
use nym_config::serde_helpers::{de_maybe_stringified, ser_maybe_stringified};
|
||||||
use nym_sphinx_addressing::Recipient;
|
use nym_sphinx_addressing::Recipient;
|
||||||
use nym_sphinx_params::{PacketSize, PacketType};
|
use nym_sphinx_params::{PacketSize, PacketType};
|
||||||
use nym_statistics_common::types::SessionType;
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
@@ -23,7 +22,7 @@ const DEFAULT_ACK_WAIT_MULTIPLIER: f64 = 1.5;
|
|||||||
const DEFAULT_ACK_WAIT_ADDITION: Duration = Duration::from_millis(1_500);
|
const DEFAULT_ACK_WAIT_ADDITION: Duration = Duration::from_millis(1_500);
|
||||||
const DEFAULT_LOOP_COVER_STREAM_AVERAGE_DELAY: Duration = Duration::from_millis(200);
|
const DEFAULT_LOOP_COVER_STREAM_AVERAGE_DELAY: Duration = Duration::from_millis(200);
|
||||||
const DEFAULT_MESSAGE_STREAM_AVERAGE_DELAY: Duration = Duration::from_millis(20);
|
const DEFAULT_MESSAGE_STREAM_AVERAGE_DELAY: Duration = Duration::from_millis(20);
|
||||||
const DEFAULT_AVERAGE_PACKET_DELAY: Duration = Duration::from_millis(15);
|
const DEFAULT_AVERAGE_PACKET_DELAY: Duration = Duration::from_millis(50);
|
||||||
const DEFAULT_TOPOLOGY_REFRESH_RATE: Duration = Duration::from_secs(5 * 60); // every 5min
|
const DEFAULT_TOPOLOGY_REFRESH_RATE: Duration = Duration::from_secs(5 * 60); // every 5min
|
||||||
const DEFAULT_TOPOLOGY_RESOLUTION_TIMEOUT: Duration = Duration::from_millis(5_000);
|
const DEFAULT_TOPOLOGY_RESOLUTION_TIMEOUT: Duration = Duration::from_millis(5_000);
|
||||||
|
|
||||||
@@ -66,10 +65,11 @@ const DEFAULT_MAXIMUM_REPLY_KEY_AGE: Duration = Duration::from_secs(24 * 60 * 60
|
|||||||
|
|
||||||
// stats reporting related
|
// stats reporting related
|
||||||
|
|
||||||
/// Time interval between reporting statistics to the given provider if it exists
|
/// Time interval between reporting statistics to the given provider if it exist
|
||||||
const STATS_REPORT_INTERVAL_SECS: Duration = Duration::from_secs(300);
|
const STATS_REPORT_INTERVAL_SECS: Duration = Duration::from_secs(300);
|
||||||
|
|
||||||
use crate::error::InvalidTrafficModeFailure;
|
use crate::error::InvalidTrafficModeFailure;
|
||||||
|
pub use nym_country_group::CountryGroup;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
|
#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
|
||||||
#[serde(deny_unknown_fields)]
|
#[serde(deny_unknown_fields)]
|
||||||
@@ -258,6 +258,15 @@ impl Config {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn with_topology_structure(mut self, topology_structure: TopologyStructure) -> Self {
|
||||||
|
self.set_topology_structure(topology_structure);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_topology_structure(&mut self, topology_structure: TopologyStructure) {
|
||||||
|
self.debug.topology.topology_structure = topology_structure;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn with_no_per_hop_delays(mut self, no_per_hop_delays: bool) -> Self {
|
pub fn with_no_per_hop_delays(mut self, no_per_hop_delays: bool) -> Self {
|
||||||
if no_per_hop_delays {
|
if no_per_hop_delays {
|
||||||
self.set_no_per_hop_delays()
|
self.set_no_per_hop_delays()
|
||||||
@@ -376,12 +385,14 @@ pub struct Traffic {
|
|||||||
/// sent packet is going to be delayed at any given mix node.
|
/// sent packet is going to be delayed at any given mix node.
|
||||||
/// So for a packet going through three mix nodes, on average, it will take three times this value
|
/// So for a packet going through three mix nodes, on average, it will take three times this value
|
||||||
/// until the packet reaches its destination.
|
/// until the packet reaches its destination.
|
||||||
|
#[serde(with = "humantime_serde")]
|
||||||
pub average_packet_delay: Duration,
|
pub average_packet_delay: Duration,
|
||||||
|
|
||||||
/// The parameter of Poisson distribution determining how long, on average,
|
/// The parameter of Poisson distribution determining how long, on average,
|
||||||
/// it is going to take another 'real traffic stream' message to be sent.
|
/// it is going to take another 'real traffic stream' message to be sent.
|
||||||
/// If no real packets are available and cover traffic is enabled,
|
/// If no real packets are available and cover traffic is enabled,
|
||||||
/// a loop cover message is sent instead in order to preserve the rate.
|
/// a loop cover message is sent instead in order to preserve the rate.
|
||||||
|
#[serde(with = "humantime_serde")]
|
||||||
pub message_sending_average_delay: Duration,
|
pub message_sending_average_delay: Duration,
|
||||||
|
|
||||||
/// Controls whether the main packet stream constantly produces packets according to the predefined
|
/// Controls whether the main packet stream constantly produces packets according to the predefined
|
||||||
@@ -404,21 +415,7 @@ pub struct Traffic {
|
|||||||
/// Do not set it unless you understand the consequences of that change.
|
/// Do not set it unless you understand the consequences of that change.
|
||||||
pub secondary_packet_size: Option<PacketSize>,
|
pub secondary_packet_size: Option<PacketSize>,
|
||||||
|
|
||||||
/// Specify whether any constructed sphinx packets should use the legacy format,
|
|
||||||
/// where the payload keys are explicitly attached rather than using the seeds
|
|
||||||
/// this affects any forward packets, acks and reply surbs
|
|
||||||
/// this flag should remain disabled until sufficient number of nodes on the network has upgraded
|
|
||||||
/// and support updated format.
|
|
||||||
/// in the case of reply surbs, the recipient must also understand the new encoding
|
|
||||||
pub use_legacy_sphinx_format: bool,
|
|
||||||
|
|
||||||
pub packet_type: PacketType,
|
pub packet_type: PacketType,
|
||||||
|
|
||||||
/// Indicates whether to mix hops or not. If mix hops are enabled, traffic
|
|
||||||
/// will be routed as usual, to the entry gateway, through three mix nodes, egressing
|
|
||||||
/// through the exit gateway. If mix hops are disabled, traffic will be routed directly
|
|
||||||
/// from the entry gateway to the exit gateway, bypassing the mix nodes.
|
|
||||||
pub disable_mix_hops: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Traffic {
|
impl Traffic {
|
||||||
@@ -445,11 +442,6 @@ impl Default for Traffic {
|
|||||||
primary_packet_size: PacketSize::RegularPacket,
|
primary_packet_size: PacketSize::RegularPacket,
|
||||||
secondary_packet_size: None,
|
secondary_packet_size: None,
|
||||||
packet_type: PacketType::Mix,
|
packet_type: PacketType::Mix,
|
||||||
|
|
||||||
// we should use the legacy format until sufficient number of nodes understand the
|
|
||||||
// improved encoding
|
|
||||||
use_legacy_sphinx_format: true,
|
|
||||||
disable_mix_hops: false,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -554,6 +546,9 @@ pub struct Topology {
|
|||||||
#[serde(with = "humantime_serde")]
|
#[serde(with = "humantime_serde")]
|
||||||
pub max_startup_gateway_waiting_period: Duration,
|
pub max_startup_gateway_waiting_period: Duration,
|
||||||
|
|
||||||
|
/// Specifies the mixnode topology to be used for sending packets.
|
||||||
|
pub topology_structure: TopologyStructure,
|
||||||
|
|
||||||
/// Specifies a minimum performance of a mixnode that is used on route construction.
|
/// Specifies a minimum performance of a mixnode that is used on route construction.
|
||||||
/// This setting is only applicable when `NymApi` topology is used.
|
/// This setting is only applicable when `NymApi` topology is used.
|
||||||
pub minimum_mixnode_performance: u8,
|
pub minimum_mixnode_performance: u8,
|
||||||
@@ -575,6 +570,30 @@ pub struct Topology {
|
|||||||
pub ignore_ingress_epoch_role: bool,
|
pub ignore_ingress_epoch_role: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::large_enum_variant)]
|
||||||
|
#[derive(Default, Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
|
pub enum TopologyStructure {
|
||||||
|
#[default]
|
||||||
|
NymApi,
|
||||||
|
GeoAware(GroupBy),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::large_enum_variant)]
|
||||||
|
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
|
pub enum GroupBy {
|
||||||
|
CountryGroup(CountryGroup),
|
||||||
|
NymAddress(Recipient),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for GroupBy {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
GroupBy::CountryGroup(group) => write!(f, "group: {group}"),
|
||||||
|
GroupBy::NymAddress(address) => write!(f, "address: {address}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Default for Topology {
|
impl Default for Topology {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Topology {
|
Topology {
|
||||||
@@ -582,6 +601,7 @@ impl Default for Topology {
|
|||||||
topology_resolution_timeout: DEFAULT_TOPOLOGY_RESOLUTION_TIMEOUT,
|
topology_resolution_timeout: DEFAULT_TOPOLOGY_RESOLUTION_TIMEOUT,
|
||||||
disable_refreshing: false,
|
disable_refreshing: false,
|
||||||
max_startup_gateway_waiting_period: DEFAULT_MAX_STARTUP_GATEWAY_WAITING_PERIOD,
|
max_startup_gateway_waiting_period: DEFAULT_MAX_STARTUP_GATEWAY_WAITING_PERIOD,
|
||||||
|
topology_structure: TopologyStructure::default(),
|
||||||
minimum_mixnode_performance: DEFAULT_MIN_MIXNODE_PERFORMANCE,
|
minimum_mixnode_performance: DEFAULT_MIN_MIXNODE_PERFORMANCE,
|
||||||
minimum_gateway_performance: DEFAULT_MIN_GATEWAY_PERFORMANCE,
|
minimum_gateway_performance: DEFAULT_MIN_GATEWAY_PERFORMANCE,
|
||||||
use_extended_topology: false,
|
use_extended_topology: false,
|
||||||
@@ -717,9 +737,6 @@ pub struct DebugConfig {
|
|||||||
|
|
||||||
/// Defines all configuration options related to the forget me flag.
|
/// Defines all configuration options related to the forget me flag.
|
||||||
pub forget_me: ForgetMe,
|
pub forget_me: ForgetMe,
|
||||||
|
|
||||||
/// Defines all configuration options related to the remember me flag.
|
|
||||||
pub remember_me: RememberMe,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DebugConfig {
|
impl DebugConfig {
|
||||||
@@ -743,7 +760,6 @@ impl Default for DebugConfig {
|
|||||||
reply_surbs: Default::default(),
|
reply_surbs: Default::default(),
|
||||||
stats_reporting: Default::default(),
|
stats_reporting: Default::default(),
|
||||||
forget_me: Default::default(),
|
forget_me: Default::default(),
|
||||||
remember_me: Default::default(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -809,57 +825,3 @@ impl ForgetMe {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Default, Debug, Deserialize, PartialEq, Serialize, Copy)]
|
|
||||||
pub struct RememberMe {
|
|
||||||
/// Signal that this client should be accounted for in the stats
|
|
||||||
stats: bool,
|
|
||||||
|
|
||||||
/// Type of the session to remember, if it should be remembered
|
|
||||||
session_type: SessionType,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl RememberMe {
|
|
||||||
pub fn new_vpn() -> Self {
|
|
||||||
Self {
|
|
||||||
stats: true,
|
|
||||||
session_type: SessionType::Vpn,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new_mixnet() -> Self {
|
|
||||||
Self {
|
|
||||||
stats: true,
|
|
||||||
session_type: SessionType::Mixnet,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new_native() -> Self {
|
|
||||||
Self {
|
|
||||||
stats: true,
|
|
||||||
session_type: SessionType::Native,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new(stats: bool, session_type: SessionType) -> Self {
|
|
||||||
Self {
|
|
||||||
stats,
|
|
||||||
session_type,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new_none() -> Self {
|
|
||||||
Self {
|
|
||||||
stats: false,
|
|
||||||
session_type: SessionType::Unknown,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn session_type(&self) -> SessionType {
|
|
||||||
self.session_type
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn stats(&self) -> bool {
|
|
||||||
self.stats
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ pub mod v2;
|
|||||||
pub mod v3;
|
pub mod v3;
|
||||||
pub mod v4;
|
pub mod v4;
|
||||||
pub mod v5;
|
pub mod v5;
|
||||||
pub mod v6;
|
|
||||||
|
|
||||||
// aliases for backwards compatibility
|
// aliases for backwards compatibility
|
||||||
pub use v1 as old_config_v1_1_13;
|
pub use v1 as old_config_v1_1_13;
|
||||||
@@ -14,4 +13,3 @@ pub use v2 as old_config_v1_1_20;
|
|||||||
pub use v3 as old_config_v1_1_20_2;
|
pub use v3 as old_config_v1_1_20_2;
|
||||||
pub use v4 as old_config_v1_1_30;
|
pub use v4 as old_config_v1_1_30;
|
||||||
pub use v5 as old_config_v1_1_33;
|
pub use v5 as old_config_v1_1_33;
|
||||||
pub use v6 as old_config_v1_1_54;
|
|
||||||
|
|||||||
@@ -2,9 +2,10 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
use crate::old::v5::{
|
use crate::old::v5::{
|
||||||
AcknowledgementsV5, ClientV5, ConfigV5, CountryGroupV5, CoverTrafficV5, DebugConfigV5,
|
AcknowledgementsV5, ClientV5, ConfigV5, CoverTrafficV5, DebugConfigV5, GatewayConnectionV5,
|
||||||
GatewayConnectionV5, GroupByV5, ReplySurbsV5, TopologyStructureV5, TopologyV5, TrafficV5,
|
GroupByV5, ReplySurbsV5, TopologyStructureV5, TopologyV5, TrafficV5,
|
||||||
};
|
};
|
||||||
|
use crate::CountryGroup;
|
||||||
use nym_sphinx_addressing::Recipient;
|
use nym_sphinx_addressing::Recipient;
|
||||||
use nym_sphinx_params::{PacketSize, PacketType};
|
use nym_sphinx_params::{PacketSize, PacketType};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
@@ -368,47 +369,31 @@ impl From<TopologyStructureV4> for TopologyStructureV5 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Hash, PartialEq, Eq, Serialize, Deserialize, Debug)]
|
|
||||||
pub enum CountryGroupV4 {
|
|
||||||
Europe,
|
|
||||||
NorthAmerica,
|
|
||||||
SouthAmerica,
|
|
||||||
Oceania,
|
|
||||||
Asia,
|
|
||||||
Africa,
|
|
||||||
Unknown,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<CountryGroupV4> for CountryGroupV5 {
|
|
||||||
fn from(value: CountryGroupV4) -> Self {
|
|
||||||
match value {
|
|
||||||
CountryGroupV4::Europe => CountryGroupV5::Europe,
|
|
||||||
CountryGroupV4::NorthAmerica => CountryGroupV5::NorthAmerica,
|
|
||||||
CountryGroupV4::SouthAmerica => CountryGroupV5::SouthAmerica,
|
|
||||||
CountryGroupV4::Oceania => CountryGroupV5::Oceania,
|
|
||||||
CountryGroupV4::Asia => CountryGroupV5::Asia,
|
|
||||||
CountryGroupV4::Africa => CountryGroupV5::Africa,
|
|
||||||
CountryGroupV4::Unknown => CountryGroupV5::Unknown,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(clippy::large_enum_variant)]
|
#[allow(clippy::large_enum_variant)]
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
pub enum GroupByV4 {
|
pub enum GroupByV4 {
|
||||||
CountryGroup(CountryGroupV4),
|
CountryGroup(CountryGroup),
|
||||||
NymAddress(Recipient),
|
NymAddress(Recipient),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<GroupByV4> for GroupByV5 {
|
impl From<GroupByV4> for GroupByV5 {
|
||||||
fn from(value: GroupByV4) -> Self {
|
fn from(value: GroupByV4) -> Self {
|
||||||
match value {
|
match value {
|
||||||
GroupByV4::CountryGroup(country) => GroupByV5::CountryGroup(country.into()),
|
GroupByV4::CountryGroup(country) => GroupByV5::CountryGroup(country),
|
||||||
GroupByV4::NymAddress(addr) => GroupByV5::NymAddress(addr),
|
GroupByV4::NymAddress(addr) => GroupByV5::NymAddress(addr),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for GroupByV4 {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
GroupByV4::CountryGroup(group) => write!(f, "group: {}", group),
|
||||||
|
GroupByV4::NymAddress(address) => write!(f, "address: {}", address),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Default for TopologyV4 {
|
impl Default for TopologyV4 {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
TopologyV4 {
|
TopologyV4 {
|
||||||
|
|||||||
@@ -1,14 +1,16 @@
|
|||||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
Acknowledgements, Client, Config, CountryGroup, CoverTraffic, DebugConfig, GatewayConnection,
|
||||||
|
GroupBy, ReplySurbs, Topology, TopologyStructure, Traffic,
|
||||||
|
};
|
||||||
use nym_sphinx_addressing::Recipient;
|
use nym_sphinx_addressing::Recipient;
|
||||||
use nym_sphinx_params::{PacketSize, PacketType};
|
use nym_sphinx_params::{PacketSize, PacketType};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
use super::v6::*;
|
|
||||||
|
|
||||||
// 'DEBUG'
|
// 'DEBUG'
|
||||||
const DEFAULT_ACK_WAIT_MULTIPLIER: f64 = 1.5;
|
const DEFAULT_ACK_WAIT_MULTIPLIER: f64 = 1.5;
|
||||||
|
|
||||||
@@ -85,18 +87,18 @@ pub struct ConfigV5 {
|
|||||||
pub debug: DebugConfigV5,
|
pub debug: DebugConfigV5,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<ConfigV5> for ConfigV6 {
|
impl From<ConfigV5> for Config {
|
||||||
fn from(value: ConfigV5) -> Self {
|
fn from(value: ConfigV5) -> Self {
|
||||||
ConfigV6 {
|
Config {
|
||||||
client: ClientV6 {
|
client: Client {
|
||||||
version: value.client.version,
|
version: value.client.version,
|
||||||
id: value.client.id,
|
id: value.client.id,
|
||||||
disabled_credentials_mode: value.client.disabled_credentials_mode,
|
disabled_credentials_mode: value.client.disabled_credentials_mode,
|
||||||
nyxd_urls: value.client.nyxd_urls,
|
nyxd_urls: value.client.nyxd_urls,
|
||||||
nym_api_urls: value.client.nym_api_urls,
|
nym_api_urls: value.client.nym_api_urls,
|
||||||
},
|
},
|
||||||
debug: DebugConfigV6 {
|
debug: DebugConfig {
|
||||||
traffic: TrafficV6 {
|
traffic: Traffic {
|
||||||
average_packet_delay: value.debug.traffic.average_packet_delay,
|
average_packet_delay: value.debug.traffic.average_packet_delay,
|
||||||
message_sending_average_delay: value
|
message_sending_average_delay: value
|
||||||
.debug
|
.debug
|
||||||
@@ -111,7 +113,7 @@ impl From<ConfigV5> for ConfigV6 {
|
|||||||
packet_type: value.debug.traffic.packet_type,
|
packet_type: value.debug.traffic.packet_type,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
cover_traffic: CoverTrafficV6 {
|
cover_traffic: CoverTraffic {
|
||||||
loop_cover_traffic_average_delay: value
|
loop_cover_traffic_average_delay: value
|
||||||
.debug
|
.debug
|
||||||
.cover_traffic
|
.cover_traffic
|
||||||
@@ -125,18 +127,18 @@ impl From<ConfigV5> for ConfigV6 {
|
|||||||
.cover_traffic
|
.cover_traffic
|
||||||
.disable_loop_cover_traffic_stream,
|
.disable_loop_cover_traffic_stream,
|
||||||
},
|
},
|
||||||
gateway_connection: GatewayConnectionV6 {
|
gateway_connection: GatewayConnection {
|
||||||
gateway_response_timeout: value
|
gateway_response_timeout: value
|
||||||
.debug
|
.debug
|
||||||
.gateway_connection
|
.gateway_connection
|
||||||
.gateway_response_timeout,
|
.gateway_response_timeout,
|
||||||
},
|
},
|
||||||
acknowledgements: AcknowledgementsV6 {
|
acknowledgements: Acknowledgements {
|
||||||
average_ack_delay: value.debug.acknowledgements.average_ack_delay,
|
average_ack_delay: value.debug.acknowledgements.average_ack_delay,
|
||||||
ack_wait_multiplier: value.debug.acknowledgements.ack_wait_multiplier,
|
ack_wait_multiplier: value.debug.acknowledgements.ack_wait_multiplier,
|
||||||
ack_wait_addition: value.debug.acknowledgements.ack_wait_addition,
|
ack_wait_addition: value.debug.acknowledgements.ack_wait_addition,
|
||||||
},
|
},
|
||||||
topology: TopologyV6 {
|
topology: Topology {
|
||||||
topology_refresh_rate: value.debug.topology.topology_refresh_rate,
|
topology_refresh_rate: value.debug.topology.topology_refresh_rate,
|
||||||
topology_resolution_timeout: value.debug.topology.topology_resolution_timeout,
|
topology_resolution_timeout: value.debug.topology.topology_resolution_timeout,
|
||||||
disable_refreshing: value.debug.topology.disable_refreshing,
|
disable_refreshing: value.debug.topology.disable_refreshing,
|
||||||
@@ -144,9 +146,10 @@ impl From<ConfigV5> for ConfigV6 {
|
|||||||
.debug
|
.debug
|
||||||
.topology
|
.topology
|
||||||
.max_startup_gateway_waiting_period,
|
.max_startup_gateway_waiting_period,
|
||||||
|
topology_structure: value.debug.topology.topology_structure.into(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
reply_surbs: ReplySurbsV6 {
|
reply_surbs: ReplySurbs {
|
||||||
minimum_reply_surb_storage_threshold: value
|
minimum_reply_surb_storage_threshold: value
|
||||||
.debug
|
.debug
|
||||||
.reply_surbs
|
.reply_surbs
|
||||||
@@ -369,24 +372,40 @@ pub enum TopologyStructureV5 {
|
|||||||
GeoAware(GroupByV5),
|
GeoAware(GroupByV5),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Hash, PartialEq, Eq, Serialize, Deserialize, Debug)]
|
impl From<TopologyStructureV5> for TopologyStructure {
|
||||||
pub enum CountryGroupV5 {
|
fn from(value: TopologyStructureV5) -> Self {
|
||||||
Europe,
|
match value {
|
||||||
NorthAmerica,
|
TopologyStructureV5::NymApi => TopologyStructure::NymApi,
|
||||||
SouthAmerica,
|
TopologyStructureV5::GeoAware(group_by) => TopologyStructure::GeoAware(group_by.into()),
|
||||||
Oceania,
|
}
|
||||||
Asia,
|
}
|
||||||
Africa,
|
|
||||||
Unknown,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::large_enum_variant)]
|
#[allow(clippy::large_enum_variant)]
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
pub enum GroupByV5 {
|
pub enum GroupByV5 {
|
||||||
CountryGroup(CountryGroupV5),
|
CountryGroup(CountryGroup),
|
||||||
NymAddress(Recipient),
|
NymAddress(Recipient),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<GroupByV5> for GroupBy {
|
||||||
|
fn from(value: GroupByV5) -> Self {
|
||||||
|
match value {
|
||||||
|
GroupByV5::CountryGroup(country) => GroupBy::CountryGroup(country),
|
||||||
|
GroupByV5::NymAddress(addr) => GroupBy::NymAddress(addr),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for GroupByV5 {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
GroupByV5::CountryGroup(group) => write!(f, "group: {}", group),
|
||||||
|
GroupByV5::NymAddress(address) => write!(f, "address: {}", address),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Default for TopologyV5 {
|
impl Default for TopologyV5 {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
TopologyV5 {
|
TopologyV5 {
|
||||||
|
|||||||
@@ -1,623 +0,0 @@
|
|||||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
use crate::{
|
|
||||||
Acknowledgements, Client, Config, CoverTraffic, DebugConfig, ForgetMe, GatewayConnection,
|
|
||||||
RememberMe, ReplySurbs, StatsReporting, Topology, Traffic,
|
|
||||||
};
|
|
||||||
use nym_config::serde_helpers::{de_maybe_stringified, ser_maybe_stringified};
|
|
||||||
use nym_sphinx_addressing::Recipient;
|
|
||||||
use nym_sphinx_params::{PacketSize, PacketType};
|
|
||||||
use nym_statistics_common::types::SessionType;
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use std::time::Duration;
|
|
||||||
use url::Url;
|
|
||||||
|
|
||||||
// 'DEBUG'
|
|
||||||
const DEFAULT_ACK_WAIT_MULTIPLIER: f64 = 1.5;
|
|
||||||
|
|
||||||
const DEFAULT_ACK_WAIT_ADDITION: Duration = Duration::from_millis(1_500);
|
|
||||||
const DEFAULT_LOOP_COVER_STREAM_AVERAGE_DELAY: Duration = Duration::from_millis(200);
|
|
||||||
const DEFAULT_MESSAGE_STREAM_AVERAGE_DELAY: Duration = Duration::from_millis(20);
|
|
||||||
const DEFAULT_AVERAGE_PACKET_DELAY: Duration = Duration::from_millis(15);
|
|
||||||
const DEFAULT_TOPOLOGY_REFRESH_RATE: Duration = Duration::from_secs(5 * 60); // every 5min
|
|
||||||
const DEFAULT_TOPOLOGY_RESOLUTION_TIMEOUT: Duration = Duration::from_millis(5_000);
|
|
||||||
|
|
||||||
// the same values as our current (10.06.24) blacklist
|
|
||||||
const DEFAULT_MIN_MIXNODE_PERFORMANCE: u8 = 50;
|
|
||||||
const DEFAULT_MIN_GATEWAY_PERFORMANCE: u8 = 50;
|
|
||||||
|
|
||||||
const DEFAULT_MAX_STARTUP_GATEWAY_WAITING_PERIOD: Duration = Duration::from_secs(70 * 60); // 70min -> full epoch (1h) + a bit of overhead
|
|
||||||
|
|
||||||
// Set this to a high value for now, so that we don't risk sporadic timeouts that might cause
|
|
||||||
// bought bandwidth tokens to not have time to be spent; Once we remove the gateway from the
|
|
||||||
// bandwidth bridging protocol, we can come back to a smaller timeout value
|
|
||||||
const DEFAULT_GATEWAY_RESPONSE_TIMEOUT: Duration = Duration::from_secs(5 * 60);
|
|
||||||
|
|
||||||
const DEFAULT_COVER_TRAFFIC_PRIMARY_SIZE_RATIO: f64 = 0.70;
|
|
||||||
|
|
||||||
// reply-surbs related:
|
|
||||||
|
|
||||||
// define when to request
|
|
||||||
// clients/client-core/src/client/replies/reply_storage/surb_storage.rs
|
|
||||||
const DEFAULT_MINIMUM_REPLY_SURB_STORAGE_THRESHOLD: usize = 10;
|
|
||||||
const DEFAULT_MAXIMUM_REPLY_SURB_STORAGE_THRESHOLD: usize = 200;
|
|
||||||
const DEFAULT_MINIMUM_REPLY_SURB_THRESHOLD_BUFFER: usize = 0;
|
|
||||||
|
|
||||||
// define how much to request at once
|
|
||||||
// clients/client-core/src/client/replies/reply_controller.rs
|
|
||||||
const DEFAULT_MINIMUM_REPLY_SURB_REQUEST_SIZE: u32 = 10;
|
|
||||||
const DEFAULT_MAXIMUM_REPLY_SURB_REQUEST_SIZE: u32 = 50;
|
|
||||||
|
|
||||||
const DEFAULT_MAXIMUM_ALLOWED_SURB_REQUEST_SIZE: u32 = 500;
|
|
||||||
|
|
||||||
const DEFAULT_MAXIMUM_REPLY_SURB_REREQUEST_WAITING_PERIOD: Duration = Duration::from_secs(10);
|
|
||||||
const DEFAULT_MAXIMUM_REPLY_SURB_DROP_WAITING_PERIOD: Duration = Duration::from_secs(5 * 60);
|
|
||||||
|
|
||||||
// 12 hours
|
|
||||||
const DEFAULT_MAXIMUM_REPLY_SURB_AGE: Duration = Duration::from_secs(12 * 60 * 60);
|
|
||||||
|
|
||||||
// 24 hours
|
|
||||||
const DEFAULT_MAXIMUM_REPLY_KEY_AGE: Duration = Duration::from_secs(24 * 60 * 60);
|
|
||||||
|
|
||||||
// stats reporting related
|
|
||||||
|
|
||||||
/// Time interval between reporting statistics to the given provider if it exists
|
|
||||||
const STATS_REPORT_INTERVAL_SECS: Duration = Duration::from_secs(300);
|
|
||||||
|
|
||||||
// aliases for backwards compatibility
|
|
||||||
pub type ConfigV1_1_54 = ConfigV6;
|
|
||||||
pub type ClientV1_1_54 = ClientV6;
|
|
||||||
pub type DebugConfigV1_1_54 = DebugConfigV6;
|
|
||||||
|
|
||||||
pub type TrafficV1_1_54 = TrafficV6;
|
|
||||||
pub type CoverTrafficV1_1_54 = CoverTrafficV6;
|
|
||||||
pub type GatewayConnectionV1_1_54 = GatewayConnectionV6;
|
|
||||||
pub type AcknowledgementsV1_1_54 = AcknowledgementsV6;
|
|
||||||
pub type TopologyV1_1_54 = TopologyV6;
|
|
||||||
pub type ReplySurbsV1_1_54 = ReplySurbsV6;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
|
|
||||||
#[serde(deny_unknown_fields)]
|
|
||||||
pub struct ConfigV6 {
|
|
||||||
pub client: ClientV6,
|
|
||||||
|
|
||||||
#[serde(default)]
|
|
||||||
pub debug: DebugConfigV6,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<ConfigV6> for Config {
|
|
||||||
fn from(value: ConfigV6) -> Self {
|
|
||||||
Config {
|
|
||||||
client: Client {
|
|
||||||
version: value.client.version,
|
|
||||||
id: value.client.id,
|
|
||||||
disabled_credentials_mode: value.client.disabled_credentials_mode,
|
|
||||||
nyxd_urls: value.client.nyxd_urls,
|
|
||||||
nym_api_urls: value.client.nym_api_urls,
|
|
||||||
},
|
|
||||||
debug: DebugConfig {
|
|
||||||
traffic: Traffic {
|
|
||||||
average_packet_delay: DEFAULT_AVERAGE_PACKET_DELAY,
|
|
||||||
message_sending_average_delay: value
|
|
||||||
.debug
|
|
||||||
.traffic
|
|
||||||
.message_sending_average_delay,
|
|
||||||
disable_main_poisson_packet_distribution: value
|
|
||||||
.debug
|
|
||||||
.traffic
|
|
||||||
.disable_main_poisson_packet_distribution,
|
|
||||||
primary_packet_size: value.debug.traffic.primary_packet_size,
|
|
||||||
secondary_packet_size: value.debug.traffic.secondary_packet_size,
|
|
||||||
packet_type: value.debug.traffic.packet_type,
|
|
||||||
deterministic_route_selection: value
|
|
||||||
.debug
|
|
||||||
.traffic
|
|
||||||
.deterministic_route_selection,
|
|
||||||
maximum_number_of_retransmissions: value
|
|
||||||
.debug
|
|
||||||
.traffic
|
|
||||||
.maximum_number_of_retransmissions,
|
|
||||||
use_legacy_sphinx_format: value.debug.traffic.use_legacy_sphinx_format,
|
|
||||||
disable_mix_hops: value.debug.traffic.disable_mix_hops,
|
|
||||||
},
|
|
||||||
cover_traffic: CoverTraffic {
|
|
||||||
loop_cover_traffic_average_delay: value
|
|
||||||
.debug
|
|
||||||
.cover_traffic
|
|
||||||
.loop_cover_traffic_average_delay,
|
|
||||||
cover_traffic_primary_size_ratio: value
|
|
||||||
.debug
|
|
||||||
.cover_traffic
|
|
||||||
.cover_traffic_primary_size_ratio,
|
|
||||||
disable_loop_cover_traffic_stream: value
|
|
||||||
.debug
|
|
||||||
.cover_traffic
|
|
||||||
.disable_loop_cover_traffic_stream,
|
|
||||||
},
|
|
||||||
gateway_connection: GatewayConnection {
|
|
||||||
gateway_response_timeout: value
|
|
||||||
.debug
|
|
||||||
.gateway_connection
|
|
||||||
.gateway_response_timeout,
|
|
||||||
},
|
|
||||||
acknowledgements: Acknowledgements {
|
|
||||||
average_ack_delay: value.debug.acknowledgements.average_ack_delay,
|
|
||||||
ack_wait_multiplier: value.debug.acknowledgements.ack_wait_multiplier,
|
|
||||||
ack_wait_addition: value.debug.acknowledgements.ack_wait_addition,
|
|
||||||
},
|
|
||||||
topology: Topology {
|
|
||||||
topology_refresh_rate: value.debug.topology.topology_refresh_rate,
|
|
||||||
topology_resolution_timeout: value.debug.topology.topology_resolution_timeout,
|
|
||||||
disable_refreshing: value.debug.topology.disable_refreshing,
|
|
||||||
max_startup_gateway_waiting_period: value
|
|
||||||
.debug
|
|
||||||
.topology
|
|
||||||
.max_startup_gateway_waiting_period,
|
|
||||||
minimum_mixnode_performance: value.debug.topology.minimum_mixnode_performance,
|
|
||||||
minimum_gateway_performance: value.debug.topology.minimum_gateway_performance,
|
|
||||||
use_extended_topology: value.debug.topology.use_extended_topology,
|
|
||||||
ignore_egress_epoch_role: value.debug.topology.ignore_egress_epoch_role,
|
|
||||||
ignore_ingress_epoch_role: value.debug.topology.ignore_ingress_epoch_role,
|
|
||||||
},
|
|
||||||
reply_surbs: ReplySurbs {
|
|
||||||
minimum_reply_surb_storage_threshold: value
|
|
||||||
.debug
|
|
||||||
.reply_surbs
|
|
||||||
.minimum_reply_surb_storage_threshold,
|
|
||||||
maximum_reply_surb_storage_threshold: value
|
|
||||||
.debug
|
|
||||||
.reply_surbs
|
|
||||||
.maximum_reply_surb_storage_threshold,
|
|
||||||
minimum_reply_surb_request_size: value
|
|
||||||
.debug
|
|
||||||
.reply_surbs
|
|
||||||
.minimum_reply_surb_request_size,
|
|
||||||
maximum_reply_surb_request_size: value
|
|
||||||
.debug
|
|
||||||
.reply_surbs
|
|
||||||
.maximum_reply_surb_request_size,
|
|
||||||
maximum_allowed_reply_surb_request_size: value
|
|
||||||
.debug
|
|
||||||
.reply_surbs
|
|
||||||
.maximum_allowed_reply_surb_request_size,
|
|
||||||
maximum_reply_surb_rerequest_waiting_period: value
|
|
||||||
.debug
|
|
||||||
.reply_surbs
|
|
||||||
.maximum_reply_surb_rerequest_waiting_period,
|
|
||||||
maximum_reply_surb_drop_waiting_period: value
|
|
||||||
.debug
|
|
||||||
.reply_surbs
|
|
||||||
.maximum_reply_surb_drop_waiting_period,
|
|
||||||
maximum_reply_surb_age: value.debug.reply_surbs.maximum_reply_surb_age,
|
|
||||||
maximum_reply_key_age: value.debug.reply_surbs.maximum_reply_key_age,
|
|
||||||
surb_mix_hops: value.debug.reply_surbs.surb_mix_hops,
|
|
||||||
minimum_reply_surb_threshold_buffer: value
|
|
||||||
.debug
|
|
||||||
.reply_surbs
|
|
||||||
.minimum_reply_surb_threshold_buffer,
|
|
||||||
fresh_sender_tags: value.debug.reply_surbs.fresh_sender_tags,
|
|
||||||
},
|
|
||||||
stats_reporting: StatsReporting {
|
|
||||||
enabled: value.debug.stats_reporting.enabled,
|
|
||||||
provider_address: value.debug.stats_reporting.provider_address,
|
|
||||||
reporting_interval: value.debug.stats_reporting.reporting_interval,
|
|
||||||
},
|
|
||||||
forget_me: ForgetMe {
|
|
||||||
client: value.debug.forget_me.client,
|
|
||||||
stats: value.debug.forget_me.stats,
|
|
||||||
},
|
|
||||||
remember_me: RememberMe {
|
|
||||||
stats: value.debug.remember_me.stats,
|
|
||||||
session_type: value.debug.remember_me.session_type.into(),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
|
|
||||||
// note: the deny_unknown_fields is VITAL here to allow upgrades from v1.1.20_2
|
|
||||||
#[serde(deny_unknown_fields)]
|
|
||||||
pub struct ClientV6 {
|
|
||||||
/// Version of the client for which this configuration was created.
|
|
||||||
pub version: String,
|
|
||||||
|
|
||||||
/// ID specifies the human readable ID of this particular client.
|
|
||||||
pub id: String,
|
|
||||||
|
|
||||||
/// Indicates whether this client is running in a disabled credentials mode, thus attempting
|
|
||||||
/// to claim bandwidth without presenting bandwidth credentials.
|
|
||||||
// TODO: this should be moved to `debug.gateway_connection`
|
|
||||||
#[serde(default)]
|
|
||||||
pub disabled_credentials_mode: bool,
|
|
||||||
|
|
||||||
/// Addresses to nyxd validators via which the client can communicate with the chain.
|
|
||||||
#[serde(alias = "validator_urls")]
|
|
||||||
pub nyxd_urls: Vec<Url>,
|
|
||||||
|
|
||||||
/// Addresses to APIs running on validator from which the client gets the view of the network.
|
|
||||||
#[serde(alias = "validator_api_urls")]
|
|
||||||
pub nym_api_urls: Vec<Url>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
|
||||||
#[serde(default, deny_unknown_fields)]
|
|
||||||
pub struct TrafficV6 {
|
|
||||||
/// The parameter of Poisson distribution determining how long, on average,
|
|
||||||
/// sent packet is going to be delayed at any given mix node.
|
|
||||||
/// So for a packet going through three mix nodes, on average, it will take three times this value
|
|
||||||
/// until the packet reaches its destination.
|
|
||||||
#[serde(with = "humantime_serde")]
|
|
||||||
pub average_packet_delay: Duration,
|
|
||||||
|
|
||||||
/// The parameter of Poisson distribution determining how long, on average,
|
|
||||||
/// it is going to take another 'real traffic stream' message to be sent.
|
|
||||||
/// If no real packets are available and cover traffic is enabled,
|
|
||||||
/// a loop cover message is sent instead in order to preserve the rate.
|
|
||||||
#[serde(with = "humantime_serde")]
|
|
||||||
pub message_sending_average_delay: Duration,
|
|
||||||
|
|
||||||
/// Controls whether the main packet stream constantly produces packets according to the predefined
|
|
||||||
/// poisson distribution.
|
|
||||||
pub disable_main_poisson_packet_distribution: bool,
|
|
||||||
|
|
||||||
/// Specify whether route selection should be determined by the packet header.
|
|
||||||
pub deterministic_route_selection: bool,
|
|
||||||
|
|
||||||
/// Specify how many times particular packet can be retransmitted
|
|
||||||
/// None - no limit
|
|
||||||
pub maximum_number_of_retransmissions: Option<u32>,
|
|
||||||
|
|
||||||
/// Specifies the packet size used for sent messages.
|
|
||||||
/// Do not override it unless you understand the consequences of that change.
|
|
||||||
pub primary_packet_size: PacketSize,
|
|
||||||
|
|
||||||
/// Specifies the optional auxiliary packet size for optimizing message streams.
|
|
||||||
/// Note that its use decreases overall anonymity.
|
|
||||||
/// Do not set it unless you understand the consequences of that change.
|
|
||||||
pub secondary_packet_size: Option<PacketSize>,
|
|
||||||
|
|
||||||
/// Specify whether any constructed sphinx packets should use the legacy format,
|
|
||||||
/// where the payload keys are explicitly attached rather than using the seeds
|
|
||||||
/// this affects any forward packets, acks and reply surbs
|
|
||||||
/// this flag should remain disabled until sufficient number of nodes on the network has upgraded
|
|
||||||
/// and support updated format.
|
|
||||||
/// in the case of reply surbs, the recipient must also understand the new encoding
|
|
||||||
pub use_legacy_sphinx_format: bool,
|
|
||||||
|
|
||||||
pub packet_type: PacketType,
|
|
||||||
|
|
||||||
/// Indicates whether to mix hops or not. If mix hops are enabled, traffic
|
|
||||||
/// will be routed as usual, to the entry gateway, through three mix nodes, egressing
|
|
||||||
/// through the exit gateway. If mix hops are disabled, traffic will be routed directly
|
|
||||||
/// from the entry gateway to the exit gateway, bypassing the mix nodes.
|
|
||||||
pub disable_mix_hops: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for TrafficV6 {
|
|
||||||
fn default() -> Self {
|
|
||||||
TrafficV6 {
|
|
||||||
average_packet_delay: DEFAULT_AVERAGE_PACKET_DELAY,
|
|
||||||
message_sending_average_delay: DEFAULT_MESSAGE_STREAM_AVERAGE_DELAY,
|
|
||||||
disable_main_poisson_packet_distribution: false,
|
|
||||||
deterministic_route_selection: false,
|
|
||||||
maximum_number_of_retransmissions: None,
|
|
||||||
primary_packet_size: PacketSize::RegularPacket,
|
|
||||||
secondary_packet_size: None,
|
|
||||||
packet_type: PacketType::Mix,
|
|
||||||
|
|
||||||
// we should use the legacy format until sufficient number of nodes understand the
|
|
||||||
// improved encoding
|
|
||||||
use_legacy_sphinx_format: true,
|
|
||||||
disable_mix_hops: false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
|
||||||
#[serde(default, deny_unknown_fields)]
|
|
||||||
pub struct CoverTrafficV6 {
|
|
||||||
/// The parameter of Poisson distribution determining how long, on average,
|
|
||||||
/// it is going to take for another loop cover traffic message to be sent.
|
|
||||||
#[serde(with = "humantime_serde")]
|
|
||||||
pub loop_cover_traffic_average_delay: Duration,
|
|
||||||
|
|
||||||
/// Specifies the ratio of `primary_packet_size` to `secondary_packet_size` used in cover traffic.
|
|
||||||
/// Only applicable if `secondary_packet_size` is enabled.
|
|
||||||
pub cover_traffic_primary_size_ratio: f64,
|
|
||||||
|
|
||||||
/// Controls whether the dedicated loop cover traffic stream should be enabled.
|
|
||||||
/// (and sending packets, on average, every [Self::loop_cover_traffic_average_delay])
|
|
||||||
pub disable_loop_cover_traffic_stream: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for CoverTrafficV6 {
|
|
||||||
fn default() -> Self {
|
|
||||||
CoverTrafficV6 {
|
|
||||||
loop_cover_traffic_average_delay: DEFAULT_LOOP_COVER_STREAM_AVERAGE_DELAY,
|
|
||||||
cover_traffic_primary_size_ratio: DEFAULT_COVER_TRAFFIC_PRIMARY_SIZE_RATIO,
|
|
||||||
disable_loop_cover_traffic_stream: false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
|
||||||
#[serde(default, deny_unknown_fields)]
|
|
||||||
pub struct GatewayConnectionV6 {
|
|
||||||
/// How long we're willing to wait for a response to a message sent to the gateway,
|
|
||||||
/// before giving up on it.
|
|
||||||
#[serde(with = "humantime_serde")]
|
|
||||||
pub gateway_response_timeout: Duration,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for GatewayConnectionV6 {
|
|
||||||
fn default() -> Self {
|
|
||||||
GatewayConnectionV6 {
|
|
||||||
gateway_response_timeout: DEFAULT_GATEWAY_RESPONSE_TIMEOUT,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
|
||||||
#[serde(default, deny_unknown_fields)]
|
|
||||||
pub struct AcknowledgementsV6 {
|
|
||||||
/// The parameter of Poisson distribution determining how long, on average,
|
|
||||||
/// sent acknowledgement is going to be delayed at any given mix node.
|
|
||||||
/// So for an ack going through three mix nodes, on average, it will take three times this value
|
|
||||||
/// until the packet reaches its destination.
|
|
||||||
#[serde(with = "humantime_serde")]
|
|
||||||
pub average_ack_delay: Duration,
|
|
||||||
|
|
||||||
/// Value multiplied with the expected round trip time of an acknowledgement packet before
|
|
||||||
/// it is assumed it was lost and retransmission of the data packet happens.
|
|
||||||
/// In an ideal network with 0 latency, this value would have been 1.
|
|
||||||
pub ack_wait_multiplier: f64,
|
|
||||||
|
|
||||||
/// Value added to the expected round trip time of an acknowledgement packet before
|
|
||||||
/// it is assumed it was lost and retransmission of the data packet happens.
|
|
||||||
/// In an ideal network with 0 latency, this value would have been 0.
|
|
||||||
#[serde(with = "humantime_serde")]
|
|
||||||
pub ack_wait_addition: Duration,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for AcknowledgementsV6 {
|
|
||||||
fn default() -> Self {
|
|
||||||
AcknowledgementsV6 {
|
|
||||||
average_ack_delay: DEFAULT_AVERAGE_PACKET_DELAY,
|
|
||||||
ack_wait_multiplier: DEFAULT_ACK_WAIT_MULTIPLIER,
|
|
||||||
ack_wait_addition: DEFAULT_ACK_WAIT_ADDITION,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
|
||||||
#[serde(default, deny_unknown_fields)]
|
|
||||||
pub struct TopologyV6 {
|
|
||||||
/// The uniform delay every which clients are querying the directory server
|
|
||||||
/// to try to obtain a compatible network topology to send sphinx packets through.
|
|
||||||
#[serde(with = "humantime_serde")]
|
|
||||||
pub topology_refresh_rate: Duration,
|
|
||||||
|
|
||||||
/// During topology refresh, test packets are sent through every single possible network
|
|
||||||
/// path. This timeout determines waiting period until it is decided that the packet
|
|
||||||
/// did not reach its destination.
|
|
||||||
#[serde(with = "humantime_serde")]
|
|
||||||
pub topology_resolution_timeout: Duration,
|
|
||||||
|
|
||||||
/// Specifies whether the client should not refresh the network topology after obtaining
|
|
||||||
/// the first valid instance.
|
|
||||||
/// Supersedes `topology_refresh_rate_ms`.
|
|
||||||
pub disable_refreshing: bool,
|
|
||||||
|
|
||||||
/// Defines how long the client is going to wait on startup for its gateway to come online,
|
|
||||||
/// before abandoning the procedure.
|
|
||||||
#[serde(with = "humantime_serde")]
|
|
||||||
pub max_startup_gateway_waiting_period: Duration,
|
|
||||||
|
|
||||||
/// Specifies a minimum performance of a mixnode that is used on route construction.
|
|
||||||
/// This setting is only applicable when `NymApi` topology is used.
|
|
||||||
pub minimum_mixnode_performance: u8,
|
|
||||||
|
|
||||||
/// Specifies a minimum performance of a gateway that is used on route construction.
|
|
||||||
/// This setting is only applicable when `NymApi` topology is used.
|
|
||||||
pub minimum_gateway_performance: u8,
|
|
||||||
|
|
||||||
/// Specifies whether this client should attempt to retrieve all available network nodes
|
|
||||||
/// as opposed to just active mixnodes/gateways.
|
|
||||||
pub use_extended_topology: bool,
|
|
||||||
|
|
||||||
/// Specifies whether this client should ignore the current epoch role of the target egress node
|
|
||||||
/// when constructing the final hop packets.
|
|
||||||
pub ignore_egress_epoch_role: bool,
|
|
||||||
|
|
||||||
/// Specifies whether this client should ignore the current epoch role of the ingress node
|
|
||||||
/// when attempting to establish new connection
|
|
||||||
pub ignore_ingress_epoch_role: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for TopologyV6 {
|
|
||||||
fn default() -> Self {
|
|
||||||
TopologyV6 {
|
|
||||||
topology_refresh_rate: DEFAULT_TOPOLOGY_REFRESH_RATE,
|
|
||||||
topology_resolution_timeout: DEFAULT_TOPOLOGY_RESOLUTION_TIMEOUT,
|
|
||||||
disable_refreshing: false,
|
|
||||||
max_startup_gateway_waiting_period: DEFAULT_MAX_STARTUP_GATEWAY_WAITING_PERIOD,
|
|
||||||
minimum_mixnode_performance: DEFAULT_MIN_MIXNODE_PERFORMANCE,
|
|
||||||
minimum_gateway_performance: DEFAULT_MIN_GATEWAY_PERFORMANCE,
|
|
||||||
use_extended_topology: false,
|
|
||||||
|
|
||||||
ignore_egress_epoch_role: true,
|
|
||||||
ignore_ingress_epoch_role: true,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
|
||||||
#[serde(default, deny_unknown_fields)]
|
|
||||||
pub struct ReplySurbsV6 {
|
|
||||||
/// Defines the minimum number of reply surbs the client wants to keep in its storage at all times.
|
|
||||||
/// It can only allow to go below that value if its to request additional reply surbs.
|
|
||||||
pub minimum_reply_surb_storage_threshold: usize,
|
|
||||||
|
|
||||||
/// Defines the maximum number of reply surbs the client wants to keep in its storage at any times.
|
|
||||||
pub maximum_reply_surb_storage_threshold: usize,
|
|
||||||
|
|
||||||
/// Defines the soft threshold ontop of the minimum reply surb storage threshold for when the client
|
|
||||||
/// should proactively request additional reply surbs.
|
|
||||||
pub minimum_reply_surb_threshold_buffer: usize,
|
|
||||||
|
|
||||||
/// Defines the minimum number of reply surbs the client would request.
|
|
||||||
pub minimum_reply_surb_request_size: u32,
|
|
||||||
|
|
||||||
/// Defines the maximum number of reply surbs the client would request.
|
|
||||||
pub maximum_reply_surb_request_size: u32,
|
|
||||||
|
|
||||||
/// Defines the maximum number of reply surbs a remote party is allowed to request from this client at once.
|
|
||||||
pub maximum_allowed_reply_surb_request_size: u32,
|
|
||||||
|
|
||||||
/// Defines maximum amount of time the client is going to wait for reply surbs before explicitly asking
|
|
||||||
/// for more even though in theory they wouldn't need to.
|
|
||||||
#[serde(with = "humantime_serde")]
|
|
||||||
pub maximum_reply_surb_rerequest_waiting_period: Duration,
|
|
||||||
|
|
||||||
/// Defines maximum amount of time the client is going to wait for reply surbs before
|
|
||||||
/// deciding it's never going to get them and would drop all pending messages
|
|
||||||
#[serde(with = "humantime_serde")]
|
|
||||||
pub maximum_reply_surb_drop_waiting_period: Duration,
|
|
||||||
|
|
||||||
/// Defines maximum amount of time given reply surb is going to be valid for.
|
|
||||||
/// This is going to be superseded by key rotation once implemented.
|
|
||||||
#[serde(with = "humantime_serde")]
|
|
||||||
pub maximum_reply_surb_age: Duration,
|
|
||||||
|
|
||||||
/// Defines maximum amount of time given reply key is going to be valid for.
|
|
||||||
/// This is going to be superseded by key rotation once implemented.
|
|
||||||
#[serde(with = "humantime_serde")]
|
|
||||||
pub maximum_reply_key_age: Duration,
|
|
||||||
|
|
||||||
/// Specifies the number of mixnet hops the packet should go through. If not specified, then
|
|
||||||
/// the default value is used.
|
|
||||||
pub surb_mix_hops: Option<u8>,
|
|
||||||
|
|
||||||
/// Specifies if we should reset all the sender tags on startup
|
|
||||||
pub fresh_sender_tags: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for ReplySurbsV6 {
|
|
||||||
fn default() -> Self {
|
|
||||||
ReplySurbsV6 {
|
|
||||||
minimum_reply_surb_storage_threshold: DEFAULT_MINIMUM_REPLY_SURB_STORAGE_THRESHOLD,
|
|
||||||
maximum_reply_surb_storage_threshold: DEFAULT_MAXIMUM_REPLY_SURB_STORAGE_THRESHOLD,
|
|
||||||
minimum_reply_surb_threshold_buffer: DEFAULT_MINIMUM_REPLY_SURB_THRESHOLD_BUFFER,
|
|
||||||
minimum_reply_surb_request_size: DEFAULT_MINIMUM_REPLY_SURB_REQUEST_SIZE,
|
|
||||||
maximum_reply_surb_request_size: DEFAULT_MAXIMUM_REPLY_SURB_REQUEST_SIZE,
|
|
||||||
maximum_allowed_reply_surb_request_size: DEFAULT_MAXIMUM_ALLOWED_SURB_REQUEST_SIZE,
|
|
||||||
maximum_reply_surb_rerequest_waiting_period:
|
|
||||||
DEFAULT_MAXIMUM_REPLY_SURB_REREQUEST_WAITING_PERIOD,
|
|
||||||
maximum_reply_surb_drop_waiting_period: DEFAULT_MAXIMUM_REPLY_SURB_DROP_WAITING_PERIOD,
|
|
||||||
maximum_reply_surb_age: DEFAULT_MAXIMUM_REPLY_SURB_AGE,
|
|
||||||
maximum_reply_key_age: DEFAULT_MAXIMUM_REPLY_KEY_AGE,
|
|
||||||
surb_mix_hops: None,
|
|
||||||
fresh_sender_tags: false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
|
||||||
#[serde(default, deny_unknown_fields)]
|
|
||||||
pub struct DebugConfigV6 {
|
|
||||||
/// Defines all configuration options related to traffic streams.
|
|
||||||
pub traffic: TrafficV6,
|
|
||||||
|
|
||||||
/// Defines all configuration options related to cover traffic stream(s).
|
|
||||||
pub cover_traffic: CoverTrafficV6,
|
|
||||||
|
|
||||||
/// Defines all configuration options related to the gateway connection.
|
|
||||||
pub gateway_connection: GatewayConnectionV6,
|
|
||||||
|
|
||||||
/// Defines all configuration options related to acknowledgements, such as delays or wait timeouts.
|
|
||||||
pub acknowledgements: AcknowledgementsV6,
|
|
||||||
|
|
||||||
/// Defines all configuration options related topology, such as refresh rates or timeouts.
|
|
||||||
pub topology: TopologyV6,
|
|
||||||
|
|
||||||
/// Defines all configuration options related to reply SURBs.
|
|
||||||
pub reply_surbs: ReplySurbsV6,
|
|
||||||
|
|
||||||
/// Defines all configuration options related to stats reporting.
|
|
||||||
pub stats_reporting: StatsReportingV6,
|
|
||||||
|
|
||||||
/// Defines all configuration options related to the forget me flag.
|
|
||||||
pub forget_me: ForgetMeV6,
|
|
||||||
|
|
||||||
/// Defines all configuration options related to the remember me flag.
|
|
||||||
pub remember_me: RememberMeV6,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
|
||||||
#[serde(default, deny_unknown_fields)]
|
|
||||||
pub struct StatsReportingV6 {
|
|
||||||
/// Is stats reporting enabled
|
|
||||||
pub enabled: bool,
|
|
||||||
|
|
||||||
/// Address of the stats collector. If this is none, no reporting will happen, regardless of `enabled`
|
|
||||||
#[serde(
|
|
||||||
serialize_with = "ser_maybe_stringified",
|
|
||||||
deserialize_with = "de_maybe_stringified"
|
|
||||||
)]
|
|
||||||
pub provider_address: Option<Recipient>,
|
|
||||||
|
|
||||||
/// With what frequence will statistics be sent
|
|
||||||
#[serde(with = "humantime_serde")]
|
|
||||||
pub reporting_interval: Duration,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for StatsReportingV6 {
|
|
||||||
fn default() -> Self {
|
|
||||||
StatsReportingV6 {
|
|
||||||
enabled: true,
|
|
||||||
provider_address: None,
|
|
||||||
reporting_interval: STATS_REPORT_INTERVAL_SECS,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Default, Debug, Deserialize, PartialEq, Serialize, Copy)]
|
|
||||||
pub struct ForgetMeV6 {
|
|
||||||
client: bool,
|
|
||||||
stats: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Default, Debug, Deserialize, PartialEq, Serialize, Copy)]
|
|
||||||
pub struct RememberMeV6 {
|
|
||||||
/// Signal that this client should be accounted for in the stats
|
|
||||||
stats: bool,
|
|
||||||
|
|
||||||
/// Type of the session to remember, if it should be remembered
|
|
||||||
session_type: SessionTypeV6,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(PartialEq, Copy, Clone, Serialize, Deserialize, Default, Debug)]
|
|
||||||
pub enum SessionTypeV6 {
|
|
||||||
Vpn,
|
|
||||||
Mixnet,
|
|
||||||
Wasm,
|
|
||||||
Native,
|
|
||||||
Socks5,
|
|
||||||
#[default]
|
|
||||||
Unknown,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<SessionTypeV6> for SessionType {
|
|
||||||
fn from(value: SessionTypeV6) -> Self {
|
|
||||||
match value {
|
|
||||||
SessionTypeV6::Vpn => Self::Vpn,
|
|
||||||
SessionTypeV6::Mixnet => Self::Mixnet,
|
|
||||||
SessionTypeV6::Wasm => Self::Wasm,
|
|
||||||
SessionTypeV6::Native => Self::Native,
|
|
||||||
SessionTypeV6::Socks5 => Self::Socks5,
|
|
||||||
SessionTypeV6::Unknown => Self::Unknown,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
use nym_crypto::asymmetric::ed25519::Ed25519RecoveryError;
|
use nym_crypto::asymmetric::identity::Ed25519RecoveryError;
|
||||||
use nym_gateway_requests::shared_key::SharedKeyConversionError;
|
use nym_gateway_requests::shared_key::SharedKeyConversionError;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
#![warn(clippy::unwrap_used)]
|
#![warn(clippy::unwrap_used)]
|
||||||
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use nym_crypto::asymmetric::ed25519;
|
use nym_crypto::asymmetric::identity;
|
||||||
use nym_gateway_requests::SharedSymmetricKey;
|
use nym_gateway_requests::SharedSymmetricKey;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
|
||||||
@@ -36,7 +36,9 @@ pub trait GatewaysDetailsStore {
|
|||||||
async fn all_gateways(&self) -> Result<Vec<GatewayRegistration>, Self::StorageError>;
|
async fn all_gateways(&self) -> Result<Vec<GatewayRegistration>, Self::StorageError>;
|
||||||
|
|
||||||
/// Return identity keys of all registered gateways.
|
/// Return identity keys of all registered gateways.
|
||||||
async fn all_gateways_identities(&self) -> Result<Vec<ed25519::PublicKey>, Self::StorageError> {
|
async fn all_gateways_identities(
|
||||||
|
&self,
|
||||||
|
) -> Result<Vec<identity::PublicKey>, Self::StorageError> {
|
||||||
Ok(self
|
Ok(self
|
||||||
.all_gateways()
|
.all_gateways()
|
||||||
.await?
|
.await?
|
||||||
@@ -62,7 +64,7 @@ pub trait GatewaysDetailsStore {
|
|||||||
|
|
||||||
async fn upgrade_stored_remote_gateway_key(
|
async fn upgrade_stored_remote_gateway_key(
|
||||||
&self,
|
&self,
|
||||||
gateway_id: ed25519::PublicKey,
|
gateway_id: identity::PublicKey,
|
||||||
updated_key: &SharedSymmetricKey,
|
updated_key: &SharedSymmetricKey,
|
||||||
) -> Result<(), Self::StorageError>;
|
) -> Result<(), Self::StorageError>;
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
use crate::BadGateway;
|
use crate::BadGateway;
|
||||||
use cosmrs::AccountId;
|
use cosmrs::AccountId;
|
||||||
use nym_crypto::asymmetric::ed25519;
|
use nym_crypto::asymmetric::identity;
|
||||||
use nym_gateway_requests::shared_key::{LegacySharedKeys, SharedGatewayKey, SharedSymmetricKey};
|
use nym_gateway_requests::shared_key::{LegacySharedKeys, SharedGatewayKey, SharedSymmetricKey};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter};
|
||||||
@@ -29,7 +29,7 @@ pub struct GatewayRegistration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl GatewayRegistration {
|
impl GatewayRegistration {
|
||||||
pub fn gateway_id(&self) -> ed25519::PublicKey {
|
pub fn gateway_id(&self) -> identity::PublicKey {
|
||||||
self.details.gateway_id()
|
self.details.gateway_id()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -64,7 +64,7 @@ impl From<GatewayDetails> for GatewayRegistration {
|
|||||||
|
|
||||||
impl GatewayDetails {
|
impl GatewayDetails {
|
||||||
pub fn new_remote(
|
pub fn new_remote(
|
||||||
gateway_id: ed25519::PublicKey,
|
gateway_id: identity::PublicKey,
|
||||||
shared_key: Arc<SharedGatewayKey>,
|
shared_key: Arc<SharedGatewayKey>,
|
||||||
gateway_owner_address: Option<AccountId>,
|
gateway_owner_address: Option<AccountId>,
|
||||||
gateway_listener: Url,
|
gateway_listener: Url,
|
||||||
@@ -77,11 +77,11 @@ impl GatewayDetails {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_custom(gateway_id: ed25519::PublicKey, data: Option<Vec<u8>>) -> Self {
|
pub fn new_custom(gateway_id: identity::PublicKey, data: Option<Vec<u8>>) -> Self {
|
||||||
GatewayDetails::Custom(CustomGatewayDetails { gateway_id, data })
|
GatewayDetails::Custom(CustomGatewayDetails { gateway_id, data })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn gateway_id(&self) -> ed25519::PublicKey {
|
pub fn gateway_id(&self) -> identity::PublicKey {
|
||||||
match self {
|
match self {
|
||||||
GatewayDetails::Remote(details) => details.gateway_id,
|
GatewayDetails::Remote(details) => details.gateway_id,
|
||||||
GatewayDetails::Custom(details) => details.gateway_id,
|
GatewayDetails::Custom(details) => details.gateway_id,
|
||||||
@@ -157,7 +157,7 @@ pub struct RawRegisteredGateway {
|
|||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub struct RegisteredGateway {
|
pub struct RegisteredGateway {
|
||||||
pub gateway_id: ed25519::PublicKey,
|
pub gateway_id: identity::PublicKey,
|
||||||
|
|
||||||
pub registration_timestamp: OffsetDateTime,
|
pub registration_timestamp: OffsetDateTime,
|
||||||
|
|
||||||
@@ -179,7 +179,7 @@ impl TryFrom<RawRemoteGatewayDetails> for RemoteGatewayDetails {
|
|||||||
|
|
||||||
fn try_from(value: RawRemoteGatewayDetails) -> Result<Self, Self::Error> {
|
fn try_from(value: RawRemoteGatewayDetails) -> Result<Self, Self::Error> {
|
||||||
let gateway_id =
|
let gateway_id =
|
||||||
ed25519::PublicKey::from_base58_string(&value.gateway_id_bs58).map_err(|source| {
|
identity::PublicKey::from_base58_string(&value.gateway_id_bs58).map_err(|source| {
|
||||||
BadGateway::MalformedGatewayIdentity {
|
BadGateway::MalformedGatewayIdentity {
|
||||||
gateway_id: value.gateway_id_bs58.clone(),
|
gateway_id: value.gateway_id_bs58.clone(),
|
||||||
source,
|
source,
|
||||||
@@ -267,7 +267,7 @@ impl<'a> From<&'a RemoteGatewayDetails> for RawRemoteGatewayDetails {
|
|||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct RemoteGatewayDetails {
|
pub struct RemoteGatewayDetails {
|
||||||
pub gateway_id: ed25519::PublicKey,
|
pub gateway_id: identity::PublicKey,
|
||||||
|
|
||||||
pub shared_key: Arc<SharedGatewayKey>,
|
pub shared_key: Arc<SharedGatewayKey>,
|
||||||
|
|
||||||
@@ -288,7 +288,7 @@ impl TryFrom<RawCustomGatewayDetails> for CustomGatewayDetails {
|
|||||||
|
|
||||||
fn try_from(value: RawCustomGatewayDetails) -> Result<Self, Self::Error> {
|
fn try_from(value: RawCustomGatewayDetails) -> Result<Self, Self::Error> {
|
||||||
let gateway_id =
|
let gateway_id =
|
||||||
ed25519::PublicKey::from_base58_string(&value.gateway_id_bs58).map_err(|source| {
|
identity::PublicKey::from_base58_string(&value.gateway_id_bs58).map_err(|source| {
|
||||||
BadGateway::MalformedGatewayIdentity {
|
BadGateway::MalformedGatewayIdentity {
|
||||||
gateway_id: value.gateway_id_bs58.clone(),
|
gateway_id: value.gateway_id_bs58.clone(),
|
||||||
source,
|
source,
|
||||||
@@ -314,12 +314,12 @@ impl<'a> From<&'a CustomGatewayDetails> for RawCustomGatewayDetails {
|
|||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct CustomGatewayDetails {
|
pub struct CustomGatewayDetails {
|
||||||
pub gateway_id: ed25519::PublicKey,
|
pub gateway_id: identity::PublicKey,
|
||||||
pub data: Option<Vec<u8>>,
|
pub data: Option<Vec<u8>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CustomGatewayDetails {
|
impl CustomGatewayDetails {
|
||||||
pub fn new(gateway_id: ed25519::PublicKey) -> CustomGatewayDetails {
|
pub fn new(gateway_id: identity::PublicKey) -> CustomGatewayDetails {
|
||||||
Self {
|
Self {
|
||||||
gateway_id,
|
gateway_id,
|
||||||
data: None,
|
data: None,
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ 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::ed25519;
|
use nym_crypto::asymmetric::identity;
|
||||||
use nym_topology::NymTopology;
|
use nym_topology::NymTopology;
|
||||||
use nym_validator_client::UserAgent;
|
use nym_validator_client::UserAgent;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
@@ -29,7 +29,7 @@ pub struct CommonClientAddGatewayArgs {
|
|||||||
/// Explicitly specify id of the gateway to register with.
|
/// Explicitly specify id of the gateway to register with.
|
||||||
/// If unspecified, a random gateway will be chosen instead.
|
/// If unspecified, a random gateway will be chosen instead.
|
||||||
#[cfg_attr(feature = "cli", clap(long, alias = "gateway"))]
|
#[cfg_attr(feature = "cli", clap(long, alias = "gateway"))]
|
||||||
pub gateway_id: Option<ed25519::PublicKey>,
|
pub gateway_id: Option<identity::PublicKey>,
|
||||||
|
|
||||||
/// Specifies whether the client will attempt to enforce tls connection to the desired gateway.
|
/// Specifies whether the client will attempt to enforce tls connection to the desired gateway.
|
||||||
#[cfg_attr(feature = "cli", clap(long))]
|
#[cfg_attr(feature = "cli", clap(long))]
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ 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::ed25519;
|
use nym_crypto::asymmetric::identity;
|
||||||
use nym_sphinx::addressing::Recipient;
|
use nym_sphinx::addressing::Recipient;
|
||||||
use nym_topology::NymTopology;
|
use nym_topology::NymTopology;
|
||||||
use nym_validator_client::UserAgent;
|
use nym_validator_client::UserAgent;
|
||||||
@@ -42,7 +42,7 @@ pub struct CommonClientInitArgs {
|
|||||||
|
|
||||||
/// Id of the gateway we are going to connect to.
|
/// Id of the gateway we are going to connect to.
|
||||||
#[cfg_attr(feature = "cli", clap(long))]
|
#[cfg_attr(feature = "cli", clap(long))]
|
||||||
pub gateway: Option<ed25519::PublicKey>,
|
pub gateway: Option<identity::PublicKey>,
|
||||||
|
|
||||||
/// Specifies whether the client will attempt to enforce tls connection to the desired gateway.
|
/// Specifies whether the client will attempt to enforce tls connection to the desired gateway.
|
||||||
#[cfg_attr(feature = "cli", clap(long))]
|
#[cfg_attr(feature = "cli", clap(long))]
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
use nym_crypto::asymmetric::ed25519;
|
use nym_crypto::asymmetric::identity;
|
||||||
use nym_sphinx::addressing::Recipient;
|
use nym_sphinx::addressing::Recipient;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
@@ -15,7 +15,7 @@ pub struct CommonClientRunArgs {
|
|||||||
/// Id of the gateway we want to connect to. If overridden, it is user's responsibility to
|
/// Id of the gateway we want to connect to. If overridden, it is user's responsibility to
|
||||||
/// ensure prior registration happened
|
/// ensure prior registration happened
|
||||||
#[cfg_attr(feature = "cli", clap(long))]
|
#[cfg_attr(feature = "cli", clap(long))]
|
||||||
pub gateway: Option<ed25519::PublicKey>,
|
pub gateway: Option<identity::PublicKey>,
|
||||||
|
|
||||||
/// Comma separated list of rest endpoints of the nyxd validators
|
/// Comma separated list of rest endpoints of the nyxd validators
|
||||||
#[cfg_attr(
|
#[cfg_attr(
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
use crate::cli_helpers::{CliClient, CliClientConfig};
|
use crate::cli_helpers::{CliClient, CliClientConfig};
|
||||||
use crate::client::base_client::non_wasm_helpers::setup_fs_gateways_storage;
|
use crate::client::base_client::non_wasm_helpers::setup_fs_gateways_storage;
|
||||||
use crate::client::base_client::storage::helpers::set_active_gateway;
|
use crate::client::base_client::storage::helpers::set_active_gateway;
|
||||||
use nym_crypto::asymmetric::ed25519;
|
use nym_crypto::asymmetric::identity;
|
||||||
|
|
||||||
#[cfg_attr(feature = "cli", derive(clap::Args))]
|
#[cfg_attr(feature = "cli", derive(clap::Args))]
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
@@ -15,7 +15,7 @@ pub struct CommonClientSwitchGatewaysArgs {
|
|||||||
|
|
||||||
/// Id of the gateway we want to switch to.
|
/// Id of the gateway we want to switch to.
|
||||||
#[cfg_attr(feature = "cli", clap(long))]
|
#[cfg_attr(feature = "cli", clap(long))]
|
||||||
pub gateway_id: ed25519::PublicKey,
|
pub gateway_id: identity::PublicKey,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn switch_gateway<C, A>(args: A) -> Result<(), C::Error>
|
pub async fn switch_gateway<C, A>(args: A) -> Result<(), C::Error>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
use nym_crypto::asymmetric::ed25519;
|
use nym_crypto::asymmetric::identity;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter};
|
||||||
use time::OffsetDateTime;
|
use time::OffsetDateTime;
|
||||||
@@ -10,7 +10,7 @@ use url::Url;
|
|||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
pub struct GatewayInfo {
|
pub struct GatewayInfo {
|
||||||
pub registration: OffsetDateTime,
|
pub registration: OffsetDateTime,
|
||||||
pub identity: ed25519::PublicKey,
|
pub identity: identity::PublicKey,
|
||||||
pub active: bool,
|
pub active: bool,
|
||||||
|
|
||||||
pub typ: String,
|
pub typ: String,
|
||||||
|
|||||||
@@ -36,10 +36,10 @@ use crate::{config, spawn_future};
|
|||||||
use futures::channel::mpsc;
|
use futures::channel::mpsc;
|
||||||
use log::*;
|
use log::*;
|
||||||
use nym_bandwidth_controller::BandwidthController;
|
use nym_bandwidth_controller::BandwidthController;
|
||||||
use nym_client_core_config_types::{ForgetMe, RememberMe};
|
use nym_client_core_config_types::ForgetMe;
|
||||||
use nym_client_core_gateways_storage::{GatewayDetails, GatewaysDetailsStore};
|
use nym_client_core_gateways_storage::{GatewayDetails, GatewaysDetailsStore};
|
||||||
use nym_credential_storage::storage::Storage as CredentialStorage;
|
use nym_credential_storage::storage::Storage as CredentialStorage;
|
||||||
use nym_crypto::asymmetric::{ed25519, x25519};
|
use nym_crypto::asymmetric::{encryption, identity};
|
||||||
use nym_crypto::hkdf::DerivationMaterial;
|
use nym_crypto::hkdf::DerivationMaterial;
|
||||||
use nym_gateway_client::client::config::GatewayClientConfig;
|
use nym_gateway_client::client::config::GatewayClientConfig;
|
||||||
use nym_gateway_client::{
|
use nym_gateway_client::{
|
||||||
@@ -238,12 +238,6 @@ where
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
#[must_use]
|
|
||||||
pub fn with_remember_me(mut self, remember_me: &RememberMe) -> Self {
|
|
||||||
self.config.debug.remember_me = *remember_me;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn with_gateway_setup(mut self, setup: GatewaySetup) -> Self {
|
pub fn with_gateway_setup(mut self, setup: GatewaySetup) -> Self {
|
||||||
self.setup_method = setup;
|
self.setup_method = setup;
|
||||||
@@ -373,7 +367,7 @@ where
|
|||||||
// buffer controlling all messages fetched from provider
|
// buffer controlling all messages fetched from provider
|
||||||
// required so that other components would be able to use them (say the websocket)
|
// required so that other components would be able to use them (say the websocket)
|
||||||
fn start_received_messages_buffer_controller(
|
fn start_received_messages_buffer_controller(
|
||||||
local_encryption_keypair: Arc<x25519::KeyPair>,
|
local_encryption_keypair: Arc<encryption::KeyPair>,
|
||||||
query_receiver: ReceivedBufferRequestReceiver,
|
query_receiver: ReceivedBufferRequestReceiver,
|
||||||
mixnet_receiver: MixnetMessageReceiver,
|
mixnet_receiver: MixnetMessageReceiver,
|
||||||
reply_key_storage: SentReplyKeys,
|
reply_key_storage: SentReplyKeys,
|
||||||
@@ -558,12 +552,18 @@ where
|
|||||||
user_agent: Option<UserAgent>,
|
user_agent: Option<UserAgent>,
|
||||||
) -> Box<dyn TopologyProvider + Send + Sync> {
|
) -> Box<dyn TopologyProvider + Send + Sync> {
|
||||||
// if no custom provider was ... provided ..., create one using nym-api
|
// if no custom provider was ... provided ..., create one using nym-api
|
||||||
custom_provider.unwrap_or_else(|| {
|
custom_provider.unwrap_or_else(|| match config_topology.topology_structure {
|
||||||
Box::new(NymApiTopologyProvider::new(
|
config::TopologyStructure::NymApi => Box::new(NymApiTopologyProvider::new(
|
||||||
config_topology,
|
config_topology,
|
||||||
nym_api_urls,
|
nym_api_urls,
|
||||||
user_agent,
|
user_agent,
|
||||||
))
|
)),
|
||||||
|
config::TopologyStructure::GeoAware(group_by) => {
|
||||||
|
warn!("using deprecated 'GeoAware' topology provider - this option will be removed very soon");
|
||||||
|
|
||||||
|
#[allow(deprecated)]
|
||||||
|
Box::new(crate::client::topology_control::GeoAwareTopologyProvider::new(nym_api_urls, group_by))
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -936,14 +936,13 @@ where
|
|||||||
task_handle: shutdown,
|
task_handle: shutdown,
|
||||||
client_request_sender,
|
client_request_sender,
|
||||||
forget_me: self.config.debug.forget_me,
|
forget_me: self.config.debug.forget_me,
|
||||||
remember_me: self.config.debug.remember_me,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct BaseClient {
|
pub struct BaseClient {
|
||||||
pub address: Recipient,
|
pub address: Recipient,
|
||||||
pub identity_keys: Arc<ed25519::KeyPair>,
|
pub identity_keys: Arc<identity::KeyPair>,
|
||||||
pub client_input: ClientInputStatus,
|
pub client_input: ClientInputStatus,
|
||||||
pub client_output: ClientOutputStatus,
|
pub client_output: ClientOutputStatus,
|
||||||
pub client_state: ClientState,
|
pub client_state: ClientState,
|
||||||
@@ -951,5 +950,4 @@ pub struct BaseClient {
|
|||||||
pub client_request_sender: ClientRequestSender,
|
pub client_request_sender: ClientRequestSender,
|
||||||
pub task_handle: TaskHandle,
|
pub task_handle: TaskHandle,
|
||||||
pub forget_me: ForgetMe,
|
pub forget_me: ForgetMe,
|
||||||
pub remember_me: RememberMe,
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ use crate::client::key_manager::persistence::KeyStore;
|
|||||||
use crate::client::key_manager::ClientKeys;
|
use crate::client::key_manager::ClientKeys;
|
||||||
use crate::error::ClientCoreError;
|
use crate::error::ClientCoreError;
|
||||||
use nym_client_core_gateways_storage::{ActiveGateway, GatewayRegistration, GatewaysDetailsStore};
|
use nym_client_core_gateways_storage::{ActiveGateway, GatewayRegistration, GatewaysDetailsStore};
|
||||||
use nym_crypto::asymmetric::ed25519;
|
use nym_crypto::asymmetric::identity;
|
||||||
|
|
||||||
// helpers for error wrapping
|
// helpers for error wrapping
|
||||||
pub async fn set_active_gateway<D>(
|
pub async fn set_active_gateway<D>(
|
||||||
@@ -26,7 +26,7 @@ where
|
|||||||
|
|
||||||
pub async fn get_active_gateway_identity<D>(
|
pub async fn get_active_gateway_identity<D>(
|
||||||
details_store: &D,
|
details_store: &D,
|
||||||
) -> Result<Option<ed25519::PublicKey>, ClientCoreError>
|
) -> Result<Option<identity::PublicKey>, ClientCoreError>
|
||||||
where
|
where
|
||||||
D: GatewaysDetailsStore,
|
D: GatewaysDetailsStore,
|
||||||
D::StorageError: Send + Sync + 'static,
|
D::StorageError: Send + Sync + 'static,
|
||||||
@@ -42,7 +42,7 @@ where
|
|||||||
|
|
||||||
pub async fn get_all_registered_identities<D>(
|
pub async fn get_all_registered_identities<D>(
|
||||||
details_store: &D,
|
details_store: &D,
|
||||||
) -> Result<Vec<ed25519::PublicKey>, ClientCoreError>
|
) -> Result<Vec<identity::PublicKey>, ClientCoreError>
|
||||||
where
|
where
|
||||||
D: GatewaysDetailsStore + Sync,
|
D: GatewaysDetailsStore + Sync,
|
||||||
D::StorageError: Send + Sync + 'static,
|
D::StorageError: Send + Sync + 'static,
|
||||||
|
|||||||
@@ -62,10 +62,6 @@ where
|
|||||||
/// Optional secondary predefined packet size used for the loop cover messages.
|
/// Optional secondary predefined packet size used for the loop cover messages.
|
||||||
secondary_packet_size: Option<PacketSize>,
|
secondary_packet_size: Option<PacketSize>,
|
||||||
|
|
||||||
/// Specify whether any constructed packets should use the legacy format,
|
|
||||||
/// where the payload keys are explicitly attached rather than using the seeds
|
|
||||||
use_legacy_sphinx_format: bool,
|
|
||||||
|
|
||||||
packet_type: PacketType,
|
packet_type: PacketType,
|
||||||
|
|
||||||
stats_tx: ClientStatsSender,
|
stats_tx: ClientStatsSender,
|
||||||
@@ -134,7 +130,6 @@ impl LoopCoverTrafficStream<OsRng> {
|
|||||||
topology_access,
|
topology_access,
|
||||||
primary_packet_size: traffic_config.primary_packet_size,
|
primary_packet_size: traffic_config.primary_packet_size,
|
||||||
secondary_packet_size: traffic_config.secondary_packet_size,
|
secondary_packet_size: traffic_config.secondary_packet_size,
|
||||||
use_legacy_sphinx_format: traffic_config.use_legacy_sphinx_format,
|
|
||||||
packet_type: traffic_config.packet_type,
|
packet_type: traffic_config.packet_type,
|
||||||
stats_tx,
|
stats_tx,
|
||||||
task_client,
|
task_client,
|
||||||
@@ -187,7 +182,6 @@ impl LoopCoverTrafficStream<OsRng> {
|
|||||||
|
|
||||||
let cover_message = match generate_loop_cover_packet(
|
let cover_message = match generate_loop_cover_packet(
|
||||||
&mut self.rng,
|
&mut self.rng,
|
||||||
self.use_legacy_sphinx_format,
|
|
||||||
topology_ref,
|
topology_ref,
|
||||||
&self.ack_key,
|
&self.ack_key,
|
||||||
&self.our_full_destination,
|
&self.our_full_destination,
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
use crate::client::key_manager::persistence::KeyStore;
|
use crate::client::key_manager::persistence::KeyStore;
|
||||||
use nym_crypto::{
|
use nym_crypto::{
|
||||||
asymmetric::{ed25519, x25519},
|
asymmetric::{encryption, identity},
|
||||||
hkdf::{DerivationMaterial, InvalidLength},
|
hkdf::{DerivationMaterial, InvalidLength},
|
||||||
};
|
};
|
||||||
use nym_gateway_requests::shared_key::{LegacySharedKeys, SharedGatewayKey, SharedSymmetricKey};
|
use nym_gateway_requests::shared_key::{LegacySharedKeys, SharedGatewayKey, SharedSymmetricKey};
|
||||||
@@ -25,10 +25,10 @@ mod test;
|
|||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct ClientKeys {
|
pub struct ClientKeys {
|
||||||
/// identity key associated with the client instance.
|
/// identity key associated with the client instance.
|
||||||
identity_keypair: Arc<ed25519::KeyPair>,
|
identity_keypair: Arc<identity::KeyPair>,
|
||||||
|
|
||||||
/// encryption key associated with the client instance.
|
/// encryption key associated with the client instance.
|
||||||
encryption_keypair: Arc<x25519::KeyPair>,
|
encryption_keypair: Arc<encryption::KeyPair>,
|
||||||
|
|
||||||
/// key used for producing and processing acknowledgement packets.
|
/// key used for producing and processing acknowledgement packets.
|
||||||
ack_key: Arc<AckKey>,
|
ack_key: Arc<AckKey>,
|
||||||
@@ -41,8 +41,8 @@ impl ClientKeys {
|
|||||||
R: RngCore + CryptoRng,
|
R: RngCore + CryptoRng,
|
||||||
{
|
{
|
||||||
ClientKeys {
|
ClientKeys {
|
||||||
identity_keypair: Arc::new(ed25519::KeyPair::new(rng)),
|
identity_keypair: Arc::new(identity::KeyPair::new(rng)),
|
||||||
encryption_keypair: Arc::new(x25519::KeyPair::new(rng)),
|
encryption_keypair: Arc::new(encryption::KeyPair::new(rng)),
|
||||||
ack_key: Arc::new(AckKey::new(rng)),
|
ack_key: Arc::new(AckKey::new(rng)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -56,18 +56,18 @@ impl ClientKeys {
|
|||||||
{
|
{
|
||||||
let secret = derivation_material.derive_secret()?;
|
let secret = derivation_material.derive_secret()?;
|
||||||
Ok(ClientKeys {
|
Ok(ClientKeys {
|
||||||
identity_keypair: Arc::new(ed25519::KeyPair::from_secret(
|
identity_keypair: Arc::new(identity::KeyPair::from_secret(
|
||||||
secret,
|
secret,
|
||||||
derivation_material.index(),
|
derivation_material.index(),
|
||||||
)),
|
)),
|
||||||
encryption_keypair: Arc::new(x25519::KeyPair::new(rng)),
|
encryption_keypair: Arc::new(encryption::KeyPair::new(rng)),
|
||||||
ack_key: Arc::new(AckKey::new(rng)),
|
ack_key: Arc::new(AckKey::new(rng)),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_keys(
|
pub fn from_keys(
|
||||||
id_keypair: ed25519::KeyPair,
|
id_keypair: identity::KeyPair,
|
||||||
enc_keypair: x25519::KeyPair,
|
enc_keypair: encryption::KeyPair,
|
||||||
ack_key: AckKey,
|
ack_key: AckKey,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
@@ -85,13 +85,13 @@ impl ClientKeys {
|
|||||||
store.store_keys(self).await
|
store.store_keys(self).await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets an atomically reference counted pointer to [`ed25519::KeyPair`].
|
/// Gets an atomically reference counted pointer to [`identity::KeyPair`].
|
||||||
pub fn identity_keypair(&self) -> Arc<ed25519::KeyPair> {
|
pub fn identity_keypair(&self) -> Arc<identity::KeyPair> {
|
||||||
Arc::clone(&self.identity_keypair)
|
Arc::clone(&self.identity_keypair)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets an atomically reference counted pointer to [`x25519::KeyPair`].
|
/// Gets an atomically reference counted pointer to [`encryption::KeyPair`].
|
||||||
pub fn encryption_keypair(&self) -> Arc<x25519::KeyPair> {
|
pub fn encryption_keypair(&self) -> Arc<encryption::KeyPair> {
|
||||||
Arc::clone(&self.encryption_keypair)
|
Arc::clone(&self.encryption_keypair)
|
||||||
}
|
}
|
||||||
/// Gets an atomically reference counted pointer to [`AckKey`].
|
/// Gets an atomically reference counted pointer to [`AckKey`].
|
||||||
@@ -103,8 +103,8 @@ impl ClientKeys {
|
|||||||
fn _assert_keys_zeroize_on_drop() {
|
fn _assert_keys_zeroize_on_drop() {
|
||||||
fn _assert_zeroize_on_drop<T: ZeroizeOnDrop>() {}
|
fn _assert_zeroize_on_drop<T: ZeroizeOnDrop>() {}
|
||||||
|
|
||||||
_assert_zeroize_on_drop::<ed25519::KeyPair>();
|
_assert_zeroize_on_drop::<identity::KeyPair>();
|
||||||
_assert_zeroize_on_drop::<x25519::KeyPair>();
|
_assert_zeroize_on_drop::<encryption::KeyPair>();
|
||||||
_assert_zeroize_on_drop::<AckKey>();
|
_assert_zeroize_on_drop::<AckKey>();
|
||||||
_assert_zeroize_on_drop::<LegacySharedKeys>();
|
_assert_zeroize_on_drop::<LegacySharedKeys>();
|
||||||
_assert_zeroize_on_drop::<SharedSymmetricKey>();
|
_assert_zeroize_on_drop::<SharedSymmetricKey>();
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ use tokio::sync::Mutex;
|
|||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
use crate::config::disk_persistence::ClientKeysPaths;
|
use crate::config::disk_persistence::ClientKeysPaths;
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
use nym_crypto::asymmetric::{ed25519, x25519};
|
use nym_crypto::asymmetric::{encryption, identity};
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
use nym_pemstore::traits::{PemStorableKey, PemStorableKeyPair};
|
use nym_pemstore::traits::{PemStorableKey, PemStorableKeyPair};
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
@@ -86,13 +86,13 @@ impl OnDiskKeys {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub fn load_encryption_keypair(&self) -> Result<x25519::KeyPair, OnDiskKeysError> {
|
pub fn load_encryption_keypair(&self) -> Result<encryption::KeyPair, OnDiskKeysError> {
|
||||||
let encryption_paths = self.paths.encryption_key_pair_path();
|
let encryption_paths = self.paths.encryption_key_pair_path();
|
||||||
self.load_keypair(encryption_paths, "encryption")
|
self.load_keypair(encryption_paths, "encryption")
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub fn load_identity_keypair(&self) -> Result<ed25519::KeyPair, OnDiskKeysError> {
|
pub fn load_identity_keypair(&self) -> Result<identity::KeyPair, OnDiskKeysError> {
|
||||||
let identity_paths = self.paths.identity_key_pair_path();
|
let identity_paths = self.paths.identity_key_pair_path();
|
||||||
self.load_keypair(identity_paths, "identity")
|
self.load_keypair(identity_paths, "identity")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use log::{debug, error};
|
use log::{debug, error};
|
||||||
use nym_credential_storage::storage::Storage as CredentialStorage;
|
use nym_credential_storage::storage::Storage as CredentialStorage;
|
||||||
use nym_crypto::asymmetric::ed25519;
|
use nym_crypto::asymmetric::identity;
|
||||||
use nym_gateway_client::error::GatewayClientError;
|
use nym_gateway_client::error::GatewayClientError;
|
||||||
use nym_gateway_client::GatewayClient;
|
use nym_gateway_client::GatewayClient;
|
||||||
pub use nym_gateway_client::{GatewayPacketRouter, PacketRouter};
|
pub use nym_gateway_client::{GatewayPacketRouter, PacketRouter};
|
||||||
@@ -30,15 +30,12 @@ fn erase_err<E: std::error::Error + Send + Sync + 'static>(err: E) -> ErasedGate
|
|||||||
/// This combines combines the functionalities of being able to send and receive mix packets.
|
/// This combines combines the functionalities of being able to send and receive mix packets.
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
pub trait GatewayTransceiver: GatewaySender + GatewayReceiver {
|
pub trait GatewayTransceiver: GatewaySender + GatewayReceiver {
|
||||||
fn gateway_identity(&self) -> ed25519::PublicKey;
|
fn gateway_identity(&self) -> identity::PublicKey;
|
||||||
fn ws_fd(&self) -> Option<RawFd>;
|
fn ws_fd(&self) -> Option<RawFd>;
|
||||||
async fn send_client_request(
|
async fn send_client_request(
|
||||||
&mut self,
|
&mut self,
|
||||||
message: ClientRequest,
|
message: ClientRequest,
|
||||||
) -> Result<(), GatewayClientError>;
|
) -> Result<(), GatewayClientError>;
|
||||||
|
|
||||||
/// Check if the websocket connection to the gateway is alive
|
|
||||||
fn is_connection_alive(&self) -> bool;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This trait defines the functionality of sending `MixPacket` into the mixnet,
|
/// This trait defines the functionality of sending `MixPacket` into the mixnet,
|
||||||
@@ -78,7 +75,7 @@ pub trait GatewayReceiver {
|
|||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl<G: GatewayTransceiver + ?Sized + Send> GatewayTransceiver for Box<G> {
|
impl<G: GatewayTransceiver + ?Sized + Send> GatewayTransceiver for Box<G> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn gateway_identity(&self) -> ed25519::PublicKey {
|
fn gateway_identity(&self) -> identity::PublicKey {
|
||||||
(**self).gateway_identity()
|
(**self).gateway_identity()
|
||||||
}
|
}
|
||||||
fn ws_fd(&self) -> Option<RawFd> {
|
fn ws_fd(&self) -> Option<RawFd> {
|
||||||
@@ -93,11 +90,6 @@ impl<G: GatewayTransceiver + ?Sized + Send> GatewayTransceiver for Box<G> {
|
|||||||
log::debug!("Sent client request: {:?}", message);
|
log::debug!("Sent client request: {:?}", message);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn is_connection_alive(&self) -> bool {
|
|
||||||
(**self).is_connection_alive()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
||||||
@@ -142,7 +134,7 @@ where
|
|||||||
St: CredentialStorage,
|
St: CredentialStorage,
|
||||||
<St as CredentialStorage>::StorageError: Send + Sync + 'static,
|
<St as CredentialStorage>::StorageError: Send + Sync + 'static,
|
||||||
{
|
{
|
||||||
fn gateway_identity(&self) -> ed25519::PublicKey {
|
fn gateway_identity(&self) -> identity::PublicKey {
|
||||||
self.gateway_client.gateway_identity()
|
self.gateway_client.gateway_identity()
|
||||||
}
|
}
|
||||||
fn ws_fd(&self) -> Option<RawFd> {
|
fn ws_fd(&self) -> Option<RawFd> {
|
||||||
@@ -155,10 +147,6 @@ where
|
|||||||
) -> Result<(), GatewayClientError> {
|
) -> Result<(), GatewayClientError> {
|
||||||
self.gateway_client.send_client_request(message).await
|
self.gateway_client.send_client_request(message).await
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_connection_alive(&self) -> bool {
|
|
||||||
self.gateway_client.is_connection_alive()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
||||||
@@ -202,7 +190,7 @@ pub enum LocalGatewayError {
|
|||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
pub struct LocalGateway {
|
pub struct LocalGateway {
|
||||||
/// Identity of the locally managed gateway
|
/// Identity of the locally managed gateway
|
||||||
local_identity: ed25519::PublicKey,
|
local_identity: identity::PublicKey,
|
||||||
|
|
||||||
// 'sender' part
|
// 'sender' part
|
||||||
/// Channel responsible for taking mix packets and forwarding them further into the further mixnet layers.
|
/// Channel responsible for taking mix packets and forwarding them further into the further mixnet layers.
|
||||||
@@ -215,7 +203,7 @@ pub struct LocalGateway {
|
|||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
impl LocalGateway {
|
impl LocalGateway {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
local_identity: ed25519::PublicKey,
|
local_identity: identity::PublicKey,
|
||||||
packet_forwarder: nym_mixnet_client::forwarder::MixForwardingSender,
|
packet_forwarder: nym_mixnet_client::forwarder::MixForwardingSender,
|
||||||
packet_router_tx: oneshot::Sender<PacketRouter>,
|
packet_router_tx: oneshot::Sender<PacketRouter>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
@@ -233,7 +221,7 @@ mod nonwasm_sealed {
|
|||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl GatewayTransceiver for LocalGateway {
|
impl GatewayTransceiver for LocalGateway {
|
||||||
fn gateway_identity(&self) -> ed25519::PublicKey {
|
fn gateway_identity(&self) -> identity::PublicKey {
|
||||||
self.local_identity
|
self.local_identity
|
||||||
}
|
}
|
||||||
fn ws_fd(&self) -> Option<RawFd> {
|
fn ws_fd(&self) -> Option<RawFd> {
|
||||||
@@ -246,11 +234,6 @@ mod nonwasm_sealed {
|
|||||||
) -> Result<(), GatewayClientError> {
|
) -> Result<(), GatewayClientError> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_connection_alive(&self) -> bool {
|
|
||||||
// LocalGateway is always "connected" since it's in-process
|
|
||||||
true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
@@ -280,7 +263,7 @@ mod nonwasm_sealed {
|
|||||||
|
|
||||||
// if we ever decided to start writing unit tests... : )
|
// if we ever decided to start writing unit tests... : )
|
||||||
pub struct MockGateway {
|
pub struct MockGateway {
|
||||||
dummy_identity: ed25519::PublicKey,
|
dummy_identity: identity::PublicKey,
|
||||||
packet_router: Option<PacketRouter>,
|
packet_router: Option<PacketRouter>,
|
||||||
sent: Vec<MixPacket>,
|
sent: Vec<MixPacket>,
|
||||||
}
|
}
|
||||||
@@ -320,7 +303,7 @@ impl GatewaySender for MockGateway {
|
|||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl GatewayTransceiver for MockGateway {
|
impl GatewayTransceiver for MockGateway {
|
||||||
fn gateway_identity(&self) -> ed25519::PublicKey {
|
fn gateway_identity(&self) -> identity::PublicKey {
|
||||||
self.dummy_identity
|
self.dummy_identity
|
||||||
}
|
}
|
||||||
fn ws_fd(&self) -> Option<RawFd> {
|
fn ws_fd(&self) -> Option<RawFd> {
|
||||||
@@ -333,9 +316,4 @@ impl GatewayTransceiver for MockGateway {
|
|||||||
) -> Result<(), GatewayClientError> {
|
) -> Result<(), GatewayClientError> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_connection_alive(&self) -> bool {
|
|
||||||
// MockGateway is always "connected" for testing purposes
|
|
||||||
true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ use crate::client::real_messages_control::{AckActionSender, Action};
|
|||||||
use crate::client::replies::reply_controller::MaxRetransmissions;
|
use crate::client::replies::reply_controller::MaxRetransmissions;
|
||||||
use crate::client::replies::reply_storage::{ReceivedReplySurbsMap, SentReplyKeys, UsedSenderTags};
|
use crate::client::replies::reply_storage::{ReceivedReplySurbsMap, SentReplyKeys, UsedSenderTags};
|
||||||
use crate::client::topology_control::{TopologyAccessor, TopologyReadPermit};
|
use crate::client::topology_control::{TopologyAccessor, TopologyReadPermit};
|
||||||
|
use log::{debug, error, info, trace, warn};
|
||||||
use nym_sphinx::acknowledgements::AckKey;
|
use nym_sphinx::acknowledgements::AckKey;
|
||||||
use nym_sphinx::addressing::clients::Recipient;
|
use nym_sphinx::addressing::clients::Recipient;
|
||||||
use nym_sphinx::anonymous_replies::requests::{AnonymousSenderTag, RepliableMessage, ReplyMessage};
|
use nym_sphinx::anonymous_replies::requests::{AnonymousSenderTag, RepliableMessage, ReplyMessage};
|
||||||
@@ -26,7 +27,6 @@ use std::collections::HashMap;
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use tracing::{debug, error, info, trace, warn};
|
|
||||||
|
|
||||||
// TODO: move that error elsewhere since it seems to be contaminating different files
|
// TODO: move that error elsewhere since it seems to be contaminating different files
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
@@ -98,12 +98,6 @@ pub(crate) struct Config {
|
|||||||
/// Specify whether route selection should be determined by the packet header.
|
/// Specify whether route selection should be determined by the packet header.
|
||||||
deterministic_route_selection: bool,
|
deterministic_route_selection: bool,
|
||||||
|
|
||||||
/// Indicates whether to mix hops or not. If mix hops are enabled, traffic
|
|
||||||
/// will be routed as usual, to the entry gateway, through three mix nodes, egressing
|
|
||||||
/// through the exit gateway. If mix hops are disabled, traffic will be routed directly
|
|
||||||
/// from the entry gateway to the exit gateway, bypassing the mix nodes.
|
|
||||||
disable_mix_hops: bool,
|
|
||||||
|
|
||||||
/// Average delay a data packet is going to get delay at a single mixnode.
|
/// Average delay a data packet is going to get delay at a single mixnode.
|
||||||
average_packet_delay: Duration,
|
average_packet_delay: Duration,
|
||||||
|
|
||||||
@@ -115,10 +109,6 @@ pub(crate) struct Config {
|
|||||||
|
|
||||||
/// Optional secondary predefined packet size used for the encapsulated messages.
|
/// Optional secondary predefined packet size used for the encapsulated messages.
|
||||||
secondary_packet_size: Option<PacketSize>,
|
secondary_packet_size: Option<PacketSize>,
|
||||||
|
|
||||||
/// Specify whether any constructed reply surbs should use the legacy format,
|
|
||||||
/// where the payload keys are explicitly attached rather than using the seeds
|
|
||||||
use_legacy_sphinx_format: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Config {
|
impl Config {
|
||||||
@@ -128,7 +118,6 @@ impl Config {
|
|||||||
average_packet_delay: Duration,
|
average_packet_delay: Duration,
|
||||||
average_ack_delay: Duration,
|
average_ack_delay: Duration,
|
||||||
deterministic_route_selection: bool,
|
deterministic_route_selection: bool,
|
||||||
use_legacy_reply_surb_format: bool,
|
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Config {
|
Config {
|
||||||
ack_key,
|
ack_key,
|
||||||
@@ -138,8 +127,6 @@ impl Config {
|
|||||||
average_ack_delay,
|
average_ack_delay,
|
||||||
primary_packet_size: PacketSize::default(),
|
primary_packet_size: PacketSize::default(),
|
||||||
secondary_packet_size: None,
|
secondary_packet_size: None,
|
||||||
use_legacy_sphinx_format: use_legacy_reply_surb_format,
|
|
||||||
disable_mix_hops: false,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,12 +141,6 @@ impl Config {
|
|||||||
self.secondary_packet_size = packet_size;
|
self.secondary_packet_size = packet_size;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Configure whether messages senders using this config should use mix hops or not when sending messages.
|
|
||||||
pub fn disable_mix_hops(mut self, disable_mix_hops: bool) -> Self {
|
|
||||||
self.disable_mix_hops = disable_mix_hops;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@@ -205,8 +186,6 @@ where
|
|||||||
config.sender_address,
|
config.sender_address,
|
||||||
config.average_packet_delay,
|
config.average_packet_delay,
|
||||||
config.average_ack_delay,
|
config.average_ack_delay,
|
||||||
config.use_legacy_sphinx_format,
|
|
||||||
config.disable_mix_hops,
|
|
||||||
);
|
);
|
||||||
MessageHandler {
|
MessageHandler {
|
||||||
config,
|
config,
|
||||||
@@ -275,11 +254,9 @@ where
|
|||||||
let topology_permit = self.topology_access.get_read_permit().await;
|
let topology_permit = self.topology_access.get_read_permit().await;
|
||||||
let topology = self.get_topology(&topology_permit)?;
|
let topology = self.get_topology(&topology_permit)?;
|
||||||
|
|
||||||
let reply_surbs = self.message_preparer.generate_reply_surbs(
|
let reply_surbs = self
|
||||||
self.config.use_legacy_sphinx_format,
|
.message_preparer
|
||||||
amount,
|
.generate_reply_surbs(amount, topology)?;
|
||||||
topology,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
let reply_keys = reply_surbs
|
let reply_keys = reply_surbs
|
||||||
.iter()
|
.iter()
|
||||||
@@ -298,7 +275,7 @@ where
|
|||||||
) -> Result<(), SurbWrappedPreparationError> {
|
) -> Result<(), SurbWrappedPreparationError> {
|
||||||
let msg = NymMessage::new_reply(message);
|
let msg = NymMessage::new_reply(message);
|
||||||
let packet_size = self.optimal_packet_size(&msg);
|
let packet_size = self.optimal_packet_size(&msg);
|
||||||
trace!("Using {packet_size} packets for {msg}");
|
debug!("Using {packet_size} packets for {msg}");
|
||||||
|
|
||||||
let mut fragment = self
|
let mut fragment = self
|
||||||
.message_preparer
|
.message_preparer
|
||||||
@@ -362,7 +339,7 @@ where
|
|||||||
pub(crate) fn split_reply_message(&mut self, message: Vec<u8>) -> Vec<Fragment> {
|
pub(crate) fn split_reply_message(&mut self, message: Vec<u8>) -> Vec<Fragment> {
|
||||||
let msg = NymMessage::new_reply(ReplyMessage::new_data_message(message));
|
let msg = NymMessage::new_reply(ReplyMessage::new_data_message(message));
|
||||||
let packet_size = self.optimal_packet_size(&msg);
|
let packet_size = self.optimal_packet_size(&msg);
|
||||||
trace!("Using {packet_size} packets for {msg}");
|
debug!("Using {packet_size} packets for {msg}");
|
||||||
|
|
||||||
self.message_preparer
|
self.message_preparer
|
||||||
.pad_and_split_message(msg, packet_size)
|
.pad_and_split_message(msg, packet_size)
|
||||||
@@ -495,7 +472,7 @@ where
|
|||||||
} else {
|
} else {
|
||||||
self.optimal_packet_size(&message)
|
self.optimal_packet_size(&message)
|
||||||
};
|
};
|
||||||
trace!("Using {packet_size} packets for {message}");
|
debug!("Using {packet_size} packets for {message}");
|
||||||
let fragments = self
|
let fragments = self
|
||||||
.message_preparer
|
.message_preparer
|
||||||
.pad_and_split_message(message, packet_size);
|
.pad_and_split_message(message, packet_size);
|
||||||
@@ -545,7 +522,6 @@ where
|
|||||||
self.generate_reply_surbs_with_keys(amount as usize).await?;
|
self.generate_reply_surbs_with_keys(amount as usize).await?;
|
||||||
|
|
||||||
let message = NymMessage::new_repliable(RepliableMessage::new_additional_surbs(
|
let message = NymMessage::new_repliable(RepliableMessage::new_additional_surbs(
|
||||||
self.config.use_legacy_sphinx_format,
|
|
||||||
sender_tag,
|
sender_tag,
|
||||||
reply_surbs,
|
reply_surbs,
|
||||||
));
|
));
|
||||||
@@ -583,12 +559,8 @@ where
|
|||||||
.generate_reply_surbs_with_keys(num_reply_surbs as usize)
|
.generate_reply_surbs_with_keys(num_reply_surbs as usize)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let message = NymMessage::new_repliable(RepliableMessage::new_data(
|
let message =
|
||||||
self.config.use_legacy_sphinx_format,
|
NymMessage::new_repliable(RepliableMessage::new_data(message, sender_tag, reply_surbs));
|
||||||
message,
|
|
||||||
sender_tag,
|
|
||||||
reply_surbs,
|
|
||||||
));
|
|
||||||
|
|
||||||
self.try_split_and_send_non_reply_message(
|
self.try_split_and_send_non_reply_message(
|
||||||
message,
|
message,
|
||||||
|
|||||||
@@ -99,11 +99,9 @@ impl<'a> From<&'a Config> for message_handler::Config {
|
|||||||
cfg.traffic.average_packet_delay,
|
cfg.traffic.average_packet_delay,
|
||||||
cfg.acks.average_ack_delay,
|
cfg.acks.average_ack_delay,
|
||||||
cfg.traffic.deterministic_route_selection,
|
cfg.traffic.deterministic_route_selection,
|
||||||
cfg.traffic.use_legacy_sphinx_format,
|
|
||||||
)
|
)
|
||||||
.with_custom_primary_packet_size(cfg.traffic.primary_packet_size)
|
.with_custom_primary_packet_size(cfg.traffic.primary_packet_size)
|
||||||
.with_custom_secondary_packet_size(cfg.traffic.secondary_packet_size)
|
.with_custom_secondary_packet_size(cfg.traffic.secondary_packet_size)
|
||||||
.disable_mix_hops(cfg.traffic.disable_mix_hops)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -252,7 +252,6 @@ where
|
|||||||
(
|
(
|
||||||
generate_loop_cover_packet(
|
generate_loop_cover_packet(
|
||||||
&mut self.rng,
|
&mut self.rng,
|
||||||
self.config.traffic.use_legacy_sphinx_format,
|
|
||||||
topology_ref,
|
topology_ref,
|
||||||
&self.config.ack_key,
|
&self.config.ack_key,
|
||||||
&self.config.our_full_destination,
|
&self.config.our_full_destination,
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ use futures::channel::mpsc;
|
|||||||
use futures::lock::Mutex;
|
use futures::lock::Mutex;
|
||||||
use futures::StreamExt;
|
use futures::StreamExt;
|
||||||
use log::*;
|
use log::*;
|
||||||
use nym_crypto::asymmetric::x25519;
|
use nym_crypto::asymmetric::encryption;
|
||||||
use nym_crypto::Digest;
|
use nym_crypto::Digest;
|
||||||
use nym_gateway_client::MixnetMessageReceiver;
|
use nym_gateway_client::MixnetMessageReceiver;
|
||||||
use nym_sphinx::anonymous_replies::requests::{
|
use nym_sphinx::anonymous_replies::requests::{
|
||||||
@@ -39,7 +39,7 @@ pub type ReconstructedMessagesReceiver = mpsc::UnboundedReceiver<Vec<Reconstruct
|
|||||||
|
|
||||||
struct ReceivedMessagesBufferInner<R: MessageReceiver> {
|
struct ReceivedMessagesBufferInner<R: MessageReceiver> {
|
||||||
messages: Vec<ReconstructedMessage>,
|
messages: Vec<ReconstructedMessage>,
|
||||||
local_encryption_keypair: Arc<x25519::KeyPair>,
|
local_encryption_keypair: Arc<encryption::KeyPair>,
|
||||||
|
|
||||||
// TODO: looking how it 'looks' here, perhaps `MessageReceiver` should be renamed to something
|
// TODO: looking how it 'looks' here, perhaps `MessageReceiver` should be renamed to something
|
||||||
// else instead.
|
// else instead.
|
||||||
@@ -176,7 +176,7 @@ struct ReceivedMessagesBuffer<R: MessageReceiver> {
|
|||||||
|
|
||||||
impl<R: MessageReceiver> ReceivedMessagesBuffer<R> {
|
impl<R: MessageReceiver> ReceivedMessagesBuffer<R> {
|
||||||
fn new(
|
fn new(
|
||||||
local_encryption_keypair: Arc<x25519::KeyPair>,
|
local_encryption_keypair: Arc<encryption::KeyPair>,
|
||||||
reply_key_storage: SentReplyKeys,
|
reply_key_storage: SentReplyKeys,
|
||||||
reply_controller_sender: ReplyControllerSender,
|
reply_controller_sender: ReplyControllerSender,
|
||||||
stats_tx: ClientStatsSender,
|
stats_tx: ClientStatsSender,
|
||||||
@@ -250,10 +250,10 @@ impl<R: MessageReceiver> ReceivedMessagesBuffer<R> {
|
|||||||
let mut reconstructed = Vec::new();
|
let mut reconstructed = Vec::new();
|
||||||
for msg in msgs {
|
for msg in msgs {
|
||||||
let (reply_surbs, from_surb_request) = match msg.content {
|
let (reply_surbs, from_surb_request) = match msg.content {
|
||||||
RepliableMessageContent::Data(content) => {
|
RepliableMessageContent::Data {
|
||||||
let reply_surbs = content.reply_surbs;
|
message,
|
||||||
let message = content.message;
|
reply_surbs,
|
||||||
|
} => {
|
||||||
trace!(
|
trace!(
|
||||||
"received message that also contained additional {} reply surbs from {:?}!",
|
"received message that also contained additional {} reply surbs from {:?}!",
|
||||||
reply_surbs.len(),
|
reply_surbs.len(),
|
||||||
@@ -264,9 +264,7 @@ impl<R: MessageReceiver> ReceivedMessagesBuffer<R> {
|
|||||||
|
|
||||||
(reply_surbs, false)
|
(reply_surbs, false)
|
||||||
}
|
}
|
||||||
RepliableMessageContent::AdditionalSurbs(content) => {
|
RepliableMessageContent::AdditionalSurbs { reply_surbs } => {
|
||||||
let reply_surbs = content.reply_surbs;
|
|
||||||
|
|
||||||
trace!(
|
trace!(
|
||||||
"received additional {} reply surbs from {:?}!",
|
"received additional {} reply surbs from {:?}!",
|
||||||
reply_surbs.len(),
|
reply_surbs.len(),
|
||||||
@@ -274,37 +272,9 @@ impl<R: MessageReceiver> ReceivedMessagesBuffer<R> {
|
|||||||
);
|
);
|
||||||
(reply_surbs, true)
|
(reply_surbs, true)
|
||||||
}
|
}
|
||||||
RepliableMessageContent::Heartbeat(content) => {
|
RepliableMessageContent::Heartbeat {
|
||||||
let additional_reply_surbs = content.additional_reply_surbs;
|
additional_reply_surbs,
|
||||||
error!("received a repliable heartbeat message - we don't know how to handle it yet (and we won't know until future PRs)");
|
} => {
|
||||||
(additional_reply_surbs, false)
|
|
||||||
}
|
|
||||||
RepliableMessageContent::DataV2(content) => {
|
|
||||||
let reply_surbs = content.reply_surbs;
|
|
||||||
let message = content.message;
|
|
||||||
|
|
||||||
trace!(
|
|
||||||
"received message that also contained additional {} reply surbs from {:?}!",
|
|
||||||
reply_surbs.len(),
|
|
||||||
msg.sender_tag
|
|
||||||
);
|
|
||||||
|
|
||||||
reconstructed.push(ReconstructedMessage::new(message, msg.sender_tag));
|
|
||||||
|
|
||||||
(reply_surbs, false)
|
|
||||||
}
|
|
||||||
RepliableMessageContent::AdditionalSurbsV2(content) => {
|
|
||||||
let reply_surbs = content.reply_surbs;
|
|
||||||
|
|
||||||
trace!(
|
|
||||||
"received additional {} reply surbs from {:?}!",
|
|
||||||
reply_surbs.len(),
|
|
||||||
msg.sender_tag
|
|
||||||
);
|
|
||||||
(reply_surbs, true)
|
|
||||||
}
|
|
||||||
RepliableMessageContent::HeartbeatV2(content) => {
|
|
||||||
let additional_reply_surbs = content.additional_reply_surbs;
|
|
||||||
error!("received a repliable heartbeat message - we don't know how to handle it yet (and we won't know until future PRs)");
|
error!("received a repliable heartbeat message - we don't know how to handle it yet (and we won't know until future PRs)");
|
||||||
(additional_reply_surbs, false)
|
(additional_reply_surbs, false)
|
||||||
}
|
}
|
||||||
@@ -566,7 +536,7 @@ pub(crate) struct ReceivedMessagesBufferController<R: MessageReceiver> {
|
|||||||
|
|
||||||
impl<R: MessageReceiver + Clone + Send + 'static> ReceivedMessagesBufferController<R> {
|
impl<R: MessageReceiver + Clone + Send + 'static> ReceivedMessagesBufferController<R> {
|
||||||
pub(crate) fn new(
|
pub(crate) fn new(
|
||||||
local_encryption_keypair: Arc<x25519::KeyPair>,
|
local_encryption_keypair: Arc<encryption::KeyPair>,
|
||||||
query_receiver: ReceivedBufferRequestReceiver,
|
query_receiver: ReceivedBufferRequestReceiver,
|
||||||
mixnet_packet_receiver: MixnetMessageReceiver,
|
mixnet_packet_receiver: MixnetMessageReceiver,
|
||||||
reply_key_storage: SentReplyKeys,
|
reply_key_storage: SentReplyKeys,
|
||||||
|
|||||||
@@ -0,0 +1,214 @@
|
|||||||
|
use crate::config::GroupBy;
|
||||||
|
use log::{debug, error};
|
||||||
|
use nym_explorer_client::{ExplorerClient, PrettyDetailedMixNodeBond};
|
||||||
|
use nym_network_defaults::var_names::EXPLORER_API;
|
||||||
|
use nym_topology::{
|
||||||
|
provider_trait::{async_trait, TopologyProvider},
|
||||||
|
NymTopology,
|
||||||
|
};
|
||||||
|
use nym_validator_client::client::NodeId;
|
||||||
|
use rand::{prelude::SliceRandom, thread_rng};
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use tap::TapOptional;
|
||||||
|
use url::Url;
|
||||||
|
|
||||||
|
pub use nym_country_group::CountryGroup;
|
||||||
|
|
||||||
|
fn create_explorer_client() -> Option<ExplorerClient> {
|
||||||
|
let Ok(explorer_api_url) = std::env::var(EXPLORER_API) else {
|
||||||
|
error!("Missing EXPLORER_API");
|
||||||
|
return None;
|
||||||
|
};
|
||||||
|
|
||||||
|
let Ok(explorer_api_url) = explorer_api_url.parse() else {
|
||||||
|
error!("Failed to parse EXPLORER_API");
|
||||||
|
return None;
|
||||||
|
};
|
||||||
|
|
||||||
|
log::debug!("Using explorer-api url: {}", explorer_api_url);
|
||||||
|
let Ok(client) = nym_explorer_client::ExplorerClient::new(explorer_api_url) else {
|
||||||
|
error!("Failed to create explorer-api client");
|
||||||
|
return None;
|
||||||
|
};
|
||||||
|
|
||||||
|
Some(client)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn group_mixnodes_by_country_code(
|
||||||
|
mixnodes: Vec<PrettyDetailedMixNodeBond>,
|
||||||
|
) -> HashMap<CountryGroup, Vec<NodeId>> {
|
||||||
|
mixnodes
|
||||||
|
.into_iter()
|
||||||
|
.fold(HashMap::<CountryGroup, Vec<NodeId>>::new(), |mut acc, m| {
|
||||||
|
if let Some(ref location) = m.location {
|
||||||
|
let country_code = location.two_letter_iso_country_code.clone();
|
||||||
|
let group_code = CountryGroup::new(country_code.as_str());
|
||||||
|
let mixnodes = acc.entry(group_code).or_default();
|
||||||
|
mixnodes.push(m.mix_id);
|
||||||
|
}
|
||||||
|
acc
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn log_mixnode_distribution(mixnodes: &HashMap<CountryGroup, Vec<NodeId>>) {
|
||||||
|
let mixnode_distribution = mixnodes
|
||||||
|
.iter()
|
||||||
|
.map(|(k, v)| format!("{}: {}", k, v.len()))
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join(", ");
|
||||||
|
debug!("Mixnode distribution - {}", mixnode_distribution);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_layer_integrity(topology: NymTopology) -> Result<(), ()> {
|
||||||
|
if topology.ensure_minimally_routable().is_err() {
|
||||||
|
error!("Layer is missing in topology!");
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[deprecated(note = "use NymApiTopologyProvider instead as explorer API will soon be removed")]
|
||||||
|
pub struct GeoAwareTopologyProvider {
|
||||||
|
validator_client: nym_validator_client::client::NymApiClient,
|
||||||
|
filter_on: GroupBy,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(deprecated)]
|
||||||
|
impl GeoAwareTopologyProvider {
|
||||||
|
pub fn new(mut nym_api_urls: Vec<Url>, filter_on: GroupBy) -> GeoAwareTopologyProvider {
|
||||||
|
log::info!(
|
||||||
|
"Creating geo-aware topology provider with filter on {}",
|
||||||
|
filter_on
|
||||||
|
);
|
||||||
|
nym_api_urls.shuffle(&mut thread_rng());
|
||||||
|
|
||||||
|
GeoAwareTopologyProvider {
|
||||||
|
validator_client: nym_validator_client::client::NymApiClient::new(
|
||||||
|
nym_api_urls[0].clone(),
|
||||||
|
),
|
||||||
|
filter_on,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_topology(&self) -> Option<NymTopology> {
|
||||||
|
let rewarded_set = self
|
||||||
|
.validator_client
|
||||||
|
.get_current_rewarded_set()
|
||||||
|
.await
|
||||||
|
.inspect_err(|err| error!("failed to get current rewarded set: {err}"))
|
||||||
|
.ok()?;
|
||||||
|
|
||||||
|
let mut topology = NymTopology::new_empty(rewarded_set);
|
||||||
|
|
||||||
|
let mixnodes = match self
|
||||||
|
.validator_client
|
||||||
|
.get_all_basic_active_mixing_assigned_nodes()
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
Err(err) => {
|
||||||
|
error!("failed to get network mixnodes - {err}");
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
Ok(mixes) => mixes,
|
||||||
|
};
|
||||||
|
|
||||||
|
let gateways = match self
|
||||||
|
.validator_client
|
||||||
|
.get_all_basic_entry_assigned_nodes()
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
Err(err) => {
|
||||||
|
error!("failed to get network gateways - {err}");
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
Ok(gateways) => gateways,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Also fetch mixnodes cached by explorer-api, with the purpose of getting their
|
||||||
|
// geolocation.
|
||||||
|
debug!("Fetching mixnodes from explorer-api...");
|
||||||
|
let explorer_client = create_explorer_client()?;
|
||||||
|
let Ok(mixnodes_from_explorer_api) = explorer_client.get_mixnodes().await else {
|
||||||
|
error!("failed to get mixnodes from explorer-api");
|
||||||
|
return None;
|
||||||
|
};
|
||||||
|
|
||||||
|
debug!("Fetching gateways from explorer-api...");
|
||||||
|
let Ok(gateways_from_explorer_api) = explorer_client.get_gateways().await else {
|
||||||
|
error!("failed to get mixnodes from explorer-api");
|
||||||
|
return None;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Determine what we should filter around
|
||||||
|
let filter_on = match self.filter_on {
|
||||||
|
GroupBy::CountryGroup(group) => group,
|
||||||
|
GroupBy::NymAddress(recipient) => {
|
||||||
|
// Convert recipient into a country group by extracting out the gateway part and
|
||||||
|
// using that as the country code.
|
||||||
|
let gateway = recipient.gateway().to_base58_string();
|
||||||
|
|
||||||
|
// Lookup the location of this gateway by using the location data from the
|
||||||
|
// explorer-api
|
||||||
|
let gateway_location = gateways_from_explorer_api
|
||||||
|
.iter()
|
||||||
|
.find(|g| g.gateway.identity_key == gateway)
|
||||||
|
.and_then(|g| g.location.clone())
|
||||||
|
.map(|location| location.two_letter_iso_country_code)
|
||||||
|
.tap_none(|| error!("No location found for the gateway: {}", gateway))?;
|
||||||
|
debug!(
|
||||||
|
"Filtering on nym-address: {}, with location: {}",
|
||||||
|
recipient, gateway_location
|
||||||
|
);
|
||||||
|
|
||||||
|
CountryGroup::new(&gateway_location)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
debug!("Filter group: {}", filter_on);
|
||||||
|
|
||||||
|
// Partition mixnodes_from_explorer_api according to the value of
|
||||||
|
// two_letter_iso_country_code.
|
||||||
|
// NOTE: we construct the full distribution here, but only use the one we're interested in.
|
||||||
|
// The reason we this instead of a straight filter is that this opens up the possibility to
|
||||||
|
// complement a small grouping with mixnodes from adjecent countries.
|
||||||
|
let mixnode_distribution = group_mixnodes_by_country_code(mixnodes_from_explorer_api);
|
||||||
|
log_mixnode_distribution(&mixnode_distribution);
|
||||||
|
|
||||||
|
let Some(filtered_mixnode_ids) = mixnode_distribution.get(&filter_on) else {
|
||||||
|
error!("no mixnodes found for: {}", filter_on);
|
||||||
|
return None;
|
||||||
|
};
|
||||||
|
|
||||||
|
let mixnodes = mixnodes
|
||||||
|
.into_iter()
|
||||||
|
.filter(|m| filtered_mixnode_ids.contains(&m.node_id))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
topology.add_skimmed_nodes(&mixnodes);
|
||||||
|
topology.add_skimmed_nodes(&gateways);
|
||||||
|
|
||||||
|
// TODO: return real error type
|
||||||
|
check_layer_integrity(topology.clone()).ok()?;
|
||||||
|
|
||||||
|
Some(topology)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(deprecated)]
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
#[async_trait]
|
||||||
|
impl TopologyProvider for GeoAwareTopologyProvider {
|
||||||
|
// this will be manually refreshed on a timer specified inside mixnet client config
|
||||||
|
async fn get_new_topology(&mut self) -> Option<NymTopology> {
|
||||||
|
self.get_topology().await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(deprecated)]
|
||||||
|
#[cfg(target_arch = "wasm32")]
|
||||||
|
#[async_trait(?Send)]
|
||||||
|
impl TopologyProvider for GeoAwareTopologyProvider {
|
||||||
|
// this will be manually refreshed on a timer specified inside mixnet client config
|
||||||
|
async fn get_new_topology(&mut self) -> Option<NymTopology> {
|
||||||
|
self.get_topology().await
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -17,8 +17,11 @@ use tokio::time::sleep;
|
|||||||
use wasmtimer::tokio::sleep;
|
use wasmtimer::tokio::sleep;
|
||||||
|
|
||||||
mod accessor;
|
mod accessor;
|
||||||
|
pub mod geo_aware_provider;
|
||||||
pub mod nym_api_provider;
|
pub mod nym_api_provider;
|
||||||
|
|
||||||
|
#[allow(deprecated)]
|
||||||
|
pub use geo_aware_provider::GeoAwareTopologyProvider;
|
||||||
pub use nym_api_provider::{Config as NymApiTopologyProviderConfig, NymApiTopologyProvider};
|
pub use nym_api_provider::{Config as NymApiTopologyProviderConfig, NymApiTopologyProvider};
|
||||||
pub use nym_topology::provider_trait::TopologyProvider;
|
pub use nym_topology::provider_trait::TopologyProvider;
|
||||||
|
|
||||||
@@ -157,12 +160,6 @@ impl TopologyRefresher {
|
|||||||
let mut interval =
|
let mut interval =
|
||||||
gloo_timers::future::IntervalStream::new(self.refresh_rate.as_millis() as u32);
|
gloo_timers::future::IntervalStream::new(self.refresh_rate.as_millis() as u32);
|
||||||
|
|
||||||
// We already have an initial topology, so no need to refresh it immediately.
|
|
||||||
// My understanding is that js setInterval does not fire immediately, so it's not
|
|
||||||
// needed there.
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
|
||||||
interval.next().await;
|
|
||||||
|
|
||||||
while !self.task_client.is_shutdown() {
|
while !self.task_client.is_shutdown() {
|
||||||
tokio::select! {
|
tokio::select! {
|
||||||
_ = interval.next() => {
|
_ = interval.next() => {
|
||||||
|
|||||||
@@ -70,10 +70,6 @@ impl NymApiTopologyProvider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn disable_bincode(&mut self) {
|
|
||||||
self.validator_client.use_bincode = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn use_next_nym_api(&mut self) {
|
fn use_next_nym_api(&mut self) {
|
||||||
if self.nym_api_urls.len() == 1 {
|
if self.nym_api_urls.len() == 1 {
|
||||||
warn!("There's only a single nym API available - it won't be possible to use a different one");
|
warn!("There's only a single nym API available - it won't be possible to use a different one");
|
||||||
@@ -86,13 +82,20 @@ impl NymApiTopologyProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn get_current_compatible_topology(&mut self) -> Option<NymTopology> {
|
async fn get_current_compatible_topology(&mut self) -> Option<NymTopology> {
|
||||||
let rewarded_set_fut = self.validator_client.get_current_rewarded_set();
|
let rewarded_set = self
|
||||||
|
.validator_client
|
||||||
|
.get_current_rewarded_set()
|
||||||
|
.await
|
||||||
|
.inspect_err(|err| error!("failed to get current rewarded set: {err}"))
|
||||||
|
.ok()?;
|
||||||
|
|
||||||
let topology = if self.config.use_extended_topology {
|
let mut topology = NymTopology::new_empty(rewarded_set);
|
||||||
let all_nodes_fut = self.validator_client.get_all_basic_nodes();
|
|
||||||
|
|
||||||
// Join rewarded_set_fut and all_nodes_fut concurrently
|
if self.config.use_extended_topology {
|
||||||
let (rewarded_set, all_nodes) = futures::try_join!(rewarded_set_fut, all_nodes_fut)
|
let all_nodes = self
|
||||||
|
.validator_client
|
||||||
|
.get_all_basic_nodes()
|
||||||
|
.await
|
||||||
.inspect_err(|err| error!("failed to get network nodes: {err}"))
|
.inspect_err(|err| error!("failed to get network nodes: {err}"))
|
||||||
.ok()?;
|
.ok()?;
|
||||||
|
|
||||||
@@ -100,28 +103,26 @@ impl NymApiTopologyProvider {
|
|||||||
"there are {} nodes on the network (before filtering)",
|
"there are {} nodes on the network (before filtering)",
|
||||||
all_nodes.len()
|
all_nodes.len()
|
||||||
);
|
);
|
||||||
let mut topology = NymTopology::new_empty(rewarded_set);
|
|
||||||
topology.add_additional_nodes(all_nodes.iter().filter(|n| {
|
topology.add_additional_nodes(all_nodes.iter().filter(|n| {
|
||||||
n.performance.round_to_integer() >= self.config.min_node_performance()
|
n.performance.round_to_integer() >= self.config.min_node_performance()
|
||||||
}));
|
}));
|
||||||
|
|
||||||
topology
|
|
||||||
} else {
|
} else {
|
||||||
// if we're not using extended topology, we're only getting active set mixnodes and gateways
|
// if we're not using extended topology, we're only getting active set mixnodes and gateways
|
||||||
|
|
||||||
let mixnodes_fut = self
|
let mixnodes = self
|
||||||
.validator_client
|
.validator_client
|
||||||
.get_all_basic_active_mixing_assigned_nodes();
|
.get_all_basic_active_mixing_assigned_nodes()
|
||||||
|
.await
|
||||||
|
.inspect_err(|err| error!("failed to get network mixnodes: {err}"))
|
||||||
|
.ok()?;
|
||||||
|
|
||||||
// TODO: we really should be getting ACTIVE gateways only
|
// TODO: we really should be getting ACTIVE gateways only
|
||||||
let gateways_fut = self.validator_client.get_all_basic_entry_assigned_nodes();
|
let gateways = self
|
||||||
|
.validator_client
|
||||||
let (rewarded_set, mixnodes, gateways) =
|
.get_all_basic_entry_assigned_nodes()
|
||||||
futures::try_join!(rewarded_set_fut, mixnodes_fut, gateways_fut)
|
.await
|
||||||
.inspect_err(|err| {
|
.inspect_err(|err| error!("failed to get network gateways: {err}"))
|
||||||
error!("failed to get network nodes: {err}");
|
.ok()?;
|
||||||
})
|
|
||||||
.ok()?;
|
|
||||||
|
|
||||||
debug!(
|
debug!(
|
||||||
"there are {} mixnodes and {} gateways in total (before performance filtering)",
|
"there are {} mixnodes and {} gateways in total (before performance filtering)",
|
||||||
@@ -129,15 +130,12 @@ impl NymApiTopologyProvider {
|
|||||||
gateways.len()
|
gateways.len()
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut topology = NymTopology::new_empty(rewarded_set);
|
|
||||||
topology.add_additional_nodes(mixnodes.iter().filter(|m| {
|
topology.add_additional_nodes(mixnodes.iter().filter(|m| {
|
||||||
m.performance.round_to_integer() >= self.config.min_mixnode_performance
|
m.performance.round_to_integer() >= self.config.min_mixnode_performance
|
||||||
}));
|
}));
|
||||||
topology.add_additional_nodes(gateways.iter().filter(|m| {
|
topology.add_additional_nodes(gateways.iter().filter(|m| {
|
||||||
m.performance.round_to_integer() >= self.config.min_gateway_performance
|
m.performance.round_to_integer() >= self.config.min_gateway_performance
|
||||||
}));
|
}));
|
||||||
|
|
||||||
topology
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if !topology.is_minimally_routable() {
|
if !topology.is_minimally_routable() {
|
||||||
|
|||||||
@@ -4,6 +4,6 @@
|
|||||||
pub use nym_client_core_config_types::disk_persistence;
|
pub use nym_client_core_config_types::disk_persistence;
|
||||||
pub use nym_client_core_config_types::old::{
|
pub use nym_client_core_config_types::old::{
|
||||||
old_config_v1_1_13, old_config_v1_1_20, old_config_v1_1_20_2, old_config_v1_1_30,
|
old_config_v1_1_13, old_config_v1_1_20, old_config_v1_1_20_2, old_config_v1_1_30,
|
||||||
old_config_v1_1_33, old_config_v1_1_54,
|
old_config_v1_1_33,
|
||||||
};
|
};
|
||||||
pub use nym_client_core_config_types::*;
|
pub use nym_client_core_config_types::*;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
use crate::client::mix_traffic::transceiver::ErasedGatewayError;
|
use crate::client::mix_traffic::transceiver::ErasedGatewayError;
|
||||||
use nym_crypto::asymmetric::ed25519::Ed25519RecoveryError;
|
use nym_crypto::asymmetric::identity::Ed25519RecoveryError;
|
||||||
use nym_gateway_client::error::GatewayClientError;
|
use nym_gateway_client::error::GatewayClientError;
|
||||||
use nym_topology::node::RoutingNodeError;
|
use nym_topology::node::RoutingNodeError;
|
||||||
use nym_topology::{NodeId, NymTopologyError};
|
use nym_topology::{NodeId, NymTopologyError};
|
||||||
@@ -166,9 +166,6 @@ pub enum ClientCoreError {
|
|||||||
#[error("there are no gateways supporting the wss protocol available")]
|
#[error("there are no gateways supporting the wss protocol available")]
|
||||||
NoWssGateways,
|
NoWssGateways,
|
||||||
|
|
||||||
#[error("there are no gateways with compatible protocol versions available")]
|
|
||||||
NoGatewaysWithCompatibleProtocol,
|
|
||||||
|
|
||||||
#[error("the specified gateway '{gateway}' does not support the wss protocol")]
|
#[error("the specified gateway '{gateway}' does not support the wss protocol")]
|
||||||
UnsupportedWssProtocol { gateway: String },
|
UnsupportedWssProtocol { gateway: String },
|
||||||
|
|
||||||
|
|||||||
@@ -5,9 +5,8 @@ use crate::error::ClientCoreError;
|
|||||||
use crate::init::types::RegistrationResult;
|
use crate::init::types::RegistrationResult;
|
||||||
use futures::{SinkExt, StreamExt};
|
use futures::{SinkExt, StreamExt};
|
||||||
use log::{debug, info, trace, warn};
|
use log::{debug, info, trace, warn};
|
||||||
use nym_crypto::asymmetric::ed25519;
|
use nym_crypto::asymmetric::identity;
|
||||||
use nym_gateway_client::GatewayClient;
|
use nym_gateway_client::GatewayClient;
|
||||||
use nym_gateway_requests::{ClientControlRequest, ServerResponse, CURRENT_PROTOCOL_VERSION};
|
|
||||||
use nym_topology::node::RoutingNode;
|
use nym_topology::node::RoutingNode;
|
||||||
use nym_validator_client::client::IdentityKeyRef;
|
use nym_validator_client::client::IdentityKeyRef;
|
||||||
use nym_validator_client::UserAgent;
|
use nym_validator_client::UserAgent;
|
||||||
@@ -53,7 +52,7 @@ const PING_TIMEOUT: Duration = Duration::from_millis(1000);
|
|||||||
// The abstraction that some of these helpers use
|
// The abstraction that some of these helpers use
|
||||||
pub trait ConnectableGateway {
|
pub trait ConnectableGateway {
|
||||||
fn node_id(&self) -> NodeId;
|
fn node_id(&self) -> NodeId;
|
||||||
fn identity(&self) -> ed25519::PublicKey;
|
fn identity(&self) -> identity::PublicKey;
|
||||||
fn clients_address(&self, prefer_ipv6: bool) -> Option<String>;
|
fn clients_address(&self, prefer_ipv6: bool) -> Option<String>;
|
||||||
fn is_wss(&self) -> bool;
|
fn is_wss(&self) -> bool;
|
||||||
}
|
}
|
||||||
@@ -63,7 +62,7 @@ impl ConnectableGateway for RoutingNode {
|
|||||||
self.node_id
|
self.node_id
|
||||||
}
|
}
|
||||||
|
|
||||||
fn identity(&self) -> ed25519::PublicKey {
|
fn identity(&self) -> identity::PublicKey {
|
||||||
self.identity_key
|
self.identity_key
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -132,63 +131,6 @@ pub async fn gateways_for_init<R: Rng>(
|
|||||||
Ok(valid_gateways)
|
Ok(valid_gateways)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn gateways_for_init_with_protocol_validation<R: Rng>(
|
|
||||||
rng: &mut R,
|
|
||||||
nym_apis: &[Url],
|
|
||||||
user_agent: Option<UserAgent>,
|
|
||||||
minimum_performance: u8,
|
|
||||||
ignore_epoch_roles: bool,
|
|
||||||
) -> Result<Vec<RoutingNode>, ClientCoreError> {
|
|
||||||
// First get the initial list of gateways
|
|
||||||
let gateways = gateways_for_init(
|
|
||||||
rng,
|
|
||||||
nym_apis,
|
|
||||||
user_agent,
|
|
||||||
minimum_performance,
|
|
||||||
ignore_epoch_roles,
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
info!(
|
|
||||||
"Checking protocol compatibility for {} gateways...",
|
|
||||||
gateways.len()
|
|
||||||
);
|
|
||||||
|
|
||||||
// Filter out gateways with invalid protocols concurrently
|
|
||||||
let validated_gateways = Arc::new(tokio::sync::Mutex::new(Vec::new()));
|
|
||||||
|
|
||||||
futures::stream::iter(&gateways)
|
|
||||||
.for_each_concurrent(CONCURRENT_GATEWAYS_MEASURED, |gateway| async {
|
|
||||||
let id = gateway.identity();
|
|
||||||
trace!("validating protocol compatibility with {id}...");
|
|
||||||
|
|
||||||
match validate_gateway_protocol(gateway).await {
|
|
||||||
Ok(()) => {
|
|
||||||
debug!("{id}: protocol check successful");
|
|
||||||
validated_gateways.lock().await.push(gateway.clone());
|
|
||||||
}
|
|
||||||
Err(err) => {
|
|
||||||
warn!("failed to check protocol for {id}: {err}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.await;
|
|
||||||
|
|
||||||
let validated_gateways = validated_gateways.lock().await;
|
|
||||||
|
|
||||||
info!(
|
|
||||||
"Protocol check complete: {}/{} gateways responded successfully",
|
|
||||||
validated_gateways.len(),
|
|
||||||
gateways.len()
|
|
||||||
);
|
|
||||||
|
|
||||||
if validated_gateways.is_empty() {
|
|
||||||
return Err(ClientCoreError::NoGatewaysWithCompatibleProtocol);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(validated_gateways.clone())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
async fn connect(endpoint: &str) -> Result<WsConn, ClientCoreError> {
|
async fn connect(endpoint: &str) -> Result<WsConn, ClientCoreError> {
|
||||||
match tokio::time::timeout(CONN_TIMEOUT, connect_async(endpoint)).await {
|
match tokio::time::timeout(CONN_TIMEOUT, connect_async(endpoint)).await {
|
||||||
@@ -268,132 +210,6 @@ where
|
|||||||
Ok(GatewayWithLatency::new(gateway, avg))
|
Ok(GatewayWithLatency::new(gateway, avg))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn validate_gateway_protocol<G>(gateway: &G) -> Result<(), ClientCoreError>
|
|
||||||
where
|
|
||||||
G: ConnectableGateway,
|
|
||||||
{
|
|
||||||
let Some(addr) = gateway.clients_address(false) else {
|
|
||||||
return Err(ClientCoreError::UnsupportedEntry {
|
|
||||||
id: gateway.node_id(),
|
|
||||||
identity: gateway.identity().to_string(),
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
trace!(
|
|
||||||
"validating protocol compatibility with {} ({addr})...",
|
|
||||||
gateway.identity(),
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut stream = connect(&addr).await?;
|
|
||||||
|
|
||||||
// Send protocol version request
|
|
||||||
let protocol_request = ClientControlRequest::SupportedProtocol {};
|
|
||||||
|
|
||||||
// Send the request as JSON text message
|
|
||||||
stream.send(Message::from(protocol_request)).await?;
|
|
||||||
|
|
||||||
// Wait for response with timeout
|
|
||||||
let protocol_timeout = Duration::from_millis(2000);
|
|
||||||
let response_future = stream.next();
|
|
||||||
|
|
||||||
match tokio::time::timeout(protocol_timeout, response_future).await {
|
|
||||||
Err(_) => {
|
|
||||||
warn!("Gateway {} protocol check timed out", gateway.identity());
|
|
||||||
Err(ClientCoreError::GatewayConnectionTimeout)
|
|
||||||
}
|
|
||||||
Ok(Some(Ok(Message::Text(response_text)))) => {
|
|
||||||
// Try to deserialize the response
|
|
||||||
let response = ServerResponse::try_from(response_text).map_err(|_| {
|
|
||||||
ClientCoreError::GatewayClientError {
|
|
||||||
gateway_id: gateway.identity().to_base58_string(),
|
|
||||||
source: *Box::new(
|
|
||||||
nym_gateway_client::error::GatewayClientError::MalformedResponse,
|
|
||||||
),
|
|
||||||
}
|
|
||||||
})?;
|
|
||||||
|
|
||||||
match response {
|
|
||||||
ServerResponse::SupportedProtocol { version } => {
|
|
||||||
debug!(
|
|
||||||
"Gateway {} supports protocol version {}, ours: {}",
|
|
||||||
gateway.identity(),
|
|
||||||
version,
|
|
||||||
CURRENT_PROTOCOL_VERSION
|
|
||||||
);
|
|
||||||
|
|
||||||
// Check protocol compatibility
|
|
||||||
if version > CURRENT_PROTOCOL_VERSION {
|
|
||||||
warn!(
|
|
||||||
"Gateway {} uses newer protocol version {} (client supports {}). \
|
|
||||||
Gateway should gracefully degrade, but consider updating your client.",
|
|
||||||
gateway.identity(),
|
|
||||||
version,
|
|
||||||
CURRENT_PROTOCOL_VERSION
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
trace!(
|
|
||||||
"Gateway {} protocol validation successful (gateway: v{}, client: v{})",
|
|
||||||
gateway.identity(),
|
|
||||||
version,
|
|
||||||
CURRENT_PROTOCOL_VERSION
|
|
||||||
);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
ServerResponse::Error { message } => {
|
|
||||||
warn!(
|
|
||||||
"Gateway {} returned error during protocol check: {}",
|
|
||||||
gateway.identity(),
|
|
||||||
message
|
|
||||||
);
|
|
||||||
Err(ClientCoreError::GatewayClientError {
|
|
||||||
gateway_id: gateway.identity().to_base58_string(),
|
|
||||||
source: *Box::new(
|
|
||||||
nym_gateway_client::error::GatewayClientError::GatewayError(message),
|
|
||||||
),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
warn!(
|
|
||||||
"Gateway {} returned unexpected response during protocol check",
|
|
||||||
gateway.identity()
|
|
||||||
);
|
|
||||||
Err(ClientCoreError::GatewayClientError {
|
|
||||||
gateway_id: gateway.identity().to_base58_string(),
|
|
||||||
source: *Box::new(
|
|
||||||
nym_gateway_client::error::GatewayClientError::UnexpectedResponse {
|
|
||||||
name: response.name().to_string(),
|
|
||||||
},
|
|
||||||
),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(Some(Ok(_))) => {
|
|
||||||
warn!(
|
|
||||||
"Gateway {} sent non-text response during protocol check",
|
|
||||||
gateway.identity()
|
|
||||||
);
|
|
||||||
Err(ClientCoreError::GatewayConnectionAbruptlyClosed)
|
|
||||||
}
|
|
||||||
Ok(Some(Err(e))) => {
|
|
||||||
warn!(
|
|
||||||
"WebSocket error during protocol check with {}: {}",
|
|
||||||
gateway.identity(),
|
|
||||||
e
|
|
||||||
);
|
|
||||||
Err(e.into())
|
|
||||||
}
|
|
||||||
Ok(None) => {
|
|
||||||
warn!(
|
|
||||||
"Gateway {} closed connection during protocol check",
|
|
||||||
gateway.identity()
|
|
||||||
);
|
|
||||||
Err(ClientCoreError::GatewayConnectionAbruptlyClosed)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn choose_gateway_by_latency<R: Rng, G: ConnectableGateway + Clone>(
|
pub async fn choose_gateway_by_latency<R: Rng, G: ConnectableGateway + Clone>(
|
||||||
rng: &mut R,
|
rng: &mut R,
|
||||||
gateways: &[G],
|
gateways: &[G],
|
||||||
@@ -471,7 +287,7 @@ pub(super) fn get_specified_gateway(
|
|||||||
must_use_tls: bool,
|
must_use_tls: bool,
|
||||||
) -> Result<RoutingNode, ClientCoreError> {
|
) -> Result<RoutingNode, ClientCoreError> {
|
||||||
log::debug!("Requesting specified gateway: {}", gateway_identity);
|
log::debug!("Requesting specified gateway: {}", gateway_identity);
|
||||||
let user_gateway = ed25519::PublicKey::from_base58_string(gateway_identity)
|
let user_gateway = identity::PublicKey::from_base58_string(gateway_identity)
|
||||||
.map_err(ClientCoreError::UnableToCreatePublicKeyFromGatewayId)?;
|
.map_err(ClientCoreError::UnableToCreatePublicKeyFromGatewayId)?;
|
||||||
|
|
||||||
let gateway = gateways
|
let gateway = gateways
|
||||||
@@ -496,9 +312,9 @@ pub(super) fn get_specified_gateway(
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(super) async fn register_with_gateway(
|
pub(super) async fn register_with_gateway(
|
||||||
gateway_id: ed25519::PublicKey,
|
gateway_id: identity::PublicKey,
|
||||||
gateway_listener: Url,
|
gateway_listener: Url,
|
||||||
our_identity: Arc<ed25519::KeyPair>,
|
our_identity: Arc<identity::KeyPair>,
|
||||||
#[cfg(unix)] connection_fd_callback: Option<Arc<dyn Fn(RawFd) + Send + Sync>>,
|
#[cfg(unix)] connection_fd_callback: Option<Arc<dyn Fn(RawFd) + Send + Sync>>,
|
||||||
) -> Result<RegistrationResult, ClientCoreError> {
|
) -> Result<RegistrationResult, ClientCoreError> {
|
||||||
let mut gateway_client = GatewayClient::new_init(
|
let mut gateway_client = GatewayClient::new_init(
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ use crate::init::{setup_gateway, use_loaded_gateway_details};
|
|||||||
use nym_client_core_gateways_storage::{
|
use nym_client_core_gateways_storage::{
|
||||||
GatewayRegistration, GatewaysDetailsStore, RemoteGatewayDetails,
|
GatewayRegistration, GatewaysDetailsStore, RemoteGatewayDetails,
|
||||||
};
|
};
|
||||||
use nym_crypto::asymmetric::ed25519;
|
use nym_crypto::asymmetric::identity;
|
||||||
use nym_gateway_client::client::InitGatewayClient;
|
use nym_gateway_client::client::InitGatewayClient;
|
||||||
use nym_gateway_requests::shared_key::SharedGatewayKey;
|
use nym_gateway_requests::shared_key::SharedGatewayKey;
|
||||||
use nym_sphinx::addressing::clients::Recipient;
|
use nym_sphinx::addressing::clients::Recipient;
|
||||||
@@ -26,14 +26,14 @@ use url::Url;
|
|||||||
|
|
||||||
pub enum SelectedGateway {
|
pub enum SelectedGateway {
|
||||||
Remote {
|
Remote {
|
||||||
gateway_id: ed25519::PublicKey,
|
gateway_id: identity::PublicKey,
|
||||||
|
|
||||||
gateway_owner_address: Option<AccountId>,
|
gateway_owner_address: Option<AccountId>,
|
||||||
|
|
||||||
gateway_listener: Url,
|
gateway_listener: Url,
|
||||||
},
|
},
|
||||||
Custom {
|
Custom {
|
||||||
gateway_id: ed25519::PublicKey,
|
gateway_id: identity::PublicKey,
|
||||||
additional_data: Option<Vec<u8>>,
|
additional_data: Option<Vec<u8>>,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -77,7 +77,7 @@ impl SelectedGateway {
|
|||||||
gateway_id: String,
|
gateway_id: String,
|
||||||
additional_data: Option<Vec<u8>>,
|
additional_data: Option<Vec<u8>>,
|
||||||
) -> Result<Self, ClientCoreError> {
|
) -> Result<Self, ClientCoreError> {
|
||||||
let gateway_id = ed25519::PublicKey::from_base58_string(&gateway_id)
|
let gateway_id = identity::PublicKey::from_base58_string(&gateway_id)
|
||||||
.map_err(|source| ClientCoreError::MalformedGatewayIdentity { gateway_id, source })?;
|
.map_err(|source| ClientCoreError::MalformedGatewayIdentity { gateway_id, source })?;
|
||||||
|
|
||||||
Ok(SelectedGateway::Custom {
|
Ok(SelectedGateway::Custom {
|
||||||
@@ -86,7 +86,7 @@ impl SelectedGateway {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn gateway_id(&self) -> &ed25519::PublicKey {
|
pub fn gateway_id(&self) -> &identity::PublicKey {
|
||||||
match self {
|
match self {
|
||||||
SelectedGateway::Remote { gateway_id, .. } => gateway_id,
|
SelectedGateway::Remote { gateway_id, .. } => gateway_id,
|
||||||
SelectedGateway::Custom { gateway_id, .. } => gateway_id,
|
SelectedGateway::Custom { gateway_id, .. } => gateway_id,
|
||||||
@@ -142,7 +142,7 @@ impl InitialisationResult {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn gateway_id(&self) -> ed25519::PublicKey {
|
pub fn gateway_id(&self) -> identity::PublicKey {
|
||||||
self.gateway_registration.details.gateway_id()
|
self.gateway_registration.details.gateway_id()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -271,7 +271,7 @@ impl GatewaySetup {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// new gateway setup performed by each client that's inbuilt in a gateway (like NR or IPR)
|
/// new gateway setup performed by each client that's inbuilt in a gateway (like NR or IPR)
|
||||||
pub fn new_inbuilt(identity: ed25519::PublicKey) -> Self {
|
pub fn new_inbuilt(identity: identity::PublicKey) -> Self {
|
||||||
GatewaySetup::New {
|
GatewaySetup::New {
|
||||||
specification: GatewaySelectionSpecification::Custom {
|
specification: GatewaySelectionSpecification::Custom {
|
||||||
gateway_identity: identity.to_base58_string(),
|
gateway_identity: identity.to_base58_string(),
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ nym-credential-storage = { path = "../../credential-storage" }
|
|||||||
nym-credentials-interface = { path = "../../credentials-interface" }
|
nym-credentials-interface = { path = "../../credentials-interface" }
|
||||||
nym-crypto = { path = "../../crypto" }
|
nym-crypto = { path = "../../crypto" }
|
||||||
nym-gateway-requests = { path = "../../gateway-requests" }
|
nym-gateway-requests = { path = "../../gateway-requests" }
|
||||||
|
nym-http-api-client = { path = "../../http-api-client" }
|
||||||
nym-network-defaults = { path = "../../network-defaults" }
|
nym-network-defaults = { path = "../../network-defaults" }
|
||||||
nym-sphinx = { path = "../../nymsphinx" }
|
nym-sphinx = { path = "../../nymsphinx" }
|
||||||
nym-statistics-common = { path = "../../statistics" }
|
nym-statistics-common = { path = "../../statistics" }
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ use nym_credential_storage::ephemeral_storage::EphemeralStorage as EphemeralCred
|
|||||||
use nym_credential_storage::storage::Storage as CredentialStorage;
|
use nym_credential_storage::storage::Storage as CredentialStorage;
|
||||||
use nym_credentials::CredentialSpendingData;
|
use nym_credentials::CredentialSpendingData;
|
||||||
use nym_credentials_interface::TicketType;
|
use nym_credentials_interface::TicketType;
|
||||||
use nym_crypto::asymmetric::ed25519;
|
use nym_crypto::asymmetric::identity;
|
||||||
use nym_gateway_requests::registration::handshake::client_handshake;
|
use nym_gateway_requests::registration::handshake::client_handshake;
|
||||||
use nym_gateway_requests::{
|
use nym_gateway_requests::{
|
||||||
BinaryRequest, ClientControlRequest, ClientRequest, GatewayProtocolVersionExt,
|
BinaryRequest, ClientControlRequest, ClientRequest, GatewayProtocolVersionExt,
|
||||||
@@ -57,7 +57,7 @@ pub(crate) mod websockets;
|
|||||||
use websockets::connect_async;
|
use websockets::connect_async;
|
||||||
|
|
||||||
pub struct GatewayConfig {
|
pub struct GatewayConfig {
|
||||||
pub gateway_identity: ed25519::PublicKey,
|
pub gateway_identity: identity::PublicKey,
|
||||||
|
|
||||||
// currently a dead field
|
// currently a dead field
|
||||||
pub gateway_owner: Option<String>,
|
pub gateway_owner: Option<String>,
|
||||||
@@ -67,7 +67,7 @@ pub struct GatewayConfig {
|
|||||||
|
|
||||||
impl GatewayConfig {
|
impl GatewayConfig {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
gateway_identity: ed25519::PublicKey,
|
gateway_identity: identity::PublicKey,
|
||||||
gateway_owner: Option<String>,
|
gateway_owner: Option<String>,
|
||||||
gateway_listener: String,
|
gateway_listener: String,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
@@ -93,8 +93,8 @@ pub struct GatewayClient<C, St = EphemeralCredentialStorage> {
|
|||||||
authenticated: bool,
|
authenticated: bool,
|
||||||
bandwidth: ClientBandwidth,
|
bandwidth: ClientBandwidth,
|
||||||
gateway_address: String,
|
gateway_address: String,
|
||||||
gateway_identity: ed25519::PublicKey,
|
gateway_identity: identity::PublicKey,
|
||||||
local_identity: Arc<ed25519::KeyPair>,
|
local_identity: Arc<identity::KeyPair>,
|
||||||
shared_key: Option<Arc<SharedGatewayKey>>,
|
shared_key: Option<Arc<SharedGatewayKey>>,
|
||||||
connection: SocketState,
|
connection: SocketState,
|
||||||
packet_router: PacketRouter,
|
packet_router: PacketRouter,
|
||||||
@@ -117,7 +117,7 @@ impl<C, St> GatewayClient<C, St> {
|
|||||||
pub fn new(
|
pub fn new(
|
||||||
cfg: GatewayClientConfig,
|
cfg: GatewayClientConfig,
|
||||||
gateway_config: GatewayConfig,
|
gateway_config: GatewayConfig,
|
||||||
local_identity: Arc<ed25519::KeyPair>,
|
local_identity: Arc<identity::KeyPair>,
|
||||||
// TODO: make it mandatory. if you don't want to pass it, use `new_init`
|
// TODO: make it mandatory. if you don't want to pass it, use `new_init`
|
||||||
shared_key: Option<Arc<SharedGatewayKey>>,
|
shared_key: Option<Arc<SharedGatewayKey>>,
|
||||||
packet_router: PacketRouter,
|
packet_router: PacketRouter,
|
||||||
@@ -145,7 +145,7 @@ impl<C, St> GatewayClient<C, St> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn gateway_identity(&self) -> ed25519::PublicKey {
|
pub fn gateway_identity(&self) -> identity::PublicKey {
|
||||||
self.gateway_identity
|
self.gateway_identity
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -165,24 +165,6 @@ impl<C, St> GatewayClient<C, St> {
|
|||||||
self.bandwidth.remaining()
|
self.bandwidth.remaining()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_connection_established(&self) -> bool {
|
|
||||||
self.connection.is_established()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Check if the websocket connection is actually alive at the socket level
|
|
||||||
pub fn is_connection_alive(&self) -> bool {
|
|
||||||
// First check if we have an established connection
|
|
||||||
if !self.connection.is_established() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the file descriptor and check if the socket is alive
|
|
||||||
match self.ws_fd() {
|
|
||||||
Some(fd) => socket_is_alive(fd),
|
|
||||||
None => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
async fn _close_connection(&mut self) -> Result<(), GatewayClientError> {
|
async fn _close_connection(&mut self) -> Result<(), GatewayClientError> {
|
||||||
match std::mem::replace(&mut self.connection, SocketState::NotConnected) {
|
match std::mem::replace(&mut self.connection, SocketState::NotConnected) {
|
||||||
@@ -1081,8 +1063,8 @@ impl GatewayClient<InitOnly, EphemeralCredentialStorage> {
|
|||||||
// for initialisation we do not need credential storage. Though it's still a bit weird we have to set the generic...
|
// for initialisation we do not need credential storage. Though it's still a bit weird we have to set the generic...
|
||||||
pub fn new_init(
|
pub fn new_init(
|
||||||
gateway_listener: Url,
|
gateway_listener: Url,
|
||||||
gateway_identity: ed25519::PublicKey,
|
gateway_identity: identity::PublicKey,
|
||||||
local_identity: Arc<ed25519::KeyPair>,
|
local_identity: Arc<identity::KeyPair>,
|
||||||
#[cfg(unix)] connection_fd_callback: Option<Arc<dyn Fn(RawFd) + Send + Sync>>,
|
#[cfg(unix)] connection_fd_callback: Option<Arc<dyn Fn(RawFd) + Send + Sync>>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
log::trace!("Initialising gateway client");
|
log::trace!("Initialising gateway client");
|
||||||
@@ -1146,49 +1128,3 @@ impl GatewayClient<InitOnly, EphemeralCredentialStorage> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check if a socket file descriptor is alive and responsive
|
|
||||||
///
|
|
||||||
/// This function performs socket-level checks to determine if the connection is actually alive.
|
|
||||||
/// It's cross-platform compatible and works on both Unix and non-Unix systems.
|
|
||||||
fn socket_is_alive(fd: RawFd) -> bool {
|
|
||||||
#[cfg(unix)]
|
|
||||||
{
|
|
||||||
use std::io::ErrorKind;
|
|
||||||
use std::net::TcpStream;
|
|
||||||
use std::os::unix::io::FromRawFd;
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
// Create a TcpStream from the raw fd to perform socket operations
|
|
||||||
let stream = TcpStream::from_raw_fd(fd);
|
|
||||||
|
|
||||||
// Try to peek at the socket to see if it's still connected
|
|
||||||
// We peek with a zero-length buffer to avoid consuming data
|
|
||||||
let mut buf = [0u8; 0];
|
|
||||||
let result = match stream.peek(&mut buf) {
|
|
||||||
Ok(_) => true, // Socket is alive and readable
|
|
||||||
Err(e) => match e.kind() {
|
|
||||||
ErrorKind::WouldBlock => true, // Socket is alive but no data available
|
|
||||||
ErrorKind::ConnectionReset
|
|
||||||
| ErrorKind::ConnectionAborted
|
|
||||||
| ErrorKind::BrokenPipe
|
|
||||||
| ErrorKind::NotConnected => false, // Socket is clearly dead
|
|
||||||
_ => true, // Other errors might be temporary, assume alive
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
// Prevent the TcpStream from closing the fd when it's dropped
|
|
||||||
// since we don't own the fd
|
|
||||||
std::mem::forget(stream);
|
|
||||||
|
|
||||||
result
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(unix))]
|
|
||||||
{
|
|
||||||
// On non-Unix systems, we can't easily check socket state
|
|
||||||
// Fall back to assuming the connection is alive if we have an fd
|
|
||||||
fd != 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
use crate::error::GatewayClientError;
|
use crate::error::GatewayClientError;
|
||||||
|
|
||||||
|
use nym_http_api_client::HickoryDnsResolver;
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
use std::{
|
use std::{
|
||||||
os::fd::{AsRawFd, RawFd},
|
os::fd::{AsRawFd, RawFd},
|
||||||
@@ -19,6 +20,7 @@ pub(crate) async fn connect_async(
|
|||||||
) -> Result<(WebSocketStream<MaybeTlsStream<TcpStream>>, Response), GatewayClientError> {
|
) -> Result<(WebSocketStream<MaybeTlsStream<TcpStream>>, Response), GatewayClientError> {
|
||||||
use tokio::net::TcpSocket;
|
use tokio::net::TcpSocket;
|
||||||
|
|
||||||
|
let resolver = HickoryDnsResolver::default();
|
||||||
let uri =
|
let uri =
|
||||||
Url::parse(endpoint).map_err(|_| GatewayClientError::InvalidUrl(endpoint.to_owned()))?;
|
Url::parse(endpoint).map_err(|_| GatewayClientError::InvalidUrl(endpoint.to_owned()))?;
|
||||||
let port: u16 = uri.port_or_known_default().unwrap_or(443);
|
let port: u16 = uri.port_or_known_default().unwrap_or(443);
|
||||||
@@ -27,18 +29,18 @@ pub(crate) async fn connect_async(
|
|||||||
.host()
|
.host()
|
||||||
.ok_or(GatewayClientError::InvalidUrl(endpoint.to_owned()))?;
|
.ok_or(GatewayClientError::InvalidUrl(endpoint.to_owned()))?;
|
||||||
|
|
||||||
// Get address for tcp connection, using system DNS resolver
|
// Get address for tcp connection, if a domain is provided use our preferred resolver rather than
|
||||||
|
// the default std resolve
|
||||||
let sock_addrs: Vec<SocketAddr> = match host {
|
let sock_addrs: Vec<SocketAddr> = match host {
|
||||||
Host::Ipv4(addr) => vec![SocketAddr::new(addr.into(), port)],
|
Host::Ipv4(addr) => vec![SocketAddr::new(addr.into(), port)],
|
||||||
Host::Ipv6(addr) => vec![SocketAddr::new(addr.into(), port)],
|
Host::Ipv6(addr) => vec![SocketAddr::new(addr.into(), port)],
|
||||||
Host::Domain(domain) => {
|
Host::Domain(domain) => {
|
||||||
// Do a DNS lookup for the domain using system DNS resolver
|
// Do a DNS lookup for the domain using our custom DNS resolver
|
||||||
tokio::net::lookup_host((domain, port))
|
resolver
|
||||||
.await
|
.resolve_str(domain)
|
||||||
.map_err(|err| GatewayClientError::NetworkConnectionFailed {
|
.await?
|
||||||
address: endpoint.to_owned(),
|
.into_iter()
|
||||||
source: err.into(),
|
.map(|a| SocketAddr::new(a, port))
|
||||||
})?
|
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -49,6 +49,10 @@ pub enum GatewayClientError {
|
|||||||
#[error("Invalid URL: {0}")]
|
#[error("Invalid URL: {0}")]
|
||||||
InvalidUrl(String),
|
InvalidUrl(String),
|
||||||
|
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
#[error("resolution failed: {0}")]
|
||||||
|
ResolutionFailed(#[from] nym_http_api_client::HickoryDnsError),
|
||||||
|
|
||||||
#[error("No shared key was provided or obtained")]
|
#[error("No shared key was provided or obtained")]
|
||||||
NoSharedKeyAvailable,
|
NoSharedKeyAvailable,
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ use futures::channel::oneshot;
|
|||||||
use futures::stream::{SplitSink, SplitStream};
|
use futures::stream::{SplitSink, SplitStream};
|
||||||
use futures::{SinkExt, StreamExt};
|
use futures::{SinkExt, StreamExt};
|
||||||
use nym_gateway_requests::shared_key::SharedGatewayKey;
|
use nym_gateway_requests::shared_key::SharedGatewayKey;
|
||||||
use nym_gateway_requests::{SensitiveServerResponse, ServerResponse, SimpleGatewayRequestsError};
|
use nym_gateway_requests::{ServerResponse, SimpleGatewayRequestsError};
|
||||||
use nym_task::TaskClient;
|
use nym_task::TaskClient;
|
||||||
use si_scale::helpers::bibytes2;
|
use si_scale::helpers::bibytes2;
|
||||||
use std::os::raw::c_int as RawFd;
|
use std::os::raw::c_int as RawFd;
|
||||||
@@ -188,34 +188,6 @@ impl PartiallyDelegatedRouter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ServerResponse::EncryptedResponse { ciphertext, nonce } => {
|
|
||||||
match SensitiveServerResponse::decrypt(
|
|
||||||
&ciphertext,
|
|
||||||
&nonce,
|
|
||||||
self.shared_key.as_ref(),
|
|
||||||
) {
|
|
||||||
Ok(response) => match response {
|
|
||||||
SensitiveServerResponse::ForgetMeAck {} => {
|
|
||||||
info!("received forget me acknowledgement");
|
|
||||||
}
|
|
||||||
SensitiveServerResponse::RememberMeAck {} => {
|
|
||||||
info!("received remember me acknowledgement");
|
|
||||||
}
|
|
||||||
SensitiveServerResponse::KeyUpgradeAck {} => {
|
|
||||||
warn!(
|
|
||||||
"received illegal key upgrade acknowledgement in an authenticated client"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
warn!("received unknown SensitiveServerResponse");
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Err(e) => {
|
|
||||||
error!("failed to handle encrypted response: {e}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
other => {
|
other => {
|
||||||
let name = other.name();
|
let name = other.name();
|
||||||
warn!("received illegal message of type '{name}' in an authenticated client");
|
warn!("received illegal message of type '{name}' in an authenticated client");
|
||||||
|
|||||||
@@ -345,47 +345,25 @@ impl<C, S> Client<C, S> {
|
|||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct NymApiClient {
|
pub struct NymApiClient {
|
||||||
pub use_bincode: bool,
|
|
||||||
pub nym_api: nym_api::Client,
|
pub nym_api: nym_api::Client,
|
||||||
// TODO: perhaps if we really need it at some (currently I don't see any reasons for it)
|
// TODO: perhaps if we really need it at some (currently I don't see any reasons for it)
|
||||||
// we could re-implement the communication with the REST API on port 1317
|
// we could re-implement the communication with the REST API on port 1317
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<nym_api::Client> for NymApiClient {
|
|
||||||
fn from(nym_api: nym_api::Client) -> Self {
|
|
||||||
NymApiClient {
|
|
||||||
use_bincode: false,
|
|
||||||
nym_api,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// we have to allow the use of deprecated method here as they're calling the deprecated trait methods
|
// we have to allow the use of deprecated method here as they're calling the deprecated trait methods
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
impl NymApiClient {
|
impl NymApiClient {
|
||||||
pub fn new(api_url: Url) -> Self {
|
pub fn new(api_url: Url) -> Self {
|
||||||
let nym_api = nym_api::Client::new(api_url, None);
|
let nym_api = nym_api::Client::new(api_url, None);
|
||||||
|
|
||||||
NymApiClient {
|
NymApiClient { nym_api }
|
||||||
use_bincode: true,
|
|
||||||
nym_api,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
pub fn new_with_timeout(api_url: Url, timeout: std::time::Duration) -> Self {
|
pub fn new_with_timeout(api_url: Url, timeout: std::time::Duration) -> Self {
|
||||||
let nym_api = nym_api::Client::new(api_url, Some(timeout));
|
let nym_api = nym_api::Client::new(api_url, Some(timeout));
|
||||||
|
|
||||||
NymApiClient {
|
NymApiClient { nym_api }
|
||||||
use_bincode: true,
|
|
||||||
nym_api,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[must_use]
|
|
||||||
pub fn with_bincode(mut self, use_bincode: bool) -> Self {
|
|
||||||
self.use_bincode = use_bincode;
|
|
||||||
self
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_with_user_agent(api_url: Url, user_agent: impl Into<UserAgent>) -> Self {
|
pub fn new_with_user_agent(api_url: Url, user_agent: impl Into<UserAgent>) -> Self {
|
||||||
@@ -395,10 +373,7 @@ impl NymApiClient {
|
|||||||
.build::<ValidatorClientError>()
|
.build::<ValidatorClientError>()
|
||||||
.expect("failed to build nym api client");
|
.expect("failed to build nym api client");
|
||||||
|
|
||||||
NymApiClient {
|
NymApiClient { nym_api }
|
||||||
use_bincode: false,
|
|
||||||
nym_api,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn api_url(&self) -> &Url {
|
pub fn api_url(&self) -> &Url {
|
||||||
@@ -435,7 +410,7 @@ impl NymApiClient {
|
|||||||
loop {
|
loop {
|
||||||
let mut res = self
|
let mut res = self
|
||||||
.nym_api
|
.nym_api
|
||||||
.get_basic_entry_assigned_nodes(false, Some(page), None, self.use_bincode)
|
.get_basic_entry_assigned_nodes(false, Some(page), None)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
nodes.append(&mut res.nodes.data);
|
nodes.append(&mut res.nodes.data);
|
||||||
@@ -461,7 +436,7 @@ impl NymApiClient {
|
|||||||
loop {
|
loop {
|
||||||
let mut res = self
|
let mut res = self
|
||||||
.nym_api
|
.nym_api
|
||||||
.get_basic_active_mixing_assigned_nodes(false, Some(page), None, self.use_bincode)
|
.get_basic_active_mixing_assigned_nodes(false, Some(page), None)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
nodes.append(&mut res.nodes.data);
|
nodes.append(&mut res.nodes.data);
|
||||||
@@ -487,7 +462,7 @@ impl NymApiClient {
|
|||||||
loop {
|
loop {
|
||||||
let mut res = self
|
let mut res = self
|
||||||
.nym_api
|
.nym_api
|
||||||
.get_basic_mixing_capable_nodes(false, Some(page), None, self.use_bincode)
|
.get_basic_mixing_capable_nodes(false, Some(page), None)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
nodes.append(&mut res.nodes.data);
|
nodes.append(&mut res.nodes.data);
|
||||||
@@ -510,7 +485,7 @@ impl NymApiClient {
|
|||||||
loop {
|
loop {
|
||||||
let mut res = self
|
let mut res = self
|
||||||
.nym_api
|
.nym_api
|
||||||
.get_basic_nodes(false, Some(page), None, self.use_bincode)
|
.get_basic_nodes(false, Some(page), None)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
nodes.append(&mut res.nodes.data);
|
nodes.append(&mut res.nodes.data);
|
||||||
|
|||||||
@@ -318,7 +318,6 @@ pub trait NymApiClientExt: ApiClient {
|
|||||||
no_legacy: bool,
|
no_legacy: bool,
|
||||||
page: Option<u32>,
|
page: Option<u32>,
|
||||||
per_page: Option<u32>,
|
per_page: Option<u32>,
|
||||||
use_bincode: bool,
|
|
||||||
) -> Result<PaginatedCachedNodesResponse<SkimmedNode>, NymAPIError> {
|
) -> Result<PaginatedCachedNodesResponse<SkimmedNode>, NymAPIError> {
|
||||||
let mut params = Vec::new();
|
let mut params = Vec::new();
|
||||||
|
|
||||||
@@ -334,11 +333,7 @@ pub trait NymApiClientExt: ApiClient {
|
|||||||
params.push(("per_page", per_page.to_string()))
|
params.push(("per_page", per_page.to_string()))
|
||||||
}
|
}
|
||||||
|
|
||||||
if use_bincode {
|
self.get_json(
|
||||||
params.push(("output", "bincode".to_string()))
|
|
||||||
}
|
|
||||||
|
|
||||||
self.get_response(
|
|
||||||
&[
|
&[
|
||||||
routes::API_VERSION,
|
routes::API_VERSION,
|
||||||
"unstable",
|
"unstable",
|
||||||
@@ -360,7 +355,6 @@ pub trait NymApiClientExt: ApiClient {
|
|||||||
no_legacy: bool,
|
no_legacy: bool,
|
||||||
page: Option<u32>,
|
page: Option<u32>,
|
||||||
per_page: Option<u32>,
|
per_page: Option<u32>,
|
||||||
use_bincode: bool,
|
|
||||||
) -> Result<PaginatedCachedNodesResponse<SkimmedNode>, NymAPIError> {
|
) -> Result<PaginatedCachedNodesResponse<SkimmedNode>, NymAPIError> {
|
||||||
let mut params = Vec::new();
|
let mut params = Vec::new();
|
||||||
|
|
||||||
@@ -376,11 +370,7 @@ pub trait NymApiClientExt: ApiClient {
|
|||||||
params.push(("per_page", per_page.to_string()))
|
params.push(("per_page", per_page.to_string()))
|
||||||
}
|
}
|
||||||
|
|
||||||
if use_bincode {
|
self.get_json(
|
||||||
params.push(("output", "bincode".to_string()))
|
|
||||||
}
|
|
||||||
|
|
||||||
self.get_response(
|
|
||||||
&[
|
&[
|
||||||
routes::API_VERSION,
|
routes::API_VERSION,
|
||||||
"unstable",
|
"unstable",
|
||||||
@@ -402,7 +392,6 @@ pub trait NymApiClientExt: ApiClient {
|
|||||||
no_legacy: bool,
|
no_legacy: bool,
|
||||||
page: Option<u32>,
|
page: Option<u32>,
|
||||||
per_page: Option<u32>,
|
per_page: Option<u32>,
|
||||||
use_bincode: bool,
|
|
||||||
) -> Result<PaginatedCachedNodesResponse<SkimmedNode>, NymAPIError> {
|
) -> Result<PaginatedCachedNodesResponse<SkimmedNode>, NymAPIError> {
|
||||||
let mut params = Vec::new();
|
let mut params = Vec::new();
|
||||||
|
|
||||||
@@ -418,11 +407,7 @@ pub trait NymApiClientExt: ApiClient {
|
|||||||
params.push(("per_page", per_page.to_string()))
|
params.push(("per_page", per_page.to_string()))
|
||||||
}
|
}
|
||||||
|
|
||||||
if use_bincode {
|
self.get_json(
|
||||||
params.push(("output", "bincode".to_string()))
|
|
||||||
}
|
|
||||||
|
|
||||||
self.get_response(
|
|
||||||
&[
|
&[
|
||||||
routes::API_VERSION,
|
routes::API_VERSION,
|
||||||
"unstable",
|
"unstable",
|
||||||
@@ -442,7 +427,6 @@ pub trait NymApiClientExt: ApiClient {
|
|||||||
no_legacy: bool,
|
no_legacy: bool,
|
||||||
page: Option<u32>,
|
page: Option<u32>,
|
||||||
per_page: Option<u32>,
|
per_page: Option<u32>,
|
||||||
use_bincode: bool,
|
|
||||||
) -> Result<PaginatedCachedNodesResponse<SkimmedNode>, NymAPIError> {
|
) -> Result<PaginatedCachedNodesResponse<SkimmedNode>, NymAPIError> {
|
||||||
let mut params = Vec::new();
|
let mut params = Vec::new();
|
||||||
|
|
||||||
@@ -458,11 +442,7 @@ pub trait NymApiClientExt: ApiClient {
|
|||||||
params.push(("per_page", per_page.to_string()))
|
params.push(("per_page", per_page.to_string()))
|
||||||
}
|
}
|
||||||
|
|
||||||
if use_bincode {
|
self.get_json(
|
||||||
params.push(("output", "bincode".to_string()))
|
|
||||||
}
|
|
||||||
|
|
||||||
self.get_response(
|
|
||||||
&[
|
&[
|
||||||
routes::API_VERSION,
|
routes::API_VERSION,
|
||||||
"unstable",
|
"unstable",
|
||||||
|
|||||||
@@ -73,7 +73,6 @@ pub const STAKE_SATURATION: &str = "stake-saturation";
|
|||||||
pub const INCLUSION_CHANCE: &str = "inclusion-probability";
|
pub const INCLUSION_CHANCE: &str = "inclusion-probability";
|
||||||
pub const SUBMIT_GATEWAY: &str = "submit-gateway-monitoring-results";
|
pub const SUBMIT_GATEWAY: &str = "submit-gateway-monitoring-results";
|
||||||
pub const SUBMIT_NODE: &str = "submit-node-monitoring-results";
|
pub const SUBMIT_NODE: &str = "submit-node-monitoring-results";
|
||||||
pub const SUBMIT_ROUTE: &str = "submit-route-monitoring-results";
|
|
||||||
|
|
||||||
pub const SERVICE_PROVIDERS: &str = "services";
|
pub const SERVICE_PROVIDERS: &str = "services";
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ use nym_credentials::{
|
|||||||
AggregatedCoinIndicesSignatures, AggregatedExpirationDateSignatures, EpochVerificationKey,
|
AggregatedCoinIndicesSignatures, AggregatedExpirationDateSignatures, EpochVerificationKey,
|
||||||
};
|
};
|
||||||
use nym_credentials_interface::TicketType;
|
use nym_credentials_interface::TicketType;
|
||||||
use nym_crypto::asymmetric::ed25519;
|
use nym_crypto::asymmetric::identity;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use tempfile::NamedTempFile;
|
use tempfile::NamedTempFile;
|
||||||
@@ -83,7 +83,7 @@ async fn issue_client_ticketbook(
|
|||||||
);
|
);
|
||||||
|
|
||||||
let persistent_storage = initialise_persistent_storage(credentials_store).await;
|
let persistent_storage = initialise_persistent_storage(credentials_store).await;
|
||||||
let private_id_key: ed25519::PrivateKey = nym_pemstore::load_key(private_id_key)?;
|
let private_id_key: identity::PrivateKey = nym_pemstore::load_key(private_id_key)?;
|
||||||
utils::issue_credential(
|
utils::issue_credential(
|
||||||
&client,
|
&client,
|
||||||
&persistent_storage,
|
&persistent_storage,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use clap::{Args, Parser, Subcommand};
|
use clap::{Args, Parser, Subcommand};
|
||||||
use nym_bin_common::output_format::OutputFormat;
|
use nym_bin_common::output_format::OutputFormat;
|
||||||
use nym_crypto::asymmetric::ed25519;
|
use nym_crypto::asymmetric::identity;
|
||||||
use nym_types::helpers::ConsoleSigningOutput;
|
use nym_types::helpers::ConsoleSigningOutput;
|
||||||
use nym_validator_client::nyxd::error::NyxdError;
|
use nym_validator_client::nyxd::error::NyxdError;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
@@ -34,14 +34,14 @@ pub struct SignArgs {
|
|||||||
|
|
||||||
pub async fn sign(args: SignArgs) -> Result<(), NyxdError> {
|
pub async fn sign(args: SignArgs) -> Result<(), NyxdError> {
|
||||||
eprintln!(">>> loading: {}", args.private_key.display());
|
eprintln!(">>> loading: {}", args.private_key.display());
|
||||||
let private_identity_key: ed25519::PrivateKey =
|
let private_identity_key: identity::PrivateKey =
|
||||||
nym_pemstore::load_key(args.private_key).expect("failed to load key");
|
nym_pemstore::load_key(args.private_key).expect("failed to load key");
|
||||||
|
|
||||||
print_signed_msg(&private_identity_key, &args.base58_msg, args.output);
|
print_signed_msg(&private_identity_key, &args.base58_msg, args.output);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_signed_msg(private_key: &ed25519::PrivateKey, raw_msg: &str, output: OutputFormat) {
|
fn print_signed_msg(private_key: &identity::PrivateKey, raw_msg: &str, output: OutputFormat) {
|
||||||
let trimmed = raw_msg.trim();
|
let trimmed = raw_msg.trim();
|
||||||
eprintln!(">>> attempting to sign: {trimmed}");
|
eprintln!(">>> attempting to sign: {trimmed}");
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
[package]
|
||||||
|
name = "nym-country-group"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors.workspace = true
|
||||||
|
repository.workspace = true
|
||||||
|
homepage.workspace = true
|
||||||
|
documentation.workspace = true
|
||||||
|
edition.workspace = true
|
||||||
|
license.workspace = true
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
serde = { workspace = true, features = ["derive"] }
|
||||||
|
tracing.workspace = true
|
||||||
@@ -0,0 +1,158 @@
|
|||||||
|
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::fmt;
|
||||||
|
use tracing::info;
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Hash, PartialEq, Eq, Serialize, Deserialize, Debug)]
|
||||||
|
pub enum CountryGroup {
|
||||||
|
Europe,
|
||||||
|
NorthAmerica,
|
||||||
|
SouthAmerica,
|
||||||
|
Oceania,
|
||||||
|
Asia,
|
||||||
|
Africa,
|
||||||
|
Unknown,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CountryGroup {
|
||||||
|
// We map country codes into group, which initially are continent codes to a first approximation,
|
||||||
|
// but we do it manually to reserve the right to tweak this distribution for our purposes.
|
||||||
|
// NOTE: I did this quickly, and it's not a complete list of all countries, but only those that
|
||||||
|
// were present in the network at the time. Please add more as needed.
|
||||||
|
pub fn new(country_code: &str) -> Self {
|
||||||
|
let country_code = country_code.to_uppercase();
|
||||||
|
use CountryGroup::*;
|
||||||
|
match country_code.as_ref() {
|
||||||
|
// Europe
|
||||||
|
"AT" => Europe,
|
||||||
|
"BG" => Europe,
|
||||||
|
"CH" => Europe,
|
||||||
|
"CY" => Europe,
|
||||||
|
"CZ" => Europe,
|
||||||
|
"DE" => Europe,
|
||||||
|
"DK" => Europe,
|
||||||
|
"ES" => Europe,
|
||||||
|
"FI" => Europe,
|
||||||
|
"FR" => Europe,
|
||||||
|
"GB" => Europe,
|
||||||
|
"GR" => Europe,
|
||||||
|
"IE" => Europe,
|
||||||
|
"IT" => Europe,
|
||||||
|
"LT" => Europe,
|
||||||
|
"LU" => Europe,
|
||||||
|
"LV" => Europe,
|
||||||
|
"MD" => Europe,
|
||||||
|
"MT" => Europe,
|
||||||
|
"NL" => Europe,
|
||||||
|
"NO" => Europe,
|
||||||
|
"PL" => Europe,
|
||||||
|
"RO" => Europe,
|
||||||
|
"SE" => Europe,
|
||||||
|
"SK" => Europe,
|
||||||
|
"TR" => Europe,
|
||||||
|
"UA" => Europe,
|
||||||
|
|
||||||
|
// North America
|
||||||
|
"CA" => NorthAmerica,
|
||||||
|
"MX" => NorthAmerica,
|
||||||
|
"US" => NorthAmerica,
|
||||||
|
|
||||||
|
// South America
|
||||||
|
"AR" => SouthAmerica,
|
||||||
|
"BR" => SouthAmerica,
|
||||||
|
"CL" => SouthAmerica,
|
||||||
|
"CO" => SouthAmerica,
|
||||||
|
"CR" => SouthAmerica,
|
||||||
|
"GT" => SouthAmerica,
|
||||||
|
|
||||||
|
// Oceania
|
||||||
|
"AU" => Oceania,
|
||||||
|
|
||||||
|
// Asia
|
||||||
|
"AM" => Asia,
|
||||||
|
"BH" => Asia,
|
||||||
|
"CN" => Asia,
|
||||||
|
"GE" => Asia,
|
||||||
|
"HK" => Asia,
|
||||||
|
"ID" => Asia,
|
||||||
|
"IL" => Asia,
|
||||||
|
"IN" => Asia,
|
||||||
|
"JP" => Asia,
|
||||||
|
"KH" => Asia,
|
||||||
|
"KR" => Asia,
|
||||||
|
"KZ" => Asia,
|
||||||
|
"MY" => Asia,
|
||||||
|
"RU" => Asia,
|
||||||
|
"SG" => Asia,
|
||||||
|
"TH" => Asia,
|
||||||
|
"VN" => Asia,
|
||||||
|
|
||||||
|
// Africa
|
||||||
|
"SC" => Africa,
|
||||||
|
"UG" => Africa,
|
||||||
|
"ZA" => Africa,
|
||||||
|
|
||||||
|
// And group level codes work too
|
||||||
|
"EU" => Europe,
|
||||||
|
"NA" => NorthAmerica,
|
||||||
|
"SA" => SouthAmerica,
|
||||||
|
"OC" => Oceania,
|
||||||
|
"AS" => Asia,
|
||||||
|
"AF" => Africa,
|
||||||
|
|
||||||
|
// And some aliases
|
||||||
|
"EUROPE" => Europe,
|
||||||
|
"NORTHAMERICA" => NorthAmerica,
|
||||||
|
"SOUTHAMERICA" => SouthAmerica,
|
||||||
|
"OCEANIA" => Oceania,
|
||||||
|
"ASIA" => Asia,
|
||||||
|
"AFRICA" => Africa,
|
||||||
|
|
||||||
|
_ => {
|
||||||
|
info!("Unknown country code: {country_code}");
|
||||||
|
Unknown
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for CountryGroup {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
use CountryGroup::*;
|
||||||
|
match self {
|
||||||
|
Europe => write!(f, "EU"),
|
||||||
|
NorthAmerica => write!(f, "NA"),
|
||||||
|
SouthAmerica => write!(f, "SA"),
|
||||||
|
Oceania => write!(f, "OC"),
|
||||||
|
Asia => write!(f, "AS"),
|
||||||
|
Africa => write!(f, "AF"),
|
||||||
|
Unknown => write!(f, "Unknown"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::str::FromStr for CountryGroup {
|
||||||
|
type Err = ();
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
|
let group = CountryGroup::new(s);
|
||||||
|
if group == CountryGroup::Unknown {
|
||||||
|
Err(())
|
||||||
|
} else {
|
||||||
|
Ok(group)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CountryGroup {
|
||||||
|
#[allow(unused)]
|
||||||
|
fn known(self) -> Option<CountryGroup> {
|
||||||
|
use CountryGroup::*;
|
||||||
|
match self {
|
||||||
|
Europe | NorthAmerica | SouthAmerica | Oceania | Asia | Africa => Some(self),
|
||||||
|
Unknown => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -172,21 +172,6 @@ impl MemoryEcachTicketbookManager {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn contains_ticketbook(&self, ticketbook: &IssuedTicketBook) -> bool {
|
|
||||||
let ser = ticketbook.pack();
|
|
||||||
let search_data = Zeroizing::new(ser.data);
|
|
||||||
self.inner
|
|
||||||
.read()
|
|
||||||
.await
|
|
||||||
.ticketbooks
|
|
||||||
.iter()
|
|
||||||
.any(|ticketbook| {
|
|
||||||
let ser = ticketbook.1.ticketbook.pack();
|
|
||||||
let data = Zeroizing::new(ser.data);
|
|
||||||
search_data.eq(&data)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) async fn get_ticketbooks_info(&self) -> Vec<BasicTicketbookInformation> {
|
pub(crate) async fn get_ticketbooks_info(&self) -> Vec<BasicTicketbookInformation> {
|
||||||
let guard = self.inner.read().await;
|
let guard = self.inner.read().await;
|
||||||
|
|
||||||
|
|||||||
@@ -95,23 +95,6 @@ impl SqliteEcashTicketbookManager {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn contains_ticketbook_data(&self, data: &[u8]) -> Result<bool, sqlx::Error> {
|
|
||||||
let exists = sqlx::query(
|
|
||||||
r#"
|
|
||||||
SELECT 1
|
|
||||||
FROM ecash_ticketbook
|
|
||||||
WHERE ticketbook_data = ?
|
|
||||||
|
|
||||||
"#,
|
|
||||||
)
|
|
||||||
.bind(data)
|
|
||||||
.fetch_optional(&self.connection_pool)
|
|
||||||
.await?
|
|
||||||
.is_some();
|
|
||||||
|
|
||||||
Ok(exists)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) async fn get_ticketbooks_info(
|
pub(crate) async fn get_ticketbooks_info(
|
||||||
&self,
|
&self,
|
||||||
) -> Result<Vec<BasicTicketbookInformation>, sqlx::Error> {
|
) -> Result<Vec<BasicTicketbookInformation>, sqlx::Error> {
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user