Compare commits

..

1 Commits

Author SHA1 Message Date
aniampio ffe9084566 Add public attributes into the commitment hash - security patch 2023-01-11 17:20:07 +00:00
578 changed files with 7664 additions and 11387 deletions
+1 -5
View File
@@ -26,7 +26,7 @@ jobs:
path: .github/workflows/support-files/notifications/deny.message
notification:
needs: cargo-deny
runs-on: custom-runner-linux
runs-on: ubuntu-20.04
steps:
- name: Check out repository code
uses: actions/checkout@v2
@@ -35,10 +35,6 @@ jobs:
with:
name: report
path: .github/workflows/support-files/notifications
- name: install npm
uses: actions/setup-node@v3
with:
node-version: 16
- name: Keybase - Node Install
run: npm install
working-directory: .github/workflows/support-files
+1 -9
View File
@@ -17,7 +17,6 @@ jobs:
steps:
- name: Install Dependencies (Linux)
run: sudo apt-get update && sudo apt-get -y install libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev libudev-dev squashfs-tools
continue-on-error: true
- name: Check out repository code
uses: actions/checkout@v2
@@ -42,12 +41,6 @@ jobs:
command: build
args: --workspace
- name: Build all examples
uses: actions-rs/cargo@v1
with:
command: build
args: --workspace --examples
- name: Run all tests
uses: actions-rs/cargo@v1
with:
@@ -63,7 +56,6 @@ jobs:
- uses: actions-rs/clippy-check@v1
name: Clippy checks
continue-on-error: true
with:
token: ${{ secrets.GITHUB_TOKEN }}
args: --workspace --all-features
@@ -72,7 +64,7 @@ jobs:
uses: actions-rs/cargo@v1
with:
command: clippy
args: --workspace --all-targets --all-features -- -D warnings
args: --workspace -- -D warnings
# COCONUT stuff
-2
View File
@@ -13,7 +13,6 @@ jobs:
steps:
- name: Install Dependencies (Linux)
run: sudo apt-get update && sudo apt-get -y install libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev squashfs-tools libayatana-appindicator3-dev
continue-on-error: true
- name: Check out repository code
uses: actions/checkout@v2
@@ -46,7 +45,6 @@ jobs:
- uses: actions-rs/clippy-check@v1
name: Clippy checks
continue-on-error: true
with:
token: ${{ secrets.GITHUB_TOKEN }}
args: --manifest-path nym-connect/Cargo.toml --workspace --all-features
-1
View File
@@ -17,7 +17,6 @@ jobs:
- uses: actions/checkout@v2
- name: Install rsync
run: sudo apt-get install rsync
continue-on-error: true
- uses: rlespinasse/github-slug-action@v3.x
- uses: actions/setup-node@v3
with:
+8 -26
View File
@@ -38,12 +38,6 @@ jobs:
override: true
components: rustfmt, clippy
- name: Check formatting
uses: actions-rs/cargo@v1
with:
command: fmt
args: --all -- --check
- name: Build all binaries
uses: actions-rs/cargo@v1
with:
@@ -56,18 +50,6 @@ jobs:
with:
command: clean
- name: Build all examples
uses: actions-rs/cargo@v1
with:
command: build
args: --workspace --examples
- name: Reclaim some disk space (because Windows is being annoying)
uses: actions-rs/cargo@v1
if: ${{ matrix.os == 'windows-latest' }}
with:
command: clean
- name: Run all tests
uses: actions-rs/cargo@v1
with:
@@ -87,6 +69,12 @@ jobs:
command: test
args: --workspace --all-features -- --ignored
- name: Check formatting
uses: actions-rs/cargo@v1
with:
command: fmt
args: --all -- --check
- name: Reclaim some disk space (because Windows is being annoying)
uses: actions-rs/cargo@v1
if: ${{ matrix.os == 'windows-latest' }}
@@ -95,7 +83,6 @@ jobs:
- uses: actions-rs/clippy-check@v1
name: Clippy checks
continue-on-error: true
with:
token: ${{ secrets.GITHUB_TOKEN }}
args: --all-features
@@ -105,7 +92,7 @@ jobs:
if: ${{ matrix.rust != 'nightly' }}
with:
command: clippy
args: --workspace --all-targets --all-features -- -D warnings
args: --workspace --all-targets -- -D warnings
- name: Reclaim some disk space
uses: actions-rs/cargo@v1
@@ -173,17 +160,12 @@ jobs:
notification:
needs: build
runs-on: custom-runner-linux
runs-on: ubuntu-20.04
steps:
- name: Collect jobs status
uses: technote-space/workflow-conclusion-action@v2
- name: Check out repository code
uses: actions/checkout@v2
- name: install npm
uses: actions/setup-node@v3
if: env.WORKFLOW_CONCLUSION == 'failure'
with:
node-version: 16
- name: Keybase - Node Install
if: env.WORKFLOW_CONCLUSION == 'failure'
run: npm install
+1 -7
View File
@@ -98,7 +98,6 @@ jobs:
- uses: actions-rs/clippy-check@v1
name: Clippy checks
continue-on-error: true
with:
token: ${{ secrets.GITHUB_TOKEN }}
args: --all-features
@@ -176,17 +175,12 @@ jobs:
notification:
needs: [build,get_release]
runs-on: custom-runner-linux
runs-on: ubuntu-20.04
steps:
- name: Collect jobs status
uses: technote-space/workflow-conclusion-action@v2
- name: Check out repository code
uses: actions/checkout@v3
- name: install npm
uses: actions/setup-node@v3
if: env.WORKFLOW_CONCLUSION == 'failure'
with:
node-version: 16
- name: Keybase - Node Install
if: env.WORKFLOW_CONCLUSION == 'failure'
run: npm install
+1 -7
View File
@@ -98,7 +98,6 @@ jobs:
- uses: actions-rs/clippy-check@v1
name: Clippy checks
continue-on-error: true
with:
token: ${{ secrets.GITHUB_TOKEN }}
args: --all-features
@@ -176,17 +175,12 @@ jobs:
notification:
needs: [build,get_release]
runs-on: custom-runner-linux
runs-on: ubuntu-20.04
steps:
- name: Collect jobs status
uses: technote-space/workflow-conclusion-action@v2
- name: Check out repository code
uses: actions/checkout@v3
- name: install npm
uses: actions/setup-node@v3
if: env.WORKFLOW_CONCLUSION == 'failure'
with:
node-version: 16
- name: Keybase - Node Install
if: env.WORKFLOW_CONCLUSION == 'failure'
run: npm install
-1
View File
@@ -16,7 +16,6 @@ jobs:
- uses: actions/checkout@v2
- name: Install rsync
run: sudo apt-get install rsync
continue-on-error: true
- uses: rlespinasse/github-slug-action@v3.x
- uses: actions/setup-node@v3
with:
+2 -2
View File
@@ -60,7 +60,7 @@ jobs:
target/release/nym-gateway
target/release/nym-mixnode
target/release/nym-socks5-client
target/release/nym-api
target/release/nym-validator-api
target/release/nym-network-requester
target/release/nym-network-statistics
target/release/nym-cli
@@ -75,7 +75,7 @@ jobs:
target/release/nym-gateway
target/release/nym-mixnode
target/release/nym-socks5-client
target/release/nym-api
target/release/nym-validator-api
target/release/nym-network-requester
target/release/nym-network-statistics
target/release/nym-cli
@@ -12,7 +12,6 @@ jobs:
- uses: actions/checkout@v2
- name: Install rsync
run: sudo apt-get install rsync
continue-on-error: true
- uses: rlespinasse/github-slug-action@v3.x
- uses: actions/setup-node@v3
with:
-49
View File
@@ -1,49 +0,0 @@
name: CI for linting Typescript
on:
push:
paths:
- 'ts-packages/**'
- 'sdk/typescript/**'
- nym-connect
- nym-wallet
jobs:
build:
runs-on: custom-runner-linux
steps:
- uses: actions/checkout@v2
- 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: Setup yarn
run: npm install -g yarn
- name: Lint
run: yarn && yarn lint
- name: Keybase - Node Install
run: npm install
working-directory: .github/workflows/support-files
- name: Keybase - Send Notification
env:
NYM_NOTIFICATION_KIND: ts-packages
NYM_PROJECT_NAME: "ts-packages"
NYM_CI_WWW_BASE: "${{ secrets.NYM_CI_WWW_BASE }}"
NYM_CI_WWW_LOCATION: "ts-${{ env.GITHUB_REF_SLUG }}"
GIT_COMMIT_MESSAGE: "${{ github.event.head_commit.message }}"
GIT_BRANCH: "${GITHUB_REF##*/}"
KEYBASE_NYMBOT_USERNAME: "${{ secrets.KEYBASE_NYMBOT_USERNAME }}"
KEYBASE_NYMBOT_PAPERKEY: "${{ secrets.KEYBASE_NYMBOT_PAPERKEY }}"
KEYBASE_NYMBOT_TEAM: "${{ secrets.KEYBASE_NYMBOT_TEAM }}"
KEYBASE_NYM_CHANNEL: "ci-ts-packages"
IS_SUCCESS: "${{ job.status == 'success' }}"
MATRIX_SERVER: "${{ secrets.MATRIX_SERVER }}"
MATRIX_ROOM: "${{ secrets.MATRIX_ROOM }}"
MATRIX_USER_ID: "${{ secrets.MATRIX_USER_ID }}"
MATRIX_TOKEN: "${{ secrets.MATRIX_TOKEN }}"
MATRIX_DEVICE_ID: "${{ secrets.MATRIX_DEVICE_ID }}"
uses: docker://keybaseio/client:stable-node
with:
args: .github/workflows/support-files/notifications/entry_point.sh
-2
View File
@@ -16,7 +16,6 @@ jobs:
steps:
- name: Install Dependencies (Linux)
run: sudo apt-get update && sudo apt-get -y install libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev squashfs-tools
continue-on-error: true
- name: Check out repository code
uses: actions/checkout@v2
@@ -49,7 +48,6 @@ jobs:
- uses: actions-rs/clippy-check@v1
name: Clippy checks
continue-on-error: true
with:
token: ${{ secrets.GITHUB_TOKEN }}
args: --manifest-path nym-wallet/Cargo.toml --workspace --all-features
+5
View File
@@ -29,6 +29,11 @@ jobs:
command: build
args: --manifest-path clients/webassembly/Cargo.toml --target wasm32-unknown-unknown --features=coconut
- uses: actions-rs/cargo@v1
with:
command: test
args: --manifest-path clients/webassembly/Cargo.toml
- uses: actions-rs/cargo@v1
with:
command: fmt
-1
View File
@@ -41,4 +41,3 @@ storybook-static
envs/qwerty.env
Cargo.lock
nym-connect/Cargo.lock
.parcel-cache
+2 -23
View File
@@ -6,43 +6,22 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
### Added
- dkg rerun from scratch and dkg-specific epochs ([#2839])
- nym-sdk: add support for surb storage ([#2870])
- nym-sdk: enable reply-SURBs by default ([#2874])
[#2839]: https://github.com/nymtech/nym/pull/2839
[#2870]: https://github.com/nymtech/nym/pull/2870
[#2874]: https://github.com/nymtech/nym/pull/2874
## [v1.1.6] (2023-01-17)
### Added
- nym-sdk: added initial version of a Rust client sdk
- nym-api: added `/circulating-supply` endpoint ([#2814])
- nym-api: add endpoint listing detailed gateway info by @octol in https://github.com/nymtech/nym/pull/2833
### Changed
- streamline override_config functions -> there's a lot of duplicate if statements everywhere ([#2774])
- clean-up nym-api startup arguments/flags to use clap 3 and its macro-derived arguments ([#2772])
- renamed all references to validator_api to nym_api
- renamed all references to nymd to nyxd ([#2696])
- renamed all references to nymd to nyxd
- all-binaries: standarised argument names (note: old names should still be accepted) ([#2762]
### Fixed
- nym-api: should now correctly use `rewarding.enabled` config flag ([#2753])
[#2696]: https://github.com/nymtech/nym/pull/2696
[#2753]: https://github.com/nymtech/nym/pull/2753
[#2762]: https://github.com/nymtech/nym/pull/2762
[#2814]: https://github.com/nymtech/nym/pull/2814
[#2772]: https://github.com/nymtech/nym/pull/2772
[#2774]: https://github.com/nymtech/nym/pull/2774
## [v1.1.5] (2023-01-10)
## [v1.1.5] (2022-01-10)
### Added
Generated
+71 -87
View File
@@ -634,13 +634,13 @@ dependencies = [
[[package]]
name = "clap"
version = "4.1.1"
version = "4.0.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ec7a4128863c188deefe750ac1d1dfe66c236909f845af04beed823638dc1b2"
checksum = "a7db700bc935f9e43e88d00b0850dae18a63773cfbec6d8e070fccf7fef89a39"
dependencies = [
"bitflags",
"clap_derive",
"clap_lex 0.3.1",
"clap_lex 0.3.0",
"is-terminal",
"once_cell",
"strsim",
@@ -649,28 +649,28 @@ dependencies = [
[[package]]
name = "clap_complete"
version = "4.1.0"
version = "4.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce8955d4e8cd4f28f9a01c93a050194c4d131e73ca02f6636bcddbed867014d7"
checksum = "10861370d2ba66b0f5989f83ebf35db6421713fd92351790e7fdd6c36774c56b"
dependencies = [
"clap 4.1.1",
"clap 4.0.32",
]
[[package]]
name = "clap_complete_fig"
version = "4.1.0"
version = "4.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf0c76d8fcf782a1102ccfcd10ca8246e7fdd609c1cd6deddbb96cb638e9bb5c"
checksum = "46b30e010e669cd021e5004f3be26cff6b7c08d2a8a0d65b48d43a8cc0efd6c3"
dependencies = [
"clap 4.1.1",
"clap 4.0.32",
"clap_complete",
]
[[package]]
name = "clap_derive"
version = "4.1.0"
version = "4.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "684a277d672e91966334af371f1a7b5833f9aa00b07c84e92fbce95e00208ce8"
checksum = "0177313f9f02afc995627906bbd8967e2be069f5261954222dac78290c2b9014"
dependencies = [
"heck 0.4.0",
"proc-macro-error",
@@ -690,9 +690,9 @@ dependencies = [
[[package]]
name = "clap_lex"
version = "0.3.1"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "783fe232adfca04f90f56201b26d79682d4cd2625e0bc7290b95123afe558ade"
checksum = "0d4198f73e42b4936b35b5bb248d81d2b595ecb170da0bac7655c54eedfa8da8"
dependencies = [
"os_str_bytes",
]
@@ -707,7 +707,7 @@ dependencies = [
[[package]]
name = "client-core"
version = "1.1.6"
version = "1.1.5"
dependencies = [
"async-trait",
"client-connections",
@@ -823,7 +823,7 @@ dependencies = [
name = "completions"
version = "0.1.0"
dependencies = [
"clap 4.1.1",
"clap 4.0.32",
"clap_complete",
"clap_complete_fig",
]
@@ -1061,7 +1061,7 @@ version = "0.1.0"
dependencies = [
"bip39",
"cfg-if 0.1.10",
"clap 4.1.1",
"clap 4.0.32",
"coconut-interface",
"completions",
"config",
@@ -1574,7 +1574,7 @@ dependencies = [
"hashbrown 0.12.3",
"lock_api",
"once_cell",
"parking_lot_core 0.9.6",
"parking_lot_core 0.9.5",
]
[[package]]
@@ -1728,9 +1728,9 @@ dependencies = [
[[package]]
name = "ed25519"
version = "1.5.3"
version = "1.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91cff35c70bba8a626e3185d8cd48cc11b5437e1a5bcd15b9b5fa3c64b6dfee7"
checksum = "1e9c280362032ea4203659fc489832d0204ef09f247a0506f170dafcac08c369"
dependencies = [
"serde",
"signature",
@@ -1901,7 +1901,7 @@ name = "explorer-api"
version = "1.1.2"
dependencies = [
"chrono",
"clap 4.1.1",
"clap 4.0.32",
"contracts-common",
"dotenv",
"humantime-serde",
@@ -2368,15 +2368,6 @@ dependencies = [
"subtle 2.4.1",
]
[[package]]
name = "group-contract-common"
version = "0.1.0"
dependencies = [
"cw4",
"schemars",
"serde",
]
[[package]]
name = "h2"
version = "0.3.15"
@@ -2844,9 +2835,9 @@ dependencies = [
[[package]]
name = "io-lifetimes"
version = "1.0.4"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7d6c6f8c91b4b9ed43484ad1a938e393caf35960fce7f82a040497207bd8e9e"
checksum = "46112a93252b123d31a119a8d1a1ac19deac4fac6e0e8b0df58f0d4e5870e63c"
dependencies = [
"libc",
"windows-sys",
@@ -3230,7 +3221,6 @@ dependencies = [
"futures",
"log",
"nymsphinx",
"task",
"tokio",
"tokio-util",
]
@@ -3353,9 +3343,9 @@ checksum = "b93853da6d84c2e3c7d730d6473e8817692dd89be387eb01b94d7f108ecb5b8c"
[[package]]
name = "nom"
version = "7.1.3"
version = "7.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
checksum = "e5507769c4919c998e69e49c839d9dc6e693ede4cc4290d6ad8b41d4f09c548c"
dependencies = [
"memchr",
"minimal-lexical",
@@ -3443,7 +3433,7 @@ dependencies = [
"bs58",
"build-information",
"cfg-if 1.0.0",
"clap 4.1.1",
"clap 4.0.32",
"coconut-bandwidth-contract-common",
"coconut-dkg-common",
"coconut-interface",
@@ -3456,7 +3446,6 @@ dependencies = [
"crypto",
"cw-utils",
"cw3",
"cw4",
"dirs",
"dkg",
"dotenv",
@@ -3498,7 +3487,6 @@ dependencies = [
"url",
"validator-client",
"version-checker",
"vesting-contract-common",
]
[[package]]
@@ -3533,13 +3521,13 @@ dependencies = [
[[package]]
name = "nym-cli"
version = "1.1.6"
version = "1.1.5"
dependencies = [
"anyhow",
"base64 0.13.1",
"bip39",
"bs58",
"clap 4.1.1",
"clap 4.0.32",
"clap_complete",
"clap_complete_fig",
"dotenv",
@@ -3563,7 +3551,7 @@ dependencies = [
"bip39",
"bs58",
"cfg-if 1.0.0",
"clap 4.1.1",
"clap 4.0.32",
"coconut-bandwidth-contract-common",
"coconut-dkg-common",
"comfy-table",
@@ -3591,10 +3579,10 @@ dependencies = [
[[package]]
name = "nym-client"
version = "1.1.6"
version = "1.1.5"
dependencies = [
"build-information",
"clap 4.1.1",
"clap 4.0.32",
"client-connections",
"client-core",
"coconut-interface",
@@ -3631,7 +3619,7 @@ dependencies = [
[[package]]
name = "nym-gateway"
version = "1.1.6"
version = "1.1.5"
dependencies = [
"anyhow",
"async-trait",
@@ -3639,7 +3627,7 @@ dependencies = [
"bip39",
"bs58",
"build-information",
"clap 4.1.1",
"clap 4.0.32",
"coconut-interface",
"colored",
"completions",
@@ -3670,7 +3658,6 @@ dependencies = [
"sqlx 0.5.13",
"statistics-common",
"subtle-encoding",
"task",
"thiserror",
"tokio",
"tokio-stream",
@@ -3683,13 +3670,13 @@ dependencies = [
[[package]]
name = "nym-mixnode"
version = "1.1.6"
version = "1.1.5"
dependencies = [
"anyhow",
"atty",
"bs58",
"build-information",
"clap 4.1.1",
"clap 4.0.32",
"colored",
"completions",
"config",
@@ -3728,10 +3715,10 @@ dependencies = [
[[package]]
name = "nym-network-requester"
version = "1.1.6"
version = "1.1.5"
dependencies = [
"async-trait",
"clap 4.1.1",
"clap 4.0.32",
"client-connections",
"completions",
"dirs",
@@ -3760,7 +3747,7 @@ dependencies = [
[[package]]
name = "nym-network-statistics"
version = "1.1.6"
version = "1.1.5"
dependencies = [
"dirs",
"log",
@@ -3812,7 +3799,6 @@ dependencies = [
"tokio",
"toml",
"url",
"validator-client",
]
[[package]]
@@ -3820,7 +3806,7 @@ name = "nym-socks5-client"
version = "1.1.5"
dependencies = [
"build-information",
"clap 4.1.1",
"clap 4.0.32",
"client-connections",
"client-core",
"coconut-interface",
@@ -4191,7 +4177,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
dependencies = [
"lock_api",
"parking_lot_core 0.9.6",
"parking_lot_core 0.9.5",
]
[[package]]
@@ -4210,9 +4196,9 @@ dependencies = [
[[package]]
name = "parking_lot_core"
version = "0.9.6"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba1ef8814b5c993410bb3adfad7a5ed269563e4a2f90c41f5d85be7fb47133bf"
checksum = "7ff9f3fef3968a3ec5945535ed654cb38ff72d7495a25619e2247fb15a2ed9ba"
dependencies = [
"cfg-if 1.0.0",
"libc",
@@ -4496,9 +4482,9 @@ dependencies = [
[[package]]
name = "proc-macro2"
version = "1.0.50"
version = "1.0.49"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ef7d57beacfaf2d8aee5937dab7b7f28de3cb8b1828479bb5de2a7106f2bae2"
checksum = "57a8eca9f9c4ffde41714334dee777596264c7825420f521abc92b5b5deb63a5"
dependencies = [
"unicode-ident",
]
@@ -5197,9 +5183,9 @@ dependencies = [
[[package]]
name = "rustls"
version = "0.20.8"
version = "0.20.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fff78fc74d175294f4e83b28343315ffcfb114b156f0185e9741cb5570f50e2f"
checksum = "539a2bfe908f471bfa933876bd1eb6a19cf2176d375f82ef7f99530a40e48c2c"
dependencies = [
"log",
"ring",
@@ -5734,9 +5720,9 @@ dependencies = [
[[package]]
name = "sqlformat"
version = "0.2.1"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c12bc9199d1db8234678b7051747c07f517cdcf019262d1847b94ec8b1aee3e"
checksum = "f87e292b4291f154971a43c3774364e2cbcaec599d3f5bf6fa9d122885dbc38a"
dependencies = [
"itertools",
"nom",
@@ -5843,11 +5829,11 @@ dependencies = [
"once_cell",
"paste",
"percent-encoding",
"rustls 0.20.8",
"rustls 0.20.7",
"rustls-pemfile",
"sha2 0.10.6",
"smallvec 1.10.0",
"sqlformat 0.2.1",
"sqlformat 0.2.0",
"sqlx-rt 0.6.2",
"stringprep",
"thiserror",
@@ -6206,9 +6192,9 @@ dependencies = [
[[package]]
name = "termcolor"
version = "1.2.0"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6"
checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755"
dependencies = [
"winapi-util",
]
@@ -6375,7 +6361,7 @@ version = "0.23.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59"
dependencies = [
"rustls 0.20.8",
"rustls 0.20.7",
"tokio",
"webpki 0.22.0",
]
@@ -6871,11 +6857,9 @@ dependencies = [
"cosmrs",
"cosmwasm-std",
"cw3",
"cw4",
"execute",
"flate2",
"futures",
"group-contract-common",
"itertools",
"log",
"mixnet-contract-common",
@@ -7220,19 +7204,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc 0.42.1",
"windows_i686_gnu 0.42.1",
"windows_i686_msvc 0.42.1",
"windows_x86_64_gnu 0.42.1",
"windows_aarch64_msvc 0.42.0",
"windows_i686_gnu 0.42.0",
"windows_i686_msvc 0.42.0",
"windows_x86_64_gnu 0.42.0",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc 0.42.1",
"windows_x86_64_msvc 0.42.0",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.42.1"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608"
checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e"
[[package]]
name = "windows_aarch64_msvc"
@@ -7242,9 +7226,9 @@ checksum = "ec7711666096bd4096ffa835238905bb33fb87267910e154b18b44eaabb340f2"
[[package]]
name = "windows_aarch64_msvc"
version = "0.42.1"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7"
checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4"
[[package]]
name = "windows_i686_gnu"
@@ -7254,9 +7238,9 @@ checksum = "763fc57100a5f7042e3057e7e8d9bdd7860d330070251a73d003563a3bb49e1b"
[[package]]
name = "windows_i686_gnu"
version = "0.42.1"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640"
checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7"
[[package]]
name = "windows_i686_msvc"
@@ -7266,9 +7250,9 @@ checksum = "7bc7cbfe58828921e10a9f446fcaaf649204dcfe6c1ddd712c5eebae6bda1106"
[[package]]
name = "windows_i686_msvc"
version = "0.42.1"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605"
checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246"
[[package]]
name = "windows_x86_64_gnu"
@@ -7278,15 +7262,15 @@ checksum = "6868c165637d653ae1e8dc4d82c25d4f97dd6605eaa8d784b5c6e0ab2a252b65"
[[package]]
name = "windows_x86_64_gnu"
version = "0.42.1"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45"
checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.42.1"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463"
checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028"
[[package]]
name = "windows_x86_64_msvc"
@@ -7296,9 +7280,9 @@ checksum = "5e4d40883ae9cae962787ca76ba76390ffa29214667a111db9e0a1ad8377e809"
[[package]]
name = "windows_x86_64_msvc"
version = "0.42.1"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd"
checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5"
[[package]]
name = "winreg"
-10
View File
@@ -34,7 +34,6 @@ members = [
"common/cosmwasm-smart-contracts/coconut-bandwidth-contract",
"common/cosmwasm-smart-contracts/coconut-dkg",
"common/cosmwasm-smart-contracts/contracts-common",
"common/cosmwasm-smart-contracts/group-contract",
"common/cosmwasm-smart-contracts/mixnet-contract",
"common/cosmwasm-smart-contracts/multisig-contract",
"common/cosmwasm-smart-contracts/vesting-contract",
@@ -96,12 +95,3 @@ default-members = [
]
exclude = ["explorer", "contracts", "clients/webassembly", "nym-wallet", "nym-connect"]
[workspace.package]
authors = ["Nym Technologies SA"]
repository = "https://github.com/nymtech/nym"
homepage = "https://nymtech.net"
edition = "2021"
[workspace.dependencies]
log = "0.4"
+4 -1
View File
@@ -4,7 +4,7 @@ no-clippy: build cargo-test wasm fmt
happy: fmt clippy-happy test
clippy-all: clippy-main clippy-coconut clippy-all-contracts clippy-all-wallet clippy-all-connect clippy-all-wasm-client
clippy-happy: clippy-happy-main clippy-happy-contracts clippy-happy-wallet clippy-happy-connect
cargo-test: test-main test-contracts test-wallet test-connect test-coconut
cargo-test: test-main test-contracts test-wallet test-connect test-coconut test-wasm-client
cargo-test-expensive: test-main-expensive test-contracts-expensive test-wallet-expensive test-connect-expensive test-coconut-expensive
build: build-contracts build-wallet build-main build-connect build-wasm-client
fmt: fmt-main fmt-contracts fmt-wallet fmt-connect fmt-wasm-client
@@ -68,6 +68,9 @@ test-wallet:
test-wallet-expensive:
cargo test --manifest-path nym-wallet/Cargo.toml --all-features -- --ignored
test-wasm-client:
cargo test --workspace --manifest-path clients/webassembly/Cargo.toml --all-features
test-connect:
cargo test --manifest-path nym-connect/Cargo.toml --all-features
+6 -6
View File
@@ -1,6 +1,6 @@
[package]
name = "client-core"
version = "1.1.6"
version = "1.1.5"
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"]
edition = "2021"
rust-version = "1.66"
@@ -13,14 +13,14 @@ dirs = "4.0"
dashmap = "5.4.0"
futures = "0.3"
humantime-serde = "1.0"
log = { workspace = true }
log = "0.4"
rand = { version = "0.7.3", features = ["wasm-bindgen"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0.89"
tap = "1.0.1"
thiserror = "1.0.34"
url = { version ="2.2", features = ["serde"] }
tokio = { version = "1.24.1", features = ["macros"]}
tokio = { version = "1.21.2", features = ["macros"]}
time = "0.3.17"
# internal
@@ -38,11 +38,11 @@ validator-client = { path = "../../common/client-libs/validator-client", default
task = { path = "../../common/task" }
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.tokio-stream]
version = "0.1.11"
version = "0.1.9"
features = ["time"]
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.tokio]
version = "1.24.1"
version = "1.21.2"
features = ["time"]
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.sqlx]
@@ -75,7 +75,7 @@ features = ["wasm-bindgen"]
tempfile = "3.1.0"
[build-dependencies]
tokio = { version = "1.24.1", features = ["rt-multi-thread", "macros"] }
tokio = { version = "1.21.2", features = ["rt-multi-thread", "macros"] }
sqlx = { version = "0.6.2", features = ["runtime-tokio-rustls", "sqlite", "macros", "migrate"] }
[features]
+2 -2
View File
@@ -9,9 +9,9 @@ async fn main() {
use std::env;
let out_dir = env::var("OUT_DIR").unwrap();
let database_path = format!("{out_dir}/fs-surbs-example.sqlite");
let database_path = format!("{}/fs-surbs-example.sqlite", out_dir);
let mut conn = SqliteConnection::connect(&format!("sqlite://{database_path}?mode=rwc"))
let mut conn = SqliteConnection::connect(&format!("sqlite://{}?mode=rwc", database_path))
.await
.expect("Failed to create SQLx database connection");
@@ -25,8 +25,6 @@ use client_connections::{ConnectionCommandReceiver, ConnectionCommandSender, Lan
use crypto::asymmetric::{encryption, identity};
use futures::channel::mpsc;
use gateway_client::bandwidth::BandwidthController;
#[cfg(target_arch = "wasm32")]
use gateway_client::wasm_mockups::CosmWasmClient;
use gateway_client::{
AcknowledgementReceiver, AcknowledgementSender, GatewayClient, MixnetMessageReceiver,
MixnetMessageSender,
@@ -41,8 +39,6 @@ use std::time::Duration;
use tap::TapFallible;
use task::{TaskClient, TaskManager};
use url::Url;
#[cfg(not(target_arch = "wasm32"))]
use validator_client::nyxd::CosmWasmClient;
use super::received_buffer::ReceivedBufferMessage;
@@ -133,7 +129,7 @@ impl From<bool> for CredentialsToggle {
}
}
pub struct BaseClientBuilder<'a, B, C: Clone> {
pub struct BaseClientBuilder<'a, B> {
// due to wasm limitations I had to split it like this : (
gateway_config: &'a GatewayEndpointConfig,
debug_config: &'a DebugConfig,
@@ -141,21 +137,20 @@ pub struct BaseClientBuilder<'a, B, C: Clone> {
nym_api_endpoints: Vec<Url>,
reply_storage_backend: B,
bandwidth_controller: Option<BandwidthController<C>>,
bandwidth_controller: Option<BandwidthController>,
key_manager: KeyManager,
}
impl<'a, B, C> BaseClientBuilder<'a, B, C>
impl<'a, B> BaseClientBuilder<'a, B>
where
B: ReplyStorageBackend + Send + Sync + 'static,
C: CosmWasmClient + Sync + Send + Clone + 'static,
{
pub fn new_from_base_config<T>(
base_config: &'a Config<T>,
key_manager: KeyManager,
bandwidth_controller: Option<BandwidthController<C>>,
bandwidth_controller: Option<BandwidthController>,
reply_storage_backend: B,
) -> BaseClientBuilder<'a, B, C> {
) -> BaseClientBuilder<'a, B> {
BaseClientBuilder {
gateway_config: base_config.get_gateway_endpoint_config(),
debug_config: base_config.get_debug_config(),
@@ -171,11 +166,11 @@ where
gateway_config: &'a GatewayEndpointConfig,
debug_config: &'a DebugConfig,
key_manager: KeyManager,
bandwidth_controller: Option<BandwidthController<C>>,
bandwidth_controller: Option<BandwidthController>,
reply_storage_backend: B,
credentials_toggle: CredentialsToggle,
nym_api_endpoints: Vec<Url>,
) -> BaseClientBuilder<'a, B, C> {
) -> BaseClientBuilder<'a, B> {
BaseClientBuilder {
gateway_config,
debug_config,
@@ -284,7 +279,7 @@ where
mixnet_message_sender: MixnetMessageSender,
ack_sender: AcknowledgementSender,
shutdown: TaskClient,
) -> Result<GatewayClient<C>, ClientCoreError> {
) -> Result<GatewayClient, ClientCoreError> {
let gateway_id = self.gateway_config.gateway_id.clone();
if gateway_id.is_empty() {
return Err(ClientCoreError::GatewayIdUnknown);
@@ -370,7 +365,7 @@ where
// over it. Perhaps GatewayClient needs to be thread-shareable or have some channel for
// requests?
fn start_mix_traffic_controller(
gateway_client: GatewayClient<C>,
gateway_client: GatewayClient,
shutdown: TaskClient,
) -> BatchMixMessageSender {
info!("Starting mix traffic controller...");
@@ -386,32 +381,22 @@ where
where
<B as ReplyStorageBackend>::StorageError: Sync + Send,
{
if backend.is_active() {
log::trace!("Setup persistent reply storage");
let persistent_storage = PersistentReplyStorage::new(backend);
let mem_store = persistent_storage
.load_state_from_backend()
let persistent_storage = PersistentReplyStorage::new(backend);
let mem_store = persistent_storage
.load_state_from_backend()
.await
.map_err(|err| ClientCoreError::SurbStorageError {
source: Box::new(err),
})?;
let store_clone = mem_store.clone();
spawn_future(async move {
persistent_storage
.flush_on_shutdown(store_clone, shutdown)
.await
.map_err(|err| ClientCoreError::SurbStorageError {
source: Box::new(err),
})?;
});
let store_clone = mem_store.clone();
spawn_future(async move {
persistent_storage
.flush_on_shutdown(store_clone, shutdown)
.await
});
Ok(mem_store)
} else {
log::trace!("Setup inactive reply storage");
Ok(backend
.get_inactive_storage()
.map_err(|err| ClientCoreError::SurbStorageError {
source: Box::new(err),
})?)
}
Ok(mem_store)
}
pub async fn start_base(mut self) -> Result<BaseClient, ClientCoreError>
@@ -43,14 +43,6 @@ async fn setup_fresh_backend<P: AsRef<Path>>(
Ok(storage_backend)
}
fn setup_inactive_backend(debug_config: &DebugConfig) -> fs_backend::Backend {
info!("creating inactive surb database");
fs_backend::Backend::new_inactive(
debug_config.minimum_reply_surb_storage_threshold,
debug_config.maximum_reply_surb_storage_threshold,
)
}
fn archive_corrupted_database<P: AsRef<Path>>(db_path: P) -> io::Result<()> {
let db_path = db_path.as_ref();
debug_assert!(db_path.exists());
@@ -61,7 +53,7 @@ fn archive_corrupted_database<P: AsRef<Path>>(db_path: P) -> io::Result<()> {
let new_extension =
if let Some(existing_extension) = db_path.extension().and_then(|ext| ext.to_str()) {
format!("{existing_extension}.{suffix}")
format!("{existing_extension}.{}", suffix)
} else {
suffix
};
@@ -73,29 +65,24 @@ fn archive_corrupted_database<P: AsRef<Path>>(db_path: P) -> io::Result<()> {
}
pub async fn setup_fs_reply_surb_backend<P: AsRef<Path>>(
db_path: Option<P>,
db_path: P,
debug_config: &DebugConfig,
) -> Result<fs_backend::Backend, ClientCoreError> {
if let Some(db_path) = db_path {
// if the database file doesnt exist, initialise fresh storage, otherwise attempt to load
// the existing one
let db_path = db_path.as_ref();
if db_path.exists() {
info!("loading existing surb database");
match fs_backend::Backend::try_load(db_path).await {
Ok(backend) => Ok(backend),
Err(err) => {
error!("failed to setup persistent storage backend for our reply needs: {err}. We're going to create a fresh database instead. This behaviour might change in the future");
// if the database file doesnt exist, initialise fresh storage, otherwise attempt to load the existing one
let db_path = db_path.as_ref();
if db_path.exists() {
info!("loading existing surb database");
match fs_backend::Backend::try_load(db_path).await {
Ok(backend) => Ok(backend),
Err(err) => {
error!("failed to setup persistent storage backend for our reply needs: {err}. We're going to create a fresh database instead. This behaviour might change in the future");
archive_corrupted_database(db_path)?;
setup_fresh_backend(db_path, debug_config).await
}
archive_corrupted_database(db_path)?;
setup_fresh_backend(db_path, debug_config).await
}
} else {
setup_fresh_backend(db_path, debug_config).await
}
} else {
Ok(setup_inactive_backend(debug_config))
setup_fresh_backend(db_path, debug_config).await
}
}
@@ -42,6 +42,9 @@ pub struct KeyManager {
*/
impl KeyManager {
// this is actually **NOT** dead code
// I have absolutely no idea why the compiler insists it's unused. The call happens during client::init::execute
#[allow(dead_code)]
/// Creates new instance of a [`KeyManager`]
pub fn new<R>(rng: &mut R) -> Self
where
@@ -127,6 +130,9 @@ impl KeyManager {
Ok(key_manager)
}
// this is actually **NOT** dead code
// I have absolutely no idea why the compiler insists it's unused. The call happens during client::init::execute
#[allow(dead_code)]
/// Stores all available keys on the disk.
// While perhaps there is no much point in storing the `AckKey` on the disk,
// it is done so for the consistency sake so that you wouldn't require an rng instance
@@ -205,6 +211,9 @@ impl KeyManager {
Arc::clone(&self.ack_key)
}
// this is actually **NOT** dead code
// I have absolutely no idea why the compiler insists it's unused. The call happens during client::init::execute
#[allow(dead_code)]
/// After shared key with the gateway is derived, puts its ownership to this instance of a [`KeyManager`].
pub fn insert_gateway_shared_key(&mut self, gateway_shared_key: Arc<SharedKeys>) {
self.gateway_shared_key = Some(gateway_shared_key)
+5 -14
View File
@@ -2,13 +2,9 @@
// SPDX-License-Identifier: Apache-2.0
use crate::spawn_future;
#[cfg(target_arch = "wasm32")]
use gateway_client::wasm_mockups::CosmWasmClient;
use gateway_client::GatewayClient;
use log::*;
use nymsphinx::forwarding::packet::MixPacket;
#[cfg(not(target_arch = "wasm32"))]
use validator_client::nyxd::CosmWasmClient;
pub type BatchMixMessageSender = tokio::sync::mpsc::Sender<Vec<MixPacket>>;
pub type BatchMixMessageReceiver = tokio::sync::mpsc::Receiver<Vec<MixPacket>>;
@@ -17,10 +13,10 @@ pub type BatchMixMessageReceiver = tokio::sync::mpsc::Receiver<Vec<MixPacket>>;
pub const MIX_MESSAGE_RECEIVER_BUFFER_SIZE: usize = 32;
const MAX_FAILURE_COUNT: usize = 100;
pub struct MixTrafficController<C: Clone> {
pub struct MixTrafficController {
// TODO: most likely to be replaced by some higher level construct as
// later on gateway_client will need to be accessible by other entities
gateway_client: GatewayClient<C>,
gateway_client: GatewayClient,
mix_rx: BatchMixMessageReceiver,
// TODO: this is temporary work-around.
@@ -28,13 +24,8 @@ pub struct MixTrafficController<C: Clone> {
consecutive_gateway_failure_count: usize,
}
impl<C> MixTrafficController<C>
where
C: CosmWasmClient + Sync + Send + Clone + 'static,
{
pub fn new(
gateway_client: GatewayClient<C>,
) -> (MixTrafficController<C>, BatchMixMessageSender) {
impl MixTrafficController {
pub fn new(gateway_client: GatewayClient) -> (MixTrafficController, BatchMixMessageSender) {
let (sphinx_message_sender, sphinx_message_receiver) =
tokio::sync::mpsc::channel(MIX_MESSAGE_RECEIVER_BUFFER_SIZE);
(
@@ -66,7 +57,7 @@ where
if self.consecutive_gateway_failure_count == MAX_FAILURE_COUNT {
// todo: in the future this should initiate a 'graceful' shutdown or try
// to reconnect?
panic!("failed to send sphinx packet to the gateway {MAX_FAILURE_COUNT} times in a row - assuming the gateway is dead. Can't do anything about it yet :(")
panic!("failed to send sphinx packet to the gateway {} times in a row - assuming the gateway is dead. Can't do anything about it yet :(", MAX_FAILURE_COUNT)
}
}
Ok(_) => {
@@ -471,10 +471,14 @@ where
let mult = self.sending_delay_controller.current_multiplier();
let delay = self.current_average_message_sending_delay().as_millis();
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: {:.2} kiB ({packets}), no delay",
backlog
)
} else {
format!(
"Status: {lanes} lanes, backlog: {backlog:.2} kiB ({packets}), avg delay: {delay}ms ({mult})"
"Status: {lanes} lanes, backlog: {:.2} kiB ({packets}), avg delay: {}ms ({mult})",
backlog, delay
)
};
if packets > 1000 {
@@ -41,8 +41,4 @@ impl ReplyStorageBackend for Backend {
async fn load_surb_storage(&self) -> Result<CombinedReplyStorage, Self::StorageError> {
self.empty.load_surb_storage().await
}
fn get_inactive_storage(&self) -> Result<CombinedReplyStorage, Self::StorageError> {
self.empty.get_inactive_storage()
}
}
@@ -10,12 +10,6 @@ pub enum StorageError {
#[error("the provided database path doesn't have a filename defined")]
DatabasePathWithoutFilename { provided_path: PathBuf },
#[error("unable to create the directory for the database")]
DatabasePathUnableToCreateParentDirectory {
provided_path: PathBuf,
source: io::Error,
},
#[error("failed to rename our databse file - {source}")]
DatabaseRenameError {
#[source]
@@ -20,16 +20,6 @@ impl StorageManager {
database_path: P,
fresh: bool,
) -> Result<Self, StorageError> {
// ensure the whole directory structure exists
if let Some(parent_dir) = database_path.as_ref().parent() {
std::fs::create_dir_all(parent_dir).map_err(|source| {
StorageError::DatabasePathUnableToCreateParentDirectory {
provided_path: database_path.as_ref().to_path_buf(),
source,
}
})?;
}
let mut opts = sqlx::sqlite::SqliteConnectOptions::new()
.filename(database_path)
.create_if_missing(fresh);
@@ -22,49 +22,11 @@ mod error;
mod manager;
mod models;
#[derive(Debug)]
enum StorageManagerState {
Storage(StorageManager),
Inactive(InactiveMetadata),
}
// When the storage backaed is initialized as inactive, it will still contain metadata parameters
// that will be needed when the in-mem storage is fetched for use.
#[derive(Debug)]
struct InactiveMetadata {
pub minimum_reply_surb_storage_threshold: usize,
pub maximum_reply_surb_storage_threshold: usize,
}
impl StorageManagerState {
fn get(&self) -> &StorageManager {
match self {
StorageManagerState::Storage(manager) => manager,
StorageManagerState::Inactive(_) => {
panic!("tried to get storage of an inactive backend")
}
}
}
fn get_mut(&mut self) -> &mut StorageManager {
match self {
StorageManagerState::Storage(manager) => manager,
StorageManagerState::Inactive(_) => {
panic!("tried to get storage of an inactive backend")
}
}
}
fn is_active(&self) -> bool {
matches!(self, StorageManagerState::Storage(_))
}
}
#[derive(Debug)]
pub struct Backend {
temporary_old_path: Option<PathBuf>,
database_path: PathBuf,
manager: StorageManagerState,
manager: StorageManager,
}
impl Backend {
@@ -78,30 +40,15 @@ impl Backend {
});
}
let manager = StorageManager::init(database_path, true).await?;
manager.create_status_table().await?;
let backend = Backend {
temporary_old_path: None,
database_path: owned_path,
manager: StorageManagerState::Storage(manager),
manager: StorageManager::init(database_path, true).await?,
};
Ok(backend)
}
backend.manager.create_status_table().await?;
pub fn new_inactive(
minimum_reply_surb_storage_threshold: usize,
maximum_reply_surb_storage_threshold: usize,
) -> Self {
Backend {
temporary_old_path: None,
database_path: PathBuf::new(),
manager: StorageManagerState::Inactive(InactiveMetadata {
minimum_reply_surb_storage_threshold,
maximum_reply_surb_storage_threshold,
}),
}
Ok(backend)
}
pub async fn try_load<P: AsRef<Path>>(database_path: P) -> Result<Self, StorageError> {
@@ -172,12 +119,12 @@ impl Backend {
Ok(Backend {
temporary_old_path: None,
database_path: owned_path,
manager: StorageManagerState::Storage(manager),
manager,
})
}
async fn close_pool(&mut self) {
self.manager.get_mut().connection_pool.close().await;
self.manager.connection_pool.close().await;
}
async fn rotate(&mut self) -> Result<(), StorageError> {
@@ -196,9 +143,8 @@ impl Backend {
fs::rename(&self.database_path, &temp_old)
.map_err(|err| StorageError::DatabaseRenameError { source: err })?;
self.manager =
StorageManagerState::Storage(StorageManager::init(&self.database_path, true).await?);
self.manager.get_mut().create_status_table().await?;
self.manager = StorageManager::init(&self.database_path, true).await?;
self.manager.create_status_table().await?;
self.temporary_old_path = Some(temp_old);
Ok(())
@@ -215,27 +161,26 @@ impl Backend {
}
async fn start_storage_flush(&self) -> Result<(), StorageError> {
Ok(self.manager.get().set_flush_status(true).await?)
Ok(self.manager.set_flush_status(true).await?)
}
async fn end_storage_flush(&self) -> Result<(), StorageError> {
self.manager
.get()
.set_previous_flush_timestamp(OffsetDateTime::now_utc().unix_timestamp())
.await?;
Ok(self.manager.get().set_flush_status(false).await?)
Ok(self.manager.set_flush_status(false).await?)
}
async fn start_client_use(&self) -> Result<(), StorageError> {
Ok(self.manager.get().set_client_in_use_status(true).await?)
Ok(self.manager.set_client_in_use_status(true).await?)
}
async fn stop_client_use(&self) -> Result<(), StorageError> {
Ok(self.manager.get().set_client_in_use_status(false).await?)
Ok(self.manager.set_client_in_use_status(false).await?)
}
async fn get_stored_tags(&self) -> Result<UsedSenderTags, StorageError> {
let stored = self.manager.get().get_tags().await?;
let stored = self.manager.get_tags().await?;
// stop at the first instance of corruption. if even a single entry is malformed,
// something weird has happened and we can't trust the rest of the data
@@ -251,7 +196,6 @@ impl Backend {
for map_ref in tags.as_raw_iter() {
let (recipient, tag) = map_ref.pair();
self.manager
.get()
.insert_tag(StoredSenderTag::new(*recipient, *tag))
.await?;
}
@@ -259,7 +203,7 @@ impl Backend {
}
async fn get_stored_reply_keys(&self) -> Result<SentReplyKeys, StorageError> {
let stored = self.manager.get().get_reply_keys().await?;
let stored = self.manager.get_reply_keys().await?;
// stop at the first instance of corruption. if even a single entry is malformed,
// something weird has happened and we can't trust the rest of the data
@@ -275,7 +219,6 @@ impl Backend {
for map_ref in reply_keys.as_raw_iter() {
let (digest, key) = map_ref.pair();
self.manager
.get()
.insert_reply_key(StoredReplyKey::new(*digest, *key))
.await?;
}
@@ -283,7 +226,7 @@ impl Backend {
}
async fn get_stored_reply_surbs(&self) -> Result<ReceivedReplySurbsMap, StorageError> {
let surb_senders = self.manager.get().get_surb_senders().await?;
let surb_senders = self.manager.get_surb_senders().await?;
let metadata = self.get_reply_surb_storage_metadata().await?;
let mut received_surbs = Vec::with_capacity(surb_senders.len());
@@ -293,7 +236,6 @@ impl Backend {
sender.try_into()?;
let stored_surbs = self
.manager
.get()
.get_reply_surbs(sender_id)
.await?
.into_iter()
@@ -321,7 +263,6 @@ impl Backend {
let (tag, received_surbs) = map_ref.pair();
let sender_id = self
.manager
.get()
.insert_surb_sender(StoredSurbSender::new(
*tag,
received_surbs.surbs_last_received_at(),
@@ -330,7 +271,6 @@ impl Backend {
for reply_surb in received_surbs.surbs_ref() {
self.manager
.get()
.insert_reply_surb(StoredReplySurb::new(sender_id, reply_surb))
.await?
}
@@ -342,7 +282,6 @@ impl Backend {
&self,
) -> Result<ReplySurbStorageMetadata, StorageError> {
self.manager
.get()
.get_reply_surb_storage_metadata()
.await
.map_err(Into::into)
@@ -353,7 +292,6 @@ impl Backend {
reply_surbs: &ReceivedReplySurbsMap,
) -> Result<(), StorageError> {
self.manager
.get()
.insert_reply_surb_storage_metadata(ReplySurbStorageMetadata::new(
reply_surbs.min_surb_threshold(),
reply_surbs.max_surb_threshold(),
@@ -367,10 +305,6 @@ impl Backend {
impl ReplyStorageBackend for Backend {
type StorageError = error::StorageError;
fn is_active(&self) -> bool {
self.manager.is_active()
}
async fn start_storage_session(&self) -> Result<(), Self::StorageError> {
self.start_client_use().await
}
@@ -408,18 +342,6 @@ impl ReplyStorageBackend for Backend {
Ok(CombinedReplyStorage::load(reply_keys, reply_surbs, tags))
}
fn get_inactive_storage(&self) -> Result<CombinedReplyStorage, Self::StorageError> {
match self.manager {
StorageManagerState::Storage(_) => {
panic!("tried to get inactive storage from an active storage backend")
}
StorageManagerState::Inactive(ref state) => Ok(CombinedReplyStorage::new(
state.minimum_reply_surb_storage_threshold,
state.maximum_reply_surb_storage_threshold,
)),
}
}
async fn stop_storage_session(self) -> Result<(), Self::StorageError> {
self.stop_client_use().await
}
@@ -44,7 +44,8 @@ impl TryFrom<StoredSenderTag> for (RecipientBytes, AnonymousSenderTag) {
let Ok(sender_tag_bytes) = value.tag.try_into() else {
return Err(StorageError::CorruptedData {
details: format!(
"the retrieved sender tag has length of {tag_len} while {SENDER_TAG_SIZE} was expected",
"the retrieved sender tag has length of {tag_len} while {} was expected",
SENDER_TAG_SIZE
),
});
};
@@ -131,7 +132,8 @@ impl TryFrom<StoredSurbSender> for (AnonymousSenderTag, i64) {
let Ok(sender_tag_bytes) = value.tag.try_into() else {
return Err(StorageError::CorruptedData {
details: format!(
"the retrieved sender tag has length of {tag_len} while {SENDER_TAG_SIZE} was expected",
"the retrieved sender tag has length of {tag_len} while {} was expected",
SENDER_TAG_SIZE
),
});
};
@@ -50,23 +50,12 @@ impl ReplyStorageBackend for Empty {
self.max_surb_threshold,
))
}
fn get_inactive_storage(&self) -> Result<CombinedReplyStorage, Self::StorageError> {
Ok(CombinedReplyStorage::new(
self.min_surb_threshold,
self.max_surb_threshold,
))
}
}
#[async_trait]
pub trait ReplyStorageBackend: Sized {
type StorageError: Error + 'static;
fn is_active(&self) -> bool {
true
}
async fn start_storage_session(&self) -> Result<(), Self::StorageError> {
Ok(())
}
@@ -84,11 +73,6 @@ pub trait ReplyStorageBackend: Sized {
async fn load_surb_storage(&self) -> Result<CombinedReplyStorage, Self::StorageError>;
/// In the case the storage backend is initialized in an inactive state (persisting data is
/// disabled), we might still need to fetch the (in-mem) storage and the parameters it was
/// created with.
fn get_inactive_storage(&self) -> Result<CombinedReplyStorage, Self::StorageError>;
async fn stop_storage_session(self) -> Result<(), Self::StorageError> {
Ok(())
}
-1
View File
@@ -88,7 +88,6 @@ impl<T> Config<T> {
Config::default().with_id(id)
}
#[must_use]
pub fn with_id<S: Into<String>>(mut self, id: S) -> Self
where
T: NymConfig,
-2
View File
@@ -65,10 +65,8 @@ pub enum ClientCoreError {
/// Set of messages that the client can send to listeners via the task manager
#[derive(thiserror::Error, Debug)]
pub enum ClientCoreStatusMessage {
// NOTE: The nym-connect frontend listens for these strings, so don't change them until we have a more robust mechanism in place
#[error("The connected gateway is slow, or the connection to it is slow")]
GatewayIsSlow,
// NOTE: The nym-connect frontend listens for these strings, so don't change them until we have a more robust mechanism in place
#[error("The connected gateway is very slow, or the connection to it is very slow")]
GatewayIsVerySlow,
}
+3 -7
View File
@@ -8,8 +8,6 @@ use crate::{
};
use config::NymConfig;
use crypto::asymmetric::identity;
#[cfg(target_arch = "wasm32")]
use gateway_client::wasm_mockups::SigningNyxdClient;
use gateway_client::GatewayClient;
use gateway_requests::registration::handshake::SharedKeys;
use rand::{seq::SliceRandom, thread_rng};
@@ -17,12 +15,10 @@ use std::{sync::Arc, time::Duration};
use tap::TapFallible;
use topology::{filter::VersionFilterable, gateway};
use url::Url;
#[cfg(not(target_arch = "wasm32"))]
use validator_client::nyxd::SigningNyxdClient;
pub(super) async fn query_gateway_details(
validator_servers: Vec<Url>,
chosen_gateway_id: Option<identity::PublicKey>,
chosen_gateway_id: Option<String>,
) -> Result<gateway::Node, ClientCoreError> {
let nym_api = validator_servers
.choose(&mut thread_rng())
@@ -44,7 +40,7 @@ pub(super) async fn query_gateway_details(
if let Some(gateway_id) = chosen_gateway_id {
filtered_gateways
.iter()
.find(|gateway| gateway.identity_key == gateway_id)
.find(|gateway| gateway.identity_key.to_base58_string() == gateway_id)
.ok_or_else(|| ClientCoreError::NoGatewayWithId(gateway_id.to_string()))
.cloned()
} else {
@@ -60,7 +56,7 @@ pub(super) async fn register_with_gateway(
our_identity: Arc<identity::KeyPair>,
) -> Result<Arc<SharedKeys>, ClientCoreError> {
let timeout = Duration::from_millis(1500);
let mut gateway_client: GatewayClient<SigningNyxdClient> = GatewayClient::new_init(
let mut gateway_client = GatewayClient::new_init(
gateway.clients_address(),
gateway.identity_key,
gateway.owner.clone(),
+75 -59
View File
@@ -69,38 +69,12 @@ pub fn new_client_keys() -> KeyManager {
KeyManager::new(&mut rng)
}
/// Authenticate and register with a gateway.
/// 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.
/// The shared key is added to the supplied `KeyManager` and the endpoint details are returned.
pub async fn register_with_gateway(
key_manager: &mut KeyManager,
nym_api_endpoints: Vec<Url>,
chosen_gateway_id: Option<identity::PublicKey>,
) -> Result<GatewayEndpointConfig, ClientCoreError> {
// Get the gateway details of the gateway we will use
let gateway = helpers::query_gateway_details(nym_api_endpoints, chosen_gateway_id).await?;
log::debug!("Querying gateway gives: {}", gateway);
let our_identity = key_manager.identity_keypair();
// Establish connection, authenticate and generate keys for talking with the gateway
let shared_keys = helpers::register_with_gateway(&gateway, our_identity).await?;
key_manager.insert_gateway_shared_key(shared_keys);
Ok(gateway.into())
}
/// Convenience function for setting up the gateway for a client given a `Config`. Depending on the
/// arguments given it will do the sensible thing. Either it will
///
/// a. Reuse existing gateway configuration from storage.
/// 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.
/// c. Create a new gateway configuration with a newly registered gateway and keys.
pub async fn setup_gateway_from_config<C, T>(
/// Convenience function for setting up the gateway for a client. Depending on the arguments given
/// it will do the sensible thing.
pub async fn setup_gateway<C, T>(
register_gateway: bool,
user_chosen_gateway_id: Option<identity::PublicKey>,
// TODO: this should get refactored to instead take Option<identity::PublicKey>
user_chosen_gateway_id: Option<String>,
config: &Config<T>,
) -> Result<GatewayEndpointConfig, ClientCoreError>
where
@@ -108,47 +82,89 @@ where
T: NymConfig,
{
let id = config.get_id();
// If we are not going to register gateway, and an explicitly chosed gateway is not passed in,
// load the existing configuration file
if !register_gateway && user_chosen_gateway_id.is_none() {
println!("Not registering gateway, will reuse existing config and keys");
return load_existing_gateway_config::<C>(&id);
if register_gateway {
register_with_gateway_and_store(user_chosen_gateway_id, config).await
} else if let Some(user_chosen_gateway_id) = user_chosen_gateway_id {
config_gateway_with_existing_keys(user_chosen_gateway_id, config).await
} else {
reuse_existing_gateway_config::<C>(&id)
}
}
// Else, we preceed by querying the nym-api
let gateway =
helpers::query_gateway_details(config.get_nym_api_endpoints(), user_chosen_gateway_id)
.await?;
log::debug!("Querying gateway gives: {}", gateway);
// If we are not registering, just return this and assume the caller has the keys already and
// wants to keep the,
if !register_gateway && user_chosen_gateway_id.is_some() {
println!("Using gateway provided by user, keeping existing keys");
return Ok(gateway.into());
}
// Create new keys and derive our identity
let mut key_manager = new_client_keys();
/// Get the gateway details by querying the validator-api. Either pick one at random or use
/// the chosen one if it's among the available ones.
pub async fn register_with_gateway(
key_manager: &mut KeyManager,
nym_api_endpoints: Vec<Url>,
chosen_gateway_id: Option<String>,
) -> Result<GatewayEndpointConfig, ClientCoreError> {
// Our identity is derived from our key
let our_identity = key_manager.identity_keypair();
// Get the gateway details of the gateway we will use
let gateway = helpers::query_gateway_details(nym_api_endpoints, chosen_gateway_id).await?;
log::debug!("Querying gateway gives: {}", gateway);
// Establish connection, authenticate and generate keys for talking with the gateway
println!("Registering with new gateway");
let shared_keys = helpers::register_with_gateway(&gateway, our_identity).await?;
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
// will load keys from storage when actually connecting.
Ok(gateway.into())
}
/// Get the gateway details by querying the validator-api. Either pick one at random or use
/// the chosen one if it's among the available ones.
/// Saves keys to disk, specified by the paths in `config`.
pub async fn register_with_gateway_and_store<T>(
chosen_gateway_id: Option<String>,
config: &Config<T>,
) -> Result<GatewayEndpointConfig, ClientCoreError>
where
T: NymConfig,
{
println!("Configuring gateway");
let mut key_manager = new_client_keys();
let gateway = register_with_gateway(
&mut key_manager,
config.get_nym_api_endpoints(),
chosen_gateway_id,
)
.await?;
helpers::store_keys(&key_manager, config)?;
println!("Saved all generated keys");
Ok(gateway)
}
/// Set the gateway using the usual procedue of querying the validator-api, but don't register or
/// create any keys.
/// This assumes that the user knows what they are doing, and that the existing keys are valid for
/// the gateway being used
pub async fn config_gateway_with_existing_keys<T>(
user_chosen_gateway_id: String,
config: &Config<T>,
) -> Result<GatewayEndpointConfig, ClientCoreError>
where
T: NymConfig,
{
println!("Using gateway provided by user, keeping existing keys");
let gateway = helpers::query_gateway_details(
config.get_nym_api_endpoints(),
Some(user_chosen_gateway_id),
)
.await?;
log::debug!("Querying gateway gives: {}", gateway);
Ok(gateway.into())
}
/// Read and reuse the existing gateway configuration from a file that was generate earlier.
pub fn load_existing_gateway_config<T>(id: &str) -> Result<GatewayEndpointConfig, ClientCoreError>
pub fn reuse_existing_gateway_config<T>(id: &str) -> Result<GatewayEndpointConfig, ClientCoreError>
where
T: NymConfig + ClientCoreConfigTrait,
{
println!("Not registering gateway, will reuse existing config and keys");
T::load_from_file(Some(id))
.map(|existing_config| existing_config.get_gateway_endpoint().clone())
.map_err(|err| {
@@ -226,9 +242,9 @@ where
pub fn output_to_json<T: Serialize>(init_results: &T, output_file: &str) {
match std::fs::File::create(output_file) {
Ok(file) => match serde_json::to_writer_pretty(file, init_results) {
Ok(_) => println!("Saved: {output_file}"),
Err(err) => eprintln!("Could not save {output_file}: {err}"),
Ok(_) => println!("Saved: {}", output_file),
Err(err) => eprintln!("Could not save {}: {err}", output_file),
},
Err(err) => eprintln!("Could not save {output_file}: {err}"),
Err(err) => eprintln!("Could not save {}: {err}", output_file),
}
}
+1 -1
View File
@@ -13,7 +13,7 @@ rand = "0.7.3"
serde = { version = "1.0", features = ["derive"] }
thiserror = "1.0"
url = "2.2"
tokio = { version = "1.24.1", features = ["rt-multi-thread", "net", "signal", "macros"] } # async runtime
tokio = { version = "1.21.2", features = ["rt-multi-thread", "net", "signal", "macros"] } # async runtime
coconut-interface = { path = "../../common/coconut-interface" }
config = { path = "../../common/config" }
+1 -4
View File
@@ -13,7 +13,6 @@ use credentials::coconut::bandwidth::{BandwidthVoucher, TOTAL_ATTRIBUTES};
use credentials::coconut::utils::obtain_aggregate_signature;
use crypto::asymmetric::{encryption, identity};
use network_defaults::{NymNetworkDetails, VOUCHER_INFO};
use validator_client::nyxd::traits::DkgQueryClient;
use validator_client::nyxd::tx::Hash;
use validator_client::{CoconutApiClient, Config};
@@ -81,8 +80,7 @@ pub(crate) async fn get_credential(state: &State, shared_storage: PersistentStor
let network_details = NymNetworkDetails::new_from_env();
let config = Config::try_from_nym_network_details(&network_details)?;
let client = validator_client::Client::new_query(config)?;
let epoch_id = client.nyxd.get_current_epoch().await?.epoch_id;
let coconut_api_clients = CoconutApiClient::all_coconut_api_clients(&client, epoch_id).await?;
let coconut_api_clients = CoconutApiClient::all_coconut_api_clients(&client).await?;
let params = Parameters::new(TOTAL_ATTRIBUTES).unwrap();
let bandwidth_credential_attributes = BandwidthVoucher::new(
@@ -108,7 +106,6 @@ pub(crate) async fn get_credential(state: &State, shared_storage: PersistentStor
bandwidth_credential_attributes.get_private_attributes()[0].to_bs58(),
bandwidth_credential_attributes.get_private_attributes()[1].to_bs58(),
signature.to_bs58(),
epoch_id.to_string(),
)
.await?;
+3 -3
View File
@@ -1,6 +1,6 @@
[package]
name = "nym-client"
version = "1.1.6"
version = "1.1.5"
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jędrzej Stuczyński <andrew@nymtech.net>"]
description = "Implementation of the Nym Client"
edition = "2021"
@@ -23,14 +23,14 @@ url = "2.2"
clap = { version = "4.0", features = ["cargo", "derive"] }
dirs = "4.0"
lazy_static = "1.4.0"
log = { workspace = true } # self explanatory
log = "0.4" # self explanatory
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
serde = { version = "1.0.104", features = ["derive"] } # for config serialization/deserialization
serde_json = "1.0"
thiserror = "1.0.34"
tap = "1.0.1"
tokio = { version = "1.24.1", features = ["rt-multi-thread", "net", "signal"] } # async runtime
tokio = { version = "1.21.2", features = ["rt-multi-thread", "net", "signal"] } # async runtime
tokio-tungstenite = "0.14" # websocket
## internal
@@ -85,7 +85,7 @@ async fn send_file_without_reply() {
let (mut ws_stream, _) = connect_async(uri).await.unwrap();
let recipient = get_self_address(&mut ws_stream).await;
println!("our full address is: {recipient}");
println!("our full address is: {}", recipient);
let read_data = std::fs::read("examples/dummy_file").unwrap();
+14 -5
View File
@@ -36,7 +36,7 @@ async fn send_text_with_reply() {
let (mut ws_stream, _) = connect_async(uri).await.unwrap();
let recipient = get_self_address(&mut ws_stream).await;
println!("our full address is: {recipient}");
println!("our full address is: {}", recipient);
let send_request = json!({
"type" : "send",
@@ -45,7 +45,10 @@ async fn send_text_with_reply() {
"withReplySurb": true,
});
println!("sending {message:?} (*with* reply SURB) over the mix network...");
println!(
"sending {:?} (*with* reply SURB) over the mix network...",
message
);
let response =
send_message_and_get_json_response(&mut ws_stream, send_request.to_string()).await;
@@ -56,7 +59,10 @@ async fn send_text_with_reply() {
"replySurb": response["replySurb"]
});
println!("sending {reply_message:?} (using reply SURB!) over the mix network...");
println!(
"sending {:?} (using reply SURB!) over the mix network...",
reply_message
);
let response =
send_message_and_get_json_response(&mut ws_stream, reply_request.to_string()).await;
@@ -70,7 +76,7 @@ async fn send_text_without_reply() {
let (mut ws_stream, _) = connect_async(uri).await.unwrap();
let recipient = get_self_address(&mut ws_stream).await;
println!("our full address is: {recipient}");
println!("our full address is: {}", recipient);
let send_request = json!({
"type" : "send",
@@ -79,7 +85,10 @@ async fn send_text_without_reply() {
"withReplySurb": false,
});
println!("sending {message:?} (*without* reply SURB) over the mix network...");
println!(
"sending {:?} (*without* reply SURB) over the mix network...",
message
);
let response =
send_message_and_get_json_response(&mut ws_stream, send_request.to_string()).await;
+45 -25
View File
@@ -21,7 +21,6 @@ use nymsphinx::addressing::clients::Recipient;
use nymsphinx::anonymous_replies::requests::AnonymousSenderTag;
use nymsphinx::receiver::ReconstructedMessage;
use task::TaskManager;
use validator_client::nyxd::QueryNyxdClient;
pub(crate) mod config;
@@ -45,28 +44,42 @@ impl SocketClient {
}
}
async fn create_bandwidth_controller(config: &Config) -> BandwidthController<QueryNyxdClient> {
let details = network_defaults::NymNetworkDetails::new_from_env();
let mut client_config = validator_client::Config::try_from_nym_network_details(&details)
.expect("failed to construct validator client config");
let nyxd_url = config
.get_base()
.get_validator_endpoints()
.pop()
.expect("No nyxd validator endpoint provided");
let api_url = config
.get_base()
.get_nym_api_endpoints()
.pop()
.expect("No validator api endpoint provided");
// overwrite env configuration with config URLs
client_config = client_config.with_urls(nyxd_url, api_url);
let client = validator_client::Client::new_query(client_config)
.expect("Could not construct query client");
BandwidthController::new(
async fn create_bandwidth_controller(config: &Config) -> BandwidthController {
#[cfg(feature = "coconut")]
let bandwidth_controller = {
let details = network_defaults::NymNetworkDetails::new_from_env();
let mut client_config =
validator_client::Config::try_from_nym_network_details(&details)
.expect("failed to construct validator client config");
let nyxd_url = config
.get_base()
.get_validator_endpoints()
.pop()
.expect("No nyxd validator endpoint provided");
let api_url = config
.get_base()
.get_nym_api_endpoints()
.pop()
.expect("No validator api endpoint provided");
// overwrite env configuration with config URLs
client_config = client_config.with_urls(nyxd_url, api_url);
let client = validator_client::Client::new_query(client_config)
.expect("Could not construct query client");
let coconut_api_clients =
validator_client::CoconutApiClient::all_coconut_api_clients(&client)
.await
.expect("Could not query api clients");
BandwidthController::new(
credential_storage::initialise_storage(config.get_base().get_database_path()).await,
coconut_api_clients,
)
};
#[cfg(not(feature = "coconut"))]
let bandwidth_controller = BandwidthController::new(
credential_storage::initialise_storage(config.get_base().get_database_path()).await,
client,
)
.expect("Could not create bandwidth controller");
bandwidth_controller
}
fn start_websocket_listener(
@@ -107,9 +120,16 @@ impl SocketClient {
/// blocking version of `start_socket` method. Will run forever (or until SIGINT is sent)
pub async fn run_socket_forever(self) -> Result<(), Box<dyn Error + Send + Sync>> {
let shutdown = self.start_socket().await?;
let mut shutdown = self.start_socket().await?;
let res = task::wait_for_signal_and_error(&mut shutdown).await;
log::info!("Sending shutdown");
shutdown.signal_shutdown().ok();
log::info!("Waiting for tasks to finish... (Press ctrl-c to force)");
shutdown.wait_for_shutdown().await;
let res = shutdown.catch_interrupt().await;
log::info!("Stopping nym-client");
res
}
@@ -124,7 +144,7 @@ impl SocketClient {
self.key_manager,
Some(Self::create_bandwidth_controller(&self.config).await),
non_wasm_helpers::setup_fs_reply_surb_backend(
Some(self.config.get_base().get_reply_surb_database_path()),
self.config.get_base().get_reply_surb_database_path(),
self.config.get_debug_settings(),
)
.await?,
@@ -161,7 +181,7 @@ impl SocketClient {
self.key_manager,
Some(Self::create_bandwidth_controller(&self.config).await),
non_wasm_helpers::setup_fs_reply_surb_backend(
Some(self.config.get_base().get_reply_surb_database_path()),
self.config.get_base().get_reply_surb_database_path(),
self.config.get_debug_settings(),
)
.await?,
+8 -7
View File
@@ -114,15 +114,16 @@ pub(crate) async fn execute(args: &Init) -> Result<(), ClientError> {
let already_init = Config::default_config_file_path(Some(id)).exists();
if already_init {
println!("Client \"{id}\" was already initialised before");
println!(
"Client \"{}\" was already initialised before! \
Config information will be overwritten (but keys will be kept)!",
id
);
}
// Usually you only register with the gateway on the first init, however you can force
// re-registering if wanted.
let user_wants_force_register = args.force_register_gateway;
if user_wants_force_register {
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
// the gateway (because this would create a new shared key).
@@ -137,9 +138,9 @@ 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
// one but with keys kept, or reusing the gateway configuration.
let gateway = client_core::init::setup_gateway_from_config::<Config, _>(
let gateway = client_core::init::setup_gateway::<Config, _>(
register_gateway,
user_chosen_gateway_id,
user_chosen_gateway_id.map(|id| id.to_base58_string()),
config.get_base(),
)
.await
@@ -168,7 +169,7 @@ pub(crate) async fn execute(args: &Init) -> Result<(), ClientError> {
fn print_saved_config(config: &Config) {
let config_save_location = config.get_config_file_save_location();
println!("Saved configuration file to {config_save_location:?}");
println!("Saved configuration file to {:?}", config_save_location);
println!("Using gateway: {}", 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());
+21 -7
View File
@@ -17,26 +17,36 @@ fn fail_upgrade<D1: Display, D2: Display>(from_version: D1, to_version: D2) -> !
}
fn print_start_upgrade<D1: Display, D2: Display>(from: D1, to: D2) {
println!("\n==================\nTrying to upgrade client from {from} to {to} ...");
println!(
"\n==================\nTrying to upgrade client from {} to {} ...",
from, to
);
}
fn print_failed_upgrade<D1: Display, D2: Display>(from: D1, to: D2) {
eprintln!("Upgrade from {from} to {to} failed!\n==================\n");
eprintln!(
"Upgrade from {} to {} failed!\n==================\n",
from, to
);
}
fn print_successful_upgrade<D1: Display, D2: Display>(from: D1, to: D2) {
println!("Upgrade from {from} to {to} was successful!\n==================\n");
println!(
"Upgrade from {} to {} was successful!\n==================\n",
from, to
);
}
fn outdated_upgrade(config_version: &Version, package_version: &Version) -> ! {
eprintln!(
"Cannot perform upgrade from {config_version} to {package_version}. Your version is too old to perform the upgrade.!"
"Cannot perform upgrade from {} to {}. Your version is too old to perform the upgrade.!",
config_version, package_version
);
process::exit(1)
}
fn unsupported_upgrade(current_version: &Version, config_version: &Version) -> ! {
eprintln!("Cannot perform upgrade from {config_version} to {current_version}. Please let the developers know about this issue if you expected it to work!");
eprintln!("Cannot perform upgrade from {} to {}. Please let the developers know about this issue if you expected it to work!", config_version, current_version);
process::exit(1)
}
@@ -55,7 +65,8 @@ fn parse_config_version(config: &Config) -> Version {
if version.is_prerelease() || !version.build.is_empty() {
eprintln!(
"Trying to upgrade from a non-released version {version}. This is not supported!"
"Trying to upgrade from a non-released version {}. This is not supported!",
version
);
process::exit(1)
}
@@ -70,7 +81,10 @@ fn parse_package_version() -> Version {
// however, we are not using them ourselves at the moment and hence it should be fine.
// if we change our mind, we could easily tweak this code
if version.is_prerelease() || !version.build.is_empty() {
eprintln!("Trying to upgrade to a non-released version {version}. This is not supported!");
eprintln!(
"Trying to upgrade to a non-released version {}. This is not supported!",
version
);
process::exit(1)
}
+19 -2
View File
@@ -3,7 +3,7 @@
use std::error::Error;
use clap::{crate_name, crate_version, Parser};
use clap::{crate_version, Parser};
use logging::setup_logging;
use network_defaults::setup_env;
@@ -15,9 +15,26 @@ pub mod websocket;
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
setup_logging();
println!("{}", logging::banner(crate_name!(), crate_version!()));
println!("{}", banner());
let args = commands::Cli::parse();
setup_env(args.config_env_file.as_ref());
commands::execute(&args).await
}
fn banner() -> String {
format!(
r#"
_ __ _ _ _ __ ___
| '_ \| | | | '_ \ _ \
| | | | |_| | | | | | |
|_| |_|\__, |_| |_| |_|
|___/
(client - version {:})
"#,
crate_version!()
)
}
+6 -2
View File
@@ -27,13 +27,17 @@ use tokio_tungstenite::{
};
use websocket_requests::{requests::ClientRequest, responses::ServerResponse};
#[derive(Default)]
enum ReceivedResponseType {
#[default]
Binary,
Text,
}
impl Default for ReceivedResponseType {
fn default() -> Self {
ReceivedResponseType::Binary
}
}
pub(crate) struct HandlerBuilder {
msg_input: InputMessageSender,
client_connection_tx: ConnectionCommandSender,
@@ -84,7 +84,7 @@ impl TryFrom<u8> for ErrorKind {
n => Err(Error::new(
ErrorKind::MalformedResponse,
format!("invalid error code {n}"),
format!("invalid error code {}", n),
)),
}
}
+2 -2
View File
@@ -15,7 +15,7 @@ clap = { version = "4.0", features = ["cargo", "derive"] }
dirs = "4.0"
futures = "0.3"
lazy_static = "1.4.0"
log = { workspace = true }
log = "0.4"
pin-project = "1.0"
pretty_env_logger = "0.4"
rand = { version = "0.7.3", features = ["wasm-bindgen"] }
@@ -23,7 +23,7 @@ serde = { version = "1.0", features = ["derive"] } # for config serialization/de
serde_json = "1.0.89"
tap = "1.0.1"
thiserror = "1.0.34"
tokio = { version = "1.24.1", features = ["rt-multi-thread", "net", "signal"] }
tokio = { version = "1.21.2", features = ["rt-multi-thread", "net", "signal"] }
url = "2.2"
# internal
+45 -25
View File
@@ -19,8 +19,7 @@ use gateway_client::bandwidth::BandwidthController;
use log::*;
use nymsphinx::addressing::clients::Recipient;
use std::error::Error;
use task::{TaskClient, TaskManager};
use validator_client::nyxd::QueryNyxdClient;
use task::{wait_for_signal_and_error, TaskClient, TaskManager};
pub mod config;
@@ -54,28 +53,42 @@ impl NymClient {
}
}
async fn create_bandwidth_controller(config: &Config) -> BandwidthController<QueryNyxdClient> {
let details = network_defaults::NymNetworkDetails::new_from_env();
let mut client_config = validator_client::Config::try_from_nym_network_details(&details)
.expect("failed to construct validator client config");
let nyxd_url = config
.get_base()
.get_validator_endpoints()
.pop()
.expect("No nyxd validator endpoint provided");
let api_url = config
.get_base()
.get_nym_api_endpoints()
.pop()
.expect("No validator api endpoint provided");
// overwrite env configuration with config URLs
client_config = client_config.with_urls(nyxd_url, api_url);
let client = validator_client::Client::new_query(client_config)
.expect("Could not construct query client");
BandwidthController::new(
async fn create_bandwidth_controller(config: &Config) -> BandwidthController {
#[cfg(feature = "coconut")]
let bandwidth_controller = {
let details = network_defaults::NymNetworkDetails::new_from_env();
let mut client_config =
validator_client::Config::try_from_nym_network_details(&details)
.expect("failed to construct validator client config");
let nyxd_url = config
.get_base()
.get_validator_endpoints()
.pop()
.expect("No nyxd validator endpoint provided");
let api_url = config
.get_base()
.get_nym_api_endpoints()
.pop()
.expect("No validator api endpoint provided");
// overwrite env configuration with config URLs
client_config = client_config.with_urls(nyxd_url, api_url);
let client = validator_client::Client::new_query(client_config)
.expect("Could not construct query client");
let coconut_api_clients =
validator_client::CoconutApiClient::all_coconut_api_clients(&client)
.await
.expect("Could not query api clients");
BandwidthController::new(
credential_storage::initialise_storage(config.get_base().get_database_path()).await,
coconut_api_clients,
)
};
#[cfg(not(feature = "coconut"))]
let bandwidth_controller = BandwidthController::new(
credential_storage::initialise_storage(config.get_base().get_database_path()).await,
client,
)
.expect("Could not create bandwidth controller");
bandwidth_controller
}
fn start_socks5_listener(
@@ -134,9 +147,16 @@ impl NymClient {
/// blocking version of `start` method. Will run forever (or until SIGINT is sent)
pub async fn run_forever(self) -> Result<(), Box<dyn Error + Send + Sync>> {
let shutdown = self.start().await?;
let mut shutdown = self.start().await?;
let res = wait_for_signal_and_error(&mut shutdown).await;
log::info!("Sending shutdown");
shutdown.signal_shutdown().ok();
log::info!("Waiting for tasks to finish... (Press ctrl-c to force)");
shutdown.wait_for_shutdown().await;
let res = shutdown.catch_interrupt().await;
log::info!("Stopping nym-socks5-client");
res
}
@@ -193,7 +213,7 @@ impl NymClient {
self.key_manager,
Some(Self::create_bandwidth_controller(&self.config).await),
non_wasm_helpers::setup_fs_reply_surb_backend(
Some(self.config.get_base().get_reply_surb_database_path()),
self.config.get_base().get_reply_surb_database_path(),
self.config.get_debug_settings(),
)
.await?,
+7 -6
View File
@@ -124,15 +124,16 @@ pub(crate) async fn execute(args: &Init) -> Result<(), Socks5ClientError> {
let already_init = Config::default_config_file_path(Some(id)).exists();
if already_init {
println!("SOCKS5 client \"{id}\" was already initialised before");
println!(
"SOCKS5 client \"{}\" was already initialised before! \
Config information will be overwritten (but keys will be kept)!",
id
);
}
// Usually you only register with the gateway on the first init, however you can force
// re-registering if wanted.
let user_wants_force_register = args.force_register_gateway;
if user_wants_force_register {
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
// the gateway (because this would create a new shared key).
@@ -150,9 +151,9 @@ 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
// one but with keys kept, or reusing the gateway configuration.
let gateway = client_core::init::setup_gateway_from_config::<Config, _>(
let gateway = client_core::init::setup_gateway::<Config, _>(
register_gateway,
user_chosen_gateway_id,
user_chosen_gateway_id.map(|id| id.to_base58_string()),
config.get_base(),
)
.await
+19 -2
View File
@@ -3,7 +3,7 @@
use std::error::Error;
use clap::{crate_name, crate_version, Parser};
use clap::{crate_version, Parser};
use logging::setup_logging;
use network_defaults::setup_env;
@@ -15,9 +15,26 @@ pub mod socks;
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
setup_logging();
println!("{}", logging::banner(crate_name!(), crate_version!()));
println!("{}", banner());
let args = commands::Cli::parse();
setup_env(args.config_env_file.as_ref());
commands::execute(&args).await
}
fn banner() -> String {
format!(
r#"
_ __ _ _ _ __ ___
| '_ \| | | | '_ \ _ \
| | | | |_| | | | | | |
|_| |_|\__, |_| |_| |_|
|___/
(socks5 proxy - version {:})
"#,
crate_version!()
)
}
+1 -3
View File
@@ -22,10 +22,8 @@ futures = "0.3"
js-sys = "0.3"
rand = { version = "0.7.3", features = ["wasm-bindgen"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
anyhow = "1.0"
serde-wasm-bindgen = "0.4"
tokio = { version = "1.24.1", features = ["sync"] }
tokio = { version = "1.21.2", features = ["sync"] }
url = "2.2"
wasm-bindgen = { version = "=0.2.83", features = ["serde-serialize"] }
wasm-bindgen-futures = "0.4"
+8 -9
View File
@@ -16,7 +16,11 @@ They should be implemented soon. You can build your applications, but don't rely
## Using it
See the [SDK directory](../../sdk/typescript/examples) for examples on how to use it and the NPM packages available.
See the [Nym docs](https://nymtech.net/docs).
### Demo
There's a demo web application in the `js-example` folder. To run it, first make sure you've got a recent `npm` installed, then follow the instructions in its README.
## Developing
@@ -32,13 +36,8 @@ To be clear, this is not something that most JS developers need to worry about,
### Packaging
If you're a Nym platform developer who's made changes to the Rust files and wants to re-publish the package to NPM, here's how you do it:
If you're a Nym platform developer who's made changes to the Rust (or JS) files and wants to re-publish the package to NPM, here's how you do it:
1. bump version numbers as necessary for SemVer
2. go the `sdk/typescript` directory (off the project root)
3. run:
```
yarn
yarn build
yarn publish
```
2. `wasm-pack build --scope nymproject` builds the wasm binaries into the `pkg` directory (not in source control)
3. `cd pkg && npm publish --access=public` will publish your changed package to NPM
@@ -0,0 +1,217 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use serde::{Deserialize, Serialize};
use wasm_bindgen::prelude::*;
use wasm_bindgen::JsCast;
#[wasm_bindgen(typescript_custom_section)]
const TS_DEFS: &'static str = r#"
export interface BinaryMessage {
kind: number,
payload: Uint8Array;
headers: string,
}
export interface StringMessage {
kind: number,
payload: string;
}
"#;
#[wasm_bindgen]
extern "C" {
#[wasm_bindgen(typescript_type = "BinaryMessage")]
pub type IBinaryMessage;
#[wasm_bindgen(typescript_type = "StringMessage")]
pub type IStringMessage;
}
#[derive(Serialize, Deserialize)]
pub struct BinaryMessage {
pub kind: u8,
pub payload: Vec<u8>,
pub headers: String,
}
#[derive(Serialize, Deserialize)]
pub struct StringMessage {
pub kind: u8,
pub payload: String,
}
/// Create a new binary message with a user-specified `kind`.
#[wasm_bindgen]
pub fn create_binary_message(kind: u8, payload: Vec<u8>) -> Vec<u8> {
create_binary_message_with_headers(kind, payload, "".to_string())
}
/// Create a new message with a UTF-8 encoded string `payload` and a user-specified `kind`.
#[wasm_bindgen]
pub fn create_binary_message_from_string(kind: u8, payload: String) -> Vec<u8> {
create_binary_message_with_headers(kind, payload.as_bytes().to_vec(), "".to_string())
}
/// Create a new binary message with a user-specified `kind`, and `headers` as a string.
#[wasm_bindgen]
pub fn create_binary_message_with_headers(kind: u8, payload: Vec<u8>, headers: String) -> Vec<u8> {
let headers = headers.as_bytes().to_vec();
let size = (headers.len() as u64).to_be_bytes().to_vec();
vec![vec![kind], size, headers, payload].concat()
}
/// Parse the `kind` and byte array `payload` from a byte array
#[wasm_bindgen]
pub async fn parse_binary_message(message: Vec<u8>) -> Result<IBinaryMessage, JsError> {
if message.len() < 2 {
return Err(JsError::new(
"Could not parse message, as less than 2 bytes long",
));
}
let (kind, _headers, payload) = parse_binary_payload(&message);
Ok(serde_wasm_bindgen::to_value(&BinaryMessage {
kind,
payload: payload.to_vec(),
headers: "".to_string(),
})
.unwrap()
.unchecked_into::<IBinaryMessage>())
}
/// Parse the `kind` and byte array `payload` from a byte array with headers
#[wasm_bindgen]
pub async fn parse_binary_message_with_headers(
message: Vec<u8>,
) -> Result<IBinaryMessage, JsError> {
if message.len() < 2 {
return Err(JsError::new(
"Could not parse message, as less than 2 bytes long",
));
}
let (kind, headers, payload) = parse_binary_payload(&message);
Ok(serde_wasm_bindgen::to_value(&BinaryMessage {
kind,
payload: payload.to_vec(),
headers,
})
.unwrap()
.unchecked_into::<IBinaryMessage>())
}
/// Parse the `kind` and UTF-8 string `payload` from a byte array with headers
#[wasm_bindgen]
pub async fn parse_string_message_with_headers(
message: Vec<u8>,
) -> Result<IStringMessage, JsError> {
if message.len() < 2 {
return Err(JsError::new(
"Could not parse message, as less than 2 bytes long",
));
}
let (kind, _headers, payload) = parse_binary_payload(&message);
let payload = String::from_utf8_lossy(payload).into_owned();
Ok(
serde_wasm_bindgen::to_value(&StringMessage { kind, payload })
.unwrap()
.unchecked_into::<IStringMessage>(),
)
}
pub(crate) fn parse_binary_payload(message: &[u8]) -> (u8, String, &[u8]) {
// 1st byte is the kind
let kind = message[0];
// then the size as u64 big endian
let mut size = [0u8; 8];
size.clone_from_slice(&message[1..9]);
let size = u64::from_be_bytes(size) as usize;
// then the headers
let headers = String::from_utf8_lossy(&message[9..9 + size]).into_owned();
// finally the payload
let payload = &message[9 + size..];
(kind, headers, payload)
}
/// Parse the `kind` and UTF-8 string `payload` from a byte array
#[wasm_bindgen]
pub async fn parse_string_message(message: Vec<u8>) -> Result<IStringMessage, JsError> {
if message.len() < 2 {
return Err(JsError::new(
"Could not parse message, as less than 2 bytes long",
));
}
let kind = message[0];
let payload = String::from_utf8_lossy(&message[1..]).into_owned();
Ok(
serde_wasm_bindgen::to_value(&StringMessage { kind, payload })
.unwrap()
.unchecked_into::<IStringMessage>(),
)
}
#[cfg(test)]
mod tests {
use super::{create_binary_message_with_headers, parse_binary_payload};
use wasm_bindgen_test::*;
#[wasm_bindgen_test]
fn test_binary_with_headers() {
let message_as_bytes = create_binary_message_with_headers(
42u8,
vec![0u8, 1u8, 2u8],
"test headers".to_string(),
);
// calculate header size
let headers = "test headers".as_bytes().to_vec();
let size = headers.len();
// the expected size
let expected_size = 12;
assert_eq!(size, expected_size);
assert_eq!(message_as_bytes[0], 42u8);
assert_eq!(message_as_bytes[1..9], 12u64.to_be_bytes());
assert_eq!(
message_as_bytes[9 + expected_size..9 + expected_size + 3],
vec![0u8, 1u8, 2u8]
);
let res = parse_binary_payload(&message_as_bytes);
assert_eq!(res.0, 42u8);
assert_eq!(res.1, "test headers".to_string());
assert_eq!(res.2, vec![0u8, 1u8, 2u8]);
}
#[wasm_bindgen_test]
fn test_binary_with_empty_headers() {
let message_as_bytes =
create_binary_message_with_headers(42u8, vec![0u8, 1u8, 2u8], "".to_string());
let expected_size = 0;
assert_eq!(message_as_bytes[0], 42u8);
assert_eq!(message_as_bytes[1..9], 0u64.to_be_bytes());
assert_eq!(
message_as_bytes[9 + expected_size..9 + expected_size + 3],
vec![0u8, 1u8, 2u8]
);
let res = parse_binary_payload(&message_as_bytes);
assert_eq!(res.0, 42u8);
assert_eq!(res.1, "".to_string());
assert_eq!(res.2, vec![0u8, 1u8, 2u8]);
}
}
+1 -2
View File
@@ -11,7 +11,6 @@ use client_core::client::base_client::{
use client_core::client::replies::reply_storage::browser_backend;
use client_core::client::{inbound_messages::InputMessage, key_manager::KeyManager};
use gateway_client::bandwidth::BandwidthController;
use gateway_client::wasm_mockups::SigningNyxdClient;
use js_sys::Promise;
use nymsphinx::addressing::clients::Recipient;
use nymsphinx::anonymous_replies::requests::AnonymousSenderTag;
@@ -48,7 +47,7 @@ pub struct NymClientBuilder {
on_message: js_sys::Function,
// unimplemented:
bandwidth_controller: Option<BandwidthController<SigningNyxdClient>>,
bandwidth_controller: Option<BandwidthController>,
disabled_credentials: bool,
}
@@ -1,238 +0,0 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use serde::{Deserialize, Serialize};
use wasm_bindgen::prelude::*;
use wasm_bindgen::JsCast;
#[wasm_bindgen(typescript_custom_section)]
const TS_DEFS: &'static str = r#"
export interface EncodedPayload {
mimeType: string,
payload: Uint8Array;
headers: string,
}
"#;
#[wasm_bindgen]
extern "C" {
#[wasm_bindgen(typescript_type = "EncodedPayload")]
pub type IEncodedPayload;
}
#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct EncodedPayload {
pub mime_type: String,
pub payload: Vec<u8>,
pub headers: Option<String>,
}
#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct EncodedPayloadMetadata {
pub mime_type: String,
pub headers: Option<String>,
}
/// Encode a payload
#[wasm_bindgen]
pub fn encode_payload(mime_type: String, payload: Vec<u8>) -> Result<Vec<u8>, JsValue> {
encode_payload_with_headers(mime_type, payload, None)
}
/// Create a new binary message with a user-specified `kind`, and `headers` as a string.
#[wasm_bindgen]
pub fn encode_payload_with_headers(
mime_type: String,
payload: Vec<u8>,
headers: Option<String>,
) -> Result<Vec<u8>, JsValue> {
match serde_json::to_string(&EncodedPayloadMetadata { mime_type, headers }) {
Ok(metadata) => {
let metadata = metadata.as_bytes().to_vec();
let size = (metadata.len() as u64).to_be_bytes().to_vec();
Ok(vec![size, metadata, payload].concat())
}
Err(e) => Err(JsValue::from(JsError::new(
format!("Could not encode message: {}", e).as_str(),
))),
}
}
/// Parse the `kind` and byte array `payload` from a byte array
#[wasm_bindgen]
pub fn decode_payload(message: Vec<u8>) -> Result<IEncodedPayload, JsValue> {
if message.len() < 8 {
return Err(JsValue::from(JsError::new(
"Could not parse message, as less than 8 bytes long",
)));
}
match parse_payload(&message) {
Ok((metadata, payload)) => Ok(serde_wasm_bindgen::to_value(&EncodedPayload {
mime_type: metadata.mime_type,
payload: payload.to_vec(),
headers: metadata.headers,
})
.unwrap()
.unchecked_into::<IEncodedPayload>()),
Err(e) => Err(JsValue::from(JsError::new(
format!("Could not parse message: {}", e).as_str(),
))),
}
}
pub(crate) fn parse_payload(message: &[u8]) -> anyhow::Result<(EncodedPayloadMetadata, &[u8])> {
// 1st 8 bytes are the size (as u64 big endian)
let mut size = [0u8; 8];
size.clone_from_slice(&message[0..8]);
let size = u64::from_be_bytes(size) as usize;
// then the metadata
let metadata = String::from_utf8_lossy(&message[8..8 + size]).into_owned();
let metadata: EncodedPayloadMetadata = serde_json::from_str(metadata.as_str())?;
// finally the payload
let payload = &message[8 + size..];
Ok((metadata, payload))
}
/// Try parse a UTF-8 string from an array of bytes
#[wasm_bindgen]
pub fn parse_utf8_string(payload: Vec<u8>) -> String {
String::from_utf8_lossy(&payload).into_owned()
}
/// Converts a UTF-8 string into an array of bytes
///
/// This method is provided as a replacement for the mess of `atob`
/// (https://developer.mozilla.org/en-US/docs/Web/API/atob) helpers provided by browsers and NodeJS.
///
/// Feel free to use `atob` if you know you won't have problems with polyfills or encoding issues.
#[wasm_bindgen]
pub fn utf8_string_to_byte_array(message: String) -> Vec<u8> {
message.into_bytes()
}
#[cfg(test)]
mod tests {
use super::*;
use wasm_bindgen_test::*;
#[wasm_bindgen_test]
async fn test_encode_payload_with_headers() {
let message_as_bytes = encode_payload_with_headers(
"text/plain".to_string(),
vec![0u8, 1u8, 2u8],
Some("test headers".to_string()),
)
.unwrap();
// the expected message size
let size = message_as_bytes.len();
let expected_size = 61;
assert_eq!(size, expected_size);
let expected_header_size = 50usize;
assert_eq!(
message_as_bytes[0..8],
(expected_header_size as u64).to_be_bytes()
);
assert_eq!(
message_as_bytes[8 + expected_header_size..8 + expected_header_size + 3],
vec![0u8, 1u8, 2u8]
);
let res = parse_payload(&message_as_bytes).unwrap();
assert_eq!(res.0.mime_type, "text/plain");
assert_eq!(res.0.headers.unwrap(), "test headers".to_string());
assert_eq!(res.1, vec![0u8, 1u8, 2u8]);
}
#[wasm_bindgen_test]
async fn test_encode_payload_with_empty_headers() {
let message_as_bytes =
encode_payload_with_headers("text/plain".to_string(), vec![0u8, 1u8, 2u8], None)
.unwrap();
// the expected message size
let size = message_as_bytes.len();
let expected_size = 51;
assert_eq!(size, expected_size);
let expected_header_size = 40usize;
assert_eq!(
message_as_bytes[0..8],
(expected_header_size as u64).to_be_bytes()
);
assert_eq!(
message_as_bytes[8 + expected_header_size..8 + expected_header_size + 3],
vec![0u8, 1u8, 2u8]
);
let res = parse_payload(&message_as_bytes).unwrap();
assert_eq!(res.0.mime_type, "text/plain");
assert_eq!(res.0.headers, None);
assert_eq!(res.1, vec![0u8, 1u8, 2u8]);
}
#[wasm_bindgen_test]
async fn test_encode_payload_with_empty_headers_and_empty_mime_type() {
let message_as_bytes =
encode_payload_with_headers("".to_string(), vec![0u8, 1u8, 2u8], None).unwrap();
// the expected message size
let size = message_as_bytes.len();
let expected_size = 41;
assert_eq!(size, expected_size);
let expected_header_size = 30usize;
assert_eq!(
message_as_bytes[0..8],
(expected_header_size as u64).to_be_bytes()
);
assert_eq!(
message_as_bytes[8 + expected_header_size..8 + expected_header_size + 3],
vec![0u8, 1u8, 2u8]
);
let res = parse_payload(&message_as_bytes).unwrap();
assert_eq!(res.0.mime_type, "");
assert_eq!(res.0.headers, None);
assert_eq!(res.1, vec![0u8, 1u8, 2u8]);
}
#[wasm_bindgen_test]
async fn test_encode_payload_with_all_empty() {
let empty: Vec<u8> = vec![];
let message_as_bytes =
encode_payload_with_headers("".to_string(), empty.clone(), None).unwrap();
// the expected message size
let size = message_as_bytes.len();
let expected_size = 38;
assert_eq!(size, expected_size);
let expected_header_size = 30usize;
assert_eq!(
message_as_bytes[0..8],
(expected_header_size as u64).to_be_bytes()
);
assert_eq!(
message_as_bytes[8 + expected_header_size..8 + expected_header_size],
empty
);
let res = parse_payload(&message_as_bytes).unwrap();
assert_eq!(res.0.mime_type, "");
assert_eq!(res.0.headers, None);
assert_eq!(res.1, empty);
}
}
+2 -4
View File
@@ -3,14 +3,12 @@
use wasm_bindgen::prelude::*;
#[cfg(target_arch = "wasm32")]
pub mod binary_message_helper;
#[cfg(target_arch = "wasm32")]
mod client;
#[cfg(target_arch = "wasm32")]
pub mod encoded_payload_helper;
#[cfg(target_arch = "wasm32")]
pub mod gateway_selector;
#[cfg(target_arch = "wasm32")]
pub mod validation;
#[wasm_bindgen]
pub fn set_panic_hook() {
-35
View File
@@ -1,35 +0,0 @@
use nymsphinx::addressing::clients::Recipient;
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn validate_recipient(recipient: String) -> Result<(), JsError> {
match Recipient::try_from_base58_string(recipient) {
Ok(_) => Ok(()),
Err(e) => Err(JsError::new(format!("{}", e).as_str())),
}
}
#[cfg(test)]
mod tests {
use super::validate_recipient;
use wasm_bindgen_test::*;
#[wasm_bindgen_test]
fn test_recipient_validation_ok() {
let res = validate_recipient("DyQmXnst5NGGjzUZxRC5Bjs5bd7CBF3xMpsSmbRiizr2.GH6YTBP2NXU3AVqd8WjiTMVyeMjunXMEsp7gVCMEJqpD@336yuXAeGEgedRfqTJZsG2YV7P13QH1bHv1SjCZYarc9".to_string());
assert!(res.is_ok())
}
#[wasm_bindgen_test]
fn test_recipient_validation_fails() {
assert!(validate_recipient(" DyQmXnst5NGGjzUZxRC5Bjs5bd7CBF3xMpsSmbRiizr2.GH6YTBP2NXU3AVqd8WjiTMVyeMjunXMEsp7gVCMEJqpD@336yuXAeGEgedRfqTJZsG2YV7P13QH1bHv1SjCZYarc9".to_string()).is_err());
assert!(validate_recipient(
"DyQmXnst5NGGjzUZxRC5BjbRiizr2.GH6YTBP2NXU3AVqd8WD@336yuXAeGEgedRfqTJZQH1bHv1SjCZYarc9"
.to_string()
)
.is_err());
assert!(validate_recipient("🙀🙀🙀🙀".to_string()).is_err());
assert!(validate_recipient("".to_string()).is_err());
assert!(validate_recipient(" ".to_string()).is_err());
}
}
+1 -1
View File
@@ -7,4 +7,4 @@ edition = "2021"
[dependencies]
futures = "0.3"
log = { workspace = true }
log = "0.4.17"
+6 -6
View File
@@ -10,12 +10,12 @@ edition = "2021"
# TODO: (for this and other crates), similarly to 'tokio', import only required "futures" modules rather than
# the entire crate
futures = "0.3"
log = { workspace = true }
log = "0.4"
thiserror = "1.0"
url = "2.2"
rand = { version = "0.7.3", features = ["wasm-bindgen"] }
async-trait = { version = "0.1.51" }
tokio = { version = "1.24.1", features = ["macros"] }
tokio = { version = "1.21.2", features = ["macros"] }
# internal
coconut-interface = { path = "../../coconut-interface", optional = true }
@@ -25,7 +25,7 @@ gateway-requests = { path = "../../../gateway/gateway-requests" }
network-defaults = { path = "../../network-defaults" }
nymsphinx = { path = "../../nymsphinx" }
pemstore = { path = "../../pemstore" }
validator-client = { path = "../validator-client" }
validator-client = { path = "../validator-client", optional = true }
task = { path = "../../task" }
serde = { version = "1.0", features = ["derive"]}
@@ -36,11 +36,11 @@ default-features = false
# non-wasm-only dependencies
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.tokio]
version = "1.24.1"
version = "1.21.2"
features = ["macros", "rt", "net", "sync", "time"]
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.tokio-stream]
version = "0.1.11"
version = "0.1.9"
features = ["net", "sync", "time"]
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.tokio-tungstenite]
@@ -79,5 +79,5 @@ features = ["js"]
#url = "2.1"
[features]
coconut = ["gateway-requests/coconut", "coconut-interface", "credentials/coconut"]
coconut = ["gateway-requests/coconut", "coconut-interface", "validator-client", "credentials/coconut"]
wasm = []
@@ -1,26 +1,23 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
#[cfg(feature = "coconut")]
use crate::error::GatewayClientError;
#[cfg(target_arch = "wasm32")]
use crate::wasm_mockups::Storage;
use crate::wasm_storage::Storage;
#[cfg(not(target_arch = "wasm32"))]
use credential_storage::storage::Storage;
#[cfg(all(target_arch = "wasm32", feature = "coconut"))]
use crate::wasm_mockups::StorageError;
use crate::wasm_storage::StorageError;
#[cfg(all(not(target_arch = "wasm32"), feature = "coconut"))]
use credential_storage::error::StorageError;
#[cfg(target_arch = "wasm32")]
use crate::wasm_mockups::{Client, CosmWasmClient};
#[cfg(feature = "coconut")]
use std::str::FromStr;
#[cfg(not(target_arch = "wasm32"))]
use validator_client::{nyxd::CosmWasmClient, Client};
#[cfg(feature = "coconut")]
use validator_client::client::CoconutApiClient;
#[cfg(feature = "coconut")]
use {
coconut_interface::Base58,
@@ -31,34 +28,41 @@ use {
// 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;
use crate::wasm_storage::PersistentStorage;
#[cfg(not(target_arch = "wasm32"))]
use credential_storage::PersistentStorage;
#[derive(Clone)]
#[allow(dead_code)]
pub struct BandwidthController<C: Clone, St: Storage = PersistentStorage> {
pub struct BandwidthController<St: Storage = PersistentStorage> {
#[allow(dead_code)]
storage: St,
nyxd_client: Client<C>,
#[cfg(feature = "coconut")]
coconut_api_clients: Vec<CoconutApiClient>,
}
impl<C, St> BandwidthController<C, St>
impl<St> BandwidthController<St>
where
C: CosmWasmClient + Sync + Send + Clone,
St: Storage + Clone + 'static,
{
pub fn new(storage: St, nyxd_client: Client<C>) -> Self {
#[cfg(feature = "coconut")]
pub fn new(storage: St, coconut_api_clients: Vec<CoconutApiClient>) -> Self {
BandwidthController {
storage,
nyxd_client,
coconut_api_clients,
}
}
#[cfg(not(feature = "coconut"))]
pub fn new(storage: St) -> Result<Self, GatewayClientError> {
Ok(BandwidthController { storage })
}
#[cfg(feature = "coconut")]
pub async fn prepare_coconut_credential(
&self,
) -> Result<(coconut_interface::Credential, i64), GatewayClientError> {
let verification_key = obtain_aggregate_verification_key(&self.coconut_api_clients).await?;
let bandwidth_credential = self.storage.get_next_coconut_credential().await?;
let voucher_value = u64::from_str(&bandwidth_credential.voucher_value)
.map_err(|_| StorageError::InconsistentData)?;
@@ -69,19 +73,6 @@ where
coconut_interface::Attribute::try_from_bs58(bandwidth_credential.binding_number)?;
let signature =
coconut_interface::Signature::try_from_bs58(bandwidth_credential.signature)?;
let epoch_id = u64::from_str(&bandwidth_credential.epoch_id)
.map_err(|_| StorageError::InconsistentData)?;
#[cfg(not(target_arch = "wasm32"))]
let coconut_api_clients = validator_client::CoconutApiClient::all_coconut_api_clients(
&self.nyxd_client,
epoch_id,
)
.await
.expect("Could not query api clients");
#[cfg(target_arch = "wasm32")]
let coconut_api_clients = vec![];
let verification_key = obtain_aggregate_verification_key(&coconut_api_clients).await?;
// the below would only be executed once we know where we want to spend it (i.e. which gateway and stuff)
Ok((
@@ -90,7 +81,6 @@ where
voucher_info,
serial_number,
binding_number,
epoch_id,
&signature,
&verification_key,
)?,
@@ -32,13 +32,9 @@ use coconut_interface::Credential;
use credential_storage::PersistentStorage;
#[cfg(not(target_arch = "wasm32"))]
use tokio_tungstenite::connect_async;
#[cfg(not(target_arch = "wasm32"))]
use validator_client::nyxd::CosmWasmClient;
#[cfg(target_arch = "wasm32")]
use crate::wasm_mockups::CosmWasmClient;
#[cfg(target_arch = "wasm32")]
use crate::wasm_mockups::PersistentStorage;
use crate::wasm_storage::PersistentStorage;
#[cfg(target_arch = "wasm32")]
use wasm_timer;
#[cfg(target_arch = "wasm32")]
@@ -47,7 +43,7 @@ use wasm_utils::websocket::JSWebsocket;
const DEFAULT_RECONNECTION_ATTEMPTS: usize = 10;
const DEFAULT_RECONNECTION_BACKOFF: Duration = Duration::from_secs(5);
pub struct GatewayClient<C: Clone> {
pub struct GatewayClient {
authenticated: bool,
disabled_credentials_mode: bool,
bandwidth_remaining: i64,
@@ -59,7 +55,7 @@ pub struct GatewayClient<C: Clone> {
connection: SocketState,
packet_router: PacketRouter,
response_timeout_duration: Duration,
bandwidth_controller: Option<BandwidthController<C, PersistentStorage>>,
bandwidth_controller: Option<BandwidthController<PersistentStorage>>,
// reconnection related variables
/// Specifies whether client should try to reconnect to gateway on connection failure.
@@ -74,10 +70,7 @@ pub struct GatewayClient<C: Clone> {
shutdown: TaskClient,
}
impl<C> GatewayClient<C>
where
C: CosmWasmClient + Sync + Send + Clone,
{
impl GatewayClient {
// TODO: put it all in a Config struct
#[allow(clippy::too_many_arguments)]
pub fn new(
@@ -89,7 +82,7 @@ where
mixnet_message_sender: MixnetMessageSender,
ack_sender: AcknowledgementSender,
response_timeout_duration: Duration,
bandwidth_controller: Option<BandwidthController<C, PersistentStorage>>,
bandwidth_controller: Option<BandwidthController<PersistentStorage>>,
shutdown: TaskClient,
) -> Self {
GatewayClient {
@@ -145,7 +138,7 @@ where
let shutdown = TaskClient::dummy();
let packet_router = PacketRouter::new(ack_tx, mix_tx, shutdown.clone());
GatewayClient::<C> {
GatewayClient {
authenticated: false,
disabled_credentials_mode: true,
bandwidth_remaining: 0,
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
#[cfg(target_arch = "wasm32")]
use crate::wasm_mockups::StorageError;
use crate::wasm_storage::StorageError;
#[cfg(not(target_arch = "wasm32"))]
use credential_storage::error::StorageError;
use gateway_requests::registration::handshake::error::HandshakeError;
+1 -1
View File
@@ -17,7 +17,7 @@ pub mod error;
pub mod packet_router;
pub mod socket_state;
#[cfg(target_arch = "wasm32")]
pub mod wasm_mockups;
mod wasm_storage;
/// Helper method for reading from websocket stream. Helps to flatten the structure.
pub(crate) fn cleanup_socket_message(
@@ -2,7 +2,6 @@
// SPDX-License-Identifier: Apache-2.0
use async_trait::async_trait;
use std::marker::PhantomData;
use thiserror::Error;
#[derive(Error, Debug)]
@@ -15,18 +14,6 @@ pub enum StorageError {
InconsistentData,
}
pub trait CosmWasmClient {}
#[derive(Clone)]
pub struct SigningNyxdClient {}
impl CosmWasmClient for SigningNyxdClient {}
#[derive(Clone)]
pub struct Client<C> {
_phantom: PhantomData<C>,
}
#[derive(Clone)]
pub struct PersistentStorage {}
@@ -37,7 +24,6 @@ pub struct CoconutCredential {
pub serial_number: String,
pub binding_number: String,
pub signature: String,
pub epoch_id: String,
}
#[async_trait]
+4 -5
View File
@@ -8,10 +8,9 @@ edition = "2021"
[dependencies]
futures = "0.3"
log = { workspace = true }
tokio = { version = "1.24.1", features = ["time", "net", "rt"] }
tokio-util = { version = "0.7.4", features = ["codec"] }
log = "0.4.8"
tokio = { version = "1.21.2", features = ["time", "net", "rt"] }
tokio-util = { version = "0.7.3", features = ["codec"] }
# internal
nymsphinx = { path = "../../nymsphinx" }
task = { path = "../../task" }
nymsphinx = {path = "../../nymsphinx" }
@@ -16,7 +16,6 @@ type MixForwardingReceiver = mpsc::UnboundedReceiver<MixPacket>;
pub struct PacketForwarder {
mixnet_client: Client,
packet_receiver: MixForwardingReceiver,
shutdown: task::TaskClient,
}
impl PacketForwarder {
@@ -26,7 +25,6 @@ impl PacketForwarder {
initial_connection_timeout: Duration,
maximum_connection_buffer_size: usize,
use_legacy_version: bool,
shutdown: task::TaskClient,
) -> (PacketForwarder, MixForwardingSender) {
let client_config = Config::new(
initial_reconnection_backoff,
@@ -42,35 +40,26 @@ impl PacketForwarder {
PacketForwarder {
mixnet_client: Client::new(client_config),
packet_receiver,
shutdown,
},
packet_sender,
)
}
pub async fn run(&mut self) {
while !self.shutdown.is_shutdown() {
tokio::select! {
biased;
_ = self.shutdown.recv() => {
log::trace!("PacketForwarder: Received shutdown");
}
Some(mix_packet) = self.packet_receiver.next() => {
trace!("Going to forward packet to {:?}", mix_packet.next_hop());
while let Some(mix_packet) = self.packet_receiver.next().await {
trace!("Going to forward packet to {:?}", mix_packet.next_hop());
let next_hop = mix_packet.next_hop();
let packet_mode = mix_packet.packet_mode();
let sphinx_packet = mix_packet.into_sphinx_packet();
// we don't care about responses, we just want to fire packets
// as quickly as possible
let next_hop = mix_packet.next_hop();
let packet_mode = mix_packet.packet_mode();
let sphinx_packet = mix_packet.into_sphinx_packet();
// we don't care about responses, we just want to fire packets
// as quickly as possible
if let Err(err) =
self.mixnet_client
.send_without_response(next_hop, sphinx_packet, packet_mode)
{
debug!("failed to forward the packet - {err}")
}
}
if let Err(err) =
self.mixnet_client
.send_without_response(next_hop, sphinx_packet, packet_mode)
{
debug!("failed to forward the packet - {err}")
}
}
}
@@ -17,15 +17,14 @@ mixnet-contract-common = { path= "../../cosmwasm-smart-contracts/mixnet-contract
vesting-contract-common = { path= "../../cosmwasm-smart-contracts/vesting-contract" }
coconut-bandwidth-contract-common = { path= "../../cosmwasm-smart-contracts/coconut-bandwidth-contract" }
multisig-contract-common = { path = "../../cosmwasm-smart-contracts/multisig-contract" }
group-contract-common = { path = "../../cosmwasm-smart-contracts/group-contract" }
vesting-contract = { path = "../../../contracts/vesting" }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
reqwest = { version = "0.11", features = ["json"] }
thiserror = "1"
log = { workspace = true }
log = "0.4"
url = { version = "2.2", features = ["serde"] }
tokio = { version = "1.24.1", features = ["sync", "time"] }
tokio = { version = "1.21.2", features = ["sync", "time"] }
futures = "0.3"
coconut-interface = { path = "../../coconut-interface" }
@@ -40,7 +39,6 @@ bip39 = { version = "1", features = ["rand"], optional = true }
config = { path = "../../config", optional = true }
cosmrs = { git = "https://github.com/neacsu/cosmos-rust", branch = "neacsu/feegrant_support", features = ["rpc", "bip32", "cosmwasm"], optional = true}
cw3 = { version = "0.13.4", optional = true }
cw4 = { version = "0.13.4", optional = true }
prost = { version = "0.10", default-features = false, optional = true }
flate2 = { version = "1.0.20", optional = true }
sha2 = { version = "0.9.5", optional = true }
@@ -58,7 +56,6 @@ nyxd-client = [
"config",
"cosmrs",
"cw3",
"cw4",
"prost",
"flate2",
"sha2",
@@ -21,9 +21,7 @@ use crate::nyxd::traits::{DkgQueryClient, MixnetQueryClient, MultisigQueryClient
use crate::nyxd::{self, CosmWasmClient, NyxdClient, QueryNyxdClient, SigningNyxdClient};
#[cfg(feature = "nyxd-client")]
use coconut_dkg_common::{
dealer::ContractDealing,
types::{DealerDetails, EpochId},
verification_key::ContractVKShare,
dealer::ContractDealing, types::DealerDetails, verification_key::ContractVKShare,
};
#[cfg(feature = "nyxd-client")]
use coconut_interface::Base58;
@@ -130,8 +128,7 @@ impl Config {
}
#[cfg(feature = "nyxd-client")]
#[derive(Clone)]
pub struct Client<C: Clone> {
pub struct Client<C> {
// TODO: we really shouldn't be storing a mnemonic here, but removing it would be
// non-trivial amount of work and it's out of scope of the current branch
mnemonic: Option<bip39::Mnemonic>,
@@ -221,10 +218,7 @@ impl Client<QueryNyxdClient> {
// nyxd wrappers
#[cfg(feature = "nyxd-client")]
impl<C> Client<C>
where
C: Clone,
{
impl<C> Client<C> {
// use case: somebody initialised client without a contract in order to upload and initialise one
// and now they want to actually use it without making new client
@@ -682,7 +676,6 @@ where
pub async fn get_all_nyxd_verification_key_shares(
&self,
epoch_id: EpochId,
) -> Result<Vec<ContractVKShare>, ValidatorClientError>
where
C: CosmWasmClient + Sync + Send,
@@ -692,11 +685,7 @@ where
loop {
let mut paged_response = self
.nyxd
.get_vk_shares_paged(
epoch_id,
start_after.take(),
self.verification_key_page_limit,
)
.get_vk_shares_paged(start_after.take(), self.verification_key_page_limit)
.await?;
shares.append(&mut paged_response.shares);
@@ -741,10 +730,7 @@ where
// validator-api wrappers
#[cfg(feature = "nyxd-client")]
impl<C> Client<C>
where
C: Clone,
{
impl<C> Client<C> {
pub fn change_nym_api(&mut self, new_endpoint: Url) {
self.nym_api.change_url(new_endpoint)
}
@@ -806,15 +792,14 @@ pub struct CoconutApiClient {
#[cfg(feature = "nyxd-client")]
impl CoconutApiClient {
pub async fn all_coconut_api_clients<C: Clone>(
pub async fn all_coconut_api_clients<C>(
nyxd_client: &Client<C>,
epoch_id: EpochId,
) -> Result<Vec<Self>, ValidatorClientError>
where
C: CosmWasmClient + Sync + Send,
{
Ok(nyxd_client
.get_all_nyxd_verification_key_shares(epoch_id)
.get_all_nyxd_verification_key_shares()
.await?
.into_iter()
.filter_map(Self::try_from)
@@ -6,7 +6,7 @@ use thiserror::Error;
#[derive(Error, Debug)]
pub enum ValidatorClientError {
#[error("nym api request failed - {source}")]
#[error("There was an issue with the validator api request - {source}")]
NymAPIError {
#[from]
source: nym_api::error::NymAPIError,
@@ -16,7 +16,7 @@ pub enum ValidatorClientError {
MalformedUrlProvided(#[from] url::ParseError),
#[cfg(feature = "nyxd-client")]
#[error("nyxd request failed - {0}")]
#[error("There was an issue with the Nyxd client - {0}")]
NyxdError(#[from] crate::nyxd::error::NyxdError),
#[error("No validator API url has been provided")]
@@ -9,8 +9,10 @@ pub mod nym_api;
#[cfg(feature = "nyxd-client")]
pub mod nyxd;
#[cfg(feature = "nyxd-client")]
pub use crate::client::{CoconutApiClient, NymApiClient};
pub use crate::error::ValidatorClientError;
pub use nym_api_requests::*;
#[cfg(feature = "nyxd-client")]
pub use client::{Client, CoconutApiClient, Config, NymApiClient};
pub use client::{Client, Config};
@@ -46,25 +46,25 @@ pub enum NyxdError {
#[error("{0} is not a valid tx hash")]
InvalidTxHash(String),
#[error("Tendermint RPC request failed - {0}")]
#[error("There was an issue with a tendermint RPC request - {0}")]
TendermintError(#[from] TendermintRpcError),
#[error("Failed when attempting to serialize data ({0})")]
#[error("There was an issue when attempting to serialize data ({0})")]
SerializationError(String),
#[error("Failed when attempting to deserialize data ({0})")]
#[error("There was an issue when attempting to deserialize data ({0})")]
DeserializationError(String),
#[error("Failed when attempting to encode our protobuf data - {0}")]
#[error("There was an issue when attempting to encode our protobuf data - {0}")]
ProtobufEncodingError(#[from] prost::EncodeError),
#[error("Failed to decode our protobuf data - {0}")]
#[error("There was an issue when attempting to decode our protobuf data - {0}")]
ProtobufDecodingError(#[from] prost::DecodeError),
#[error("Account {0} does not exist on the chain")]
NonExistentAccountError(AccountId),
#[error("Failed on json serialization/deserialization - {0}")]
#[error("There was an issue with the serialization/deserialization - {0}")]
SerdeJsonError(#[from] serde_json::Error),
#[error("Account {0} is not a valid account address")]
@@ -17,13 +17,11 @@ use cosmrs::rpc::HttpClientUrl;
use cosmrs::tx::Msg;
use execute::execute;
use log::debug;
use mixnet_contract_common::MixId;
use network_defaults::{ChainDetails, NymNetworkDetails};
use serde::{Deserialize, Serialize};
use std::convert::TryInto;
use std::time::SystemTime;
use vesting_contract_common::ExecuteMsg as VestingExecuteMsg;
use vesting_contract_common::PledgeCap;
pub use crate::nyxd::cosmwasm_client::client::CosmWasmClient;
pub use crate::nyxd::cosmwasm_client::signing_client::SigningCosmWasmClient;
@@ -45,8 +43,10 @@ pub use cosmrs::Coin as CosmosCoin;
pub use cosmrs::{bip32, AccountId, Decimal, Denom};
pub use cosmwasm_std::Coin as CosmWasmCoin;
pub use fee::{gas_price::GasPrice, GasAdjustable, GasAdjustment};
use mixnet_contract_common::MixId;
pub use signing_client::Client as SigningNyxdClient;
pub use traits::{VestingQueryClient, VestingSigningClient};
use vesting_contract_common::PledgeCap;
pub mod coin;
pub mod cosmwasm_client;
@@ -65,7 +65,6 @@ pub struct Config {
pub(crate) vesting_contract_address: Option<AccountId>,
pub(crate) bandwidth_claim_contract_address: Option<AccountId>,
pub(crate) coconut_bandwidth_contract_address: Option<AccountId>,
pub(crate) group_contract_address: Option<AccountId>,
pub(crate) multisig_contract_address: Option<AccountId>,
pub(crate) coconut_dkg_contract_address: Option<AccountId>,
// TODO: add this in later commits
@@ -120,10 +119,6 @@ impl Config {
.as_ref(),
prefix,
)?,
group_contract_address: Self::parse_optional_account(
details.contracts.group_contract_address.as_ref(),
prefix,
)?,
multisig_contract_address: Self::parse_optional_account(
details.contracts.multisig_contract_address.as_ref(),
prefix,
@@ -136,8 +131,8 @@ impl Config {
}
}
#[derive(Clone, Debug)]
pub struct NyxdClient<C: Clone> {
#[derive(Debug)]
pub struct NyxdClient<C> {
client: C,
config: Config,
client_address: Option<Vec<AccountId>>,
@@ -214,10 +209,7 @@ impl NyxdClient<SigningNyxdClient> {
}
}
impl<C> NyxdClient<C>
where
C: Clone,
{
impl<C> NyxdClient<C> {
pub fn current_config(&self) -> &Config {
&self.config
}
@@ -284,10 +276,6 @@ where
.unwrap()
}
pub fn group_contract_address(&self) -> &AccountId {
self.config.group_contract_address.as_ref().unwrap()
}
// TODO: this should get changed into Result<&AccountId, NyxdError> (or Option<&AccountId> in future commits
// note: what unwrap is doing here is just moving a failure that would have normally
// occurred in `connect` when attempting to parse an empty address,
@@ -18,7 +18,7 @@ pub trait CoconutBandwidthQueryClient {
}
#[async_trait]
impl<C: CosmWasmClient + Sync + Send + Clone> CoconutBandwidthQueryClient for NyxdClient<C> {
impl<C: CosmWasmClient + Sync + Send> CoconutBandwidthQueryClient for NyxdClient<C> {
async fn get_spent_credential(
&self,
blinded_serial_number: String,
@@ -30,9 +30,7 @@ pub trait CoconutBandwidthSigningClient {
}
#[async_trait]
impl<C: SigningCosmWasmClient + Sync + Send + Clone> CoconutBandwidthSigningClient
for NyxdClient<C>
{
impl<C: SigningCosmWasmClient + Sync + Send> CoconutBandwidthSigningClient for NyxdClient<C> {
async fn deposit(
&self,
amount: Coin,
@@ -8,7 +8,7 @@ use coconut_dkg_common::dealer::{
DealerDetailsResponse, PagedDealerResponse, PagedDealingsResponse,
};
use coconut_dkg_common::msg::QueryMsg as DkgQueryMsg;
use coconut_dkg_common::types::{Epoch, EpochId};
use coconut_dkg_common::types::Epoch;
use coconut_dkg_common::verification_key::PagedVKSharesResponse;
use cosmrs::AccountId;
@@ -39,7 +39,6 @@ pub trait DkgQueryClient {
) -> Result<PagedDealingsResponse, NyxdError>;
async fn get_vk_shares_paged(
&self,
epoch_id: EpochId,
start_after: Option<String>,
page_limit: Option<u32>,
) -> Result<PagedVKSharesResponse, NyxdError>;
@@ -48,7 +47,7 @@ pub trait DkgQueryClient {
#[async_trait]
impl<C> DkgQueryClient for NyxdClient<C>
where
C: CosmWasmClient + Send + Sync + Clone,
C: CosmWasmClient + Send + Sync,
{
async fn get_current_epoch(&self) -> Result<Epoch, NyxdError> {
let request = DkgQueryMsg::GetCurrentEpochState {};
@@ -120,12 +119,10 @@ where
async fn get_vk_shares_paged(
&self,
epoch_id: EpochId,
start_after: Option<String>,
page_limit: Option<u32>,
) -> Result<PagedVKSharesResponse, NyxdError> {
let request = DkgQueryMsg::GetVerificationKeys {
epoch_id,
limit: page_limit,
start_after,
};
@@ -36,7 +36,7 @@ pub trait DkgSigningClient {
#[async_trait]
impl<C> DkgSigningClient for NyxdClient<C>
where
C: SigningCosmWasmClient + Send + Sync + Clone,
C: SigningCosmWasmClient + Send + Sync,
{
async fn advance_dkg_epoch_state(&self, fee: Option<Fee>) -> Result<ExecuteResult, NyxdError> {
let req = DkgExecuteMsg::AdvanceEpochState {};
@@ -1,28 +0,0 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::nyxd::error::NyxdError;
use crate::nyxd::{CosmWasmClient, NyxdClient};
use group_contract_common::msg::QueryMsg;
use async_trait::async_trait;
use cw4::MemberResponse;
#[async_trait]
pub trait GroupQueryClient {
async fn member(&self, addr: String) -> Result<MemberResponse, NyxdError>;
}
#[async_trait]
impl<C: CosmWasmClient + Sync + Send + Clone> GroupQueryClient for NyxdClient<C> {
async fn member(&self, addr: String) -> Result<MemberResponse, NyxdError> {
let request = QueryMsg::Member {
addr,
at_height: None,
};
self.client
.query_contract_smart(self.group_contract_address(), &request)
.await
}
}
@@ -395,7 +395,7 @@ pub trait MixnetQueryClient {
#[async_trait]
impl<C> MixnetQueryClient for NyxdClient<C>
where
C: CosmWasmClient + Sync + Send + Clone,
C: CosmWasmClient + Sync + Send,
{
async fn query_mixnet_contract<T>(&self, query: MixnetQueryMsg) -> Result<T, NyxdError>
where
@@ -410,7 +410,7 @@ where
#[async_trait]
impl<C> MixnetQueryClient for crate::Client<C>
where
C: CosmWasmClient + Sync + Send + Clone,
C: CosmWasmClient + Sync + Send,
{
async fn query_mixnet_contract<T>(&self, query: MixnetQueryMsg) -> Result<T, NyxdError>
where
@@ -627,7 +627,7 @@ pub trait MixnetSigningClient {
#[async_trait]
impl<C> MixnetSigningClient for NyxdClient<C>
where
C: SigningCosmWasmClient + Sync + Send + Clone,
C: SigningCosmWasmClient + Sync + Send,
{
async fn execute_mixnet_contract(
&self,
@@ -653,7 +653,7 @@ where
#[async_trait]
impl<C> MixnetSigningClient for crate::Client<C>
where
C: SigningCosmWasmClient + Sync + Send + Clone,
C: SigningCosmWasmClient + Sync + Send,
{
async fn execute_mixnet_contract(
&self,
@@ -5,7 +5,6 @@ mod coconut_bandwidth_query_client;
mod coconut_bandwidth_signing_client;
mod dkg_query_client;
mod dkg_signing_client;
mod group_query_client;
mod mixnet_query_client;
mod mixnet_signing_client;
mod multisig_query_client;
@@ -17,7 +16,6 @@ pub use coconut_bandwidth_query_client::CoconutBandwidthQueryClient;
pub use coconut_bandwidth_signing_client::CoconutBandwidthSigningClient;
pub use dkg_query_client::DkgQueryClient;
pub use dkg_signing_client::DkgSigningClient;
pub use group_query_client::GroupQueryClient;
pub use mixnet_query_client::MixnetQueryClient;
pub use mixnet_signing_client::MixnetSigningClient;
pub use multisig_query_client::MultisigQueryClient;
@@ -20,7 +20,7 @@ pub trait MultisigQueryClient {
}
#[async_trait]
impl<C: CosmWasmClient + Sync + Send + Clone> MultisigQueryClient for NyxdClient<C> {
impl<C: CosmWasmClient + Sync + Send> MultisigQueryClient for NyxdClient<C> {
async fn get_proposal(&self, proposal_id: u64) -> Result<ProposalResponse, NyxdError> {
let request = QueryMsg::Proposal { proposal_id };
self.client
@@ -38,7 +38,7 @@ pub trait MultisigSigningClient {
}
#[async_trait]
impl<C: SigningCosmWasmClient + Sync + Send + Clone> MultisigSigningClient for NyxdClient<C> {
impl<C: SigningCosmWasmClient + Sync + Send> MultisigSigningClient for NyxdClient<C> {
async fn propose_release_funds(
&self,
title: String,
@@ -269,7 +269,7 @@ pub trait VestingQueryClient {
}
#[async_trait]
impl<C: CosmWasmClient + Sync + Send + Clone> VestingQueryClient for NyxdClient<C> {
impl<C: CosmWasmClient + Sync + Send> VestingQueryClient for NyxdClient<C> {
async fn query_vesting_contract<T>(&self, query: VestingQueryMsg) -> Result<T, NyxdError>
where
for<'a> T: Deserialize<'a>,
@@ -129,7 +129,7 @@ pub trait VestingSigningClient {
}
#[async_trait]
impl<C: SigningCosmWasmClient + Sync + Send + Clone> VestingSigningClient for NyxdClient<C> {
impl<C: SigningCosmWasmClient + Sync + Send> VestingSigningClient for NyxdClient<C> {
async fn execute_vesting_contract(
&self,
fee: Option<Fee>,
+2 -11
View File
@@ -18,8 +18,6 @@ pub struct Credential {
theta: Theta,
voucher_value: u64,
voucher_info: String,
#[getset(get = "pub")]
epoch_id: u64,
}
impl Credential {
pub fn new(
@@ -27,14 +25,12 @@ impl Credential {
theta: Theta,
voucher_value: u64,
voucher_info: String,
epoch_id: u64,
) -> Credential {
Credential {
n_params,
theta,
voucher_value,
voucher_info,
epoch_id,
}
}
@@ -72,7 +68,6 @@ impl Credential {
let theta_bytes = self.theta.to_bytes();
let theta_bytes_len = theta_bytes.len();
let voucher_value_bytes = self.voucher_value.to_be_bytes();
let epoch_id_bytes = self.epoch_id.to_be_bytes();
let voucher_info_bytes = self.voucher_info.as_bytes();
let voucher_info_len = voucher_info_bytes.len();
@@ -81,7 +76,6 @@ impl Credential {
bytes.extend_from_slice(&(theta_bytes_len as u64).to_be_bytes());
bytes.extend_from_slice(&theta_bytes);
bytes.extend_from_slice(&voucher_value_bytes);
bytes.extend_from_slice(&epoch_id_bytes);
bytes.extend_from_slice(voucher_info_bytes);
bytes
@@ -109,9 +103,7 @@ impl Credential {
.map_err(|e| CoconutError::Deserialization(e.to_string()))?;
eight_byte.copy_from_slice(&bytes[12 + theta_len as usize..20 + theta_len as usize]);
let voucher_value = u64::from_be_bytes(eight_byte);
eight_byte.copy_from_slice(&bytes[20 + theta_len as usize..28 + theta_len as usize]);
let epoch_id = u64::from_be_bytes(eight_byte);
let voucher_info = String::from_utf8(bytes[28 + theta_len as usize..].to_vec())
let voucher_info = String::from_utf8(bytes[20 + theta_len as usize..].to_vec())
.map_err(|e| CoconutError::Deserialization(e.to_string()))?;
Ok(Credential {
@@ -119,7 +111,6 @@ impl Credential {
theta,
voucher_value,
voucher_info,
epoch_id,
})
}
}
@@ -175,7 +166,7 @@ mod tests {
binding_number,
)
.unwrap();
let credential = Credential::new(4, theta, voucher_value, voucher_info, 42);
let credential = Credential::new(4, theta, voucher_value, voucher_info);
let serialized_credential = credential.as_bytes();
let deserialized_credential = Credential::from_bytes(&serialized_credential).unwrap();
+2 -2
View File
@@ -1,7 +1,7 @@
[package]
name = "nym-cli-commands"
version = "1.0.0"
authors.workspace = true
authors = ["Nym Technologies SA"]
edition = "2021"
[dependencies]
@@ -15,7 +15,7 @@ cw-utils = { version = "0.13.4" }
handlebars = "3.0.1"
humantime-serde = "1.0"
k256 = { version = "0.10", features = ["ecdsa", "sha256"] }
log = { workspace = true }
log = "0.4"
rand = {version = "0.6", features = ["std"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1"
+4 -4
View File
@@ -80,7 +80,7 @@ pub fn create_signing_client(
match NyxdClient::connect_with_mnemonic(client_config, nyxd_url, mnemonic, None) {
Ok(client) => Ok(client),
Err(e) => Err(ContextError::NyxdError(format!("{e}"))),
Err(e) => Err(ContextError::NyxdError(format!("{:?}", e))),
}
}
@@ -99,7 +99,7 @@ pub fn create_query_client(
match NyxdClient::connect(client_config, nyxd_url) {
Ok(client) => Ok(client),
Err(e) => Err(ContextError::NyxdError(format!("{e}"))),
Err(e) => Err(ContextError::NyxdError(format!("{:?}", e))),
}
}
@@ -122,7 +122,7 @@ pub fn create_signing_client_with_nym_api(
match validator_client::client::Client::new_signing(client_config, mnemonic) {
Ok(client) => Ok(client),
Err(e) => Err(ContextError::NyxdError(format!("{e}"))),
Err(e) => Err(ContextError::NyxdError(format!("{:?}", e))),
}
}
@@ -134,6 +134,6 @@ pub fn create_query_client_with_nym_api(
match validator_client::client::Client::new_query(client_config) {
Ok(client) => Ok(client),
Err(e) => Err(ContextError::NyxdError(format!("{e}"))),
Err(e) => Err(ContextError::NyxdError(format!("{:?}", e))),
}
}
+3 -3
View File
@@ -15,7 +15,7 @@ pub fn pretty_coin(coin: &Coin) -> String {
} else {
&coin.denom
};
format!("{amount} {denom}")
format!("{} {}", amount, denom)
}
pub fn pretty_cosmwasm_coin(coin: &CosmWasmCoin) -> String {
@@ -25,12 +25,12 @@ pub fn pretty_cosmwasm_coin(coin: &CosmWasmCoin) -> String {
} else {
&coin.denom
};
format!("{amount} {denom}")
format!("{} {}", amount, denom)
}
pub fn pretty_decimal_with_denom(value: Decimal, denom: &str) -> String {
// TODO: we might have to truncate the value here (that's why I moved it to separate function)
format!("{value} {denom}")
format!("{} {}", value, denom)
}
pub fn show_error<E>(e: E)
@@ -57,7 +57,7 @@ pub async fn query_balance(
if denom.is_empty() || denom.eq_ignore_ascii_case(&coin.denom) {
if args.raw {
if !args.hide_denom {
println!("{coin}");
println!("{}", coin);
} else {
println!("{}", coin.amount);
}
@@ -77,12 +77,12 @@ pub async fn get_pubkey_from_chain(address: AccountId, client: &QueryClient) {
if let Some(pubkey) = base_account.pubkey {
println!("{}", pubkey.to_string());
} else {
println!("No account associated with address {address}");
println!("No account associated with address {}", address);
}
}
}
Ok(None) => {
println!("No account associated with address {address}");
println!("No account associated with address {}", address);
}
Err(e) => show_error(e),
}
@@ -43,5 +43,5 @@ pub async fn generate(args: Args) {
let res =
serde_json::to_string(&instantiate_msg).expect("failed to convert instantiate msg to json");
println!("{res}")
println!("{}", res)
}
@@ -96,5 +96,5 @@ pub async fn generate(args: Args) {
let res =
serde_json::to_string(&instantiate_msg).expect("failed to convert instantiate msg to json");
println!("{res}")
println!("{}", res)
}
@@ -105,5 +105,5 @@ pub async fn generate(args: Args) {
let res =
serde_json::to_string(&instantiate_msg).expect("failed to convert instantiate msg to json");
println!("{res}")
println!("{}", res)
}
@@ -58,5 +58,5 @@ pub async fn generate(args: Args) {
let res =
serde_json::to_string(&instantiate_msg).expect("failed to convert instantiate msg to json");
println!("{res}")
println!("{}", res)
}
@@ -39,5 +39,5 @@ pub async fn generate(args: Args) {
let res =
serde_json::to_string(&instantiate_msg).expect("failed to convert instantiate msg to json");
println!("{res}")
println!("{}", res)
}
@@ -13,5 +13,5 @@ pub fn decode_mixnode_key(args: Args) {
let b64_decoded = base64::decode(args.key).expect("failed to decode base64 string");
let b58_encoded = bs58::encode(&b64_decoded).into_string();
println!("{b58_encoded}")
println!("{}", b58_encoded)
}
+1 -1
View File
@@ -9,7 +9,7 @@ edition = "2021"
[dependencies]
cfg-if = "1.0.0"
handlebars = "3.0.1"
log = { workspace = true }
log = "0.4"
serde = { version = "1.0", features = ["derive"] }
toml = "0.5.6"
url = "2.2"
-19
View File
@@ -148,25 +148,6 @@ pub trait OptionalSet {
}
}
fn with_validated_optional<F, T, V, E>(
self,
f: F,
value: Option<T>,
validate: V,
) -> Result<Self, E>
where
F: Fn(Self, T) -> Self,
V: Fn(&T) -> Result<(), E>,
Self: Sized,
{
if let Some(val) = value {
validate(&val)?;
Ok(f(self, val))
} else {
Ok(self)
}
}
fn with_optional_env<F, T>(self, f: F, val: Option<T>, env_var: &str) -> Self
where
F: Fn(Self, T) -> Self,
@@ -1,7 +1,7 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::types::{ContractSafeBytes, EncodedBTEPublicKeyWithProof, EpochId, TimeConfiguration};
use crate::types::{ContractSafeBytes, EncodedBTEPublicKeyWithProof, TimeConfiguration};
use crate::verification_key::VerificationKeyShare;
use cosmwasm_std::Addr;
use schemars::JsonSchema;
@@ -35,8 +35,6 @@ pub enum ExecuteMsg {
owner: Addr,
},
SurpassedThreshold {},
AdvanceEpochState {},
}
@@ -62,7 +60,6 @@ pub enum QueryMsg {
start_after: Option<String>,
},
GetVerificationKeys {
epoch_id: EpochId,
limit: Option<u32>,
start_after: Option<String>,
},

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