Compare commits

..

2 Commits

Author SHA1 Message Date
Jon Häggblad 8853a4c443 rustfmt 2023-03-29 13:52:53 +02:00
Jon Häggblad caf065514e task-client: add source to UnexpectedHalt 2023-03-29 13:47:42 +02:00
734 changed files with 48136 additions and 27182 deletions
-16
View File
@@ -1,16 +0,0 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
version: 2
updates:
# Maintain dependencies for GitHub Actions
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "daily"
commit-message:
prefix: build
prefix-development: chore
include: scope
@@ -98,7 +98,7 @@ jobs:
cp target/release/nym-network-requester $OUTPUT_DIR cp target/release/nym-network-requester $OUTPUT_DIR
cp target/release/nym-network-statistics $OUTPUT_DIR cp target/release/nym-network-statistics $OUTPUT_DIR
cp target/release/nym-cli $OUTPUT_DIR cp target/release/nym-cli $OUTPUT_DIR
cp target/release/nym-credential-client $OUTPUT_DIR cp target/release/credential $OUTPUT_DIR
cp target/release/explorer-api $OUTPUT_DIR cp target/release/explorer-api $OUTPUT_DIR
cp contracts/target/wasm32-unknown-unknown/release/mixnet_contract.wasm $OUTPUT_DIR cp contracts/target/wasm32-unknown-unknown/release/mixnet_contract.wasm $OUTPUT_DIR
-76
View File
@@ -1,76 +0,0 @@
name: CD dev-portal
on:
push:
branches: master
paths:
- 'documentation/dev-portal/**'
jobs:
build:
runs-on: custom-runner-linux
steps:
- uses: actions/checkout@v3
- name: Install rsync
run: sudo apt-get install rsync
- uses: rlespinasse/github-slug-action@v3.x
- uses: actions/setup-node@v3
with:
node-version: "16"
- name: Install Rust stable
uses: actions-rs/toolchain@v1
with:
toolchain: stable
- name: Install mdbook
run: (test -x $HOME/.cargo/bin/mdbook || cargo install --vers "^0.4" mdbook)
- name: Install mdbook plugins
run: |
cargo install --vers "^0.2.0" mdbook-variables && cargo install \
--vers "^1.8.0" mdbook-admonish && cargo install --vers \
"^0.1.2" mdbook-last-changed && cargo install --vers "^0.1.2" \
mdbook-theme && cargo install --vers "^0.7.7" mdbook-linkcheck
- name: Clean website
run: cd documentation/dev-portal && mdbook clean
- name: Build website
run: cd documentation/dev-portal && mdbook build
- name: Deploy branch master to dev
continue-on-error: true
uses: easingthemes/ssh-deploy@main
env:
SSH_PRIVATE_KEY: ${{ secrets.CD_WWW_SSH_PRIVATE_KEY }}
ARGS: "-rltgoDzvO --delete"
SOURCE: "documentation/dev-portal/book/html/"
REMOTE_HOST: ${{ secrets.CD_WWW_REMOTE_HOST_DEV }}
REMOTE_USER: ${{ secrets.CD_WWW_REMOTE_USER }}
TARGET: ${{ secrets.CD_WWW_REMOTE_TARGET_DEVP }}/
EXCLUDE: "/dist/, /node_modules/"
- name: Deploy branch master to prod
uses: easingthemes/ssh-deploy@main
env:
SSH_PRIVATE_KEY: ${{ secrets.CD_WWW_SSH_PRIVATE_KEY }}
ARGS: "-rltgoDzvO --delete"
SOURCE: "documentation/dev-portal/book/html/"
REMOTE_HOST: ${{ secrets.CD_WWW_REMOTE_HOST_PROD }}
REMOTE_USER: ${{ secrets.CD_WWW_REMOTE_USER }}
TARGET: ${{ secrets.CD_WWW_REMOTE_TARGET_DEVP }}/
EXCLUDE: "/dist/, /node_modules/"
- name: Matrix - Node Install
run: npm install
working-directory: .github/workflows/support-files
- name: Matrix - Send Notification
env:
NYM_NOTIFICATION_KIND: cd-dev
NYM_PROJECT_NAME: "Dev portal CD"
NYM_CI_WWW_BASE: "${{ secrets.NYM_CD_WWW_BASE }}"
NYM_CI_WWW_LOCATION: "${{ env.GITHUB_REF_SLUG }}"
GIT_COMMIT_MESSAGE: "${{ github.event.head_commit.message }}"
GIT_BRANCH: "${GITHUB_REF##*/}"
MATRIX_SERVER: "${{ secrets.MATRIX_SERVER }}"
MATRIX_ROOM: "${{ secrets.MATRIX_ROOM_DEVP }}"
MATRIX_USER_ID: "${{ secrets.MATRIX_USER_ID }}"
MATRIX_TOKEN: "${{ secrets.MATRIX_TOKEN }}"
MATRIX_DEVICE_ID: "${{ secrets.MATRIX_DEVICE_ID }}"
IS_SUCCESS: "${{ job.status == 'success' }}"
uses: docker://keybaseio/client:stable-node
with:
args: .github/workflows/support-files/notifications/entry_point.sh
-82
View File
@@ -1,82 +0,0 @@
name: CD docs
on:
push:
branches: master
paths:
- 'documentation/docs/**'
jobs:
build:
runs-on: custom-runner-linux
steps:
- uses: actions/checkout@v3
- name: Install rsync
run: sudo apt-get install rsync
- uses: rlespinasse/github-slug-action@v3.x
- uses: actions/setup-node@v3
with:
node-version: "16"
- name: Install Rust stable
uses: actions-rs/toolchain@v1
with:
toolchain: stable
- name: Build all binaries
uses: actions-rs/cargo@v1
with:
command: build
args: --workspace --release --all
- name: Install mdbook
run: (test -x $HOME/.cargo/bin/mdbook || cargo install --vers "^0.4" mdbook)
- name: Install mdbook plugins
run: |
cargo install --vers "^0.2.0" mdbook-variables && cargo install \
--vers "^1.8.0" mdbook-admonish && cargo install --vers \
"^0.1.2" mdbook-last-changed && cargo install --vers "^0.1.2" \
mdbook-theme && cargo install --vers "^0.7.7" mdbook-linkcheck && \
cargo install --vers "^0.5.0" mdbook-cmdrun
- name: Clean website
run: cd documentation/docs && mdbook clean
- name: Build website
run: cd documentation/docs && mdbook build
- name: Deploy branch master to dev
continue-on-error: true
uses: easingthemes/ssh-deploy@main
env:
SSH_PRIVATE_KEY: ${{ secrets.CD_WWW_SSH_PRIVATE_KEY }}
ARGS: "-rltgoDzvO --delete"
SOURCE: "documentation/docs/book/"
REMOTE_HOST: ${{ secrets.CD_WWW_REMOTE_HOST_DEV }}
REMOTE_USER: ${{ secrets.CD_WWW_REMOTE_USER }}
TARGET: ${{ secrets.CD_WWW_REMOTE_TARGET }}/
EXCLUDE: "/dist/, /node_modules/"
- name: Deploy branch master to prod
uses: easingthemes/ssh-deploy@main
env:
SSH_PRIVATE_KEY: ${{ secrets.CD_WWW_SSH_PRIVATE_KEY }}
ARGS: "-rltgoDzvO --delete"
SOURCE: "documentation/docs/book/"
REMOTE_HOST: ${{ secrets.CD_WWW_REMOTE_HOST_PROD }}
REMOTE_USER: ${{ secrets.CD_WWW_REMOTE_USER }}
TARGET: ${{ secrets.CD_WWW_REMOTE_TARGET }}/
EXCLUDE: "/dist/, /node_modules/"
- name: Matrix - Node Install
run: npm install
working-directory: .github/workflows/support-files
- name: Matrix - Send Notification
env:
NYM_NOTIFICATION_KIND: cd-docs
NYM_PROJECT_NAME: "Docs CD"
NYM_CI_WWW_BASE: "${{ secrets.NYM_CD_WWW_BASE }}"
NYM_CI_WWW_LOCATION: "${{ env.GITHUB_REF_SLUG }}"
GIT_COMMIT_MESSAGE: "${{ github.event.head_commit.message }}"
GIT_BRANCH: "${GITHUB_REF##*/}"
MATRIX_SERVER: "${{ secrets.MATRIX_SERVER }}"
MATRIX_ROOM: "${{ secrets.MATRIX_ROOM_DOCS }}"
MATRIX_USER_ID: "${{ secrets.MATRIX_USER_ID }}"
MATRIX_TOKEN: "${{ secrets.MATRIX_TOKEN }}"
MATRIX_DEVICE_ID: "${{ secrets.MATRIX_DEVICE_ID }}"
IS_SUCCESS: "${{ job.status == 'success' }}"
uses: docker://keybaseio/client:stable-node
with:
args: .github/workflows/support-files/notifications/entry_point.sh
-66
View File
@@ -1,66 +0,0 @@
name: CI dev-portal
on:
push:
branches-ignore: master
paths:
- 'documentation/dev-portal/**'
jobs:
build:
runs-on: custom-runner-linux
steps:
- uses: actions/checkout@v3
- name: Install rsync
run: sudo apt-get install rsync
- uses: rlespinasse/github-slug-action@v3.x
- uses: actions/setup-node@v3
with:
node-version: "16"
- name: Install Rust stable
uses: actions-rs/toolchain@v1
with:
toolchain: stable
- name: Install mdbook
run: (test -x $HOME/.cargo/bin/mdbook || cargo install --vers "^0.4" mdbook)
- name: Install mdbook plugins
run: |
cargo install --vers "^0.2.0" mdbook-variables && cargo install \
--vers "^1.8.0" mdbook-admonish && cargo install --vers \
"^0.1.2" mdbook-last-changed && cargo install --vers "^0.1.2" mdbook-theme \
&& cargo install --vers "^0.7.7" mdbook-linkcheck
- name: Clean website
run: cd documentation/dev-portal && mdbook clean
- name: Build website
run: cd documentation/dev-portal && mdbook build
- name: Deploy branch to CI www
continue-on-error: true
uses: easingthemes/ssh-deploy@main
env:
SSH_PRIVATE_KEY: ${{ secrets.CI_WWW_SSH_PRIVATE_KEY }}
ARGS: "-rltgoDzvO --delete"
SOURCE: "documentation/dev-portal/book/html/"
REMOTE_HOST: ${{ secrets.CI_WWW_REMOTE_HOST }}
REMOTE_USER: ${{ secrets.CI_WWW_REMOTE_USER }}
TARGET: ${{ secrets.CI_WWW_REMOTE_TARGET }}/dev-portal-${{ env.GITHUB_REF_SLUG }}
EXCLUDE: "/dist/, /node_modules/"
- name: Matrix - Node Install
run: npm install
working-directory: .github/workflows/support-files
- name: Matrix - Send Notification
env:
NYM_NOTIFICATION_KIND: ci-dev
NYM_PROJECT_NAME: "Dev portal CI"
NYM_CI_WWW_BASE: "${{ secrets.NYM_CI_WWW_BASE }}"
NYM_CI_WWW_LOCATION: "dev-portal-${{ env.GITHUB_REF_SLUG }}"
GIT_COMMIT_MESSAGE: "${{ github.event.head_commit.message }}"
GIT_BRANCH: "${GITHUB_REF##*/}"
MATRIX_SERVER: "${{ secrets.MATRIX_SERVER }}"
MATRIX_ROOM: "${{ secrets.MATRIX_ROOM_DEVP }}"
MATRIX_USER_ID: "${{ secrets.MATRIX_USER_ID }}"
MATRIX_TOKEN: "${{ secrets.MATRIX_TOKEN }}"
MATRIX_DEVICE_ID: "${{ secrets.MATRIX_DEVICE_ID }}"
IS_SUCCESS: "${{ job.status == 'success' }}"
uses: docker://keybaseio/client:stable-node
with:
args: .github/workflows/support-files/notifications/entry_point.sh
-72
View File
@@ -1,72 +0,0 @@
name: CI docs
on:
push:
branches-ignore: master
paths:
- 'documentation/docs/**'
jobs:
build:
runs-on: custom-runner-linux
steps:
- uses: actions/checkout@v3
- name: Install rsync
run: sudo apt-get install rsync
- uses: rlespinasse/github-slug-action@v3.x
- uses: actions/setup-node@v3
with:
node-version: "16"
- name: Install Rust stable
uses: actions-rs/toolchain@v1
with:
toolchain: stable
- name: Build all binaries
uses: actions-rs/cargo@v1
with:
command: build
args: --workspace --release --all
- name: Install mdbook
run: (test -x $HOME/.cargo/bin/mdbook || cargo install --vers "^0.4" mdbook)
- name: Install mdbook plugins
run: |
cargo install --vers "^0.2.0" mdbook-variables && cargo install \
--vers "^1.8.0" mdbook-admonish && cargo install --vers \
"^0.1.2" mdbook-last-changed && cargo install --vers "^0.1.2" \
mdbook-theme && cargo install --vers "^0.7.7" mdbook-linkcheck && \
cargo install --vers "^0.5.0" mdbook-cmdrun
- name: Clean website
run: cd documentation/docs && mdbook clean
- name: Build website
run: cd documentation/docs && mdbook build
- name: Deploy branch to CI www
continue-on-error: true
uses: easingthemes/ssh-deploy@main
env:
SSH_PRIVATE_KEY: ${{ secrets.CI_WWW_SSH_PRIVATE_KEY }}
ARGS: "-rltgoDzvO --delete"
SOURCE: "documentation/docs/book/"
REMOTE_HOST: ${{ secrets.CI_WWW_REMOTE_HOST }}
REMOTE_USER: ${{ secrets.CI_WWW_REMOTE_USER }}
TARGET: ${{ secrets.CI_WWW_REMOTE_TARGET }}/docs-${{ env.GITHUB_REF_SLUG }}
EXCLUDE: "/dist/, /node_modules/"
- name: Matrix - Node Install
run: npm install
working-directory: .github/workflows/support-files
- name: Matrix - Send Notification
env:
NYM_NOTIFICATION_KIND: ci-docs
NYM_PROJECT_NAME: "Docs CI"
NYM_CI_WWW_BASE: "${{ secrets.NYM_CI_WWW_BASE }}"
NYM_CI_WWW_LOCATION: "docs-${{ env.GITHUB_REF_SLUG }}"
GIT_COMMIT_MESSAGE: "${{ github.event.head_commit.message }}"
GIT_BRANCH: "${GITHUB_REF##*/}"
MATRIX_SERVER: "${{ secrets.MATRIX_SERVER }}"
MATRIX_ROOM: "${{ secrets.MATRIX_ROOM_DOCS }}"
MATRIX_USER_ID: "${{ secrets.MATRIX_USER_ID }}"
MATRIX_TOKEN: "${{ secrets.MATRIX_TOKEN }}"
MATRIX_DEVICE_ID: "${{ secrets.MATRIX_DEVICE_ID }}"
IS_SUCCESS: "${{ job.status == 'success' }}"
uses: docker://keybaseio/client:stable-node
with:
args: .github/workflows/support-files/notifications/entry_point.sh
+1 -2
View File
@@ -30,7 +30,6 @@ jobs:
continue-on-error: ${{ matrix.rust == 'nightly' }} continue-on-error: ${{ matrix.rust == 'nightly' }}
needs: matrix_prep needs: matrix_prep
strategy: strategy:
fail-fast: false
matrix: ${{fromJson(needs.matrix_prep.outputs.matrix)}} matrix: ${{fromJson(needs.matrix_prep.outputs.matrix)}}
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
@@ -64,4 +63,4 @@ jobs:
if: ${{ matrix.rust != 'nightly' }} if: ${{ matrix.rust != 'nightly' }}
with: with:
command: clippy command: clippy
args: --manifest-path contracts/Cargo.toml --workspace --all-targets -- -D warnings args: --manifest-path contracts/Cargo.toml --workspace -- -D warnings
-13
View File
@@ -1,13 +0,0 @@
name: Greetings
on: [pull_request_target, issues]
jobs:
greeting:
runs-on: ubuntu-latest
steps:
- uses: actions/first-interaction@v1
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
issue-message: 'Thank you for raising this issue'
pr-message: 'Thank you for making this first PR'
@@ -1,29 +0,0 @@
const Handlebars = require('handlebars');
const fs = require('fs');
const path = require('path');
async function addToContextAndValidate(context) {
if (!context.env.NYM_CI_WWW_LOCATION) {
throw new Error('Please ensure the env var NYM_CI_WWW_LOCATION is set');
}
if (!context.env.NYM_CI_WWW_BASE) {
throw new Error('Please ensure the env var NYM_CI_WWW_BASE is set');
}
}
async function getMessageBody(context) {
const source = fs
.readFileSync(
context.env.IS_SUCCESS === 'true'
? path.resolve(__dirname, 'templates', 'success')
: path.resolve(__dirname, 'templates', 'failure'),
)
.toString();
const template = Handlebars.compile(source);
return template(context);
}
module.exports = {
addToContextAndValidate,
getMessageBody,
};
@@ -1,17 +0,0 @@
🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥
> :rocket: {{ env.NYM_PROJECT_NAME }}
>
> 🔴 **FAILURE** :cry:
>
> `branch` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/tree/{{ env.GIT_BRANCH_NAME }}
>
> `commit` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/commit/{{ env.GITHUB_SHA }}
>
> `build ` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/actions/runs/{{ env.GITHUB_RUN_ID }}
>
Commit message:
```
{{ env.GIT_COMMIT_MESSAGE }}
```
@@ -1,17 +0,0 @@
🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩
> :rocket: {{ env.NYM_PROJECT_NAME }} ➡️➡️➡️➡️➡️ **View output:** https://{{ env.NYM_CI_WWW_BASE }}/developers/
>
> ✅ **SUCCESS**
>
> `branch` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/tree/{{ env.GIT_BRANCH_NAME }}
>
> `commit` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/commit/{{ env.GITHUB_SHA }}
>
> `build ` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/actions/runs/{{ env.GITHUB_RUN_ID }}
>
Commit message by `{{ env.GITHUB_ACTOR }}` at {{ timestamp }}:
```
{{ env.GIT_COMMIT_MESSAGE }}
```
@@ -1,29 +0,0 @@
const Handlebars = require('handlebars');
const fs = require('fs');
const path = require('path');
async function addToContextAndValidate(context) {
if (!context.env.NYM_CI_WWW_LOCATION) {
throw new Error('Please ensure the env var NYM_CI_WWW_LOCATION is set');
}
if (!context.env.NYM_CI_WWW_BASE) {
throw new Error('Please ensure the env var NYM_CI_WWW_BASE is set');
}
}
async function getMessageBody(context) {
const source = fs
.readFileSync(
context.env.IS_SUCCESS === 'true'
? path.resolve(__dirname, 'templates', 'success')
: path.resolve(__dirname, 'templates', 'failure'),
)
.toString();
const template = Handlebars.compile(source);
return template(context);
}
module.exports = {
addToContextAndValidate,
getMessageBody,
};
@@ -1,11 +0,0 @@
🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥
> :rocket: {{ env.NYM_PROJECT_NAME }}
> 🔴 **FAILURE** :cry:
> `branch` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/tree/{{ env.GIT_BRANCH_NAME }}
> `commit` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/commit/{{ env.GITHUB_SHA }}
> `build ` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/actions/runs/{{ env.GITHUB_RUN_ID }}
Commit message:
```
{{ env.GIT_COMMIT_MESSAGE }}
```
@@ -1,17 +0,0 @@
🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩
> :rocket: {{ env.NYM_PROJECT_NAME }} ➡️➡️➡️➡️➡️ **View output:** https://{{ env.NYM_CI_WWW_BASE }}/docs/
>
> ✅ **SUCCESS**
>
> `branch` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/tree/{{ env.GIT_BRANCH_NAME }}
>
> `commit` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/commit/{{ env.GITHUB_SHA }}
>
> `build ` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/actions/runs/{{ env.GITHUB_RUN_ID }}
>
Commit message by `{{ env.GITHUB_ACTOR }}` at {{ timestamp }}:
```
{{ env.GIT_COMMIT_MESSAGE }}
```
@@ -1,29 +0,0 @@
const Handlebars = require('handlebars');
const fs = require('fs');
const path = require('path');
async function addToContextAndValidate(context) {
if (!context.env.NYM_CI_WWW_LOCATION) {
throw new Error('Please ensure the env var NYM_CI_WWW_LOCATION is set');
}
if (!context.env.NYM_CI_WWW_BASE) {
throw new Error('Please ensure the env var NYM_CI_WWW_BASE is set');
}
}
async function getMessageBody(context) {
const source = fs
.readFileSync(
context.env.IS_SUCCESS === 'true'
? path.resolve(__dirname, 'templates', 'success')
: path.resolve(__dirname, 'templates', 'failure'),
)
.toString();
const template = Handlebars.compile(source);
return template(context);
}
module.exports = {
addToContextAndValidate,
getMessageBody,
};
@@ -1,17 +0,0 @@
🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥
> :rocket: {{ env.NYM_PROJECT_NAME }}
>
> 🔴 **FAILURE** :cry:
>
> `branch` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/tree/{{ env.GIT_BRANCH_NAME }}
>
> `commit` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/commit/{{ env.GITHUB_SHA }}
>
> `build ` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/actions/runs/{{ env.GITHUB_RUN_ID }}
>
Commit message:
```
{{ env.GIT_COMMIT_MESSAGE }}
```
@@ -1,17 +0,0 @@
🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩
> :rocket: {{ env.NYM_PROJECT_NAME }} ➡️➡️➡️➡️➡️ **View output:** https://{{ env.NYM_CI_WWW_LOCATION }}.{{ env.NYM_CI_WWW_BASE }}/
>
> ✅ **SUCCESS**
>
> `branch` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/tree/{{ env.GIT_BRANCH_NAME }}
>
> `commit` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/commit/{{ env.GITHUB_SHA }}
>
> `build ` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/actions/runs/{{ env.GITHUB_RUN_ID }}
>
Commit message by `{{ env.GITHUB_ACTOR }}` at {{ timestamp }}:
```
{{ env.GIT_COMMIT_MESSAGE }}
```
@@ -1,29 +0,0 @@
const Handlebars = require('handlebars');
const fs = require('fs');
const path = require('path');
async function addToContextAndValidate(context) {
if (!context.env.NYM_CI_WWW_LOCATION) {
throw new Error('Please ensure the env var NYM_CI_WWW_LOCATION is set');
}
if (!context.env.NYM_CI_WWW_BASE) {
throw new Error('Please ensure the env var NYM_CI_WWW_BASE is set');
}
}
async function getMessageBody(context) {
const source = fs
.readFileSync(
context.env.IS_SUCCESS === 'true'
? path.resolve(__dirname, 'templates', 'success')
: path.resolve(__dirname, 'templates', 'failure'),
)
.toString();
const template = Handlebars.compile(source);
return template(context);
}
module.exports = {
addToContextAndValidate,
getMessageBody,
};
@@ -1,17 +0,0 @@
🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥
> :rocket: {{ env.NYM_PROJECT_NAME }}
>
> 🔴 **FAILURE** :cry:
>
> `branch` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/tree/{{ env.GIT_BRANCH_NAME }}
>
> `commit` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/commit/{{ env.GITHUB_SHA }}
>
> `build ` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/actions/runs/{{ env.GITHUB_RUN_ID }}
>
Commit message:
```
{{ env.GIT_COMMIT_MESSAGE }}
```
@@ -1,17 +0,0 @@
🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩
> :rocket: {{ env.NYM_PROJECT_NAME }} ➡️➡️➡️➡️➡️ **View output:** https://{{ env.NYM_CI_WWW_LOCATION }}.{{ env.NYM_CI_WWW_BASE }}/
>
> ✅ **SUCCESS**
>
> `branch` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/tree/{{ env.GIT_BRANCH_NAME }}
>
> `commit` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/commit/{{ env.GITHUB_SHA }}
>
> `build ` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/actions/runs/{{ env.GITHUB_RUN_ID }}
>
Commit message by `{{ env.GITHUB_ACTOR }}` at {{ timestamp }}:
```
{{ env.GIT_COMMIT_MESSAGE }}
```
@@ -3,7 +3,7 @@ require('dotenv').config();
const { sendMatrixMessage } = require('./send_message_to_matrix'); const { sendMatrixMessage } = require('./send_message_to_matrix');
let context = { let context = {
kinds: ['nym-wallet', 'ts-packages', 'network-explorer', 'nightly', 'nym-connect','security','ci-docs','cd-docs','ci-dev','cd-dev'], kinds: ['nym-wallet', 'ts-packages', 'network-explorer', 'nightly', 'nym-connect','security'],
}; };
/** /**
+1 -1
View File
@@ -22,6 +22,6 @@
"unified": "^9.2.2" "unified": "^9.2.2"
}, },
"devDependencies": { "devDependencies": {
"prettier": "^2.8.7" "prettier": "2.3.2"
} }
} }
+1 -1
View File
@@ -64,4 +64,4 @@ jobs:
uses: actions-rs/cargo@v1 uses: actions-rs/cargo@v1
with: with:
command: clippy command: clippy
args: --manifest-path nym-wallet/Cargo.toml --workspace --all-features --all-targets -- -D warnings args: --manifest-path nym-wallet/Cargo.toml --workspace --all-features -- -D warnings
+3 -43
View File
@@ -5,58 +5,17 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
## [Unreleased] ## [Unreleased]
- nym-network-statistics properly handles signals ([#3209]) - nym-network-statistics properly handles signals ([#3209])
- add socks5 support for Rust SDK ([#3226], [#3255]) - add socks5 support for Rust SDK ([#3226])
- add coconut bandwidth credential support for Rust SDK ([#3273])
[#3209]: https://github.com/nymtech/nym/issues/3209 [#3209]: https://github.com/nymtech/nym/issues/3209
[#3226]: https://github.com/nymtech/nym/pull/3226 [#3226]: https://github.com/nymtech/nym/pull/3226
[#3255]: https://github.com/nymtech/nym/pull/3255
[#3273]: https://github.com/nymtech/nym/pull/3273
## [v1.1.15] (2023-04-18)
- Fix verloc being stuck waiting for shutdown signal ([#3250])
- Introduce `--output json` flag to `sign` command to allow to more easily capture the output ([#3249])
- Explorer - Dont fetch Service Provider list on Testnet ([#3245])
- When determining active set, rather than weighting the nodes by just the `stake`, use `stake * performance` ([#3234])
- Introduce dual packet sizes to our clients (as in use two packet sizes at the same time depending on message size) ([#3189])
- Experiment with offline signing in our validator client ([#3174])
- Modify network requester binary to reload `allowed.list` periodically to pull in any changes made upstream without having to restart the service ([#3149])
- Standardise all `--output json` on binary inits, we pass the output json at different points for different binaries. ([#3080])
- Service provider directory contract: initial version ([#2759])
- Fix issue where network-requester run failed on fresh init due to missing allow file ([#3316])
[#3250]: https://github.com/nymtech/nym/issues/3250
[#3249]: https://github.com/nymtech/nym/issues/3249
[#3245]: https://github.com/nymtech/nym/issues/3245
[#3234]: https://github.com/nymtech/nym/issues/3234
[#3189]: https://github.com/nymtech/nym/issues/3189
[#3174]: https://github.com/nymtech/nym/issues/3174
[#3149]: https://github.com/nymtech/nym/issues/3149
[#3080]: https://github.com/nymtech/nym/issues/3080
[#2759]: https://github.com/nymtech/nym/issues/2759
[#3316]: https://github.com/nymtech/nym/pull/3316
## [v1.1.14] (2023-04-04)
- Investigate cause of qwerty validator being in invalid rewarding state ([#3224])
- Fix NR config due to changes in #3199 ([#3223])
- [Issue] Mixnodes and gateway do not close connections properly ([#3187])
- disable sign-ext when using wasm-opt + update wasm-opt ([#3203])
- chore: tidy up client `Debug` config section ([#3199])
[#3224]: https://github.com/nymtech/nym/issues/3224
[#3223]: https://github.com/nymtech/nym/issues/3223
[#3187]: https://github.com/nymtech/nym/issues/3187
[#3203]: https://github.com/nymtech/nym/pull/3203
[#3199]: https://github.com/nymtech/nym/pull/3199
>>>>>>> master
## [v1.1.13] (2023-03-15) ## [v1.1.13] (2023-03-15)
- NE - instead of throwing a "Mixnode/Gateway not found" error for blacklisted nodes due to bad performance, show their history but tag them as "Having poor performance" ([#2979]) - NE - instead of throwing a "Mixnode/Gateway not found" error for blacklisted nodes due to bad performance, show their history but tag them as "Having poor performance" ([#2979])
- NE - Upgrade Sandbox and make below changes: ([#2332]) - NE - Upgrade Sandbox and make below changes: ([#2332])
- Explorer - Updates ([#3168]) - Explorer - Updates ([#3168])
- Fix contracts and nym-api audit findings ([#3026])
- Website v2 - deploy infrastructure for strapi and CI ([#2213]) - Website v2 - deploy infrastructure for strapi and CI ([#2213])
- add blockstream green to sp list ([#3180]) - add blockstream green to sp list ([#3180])
- mock-nym-api: fix .storybook lint error ([#3178]) - mock-nym-api: fix .storybook lint error ([#3178])
@@ -65,6 +24,7 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
[#2979]: https://github.com/nymtech/nym/issues/2979 [#2979]: https://github.com/nymtech/nym/issues/2979
[#2332]: https://github.com/nymtech/nym/issues/2332 [#2332]: https://github.com/nymtech/nym/issues/2332
[#3168]: https://github.com/nymtech/nym/issues/3168 [#3168]: https://github.com/nymtech/nym/issues/3168
[#3026]: https://github.com/nymtech/nym/issues/3026
[#2213]: https://github.com/nymtech/nym/issues/2213 [#2213]: https://github.com/nymtech/nym/issues/2213
[#3180]: https://github.com/nymtech/nym/pull/3180 [#3180]: https://github.com/nymtech/nym/pull/3180
[#3178]: https://github.com/nymtech/nym/pull/3178 [#3178]: https://github.com/nymtech/nym/pull/3178
Generated
+326 -587
View File
File diff suppressed because it is too large Load Diff
+1 -3
View File
@@ -21,8 +21,6 @@ members = [
"clients/native", "clients/native",
"clients/native/websocket-requests", "clients/native/websocket-requests",
"clients/socks5", "clients/socks5",
"common/async-file-watcher",
"common/bandwidth-controller",
"common/bin-common", "common/bin-common",
"common/client-core", "common/client-core",
"common/client-libs/gateway-client", "common/client-libs/gateway-client",
@@ -37,8 +35,8 @@ members = [
"common/cosmwasm-smart-contracts/group-contract", "common/cosmwasm-smart-contracts/group-contract",
"common/cosmwasm-smart-contracts/mixnet-contract", "common/cosmwasm-smart-contracts/mixnet-contract",
"common/cosmwasm-smart-contracts/multisig-contract", "common/cosmwasm-smart-contracts/multisig-contract",
"common/cosmwasm-smart-contracts/service-provider-directory",
"common/cosmwasm-smart-contracts/vesting-contract", "common/cosmwasm-smart-contracts/vesting-contract",
"common/mobile-storage",
"common/credential-storage", "common/credential-storage",
"common/credentials", "common/credentials",
"common/crypto", "common/crypto",
+11 -37
View File
@@ -9,10 +9,6 @@ no-clippy: build cargo-test wasm fmt
happy: fmt clippy-happy test happy: fmt clippy-happy test
# Building release binaries is a little manual as we can't just build --release
# on all workspaces.
build-release: build-release-main wasm
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
# Define targets for a given workspace # Define targets for a given workspace
# $(1): name # $(1): name
@@ -27,37 +23,29 @@ clippy-happy-$(1):
clippy-$(1): clippy-$(1):
cargo clippy --manifest-path $(2)/Cargo.toml --workspace $(3) -- -D warnings cargo clippy --manifest-path $(2)/Cargo.toml --workspace $(3) -- -D warnings
clippy-examples-$(1): clippy-$(1)-examples:
cargo clippy --manifest-path $(2)/Cargo.toml --workspace --examples -- -D warnings cargo clippy --manifest-path $(2)/Cargo.toml --workspace --examples -- -D warnings
check-$(1):
cargo check --manifest-path $(2)/Cargo.toml --workspace $(3)
test-$(1): test-$(1):
cargo test --manifest-path $(2)/Cargo.toml --workspace cargo test --manifest-path $(2)/Cargo.toml --workspace
test-expensive-$(1): test-$(1)-expensive:
cargo test --manifest-path $(2)/Cargo.toml --workspace -- --ignored cargo test --manifest-path $(2)/Cargo.toml --workspace -- --ignored
build-$(1): build-$(1):
cargo build --manifest-path $(2)/Cargo.toml --workspace $(3) cargo build --manifest-path $(2)/Cargo.toml --workspace $(3)
build-examples-$(1): build-$(1)-examples:
cargo build --manifest-path $(2)/Cargo.toml --workspace --examples cargo build --manifest-path $(2)/Cargo.toml --workspace --examples
build-release-$(1):
cargo build --manifest-path $(2)/Cargo.toml --workspace --release $(3)
fmt-$(1): fmt-$(1):
cargo fmt --manifest-path $(2)/Cargo.toml --all cargo fmt --manifest-path $(2)/Cargo.toml --all
clippy-happy: clippy-happy-$(1) clippy-happy: clippy-happy-$(1)
clippy-all: clippy-$(1) clippy-examples-$(1) clippy-all: clippy-$(1) clippy-$(1)-examples
check: check-$(1)
cargo-test: test-$(1) cargo-test: test-$(1)
cargo-test-expensive: test-expensive-$(1) cargo-test-expensive: test-$(1)-expensive
build: build-$(1) build-$(1)-examples build: build-$(1) build-$(1)-examples
build-release-all: build-release-$(1)
fmt: fmt-$(1) fmt: fmt-$(1)
endef endef
@@ -73,7 +61,7 @@ $(eval $(call add_cargo_workspace,contracts,contracts,--target wasm32-unknown-un
$(eval $(call add_cargo_workspace,wasm-client,clients/webassembly,--target wasm32-unknown-unknown)) $(eval $(call add_cargo_workspace,wasm-client,clients/webassembly,--target wasm32-unknown-unknown))
$(eval $(call add_cargo_workspace,wallet,nym-wallet,)) $(eval $(call add_cargo_workspace,wallet,nym-wallet,))
$(eval $(call add_cargo_workspace,connect,nym-connect/desktop)) $(eval $(call add_cargo_workspace,connect,nym-connect/desktop))
ifdef NYM_MOBILE ifndef NYM_NO_MOBILE
$(eval $(call add_cargo_workspace,connect-mobile,nym-connect/mobile/src-tauri)) $(eval $(call add_cargo_workspace,connect-mobile,nym-connect/mobile/src-tauri))
endif endif
@@ -87,29 +75,15 @@ build-explorer-api:
build-nym-cli: build-nym-cli:
cargo build -p nym-cli --release cargo build -p nym-cli --release
# -----------------------------------------------------------------------------
# Build contracts ready for deploy
# -----------------------------------------------------------------------------
CONTRACTS_OUT_DIR=contracts/target/wasm32-unknown-unknown/release
VESTING_CONTRACT=$(CONTRACTS_OUT_DIR)/vesting_contract.wasm
MIXNET_CONTRACT=$(CONTRACTS_OUT_DIR)/mixnet_contract.wasm
SERVICE_PROVIDER_DIRECTORY_CONTRACT=$(CONTRACTS_OUT_DIR)/nym_service_provider_directory.wasm
wasm: wasm-build wasm-opt
wasm-build:
RUSTFLAGS='-C link-arg=-s' cargo build --manifest-path contracts/Cargo.toml --release --target wasm32-unknown-unknown
wasm-opt:
wasm-opt --disable-sign-ext -Os $(VESTING_CONTRACT) -o $(VESTING_CONTRACT)
wasm-opt --disable-sign-ext -Os $(MIXNET_CONTRACT) -o $(MIXNET_CONTRACT)
wasm-opt --disable-sign-ext -Os $(SERVICE_PROVIDER_DIRECTORY_CONTRACT) -o $(SERVICE_PROVIDER_DIRECTORY_CONTRACT)
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
# Misc # Misc
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
wasm:
RUSTFLAGS='-C link-arg=-s' cargo build --manifest-path contracts/Cargo.toml --release --target wasm32-unknown-unknown
wasm-opt --disable-sign-ext -Os contracts/target/wasm32-unknown-unknown/release/vesting_contract.wasm -o contracts/target/wasm32-unknown-unknown/release/vesting_contract.wasm
wasm-opt --disable-sign-ext -Os contracts/target/wasm32-unknown-unknown/release/mixnet_contract.wasm -o contracts/target/wasm32-unknown-unknown/release/mixnet_contract.wasm
# NOTE: this seems deprecated an not needed anymore? # NOTE: this seems deprecated an not needed anymore?
mixnet-opt: wasm mixnet-opt: wasm
cd contracts/mixnet && make opt cd contracts/mixnet && make opt
+1 -1
View File
@@ -21,7 +21,7 @@ The platform is composed of multiple Rust crates. Top-level executable binary cr
### Building ### Building
Platform build instructions are available on [our docs site](https://nymtech.net/docs/binaries/building-nym.html). Platform build instructions are available on [our docs site](https://nymtech.net/docs/stable/run-nym-nodes/build-nym).
Wallet build instructions are also available on [our docs site](https://nymtech.net/docs/stable/nym-apps/wallet#for-developers). Wallet build instructions are also available on [our docs site](https://nymtech.net/docs/stable/nym-apps/wallet#for-developers).
### Developing ### Developing
+3 -3
View File
@@ -3,8 +3,8 @@ Critical bug or security issue 💥
If you're here because you're trying to figure out how to notify us of a security issue, go to Discord, and alert the core engineers: If you're here because you're trying to figure out how to notify us of a security issue, go to Discord, and alert the core engineers:
Dave Hrycyszyn futurechimp#5430 Dave Hrycyszyn futurechimp#5430
Drazen Urch drazen#4873
Jedrzej Stuczynski "Jedrzej | Nym#5666" Jedrzej Stuczynski "Jedrzej | Nym#5666"
Fran Arbanas | franarbanas#0995
Mark Sinclair | marknym#8088
Please avoid opening public issues on GitHub that contain information about a potential security vulnerability as this makes it difficult to reduce the impact and harm of valid security issues.
Please avoid opening public issues on GitHub that contain information about a potential security vulnerability as this makes it difficult to reduce the impact and harm of valid security issues.
+8 -4
View File
@@ -1,23 +1,27 @@
[package] [package]
name = "nym-credential-client" name = "credential"
version = "0.1.0" version = "0.1.0"
edition = "2021" edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
bip39 = { workspace = true }
clap = { version = "4.0", features = ["cargo", "derive"] } clap = { version = "4.0", features = ["cargo", "derive"] }
log = "0.4" log = "0.4"
serde = { workspace = true, features = ["derive"] } rand = "0.7.3"
serde = { version = "1.0", features = ["derive"] }
thiserror = "1.0" thiserror = "1.0"
url = "2.2"
tokio = { version = "1.24.1", features = ["rt-multi-thread", "net", "signal", "macros"] } # async runtime tokio = { version = "1.24.1", features = ["rt-multi-thread", "net", "signal", "macros"] } # async runtime
nym-bandwidth-controller = { path = "../../common/bandwidth-controller" } nym-coconut-interface = { path = "../../common/coconut-interface" }
nym-config = { path = "../../common/config" } nym-config = { path = "../../common/config" }
nym-credentials = { path = "../../common/credentials" } nym-credentials = { path = "../../common/credentials" }
nym-credential-storage = { path = "../../common/credential-storage" } nym-credential-storage = { path = "../../common/credential-storage" }
nym-crypto = { path = "../../common/crypto", features = ["rand", "asymmetric", "symmetric", "aes", "hashing"] }
nym-bin-common = { path = "../../common/bin-common"} nym-bin-common = { path = "../../common/bin-common"}
nym-network-defaults = { path = "../../common/network-defaults" } nym-network-defaults = { path = "../../common/network-defaults" }
nym-pemstore = { path = "../../common/pemstore" } nym-pemstore = { path = "../../common/pemstore" }
nym-validator-client = { path = "../../common/client-libs/validator-client", features = ["nyxd-client"] } validator-client = { path = "../../common/client-libs/validator-client", features = ["nyxd-client"] }
+3 -3
View File
@@ -4,11 +4,11 @@
use crate::error::Result; use crate::error::Result;
use bip39::Mnemonic; use bip39::Mnemonic;
use nym_network_defaults::{NymNetworkDetails, VOUCHER_INFO}; use nym_network_defaults::{NymNetworkDetails, VOUCHER_INFO};
use nym_validator_client::nyxd;
use nym_validator_client::nyxd::traits::CoconutBandwidthSigningClient;
use nym_validator_client::nyxd::{Coin, DirectSigningNyxdClient, Fee, NyxdClient};
use std::str::FromStr; use std::str::FromStr;
use url::Url; use url::Url;
use validator_client::nyxd;
use validator_client::nyxd::traits::CoconutBandwidthSigningClient;
use validator_client::nyxd::{Coin, DirectSigningNyxdClient, Fee, NyxdClient};
pub(crate) struct Client { pub(crate) struct Client {
nyxd_client: NyxdClient<DirectSigningNyxdClient>, nyxd_client: NyxdClient<DirectSigningNyxdClient>,
+89 -9
View File
@@ -3,13 +3,24 @@
use clap::{ArgGroup, Args, Subcommand}; use clap::{ArgGroup, Args, Subcommand};
use log::*; use log::*;
use nym_bandwidth_controller::acquire::state::State;
use nym_bin_common::completions::ArgShell; use nym_bin_common::completions::ArgShell;
use nym_credential_storage::persistent_storage::PersistentStorage; use nym_coconut_interface::{Base58, Parameters};
use nym_validator_client::nyxd::traits::DkgQueryClient; use nym_credential_storage::storage::Storage;
use nym_credential_storage::PersistentStorage;
use nym_credentials::coconut::bandwidth::{BandwidthVoucher, TOTAL_ATTRIBUTES};
use nym_credentials::coconut::utils::obtain_aggregate_signature;
use nym_crypto::asymmetric::{encryption, identity};
use nym_network_defaults::VOUCHER_INFO;
use rand::rngs::OsRng;
use std::str::FromStr;
use validator_client::nyxd::traits::DkgQueryClient;
use validator_client::nyxd::tx::Hash;
use validator_client::CoconutApiClient;
use crate::error::Result; use crate::client::Client;
use crate::error::{CredentialClientError, Result};
use crate::recovery_storage::RecoveryStorage; use crate::recovery_storage::RecoveryStorage;
use crate::state::{KeyPair, State};
#[derive(Subcommand)] #[derive(Subcommand)]
pub(crate) enum Command { pub(crate) enum Command {
@@ -34,6 +45,10 @@ pub(crate) struct Run {
#[clap(long)] #[clap(long)]
pub(crate) client_home_directory: std::path::PathBuf, pub(crate) client_home_directory: std::path::PathBuf,
/// The nyxd URL that should be used
#[clap(long)]
pub(crate) nyxd_url: String,
/// A mnemonic for the account that buys the credential /// A mnemonic for the account that buys the credential
#[clap(long)] #[clap(long)]
pub(crate) mnemonic: String, pub(crate) mnemonic: String,
@@ -52,16 +67,81 @@ pub(crate) struct Run {
pub(crate) recovery_mode: bool, pub(crate) recovery_mode: bool,
} }
pub(crate) async fn deposit(nyxd_url: &str, mnemonic: &str, amount: u64) -> Result<State> {
let mut rng = OsRng;
let signing_keypair = KeyPair::from(identity::KeyPair::new(&mut rng));
let encryption_keypair = KeyPair::from(encryption::KeyPair::new(&mut rng));
let params = Parameters::new(TOTAL_ATTRIBUTES).unwrap();
let client = Client::new(nyxd_url, mnemonic);
let tx_hash = client
.deposit(
amount,
signing_keypair.public_key.clone(),
encryption_keypair.public_key.clone(),
None,
)
.await?;
let voucher = BandwidthVoucher::new(
&params,
amount.to_string(),
VOUCHER_INFO.to_string(),
Hash::from_str(&tx_hash).map_err(|_| CredentialClientError::InvalidTxHash)?,
identity::PrivateKey::from_base58_string(&signing_keypair.private_key)?,
encryption::PrivateKey::from_base58_string(&encryption_keypair.private_key)?,
);
let state = State { voucher, params };
Ok(state)
}
pub(crate) async fn get_credential<C: DkgQueryClient + Send + Sync>(
state: &State,
client: &C,
shared_storage: PersistentStorage,
) -> Result<()> {
let epoch_id = client.get_current_epoch().await?.epoch_id;
let threshold = client
.get_current_epoch_threshold()
.await?
.ok_or(CredentialClientError::NoThreshold)?;
let coconut_api_clients = CoconutApiClient::all_coconut_api_clients(client, epoch_id).await?;
let signature = obtain_aggregate_signature(
&state.params,
&state.voucher,
&coconut_api_clients,
threshold,
)
.await?;
info!("Signature: {:?}", signature.to_bs58());
shared_storage
.insert_coconut_credential(
state.voucher.get_voucher_value(),
VOUCHER_INFO.to_string(),
state.voucher.get_private_attributes()[0].to_bs58(),
state.voucher.get_private_attributes()[1].to_bs58(),
signature.to_bs58(),
epoch_id.to_string(),
)
.await?;
Ok(())
}
pub(crate) async fn recover_credentials<C: DkgQueryClient + Send + Sync>( pub(crate) async fn recover_credentials<C: DkgQueryClient + Send + Sync>(
client: &C, client: &C,
recovery_storage: &RecoveryStorage, recovery_storage: &RecoveryStorage,
shared_storage: &PersistentStorage, shared_storage: PersistentStorage,
) -> Result<()> { ) -> Result<()> {
for voucher in recovery_storage.unconsumed_vouchers()? { for voucher in recovery_storage.unconsumed_vouchers()? {
let state = State::new(voucher); let state = State {
if let Err(e) = voucher,
nym_bandwidth_controller::acquire::get_credential(&state, client, shared_storage).await params: Parameters::new(TOTAL_ATTRIBUTES).unwrap(),
{ };
if let Err(e) = get_credential(&state, client, shared_storage.clone()).await {
error!( error!(
"Could not recover deposit {} due to {:?}, try again later", "Could not recover deposit {} due to {:?}, try again later",
state.voucher.tx_hash(), state.voucher.tx_hash(),
+16 -5
View File
@@ -6,8 +6,10 @@ use thiserror::Error;
use nym_credential_storage::error::StorageError; use nym_credential_storage::error::StorageError;
use nym_credentials::error::Error as CredentialError; use nym_credentials::error::Error as CredentialError;
use nym_validator_client::nyxd::error::NyxdError; use nym_crypto::asymmetric::encryption::KeyRecoveryError;
use nym_validator_client::ValidatorClientError; use nym_crypto::asymmetric::identity::Ed25519RecoveryError;
use validator_client::nyxd::error::NyxdError;
use validator_client::ValidatorClientError;
pub type Result<T> = std::result::Result<T, CredentialClientError>; pub type Result<T> = std::result::Result<T, CredentialClientError>;
@@ -16,9 +18,6 @@ pub enum CredentialClientError {
#[error("IO error: {0}")] #[error("IO error: {0}")]
IOError(#[from] std::io::Error), IOError(#[from] std::io::Error),
#[error("Bandwidth controller error: {0}")]
BandwidthControllerError(#[from] nym_bandwidth_controller::error::BandwidthControllerError),
#[error("Nyxd error: {0}")] #[error("Nyxd error: {0}")]
Nyxd(#[from] NyxdError), Nyxd(#[from] NyxdError),
@@ -28,9 +27,21 @@ pub enum CredentialClientError {
#[error("Credential error: {0}")] #[error("Credential error: {0}")]
Credential(#[from] CredentialError), Credential(#[from] CredentialError),
#[error("The tx hash provided is not valid")]
InvalidTxHash,
#[error("Could not parse Ed25519 data")]
Ed25519ParseError(#[from] Ed25519RecoveryError),
#[error("Could not parse X25519 data")]
X25519ParseError(#[from] KeyRecoveryError),
#[error("Could not use shared storage")] #[error("Could not use shared storage")]
SharedStorageError(#[from] StorageError), SharedStorageError(#[from] StorageError),
#[error("Could not get system time")] #[error("Could not get system time")]
SysTimeError(#[from] SystemTimeError), SysTimeError(#[from] SystemTimeError),
#[error("Threshold not set yet")]
NoThreshold,
} }
+17 -28
View File
@@ -1,9 +1,11 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net> // Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
mod client;
mod commands; mod commands;
mod error; mod error;
mod recovery_storage; mod recovery_storage;
mod state;
use commands::*; use commands::*;
use error::Result; use error::Result;
@@ -16,9 +18,9 @@ use std::time::{Duration, SystemTime};
use clap::{CommandFactory, Parser}; use clap::{CommandFactory, Parser};
use nym_bin_common::logging::setup_logging; use nym_bin_common::logging::setup_logging;
use nym_validator_client::nyxd::traits::DkgQueryClient; use validator_client::nyxd::traits::DkgQueryClient;
use nym_validator_client::nyxd::{Coin, CosmWasmClient}; use validator_client::nyxd::CosmWasmClient;
use nym_validator_client::Config; use validator_client::Config;
const SAFETY_BUFFER_SECS: u64 = 60; // 1 minute const SAFETY_BUFFER_SECS: u64 = 60; // 1 minute
@@ -33,8 +35,8 @@ struct Cli {
pub(crate) command: Command, pub(crate) command: Command,
} }
async fn block_until_coconut_is_available<C: CosmWasmClient + Send + Sync>( async fn block_until_coconut_is_available<C: Clone + CosmWasmClient + Send + Sync>(
client: &nym_validator_client::Client<C>, client: &validator_client::Client<C>,
) -> Result<()> { ) -> Result<()> {
loop { loop {
let epoch = client.nyxd.get_current_epoch().await?; let epoch = client.nyxd.get_current_epoch().await?;
@@ -75,34 +77,21 @@ async fn main() -> Result<()> {
.client_home_directory .client_home_directory
.join(DATA_DIR) .join(DATA_DIR)
.join(CRED_DB_FILE_NAME); .join(CRED_DB_FILE_NAME);
let shared_storage = let shared_storage = nym_credential_storage::initialise_storage(db_path).await;
nym_credential_storage::initialise_persistent_storage(db_path).await;
let recovery_storage = recovery_storage::RecoveryStorage::new(r.recovery_dir)?; let recovery_storage = recovery_storage::RecoveryStorage::new(r.recovery_dir)?;
let network_details = NymNetworkDetails::new_from_env(); let network_details = NymNetworkDetails::new_from_env();
let config = Config::try_from_nym_network_details(&network_details).expect( let config = Config::try_from_nym_network_details(&network_details)?;
"failed to construct valid validator client config with the provided network", let client = validator_client::Client::new_query(config)?;
);
let amount = Coin::new(
r.amount as u128,
network_details.chain_details.mix_denom.base,
);
let client =
nym_validator_client::Client::new_signing(config, r.mnemonic.parse().unwrap())?;
block_until_coconut_is_available(&client).await?; block_until_coconut_is_available(&client).await?;
info!("Starting depositing funds, don't kill the process"); info!("Starting depositing funds, don't kill the process");
if !r.recovery_mode { if !r.recovery_mode {
let state = let state = deposit(&r.nyxd_url, &r.mnemonic, r.amount).await?;
nym_bandwidth_controller::acquire::deposit(&client.nyxd, amount).await?; if get_credential(&state, &client.nyxd, shared_storage)
if nym_bandwidth_controller::acquire::get_credential( .await
&state, .is_err()
&client,
&shared_storage,
)
.await
.is_err()
{ {
warn!("Failed to obtain credential. Dumping recovery data.",); warn!("Failed to obtain credential. Dumping recovery data.",);
match recovery_storage.insert_voucher(&state.voucher) { match recovery_storage.insert_voucher(&state.voucher) {
@@ -115,11 +104,11 @@ async fn main() -> Result<()> {
} }
} }
} else { } else {
recover_credentials(&client.nyxd, &recovery_storage, &shared_storage).await?; recover_credentials(&client.nyxd, &recovery_storage, shared_storage).await?;
} }
} }
Command::Completions(c) => c.generate(&mut Cli::command(), bin_name), Command::Completions(c) => c.generate(&mut crate::Cli::command(), bin_name),
Command::GenerateFigSpec => fig_generate(&mut Cli::command(), bin_name), Command::GenerateFigSpec => fig_generate(&mut crate::Cli::command(), bin_name),
} }
Ok(()) Ok(())
@@ -1,8 +1,8 @@
// Copyright 2022-2023 - Nym Technologies SA <contact@nymtech.net> // Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use nym_coconut_interface::Parameters; use nym_coconut_interface::Parameters;
use nym_credentials::coconut::bandwidth::{BandwidthVoucher, TOTAL_ATTRIBUTES}; use nym_credentials::coconut::bandwidth::BandwidthVoucher;
use nym_crypto::asymmetric::{encryption, identity}; use nym_crypto::asymmetric::{encryption, identity};
@@ -29,16 +29,7 @@ impl From<encryption::KeyPair> for KeyPair {
} }
} }
pub struct State { pub(crate) struct State {
pub voucher: BandwidthVoucher, pub voucher: BandwidthVoucher,
pub params: Parameters, pub params: Parameters,
} }
impl State {
pub fn new(voucher: BandwidthVoucher) -> Self {
State {
voucher,
params: Parameters::new(TOTAL_ATTRIBUTES).unwrap(),
}
}
}
+10 -9
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "nym-client" name = "nym-client"
version = "1.1.15" version = "1.1.13"
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,29 +26,30 @@ lazy_static = "1.4.0"
log = { workspace = true } # self explanatory log = { workspace = true } # self explanatory
pretty_env_logger = "0.4" # for formatting log messages pretty_env_logger = "0.4" # for formatting log messages
rand = { version = "0.7.3", features = ["wasm-bindgen"] } # rng-related traits + some rng implementation to use rand = { version = "0.7.3", features = ["wasm-bindgen"] } # rng-related traits + some rng implementation to use
serde = { workspace = true, features = ["derive"] } # for config serialization/deserialization serde = { version = "1.0.104", features = ["derive"] } # for config serialization/deserialization
serde_json = { workspace = true } serde_json = "1.0"
thiserror = "1.0.34" thiserror = "1.0.34"
tap = "1.0.1" tap = "1.0.1"
tokio = { version = "1.24.1", features = ["rt-multi-thread", "net", "signal"] } # async runtime tokio = { version = "1.24.1", features = ["rt-multi-thread", "net", "signal"] } # async runtime
tokio-tungstenite = "0.14" # websocket tokio-tungstenite = "0.14" # websocket
## internal ## internal
nym-bandwidth-controller = { path = "../../common/bandwidth-controller" } nym-bin-common = { path = "../../common/bin-common" }
nym-bin-common = { path = "../../common/bin-common", features = ["output_format"] } client-core = { path = "../../common/client-core", features = ["fs-surb-storage"] }
nym-client-core = { path = "../../common/client-core", features = ["fs-surb-storage"] }
nym-coconut-interface = { path = "../../common/coconut-interface" } nym-coconut-interface = { path = "../../common/coconut-interface" }
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 = "../../gateway/gateway-requests" } gateway-client = { path = "../../common/client-libs/gateway-client" }
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 = ["nyxd-client"] } validator-client = { path = "../../common/client-libs/validator-client", features = ["nyxd-client"] }
nym-client-websocket-requests = { path = "websocket-requests" } websocket-requests = { path = "websocket-requests" }
[dev-dependencies] [dev-dependencies]
serde_json = "1.0" # for the "textsend" example
@@ -13,7 +13,7 @@
}, },
"devDependencies": { "devDependencies": {
"clean-webpack-plugin": "^4.0.0", "clean-webpack-plugin": "^4.0.0",
"webpack": "^5.76.0", "webpack": "^5.70.0",
"webpack-cli": "^4.9.2", "webpack-cli": "^4.9.2",
"webpack-dev-server": "^4.7.4" "webpack-dev-server": "^4.7.4"
} }
@@ -490,9 +490,9 @@
} }
}, },
"node_modules/acorn": { "node_modules/acorn": {
"version": "8.8.2", "version": "8.7.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz",
"integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==",
"bin": { "bin": {
"acorn": "bin/acorn" "acorn": "bin/acorn"
}, },
@@ -1327,9 +1327,9 @@
} }
}, },
"node_modules/enhanced-resolve": { "node_modules/enhanced-resolve": {
"version": "5.12.0", "version": "5.9.2",
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.9.2.tgz",
"integrity": "sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ==", "integrity": "sha512-GIm3fQfwLJ8YZx2smuHpBKkXC1yOk+OBEmKckVyL0i/ea8mqDEykK3ld5dgH1QYPNyT/lIllxV2LULnxCHaHkA==",
"dependencies": { "dependencies": {
"graceful-fs": "^4.2.4", "graceful-fs": "^4.2.4",
"tapable": "^2.2.0" "tapable": "^2.2.0"
@@ -2380,10 +2380,10 @@
"node": ">= 10.13.0" "node": ">= 10.13.0"
} }
}, },
"node_modules/json-parse-even-better-errors": { "node_modules/json-parse-better-errors": {
"version": "2.3.1", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz",
"integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw=="
}, },
"node_modules/json-schema-traverse": { "node_modules/json-schema-traverse": {
"version": "0.4.1", "version": "0.4.1",
@@ -3824,9 +3824,9 @@
} }
}, },
"node_modules/watchpack": { "node_modules/watchpack": {
"version": "2.4.0", "version": "2.3.1",
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.3.1.tgz",
"integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", "integrity": "sha512-x0t0JuydIo8qCNctdDrn1OzH/qDzk2+rdCOC3YzumZ42fiMqmQ7T3xQurykYMhYfHaPHTp4ZxAx2NfUo1K6QaA==",
"dependencies": { "dependencies": {
"glob-to-regexp": "^0.4.1", "glob-to-regexp": "^0.4.1",
"graceful-fs": "^4.1.2" "graceful-fs": "^4.1.2"
@@ -3845,33 +3845,33 @@
} }
}, },
"node_modules/webpack": { "node_modules/webpack": {
"version": "5.76.0", "version": "5.70.0",
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.76.0.tgz", "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.70.0.tgz",
"integrity": "sha512-l5sOdYBDunyf72HW8dF23rFtWq/7Zgvt/9ftMof71E/yUb1YLOBmTgA2K4vQthB3kotMrSj609txVE0dnr2fjA==", "integrity": "sha512-ZMWWy8CeuTTjCxbeaQI21xSswseF2oNOwc70QSKNePvmxE7XW36i7vpBMYZFAUHPwQiEbNGCEYIOOlyRbdGmxw==",
"dependencies": { "dependencies": {
"@types/eslint-scope": "^3.7.3", "@types/eslint-scope": "^3.7.3",
"@types/estree": "^0.0.51", "@types/estree": "^0.0.51",
"@webassemblyjs/ast": "1.11.1", "@webassemblyjs/ast": "1.11.1",
"@webassemblyjs/wasm-edit": "1.11.1", "@webassemblyjs/wasm-edit": "1.11.1",
"@webassemblyjs/wasm-parser": "1.11.1", "@webassemblyjs/wasm-parser": "1.11.1",
"acorn": "^8.7.1", "acorn": "^8.4.1",
"acorn-import-assertions": "^1.7.6", "acorn-import-assertions": "^1.7.6",
"browserslist": "^4.14.5", "browserslist": "^4.14.5",
"chrome-trace-event": "^1.0.2", "chrome-trace-event": "^1.0.2",
"enhanced-resolve": "^5.10.0", "enhanced-resolve": "^5.9.2",
"es-module-lexer": "^0.9.0", "es-module-lexer": "^0.9.0",
"eslint-scope": "5.1.1", "eslint-scope": "5.1.1",
"events": "^3.2.0", "events": "^3.2.0",
"glob-to-regexp": "^0.4.1", "glob-to-regexp": "^0.4.1",
"graceful-fs": "^4.2.9", "graceful-fs": "^4.2.9",
"json-parse-even-better-errors": "^2.3.1", "json-parse-better-errors": "^1.0.2",
"loader-runner": "^4.2.0", "loader-runner": "^4.2.0",
"mime-types": "^2.1.27", "mime-types": "^2.1.27",
"neo-async": "^2.6.2", "neo-async": "^2.6.2",
"schema-utils": "^3.1.0", "schema-utils": "^3.1.0",
"tapable": "^2.1.1", "tapable": "^2.1.1",
"terser-webpack-plugin": "^5.1.3", "terser-webpack-plugin": "^5.1.3",
"watchpack": "^2.4.0", "watchpack": "^2.3.1",
"webpack-sources": "^3.2.3" "webpack-sources": "^3.2.3"
}, },
"bin": { "bin": {
@@ -4894,9 +4894,9 @@
} }
}, },
"acorn": { "acorn": {
"version": "8.8.2", "version": "8.7.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz",
"integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==" "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ=="
}, },
"acorn-import-assertions": { "acorn-import-assertions": {
"version": "1.8.0", "version": "1.8.0",
@@ -5527,9 +5527,9 @@
"dev": true "dev": true
}, },
"enhanced-resolve": { "enhanced-resolve": {
"version": "5.12.0", "version": "5.9.2",
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.9.2.tgz",
"integrity": "sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ==", "integrity": "sha512-GIm3fQfwLJ8YZx2smuHpBKkXC1yOk+OBEmKckVyL0i/ea8mqDEykK3ld5dgH1QYPNyT/lIllxV2LULnxCHaHkA==",
"requires": { "requires": {
"graceful-fs": "^4.2.4", "graceful-fs": "^4.2.4",
"tapable": "^2.2.0" "tapable": "^2.2.0"
@@ -6305,10 +6305,10 @@
"supports-color": "^8.0.0" "supports-color": "^8.0.0"
} }
}, },
"json-parse-even-better-errors": { "json-parse-better-errors": {
"version": "2.3.1", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz",
"integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw=="
}, },
"json-schema-traverse": { "json-schema-traverse": {
"version": "0.4.1", "version": "0.4.1",
@@ -7396,9 +7396,9 @@
"dev": true "dev": true
}, },
"watchpack": { "watchpack": {
"version": "2.4.0", "version": "2.3.1",
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.3.1.tgz",
"integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", "integrity": "sha512-x0t0JuydIo8qCNctdDrn1OzH/qDzk2+rdCOC3YzumZ42fiMqmQ7T3xQurykYMhYfHaPHTp4ZxAx2NfUo1K6QaA==",
"requires": { "requires": {
"glob-to-regexp": "^0.4.1", "glob-to-regexp": "^0.4.1",
"graceful-fs": "^4.1.2" "graceful-fs": "^4.1.2"
@@ -7414,33 +7414,33 @@
} }
}, },
"webpack": { "webpack": {
"version": "5.76.0", "version": "5.70.0",
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.76.0.tgz", "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.70.0.tgz",
"integrity": "sha512-l5sOdYBDunyf72HW8dF23rFtWq/7Zgvt/9ftMof71E/yUb1YLOBmTgA2K4vQthB3kotMrSj609txVE0dnr2fjA==", "integrity": "sha512-ZMWWy8CeuTTjCxbeaQI21xSswseF2oNOwc70QSKNePvmxE7XW36i7vpBMYZFAUHPwQiEbNGCEYIOOlyRbdGmxw==",
"requires": { "requires": {
"@types/eslint-scope": "^3.7.3", "@types/eslint-scope": "^3.7.3",
"@types/estree": "^0.0.51", "@types/estree": "^0.0.51",
"@webassemblyjs/ast": "1.11.1", "@webassemblyjs/ast": "1.11.1",
"@webassemblyjs/wasm-edit": "1.11.1", "@webassemblyjs/wasm-edit": "1.11.1",
"@webassemblyjs/wasm-parser": "1.11.1", "@webassemblyjs/wasm-parser": "1.11.1",
"acorn": "^8.7.1", "acorn": "^8.4.1",
"acorn-import-assertions": "^1.7.6", "acorn-import-assertions": "^1.7.6",
"browserslist": "^4.14.5", "browserslist": "^4.14.5",
"chrome-trace-event": "^1.0.2", "chrome-trace-event": "^1.0.2",
"enhanced-resolve": "^5.10.0", "enhanced-resolve": "^5.9.2",
"es-module-lexer": "^0.9.0", "es-module-lexer": "^0.9.0",
"eslint-scope": "5.1.1", "eslint-scope": "5.1.1",
"events": "^3.2.0", "events": "^3.2.0",
"glob-to-regexp": "^0.4.1", "glob-to-regexp": "^0.4.1",
"graceful-fs": "^4.2.9", "graceful-fs": "^4.2.9",
"json-parse-even-better-errors": "^2.3.1", "json-parse-better-errors": "^1.0.2",
"loader-runner": "^4.2.0", "loader-runner": "^4.2.0",
"mime-types": "^2.1.27", "mime-types": "^2.1.27",
"neo-async": "^2.6.2", "neo-async": "^2.6.2",
"schema-utils": "^3.1.0", "schema-utils": "^3.1.0",
"tapable": "^2.1.1", "tapable": "^2.1.1",
"terser-webpack-plugin": "^5.1.3", "terser-webpack-plugin": "^5.1.3",
"watchpack": "^2.4.0", "watchpack": "^2.3.1",
"webpack-sources": "^3.2.3" "webpack-sources": "^3.2.3"
} }
}, },
@@ -19,7 +19,7 @@
"license": "Apache-2.0", "license": "Apache-2.0",
"devDependencies": { "devDependencies": {
"clean-webpack-plugin": "^4.0.0", "clean-webpack-plugin": "^4.0.0",
"webpack": "^5.76.0", "webpack": "^5.70.0",
"webpack-cli": "^4.9.2", "webpack-cli": "^4.9.2",
"webpack-dev-server": "^4.7.4" "webpack-dev-server": "^4.7.4"
}, },
@@ -1,10 +1,10 @@
use futures::{SinkExt, StreamExt}; use futures::{SinkExt, StreamExt};
use nym_client_websocket_requests::{requests::ClientRequest, responses::ServerResponse};
use nym_sphinx::addressing::clients::Recipient; use nym_sphinx::addressing::clients::Recipient;
use tokio::net::TcpStream; use tokio::net::TcpStream;
use tokio_tungstenite::{ use tokio_tungstenite::{
connect_async, tungstenite::protocol::Message, MaybeTlsStream, WebSocketStream, connect_async, tungstenite::protocol::Message, MaybeTlsStream, WebSocketStream,
}; };
use websocket_requests::{requests::ClientRequest, responses::ServerResponse};
// just helpers functions that work in this very particular context because we are sending to ourselves // just helpers functions that work in this very particular context because we are sending to ourselves
// and hence will always get a response back (i.e. the message we sent) // and hence will always get a response back (i.e. the message we sent)
+5 -10
View File
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use crate::client::config::template::config_template; use crate::client::config::template::config_template;
use nym_client_core::config::ClientCoreConfigTrait; use client_core::config::ClientCoreConfigTrait;
use nym_config::defaults::DEFAULT_WEBSOCKET_LISTENING_PORT; use nym_config::defaults::DEFAULT_WEBSOCKET_LISTENING_PORT;
use nym_config::{NymConfig, OptionalSet}; use nym_config::{NymConfig, OptionalSet};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@@ -11,9 +11,9 @@ use std::net::{IpAddr, Ipv4Addr};
use std::path::PathBuf; use std::path::PathBuf;
use std::str::FromStr; use std::str::FromStr;
pub use nym_client_core::config::Config as BaseConfig; pub use client_core::config::Config as BaseConfig;
pub use nym_client_core::config::MISSING_VALUE; pub use client_core::config::MISSING_VALUE;
pub use nym_client_core::config::{DebugConfig, GatewayEndpointConfig}; pub use client_core::config::{DebugConfig, GatewayEndpointConfig};
pub mod old_config_v1_1_13; pub mod old_config_v1_1_13;
mod template; mod template;
@@ -81,7 +81,7 @@ impl NymConfig for Config {
} }
impl ClientCoreConfigTrait for Config { impl ClientCoreConfigTrait for Config {
fn get_gateway_endpoint(&self) -> &nym_client_core::config::GatewayEndpointConfig { fn get_gateway_endpoint(&self) -> &client_core::config::GatewayEndpointConfig {
self.base.get_gateway_endpoint() self.base.get_gateway_endpoint()
} }
} }
@@ -94,11 +94,6 @@ impl Config {
} }
} }
pub fn validate(&self) -> bool {
// no other sections have explicit requirements (yet)
self.base.validate()
}
pub fn with_socket(mut self, socket_type: SocketType) -> Self { pub fn with_socket(mut self, socket_type: SocketType) -> Self {
self.socket.socket_type = socket_type; self.socket.socket_type = socket_type;
self self
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use crate::client::config::{Config, Socket}; use crate::client::config::{Config, Socket};
use nym_client_core::config::old_config_v1_1_13::OldConfigV1_1_13 as OldBaseConfigV1_1_13; use client_core::config::old_config_v1_1_13::OldConfigV1_1_13 as OldBaseConfigV1_1_13;
use nym_config::NymConfig; use nym_config::NymConfig;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::path::PathBuf; use std::path::PathBuf;
+15 -20
View File
@@ -4,29 +4,28 @@
use crate::client::config::Config; use crate::client::config::Config;
use crate::error::ClientError; use crate::error::ClientError;
use crate::websocket; use crate::websocket;
use futures::channel::mpsc; use client_core::client::base_client::{
use log::*;
use nym_bandwidth_controller::BandwidthController;
use nym_client_core::client::base_client::{
non_wasm_helpers, BaseClientBuilder, ClientInput, ClientOutput, ClientState, non_wasm_helpers, BaseClientBuilder, ClientInput, ClientOutput, ClientState,
}; };
use nym_client_core::client::inbound_messages::InputMessage; use client_core::client::inbound_messages::InputMessage;
use nym_client_core::client::received_buffer::{ use client_core::client::received_buffer::{
ReceivedBufferMessage, ReceivedBufferRequestSender, ReconstructedMessagesReceiver, ReceivedBufferMessage, ReceivedBufferRequestSender, ReconstructedMessagesReceiver,
}; };
use nym_client_core::config::persistence::key_pathfinder::ClientKeyPathfinder; use client_core::config::persistence::key_pathfinder::ClientKeyPathfinder;
use futures::channel::mpsc;
use gateway_client::bandwidth::BandwidthController;
use log::*;
use nym_sphinx::anonymous_replies::requests::AnonymousSenderTag; use nym_sphinx::anonymous_replies::requests::AnonymousSenderTag;
use nym_task::connections::TransmissionLane; use nym_task::connections::TransmissionLane;
use nym_task::TaskManager; use nym_task::TaskManager;
use nym_validator_client::nyxd::QueryNyxdClient;
use std::error::Error; use std::error::Error;
use tokio::sync::watch::error::SendError; use tokio::sync::watch::error::SendError;
use validator_client::nyxd::QueryNyxdClient;
pub use nym_client_core::client::key_manager::KeyManager; pub use client_core::client::key_manager::KeyManager;
use nym_credential_storage::persistent_storage::PersistentStorage;
pub use nym_sphinx::addressing::clients::Recipient; pub use nym_sphinx::addressing::clients::Recipient;
pub use nym_sphinx::receiver::ReconstructedMessage; pub use nym_sphinx::receiver::ReconstructedMessage;
use nym_validator_client::Client; use validator_client::Client;
pub mod config; pub mod config;
@@ -59,11 +58,10 @@ impl SocketClient {
async fn create_bandwidth_controller( async fn create_bandwidth_controller(
config: &Config, config: &Config,
) -> BandwidthController<Client<QueryNyxdClient>, PersistentStorage> { ) -> BandwidthController<Client<QueryNyxdClient>> {
let details = nym_network_defaults::NymNetworkDetails::new_from_env(); let details = nym_network_defaults::NymNetworkDetails::new_from_env();
let mut client_config = let mut client_config = validator_client::Config::try_from_nym_network_details(&details)
nym_validator_client::Config::try_from_nym_network_details(&details) .expect("failed to construct validator client config");
.expect("failed to construct validator client config");
let nyxd_url = config let nyxd_url = config
.get_base() .get_base()
.get_validator_endpoints() .get_validator_endpoints()
@@ -76,13 +74,10 @@ impl SocketClient {
.expect("No validator api endpoint provided"); .expect("No validator api endpoint provided");
// overwrite env configuration with config URLs // overwrite env configuration with config URLs
client_config = client_config.with_urls(nyxd_url, api_url); client_config = client_config.with_urls(nyxd_url, api_url);
let client = nym_validator_client::Client::new_query(client_config) let client = validator_client::Client::new_query(client_config)
.expect("Could not construct query client"); .expect("Could not construct query client");
BandwidthController::new( BandwidthController::new(
nym_credential_storage::initialise_persistent_storage( nym_credential_storage::initialise_storage(config.get_base().get_database_path()).await,
config.get_base().get_database_path(),
)
.await,
client, client,
) )
} }
+21 -19
View File
@@ -8,9 +8,7 @@ use crate::{
error::ClientError, error::ClientError,
}; };
use clap::Args; use clap::Args;
use nym_bin_common::output_format::OutputFormat;
use nym_config::NymConfig; use nym_config::NymConfig;
use nym_credential_storage::persistent_storage::PersistentStorage;
use nym_crypto::asymmetric::identity; use nym_crypto::asymmetric::identity;
use nym_sphinx::addressing::clients::Recipient; use nym_sphinx::addressing::clients::Recipient;
use serde::Serialize; use serde::Serialize;
@@ -73,8 +71,9 @@ pub(crate) struct Init {
#[clap(long, hide = true)] #[clap(long, hide = true)]
enabled_credentials_mode: Option<bool>, enabled_credentials_mode: Option<bool>,
#[clap(short, long, default_value_t = OutputFormat::default())] /// Save a summary of the initialization to a json file
output: OutputFormat, #[clap(long)]
output_json: bool,
} }
impl From<Init> for OverrideConfig { impl From<Init> for OverrideConfig {
@@ -96,17 +95,15 @@ impl From<Init> for OverrideConfig {
#[derive(Debug, Serialize)] #[derive(Debug, Serialize)]
pub struct InitResults { pub struct InitResults {
#[serde(flatten)] #[serde(flatten)]
client_core: nym_client_core::init::InitResults, client_core: client_core::init::InitResults,
client_listening_port: String, client_listening_port: String,
client_address: String,
} }
impl InitResults { impl InitResults {
fn new(config: &Config, address: &Recipient) -> Self { fn new(config: &Config, address: &Recipient) -> Self {
Self { Self {
client_core: nym_client_core::init::InitResults::new(config.get_base(), address), client_core: client_core::init::InitResults::new(config.get_base(), address),
client_listening_port: config.get_listening_port().to_string(), client_listening_port: config.get_listening_port().to_string(),
client_address: address.to_string(),
} }
} }
} }
@@ -114,13 +111,12 @@ impl InitResults {
impl Display for InitResults { impl Display for InitResults {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
writeln!(f, "{}", self.client_core)?; writeln!(f, "{}", self.client_core)?;
writeln!(f, "Client listening port: {}", self.client_listening_port)?; write!(f, "Client listening port: {}", self.client_listening_port)
write!(f, "Address of this client: {}", self.client_address)
} }
} }
pub(crate) async fn execute(args: &Init) -> Result<(), ClientError> { pub(crate) async fn execute(args: &Init) -> Result<(), ClientError> {
eprintln!("Initialising client..."); println!("Initialising client...");
let id = &args.id; let id = &args.id;
@@ -129,14 +125,14 @@ pub(crate) async fn execute(args: &Init) -> Result<(), ClientError> {
// in case we're using old config, try to upgrade it // in case we're using old config, try to upgrade it
// (if we're using the current version, it's a no-op) // (if we're using the current version, it's a no-op)
try_upgrade_v1_1_13_config(id)?; try_upgrade_v1_1_13_config(id)?;
eprintln!("Client \"{id}\" was already initialised before"); println!("Client \"{id}\" was already initialised before");
} }
// Usually you only register with the gateway on the first init, however you can force // Usually you only register with the gateway on the first init, however you can force
// re-registering if wanted. // re-registering if wanted.
let user_wants_force_register = args.force_register_gateway; let user_wants_force_register = args.force_register_gateway;
if user_wants_force_register { if user_wants_force_register {
eprintln!("Instructed to force registering gateway. This might overwrite keys!"); println!("Instructed to force registering gateway. This might overwrite keys!");
} }
// If the client was already initialized, don't generate new keys and don't re-register with // If the client was already initialized, don't generate new keys and don't re-register with
@@ -152,7 +148,7 @@ pub(crate) async fn execute(args: &Init) -> Result<(), ClientError> {
// Setup gateway by either registering a new one, or creating a new config from the selected // Setup gateway by either registering a new one, or creating a new config from the selected
// one but with keys kept, or reusing the gateway configuration. // one but with keys kept, or reusing the gateway configuration.
let gateway = nym_client_core::init::setup_gateway_from_config::<Config, _, PersistentStorage>( let gateway = client_core::init::setup_gateway_from_config::<Config, _>(
register_gateway, register_gateway,
user_chosen_gateway_id, user_chosen_gateway_id,
config.get_base(), config.get_base(),
@@ -169,22 +165,28 @@ pub(crate) async fn execute(args: &Init) -> Result<(), ClientError> {
print_saved_config(&config); print_saved_config(&config);
let address = nym_client_core::init::get_client_address_from_stored_keys(config.get_base())?; let address = client_core::init::get_client_address_from_stored_keys(config.get_base())?;
let init_results = InitResults::new(&config, &address); let init_results = InitResults::new(&config, &address);
println!("{}", args.output.format(&init_results)); println!("{init_results}");
// Output summary to a json file, if specified
if args.output_json {
client_core::init::output_to_json(&init_results, "client_init_results.json");
}
println!("\nThe address of this client is: {address}\n");
Ok(()) Ok(())
} }
fn print_saved_config(config: &Config) { fn print_saved_config(config: &Config) {
let config_save_location = config.get_config_file_save_location(); let config_save_location = config.get_config_file_save_location();
eprintln!("Saved configuration file to {config_save_location:?}"); println!("Saved configuration file to {config_save_location:?}");
eprintln!("Using gateway: {}", config.get_base().get_gateway_id()); println!("Using gateway: {}", config.get_base().get_gateway_id());
log::debug!("Gateway id: {}", config.get_base().get_gateway_id()); log::debug!("Gateway id: {}", config.get_base().get_gateway_id());
log::debug!("Gateway owner: {}", config.get_base().get_gateway_owner()); log::debug!("Gateway owner: {}", config.get_base().get_gateway_owner());
log::debug!( log::debug!(
"Gateway listener: {}", "Gateway listener: {}",
config.get_base().get_gateway_listener() config.get_base().get_gateway_listener()
); );
eprintln!("Client configuration completed.\n"); println!("Client configuration completed.\n");
} }
-4
View File
@@ -112,10 +112,6 @@ pub(crate) async fn execute(args: &Run) -> Result<(), Box<dyn Error + Send + Syn
} }
}; };
if !config.validate() {
return Err(Box::new(ClientError::ConfigValidationFailure));
}
let override_config_fields = OverrideConfig::from(args.clone()); let override_config_fields = OverrideConfig::from(args.clone());
config = override_config(config, override_config_fields); config = override_config(config, override_config_fields);
+1 -5
View File
@@ -1,4 +1,4 @@
use nym_client_core::error::ClientCoreError; use client_core::error::ClientCoreError;
#[derive(thiserror::Error, Debug)] #[derive(thiserror::Error, Debug)]
pub enum ClientError { pub enum ClientError {
@@ -11,10 +11,6 @@ pub enum ClientError {
#[error("Failed to load config for: {0}")] #[error("Failed to load config for: {0}")]
FailedToLoadConfig(String), FailedToLoadConfig(String),
// TODO: add more details here
#[error("Failed to validate the loaded config")]
ConfigValidationFailure,
#[error("Failed local version check, client and config mismatch")] #[error("Failed local version check, client and config mismatch")]
FailedLocalVersionCheck, FailedLocalVersionCheck,
+2 -2
View File
@@ -4,7 +4,7 @@
use std::error::Error; use std::error::Error;
use clap::{crate_name, crate_version, Parser}; use clap::{crate_name, crate_version, Parser};
use nym_bin_common::logging::{maybe_print_banner, setup_logging}; use nym_bin_common::logging::{banner, setup_logging};
use nym_network_defaults::setup_env; use nym_network_defaults::setup_env;
pub mod client; pub mod client;
@@ -15,7 +15,7 @@ pub mod websocket;
#[tokio::main] #[tokio::main]
async fn main() -> Result<(), Box<dyn Error + Send + Sync>> { async fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
setup_logging(); setup_logging();
maybe_print_banner(crate_name!(), crate_version!()); println!("{}", banner(crate_name!(), crate_version!()));
let args = commands::Cli::parse(); let args = commands::Cli::parse();
setup_env(args.config_env_file.as_ref()); setup_env(args.config_env_file.as_ref());
+6 -6
View File
@@ -1,17 +1,16 @@
// 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 futures::channel::mpsc; use client_core::client::replies::reply_controller::requests::ReplyControllerSender;
use futures::{SinkExt, StreamExt}; use client_core::client::{
use log::*;
use nym_client_core::client::replies::reply_controller::requests::ReplyControllerSender;
use nym_client_core::client::{
inbound_messages::{InputMessage, InputMessageSender}, inbound_messages::{InputMessage, InputMessageSender},
received_buffer::{ received_buffer::{
ReceivedBufferMessage, ReceivedBufferRequestSender, ReconstructedMessagesReceiver, ReceivedBufferMessage, ReceivedBufferRequestSender, ReconstructedMessagesReceiver,
}, },
}; };
use nym_client_websocket_requests::{requests::ClientRequest, responses::ServerResponse}; use futures::channel::mpsc;
use futures::{SinkExt, StreamExt};
use log::*;
use nym_sphinx::addressing::clients::Recipient; use nym_sphinx::addressing::clients::Recipient;
use nym_sphinx::anonymous_replies::requests::AnonymousSenderTag; use nym_sphinx::anonymous_replies::requests::AnonymousSenderTag;
use nym_sphinx::receiver::ReconstructedMessage; use nym_sphinx::receiver::ReconstructedMessage;
@@ -26,6 +25,7 @@ use tokio_tungstenite::{
tungstenite::{protocol::Message as WsMessage, Error as WsError}, tungstenite::{protocol::Message as WsMessage, Error as WsError},
WebSocketStream, WebSocketStream,
}; };
use websocket_requests::{requests::ClientRequest, responses::ServerResponse};
#[derive(Default)] #[derive(Default)]
enum ReceivedResponseType { enum ReceivedResponseType {
+3 -3
View File
@@ -1,5 +1,5 @@
[package] [package]
name = "nym-client-websocket-requests" name = "websocket-requests"
version = "0.1.0" version = "0.1.0"
authors = ["Jędrzej Stuczyński <andrew@nymtech.net>"] authors = ["Jędrzej Stuczyński <andrew@nymtech.net>"]
edition = "2021" edition = "2021"
@@ -7,7 +7,7 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
serde = { workspace = true, features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
serde_json = { workspace = true } serde_json = "1.0"
nym-sphinx = { path = "../../../common/nymsphinx" } nym-sphinx = { path = "../../../common/nymsphinx" }
+6 -5
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "nym-socks5-client" name = "nym-socks5-client"
version = "1.1.15" version = "1.1.13"
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"
@@ -19,14 +19,14 @@ tokio = { version = "1.24.1", features = ["rt-multi-thread", "net", "signal"] }
url = "2.2" url = "2.2"
# internal # internal
nym-bin-common = { path = "../../common/bin-common", features = ["output_format"] } nym-bin-common = { path = "../../common/bin-common" }
nym-client-core = { path = "../../common/client-core", features = ["fs-surb-storage"] } client-core = { path = "../../common/client-core", features = ["fs-surb-storage"] }
nym-coconut-interface = { path = "../../common/coconut-interface" } nym-coconut-interface = { path = "../../common/coconut-interface" }
nym-config = { path = "../../common/config" } nym-config = { path = "../../common/config" }
mobile-storage = { path = "../../common/mobile-storage", optional = true }
nym-credentials = { path = "../../common/credentials" } nym-credentials = { path = "../../common/credentials" }
nym-crypto = { path = "../../common/crypto" } nym-crypto = { path = "../../common/crypto" }
nym-gateway-requests = { path = "../../gateway/gateway-requests" } gateway-requests = { path = "../../gateway/gateway-requests" }
nym-credential-storage = { path = "../../common/credential-storage" }
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-ordered-buffer = { path = "../../common/socks5/ordered-buffer" } nym-ordered-buffer = { path = "../../common/socks5/ordered-buffer" }
@@ -37,3 +37,4 @@ nym-socks5-client-core = { path = "../../common/socks5-client-core" }
[features] [features]
default = [] default = []
eth = [] eth = []
mobile = ["mobile-storage", "nym-socks5-client-core/mobile"]
+23 -21
View File
@@ -1,4 +1,4 @@
// Copyright 2021-2023 - 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 crate::commands::try_upgrade_v1_1_13_config; use crate::commands::try_upgrade_v1_1_13_config;
@@ -7,9 +7,7 @@ use crate::{
error::Socks5ClientError, error::Socks5ClientError,
}; };
use clap::Args; use clap::Args;
use nym_bin_common::output_format::OutputFormat;
use nym_config::NymConfig; use nym_config::NymConfig;
use nym_credential_storage::persistent_storage::PersistentStorage;
use nym_crypto::asymmetric::identity; use nym_crypto::asymmetric::identity;
use nym_socks5_client_core::config::Config; use nym_socks5_client_core::config::Config;
use nym_sphinx::addressing::clients::Recipient; use nym_sphinx::addressing::clients::Recipient;
@@ -77,8 +75,9 @@ pub(crate) struct Init {
#[clap(long, hide = true)] #[clap(long, hide = true)]
enabled_credentials_mode: Option<bool>, enabled_credentials_mode: Option<bool>,
#[clap(short, long, default_value_t = OutputFormat::default())] /// Save a summary of the initialization to a json file
output: OutputFormat, #[clap(long)]
output_json: bool,
} }
impl From<Init> for OverrideConfig { impl From<Init> for OverrideConfig {
@@ -98,17 +97,15 @@ impl From<Init> for OverrideConfig {
#[derive(Debug, Serialize)] #[derive(Debug, Serialize)]
pub struct InitResults { pub struct InitResults {
#[serde(flatten)] #[serde(flatten)]
client_core: nym_client_core::init::InitResults, client_core: client_core::init::InitResults,
socks5_listening_port: String, socks5_listening_port: String,
client_address: String,
} }
impl InitResults { impl InitResults {
fn new(config: &Config, address: &Recipient) -> Self { fn new(config: &Config, address: &Recipient) -> Self {
Self { Self {
client_core: nym_client_core::init::InitResults::new(config.get_base(), address), client_core: client_core::init::InitResults::new(config.get_base(), address),
socks5_listening_port: config.get_socks5().get_listening_port().to_string(), socks5_listening_port: config.get_listening_port().to_string(),
client_address: address.to_string(),
} }
} }
} }
@@ -116,13 +113,12 @@ impl InitResults {
impl Display for InitResults { impl Display for InitResults {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
writeln!(f, "{}", self.client_core)?; writeln!(f, "{}", self.client_core)?;
writeln!(f, "SOCKS5 listening port: {}", self.socks5_listening_port)?; write!(f, "SOCKS5 listening port: {}", self.socks5_listening_port)
write!(f, "Address of this client: {}", self.client_address)
} }
} }
pub(crate) async fn execute(args: &Init) -> Result<(), Socks5ClientError> { pub(crate) async fn execute(args: &Init) -> Result<(), Socks5ClientError> {
eprintln!("Initialising client..."); println!("Initialising client...");
let id = &args.id; let id = &args.id;
let provider_address = &args.provider; let provider_address = &args.provider;
@@ -132,14 +128,14 @@ pub(crate) async fn execute(args: &Init) -> Result<(), Socks5ClientError> {
// in case we're using old config, try to upgrade it // in case we're using old config, try to upgrade it
// (if we're using the current version, it's a no-op) // (if we're using the current version, it's a no-op)
try_upgrade_v1_1_13_config(id)?; try_upgrade_v1_1_13_config(id)?;
eprintln!("SOCKS5 client \"{id}\" was already initialised before"); println!("SOCKS5 client \"{id}\" was already initialised before");
} }
// Usually you only register with the gateway on the first init, however you can force // Usually you only register with the gateway on the first init, however you can force
// re-registering if wanted. // re-registering if wanted.
let user_wants_force_register = args.force_register_gateway; let user_wants_force_register = args.force_register_gateway;
if user_wants_force_register { if user_wants_force_register {
eprintln!("Instructed to force registering gateway. This might overwrite keys!"); println!("Instructed to force registering gateway. This might overwrite keys!");
} }
// If the client was already initialized, don't generate new keys and don't re-register with // If the client was already initialized, don't generate new keys and don't re-register with
@@ -158,7 +154,7 @@ pub(crate) async fn execute(args: &Init) -> Result<(), Socks5ClientError> {
// Setup gateway by either registering a new one, or creating a new config from the selected // Setup gateway by either registering a new one, or creating a new config from the selected
// one but with keys kept, or reusing the gateway configuration. // one but with keys kept, or reusing the gateway configuration.
let gateway = nym_client_core::init::setup_gateway_from_config::<Config, _, PersistentStorage>( let gateway = client_core::init::setup_gateway_from_config::<Config, _>(
register_gateway, register_gateway,
user_chosen_gateway_id, user_chosen_gateway_id,
config.get_base(), config.get_base(),
@@ -177,22 +173,28 @@ pub(crate) async fn execute(args: &Init) -> Result<(), Socks5ClientError> {
print_saved_config(&config); print_saved_config(&config);
let address = nym_client_core::init::get_client_address_from_stored_keys(config.get_base())?; let address = client_core::init::get_client_address_from_stored_keys(config.get_base())?;
let init_results = InitResults::new(&config, &address); let init_results = InitResults::new(&config, &address);
println!("{}", args.output.format(&init_results)); println!("{}", init_results);
// Output summary to a json file, if specified
if args.output_json {
client_core::init::output_to_json(&init_results, "socks5_client_init_results.json");
}
println!("\nThe address of this client is: {}\n", address);
Ok(()) Ok(())
} }
fn print_saved_config(config: &Config) { fn print_saved_config(config: &Config) {
let config_save_location = config.get_config_file_save_location(); let config_save_location = config.get_config_file_save_location();
eprintln!("Saved configuration file to {:?}", config_save_location); println!("Saved configuration file to {:?}", config_save_location);
eprintln!("Using gateway: {}", config.get_base().get_gateway_id()); println!("Using gateway: {}", config.get_base().get_gateway_id());
log::debug!("Gateway id: {}", config.get_base().get_gateway_id()); log::debug!("Gateway id: {}", config.get_base().get_gateway_id());
log::debug!("Gateway owner: {}", config.get_base().get_gateway_owner()); log::debug!("Gateway owner: {}", config.get_base().get_gateway_owner());
log::debug!( log::debug!(
"Gateway listener: {}", "Gateway listener: {}",
config.get_base().get_gateway_listener() config.get_base().get_gateway_listener()
); );
eprintln!("Client configuration completed.\n"); println!("Client configuration completed.\n");
} }
-4
View File
@@ -122,10 +122,6 @@ pub(crate) async fn execute(args: &Run) -> Result<(), Box<dyn std::error::Error
} }
}; };
if !config.validate() {
return Err(Box::new(Socks5ClientError::ConfigValidationFailure));
}
let override_config_fields = OverrideConfig::from(args.clone()); let override_config_fields = OverrideConfig::from(args.clone());
config = override_config(config, override_config_fields); config = override_config(config, override_config_fields);
+1 -5
View File
@@ -1,4 +1,4 @@
use nym_client_core::error::ClientCoreError; use client_core::error::ClientCoreError;
#[derive(thiserror::Error, Debug)] #[derive(thiserror::Error, Debug)]
pub enum Socks5ClientError { pub enum Socks5ClientError {
@@ -8,10 +8,6 @@ pub enum Socks5ClientError {
#[error("Failed to load config for: {0}")] #[error("Failed to load config for: {0}")]
FailedToLoadConfig(String), FailedToLoadConfig(String),
// TODO: add more details here
#[error("Failed to validate the loaded config")]
ConfigValidationFailure,
#[error("Failed local version check, client and config mismatch")] #[error("Failed local version check, client and config mismatch")]
FailedLocalVersionCheck, FailedLocalVersionCheck,
+2 -2
View File
@@ -4,7 +4,7 @@
use std::error::Error; use std::error::Error;
use clap::{crate_name, crate_version, Parser}; use clap::{crate_name, crate_version, Parser};
use nym_bin_common::logging::{maybe_print_banner, setup_logging}; use nym_bin_common::logging::{banner, setup_logging};
use nym_network_defaults::setup_env; use nym_network_defaults::setup_env;
mod commands; mod commands;
@@ -13,7 +13,7 @@ pub mod error;
#[tokio::main] #[tokio::main]
async fn main() -> Result<(), Box<dyn Error + Send + Sync>> { async fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
setup_logging(); setup_logging();
maybe_print_banner(crate_name!(), crate_version!()); println!("{}", banner(crate_name!(), crate_version!()));
let args = commands::Cli::parse(); let args = commands::Cli::parse();
setup_env(args.config_env_file.as_ref()); setup_env(args.config_env_file.as_ref());
+1 -1
View File
@@ -48,7 +48,7 @@
"eslint-plugin-mocha": "^10.0.3", "eslint-plugin-mocha": "^10.0.3",
"eslint-plugin-prettier": "^4.0.0", "eslint-plugin-prettier": "^4.0.0",
"mocha": "^10.0.0", "mocha": "^10.0.0",
"prettier": "^2.8.7", "prettier": "^2.5.1",
"ts-mocha": "^10.0.0", "ts-mocha": "^10.0.0",
"typedoc": "^0.22.13", "typedoc": "^0.22.13",
"typescript": "^4.6.2", "typescript": "^4.6.2",
+1 -10
View File
@@ -34,11 +34,10 @@ import {
StakeSaturationResponse, StakeSaturationResponse,
UnbondedMixnodeResponse, UnbondedMixnodeResponse,
VestingAccountInfo, VestingAccountInfo,
ContractState, VestingAccountsCoinPaged, VestingAccountsPaged, DelegationTimes, Delegations, Period, VestingAccountNode, DelegationBlock ContractState, VestingAccountsCoinPaged, VestingAccountsPaged, DelegationTimes, Delegations, Period, VestingAccountNode
} from '@nymproject/types'; } from '@nymproject/types';
import QueryClient from './query-client'; import QueryClient from './query-client';
import SigningClient, { ISigningClient } from './signing-client'; import SigningClient, { ISigningClient } from './signing-client';
// import { DelegationBlock } from './types/shared';
export interface INymClient { export interface INymClient {
readonly mixnetContract: string; readonly mixnetContract: string;
@@ -607,14 +606,6 @@ export default class ValidatorClient implements INymClient {
return this.client.getAllDelegations(this.vestingContract); return this.client.getAllDelegations(this.vestingContract);
} }
public async getDelegation(address: string, mix_id: number): Promise<DelegationBlock> {
return this.client.getDelegation(this.vestingContract, address, mix_id );
}
public async getTotalDelegationAmount(address: string, mix_id: number, block_timestamp_sec: number): Promise<Coin> {
return this.client.getTotalDelegationAmount(this.vestingContract, address, mix_id, block_timestamp_sec);
}
public async getCurrentVestingPeriod(address: string): Promise<Period> { public async getCurrentVestingPeriod(address: string): Promise<Period> {
return this.client.getCurrentVestingPeriod(this.vestingContract, address); return this.client.getCurrentVestingPeriod(this.vestingContract, address);
} }
+1 -13
View File
@@ -18,7 +18,7 @@ import {
PagedMixNodeDetailsResponse, PagedMixNodeDetailsResponse,
PagedUnbondedMixnodesResponse, PagedUnbondedMixnodesResponse,
LayerDistribution, LayerDistribution,
ContractState, VestingAccountsCoinPaged, VestingAccountsPaged, DelegationTimes, Delegations, Period, VestingAccountNode, DelegationBlock ContractState, VestingAccountsCoinPaged, VestingAccountsPaged, DelegationTimes, Delegations, Period, VestingAccountNode
} from '@nymproject/types'; } from '@nymproject/types';
import { SmartContractQuery } from './types/shared'; import { SmartContractQuery } from './types/shared';
import { Coin } from 'cosmjs-types/cosmos/base/v1beta1/coin'; import { Coin } from 'cosmjs-types/cosmos/base/v1beta1/coin';
@@ -317,18 +317,6 @@ export default class NyxdQuerier implements INyxdQuery {
}); });
} }
getDelegation(vestingContractAddress: string, address: string, mix_id: number): Promise<DelegationBlock> {
return this.client.queryContractSmart(vestingContractAddress, {
get_all_delegations: {address: address, mix_id: mix_id}
});
}
getTotalDelegationAmount(vestingContractAddress: string, address: string, mix_id: number, block_timestamp_sec: number): Promise<Coin> {
return this.client.queryContractSmart(vestingContractAddress, {
get_all_delegations: {address: address, mix_id: mix_id, block_timestamp_sec: block_timestamp_sec}
});
}
getCurrentVestingPeriod(vestingContractAddress: string, address: string): Promise<Period> { getCurrentVestingPeriod(vestingContractAddress: string, address: string): Promise<Period> {
return this.client.queryContractSmart(vestingContractAddress, { return this.client.queryContractSmart(vestingContractAddress, {
get_current_vesting_period: { address: address } get_current_vesting_period: { address: address }
+1 -9
View File
@@ -22,7 +22,7 @@ import {
MixNodeRewarding, MixNodeRewarding,
OriginalVestingResponse, OriginalVestingResponse,
VestingAccountInfo, VestingAccountInfo,
ContractState, VestingAccountsCoinPaged, VestingAccountsPaged, DelegationTimes, Delegations, Period, VestingAccountNode, DelegationBlock ContractState, VestingAccountsCoinPaged, VestingAccountsPaged, DelegationTimes, Delegations, Period, VestingAccountNode
} from '@nymproject/types'; } from '@nymproject/types';
import NymApiQuerier, { INymApiQuery } from './nym-api-querier'; import NymApiQuerier, { INymApiQuery } from './nym-api-querier';
import { ICosmWasmQuery } from './types/shared'; import { ICosmWasmQuery } from './types/shared';
@@ -288,14 +288,6 @@ export default class QueryClient extends CosmWasmClient implements IQueryClient
return this.nyxdQuerier.getAllDelegations(vestingContractAddress); return this.nyxdQuerier.getAllDelegations(vestingContractAddress);
} }
getDelegation(vestingContractAddress: string, vestingAccountAddress: string, mix_id: number): Promise<DelegationBlock> {
return this.nyxdQuerier.getDelegation(vestingContractAddress, vestingAccountAddress, mix_id);
}
getTotalDelegationAmount(vestingContractAddress: string, vestingAccountAddress: string, mix_id: number, block_timestamp_sec: number): Promise<Coin> {
return this.nyxdQuerier.getTotalDelegationAmount(vestingContractAddress, vestingAccountAddress, mix_id, block_timestamp_sec);
}
getCurrentVestingPeriod(vestingContractAddress: string, address: string): Promise<Period> { getCurrentVestingPeriod(vestingContractAddress: string, address: string): Promise<Period> {
return this.nyxdQuerier.getCurrentVestingPeriod(vestingContractAddress, address); return this.nyxdQuerier.getCurrentVestingPeriod(vestingContractAddress, address);
} }
+1 -9
View File
@@ -40,7 +40,7 @@ import {
RewardingParams, RewardingParams,
UnbondedMixnodeResponse, UnbondedMixnodeResponse,
VestingAccountInfo, VestingAccountInfo,
ContractState, VestingAccountsCoinPaged, VestingAccountsPaged, DelegationTimes, Delegations, Period, VestingAccountNode, DelegationBlock ContractState, VestingAccountsCoinPaged, VestingAccountsPaged, DelegationTimes, Delegations, Period, VestingAccountNode
} from '@nymproject/types'; } from '@nymproject/types';
import NymApiQuerier from './nym-api-querier'; import NymApiQuerier from './nym-api-querier';
@@ -597,14 +597,6 @@ export default class SigningClient extends SigningCosmWasmClient implements ISig
return this.nyxdQuerier.getAllDelegations(vestingContractAddress); return this.nyxdQuerier.getAllDelegations(vestingContractAddress);
} }
getDelegation(vestingContractAddress: string, vestingAccountAddress: string, mix_id: number): Promise<DelegationBlock> {
return this.nyxdQuerier.getDelegation(vestingContractAddress, vestingAccountAddress, mix_id);
}
getTotalDelegationAmount(vestingContractAddress: string, vestingAccountAddress: string, mix_id: number, block_timestamp_sec: number): Promise<Coin> {
return this.nyxdQuerier.getTotalDelegationAmount(vestingContractAddress, vestingAccountAddress, mix_id, block_timestamp_sec);
}
getCurrentVestingPeriod(vestingContractAddress: string, address: string): Promise<Period> { getCurrentVestingPeriod(vestingContractAddress: string, address: string): Promise<Period> {
return this.nyxdQuerier.getCurrentVestingPeriod(vestingContractAddress, address); return this.nyxdQuerier.getCurrentVestingPeriod(vestingContractAddress, address);
} }
+3 -4
View File
@@ -30,14 +30,13 @@ wasm-bindgen = { version = "=0.2.83", features = ["serde-serialize"] }
wasm-bindgen-futures = "0.4" wasm-bindgen-futures = "0.4"
# internal # internal
nym-client-core = { path = "../../common/client-core", default-features = false, features = ["wasm"] } client-core = { path = "../../common/client-core", default-features = false, features = ["wasm"] }
nym-bandwidth-controller = { path = "../../common/bandwidth-controller" }
nym-coconut-interface = { path = "../../common/coconut-interface" } nym-coconut-interface = { path = "../../common/coconut-interface" }
nym-credentials = { path = "../../common/credentials" } nym-credentials = { path = "../../common/credentials" }
nym-credential-storage = { path = "../../common/credential-storage" }
nym-crypto = { path = "../../common/crypto" } nym-crypto = { path = "../../common/crypto" }
nym-sphinx = { path = "../../common/nymsphinx" } nym-sphinx = { path = "../../common/nymsphinx" }
nym-validator-client = { path = "../../common/client-libs/validator-client", default-features = false } gateway-client = { path = "../../common/client-libs/gateway-client", default-features = false, features = ["wasm"] }
validator-client = { path = "../../common/client-libs/validator-client", default-features = false }
wasm-utils = { path = "../../common/wasm-utils" } wasm-utils = { path = "../../common/wasm-utils" }
nym-task = { path = "../../common/task" } nym-task = { path = "../../common/task" }
# The `console_error_panic_hook` crate provides better debugging of panics by # The `console_error_panic_hook` crate provides better debugging of panics by
+5 -13
View File
@@ -6,13 +6,12 @@
// another issue due to #[wasm_bindgen] and `Copy` trait // another issue due to #[wasm_bindgen] and `Copy` trait
#![allow(clippy::drop_copy)] #![allow(clippy::drop_copy)]
use nym_client_core::config::{ use client_core::config::{
Acknowledgements as ConfigAcknowledgements, CoverTraffic as ConfigCoverTraffic, Acknowledgements as ConfigAcknowledgements, CoverTraffic as ConfigCoverTraffic,
DebugConfig as ConfigDebug, GatewayConnection as ConfigGatewayConnection, DebugConfig as ConfigDebug, ExtendedPacketSize, GatewayConnection as ConfigGatewayConnection,
GatewayEndpointConfig, ReplySurbs as ConfigReplySurbs, Topology as ConfigTopology, GatewayEndpointConfig, ReplySurbs as ConfigReplySurbs, Topology as ConfigTopology,
Traffic as ConfigTraffic, Traffic as ConfigTraffic,
}; };
use nym_sphinx::params::PacketSize;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::time::Duration; use std::time::Duration;
use url::Url; use url::Url;
@@ -83,7 +82,7 @@ impl From<Traffic> for ConfigTraffic {
fn from(traffic: Traffic) -> Self { fn from(traffic: Traffic) -> Self {
let use_extended_packet_size = traffic let use_extended_packet_size = traffic
.use_extended_packet_size .use_extended_packet_size
.then(|| PacketSize::ExtendedPacket32); .then(|| ExtendedPacketSize::Extended32);
ConfigTraffic { ConfigTraffic {
average_packet_delay: Duration::from_millis(traffic.average_packet_delay_ms), average_packet_delay: Duration::from_millis(traffic.average_packet_delay_ms),
@@ -92,8 +91,7 @@ impl From<Traffic> for ConfigTraffic {
), ),
disable_main_poisson_packet_distribution: traffic disable_main_poisson_packet_distribution: traffic
.disable_main_poisson_packet_distribution, .disable_main_poisson_packet_distribution,
primary_packet_size: PacketSize::RegularPacket, use_extended_packet_size,
secondary_packet_size: use_extended_packet_size,
} }
} }
} }
@@ -106,7 +104,7 @@ impl From<ConfigTraffic> for Traffic {
as u64, as u64,
disable_main_poisson_packet_distribution: traffic disable_main_poisson_packet_distribution: traffic
.disable_main_poisson_packet_distribution, .disable_main_poisson_packet_distribution,
use_extended_packet_size: traffic.secondary_packet_size.is_some(), use_extended_packet_size: traffic.use_extended_packet_size.is_some(),
} }
} }
} }
@@ -118,10 +116,6 @@ pub struct CoverTraffic {
/// it is going to take for another loop cover traffic message to be sent. /// it is going to take for another loop cover traffic message to be sent.
pub loop_cover_traffic_average_delay_ms: u64, pub loop_cover_traffic_average_delay_ms: u64,
/// Specifies the ratio of `primary_packet_size` to `secondary_packet_size` used in cover traffic.
/// Only applicable if `secondary_packet_size` is enabled.
pub cover_traffic_primary_size_ratio: f64,
/// Controls whether the dedicated loop cover traffic stream should be enabled. /// Controls whether the dedicated loop cover traffic stream should be enabled.
/// (and sending packets, on average, every [Self::loop_cover_traffic_average_delay]) /// (and sending packets, on average, every [Self::loop_cover_traffic_average_delay])
pub disable_loop_cover_traffic_stream: bool, pub disable_loop_cover_traffic_stream: bool,
@@ -133,7 +127,6 @@ impl From<CoverTraffic> for ConfigCoverTraffic {
loop_cover_traffic_average_delay: Duration::from_millis( loop_cover_traffic_average_delay: Duration::from_millis(
cover_traffic.loop_cover_traffic_average_delay_ms, cover_traffic.loop_cover_traffic_average_delay_ms,
), ),
cover_traffic_primary_size_ratio: cover_traffic.cover_traffic_primary_size_ratio,
disable_loop_cover_traffic_stream: cover_traffic.disable_loop_cover_traffic_stream, disable_loop_cover_traffic_stream: cover_traffic.disable_loop_cover_traffic_stream,
} }
} }
@@ -145,7 +138,6 @@ impl From<ConfigCoverTraffic> for CoverTraffic {
loop_cover_traffic_average_delay_ms: cover_traffic loop_cover_traffic_average_delay_ms: cover_traffic
.loop_cover_traffic_average_delay .loop_cover_traffic_average_delay
.as_millis() as u64, .as_millis() as u64,
cover_traffic_primary_size_ratio: cover_traffic.cover_traffic_primary_size_ratio,
disable_loop_cover_traffic_stream: cover_traffic.disable_loop_cover_traffic_stream, disable_loop_cover_traffic_stream: cover_traffic.disable_loop_cover_traffic_stream,
} }
} }
+2 -2
View File
@@ -1,9 +1,9 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net> // Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use client_core::client::base_client::ClientInput;
use client_core::client::inbound_messages::InputMessage;
use js_sys::Promise; use js_sys::Promise;
use nym_client_core::client::base_client::ClientInput;
use nym_client_core::client::inbound_messages::InputMessage;
use std::sync::Arc; use std::sync::Arc;
use wasm_bindgen::JsValue; use wasm_bindgen::JsValue;
use wasm_bindgen_futures::future_to_promise; use wasm_bindgen_futures::future_to_promise;
+7 -9
View File
@@ -4,15 +4,14 @@
use self::config::Config; use self::config::Config;
use crate::client::helpers::InputSender; use crate::client::helpers::InputSender;
use crate::client::response_pusher::ResponsePusher; use crate::client::response_pusher::ResponsePusher;
use js_sys::Promise; use client_core::client::base_client::{
use nym_bandwidth_controller::wasm_mockups::{Client as FakeClient, DirectSigningNyxdClient};
use nym_bandwidth_controller::BandwidthController;
use nym_client_core::client::base_client::{
BaseClientBuilder, ClientInput, ClientOutput, CredentialsToggle, BaseClientBuilder, ClientInput, ClientOutput, CredentialsToggle,
}; };
use nym_client_core::client::replies::reply_storage::browser_backend; use client_core::client::replies::reply_storage::browser_backend;
use nym_client_core::client::{inbound_messages::InputMessage, key_manager::KeyManager}; use client_core::client::{inbound_messages::InputMessage, key_manager::KeyManager};
use nym_credential_storage::ephemeral_storage::EphemeralStorage; use gateway_client::bandwidth::BandwidthController;
use gateway_client::wasm_mockups::{Client as FakeClient, DirectSigningNyxdClient};
use js_sys::Promise;
use nym_sphinx::addressing::clients::Recipient; use nym_sphinx::addressing::clients::Recipient;
use nym_sphinx::anonymous_replies::requests::AnonymousSenderTag; use nym_sphinx::anonymous_replies::requests::AnonymousSenderTag;
use nym_task::connections::TransmissionLane; use nym_task::connections::TransmissionLane;
@@ -49,8 +48,7 @@ pub struct NymClientBuilder {
on_message: js_sys::Function, on_message: js_sys::Function,
// unimplemented: // unimplemented:
bandwidth_controller: bandwidth_controller: Option<BandwidthController<FakeClient<DirectSigningNyxdClient>>>,
Option<BandwidthController<FakeClient<DirectSigningNyxdClient>, EphemeralStorage>>,
disabled_credentials: bool, disabled_credentials: bool,
} }
@@ -1,13 +1,11 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net> // Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use client_core::client::base_client::ClientOutput;
use client_core::client::received_buffer::{ReceivedBufferMessage, ReconstructedMessagesReceiver};
use futures::channel::mpsc; use futures::channel::mpsc;
use futures::StreamExt; use futures::StreamExt;
use js_sys::Uint8Array; use js_sys::Uint8Array;
use nym_client_core::client::base_client::ClientOutput;
use nym_client_core::client::received_buffer::{
ReceivedBufferMessage, ReconstructedMessagesReceiver,
};
use wasm_bindgen::JsValue; use wasm_bindgen::JsValue;
use wasm_bindgen_futures::spawn_local; use wasm_bindgen_futures::spawn_local;
use wasm_utils::console_error; use wasm_utils::console_error;
+2 -3
View File
@@ -1,13 +1,12 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net> // Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use nym_client_core::config::GatewayEndpointConfig; use client_core::config::GatewayEndpointConfig;
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;
#[wasm_bindgen] #[wasm_bindgen]
pub async fn get_gateway(api_server: String, preferred: Option<String>) -> GatewayEndpointConfig { pub async fn get_gateway(api_server: String, preferred: Option<String>) -> GatewayEndpointConfig {
let validator_client = let validator_client = validator_client::client::NymApiClient::new(api_server.parse().unwrap());
nym_validator_client::client::NymApiClient::new(api_server.parse().unwrap());
let gateways = match validator_client.get_cached_gateways().await { let gateways = match validator_client.get_cached_gateways().await {
Err(err) => panic!("failed to obtain list of all gateways - {err}"), Err(err) => panic!("failed to obtain list of all gateways - {err}"),
-12
View File
@@ -1,12 +0,0 @@
[package]
name = "async-file-watcher"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
log = "0.4"
tokio = { workspace = true, features = ["time"] }
futures = "0.3"
notify = "5.1.0"
-158
View File
@@ -1,158 +0,0 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use futures::channel::mpsc;
use futures::StreamExt;
use notify::event::{DataChange, MetadataKind, ModifyKind};
use notify::{Config, Event, EventKind, RecommendedWatcher, RecursiveMode, Watcher};
use std::collections::HashMap;
use std::path::{Path, PathBuf};
use std::time::Duration;
use tokio::time::Instant;
pub type FileWatcherEventSender = mpsc::UnboundedSender<Event>;
pub type FileWatcherEventReceiver = mpsc::UnboundedReceiver<Event>;
/// Simple file watcher that sends a notification whenever there was any changed in the watched file.
pub struct AsyncFileWatcher {
path: PathBuf,
watcher: RecommendedWatcher,
is_watching: bool,
filters: Option<Vec<EventKind>>,
last_received: HashMap<EventKind, Instant>,
tick_duration: Duration,
inner_rx: mpsc::UnboundedReceiver<notify::Result<Event>>,
event_sender: FileWatcherEventSender,
}
impl AsyncFileWatcher {
pub fn new_file_changes_watcher<P: AsRef<Path>>(
path: P,
event_sender: FileWatcherEventSender,
) -> notify::Result<Self> {
Self::new(
path,
event_sender,
Some(vec![
EventKind::Modify(ModifyKind::Data(DataChange::Content)),
EventKind::Modify(ModifyKind::Data(DataChange::Any)),
EventKind::Modify(ModifyKind::Metadata(MetadataKind::Any)),
]),
None,
)
}
pub fn new<P: AsRef<Path>>(
path: P,
event_sender: FileWatcherEventSender,
filters: Option<Vec<EventKind>>,
tick_duration: Option<Duration>,
) -> notify::Result<Self> {
let watcher_config = Config::default();
let (inner_tx, inner_rx) = mpsc::unbounded();
let watcher = RecommendedWatcher::new(
move |res| {
if let Err(_err) = inner_tx.unbounded_send(res) {
// I guess it's theoretically possible during shutdown?
log::error!(
"failed to send watched file event - the received must have been dropped!"
);
}
},
watcher_config,
)?;
Ok(AsyncFileWatcher {
path: path.as_ref().to_path_buf(),
watcher,
is_watching: false,
filters,
last_received: HashMap::new(),
tick_duration: tick_duration.unwrap_or(Duration::from_secs(5)),
inner_rx,
event_sender,
})
}
pub fn with_filters(mut self, filters: Option<Vec<EventKind>>) -> Self {
self.filters = filters;
self
}
pub fn with_filter(mut self, filter: EventKind) -> Self {
match &mut self.filters {
None => {
self.filters = Some(vec![filter]);
}
Some(filters) => filters.push(filter),
}
self
}
fn should_propagate(&self, event: &Event, now: Instant) -> bool {
// when testing I was consistently getting two `Modify(Data(Any))` events in quick succession
// (probably to modify content and metadata).
// we really only want to propagate one of them
if let Some(previous) = self.last_received.get(&event.kind) {
if now.duration_since(*previous) < self.tick_duration {
return false;
}
}
let Some(filters) = &self.filters else {
return true
};
for filter in filters {
if &event.kind == filter {
return true;
}
}
false
}
fn start_watching(&mut self) -> notify::Result<()> {
self.is_watching = true;
self.watcher.watch(&self.path, RecursiveMode::NonRecursive)
}
fn stop_watching(&mut self) -> notify::Result<()> {
self.is_watching = false;
self.watcher.unwatch(&self.path)
}
pub async fn watch(&mut self) -> notify::Result<()> {
self.start_watching()?;
while let Some(event) = self.inner_rx.next().await {
match event {
Ok(event) => {
let now = Instant::now();
if self.should_propagate(&event, now) {
self.last_received.insert(event.kind.clone(), now);
if let Err(_err) = self.event_sender.unbounded_send(event) {
log::error!("the file watcher receiver has been dropped!");
}
} else {
log::debug!("will not propagate information about {:?}", event);
}
}
Err(err) => {
// TODO: to be determined if this should stop the whole thing or not
// (need to know what kind of errors can be returned)
log::error!(
"encountered an error while watching {:?}: {err}",
self.path.as_path()
);
}
}
}
self.stop_watching()
}
pub fn is_watching(&self) -> bool {
self.is_watching
}
}
-24
View File
@@ -1,24 +0,0 @@
[package]
name = "nym-bandwidth-controller"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
bip39 = { workspace = true }
rand = "0.7.3"
thiserror = "1.0"
url = "2.2"
nym-coconut-interface = { path = "../coconut-interface" }
nym-credential-storage = { path = "../credential-storage" }
nym-credentials = { path = "../credentials" }
nym-crypto = { path = "../crypto", features = ["rand", "asymmetric", "symmetric", "aes", "hashing"] }
nym-network-defaults = { path = "../network-defaults" }
nym-validator-client = { path = "../client-libs/validator-client", default-features = false }
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.nym-validator-client]
path = "../client-libs/validator-client"
features = ["nyxd-client"]
@@ -1,89 +0,0 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::error::BandwidthControllerError;
use nym_coconut_interface::{Base58, Parameters};
use nym_credential_storage::storage::Storage;
use nym_credentials::coconut::bandwidth::{BandwidthVoucher, TOTAL_ATTRIBUTES};
use nym_credentials::coconut::utils::obtain_aggregate_signature;
use nym_crypto::asymmetric::{encryption, identity};
use nym_network_defaults::VOUCHER_INFO;
use nym_validator_client::nyxd::traits::CoconutBandwidthSigningClient;
use nym_validator_client::nyxd::traits::DkgQueryClient;
use nym_validator_client::nyxd::tx::Hash;
use nym_validator_client::nyxd::Coin;
use nym_validator_client::CoconutApiClient;
use rand::rngs::OsRng;
use state::{KeyPair, State};
use std::str::FromStr;
pub mod state;
pub async fn deposit<C>(client: &C, amount: Coin) -> Result<State, BandwidthControllerError>
where
C: CoconutBandwidthSigningClient,
{
let mut rng = OsRng;
let signing_keypair = KeyPair::from(identity::KeyPair::new(&mut rng));
let encryption_keypair = KeyPair::from(encryption::KeyPair::new(&mut rng));
let params = Parameters::new(TOTAL_ATTRIBUTES).unwrap();
let voucher_value = amount.amount.to_string();
let tx_hash = client
.deposit(
amount,
String::from(VOUCHER_INFO),
signing_keypair.public_key.clone(),
encryption_keypair.public_key.clone(),
None,
)
.await?
.transaction_hash
.to_string();
let voucher = BandwidthVoucher::new(
&params,
voucher_value,
VOUCHER_INFO.to_string(),
Hash::from_str(&tx_hash).map_err(|_| BandwidthControllerError::InvalidTxHash)?,
identity::PrivateKey::from_base58_string(&signing_keypair.private_key)?,
encryption::PrivateKey::from_base58_string(&encryption_keypair.private_key)?,
);
let state = State { voucher, params };
Ok(state)
}
pub async fn get_credential<C: DkgQueryClient + Send + Sync, St: Storage>(
state: &State,
client: &C,
storage: &St,
) -> Result<(), BandwidthControllerError> {
let epoch_id = client.get_current_epoch().await?.epoch_id;
let threshold = client
.get_current_epoch_threshold()
.await?
.ok_or(BandwidthControllerError::NoThreshold)?;
let coconut_api_clients = CoconutApiClient::all_coconut_api_clients(client, epoch_id).await?;
let signature = obtain_aggregate_signature(
&state.params,
&state.voucher,
&coconut_api_clients,
threshold,
)
.await?;
storage
.insert_coconut_credential(
state.voucher.get_voucher_value(),
VOUCHER_INFO.to_string(),
state.voucher.get_private_attributes()[0].to_bs58(),
state.voucher.get_private_attributes()[1].to_bs58(),
signature.to_bs58(),
epoch_id.to_string(),
)
.await?;
Ok(())
}
-41
View File
@@ -1,41 +0,0 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use nym_coconut_interface::CoconutError;
use nym_credential_storage::error::StorageError;
use nym_credentials::error::Error as CredentialsError;
use nym_crypto::asymmetric::encryption::KeyRecoveryError;
use nym_crypto::asymmetric::identity::Ed25519RecoveryError;
use nym_validator_client::error::ValidatorClientError;
use thiserror::Error;
#[derive(Debug, Error)]
pub enum BandwidthControllerError {
#[cfg(not(target_arch = "wasm32"))]
#[error("Nyxd error: {0}")]
Nyxd(#[from] nym_validator_client::nyxd::error::NyxdError),
#[error("There was a credential storage error - {0}")]
CredentialStorageError(#[from] StorageError),
#[error("Coconut error - {0}")]
CoconutError(#[from] CoconutError),
#[error("Validator client error - {0}")]
ValidatorError(#[from] ValidatorClientError),
#[error("Credential error - {0}")]
CredentialError(#[from] CredentialsError),
#[error("Could not parse Ed25519 data")]
Ed25519ParseError(#[from] Ed25519RecoveryError),
#[error("Could not parse X25519 data")]
X25519ParseError(#[from] KeyRecoveryError),
#[error("The tx hash provided is not valid")]
InvalidTxHash,
#[error("Threshold not set yet")]
NoThreshold,
}
@@ -1,17 +0,0 @@
// Copyright 2022-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use std::marker::PhantomData;
pub struct DirectSigningNyxdClient {}
pub trait DkgQueryClient {}
// impl CosmWasmClient for DirectSigningNyxdClient {}
#[derive(Clone)]
pub struct Client<C> {
_phantom: PhantomData<C>,
}
impl<C> DkgQueryClient for Client<C> {}
+2 -19
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "nym-bin-common" name = "nym-bin-common"
version = "0.5.0" version = "0.3.0"
description = "Common code for nym binaries" description = "Common code for nym binaries"
edition = { workspace = true } edition = { workspace = true }
authors = { workspace = true } authors = { workspace = true }
@@ -8,7 +8,6 @@ license = { workspace = true }
repository = { workspace = true } repository = { workspace = true }
[dependencies] [dependencies]
atty = "0.2"
clap = { version = "4.0", features = ["derive"] } clap = { version = "4.0", features = ["derive"] }
clap_complete = "4.0" clap_complete = "4.0"
clap_complete_fig = "4.0" clap_complete_fig = "4.0"
@@ -16,25 +15,9 @@ log = { workspace = true }
pretty_env_logger = "0.4.0" pretty_env_logger = "0.4.0"
semver = "0.11" semver = "0.11"
serde = { workspace = true, features = ["derive"], optional = true } serde = { workspace = true, features = ["derive"], optional = true }
serde_json = { workspace = true, optional = true }
## tracing
tracing-appender = { version = "0.2.2", optional = true }
tracing-subscriber = { version = "0.3.16", features = [
"env-filter",
], optional = true }
tracing-tree = { version = "0.2.2", optional = true }
[build-dependencies] [build-dependencies]
vergen = { version = "=7.4.3", default-features = false, features = [ vergen = { version = "=7.4.3", default-features = false, features = ["build", "git", "rustc", "cargo"] }
"build",
"git",
"rustc",
"cargo",
] }
[features] [features]
default = [] default = []
output_format = ["serde", "serde_json"]
tracing = ["tracing-appender", "tracing-subscriber", "tracing-tree"]
-1
View File
@@ -4,5 +4,4 @@
pub mod build_information; pub mod build_information;
pub mod completions; pub mod completions;
pub mod logging; pub mod logging;
pub mod output_format;
pub mod version_checker; pub mod version_checker;
-45
View File
@@ -1,16 +1,5 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net> // Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
// use tracing_subscriber::{
// fmt::Layer, layer::SubscriberExt, util::SubscriberInitExt, EnvFilter, Registry,
// };
// use tracing_tree::HierarchicalLayer;
#[cfg(feature = "tracing")]
pub use tracing_appender;
#[cfg(feature = "tracing")]
pub use tracing_subscriber;
#[cfg(feature = "tracing")]
pub use tracing_tree;
// I'd argue we should start transitioning from `log` to `tracing` // I'd argue we should start transitioning from `log` to `tracing`
pub fn setup_logging() { pub fn setup_logging() {
@@ -35,34 +24,6 @@ pub fn setup_logging() {
.init(); .init();
} }
// TODO: This has to be a macro, running it as a function does not work for the file_appender for some reason
#[cfg(feature = "tracing")]
#[macro_export]
macro_rules! setup_tracing {
($file_name: expr) => {
use nym_bin_common::logging::tracing_subscriber::layer::SubscriberExt;
use nym_bin_common::logging::tracing_subscriber::util::SubscriberInitExt;
let file_appender =
nym_bin_common::logging::tracing_appender::rolling::hourly($file_name, "log");
let (non_blocking, _guard) =
nym_bin_common::logging::tracing_appender::non_blocking(file_appender);
let appender_layer = nym_bin_common::logging::tracing_subscriber::fmt::Layer::new()
.with_ansi(false)
.with_writer(non_blocking);
nym_bin_common::logging::tracing_subscriber::Registry::default()
.with(nym_bin_common::logging::tracing_subscriber::EnvFilter::from_default_env())
.with(appender_layer)
.with(
nym_bin_common::logging::tracing_tree::HierarchicalLayer::new(4)
.with_targets(true)
.with_bracketed_fields(true),
)
.init();
};
}
pub fn banner(crate_name: &str, crate_version: &str) -> String { pub fn banner(crate_name: &str, crate_version: &str) -> String {
format!( format!(
r#" r#"
@@ -78,9 +39,3 @@ pub fn banner(crate_name: &str, crate_version: &str) -> String {
"# "#
) )
} }
pub fn maybe_print_banner(crate_name: &str, crate_version: &str) {
if atty::is(atty::Stream::Stdout) {
println!("{}", banner(crate_name, crate_version))
}
}
@@ -1,35 +0,0 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use clap::ValueEnum;
use std::fmt::{Display, Formatter};
#[derive(Default, Copy, Debug, Clone, ValueEnum)]
pub enum OutputFormat {
#[default]
Text,
Json,
}
impl Display for OutputFormat {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
OutputFormat::Text => write!(f, "text"),
OutputFormat::Json => write!(f, "json"),
}
}
}
impl OutputFormat {
pub fn is_text(&self) -> bool {
matches!(self, OutputFormat::Text)
}
#[cfg(feature = "output_format")]
pub fn format<T: serde::Serialize + ToString>(&self, data: &T) -> String {
match self {
OutputFormat::Text => data.to_string(),
OutputFormat::Json => serde_json::to_string(data).unwrap(),
}
}
}
+9 -11
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "nym-client-core" name = "client-core"
version = "1.1.14" version = "1.1.13"
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"] authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"]
edition = "2021" edition = "2021"
rust-version = "1.66" rust-version = "1.66"
@@ -15,8 +15,8 @@ futures = "0.3"
humantime-serde = "1.0" humantime-serde = "1.0"
log = { workspace = true } log = { workspace = true }
rand = { version = "0.7.3", features = ["wasm-bindgen"] } rand = { version = "0.7.3", features = ["wasm-bindgen"] }
serde = { workspace = true, features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
serde_json = { workspace = true } serde_json = "1.0.89"
tap = "1.0.1" tap = "1.0.1"
thiserror = "1.0.34" thiserror = "1.0.34"
url = { version ="2.2", features = ["serde"] } url = { version ="2.2", features = ["serde"] }
@@ -25,21 +25,19 @@ tokio = { version = "1.24.1", features = ["macros"]}
time = "0.3.17" time = "0.3.17"
# internal # internal
nym-bandwidth-controller = { path = "../bandwidth-controller" }
nym-config = { path = "../config" } nym-config = { path = "../config" }
nym-crypto = { path = "../crypto" } nym-crypto = { path = "../crypto" }
nym-gateway-client = { path = "../client-libs/gateway-client" } gateway-client = { path = "../client-libs/gateway-client" }
#gateway-client = { path = "../../common/client-libs/gateway-client", default-features = false, features = ["wasm", "coconut"] } #gateway-client = { path = "../../common/client-libs/gateway-client", default-features = false, features = ["wasm", "coconut"] }
nym-gateway-requests = { path = "../../gateway/gateway-requests" } gateway-requests = { path = "../../gateway/gateway-requests" }
nym-nonexhaustive-delayqueue = { path = "../nonexhaustive-delayqueue" } nym-nonexhaustive-delayqueue = { path = "../nonexhaustive-delayqueue" }
nym-sphinx = { path = "../nymsphinx" } nym-sphinx = { path = "../nymsphinx" }
nym-pemstore = { path = "../pemstore" } nym-pemstore = { path = "../pemstore" }
nym-topology = { path = "../topology" } nym-topology = { path = "../topology" }
nym-validator-client = { path = "../client-libs/validator-client", default-features = false } validator-client = { path = "../client-libs/validator-client", default-features = false }
nym-task = { path = "../task" } nym-task = { path = "../task" }
nym-credential-storage = { path = "../credential-storage" }
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.nym-validator-client] [target."cfg(not(target_arch = \"wasm32\"))".dependencies.validator-client]
path = "../client-libs/validator-client" path = "../client-libs/validator-client"
features = ["nyxd-client"] features = ["nyxd-client"]
@@ -91,5 +89,5 @@ sqlx = { version = "0.6.2", features = ["runtime-tokio-rustls", "sqlite", "macro
[features] [features]
default = [] default = []
fs-surb-storage = ["sqlx"] fs-surb-storage = ["sqlx"]
wasm = ["nym-gateway-client/wasm"] wasm = ["gateway-client/wasm"]
@@ -24,13 +24,13 @@ use crate::config::{Config, DebugConfig, GatewayEndpointConfig};
use crate::error::ClientCoreError; use crate::error::ClientCoreError;
use crate::spawn_future; use crate::spawn_future;
use futures::channel::mpsc; use futures::channel::mpsc;
use log::{debug, info}; use gateway_client::bandwidth::BandwidthController;
use nym_bandwidth_controller::BandwidthController; use gateway_client::{
use nym_crypto::asymmetric::{encryption, identity};
use nym_gateway_client::{
AcknowledgementReceiver, AcknowledgementSender, GatewayClient, MixnetMessageReceiver, AcknowledgementReceiver, AcknowledgementSender, GatewayClient, MixnetMessageReceiver,
MixnetMessageSender, MixnetMessageSender,
}; };
use log::{debug, info};
use nym_crypto::asymmetric::{encryption, identity};
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;
@@ -43,12 +43,11 @@ use std::time::Duration;
use tap::TapFallible; use tap::TapFallible;
use url::Url; use url::Url;
use nym_credential_storage::storage::Storage;
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
use nym_validator_client::nyxd::traits::DkgQueryClient; use validator_client::nyxd::traits::DkgQueryClient;
#[cfg(target_arch = "wasm32")] #[cfg(target_arch = "wasm32")]
use nym_bandwidth_controller::wasm_mockups::DkgQueryClient; use gateway_client::wasm_mockups::DkgQueryClient;
#[cfg(all(not(target_arch = "wasm32"), feature = "fs-surb-storage"))] #[cfg(all(not(target_arch = "wasm32"), feature = "fs-surb-storage"))]
pub mod non_wasm_helpers; pub mod non_wasm_helpers;
@@ -152,7 +151,7 @@ impl From<bool> for CredentialsToggle {
} }
} }
pub struct BaseClientBuilder<'a, B, C, St: Storage> { pub struct BaseClientBuilder<'a, B, C> {
// due to wasm limitations I had to split it like this : ( // due to wasm limitations I had to split it like this : (
gateway_config: &'a GatewayEndpointConfig, gateway_config: &'a GatewayEndpointConfig,
debug_config: &'a DebugConfig, debug_config: &'a DebugConfig,
@@ -161,22 +160,21 @@ pub struct BaseClientBuilder<'a, B, C, St: Storage> {
reply_storage_backend: B, reply_storage_backend: B,
custom_topology_provider: Option<Box<dyn TopologyProvider>>, custom_topology_provider: Option<Box<dyn TopologyProvider>>,
bandwidth_controller: Option<BandwidthController<C, St>>, bandwidth_controller: Option<BandwidthController<C>>,
key_manager: KeyManager, key_manager: KeyManager,
} }
impl<'a, B, C, St> BaseClientBuilder<'a, B, C, St> impl<'a, B, C> BaseClientBuilder<'a, B, C>
where where
B: ReplyStorageBackend + Send + Sync + 'static, B: ReplyStorageBackend + Send + Sync + 'static,
C: DkgQueryClient + Sync + Send + 'static, C: DkgQueryClient + Sync + Send + 'static,
St: Storage + 'static,
{ {
pub fn new_from_base_config<T>( pub fn new_from_base_config<T>(
base_config: &'a Config<T>, base_config: &'a Config<T>,
key_manager: KeyManager, key_manager: KeyManager,
bandwidth_controller: Option<BandwidthController<C, St>>, bandwidth_controller: Option<BandwidthController<C>>,
reply_storage_backend: B, reply_storage_backend: B,
) -> BaseClientBuilder<'a, B, C, St> { ) -> BaseClientBuilder<'a, B, C> {
BaseClientBuilder { BaseClientBuilder {
gateway_config: base_config.get_gateway_endpoint_config(), gateway_config: base_config.get_gateway_endpoint_config(),
debug_config: base_config.get_debug_config(), debug_config: base_config.get_debug_config(),
@@ -193,11 +191,11 @@ where
gateway_config: &'a GatewayEndpointConfig, gateway_config: &'a GatewayEndpointConfig,
debug_config: &'a DebugConfig, debug_config: &'a DebugConfig,
key_manager: KeyManager, key_manager: KeyManager,
bandwidth_controller: Option<BandwidthController<C, St>>, bandwidth_controller: Option<BandwidthController<C>>,
reply_storage_backend: B, reply_storage_backend: B,
credentials_toggle: CredentialsToggle, credentials_toggle: CredentialsToggle,
nym_api_endpoints: Vec<Url>, nym_api_endpoints: Vec<Url>,
) -> BaseClientBuilder<'a, B, C, St> { ) -> BaseClientBuilder<'a, B, C> {
BaseClientBuilder { BaseClientBuilder {
gateway_config, gateway_config,
debug_config, debug_config,
@@ -237,16 +235,21 @@ where
) { ) {
info!("Starting loop cover traffic stream..."); info!("Starting loop cover traffic stream...");
let stream = LoopCoverTrafficStream::new( let mut stream = LoopCoverTrafficStream::new(
ack_key, ack_key,
debug_config.acknowledgements.average_ack_delay, debug_config.acknowledgements.average_ack_delay,
debug_config.traffic.average_packet_delay,
debug_config.cover_traffic.loop_cover_traffic_average_delay,
mix_tx, mix_tx,
self_address, self_address,
topology_accessor, topology_accessor,
debug_config.traffic,
debug_config.cover_traffic,
); );
if let Some(size) = debug_config.traffic.use_extended_packet_size {
log::debug!("Setting extended packet size: {:?}", size);
stream.set_custom_packet_size(size.into());
}
stream.start_with_shutdown(shutdown); stream.start_with_shutdown(shutdown);
} }
@@ -308,7 +311,7 @@ where
mixnet_message_sender: MixnetMessageSender, mixnet_message_sender: MixnetMessageSender,
ack_sender: AcknowledgementSender, ack_sender: AcknowledgementSender,
shutdown: TaskClient, shutdown: TaskClient,
) -> Result<GatewayClient<C, St>, ClientCoreError> { ) -> Result<GatewayClient<C>, ClientCoreError> {
let gateway_id = self.gateway_config.gateway_id.clone(); let gateway_id = self.gateway_config.gateway_id.clone();
if gateway_id.is_empty() { if gateway_id.is_empty() {
return Err(ClientCoreError::GatewayIdUnknown); return Err(ClientCoreError::GatewayIdUnknown);
@@ -405,7 +408,7 @@ where
// over it. Perhaps GatewayClient needs to be thread-shareable or have some channel for // over it. Perhaps GatewayClient needs to be thread-shareable or have some channel for
// requests? // requests?
fn start_mix_traffic_controller( fn start_mix_traffic_controller(
gateway_client: GatewayClient<C, St>, gateway_client: GatewayClient<C>,
shutdown: TaskClient, shutdown: TaskClient,
) -> BatchMixMessageSender { ) -> BatchMixMessageSender {
info!("Starting mix traffic controller..."); info!("Starting mix traffic controller...");
@@ -530,12 +533,17 @@ where
// primarily to throttle incoming connections (e.g socks5 for attached network-requesters) // primarily to throttle incoming connections (e.g socks5 for attached network-requesters)
let shared_lane_queue_lengths = LaneQueueLengths::new(); let shared_lane_queue_lengths = LaneQueueLengths::new();
let controller_config = real_messages_control::Config::new( let mut controller_config = real_messages_control::Config::new(
self.debug_config, self.debug_config,
self.key_manager.ack_key(), self.key_manager.ack_key(),
self_address, self_address,
); );
if let Some(size) = self.debug_config.traffic.use_extended_packet_size {
log::debug!("Setting extended packet size: {:?}", size);
controller_config.set_custom_packet_size(size.into());
}
Self::start_real_traffic_controller( Self::start_real_traffic_controller(
controller_config, controller_config,
shared_topology_accessor.clone(), shared_topology_accessor.clone(),
@@ -3,7 +3,7 @@
use crate::client::mix_traffic::BatchMixMessageSender; use crate::client::mix_traffic::BatchMixMessageSender;
use crate::client::topology_control::TopologyAccessor; use crate::client::topology_control::TopologyAccessor;
use crate::{config, spawn_future}; use crate::spawn_future;
use futures::task::{Context, Poll}; use futures::task::{Context, Poll};
use futures::{Future, Stream, StreamExt}; use futures::{Future, Stream, StreamExt};
use log::*; use log::*;
@@ -34,8 +34,11 @@ where
/// Average delay an acknowledgement packet is going to get delay at a single mixnode. /// Average delay an acknowledgement packet is going to get delay at a single mixnode.
average_ack_delay: Duration, average_ack_delay: Duration,
/// Defines configuration options related to cover traffic. /// Average delay a data packet is going to get delay at a single mixnode.
cover_traffic: config::CoverTraffic, average_packet_delay: Duration,
/// Average delay between sending subsequent cover packets.
average_cover_message_sending_delay: Duration,
/// Internal state, determined by `average_message_sending_delay`, /// Internal state, determined by `average_message_sending_delay`,
/// used to keep track of when a next packet should be sent out. /// used to keep track of when a next packet should be sent out.
@@ -58,11 +61,8 @@ where
/// Accessor to the common instance of network topology. /// Accessor to the common instance of network topology.
topology_access: TopologyAccessor, topology_access: TopologyAccessor,
/// Primary predefined packet size used for the loop cover messages. /// Predefined packet size used for the loop cover messages.
primary_packet_size: PacketSize, packet_size: PacketSize,
/// Optional secondary predefined packet size used for the loop cover messages.
secondary_packet_size: Option<PacketSize>,
} }
impl<R> Stream for LoopCoverTrafficStream<R> impl<R> Stream for LoopCoverTrafficStream<R>
@@ -83,7 +83,7 @@ where
// we know it's time to send a message, so let's prepare delay for the next one // we know it's time to send a message, so let's prepare delay for the next one
// Get the `now` by looking at the current `delay` deadline // Get the `now` by looking at the current `delay` deadline
let avg_delay = self.cover_traffic.loop_cover_traffic_average_delay; let avg_delay = self.average_cover_message_sending_delay;
let next_poisson_delay = sample_poisson_duration(&mut self.rng, avg_delay); let next_poisson_delay = sample_poisson_duration(&mut self.rng, avg_delay);
// The next interval value is `next_poisson_delay` after the one that just // The next interval value is `next_poisson_delay` after the one that just
@@ -107,14 +107,15 @@ where
// obviously when we finally make shared rng that is on 'higher' level, this should become // obviously when we finally make shared rng that is on 'higher' level, this should become
// generic `R` // generic `R`
impl LoopCoverTrafficStream<OsRng> { impl LoopCoverTrafficStream<OsRng> {
#[allow(clippy::too_many_arguments)]
pub fn new( pub fn new(
ack_key: Arc<AckKey>, ack_key: Arc<AckKey>,
average_ack_delay: Duration, average_ack_delay: Duration,
average_packet_delay: Duration,
average_cover_message_sending_delay: Duration,
mix_tx: BatchMixMessageSender, mix_tx: BatchMixMessageSender,
our_full_destination: Recipient, our_full_destination: Recipient,
topology_access: TopologyAccessor, topology_access: TopologyAccessor,
traffic_config: config::Traffic,
cover_config: config::CoverTraffic,
) -> Self { ) -> Self {
let rng = OsRng; let rng = OsRng;
@@ -127,17 +128,21 @@ impl LoopCoverTrafficStream<OsRng> {
LoopCoverTrafficStream { LoopCoverTrafficStream {
ack_key, ack_key,
average_ack_delay, average_ack_delay,
cover_traffic: cover_config, average_packet_delay,
average_cover_message_sending_delay,
next_delay, next_delay,
mix_tx, mix_tx,
our_full_destination, our_full_destination,
rng, rng,
topology_access, topology_access,
primary_packet_size: traffic_config.primary_packet_size, packet_size: Default::default(),
secondary_packet_size: traffic_config.secondary_packet_size,
} }
} }
pub fn set_custom_packet_size(&mut self, packet_size: PacketSize) {
self.packet_size = packet_size;
}
fn set_next_delay(&mut self, amount: Duration) { fn set_next_delay(&mut self, amount: Duration) {
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
let next_delay = Box::pin(time::sleep(amount)); let next_delay = Box::pin(time::sleep(amount));
@@ -148,28 +153,9 @@ impl LoopCoverTrafficStream<OsRng> {
self.next_delay = next_delay; self.next_delay = next_delay;
} }
fn loop_cover_message_size(&mut self) -> PacketSize {
let Some(secondary_packet_size) = self.secondary_packet_size else {
return self.primary_packet_size
};
let use_primary = self
.rng
.gen_bool(self.cover_traffic.cover_traffic_primary_size_ratio);
if use_primary {
self.primary_packet_size
} else {
secondary_packet_size
}
}
async fn on_new_message(&mut self) { async fn on_new_message(&mut self) {
trace!("next cover message!"); trace!("next cover message!");
let cover_traffic_packet_size = self.loop_cover_message_size();
trace!("the next loop cover message will be put in a {cover_traffic_packet_size} packet");
// TODO for way down the line: in very rare cases (during topology update) we might have // TODO for way down the line: in very rare cases (during topology update) we might have
// to wait a really tiny bit before actually obtaining the permit hence messing with our // to wait a really tiny bit before actually obtaining the permit hence messing with our
// poisson delay, but is it really a problem? // poisson delay, but is it really a problem?
@@ -192,8 +178,8 @@ impl LoopCoverTrafficStream<OsRng> {
&self.ack_key, &self.ack_key,
&self.our_full_destination, &self.our_full_destination,
self.average_ack_delay, self.average_ack_delay,
self.cover_traffic.loop_cover_traffic_average_delay, self.average_packet_delay,
cover_traffic_packet_size, self.packet_size,
) )
.expect("Somehow failed to generate a loop cover message with a valid topology"); .expect("Somehow failed to generate a loop cover message with a valid topology");
@@ -203,6 +189,10 @@ impl LoopCoverTrafficStream<OsRng> {
// This isn't a problem, if the channel is full means we're already sending the // This isn't a problem, if the channel is full means we're already sending the
// max amount of messages downstream can handle. // max amount of messages downstream can handle.
log::debug!("Failed to send cover message - channel full"); log::debug!("Failed to send cover message - channel full");
// However it's still useful to alert the user that the gateway or the link to
// the gateway can't keep up. Either due to insufficient bandwidth on the
// client side, or that the gateway is overloaded.
log::warn!("Failed to send sphinx packet - gateway or connection to gateway can't keep up");
} }
TrySendError::Closed(_) => { TrySendError::Closed(_) => {
log::warn!("Failed to send cover message - channel closed"); log::warn!("Failed to send cover message - channel closed");
@@ -224,17 +214,9 @@ impl LoopCoverTrafficStream<OsRng> {
} }
pub fn start_with_shutdown(mut self, mut shutdown: nym_task::TaskClient) { pub fn start_with_shutdown(mut self, mut shutdown: nym_task::TaskClient) {
if self.cover_traffic.disable_loop_cover_traffic_stream {
// we should have never got here in the first place - the task should have never been created to begin with
// so panic and review the code that lead to this branch
panic!("attempted to start LoopCoverTrafficStream while config explicitly disabled it.")
}
// we should set initial delay only when we actually start the stream // we should set initial delay only when we actually start the stream
let sampled = sample_poisson_duration( let sampled =
&mut self.rng, sample_poisson_duration(&mut self.rng, self.average_cover_message_sending_delay);
self.cover_traffic.loop_cover_traffic_average_delay,
);
self.set_next_delay(sampled); self.set_next_delay(sampled);
spawn_future(async move { spawn_future(async move {
+1 -1
View File
@@ -2,9 +2,9 @@
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use crate::config::persistence::key_pathfinder::ClientKeyPathfinder; use crate::config::persistence::key_pathfinder::ClientKeyPathfinder;
use gateway_requests::registration::handshake::SharedKeys;
use log::*; use log::*;
use nym_crypto::asymmetric::{encryption, identity}; use nym_crypto::asymmetric::{encryption, identity};
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::io; use std::io;
+8 -10
View File
@@ -2,16 +2,15 @@
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use crate::spawn_future; use crate::spawn_future;
use gateway_client::GatewayClient;
use log::*; use log::*;
use nym_gateway_client::GatewayClient;
use nym_sphinx::forwarding::packet::MixPacket; use nym_sphinx::forwarding::packet::MixPacket;
use nym_credential_storage::storage::Storage;
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
use nym_validator_client::nyxd::traits::DkgQueryClient; use validator_client::nyxd::traits::DkgQueryClient;
#[cfg(target_arch = "wasm32")] #[cfg(target_arch = "wasm32")]
use nym_bandwidth_controller::wasm_mockups::DkgQueryClient; use gateway_client::wasm_mockups::DkgQueryClient;
pub type BatchMixMessageSender = tokio::sync::mpsc::Sender<Vec<MixPacket>>; pub type BatchMixMessageSender = tokio::sync::mpsc::Sender<Vec<MixPacket>>;
pub type BatchMixMessageReceiver = tokio::sync::mpsc::Receiver<Vec<MixPacket>>; pub type BatchMixMessageReceiver = tokio::sync::mpsc::Receiver<Vec<MixPacket>>;
@@ -20,10 +19,10 @@ pub type BatchMixMessageReceiver = tokio::sync::mpsc::Receiver<Vec<MixPacket>>;
pub const MIX_MESSAGE_RECEIVER_BUFFER_SIZE: usize = 32; pub const MIX_MESSAGE_RECEIVER_BUFFER_SIZE: usize = 32;
const MAX_FAILURE_COUNT: usize = 100; const MAX_FAILURE_COUNT: usize = 100;
pub struct MixTrafficController<C, St: Storage> { pub struct MixTrafficController<C> {
// TODO: most likely to be replaced by some higher level construct as // TODO: most likely to be replaced by some higher level construct as
// later on gateway_client will need to be accessible by other entities // later on gateway_client will need to be accessible by other entities
gateway_client: GatewayClient<C, St>, gateway_client: GatewayClient<C>,
mix_rx: BatchMixMessageReceiver, mix_rx: BatchMixMessageReceiver,
// TODO: this is temporary work-around. // TODO: this is temporary work-around.
@@ -31,14 +30,13 @@ pub struct MixTrafficController<C, St: Storage> {
consecutive_gateway_failure_count: usize, consecutive_gateway_failure_count: usize,
} }
impl<C, St> MixTrafficController<C, St> impl<C> MixTrafficController<C>
where where
C: DkgQueryClient + Sync + Send + 'static, C: DkgQueryClient + Sync + Send + 'static,
St: Storage + 'static,
{ {
pub fn new( pub fn new(
gateway_client: GatewayClient<C, St>, gateway_client: GatewayClient<C>,
) -> (MixTrafficController<C, St>, BatchMixMessageSender) { ) -> (MixTrafficController<C>, BatchMixMessageSender) {
let (sphinx_message_sender, sphinx_message_receiver) = let (sphinx_message_sender, sphinx_message_receiver) =
tokio::sync::mpsc::channel(MIX_MESSAGE_RECEIVER_BUFFER_SIZE); tokio::sync::mpsc::channel(MIX_MESSAGE_RECEIVER_BUFFER_SIZE);
( (
@@ -3,8 +3,8 @@
use super::action_controller::{AckActionSender, Action}; use super::action_controller::{AckActionSender, Action};
use futures::StreamExt; use futures::StreamExt;
use gateway_client::AcknowledgementReceiver;
use log::*; use log::*;
use nym_gateway_client::AcknowledgementReceiver;
use nym_sphinx::{ use nym_sphinx::{
acknowledgements::{identifier::recover_identifier, AckKey}, acknowledgements::{identifier::recover_identifier, AckKey},
chunking::fragment::{FragmentIdentifier, COVER_FRAG_ID}, chunking::fragment::{FragmentIdentifier, COVER_FRAG_ID},
@@ -13,8 +13,8 @@ use crate::client::replies::reply_controller::ReplyControllerSender;
use crate::spawn_future; use crate::spawn_future;
use action_controller::AckActionReceiver; use action_controller::AckActionReceiver;
use futures::channel::mpsc; use futures::channel::mpsc;
use gateway_client::AcknowledgementReceiver;
use log::*; use log::*;
use nym_gateway_client::AcknowledgementReceiver;
use nym_sphinx::anonymous_replies::requests::AnonymousSenderTag; use nym_sphinx::anonymous_replies::requests::AnonymousSenderTag;
use nym_sphinx::params::PacketSize; use nym_sphinx::params::PacketSize;
use nym_sphinx::{ use nym_sphinx::{
@@ -101,11 +101,8 @@ pub(crate) struct Config {
/// Note that it does not include gateway hops. /// Note that it does not include gateway hops.
num_mix_hops: u8, num_mix_hops: u8,
/// Primary predefined packet size used for the encapsulated messages. /// Predefined packet size used for the encapsulated messages.
primary_packet_size: PacketSize, packet_size: PacketSize,
/// Optional secondary predefined packet size used for the encapsulated messages.
secondary_packet_size: Option<PacketSize>,
} }
impl Config { impl Config {
@@ -121,8 +118,7 @@ impl Config {
average_packet_delay, average_packet_delay,
average_ack_delay, average_ack_delay,
num_mix_hops: DEFAULT_NUM_MIX_HOPS, num_mix_hops: DEFAULT_NUM_MIX_HOPS,
primary_packet_size: PacketSize::default(), packet_size: PacketSize::default(),
secondary_packet_size: None,
} }
} }
@@ -134,14 +130,8 @@ impl Config {
} }
/// Allows setting non-default size of the sphinx packets sent out. /// Allows setting non-default size of the sphinx packets sent out.
pub fn with_custom_primary_packet_size(mut self, packet_size: PacketSize) -> Self { pub fn with_custom_packet_size(mut self, packet_size: PacketSize) -> Self {
self.primary_packet_size = packet_size; self.packet_size = packet_size;
self
}
/// Allows setting non-default size of the sphinx packets sent out.
pub fn with_custom_secondary_packet_size(mut self, packet_size: Option<PacketSize>) -> Self {
self.secondary_packet_size = packet_size;
self self
} }
} }
@@ -180,6 +170,7 @@ where
config.average_packet_delay, config.average_packet_delay,
config.average_ack_delay, config.average_ack_delay,
) )
.with_custom_real_message_packet_size(config.packet_size)
.with_mix_hops(config.num_mix_hops); .with_mix_hops(config.num_mix_hops);
MessageHandler { MessageHandler {
@@ -220,28 +211,6 @@ where
} }
} }
fn optimal_packet_size(&self, msg: &NymMessage) -> PacketSize {
// if secondary packet was never set, then it's obvious we have to use the primary packet
let Some(secondary_packet) = self.config.secondary_packet_size else {
trace!("only primary packet size is available");
return self.config.primary_packet_size
};
let primary_count =
msg.required_packets(self.config.primary_packet_size, self.config.num_mix_hops);
let secondary_count = msg.required_packets(secondary_packet, self.config.num_mix_hops);
trace!("This message would require: {primary_count} primary packets or {secondary_count} secondary packets...");
// if there would be no benefit in using the secondary packet - use the primary (duh)
if primary_count <= secondary_count {
trace!("so choosing primary for this message");
self.config.primary_packet_size
} else {
trace!("so choosing secondary for this message");
secondary_packet
}
}
async fn generate_reply_surbs_with_keys( async fn generate_reply_surbs_with_keys(
&mut self, &mut self,
amount: usize, amount: usize,
@@ -268,13 +237,9 @@ where
reply_surb: ReplySurb, reply_surb: ReplySurb,
is_extra_surb_request: bool, is_extra_surb_request: bool,
) -> Result<(), SurbWrappedPreparationError> { ) -> Result<(), SurbWrappedPreparationError> {
let msg = NymMessage::new_reply(message);
let packet_size = self.optimal_packet_size(&msg);
debug!("Using {packet_size} packets for {msg}");
let mut fragment = self let mut fragment = self
.message_preparer .message_preparer
.pad_and_split_message(msg, packet_size); .pad_and_split_message(NymMessage::new_reply(message));
if fragment.len() > 1 { if fragment.len() > 1 {
// well, it's not a single surb message // well, it's not a single surb message
return Err(SurbWrappedPreparationError { return Err(SurbWrappedPreparationError {
@@ -324,12 +289,10 @@ where
// // TODO: this will require additional argument to make it use different variant of `ReplyMessage` // // TODO: this will require additional argument to make it use different variant of `ReplyMessage`
pub(crate) fn split_reply_message(&mut self, message: Vec<u8>) -> Vec<Fragment> { pub(crate) fn split_reply_message(&mut self, message: Vec<u8>) -> Vec<Fragment> {
let msg = NymMessage::new_reply(ReplyMessage::new_data_message(message));
let packet_size = self.optimal_packet_size(&msg);
debug!("Using {packet_size} packets for {msg}");
self.message_preparer self.message_preparer
.pad_and_split_message(msg, packet_size) .pad_and_split_message(NymMessage::new_reply(ReplyMessage::new_data_message(
message,
)))
} }
pub(crate) async fn send_retransmission_reply_chunks( pub(crate) async fn send_retransmission_reply_chunks(
@@ -425,11 +388,7 @@ where
let topology_permit = self.topology_access.get_read_permit().await; let topology_permit = self.topology_access.get_read_permit().await;
let topology = self.get_topology(&topology_permit)?; let topology = self.get_topology(&topology_permit)?;
let packet_size = self.optimal_packet_size(&message); let fragments = self.message_preparer.pad_and_split_message(message);
debug!("Using {packet_size} packets for {message}");
let fragments = self
.message_preparer
.pad_and_split_message(message, packet_size);
let mut pending_acks = Vec::with_capacity(fragments.len()); let mut pending_acks = Vec::with_capacity(fragments.len());
let mut real_messages = Vec::with_capacity(fragments.len()); let mut real_messages = Vec::with_capacity(fragments.len());
@@ -1,4 +1,4 @@
// Copyright 2021-2023 - 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
// INPUT: InputMessage from user // INPUT: InputMessage from user
@@ -22,13 +22,15 @@ use crate::{
spawn_future, spawn_future,
}; };
use futures::channel::mpsc; use futures::channel::mpsc;
use gateway_client::AcknowledgementReceiver;
use log::*; use log::*;
use nym_gateway_client::AcknowledgementReceiver;
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::params::PacketSize;
use nym_task::connections::{ConnectionCommandReceiver, LaneQueueLengths}; use nym_task::connections::{ConnectionCommandReceiver, LaneQueueLengths};
use rand::{rngs::OsRng, CryptoRng, Rng}; use rand::{rngs::OsRng, CryptoRng, Rng};
use std::sync::Arc; use std::sync::Arc;
use std::time::Duration;
use crate::client::replies::reply_controller; use crate::client::replies::reply_controller;
use crate::config; use crate::config;
@@ -43,29 +45,61 @@ pub struct Config {
/// Key used to decrypt contents of received SURBAcks /// Key used to decrypt contents of received SURBAcks
ack_key: Arc<AckKey>, ack_key: Arc<AckKey>,
/// Given ack timeout in the form a * BASE_DELAY + b, it specifies the additive part `b`
ack_wait_addition: Duration,
/// Given ack timeout in the form a * BASE_DELAY + b, it specifies the multiplier `a`
ack_wait_multiplier: f64,
/// Address of `this` client. /// Address of `this` client.
self_recipient: Recipient, self_recipient: Recipient,
/// Specifies all traffic related configuration options. /// Average delay between sending subsequent packets from this client.
traffic: config::Traffic, average_message_sending_delay: Duration,
/// Specifies all cover traffic related configuration options. /// Average delay a data packet is going to get delayed at a single mixnode.
cover_traffic: config::CoverTraffic, average_packet_delay_duration: Duration,
/// Specifies all acknowledgements related configuration options. /// Average delay an acknowledgement packet is going to get delayed at a single mixnode.
acks: config::Acknowledgements, average_ack_delay_duration: Duration,
/// Specifies all reply SURBs related configuration options. /// Controls whether the main packet stream constantly produces packets according to the predefined
reply_surbs: config::ReplySurbs, /// poisson distribution.
disable_main_poisson_packet_distribution: bool,
/// Predefined packet size used for the encapsulated messages.
packet_size: PacketSize,
/// Defines the minimum number of reply surbs the client would request.
minimum_reply_surb_request_size: u32,
/// Defines the maximum number of reply surbs the client would request.
maximum_reply_surb_request_size: u32,
/// Defines the maximum number of reply surbs a remote party is allowed to request from this client at once.
maximum_allowed_reply_surb_request_size: u32,
/// Defines maximum amount of time the client is going to wait for reply surbs before explicitly asking
/// for more even though in theory they wouldn't need to.
maximum_reply_surb_rerequest_waiting_period: Duration,
/// Defines maximum amount of time the client is going to wait for reply surbs before
/// deciding it's never going to get them and would drop all pending messages
maximum_reply_surb_drop_waiting_period: Duration,
/// Defines maximum amount of time given reply surb is going to be valid for.
/// This is going to be superseded by key rotation once implemented.
maximum_reply_surb_age: Duration,
/// Defines maximum amount of time given reply key is going to be valid for.
/// This is going to be superseded by key rotation once implemented.
maximum_reply_key_age: Duration,
} }
impl<'a> From<&'a Config> for acknowledgement_control::Config { impl<'a> From<&'a Config> for acknowledgement_control::Config {
fn from(cfg: &'a Config) -> Self { fn from(cfg: &'a Config) -> Self {
acknowledgement_control::Config::new( acknowledgement_control::Config::new(cfg.ack_wait_addition, cfg.ack_wait_multiplier)
cfg.acks.ack_wait_addition, .with_custom_packet_size(cfg.packet_size)
cfg.acks.ack_wait_multiplier,
)
.with_custom_packet_size(cfg.traffic.primary_packet_size)
} }
} }
@@ -74,16 +108,26 @@ impl<'a> From<&'a Config> for real_traffic_stream::Config {
real_traffic_stream::Config::new( real_traffic_stream::Config::new(
Arc::clone(&cfg.ack_key), Arc::clone(&cfg.ack_key),
cfg.self_recipient, cfg.self_recipient,
cfg.acks.average_ack_delay, cfg.average_ack_delay_duration,
cfg.traffic, cfg.average_packet_delay_duration,
cfg.cover_traffic.cover_traffic_primary_size_ratio, cfg.average_message_sending_delay,
cfg.disable_main_poisson_packet_distribution,
) )
.with_custom_cover_packet_size(cfg.packet_size)
} }
} }
impl<'a> From<&'a Config> for reply_controller::Config { impl<'a> From<&'a Config> for reply_controller::Config {
fn from(cfg: &'a Config) -> Self { fn from(cfg: &'a Config) -> Self {
reply_controller::Config::new(cfg.reply_surbs) reply_controller::Config::new(
cfg.minimum_reply_surb_request_size,
cfg.maximum_reply_surb_request_size,
cfg.maximum_allowed_reply_surb_request_size,
cfg.maximum_reply_surb_rerequest_waiting_period,
cfg.maximum_reply_surb_drop_waiting_period,
cfg.maximum_reply_surb_age,
cfg.maximum_reply_key_age,
)
} }
} }
@@ -92,11 +136,10 @@ impl<'a> From<&'a Config> for message_handler::Config {
message_handler::Config::new( message_handler::Config::new(
Arc::clone(&cfg.ack_key), Arc::clone(&cfg.ack_key),
cfg.self_recipient, cfg.self_recipient,
cfg.traffic.average_packet_delay, cfg.average_packet_delay_duration,
cfg.acks.average_ack_delay, cfg.average_ack_delay_duration,
) )
.with_custom_primary_packet_size(cfg.traffic.primary_packet_size) .with_custom_packet_size(cfg.packet_size)
.with_custom_secondary_packet_size(cfg.traffic.secondary_packet_size)
} }
} }
@@ -109,12 +152,42 @@ impl Config {
Config { Config {
ack_key, ack_key,
self_recipient, self_recipient,
traffic: base_client_debug_config.traffic, packet_size: Default::default(),
cover_traffic: base_client_debug_config.cover_traffic, ack_wait_addition: base_client_debug_config.acknowledgements.ack_wait_addition,
acks: base_client_debug_config.acknowledgements, ack_wait_multiplier: base_client_debug_config
reply_surbs: base_client_debug_config.reply_surbs, .acknowledgements
.ack_wait_multiplier,
average_message_sending_delay: base_client_debug_config
.traffic
.message_sending_average_delay,
average_packet_delay_duration: base_client_debug_config.traffic.average_packet_delay,
average_ack_delay_duration: base_client_debug_config.acknowledgements.average_ack_delay,
disable_main_poisson_packet_distribution: base_client_debug_config
.traffic
.disable_main_poisson_packet_distribution,
minimum_reply_surb_request_size: base_client_debug_config
.reply_surbs
.minimum_reply_surb_request_size,
maximum_reply_surb_request_size: base_client_debug_config
.reply_surbs
.maximum_reply_surb_request_size,
maximum_allowed_reply_surb_request_size: base_client_debug_config
.reply_surbs
.maximum_allowed_reply_surb_request_size,
maximum_reply_surb_rerequest_waiting_period: base_client_debug_config
.reply_surbs
.maximum_reply_surb_rerequest_waiting_period,
maximum_reply_surb_drop_waiting_period: base_client_debug_config
.reply_surbs
.maximum_reply_surb_drop_waiting_period,
maximum_reply_surb_age: base_client_debug_config.reply_surbs.maximum_reply_surb_age,
maximum_reply_key_age: base_client_debug_config.reply_surbs.maximum_reply_key_age,
} }
} }
pub fn set_custom_packet_size(&mut self, packet_size: PacketSize) {
self.packet_size = packet_size;
}
} }
pub(crate) struct RealMessagesController<R> pub(crate) struct RealMessagesController<R>
@@ -6,7 +6,6 @@ use crate::client::mix_traffic::BatchMixMessageSender;
use crate::client::real_messages_control::acknowledgement_control::SentPacketNotificationSender; use crate::client::real_messages_control::acknowledgement_control::SentPacketNotificationSender;
use crate::client::topology_control::TopologyAccessor; use crate::client::topology_control::TopologyAccessor;
use crate::client::transmission_buffer::TransmissionBuffer; use crate::client::transmission_buffer::TransmissionBuffer;
use crate::config;
use futures::task::{Context, Poll}; use futures::task::{Context, Poll};
use futures::{Future, Stream, StreamExt}; use futures::{Future, Stream, StreamExt};
use log::*; use log::*;
@@ -28,6 +27,7 @@ use std::time::Duration;
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
use tokio::time; use tokio::time;
#[cfg(target_arch = "wasm32")] #[cfg(target_arch = "wasm32")]
use wasm_timer; use wasm_timer;
@@ -44,12 +44,18 @@ pub(crate) struct Config {
/// Average delay an acknowledgement packet is going to get delay at a single mixnode. /// Average delay an acknowledgement packet is going to get delay at a single mixnode.
average_ack_delay: Duration, average_ack_delay: Duration,
/// Defines all configuration options related to this traffic stream. /// Average delay a data packet is going to get delay at a single mixnode.
traffic: config::Traffic, average_packet_delay: Duration,
/// Specifies the ratio of `primary_packet_size` to `secondary_packet_size` used in cover traffic. /// Average delay between sending subsequent packets.
/// Only applicable if `secondary_packet_size` is enabled. average_message_sending_delay: Duration,
cover_traffic_primary_size_ratio: f64,
/// Controls whether the stream constantly produces packets according to the predefined
/// poisson distribution.
disable_poisson_packet_distribution: bool,
/// Predefined packet size used for the loop cover messages.
cover_packet_size: PacketSize,
} }
impl Config { impl Config {
@@ -57,17 +63,25 @@ impl Config {
ack_key: Arc<AckKey>, ack_key: Arc<AckKey>,
our_full_destination: Recipient, our_full_destination: Recipient,
average_ack_delay: Duration, average_ack_delay: Duration,
traffic: config::Traffic, average_packet_delay: Duration,
cover_traffic_primary_size_ratio: f64, average_message_sending_delay: Duration,
disable_poisson_packet_distribution: bool,
) -> Self { ) -> Self {
Config { Config {
ack_key, ack_key,
our_full_destination, our_full_destination,
average_ack_delay, average_ack_delay,
traffic, average_packet_delay,
cover_traffic_primary_size_ratio, average_message_sending_delay,
disable_poisson_packet_distribution,
cover_packet_size: Default::default(),
} }
} }
pub fn with_custom_cover_packet_size(mut self, packet_size: PacketSize) -> Self {
self.cover_packet_size = packet_size;
self
}
} }
pub(crate) struct OutQueueControl<R> pub(crate) struct OutQueueControl<R>
@@ -198,30 +212,11 @@ where
self.sent_notifier.unbounded_send(frag_id).unwrap(); self.sent_notifier.unbounded_send(frag_id).unwrap();
} }
fn loop_cover_message_size(&mut self) -> PacketSize {
let Some(secondary_packet_size) = self.config.traffic.secondary_packet_size else {
return self.config.traffic.primary_packet_size
};
let use_primary = self
.rng
.gen_bool(self.config.cover_traffic_primary_size_ratio);
if use_primary {
self.config.traffic.primary_packet_size
} else {
secondary_packet_size
}
}
async fn on_message(&mut self, next_message: StreamMessage) { async fn on_message(&mut self, next_message: StreamMessage) {
trace!("created new message"); trace!("created new message");
let (next_message, fragment_id) = match next_message { let (next_message, fragment_id) = match next_message {
StreamMessage::Cover => { StreamMessage::Cover => {
let cover_traffic_packet_size = self.loop_cover_message_size();
trace!("the next loop cover message will be put in a {cover_traffic_packet_size} packet");
// TODO for way down the line: in very rare cases (during topology update) we might have // TODO for way down the line: in very rare cases (during topology update) we might have
// to wait a really tiny bit before actually obtaining the permit hence messing with our // to wait a really tiny bit before actually obtaining the permit hence messing with our
// poisson delay, but is it really a problem? // poisson delay, but is it really a problem?
@@ -245,8 +240,8 @@ where
&self.config.ack_key, &self.config.ack_key,
&self.config.our_full_destination, &self.config.our_full_destination,
self.config.average_ack_delay, self.config.average_ack_delay,
self.config.traffic.average_packet_delay, self.config.average_packet_delay,
cover_traffic_packet_size, self.config.cover_packet_size,
) )
.expect( .expect(
"Somehow failed to generate a loop cover message with a valid topology", "Somehow failed to generate a loop cover message with a valid topology",
@@ -291,7 +286,7 @@ where
} }
fn current_average_message_sending_delay(&self) -> Duration { fn current_average_message_sending_delay(&self) -> Duration {
self.config.traffic.message_sending_average_delay self.config.average_message_sending_delay
* self.sending_delay_controller.current_multiplier() * self.sending_delay_controller.current_multiplier()
} }
@@ -302,34 +297,24 @@ where
self.sending_delay_controller.current_multiplier() self.sending_delay_controller.current_multiplier()
); );
if self // Even just a single used slot is enough to signal backpressure
.sending_delay_controller if used_slots > 0 {
.is_backpressure_currently_detected(used_slots)
{
log::trace!("Backpressure detected"); log::trace!("Backpressure detected");
self.sending_delay_controller.record_backpressure_detected(); self.sending_delay_controller.record_backpressure_detected();
} }
// If the buffer is running out, slow down the sending rate by increasing the delay // If the buffer is running out, slow down the sending rate
// multiplier.
if self.mix_tx.capacity() == 0 if self.mix_tx.capacity() == 0
&& self.sending_delay_controller.not_increased_delay_recently() && self.sending_delay_controller.not_increased_delay_recently()
{ {
self.sending_delay_controller.increase_delay_multiplier(); self.sending_delay_controller.increase_delay_multiplier();
} }
// If it looks like we are sending reliably, increase the sending rate by decreasing the // Very carefully step up the sending rate in case it seems like we can solidly handle the
// sending delay multiplier. // current rate.
if !self if self.sending_delay_controller.is_sending_reliable() {
.sending_delay_controller
.was_backpressure_detected_recently()
&& self.sending_delay_controller.not_decreased_delay_recently()
{
self.sending_delay_controller.decrease_delay_multiplier(); self.sending_delay_controller.decrease_delay_multiplier();
} }
// Keep track of multiplier changes, and log if necessary.
self.sending_delay_controller.record_delay_multiplier();
} }
fn pop_next_message(&mut self) -> Option<RealMessage> { fn pop_next_message(&mut self) -> Option<RealMessage> {
@@ -415,10 +400,8 @@ where
// we never set an initial delay - let's do it now // we never set an initial delay - let's do it now
cx.waker().wake_by_ref(); cx.waker().wake_by_ref();
let sampled = sample_poisson_duration( let sampled =
&mut self.rng, sample_poisson_duration(&mut self.rng, self.config.average_message_sending_delay);
self.config.traffic.message_sending_average_delay,
);
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
let next_delay = Box::pin(time::sleep(sampled)); let next_delay = Box::pin(time::sleep(sampled));
@@ -469,7 +452,7 @@ where
mut self: Pin<&mut Self>, mut self: Pin<&mut Self>,
cx: &mut Context<'_>, cx: &mut Context<'_>,
) -> Poll<Option<StreamMessage>> { ) -> Poll<Option<StreamMessage>> {
if self.config.traffic.disable_main_poisson_packet_distribution { if self.config.disable_poisson_packet_distribution {
self.poll_immediate(cx) self.poll_immediate(cx)
} else { } else {
self.poll_poisson(cx) self.poll_poisson(cx)
@@ -485,7 +468,7 @@ where
let lanes = self.transmission_buffer.num_lanes(); let lanes = self.transmission_buffer.num_lanes();
let mult = self.sending_delay_controller.current_multiplier(); let mult = self.sending_delay_controller.current_multiplier();
let delay = self.current_average_message_sending_delay().as_millis(); let delay = self.current_average_message_sending_delay().as_millis();
let status_str = if self.config.traffic.disable_main_poisson_packet_distribution { let status_str = if self.config.disable_poisson_packet_distribution {
format!("Status: {lanes} lanes, backlog: {backlog:.2} kiB ({packets}), no delay") format!("Status: {lanes} lanes, backlog: {backlog:.2} kiB ({packets}), no delay")
} else { } else {
format!( format!(
@@ -508,12 +491,23 @@ where
} }
} }
#[cfg(not(target_arch = "wasm32"))]
fn log_status_infrequent(&self) {
if self.sending_delay_controller.current_multiplier() > 1 {
log::warn!(
"Unable to send packets at the default rate - rate reduced by setting the delay multiplier set to: {}",
self.sending_delay_controller.current_multiplier()
);
}
}
pub(super) async fn run_with_shutdown(&mut self, mut shutdown: nym_task::TaskClient) { pub(super) async fn run_with_shutdown(&mut self, mut shutdown: nym_task::TaskClient) {
debug!("Started OutQueueControl with graceful shutdown support"); debug!("Started OutQueueControl with graceful shutdown support");
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
{ {
let mut status_timer = tokio::time::interval(Duration::from_secs(5)); let mut status_timer = tokio::time::interval(Duration::from_secs(5));
let mut infrequent_status_timer = tokio::time::interval(Duration::from_secs(60));
while !shutdown.is_shutdown() { while !shutdown.is_shutdown() {
tokio::select! { tokio::select! {
@@ -524,6 +518,9 @@ where
_ = status_timer.tick() => { _ = status_timer.tick() => {
self.log_status(&mut shutdown); self.log_status(&mut shutdown);
} }
_ = infrequent_status_timer.tick() => {
self.log_status_infrequent();
}
next_message = self.next() => if let Some(next_message) = next_message { next_message = self.next() => if let Some(next_message) = next_message {
self.on_message(next_message).await; self.on_message(next_message).await;
} else { } else {
@@ -11,20 +11,15 @@ const INCREASE_DELAY_MIN_CHANGE_INTERVAL_SECS: u64 = 1;
// The minimum time between decreasing the average delay between packets. We don't want to change // The minimum time between decreasing the average delay between packets. We don't want to change
// to quickly to keep things somewhat stable. Also there are buffers downstreams meaning we need to // to quickly to keep things somewhat stable. Also there are buffers downstreams meaning we need to
// wait a little to see the effect before we decrease further. // wait a little to see the effect before we decrease further.
const DECREASE_DELAY_MIN_CHANGE_INTERVAL_SECS: u64 = 2; const DECREASE_DELAY_MIN_CHANGE_INTERVAL_SECS: u64 = 30;
// The queue length that is required for us to register that backpressure occured. If there are
// more than this many packets waiting to be sent, we consider the channel to be under
// backpressure.
const BACKPRESSURE_THRESHOLD: usize = 10;
// If we enough time passes without any sign of backpressure in the channel, we can consider // If we enough time passes without any sign of backpressure in the channel, we can consider
// lowering the average delay. // lowering the average delay. The goal is to keep somewhat stable, rather than maxing out
const ACCEPTABLE_TIME_WITHOUT_BACKPRESSURE_SECS: u64 = 2; // bandwidth at all times.
const ACCEPTABLE_TIME_WITHOUT_BACKPRESSURE_SECS: u64 = 30;
// The maximum multiplier we apply to the base average Poisson delay. // The maximum multiplier we apply to the base average Poisson delay.
const MAX_DELAY_MULTIPLIER: u32 = 6; const MAX_DELAY_MULTIPLIER: u32 = 6;
// The minium multiplier we apply to the base average Poisson delay. // The minium multiplier we apply to the base average Poisson delay.
const MIN_DELAY_MULTIPLIER: u32 = 1; const MIN_DELAY_MULTIPLIER: u32 = 1;
// If the multipler increases we log it, but we don't want to log about it too often.
const INTERVAL_BETWEEN_WARNING_ABOUT_ELEVATED_MULTIPLIER_SECS: u64 = 60;
pub(crate) struct SendingDelayController { pub(crate) struct SendingDelayController {
/// Multiply the average sending delay. /// Multiply the average sending delay.
@@ -38,14 +33,6 @@ pub(crate) struct SendingDelayController {
/// Minimum delay multiplier /// Minimum delay multiplier
lower_bound: u32, lower_bound: u32,
/// We counter the number of times the multiplier has been elevated. If it is elevated for long
/// enough we need to log about it.
multiplier_elevated_counter: u32,
/// We can't log about the elevated multiplier too often, so we keep track of the last time we
/// did,
time_when_logged_about_elevated_multiplier: Instant,
/// To make sure we don't change the multiplier to fast, we limit a change to some duration /// To make sure we don't change the multiplier to fast, we limit a change to some duration
time_when_changed: Instant, time_when_changed: Instant,
@@ -68,9 +55,6 @@ impl SendingDelayController {
current_multiplier: MIN_DELAY_MULTIPLIER, current_multiplier: MIN_DELAY_MULTIPLIER,
upper_bound, upper_bound,
lower_bound, lower_bound,
multiplier_elevated_counter: 0,
time_when_logged_about_elevated_multiplier: now
- Duration::from_secs(INTERVAL_BETWEEN_WARNING_ABOUT_ELEVATED_MULTIPLIER_SECS),
time_when_changed: now, time_when_changed: now,
time_when_backpressure_detected: now, time_when_backpressure_detected: now,
} }
@@ -95,7 +79,7 @@ impl SendingDelayController {
self.current_multiplier = self.current_multiplier =
(self.current_multiplier + 1).clamp(self.lower_bound, self.upper_bound); (self.current_multiplier + 1).clamp(self.lower_bound, self.upper_bound);
self.time_when_changed = get_time_now(); self.time_when_changed = get_time_now();
log::debug!( log::warn!(
"Increasing sending delay multiplier to: {}", "Increasing sending delay multiplier to: {}",
self.current_multiplier self.current_multiplier
); );
@@ -116,58 +100,22 @@ impl SendingDelayController {
} }
} }
pub(crate) fn record_backpressure_detected(&mut self) {
self.time_when_backpressure_detected = get_time_now();
}
pub(crate) fn not_increased_delay_recently(&self) -> bool { pub(crate) fn not_increased_delay_recently(&self) -> bool {
get_time_now() get_time_now()
> self.time_when_changed + Duration::from_secs(INCREASE_DELAY_MIN_CHANGE_INTERVAL_SECS) > self.time_when_changed + Duration::from_secs(INCREASE_DELAY_MIN_CHANGE_INTERVAL_SECS)
} }
pub(crate) fn not_decreased_delay_recently(&self) -> bool { pub(crate) fn is_sending_reliable(&self) -> bool {
get_time_now()
> self.time_when_changed + Duration::from_secs(DECREASE_DELAY_MIN_CHANGE_INTERVAL_SECS)
}
pub(crate) fn is_backpressure_currently_detected(&self, queue_length: usize) -> bool {
queue_length > BACKPRESSURE_THRESHOLD
}
pub(crate) fn record_backpressure_detected(&mut self) {
self.time_when_backpressure_detected = get_time_now();
}
pub(crate) fn was_backpressure_detected_recently(&self) -> bool {
get_time_now()
< self.time_when_backpressure_detected
+ Duration::from_secs(ACCEPTABLE_TIME_WITHOUT_BACKPRESSURE_SECS)
}
pub(crate) fn record_delay_multiplier(&mut self) {
// Count the number of times the multiplier has been elevated.
let multiplier_elevated = self.current_multiplier - self.lower_bound;
if multiplier_elevated == 0 {
self.multiplier_elevated_counter = 0;
} else {
self.multiplier_elevated_counter += 1;
}
// If needed, log about the elevated multiplier.
let now = get_time_now(); let now = get_time_now();
if self.multiplier_elevated_counter > 20 let delay_change_interval = Duration::from_secs(DECREASE_DELAY_MIN_CHANGE_INTERVAL_SECS);
&& now let acceptable_time_without_backpressure =
> self.time_when_logged_about_elevated_multiplier Duration::from_secs(ACCEPTABLE_TIME_WITHOUT_BACKPRESSURE_SECS);
+ Duration::from_secs(INTERVAL_BETWEEN_WARNING_ABOUT_ELEVATED_MULTIPLIER_SECS)
{ now > self.time_when_backpressure_detected + acceptable_time_without_backpressure
let status_str = format!( && now > self.time_when_changed + delay_change_interval
"Poisson delay currently scaled by: {}",
self.current_multiplier()
);
if self.current_multiplier() > 0 {
log::debug!("{}", status_str);
} else if self.current_multiplier() > 1 {
log::info!("{}", status_str);
} else if self.current_multiplier() > 2 {
log::warn!("{}", status_str);
}
self.time_when_logged_about_elevated_multiplier = now;
}
} }
} }
@@ -7,10 +7,10 @@ use crate::spawn_future;
use futures::channel::mpsc; use futures::channel::mpsc;
use futures::lock::Mutex; use futures::lock::Mutex;
use futures::StreamExt; use futures::StreamExt;
use gateway_client::MixnetMessageReceiver;
use log::*; use log::*;
use nym_crypto::asymmetric::encryption; use nym_crypto::asymmetric::encryption;
use nym_crypto::Digest; use nym_crypto::Digest;
use nym_gateway_client::MixnetMessageReceiver;
use nym_sphinx::anonymous_replies::requests::{ use nym_sphinx::anonymous_replies::requests::{
RepliableMessage, RepliableMessageContent, ReplyMessage, ReplyMessageContent, RepliableMessage, RepliableMessageContent, ReplyMessage, ReplyMessageContent,
}; };
@@ -22,21 +22,38 @@ use time::OffsetDateTime;
use crate::client::helpers::new_interval_stream; use crate::client::helpers::new_interval_stream;
use crate::client::transmission_buffer::TransmissionBuffer; use crate::client::transmission_buffer::TransmissionBuffer;
use crate::config;
pub(crate) use requests::{ReplyControllerMessage, ReplyControllerReceiver, ReplyControllerSender}; pub(crate) use requests::{ReplyControllerMessage, ReplyControllerReceiver, ReplyControllerSender};
pub mod requests; pub mod requests;
// this is still left as a separate config so I wouldn't need to replace it everywhere
// plus its not unreasonable to think that we might need something outside config::ReplySurbs struct
pub struct Config { pub struct Config {
reply_surbs: config::ReplySurbs, min_surb_request_size: u32,
max_surb_request_size: u32,
maximum_allowed_reply_surb_request_size: u32,
max_surb_rerequest_waiting_period: Duration,
max_surb_drop_waiting_period: Duration,
max_reply_surb_age: Duration,
max_reply_key_age: Duration,
} }
impl Config { impl Config {
pub(crate) fn new(reply_surbs_cfg: config::ReplySurbs) -> Self { pub(crate) fn new(
min_surb_request_size: u32,
max_surb_request_size: u32,
maximum_allowed_reply_surb_request_size: u32,
max_surb_rerequest_waiting_period: Duration,
max_surb_drop_waiting_period: Duration,
max_reply_surb_age: Duration,
max_reply_key_age: Duration,
) -> Self {
Self { Self {
reply_surbs: reply_surbs_cfg, min_surb_request_size,
max_surb_request_size,
maximum_allowed_reply_surb_request_size,
max_surb_rerequest_waiting_period,
max_surb_drop_waiting_period,
max_reply_surb_age,
max_reply_key_age,
} }
} }
} }
@@ -492,17 +509,9 @@ where
} }
// 2. check whether the requested amount is within sane range // 2. check whether the requested amount is within sane range
if amount if amount > self.config.maximum_allowed_reply_surb_request_size {
> self warn!("The requested reply surb amount is larger than our maximum allowed ({amount} > {}). Lowering it to a more sane value...", self.config.maximum_allowed_reply_surb_request_size);
.config amount = self.config.maximum_allowed_reply_surb_request_size;
.reply_surbs
.maximum_allowed_reply_surb_request_size
{
warn!("The requested reply surb amount is larger than our maximum allowed ({amount} > {}). Lowering it to a more sane value...", self.config.reply_surbs.maximum_allowed_reply_surb_request_size);
amount = self
.config
.reply_surbs
.maximum_allowed_reply_surb_request_size;
} }
// 3. construct and send the surbs away // 3. construct and send the surbs away
@@ -698,11 +707,8 @@ where
} }
let request_size = min( let request_size = min(
self.config.reply_surbs.maximum_reply_surb_request_size, self.config.max_surb_request_size,
max( max(total_queue, self.config.min_surb_request_size),
total_queue,
self.config.reply_surbs.minimum_reply_surb_request_size,
),
); );
if let Err(err) = self if let Err(err) = self
@@ -738,17 +744,9 @@ where
}; };
let diff = now - last_received_time; let diff = now - last_received_time;
let max_rerequest_wait = self
.config
.reply_surbs
.maximum_reply_surb_rerequest_waiting_period;
let max_drop_wait = self
.config
.reply_surbs
.maximum_reply_surb_drop_waiting_period;
if diff > max_rerequest_wait { if diff > self.config.max_surb_rerequest_waiting_period {
if diff > max_drop_wait { if diff > self.config.max_surb_drop_waiting_period {
to_remove.push(*pending_reply_target) to_remove.push(*pending_reply_target)
} else { } else {
debug!("We haven't received any surbs in {:?} from {pending_reply_target}. Going to explicitly ask for more", diff); debug!("We haven't received any surbs in {:?} from {pending_reply_target}. Going to explicitly ask for more", diff);
@@ -795,7 +793,7 @@ where
}; };
let diff = now - last_received_time; let diff = now - last_received_time;
if diff > self.config.reply_surbs.maximum_reply_surb_age { if diff > self.config.max_reply_surb_age {
info!("it's been {diff:?} since we last received any reply surb from {sender}. Going to remove all stored entries..."); info!("it's been {diff:?} since we last received any reply surb from {sender}. Going to remove all stored entries...");
to_remove_surbs.push(*sender); to_remove_surbs.push(*sender);
@@ -815,7 +813,7 @@ where
let diff = now - sent_at; let diff = now - sent_at;
if diff > self.config.reply_surbs.maximum_reply_key_age { if diff > self.config.max_reply_key_age {
debug!("it's been {diff:?} since we created this reply key. it's probably never going to get used, so we're going to purge it..."); debug!("it's been {diff:?} since we created this reply key. it's probably never going to get used, so we're going to purge it...");
to_remove_keys.push(*digest); to_remove_keys.push(*digest);
} }
@@ -844,8 +842,7 @@ where
let mut stale_inspection = new_interval_stream(polling_rate); let mut stale_inspection = new_interval_stream(polling_rate);
// this is in the order of hours/days so we don't have to poll it that often // this is in the order of hours/days so we don't have to poll it that often
let polling_rate = let polling_rate = Duration::from_secs(self.config.max_reply_surb_age.as_secs() / 10);
Duration::from_secs(self.config.reply_surbs.maximum_reply_surb_age.as_secs() / 10);
let mut invalidation_inspection = new_interval_stream(polling_rate); let mut invalidation_inspection = new_interval_stream(polling_rate);
while !shutdown.is_shutdown() { while !shutdown.is_shutdown() {
@@ -10,7 +10,7 @@ use rand::thread_rng;
use url::Url; use url::Url;
pub(crate) struct NymApiTopologyProvider { pub(crate) struct NymApiTopologyProvider {
validator_client: nym_validator_client::client::NymApiClient, validator_client: validator_client::client::NymApiClient,
nym_api_urls: Vec<Url>, nym_api_urls: Vec<Url>,
client_version: String, client_version: String,
@@ -22,9 +22,7 @@ impl NymApiTopologyProvider {
nym_api_urls.shuffle(&mut thread_rng()); nym_api_urls.shuffle(&mut thread_rng());
NymApiTopologyProvider { NymApiTopologyProvider {
validator_client: nym_validator_client::client::NymApiClient::new( validator_client: validator_client::client::NymApiClient::new(nym_api_urls[0].clone()),
nym_api_urls[0].clone(),
),
nym_api_urls, nym_api_urls,
client_version, client_version,
currently_used_api: 0, currently_used_api: 0,
@@ -171,6 +171,8 @@ impl<T> TransmissionBuffer<T> {
&mut self, &mut self,
n: usize, n: usize,
) -> Option<Vec<(TransmissionLane, T)>> { ) -> Option<Vec<(TransmissionLane, T)>> {
// let start = Instant::now();
if self.buffer.is_empty() { if self.buffer.is_empty() {
return None; return None;
} }
@@ -185,6 +187,8 @@ impl<T> TransmissionBuffer<T> {
items.push(next) items.push(next)
} }
// todo!("time time taken");
Some(items) Some(items)
} }
+24 -41
View File
@@ -32,8 +32,6 @@ const DEFAULT_TOPOLOGY_RESOLUTION_TIMEOUT: Duration = Duration::from_millis(5_00
// bandwidth bridging protocol, we can come back to a smaller timeout value // bandwidth bridging protocol, we can come back to a smaller timeout value
const DEFAULT_GATEWAY_RESPONSE_TIMEOUT: Duration = Duration::from_secs(5 * 60); const DEFAULT_GATEWAY_RESPONSE_TIMEOUT: Duration = Duration::from_secs(5 * 60);
const DEFAULT_COVER_TRAFFIC_PRIMARY_SIZE_RATIO: f64 = 0.70;
// reply-surbs related: // reply-surbs related:
// define when to request // define when to request
@@ -92,11 +90,6 @@ impl<T> Config<T> {
Config::default().with_id(id) Config::default().with_id(id)
} }
pub fn validate(&self) -> bool {
// no other sections have explicit requirements (yet)
self.debug.validate()
}
#[must_use] #[must_use]
pub fn with_id<S: Into<String>>(mut self, id: S) -> Self pub fn with_id<S: Into<String>>(mut self, id: S) -> Self
where where
@@ -363,6 +356,10 @@ impl<T> Config<T> {
self.debug.traffic.disable_main_poisson_packet_distribution self.debug.traffic.disable_main_poisson_packet_distribution
} }
pub fn get_use_extended_packet_size(&self) -> Option<ExtendedPacketSize> {
self.debug.traffic.use_extended_packet_size
}
pub fn get_minimum_reply_surb_storage_threshold(&self) -> usize { pub fn get_minimum_reply_surb_storage_threshold(&self) -> usize {
self.debug.reply_surbs.minimum_reply_surb_storage_threshold self.debug.reply_surbs.minimum_reply_surb_storage_threshold
} }
@@ -599,7 +596,7 @@ impl<T: NymConfig> Client<T> {
pub struct Logging {} pub struct Logging {}
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)] #[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
#[serde(default)] #[serde(default, deny_unknown_fields)]
pub struct Traffic { pub struct Traffic {
/// The parameter of Poisson distribution determining how long, on average, /// The parameter of Poisson distribution determining how long, on average,
/// sent packet is going to be delayed at any given mix node. /// sent packet is going to be delayed at any given mix node.
@@ -619,27 +616,8 @@ pub struct Traffic {
/// poisson distribution. /// poisson distribution.
pub disable_main_poisson_packet_distribution: bool, pub disable_main_poisson_packet_distribution: bool,
/// Specifies the packet size used for sent messages. /// Controls whether the sent sphinx packet use a NON-DEFAULT bigger size.
/// Do not override it unless you understand the consequences of that change. pub use_extended_packet_size: Option<ExtendedPacketSize>,
pub primary_packet_size: PacketSize,
/// Specifies the optional auxiliary packet size for optimizing message streams.
/// Note that its use decreases overall anonymity.
/// Do not set it it unless you understand the consequences of that change.
pub secondary_packet_size: Option<PacketSize>,
}
impl Traffic {
pub fn validate(&self) -> bool {
if let Some(secondary_packet_size) = self.secondary_packet_size {
if secondary_packet_size == PacketSize::AckPacket
|| secondary_packet_size == self.primary_packet_size
{
return false;
}
}
true
}
} }
impl Default for Traffic { impl Default for Traffic {
@@ -648,8 +626,7 @@ impl Default for Traffic {
average_packet_delay: DEFAULT_AVERAGE_PACKET_DELAY, average_packet_delay: DEFAULT_AVERAGE_PACKET_DELAY,
message_sending_average_delay: DEFAULT_MESSAGE_STREAM_AVERAGE_DELAY, message_sending_average_delay: DEFAULT_MESSAGE_STREAM_AVERAGE_DELAY,
disable_main_poisson_packet_distribution: false, disable_main_poisson_packet_distribution: false,
primary_packet_size: PacketSize::RegularPacket, use_extended_packet_size: None,
secondary_packet_size: None,
} }
} }
} }
@@ -662,10 +639,6 @@ pub struct CoverTraffic {
#[serde(with = "humantime_serde")] #[serde(with = "humantime_serde")]
pub loop_cover_traffic_average_delay: Duration, pub loop_cover_traffic_average_delay: Duration,
/// Specifies the ratio of `primary_packet_size` to `secondary_packet_size` used in cover traffic.
/// Only applicable if `secondary_packet_size` is enabled.
pub cover_traffic_primary_size_ratio: f64,
/// Controls whether the dedicated loop cover traffic stream should be enabled. /// Controls whether the dedicated loop cover traffic stream should be enabled.
/// (and sending packets, on average, every [Self::loop_cover_traffic_average_delay]) /// (and sending packets, on average, every [Self::loop_cover_traffic_average_delay])
pub disable_loop_cover_traffic_stream: bool, pub disable_loop_cover_traffic_stream: bool,
@@ -675,7 +648,6 @@ impl Default for CoverTraffic {
fn default() -> Self { fn default() -> Self {
CoverTraffic { CoverTraffic {
loop_cover_traffic_average_delay: DEFAULT_LOOP_COVER_STREAM_AVERAGE_DELAY, loop_cover_traffic_average_delay: DEFAULT_LOOP_COVER_STREAM_AVERAGE_DELAY,
cover_traffic_primary_size_ratio: DEFAULT_COVER_TRAFFIC_PRIMARY_SIZE_RATIO,
disable_loop_cover_traffic_stream: false, disable_loop_cover_traffic_stream: false,
} }
} }
@@ -833,11 +805,12 @@ pub struct DebugConfig {
pub reply_surbs: ReplySurbs, pub reply_surbs: ReplySurbs,
} }
impl DebugConfig { #[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq)]
pub fn validate(&self) -> bool { #[serde(rename_all = "lowercase")]
// no other sections have explicit requirements (yet) pub enum ExtendedPacketSize {
self.traffic.validate() Extended8,
} Extended16,
Extended32,
} }
// it could be derived, sure, but I'd rather have an explicit implementation in case we had to change // it could be derived, sure, but I'd rather have an explicit implementation in case we had to change
@@ -855,3 +828,13 @@ impl Default for DebugConfig {
} }
} }
} }
impl From<ExtendedPacketSize> for PacketSize {
fn from(size: ExtendedPacketSize) -> PacketSize {
match size {
ExtendedPacketSize::Extended8 => PacketSize::ExtendedPacket8,
ExtendedPacketSize::Extended16 => PacketSize::ExtendedPacket16,
ExtendedPacketSize::Extended32 => PacketSize::ExtendedPacket32,
}
}
}
@@ -2,9 +2,9 @@
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use crate::config::{ use crate::config::{
Acknowledgements, Client, Config, CoverTraffic, DebugConfig, GatewayConnection, Logging, Acknowledgements, Client, Config, CoverTraffic, DebugConfig, ExtendedPacketSize,
ReplySurbs, Topology, Traffic, DEFAULT_ACK_WAIT_ADDITION, DEFAULT_ACK_WAIT_MULTIPLIER, GatewayConnection, Logging, ReplySurbs, Topology, Traffic, DEFAULT_ACK_WAIT_ADDITION,
DEFAULT_AVERAGE_PACKET_DELAY, DEFAULT_GATEWAY_RESPONSE_TIMEOUT, DEFAULT_ACK_WAIT_MULTIPLIER, DEFAULT_AVERAGE_PACKET_DELAY, DEFAULT_GATEWAY_RESPONSE_TIMEOUT,
DEFAULT_LOOP_COVER_STREAM_AVERAGE_DELAY, DEFAULT_MAXIMUM_ALLOWED_SURB_REQUEST_SIZE, DEFAULT_LOOP_COVER_STREAM_AVERAGE_DELAY, DEFAULT_MAXIMUM_ALLOWED_SURB_REQUEST_SIZE,
DEFAULT_MAXIMUM_REPLY_KEY_AGE, DEFAULT_MAXIMUM_REPLY_SURB_AGE, DEFAULT_MAXIMUM_REPLY_KEY_AGE, DEFAULT_MAXIMUM_REPLY_SURB_AGE,
DEFAULT_MAXIMUM_REPLY_SURB_DROP_WAITING_PERIOD, DEFAULT_MAXIMUM_REPLY_SURB_REQUEST_SIZE, DEFAULT_MAXIMUM_REPLY_SURB_DROP_WAITING_PERIOD, DEFAULT_MAXIMUM_REPLY_SURB_REQUEST_SIZE,
@@ -14,29 +14,10 @@ use crate::config::{
DEFAULT_TOPOLOGY_REFRESH_RATE, DEFAULT_TOPOLOGY_RESOLUTION_TIMEOUT, DEFAULT_TOPOLOGY_REFRESH_RATE, DEFAULT_TOPOLOGY_RESOLUTION_TIMEOUT,
}; };
use nym_config::NymConfig; use nym_config::NymConfig;
use nym_sphinx::params::PacketSize;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::marker::PhantomData; use std::marker::PhantomData;
use std::time::Duration; use std::time::Duration;
#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "lowercase")]
pub enum ExtendedPacketSize {
Extended8,
Extended16,
Extended32,
}
impl From<ExtendedPacketSize> for PacketSize {
fn from(size: ExtendedPacketSize) -> PacketSize {
match size {
ExtendedPacketSize::Extended8 => PacketSize::ExtendedPacket8,
ExtendedPacketSize::Extended16 => PacketSize::ExtendedPacket16,
ExtendedPacketSize::Extended32 => PacketSize::ExtendedPacket32,
}
}
}
#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)] #[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
#[serde(deny_unknown_fields)] #[serde(deny_unknown_fields)]
pub struct OldConfigV1_1_13<T> { pub struct OldConfigV1_1_13<T> {
@@ -123,13 +104,11 @@ impl From<OldDebugConfigV1_1_13> for DebugConfig {
message_sending_average_delay: value.message_sending_average_delay, message_sending_average_delay: value.message_sending_average_delay,
disable_main_poisson_packet_distribution: value disable_main_poisson_packet_distribution: value
.disable_main_poisson_packet_distribution, .disable_main_poisson_packet_distribution,
primary_packet_size: PacketSize::RegularPacket, use_extended_packet_size: value.use_extended_packet_size,
secondary_packet_size: value.use_extended_packet_size.map(Into::into),
}, },
cover_traffic: CoverTraffic { cover_traffic: CoverTraffic {
loop_cover_traffic_average_delay: value.loop_cover_traffic_average_delay, loop_cover_traffic_average_delay: value.loop_cover_traffic_average_delay,
disable_loop_cover_traffic_stream: value.disable_loop_cover_traffic_stream, disable_loop_cover_traffic_stream: value.disable_loop_cover_traffic_stream,
..CoverTraffic::default()
}, },
gateway_connection: GatewayConnection { gateway_connection: GatewayConnection {
gateway_response_timeout: value.gateway_response_timeout, gateway_response_timeout: value.gateway_response_timeout,
+2 -2
View File
@@ -1,11 +1,11 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net> // Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use gateway_client::error::GatewayClientError;
use nym_crypto::asymmetric::identity::Ed25519RecoveryError; use nym_crypto::asymmetric::identity::Ed25519RecoveryError;
use nym_gateway_client::error::GatewayClientError;
use nym_topology::gateway::GatewayConversionError; use nym_topology::gateway::GatewayConversionError;
use nym_topology::NymTopologyError; use nym_topology::NymTopologyError;
use nym_validator_client::ValidatorClientError; use validator_client::ValidatorClientError;
#[derive(thiserror::Error, Debug)] #[derive(thiserror::Error, Debug)]
pub enum ClientCoreError { pub enum ClientCoreError {
+14 -12
View File
@@ -7,11 +7,11 @@ use crate::{
error::ClientCoreError, error::ClientCoreError,
}; };
use futures::{SinkExt, StreamExt}; use futures::{SinkExt, StreamExt};
use gateway_client::GatewayClient;
use gateway_requests::registration::handshake::SharedKeys;
use log::{debug, info, trace, warn}; use log::{debug, info, trace, warn};
use nym_config::NymConfig; use nym_config::NymConfig;
use nym_crypto::asymmetric::identity; use nym_crypto::asymmetric::identity;
use nym_gateway_client::GatewayClient;
use nym_gateway_requests::registration::handshake::SharedKeys;
use nym_topology::{filter::VersionFilterable, gateway}; use nym_topology::{filter::VersionFilterable, gateway};
use rand::{seq::SliceRandom, thread_rng, Rng}; use rand::{seq::SliceRandom, thread_rng, Rng};
use std::{sync::Arc, time::Duration}; use std::{sync::Arc, time::Duration};
@@ -19,8 +19,6 @@ use tap::TapFallible;
use tungstenite::Message; use tungstenite::Message;
use url::Url; use url::Url;
#[cfg(not(target_arch = "wasm32"))]
use nym_validator_client::nyxd::DirectSigningNyxdClient;
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
use tokio::net::TcpStream; use tokio::net::TcpStream;
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
@@ -29,13 +27,14 @@ use tokio::time::Instant;
use tokio_tungstenite::connect_async; use tokio_tungstenite::connect_async;
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
use tokio_tungstenite::{MaybeTlsStream, WebSocketStream}; use tokio_tungstenite::{MaybeTlsStream, WebSocketStream};
#[cfg(not(target_arch = "wasm32"))]
use validator_client::nyxd::DirectSigningNyxdClient;
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
type WsConn = WebSocketStream<MaybeTlsStream<TcpStream>>; type WsConn = WebSocketStream<MaybeTlsStream<TcpStream>>;
use nym_credential_storage::storage::Storage;
#[cfg(target_arch = "wasm32")] #[cfg(target_arch = "wasm32")]
use nym_bandwidth_controller::wasm_mockups::DirectSigningNyxdClient; use gateway_client::wasm_mockups::DirectSigningNyxdClient;
#[cfg(target_arch = "wasm32")] #[cfg(target_arch = "wasm32")]
use wasm_timer::Instant; use wasm_timer::Instant;
#[cfg(target_arch = "wasm32")] #[cfg(target_arch = "wasm32")]
@@ -68,7 +67,7 @@ async fn current_gateways<R: Rng>(
let nym_api = nym_apis let nym_api = nym_apis
.choose(rng) .choose(rng)
.ok_or(ClientCoreError::ListOfNymApisIsEmpty)?; .ok_or(ClientCoreError::ListOfNymApisIsEmpty)?;
let client = nym_validator_client::client::NymApiClient::new(nym_api.clone()); let client = validator_client::client::NymApiClient::new(nym_api.clone());
log::trace!("Fetching list of gateways from: {}", nym_api); log::trace!("Fetching list of gateways from: {}", nym_api);
@@ -177,7 +176,10 @@ async fn choose_gateway_by_latency<R: Rng>(
continue; continue;
} }
}; };
debug!("{id}: {:?}", with_latency.latency); debug!(
"{id} ({}): {:?}",
with_latency.gateway.location, with_latency.latency
);
gateways_with_latency.push(with_latency) gateways_with_latency.push(with_latency)
} }
@@ -186,8 +188,8 @@ async fn choose_gateway_by_latency<R: Rng>(
.expect("invalid selection weight!"); .expect("invalid selection weight!");
info!( info!(
"chose gateway {} with average latency of {:?}", "chose gateway {} (located at {}) with average latency of {:?}",
chosen.gateway.identity_key, chosen.latency chosen.gateway.identity_key, chosen.gateway.location, chosen.latency
); );
Ok(chosen.gateway.clone()) Ok(chosen.gateway.clone())
@@ -224,12 +226,12 @@ pub(super) async fn query_gateway_details(
} }
} }
pub(super) async fn register_with_gateway<St: Storage>( pub(super) async fn register_with_gateway(
gateway: &gateway::Node, gateway: &gateway::Node,
our_identity: Arc<identity::KeyPair>, our_identity: Arc<identity::KeyPair>,
) -> Result<Arc<SharedKeys>, ClientCoreError> { ) -> Result<Arc<SharedKeys>, ClientCoreError> {
let timeout = Duration::from_millis(1500); let timeout = Duration::from_millis(1500);
let mut gateway_client: GatewayClient<DirectSigningNyxdClient, St> = GatewayClient::new_init( let mut gateway_client: GatewayClient<DirectSigningNyxdClient> = GatewayClient::new_init(
gateway.clients_address(), gateway.clients_address(),
gateway.identity_key, gateway.identity_key,
our_identity.clone(), our_identity.clone(),
+7 -9
View File
@@ -11,7 +11,6 @@ use serde::Serialize;
use tap::TapFallible; use tap::TapFallible;
use nym_config::NymConfig; use nym_config::NymConfig;
use nym_credential_storage::storage::Storage;
use nym_crypto::asymmetric::{encryption, identity}; use nym_crypto::asymmetric::{encryption, identity};
use url::Url; use url::Url;
@@ -74,7 +73,7 @@ pub fn new_client_keys() -> KeyManager {
/// Either pick one at random by querying the available gateways from the nym-api, or use the /// Either pick one at random by querying the available gateways from the nym-api, or use the
/// chosen one if it's among the available ones. /// chosen one if it's among the available ones.
/// The shared key is added to the supplied `KeyManager` and the endpoint details are returned. /// The shared key is added to the supplied `KeyManager` and the endpoint details are returned.
pub async fn register_with_gateway<St: Storage>( pub async fn register_with_gateway(
key_manager: &mut KeyManager, key_manager: &mut KeyManager,
nym_api_endpoints: Vec<Url>, nym_api_endpoints: Vec<Url>,
chosen_gateway_id: Option<identity::PublicKey>, chosen_gateway_id: Option<identity::PublicKey>,
@@ -88,7 +87,7 @@ pub async fn register_with_gateway<St: Storage>(
let our_identity = key_manager.identity_keypair(); let our_identity = key_manager.identity_keypair();
// Establish connection, authenticate and generate keys for talking with the gateway // Establish connection, authenticate and generate keys for talking with the gateway
let shared_keys = helpers::register_with_gateway::<St>(&gateway, our_identity).await?; let shared_keys = helpers::register_with_gateway(&gateway, our_identity).await?;
key_manager.insert_gateway_shared_key(shared_keys); key_manager.insert_gateway_shared_key(shared_keys);
Ok(gateway.into()) Ok(gateway.into())
@@ -101,7 +100,7 @@ pub async fn register_with_gateway<St: Storage>(
/// b. Create a new gateway configuration but keep existing keys. This assumes that the caller /// b. Create a new gateway configuration but keep existing keys. This assumes that the caller
/// knows what they are doing and that the keys match the requested gateway. /// knows what they are doing and that the keys match the requested gateway.
/// c. Create a new gateway configuration with a newly registered gateway and keys. /// c. Create a new gateway configuration with a newly registered gateway and keys.
pub async fn setup_gateway_from_config<C, T, St>( pub async fn setup_gateway_from_config<C, T>(
register_gateway: bool, register_gateway: bool,
user_chosen_gateway_id: Option<identity::PublicKey>, user_chosen_gateway_id: Option<identity::PublicKey>,
config: &Config<T>, config: &Config<T>,
@@ -110,14 +109,13 @@ pub async fn setup_gateway_from_config<C, T, St>(
where where
C: NymConfig + ClientCoreConfigTrait, C: NymConfig + ClientCoreConfigTrait,
T: NymConfig, T: NymConfig,
St: Storage,
{ {
let id = config.get_id(); let id = config.get_id();
// If we are not going to register gateway, and an explicitly chosen gateway is not passed in, // If we are not going to register gateway, and an explicitly chosen gateway is not passed in,
// load the existing configuration file // load the existing configuration file
if !register_gateway && user_chosen_gateway_id.is_none() { if !register_gateway && user_chosen_gateway_id.is_none() {
eprintln!("Not registering gateway, will reuse existing config and keys"); println!("Not registering gateway, will reuse existing config and keys");
return load_existing_gateway_config::<C>(&id); return load_existing_gateway_config::<C>(&id);
} }
@@ -133,7 +131,7 @@ where
// If we are not registering, just return this and assume the caller has the keys already and // If we are not registering, just return this and assume the caller has the keys already and
// wants to keep the, // wants to keep the,
if !register_gateway && user_chosen_gateway_id.is_some() { if !register_gateway && user_chosen_gateway_id.is_some() {
eprintln!("Using gateway provided by user, keeping existing keys"); println!("Using gateway provided by user, keeping existing keys");
return Ok(gateway.into()); return Ok(gateway.into());
} }
@@ -142,8 +140,8 @@ where
let our_identity = key_manager.identity_keypair(); let our_identity = key_manager.identity_keypair();
// Establish connection, authenticate and generate keys for talking with the gateway // Establish connection, authenticate and generate keys for talking with the gateway
eprintln!("Registering with new gateway"); println!("Registering with new gateway");
let shared_keys = helpers::register_with_gateway::<St>(&gateway, our_identity).await?; let shared_keys = helpers::register_with_gateway(&gateway, our_identity).await?;
key_manager.insert_gateway_shared_key(shared_keys); key_manager.insert_gateway_shared_key(shared_keys);
// Write all keys to storage and just return the gateway endpoint config. It is assumed that we // Write all keys to storage and just return the gateway endpoint config. It is assumed that we
+11 -6
View File
@@ -1,5 +1,5 @@
[package] [package]
name = "nym-gateway-client" name = "gateway-client"
version = "0.1.0" version = "0.1.0"
authors = ["Jędrzej Stuczyński <andrew@nymtech.net>"] authors = ["Jędrzej Stuczyński <andrew@nymtech.net>"]
edition = "2021" edition = "2021"
@@ -14,20 +14,21 @@ log = { workspace = true }
thiserror = "1.0" thiserror = "1.0"
url = "2.2" url = "2.2"
rand = { version = "0.7.3", features = ["wasm-bindgen"] } rand = { version = "0.7.3", features = ["wasm-bindgen"] }
async-trait = { workspace = true }
tokio = { version = "1.24.1", features = ["macros"] } tokio = { version = "1.24.1", features = ["macros"] }
# internal # internal
nym-bandwidth-controller = { path = "../../bandwidth-controller" }
nym-coconut-interface = { path = "../../coconut-interface" } nym-coconut-interface = { path = "../../coconut-interface" }
nym-credential-storage = { path = "../../credential-storage" } nym-credentials = { path = "../../credentials" }
nym-crypto = { path = "../../crypto" } nym-crypto = { path = "../../crypto" }
nym-gateway-requests = { path = "../../../gateway/gateway-requests" } gateway-requests = { path = "../../../gateway/gateway-requests" }
nym-network-defaults = { path = "../../network-defaults" } nym-network-defaults = { path = "../../network-defaults" }
nym-sphinx = { path = "../../nymsphinx" } nym-sphinx = { path = "../../nymsphinx" }
nym-pemstore = { path = "../../pemstore" } nym-pemstore = { path = "../../pemstore" }
nym-validator-client = { path = "../validator-client" } validator-client = { path = "../validator-client" }
nym-task = { path = "../../task" } nym-task = { path = "../../task" }
serde = { workspace = true, features = ["derive"] } serde = { version = "1.0", features = ["derive"]}
mobile-storage = { path = "../../mobile-storage" }
[dependencies.tungstenite] [dependencies.tungstenite]
@@ -46,6 +47,9 @@ features = ["net", "sync", "time"]
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.tokio-tungstenite] [target."cfg(not(target_arch = \"wasm32\"))".dependencies.tokio-tungstenite]
version = "0.14" version = "0.14"
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.nym-credential-storage]
path = "../../credential-storage"
# wasm-only dependencies # wasm-only dependencies
[target."cfg(target_arch = \"wasm32\")".dependencies.wasm-bindgen] [target."cfg(target_arch = \"wasm32\")".dependencies.wasm-bindgen]
version = "0.2" version = "0.2"
@@ -77,3 +81,4 @@ features = ["js"]
[features] [features]
wasm = [] wasm = []
mobile = []
@@ -1,11 +1,29 @@
// Copyright 2021-2023 - 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 crate::error::BandwidthControllerError; use crate::error::GatewayClientError;
use nym_credential_storage::error::StorageError; #[cfg(target_arch = "wasm32")]
use crate::wasm_mockups::Storage;
#[cfg(not(target_arch = "wasm32"))]
#[cfg(not(feature = "mobile"))]
use nym_credential_storage::storage::Storage; use nym_credential_storage::storage::Storage;
#[cfg(not(target_arch = "wasm32"))]
#[cfg(feature = "mobile")]
use mobile_storage::Storage;
#[cfg(not(target_arch = "wasm32"))]
#[cfg(feature = "mobile")]
use mobile_storage::StorageError;
#[cfg(target_arch = "wasm32")]
use crate::wasm_mockups::StorageError;
#[cfg(not(target_arch = "wasm32"))]
#[cfg(not(feature = "mobile"))]
use nym_credential_storage::error::StorageError;
use std::str::FromStr; use std::str::FromStr;
use { use {
nym_coconut_interface::Base58, nym_coconut_interface::Base58,
@@ -15,34 +33,40 @@ use {
}; };
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
use nym_validator_client::nyxd::traits::DkgQueryClient; use validator_client::nyxd::traits::DkgQueryClient;
// TODO: make it nicer for wasm (I don't want to touch it for this experiment)
#[cfg(target_arch = "wasm32")]
use crate::wasm_mockups::PersistentStorage;
#[cfg(target_arch = "wasm32")] #[cfg(target_arch = "wasm32")]
use crate::wasm_mockups::DkgQueryClient; use crate::wasm_mockups::DkgQueryClient;
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
pub mod acquire; #[cfg(not(feature = "mobile"))]
pub mod error; use nym_credential_storage::PersistentStorage;
#[cfg(target_arch = "wasm32")]
pub mod wasm_mockups;
pub struct BandwidthController<C, St: Storage> { #[cfg(not(target_arch = "wasm32"))]
#[cfg(feature = "mobile")]
use mobile_storage::PersistentStorage;
#[allow(dead_code)]
pub struct BandwidthController<C, St: Storage = PersistentStorage> {
storage: St, storage: St,
client: C, client: C,
} }
impl<C, St: Storage> BandwidthController<C, St> { impl<C, St> BandwidthController<C, St>
where
St: Storage + 'static,
{
pub fn new(storage: St, client: C) -> Self { pub fn new(storage: St, client: C) -> Self {
BandwidthController { storage, client } BandwidthController { storage, client }
} }
pub fn storage(&self) -> &St {
&self.storage
}
pub async fn prepare_coconut_credential( pub async fn prepare_coconut_credential(
&self, &self,
) -> Result<(nym_coconut_interface::Credential, i64), BandwidthControllerError> ) -> Result<(nym_coconut_interface::Credential, i64), GatewayClientError>
where where
C: DkgQueryClient + Sync + Send, C: DkgQueryClient + Sync + Send,
{ {
@@ -61,8 +85,9 @@ impl<C, St: Storage> BandwidthController<C, St> {
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
let coconut_api_clients = let coconut_api_clients =
nym_validator_client::CoconutApiClient::all_coconut_api_clients(&self.client, epoch_id) validator_client::CoconutApiClient::all_coconut_api_clients(&self.client, epoch_id)
.await?; .await
.expect("Could not query api clients");
#[cfg(target_arch = "wasm32")] #[cfg(target_arch = "wasm32")]
let coconut_api_clients = vec![]; let coconut_api_clients = vec![];
let verification_key = obtain_aggregate_verification_key(&coconut_api_clients).await?; let verification_key = obtain_aggregate_verification_key(&coconut_api_clients).await?;
@@ -82,7 +107,7 @@ impl<C, St: Storage> BandwidthController<C, St> {
)) ))
} }
pub async fn consume_credential(&self, id: i64) -> Result<(), BandwidthControllerError> { pub async fn consume_credential(&self, id: i64) -> Result<(), GatewayClientError> {
// JS: shouldn't we send some contract/validator/gateway message here to actually, you know, // JS: shouldn't we send some contract/validator/gateway message here to actually, you know,
// consume it? // consume it?
Ok(self.storage.consume_coconut_credential(id).await?) Ok(self.storage.consume_coconut_credential(id).await?)
+23 -14
View File
@@ -1,6 +1,7 @@
// 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 crate::bandwidth::BandwidthController;
use crate::error::GatewayClientError; use crate::error::GatewayClientError;
use crate::packet_router::PacketRouter; use crate::packet_router::PacketRouter;
pub use crate::packet_router::{ pub use crate::packet_router::{
@@ -9,14 +10,13 @@ pub use crate::packet_router::{
use crate::socket_state::{PartiallyDelegated, SocketState}; use crate::socket_state::{PartiallyDelegated, SocketState};
use crate::{cleanup_socket_message, try_decrypt_binary_message}; use crate::{cleanup_socket_message, try_decrypt_binary_message};
use futures::{SinkExt, StreamExt}; use futures::{SinkExt, StreamExt};
use gateway_requests::authentication::encrypted_address::EncryptedAddressBytes;
use gateway_requests::iv::IV;
use gateway_requests::registration::handshake::{client_handshake, SharedKeys};
use gateway_requests::{BinaryRequest, ClientControlRequest, ServerResponse, PROTOCOL_VERSION};
use log::*; use log::*;
use nym_bandwidth_controller::BandwidthController;
use nym_coconut_interface::Credential; use nym_coconut_interface::Credential;
use nym_crypto::asymmetric::identity; use nym_crypto::asymmetric::identity;
use nym_gateway_requests::authentication::encrypted_address::EncryptedAddressBytes;
use nym_gateway_requests::iv::IV;
use nym_gateway_requests::registration::handshake::{client_handshake, SharedKeys};
use nym_gateway_requests::{BinaryRequest, ClientControlRequest, ServerResponse, PROTOCOL_VERSION};
use nym_network_defaults::{REMAINING_BANDWIDTH_THRESHOLD, TOKENS_TO_BURN}; use nym_network_defaults::{REMAINING_BANDWIDTH_THRESHOLD, TOKENS_TO_BURN};
use nym_sphinx::forwarding::packet::MixPacket; use nym_sphinx::forwarding::packet::MixPacket;
use nym_task::TaskClient; use nym_task::TaskClient;
@@ -26,14 +26,24 @@ use std::sync::Arc;
use std::time::Duration; use std::time::Duration;
use tungstenite::protocol::Message; use tungstenite::protocol::Message;
use nym_credential_storage::storage::Storage;
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
use nym_validator_client::nyxd::traits::DkgQueryClient; use validator_client::nyxd::traits::DkgQueryClient;
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
use tokio_tungstenite::connect_async; use tokio_tungstenite::connect_async;
#[cfg(not(target_arch = "wasm32"))]
#[cfg(not(feature = "mobile"))]
use nym_credential_storage::PersistentStorage;
#[cfg(not(target_arch = "wasm32"))]
#[cfg(feature = "mobile")]
use mobile_storage::PersistentStorage;
#[cfg(target_arch = "wasm32")] #[cfg(target_arch = "wasm32")]
use nym_bandwidth_controller::wasm_mockups::DkgQueryClient; use crate::wasm_mockups::DkgQueryClient;
#[cfg(target_arch = "wasm32")]
use crate::wasm_mockups::PersistentStorage;
#[cfg(target_arch = "wasm32")] #[cfg(target_arch = "wasm32")]
use wasm_timer; use wasm_timer;
#[cfg(target_arch = "wasm32")] #[cfg(target_arch = "wasm32")]
@@ -42,7 +52,7 @@ use wasm_utils::websocket::JSWebsocket;
const DEFAULT_RECONNECTION_ATTEMPTS: usize = 10; const DEFAULT_RECONNECTION_ATTEMPTS: usize = 10;
const DEFAULT_RECONNECTION_BACKOFF: Duration = Duration::from_secs(5); const DEFAULT_RECONNECTION_BACKOFF: Duration = Duration::from_secs(5);
pub struct GatewayClient<C, St: Storage> { pub struct GatewayClient<C> {
authenticated: bool, authenticated: bool,
disabled_credentials_mode: bool, disabled_credentials_mode: bool,
bandwidth_remaining: i64, bandwidth_remaining: i64,
@@ -53,7 +63,7 @@ pub struct GatewayClient<C, St: Storage> {
connection: SocketState, connection: SocketState,
packet_router: PacketRouter, packet_router: PacketRouter,
response_timeout_duration: Duration, response_timeout_duration: Duration,
bandwidth_controller: Option<BandwidthController<C, St>>, bandwidth_controller: Option<BandwidthController<C, PersistentStorage>>,
// reconnection related variables // reconnection related variables
/// Specifies whether client should try to reconnect to gateway on connection failure. /// Specifies whether client should try to reconnect to gateway on connection failure.
@@ -68,10 +78,9 @@ pub struct GatewayClient<C, St: Storage> {
shutdown: TaskClient, shutdown: TaskClient,
} }
impl<C, St> GatewayClient<C, St> impl<C> GatewayClient<C>
where where
C: Sync + Send, C: Sync + Send,
St: Storage,
{ {
// TODO: put it all in a Config struct // TODO: put it all in a Config struct
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
@@ -83,7 +92,7 @@ where
mixnet_message_sender: MixnetMessageSender, mixnet_message_sender: MixnetMessageSender,
ack_sender: AcknowledgementSender, ack_sender: AcknowledgementSender,
response_timeout_duration: Duration, response_timeout_duration: Duration,
bandwidth_controller: Option<BandwidthController<C, St>>, bandwidth_controller: Option<BandwidthController<C, PersistentStorage>>,
shutdown: TaskClient, shutdown: TaskClient,
) -> Self { ) -> Self {
GatewayClient { GatewayClient {
@@ -137,7 +146,7 @@ where
let shutdown = TaskClient::dummy(); let shutdown = TaskClient::dummy();
let packet_router = PacketRouter::new(ack_tx, mix_tx, shutdown.clone()); let packet_router = PacketRouter::new(ack_tx, mix_tx, shutdown.clone());
GatewayClient::<C, St> { GatewayClient::<C> {
authenticated: false, authenticated: false,
disabled_credentials_mode: true, disabled_credentials_mode: true,
bandwidth_remaining: 0, bandwidth_remaining: 0,
+17 -3
View File
@@ -1,7 +1,15 @@
// 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 nym_gateway_requests::registration::handshake::error::HandshakeError; #[cfg(target_arch = "wasm32")]
use crate::wasm_mockups::StorageError;
use gateway_requests::registration::handshake::error::HandshakeError;
#[cfg(feature = "mobile")]
#[cfg(not(target_arch = "wasm32"))]
use mobile_storage::StorageError;
#[cfg(not(feature = "mobile"))]
#[cfg(not(target_arch = "wasm32"))]
use nym_credential_storage::error::StorageError;
use std::io; use std::io;
use thiserror::Error; use thiserror::Error;
use tungstenite::Error as WsError; use tungstenite::Error as WsError;
@@ -19,6 +27,12 @@ pub enum GatewayClientError {
#[error("There was a network error - {0}")] #[error("There was a network error - {0}")]
NetworkError(#[from] WsError), NetworkError(#[from] WsError),
#[error("There was a credential storage error - {0}")]
CredentialStorageError(#[from] StorageError),
#[error("Coconut error - {0}")]
CoconutError(#[from] nym_coconut_interface::CoconutError),
// TODO: see if `JsValue` is a reasonable type for this // TODO: see if `JsValue` is a reasonable type for this
#[cfg(target_arch = "wasm32")] #[cfg(target_arch = "wasm32")]
#[error("There was a network error")] #[error("There was a network error")]
@@ -33,8 +47,8 @@ pub enum GatewayClientError {
#[error("No bandwidth controller provided")] #[error("No bandwidth controller provided")]
NoBandwidthControllerAvailable, NoBandwidthControllerAvailable,
#[error("Bandwidth controller error - {0}")] #[error("Credential error - {0}")]
BandwidthControllerError(#[from] nym_bandwidth_controller::error::BandwidthControllerError), CredentialError(#[from] nym_credentials::error::Error),
#[error("Connection was abruptly closed")] #[error("Connection was abruptly closed")]
ConnectionAbruptlyClosed, ConnectionAbruptlyClosed,
+5 -2
View File
@@ -3,18 +3,21 @@
use crate::error::GatewayClientError; use crate::error::GatewayClientError;
pub use client::GatewayClient; pub use client::GatewayClient;
use gateway_requests::registration::handshake::SharedKeys;
use gateway_requests::BinaryResponse;
use log::warn; use log::warn;
use nym_gateway_requests::registration::handshake::SharedKeys;
use nym_gateway_requests::BinaryResponse;
pub use packet_router::{ pub use packet_router::{
AcknowledgementReceiver, AcknowledgementSender, MixnetMessageReceiver, MixnetMessageSender, AcknowledgementReceiver, AcknowledgementSender, MixnetMessageReceiver, MixnetMessageSender,
}; };
use tungstenite::{protocol::Message, Error as WsError}; use tungstenite::{protocol::Message, Error as WsError};
pub mod bandwidth;
pub mod client; pub mod client;
pub mod error; pub mod error;
pub mod packet_router; pub mod packet_router;
pub mod socket_state; pub mod socket_state;
#[cfg(target_arch = "wasm32")]
pub mod wasm_mockups;
/// Helper method for reading from websocket stream. Helps to flatten the structure. /// Helper method for reading from websocket stream. Helps to flatten the structure.
pub(crate) fn cleanup_socket_message( pub(crate) fn cleanup_socket_message(
@@ -7,8 +7,8 @@ use crate::{cleanup_socket_messages, try_decrypt_binary_message};
use futures::channel::oneshot; use futures::channel::oneshot;
use futures::stream::{SplitSink, SplitStream}; use futures::stream::{SplitSink, SplitStream};
use futures::{SinkExt, StreamExt}; use futures::{SinkExt, StreamExt};
use gateway_requests::registration::handshake::SharedKeys;
use log::*; use log::*;
use nym_gateway_requests::registration::handshake::SharedKeys;
use nym_task::TaskClient; use nym_task::TaskClient;
use std::sync::Arc; use std::sync::Arc;
use tungstenite::Message; use tungstenite::Message;

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