Compare commits

..

1 Commits

Author SHA1 Message Date
Jon Häggblad e5d68a5e7f Don't set NYM_VPN_API to default (#4740) 2024-07-31 11:45:36 +02:00
900 changed files with 15830 additions and 54935 deletions
-7
View File
@@ -1,7 +0,0 @@
.git
.github
.gitignore
**/node_modules
**/target
dist
documentation
-17
View File
@@ -14,20 +14,3 @@ updates:
prefix: build prefix: build
prefix-development: chore prefix-development: chore
include: scope include: scope
# Update the root workspace (only). For now we don't include
# the contracts workspcae.
- package-ecosystem: cargo
directory: /
schedule:
interval: weekly
time: "09:00"
ignore:
- dependency-name: "cosmwasm-*"
- dependency-name: "cw*"
groups:
patch-updates:
patterns:
- "*"
update-types:
- "patch"
open-pull-requests-limit: 10
-39
View File
@@ -1,39 +0,0 @@
name: build-deb-meta
on:
workflow_dispatch:
jobs:
build:
runs-on: arc-ubuntu-22.04
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Set up Build Environment
run: sudo apt-get update && sudo apt-get install -y make dpkg-dev
- name: Build Debian Packages
working-directory: ppa/packages
run: make
- name: Find .deb files
working-directory: ppa/packages
run: |
echo "file1=$(ls nym-repo-setup*.deb)" >> $GITHUB_ENV
echo "file2=$(ls nym-vpn*.deb)" >> $GITHUB_ENV
- name: Upload nym-repo-setup
uses: actions/upload-artifact@v4
with:
name: ${{ env.file1 }}
path: ppa/packages/nym-repo-setup*.deb
retention-days: 10
- name: Upload nym-vpn
uses: actions/upload-artifact@v4
with:
name: ${{ env.file2 }}
path: ppa/packages/nym-vpn*.deb
retention-days: 10
+2 -2
View File
@@ -7,7 +7,7 @@ jobs:
build: build:
runs-on: ubuntu-20.04-16-core runs-on: ubuntu-20.04-16-core
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v3
- name: Install Dependencies (Linux) - name: Install Dependencies (Linux)
run: sudo apt-get update && sudo apt-get install -y build-essential curl wget libssl-dev libudev-dev squashfs-tools protobuf-compiler git python3 && sudo apt-get update --fix-missing run: sudo apt-get update && sudo apt-get install -y build-essential curl wget libssl-dev libudev-dev squashfs-tools protobuf-compiler git python3 && sudo apt-get update --fix-missing
- name: Install pip3 - name: Install pip3
@@ -17,7 +17,7 @@ jobs:
- name: Install rsync - name: Install rsync
run: sudo apt-get install rsync run: sudo apt-get install rsync
- uses: rlespinasse/github-slug-action@v3.x - uses: rlespinasse/github-slug-action@v3.x
- uses: actions/setup-node@v4 - uses: actions/setup-node@v3
with: with:
node-version: 18 node-version: 18
- name: Install Rust stable - name: Install Rust stable
@@ -13,7 +13,6 @@ on:
- 'mixnode/**' - 'mixnode/**'
- 'sdk/rust/nym-sdk/**' - 'sdk/rust/nym-sdk/**'
- 'service-providers/**' - 'service-providers/**'
- '.github/workflows/ci-binary-config-checker.yml'
pull_request: pull_request:
paths: paths:
- 'clients/**' - 'clients/**'
@@ -23,7 +22,6 @@ on:
- 'mixnode/**' - 'mixnode/**'
- 'sdk/rust/nym-sdk/**' - 'sdk/rust/nym-sdk/**'
- 'service-providers/**' - 'service-providers/**'
- '.github/workflows/ci-binary-config-checker.yml'
env: env:
NETWORK: mainnet NETWORK: mainnet
@@ -33,11 +31,11 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
platform: [arc-ubuntu-20.04] platform: [custom-linux]
runs-on: ${{ matrix.platform }} runs-on: ${{ matrix.platform }}
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v3
- name: Install Dependencies (Linux) - name: Install Dependencies (Linux)
run: sudo apt-get update && sudo apt-get -y install jq vim libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev libudev-dev squashfs-tools run: sudo apt-get update && sudo apt-get -y install jq vim libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev libudev-dev squashfs-tools
+2 -3
View File
@@ -5,18 +5,17 @@ on:
paths: paths:
- "ts-packages/**" - "ts-packages/**"
- "sdk/typescript/**" - "sdk/typescript/**"
- ".github/workflows/ci-build-ts.yml"
jobs: jobs:
build: build:
runs-on: ubuntu-20.04-16-core runs-on: ubuntu-20.04-16-core
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v2
- name: Install rsync - name: Install rsync
run: sudo apt-get install rsync run: sudo apt-get install rsync
continue-on-error: true continue-on-error: true
- uses: rlespinasse/github-slug-action@v3.x - uses: rlespinasse/github-slug-action@v3.x
- uses: actions/setup-node@v4 - uses: actions/setup-node@v3
with: with:
node-version: 18 node-version: 18
- name: Setup yarn - name: Setup yarn
+16 -8
View File
@@ -8,6 +8,11 @@ on:
required: true required: true
default: false default: false
type: boolean type: boolean
enable_wireguard:
description: "Add --features wireguard"
required: true
default: false
type: boolean
enable_deb: enable_deb:
description: "True to enable cargo-deb installation and .deb package building" description: "True to enable cargo-deb installation and .deb package building"
required: false required: false
@@ -26,26 +31,24 @@ on:
- "nym-api/**" - "nym-api/**"
- "nym-node/**" - "nym-node/**"
- "nym-outfox/**" - "nym-outfox/**"
- 'nym-data-observatory/**'
- "nym-validator-rewarder/**" - "nym-validator-rewarder/**"
- "sdk/rust/nym-sdk/**" - "sdk/rust/nym-sdk/**"
- "service-providers/**" - "service-providers/**"
- "tools/**" - "tools/**"
- "nymvisor/**" - "nymvisor/**"
- ".github/workflows/ci-build-upload-binaries.yml"
jobs: jobs:
publish-nym: publish-nym:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
platform: [ arc-ubuntu-20.04 ] platform: [ubuntu-20.04]
runs-on: ${{ matrix.platform }} runs-on: ${{ matrix.platform }}
env: env:
CARGO_TERM_COLOR: always CARGO_TERM_COLOR: always
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v3
- name: Prepare build output directory - name: Prepare build output directory
shell: bash shell: bash
@@ -57,13 +60,20 @@ jobs:
echo $OUTPUT_DIR echo $OUTPUT_DIR
- name: Install Dependencies (Linux) - name: Install Dependencies (Linux)
run: sudo apt-get update && sudo apt-get -y install libudev-dev run: sudo apt update && sudo apt install libudev-dev
- name: Sets env vars for tokio if set in manual dispatch inputs - name: Sets env vars for tokio if set in manual dispatch inputs
run: | run: |
echo 'RUSTFLAGS="--cfg tokio_unstable"' >> $GITHUB_ENV echo 'RUSTFLAGS="--cfg tokio_unstable"' >> $GITHUB_ENV
if: github.event_name == 'workflow_dispatch' && inputs.add_tokio_unstable == true if: github.event_name == 'workflow_dispatch' && inputs.add_tokio_unstable == true
- name: Set CARGO_FEATURES
run: |
echo 'CARGO_FEATURES=--features wireguard' >> $GITHUB_ENV
if: >
github.event_name == 'schedule' ||
(github.event_name == 'workflow_dispatch' && inputs.enable_wireguard == true)
- name: Install Rust stable - name: Install Rust stable
uses: actions-rs/toolchain@v1 uses: actions-rs/toolchain@v1
with: with:
@@ -89,7 +99,7 @@ jobs:
- name: Upload Artifact - name: Upload Artifact
if: github.event_name == 'workflow_dispatch' if: github.event_name == 'workflow_dispatch'
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v3
with: with:
name: nym-binaries-artifacts name: nym-binaries-artifacts
path: | path: |
@@ -97,7 +107,6 @@ jobs:
target/release/nym-socks5-client target/release/nym-socks5-client
target/release/nym-api target/release/nym-api
target/release/nym-network-requester target/release/nym-network-requester
target/release/nym-data-observatory
target/release/nym-cli target/release/nym-cli
target/release/nymvisor target/release/nymvisor
target/release/nym-node target/release/nym-node
@@ -115,7 +124,6 @@ jobs:
cp target/release/nym-socks5-client $OUTPUT_DIR cp target/release/nym-socks5-client $OUTPUT_DIR
cp target/release/nym-api $OUTPUT_DIR cp target/release/nym-api $OUTPUT_DIR
cp target/release/nym-network-requester $OUTPUT_DIR cp target/release/nym-network-requester $OUTPUT_DIR
cp target/release/nym-data-observatory $OUTPUT_DIR
cp target/release/nymvisor $OUTPUT_DIR cp target/release/nymvisor $OUTPUT_DIR
cp target/release/nym-node $OUTPUT_DIR cp target/release/nym-node $OUTPUT_DIR
cp target/release/nym-cli $OUTPUT_DIR cp target/release/nym-cli $OUTPUT_DIR
+42 -28
View File
@@ -1,6 +1,23 @@
name: ci-build name: ci-build
on: on:
push:
paths:
- 'clients/**'
- 'common/**'
- 'explorer-api/**'
- 'gateway/**'
- 'integrations/**'
- 'mixnode/**'
- 'sdk/lib/socks5-listener/**'
- 'sdk/rust/nym-sdk/**'
- 'service-providers/**'
- 'nym-api/**'
- 'nym-outfox/**'
- 'tools/nym-cli/**'
- 'tools/nym-nr-query/**'
- 'tools/ts-rs-cli/**'
- 'Cargo.toml'
pull_request: pull_request:
paths: paths:
- 'clients/**' - 'clients/**'
@@ -9,20 +26,15 @@ on:
- 'gateway/**' - 'gateway/**'
- 'integrations/**' - 'integrations/**'
- 'mixnode/**' - 'mixnode/**'
- 'sdk/rust/**' - 'sdk/lib/socks5-listener/**'
- 'sdk/lib/**' - 'sdk/rust/nym-sdk/**'
- 'service-providers/**' - 'service-providers/**'
- 'nym-network-monitor/**'
- 'nym-api/**' - 'nym-api/**'
- 'nym-node/**'
- 'nym-outfox/**' - 'nym-outfox/**'
- 'nym-data-observatory/**' - 'tools/nym-cli/**'
- 'nym-validator-rewarder/**' - 'tools/nym-nr-query/**'
- 'tools/**' - 'tools/ts-rs-cli/**'
- 'wasm/**'
- 'Cargo.toml' - 'Cargo.toml'
- 'Cargo.lock'
- '.github/workflows/ci-build.yml'
workflow_dispatch: workflow_dispatch:
jobs: jobs:
@@ -30,7 +42,7 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
os: [arc-ubuntu-20.04, custom-runner-mac-m1] os: [custom-linux, custom-runner-mac-m1]
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
env: env:
CARGO_TERM_COLOR: always CARGO_TERM_COLOR: always
@@ -38,10 +50,10 @@ jobs:
- name: Install Dependencies (Linux) - name: Install Dependencies (Linux)
run: sudo apt-get update && sudo apt-get -y install libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev libudev-dev squashfs-tools protobuf-compiler run: sudo apt-get update && sudo apt-get -y install libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev libudev-dev squashfs-tools protobuf-compiler
continue-on-error: true continue-on-error: true
if: contains(matrix.os, 'ubuntu') if: matrix.os == 'custom-linux'
- name: Check out repository code - name: Check out repository code
uses: actions/checkout@v4 uses: actions/checkout@v2
- name: Install rust toolchain - name: Install rust toolchain
uses: actions-rs/toolchain@v1 uses: actions-rs/toolchain@v1
@@ -61,38 +73,40 @@ jobs:
uses: actions-rs/cargo@v1 uses: actions-rs/cargo@v1
with: with:
command: build command: build
# Enable wireguard by default on linux only
# while disabled by default, this build ensures nothing is broken within args: --workspace --features wireguard
# `axum` feature
- name: Build with `axum` feature
uses: actions-rs/cargo@v1
with:
command: build
args: --features axum
- name: Build all examples - name: Build all examples
if: contains(matrix.os, 'ubuntu') if: matrix.os == 'custom-linux'
uses: actions-rs/cargo@v1 uses: actions-rs/cargo@v1
with: with:
command: build command: build
args: --workspace --examples args: --workspace --examples --features wireguard
- name: Run all tests - name: Run all tests
if: contains(matrix.os, 'ubuntu') if: matrix.os == 'custom-linux'
uses: actions-rs/cargo@v1 uses: actions-rs/cargo@v1
with: with:
command: test command: test
args: --workspace args: --workspace --features wireguard
- name: Run expensive tests - name: Run expensive tests
if: (github.ref == 'refs/heads/develop' || github.event.pull_request.base.ref == 'develop' || github.event.pull_request.base.ref == 'master') && contains(matrix.os, 'ubuntu') if: (github.ref == 'refs/heads/develop' || github.event.pull_request.base.ref == 'develop' || github.event.pull_request.base.ref == 'master') && matrix.os == 'custom-linux'
uses: actions-rs/cargo@v1 uses: actions-rs/cargo@v1
with: with:
command: test command: test
args: --workspace -- --ignored args: --workspace --features wireguard -- --ignored
- name: Annotate with clippy checks
if: matrix.os == 'custom-linux'
uses: actions-rs/clippy-check@v1
continue-on-error: true
with:
token: ${{ secrets.GITHUB_TOKEN }}
args: --workspace --features wireguard
- name: Clippy - name: Clippy
uses: actions-rs/cargo@v1 uses: actions-rs/cargo@v1
with: with:
command: clippy command: clippy
args: --workspace --all-targets --features axum -- -D warnings args: --workspace --all-targets --features wireguard -- -D warnings
+4 -8
View File
@@ -2,14 +2,10 @@ name: ci-cargo-deny
on: on:
workflow_dispatch: workflow_dispatch:
pull_request: pull_request:
paths:
- 'Cargo.toml'
- 'Cargo.lock'
- '.github/workflows/ci-cargo-deny.yml'
jobs: jobs:
cargo-deny: cargo-deny:
runs-on: arc-ubuntu-22.04-dind runs-on: ubuntu-22.04
strategy: strategy:
matrix: matrix:
checks: checks:
@@ -17,9 +13,9 @@ jobs:
- licenses bans sources - licenses bans sources
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v3
- uses: EmbarkStudios/cargo-deny-action@v2 - uses: EmbarkStudios/cargo-deny-action@v1
with: with:
log-level: warn log-level: warn
command: check ${{ matrix.checks }} command: check ${{ matrix.checks }}
arguments: --all-features argument: --all-features
+2 -3
View File
@@ -6,17 +6,16 @@ on:
paths: paths:
- 'contracts/**' - 'contracts/**'
- 'common/**' - 'common/**'
- '.github/workflows/ci-contracts-schema.yml'
jobs: jobs:
check-schema: check-schema:
name: Generate and check schema name: Generate and check schema
runs-on: arc-ubuntu-20.04 runs-on: custom-linux
env: env:
CARGO_TERM_COLOR: always CARGO_TERM_COLOR: always
steps: steps:
- name: Check out repository code - name: Check out repository code
uses: actions/checkout@v4 uses: actions/checkout@v2
- name: Install Rust toolchain - name: Install Rust toolchain
uses: actions-rs/toolchain@v1 uses: actions-rs/toolchain@v1
@@ -6,7 +6,6 @@ on:
paths: paths:
- 'common/**' - 'common/**'
- 'contracts/**' - 'contracts/**'
- '.github/workflows/ci-contracts-upload-binaries.yml'
env: env:
NETWORK: mainnet NETWORK: mainnet
@@ -16,13 +15,13 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
platform: arc-ubuntu-20.04 platform: [ubuntu-20.04]
runs-on: ${{ matrix.platform }} runs-on: ${{ matrix.platform }}
env: env:
CARGO_TERM_COLOR: always CARGO_TERM_COLOR: always
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v3
- name: Prepare build output directory - name: Prepare build output directory
shell: bash shell: bash
@@ -59,7 +58,6 @@ jobs:
cp contracts/target/wasm32-unknown-unknown/release/nym_coconut_dkg.wasm $OUTPUT_DIR cp contracts/target/wasm32-unknown-unknown/release/nym_coconut_dkg.wasm $OUTPUT_DIR
cp contracts/target/wasm32-unknown-unknown/release/cw3_flex_multisig.wasm $OUTPUT_DIR cp contracts/target/wasm32-unknown-unknown/release/cw3_flex_multisig.wasm $OUTPUT_DIR
cp contracts/target/wasm32-unknown-unknown/release/cw4_group.wasm $OUTPUT_DIR cp contracts/target/wasm32-unknown-unknown/release/cw4_group.wasm $OUTPUT_DIR
cp contracts/target/wasm32-unknown-unknown/release/nym_ecash.wasm $OUTPUT_DIR
- name: Deploy branch to CI www - name: Deploy branch to CI www
continue-on-error: true continue-on-error: true
+3 -4
View File
@@ -9,16 +9,15 @@ on:
paths: paths:
- 'contracts/**' - 'contracts/**'
- 'common/**' - 'common/**'
- '.github/workflows/ci-contracts.yml'
jobs: jobs:
matrix_prep: matrix_prep:
runs-on: arc-ubuntu-20.04 runs-on: ubuntu-20.04
outputs: outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }} matrix: ${{ steps.set-matrix.outputs.matrix }}
steps: steps:
# creates the matrix strategy from ci-contracts-matrix-includes.json # creates the matrix strategy from ci-contracts-matrix-includes.json
- uses: actions/checkout@v4 - uses: actions/checkout@v2
- id: set-matrix - id: set-matrix
uses: JoshuaTheMiller/conditional-build-matrix@main uses: JoshuaTheMiller/conditional-build-matrix@main
with: with:
@@ -35,7 +34,7 @@ jobs:
fail-fast: false fail-fast: false
matrix: ${{fromJson(needs.matrix_prep.outputs.matrix)}} matrix: ${{fromJson(needs.matrix_prep.outputs.matrix)}}
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v2
- name: Setup rust - name: Setup rust
uses: actions-rs/toolchain@v1 uses: actions-rs/toolchain@v1
+2 -3
View File
@@ -6,13 +6,12 @@ on:
branches-ignore: master branches-ignore: master
paths: paths:
- 'documentation/docs/**' - 'documentation/docs/**'
- '.github/workflows/ci-docs.yml'
jobs: jobs:
build: build:
runs-on: ubuntu-20.04-16-core runs-on: ubuntu-20.04-16-core
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v3
- name: Install Dependencies (Linux) - name: Install Dependencies (Linux)
run: sudo apt-get update && sudo apt-get install -y build-essential curl wget libssl-dev libudev-dev squashfs-tools protobuf-compiler git python3 && sudo apt-get update --fix-missing run: sudo apt-get update && sudo apt-get install -y build-essential curl wget libssl-dev libudev-dev squashfs-tools protobuf-compiler git python3 && sudo apt-get update --fix-missing
- name: Install pip3 - name: Install pip3
@@ -22,7 +21,7 @@ jobs:
- name: Install rsync - name: Install rsync
run: sudo apt-get install rsync run: sudo apt-get install rsync
- uses: rlespinasse/github-slug-action@v3.x - uses: rlespinasse/github-slug-action@v3.x
- uses: actions/setup-node@v4 - uses: actions/setup-node@v3
with: with:
node-version: 18 node-version: 18
- name: Install Rust stable - name: Install Rust stable
+3 -4
View File
@@ -10,16 +10,15 @@ on:
- "nym-wallet/src/**" - "nym-wallet/src/**"
- "nym-wallet/package.json" - "nym-wallet/package.json"
- "explorer/**" - "explorer/**"
- ".github/workflows/ci-lint-typescript.yml"
jobs: jobs:
build: build:
runs-on: ubuntu-20.04-16-core runs-on: ubuntu-20.04-16-core
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v2
- uses: rlespinasse/github-slug-action@v3.x - uses: rlespinasse/github-slug-action@v3.x
- uses: actions/setup-node@v4 - uses: actions/setup-node@v3
with: with:
node-version: 18 node-version: 18
- name: Setup yarn - name: Setup yarn
@@ -39,7 +38,7 @@ jobs:
version: '116' version: '116'
- name: Set up Go - name: Set up Go
uses: actions/setup-go@v5 uses: actions/setup-go@v4
with: with:
go-version: '1.20' go-version: '1.20'
+2 -2
View File
@@ -15,7 +15,7 @@ jobs:
name: nym-api tests name: nym-api tests
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v2
- name: install yarn in root - name: install yarn in root
run: cd ../.. && yarn install run: cd ../.. && yarn install
@@ -24,7 +24,7 @@ jobs:
run: npm install run: npm install
- name: Node v18 - name: Node v18
uses: actions/setup-node@v4 uses: actions/setup-node@v3
with: with:
node-version: 18.1.0 node-version: 18.1.0
@@ -5,7 +5,6 @@ on:
push: push:
paths: paths:
- 'explorer/**' - 'explorer/**'
- '.github/workflows/ci-nym-network-explorer.yml'
defaults: defaults:
run: run:
@@ -15,12 +14,12 @@ jobs:
build: build:
runs-on: custom-linux runs-on: custom-linux
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v2
- name: Install rsync - name: Install rsync
run: sudo apt-get install rsync run: sudo apt-get install rsync
continue-on-error: true continue-on-error: true
- uses: rlespinasse/github-slug-action@v3.x - uses: rlespinasse/github-slug-action@v3.x
- uses: actions/setup-node@v4 - uses: actions/setup-node@v3
with: with:
node-version: 18 node-version: 18
- name: Setup yarn - name: Setup yarn
+8 -3
View File
@@ -1,17 +1,22 @@
name: ci-nym-wallet-rust name: ci-nym-wallet-rust
on: on:
push:
paths:
- 'nym-wallet/**'
- 'common/**'
- 'contracts/vesting/**'
- 'nym-api/nym-api-requests/**'
pull_request: pull_request:
paths: paths:
- 'nym-wallet/**' - 'nym-wallet/**'
- 'common/**' - 'common/**'
- 'contracts/vesting/**' - 'contracts/vesting/**'
- 'nym-api/nym-api-requests/**' - 'nym-api/nym-api-requests/**'
- '.github/workflows/ci-nym-wallet-rust.yml'
jobs: jobs:
build: build:
runs-on: arc-ubuntu-20.04 runs-on: [ self-hosted, custom-linux ]
env: env:
CARGO_TERM_COLOR: always CARGO_TERM_COLOR: always
steps: steps:
@@ -20,7 +25,7 @@ jobs:
continue-on-error: true continue-on-error: true
- name: Check out repository code - name: Check out repository code
uses: actions/checkout@v4 uses: actions/checkout@v2
- name: Install rust toolchain - name: Install rust toolchain
uses: actions-rs/toolchain@v1 uses: actions-rs/toolchain@v1
@@ -4,13 +4,12 @@ on:
pull_request: pull_request:
paths: paths:
- 'nym-wallet/**' - 'nym-wallet/**'
- '.github/workflows/ci-nym-wallet-storybook.yml'
jobs: jobs:
build: build:
runs-on: custom-linux runs-on: custom-linux
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v2
- name: Install rsync - name: Install rsync
run: sudo apt-get install rsync run: sudo apt-get install rsync
@@ -18,7 +17,7 @@ jobs:
- uses: rlespinasse/github-slug-action@v3.x - uses: rlespinasse/github-slug-action@v3.x
- uses: actions/setup-node@v4 - uses: actions/setup-node@v3
with: with:
node-version: 18 node-version: 18
+3 -4
View File
@@ -5,18 +5,17 @@ on:
paths: paths:
- "sdk/typescript/**" - "sdk/typescript/**"
- "wasm/**" - "wasm/**"
- '.github/workflows/ci-sdk-docs-typescript.yml'
jobs: jobs:
build: build:
runs-on: custom-linux runs-on: custom-linux
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v2
- name: Install rsync - name: Install rsync
run: sudo apt-get install rsync run: sudo apt-get install rsync
continue-on-error: true continue-on-error: true
- uses: rlespinasse/github-slug-action@v3.x - uses: rlespinasse/github-slug-action@v3.x
- uses: actions/setup-node@v4 - uses: actions/setup-node@v3
with: with:
node-version: 18.17 node-version: 18.17
- name: Install Rust stable - name: Install Rust stable
@@ -27,7 +26,7 @@ jobs:
run: npm install -g yarn run: npm install -g yarn
- name: Set up Go - name: Set up Go
uses: actions/setup-go@v5 uses: actions/setup-go@v4
with: with:
go-version: '1.20' go-version: '1.20'
+4 -5
View File
@@ -6,17 +6,16 @@ on:
- 'wasm/**' - 'wasm/**'
- 'clients/client-core/**' - 'clients/client-core/**'
- 'common/**' - 'common/**'
- '.github/workflows/ci-sdk-wasm.yml'
jobs: jobs:
wasm: wasm:
runs-on: arc-ubuntu-20.04 runs-on: [custom-linux]
env: env:
CARGO_TERM_COLOR: always CARGO_TERM_COLOR: always
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v2
- uses: actions/setup-node@v4 - uses: actions/setup-node@v3
with: with:
node-version: 18 node-version: 18
@@ -29,7 +28,7 @@ jobs:
components: rustfmt, clippy components: rustfmt, clippy
- name: Set up Go - name: Set up Go
uses: actions/setup-go@v5 uses: actions/setup-go@v4
with: with:
go-version: '1.20' go-version: '1.20'
+4 -4
View File
@@ -30,14 +30,14 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v3
- name: Setup Pages - name: Setup Pages
uses: actions/configure-pages@v5 uses: actions/configure-pages@v3
- name: Upload artifact - name: Upload artifact
uses: actions/upload-pages-artifact@v3 uses: actions/upload-pages-artifact@v2
with: with:
# Upload entire repository # Upload entire repository
path: './ppa' path: './ppa'
- name: Deploy to GitHub Pages - name: Deploy to GitHub Pages
id: deployment id: deployment
uses: actions/deploy-pages@v4 uses: actions/deploy-pages@v2
+5 -5
View File
@@ -18,7 +18,7 @@ jobs:
continue-on-error: true continue-on-error: true
steps: steps:
- name: Check out repository code - name: Check out repository code
uses: actions/checkout@v4 uses: actions/checkout@v3
- name: Install Dependencies (Linux) - name: Install Dependencies (Linux)
run: sudo apt-get update && sudo apt-get install -y build-essential curl wget libssl-dev libudev-dev squashfs-tools protobuf-compiler run: sudo apt-get update && sudo apt-get install -y build-essential curl wget libssl-dev libudev-dev squashfs-tools protobuf-compiler
@@ -33,7 +33,7 @@ jobs:
components: rustfmt, clippy components: rustfmt, clippy
- name: Install Protoc - name: Install Protoc
uses: arduino/setup-protoc@v3 uses: arduino/setup-protoc@v2
if: matrix.os == 'macos-latest' || matrix.os == 'windows-latest' if: matrix.os == 'macos-latest' || matrix.os == 'windows-latest'
with: with:
repo-token: ${{ secrets.GITHUB_TOKEN }} repo-token: ${{ secrets.GITHUB_TOKEN }}
@@ -98,11 +98,11 @@ jobs:
runs-on: custom-linux runs-on: custom-linux
steps: steps:
- name: Collect jobs status - name: Collect jobs status
uses: technote-space/workflow-conclusion-action@v3 uses: technote-space/workflow-conclusion-action@v2
- name: Check out repository code - name: Check out repository code
uses: actions/checkout@v4 uses: actions/checkout@v3
- name: install npm - name: install npm
uses: actions/setup-node@v4 uses: actions/setup-node@v3
if: env.WORKFLOW_CONCLUSION == 'failure' if: env.WORKFLOW_CONCLUSION == 'failure'
with: with:
node-version: 18 node-version: 18
@@ -15,7 +15,7 @@ jobs:
output1: ${{ steps.step2.outputs.latest_release }} output1: ${{ steps.step2.outputs.latest_release }}
steps: steps:
- name: Check out repository code - name: Check out repository code
uses: actions/checkout@v4 uses: actions/checkout@v3
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Set output variable to latest release branch - name: Set output variable to latest release branch
@@ -28,7 +28,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@v4 uses: actions/checkout@v3
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Setup git user - name: Setup git user
@@ -47,7 +47,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@v4 uses: actions/checkout@v3
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Setup git user - name: Setup git user
@@ -18,7 +18,7 @@ jobs:
continue-on-error: true continue-on-error: true
steps: steps:
- name: Check out repository code - name: Check out repository code
uses: actions/checkout@v4 uses: actions/checkout@v3
- name: Install Dependencies (Linux) - name: Install Dependencies (Linux)
run: sudo apt-get update && sudo apt-get install -y libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev squashfs-tools run: sudo apt-get update && sudo apt-get install -y libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev squashfs-tools
@@ -61,11 +61,11 @@ jobs:
runs-on: custom-linux runs-on: custom-linux
steps: steps:
- name: Collect jobs status - name: Collect jobs status
uses: technote-space/workflow-conclusion-action@v3 uses: technote-space/workflow-conclusion-action@v2
- name: Check out repository code - name: Check out repository code
uses: actions/checkout@v4 uses: actions/checkout@v3
- name: install npm - name: install npm
uses: actions/setup-node@v4 uses: actions/setup-node@v3
if: env.WORKFLOW_CONCLUSION == 'failure' if: env.WORKFLOW_CONCLUSION == 'failure'
with: with:
node-version: 18 node-version: 18
+5 -5
View File
@@ -8,7 +8,7 @@ jobs:
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
steps: steps:
- name: Checkout repository code - name: Checkout repository code
uses: actions/checkout@v4 uses: actions/checkout@v2
- name: Install rust toolchain - name: Install rust toolchain
uses: actions-rs/toolchain@v1 uses: actions-rs/toolchain@v1
with: with:
@@ -20,7 +20,7 @@ jobs:
find . -name Cargo.toml -exec cargo deny --manifest-path {} check \ find . -name Cargo.toml -exec cargo deny --manifest-path {} check \
advisories -A advisory-not-detected --hide-inclusion-graph \; &> \ advisories -A advisory-not-detected --hide-inclusion-graph \; &> \
>(uniq &> .github/workflows/support-files/notifications/deny.message ) >(uniq &> .github/workflows/support-files/notifications/deny.message )
- uses: actions/upload-artifact@v4 - uses: actions/upload-artifact@v3
with: with:
name: report name: report
path: .github/workflows/support-files/notifications/deny.message path: .github/workflows/support-files/notifications/deny.message
@@ -29,14 +29,14 @@ jobs:
runs-on: custom-linux runs-on: custom-linux
steps: steps:
- name: Check out repository code - name: Check out repository code
uses: actions/checkout@v4 uses: actions/checkout@v2
- name: Download report from previous job - name: Download report from previous job
uses: actions/download-artifact@v4 uses: actions/download-artifact@v3
with: with:
name: report name: report
path: .github/workflows/support-files/notifications path: .github/workflows/support-files/notifications
- name: install npm - name: install npm
uses: actions/setup-node@v4 uses: actions/setup-node@v3
with: with:
node-version: 18 node-version: 18
- name: Matrix - Node Install - name: Matrix - Node Install
+7 -3
View File
@@ -40,7 +40,7 @@ jobs:
cli_version: ${{ steps.binary-versions.outputs.cli_version }} cli_version: ${{ steps.binary-versions.outputs.cli_version }}
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v3
- name: Install Dependencies (Linux) - name: Install Dependencies (Linux)
run: sudo apt-get update && sudo apt-get -y install ripgrep libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev libudev-dev squashfs-tools run: sudo apt-get update && sudo apt-get -y install ripgrep libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev libudev-dev squashfs-tools
@@ -51,6 +51,10 @@ jobs:
echo 'RUSTFLAGS="--cfg tokio_unstable"' >> $GITHUB_ENV echo 'RUSTFLAGS="--cfg tokio_unstable"' >> $GITHUB_ENV
if: github.event_name == 'workflow_dispatch' && inputs.add_tokio_unstable == true if: github.event_name == 'workflow_dispatch' && inputs.add_tokio_unstable == true
- name: Set CARGO_FEATURES
run: |
echo 'CARGO_FEATURES=--features wireguard' >> $GITHUB_ENV
- name: Install Rust stable - name: Install Rust stable
uses: actions-rs/toolchain@v1 uses: actions-rs/toolchain@v1
with: with:
@@ -63,7 +67,7 @@ jobs:
args: --workspace --release ${{ env.CARGO_FEATURES }} args: --workspace --release ${{ env.CARGO_FEATURES }}
- name: Upload Artifact - name: Upload Artifact
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v3
with: with:
name: my-artifact name: my-artifact
path: | path: |
@@ -79,7 +83,7 @@ jobs:
- 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@v1
if: github.event_name == 'release' if: github.event_name == 'release'
with: with:
files: | files: |
+4 -4
View File
@@ -9,7 +9,7 @@ jobs:
if: ${{ (startsWith(github.ref, 'refs/tags/nym-contracts-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }} if: ${{ (startsWith(github.ref, 'refs/tags/nym-contracts-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }}
runs-on: [self-hosted, custom-ubuntu-20.04] runs-on: [self-hosted, custom-ubuntu-20.04]
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v2
- name: Install Rust stable - name: Install Rust stable
uses: actions-rs/toolchain@v1 uses: actions-rs/toolchain@v1
@@ -26,21 +26,21 @@ jobs:
run: make contracts run: make contracts
- name: Upload Mixnet Contract Artifact - name: Upload Mixnet Contract Artifact
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v3
with: with:
name: mixnet_contract.wasm name: mixnet_contract.wasm
path: contracts/target/wasm32-unknown-unknown/release/mixnet_contract.wasm path: contracts/target/wasm32-unknown-unknown/release/mixnet_contract.wasm
retention-days: 5 retention-days: 5
- name: Upload Vesting Contract Artifact - name: Upload Vesting Contract Artifact
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v3
with: with:
name: vesting_contract.wasm name: vesting_contract.wasm
path: contracts/target/wasm32-unknown-unknown/release/vesting_contract.wasm path: contracts/target/wasm32-unknown-unknown/release/vesting_contract.wasm
retention-days: 5 retention-days: 5
- 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@v1
if: github.event_name == 'release' if: github.event_name == 'release'
with: with:
files: | files: |
@@ -25,10 +25,10 @@ jobs:
file_hash: ${{ steps.release-info.outputs.file_hash }} file_hash: ${{ steps.release-info.outputs.file_hash }}
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v2
- name: Node - name: Node
uses: actions/setup-node@v4 uses: actions/setup-node@v3
with: with:
node-version: 18 node-version: 18
- name: Install Rust stable - name: Install Rust stable
@@ -83,7 +83,7 @@ jobs:
run: yarn && yarn build run: yarn && yarn build
- name: Upload Artifact - name: Upload Artifact
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v3
with: with:
name: nym-wallet.app.tar.gz name: nym-wallet.app.tar.gz
path: nym-wallet/target/release/bundle/macos/nym-wallet.app.tar.gz path: nym-wallet/target/release/bundle/macos/nym-wallet.app.tar.gz
@@ -95,7 +95,7 @@ jobs:
security delete-keychain $RUNNER_TEMP/app-signing.keychain-db security delete-keychain $RUNNER_TEMP/app-signing.keychain-db
- 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@v1
if: github.event_name == 'release' if: github.event_name == 'release'
with: with:
files: | files: |
@@ -25,7 +25,7 @@ jobs:
file_hash: ${{ steps.release-info.outputs.file_hash }} file_hash: ${{ steps.release-info.outputs.file_hash }}
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v2
- name: Tauri dependencies - name: Tauri dependencies
run: > run: >
@@ -34,7 +34,7 @@ jobs:
continue-on-error: true continue-on-error: true
- name: Node - name: Node
uses: actions/setup-node@v4 uses: actions/setup-node@v3
with: with:
node-version: 18 node-version: 18
@@ -62,7 +62,7 @@ jobs:
TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }} TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
- name: Upload Artifact - name: Upload Artifact
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v3
with: with:
name: nym-wallet_1.0.0_amd64.AppImage.tar.gz name: nym-wallet_1.0.0_amd64.AppImage.tar.gz
path: nym-wallet/target/release/bundle/appimage/nym-wallet*.AppImage.tar.gz path: nym-wallet/target/release/bundle/appimage/nym-wallet*.AppImage.tar.gz
@@ -70,7 +70,7 @@ jobs:
- 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@v1
if: github.event_name == 'release' if: github.event_name == 'release'
with: with:
files: | files: |
@@ -1,4 +1,4 @@
name: publish-nym-wallet-win11 name: publish-nym-wallet-win10
on: on:
workflow_dispatch: workflow_dispatch:
release: release:
@@ -14,7 +14,7 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
platform: [custom-windows-11] platform: [windows10]
runs-on: ${{ matrix.platform }} runs-on: ${{ matrix.platform }}
outputs: outputs:
@@ -33,7 +33,7 @@ jobs:
del /s /q /A:H nym del /s /q /A:H nym
rmdir /s /q nym rmdir /s /q nym
- uses: actions/checkout@v4 - uses: actions/checkout@v3
- name: Import signing certificate - name: Import signing certificate
env: env:
@@ -47,7 +47,7 @@ jobs:
Import-PfxCertificate -FilePath certificate/certificate.pfx -CertStoreLocation Cert:\CurrentUser\My -Password (ConvertTo-SecureString -String $env:WINDOWS_CERTIFICATE_PASSWORD -Force -AsPlainText) 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@v3
with: with:
node-version: 18 node-version: 18
@@ -62,9 +62,6 @@ jobs:
fileName: '.env' fileName: '.env'
encodedString: ${{ secrets.WALLET_ADMIN_ADDRESS }} encodedString: ${{ secrets.WALLET_ADMIN_ADDRESS }}
- name: Install Yarn
run: npm install -g yarn
- name: Install project dependencies - name: Install project dependencies
shell: bash shell: bash
run: cd .. && yarn --network-timeout 100000 run: cd .. && yarn --network-timeout 100000
@@ -85,7 +82,7 @@ jobs:
run: yarn build run: yarn build
- name: Upload Artifact - name: Upload Artifact
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v3
with: with:
name: nym-wallet_1.0.0_x64_en-US.msi name: nym-wallet_1.0.0_x64_en-US.msi
path: nym-wallet/target/release/bundle/msi/nym-wallet_1.*.msi path: nym-wallet/target/release/bundle/msi/nym-wallet_1.*.msi
@@ -93,7 +90,7 @@ jobs:
- 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@v1
if: github.event_name == 'release' if: github.event_name == 'release'
with: with:
files: | files: |
@@ -22,10 +22,10 @@ jobs:
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v3
- name: Install Java - name: Install Java
uses: actions/setup-java@v4 uses: actions/setup-java@v3
with: with:
distribution: "temurin" distribution: "temurin"
java-version: "17" java-version: "17"
@@ -49,7 +49,7 @@ jobs:
"build-tools;$SDK_BUILDTOOLS_VERSION" "build-tools;$SDK_BUILDTOOLS_VERSION"
- name: Install Rust toolchain - name: Install Rust toolchain
uses: dtolnay/rust-toolchain@1.90.0 uses: dtolnay/rust-toolchain@1.70.0
- name: Install rust android targets - name: Install rust android targets
run: | run: |
@@ -84,7 +84,7 @@ jobs:
apk/nyms5-arch64-release.apk apk/nyms5-arch64-release.apk
- name: Upload APKs - name: Upload APKs
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v3
with: with:
name: nyms5-apk-arch64 name: nyms5-apk-arch64
path: | path: |
@@ -97,14 +97,14 @@ jobs:
runs-on: custom-linux runs-on: custom-linux
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v3
- name: Download binary artifact - name: Download binary artifact
uses: actions/download-artifact@v4 uses: actions/download-artifact@v3
with: with:
name: nyms5-apk-arch64 name: nyms5-apk-arch64
path: apk path: apk
- name: Release - name: Release
uses: softprops/action-gh-release@v2 uses: softprops/action-gh-release@v1
with: with:
files: | files: |
apk/nyms5-arch64-debug.apk apk/nyms5-arch64-debug.apk
+4 -4
View File
@@ -6,10 +6,10 @@ jobs:
publish: publish:
runs-on: ubuntu-20.04-16-core runs-on: ubuntu-20.04-16-core
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v2
- name: Install Node - name: Install Node
uses: actions/setup-node@v4 uses: actions/setup-node@v3
with: with:
node-version: 18 node-version: 18
registry-url: "https://registry.npmjs.org" registry-url: "https://registry.npmjs.org"
@@ -29,12 +29,12 @@ jobs:
run: cargo install wasm-opt run: cargo install wasm-opt
- name: Set up Go - name: Set up Go
uses: actions/setup-go@v5 uses: actions/setup-go@v4
with: with:
go-version: "1.20" go-version: "1.20"
- name: Install TinyGo - name: Install TinyGo
uses: acifani/setup-tinygo@v2 uses: acifani/setup-tinygo@v1
with: with:
tinygo-version: "0.27.0" tinygo-version: "0.27.0"
@@ -1,55 +0,0 @@
name: Build and upload Network monitor container to harbor.nymte.ch
on:
workflow_dispatch:
env:
WORKING_DIRECTORY: "."
CONTAINER_NAME: "network-monitor"
jobs:
build-container:
runs-on: arc-ubuntu-22.04-dind
steps:
- name: Login to Harbor
uses: docker/login-action@v3
with:
registry: harbor.nymte.ch
username: ${{ secrets.HARBOR_ROBOT_USERNAME }}
password: ${{ secrets.HARBOR_ROBOT_SECRET }}
- name: Checkout repo
uses: actions/checkout@v4
- name: Configure git identity
run: |
git config --global user.email "lawrence@nymtech.net"
git config --global user.name "Lawrence Stalder"
- name: Get version from package.json
uses: sergeysova/jq-action@v2
id: get_version
with:
cmd: jq -r '.version' ${{ env.WORKING_DIRECTORY }}/package.json
- name: Check if tag exists
run: |
if git rev-parse ${{ steps.get_version.outputs.value }} >/dev/null 2>&1; then
echo "Tag ${{ steps.get_version.outputs.value }} already exists"
fi
- name: Remove existing tag if exists
run: |
if git rev-parse ${{ steps.get_version.outputs.value }} >/dev/null 2>&1; then
git push --delete origin ${{ steps.get_version.outputs.value }}
git tag -d ${{ steps.get_version.outputs.value }}
fi
- name: Create tag
run: |
git tag -a ${{ steps.get_version.outputs.value }} -m "Version ${{ steps.get_version.outputs.value }}"
git push origin ${{ steps.get_version.outputs.value }}
- name: BuildAndPushImageOnHarbor
run: |
docker build -f nym-network-monitor.dockerfile ${{ env.WORKING_DIRECTORY }} -t harbor.nymte.ch/nym/${{ env.CONTAINER_NAME }}:${{ steps.get_version.outputs.value }} -t harbor.nymte.ch/nym/${{ env.CONTAINER_NAME }}:latest
docker push harbor.nymte.ch/nym/${{ env.CONTAINER_NAME }} --all-tags
+3 -3
View File
@@ -20,8 +20,8 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Check out repository code - name: Check out repository code
uses: actions/checkout@v4 uses: actions/checkout@v3
- uses: actions/setup-node@v4 - uses: actions/setup-node@v3
with: with:
node-version: 18 node-version: 18
- uses: nymtech/nym/.github/actions/nym-hash-releases@develop - uses: nymtech/nym/.github/actions/nym-hash-releases@develop
@@ -30,7 +30,7 @@ jobs:
with: with:
release-tag-or-name-or-id: ${{ inputs.release_tag }} release-tag-or-name-or-id: ${{ inputs.release_tag }}
- uses: actions/upload-artifact@v4 - uses: actions/upload-artifact@v2
with: with:
name: Asset Hashes name: Asset Hashes
path: hashes.json path: hashes.json
+1 -4
View File
@@ -48,7 +48,4 @@ foxyfox.env
.next .next
ppa-private-key.b64 ppa-private-key.b64
ppa-private-key.asc ppa-private-key.asc
nym-network-monitor/topology.json
nym-network-monitor/__pycache__
nym-network-monitor/*.key
-144
View File
@@ -4,150 +4,6 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
## [Unreleased] ## [Unreleased]
## [2024.11-wedel] (2024-09-23)
- Backport #4894 to fix ci ([#4899])
- Bugfix/ticketbook false double spending ([#4892])
- fix: allow updating globally stored signatures ([#4891])
- [DOCs/operators]: Document changelog for patch/2024.10-caramello ([#4886])
- [DOCs/operators]: Post release docs updates ([#4874])
- Bump defguard to github latest version ([#4872])
- chore: removed completed queued mixnet migration ([#4865])
- Disable push trigger and add missing paths in ci-build ([#4864])
- Fix linux conditional in ci-build.yml ([#4863])
- Remove golang workaround in ci-sdk-wasm ([#4858])
- Revert runner for ci-docs ([#4855])
- Move credential verification into common crate ([#4853])
- Fix test failure in ipr request size ([#4844])
- Start switching over jobs to arc-ubuntu-20.04 ([#4843])
- Use ecash credential type for bandwidth value ([#4840])
- Create nym-repo-setup debian package and nym-vpn meta package ([#4837])
- Remove serde_crate named import ([#4832])
- Run cargo autoinherit following last weeks dependabot updates ([#4831])
- revamped ticketbook serialisation and exposed additional cli methods ([#4827])
- Expose wireguard details on self described endpoint ([#4825])
- Remove unused wireguard flag from SDK ([#4823])
- Add `axum` server to `nym-api` ([#4803])
- Run cargo-autoinherit for a few new crates ([#4801])
- Update dependabot ([#4796])
- Fix clippy for unwrap_or_default ([#4783])
- Enable dependabot version upgrades for root rust workspace ([#4778])
- Persist used wireguard private IPs ([#4771])
- Avoid race on ip and registration structures ([#4766])
- docs/hotfix ([#4765])
- chore: remove repetitive words ([#4763])
- Make gateway latency check generic ([#4759])
- Remove duplicate stat count for retransmissions ([#4756])
- Update peer refresh value ([#4754])
- Remove deprecated mark_as_success and use new disarm ([#4751])
- Add get_mixnodes_described to validator_client ([#4725])
- New Network Monitor ([#4610])
[#4899]: https://github.com/nymtech/nym/pull/4899
[#4892]: https://github.com/nymtech/nym/pull/4892
[#4891]: https://github.com/nymtech/nym/pull/4891
[#4886]: https://github.com/nymtech/nym/pull/4886
[#4874]: https://github.com/nymtech/nym/pull/4874
[#4872]: https://github.com/nymtech/nym/pull/4872
[#4865]: https://github.com/nymtech/nym/pull/4865
[#4864]: https://github.com/nymtech/nym/pull/4864
[#4863]: https://github.com/nymtech/nym/pull/4863
[#4858]: https://github.com/nymtech/nym/pull/4858
[#4855]: https://github.com/nymtech/nym/pull/4855
[#4853]: https://github.com/nymtech/nym/pull/4853
[#4844]: https://github.com/nymtech/nym/pull/4844
[#4843]: https://github.com/nymtech/nym/pull/4843
[#4840]: https://github.com/nymtech/nym/pull/4840
[#4837]: https://github.com/nymtech/nym/pull/4837
[#4832]: https://github.com/nymtech/nym/pull/4832
[#4831]: https://github.com/nymtech/nym/pull/4831
[#4827]: https://github.com/nymtech/nym/pull/4827
[#4825]: https://github.com/nymtech/nym/pull/4825
[#4823]: https://github.com/nymtech/nym/pull/4823
[#4803]: https://github.com/nymtech/nym/pull/4803
[#4801]: https://github.com/nymtech/nym/pull/4801
[#4796]: https://github.com/nymtech/nym/pull/4796
[#4783]: https://github.com/nymtech/nym/pull/4783
[#4778]: https://github.com/nymtech/nym/pull/4778
[#4771]: https://github.com/nymtech/nym/pull/4771
[#4766]: https://github.com/nymtech/nym/pull/4766
[#4765]: https://github.com/nymtech/nym/pull/4765
[#4763]: https://github.com/nymtech/nym/pull/4763
[#4759]: https://github.com/nymtech/nym/pull/4759
[#4756]: https://github.com/nymtech/nym/pull/4756
[#4754]: https://github.com/nymtech/nym/pull/4754
[#4751]: https://github.com/nymtech/nym/pull/4751
[#4725]: https://github.com/nymtech/nym/pull/4725
[#4610]: https://github.com/nymtech/nym/pull/4610
## [2024.10-caramello] (2024-09-10)
- Backport 4844 and 4845 ([#4857])
- Bugfix/client registration vol2 ([#4856])
- Remove wireguard feature flag and pass runtime enabled flag ([#4839])
- Eliminate cancel unsafe sig awaiting ([#4834])
- added explicit updateable admin to the mixnet contract ([#4822])
- using legacy signing payload in CLI and verifying both variants in contract ([#4821])
- adding ecash contract address ([#4819])
- Check profit margin of node before defaulting to hardcoded value ([#4802])
- Sync last_seen_bandwidth immediately ([#4774])
- Feature/additional ecash nym cli utils ([#4773])
- Better storage error logging ([#4772])
- bugfix: make sure DKG parses data out of events if logs are empty ([#4764])
- Fix clippy on rustc beta toolchain ([#4746])
- Fix clippy for beta toolchain ([#4742])
- Disable testnet-manager on non-unix ([#4741])
- Don't set NYM_VPN_API to default ([#4740])
- Update publish-nym-binaries.yml ([#4739])
- Update ci-build-upload-binaries.yml ([#4738])
- Add NYM_VPN_API to network config ([#4736])
- Re-export RecipientFormattingError in nym sdk ([#4735])
- Persist wireguard peers ([#4732])
- Fix tokio error in 1.39 ([#4730])
- Feature/vesting purge plus ranged cost params ([#4716])
- Fix (some) feature unification build failures ([#4681])
- Feature Compact Ecash : The One PR ([#4623])
[#4857]: https://github.com/nymtech/nym/pull/4857
[#4856]: https://github.com/nymtech/nym/pull/4856
[#4839]: https://github.com/nymtech/nym/pull/4839
[#4834]: https://github.com/nymtech/nym/pull/4834
[#4822]: https://github.com/nymtech/nym/pull/4822
[#4821]: https://github.com/nymtech/nym/pull/4821
[#4819]: https://github.com/nymtech/nym/pull/4819
[#4802]: https://github.com/nymtech/nym/pull/4802
[#4774]: https://github.com/nymtech/nym/pull/4774
[#4773]: https://github.com/nymtech/nym/pull/4773
[#4772]: https://github.com/nymtech/nym/pull/4772
[#4764]: https://github.com/nymtech/nym/pull/4764
[#4746]: https://github.com/nymtech/nym/pull/4746
[#4742]: https://github.com/nymtech/nym/pull/4742
[#4741]: https://github.com/nymtech/nym/pull/4741
[#4740]: https://github.com/nymtech/nym/pull/4740
[#4739]: https://github.com/nymtech/nym/pull/4739
[#4738]: https://github.com/nymtech/nym/pull/4738
[#4736]: https://github.com/nymtech/nym/pull/4736
[#4735]: https://github.com/nymtech/nym/pull/4735
[#4732]: https://github.com/nymtech/nym/pull/4732
[#4730]: https://github.com/nymtech/nym/pull/4730
[#4716]: https://github.com/nymtech/nym/pull/4716
[#4681]: https://github.com/nymtech/nym/pull/4681
[#4623]: https://github.com/nymtech/nym/pull/4623
## [2024.9-topdeck] (2024-07-26)
- chore: fix 1.80 lint issues ([#4731])
- Handle clients with different versions in IPR ([#4723])
- Add 1GB/day/user bandwidth cap ([#4717])
- Feature/merge back ([#4710])
- removed mixnode/gateway config migration code and disabled cli without explicit flag ([#4706])
[#4731]: https://github.com/nymtech/nym/pull/4731
[#4723]: https://github.com/nymtech/nym/pull/4723
[#4717]: https://github.com/nymtech/nym/pull/4717
[#4710]: https://github.com/nymtech/nym/pull/4710
[#4706]: https://github.com/nymtech/nym/pull/4706
## [2024.8-wispa] (2024-07-10) ## [2024.8-wispa] (2024-07-10)
- add event parsing to support cosmos_sdk > 0.50 ([#4697]) - add event parsing to support cosmos_sdk > 0.50 ([#4697])
Generated
+879 -1840
View File
File diff suppressed because it is too large Load Diff
+59 -102
View File
@@ -5,7 +5,6 @@
panic = "abort" panic = "abort"
opt-level = "s" opt-level = "s"
overflow-checks = true overflow-checks = true
debug = true
[profile.dev] [profile.dev]
panic = "abort" panic = "abort"
@@ -15,6 +14,7 @@ panic = "abort"
opt-level = 3 opt-level = 3
[workspace] [workspace]
resolver = "2" resolver = "2"
members = [ members = [
"clients/native", "clients/native",
@@ -34,7 +34,6 @@ members = [
"common/commands", "common/commands",
"common/config", "common/config",
"common/cosmwasm-smart-contracts/coconut-bandwidth-contract", "common/cosmwasm-smart-contracts/coconut-bandwidth-contract",
"common/cosmwasm-smart-contracts/ecash-contract",
"common/cosmwasm-smart-contracts/coconut-dkg", "common/cosmwasm-smart-contracts/coconut-dkg",
"common/cosmwasm-smart-contracts/contracts-common", "common/cosmwasm-smart-contracts/contracts-common",
"common/cosmwasm-smart-contracts/group-contract", "common/cosmwasm-smart-contracts/group-contract",
@@ -46,15 +45,10 @@ members = [
"common/credentials", "common/credentials",
"common/credential-utils", "common/credential-utils",
"common/credentials-interface", "common/credentials-interface",
"common/credential-verification",
"common/crypto", "common/crypto",
"common/dkg", "common/dkg",
"common/ecash-double-spending",
"common/ecash-time",
"common/execute", "common/execute",
"common/exit-policy", "common/exit-policy",
"common/gateway-requests",
"common/gateway-storage",
"common/http-api-client", "common/http-api-client",
"common/http-api-common", "common/http-api-common",
"common/inclusion-probability", "common/inclusion-probability",
@@ -65,7 +59,6 @@ members = [
"common/node-tester-utils", "common/node-tester-utils",
"common/nonexhaustive-delayqueue", "common/nonexhaustive-delayqueue",
"common/nymcoconut", "common/nymcoconut",
"common/nym_offline_compact_ecash",
"common/nym-id", "common/nym-id",
"common/nym-metrics", "common/nym-metrics",
"common/nymsphinx", "common/nymsphinx",
@@ -81,8 +74,6 @@ members = [
"common/nymsphinx/types", "common/nymsphinx/types",
"common/nyxd-scraper", "common/nyxd-scraper",
"common/pemstore", "common/pemstore",
"common/serde-helpers",
"common/service-provider-requests-common",
"common/socks5-client-core", "common/socks5-client-core",
"common/socks5/proxy-helpers", "common/socks5/proxy-helpers",
"common/socks5/requests", "common/socks5/requests",
@@ -100,32 +91,25 @@ members = [
"explorer-api/explorer-api-requests", "explorer-api/explorer-api-requests",
"explorer-api/explorer-client", "explorer-api/explorer-client",
"gateway", "gateway",
"gateway/gateway-requests",
"integrations/bity", "integrations/bity",
"mixnode", "mixnode",
"sdk/lib/socks5-listener", "sdk/lib/socks5-listener",
"sdk/rust/nym-sdk", "sdk/rust/nym-sdk",
"sdk/ffi/shared",
"sdk/ffi/go",
"sdk/ffi/cpp",
"service-providers/authenticator", "service-providers/authenticator",
"service-providers/common", "service-providers/common",
"service-providers/ip-packet-router", "service-providers/ip-packet-router",
"service-providers/network-requester", "service-providers/network-requester",
"nym-network-monitor",
"nym-api", "nym-api",
"nym-browser-extension/storage", "nym-browser-extension/storage",
"nym-api/nym-api-requests", "nym-api/nym-api-requests",
"nym-data-observatory",
"nym-node", "nym-node",
"nym-node/nym-node-http-api", "nym-node/nym-node-http-api",
"nym-node/nym-node-requests", "nym-node/nym-node-requests",
"nym-outfox", "nym-outfox",
"nym-validator-rewarder", "nym-validator-rewarder",
"tools/echo-server",
"tools/internal/ssl-inject", "tools/internal/ssl-inject",
# "tools/internal/sdk-version-bump", # "tools/internal/sdk-version-bump",
"tools/internal/testnet-manager",
"tools/internal/testnet-manager/dkg-bypass-contract",
"tools/nym-cli", "tools/nym-cli",
"tools/nym-id-cli", "tools/nym-id-cli",
"tools/nym-nr-query", "tools/nym-nr-query",
@@ -136,33 +120,27 @@ members = [
"wasm/mix-fetch", "wasm/mix-fetch",
"wasm/node-tester", "wasm/node-tester",
"wasm/zknym-lib", "wasm/zknym-lib",
"tools/internal/testnet-manager",
"tools/internal/testnet-manager/dkg-bypass-contract",
"tools/echo-server",
] ]
default-members = [ default-members = [
"clients/native", "clients/native",
"clients/socks5", "clients/socks5",
"explorer-api",
"gateway", "gateway",
"service-providers/network-requester",
"mixnode", "mixnode",
"nym-api", "nym-api",
"nym-data-observatory",
"nym-node",
"nym-validator-rewarder",
"service-providers/authenticator",
"service-providers/ip-packet-router",
"service-providers/network-requester",
"tools/nymvisor", "tools/nymvisor",
"explorer-api",
"nym-validator-rewarder",
"nym-node"
] ]
exclude = [ exclude = [
"explorer", "explorer",
"contracts", "contracts",
"nym-wallet", "nym-wallet",
"nym-vpn/ui/src-tauri",
"cpu-cycles", "cpu-cycles",
"sdk/ffi/cpp",
] ]
[workspace.package] [workspace.package]
@@ -172,33 +150,24 @@ homepage = "https://nymtech.net"
documentation = "https://nymtech.net" documentation = "https://nymtech.net"
edition = "2021" edition = "2021"
license = "Apache-2.0" license = "Apache-2.0"
rust-version = "1.80"
readme = "README.md"
[workspace.dependencies] [workspace.dependencies]
addr = "0.15.6" addr = "0.15.6"
aes = "0.8.1" aes = "0.8.1"
aes-gcm = "0.10.1" aes-gcm = "0.10.1"
aes-gcm-siv = "0.11.1" anyhow = "1.0.71"
aead = "0.5.2"
anyhow = "1.0.89"
argon2 = "0.5.0" argon2 = "0.5.0"
async-trait = "0.1.82" async-trait = "0.1.68"
axum = "0.7.5" axum = "0.7.5"
axum-extra = "0.9.3" axum-extra = "0.9.3"
base64 = "0.22.1" base64 = "0.21.4"
bincode = "1.3.3" bincode = "1.3.3"
bip39 = { version = "2.0.0", features = ["zeroize"] } bip39 = { version = "2.0.0", features = ["zeroize"] }
# can we unify those?
bit-vec = "0.7.0"
bitvec = "1.0.0" bitvec = "1.0.0"
blake3 = "1.3.1"
blake3 = "1.5.4"
bloomfilter = "1.0.14"
bs58 = "0.5.1" bs58 = "0.5.1"
bytecodec = "0.4.15" bytecodec = "0.4.15"
bytes = "1.7.1" bytes = "1.5.0"
cargo_metadata = "0.18.1" cargo_metadata = "0.18.1"
celes = "2.4.0" celes = "2.4.0"
cfg-if = "1.0.0" cfg-if = "1.0.0"
@@ -206,38 +175,36 @@ chacha20 = "0.9.0"
chacha20poly1305 = "0.10.1" chacha20poly1305 = "0.10.1"
chrono = "0.4.31" chrono = "0.4.31"
cipher = "0.4.3" cipher = "0.4.3"
clap = "4.5.17" clap = "4.4.7"
clap_complete = "4.5" clap_complete = "4.0"
clap_complete_fig = "4.5" clap_complete_fig = "4.0"
colored = "2.0" colored = "2.0"
comfy-table = "7.1.1" comfy-table = "6.0.0"
console = "0.15.8"
console-subscriber = "0.1.1" console-subscriber = "0.1.1"
console_error_panic_hook = "0.1" console_error_panic_hook = "0.1"
const-str = "0.5.6" const-str = "0.5.6"
const_format = "0.2.33" const_format = "0.2.32"
criterion = "0.4" criterion = "0.4"
csv = "1.3.0" csv = "1.3.0"
ctr = "0.9.1" ctr = "0.9.1"
cupid = "0.6.1" cupid = "0.6.1"
curve25519-dalek = "4.1" curve25519-dalek = "4.1"
dashmap = "5.5.3" dashmap = "5.5.3"
# We want https://github.com/DefGuard/wireguard-rs/pull/64 , but there's no crates.io release being pushed out anymore defguard_wireguard_rs = "0.4.2"
defguard_wireguard_rs = { git = "https://github.com/DefGuard/wireguard-rs.git", rev = "v0.4.7" }
digest = "0.10.7" digest = "0.10.7"
dirs = "5.0" dirs = "4.0"
doc-comment = "0.3" doc-comment = "0.3"
dotenvy = "0.15.6" dotenvy = "0.15.6"
ecdsa = "0.16" ecdsa = "0.16"
ed25519-dalek = "2.1" ed25519-dalek = "2.1"
etherparse = "0.13.0" etherparse = "0.13.0"
eyre = "0.6.9" eyre = "0.6.9"
fastrand = "2.1.1" fastrand = "2.1.0"
flate2 = "1.0.33" flate2 = "1.0.28"
futures = "0.3.28" futures = "0.3.28"
generic-array = "0.14.7" generic-array = "0.14.7"
getrandom = "0.2.10" getrandom = "0.2.10"
getset = "0.1.3" getset = "0.1.1"
handlebars = "3.5.5" handlebars = "3.5.5"
headers = "0.4.0" headers = "0.4.0"
hex = "0.4.3" hex = "0.4.3"
@@ -245,18 +212,15 @@ hex-literal = "0.3.3"
hkdf = "0.12.3" hkdf = "0.12.3"
hmac = "0.12.1" hmac = "0.12.1"
http = "1" http = "1"
http-body-util = "0.1"
httpcodec = "0.2.3" httpcodec = "0.2.3"
humantime = "2.1.0" humantime = "2.1.0"
humantime-serde = "1.1.1" humantime-serde = "1.1.1"
hyper = "1.4.1" hyper = "1.3.1"
hyper-util = "0.1" indexed_db_futures = "0.3.0"
indicatif = "0.17.8"
inquire = "0.6.2" inquire = "0.6.2"
ip_network = "0.4.1" ip_network = "0.4.1"
ipnetwork = "0.20" ipnetwork = "0.16"
isocountry = "0.3.2" isocountry = "0.3.2"
itertools = "0.13.0"
k256 = "0.13" k256 = "0.13"
lazy_static = "1.4.0" lazy_static = "1.4.0"
ledger-transport = "0.10.0" ledger-transport = "0.10.0"
@@ -270,54 +234,54 @@ okapi = "0.7.0"
once_cell = "1.7.2" once_cell = "1.7.2"
opentelemetry = "0.19.0" opentelemetry = "0.19.0"
opentelemetry-jaeger = "0.18.0" opentelemetry-jaeger = "0.18.0"
parking_lot = "0.12.3" parking_lot = "0.12.1"
pem = "0.8" pem = "0.8"
petgraph = "0.6.5"
pin-project = "1.0" pin-project = "1.0"
pretty_env_logger = "0.4.0" pretty_env_logger = "0.4.0"
publicsuffix = "2.2.3" publicsuffix = "2.2.3"
quote = "1" quote = "1"
rand = "0.8.5" rand = "0.8.5"
rand-07 = "0.7.3"
rand_chacha = "0.3" rand_chacha = "0.3"
rand_chacha_02 = "0.2"
rand_core = "0.6.3" rand_core = "0.6.3"
rand_distr = "0.4" rand_distr = "0.4"
rand_pcg = "0.3.1" rand_pcg = "0.3.1"
rand_seeder = "0.2.3" rand_seeder = "0.2.3"
rayon = "1.5.1" rayon = "1.5.1"
regex = "1.10.6" regex = "1.8.4"
reqwest = { version = "0.12.4", default-features = false } reqwest = { version = "0.12.4", default-features = false }
rocket = "0.5.0" rocket = "0.5.0"
rocket_cors = "0.6.0" rocket_cors = "0.6.0"
rocket_okapi = "0.8.0" rocket_okapi = "0.8.0"
safer-ffi = "0.1.13" safer-ffi = "0.1.4"
schemars = "0.8.21" schemars = "0.8.1"
semver = "1.0.23" semver = "1.0.23"
serde = "1.0.210" serde = "1.0.152"
serde_bytes = "0.11.15" serde_bytes = "0.11.6"
serde_derive = "1.0" serde_derive = "1.0"
serde_json = "1.0.128" serde_json = "1.0.91"
serde_repr = "0.1" serde_repr = "0.1"
serde_with = "3.9.0" serde_with = "3.4.0"
serde_yaml = "0.9.25" serde_yaml = "0.9.25"
sha2 = "0.10.8" sha2 = "0.10.8"
si-scale = "0.2.3" si-scale = "0.2.2"
sphinx-packet = "0.1.1" sphinx-packet = "0.1.1"
sqlx = "0.6.3" sqlx = "0.6.3"
strum = "0.26" strum = "0.25"
subtle-encoding = "0.5" subtle-encoding = "0.5"
syn = "1" syn = "1"
sysinfo = "0.30.13" sysinfo = "0.30.12"
tap = "1.0.1" tap = "1.0.1"
tar = "0.4.41" tar = "0.4.40"
tempfile = "3.5.0" tempfile = "3.5.0"
thiserror = "1.0.63" thiserror = "1.0.48"
time = "0.3.30" time = "0.3.30"
tokio = "1.39" tokio = "1.39"
tokio-stream = "0.1.16" tokio-stream = "0.1.15"
tokio-test = "0.4.4" tokio-test = "0.4.4"
tokio-tun = "0.11.5"
tokio-tungstenite = { version = "0.20.1" } tokio-tungstenite = { version = "0.20.1" }
tokio-util = "0.7.12" tokio-util = "0.7.11"
toml = "0.8.14" toml = "0.8.14"
tower = "0.4.13" tower = "0.4.13"
tower-http = "0.5.2" tower-http = "0.5.2"
@@ -327,14 +291,12 @@ tracing-subscriber = "0.3.16"
tracing-tree = "0.2.2" tracing-tree = "0.2.2"
ts-rs = "7.0.0" ts-rs = "7.0.0"
tungstenite = { version = "0.20.1", default-features = false } tungstenite = { version = "0.20.1", default-features = false }
url = "2.5" url = "2.4"
utoipa = "4.2" utoipa = "4.2.0"
utoipa-swagger-ui = "7.1" utoipa-swagger-ui = "6.0.0"
utoipauto = "0.1"
uuid = "*"
vergen = { version = "=8.3.1", default-features = false } vergen = { version = "=8.3.1", default-features = false }
walkdir = "2" walkdir = "2"
wasm-bindgen-test = "0.3.43" wasm-bindgen-test = "0.3.36"
x25519-dalek = "2.0.0" x25519-dalek = "2.0.0"
zeroize = "1.6.0" zeroize = "1.6.0"
@@ -343,12 +305,12 @@ 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
# as we need to be able to serialize Gt so that we could create the lookup table for baby-step-giant-step algorithm # as we need to be able to serialize Gt so that we could create the lookup table for baby-step-giant-step algorithm
# plus to make our live easier we need serde support from https://github.com/zkcrypto/bls12_381/pull/125 bls12_381 = { git = "https://github.com/jstuczyn/bls12_381", default-features = false, branch = "feature/gt-serialization-0.8.0" }
bls12_381 = { git = "https://github.com/jstuczyn/bls12_381", default-features = false, branch = "temp/experimental-serdect" }
group = { version = "0.13.0", default-features = false } group = { version = "0.13.0", default-features = false }
ff = { version = "0.13.0", default-features = false } ff = { version = "0.13.0", default-features = false }
# cosmwasm-related # cosmwasm-related
cosmwasm-derive = "=1.4.3"
cosmwasm-schema = "=1.4.3" cosmwasm-schema = "=1.4.3"
cosmwasm-std = "=1.4.3" cosmwasm-std = "=1.4.3"
# use 0.5.0 as that's the version used by cosmwasm-std 1.4.3 # use 0.5.0 as that's the version used by cosmwasm-std 1.4.3
@@ -364,31 +326,26 @@ cw4 = { version = "=1.1.2" }
cw-controllers = { version = "=1.1.0" } cw-controllers = { version = "=1.1.0" }
# cosmrs-related # cosmrs-related
bip32 = { version = "0.5.2", default-features = false } bip32 = { version = "0.5.1", default-features = false }
# temporarily using a fork again (yay.) because we need staking and slashing support (which are already on main but not released) # temporarily using a fork again (yay.) because we need staking and slashing support
# plus response message parsing (which is, as of the time of writing this message, waiting to get merged) cosmrs = { git = "https://github.com/jstuczyn/cosmos-rust", branch = "nym-temp/all-validator-features" }
#cosmrs = { path = "../cosmos-rust-fork/cosmos-rust/cosmrs" } #cosmrs = { git = "https://github.com/jstuczyn/cosmos-rust", branch = "nym-temp/all-validator-features" } # unfortuntely we need a fork by yours truly to get the staking support
cosmrs = { git = "https://github.com/cosmos/cosmos-rust", rev = "4b1332e6d8258ac845cef71589c8d362a669675a" } # unfortuntely we need a fork by yours truly to get the staking support tendermint = "0.34" # same version as used by cosmrs
tendermint = "0.37.0" # same version as used by cosmrs tendermint-rpc = "0.34" # same version as used by cosmrs
tendermint-rpc = "0.37.0" # same version as used by cosmrs
prost = { version = "0.12", default-features = false } prost = { version = "0.12", default-features = false }
# wasm-related dependencies # wasm-related dependencies
gloo-utils = "0.2.0" gloo-utils = "0.2.0"
gloo-net = "0.5.0" gloo-net = "0.5.0"
js-sys = "0.3.69"
# use a separate branch due to feature unification failures
# this is blocked until the upstream removes outdates `wasm_bindgen` feature usage
# indexed_db_futures = "0.4.1"
indexed_db_futures = { git = "https://github.com/TiemenSch/rust-indexed-db", branch = "update-uuid" }
js-sys = "0.3.70"
serde-wasm-bindgen = "0.6.5" serde-wasm-bindgen = "0.6.5"
tsify = "0.4.5" tsify = "0.4.5"
wasm-bindgen = "0.2.93" wasm-bindgen = "0.2.92"
wasm-bindgen-futures = "0.4.43" wasm-bindgen-futures = "0.4.39"
wasmtimer = "0.2.0" wasmtimer = "0.2.0"
web-sys = "0.3.70" web-sys = "0.3.69"
itertools = "0.12.0"
# Profile settings for individual crates # Profile settings for individual crates
+1 -1
View File
@@ -133,7 +133,7 @@ clippy: sdk-wasm-lint
# Build contracts ready for deploy # Build contracts ready for deploy
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
CONTRACTS=vesting_contract mixnet_contract nym_ecash CONTRACTS=vesting_contract mixnet_contract
CONTRACTS_WASM=$(addsuffix .wasm, $(CONTRACTS)) CONTRACTS_WASM=$(addsuffix .wasm, $(CONTRACTS))
CONTRACTS_OUT_DIR=contracts/target/wasm32-unknown-unknown/release CONTRACTS_OUT_DIR=contracts/target/wasm32-unknown-unknown/release
+7 -23
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "nym-client" name = "nym-client"
version = "1.1.41" version = "1.1.38"
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"
@@ -26,46 +26,30 @@ clap = { workspace = true, features = ["cargo", "derive"] }
dirs = { workspace = true } dirs = { workspace = true }
log = { workspace = true } # self explanatory log = { workspace = true } # self explanatory
rand = { workspace = true } rand = { workspace = true }
serde = { workspace = true, features = [ serde = { workspace = true, features = ["derive"] } # for config serialization/deserialization
"derive",
] } # for config serialization/deserialization
serde_json = { workspace = true } serde_json = { workspace = true }
thiserror = { workspace = true } thiserror = { workspace = true }
tap = { workspace = true } tap = { workspace = true }
time = { workspace = true } time = { workspace = true }
tokio = { workspace = true, features = [ tokio = { workspace = true, features = ["rt-multi-thread", "net", "signal"] } # async runtime
"rt-multi-thread",
"net",
"signal",
] } # async runtime
tokio-tungstenite = { workspace = true } tokio-tungstenite = { workspace = true }
zeroize = { workspace = true } zeroize = { workspace = true }
## internal ## internal
nym-bandwidth-controller = { path = "../../common/bandwidth-controller" } 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", "clap"] }
"output_format", nym-client-core = { path = "../../common/client-core", features = ["fs-surb-storage", "fs-gateways-storage", "cli"] }
"clap",
] }
nym-client-core = { path = "../../common/client-core", features = [
"fs-credentials-storage",
"fs-surb-storage",
"fs-gateways-storage",
"cli",
] }
nym-config = { path = "../../common/config" } nym-config = { path = "../../common/config" }
nym-credential-storage = { path = "../../common/credential-storage" } nym-credential-storage = { path = "../../common/credential-storage" }
nym-credentials = { path = "../../common/credentials" } nym-credentials = { path = "../../common/credentials" }
nym-crypto = { path = "../../common/crypto" } nym-crypto = { path = "../../common/crypto" }
nym-gateway-requests = { path = "../../common/gateway-requests" } nym-gateway-requests = { path = "../../gateway/gateway-requests" }
nym-network-defaults = { path = "../../common/network-defaults" } nym-network-defaults = { path = "../../common/network-defaults" }
nym-sphinx = { path = "../../common/nymsphinx" } nym-sphinx = { path = "../../common/nymsphinx" }
nym-pemstore = { path = "../../common/pemstore" } nym-pemstore = { path = "../../common/pemstore" }
nym-task = { path = "../../common/task" } nym-task = { path = "../../common/task" }
nym-topology = { path = "../../common/topology" } nym-topology = { path = "../../common/topology" }
nym-validator-client = { path = "../../common/client-libs/validator-client", features = [ nym-validator-client = { path = "../../common/client-libs/validator-client", features = ["http-client"] }
"http-client",
] }
nym-client-websocket-requests = { path = "websocket-requests" } nym-client-websocket-requests = { path = "websocket-requests" }
nym-id = { path = "../../common/nym-id" } nym-id = { path = "../../common/nym-id" }
@@ -1,16 +0,0 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::commands::CliNativeClient;
use crate::error::ClientError;
use nym_client_core::cli_helpers::client_import_coin_index_signatures::{
import_coin_index_signatures, CommonClientImportCoinIndexSignaturesArgs,
};
pub(crate) async fn execute(
args: CommonClientImportCoinIndexSignaturesArgs,
) -> Result<(), ClientError> {
import_coin_index_signatures::<CliNativeClient, _>(args).await?;
println!("successfully imported coin index signatures!");
Ok(())
}
@@ -1,16 +0,0 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::commands::CliNativeClient;
use crate::error::ClientError;
use nym_client_core::cli_helpers::client_import_expiration_date_signatures::{
import_expiration_date_signatures, CommonClientImportExpirationDateSignaturesArgs,
};
pub(crate) async fn execute(
args: CommonClientImportExpirationDateSignaturesArgs,
) -> Result<(), ClientError> {
import_expiration_date_signatures::<CliNativeClient, _>(args).await?;
println!("successfully imported expiration date signatures!");
Ok(())
}
@@ -1,16 +0,0 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::commands::CliNativeClient;
use crate::error::ClientError;
use nym_client_core::cli_helpers::client_import_master_verification_key::{
import_master_verification_key, CommonClientImportMasterVerificationKeyArgs,
};
pub(crate) async fn execute(
args: CommonClientImportMasterVerificationKeyArgs,
) -> Result<(), ClientError> {
import_master_verification_key::<CliNativeClient, _>(args).await?;
println!("successfully imported master verification key!");
Ok(())
}
-59
View File
@@ -1,59 +0,0 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use clap::{Args, Subcommand};
use nym_client_core::cli_helpers::client_import_coin_index_signatures::CommonClientImportCoinIndexSignaturesArgs;
use nym_client_core::cli_helpers::client_import_credential::CommonClientImportTicketBookArgs;
use nym_client_core::cli_helpers::client_import_expiration_date_signatures::CommonClientImportExpirationDateSignaturesArgs;
use nym_client_core::cli_helpers::client_import_master_verification_key::CommonClientImportMasterVerificationKeyArgs;
use std::error::Error;
pub(crate) mod import_coin_index_signatures;
pub(crate) mod import_credential;
pub(crate) mod import_expiration_date_signatures;
pub(crate) mod import_master_verification_key;
pub(crate) mod show_ticketbooks;
#[derive(Args)]
#[clap(args_conflicts_with_subcommands = true, subcommand_required = true)]
pub struct Ecash {
#[clap(subcommand)]
pub command: EcashCommands,
}
impl Ecash {
pub async fn execute(self) -> Result<(), Box<dyn Error + Send + Sync>> {
match self.command {
EcashCommands::ShowTicketBooks(args) => show_ticketbooks::execute(args).await?,
EcashCommands::ImportTicketBook(args) => import_credential::execute(args).await?,
EcashCommands::ImportCoinIndexSignatures(args) => {
import_coin_index_signatures::execute(args).await?
}
EcashCommands::ImportExpirationDateSignatures(args) => {
import_expiration_date_signatures::execute(args).await?
}
EcashCommands::ImportMasterVerificationKey(args) => {
import_master_verification_key::execute(args).await?
}
}
Ok(())
}
}
#[derive(Subcommand)]
pub enum EcashCommands {
/// Display information associated with the imported ticketbooks,
ShowTicketBooks(show_ticketbooks::Args),
/// Import a pre-generated ticketbook
ImportTicketBook(CommonClientImportTicketBookArgs),
/// Import coin index signatures needed for ticketbooks
ImportCoinIndexSignatures(CommonClientImportCoinIndexSignaturesArgs),
/// Import expiration date signatures needed for ticketbooks
ImportExpirationDateSignatures(CommonClientImportExpirationDateSignaturesArgs),
/// Import master verification key needed for ticketbooks
ImportMasterVerificationKey(CommonClientImportMasterVerificationKeyArgs),
}
@@ -1,32 +0,0 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::commands::CliNativeClient;
use crate::error::ClientError;
use nym_bin_common::output_format::OutputFormat;
use nym_client_core::cli_helpers::client_show_ticketbooks::{
show_ticketbooks, CommonShowTicketbooksArgs,
};
#[derive(clap::Args)]
pub(crate) struct Args {
#[command(flatten)]
common_args: CommonShowTicketbooksArgs,
#[arg(short, long, default_value_t = OutputFormat::default())]
output: OutputFormat,
}
impl AsRef<CommonShowTicketbooksArgs> for Args {
fn as_ref(&self) -> &CommonShowTicketbooksArgs {
&self.common_args
}
}
pub(crate) async fn execute(args: Args) -> Result<(), ClientError> {
let output = args.output;
let res = show_ticketbooks::<CliNativeClient, _>(args).await?;
println!("{}", output.format(&res));
Ok(())
}
@@ -4,10 +4,10 @@
use crate::commands::CliNativeClient; use crate::commands::CliNativeClient;
use crate::error::ClientError; use crate::error::ClientError;
use nym_client_core::cli_helpers::client_import_credential::{ use nym_client_core::cli_helpers::client_import_credential::{
import_credential, CommonClientImportTicketBookArgs, import_credential, CommonClientImportCredentialArgs,
}; };
pub(crate) async fn execute(args: CommonClientImportTicketBookArgs) -> Result<(), ClientError> { pub(crate) async fn execute(args: CommonClientImportCredentialArgs) -> Result<(), ClientError> {
import_credential::<CliNativeClient, _>(args).await?; import_credential::<CliNativeClient, _>(args).await?;
println!("successfully imported credential!"); println!("successfully imported credential!");
Ok(()) Ok(())
+5 -5
View File
@@ -6,13 +6,13 @@ 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::{BaseClientConfig, Config}; use crate::client::config::{BaseClientConfig, Config};
use crate::commands::ecash::Ecash;
use crate::error::ClientError; use crate::error::ClientError;
use clap::CommandFactory; use clap::CommandFactory;
use clap::{Parser, Subcommand}; use clap::{Parser, Subcommand};
use log::{error, info}; use log::{error, info};
use nym_bin_common::bin_info; use nym_bin_common::bin_info;
use nym_bin_common::completions::{fig_generate, ArgShell}; use nym_bin_common::completions::{fig_generate, ArgShell};
use nym_client_core::cli_helpers::client_import_credential::CommonClientImportCredentialArgs;
use nym_client_core::cli_helpers::CliClient; use nym_client_core::cli_helpers::CliClient;
use nym_client_core::client::base_client::storage::migration_helpers::v1_1_33; use nym_client_core::client::base_client::storage::migration_helpers::v1_1_33;
use nym_config::OptionalSet; use nym_config::OptionalSet;
@@ -22,7 +22,7 @@ use std::sync::OnceLock;
mod add_gateway; mod add_gateway;
pub(crate) mod build_info; pub(crate) mod build_info;
pub(crate) mod ecash; pub(crate) mod import_credential;
pub(crate) mod init; pub(crate) mod init;
mod list_gateways; mod list_gateways;
pub(crate) mod run; pub(crate) mod run;
@@ -72,8 +72,8 @@ pub(crate) enum Commands {
/// Run the Nym client with provided configuration client optionally overriding set parameters /// Run the Nym client with provided configuration client optionally overriding set parameters
Run(run::Run), Run(run::Run),
/// Ecash-related functionalities /// Import a pre-generated credential
Ecash(Ecash), ImportCredential(CommonClientImportCredentialArgs),
/// List all registered with gateways /// List all registered with gateways
ListGateways(list_gateways::Args), ListGateways(list_gateways::Args),
@@ -112,7 +112,7 @@ pub(crate) async fn execute(args: Cli) -> Result<(), Box<dyn Error + Send + Sync
match args.command { match args.command {
Commands::Init(m) => init::execute(m).await?, Commands::Init(m) => init::execute(m).await?,
Commands::Run(m) => run::execute(m).await?, Commands::Run(m) => run::execute(m).await?,
Commands::Ecash(ecash) => ecash.execute().await?, Commands::ImportCredential(m) => import_credential::execute(m).await?,
Commands::ListGateways(args) => list_gateways::execute(args).await?, Commands::ListGateways(args) => list_gateways::execute(args).await?,
Commands::AddGateway(args) => add_gateway::execute(args).await?, Commands::AddGateway(args) => add_gateway::execute(args).await?,
Commands::SwitchGateway(args) => switch_gateway::execute(args).await?, Commands::SwitchGateway(args) => switch_gateway::execute(args).await?,
+1 -1
View File
@@ -422,7 +422,7 @@ impl Handler {
) { ) {
// We don't want a crash in the connection handler to trigger a shutdown of the whole // We don't want a crash in the connection handler to trigger a shutdown of the whole
// process. // process.
task_client.disarm(); task_client.mark_as_success();
let ws_stream = match accept_async(socket).await { let ws_stream = match accept_async(socket).await {
Ok(ws_stream) => ws_stream, Ok(ws_stream) => ws_stream,
+6 -18
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "nym-socks5-client" name = "nym-socks5-client"
version = "1.1.41" version = "1.1.38"
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"
@@ -11,9 +11,7 @@ license.workspace = true
bs58 = { workspace = true } bs58 = { workspace = true }
clap = { workspace = true, features = ["cargo", "derive"] } clap = { workspace = true, features = ["cargo", "derive"] }
log = { workspace = true } log = { workspace = true }
serde = { workspace = true, features = [ serde = { workspace = true, features = ["derive"] } # for config serialization/deserialization
"derive",
] } # for config serialization/deserialization
serde_json = { workspace = true } serde_json = { workspace = true }
tap = { workspace = true } tap = { workspace = true }
thiserror = { workspace = true } thiserror = { workspace = true }
@@ -24,21 +22,13 @@ url = { workspace = true }
zeroize = { workspace = true } zeroize = { workspace = true }
# internal # internal
nym-bin-common = { path = "../../common/bin-common", features = [ nym-bin-common = { path = "../../common/bin-common", features = ["output_format"] }
"output_format", nym-client-core = { path = "../../common/client-core", features = ["fs-surb-storage", "fs-gateways-storage", "cli"] }
"clap",
] }
nym-client-core = { path = "../../common/client-core", features = [
"fs-credentials-storage",
"fs-surb-storage",
"fs-gateways-storage",
"cli",
] }
nym-config = { path = "../../common/config" } nym-config = { path = "../../common/config" }
nym-credential-storage = { path = "../../common/credential-storage" } nym-credential-storage = { path = "../../common/credential-storage" }
nym-credentials = { path = "../../common/credentials" } nym-credentials = { path = "../../common/credentials" }
nym-crypto = { path = "../../common/crypto" } nym-crypto = { path = "../../common/crypto" }
nym-gateway-requests = { path = "../../common/gateway-requests" } nym-gateway-requests = { path = "../../gateway/gateway-requests" }
nym-id = { path = "../../common/nym-id" } nym-id = { path = "../../common/nym-id" }
nym-network-defaults = { path = "../../common/network-defaults" } nym-network-defaults = { path = "../../common/network-defaults" }
nym-ordered-buffer = { path = "../../common/socks5/ordered-buffer" } nym-ordered-buffer = { path = "../../common/socks5/ordered-buffer" }
@@ -46,9 +36,7 @@ nym-pemstore = { path = "../../common/pemstore" }
nym-socks5-client-core = { path = "../../common/socks5-client-core" } nym-socks5-client-core = { path = "../../common/socks5-client-core" }
nym-sphinx = { path = "../../common/nymsphinx" } nym-sphinx = { path = "../../common/nymsphinx" }
nym-topology = { path = "../../common/topology" } nym-topology = { path = "../../common/topology" }
nym-validator-client = { path = "../../common/client-libs/validator-client", features = [ nym-validator-client = { path = "../../common/client-libs/validator-client", features = ["http-client"] }
"http-client",
] }
[features] [features]
default = [] default = []
@@ -1,16 +0,0 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::commands::CliSocks5Client;
use crate::error::Socks5ClientError;
use nym_client_core::cli_helpers::client_import_coin_index_signatures::{
import_coin_index_signatures, CommonClientImportCoinIndexSignaturesArgs,
};
pub(crate) async fn execute(
args: CommonClientImportCoinIndexSignaturesArgs,
) -> Result<(), Socks5ClientError> {
import_coin_index_signatures::<CliSocks5Client, _>(args).await?;
println!("successfully imported coin index signatures!");
Ok(())
}
@@ -1,16 +0,0 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::commands::CliSocks5Client;
use crate::error::Socks5ClientError;
use nym_client_core::cli_helpers::client_import_expiration_date_signatures::{
import_expiration_date_signatures, CommonClientImportExpirationDateSignaturesArgs,
};
pub(crate) async fn execute(
args: CommonClientImportExpirationDateSignaturesArgs,
) -> Result<(), Socks5ClientError> {
import_expiration_date_signatures::<CliSocks5Client, _>(args).await?;
println!("successfully imported expiration date signatures!");
Ok(())
}
@@ -1,16 +0,0 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::commands::CliSocks5Client;
use crate::error::Socks5ClientError;
use nym_client_core::cli_helpers::client_import_master_verification_key::{
import_master_verification_key, CommonClientImportMasterVerificationKeyArgs,
};
pub(crate) async fn execute(
args: CommonClientImportMasterVerificationKeyArgs,
) -> Result<(), Socks5ClientError> {
import_master_verification_key::<CliSocks5Client, _>(args).await?;
println!("successfully imported master verification key!");
Ok(())
}
-59
View File
@@ -1,59 +0,0 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use clap::{Args, Subcommand};
use nym_client_core::cli_helpers::client_import_coin_index_signatures::CommonClientImportCoinIndexSignaturesArgs;
use nym_client_core::cli_helpers::client_import_credential::CommonClientImportTicketBookArgs;
use nym_client_core::cli_helpers::client_import_expiration_date_signatures::CommonClientImportExpirationDateSignaturesArgs;
use nym_client_core::cli_helpers::client_import_master_verification_key::CommonClientImportMasterVerificationKeyArgs;
use std::error::Error;
pub(crate) mod import_coin_index_signatures;
pub(crate) mod import_credential;
pub(crate) mod import_expiration_date_signatures;
pub(crate) mod import_master_verification_key;
pub(crate) mod show_ticketbooks;
#[derive(Args)]
#[clap(args_conflicts_with_subcommands = true, subcommand_required = true)]
pub struct Ecash {
#[clap(subcommand)]
pub command: EcashCommands,
}
impl Ecash {
pub async fn execute(self) -> Result<(), Box<dyn Error + Send + Sync>> {
match self.command {
EcashCommands::ShowTicketBooks(args) => show_ticketbooks::execute(args).await?,
EcashCommands::ImportTicketBook(args) => import_credential::execute(args).await?,
EcashCommands::ImportCoinIndexSignatures(args) => {
import_coin_index_signatures::execute(args).await?
}
EcashCommands::ImportExpirationDateSignatures(args) => {
import_expiration_date_signatures::execute(args).await?
}
EcashCommands::ImportMasterVerificationKey(args) => {
import_master_verification_key::execute(args).await?
}
}
Ok(())
}
}
#[derive(Subcommand)]
pub enum EcashCommands {
/// Display information associated with the imported ticketbooks,
ShowTicketBooks(show_ticketbooks::Args),
/// Import a pre-generated ticketbook
ImportTicketBook(CommonClientImportTicketBookArgs),
/// Import coin index signatures needed for ticketbooks
ImportCoinIndexSignatures(CommonClientImportCoinIndexSignaturesArgs),
/// Import expiration date signatures needed for ticketbooks
ImportExpirationDateSignatures(CommonClientImportExpirationDateSignaturesArgs),
/// Import master verification key needed for ticketbooks
ImportMasterVerificationKey(CommonClientImportMasterVerificationKeyArgs),
}
@@ -1,32 +0,0 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::commands::CliSocks5Client;
use crate::error::Socks5ClientError;
use nym_bin_common::output_format::OutputFormat;
use nym_client_core::cli_helpers::client_show_ticketbooks::{
show_ticketbooks, CommonShowTicketbooksArgs,
};
#[derive(clap::Args)]
pub struct Args {
#[command(flatten)]
common_args: CommonShowTicketbooksArgs,
#[arg(short, long, default_value_t = OutputFormat::default())]
output: OutputFormat,
}
impl AsRef<CommonShowTicketbooksArgs> for Args {
fn as_ref(&self) -> &CommonShowTicketbooksArgs {
&self.common_args
}
}
pub async fn execute(args: Args) -> Result<(), Socks5ClientError> {
let output = args.output;
let res = show_ticketbooks::<CliSocks5Client, _>(args).await?;
println!("{}", output.format(&res));
Ok(())
}
@@ -4,10 +4,12 @@
use crate::commands::CliSocks5Client; use crate::commands::CliSocks5Client;
use crate::error::Socks5ClientError; use crate::error::Socks5ClientError;
use nym_client_core::cli_helpers::client_import_credential::{ use nym_client_core::cli_helpers::client_import_credential::{
import_credential, CommonClientImportTicketBookArgs, import_credential, CommonClientImportCredentialArgs,
}; };
pub async fn execute(args: CommonClientImportTicketBookArgs) -> Result<(), Socks5ClientError> { pub(crate) async fn execute(
args: CommonClientImportCredentialArgs,
) -> Result<(), Socks5ClientError> {
import_credential::<CliSocks5Client, _>(args).await?; import_credential::<CliSocks5Client, _>(args).await?;
println!("successfully imported credential!"); println!("successfully imported credential!");
Ok(()) Ok(())
+5 -5
View File
@@ -1,7 +1,6 @@
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net> // Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use crate::commands::ecash::Ecash;
use crate::config::old_config_v1_1_13::OldConfigV1_1_13; use crate::config::old_config_v1_1_13::OldConfigV1_1_13;
use crate::config::old_config_v1_1_20::ConfigV1_1_20; use crate::config::old_config_v1_1_20::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;
@@ -14,6 +13,7 @@ use clap::{Parser, Subcommand};
use log::{error, info}; use log::{error, info};
use nym_bin_common::bin_info; use nym_bin_common::bin_info;
use nym_bin_common::completions::{fig_generate, ArgShell}; use nym_bin_common::completions::{fig_generate, ArgShell};
use nym_client_core::cli_helpers::client_import_credential::CommonClientImportCredentialArgs;
use nym_client_core::cli_helpers::CliClient; use nym_client_core::cli_helpers::CliClient;
use nym_client_core::client::base_client::storage::migration_helpers::v1_1_33; use nym_client_core::client::base_client::storage::migration_helpers::v1_1_33;
use nym_client_core::client::topology_control::geo_aware_provider::CountryGroup; use nym_client_core::client::topology_control::geo_aware_provider::CountryGroup;
@@ -26,7 +26,7 @@ use std::sync::OnceLock;
mod add_gateway; mod add_gateway;
pub(crate) mod build_info; pub(crate) mod build_info;
pub mod ecash; mod import_credential;
pub mod init; pub mod init;
mod list_gateways; mod list_gateways;
pub(crate) mod run; pub(crate) mod run;
@@ -76,8 +76,8 @@ pub(crate) enum Commands {
/// Run the Nym client with provided configuration client optionally overriding set parameters /// Run the Nym client with provided configuration client optionally overriding set parameters
Run(run::Run), Run(run::Run),
/// Ecash-related functionalities /// Import a pre-generated credential
Ecash(Ecash), ImportCredential(CommonClientImportCredentialArgs),
/// List all registered with gateways /// List all registered with gateways
ListGateways(list_gateways::Args), ListGateways(list_gateways::Args),
@@ -119,7 +119,7 @@ pub(crate) async fn execute(args: Cli) -> Result<(), Box<dyn Error + Send + Sync
match args.command { match args.command {
Commands::Init(m) => init::execute(m).await?, Commands::Init(m) => init::execute(m).await?,
Commands::Run(m) => run::execute(m).await?, Commands::Run(m) => run::execute(m).await?,
Commands::Ecash(ecash) => ecash.execute().await?, Commands::ImportCredential(m) => import_credential::execute(m).await?,
Commands::ListGateways(args) => list_gateways::execute(args).await?, Commands::ListGateways(args) => list_gateways::execute(args).await?,
Commands::AddGateway(args) => add_gateway::execute(args).await?, Commands::AddGateway(args) => add_gateway::execute(args).await?,
Commands::SwitchGateway(args) => switch_gateway::execute(args).await?, Commands::SwitchGateway(args) => switch_gateway::execute(args).await?,
-15
View File
@@ -9,24 +9,9 @@ edition.workspace = true
license.workspace = true license.workspace = true
[dependencies] [dependencies]
base64 = { workspace = true }
bincode = { workspace = true } bincode = { workspace = true }
rand = { workspace = true } rand = { workspace = true }
serde = { workspace = true, features = ["derive"] } serde = { workspace = true, features = ["derive"] }
thiserror = { workspace = true }
nym-credentials-interface = { path = "../credentials-interface" }
nym-crypto = { path = "../crypto", features = ["asymmetric"] }
nym-service-provider-requests-common = { path = "../service-provider-requests-common" }
nym-sphinx = { path = "../nymsphinx" } nym-sphinx = { path = "../nymsphinx" }
nym-wireguard-types = { path = "../wireguard-types" } nym-wireguard-types = { path = "../wireguard-types" }
## verify:
hmac = { workspace = true, optional = true }
sha2 = { workspace = true, optional = true }
x25519-dalek = { workspace = true, features = ["static_secrets"] }
[features]
default = ["verify"]
# this is moved to a separate feature as we really need clients to import it (especially, *cough*, wasm)
verify = ["hmac", "sha2"]
@@ -1,22 +0,0 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use thiserror::Error;
#[derive(Debug, Error)]
pub enum Error {
#[error("the provided base64-encoded client MAC ('{mac}') was malformed: {source}")]
MalformedClientMac {
mac: String,
#[source]
source: base64::DecodeError,
},
#[cfg(feature = "verify")]
#[error("failed to verify mac provided by '{client}': {source}")]
FailedClientMacVerification {
client: String,
#[source]
source: hmac::digest::MacError,
},
}
+1 -7
View File
@@ -2,14 +2,8 @@
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
pub mod v1; pub mod v1;
pub mod v2;
mod error; pub const CURRENT_VERSION: u8 = 1;
pub use error::Error;
pub use v2 as latest;
pub const CURRENT_VERSION: u8 = 2;
fn make_bincode_serializer() -> impl bincode::Options { fn make_bincode_serializer() -> impl bincode::Options {
use bincode::Options; use bincode::Options;
@@ -1,13 +1,7 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net> // Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
pub mod registration;
pub mod request; pub mod request;
pub mod response; pub mod response;
pub use registration::{ClientMac, GatewayClient, InitMessage, Nonce};
#[cfg(feature = "verify")]
pub use registration::HmacSha256;
const VERSION: u8 = 1; const VERSION: u8 = 1;
@@ -1,218 +0,0 @@
// Copyright 2023-2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::error::Error;
use base64::{engine::general_purpose, Engine};
use nym_wireguard_types::PeerPublicKey;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::net::IpAddr;
use std::time::SystemTime;
use std::{fmt, ops::Deref, str::FromStr};
#[cfg(feature = "verify")]
use hmac::{Hmac, Mac};
#[cfg(feature = "verify")]
use nym_crypto::asymmetric::encryption::PrivateKey;
#[cfg(feature = "verify")]
use sha2::Sha256;
pub type PendingRegistrations = HashMap<PeerPublicKey, RegistrationData>;
pub type PrivateIPs = HashMap<IpAddr, Taken>;
#[cfg(feature = "verify")]
pub type HmacSha256 = Hmac<Sha256>;
pub type Nonce = u64;
pub type Taken = Option<SystemTime>;
pub const BANDWIDTH_CAP_PER_DAY: i64 = 1024 * 1024 * 1024; // 1 GB
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct InitMessage {
/// Base64 encoded x25519 public key
pub pub_key: PeerPublicKey,
}
impl InitMessage {
pub fn new(pub_key: PeerPublicKey) -> Self {
InitMessage { pub_key }
}
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct RegistrationData {
pub nonce: u64,
pub gateway_data: GatewayClient,
pub wg_port: u16,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct RegistredData {
pub pub_key: PeerPublicKey,
pub private_ip: IpAddr,
pub wg_port: u16,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct RemainingBandwidthData {
pub available_bandwidth: u64,
pub suspended: bool,
}
/// Client that wants to register sends its PublicKey bytes mac digest encrypted with a DH shared secret.
/// Gateway/Nym node can then verify pub_key payload using the same process
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct GatewayClient {
/// Base64 encoded x25519 public key
pub pub_key: PeerPublicKey,
/// Assigned private IP
pub private_ip: IpAddr,
/// Sha256 hmac on the data (alongside the prior nonce)
pub mac: ClientMac,
}
impl GatewayClient {
#[cfg(feature = "verify")]
pub fn new(
local_secret: &PrivateKey,
remote_public: x25519_dalek::PublicKey,
private_ip: IpAddr,
nonce: u64,
) -> Self {
// convert from 1.0 x25519-dalek private key into 2.0 x25519-dalek
#[allow(clippy::expect_used)]
let static_secret = x25519_dalek::StaticSecret::from(local_secret.to_bytes());
let local_public: x25519_dalek::PublicKey = (&static_secret).into();
let dh = static_secret.diffie_hellman(&remote_public);
// TODO: change that to use our nym_crypto::hmac module instead
#[allow(clippy::expect_used)]
let mut mac = HmacSha256::new_from_slice(dh.as_bytes())
.expect("x25519 shared secret is always 32 bytes long");
mac.update(local_public.as_bytes());
mac.update(private_ip.to_string().as_bytes());
mac.update(&nonce.to_le_bytes());
GatewayClient {
pub_key: PeerPublicKey::new(local_public),
private_ip,
mac: ClientMac(mac.finalize().into_bytes().to_vec()),
}
}
// Reusable secret should be gateways Wireguard PK
// Client should perform this step when generating its payload, using its own WG PK
#[cfg(feature = "verify")]
pub fn verify(&self, gateway_key: &PrivateKey, nonce: u64) -> Result<(), Error> {
// convert from 1.0 x25519-dalek private key into 2.0 x25519-dalek
#[allow(clippy::expect_used)]
let static_secret = x25519_dalek::StaticSecret::from(gateway_key.to_bytes());
let dh = static_secret.diffie_hellman(&self.pub_key);
// TODO: change that to use our nym_crypto::hmac module instead
#[allow(clippy::expect_used)]
let mut mac = HmacSha256::new_from_slice(dh.as_bytes())
.expect("x25519 shared secret is always 32 bytes long");
mac.update(self.pub_key.as_bytes());
mac.update(self.private_ip.to_string().as_bytes());
mac.update(&nonce.to_le_bytes());
mac.verify_slice(&self.mac)
.map_err(|source| Error::FailedClientMacVerification {
client: self.pub_key.to_string(),
source,
})
}
pub fn pub_key(&self) -> PeerPublicKey {
self.pub_key
}
}
// TODO: change the inner type into generic array of size HmacSha256::OutputSize
// TODO2: rely on our internal crypto/hmac
#[derive(Debug, Clone)]
pub struct ClientMac(Vec<u8>);
impl fmt::Display for ClientMac {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", general_purpose::STANDARD.encode(&self.0))
}
}
impl ClientMac {
#[allow(dead_code)]
pub fn new(mac: Vec<u8>) -> Self {
ClientMac(mac)
}
}
impl Deref for ClientMac {
type Target = Vec<u8>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl FromStr for ClientMac {
type Err = Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let mac_bytes: Vec<u8> =
general_purpose::STANDARD
.decode(s)
.map_err(|source| Error::MalformedClientMac {
mac: s.to_string(),
source,
})?;
Ok(ClientMac(mac_bytes))
}
}
impl Serialize for ClientMac {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
let encoded_key = general_purpose::STANDARD.encode(self.0.clone());
serializer.serialize_str(&encoded_key)
}
}
impl<'de> Deserialize<'de> for ClientMac {
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
let encoded_key = String::deserialize(deserializer)?;
ClientMac::from_str(&encoded_key).map_err(serde::de::Error::custom)
}
}
#[cfg(test)]
mod tests {
use super::*;
use nym_crypto::asymmetric::encryption;
#[test]
#[cfg(feature = "verify")]
fn client_request_roundtrip() {
let mut rng = rand::thread_rng();
let gateway_key_pair = encryption::KeyPair::new(&mut rng);
let client_key_pair = encryption::KeyPair::new(&mut rng);
let nonce = 1234567890;
let client = GatewayClient::new(
client_key_pair.private_key(),
x25519_dalek::PublicKey::from(gateway_key_pair.public_key().to_bytes()),
"10.0.0.42".parse().unwrap(),
nonce,
);
assert!(client.verify(gateway_key_pair.private_key(), nonce).is_ok())
}
}
@@ -1,9 +1,8 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net> // Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use super::registration::{GatewayClient, InitMessage};
use nym_sphinx::addressing::Recipient; use nym_sphinx::addressing::Recipient;
use nym_wireguard_types::PeerPublicKey; use nym_wireguard_types::{GatewayClient, InitMessage, PeerPublicKey};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::make_bincode_serializer; use crate::make_bincode_serializer;
@@ -83,24 +82,3 @@ pub enum AuthenticatorRequestData {
Final(GatewayClient), Final(GatewayClient),
QueryBandwidth(PeerPublicKey), QueryBandwidth(PeerPublicKey),
} }
#[cfg(test)]
mod tests {
use super::*;
use std::str::FromStr;
#[test]
fn check_first_byte_version() {
let version = 2;
let data = AuthenticatorRequest {
version,
data: AuthenticatorRequestData::Initial(InitMessage::new(
PeerPublicKey::from_str("yvNUDpT5l7W/xDhiu6HkqTHDQwbs/B3J5UrLmORl1EQ=").unwrap(),
)),
reply_to: Recipient::try_from_base58_string("D1rrpsysCGCYXy9saP8y3kmNpGtJZUXN9SvFoUcqAsM9.9Ssso1ea5NfkbMASdiseDSjTN1fSWda5SgEVjdSN4CvV@GJqd3ZxpXWSNxTfx7B1pPtswpetH4LnJdFeLeuY5KUuN").unwrap(),
request_id: 1,
};
let bytes = data.to_bytes().unwrap();
assert_eq!(*bytes.first().unwrap(), version);
}
}
@@ -1,8 +1,8 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net> // Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use super::registration::{RegistrationData, RegistredData, RemainingBandwidthData};
use nym_sphinx::addressing::Recipient; use nym_sphinx::addressing::Recipient;
use nym_wireguard_types::registration::{RegistrationData, RegistredData, RemainingBandwidthData};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::make_bincode_serializer; use crate::make_bincode_serializer;
@@ -1,69 +0,0 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use nym_service_provider_requests_common::{Protocol, ServiceProviderType};
use crate::{v1, v2};
impl From<v1::request::AuthenticatorRequest> for v2::request::AuthenticatorRequest {
fn from(authenticator_request: v1::request::AuthenticatorRequest) -> Self {
Self {
protocol: Protocol {
version: 2,
service_provider_type: ServiceProviderType::Authenticator,
},
data: authenticator_request.data.into(),
reply_to: authenticator_request.reply_to,
request_id: authenticator_request.request_id,
}
}
}
impl From<v1::request::AuthenticatorRequestData> for v2::request::AuthenticatorRequestData {
fn from(authenticator_request_data: v1::request::AuthenticatorRequestData) -> Self {
match authenticator_request_data {
v1::request::AuthenticatorRequestData::Initial(init_msg) => {
v2::request::AuthenticatorRequestData::Initial(init_msg.into())
}
v1::request::AuthenticatorRequestData::Final(gw_client) => {
v2::request::AuthenticatorRequestData::Final(gw_client.into())
}
v1::request::AuthenticatorRequestData::QueryBandwidth(pub_key) => {
v2::request::AuthenticatorRequestData::QueryBandwidth(pub_key)
}
}
}
}
impl From<v1::registration::InitMessage> for v2::registration::InitMessage {
fn from(init_msg: v1::registration::InitMessage) -> Self {
Self {
pub_key: init_msg.pub_key,
}
}
}
impl From<v1::registration::GatewayClient> for Box<v2::registration::FinalMessage> {
fn from(gw_client: v1::registration::GatewayClient) -> Self {
Box::new(v2::registration::FinalMessage {
gateway_client: gw_client.into(),
credential: None,
})
}
}
impl From<v1::registration::GatewayClient> for v2::registration::GatewayClient {
fn from(gw_client: v1::registration::GatewayClient) -> Self {
Self {
pub_key: gw_client.pub_key,
private_ip: gw_client.private_ip,
mac: gw_client.mac.into(),
}
}
}
impl From<v1::registration::ClientMac> for v2::registration::ClientMac {
fn from(mac: v1::registration::ClientMac) -> Self {
Self::new(mac.to_vec())
}
}
@@ -1,9 +0,0 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
pub mod conversion;
pub mod registration;
pub mod request;
pub mod response;
const VERSION: u8 = 2;
@@ -1,116 +0,0 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use super::registration::{FinalMessage, InitMessage};
use nym_service_provider_requests_common::{Protocol, ServiceProviderType};
use nym_sphinx::addressing::Recipient;
use nym_wireguard_types::PeerPublicKey;
use serde::{Deserialize, Serialize};
use crate::make_bincode_serializer;
use super::VERSION;
fn generate_random() -> u64 {
use rand::RngCore;
let mut rng = rand::rngs::OsRng;
rng.next_u64()
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct AuthenticatorRequest {
pub protocol: Protocol,
pub data: AuthenticatorRequestData,
pub reply_to: Recipient,
pub request_id: u64,
}
impl AuthenticatorRequest {
pub fn from_reconstructed_message(
message: &nym_sphinx::receiver::ReconstructedMessage,
) -> Result<Self, bincode::Error> {
use bincode::Options;
make_bincode_serializer().deserialize(&message.message)
}
pub fn new_initial_request(init_message: InitMessage, reply_to: Recipient) -> (Self, u64) {
let request_id = generate_random();
(
Self {
protocol: Protocol {
service_provider_type: ServiceProviderType::Authenticator,
version: VERSION,
},
data: AuthenticatorRequestData::Initial(init_message),
reply_to,
request_id,
},
request_id,
)
}
pub fn new_final_request(final_message: FinalMessage, reply_to: Recipient) -> (Self, u64) {
let request_id = generate_random();
(
Self {
protocol: Protocol {
service_provider_type: ServiceProviderType::Authenticator,
version: VERSION,
},
data: AuthenticatorRequestData::Final(Box::new(final_message)),
reply_to,
request_id,
},
request_id,
)
}
pub fn new_query_request(peer_public_key: PeerPublicKey, reply_to: Recipient) -> (Self, u64) {
let request_id = generate_random();
(
Self {
protocol: Protocol {
service_provider_type: ServiceProviderType::Authenticator,
version: VERSION,
},
data: AuthenticatorRequestData::QueryBandwidth(peer_public_key),
reply_to,
request_id,
},
request_id,
)
}
pub fn to_bytes(&self) -> Result<Vec<u8>, bincode::Error> {
use bincode::Options;
make_bincode_serializer().serialize(self)
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum AuthenticatorRequestData {
Initial(InitMessage),
Final(Box<FinalMessage>),
QueryBandwidth(PeerPublicKey),
}
#[cfg(test)]
mod tests {
use super::*;
use std::str::FromStr;
#[test]
fn check_first_bytes_protocol() {
let version = 2;
let data = AuthenticatorRequest {
protocol: Protocol { version, service_provider_type: ServiceProviderType::Authenticator },
data: AuthenticatorRequestData::Initial(InitMessage::new(
PeerPublicKey::from_str("yvNUDpT5l7W/xDhiu6HkqTHDQwbs/B3J5UrLmORl1EQ=").unwrap(),
)),
reply_to: Recipient::try_from_base58_string("D1rrpsysCGCYXy9saP8y3kmNpGtJZUXN9SvFoUcqAsM9.9Ssso1ea5NfkbMASdiseDSjTN1fSWda5SgEVjdSN4CvV@GJqd3ZxpXWSNxTfx7B1pPtswpetH4LnJdFeLeuY5KUuN").unwrap(),
request_id: 1,
};
let bytes = *data.to_bytes().unwrap().first_chunk::<2>().unwrap();
assert_eq!(bytes, [version, ServiceProviderType::Authenticator as u8]);
}
}
@@ -1,129 +0,0 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use super::registration::{RegistrationData, RegistredData, RemainingBandwidthData};
use nym_service_provider_requests_common::{Protocol, ServiceProviderType};
use nym_sphinx::addressing::Recipient;
use serde::{Deserialize, Serialize};
use crate::make_bincode_serializer;
use super::VERSION;
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct AuthenticatorResponse {
pub protocol: Protocol,
pub data: AuthenticatorResponseData,
pub reply_to: Recipient,
}
impl AuthenticatorResponse {
pub fn new_pending_registration_success(
registration_data: RegistrationData,
request_id: u64,
reply_to: Recipient,
) -> Self {
Self {
protocol: Protocol {
service_provider_type: ServiceProviderType::Authenticator,
version: VERSION,
},
data: AuthenticatorResponseData::PendingRegistration(PendingRegistrationResponse {
reply: registration_data,
reply_to,
request_id,
}),
reply_to,
}
}
pub fn new_registered(
registred_data: RegistredData,
reply_to: Recipient,
request_id: u64,
) -> Self {
Self {
protocol: Protocol {
service_provider_type: ServiceProviderType::Authenticator,
version: VERSION,
},
data: AuthenticatorResponseData::Registered(RegisteredResponse {
reply: registred_data,
reply_to,
request_id,
}),
reply_to,
}
}
pub fn new_remaining_bandwidth(
remaining_bandwidth_data: Option<RemainingBandwidthData>,
reply_to: Recipient,
request_id: u64,
) -> Self {
Self {
protocol: Protocol {
service_provider_type: ServiceProviderType::Authenticator,
version: VERSION,
},
data: AuthenticatorResponseData::RemainingBandwidth(RemainingBandwidthResponse {
reply: remaining_bandwidth_data,
reply_to,
request_id,
}),
reply_to,
}
}
pub fn recipient(&self) -> Recipient {
self.reply_to
}
pub fn to_bytes(&self) -> Result<Vec<u8>, bincode::Error> {
use bincode::Options;
make_bincode_serializer().serialize(self)
}
pub fn from_reconstructed_message(
message: &nym_sphinx::receiver::ReconstructedMessage,
) -> Result<Self, bincode::Error> {
use bincode::Options;
make_bincode_serializer().deserialize(&message.message)
}
pub fn id(&self) -> Option<u64> {
match &self.data {
AuthenticatorResponseData::PendingRegistration(response) => Some(response.request_id),
AuthenticatorResponseData::Registered(response) => Some(response.request_id),
AuthenticatorResponseData::RemainingBandwidth(response) => Some(response.request_id),
}
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum AuthenticatorResponseData {
PendingRegistration(PendingRegistrationResponse),
Registered(RegisteredResponse),
RemainingBandwidth(RemainingBandwidthResponse),
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct PendingRegistrationResponse {
pub request_id: u64,
pub reply_to: Recipient,
pub reply: RegistrationData,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct RegisteredResponse {
pub request_id: u64,
pub reply_to: Recipient,
pub reply: RegistredData,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct RemainingBandwidthResponse {
pub request_id: u64,
pub reply_to: Recipient,
pub reply: Option<RemainingBandwidthData>,
}
+2 -3
View File
@@ -14,14 +14,13 @@ thiserror = { workspace = true }
url = { workspace = true } url = { workspace = true }
zeroize = { workspace = true } zeroize = { workspace = true }
nym-ecash-time = { path = "../ecash-time" } nym-coconut = { path = "../nymcoconut" }
nym-credential-storage = { path = "../credential-storage" } nym-credential-storage = { path = "../credential-storage" }
nym-credentials = { path = "../credentials" } nym-credentials = { path = "../credentials" }
nym-credentials-interface = { path = "../credentials-interface" } nym-credentials-interface = { path = "../credentials-interface" }
nym-crypto = { path = "../crypto", features = ["rand", "asymmetric", "stream_cipher", "aes", "hashing"] } nym-crypto = { path = "../crypto", features = ["rand", "asymmetric", "symmetric", "aes", "hashing"] }
nym-network-defaults = { path = "../network-defaults" } nym-network-defaults = { path = "../network-defaults" }
nym-validator-client = { path = "../client-libs/validator-client", default-features = false } nym-validator-client = { path = "../client-libs/validator-client", default-features = false }
nym-ecash-contract-common = { path = "../cosmwasm-smart-contracts/ecash-contract" }
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.nym-validator-client] [target."cfg(not(target_arch = \"wasm32\"))".dependencies.nym-validator-client]
path = "../client-libs/validator-client" path = "../client-libs/validator-client"
+50 -95
View File
@@ -1,132 +1,87 @@
// Copyright 2023-2024 - 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 crate::error::BandwidthControllerError; use crate::error::BandwidthControllerError;
use crate::utils::{ use nym_credential_storage::models::StorableIssuedCredential;
get_aggregate_verification_key, get_coin_index_signatures, get_expiration_date_signatures,
};
use log::info;
use nym_credential_storage::storage::Storage; use nym_credential_storage::storage::Storage;
use nym_credentials::ecash::bandwidth::IssuanceTicketBook; use nym_credentials::coconut::bandwidth::{CredentialType, IssuanceBandwidthCredential};
use nym_credentials::ecash::utils::obtain_aggregate_wallet; use nym_credentials::coconut::utils::obtain_aggregate_signature;
use nym_credentials::IssuedTicketBook; use nym_crypto::asymmetric::{encryption, identity};
use nym_credentials_interface::TicketType; use nym_validator_client::coconut::all_coconut_api_clients;
use nym_crypto::asymmetric::identity; use nym_validator_client::nyxd::contract_traits::CoconutBandwidthSigningClient;
use nym_ecash_time::{ecash_default_expiration_date, Date}; use nym_validator_client::nyxd::contract_traits::DkgQueryClient;
use nym_validator_client::coconut::all_ecash_api_clients; use nym_validator_client::nyxd::Coin;
use nym_validator_client::nym_api::EpochId;
use nym_validator_client::nyxd::contract_traits::EcashSigningClient;
use nym_validator_client::nyxd::contract_traits::{DkgQueryClient, EcashQueryClient};
use nym_validator_client::nyxd::cosmwasm_client::ToSingletonContractData;
use nym_validator_client::EcashApiClient;
use rand::rngs::OsRng; use rand::rngs::OsRng;
use state::State;
use zeroize::Zeroizing;
pub async fn make_deposit<C>( pub mod state;
client: &C,
client_id: &[u8], pub async fn deposit<C>(client: &C, amount: Coin) -> Result<State, BandwidthControllerError>
expiration: Option<Date>,
ticketbook_type: TicketType,
) -> Result<IssuanceTicketBook, BandwidthControllerError>
where where
C: EcashSigningClient + EcashQueryClient + Sync, C: CoconutBandwidthSigningClient + Sync,
{ {
let mut rng = OsRng; let mut rng = OsRng;
let signing_key = identity::PrivateKey::new(&mut rng); let signing_key = identity::PrivateKey::new(&mut rng);
let expiration = expiration.unwrap_or_else(ecash_default_expiration_date); let encryption_key = encryption::PrivateKey::new(&mut rng);
let deposit_amount = client.get_required_deposit_amount().await?; let tx_hash = client
info!("we'll need to deposit {deposit_amount} to obtain the ticketbook"); .deposit(
let result = client amount.clone(),
.make_ticketbook_deposit( CredentialType::Voucher.to_string(),
signing_key.public_key().to_base58_string(), signing_key.public_key().to_base58_string(),
deposit_amount.into(), encryption_key.public_key().to_base58_string(),
None, None,
) )
.await?; .await?
.transaction_hash;
let deposit_id = result.parse_singleton_u32_contract_data()?; let voucher =
IssuanceBandwidthCredential::new_voucher(amount, tx_hash, signing_key, encryption_key);
info!("our ticketbook deposit has been stored under id {deposit_id}"); let state = State { voucher };
Ok(IssuanceTicketBook::new_with_expiration( Ok(state)
deposit_id,
client_id,
signing_key,
ticketbook_type,
expiration,
))
} }
pub async fn query_and_persist_required_global_data<S>( pub async fn get_bandwidth_voucher<C, St>(
storage: &S, state: &State,
epoch_id: EpochId,
expiration_date: Date,
apis: Vec<EcashApiClient>,
) -> Result<(), BandwidthControllerError>
where
S: Storage,
<S as Storage>::StorageError: Send + Sync + 'static,
{
log::info!("Getting master verification key");
// this will also persist the key in the storage if was not there already
get_aggregate_verification_key(storage, epoch_id, apis.clone()).await?;
log::info!("Getting expiration date signatures");
// this will also persist the signatures in the storage if they were not there already
get_expiration_date_signatures(storage, epoch_id, expiration_date, apis.clone()).await?;
log::info!("Getting coin indices signatures");
// this will also persist the signatures in the storage if they were not there already
get_coin_index_signatures(storage, epoch_id, apis).await?;
Ok(())
}
pub async fn get_ticket_book<C, St>(
issuance_data: &IssuanceTicketBook,
client: &C, client: &C,
storage: &St, storage: &St,
apis: Option<Vec<EcashApiClient>>, ) -> Result<(), BandwidthControllerError>
) -> Result<IssuedTicketBook, BandwidthControllerError>
where where
C: DkgQueryClient + Send + Sync, C: DkgQueryClient + Send + Sync,
St: Storage, St: Storage,
<St as Storage>::StorageError: Send + Sync + 'static, <St as Storage>::StorageError: Send + Sync + 'static,
{ {
// temporary
assert!(state.voucher.typ().is_voucher());
let epoch_id = client.get_current_epoch().await?.epoch_id; let epoch_id = client.get_current_epoch().await?.epoch_id;
let threshold = client let threshold = client
.get_current_epoch_threshold() .get_current_epoch_threshold()
.await? .await?
.ok_or(BandwidthControllerError::NoThreshold)?; .ok_or(BandwidthControllerError::NoThreshold)?;
let apis = match apis { let coconut_api_clients = all_coconut_api_clients(client, epoch_id).await?;
Some(apis) => apis,
None => all_ecash_api_clients(client, epoch_id).await?, let signature =
obtain_aggregate_signature(&state.voucher, &coconut_api_clients, threshold).await?;
let issued = state.voucher.to_issued_credential(signature, epoch_id);
// make sure the data gets zeroized after persisting it
let credential_data = Zeroizing::new(issued.pack_v1());
let storable = StorableIssuedCredential {
serialization_revision: issued.current_serialization_revision(),
credential_data: credential_data.as_ref(),
credential_type: issued.typ().to_string(),
epoch_id: epoch_id
.try_into()
.expect("our epoch is has run over u32::MAX!"),
}; };
log::info!("Querying wallet signatures");
let wallet = obtain_aggregate_wallet(issuance_data, &apis, threshold).await?;
info!("managed to obtain sufficient number of partial signatures!");
log::info!("Getting expiration date signatures");
// this will also persist the signatures in the storage if they were not there already
get_expiration_date_signatures(
storage,
epoch_id,
issuance_data.expiration_date(),
apis.clone(),
)
.await?;
log::info!("Getting coin indices signatures");
// this will also persist the signatures in the storage if they were not there already
get_coin_index_signatures(storage, epoch_id, apis).await?;
let issued = issuance_data.to_issued_ticketbook(wallet, epoch_id);
info!("persisting the ticketbook into the storage...");
storage storage
.insert_issued_ticketbook(&issued) .insert_issued_credential(storable)
.await .await
.map_err(|err| BandwidthControllerError::CredentialStorageError(Box::new(err)))?; .map_err(|err| BandwidthControllerError::CredentialStorageError(Box::new(err)))
Ok(issued)
} }
@@ -0,0 +1,14 @@
// Copyright 2022-2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use nym_credentials::coconut::bandwidth::IssuanceBandwidthCredential;
pub struct State {
pub voucher: IssuanceBandwidthCredential,
}
impl State {
pub fn new(voucher: IssuanceBandwidthCredential) -> Self {
State { voucher }
}
}
+5 -16
View File
@@ -1,12 +1,12 @@
// 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_coconut::CoconutError;
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_crypto::asymmetric::encryption::KeyRecoveryError; use nym_crypto::asymmetric::encryption::KeyRecoveryError;
use nym_crypto::asymmetric::identity::Ed25519RecoveryError; use nym_crypto::asymmetric::identity::Ed25519RecoveryError;
use nym_validator_client::coconut::EcashApiError; use nym_validator_client::coconut::CoconutApiError;
use nym_validator_client::error::ValidatorClientError; use nym_validator_client::error::ValidatorClientError;
use thiserror::Error; use thiserror::Error;
@@ -16,7 +16,7 @@ pub enum BandwidthControllerError {
Nyxd(#[from] nym_validator_client::nyxd::error::NyxdError), Nyxd(#[from] nym_validator_client::nyxd::error::NyxdError),
#[error("coconut api query failure: {0}")] #[error("coconut api query failure: {0}")]
CoconutApiError(#[from] EcashApiError), CoconutApiError(#[from] CoconutApiError),
#[error("There was a credential storage error - {0}")] #[error("There was a credential storage error - {0}")]
CredentialStorageError(Box<dyn std::error::Error + Send + Sync>), CredentialStorageError(Box<dyn std::error::Error + Send + Sync>),
@@ -28,8 +28,8 @@ pub enum BandwidthControllerError {
#[error(transparent)] #[error(transparent)]
StorageError(#[from] StorageError), StorageError(#[from] StorageError),
#[error("Ecash error - {0}")] #[error("Coconut error - {0}")]
EcashError(#[from] CompactEcashError), CoconutError(#[from] CoconutError),
#[error("Validator client error - {0}")] #[error("Validator client error - {0}")]
ValidatorError(#[from] ValidatorClientError), ValidatorError(#[from] ValidatorClientError),
@@ -51,15 +51,4 @@ pub enum BandwidthControllerError {
#[error("can't handle recovering storage with revision {stored}. {expected} was expected")] #[error("can't handle recovering storage with revision {stored}. {expected} was expected")]
UnsupportedCredentialStorageRevision { stored: u8, expected: u8 }, UnsupportedCredentialStorageRevision { stored: u8, expected: u8 },
#[error("did not receive a valid response for aggregated data ({typ}) from ANY nym-api")]
ExhaustedApiQueries { typ: String },
}
impl BandwidthControllerError {
pub fn credential_storage_error(
source: impl std::error::Error + Send + Sync + 'static,
) -> Self {
BandwidthControllerError::CredentialStorageError(Box::new(source))
}
} }
+90 -151
View File
@@ -1,24 +1,16 @@
// Copyright 2021-2024 - Nym Technologies SA <contact@nymtech.net> // Copyright 2021-2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
#![warn(clippy::expect_used)]
#![warn(clippy::unwrap_used)]
#![warn(clippy::todo)]
#![warn(clippy::dbg_macro)]
use crate::error::BandwidthControllerError; use crate::error::BandwidthControllerError;
use crate::utils::{ use crate::utils::stored_credential_to_issued_bandwidth;
get_aggregate_verification_key, get_coin_index_signatures, get_expiration_date_signatures, use log::{debug, error, warn};
ApiClientsWrapper,
};
use log::error;
use nym_credential_storage::models::RetrievedTicketbook;
use nym_credential_storage::storage::Storage; use nym_credential_storage::storage::Storage;
use nym_credentials::ecash::bandwidth::CredentialSpendingData; use nym_credentials::coconut::bandwidth::issued::BandwidthCredentialIssuedDataVariant;
use nym_credentials_interface::{ use nym_credentials::coconut::bandwidth::CredentialSpendingData;
AnnotatedCoinIndexSignature, AnnotatedExpirationDateSignature, VerificationKeyAuth, use nym_credentials::coconut::utils::obtain_aggregate_verification_key;
}; use nym_credentials::IssuedBandwidthCredential;
use nym_ecash_time::Date; use nym_credentials_interface::VerificationKey;
use nym_validator_client::coconut::all_coconut_api_clients;
use nym_validator_client::nym_api::EpochId; use nym_validator_client::nym_api::EpochId;
use nym_validator_client::nyxd::contract_traits::DkgQueryClient; use nym_validator_client::nyxd::contract_traits::DkgQueryClient;
@@ -43,20 +35,13 @@ pub struct PreparedCredential {
/// could use correct verification key for validation. /// could use correct verification key for validation.
pub epoch_id: EpochId, pub epoch_id: EpochId,
/// Auxiliary metadata associated with the withdrawn credential /// The database id of the stored credential.
pub metadata: PreparedCredentialMetadata, pub credential_id: i64,
} }
#[derive(Copy, Clone)] pub struct RetrievedCredential {
pub struct PreparedCredentialMetadata { pub credential: IssuedBandwidthCredential,
/// The database id of the stored credential. pub credential_id: i64,
pub ticketbook_id: i64,
/// The number of tickets withdrawn in this credential
pub tickets_withdrawn: u32,
/// The amount of tickets used INCLUDING those tickets that JUST got withdrawn
pub used_tickets: u32,
} }
impl<C, St: Storage> BandwidthController<C, St> { impl<C, St: Storage> BandwidthController<C, St> {
@@ -65,157 +50,111 @@ impl<C, St: Storage> BandwidthController<C, St> {
} }
/// Tries to retrieve one of the stored, unused credentials that hasn't yet expired. /// Tries to retrieve one of the stored, unused credentials that hasn't yet expired.
pub async fn get_next_usable_ticketbook( /// It marks any retrieved intermediate credentials as expired.
pub async fn get_next_usable_credential(
&self, &self,
tickets: u32, gateway_id: &str,
) -> Result<RetrievedTicketbook, BandwidthControllerError> ) -> Result<RetrievedCredential, BandwidthControllerError>
where where
<St as Storage>::StorageError: Send + Sync + 'static, <St as Storage>::StorageError: Send + Sync + 'static,
{ {
let Some(ticketbook) = self loop {
.storage let Some(maybe_next) = self
.get_next_unspent_usable_ticketbook(tickets) .storage
.await .get_next_unspent_credential(gateway_id)
.map_err(BandwidthControllerError::credential_storage_error)? .await
else { .map_err(|err| BandwidthControllerError::CredentialStorageError(Box::new(err)))?
return Err(BandwidthControllerError::NoCredentialsAvailable); else {
}; return Err(BandwidthControllerError::NoCredentialsAvailable);
};
let id = maybe_next.id;
Ok(ticketbook) // try to deserialize it
let valid_credential = match stored_credential_to_issued_bandwidth(maybe_next) {
// check if it has already expired
Ok(credential) => match credential.variant_data() {
BandwidthCredentialIssuedDataVariant::Voucher(_) => {
debug!("credential {id} is a bandwidth voucher");
credential
}
BandwidthCredentialIssuedDataVariant::FreePass(freepass_info) => {
debug!("credential {id} is a free pass");
if freepass_info.expired() {
warn!("the free pass (id: {id}) has already expired! The expiration was set to {}", freepass_info.expiry_date());
self.storage.mark_expired(id).await.map_err(|err| {
BandwidthControllerError::CredentialStorageError(Box::new(err))
})?;
continue;
}
credential
}
},
Err(err) => {
error!("failed to deserialize credential with id {id}: {err}. it may need to be manually removed from the storage");
return Err(err);
}
};
return Ok(RetrievedCredential {
credential: valid_credential,
credential_id: id,
});
}
} }
pub async fn attempt_revert_ticket_usage( pub fn storage(&self) -> &St {
&self, &self.storage
info: PreparedCredentialMetadata,
) -> Result<bool, BandwidthControllerError>
where
<St as Storage>::StorageError: Send + Sync + 'static,
{
self.storage
.attempt_revert_ticketbook_withdrawal(
info.ticketbook_id,
info.used_tickets,
info.tickets_withdrawn,
)
.await
.map_err(BandwidthControllerError::credential_storage_error)
} }
async fn get_aggregate_verification_key( async fn get_aggregate_verification_key(
&self, &self,
epoch_id: EpochId, epoch_id: EpochId,
apis: &mut ApiClientsWrapper, ) -> Result<VerificationKey, BandwidthControllerError>
) -> Result<VerificationKeyAuth, BandwidthControllerError>
where where
C: DkgQueryClient + Sync + Send, C: DkgQueryClient + Sync + Send,
<St as Storage>::StorageError: Send + Sync + 'static, <St as Storage>::StorageError: Send + Sync + 'static,
{ {
let ecash_apis = apis.get_or_init(epoch_id, &self.client).await?; let coconut_api_clients = all_coconut_api_clients(&self.client, epoch_id).await?;
get_aggregate_verification_key(&self.storage, epoch_id, ecash_apis).await Ok(obtain_aggregate_verification_key(&coconut_api_clients)?)
} }
async fn get_coin_index_signatures( pub async fn prepare_bandwidth_credential(
&self, &self,
epoch_id: EpochId, gateway_id: &str,
apis: &mut ApiClientsWrapper,
) -> Result<Vec<AnnotatedCoinIndexSignature>, BandwidthControllerError>
where
C: DkgQueryClient + Sync + Send,
<St as Storage>::StorageError: Send + Sync + 'static,
{
let ecash_apis = apis.get_or_init(epoch_id, &self.client).await?;
get_coin_index_signatures(&self.storage, epoch_id, ecash_apis).await
}
async fn get_expiration_date_signatures(
&self,
epoch_id: EpochId,
expiration_date: Date,
apis: &mut ApiClientsWrapper,
) -> Result<Vec<AnnotatedExpirationDateSignature>, BandwidthControllerError>
where
C: DkgQueryClient + Sync + Send,
<St as Storage>::StorageError: Send + Sync + 'static,
{
let ecash_apis = apis.get_or_init(epoch_id, &self.client).await?;
get_expiration_date_signatures(&self.storage, epoch_id, expiration_date, ecash_apis).await
}
async fn prepare_ecash_ticket_inner(
&self,
provider_pk: [u8; 32],
tickets_to_spend: u32,
mut retrieved_ticketbook: RetrievedTicketbook,
) -> Result<CredentialSpendingData, BandwidthControllerError>
where
C: DkgQueryClient + Sync + Send,
<St as Storage>::StorageError: Send + Sync + 'static,
{
let epoch_id = retrieved_ticketbook.ticketbook.epoch_id();
let expiration_date = retrieved_ticketbook.ticketbook.expiration_date();
let mut api_clients = Default::default();
let verification_key = self
.get_aggregate_verification_key(epoch_id, &mut api_clients)
.await?;
let expiration_signatures = self
.get_expiration_date_signatures(epoch_id, expiration_date, &mut api_clients)
.await?;
let coin_indices_signatures = self
.get_coin_index_signatures(epoch_id, &mut api_clients)
.await?;
let pay_info = retrieved_ticketbook
.ticketbook
.generate_pay_info(provider_pk);
let spend_request = retrieved_ticketbook.ticketbook.prepare_for_spending(
&verification_key,
pay_info.into(),
&coin_indices_signatures,
&expiration_signatures,
tickets_to_spend as u64,
)?;
Ok(spend_request)
}
pub async fn prepare_ecash_ticket(
&self,
provider_pk: [u8; 32],
tickets_to_spend: u32,
) -> Result<PreparedCredential, BandwidthControllerError> ) -> Result<PreparedCredential, BandwidthControllerError>
where where
C: DkgQueryClient + Sync + Send, C: DkgQueryClient + Sync + Send,
<St as Storage>::StorageError: Send + Sync + 'static, <St as Storage>::StorageError: Send + Sync + 'static,
{ {
let retrieved_ticketbook = self.get_next_usable_ticketbook(tickets_to_spend).await?; let retrieved_credential = self.get_next_usable_credential(gateway_id).await?;
let ticketbook_id = retrieved_ticketbook.ticketbook_id; let epoch_id = retrieved_credential.credential.epoch_id();
let epoch_id = retrieved_ticketbook.ticketbook.epoch_id(); let credential_id = retrieved_credential.credential_id;
let used_tickets = let verification_key = self.get_aggregate_verification_key(epoch_id).await?;
retrieved_ticketbook.ticketbook.spent_tickets() as u32 + tickets_to_spend;
let metadata = PreparedCredentialMetadata {
ticketbook_id,
tickets_withdrawn: tickets_to_spend,
used_tickets,
};
match self let spend_request = retrieved_credential
.prepare_ecash_ticket_inner(provider_pk, tickets_to_spend, retrieved_ticketbook) .credential
.prepare_for_spending(&verification_key)?;
Ok(PreparedCredential {
data: spend_request,
epoch_id,
credential_id,
})
}
pub async fn consume_credential(
&self,
id: i64,
gateway_id: &str,
) -> Result<(), BandwidthControllerError>
where
<St as Storage>::StorageError: Send + Sync + 'static,
{
self.storage
.consume_coconut_credential(id, gateway_id)
.await .await
{ .map_err(|err| BandwidthControllerError::CredentialStorageError(Box::new(err)))
Ok(data) => Ok(PreparedCredential {
data,
epoch_id,
metadata,
}),
Err(err) => {
error!("failed to prepare credential spending request. attempting to revert withdrawal...");
self.attempt_revert_ticket_usage(metadata).await?;
Err(err)
}
}
} }
} }
+15 -194
View File
@@ -2,200 +2,21 @@
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use crate::error::BandwidthControllerError; use crate::error::BandwidthControllerError;
use log::warn; use nym_credential_storage::models::StoredIssuedCredential;
use nym_credential_storage::storage::Storage; use nym_credentials::coconut::bandwidth::issued::CURRENT_SERIALIZATION_REVISION;
use nym_credentials::ecash::bandwidth::serialiser::keys::EpochVerificationKey; use nym_credentials::coconut::bandwidth::IssuedBandwidthCredential;
use nym_credentials::ecash::bandwidth::serialiser::signatures::{
AggregatedCoinIndicesSignatures, AggregatedExpirationDateSignatures,
};
use nym_credentials_interface::{
AnnotatedCoinIndexSignature, AnnotatedExpirationDateSignature, VerificationKeyAuth,
};
use nym_ecash_time::Date;
use nym_validator_client::coconut::all_ecash_api_clients;
use nym_validator_client::nym_api::EpochId;
use nym_validator_client::nyxd::contract_traits::DkgQueryClient;
use nym_validator_client::EcashApiClient;
use rand::prelude::SliceRandom;
use rand::thread_rng;
use std::fmt::Display;
use std::future::Future;
// it really doesn't need the RwLock because it's never moved across tasks, pub fn stored_credential_to_issued_bandwidth(
// but we need all the Send/Sync action cred: StoredIssuedCredential,
#[derive(Default)] ) -> Result<IssuedBandwidthCredential, BandwidthControllerError> {
pub(crate) struct ApiClientsWrapper(Option<Vec<EcashApiClient>>); if cred.serialization_revision != CURRENT_SERIALIZATION_REVISION {
return Err(
impl ApiClientsWrapper { BandwidthControllerError::UnsupportedCredentialStorageRevision {
pub(crate) async fn get_or_init<C>( stored: cred.serialization_revision,
&mut self, expected: CURRENT_SERIALIZATION_REVISION,
epoch_id: EpochId, },
dkg_client: &C, );
) -> Result<Vec<EcashApiClient>, BandwidthControllerError>
where
C: DkgQueryClient + Sync + Send,
{
if let Some(cached) = &self.0 {
return Ok(cached.clone());
}
let clients = all_ecash_api_clients(dkg_client, epoch_id).await?;
// technically we don't have to be cloning all the clients here, but it's way simpler than
// dealing with locking and whatnot given the performance penalty is negligible
self.0 = Some(clients.clone());
Ok(clients)
} }
}
Ok(IssuedBandwidthCredential::unpack_v1(&cred.credential_data)?)
pub(crate) async fn query_random_apis_until_success<F, T, U, E>(
mut apis: Vec<EcashApiClient>,
f: F,
typ: impl Into<String>,
) -> Result<T, BandwidthControllerError>
where
F: Fn(EcashApiClient) -> U,
U: Future<Output = Result<T, E>>,
E: Display,
{
// try apis in pseudorandom way to remove any bias towards the first registered dealer
apis.shuffle(&mut thread_rng());
for api in apis {
let disp = api.to_string();
match f(api).await {
Ok(res) => return Ok(res),
Err(err) => {
warn!("failed to obtain valid response from API {disp}: {err}")
}
}
}
Err(BandwidthControllerError::ExhaustedApiQueries { typ: typ.into() })
}
pub(crate) async fn get_aggregate_verification_key<St>(
storage: &St,
epoch_id: EpochId,
ecash_apis: Vec<EcashApiClient>,
) -> Result<VerificationKeyAuth, BandwidthControllerError>
where
St: Storage,
<St as Storage>::StorageError: Send + Sync + 'static,
{
if let Some(stored) = storage
.get_master_verification_key(epoch_id)
.await
.map_err(BandwidthControllerError::credential_storage_error)?
{
return Ok(stored);
};
let master_vk = query_random_apis_until_success(
ecash_apis,
|api| async move { api.api_client.master_verification_key(Some(epoch_id)).await },
format!("aggregated verification key for epoch {epoch_id}"),
)
.await?
.key;
let full = EpochVerificationKey {
epoch_id,
key: master_vk,
};
// store the retrieved key
storage
.insert_master_verification_key(&full)
.await
.map_err(BandwidthControllerError::credential_storage_error)?;
Ok(full.key)
}
pub(crate) async fn get_coin_index_signatures<St>(
storage: &St,
epoch_id: EpochId,
ecash_apis: Vec<EcashApiClient>,
) -> Result<Vec<AnnotatedCoinIndexSignature>, BandwidthControllerError>
where
St: Storage,
<St as Storage>::StorageError: Send + Sync + 'static,
{
if let Some(stored) = storage
.get_coin_index_signatures(epoch_id)
.await
.map_err(BandwidthControllerError::credential_storage_error)?
{
return Ok(stored);
};
let index_sigs = query_random_apis_until_success(
ecash_apis,
|api| async move {
api.api_client
.global_coin_indices_signatures(Some(epoch_id))
.await
},
format!("aggregated coin index signatures for epoch {epoch_id}"),
)
.await?
.signatures;
let aggregated = AggregatedCoinIndicesSignatures {
epoch_id,
signatures: index_sigs,
};
// store the retrieved key
storage
.insert_coin_index_signatures(&aggregated)
.await
.map_err(BandwidthControllerError::credential_storage_error)?;
Ok(aggregated.signatures)
}
pub(crate) async fn get_expiration_date_signatures<St>(
storage: &St,
epoch_id: EpochId,
expiration_date: Date,
ecash_apis: Vec<EcashApiClient>,
) -> Result<Vec<AnnotatedExpirationDateSignature>, BandwidthControllerError>
where
St: Storage,
<St as Storage>::StorageError: Send + Sync + 'static,
{
if let Some(stored) = storage
.get_expiration_date_signatures(expiration_date)
.await
.map_err(BandwidthControllerError::credential_storage_error)?
{
return Ok(stored);
};
let expiration_sigs = query_random_apis_until_success(
ecash_apis,
|api| async move {
api.api_client
.global_expiration_date_signatures(Some(expiration_date))
.await
},
format!("aggregated coin index signatures for date {expiration_date}"),
)
.await?
.signatures;
let aggregated = AggregatedExpirationDateSignatures {
epoch_id,
expiration_date,
signatures: expiration_sigs,
};
// store the retrieved key
storage
.insert_expiration_date_signatures(&aggregated)
.await
.map_err(BandwidthControllerError::credential_storage_error)?;
Ok(aggregated.signatures)
} }
+2 -2
View File
@@ -8,14 +8,14 @@ license = { workspace = true }
repository = { workspace = true } repository = { workspace = true }
[dependencies] [dependencies]
const-str = { workspace = true }
clap = { workspace = true, features = ["derive"], optional = true } clap = { workspace = true, features = ["derive"], optional = true }
clap_complete = { workspace = true, optional = true } clap_complete = { workspace = true, optional = true }
clap_complete_fig = { workspace = true, optional = true } clap_complete_fig = { workspace = true, optional = true }
const-str = { workspace = true }
log = { workspace = true } log = { workspace = true }
pretty_env_logger = { workspace = true } pretty_env_logger = { workspace = true }
semver = "0.11"
schemars = { workspace = true, features = ["preserve_order"], optional = true } schemars = { workspace = true, features = ["preserve_order"], optional = true }
semver.workspace = true
serde = { workspace = true, features = ["derive"] } serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true, optional = true } serde_json = { workspace = true, optional = true }
+2 -3
View File
@@ -1,10 +1,9 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net> // Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use semver::SemVerError;
pub use semver::Version; pub use semver::Version;
/// Checks if the version is minor version compatible.
///
/// Checks whether given `version` is compatible with a given semantic version requirement `req` /// Checks whether given `version` is compatible with a given semantic version requirement `req`
/// according to major-minor semver rules. The semantic version requirement can be passed as a full, /// according to major-minor semver rules. The semantic version requirement can be passed as a full,
/// concrete version number, because that's what we'll have in our Cargo.toml files (e.g. 0.3.2). /// concrete version number, because that's what we'll have in our Cargo.toml files (e.g. 0.3.2).
@@ -23,7 +22,7 @@ pub fn is_minor_version_compatible(version: &str, req: &str) -> bool {
expected_version.major == req_version.major && expected_version.minor == req_version.minor expected_version.major == req_version.major && expected_version.minor == req_version.minor
} }
pub fn parse_version(raw_version: &str) -> Result<Version, semver::Error> { pub fn parse_version(raw_version: &str) -> Result<Version, SemVerError> {
Version::parse(raw_version) Version::parse(raw_version)
} }
+9 -16
View File
@@ -14,12 +14,10 @@ base64 = { workspace = true }
bs58 = { workspace = true } bs58 = { workspace = true }
cfg-if = { workspace = true } cfg-if = { workspace = true }
clap = { workspace = true, optional = true } clap = { workspace = true, optional = true }
comfy-table = { workspace = true, optional = true }
futures = { workspace = true } futures = { workspace = true }
humantime-serde = { workspace = true } humantime-serde = { workspace = true }
log = { workspace = true } log = { workspace = true }
rand = { workspace = true } rand = { workspace = true }
rand_chacha = { workspace = true }
serde = { workspace = true, features = ["derive"] } serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true } serde_json = { workspace = true }
sha2 = { workspace = true } sha2 = { workspace = true }
@@ -39,7 +37,7 @@ nym-country-group = { path = "../country-group" }
nym-crypto = { path = "../crypto" } nym-crypto = { path = "../crypto" }
nym-explorer-client = { path = "../../explorer-api/explorer-client" } 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/gateway-requests" }
nym-metrics = { path = "../nym-metrics" } nym-metrics = { path = "../nym-metrics" }
nym-nonexhaustive-delayqueue = { path = "../nonexhaustive-delayqueue" } nym-nonexhaustive-delayqueue = { path = "../nonexhaustive-delayqueue" }
nym-sphinx = { path = "../nymsphinx" } nym-sphinx = { path = "../nymsphinx" }
@@ -47,31 +45,27 @@ nym-pemstore = { path = "../pemstore" }
nym-topology = { path = "../topology", features = ["serializable"] } nym-topology = { path = "../topology", features = ["serializable"] }
nym-validator-client = { path = "../client-libs/validator-client", default-features = false } nym-validator-client = { path = "../client-libs/validator-client", default-features = false }
nym-task = { path = "../task" } nym-task = { path = "../task" }
nym-credentials-interface = { path = "../credentials-interface" }
nym-credential-storage = { path = "../credential-storage" } nym-credential-storage = { path = "../credential-storage" }
nym-network-defaults = { path = "../network-defaults" } nym-network-defaults = { path = "../network-defaults" }
nym-client-core-config-types = { path = "./config-types", features = [ nym-client-core-config-types = { path = "./config-types", features = ["disk-persistence"] }
"disk-persistence",
] }
nym-client-core-surb-storage = { path = "./surb-storage" } nym-client-core-surb-storage = { path = "./surb-storage" }
nym-client-core-gateways-storage = { path = "./gateways-storage" } nym-client-core-gateways-storage = { path = "./gateways-storage" }
nym-ecash-time = { path = "../ecash-time" }
### For serving prometheus metrics ### For serving prometheus metrics
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.hyper] [target."cfg(not(target_arch = \"wasm32\"))".dependencies.hyper]
workspace = true version = "1"
features = ["server", "http1"] features = ["server", "http1"]
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.http-body-util] [target."cfg(not(target_arch = \"wasm32\"))".dependencies.http-body-util]
workspace = true version = "0.1"
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.hyper-util] [target."cfg(not(target_arch = \"wasm32\"))".dependencies.hyper-util]
workspace = true version = "0.1"
features = ["tokio"] features = ["tokio"]
### ###
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.tokio-stream] [target."cfg(not(target_arch = \"wasm32\"))".dependencies.tokio-stream]
workspace = true version = "0.1.11"
features = ["time"] features = ["time"]
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.tokio] [target."cfg(not(target_arch = \"wasm32\"))".dependencies.tokio]
@@ -102,7 +96,7 @@ workspace = true
features = ["tokio"] features = ["tokio"]
[target."cfg(target_arch = \"wasm32\")".dependencies.gloo-timers] [target."cfg(target_arch = \"wasm32\")".dependencies.gloo-timers]
version = "0.3.0" version = "0.2.4"
features = ["futures"] features = ["futures"]
[target."cfg(target_arch = \"wasm32\")".dependencies.wasm-utils] [target."cfg(target_arch = \"wasm32\")".dependencies.wasm-utils]
@@ -110,7 +104,7 @@ path = "../wasm/utils"
features = ["websocket"] features = ["websocket"]
[target."cfg(target_arch = \"wasm32\")".dependencies.time] [target."cfg(target_arch = \"wasm32\")".dependencies.time]
workspace = true version = "0.3.17"
features = ["wasm-bindgen"] features = ["wasm-bindgen"]
[dev-dependencies] [dev-dependencies]
@@ -118,8 +112,7 @@ tempfile = { workspace = true }
[features] [features]
default = [] default = []
cli = ["clap", "comfy-table"] cli = ["clap"]
fs-credentials-storage = ["nym-credential-storage/persistent-storage"]
fs-surb-storage = ["nym-client-core-surb-storage/fs-surb-storage"] fs-surb-storage = ["nym-client-core-surb-storage/fs-surb-storage"]
fs-gateways-storage = ["nym-client-core-gateways-storage/fs-gateways-storage"] fs-gateways-storage = ["nym-client-core-gateways-storage/fs-gateways-storage"]
wasm = ["nym-gateway-client/wasm"] wasm = ["nym-gateway-client/wasm"]
@@ -18,7 +18,7 @@ url.workspace = true
zeroize = { workspace = true, features = ["zeroize_derive"] } zeroize = { workspace = true, features = ["zeroize_derive"] }
nym-crypto = { path = "../../crypto", features = ["asymmetric"] } nym-crypto = { path = "../../crypto", features = ["asymmetric"] }
nym-gateway-requests = { path = "../../gateway-requests" } nym-gateway-requests = { path = "../../../gateway/gateway-requests" }
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.sqlx] [target."cfg(not(target_arch = \"wasm32\"))".dependencies.sqlx]
workspace = true workspace = true
@@ -27,12 +27,7 @@ optional = true
[build-dependencies] [build-dependencies]
tokio = { workspace = true, features = ["rt-multi-thread", "macros"] } tokio = { workspace = true, features = ["rt-multi-thread", "macros"] }
sqlx = { workspace = true, features = [ sqlx = { workspace = true, features = ["runtime-tokio-rustls", "sqlite", "macros", "migrate"] }
"runtime-tokio-rustls",
"sqlite",
"macros",
"migrate",
] }
[features] [features]
fs-gateways-storage = ["sqlx"] fs-gateways-storage = ["sqlx"]
@@ -1,17 +0,0 @@
/*
* Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
* SPDX-License-Identifier: Apache-2.0
*/
CREATE TABLE remote_gateway_details_temp
(
gateway_id_bs58 TEXT NOT NULL UNIQUE PRIMARY KEY REFERENCES registered_gateway (gateway_id_bs58),
derived_aes128_ctr_blake3_hmac_keys_bs58 TEXT NOT NULL,
gateway_owner_address TEXT,
gateway_listener TEXT NOT NULL
);
INSERT INTO remote_gateway_details_temp SELECT gateway_id_bs58, derived_aes128_ctr_blake3_hmac_keys_bs58, gateway_owner_address, gateway_listener FROM remote_gateway_details;
DROP TABLE remote_gateway_details;
ALTER TABLE remote_gateway_details_temp RENAME TO remote_gateway_details;
@@ -1,13 +0,0 @@
/*
* Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
* SPDX-License-Identifier: Apache-2.0
*/
-- make aes128 key column nullable and add aes256 column
ALTER TABLE remote_gateway_details RENAME COLUMN derived_aes128_ctr_blake3_hmac_keys_bs58 TO derived_aes128_ctr_blake3_hmac_keys_bs58_old;
ALTER TABLE remote_gateway_details ADD COLUMN derived_aes128_ctr_blake3_hmac_keys_bs58 TEXT;
ALTER TABLE remote_gateway_details ADD COLUMN derived_aes256_gcm_siv_key BLOB;
UPDATE remote_gateway_details SET derived_aes128_ctr_blake3_hmac_keys_bs58 = derived_aes128_ctr_blake3_hmac_keys_bs58_old;
ALTER TABLE remote_gateway_details DROP COLUMN derived_aes128_ctr_blake3_hmac_keys_bs58_old;
@@ -155,44 +155,20 @@ impl StorageManager {
) -> Result<(), sqlx::Error> { ) -> Result<(), sqlx::Error> {
sqlx::query!( sqlx::query!(
r#" r#"
INSERT INTO remote_gateway_details(gateway_id_bs58, derived_aes128_ctr_blake3_hmac_keys_bs58, derived_aes256_gcm_siv_key, gateway_owner_address, gateway_listener) INSERT INTO remote_gateway_details(gateway_id_bs58, derived_aes128_ctr_blake3_hmac_keys_bs58, gateway_owner_address, gateway_listener, wg_tun_address)
VALUES (?, ?, ?, ?, ?) VALUES (?, ?, ?, ?, ?)
"#, "#,
remote.gateway_id_bs58, remote.gateway_id_bs58,
remote.derived_aes128_ctr_blake3_hmac_keys_bs58, remote.derived_aes128_ctr_blake3_hmac_keys_bs58,
remote.derived_aes256_gcm_siv_key,
remote.gateway_owner_address, remote.gateway_owner_address,
remote.gateway_listener, remote.gateway_listener,
remote.wg_tun_address,
) )
.execute(&self.connection_pool) .execute(&self.connection_pool)
.await?; .await?;
Ok(()) Ok(())
} }
pub(crate) async fn update_remote_gateway_key(
&self,
gateway_id_bs58: &str,
derived_aes128_ctr_blake3_hmac_keys_bs58: Option<&str>,
derived_aes256_gcm_siv_key: Option<&[u8]>,
) -> Result<(), sqlx::Error> {
sqlx::query!(
r#"
UPDATE remote_gateway_details
SET
derived_aes128_ctr_blake3_hmac_keys_bs58 = ?,
derived_aes256_gcm_siv_key = ?
WHERE gateway_id_bs58 = ?
"#,
derived_aes128_ctr_blake3_hmac_keys_bs58,
derived_aes256_gcm_siv_key,
gateway_id_bs58
)
.execute(&self.connection_pool)
.await?;
Ok(())
}
pub(crate) async fn remove_remote_gateway_details( pub(crate) async fn remove_remote_gateway_details(
&self, &self,
gateway_id: &str, gateway_id: &str,
@@ -7,8 +7,7 @@ use crate::{
}; };
use async_trait::async_trait; use async_trait::async_trait;
use manager::StorageManager; use manager::StorageManager;
use nym_crypto::asymmetric::ed25519; use nym_crypto::asymmetric::identity::PublicKey;
use nym_gateway_requests::SharedSymmetricKey;
use std::path::Path; use std::path::Path;
pub mod error; pub mod error;
@@ -68,7 +67,7 @@ impl GatewaysDetailsStore for OnDiskGatewaysDetails {
Ok(registered) Ok(registered)
} }
async fn all_gateways_identities(&self) -> Result<Vec<ed25519::PublicKey>, Self::StorageError> { async fn all_gateways_identities(&self) -> Result<Vec<PublicKey>, Self::StorageError> {
Ok(self Ok(self
.manager .manager
.registered_gateways() .registered_gateways()
@@ -133,21 +132,6 @@ impl GatewaysDetailsStore for OnDiskGatewaysDetails {
Ok(()) Ok(())
} }
async fn upgrade_stored_remote_gateway_key(
&self,
gateway_id: ed25519::PublicKey,
updated_key: &SharedSymmetricKey,
) -> Result<(), Self::StorageError> {
self.manager
.update_remote_gateway_key(
&gateway_id.to_base58_string(),
None,
Some(updated_key.as_bytes()),
)
.await?;
Ok(())
}
// ideally all of those should be run under a storage tx to ensure storage consistency, // ideally all of those should be run under a storage tx to ensure storage consistency,
// but at that point it's fine // but at that point it's fine
async fn remove_gateway_details(&self, gateway_id: &str) -> Result<(), Self::StorageError> { async fn remove_gateway_details(&self, gateway_id: &str) -> Result<(), Self::StorageError> {
@@ -2,10 +2,8 @@
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use crate::types::{ActiveGateway, GatewayRegistration}; use crate::types::{ActiveGateway, GatewayRegistration};
use crate::{BadGateway, GatewayDetails, GatewaysDetailsStore}; use crate::{BadGateway, GatewaysDetailsStore};
use async_trait::async_trait; use async_trait::async_trait;
use nym_crypto::asymmetric::ed25519::PublicKey;
use nym_gateway_requests::{SharedGatewayKey, SharedSymmetricKey};
use std::collections::HashMap; use std::collections::HashMap;
use std::sync::Arc; use std::sync::Arc;
use thiserror::Error; use thiserror::Error;
@@ -36,6 +34,10 @@ struct InMemStorageInner {
impl GatewaysDetailsStore for InMemGatewaysDetails { impl GatewaysDetailsStore for InMemGatewaysDetails {
type StorageError = InMemStorageError; type StorageError = InMemStorageError;
async fn has_gateway_details(&self, gateway_id: &str) -> Result<bool, Self::StorageError> {
Ok(self.inner.read().await.gateways.contains_key(gateway_id))
}
async fn active_gateway(&self) -> Result<ActiveGateway, Self::StorageError> { async fn active_gateway(&self) -> Result<ActiveGateway, Self::StorageError> {
let guard = self.inner.read().await; let guard = self.inner.read().await;
@@ -66,10 +68,6 @@ impl GatewaysDetailsStore for InMemGatewaysDetails {
Ok(self.inner.read().await.gateways.values().cloned().collect()) Ok(self.inner.read().await.gateways.values().cloned().collect())
} }
async fn has_gateway_details(&self, gateway_id: &str) -> Result<bool, Self::StorageError> {
Ok(self.inner.read().await.gateways.contains_key(gateway_id))
}
async fn load_gateway_details( async fn load_gateway_details(
&self, &self,
gateway_id: &str, gateway_id: &str,
@@ -96,29 +94,6 @@ impl GatewaysDetailsStore for InMemGatewaysDetails {
Ok(()) Ok(())
} }
async fn upgrade_stored_remote_gateway_key(
&self,
gateway_id: PublicKey,
updated_key: &SharedSymmetricKey,
) -> Result<(), Self::StorageError> {
let mut guard = self.inner.write().await;
#[allow(clippy::unwrap_used)]
if let Some(target) = guard.gateways.get_mut(&gateway_id.to_string()) {
let GatewayDetails::Remote(details) = &mut target.details else {
return Ok(());
};
assert_eq!(Arc::strong_count(&details.shared_key), 1);
// eh. that's nasty, but it's only ever used for ephemeral clients so should be fine for now...
details.shared_key = Arc::new(SharedGatewayKey::Current(
SharedSymmetricKey::try_from_bytes(updated_key.as_bytes()).unwrap(),
))
}
Ok(())
}
async fn remove_gateway_details(&self, gateway_id: &str) -> Result<(), Self::StorageError> { async fn remove_gateway_details(&self, gateway_id: &str) -> Result<(), Self::StorageError> {
let mut guard = self.inner.write().await; let mut guard = self.inner.write().await;
if let Some(active) = guard.active_gateway.as_ref() { if let Some(active) = guard.active_gateway.as_ref() {
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use nym_crypto::asymmetric::identity::Ed25519RecoveryError; use nym_crypto::asymmetric::identity::Ed25519RecoveryError;
use nym_gateway_requests::shared_key::SharedKeyConversionError; use nym_gateway_requests::registration::handshake::shared_key::SharedKeyConversionError;
use thiserror::Error; use thiserror::Error;
#[derive(Debug, Error)] #[derive(Debug, Error)]
@@ -36,9 +36,6 @@ pub enum BadGateway {
source: SharedKeyConversionError, source: SharedKeyConversionError,
}, },
#[error("could not find any valid shared keys for gateway {gateway_id}")]
MissingSharedKey { gateway_id: String },
#[error( #[error(
"the listening address of gateway {gateway_id} ({raw_listener}) is malformed: {source}" "the listening address of gateway {gateway_id} ({raw_listener}) is malformed: {source}"
)] )]
@@ -5,8 +5,6 @@
#![warn(clippy::unwrap_used)] #![warn(clippy::unwrap_used)]
use async_trait::async_trait; use async_trait::async_trait;
use nym_crypto::asymmetric::identity;
use nym_gateway_requests::SharedSymmetricKey;
use std::error::Error; use std::error::Error;
pub mod backend; pub mod backend;
@@ -20,6 +18,7 @@ pub use error::BadGateway;
#[cfg(all(not(target_arch = "wasm32"), feature = "fs-gateways-storage"))] #[cfg(all(not(target_arch = "wasm32"), feature = "fs-gateways-storage"))]
pub use backend::fs_backend::{error::StorageError, OnDiskGatewaysDetails}; pub use backend::fs_backend::{error::StorageError, OnDiskGatewaysDetails};
use nym_crypto::asymmetric::identity;
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))] #[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
#[cfg_attr(not(target_arch = "wasm32"), async_trait)] #[cfg_attr(not(target_arch = "wasm32"), async_trait)]
@@ -62,12 +61,6 @@ pub trait GatewaysDetailsStore {
details: &GatewayRegistration, details: &GatewayRegistration,
) -> Result<(), Self::StorageError>; ) -> Result<(), Self::StorageError>;
async fn upgrade_stored_remote_gateway_key(
&self,
gateway_id: identity::PublicKey,
updated_key: &SharedSymmetricKey,
) -> Result<(), Self::StorageError>;
/// Remove given gateway details from the underlying store. /// Remove given gateway details from the underlying store.
async fn remove_gateway_details(&self, gateway_id: &str) -> Result<(), Self::StorageError>; async fn remove_gateway_details(&self, gateway_id: &str) -> Result<(), Self::StorageError>;
} }
@@ -4,10 +4,9 @@
use crate::BadGateway; use crate::BadGateway;
use cosmrs::AccountId; use cosmrs::AccountId;
use nym_crypto::asymmetric::identity; use nym_crypto::asymmetric::identity;
use nym_gateway_requests::shared_key::{LegacySharedKeys, SharedGatewayKey, SharedSymmetricKey}; use nym_gateway_requests::registration::handshake::SharedKeys;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::fmt::{Display, Formatter}; use std::fmt::{Display, Formatter};
use std::ops::Deref;
use std::str::FromStr; use std::str::FromStr;
use std::sync::Arc; use std::sync::Arc;
use time::OffsetDateTime; use time::OffsetDateTime;
@@ -65,15 +64,17 @@ impl From<GatewayDetails> for GatewayRegistration {
impl GatewayDetails { impl GatewayDetails {
pub fn new_remote( pub fn new_remote(
gateway_id: identity::PublicKey, gateway_id: identity::PublicKey,
shared_key: Arc<SharedGatewayKey>, derived_aes128_ctr_blake3_hmac_keys: Arc<SharedKeys>,
gateway_owner_address: Option<AccountId>, gateway_owner_address: Option<AccountId>,
gateway_listener: Url, gateway_listener: Url,
wg_tun_address: Option<Url>,
) -> Self { ) -> Self {
GatewayDetails::Remote(RemoteGatewayDetails { GatewayDetails::Remote(RemoteGatewayDetails {
gateway_id, gateway_id,
shared_key, derived_aes128_ctr_blake3_hmac_keys,
gateway_owner_address, gateway_owner_address,
gateway_listener, gateway_listener,
wg_tun_address,
}) })
} }
@@ -88,9 +89,9 @@ impl GatewayDetails {
} }
} }
pub fn shared_key(&self) -> Option<&SharedGatewayKey> { pub fn shared_key(&self) -> Option<&SharedKeys> {
match self { match self {
GatewayDetails::Remote(details) => Some(&details.shared_key), GatewayDetails::Remote(details) => Some(&details.derived_aes128_ctr_blake3_hmac_keys),
GatewayDetails::Custom(_) => None, GatewayDetails::Custom(_) => None,
} }
} }
@@ -168,10 +169,10 @@ pub struct RegisteredGateway {
#[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))] #[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))]
pub struct RawRemoteGatewayDetails { pub struct RawRemoteGatewayDetails {
pub gateway_id_bs58: String, pub gateway_id_bs58: String,
pub derived_aes128_ctr_blake3_hmac_keys_bs58: Option<String>, pub derived_aes128_ctr_blake3_hmac_keys_bs58: String,
pub derived_aes256_gcm_siv_key: Option<Vec<u8>>,
pub gateway_owner_address: Option<String>, pub gateway_owner_address: Option<String>,
pub gateway_listener: String, pub gateway_listener: String,
pub wg_tun_address: Option<String>,
} }
impl TryFrom<RawRemoteGatewayDetails> for RemoteGatewayDetails { impl TryFrom<RawRemoteGatewayDetails> for RemoteGatewayDetails {
@@ -186,35 +187,13 @@ impl TryFrom<RawRemoteGatewayDetails> for RemoteGatewayDetails {
} }
})?; })?;
let shared_key = let derived_aes128_ctr_blake3_hmac_keys = Arc::new(
match ( SharedKeys::try_from_base58_string(&value.derived_aes128_ctr_blake3_hmac_keys_bs58)
&value.derived_aes256_gcm_siv_key, .map_err(|source| BadGateway::MalformedSharedKeys {
&value.derived_aes128_ctr_blake3_hmac_keys_bs58, gateway_id: value.gateway_id_bs58.clone(),
) { source,
(None, None) => { })?,
return Err(BadGateway::MissingSharedKey { );
gateway_id: value.gateway_id_bs58.clone(),
})
}
(Some(aes256gcm_siv), _) => {
let current_key =
SharedSymmetricKey::try_from_bytes(aes256gcm_siv).map_err(|source| {
BadGateway::MalformedSharedKeys {
gateway_id: value.gateway_id_bs58.clone(),
source,
}
})?;
SharedGatewayKey::Current(current_key)
}
(None, Some(aes128ctr_hmac)) => {
let legacy_key = LegacySharedKeys::try_from_base58_string(aes128ctr_hmac)
.map_err(|source| BadGateway::MalformedSharedKeys {
gateway_id: value.gateway_id_bs58.clone(),
source,
})?;
SharedGatewayKey::Legacy(legacy_key)
}
};
let gateway_owner_address = value let gateway_owner_address = value
.gateway_owner_address .gateway_owner_address
@@ -238,29 +217,38 @@ impl TryFrom<RawRemoteGatewayDetails> for RemoteGatewayDetails {
} }
})?; })?;
let wg_tun_address = value
.wg_tun_address
.as_ref()
.map(|addr| {
Url::parse(addr).map_err(|source| BadGateway::MalformedListener {
gateway_id: value.gateway_id_bs58.clone(),
raw_listener: addr.clone(),
source,
})
})
.transpose()?;
Ok(RemoteGatewayDetails { Ok(RemoteGatewayDetails {
gateway_id, gateway_id,
shared_key: Arc::new(shared_key), derived_aes128_ctr_blake3_hmac_keys,
gateway_owner_address, gateway_owner_address,
gateway_listener, gateway_listener,
wg_tun_address,
}) })
} }
} }
impl<'a> From<&'a RemoteGatewayDetails> for RawRemoteGatewayDetails { impl<'a> From<&'a RemoteGatewayDetails> for RawRemoteGatewayDetails {
fn from(value: &'a RemoteGatewayDetails) -> Self { fn from(value: &'a RemoteGatewayDetails) -> Self {
let (derived_aes128_ctr_blake3_hmac_keys_bs58, derived_aes256_gcm_siv_key) =
match value.shared_key.deref() {
SharedGatewayKey::Current(key) => (None, Some(key.to_bytes())),
SharedGatewayKey::Legacy(key) => (Some(key.to_base58_string()), None),
};
RawRemoteGatewayDetails { RawRemoteGatewayDetails {
gateway_id_bs58: value.gateway_id.to_base58_string(), gateway_id_bs58: value.gateway_id.to_base58_string(),
derived_aes128_ctr_blake3_hmac_keys_bs58, derived_aes128_ctr_blake3_hmac_keys_bs58: value
derived_aes256_gcm_siv_key, .derived_aes128_ctr_blake3_hmac_keys
.to_base58_string(),
gateway_owner_address: value.gateway_owner_address.as_ref().map(|o| o.to_string()), gateway_owner_address: value.gateway_owner_address.as_ref().map(|o| o.to_string()),
gateway_listener: value.gateway_listener.to_string(), gateway_listener: value.gateway_listener.to_string(),
wg_tun_address: value.wg_tun_address.as_ref().map(|addr| addr.to_string()),
} }
} }
} }
@@ -269,11 +257,15 @@ impl<'a> From<&'a RemoteGatewayDetails> for RawRemoteGatewayDetails {
pub struct RemoteGatewayDetails { pub struct RemoteGatewayDetails {
pub gateway_id: identity::PublicKey, pub gateway_id: identity::PublicKey,
pub shared_key: Arc<SharedGatewayKey>, // note: `SharedKeys` implement ZeroizeOnDrop, meaning when `RemoteGatewayDetails` is dropped,
// the keys will be zeroized
pub derived_aes128_ctr_blake3_hmac_keys: Arc<SharedKeys>,
pub gateway_owner_address: Option<AccountId>, pub gateway_owner_address: Option<AccountId>,
pub gateway_listener: Url, pub gateway_listener: Url,
pub wg_tun_address: Option<Url>,
} }
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
@@ -133,6 +133,7 @@ where
let gateway_setup = GatewaySetup::New { let gateway_setup = GatewaySetup::New {
specification: selection_spec, specification: selection_spec,
available_gateways, available_gateways,
wg_tun_address: None,
}; };
let init_details = let init_details =
@@ -161,5 +162,6 @@ where
active: common_args.set_active, active: common_args.set_active,
typ: gateway_registration.details.typ().to_string(), typ: gateway_registration.details.typ().to_string(),
endpoint: Some(gateway_details.gateway_listener.clone()), endpoint: Some(gateway_details.gateway_listener.clone()),
wg_tun_address: gateway_details.wg_tun_address.clone(),
}) })
} }
@@ -1,68 +0,0 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::cli_helpers::{CliClient, CliClientConfig};
use std::fs;
use std::path::PathBuf;
#[cfg(feature = "cli")]
fn parse_encoded_signatures_data(raw: &str) -> bs58::decode::Result<Vec<u8>> {
bs58::decode(raw).into_vec()
}
#[cfg_attr(feature = "cli", derive(clap::Args))]
#[cfg_attr(feature = "cli",
clap(
group(clap::ArgGroup::new("sig_data").required(true)),
))
]
pub struct CommonClientImportCoinIndexSignaturesArgs {
/// Id of client that is going to import the signatures
#[cfg_attr(feature = "cli", clap(long))]
pub id: String,
/// Config file of the client that is supposed to use the signatures.
#[cfg_attr(feature = "cli", clap(long))]
pub(crate) client_config: PathBuf,
/// Explicitly provide the encoded signatures data (as base58)
#[cfg_attr(feature = "cli", clap(long, group = "sig_data", value_parser = parse_encoded_signatures_data))]
pub(crate) signatures_data: Option<Vec<u8>>,
/// Specifies the path to file containing binary signatures data
#[cfg_attr(feature = "cli", clap(long, group = "sig_data"))]
pub(crate) signatures_path: Option<PathBuf>,
// currently hidden as there exists only a single serialization standard
#[cfg_attr(feature = "cli", clap(long, hide = true))]
pub(crate) version: Option<u8>,
}
pub async fn import_coin_index_signatures<C, A>(args: A) -> Result<(), C::Error>
where
A: Into<CommonClientImportCoinIndexSignaturesArgs>,
C: CliClient,
C::Error: From<std::io::Error> + From<nym_id::NymIdError>,
{
let common_args = args.into();
let id = &common_args.id;
let config = C::try_load_current_config(id).await?;
let paths = config.common_paths();
let credentials_store =
nym_credential_storage::initialise_persistent_storage(&paths.credentials_database).await;
let version = common_args.version;
let raw_key = match common_args.signatures_data {
Some(data) => data,
None => {
// SAFETY: one of those arguments must have been set
fs::read(common_args.signatures_path.unwrap())?
}
};
nym_id::import_coin_index_signatures(credentials_store, raw_key, version).await?;
Ok(())
}
@@ -11,14 +11,9 @@ fn parse_encoded_credential_data(raw: &str) -> bs58::decode::Result<Vec<u8>> {
} }
#[cfg_attr(feature = "cli", derive(clap::Args))] #[cfg_attr(feature = "cli", derive(clap::Args))]
#[cfg_attr(feature = "cli", #[cfg_attr(feature = "cli", clap(group(clap::ArgGroup::new("cred_data").required(true))))]
clap(
group(clap::ArgGroup::new("cred_data").required(true)),
group(clap::ArgGroup::new("type").required(true)),
))
]
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct CommonClientImportTicketBookArgs { pub struct CommonClientImportCredentialArgs {
/// Id of client that is going to import the credential /// Id of client that is going to import the credential
#[cfg_attr(feature = "cli", clap(long))] #[cfg_attr(feature = "cli", clap(long))]
pub id: String, pub id: String,
@@ -31,15 +26,6 @@ pub struct CommonClientImportTicketBookArgs {
#[cfg_attr(feature = "cli", clap(long, group = "cred_data"))] #[cfg_attr(feature = "cli", clap(long, group = "cred_data"))]
pub(crate) credential_path: Option<PathBuf>, pub(crate) credential_path: Option<PathBuf>,
/// Specifies whether we're attempting to import a standalone ticketbook (i.e. serialised `IssuedTicketBook`)
#[cfg_attr(feature = "cli", clap(long, group = "type"))]
pub(crate) standalone: bool,
/// Specifies whether we're attempting to import full ticketboot
/// (i.e. one that **might** contain required global signatures; that is serialised `ImportableTicketBook`)
#[cfg_attr(feature = "cli", clap(long, group = "type"))]
pub(crate) full: bool,
// currently hidden as there exists only a single serialization standard // currently hidden as there exists only a single serialization standard
#[cfg_attr(feature = "cli", clap(long, hide = true))] #[cfg_attr(feature = "cli", clap(long, hide = true))]
pub(crate) version: Option<u8>, pub(crate) version: Option<u8>,
@@ -47,7 +33,7 @@ pub struct CommonClientImportTicketBookArgs {
pub async fn import_credential<C, A>(args: A) -> Result<(), C::Error> pub async fn import_credential<C, A>(args: A) -> Result<(), C::Error>
where where
A: Into<CommonClientImportTicketBookArgs>, A: Into<CommonClientImportCredentialArgs>,
C: CliClient, C: CliClient,
C::Error: From<std::io::Error> + From<nym_id::NymIdError>, C::Error: From<std::io::Error> + From<nym_id::NymIdError>,
{ {
@@ -68,19 +54,6 @@ where
} }
}; };
if common_args.standalone { nym_id::import_credential(credentials_store, raw_credential, common_args.version).await?;
nym_id::import_standalone_ticketbook(
credentials_store,
raw_credential,
common_args.version,
)
.await?;
} else {
// sanity check; clap should have ensured it
assert!(common_args.full);
nym_id::import_full_ticketbook(credentials_store, raw_credential, common_args.version)
.await?;
}
Ok(()) Ok(())
} }
@@ -1,68 +0,0 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::cli_helpers::{CliClient, CliClientConfig};
use std::fs;
use std::path::PathBuf;
#[cfg(feature = "cli")]
fn parse_encoded_signatures_data(raw: &str) -> bs58::decode::Result<Vec<u8>> {
bs58::decode(raw).into_vec()
}
#[cfg_attr(feature = "cli", derive(clap::Args))]
#[cfg_attr(feature = "cli",
clap(
group(clap::ArgGroup::new("sig_data").required(true)),
))
]
pub struct CommonClientImportExpirationDateSignaturesArgs {
/// Id of client that is going to import the signatures
#[cfg_attr(feature = "cli", clap(long))]
pub id: String,
/// Config file of the client that is supposed to use the signatures.
#[cfg_attr(feature = "cli", clap(long))]
pub(crate) client_config: PathBuf,
/// Explicitly provide the encoded signatures data (as base58)
#[cfg_attr(feature = "cli", clap(long, group = "sig_data", value_parser = parse_encoded_signatures_data))]
pub(crate) signatures_data: Option<Vec<u8>>,
/// Specifies the path to file containing binary signatures data
#[cfg_attr(feature = "cli", clap(long, group = "sig_data"))]
pub(crate) signatures_path: Option<PathBuf>,
// currently hidden as there exists only a single serialization standard
#[cfg_attr(feature = "cli", clap(long, hide = true))]
pub(crate) version: Option<u8>,
}
pub async fn import_expiration_date_signatures<C, A>(args: A) -> Result<(), C::Error>
where
A: Into<CommonClientImportExpirationDateSignaturesArgs>,
C: CliClient,
C::Error: From<std::io::Error> + From<nym_id::NymIdError>,
{
let common_args = args.into();
let id = &common_args.id;
let config = C::try_load_current_config(id).await?;
let paths = config.common_paths();
let credentials_store =
nym_credential_storage::initialise_persistent_storage(&paths.credentials_database).await;
let version = common_args.version;
let raw_key = match common_args.signatures_data {
Some(data) => data,
None => {
// SAFETY: one of those arguments must have been set
fs::read(common_args.signatures_path.unwrap())?
}
};
nym_id::import_expiration_date_signatures(credentials_store, raw_key, version).await?;
Ok(())
}
@@ -1,68 +0,0 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::cli_helpers::{CliClient, CliClientConfig};
use std::fs;
use std::path::PathBuf;
#[cfg(feature = "cli")]
fn parse_encoded_key_data(raw: &str) -> bs58::decode::Result<Vec<u8>> {
bs58::decode(raw).into_vec()
}
#[cfg_attr(feature = "cli", derive(clap::Args))]
#[cfg_attr(feature = "cli",
clap(
group(clap::ArgGroup::new("key_data_group").required(true)),
))
]
pub struct CommonClientImportMasterVerificationKeyArgs {
/// Id of client that is going to import the key
#[cfg_attr(feature = "cli", clap(long))]
pub id: String,
/// Config file of the client that is supposed to use the key.
#[cfg_attr(feature = "cli", clap(long))]
pub(crate) client_config: PathBuf,
/// Explicitly provide the encoded key data (as base58)
#[cfg_attr(feature = "cli", clap(long, group = "key_data_group", value_parser = parse_encoded_key_data))]
pub(crate) key_data: Option<Vec<u8>>,
/// Specifies the path to file containing binary key data
#[cfg_attr(feature = "cli", clap(long, group = "key_data_group"))]
pub(crate) key_path: Option<PathBuf>,
// currently hidden as there exists only a single serialization standard
#[cfg_attr(feature = "cli", clap(long, hide = true))]
pub(crate) version: Option<u8>,
}
pub async fn import_master_verification_key<C, A>(args: A) -> Result<(), C::Error>
where
A: Into<CommonClientImportMasterVerificationKeyArgs>,
C: CliClient,
C::Error: From<std::io::Error> + From<nym_id::NymIdError>,
{
let common_args = args.into();
let id = &common_args.id;
let config = C::try_load_current_config(id).await?;
let paths = config.common_paths();
let credentials_store =
nym_credential_storage::initialise_persistent_storage(&paths.credentials_database).await;
let version = common_args.version;
let raw_key = match common_args.key_data {
Some(data) => data,
None => {
// SAFETY: one of those arguments must have been set
fs::read(common_args.key_path.unwrap())?
}
};
nym_id::import_master_verification_key(credentials_store, raw_key, version).await?;
Ok(())
}
@@ -172,6 +172,7 @@ where
let gateway_setup = GatewaySetup::New { let gateway_setup = GatewaySetup::New {
specification: selection_spec, specification: selection_spec,
available_gateways, available_gateways,
wg_tun_address: None,
}; };
let init_details = let init_details =
@@ -57,6 +57,7 @@ where
active: active_gateway == Some(remote_details.gateway_id), active: active_gateway == Some(remote_details.gateway_id),
typ: GatewayType::Remote.to_string(), typ: GatewayType::Remote.to_string(),
endpoint: Some(remote_details.gateway_listener), endpoint: Some(remote_details.gateway_listener),
wg_tun_address: remote_details.wg_tun_address,
}), }),
GatewayDetails::Custom(_) => info.push(GatewayInfo { GatewayDetails::Custom(_) => info.push(GatewayInfo {
registration: gateway.registration_timestamp, registration: gateway.registration_timestamp,
@@ -64,6 +65,7 @@ where
active: active_gateway == Some(gateway.details.gateway_id()), active: active_gateway == Some(gateway.details.gateway_id()),
typ: gateway.details.typ().to_string(), typ: gateway.details.typ().to_string(),
endpoint: None, endpoint: None,
wg_tun_address: None,
}), }),
}; };
} }
@@ -1,140 +0,0 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::cli_helpers::{CliClient, CliClientConfig};
use crate::error::ClientCoreError;
use nym_credential_storage::models::BasicTicketbookInformation;
use nym_credential_storage::storage::Storage;
use nym_credentials_interface::TicketType;
use nym_ecash_time::ecash_today;
use serde::{Deserialize, Serialize};
use time::Date;
#[derive(Serialize, Deserialize)]
pub struct AvailableTicketbook {
pub id: i64,
pub typ: TicketType,
pub expiration: Date,
pub issued_tickets: u32,
pub claimed_tickets: u32,
pub ticket_size: u64,
}
impl AvailableTicketbook {
#[cfg(feature = "cli")]
fn table_row(&self) -> comfy_table::Row {
let ecash_today = ecash_today().date();
let issued = self.issued_tickets;
let si_issued = si_scale::helpers::bibytes2((issued as u64 * self.ticket_size) as f64);
let claimed = self.claimed_tickets;
let si_claimed = si_scale::helpers::bibytes2((claimed as u64 * self.ticket_size) as f64);
let remaining = issued - claimed;
let si_remaining =
si_scale::helpers::bibytes2((remaining as u64 * self.ticket_size) as f64);
let si_size = si_scale::helpers::bibytes2(self.ticket_size as f64);
let expiration = if self.expiration <= ecash_today {
comfy_table::Cell::new(format!("EXPIRED ON {}", self.expiration))
.fg(comfy_table::Color::Red)
.add_attribute(comfy_table::Attribute::Bold)
} else {
comfy_table::Cell::new(self.expiration.to_string())
};
vec![
comfy_table::Cell::new(self.id.to_string()),
comfy_table::Cell::new(self.typ),
expiration,
comfy_table::Cell::new(format!("{issued} ({si_issued})")),
comfy_table::Cell::new(format!("{claimed} ({si_claimed})")),
comfy_table::Cell::new(format!("{remaining} ({si_remaining})")),
comfy_table::Cell::new(si_size),
]
.into()
}
}
impl TryFrom<BasicTicketbookInformation> for AvailableTicketbook {
type Error = ClientCoreError;
fn try_from(value: BasicTicketbookInformation) -> Result<Self, Self::Error> {
let typ = value
.ticketbook_type
.parse()
.map_err(|_| ClientCoreError::UnknownTicketType)?;
Ok(AvailableTicketbook {
id: value.id,
typ,
expiration: value.expiration_date,
issued_tickets: value.total_tickets,
claimed_tickets: value.used_tickets,
ticket_size: typ.to_repr().bandwidth_value(),
})
}
}
#[derive(Serialize, Deserialize)]
#[serde(transparent)]
pub struct AvailableTicketbooks(Vec<AvailableTicketbook>);
#[cfg(feature = "cli")]
impl std::fmt::Display for AvailableTicketbooks {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut table = comfy_table::Table::new();
table.set_header(vec![
"id",
"type",
"expiration",
"issued tickets (bandwidth)",
"claimed tickets (bandwidth)",
"remaining tickets (bandwidth)",
"ticket size",
]);
for ticketbook in &self.0 {
table.add_row(ticketbook.table_row());
}
writeln!(f, "{table}")?;
Ok(())
}
}
#[cfg_attr(feature = "cli", derive(clap::Args))]
#[derive(Debug, Clone)]
pub struct CommonShowTicketbooksArgs {
/// Id of client that is going to display the ticketbook information
#[cfg_attr(feature = "cli", clap(long))]
pub id: String,
}
pub async fn show_ticketbooks<C, A>(args: A) -> Result<AvailableTicketbooks, C::Error>
where
A: AsRef<CommonShowTicketbooksArgs>,
C: CliClient,
{
let common_args = args.as_ref();
let id = &common_args.id;
let config = C::try_load_current_config(id).await?;
let paths = config.common_paths();
let credentials_store =
nym_credential_storage::initialise_persistent_storage(&paths.credentials_database).await;
let ticketbooks = credentials_store
.get_ticketbooks_info()
.await
.map_err(|err| ClientCoreError::CredentialStoreError {
source: Box::new(err),
})?;
Ok(AvailableTicketbooks(
ticketbooks
.into_iter()
.map(TryInto::<AvailableTicketbook>::try_into)
.collect::<Result<_, _>>()?,
))
}
@@ -2,14 +2,10 @@
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
pub mod client_add_gateway; pub mod client_add_gateway;
pub mod client_import_coin_index_signatures;
pub mod client_import_credential; pub mod client_import_credential;
pub mod client_import_expiration_date_signatures;
pub mod client_import_master_verification_key;
pub mod client_init; pub mod client_init;
pub mod client_list_gateways; pub mod client_list_gateways;
pub mod client_run; pub mod client_run;
pub mod client_show_ticketbooks;
pub mod client_switch_gateway; pub mod client_switch_gateway;
pub mod traits; pub mod traits;
mod types; mod types;
@@ -15,6 +15,7 @@ pub struct GatewayInfo {
pub typ: String, pub typ: String,
pub endpoint: Option<Url>, pub endpoint: Option<Url>,
pub wg_tun_address: Option<Url>,
} }
impl Display for GatewayInfo { impl Display for GatewayInfo {
@@ -30,6 +31,10 @@ impl Display for GatewayInfo {
if let Some(endpoint) = &self.endpoint { if let Some(endpoint) = &self.endpoint {
write!(f, " endpoint: {endpoint}")?; write!(f, " endpoint: {endpoint}")?;
} }
if let Some(wg_tun_address) = &self.wg_tun_address {
write!(f, " wg tun address: {wg_tun_address}")?;
}
Ok(()) Ok(())
} }
} }
@@ -35,15 +35,15 @@ use crate::init::{
}; };
use crate::{config, spawn_future}; use crate::{config, spawn_future};
use futures::channel::mpsc; use futures::channel::mpsc;
use log::*; use log::{debug, error, info, warn};
use nym_bandwidth_controller::BandwidthController; use nym_bandwidth_controller::BandwidthController;
use nym_client_core_gateways_storage::{GatewayDetails, GatewaysDetailsStore}; use nym_client_core_gateways_storage::{GatewayDetails, GatewaysDetailsStore};
use nym_credential_storage::storage::Storage as CredentialStorage; use nym_credential_storage::storage::Storage as CredentialStorage;
use nym_crypto::asymmetric::{encryption, identity}; use nym_crypto::asymmetric::{encryption, identity};
use nym_gateway_client::client::config::GatewayClientConfig;
use nym_gateway_client::{ use nym_gateway_client::{
AcknowledgementReceiver, GatewayClient, GatewayConfig, MixnetMessageReceiver, PacketRouter, AcknowledgementReceiver, GatewayClient, GatewayConfig, MixnetMessageReceiver, PacketRouter,
}; };
use nym_network_defaults::{DEFAULT_CLIENT_LISTENING_PORT, WG_TUN_DEVICE_ADDRESS};
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::addressing::nodes::NodeIdentity; use nym_sphinx::addressing::nodes::NodeIdentity;
@@ -180,6 +180,7 @@ pub struct BaseClientBuilder<'a, C, S: MixnetClientStorage> {
dkg_query_client: Option<C>, dkg_query_client: Option<C>,
wait_for_gateway: bool, wait_for_gateway: bool,
wireguard_connection: bool,
custom_topology_provider: Option<Box<dyn TopologyProvider + Send + Sync>>, custom_topology_provider: Option<Box<dyn TopologyProvider + Send + Sync>>,
custom_gateway_transceiver: Option<Box<dyn GatewayTransceiver + Send>>, custom_gateway_transceiver: Option<Box<dyn GatewayTransceiver + Send>>,
shutdown: Option<TaskClient>, shutdown: Option<TaskClient>,
@@ -203,6 +204,7 @@ where
client_store, client_store,
dkg_query_client, dkg_query_client,
wait_for_gateway: false, wait_for_gateway: false,
wireguard_connection: false,
custom_topology_provider: None, custom_topology_provider: None,
custom_gateway_transceiver: None, custom_gateway_transceiver: None,
shutdown: None, shutdown: None,
@@ -223,6 +225,12 @@ where
self self
} }
#[must_use]
pub fn with_wireguard_connection(mut self, wireguard_connection: bool) -> Self {
self.wireguard_connection = wireguard_connection;
self
}
#[must_use] #[must_use]
pub fn with_topology_provider( pub fn with_topology_provider(
mut self, mut self,
@@ -352,16 +360,15 @@ where
async fn start_gateway_client( async fn start_gateway_client(
config: &Config, config: &Config,
wireguard_connection: bool,
initialisation_result: InitialisationResult, initialisation_result: InitialisationResult,
bandwidth_controller: Option<BandwidthController<C, S::CredentialStore>>, bandwidth_controller: Option<BandwidthController<C, S::CredentialStore>>,
details_store: &S::GatewaysDetailsStore,
packet_router: PacketRouter, packet_router: PacketRouter,
shutdown: TaskClient, shutdown: TaskClient,
) -> Result<GatewayClient<C, S::CredentialStore>, ClientCoreError> ) -> Result<GatewayClient<C, S::CredentialStore>, ClientCoreError>
where where
<S::KeyStore as KeyStore>::StorageError: Send + Sync + 'static, <S::KeyStore as KeyStore>::StorageError: Send + Sync + 'static,
<S::CredentialStore as CredentialStorage>::StorageError: Send + Sync + 'static, <S::CredentialStore as CredentialStorage>::StorageError: Send + Sync + 'static,
<S::GatewaysDetailsStore as GatewaysDetailsStore>::StorageError: Sync + Send,
{ {
let managed_keys = initialisation_result.client_keys; let managed_keys = initialisation_result.client_keys;
let GatewayDetails::Remote(details) = initialisation_result.gateway_registration.details let GatewayDetails::Remote(details) = initialisation_result.gateway_registration.details
@@ -369,77 +376,54 @@ where
return Err(ClientCoreError::UnexpectedPersistedCustomGatewayDetails); return Err(ClientCoreError::UnexpectedPersistedCustomGatewayDetails);
}; };
let mut gateway_client = let mut gateway_client = if let Some(existing_client) =
if let Some(existing_client) = initialisation_result.authenticated_ephemeral_client { initialisation_result.authenticated_ephemeral_client
existing_client.upgrade(packet_router, bandwidth_controller, shutdown) {
existing_client.upgrade(packet_router, bandwidth_controller, shutdown)
} else {
let gateway_listener = if wireguard_connection {
if let Some(tun_address) = details.wg_tun_address {
tun_address.to_string()
} else {
let default =
format!("ws://{WG_TUN_DEVICE_ADDRESS}:{DEFAULT_CLIENT_LISTENING_PORT}");
warn!("gateway {} does not have tun device address set. defaulting to '{default}'", details.gateway_id);
default
}
} else { } else {
let cfg = GatewayConfig::new( details.gateway_listener.to_string()
details.gateway_id,
details
.gateway_owner_address
.as_ref()
.map(|o| o.to_string()),
details.gateway_listener.to_string(),
);
GatewayClient::new(
GatewayClientConfig::new_default()
.with_disabled_credentials_mode(config.client.disabled_credentials_mode)
.with_response_timeout(
config.debug.gateway_connection.gateway_response_timeout,
),
cfg,
managed_keys.identity_keypair(),
Some(details.shared_key),
packet_router,
bandwidth_controller,
shutdown,
)
}; };
let gateway_failure = |err| { let cfg = GatewayConfig::new(
log::error!("Could not authenticate and start up the gateway connection - {err}"); details.gateway_id,
ClientCoreError::GatewayClientError { details
gateway_id: details.gateway_id.to_base58_string(), .gateway_owner_address
source: err, .as_ref()
} .map(|o| o.to_string()),
gateway_listener,
);
GatewayClient::new(
cfg,
managed_keys.identity_keypair(),
Some(details.derived_aes128_ctr_blake3_hmac_keys),
packet_router,
bandwidth_controller,
shutdown,
)
.with_disabled_credentials_mode(config.client.disabled_credentials_mode)
.with_response_timeout(config.debug.gateway_connection.gateway_response_timeout)
}; };
// the gateway client startup procedure is slightly more complicated now
// we need to:
// - perform handshake (reg or auth)
// - check for key upgrade
// - maybe perform another upgrade handshake
// - check for bandwidth
// - start background tasks
let auth_res = gateway_client
.perform_initial_authentication()
.await
.map_err(gateway_failure)?;
if auth_res.requires_key_upgrade {
// drop the shared_key arc because we don't need it and we can't hold it for the purposes of upgrade
drop(auth_res);
let updated_key = gateway_client
.upgrade_key_authenticated()
.await
.map_err(gateway_failure)?;
details_store
.upgrade_stored_remote_gateway_key(gateway_client.gateway_identity(), &updated_key)
.await.map_err(|err| {
error!("failed to store upgraded gateway key! this connection might be forever broken now: {err}");
ClientCoreError::GatewaysDetailsStoreError { source: Box::new(err) }
})?
}
gateway_client gateway_client
.claim_initial_bandwidth() .authenticate_and_start()
.await .await
.map_err(gateway_failure)?; .map_err(|err| {
gateway_client log::error!("Could not authenticate and start up the gateway connection - {err}");
.start_listening_for_mixnet_messages() ClientCoreError::GatewayClientError {
.map_err(gateway_failure)?; gateway_id: details.gateway_id.to_base58_string(),
source: err,
}
})?;
Ok(gateway_client) Ok(gateway_client)
} }
@@ -447,16 +431,15 @@ where
async fn setup_gateway_transceiver( async fn setup_gateway_transceiver(
custom_gateway_transceiver: Option<Box<dyn GatewayTransceiver + Send>>, custom_gateway_transceiver: Option<Box<dyn GatewayTransceiver + Send>>,
config: &Config, config: &Config,
wireguard_connection: bool,
initialisation_result: InitialisationResult, initialisation_result: InitialisationResult,
bandwidth_controller: Option<BandwidthController<C, S::CredentialStore>>, bandwidth_controller: Option<BandwidthController<C, S::CredentialStore>>,
details_store: &S::GatewaysDetailsStore,
packet_router: PacketRouter, packet_router: PacketRouter,
mut shutdown: TaskClient, mut shutdown: TaskClient,
) -> Result<Box<dyn GatewayTransceiver + Send>, ClientCoreError> ) -> Result<Box<dyn GatewayTransceiver + Send>, ClientCoreError>
where where
<S::KeyStore as KeyStore>::StorageError: Send + Sync + 'static, <S::KeyStore as KeyStore>::StorageError: Send + Sync + 'static,
<S::CredentialStore as CredentialStorage>::StorageError: Send + Sync + 'static, <S::CredentialStore as CredentialStorage>::StorageError: Send + Sync + 'static,
<S::GatewaysDetailsStore as GatewaysDetailsStore>::StorageError: Sync + Send,
{ {
// if we have setup custom gateway sender and persisted details agree with it, return it // if we have setup custom gateway sender and persisted details agree with it, return it
if let Some(mut custom_gateway_transceiver) = custom_gateway_transceiver { if let Some(mut custom_gateway_transceiver) = custom_gateway_transceiver {
@@ -467,8 +450,8 @@ where
{ {
Err(ClientCoreError::CustomGatewaySelectionExpected) Err(ClientCoreError::CustomGatewaySelectionExpected)
} else { } else {
// and make sure to invalidate the task client, so we wouldn't cause premature shutdown // and make sure to invalidate the task client so we wouldn't cause premature shutdown
shutdown.disarm(); shutdown.mark_as_success();
custom_gateway_transceiver.set_packet_router(packet_router)?; custom_gateway_transceiver.set_packet_router(packet_router)?;
Ok(custom_gateway_transceiver) Ok(custom_gateway_transceiver)
}; };
@@ -477,9 +460,9 @@ where
// otherwise, setup normal gateway client, etc // otherwise, setup normal gateway client, etc
let gateway_client = Self::start_gateway_client( let gateway_client = Self::start_gateway_client(
config, config,
wireguard_connection,
initialisation_result, initialisation_result,
bandwidth_controller, bandwidth_controller,
details_store,
packet_router, packet_router,
shutdown, shutdown,
) )
@@ -575,7 +558,7 @@ where
if topology_config.disable_refreshing { if topology_config.disable_refreshing {
// if we're not spawning the refresher, don't cause shutdown immediately // if we're not spawning the refresher, don't cause shutdown immediately
info!("The topology refesher is not going to be started"); info!("The topology refesher is not going to be started");
shutdown.disarm(); shutdown.mark_as_success();
} else { } else {
// don't spawn the refresher if we don't want to be refreshing the topology. // don't spawn the refresher if we don't want to be refreshing the topology.
// only use the initial values obtained // only use the initial values obtained
@@ -669,8 +652,7 @@ where
) )
.await?; .await?;
let (reply_storage_backend, credential_store, details_store) = let (reply_storage_backend, credential_store) = self.client_store.into_runtime_stores();
self.client_store.into_runtime_stores();
// channels for inter-component communication // channels for inter-component communication
// TODO: make the channels be internally created by the relevant components // TODO: make the channels be internally created by the relevant components
@@ -743,9 +725,9 @@ where
let gateway_transceiver = Self::setup_gateway_transceiver( let gateway_transceiver = Self::setup_gateway_transceiver(
self.custom_gateway_transceiver, self.custom_gateway_transceiver,
self.config, self.config,
self.wireguard_connection,
init_res, init_res,
bandwidth_controller, bandwidth_controller,
&details_store,
gateway_packet_router, gateway_packet_router,
shutdown.fork("gateway_transceiver"), shutdown.fork("gateway_transceiver"),
) )
@@ -13,7 +13,7 @@ pub mod v1_1_33 {
use nym_client_core_gateways_storage::{ use nym_client_core_gateways_storage::{
CustomGatewayDetails, GatewayDetails, GatewayRegistration, RemoteGatewayDetails, CustomGatewayDetails, GatewayDetails, GatewayRegistration, RemoteGatewayDetails,
}; };
use nym_gateway_requests::shared_key::LegacySharedKeys; use nym_gateway_requests::registration::handshake::SharedKeys;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use sha2::{digest::Digest, Sha256}; use sha2::{digest::Digest, Sha256};
use std::ops::Deref; use std::ops::Deref;
@@ -58,7 +58,7 @@ pub mod v1_1_33 {
} }
impl PersistedGatewayConfig { impl PersistedGatewayConfig {
fn verify(&self, shared_key: &LegacySharedKeys) -> bool { fn verify(&self, shared_key: &SharedKeys) -> bool {
let key_bytes = Zeroizing::new(shared_key.to_bytes()); let key_bytes = Zeroizing::new(shared_key.to_bytes());
let mut key_hasher = Sha256::new(); let mut key_hasher = Sha256::new();
@@ -74,7 +74,7 @@ pub mod v1_1_33 {
gateway_id: String, gateway_id: String,
} }
fn load_shared_key<P: AsRef<Path>>(path: P) -> Result<LegacySharedKeys, ClientCoreError> { fn load_shared_key<P: AsRef<Path>>(path: P) -> Result<SharedKeys, ClientCoreError> {
// the shared key was a simple pem file // the shared key was a simple pem file
Ok(nym_pemstore::load_key(path)?) Ok(nym_pemstore::load_key(path)?)
} }
@@ -83,7 +83,7 @@ pub mod v1_1_33 {
gateway_id: String, gateway_id: String,
gateway_owner: String, gateway_owner: String,
gateway_listener: String, gateway_listener: String,
gateway_shared_key: LegacySharedKeys, gateway_shared_key: SharedKeys,
) -> Result<GatewayDetails, ClientCoreError> { ) -> Result<GatewayDetails, ClientCoreError> {
Ok(GatewayDetails::Remote(RemoteGatewayDetails { Ok(GatewayDetails::Remote(RemoteGatewayDetails {
gateway_id: gateway_id gateway_id: gateway_id
@@ -91,7 +91,7 @@ pub mod v1_1_33 {
.map_err(|err| ClientCoreError::UpgradeFailure { .map_err(|err| ClientCoreError::UpgradeFailure {
message: format!("the stored gateway id was malformed: {err}"), message: format!("the stored gateway id was malformed: {err}"),
})?, })?,
shared_key: Arc::new(gateway_shared_key.into()), derived_aes128_ctr_blake3_hmac_keys: Arc::new(gateway_shared_key),
gateway_owner_address: Some(gateway_owner.parse().map_err(|err| { gateway_owner_address: Some(gateway_owner.parse().map_err(|err| {
ClientCoreError::UpgradeFailure { ClientCoreError::UpgradeFailure {
message: format!("the stored gateway owner address was malformed: {err}"), message: format!("the stored gateway owner address was malformed: {err}"),
@@ -102,6 +102,7 @@ pub mod v1_1_33 {
message: format!("the stored gateway listener address was malformed: {err}"), message: format!("the stored gateway listener address was malformed: {err}"),
} }
})?, })?,
wg_tun_address: None,
})) }))
} }
@@ -23,7 +23,7 @@ use crate::{
config::{self, disk_persistence::CommonClientPaths}, config::{self, disk_persistence::CommonClientPaths},
error::ClientCoreError, error::ClientCoreError,
}; };
#[cfg(all(not(target_arch = "wasm32"), feature = "fs-credentials-storage"))] #[cfg(all(not(target_arch = "wasm32"), feature = "fs-surb-storage"))]
use nym_credential_storage::persistent_storage::PersistentStorage as PersistentCredentialStorage; use nym_credential_storage::persistent_storage::PersistentStorage as PersistentCredentialStorage;
pub use nym_client_core_gateways_storage as gateways_storage; pub use nym_client_core_gateways_storage as gateways_storage;
@@ -49,13 +49,7 @@ pub trait MixnetClientStorage {
type CredentialStore: CredentialStorage; type CredentialStore: CredentialStorage;
type GatewaysDetailsStore: GatewaysDetailsStore; type GatewaysDetailsStore: GatewaysDetailsStore;
fn into_runtime_stores( fn into_runtime_stores(self) -> (Self::ReplyStore, Self::CredentialStore);
self,
) -> (
Self::ReplyStore,
Self::CredentialStore,
Self::GatewaysDetailsStore,
);
fn key_store(&self) -> &Self::KeyStore; fn key_store(&self) -> &Self::KeyStore;
fn reply_store(&self) -> &Self::ReplyStore; fn reply_store(&self) -> &Self::ReplyStore;
@@ -83,18 +77,8 @@ impl MixnetClientStorage for Ephemeral {
type CredentialStore = EphemeralCredentialStorage; type CredentialStore = EphemeralCredentialStorage;
type GatewaysDetailsStore = InMemGatewaysDetails; type GatewaysDetailsStore = InMemGatewaysDetails;
fn into_runtime_stores( fn into_runtime_stores(self) -> (Self::ReplyStore, Self::CredentialStore) {
self, (self.reply_store, self.credential_store)
) -> (
Self::ReplyStore,
Self::CredentialStore,
Self::GatewaysDetailsStore,
) {
(
self.reply_store,
self.credential_store,
self.gateway_details_store,
)
} }
fn key_store(&self) -> &Self::KeyStore { fn key_store(&self) -> &Self::KeyStore {
@@ -184,18 +168,8 @@ impl MixnetClientStorage for OnDiskPersistent {
type CredentialStore = PersistentCredentialStorage; type CredentialStore = PersistentCredentialStorage;
type GatewaysDetailsStore = OnDiskGatewaysDetails; type GatewaysDetailsStore = OnDiskGatewaysDetails;
fn into_runtime_stores( fn into_runtime_stores(self) -> (Self::ReplyStore, Self::CredentialStore) {
self, (self.reply_store, self.credential_store)
) -> (
Self::ReplyStore,
Self::CredentialStore,
Self::GatewaysDetailsStore,
) {
(
self.reply_store,
self.credential_store,
self.gateway_details_store,
)
} }
fn key_store(&self) -> &Self::KeyStore { fn key_store(&self) -> &Self::KeyStore {
@@ -3,7 +3,7 @@
use crate::client::key_manager::persistence::KeyStore; use crate::client::key_manager::persistence::KeyStore;
use nym_crypto::asymmetric::{encryption, identity}; use nym_crypto::asymmetric::{encryption, identity};
use nym_gateway_requests::shared_key::{LegacySharedKeys, SharedGatewayKey, SharedSymmetricKey}; use nym_gateway_requests::registration::handshake::SharedKeys;
use nym_sphinx::acknowledgements::AckKey; use nym_sphinx::acknowledgements::AckKey;
use rand::{CryptoRng, RngCore}; use rand::{CryptoRng, RngCore};
use std::sync::Arc; use std::sync::Arc;
@@ -84,7 +84,5 @@ fn _assert_keys_zeroize_on_drop() {
_assert_zeroize_on_drop::<identity::KeyPair>(); _assert_zeroize_on_drop::<identity::KeyPair>();
_assert_zeroize_on_drop::<encryption::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::<SharedKeys>();
_assert_zeroize_on_drop::<SharedSymmetricKey>();
_assert_zeroize_on_drop::<SharedGatewayKey>();
} }
@@ -3,12 +3,10 @@
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_crypto::asymmetric::identity; use nym_crypto::asymmetric::identity;
use nym_gateway_client::GatewayClient; use nym_gateway_client::GatewayClient;
pub use nym_gateway_client::{GatewayPacketRouter, PacketRouter}; pub use nym_gateway_client::{GatewayPacketRouter, PacketRouter};
use nym_sphinx::forwarding::packet::MixPacket; use nym_sphinx::forwarding::packet::MixPacket;
use nym_validator_client::nyxd::contract_traits::DkgQueryClient;
use std::fmt::Debug; use std::fmt::Debug;
use std::os::raw::c_int as RawFd; use std::os::raw::c_int as RawFd;
use thiserror::Error; use thiserror::Error;
@@ -113,9 +111,8 @@ impl<C, St> RemoteGateway<C, St> {
impl<C, St> GatewayTransceiver for RemoteGateway<C, St> impl<C, St> GatewayTransceiver for RemoteGateway<C, St>
where where
C: DkgQueryClient + Send + Sync, C: Send,
St: CredentialStorage, St: Send,
<St as CredentialStorage>::StorageError: Send + Sync + 'static,
{ {
fn gateway_identity(&self) -> identity::PublicKey { fn gateway_identity(&self) -> identity::PublicKey {
self.gateway_client.gateway_identity() self.gateway_client.gateway_identity()
@@ -129,9 +126,8 @@ where
#[cfg_attr(not(target_arch = "wasm32"), async_trait)] #[cfg_attr(not(target_arch = "wasm32"), async_trait)]
impl<C, St> GatewaySender for RemoteGateway<C, St> impl<C, St> GatewaySender for RemoteGateway<C, St>
where where
C: DkgQueryClient + Send + Sync, C: Send,
St: CredentialStorage, St: Send,
<St as CredentialStorage>::StorageError: Send + Sync + 'static,
{ {
async fn send_mix_packet(&mut self, packet: MixPacket) -> Result<(), ErasedGatewayError> { async fn send_mix_packet(&mut self, packet: MixPacket) -> Result<(), ErasedGatewayError> {
self.gateway_client self.gateway_client

Some files were not shown because too many files have changed in this diff Show More