Compare commits

...

87 Commits

Author SHA1 Message Date
Simon Wicky c28410f6de allow multiple messages decryption 2023-08-02 13:59:06 +02:00
Simon Wicky 203633cabf noise between client and gateway, first try 2023-07-28 14:33:01 +02:00
Simon Wicky 331a0328c7 remove absolute dependence on topology 2023-07-28 12:09:13 +02:00
Simon Wicky 9e3bb6ef24 error handling on try_read + EOF 2023-07-28 09:25:44 +02:00
Simon Wicky 4014467496 revamp poll_read for Noise Stream 2023-07-27 12:25:17 +02:00
Simon Wicky 3cd17be26f error handling 2023-07-27 10:56:35 +02:00
Simon Wicky 9d91145f0a somewhat working stream 2023-07-26 16:18:40 +02:00
Simon Wicky 83d0dfc657 bit of cleanup 2023-07-26 15:47:43 +02:00
Simon Wicky f91a22cb6a store extra bytes in storage 2023-07-26 14:49:09 +02:00
Simon Wicky 981f567131 first try at noisestream 2023-07-26 14:44:56 +02:00
Simon Wicky c58331f9b0 change to sphinx key initiator side 2023-07-25 09:52:04 +02:00
Simon Wicky 5d26fefaaa hash psk 2023-07-25 09:23:51 +02:00
Simon Wicky dc77e3f962 swap id key for sphinx key 2023-07-24 16:54:08 +02:00
Simon Wicky eca406d9a7 more debugging... 2023-07-24 16:26:32 +02:00
Simon Wicky 139bde0176 more debugging 2023-07-24 16:19:31 +02:00
Simon Wicky a4c0be13f8 continue debugging 2023-07-24 15:16:32 +02:00
Simon Wicky f680222b91 add debug info 2023-07-24 11:48:18 +02:00
Simon Wicky 27b399331b debug info 2023-07-24 11:27:36 +02:00
Simon Wicky 3228bb5aa0 swap misplaced arguments for upgrade responder 2023-07-24 11:27:26 +02:00
Simon Wicky 8e4516a0a8 find node by ip not by full ip,port addr 2023-07-24 10:44:49 +02:00
Simon Wicky 234656aba8 draft a full noise handshake, with dummy secret 2023-07-24 10:18:22 +02:00
Simon Wicky 15f43c705a bring what's needed for secret, but epoch 2023-07-21 16:37:52 +02:00
Simon Wicky 044251d60f bring private key to the noise handshake. still does nothing though 2023-07-21 14:41:31 +02:00
Simon Wicky 5424568e81 add NoiseStream decorator, does nothing yet 2023-07-21 12:02:03 +02:00
Simon Wicky b939978c28 add topology refresher to gateways and mixnodes 2023-07-21 09:20:23 +02:00
farbanas c3ce9e24e2 Merge branch 'release/v1.1.23' 2023-07-05 16:28:58 +02:00
Mark Sinclair bdda08c0b4 GitHub Actions: Change artifact upload paths to wildcards 2023-07-05 14:28:10 +01:00
Mark Sinclair 0e48ff5e9e GitHub Action: upload artifact 2023-07-05 13:49:12 +01:00
Mark Sinclair 68d6ece6c2 GitHub Actions: add manual trigger 2023-07-05 13:11:03 +01:00
Mark Sinclair 493f036687 GitHub Actions: fix up installing project dependencies 2023-07-05 13:07:19 +01:00
Mark Sinclair 1f4f312e8e Removing pre-install target 2023-07-05 12:24:06 +01:00
Mark Sinclair d829837275 GitHub Actions: install project root dependencies first 2023-07-05 12:13:39 +01:00
Mark Sinclair 36253e3f36 GitHub Actions: fix up naming and versions 2023-07-05 12:13:21 +01:00
Mark Sinclair 7743554bb8 Update nym-wallet-publish-windows10.yml 2023-07-05 11:43:33 +01:00
Mark Sinclair de05e32845 Removing bash shell from GitHub Action 2023-07-04 17:45:23 +01:00
Mark Sinclair 136f4a8473 Revert adding copyfiles 2023-07-04 17:42:36 +01:00
Mark Sinclair 57e2628928 GitHub Actions adding bash to Windows publish workflow 2023-07-04 17:32:32 +01:00
Mark Sinclair 879e324696 Add another target for install and CI 2023-07-04 17:26:41 +01:00
Mark Sinclair 351552b863 Add back preinstall target 2023-07-04 17:22:54 +01:00
Mark Sinclair 847f3a0ecc Remove preinstall target that needs wasm-pack 2023-07-04 17:03:24 +01:00
Mark Sinclair 58958a2449 nym-wallet: use NPM published package and add -rc0 prefix to workspace SDK package 2023-07-04 17:01:05 +01:00
Mark Sinclair 3051d84e8d Revert GitHub Action changes to add wasm-pack to Typescript workflows 2023-07-04 17:00:11 +01:00
Mark Sinclair 2d7003dfae Add npm registry to setup-node to create .npmrc file with reg details 2023-07-04 16:06:55 +01:00
Mark Sinclair a91c997aed Revert building SDK from root package.json 2023-07-04 15:48:44 +01:00
Mark Sinclair 5787653210 GitHub Action to publish SDK 2023-07-04 15:40:45 +01:00
Mark Sinclair adbeeb3e5f GitHub Action to publish SDK 2023-07-04 15:39:11 +01:00
Mark Sinclair 4899ccf4ef GitHub Action to publish SDK 2023-07-04 15:36:26 +01:00
Mark Sinclair 9e0bcc025f Fix up working directory in GH Action to publish to NPM 2023-07-04 15:34:37 +01:00
Mark Sinclair 16d6444169 Add GH Actions workflow to publish the SDK 2023-07-04 15:30:49 +01:00
Mark Sinclair 730f03de30 Update nym-wallet-publish-windows10.yml 2023-07-04 11:54:46 +01:00
Mark Sinclair 2e366a094d Update nym-wallet-publish-windows10.yml 2023-07-04 11:52:13 +01:00
Mark Sinclair b134334ec7 Fix package.json preinstall error 2023-07-04 11:43:42 +01:00
Mark Sinclair f95b9b7f4a Add preinstall targets to some package.json files to build pre-requisites 2023-07-04 11:37:00 +01:00
Mark Sinclair 11ed3b3e45 GitHub Actions: run Windows steps that use yarn in bash 2023-07-04 11:33:05 +01:00
Mark Sinclair a71e228a25 Add wasm-pack install to GitHub Actions 2023-07-04 09:34:35 +01:00
farbanas da9c2e5a7c Merge remote-tracking branch 'refs/remotes/origin/master' 2023-07-04 09:55:15 +02:00
farbanas e025564678 update changelog 2023-07-04 09:48:43 +02:00
mx cf6188d794 Merge pull request #3635 from nymtech/feature/v1-1-23-docs
Feature/v1 1 23 docs
2023-07-03 18:50:57 +00:00
mfahampshire dd7308d92f Merge branch 'release/v1.1.23' into feature/v1-1-23-docs 2023-07-03 17:39:27 +00:00
mfahampshire 73ca14aae2 added alias info + some restructuring 2023-07-03 17:29:58 +00:00
mfahampshire 0fee189a89 moved image 2023-07-03 17:29:29 +00:00
Pierre Dommerc a0c6efafd2 feat(nc): monitoring update (#3609) 2023-07-03 18:35:28 +02:00
Fouad fcc5398aab Feature/node tester package (#3634)
* create node tester package dir

* start building node tester package

* refactor code + build updates

* fix up types

* add more methods and fix up types

* use node tester sdk inside wallet

* fix frontend state

* Use Node 18 instead of 16

* Fix up dependencies and yarn workspace

* Fix lint error

* Try to fix up linting error

* Remove explorer linting and move it to the existing action

* Add wasm-pack build to linting GH Action

* change lerna to use workspaces and fix linting errors

* Fix up node versions in GitHub Actions and add wasm-pack

* fix build:lint target in sdk

* exclude all worker.js from eslint for sdk

---------

Co-authored-by: Mark Sinclair <mmsinclair@users.noreply.github.com>
2023-07-03 16:53:39 +01:00
serinko 9f1f765f73 created matrix<>nymconnect user manual 2023-07-03 17:13:50 +02:00
mx 7bbb10e52c Merge branch 'release/v1.1.23' into feature/v1-1-23-docs 2023-07-03 09:47:55 +00:00
mfahampshire 1aad69a527 tidyup extra '/' in fixed last-changed git commit link 2023-07-03 09:43:04 +00:00
mfahampshire 4ad02d5328 fix attempt #3 2023-07-03 09:40:00 +00:00
mfahampshire 45b74008f1 fixed broken links to platform and wallet build instructions in readme 2023-07-03 09:36:23 +00:00
mfahampshire 2ddf9646ec push fix attempt 2 to get actual commit message on CI deployment 2023-07-03 09:31:56 +00:00
mfahampshire b258cd8733 fixed broken git url for last-changed mdbook plugin 2023-07-03 09:28:14 +00:00
Pierre Dommerc 7a1a7c003e feat(nc-desktop): add matrix and monero to providers list (ui) (#3623) 2023-06-30 12:13:52 +02:00
pierre 4b13a5cf61 build: add workflow to push release data to strapi 2023-06-29 16:07:54 +02:00
mx 02a4452eca Merge pull request #3613 from nymtech/dev-portal-edit
created monero.md user manual
2023-06-29 11:38:58 +00:00
mx d47633faa8 Update documentation/dev-portal/src/tutorials/monero.md
Co-authored-by: Mark Sinclair <14054343+mmsinclair@users.noreply.github.com>
2023-06-29 13:26:41 +02:00
serinko a3da077ce9 reverted cargo.lock & changed video size 2023-06-29 13:26:40 +02:00
serinko 131952c036 changed video link 2023-06-29 13:26:27 +02:00
mx 8d2ef605ed quickfix 2023-06-29 13:26:27 +02:00
mx fbcc2907bb fixed dead image link + added monero x nymconnect page to sidebare 2023-06-29 13:26:27 +02:00
serinko c0bb5503cf removed redundant copy 2023-06-29 13:26:27 +02:00
serinko ef7beaa12f created user manuals & monero.md 2023-06-29 13:26:24 +02:00
Jon Häggblad 2953837f25 Add medium toggle to socks5 client (#3615)
* Add medium toggle to socks5 client

* rustfmt
2023-06-28 23:47:00 +02:00
Jon Häggblad ee98820bb4 Use different service provider directory when medium toggle enabled (#3617) 2023-06-28 23:45:45 +02:00
Dave Hrycyszyn 0f41dda013 Made a few additions to upgrade notes 2023-06-28 12:23:32 +02:00
Dave Hrycyszyn 51d66c3e0c Made a few additions to upgrade notes 2023-06-28 11:21:24 +01:00
mx f14b40a769 hotfix on broken releases page link 2023-06-27 16:06:03 +02:00
mx d8f80434b4 * updated libwasmvm.so linking instructions
* added note on upgrading to v0.31.1
2023-06-27 16:02:31 +02:00
benedettadavico 2f98912778 fix nym-connect version 2023-06-20 13:56:38 +02:00
138 changed files with 3165 additions and 1097 deletions
+1 -1
View File
@@ -38,7 +38,7 @@ jobs:
- name: install npm
uses: actions/setup-node@v3
with:
node-version: 16
node-version: 18
- name: Matrix - Node Install
run: npm install
working-directory: .github/workflows/support-files
+1 -1
View File
@@ -16,7 +16,7 @@ jobs:
- uses: rlespinasse/github-slug-action@v3.x
- uses: actions/setup-node@v3
with:
node-version: 16
node-version: 18
- name: Setup yarn
run: npm install -g yarn
- name: Build
+1 -1
View File
@@ -16,7 +16,7 @@ jobs:
- uses: rlespinasse/github-slug-action@v3.x
- uses: actions/setup-node@v3
with:
node-version: "16"
node-version: 18
- name: Install Rust stable
uses: actions-rs/toolchain@v1
with:
+1 -1
View File
@@ -16,7 +16,7 @@ jobs:
- uses: rlespinasse/github-slug-action@v3.x
- uses: actions/setup-node@v3
with:
node-version: "16"
node-version: 18
- name: Install Rust stable
uses: actions-rs/toolchain@v1
with:
+1 -1
View File
@@ -16,7 +16,7 @@ jobs:
- uses: rlespinasse/github-slug-action@v3.x
- uses: actions/setup-node@v3
with:
node-version: "16"
node-version: 18
- name: Install Rust stable
uses: actions-rs/toolchain@v1
with:
+1 -1
View File
@@ -16,7 +16,7 @@ jobs:
- uses: rlespinasse/github-slug-action@v3.x
- uses: actions/setup-node@v3
with:
node-version: "16"
node-version: 18
- name: Install Rust stable
uses: actions-rs/toolchain@v1
with:
+1 -1
View File
@@ -20,7 +20,7 @@ jobs:
- uses: rlespinasse/github-slug-action@v3.x
- uses: actions/setup-node@v3
with:
node-version: 16
node-version: 18
- name: Install Yarn
run: npm install -g yarn
- run: yarn
@@ -1,24 +0,0 @@
name: Linting for Network Explorer (eslint/prettier)
on:
pull_request:
paths:
- 'explorer/**'
defaults:
run:
working-directory: explorer
jobs:
build:
runs-on: custom-runner-linux
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v3
with:
node-version: 16
- name: Setup yarn
run: npm install -g yarn
- name: Run ESLint
# GitHub should automatically annotate the PR
run: yarn && yarn lint
+1 -1
View File
@@ -21,7 +21,7 @@ jobs:
- uses: rlespinasse/github-slug-action@v3.x
- uses: actions/setup-node@v3
with:
node-version: 16
node-version: 18
- name: Setup yarn
run: npm install -g yarn
continue-on-error: true
+1 -1
View File
@@ -152,7 +152,7 @@ jobs:
uses: actions/setup-node@v3
if: env.WORKFLOW_CONCLUSION == 'failure'
with:
node-version: 16
node-version: 18
- name: Matrix - Node Install
if: env.WORKFLOW_CONCLUSION == 'failure'
run: npm install
+1 -1
View File
@@ -167,7 +167,7 @@ jobs:
uses: actions/setup-node@v3
if: env.WORKFLOW_CONCLUSION == 'failure'
with:
node-version: 16
node-version: 18
- name: Matrix - Node Install
if: env.WORKFLOW_CONCLUSION == 'failure'
run: npm install
+1 -1
View File
@@ -167,7 +167,7 @@ jobs:
uses: actions/setup-node@v3
if: env.WORKFLOW_CONCLUSION == 'failure'
with:
node-version: 16
node-version: 18
- name: Matrix - Node Install
if: env.WORKFLOW_CONCLUSION == 'failure'
run: npm install
@@ -20,10 +20,10 @@ jobs:
steps:
- uses: actions/checkout@v2
- name: Node v16
- name: Node
uses: actions/setup-node@v3
with:
node-version: 16
node-version: 18
- name: Install Rust stable
uses: actions-rs/toolchain@v1
with:
@@ -51,11 +51,15 @@ jobs:
security list-keychain -d user -s $KEYCHAIN_PATH
- name: Create env file
uses: timheuer/base64-to-file@v1.1
uses: timheuer/base64-to-file@v1.2
with:
fileName: '.env'
encodedString: ${{ secrets.WALLET_ADMIN_ADDRESS }}
- name: Install project dependencies
shell: bash
run: cd .. && yarn --network-timeout 100000
- name: Install app dependencies and build it
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -73,7 +77,7 @@ jobs:
uses: actions/upload-artifact@v3
with:
name: nym-connect_1.0.0_x64.dmg
path: nym-connect/desktop/target/release/bundle/dmg/nym-connect_1.0.0_x64.dmg
path: nym-connect/desktop/target/release/bundle/dmg/nym-connect_1*_x64.dmg
retention-days: 30
- name: Clean up keychain
@@ -26,19 +26,25 @@ jobs:
sudo apt-get install -y webkit2gtk-4.0 libayatana-appindicator3-dev
continue-on-error: true
- name: Node v16
- name: Node
uses: actions/setup-node@v3
with:
node-version: 16
node-version: 18
- name: Install Rust stable
uses: actions-rs/toolchain@v1
with:
toolchain: stable
- name: Install project dependencies
shell: bash
run: cd .. && yarn --network-timeout 100000
- name: Install app dependencies
run: yarn
- name: Create env file
uses: timheuer/base64-to-file@v1.1
uses: timheuer/base64-to-file@v1.2
with:
fileName: '.env'
encodedString: ${{ secrets.WALLET_ADMIN_ADDRESS }}
@@ -53,7 +59,7 @@ jobs:
uses: actions/upload-artifact@v3
with:
name: nym-connect.AppImage.tar.gz
path: nym-connect/desktop/target/release/bundle/appimage/nym-connect_1.0.0_amd64.AppImage
path: nym-connect/desktop/target/release/bundle/appimage/nym-connect_1*_amd64.AppImage
retention-days: 30
- name: Upload to release based on tag name
@@ -39,10 +39,10 @@ jobs:
Remove-Item -path certificate -include tempCert.txt
Import-PfxCertificate -FilePath certificate/certificate.pfx -CertStoreLocation Cert:\CurrentUser\My -Password (ConvertTo-SecureString -String $env:WINDOWS_CERTIFICATE_PASSWORD -Force -AsPlainText)
- name: Node v16
- name: Node
uses: actions/setup-node@v3
with:
node-version: 16
node-version: 18
- name: Install Rust stable
uses: actions-rs/toolchain@v1
@@ -50,15 +50,21 @@ jobs:
toolchain: stable
- name: Create env file
uses: timheuer/base64-to-file@v1.1
uses: timheuer/base64-to-file@v1.2
with:
fileName: '.env'
encodedString: ${{ secrets.WALLET_ADMIN_ADDRESS }}
- name: Install project dependencies
shell: bash
run: cd .. && yarn --network-timeout 100000
- name: Install app dependencies
shell: bash
run: yarn --network-timeout 100000
- name: Build and sign it
shell: bash
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
ENABLE_CODE_SIGNING: ${{ secrets.WINDOWS_CERTIFICATE }}
@@ -72,7 +78,7 @@ jobs:
uses: actions/upload-artifact@v3
with:
name: nym-connect_1.0.0_x64_en-US.msi
path: nym-connect/desktop/target/release/bundle/msi/nym-connect_1.0.0_x64_en-US.msi
path: nym-connect/desktop/target/release/bundle/msi/nym-connect_1*_x64_en-US.msi
retention-days: 30
- name: Upload to release based on tag name
@@ -20,10 +20,10 @@ jobs:
steps:
- uses: actions/checkout@v2
- name: Node v16
- name: Node
uses: actions/setup-node@v3
with:
node-version: 16
node-version: 18
- name: Install Rust stable
uses: actions-rs/toolchain@v1
with:
@@ -51,11 +51,15 @@ jobs:
security list-keychain -d user -s $KEYCHAIN_PATH
- name: Create env file
uses: timheuer/base64-to-file@v1.1
uses: timheuer/base64-to-file@v1.2
with:
fileName: '.env'
encodedString: ${{ secrets.WALLET_ADMIN_ADDRESS }}
- name: Install project dependencies
shell: bash
run: cd .. && yarn --network-timeout 100000
- name: Install app dependencies and build it
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -1,5 +1,6 @@
name: Publish Nym Wallet (Ubuntu)
on:
workflow_dispatch:
release:
types: [created]
@@ -25,19 +26,24 @@ jobs:
sudo apt-get install -y webkit2gtk-4.0
continue-on-error: true
- name: Node v16
- name: Node
uses: actions/setup-node@v3
with:
node-version: 16
node-version: 18
- name: Install Rust stable
uses: actions-rs/toolchain@v1
with:
toolchain: stable
- name: Install project dependencies
shell: bash
run: cd .. && yarn --network-timeout 100000
- name: Install app dependencies
run: yarn
- name: Create env file
uses: timheuer/base64-to-file@v1.1
uses: timheuer/base64-to-file@v1.2
with:
fileName: '.env'
encodedString: ${{ secrets.WALLET_ADMIN_ADDRESS }}
@@ -47,8 +53,17 @@ jobs:
env:
TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
- name: Upload Artifact
uses: actions/upload-artifact@v3
with:
name: nym-wallet_1.0.0_amd64.AppImage.tar.gz
path: nym-wallet/target/release/bundle/appimage/nym-wallet*.AppImage.tar.gz
retention-days: 30
- name: Upload to release based on tag name
uses: softprops/action-gh-release@v1
if: github.event_name == 'release'
with:
files: |
nym-wallet/target/release/bundle/appimage/*.AppImage
@@ -39,10 +39,10 @@ jobs:
Remove-Item -path certificate -include tempCert.txt
Import-PfxCertificate -FilePath certificate/certificate.pfx -CertStoreLocation Cert:\CurrentUser\My -Password (ConvertTo-SecureString -String $env:WINDOWS_CERTIFICATE_PASSWORD -Force -AsPlainText)
- name: Node v16
- name: Node
uses: actions/setup-node@v3
with:
node-version: 16
node-version: 18
- name: Install Rust stable
uses: actions-rs/toolchain@v1
@@ -50,15 +50,21 @@ jobs:
toolchain: stable
- name: Create env file
uses: timheuer/base64-to-file@v1.1
uses: timheuer/base64-to-file@v1.2
with:
fileName: '.env'
encodedString: ${{ secrets.WALLET_ADMIN_ADDRESS }}
- name: Install project dependencies
shell: bash
run: cd .. && yarn --network-timeout 100000
- name: Install app dependencies
shell: bash
run: yarn --network-timeout 100000
- name: Build and sign it
shell: bash
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
ENABLE_CODE_SIGNING: ${{ secrets.WINDOWS_CERTIFICATE }}
+1 -11
View File
@@ -16,19 +16,9 @@ jobs:
- uses: rlespinasse/github-slug-action@v3.x
- uses: actions/setup-node@v3
with:
node-version: 16
node-version: 18
- name: Setup yarn
run: npm install -g yarn
- name: Install Rust stable
uses: actions-rs/toolchain@v1
with:
toolchain: stable
- name: Install wasm-pack
run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
working-directory: clients/webassembly
- name: Build WASM
run: wasm-pack build
working-directory: clients/webassembly
- name: Build dependencies
run: yarn && yarn build
- name: Build storybook
+2 -2
View File
@@ -34,10 +34,10 @@ jobs:
profile: minimal
toolchain: stable
- name: Node v16
- name: Node
uses: actions/setup-node@v3
with:
node-version: 16
node-version: 18
- name: Install yarn for building application
run: yarn install
+154
View File
@@ -0,0 +1,154 @@
name: Push release data
env:
strapi_download_url: 'https://strapi.feat-nym-update-nym-web.websites.dev.nymte.ch/api/downloaders'
strapi_updater_url: 'https://strapi.feat-nym-update-nym-web.websites.dev.nymte.ch/api/updaters'
on:
workflow_call:
inputs: &wf-inputs
release_tag:
required: true
description: Release tag
type: string
release_id:
required: true
description: Release ID
type: string
release_date:
required: true
description: Release date
type: string
download_base_url:
required: true
description: Download base URL
type: string
changelog_url:
required: true
description: Changelog URL
type: string
archive_url:
required: false
description: Binary archive URL
type: string
sig_url:
required: false
description: Archive signature URL
type: string
version:
required: true
description: Release version (semver)
type: string
filename:
required: true
description: Binary file name
type: string
file_hash:
required: true
description: Binary hash (sha256)
type: string
name:
required: true
description: Name
type: string
category:
required: true
description: Category
type: string
platform:
required: false
description: Platform
type: string
workflow_dispatch:
inputs:
<<: *wf-inputs
category:
required: true
description: Category
default: 'wallet'
type: choice
options:
- wallet
- connect
- binaries
platform:
required: false
description: Platform
default: 'Ubuntu'
type: choice
options:
- Ubuntu
- Windows
- MacOS
jobs:
push-download-data:
name: Push download data to Strapi
runs-on: custom-runner-linux
steps:
- id: get_sig
name: Get sig
if: ${{ inputs.sig_url != null }}
run: |
output=$(curl -LsSf ${{ inputs.sig_url }})
echo "sig=$output" >> "$GITHUB_OUTPUT"
- name: Push download data
uses: fjogeleit/http-request-action@v1
with:
url: ${{ env.strapi_download_url }}
method: 'POST'
# bearerToken: ${{ secrets.STRAPI_AUTH_TOKEN }} TODO
customHeaders: '{"Content-Type": "application/json"}'
data: |
{
"data": {
"releaseId": "${{ inputs.release_id }}",
"releaseDate": "${{ inputs.release_date }}",
"downloadBaseUrl": "${{ inputs.download_base_url }}",
"changelogUrl": "${{ inputs.changelog_url }}",
"version": "${{ inputs.version }}",
"filename": "${{ inputs.filename }}",
"name": "${{ inputs.name }}",
"category": "${{ inputs.category }}",
"platform": "${{ inputs.platform }}",
"sha256": "${{ inputs.file_hash }}",
"sig": "${{ steps.get_sig.outputs.sig }}"
}
}
push-update-data:
name: Push update data to Strapi
runs-on: ${{ matrix.platform }}
# only push update data for tauri apps (desktop wallet and NC)
if: ${{ inputs.category == 'wallet' || inputs.category == 'connect' }}
steps:
- id: get_sig
name: Get sig
if: ${{ inputs.sig_url != null }}
run: |
output=$(curl -LsSf ${{ inputs.sig_url }})
echo "sig=$output" >> "$GITHUB_OUTPUT"
- name: Push update data
uses: fjogeleit/http-request-action@v1
with:
url: ${{ env.strapi_updater_url }}
method: 'POST'
# bearerToken: ${{ secrets.STRAPI_AUTH_TOKEN }} TODO
customHeaders: '{"Content-Type": "application/json"}'
data: |
{
"data": {
"releaseId": "${{ inputs.release_id }}",
"releaseDate": "${{ inputs.release_date }}",
"downloadUrl": "${{ inputs.archive_url }}",
"changelog": "See ${{ inputs.changelog_url }} for the changelog",
"version": "${{ inputs.version }}",
"filename": "${{ inputs.filename }}",
"category": "${{ inputs.category }}",
"platform": "${{ inputs.platform }}",
"sha256": "${{ inputs.file_hash }}",
"sig": "${{ steps.get_sig.outputs.sig }}"
}
}
+35
View File
@@ -0,0 +1,35 @@
name: Publish SDK to NPM
on:
workflow_dispatch:
jobs:
publish:
runs-on: [custom-runner-linux]
steps:
- uses: actions/checkout@v2
- name: Install Node
uses: actions/setup-node@v3
with:
node-version: 18
registry-url: 'https://registry.npmjs.org'
- name: Setup yarn
run: npm install -g yarn
- name: Install Rust stable
uses: actions-rs/toolchain@v1
with:
toolchain: stable
- name: Install wasm-pack
run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
- name: Install dependencies
run: yarn
- name: Build and publish
env:
NODE_AUTH_TOKEN: ${{ secrets.NODE_AUTH_TOKEN }}
working-directory: ./sdk/typescript/packages/sdk
run: scripts/publish.sh
+1 -1
View File
@@ -1 +1 @@
16
18
+3 -11
View File
@@ -11,6 +11,7 @@ on:
- 'nym-connect/mobile/package.json'
- 'nym-wallet/src/**'
- 'nym-wallet/package.json'
- 'explorer/**'
pull_request:
paths:
- 'ts-packages/**'
@@ -21,6 +22,7 @@ on:
- 'nym-connect/mobile/package.json'
- 'nym-wallet/src/**'
- 'nym-wallet/package.json'
- 'explorer/**'
jobs:
build:
@@ -33,19 +35,9 @@ jobs:
- uses: rlespinasse/github-slug-action@v3.x
- uses: actions/setup-node@v3
with:
node-version: 16
node-version: 18
- name: Setup yarn
run: npm install -g yarn
- name: Install Rust stable
uses: actions-rs/toolchain@v1
with:
toolchain: stable
- name: Install wasm-pack
run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
working-directory: clients/webassembly
- name: Build WASM
run: wasm-pack build
working-directory: clients/webassembly
- name: Install
run: yarn
- name: Build packages
+5 -1
View File
@@ -4,12 +4,16 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
## [Unreleased]
## [1.1.23] (2023-06-27)
## [v1.1.23] (2023-07-04)
- nym-cli: add client identity key signing support ([#3576])
- Feature/node tester package ([#3634])
- Add medium toggle to socks5 client ([#3615])
- Don't fully turn off background task when cover traffic is disabled ([#3596])
[#3576]: https://github.com/nymtech/nym/issues/3576
[#3634]: https://github.com/nymtech/nym/pull/3634
[#3615]: https://github.com/nymtech/nym/pull/3615
[#3596]: https://github.com/nymtech/nym/pull/3596
## [v1.1.22] (2023-06-20)
Generated
+239 -69
View File
@@ -14,6 +14,15 @@ version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "aead"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b613b8e1e3cf911a086f53f03bf286f52fd7a7258e4fa606f0ef220d39d8877"
dependencies = [
"generic-array 0.14.7",
]
[[package]]
name = "aead"
version = "0.5.2"
@@ -48,17 +57,31 @@ dependencies = [
"cpufeatures",
]
[[package]]
name = "aes-gcm"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df5f85a83a7d8b0442b6aa7b504b8212c1733da07b98aae43d4bc21b2cb3cdf6"
dependencies = [
"aead 0.4.3",
"aes 0.7.5",
"cipher 0.3.0",
"ctr 0.8.0",
"ghash 0.4.4",
"subtle 2.4.1",
]
[[package]]
name = "aes-gcm"
version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "82e1366e0c69c9f927b1fa5ce2c7bf9eafc8f9268c0b9800729e8b267612447c"
dependencies = [
"aead",
"aead 0.5.2",
"aes 0.8.2",
"cipher 0.4.4",
"ctr 0.9.2",
"ghash",
"ghash 0.5.0",
"subtle 2.4.1",
]
@@ -244,7 +267,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.16",
"syn 2.0.27",
]
[[package]]
@@ -255,7 +278,7 @@ checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.16",
"syn 2.0.27",
]
[[package]]
@@ -472,7 +495,7 @@ version = "0.10.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe"
dependencies = [
"digest 0.10.6",
"digest 0.10.7",
]
[[package]]
@@ -486,7 +509,7 @@ dependencies = [
"cc",
"cfg-if",
"constant_time_eq",
"digest 0.10.6",
"digest 0.10.7",
]
[[package]]
@@ -618,6 +641,18 @@ dependencies = [
"keystream",
]
[[package]]
name = "chacha20"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c80e5460aa66fe3b91d40bcbdab953a597b60053e34d684ac6903f863b680a6"
dependencies = [
"cfg-if",
"cipher 0.3.0",
"cpufeatures",
"zeroize",
]
[[package]]
name = "chacha20"
version = "0.9.1"
@@ -629,16 +664,29 @@ dependencies = [
"cpufeatures",
]
[[package]]
name = "chacha20poly1305"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a18446b09be63d457bbec447509e85f662f32952b035ce892290396bc0b0cff5"
dependencies = [
"aead 0.4.3",
"chacha20 0.8.2",
"cipher 0.3.0",
"poly1305 0.7.2",
"zeroize",
]
[[package]]
name = "chacha20poly1305"
version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35"
dependencies = [
"aead",
"chacha20",
"aead 0.5.2",
"chacha20 0.9.1",
"cipher 0.4.4",
"poly1305",
"poly1305 0.8.0",
"zeroize",
]
@@ -770,7 +818,7 @@ dependencies = [
"heck 0.4.1",
"proc-macro2",
"quote",
"syn 2.0.16",
"syn 2.0.27",
]
[[package]]
@@ -899,13 +947,13 @@ version = "0.16.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e859cd57d0710d9e06c381b550c06e76992472a8c6d527aecd2fc673dcc231fb"
dependencies = [
"aes-gcm",
"aes-gcm 0.10.1",
"base64 0.20.0",
"hkdf 0.12.3",
"hmac 0.12.1",
"percent-encoding",
"rand 0.8.5",
"sha2 0.10.6",
"sha2 0.10.7",
"subtle 2.4.1",
"time 0.3.21",
"version_check",
@@ -1308,6 +1356,20 @@ dependencies = [
"zeroize",
]
[[package]]
name = "curve25519-dalek"
version = "4.0.0-rc.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d4ba9852b42210c7538b75484f9daa0655e9a3ac04f693747bb0f02cf3cfe16"
dependencies = [
"cfg-if",
"fiat-crypto",
"packed_simd_2",
"platforms",
"subtle 2.4.1",
"zeroize",
]
[[package]]
name = "cw-controllers"
version = "0.13.4"
@@ -1501,9 +1563,9 @@ dependencies = [
[[package]]
name = "digest"
version = "0.10.6"
version = "0.10.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f"
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
dependencies = [
"block-buffer 0.10.4",
"crypto-common",
@@ -1603,7 +1665,7 @@ version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c762bae6dcaf24c4c84667b8579785430908723d5c889f469d76a41d59cc7a9d"
dependencies = [
"curve25519-dalek",
"curve25519-dalek 3.2.0",
"ed25519",
"rand 0.7.3",
"serde",
@@ -1618,7 +1680,7 @@ version = "3.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c24f403d068ad0b359e577a77f92392118be3f3c927538f2bb544a5ecd828c6"
dependencies = [
"curve25519-dalek",
"curve25519-dalek 3.2.0",
"hashbrown 0.12.3",
"hex",
"rand_core 0.6.4",
@@ -1677,7 +1739,7 @@ checksum = "eecf8589574ce9b895052fa12d69af7a233f99e6107f5cb8dd1044f2a17bfdcb"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.16",
"syn 2.0.27",
]
[[package]]
@@ -1832,6 +1894,12 @@ dependencies = [
"subtle 2.4.1",
]
[[package]]
name = "fiat-crypto"
version = "0.1.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e825f6987101665dea6ec934c09ec6d721de7bc1bf92248e1d5810c8cd636b77"
[[package]]
name = "figment"
version = "0.10.8"
@@ -2029,7 +2097,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.16",
"syn 2.0.27",
]
[[package]]
@@ -2140,6 +2208,16 @@ dependencies = [
"syn 1.0.109",
]
[[package]]
name = "ghash"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1583cc1656d7839fd3732b80cf4f38850336cdb9b8ded1cd399ca62958de3c99"
dependencies = [
"opaque-debug 0.3.0",
"polyval 0.5.3",
]
[[package]]
name = "ghash"
version = "0.5.0"
@@ -2147,7 +2225,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d930750de5717d2dd0b8c0d42c076c0e884c81a73e6cab859bbd2339c71e3e40"
dependencies = [
"opaque-debug 0.3.0",
"polyval",
"polyval 0.6.0",
]
[[package]]
@@ -2158,7 +2236,7 @@ checksum = "e77ac7b51b8e6313251737fcef4b1c01a2ea102bde68415b62c0ee9268fec357"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.16",
"syn 2.0.27",
]
[[package]]
@@ -2439,7 +2517,7 @@ version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
dependencies = [
"digest 0.10.6",
"digest 0.10.7",
]
[[package]]
@@ -3010,6 +3088,12 @@ dependencies = [
"pkg-config",
]
[[package]]
name = "libm"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fc7aa29613bd6a620df431842069224d8bc9011086b1db4c0e0cd47fa03ec9a"
[[package]]
name = "libm"
version = "0.2.7"
@@ -3069,12 +3153,9 @@ dependencies = [
[[package]]
name = "log"
version = "0.4.17"
version = "0.4.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
dependencies = [
"cfg-if",
]
checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4"
[[package]]
name = "loom"
@@ -3307,7 +3388,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
dependencies = [
"autocfg 1.1.0",
"libm",
"libm 0.2.7",
]
[[package]]
@@ -3587,7 +3668,7 @@ dependencies = [
"rand 0.7.3",
"serde",
"serde_json",
"sha2 0.10.6",
"sha2 0.10.7",
"sqlx 0.6.3",
"tap",
"tempfile",
@@ -3749,7 +3830,7 @@ dependencies = [
"bs58",
"cipher 0.4.4",
"ctr 0.9.2",
"digest 0.10.6",
"digest 0.10.7",
"ed25519-dalek",
"generic-array 0.14.7",
"hkdf 0.12.3",
@@ -3817,6 +3898,7 @@ dependencies = [
"log",
"nym-api-requests",
"nym-bin-common",
"nym-client-core",
"nym-coconut-interface",
"nym-config",
"nym-credentials",
@@ -3825,10 +3907,12 @@ dependencies = [
"nym-mixnet-client",
"nym-mixnode-common",
"nym-network-defaults",
"nym-noise",
"nym-pemstore",
"nym-sphinx",
"nym-statistics-common",
"nym-task",
"nym-topology",
"nym-types",
"nym-validator-client",
"once_cell",
@@ -3860,6 +3944,7 @@ dependencies = [
"nym-crypto",
"nym-gateway-requests",
"nym-network-defaults",
"nym-noise",
"nym-pemstore",
"nym-sphinx",
"nym-task",
@@ -3923,6 +4008,9 @@ version = "0.1.0"
dependencies = [
"futures",
"log",
"nym-client-core",
"nym-crypto",
"nym-noise",
"nym-sphinx",
"nym-task",
"tokio",
@@ -3965,11 +4053,13 @@ dependencies = [
"lazy_static",
"log",
"nym-bin-common",
"nym-client-core",
"nym-config",
"nym-contracts-common",
"nym-crypto",
"nym-mixnet-client",
"nym-mixnode-common",
"nym-noise",
"nym-nonexhaustive-delayqueue",
"nym-pemstore",
"nym-sphinx",
@@ -4140,6 +4230,21 @@ dependencies = [
"wasm-utils",
]
[[package]]
name = "nym-noise"
version = "0.1.0"
dependencies = [
"bytes",
"futures",
"log",
"nym-topology",
"pin-project",
"sha2 0.10.7",
"snow",
"thiserror",
"tokio",
]
[[package]]
name = "nym-nonexhaustive-delayqueue"
version = "0.1.0"
@@ -4181,10 +4286,10 @@ name = "nym-outfox"
version = "0.1.0"
dependencies = [
"blake3",
"chacha20",
"chacha20poly1305",
"chacha20 0.9.1",
"chacha20poly1305 0.10.1",
"criterion",
"curve25519-dalek",
"curve25519-dalek 3.2.0",
"fastrand",
"getrandom 0.2.10",
"log",
@@ -4539,7 +4644,7 @@ dependencies = [
name = "nym-store-cipher"
version = "0.1.0"
dependencies = [
"aes-gcm",
"aes-gcm 0.10.1",
"argon2",
"generic-array 0.14.7",
"getrandom 0.2.10",
@@ -4758,7 +4863,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.16",
"syn 2.0.27",
]
[[package]]
@@ -4906,6 +5011,16 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
[[package]]
name = "packed_simd_2"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1914cd452d8fccd6f9db48147b29fd4ae05bea9dc5d9ad578509f72415de282"
dependencies = [
"cfg-if",
"libm 0.1.4",
]
[[package]]
name = "pairing"
version = "0.20.0"
@@ -5024,7 +5139,7 @@ dependencies = [
"proc-macro2",
"proc-macro2-diagnostics 0.10.0",
"quote",
"syn 2.0.16",
"syn 2.0.27",
]
[[package]]
@@ -5101,7 +5216,7 @@ dependencies = [
"pest_meta",
"proc-macro2",
"quote",
"syn 2.0.16",
"syn 2.0.27",
]
[[package]]
@@ -5112,7 +5227,7 @@ checksum = "745a452f8eb71e39ffd8ee32b3c5f51d03845f99786fa9b68db6ff509c505411"
dependencies = [
"once_cell",
"pest",
"sha2 0.10.6",
"sha2 0.10.7",
]
[[package]]
@@ -5132,7 +5247,7 @@ checksum = "39407670928234ebc5e6e580247dd567ad73a3578460c5990f9503df207e8f07"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.16",
"syn 2.0.27",
]
[[package]]
@@ -5164,6 +5279,12 @@ version = "0.3.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964"
[[package]]
name = "platforms"
version = "3.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3d7ddaed09e0eb771a79ab0fd64609ba0afb0a8366421957936ad14cbd13630"
[[package]]
name = "plotters"
version = "0.3.4"
@@ -5208,6 +5329,17 @@ dependencies = [
"windows-sys 0.48.0",
]
[[package]]
name = "poly1305"
version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "048aeb476be11a4b6ca432ca569e375810de9294ae78f4774e78ea98a9246ede"
dependencies = [
"cpufeatures",
"opaque-debug 0.3.0",
"universal-hash 0.4.1",
]
[[package]]
name = "poly1305"
version = "0.8.0"
@@ -5216,7 +5348,19 @@ checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf"
dependencies = [
"cpufeatures",
"opaque-debug 0.3.0",
"universal-hash",
"universal-hash 0.5.0",
]
[[package]]
name = "polyval"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8419d2b623c7c0896ff2d5d96e2cb4ede590fed28fcc34934f4c33c036e620a1"
dependencies = [
"cfg-if",
"cpufeatures",
"opaque-debug 0.3.0",
"universal-hash 0.4.1",
]
[[package]]
@@ -5228,7 +5372,7 @@ dependencies = [
"cfg-if",
"cpufeatures",
"opaque-debug 0.3.0",
"universal-hash",
"universal-hash 0.5.0",
]
[[package]]
@@ -5283,9 +5427,9 @@ dependencies = [
[[package]]
name = "proc-macro2"
version = "1.0.58"
version = "1.0.66"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa1fb82fc0c281dd9671101b66b771ebbe1eaf967b96ac8740dcba4b70005ca8"
checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9"
dependencies = [
"unicode-ident",
]
@@ -5311,7 +5455,7 @@ checksum = "606c4ba35817e2922a308af55ad51bab3645b59eae5c570d4a6cf07e36bd493b"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.16",
"syn 2.0.27",
"version_check",
"yansi",
]
@@ -5406,9 +5550,9 @@ checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3"
[[package]]
name = "quote"
version = "1.0.27"
version = "1.0.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f4f29d145265ec1c483c7c654450edde0bfe043d3938d6972630663356d9500"
checksum = "50f3b39ccfb720540debaa0164757101c08ecb8d326b15358ce76a62c7e85965"
dependencies = [
"proc-macro2",
]
@@ -5701,7 +5845,7 @@ checksum = "8d2275aab483050ab2a7364c1a46604865ee7d6906684e08db0f090acf74f9e7"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.16",
"syn 2.0.27",
]
[[package]]
@@ -6253,7 +6397,7 @@ checksum = "8c805777e3930c8883389c602315a24224bcc738b63905ef87cd1420353ea93e"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.16",
"syn 2.0.27",
]
[[package]]
@@ -6286,7 +6430,7 @@ checksum = "bcec881020c684085e55a25f7fd888954d56609ef363479dc5a1305eb0d40cab"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.16",
"syn 2.0.27",
]
[[package]]
@@ -6331,7 +6475,7 @@ checksum = "f5058ada175748e33390e40e872bd0fe59a19f265d0158daa551c5a88a76009c"
dependencies = [
"cfg-if",
"cpufeatures",
"digest 0.10.6",
"digest 0.10.7",
]
[[package]]
@@ -6342,7 +6486,7 @@ checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3"
dependencies = [
"cfg-if",
"cpufeatures",
"digest 0.10.6",
"digest 0.10.7",
]
[[package]]
@@ -6360,13 +6504,13 @@ dependencies = [
[[package]]
name = "sha2"
version = "0.10.6"
version = "0.10.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0"
checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8"
dependencies = [
"cfg-if",
"cpufeatures",
"digest 0.10.6",
"digest 0.10.7",
]
[[package]]
@@ -6478,6 +6622,22 @@ dependencies = [
"syn 1.0.109",
]
[[package]]
name = "snow"
version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ccba027ba85743e09d15c03296797cad56395089b832b48b5a5217880f57733"
dependencies = [
"aes-gcm 0.9.4",
"blake2 0.10.6",
"chacha20poly1305 0.9.1",
"curve25519-dalek 4.0.0-rc.1",
"rand_core 0.6.4",
"rustc_version 0.4.0",
"sha2 0.10.7",
"subtle 2.4.1",
]
[[package]]
name = "socket2"
version = "0.4.9"
@@ -6500,7 +6660,7 @@ dependencies = [
"bs58",
"byteorder",
"chacha",
"curve25519-dalek",
"curve25519-dalek 3.2.0",
"digest 0.9.0",
"hkdf 0.11.0",
"hmac 0.11.0",
@@ -6613,7 +6773,7 @@ dependencies = [
"paste",
"percent-encoding",
"rustls 0.19.1",
"sha2 0.10.6",
"sha2 0.10.7",
"smallvec",
"sqlformat 0.1.8",
"sqlx-rt 0.5.13",
@@ -6661,7 +6821,7 @@ dependencies = [
"percent-encoding",
"rustls 0.20.8",
"rustls-pemfile",
"sha2 0.10.6",
"sha2 0.10.7",
"smallvec",
"sqlformat 0.2.1",
"sqlx-rt 0.6.3",
@@ -6684,7 +6844,7 @@ dependencies = [
"once_cell",
"proc-macro2",
"quote",
"sha2 0.10.6",
"sha2 0.10.7",
"sqlx-core 0.5.13",
"sqlx-rt 0.5.13",
"syn 1.0.109",
@@ -6703,7 +6863,7 @@ dependencies = [
"once_cell",
"proc-macro2",
"quote",
"sha2 0.10.6",
"sha2 0.10.7",
"sqlx-core 0.6.3",
"sqlx-rt 0.6.3",
"syn 1.0.109",
@@ -6847,9 +7007,9 @@ dependencies = [
[[package]]
name = "syn"
version = "2.0.16"
version = "2.0.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a6f671d4b5ffdb8eadec19c0ae67fe2639df8684bd7bc4b83d986b8db549cf01"
checksum = "b60f673f44a8255b9c8c657daf66a596d435f2da81a555b06dc644d080ba45e0"
dependencies = [
"proc-macro2",
"quote",
@@ -7009,22 +7169,22 @@ checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d"
[[package]]
name = "thiserror"
version = "1.0.40"
version = "1.0.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac"
checksum = "611040a08a0439f8248d1990b111c95baa9c704c805fa1f62104b39655fd7f90"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.40"
version = "1.0.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f"
checksum = "090198534930841fab3a5d1bb637cde49e339654e606195f8d9c76eeb081dc96"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.16",
"syn 2.0.27",
]
[[package]]
@@ -7161,7 +7321,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.16",
"syn 2.0.27",
]
[[package]]
@@ -7397,7 +7557,7 @@ checksum = "0f57e3ca2a01450b1a921183a9c9cbfda207fd822cef4ccb00a65402cbba7a74"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.16",
"syn 2.0.27",
]
[[package]]
@@ -7675,6 +7835,16 @@ dependencies = [
"extension-traits",
]
[[package]]
name = "universal-hash"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f214e8f697e925001e66ec2c6e37a4ef93f0f78c2eed7814394e10c62025b05"
dependencies = [
"generic-array 0.14.7",
"subtle 2.4.1",
]
[[package]]
name = "universal-hash"
version = "0.5.0"
@@ -8208,7 +8378,7 @@ version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a0c105152107e3b96f6a00a65e86ce82d9b125230e1c4302940eca58ff71f4f"
dependencies = [
"curve25519-dalek",
"curve25519-dalek 3.2.0",
"rand_core 0.5.1",
"serde",
"zeroize",
@@ -8237,5 +8407,5 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.16",
"syn 2.0.27",
]
+4 -5
View File
@@ -13,7 +13,7 @@ The platform is composed of multiple Rust crates. Top-level executable binary cr
* nym-gateway - acts sort of like a mailbox for mixnet messages, which removes the need for direct delivery to potentially offline or firewalled devices.
* nym-network-monitor - sends packets through the full system to check that they are working as expected, and stores node uptime histories as the basis of a rewards system ("mixmining" or "proof-of-mixing").
* nym-explorer - a (projected) block explorer and (existing) mixnet viewer.
* nym-wallet - a desktop wallet implemented using the [Tauri](https://tauri.studio/en/docs/about/intro) framework.
* nym-wallet - a desktop wallet implemented using the [Tauri](https://tauri.studio/en/docs/about/intro) framework.
[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg?style=for-the-badge)](https://opensource.org/licenses/Apache-2.0)
[![Build Status](https://img.shields.io/github/actions/workflow/status/nymtech/nym/build.yml?branch=develop&style=for-the-badge&logo=github-actions)](https://github.com/nymtech/nym/actions?query=branch%3Adevelop)
@@ -21,7 +21,7 @@ The platform is composed of multiple Rust crates. Top-level executable binary cr
### Building
Platform build instructions are available on [our docs site](https://nymtech.net/docs/binaries/build-nym.html).
Platform build instructions are available on [our docs site](https://nymtech.net/docs/binaries/pre-built-binaries.html).
Wallet build instructions are also available on [our docs site](https://nymtech.net/docs/wallet/desktop-wallet.html).
### Developing
@@ -32,9 +32,9 @@ For Typescript components, please see [ts-packages](./ts-packages).
### Developer chat
> We used to use Keybase for developer chats, but we have since migrated to Matrix and Discord. We no longer check the old **nymtech.friends** Keybase team.
> We used to use Keybase for developer chats, but we have since migrated to Matrix and Discord. We no longer check the old **nymtech.friends** Keybase team.
You can chat to us in two places:
You can chat to us in two places:
* The #dev channel on [Matrix](https://matrix.to/#/#dev:nymtech.chat)
* The various developer channels on [Discord](https://discord.gg/nym)
@@ -84,4 +84,3 @@ where `s'` is stake `s` scaled over total token circulating supply.
### Licensing and copyright information
This program is available as open source under the terms of the Apache 2.0 license. However, some elements are being licensed under CC0-1.0 and MIT. For accurate information, please check individual files.
+1
View File
@@ -94,6 +94,7 @@ impl From<Init> for OverrideConfig {
use_anonymous_replies: init_config.use_reply_surbs,
fastmode: init_config.fastmode,
no_cover: init_config.no_cover,
medium_toggle: false,
nyxd_urls: init_config.nyxd_urls,
enabled_credentials_mode: init_config.enabled_credentials_mode,
outfox: false,
+17 -1
View File
@@ -19,7 +19,7 @@ use nym_client_core::client::key_manager::persistence::OnDiskKeys;
use nym_client_core::config::GatewayEndpointConfig;
use nym_client_core::error::ClientCoreError;
use nym_config::OptionalSet;
use nym_sphinx::params::PacketType;
use nym_sphinx::params::{PacketSize, PacketType};
use std::error::Error;
pub mod init;
@@ -72,6 +72,7 @@ pub(crate) struct OverrideConfig {
use_anonymous_replies: Option<bool>,
fastmode: bool,
no_cover: bool,
medium_toggle: bool,
nyxd_urls: Option<Vec<url::Url>>,
enabled_credentials_mode: Option<bool>,
outfox: bool,
@@ -91,6 +92,10 @@ pub(crate) async fn execute(args: &Cli) -> Result<(), Box<dyn Error + Send + Syn
}
pub(crate) fn override_config(config: Config, args: OverrideConfig) -> Config {
let disable_cover_traffic_with_keepalive = args.medium_toggle;
let secondary_packet_size = args.medium_toggle.then_some(PacketSize::ExtendedPacket16);
let no_per_hop_delays = args.medium_toggle;
let packet_type = if args.outfox {
PacketType::Outfox
} else {
@@ -101,6 +106,17 @@ pub(crate) fn override_config(config: Config, args: OverrideConfig) -> Config {
BaseClientConfig::with_high_default_traffic_volume,
args.fastmode,
)
.with_base(
// NOTE: This interacts with disabling cover traffic fully, so we want to this to be set before
BaseClientConfig::with_disabled_cover_traffic_with_keepalive,
disable_cover_traffic_with_keepalive,
)
.with_base(
BaseClientConfig::with_secondary_packet_size,
secondary_packet_size,
)
.with_base(BaseClientConfig::with_no_per_hop_delays, no_per_hop_delays)
// NOTE: see comment above about the order of the other disble cover traffic config
.with_base(BaseClientConfig::with_disabled_cover_traffic, args.no_cover)
.with_base(BaseClientConfig::with_packet_type, packet_type)
.with_optional(Config::with_anonymous_replies, args.use_anonymous_replies)
+6
View File
@@ -60,6 +60,11 @@ pub(crate) struct Run {
#[clap(long, hide = true)]
no_cover: bool,
/// Enable medium mixnet traffic, for experiments only.
/// This includes things like disabling cover traffic, no per hop delays, etc.
#[clap(long, hide = true)]
medium_toggle: bool,
/// Set this client to work in a enabled credentials mode that would attempt to use gateway
/// with bandwidth credential requirement.
#[clap(long, hide = true)]
@@ -77,6 +82,7 @@ impl From<Run> for OverrideConfig {
use_anonymous_replies: run_config.use_anonymous_replies,
fastmode: run_config.fastmode,
no_cover: run_config.no_cover,
medium_toggle: run_config.medium_toggle,
nyxd_urls: run_config.nyxd_urls,
enabled_credentials_mode: run_config.enabled_credentials_mode,
outfox: run_config.outfox,
+1 -1
View File
@@ -1 +1 @@
16
18
@@ -306,15 +306,21 @@ where
{
let gateway_address = gateway_config.gateway_listener.clone();
let gateway_id = gateway_config.gateway_id;
let gateway_sphinx = gateway_config.gateway_sphinx;
// TODO: in theory, at this point, this should be infallible
let gateway_identity = identity::PublicKey::from_base58_string(gateway_id)
.map_err(ClientCoreError::UnableToCreatePublicKeyFromGatewayId)?;
let gateway_sphinx_key = encryption::PublicKey::from_base58_string(gateway_sphinx)
.map_err(ClientCoreError::UnableToCreateSphinxKeyFromGatewayId)?;
let mut gateway_client = GatewayClient::new(
gateway_address,
managed_keys.identity_keypair(),
managed_keys.encryption_keypair(),
gateway_identity,
gateway_sphinx_key,
Some(managed_keys.must_get_gateway_shared_key()),
mixnet_message_sender,
ack_sender,
@@ -83,6 +83,16 @@ impl<'a> TopologyReadPermit<'a> {
Ok(topology)
}
pub fn try_get_raw_topology_ref(&'a self) -> Result<&'a NymTopology, NymTopologyError> {
// 1. Have we managed to get anything from the refresher, i.e. have the nym-api queries gone through?
let topology = self
.permit
.as_ref()
.ok_or(NymTopologyError::EmptyNetworkTopology)?;
Ok(topology)
}
}
impl<'a> From<RwLockReadGuard<'a, Option<NymTopology>>> for TopologyReadPermit<'a> {
@@ -9,8 +9,8 @@ use nym_topology::provider_trait::TopologyProvider;
use nym_topology::NymTopologyError;
use std::time::Duration;
mod accessor;
pub(crate) mod nym_api_provider;
pub mod accessor;
pub mod nym_api_provider;
// TODO: move it to config later
const MAX_FAILURE_COUNT: usize = 10;
@@ -9,7 +9,7 @@ use rand::prelude::SliceRandom;
use rand::thread_rng;
use url::Url;
pub(crate) struct NymApiTopologyProvider {
pub struct NymApiTopologyProvider {
validator_client: nym_validator_client::client::NymApiClient,
nym_api_urls: Vec<Url>,
@@ -18,7 +18,7 @@ pub(crate) struct NymApiTopologyProvider {
}
impl NymApiTopologyProvider {
pub(crate) fn new(mut nym_api_urls: Vec<Url>, client_version: String) -> Self {
pub fn new(mut nym_api_urls: Vec<Url>, client_version: String) -> Self {
nym_api_urls.shuffle(&mut thread_rng());
NymApiTopologyProvider {
+11 -1
View File
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
use nym_config::defaults::NymNetworkDetails;
use nym_crypto::asymmetric::identity;
use nym_crypto::asymmetric::{encryption, identity};
use nym_sphinx::params::{PacketSize, PacketType};
use serde::{Deserialize, Serialize};
use std::time::Duration;
@@ -207,6 +207,8 @@ pub struct GatewayEndpointConfig {
/// If initially omitted, a random gateway will be chosen from the available topology.
pub gateway_id: String,
pub gateway_sphinx: String,
/// Address of the gateway owner to which the client should send messages.
pub gateway_owner: String,
@@ -219,11 +221,13 @@ impl GatewayEndpointConfig {
#[cfg_attr(target_arch = "wasm32", wasm_bindgen(constructor))]
pub fn new(
gateway_id: String,
gateway_sphinx: String,
gateway_owner: String,
gateway_listener: String,
) -> GatewayEndpointConfig {
GatewayEndpointConfig {
gateway_id,
gateway_sphinx,
gateway_owner,
gateway_listener,
}
@@ -236,6 +240,11 @@ impl GatewayEndpointConfig {
identity::PublicKey::from_base58_string(&self.gateway_id)
.map_err(ClientCoreError::UnableToCreatePublicKeyFromGatewayId)
}
pub fn try_get_gateway_sphinx_key(&self) -> Result<encryption::PublicKey, ClientCoreError> {
encryption::PublicKey::from_base58_string(&self.gateway_sphinx)
.map_err(ClientCoreError::UnableToCreateSphinxKeyFromGatewayId)
}
}
impl From<nym_topology::gateway::Node> for GatewayEndpointConfig {
@@ -243,6 +252,7 @@ impl From<nym_topology::gateway::Node> for GatewayEndpointConfig {
let gateway_listener = node.clients_address();
GatewayEndpointConfig {
gateway_id: node.identity_key.to_base58_string(),
gateway_sphinx: node.sphinx_key.to_base58_string(),
gateway_owner: node.owner,
gateway_listener,
}
@@ -68,6 +68,7 @@ pub struct ConfigV1_1_20<T> {
#[derive(Clone, Debug, Default, Deserialize, PartialEq, Eq, Serialize)]
pub struct GatewayEndpointConfigV1_1_20 {
pub gateway_id: String,
pub gateway_sphinx: String,
pub gateway_owner: String,
pub gateway_listener: String,
}
@@ -76,6 +77,7 @@ impl From<GatewayEndpointConfigV1_1_20> for GatewayEndpointConfigV1_1_20_2 {
fn from(value: GatewayEndpointConfigV1_1_20) -> Self {
GatewayEndpointConfigV1_1_20_2 {
gateway_id: value.gateway_id,
gateway_sphinx: value.gateway_sphinx,
gateway_owner: value.gateway_owner,
gateway_listener: value.gateway_listener,
}
@@ -73,6 +73,8 @@ pub struct GatewayEndpointConfigV1_1_20_2 {
/// If initially omitted, a random gateway will be chosen from the available topology.
pub gateway_id: String,
pub gateway_sphinx: String,
/// Address of the gateway owner to which the client should send messages.
pub gateway_owner: String,
@@ -84,6 +86,7 @@ impl From<GatewayEndpointConfigV1_1_20_2> for GatewayEndpointConfig {
fn from(value: GatewayEndpointConfigV1_1_20_2) -> Self {
GatewayEndpointConfig {
gateway_id: value.gateway_id,
gateway_sphinx: value.gateway_sphinx,
gateway_owner: value.gateway_owner,
gateway_listener: value.gateway_listener,
}
+4
View File
@@ -1,6 +1,7 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use nym_crypto::asymmetric::encryption::KeyRecoveryError;
use nym_crypto::asymmetric::identity::Ed25519RecoveryError;
use nym_gateway_client::error::GatewayClientError;
use nym_topology::gateway::GatewayConversionError;
@@ -58,6 +59,9 @@ pub enum ClientCoreError {
#[error("The gateway id is invalid - {0}")]
UnableToCreatePublicKeyFromGatewayId(Ed25519RecoveryError),
#[error("The gateway sphinx is invalid - {0}")]
UnableToCreateSphinxKeyFromGatewayId(KeyRecoveryError),
#[error("The identity of the gateway is unknown - did you run init?")]
GatewayIdUnknown,
+4 -1
View File
@@ -5,7 +5,7 @@ use crate::config::GatewayEndpointConfig;
use crate::error::ClientCoreError;
use futures::{SinkExt, StreamExt};
use log::{debug, info, trace, warn};
use nym_crypto::asymmetric::identity;
use nym_crypto::asymmetric::{encryption, identity};
use nym_gateway_client::GatewayClient;
use nym_gateway_requests::registration::handshake::SharedKeys;
use nym_topology::{filter::VersionFilterable, gateway};
@@ -200,12 +200,15 @@ pub(super) fn uniformly_random_gateway<R: Rng>(
pub(super) async fn register_with_gateway(
gateway: &GatewayEndpointConfig,
our_identity: Arc<identity::KeyPair>,
our_sphinx: Arc<encryption::KeyPair>,
) -> Result<Arc<SharedKeys>, ClientCoreError> {
let timeout = Duration::from_millis(1500);
let mut gateway_client: GatewayClient<DirectSigningNyxdClient, _> = GatewayClient::new_init(
gateway.gateway_listener.clone(),
gateway.try_get_gateway_identity_key()?,
gateway.try_get_gateway_sphinx_key()?,
our_identity.clone(),
our_sphinx.clone(),
timeout,
);
gateway_client
+4 -1
View File
@@ -370,8 +370,11 @@ where
// get our identity key
let our_identity = managed_keys.identity_keypair();
let our_sphinx = managed_keys.encryption_keypair();
// Establish connection, authenticate and generate keys for talking with the gateway
let shared_keys = helpers::register_with_gateway(&gateway_details, our_identity).await?;
let shared_keys =
helpers::register_with_gateway(&gateway_details, our_identity, our_sphinx).await?;
let persisted_details = PersistedGatewayDetails::new(gateway_details, &shared_keys);
@@ -27,6 +27,7 @@ nym-sphinx = { path = "../../nymsphinx" }
nym-pemstore = { path = "../../pemstore" }
nym-validator-client = { path = "../validator-client" }
nym-task = { path = "../../task" }
nym-noise = { path = "../../nymnoise"}
serde = { workspace = true, features = ["derive"] }
@@ -14,24 +14,27 @@ use nym_bandwidth_controller::BandwidthController;
use nym_coconut_interface::Credential;
use nym_credential_storage::ephemeral_storage::EphemeralStorage as EphemeralCredentialStorage;
use nym_credential_storage::storage::Storage as CredentialStorage;
use nym_crypto::asymmetric::identity;
use nym_crypto::asymmetric::{encryption, identity};
use nym_gateway_requests::authentication::encrypted_address::EncryptedAddressBytes;
use nym_gateway_requests::iv::IV;
use nym_gateway_requests::registration::handshake::{client_handshake, SharedKeys};
use nym_gateway_requests::{BinaryRequest, ClientControlRequest, ServerResponse, PROTOCOL_VERSION};
use nym_network_defaults::{REMAINING_BANDWIDTH_THRESHOLD, TOKENS_TO_BURN};
use nym_noise::upgrade_noise_initiator;
use nym_sphinx::forwarding::packet::MixPacket;
use nym_task::TaskClient;
use rand::rngs::OsRng;
use std::convert::TryFrom;
use std::net::SocketAddr;
use std::sync::Arc;
use std::time::Duration;
use tokio::net::TcpStream;
use tungstenite::protocol::Message;
#[cfg(not(target_arch = "wasm32"))]
use nym_validator_client::nyxd::traits::DkgQueryClient;
#[cfg(not(target_arch = "wasm32"))]
use tokio_tungstenite::connect_async;
use tokio_tungstenite::client_async;
#[cfg(target_arch = "wasm32")]
use nym_bandwidth_controller::wasm_mockups::DkgQueryClient;
@@ -49,7 +52,9 @@ pub struct GatewayClient<C, St> {
bandwidth_remaining: i64,
gateway_address: String,
gateway_identity: identity::PublicKey,
gateway_sphinx: encryption::PublicKey,
local_identity: Arc<identity::KeyPair>,
local_sphinx: Arc<encryption::KeyPair>,
shared_key: Option<Arc<SharedKeys>>,
connection: SocketState,
packet_router: PacketRouter,
@@ -75,7 +80,9 @@ impl<C, St> GatewayClient<C, St> {
pub fn new(
gateway_address: String,
local_identity: Arc<identity::KeyPair>,
local_sphinx: Arc<encryption::KeyPair>,
gateway_identity: identity::PublicKey,
gateway_sphinx: encryption::PublicKey,
// TODO: make it mandatory. if you don't want to pass it, use `new_init`
shared_key: Option<Arc<SharedKeys>>,
mixnet_message_sender: MixnetMessageSender,
@@ -89,8 +96,10 @@ impl<C, St> GatewayClient<C, St> {
disabled_credentials_mode: true,
bandwidth_remaining: 0,
gateway_address,
gateway_identity,
local_identity,
local_sphinx,
gateway_identity,
gateway_sphinx,
shared_key,
connection: SocketState::NotConnected,
packet_router: PacketRouter::new(ack_sender, mixnet_message_sender, shutdown.clone()),
@@ -163,7 +172,50 @@ impl<C, St> GatewayClient<C, St> {
#[cfg(not(target_arch = "wasm32"))]
pub async fn establish_connection(&mut self) -> Result<(), GatewayClientError> {
let ws_stream = match connect_async(&self.gateway_address).await {
let socket_addr: SocketAddr = self.gateway_address.parse().unwrap();
let connection_fut = TcpStream::connect(socket_addr);
//arbitrary TO, it's a POC
let noise_conn = match tokio::time::timeout(Duration::from_secs(5), connection_fut).await {
Ok(stream_res) => match stream_res {
Ok(stream) => {
debug!("Managed to establish connection to gateway");
let noise_stream = match upgrade_noise_initiator(
stream,
None, //as a client, the gateway cannot know my pub key
&self.local_sphinx.private_key().to_bytes(),
&self.gateway_sphinx.to_bytes(),
)
.await
{
Ok(noise_stream) => noise_stream,
Err(err) => {
error!(
"Failed to perform Noise handshake with {:?} - {err}",
self.gateway_address
);
return Err(GatewayClientError::ConnectionNotEstablished);
}
};
debug!(
"Noise initiator handshake completed for {:?}",
self.gateway_address
);
noise_stream
}
Err(err) => {
debug!("failed to establish connection to gateway (err: {})", err);
return Err(GatewayClientError::NetworkIoError(err));
}
},
Err(_) => {
debug!("failed to connect to {} within 5s", self.gateway_address);
return Err(GatewayClientError::Timeout);
}
};
let ws_address = format!("ws://{}", self.gateway_address);
let ws_stream = match client_async(ws_address, noise_conn).await {
Ok((ws_stream, _)) => ws_stream,
Err(e) => return Err(GatewayClientError::NetworkError(e)),
};
@@ -773,7 +825,9 @@ impl<C> GatewayClient<C, EphemeralCredentialStorage> {
pub fn new_init(
gateway_address: String,
gateway_identity: identity::PublicKey,
gateway_sphinx: encryption::PublicKey,
local_identity: Arc<identity::KeyPair>,
local_sphinx: Arc<encryption::KeyPair>,
response_timeout_duration: Duration,
) -> Self {
use futures::channel::mpsc;
@@ -791,7 +845,9 @@ impl<C> GatewayClient<C, EphemeralCredentialStorage> {
bandwidth_remaining: 0,
gateway_address,
gateway_identity,
gateway_sphinx,
local_identity,
local_sphinx,
shared_key: None,
connection: SocketState::NotConnected,
packet_router,
@@ -19,6 +19,9 @@ pub enum GatewayClientError {
#[error("There was a network error - {0}")]
NetworkError(#[from] WsError),
#[error("There was a network error - {0}")]
NetworkIoError(#[from] io::Error),
// TODO: see if `JsValue` is a reasonable type for this
#[cfg(target_arch = "wasm32")]
#[error("There was a network error")]
@@ -9,14 +9,13 @@ use futures::stream::{SplitSink, SplitStream};
use futures::{SinkExt, StreamExt};
use log::*;
use nym_gateway_requests::registration::handshake::SharedKeys;
use nym_noise::NoiseStream;
use nym_task::TaskClient;
use std::sync::Arc;
use tungstenite::Message;
#[cfg(not(target_arch = "wasm32"))]
use tokio::net::TcpStream;
#[cfg(not(target_arch = "wasm32"))]
use tokio_tungstenite::{MaybeTlsStream, WebSocketStream};
use tokio_tungstenite::WebSocketStream;
#[cfg(target_arch = "wasm32")]
use wasm_bindgen_futures;
@@ -26,7 +25,7 @@ use wasm_utils::websocket::JSWebsocket;
// type alias for not having to type the whole thing every single time (and now it makes it easier
// to use different types based on compilation target)
#[cfg(not(target_arch = "wasm32"))]
type WsConn = WebSocketStream<MaybeTlsStream<TcpStream>>;
type WsConn = WebSocketStream<NoiseStream>;
#[cfg(target_arch = "wasm32")]
type WsConn = JSWebsocket;
@@ -15,3 +15,6 @@ tokio-util = { version = "0.7.4", features = ["codec"] }
# internal
nym-sphinx = { path = "../../nymsphinx" }
nym-task = { path = "../../task" }
nym-client-core = { path = "../../client-core" }
nym-noise = { path = "../../nymnoise"}
nym-crypto = { path = "../../crypto" }
+58 -9
View File
@@ -4,6 +4,9 @@
use futures::channel::mpsc;
use futures::StreamExt;
use log::*;
use nym_client_core::client::topology_control::accessor::TopologyAccessor;
use nym_crypto::asymmetric::encryption;
use nym_noise::upgrade_noise_initiator_with_topology;
use nym_sphinx::addressing::nodes::NymNodeRoutingAddress;
use nym_sphinx::framing::codec::NymCodec;
use nym_sphinx::framing::packet::FramedNymPacket;
@@ -59,6 +62,8 @@ pub trait SendWithoutResponse {
pub struct Client {
conn_new: HashMap<NymNodeRoutingAddress, ConnectionSender>,
config: Config,
topology_access: TopologyAccessor,
local_identity: Arc<encryption::KeyPair>,
}
struct ConnectionSender {
@@ -76,10 +81,16 @@ impl ConnectionSender {
}
impl Client {
pub fn new(config: Config) -> Client {
pub fn new(
config: Config,
topology_access: TopologyAccessor,
local_identity: Arc<encryption::KeyPair>,
) -> Client {
Client {
conn_new: HashMap::new(),
config,
topology_access,
local_identity,
}
}
@@ -88,6 +99,9 @@ impl Client {
receiver: mpsc::Receiver<FramedNymPacket>,
connection_timeout: Duration,
current_reconnection: &AtomicU32,
topology_access: TopologyAccessor,
local_public_key: &[u8],
local_private_key: &[u8],
) {
let connection_fut = TcpStream::connect(address);
@@ -97,7 +111,32 @@ impl Client {
debug!("Managed to establish connection to {}", address);
// if we managed to connect, reset the reconnection count (whatever it might have been)
current_reconnection.store(0, Ordering::Release);
Framed::new(stream, NymCodec)
//Get the topology, because we need the keys for the handshake
let topology_permit = topology_access.get_read_permit().await;
let topology_ref = match topology_permit.try_get_raw_topology_ref() {
Ok(topology) => topology,
Err(err) => {
error!("Cannot perform Noise handshake to {address}, due to topology error - {err}");
return;
}
};
let noise_stream = match upgrade_noise_initiator_with_topology(
stream,
topology_ref,
local_public_key,
local_private_key,
)
.await
{
Ok(noise_stream) => noise_stream,
Err(err) => {
error!("Failed to perform Noise handshake with {address} - {err}");
return;
}
};
debug!("Noise initiator handshake completed for {:?}", address);
Framed::new(noise_stream, NymCodec)
}
Err(err) => {
debug!(
@@ -175,6 +214,10 @@ impl Client {
// copy the value before moving into another task
let initial_connection_timeout = self.config.initial_connection_timeout;
let topology_access_clone = self.topology_access.clone();
let local_public_key = self.local_identity.public_key().to_bytes();
let local_private_key = self.local_identity.private_key().to_bytes();
tokio::spawn(async move {
// before executing the manager, wait for what was specified, if anything
if let Some(backoff) = backoff {
@@ -187,6 +230,9 @@ impl Client {
receiver,
initial_connection_timeout,
&current_reconnection_attempt,
topology_access_clone,
&local_public_key,
&local_private_key,
)
.await
});
@@ -255,13 +301,16 @@ mod tests {
use super::*;
fn dummy_client() -> Client {
Client::new(Config {
initial_reconnection_backoff: Duration::from_millis(10_000),
maximum_reconnection_backoff: Duration::from_millis(300_000),
initial_connection_timeout: Duration::from_millis(1_500),
maximum_connection_buffer_size: 128,
use_legacy_version: false,
})
Client::new(
Config {
initial_reconnection_backoff: Duration::from_millis(10_000),
maximum_reconnection_backoff: Duration::from_millis(300_000),
initial_connection_timeout: Duration::from_millis(1_500),
maximum_connection_buffer_size: 128,
use_legacy_version: false,
},
TopologyAccessor::new(),
)
}
#[test]
@@ -5,7 +5,10 @@ use crate::client::{Client, Config, SendWithoutResponse};
use futures::channel::mpsc;
use futures::StreamExt;
use log::*;
use nym_client_core::client::topology_control::accessor::TopologyAccessor;
use nym_crypto::asymmetric::encryption;
use nym_sphinx::forwarding::packet::MixPacket;
use std::sync::Arc;
use std::time::Duration;
pub type MixForwardingSender = mpsc::UnboundedSender<MixPacket>;
@@ -26,6 +29,8 @@ impl PacketForwarder {
initial_connection_timeout: Duration,
maximum_connection_buffer_size: usize,
use_legacy_version: bool,
topology_access: TopologyAccessor,
local_identity: Arc<encryption::KeyPair>,
shutdown: nym_task::TaskClient,
) -> (PacketForwarder, MixForwardingSender) {
let client_config = Config::new(
@@ -40,7 +45,7 @@ impl PacketForwarder {
(
PacketForwarder {
mixnet_client: Client::new(client_config),
mixnet_client: Client::new(client_config, topology_access, local_identity),
packet_receiver,
shutdown,
},
+18
View File
@@ -0,0 +1,18 @@
[package]
name = "nym-noise"
version = "0.1.0"
authors = ["Simon Wicky <simon@nymtech.net>"]
edition = "2021"
[dependencies]
snow = "0.9.2"
futures = "0.3"
tokio = { version = "1.24.1", features = ["net","io-util"] }
pin-project = "1"
log = "0.4.19"
sha2 = "0.10.7"
bytes = "1.0"
thiserror = "1.0.44"
# internal
nym-topology = { path = "../topology"}
+355
View File
@@ -0,0 +1,355 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use log::*;
use nym_topology::NymTopology;
use pin_project::pin_project;
use sha2::{Digest, Sha256};
use snow::error::Prerequisite;
use snow::Builder;
use snow::Error;
use snow::TransportState;
use std::cmp::min;
use std::collections::VecDeque;
use std::io;
use std::io::ErrorKind;
use std::pin::Pin;
use std::task::Poll;
use thiserror::Error;
use tokio::io::AsyncReadExt;
use tokio::io::AsyncWriteExt;
use tokio::io::ReadBuf;
use tokio::{
io::{AsyncRead, AsyncWrite},
net::TcpStream,
};
const NOISE_HS_PATTERN: &str = "Noise_XKpsk3_25519_AESGCM_SHA256";
const MAXMSGLEN: usize = 65535;
const TAGLEN: usize = 16;
const HEADER_SIZE: usize = 2;
#[derive(Error, Debug)]
pub enum NoiseError {
#[error("encountered a Noise decryption error")]
DecryptionError,
#[error("encountered a Noise Protocol error - {0}")]
ProtocolError(Error),
#[error("encountered an IO error - {0}")]
IoError(#[from] io::Error),
}
impl From<Error> for NoiseError {
fn from(err: Error) -> Self {
match err {
Error::Decrypt => NoiseError::DecryptionError,
err => NoiseError::ProtocolError(err),
}
}
}
/// Wrapper around a TcpStream
#[pin_project]
pub struct NoiseStream {
#[pin]
inner_stream: TcpStream,
noise: TransportState,
enc_storage: VecDeque<u8>,
dec_storage: VecDeque<u8>,
}
impl NoiseStream {
fn new(inner_stream: TcpStream, noise: TransportState) -> NoiseStream {
NoiseStream {
inner_stream,
noise,
enc_storage: VecDeque::with_capacity(MAXMSGLEN + HEADER_SIZE),
dec_storage: VecDeque::with_capacity(MAXMSGLEN + HEADER_SIZE),
}
}
}
impl AsyncRead for NoiseStream {
fn poll_read(
self: Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
buf: &mut ReadBuf<'_>,
) -> Poll<std::io::Result<()>> {
let projected_self = self.project();
let enc_storage = projected_self.enc_storage;
let ready_to_read = projected_self.inner_stream.poll_read_ready(cx);
match ready_to_read {
Poll::Pending => {
//no new data, waking is already scheduled.
//Nothing new to decrypt, only check if we can return something from dec_storage, happens after
}
Poll::Ready(Ok(())) => {
//Read what we can into enc_storage, decrypt what we can into dec_storage
let mut tcp_buf = vec![0u8; MAXMSGLEN + HEADER_SIZE];
if let Ok(tcp_len) = projected_self.inner_stream.try_read(&mut tcp_buf) {
if tcp_len == 0 && projected_self.dec_storage.len() == 0 {
//EOF
return Poll::Ready(Ok(()));
}
enc_storage.extend(&tcp_buf[..tcp_len]);
//we can at least read the length
while enc_storage.len() >= HEADER_SIZE {
let msg_len = ((enc_storage[0] as usize) << 8) + (enc_storage[1] as usize);
//no more messages to read
if enc_storage.len() < HEADER_SIZE + msg_len {
break;
}
//we have a full message to decrypt
//remove size
enc_storage.pop_front();
enc_storage.pop_front();
let noise_msg = enc_storage.drain(..msg_len).collect::<Vec<u8>>();
let mut dec_msg = vec![0u8; MAXMSGLEN];
let len = match projected_self.noise.read_message(&noise_msg, &mut dec_msg)
{
Ok(len) => len,
Err(_) => return Poll::Ready(Err(ErrorKind::InvalidData.into())),
};
projected_self.dec_storage.extend(&dec_msg[..len]);
}
}
}
//an error occured, let's return it right away
Poll::Ready(Err(err)) => return Poll::Ready(Err(err)),
}
//check if we can return something
let read_len = min(buf.remaining(), projected_self.dec_storage.len());
if read_len > 0 {
buf.put_slice(
&projected_self
.dec_storage
.drain(..read_len)
.collect::<Vec<u8>>(),
);
return Poll::Ready(Ok(()));
}
//can't return anything, schedule the wakeup and return pending
match projected_self.inner_stream.poll_read_ready(cx) {
Poll::Ready(Ok(())) => {
//we got data in the meantime, we can wake up immediately
cx.waker().wake_by_ref();
}
_ => {}
}
Poll::Pending
}
}
impl AsyncWrite for NoiseStream {
fn poll_write(
self: Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
buf: &[u8],
) -> Poll<Result<usize, std::io::Error>> {
let projected_self = self.project();
let mut noise_buf = vec![0u8; MAXMSGLEN];
let len = match projected_self.noise.write_message(buf, &mut noise_buf) {
Ok(len) => len,
Err(_) => return Poll::Ready(Err(ErrorKind::InvalidInput.into())),
};
let to_send = [&[(len >> 8) as u8, (len & 0xff) as u8], &noise_buf[..len]].concat();
match projected_self.inner_stream.poll_write(cx, &to_send) {
Poll::Pending => return Poll::Pending,
Poll::Ready(Err(err)) => return Poll::Ready(Err(err)),
Poll::Ready(Ok(n)) => {
//didn't send a thing, no problem for the underlying stream
if n == 0 {
return Poll::Ready(Ok(0));
}
//we sent the whole thing, no problem for the underlying stream
//We must guarantee that the return number is <= buf.len()
if n == to_send.len() {
return Poll::Ready(Ok(n - HEADER_SIZE - TAGLEN));
}
//We didn't write the whole message, the stream will be corrupted
return Poll::Ready(Err(ErrorKind::WriteZero.into()));
}
}
}
fn poll_flush(
self: Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
) -> Poll<Result<(), std::io::Error>> {
self.project().inner_stream.poll_flush(cx)
}
fn poll_shutdown(
self: Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
) -> Poll<Result<(), std::io::Error>> {
self.project().inner_stream.poll_shutdown(cx)
}
}
pub async fn upgrade_noise_initiator(
mut conn: TcpStream,
local_public_key: Option<&[u8]>,
local_private_key: &[u8],
remote_pub_key: &[u8],
) -> Result<NoiseStream, NoiseError> {
trace!("Perform Noise Handshake, initiator side");
//In case the local key cannot be known by the remote party, e.g. in a client-gateway connection
let secret = [local_public_key.unwrap_or(&[]), remote_pub_key].concat();
let secret_hash = Sha256::digest(secret);
let builder = Builder::new(NOISE_HS_PATTERN.parse().unwrap()); //This cannot fail, hardcoded pattern must be correct
let mut handshake = builder
.local_private_key(local_private_key)
.remote_public_key(&remote_pub_key)
.psk(3, &secret_hash)
.build_initiator()?;
//Actual Handshake
let mut buf = vec![0u8; MAXMSGLEN];
// -> e, es
let len = handshake.write_message(&[], &mut buf)?;
send(&mut conn, &buf[..len]).await?;
// <- e, ee
handshake.read_message(&recv(&mut conn).await?, &mut buf)?;
// -> s, se, psk
let len = handshake.write_message(&[], &mut buf)?;
send(&mut conn, &buf[..len]).await?;
let noise = handshake.into_transport_mode()?;
Ok(NoiseStream::new(conn, noise))
}
pub async fn upgrade_noise_initiator_with_topology(
conn: TcpStream,
topology: &NymTopology,
local_public_key: &[u8],
local_private_key: &[u8],
) -> Result<NoiseStream, NoiseError> {
//Get init material
let responder_addr = match conn.peer_addr() {
Ok(addr) => addr,
Err(err) => {
error!("Unable to extract peer address from connection - {err}");
return Err(Error::Prereq(Prerequisite::RemotePublicKey).into());
}
};
let remote_pub_key = match topology.find_node_key_by_mix_host(responder_addr) {
Some(pub_key) => pub_key.to_bytes(),
None => {
error!(
"Cannot find public key for node with address {:?}",
responder_addr
);
return Err(Error::Prereq(Prerequisite::RemotePublicKey).into());
}
};
upgrade_noise_initiator(
conn,
Some(local_public_key),
local_private_key,
&remote_pub_key,
)
.await
}
pub async fn upgrade_noise_responder(
mut conn: TcpStream,
local_public_key: &[u8],
local_private_key: &[u8],
remote_pub_key: Option<&[u8]>,
) -> Result<NoiseStream, NoiseError> {
trace!("Perform Noise Handshake, responder side");
//If the remote_key cannot be kwnown, e.g. in a client-gateway connection
let secret = [&remote_pub_key.unwrap_or(&[]), local_public_key].concat();
let secret_hash = Sha256::digest(secret);
let builder = Builder::new(NOISE_HS_PATTERN.parse().unwrap()); //This cannot fail, hardcoded pattern must be correct
let mut handshake = builder
.local_private_key(local_private_key)
.psk(3, &secret_hash)
.build_responder()?;
//Actual Handshake
let mut buf = vec![0u8; MAXMSGLEN];
// <- e, es
handshake.read_message(&recv(&mut conn).await?, &mut buf)?;
// -> e, ee
let len = handshake.write_message(&[], &mut buf)?;
send(&mut conn, &buf[..len]).await?;
// <- s, se, psk
handshake.read_message(&recv(&mut conn).await?, &mut buf)?;
let noise = handshake.into_transport_mode()?;
Ok(NoiseStream::new(conn, noise))
}
pub async fn upgrade_noise_responder_with_topology(
conn: TcpStream,
topology: &NymTopology,
local_public_key: &[u8],
local_private_key: &[u8],
) -> Result<NoiseStream, NoiseError> {
//Get init material
let initiator_addr = match conn.peer_addr() {
Ok(addr) => addr,
Err(err) => {
error!("Unable to extract peer address from connection - {err}");
return Err(Error::Prereq(Prerequisite::RemotePublicKey).into());
}
};
let remote_pub_key = match topology.find_node_key_by_mix_host(initiator_addr) {
Some(pub_key) => pub_key.to_bytes(),
None => {
error!(
"Cannot find public key for node with address {:?}",
initiator_addr
);
return Err(Error::Prereq(Prerequisite::RemotePublicKey).into());
}
};
upgrade_noise_responder(
conn,
local_public_key,
local_private_key,
Some(&remote_pub_key),
)
.await
}
/// Hyper-basic stream transport receiver. 16-bit BE size followed by payload.
async fn recv(stream: &mut TcpStream) -> io::Result<Vec<u8>> {
let mut msg_len_buf = [0u8; HEADER_SIZE];
stream.read_exact(&mut msg_len_buf).await?;
let msg_len = ((msg_len_buf[0] as usize) << 8) + (msg_len_buf[1] as usize);
let mut msg = vec![0u8; msg_len];
stream.read_exact(&mut msg[..]).await?;
Ok(msg)
}
/// Hyper-basic stream transport sender. 16-bit BE size followed by payload.
async fn send(stream: &mut TcpStream, buf: &[u8]) -> io::Result<()> {
let msg_len_buf = [(buf.len() >> 8) as u8, (buf.len() & 0xff) as u8];
stream.write_all(&msg_len_buf).await?;
stream.write_all(buf).await?;
Ok(())
}
+1 -1
View File
@@ -67,7 +67,7 @@ impl Node {
}
pub fn clients_address(&self) -> String {
format!("ws://{}:{}", self.host, self.clients_port)
format!("{}:{}", self.host, self.clients_port)
}
}
+20
View File
@@ -3,6 +3,7 @@
use crate::filter::VersionFilterable;
use log::warn;
use nym_crypto::asymmetric::encryption;
use nym_mixnet_contract_common::mixnode::MixNodeDetails;
use nym_mixnet_contract_common::{GatewayBond, IdentityKeyRef, MixId};
use nym_sphinx_addressing::nodes::NodeIdentity;
@@ -107,6 +108,25 @@ impl NymTopology {
None
}
pub fn find_node_key_by_mix_host(
&self,
mix_host: SocketAddr,
) -> Option<&encryption::PublicKey> {
for node in self.gateways.iter() {
if node.mix_host.ip() == mix_host.ip() {
return Some(&node.sphinx_key);
}
}
for nodes in self.mixes.values() {
for node in nodes {
if node.mix_host.ip() == mix_host.ip() {
return Some(&node.sphinx_key);
}
}
}
None
}
pub fn find_gateway(&self, gateway_identity: IdentityKeyRef) -> Option<&gateway::Node> {
self.gateways
.iter()
+1 -1
View File
@@ -79,7 +79,7 @@ copy-fonts = true
no-section-label = false
additional-css = ["theme/pagetoc.css", "././mdbook-admonish.css", "last-changed.css"]
additional-js = ["theme/pagetoc.js"]
git-repository-url = "https://github.com/nymtech/dev-portal"
git-repository-url = "https://github.com/nymtech/nym"
git-repository-icon = "fa-github"
# edit-url-template = "https://github.com/rust-lang/mdBook/edit/master/guide/{path}"
site-url = "/developers/"
+7 -2
View File
@@ -14,6 +14,11 @@
- [SOCKS Proxy (CLI)](quickstart/socks-proxy.md)
- [NymConnect Beta (GUI)](quickstart/nymconnect-gui.md)
# User Manuals
- [NymConnect Monero](tutorials/monero.md)
- [NymConnect Matrix](tutorials/matrix.md)
# Integrations
- [Integration Options](integrations/integration-options.md)
@@ -39,10 +44,10 @@
- [Community Guides](community-resources/community-guides.md)
- [Change Service Grantee Information](info-request.md)
- [Rewards FAQ](community-resources/rewards-faq.md)
---
---
# Misc.
- [Glossary](glossary.md)
- [Code of Conduct](coc.md)
- [Licensing](licensing.md)
---
---
Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 314 KiB

@@ -0,0 +1,44 @@
# Matrix NymConnect Integration
Chat applications became an essential part of human communication. Matrix chat has end to end encryption on protocol level and Element app users can sort their communication into spaces and rooms. Now the Matrix communities can rely on network privacy as NymConnect supports Matrix chat protocol.
Currently there is no option in Matrix's Element client to set a socks5 proxy. In order to use Element via NymConnect users have to start it from the command-line. The setup is simple, for convenience a a keyboard shortcut setting can be easily done.
## Setup & Run
Make sure you have installed and started **[NymConnect](https://nymtech.net/developers/quickstart/nymconnect-gui.html)** on your desktop.
To then start Matrix's Element client via a Socks5 proxy connected to NymConnect, open terminal and run:
```sh
element-desktop --proxy-server=socks5://127.0.0.1:1080
```
## Optimise setup with a keybinding / alias
### Keybinding
An eloquent solution to avoid entering a command every time is to setup your keybinding. Open your settings, navigate to `Keyboard Shortcuts` and choose to `Set Custom Shortcut`. `Name` and `Shortcut` fields are up to your preference, to the `Command` line add:
```sh
element-desktop --proxy-server=socks5://127.0.0.1:1080
```
Make sure your `Shortcut` isn't already taken by something else in the menu.
An example can look like this.
![](../images/element_nym_keybind.png)
Alternatively you can add a keybinding via the CLI, using whatever config files you edit for your given desktop environment / window manager.
### Create an alias
If you prefer to simply shorten the length of the command (or all your keybindings are already taken) then you can simply create an alias for this long-winded command (this example aliases that command to the single word `element`, but you can replace it with whatever you like):
```sh
alias element="element-desktop --proxy-server=socks5://127.0.0.1:1080"
```
To make this alias persist, then add this to your `.bashrc` or `.zshrc` file (usually located in your `$HOME` directory) and `source` that file.
Now you can run Element throught the mixnet with a single-word command.
@@ -0,0 +1,42 @@
# Monero NymConnect Integration
*New Nym mixnet integration launched for Monero desktop to secure the right to financial privacy and censorship-resistance*
![](../images/monero_tutorial/monero.png)
Financial privacy is an important component of digital currencies and the use of Nym will provide users with the highest level of privacy at the infrastructure level. All users of digital currencies should be afforded equal rights to protection from financial surveillance.
A team made up of Monero community members have successfully set up a service provider to use Monero (using the Monero desktop wallet) over the Nym mixnet. This allows Monero users to easily use NymConnect to run Monero over the mixnet, thereby enhancing the privacy of Monero transactions.
## How can I use Monero over the Nym mixnet?
The mainnet service provider to Monero over the Nym mixnet is now ready for use via [NymConnect](https://nymtech.net/download-nymconnect/).
* Download and open the latest version of [NymConnect](https://nymtech.net/download-nymconnect/).
* Click on the top left options and go to Settings
* Go to “Select service provider” and turn it on
* For Mainnet, search for this provider or insert it manually:
```sh
i1TiuoNp4jp9weffCW7tPnkb4hRTPydRjX8iXFVaYDG.88Z1hruuvbzWpdCE2xYnTbPNrr49j4s7mmUQC5wvRRLZ@3EPuxwGn2WP2HdxybzoDa5QsohYSP76aQQRUJuPMvk23
```
* Go to the main NymConnect interface and connect to the mixnet
Then go to your Monero wallet (gui or otherwise) and change the settings to run over socks5 proxy:
**Monero desktop:**
* Settings -> Interface -> Socks5 proxy -> Add values: IP address `localhost`, Port `1080`
<iframe width="700" height="400" src="https://www.youtube.com/embed/oSHnk1BG_f0" title="Demo: Connect Your Monero Wallet to the Nym Mixnet via NymConnect" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
**CLI**
* **Monerod:** add `--proxy 127.0.0.1:1080 --bootstrap-daemon-proxy 127.0.0.1:1080` to args
* **Monero-wallet-{rpc, cli}:** add `--proxy 127.0.0.1:1080 --daemon-ssl-allow-any-cert` to args
Follow the instructions and the Monero mainnet will be connected through to the Nym mixnet.
For those who want to try it out in testnet, a stagenet service provider is also available: [https://nymtech.net/.wellknown/connect/service-providers.json](https://nymtech.net/.wellknown/connect/service-providers.json)
+4 -4
View File
@@ -48,9 +48,9 @@ assets_version = "2.0.0" # do not edit: managed by `mdbook-admonish install`
# https://gitlab.com/tglman/mdbook-variables/
[preprocessor.variables.variables]
minimum_rust_version = "1.66"
# old variables - this is still needed for links.. TODO change to develop?
platform_release_version = "v1.1.21"
# vars for links: TODO think on how to streamline updating
platform_release_version = "v1.1.22"
wallet_release_version = "v1.2.5"
[preprocessor.last-changed]
command = "mdbook-last-changed"
@@ -87,7 +87,7 @@ copy-fonts = true
no-section-label = false
additional-css = ["theme/pagetoc.css", "././mdbook-admonish.css", "last-changed.css"]
additional-js = ["theme/pagetoc.js"]
git-repository-url = "https://github.com/nymtech/docs"
git-repository-url = "https://github.com/nymtech/nym"
git-repository-icon = "fa-github"
# edit-url-template = "https://github.com/rust-lang/mdBook/edit/master/guide/{path}"
# site-url = "/docs/"
@@ -593,10 +593,19 @@ nyxd tx slashing unjail
### Upgrading your validator
Upgrading from `v0.26.0` -> `v0.31.1` doesn't require many modifications, simply grab a binary from the [`nyxd` releases page](https://github.com/nymtech/nyxd/releases) and once the chain has halted at the decided upon haltheight, stop your `nyxd` process, replace your binaries, and restart your process.
Upgrading from `v0.26.0` -> `v0.31.1` process is fairly simple. Grab the v0.31.1 release tarball from the [`nyxd` releases page](https://github.com/nymtech/nyxd/releases), and untar it. Inside are two files:
- the new validator (`nyxd`) v0.31.1
- the new wasmvm (it depends on your platform, but most common filename is `libwasmvm.x86_64.so`)
Before the upgrade height, copy `libwasmvm.x86_64.so` to the default LD_LIBRARY_PATH on your system (on Ubuntu 20.04 this is `/lib/x86_64-linux-gnu/`):
Then just swap in your new `nyxd` binary and restart once the halt height is reached.
You can also use something like [Cosmovisor](https://github.com/cosmos/cosmos-sdk/tree/main/tools/cosmovisor) - grab the relevant information from the current upgrade proposal [here](https://nym.explorers.guru/proposal/8).
Note: Cosmovisor will swap the `nyxd` binary, but you'll need to already have the `libwasmvm.x86_64.so` in place. Luckily, the name of the wasmvm in v0.26.1 was `libwasmvm.so`, and the new name is `libwasmvm.x86_64.so`, so you can have it already sitting there without disrupting service.
#### Common reasons for your validator being jailed
The most common reason for your validator being jailed is that your validator is out of memory because of bloated syslogs.
+1 -1
View File
@@ -1 +1 @@
16
18
+3
View File
@@ -61,6 +61,9 @@ nym-statistics-common = { path = "../common/statistics" }
nym-task = { path = "../common/task" }
nym-types = { path = "../common/types" }
nym-validator-client = { path = "../common/client-libs/validator-client", features = [ "nyxd-client" ] }
nym-client-core = { path = "../common/client-core" }
nym-topology = { path = "../common/topology" }
nym-noise = { path = "../common/nymnoise" }
[build-dependencies]
tokio = { version = "1.24.1", features = ["rt-multi-thread", "macros"] }
+37
View File
@@ -33,6 +33,9 @@ const DEFAULT_PACKET_FORWARDING_MAXIMUM_BACKOFF: Duration = Duration::from_milli
const DEFAULT_INITIAL_CONNECTION_TIMEOUT: Duration = Duration::from_millis(1_500);
const DEFAULT_MAXIMUM_CONNECTION_BUFFER_SIZE: usize = 2000;
const DEFAULT_TOPOLOGY_REFRESH_RATE: Duration = Duration::from_secs(5 * 60); // every 5min
const DEFAULT_TOPOLOGY_RESOLUTION_TIMEOUT: Duration = Duration::from_millis(5_000);
const DEFAULT_STORED_MESSAGE_FILENAME_LENGTH: u16 = 16;
const DEFAULT_MESSAGE_RETRIEVAL_LIMIT: i64 = 100;
@@ -74,6 +77,9 @@ pub struct Config {
#[serde(default)]
pub debug: Debug,
#[serde(default)]
pub topology: Topology,
}
impl NymConfigTemplate for Config {
@@ -89,6 +95,7 @@ impl Config {
storage_paths: GatewayPaths::new_default(id.as_ref()),
logging: Default::default(),
debug: Default::default(),
topology: Default::default(),
}
}
@@ -302,3 +309,33 @@ impl Default for Debug {
}
}
}
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct Topology {
/// The uniform delay every which clients are querying the directory server
/// to try to obtain a compatible network topology to send sphinx packets through.
#[serde(with = "humantime_serde")]
pub topology_refresh_rate: Duration,
/// During topology refresh, test packets are sent through every single possible network
/// path. This timeout determines waiting period until it is decided that the packet
/// did not reach its destination.
#[serde(with = "humantime_serde")]
pub topology_resolution_timeout: Duration,
/// Specifies whether the client should not refresh the network topology after obtaining
/// the first valid instance.
/// Supersedes `topology_refresh_rate_ms`.
pub disable_refreshing: bool,
}
impl Default for Topology {
fn default() -> Self {
Topology {
topology_refresh_rate: DEFAULT_TOPOLOGY_REFRESH_RATE,
topology_resolution_timeout: DEFAULT_TOPOLOGY_RESOLUTION_TIMEOUT,
disable_refreshing: false,
}
}
}
+1
View File
@@ -69,6 +69,7 @@ impl From<ConfigV1_1_20> for Config {
},
logging: value.logging.into(),
debug: value.debug.into(),
topology: Default::default(),
}
}
}
@@ -6,8 +6,9 @@ use crate::node::client_handling::websocket::connection_handler::coconut::Coconu
use crate::node::client_handling::websocket::connection_handler::FreshHandler;
use crate::node::storage::Storage;
use log::*;
use nym_crypto::asymmetric::identity;
use nym_crypto::asymmetric::{encryption, identity};
use nym_mixnet_client::forwarder::MixForwardingSender;
use nym_noise::upgrade_noise_responder;
use rand::rngs::OsRng;
use std::net::SocketAddr;
use std::process;
@@ -17,6 +18,7 @@ use tokio::task::JoinHandle;
pub(crate) struct Listener {
address: SocketAddr,
local_identity: Arc<identity::KeyPair>,
local_sphinx: Arc<encryption::KeyPair>,
only_coconut_credentials: bool,
pub(crate) coconut_verifier: Arc<CoconutVerifier>,
}
@@ -25,12 +27,14 @@ impl Listener {
pub(crate) fn new(
address: SocketAddr,
local_identity: Arc<identity::KeyPair>,
local_sphinx: Arc<encryption::KeyPair>,
only_coconut_credentials: bool,
coconut_verifier: Arc<CoconutVerifier>,
) -> Self {
Listener {
address,
local_identity,
local_sphinx,
only_coconut_credentials,
coconut_verifier,
}
@@ -68,9 +72,23 @@ impl Listener {
trace!("received a socket connection from {remote_addr}");
// TODO: I think we *REALLY* need a mechanism for having a maximum number of connected
// clients or spawned tokio tasks -> perhaps a worker system?
let noise_stream = match upgrade_noise_responder(
socket,
&self.local_sphinx.public_key().to_bytes(),
&self.local_sphinx.private_key().to_bytes(),
None, //connection from client, no remote pub key
)
.await
{
Ok(noise_stream) => noise_stream,
Err(err) => {
error!("Failed to perform Noise handshake with {remote_addr} - {err}");
return;
}
};
let handle = FreshHandler::new(
OsRng,
socket,
noise_stream,
self.only_coconut_credentials,
outbound_mix_sender.clone(),
Arc::clone(&self.local_identity),
@@ -8,8 +8,11 @@ use crate::node::storage::error::StorageError;
use crate::node::storage::Storage;
use futures::StreamExt;
use log::*;
use nym_client_core::client::topology_control::accessor::TopologyAccessor;
use nym_crypto::asymmetric::encryption;
use nym_mixnet_client::forwarder::MixForwardingSender;
use nym_mixnode_common::packet_processor::processor::ProcessedFinalHop;
use nym_noise::upgrade_noise_responder_with_topology;
use nym_sphinx::forwarding::packet::MixPacket;
use nym_sphinx::framing::codec::NymCodec;
use nym_sphinx::framing::packet::FramedNymPacket;
@@ -17,6 +20,7 @@ use nym_sphinx::DestinationAddressBytes;
use nym_task::TaskClient;
use std::collections::HashMap;
use std::net::SocketAddr;
use std::sync::Arc;
use tokio::net::TcpStream;
use tokio_util::codec::Framed;
@@ -31,6 +35,8 @@ pub(crate) struct ConnectionHandler<St: Storage> {
active_clients_store: ActiveClientsStore,
storage: St,
ack_sender: MixForwardingSender,
topology_access: TopologyAccessor,
local_identity: Arc<encryption::KeyPair>,
}
impl<St: Storage + Clone> Clone for ConnectionHandler<St> {
@@ -49,6 +55,8 @@ impl<St: Storage + Clone> Clone for ConnectionHandler<St> {
active_clients_store: self.active_clients_store.clone(),
storage: self.storage.clone(),
ack_sender: self.ack_sender.clone(),
topology_access: self.topology_access.clone(),
local_identity: self.local_identity.clone(),
}
}
}
@@ -59,6 +67,8 @@ impl<St: Storage> ConnectionHandler<St> {
storage: St,
ack_sender: MixForwardingSender,
active_clients_store: ActiveClientsStore,
topology_access: TopologyAccessor,
local_identity: Arc<encryption::KeyPair>,
) -> Self {
ConnectionHandler {
packet_processor,
@@ -66,6 +76,8 @@ impl<St: Storage> ConnectionHandler<St> {
storage,
active_clients_store,
ack_sender,
topology_access,
local_identity,
}
}
@@ -182,7 +194,33 @@ impl<St: Storage> ConnectionHandler<St> {
) {
debug!("Starting connection handler for {:?}", remote);
shutdown.mark_as_success();
let mut framed_conn = Framed::new(conn, NymCodec);
let topology_access_clonne = self.topology_access.clone();
let topology_permit = topology_access_clonne.get_read_permit().await;
let topology_ref = match topology_permit.try_get_raw_topology_ref() {
Ok(topology) => topology,
Err(err) => {
error!("Cannot connect to {remote}, due to topology error - {err}");
return;
}
};
let noise_stream = match upgrade_noise_responder_with_topology(
conn,
topology_ref,
&self.local_identity.public_key().to_bytes(),
&self.local_identity.private_key().to_bytes(),
)
.await
{
Ok(noise_stream) => noise_stream,
Err(err) => {
error!("Failed to perform Noise handshake with {remote} - {err}");
return;
}
};
debug!("Noise responder handshake completed for {:?}", remote);
let mut framed_conn = Framed::new(noise_stream, NymCodec);
while !shutdown.is_shutdown() {
tokio::select! {
biased;
@@ -212,9 +250,6 @@ impl<St: Storage> ConnectionHandler<St> {
}
}
info!(
"Closing connection from {:?}",
framed_conn.into_inner().peer_addr()
);
info!("Closing connection from {:?}", remote);
}
}
+73 -3
View File
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
use self::storage::PersistentStorage;
use crate::config::Config;
use crate::config::{Config, Topology};
use crate::error::GatewayError;
use crate::node::client_handling::active_clients::ActiveClientsStore;
use crate::node::client_handling::websocket;
@@ -12,17 +12,23 @@ use crate::node::statistics::collector::GatewayStatisticsCollector;
use crate::node::storage::Storage;
use log::*;
use nym_bin_common::output_format::OutputFormat;
use nym_client_core::client::topology_control::accessor::TopologyAccessor;
use nym_client_core::client::topology_control::nym_api_provider::NymApiTopologyProvider;
use nym_client_core::client::topology_control::TopologyRefresher;
use nym_client_core::client::topology_control::TopologyRefresherConfig;
use nym_crypto::asymmetric::{encryption, identity};
use nym_mixnet_client::forwarder::{MixForwardingSender, PacketForwarder};
use nym_network_defaults::NymNetworkDetails;
use nym_statistics_common::collector::StatisticsSender;
use nym_task::{TaskClient, TaskManager};
use nym_topology::provider_trait::TopologyProvider;
use nym_validator_client::Client;
use rand::seq::SliceRandom;
use rand::thread_rng;
use std::error::Error;
use std::net::SocketAddr;
use std::sync::Arc;
use url::Url;
pub(crate) mod client_handling;
pub(crate) mod mixnet_handling;
@@ -124,6 +130,7 @@ impl<St> Gateway<St> {
&self,
ack_sender: MixForwardingSender,
active_clients_store: ActiveClientsStore,
topology_access: TopologyAccessor,
shutdown: TaskClient,
) where
St: Storage + Clone + 'static,
@@ -138,6 +145,8 @@ impl<St> Gateway<St> {
self.storage.clone(),
ack_sender,
active_clients_store,
topology_access,
Arc::clone(&self.sphinx_keypair),
);
let listening_address = SocketAddr::new(
@@ -167,6 +176,7 @@ impl<St> Gateway<St> {
websocket::Listener::new(
listening_address,
Arc::clone(&self.identity_keypair),
Arc::clone(&self.sphinx_keypair),
self.config.gateway.only_coconut_credentials,
coconut_verifier,
)
@@ -178,7 +188,11 @@ impl<St> Gateway<St> {
);
}
fn start_packet_forwarder(&self, shutdown: TaskClient) -> MixForwardingSender {
fn start_packet_forwarder(
&self,
topology_access: TopologyAccessor,
shutdown: TaskClient,
) -> MixForwardingSender {
info!("Starting mix packet forwarder...");
let (mut packet_forwarder, packet_sender) = PacketForwarder::new(
@@ -187,6 +201,8 @@ impl<St> Gateway<St> {
self.config.debug.initial_connection_timeout,
self.config.debug.maximum_connection_buffer_size,
self.config.debug.use_legacy_framed_packet_version,
topology_access,
Arc::clone(&self.sphinx_keypair),
shutdown,
);
@@ -234,6 +250,47 @@ impl<St> Gateway<St> {
client
}
fn setup_topology_provider(nym_api_urls: Vec<Url>) -> Box<dyn TopologyProvider + Send + Sync> {
// if no custom provider was ... provided ..., create one using nym-api
Box::new(NymApiTopologyProvider::new(
nym_api_urls,
env!("CARGO_PKG_VERSION").to_string(),
))
}
// future responsible for periodically polling directory server and updating
// the current global view of topology
async fn start_topology_refresher(
topology_provider: Box<dyn TopologyProvider + Send + Sync>,
topology_config: Topology,
topology_accessor: TopologyAccessor,
mut shutdown: TaskClient,
) {
let topology_refresher_config =
TopologyRefresherConfig::new(topology_config.topology_refresh_rate);
let mut topology_refresher = TopologyRefresher::new(
topology_refresher_config,
topology_accessor,
topology_provider,
);
// before returning, block entire runtime to refresh the current network view so that any
// components depending on topology would see a non-empty view
info!("Obtaining initial network topology");
topology_refresher.try_refresh().await;
if topology_config.disable_refreshing {
// if we're not spawning the refresher, don't cause shutdown immediately
info!("The topology refesher is not going to be started");
shutdown.mark_as_success();
} else {
// don't spawn the refresher if we don't want to be refreshing the topology.
// only use the initial values obtained
info!("Starting topology refresher...");
topology_refresher.start_with_shutdown(shutdown);
}
}
async fn check_if_bonded(&self) -> Result<bool, GatewayError> {
// TODO: if anything, this should be getting data directly from the contract
// as opposed to the validator API
@@ -268,12 +325,25 @@ impl<St> Gateway<St> {
CoconutVerifier::new(nyxd_client)
};
let mix_forwarding_channel = self.start_packet_forwarder(shutdown.subscribe());
let topology_provider = Self::setup_topology_provider(self.config.get_nym_api_endpoints());
let shared_topology_access = TopologyAccessor::new();
Self::start_topology_refresher(
topology_provider,
self.config.topology,
shared_topology_access.clone(),
shutdown.subscribe(),
)
.await;
let mix_forwarding_channel =
self.start_packet_forwarder(shared_topology_access.clone(), shutdown.subscribe());
let active_clients_store = ActiveClientsStore::new();
self.start_mix_socket_listener(
mix_forwarding_channel.clone(),
active_clients_store.clone(),
shared_topology_access,
shutdown.subscribe(),
);
+2 -8
View File
@@ -1,10 +1,4 @@
{
"packages": [
"ts-packages/*",
"nym-wallet",
"nym-connect/**",
"sdk/typescript/examples/docs",
"sdk/typescript/packages/**"
],
"version": "0.0.0"
"version": "0.0.0",
"useWorkspaces": true
}
+2
View File
@@ -56,9 +56,11 @@ nym-pemstore = { path = "../common/pemstore", version = "0.3.0" }
nym-task = { path = "../common/task" }
nym-types = { path = "../common/types" }
nym-topology = { path = "../common/topology" }
nym-client-core = { path = "../common/client-core/" }
nym-validator-client = { path = "../common/client-libs/validator-client" }
nym-bin-common = { path = "../common/bin-common", features = ["output_format"] }
cpu-cycles = { path = "../cpu-cycles", optional = true }
nym-noise = { path = "../common/nymnoise" }
[dev-dependencies]
tokio = { version = "1.21.2", features = [
+37
View File
@@ -44,6 +44,9 @@ const DEFAULT_PACKET_FORWARDING_MAXIMUM_BACKOFF: Duration = Duration::from_milli
const DEFAULT_INITIAL_CONNECTION_TIMEOUT: Duration = Duration::from_millis(1_500);
const DEFAULT_MAXIMUM_CONNECTION_BUFFER_SIZE: usize = 2000;
const DEFAULT_TOPOLOGY_REFRESH_RATE: Duration = Duration::from_secs(5 * 60); // every 5min
const DEFAULT_TOPOLOGY_RESOLUTION_TIMEOUT: Duration = Duration::from_millis(5_000);
/// Derive default path to mixnodes's config directory.
/// It should get resolved to `$HOME/.nym/mixnodes/<id>/config`
pub fn default_config_directory<P: AsRef<Path>>(id: P) -> PathBuf {
@@ -85,6 +88,9 @@ pub struct Config {
#[serde(default)]
pub debug: Debug,
#[serde(default)]
pub topology: Topology,
}
impl NymConfigTemplate for Config {
@@ -101,6 +107,7 @@ impl Config {
verloc: Default::default(),
logging: Default::default(),
debug: Default::default(),
topology: Default::default(),
}
}
@@ -292,3 +299,33 @@ impl Default for Debug {
}
}
}
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct Topology {
/// The uniform delay every which clients are querying the directory server
/// to try to obtain a compatible network topology to send sphinx packets through.
#[serde(with = "humantime_serde")]
pub topology_refresh_rate: Duration,
/// During topology refresh, test packets are sent through every single possible network
/// path. This timeout determines waiting period until it is decided that the packet
/// did not reach its destination.
#[serde(with = "humantime_serde")]
pub topology_resolution_timeout: Duration,
/// Specifies whether the client should not refresh the network topology after obtaining
/// the first valid instance.
/// Supersedes `topology_refresh_rate_ms`.
pub disable_refreshing: bool,
}
impl Default for Topology {
fn default() -> Self {
Topology {
topology_refresh_rate: DEFAULT_TOPOLOGY_REFRESH_RATE,
topology_resolution_timeout: DEFAULT_TOPOLOGY_RESOLUTION_TIMEOUT,
disable_refreshing: false,
}
}
}
+1
View File
@@ -94,6 +94,7 @@ impl From<ConfigV1_1_21> for Config {
verloc: value.verloc.into(),
logging: value.logging.into(),
debug: value.debug.into(),
topology: Default::default(),
}
}
}
@@ -7,12 +7,16 @@ use crate::node::listener::connection_handler::packet_processing::{
use crate::node::packet_delayforwarder::PacketDelayForwardSender;
use crate::node::TaskClient;
use futures::StreamExt;
use nym_client_core::client::topology_control::accessor::TopologyAccessor;
use nym_crypto::asymmetric::encryption;
use nym_mixnode_common::measure;
use nym_noise::upgrade_noise_responder_with_topology;
use nym_sphinx::forwarding::packet::MixPacket;
use nym_sphinx::framing::codec::NymCodec;
use nym_sphinx::framing::packet::FramedNymPacket;
use nym_sphinx::Delay as SphinxDelay;
use std::net::SocketAddr;
use std::sync::Arc;
use tokio::net::TcpStream;
use tokio::time::Instant;
use tokio_util::codec::Framed;
@@ -25,16 +29,22 @@ pub(crate) mod packet_processing;
pub(crate) struct ConnectionHandler {
packet_processor: PacketProcessor,
delay_forwarding_channel: PacketDelayForwardSender,
topology_access: TopologyAccessor,
local_identity: Arc<encryption::KeyPair>,
}
impl ConnectionHandler {
pub(crate) fn new(
packet_processor: PacketProcessor,
delay_forwarding_channel: PacketDelayForwardSender,
topology_access: TopologyAccessor,
local_identity: Arc<encryption::KeyPair>,
) -> Self {
ConnectionHandler {
packet_processor,
delay_forwarding_channel,
topology_access,
local_identity,
}
}
@@ -85,8 +95,34 @@ impl ConnectionHandler {
mut shutdown: TaskClient,
) {
debug!("Starting connection handler for {:?}", remote);
shutdown.mark_as_success();
let mut framed_conn = Framed::new(conn, NymCodec);
let topology_permit = self.topology_access.get_read_permit().await;
let topology_ref = match topology_permit.try_get_raw_topology_ref() {
Ok(topology) => topology,
Err(err) => {
error!("Cannot connect to {remote}, due to topology error - {err}");
return;
}
};
let noise_stream = match upgrade_noise_responder_with_topology(
conn,
topology_ref,
&self.local_identity.public_key().to_bytes(),
&self.local_identity.private_key().to_bytes(),
)
.await
{
Ok(noise_stream) => noise_stream,
Err(err) => {
error!("Failed to perform Noise handshake with {remote} - {err}");
return;
}
};
debug!("Noise responder handshake completed for {:?}", remote);
let mut framed_conn = Framed::new(noise_stream, NymCodec);
while !shutdown.is_shutdown() {
tokio::select! {
biased;
@@ -118,10 +154,7 @@ impl ConnectionHandler {
}
}
info!(
"Closing connection from {:?}",
framed_conn.into_inner().peer_addr()
);
info!("Closing connection from {:?}", remote);
log::trace!("ConnectionHandler: Exiting");
}
}
+79 -5
View File
@@ -1,7 +1,7 @@
// Copyright 2020-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::config::Config;
use crate::config::{Config, Topology};
use crate::node::http::{
description::description,
hardware::hardware,
@@ -17,14 +17,20 @@ use crate::node::node_statistics::SharedNodeStats;
use crate::node::packet_delayforwarder::{DelayForwarder, PacketDelayForwardSender};
use nym_bin_common::output_format::OutputFormat;
use nym_bin_common::version_checker::parse_version;
use nym_client_core::client::topology_control::accessor::TopologyAccessor;
use nym_client_core::client::topology_control::nym_api_provider::NymApiTopologyProvider;
use nym_client_core::client::topology_control::TopologyRefresher;
use nym_client_core::client::topology_control::TopologyRefresherConfig;
use nym_crypto::asymmetric::{encryption, identity};
use nym_mixnode_common::verloc::{self, AtomicVerlocResult, VerlocMeasurer};
use nym_task::{TaskClient, TaskManager};
use nym_topology::provider_trait::TopologyProvider;
use rand::seq::SliceRandom;
use rand::thread_rng;
use std::net::SocketAddr;
use std::process;
use std::sync::Arc;
use url::Url;
#[cfg(feature = "cpucycles")]
use tracing::{error, info, warn};
@@ -146,6 +152,7 @@ impl MixNode {
&self,
node_stats_update_sender: node_statistics::UpdateSender,
delay_forwarding_channel: PacketDelayForwardSender,
topology_access: TopologyAccessor,
shutdown: TaskClient,
) {
info!("Starting socket listener...");
@@ -153,7 +160,12 @@ impl MixNode {
let packet_processor =
PacketProcessor::new(self.sphinx_keypair.private_key(), node_stats_update_sender);
let connection_handler = ConnectionHandler::new(packet_processor, delay_forwarding_channel);
let connection_handler = ConnectionHandler::new(
packet_processor,
delay_forwarding_channel,
topology_access,
Arc::clone(&self.sphinx_keypair),
);
let listening_address = SocketAddr::new(
self.config.mixnode.listening_address,
@@ -166,6 +178,7 @@ impl MixNode {
fn start_packet_delay_forwarder(
&mut self,
node_stats_update_sender: node_statistics::UpdateSender,
topology_access: TopologyAccessor,
shutdown: TaskClient,
) -> PacketDelayForwardSender {
info!("Starting packet delay-forwarder...");
@@ -179,7 +192,11 @@ impl MixNode {
);
let mut packet_forwarder = DelayForwarder::new(
nym_mixnet_client::Client::new(client_config),
nym_mixnet_client::Client::new(
client_config,
topology_access,
Arc::clone(&self.sphinx_keypair),
),
node_stats_update_sender,
shutdown,
);
@@ -230,6 +247,47 @@ impl MixNode {
atomic_verloc_results
}
fn setup_topology_provider(nym_api_urls: Vec<Url>) -> Box<dyn TopologyProvider + Send + Sync> {
// if no custom provider was ... provided ..., create one using nym-api
Box::new(NymApiTopologyProvider::new(
nym_api_urls,
env!("CARGO_PKG_VERSION").to_string(),
))
}
// future responsible for periodically polling directory server and updating
// the current global view of topology
async fn start_topology_refresher(
topology_provider: Box<dyn TopologyProvider + Send + Sync>,
topology_config: Topology,
topology_accessor: TopologyAccessor,
mut shutdown: TaskClient,
) {
let topology_refresher_config =
TopologyRefresherConfig::new(topology_config.topology_refresh_rate);
let mut topology_refresher = TopologyRefresher::new(
topology_refresher_config,
topology_accessor,
topology_provider,
);
// before returning, block entire runtime to refresh the current network view so that any
// components depending on topology would see a non-empty view
info!("Obtaining initial network topology");
topology_refresher.try_refresh().await;
if topology_config.disable_refreshing {
// if we're not spawning the refresher, don't cause shutdown immediately
info!("The topology refesher is not going to be started");
shutdown.mark_as_success();
} else {
// don't spawn the refresher if we don't want to be refreshing the topology.
// only use the initial values obtained
info!("Starting topology refresher...");
topology_refresher.start_with_shutdown(shutdown);
}
}
fn random_api_client(&self) -> nym_validator_client::NymApiClient {
let endpoints = self.config.get_nym_api_endpoints();
let nym_api = endpoints
@@ -276,11 +334,27 @@ impl MixNode {
let (node_stats_pointer, node_stats_update_sender) =
self.start_node_stats_controller(shutdown.subscribe());
let delay_forwarding_channel = self
.start_packet_delay_forwarder(node_stats_update_sender.clone(), shutdown.subscribe());
let topology_provider = Self::setup_topology_provider(self.config.get_nym_api_endpoints());
let shared_topology_access = TopologyAccessor::new();
Self::start_topology_refresher(
topology_provider,
self.config.topology,
shared_topology_access.clone(),
shutdown.subscribe(),
)
.await;
let delay_forwarding_channel = self.start_packet_delay_forwarder(
node_stats_update_sender.clone(),
shared_topology_access.clone(),
shutdown.subscribe(),
);
self.start_socket_listener(
node_stats_update_sender,
delay_forwarding_channel,
shared_topology_access,
shutdown.subscribe(),
);
let atomic_verloc_results = self.start_verloc_measurements(shutdown.subscribe());
+3
View File
@@ -105,6 +105,7 @@ impl<'a> NetworkMonitorBuilder<'a> {
self.config,
gateway_status_update_sender,
Arc::clone(&identity_keypair),
Arc::clone(&encryption_keypair),
self.config.debug.gateway_sending_rate,
bandwidth_controller,
self.config.debug.disabled_credentials_mode,
@@ -177,6 +178,7 @@ fn new_packet_sender(
config: &config::NetworkMonitor,
gateways_status_updater: GatewayClientUpdateSender,
local_identity: Arc<identity::KeyPair>,
local_sphinx: Arc<encryption::KeyPair>,
max_sending_rate: usize,
bandwidth_controller: BandwidthController<nyxd::Client, PersistentStorage>,
disabled_credentials_mode: bool,
@@ -184,6 +186,7 @@ fn new_packet_sender(
PacketSender::new(
gateways_status_updater,
local_identity,
local_sphinx,
config.debug.gateway_response_timeout,
config.debug.gateway_connection_timeout,
config.debug.max_concurrent_gateway_clients,
@@ -310,6 +310,7 @@ impl PacketPreparer {
GatewayPackets::new(
route.gateway_clients_address(),
route.gateway_identity(),
route.gateway_sphinx(),
mix_packets,
)
}
@@ -387,6 +388,7 @@ impl PacketPreparer {
let route_ext = test_route.test_message_ext(test_nonce);
let gateway_address = test_route.gateway_clients_address();
let gateway_identity = test_route.gateway_identity();
let gateway_sphinx = test_route.gateway_sphinx();
let mut mix_tester = self.ephemeral_mix_tester(test_route);
@@ -408,7 +410,9 @@ impl PacketPreparer {
let gateway_packets = all_gateway_packets
.entry(gateway_identity.to_bytes())
.or_insert_with(|| GatewayPackets::empty(gateway_address, gateway_identity));
.or_insert_with(|| {
GatewayPackets::empty(gateway_address, gateway_identity, gateway_sphinx)
});
gateway_packets.push_packets(mix_packets);
// and generate test packets for gateways (note the variable recipient)
@@ -436,7 +440,9 @@ impl PacketPreparer {
// or create a new one
let gateway_packets = all_gateway_packets
.entry(gateway_identity.to_bytes())
.or_insert_with(|| GatewayPackets::empty(gateway_address, gateway_identity));
.or_insert_with(|| {
GatewayPackets::empty(gateway_address, gateway_identity, gateway_sphinx)
});
gateway_packets.push_packets(gateway_mix_packets);
}
}
+20 -2
View File
@@ -15,6 +15,7 @@ use log::{debug, info, trace, warn};
use nym_bandwidth_controller::BandwidthController;
use nym_config::defaults::REMAINING_BANDWIDTH_THRESHOLD;
use nym_credential_storage::persistent_storage::PersistentStorage;
use nym_crypto::asymmetric::encryption;
use nym_crypto::asymmetric::identity::{self, PUBLIC_KEY_LENGTH};
use nym_gateway_client::error::GatewayClientError;
use nym_gateway_client::{AcknowledgementReceiver, GatewayClient, MixnetMessageReceiver};
@@ -38,6 +39,8 @@ pub(crate) struct GatewayPackets {
/// Public key of the target gateway.
pub(crate) pub_key: identity::PublicKey,
pub(crate) encryption_key: encryption::PublicKey,
/// All the packets that are going to get sent to the gateway.
pub(crate) packets: Vec<MixPacket>,
}
@@ -46,19 +49,26 @@ impl GatewayPackets {
pub(crate) fn new(
clients_address: String,
pub_key: identity::PublicKey,
encryption_key: encryption::PublicKey,
packets: Vec<MixPacket>,
) -> Self {
GatewayPackets {
clients_address,
pub_key,
encryption_key,
packets,
}
}
pub(crate) fn empty(clients_address: String, pub_key: identity::PublicKey) -> Self {
pub(crate) fn empty(
clients_address: String,
pub_key: identity::PublicKey,
encryption_key: encryption::PublicKey,
) -> Self {
GatewayPackets {
clients_address,
pub_key,
encryption_key,
packets: Vec::new(),
}
}
@@ -79,6 +89,7 @@ impl GatewayPackets {
struct FreshGatewayClientData {
gateways_status_updater: GatewayClientUpdateSender,
local_identity: Arc<identity::KeyPair>,
local_sphinx: Arc<encryption::KeyPair>,
gateway_response_timeout: Duration,
bandwidth_controller: BandwidthController<nyxd::Client, PersistentStorage>,
disabled_credentials_mode: bool,
@@ -134,6 +145,7 @@ impl PacketSender {
pub(crate) fn new(
gateways_status_updater: GatewayClientUpdateSender,
local_identity: Arc<identity::KeyPair>,
local_sphinx: Arc<encryption::KeyPair>,
gateway_response_timeout: Duration,
gateway_connection_timeout: Duration,
max_concurrent_clients: usize,
@@ -146,6 +158,7 @@ impl PacketSender {
fresh_gateway_client_data: Arc::new(FreshGatewayClientData {
gateways_status_updater,
local_identity,
local_sphinx,
gateway_response_timeout,
bandwidth_controller,
disabled_credentials_mode,
@@ -171,6 +184,7 @@ impl PacketSender {
fn new_gateway_client_handle(
address: String,
identity: identity::PublicKey,
sphinx: encryption::PublicKey,
fresh_gateway_client_data: &FreshGatewayClientData,
) -> (
GatewayClientHandle,
@@ -187,7 +201,9 @@ impl PacketSender {
let mut gateway_client = GatewayClient::new(
address,
Arc::clone(&fresh_gateway_client_data.local_identity),
Arc::clone(&fresh_gateway_client_data.local_sphinx),
identity,
sphinx,
None,
message_sender,
ack_sender,
@@ -267,6 +283,7 @@ impl PacketSender {
async fn create_new_gateway_client_handle_and_authenticate(
address: String,
identity: identity::PublicKey,
sphinx: encryption::PublicKey,
fresh_gateway_client_data: &FreshGatewayClientData,
gateway_connection_timeout: Duration,
) -> Option<(
@@ -274,7 +291,7 @@ impl PacketSender {
(MixnetMessageReceiver, AcknowledgementReceiver),
)> {
let (new_client, (message_receiver, ack_receiver)) =
Self::new_gateway_client_handle(address, identity, fresh_gateway_client_data);
Self::new_gateway_client_handle(address, identity, sphinx, fresh_gateway_client_data);
// Put this in timeout in case the gateway has incorrectly set their ulimit and our connection
// gets stuck in their TCP queue and just hangs on our end but does not terminate
@@ -351,6 +368,7 @@ impl PacketSender {
Self::create_new_gateway_client_handle_and_authenticate(
packets.clients_address,
packets.pub_key,
packets.encryption_key,
&fresh_gateway_client_data,
gateway_connection_timeout,
)
@@ -3,7 +3,7 @@
use crate::network_monitor::test_packet::NymApiTestMessageExt;
use crate::network_monitor::ROUTE_TESTING_TEST_NONCE;
use nym_crypto::asymmetric::identity;
use nym_crypto::asymmetric::{encryption, identity};
use nym_topology::{gateway, mix, NymTopology};
use std::fmt::{Debug, Formatter};
@@ -63,6 +63,10 @@ impl TestRoute {
self.gateway().identity_key
}
pub(crate) fn gateway_sphinx(&self) -> encryption::PublicKey {
self.gateway().sphinx_key
}
pub(crate) fn topology(&self) -> &NymTopology {
&self.nodes
}
+1 -1
View File
@@ -1 +1 @@
14
18
+3 -1
View File
@@ -2,16 +2,18 @@
## [Unreleased]
## [v1.1.14] (2023-06-27)
## [v1.1.14] (2023-07-04)
- Nym connect fails to start when encountering an old config version ([#3588])
- NC desktop - apps section adjustments + add monero integration ([#2977])
- nym-connect: use different service provider directory when medium toggle enabled ([#3617])
- Fix medium toggle in nym-connect ([#3590])
- [bugfix] NC: load old gateway configuration if we're not registering ([#3586])
- nym-connect: medium speed setting ([#3585])
[#3588]: https://github.com/nymtech/nym/issues/3588
[#2977]: https://github.com/nymtech/nym/issues/2977
[#3617]: https://github.com/nymtech/nym/pull/3617
[#3590]: https://github.com/nymtech/nym/pull/3590
[#3586]: https://github.com/nymtech/nym/pull/3586
[#3585]: https://github.com/nymtech/nym/pull/3585
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@nym/nym-connect",
"version": "1.1.14",
"version": "1.1.13",
"main": "index.js",
"license": "MIT",
"scripts": {
@@ -10,39 +10,58 @@ use nym_contracts_common::types::Percent;
static SERVICE_PROVIDER_WELLKNOWN_URL: &str =
"https://nymtech.net/.wellknown/connect/service-providers.json";
// List of network-requesters running with medium toggle enabled, for testing
static SERVICE_PROVIDER_WELLKNOWN_URL_MEDIUM: &str =
"https://nymtech.net/.wellknown/connect/service-providers-medium.json";
static HARBOUR_MASTER_URL: &str = "https://harbourmaster.nymtech.net/v1/services/?size=100";
static GATEWAYS_DETAILED_URL: &str =
"https://validator.nymtech.net/api/v1/status/gateways/detailed";
fn get_services_url() -> &'static str {
std::env::var("NYM_CONNECT_ENABLE_MEDIUM")
.is_ok()
.then(|| SERVICE_PROVIDER_WELLKNOWN_URL_MEDIUM)
.unwrap_or(SERVICE_PROVIDER_WELLKNOWN_URL)
}
#[tauri::command]
pub async fn get_services() -> Result<Vec<DirectoryServiceProvider>> {
log::trace!("Fetching services");
let services_res = reqwest::get(SERVICE_PROVIDER_WELLKNOWN_URL)
.await?
.json::<Vec<DirectoryService>>()
.await?;
log::trace!("Received: {:#?}", services_res);
let all_services = fetch_services().await?;
log::trace!("Received: {:#?}", all_services);
log::trace!("Fetching gateways");
let gateway_res = reqwest::get(GATEWAYS_DETAILED_URL)
.await?
.json::<Vec<GatewayBondAnnotated>>()
.await?;
log::trace!("Received: {:#?}", gateway_res);
// Early return if we're running with medium toggle enabled
if std::env::var("NYM_CONNECT_ENABLE_MEDIUM").is_ok() {
return Ok(all_services.into_iter().flat_map(|sp| sp.items).collect());
}
// TODO: get paged
log::trace!("Fetching active services");
let active_services = reqwest::get(HARBOUR_MASTER_URL)
.await?
.json::<PagedResult<HarbourMasterService>>()
.await?;
let active_services = fetch_active_services().await?;
log::trace!("Active: {:#?}", active_services);
let mut filtered: Vec<DirectoryService> = vec![];
let filtered_services = filter_out_inactive(all_services, active_services);
for service in &services_res {
let items = service
log::trace!("Fetching gateways");
let gateway_res = get_gateways_detailed().await?;
log::trace!("Received: {:#?}", gateway_res);
// Use only services that are active AND have a performance of >= 90%
let filtered_services_with_good_gateway =
filter_out_poor_gateways(filtered_services, gateway_res);
Ok(filtered_services_with_good_gateway)
}
fn filter_out_inactive(
services_res: Vec<DirectoryService>,
active_services: PagedResult<HarbourMasterService>,
) -> Vec<DirectoryService> {
let mut filtered: Vec<DirectoryService> = vec![];
for service_type in &services_res {
let items = service_type
.items
.clone()
.into_iter()
@@ -53,33 +72,48 @@ pub async fn get_services() -> Result<Vec<DirectoryServiceProvider>> {
.any(|active| active.service_provider_client_id == sp.address)
})
.collect_vec();
log::trace!("service = {} has {} items", service.id, items.len());
log::trace!("service = {} has {} items", service_type.id, items.len());
filtered.push(DirectoryService {
id: service.id.clone(),
description: service.description.clone(),
id: service_type.id.clone(),
description: service_type.description.clone(),
items,
})
}
filtered
}
fn filter_out_poor_gateways(
services: Vec<DirectoryService>,
gateway_res: Vec<GatewayBondAnnotated>,
) -> Vec<DirectoryServiceProvider> {
let perf_threshold = Percent::from_percentage_value(90).unwrap();
// Use only services that are active AND have a performance of >= 90%
let services_with_good_performance: Vec<DirectoryServiceProvider> = filtered
.iter_mut()
.fold(vec![], |mut acc, sp| {
acc.append(&mut sp.items);
acc
})
services
.into_iter()
.flat_map(|sp| sp.items)
.filter(|sp| {
gateway_res.iter().any(|gateway| {
gateway.gateway_bond.gateway.identity_key == sp.gateway
&& gateway.performance >= perf_threshold
})
})
.collect();
.collect()
}
Ok(services_with_good_performance)
async fn fetch_services() -> Result<Vec<DirectoryService>> {
let services_url = get_services_url();
let services_res = reqwest::get(services_url)
.await?
.json::<Vec<DirectoryService>>()
.await?;
Ok(services_res)
}
async fn fetch_active_services() -> Result<PagedResult<HarbourMasterService>> {
let active_services = reqwest::get(HARBOUR_MASTER_URL)
.await?
.json::<PagedResult<HarbourMasterService>>()
.await?;
Ok(active_services)
}
#[tauri::command]
+5 -8
View File
@@ -3,34 +3,31 @@ import { Divider, Typography } from '@mui/material';
import { Box } from '@mui/system';
const appsSchema = {
messagingApps: ['Telegram', 'Keybase'],
wallets: ['Blockstream', 'Electrum'],
messagingApps: ['Matrix', 'Telegram', 'Keybase'],
wallets: ['Monero', 'Blockstream', 'Electrum'],
};
export const CompatibleApps = () => (
<Box>
<Typography fontSize="small" color="grey.600" sx={{ mb: 2 }}>
<Typography fontWeight="bold" variant="body2" sx={{ mb: 2 }}>
Supported apps
</Typography>
<Typography color="nym.highlight" sx={{ mb: 2 }}>
Messaging apps
</Typography>
<Divider sx={{ mb: 2 }} />
<Box sx={{ mb: 4 }}>
<Box sx={{ mb: 2 }}>
{appsSchema.messagingApps.map((app) => (
<Typography variant="body2" color="grey.400" sx={{ mb: 2 }} key={app}>
{app}
</Typography>
))}
</Box>
<Divider sx={{ mb: 2 }} />
<Typography color="nym.highlight" sx={{ mb: 2 }}>
Wallets
</Typography>
<Divider sx={{ mb: 2 }} />
<Box sx={{ mb: 4 }}>
{appsSchema.wallets.map((wallet) => (
<Typography variant="body2" color="grey.400" sx={{ mb: 2 }} key={wallet}>
+2 -1
View File
@@ -1,5 +1,5 @@
import React from 'react';
import { Apps, HelpOutline, Settings } from '@mui/icons-material';
import { Apps, HelpOutline, Settings, BugReport } from '@mui/icons-material';
import { Stack, Link, List, ListItem, ListItemButton, ListItemIcon, ListItemText } from '@mui/material';
import { Link as RouterLink } from 'react-router-dom';
import { AppVersion } from 'src/components/AppVersion';
@@ -7,6 +7,7 @@ import { AppVersion } from 'src/components/AppVersion';
const menuSchema = [
{ title: 'Supported apps', icon: Apps, path: 'apps' },
{ title: 'How to connect guide', icon: HelpOutline, path: 'guide' },
{ title: 'Please help us improve the app', icon: BugReport, path: 'monitoring' },
{ title: 'Settings', icon: Settings, path: 'settings' },
];
@@ -34,10 +34,6 @@ export const MonitoringSettings = () => {
occur or if the app crashes, it will automatically send a report. Also it tracks various performance
metrics. We use sentry.io service to handle this.
</FormHelperText>
<FormHelperText sx={{ m: 0, mb: 2 }}>
Note: A report can include your external IP, this can be useful to catch issues related to IP location.
All recorded data is used by Nym developers and for app development purposes only.
</FormHelperText>
</FormControl>
<Stack direction="row" gap={1} alignItems="center">
<WarningIcon color="warning" fontSize="small" />
@@ -7,7 +7,6 @@ import { toggleLogViewer } from 'src/utils';
const menuSchema = [
{ title: 'Select your gateway', path: 'gateway' },
{ title: 'Select a service provider', path: 'service-provider' },
{ title: 'Help improve the app', path: 'monitoring' },
];
export const SettingsMenu = () => (
+1 -1
View File
@@ -25,11 +25,11 @@ export const AppRoutes = () => {
<Route index element={<Menu />} />
<Route path="apps" element={<CompatibleApps />} />
<Route path="guide" element={<HelpGuide />} />
<Route path="monitoring" element={<MonitoringSettings />} />
<Route path="settings">
<Route index element={<SettingsMenu />} />
<Route path="gateway" element={<GatewaySettings />} />
<Route path="service-provider" element={<ServiceProviderSettings />} />
<Route path="monitoring" element={<MonitoringSettings />} />
</Route>
</Route>
</RoutesContainer>
+2
View File
@@ -43,6 +43,8 @@ async function initSentry() {
getVersion().then((version) => {
Sentry.setTag('app_version', version);
});
Sentry.setUser({ id: 'nym', ip_address: undefined });
}
export default initSentry;
+1 -1
View File
@@ -1 +1 @@
14
18
+1 -1
View File
@@ -99,7 +99,6 @@ android {
}
dependencies {
implementation 'androidx.core:core-ktx:1.10.1'
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.6.1'
implementation 'androidx.activity:activity-compose:1.7.2'
@@ -124,4 +123,5 @@ dependencies {
debugImplementation 'androidx.compose.ui:ui-tooling'
debugImplementation 'androidx.compose.ui:ui-test-manifest'
implementation 'com.github.kittinunf.fuel:fuel:3.0.0-alpha1'
implementation 'io.sentry:sentry-android:6.24.0'
}
@@ -2,6 +2,8 @@ package net.nymtech.nyms5
import android.app.Application
import android.content.Context
import android.content.pm.PackageManager
import android.os.Build
import android.util.Log
import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.Preferences
@@ -9,11 +11,15 @@ import androidx.datastore.preferences.core.booleanPreferencesKey
import androidx.datastore.preferences.preferencesDataStore
import androidx.work.Configuration
import androidx.work.DelegatingWorkerFactory
import io.sentry.Scope
import io.sentry.Sentry
import io.sentry.android.core.SentryAndroid
import io.sentry.protocol.User
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.runBlocking
val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "settings")
val monitoringKey = booleanPreferencesKey("monitoring")
@@ -40,11 +46,34 @@ class App : Application(), Configuration.Provider {
options.dsn =
"https://6872f5818bc147ef9c0fce114fcaac8a@o967446.ingest.sentry.io/4505306218102784"
options.enableAllAutoBreadcrumbs(true)
options.isEnableUserInteractionTracing = true
options.isEnableUserInteractionBreadcrumbs = true
// TODO should be adjusted in production env
options.sampleRate = 1.0
options.tracesSampleRate = 1.0
options.profilesSampleRate = 1.0
}
Sentry.configureScope { scope: Scope ->
val packageManager = applicationContext.packageManager
val packageInfo = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
packageManager.getPackageInfo(
packageName,
PackageManager.PackageInfoFlags.of(0)
)
} else {
packageManager.getPackageInfo(packageName, 0)
}
scope.setTag("app_version", packageInfo.versionName)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
scope.setTag("app_version_code", packageInfo.longVersionCode.toString())
}
}
val user = User()
user.id = "nym"
Sentry.setUser(user)
}
}
}
@@ -50,6 +50,7 @@ import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalClipboardManager
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.AnnotatedString
@@ -249,7 +250,7 @@ fun S5ClientSwitch(
Spacer(modifier = modifier.width(14.dp))
Switch(checked = connected, enabled = !loading, onCheckedChange = {
onSwitch(!connected)
})
}, modifier = Modifier.testTag("switch_connect"))
}
if (connected && !loading) {
Column(modifier = modifier.padding(16.dp)) {
@@ -332,12 +333,10 @@ fun Monitoring(
tint = Color.Yellow
)
Spacer(modifier = modifier.width(16.dp))
Text(stringResource(R.string.monitoring_desc_3), color = Color.Yellow)
Text(stringResource(R.string.monitoring_desc_2), color = Color.Yellow)
}
Spacer(modifier = modifier.height(18.dp))
Text(stringResource(R.string.monitoring_desc_1))
Spacer(modifier = modifier.height(18.dp))
Text(stringResource(R.string.monitoring_desc_2))
}
}
@@ -1,6 +1,7 @@
package net.nymtech.nyms5
import android.util.Log
import io.sentry.Sentry
const val nymNativeLib = "nym_socks5_listener"
@@ -27,6 +28,7 @@ class NymProxy {
startClient(serviceProvider, onStartCbObj, onStopCbObj)
} catch (e: Throwable) {
Log.e(tag, "$nymNativeLib:startClient internal error: $e")
Sentry.captureException(e)
}
}
@@ -36,6 +38,7 @@ class NymProxy {
stopClient()
} catch (e: Throwable) {
Log.e(tag, "$nymNativeLib:stopClient internal error: $e")
Sentry.captureException(e)
}
}
@@ -50,6 +53,7 @@ class NymProxy {
}
} catch (e: Throwable) {
Log.e(tag, "$nymNativeLib:getClientState internal error: $e")
Sentry.captureException(e)
}
return State.UNINITIALIZED
}
@@ -17,6 +17,7 @@ import androidx.work.WorkerParameters
import androidx.work.workDataOf
import fuel.Fuel
import fuel.get
import io.sentry.Sentry
import kotlinx.serialization.Serializable
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json
@@ -100,6 +101,7 @@ class ProxyWorker(
tag,
"failed to make the work run in the context of a foreground service"
)
Sentry.captureException(e)
}
return try {
@@ -127,6 +129,7 @@ class ProxyWorker(
tag,
"an error occurred while fetching the service providers list: $e"
)
Sentry.captureException(e)
Log.w(tag, "using a default service provider $defaultSp")
}
@@ -139,6 +142,7 @@ class ProxyWorker(
Result.success()
} catch (e: Throwable) {
Log.e(tag, "error: ${e.message}")
Sentry.captureException(e)
Result.failure()
}
}
@@ -12,7 +12,5 @@
<string name="default_sp">DpB3cHAchJiNBQi5FrZx2csXb1mrHkpYh9Wzf8Rjsuko.ANNWrvHqMYuertHGHUrZdBntQhpzfbWekB39qez9U2Vx@2BuMSfMW3zpeAjKXyKLhmY4QW1DXurrtSPEJ6CjX3SEh</string>
<string name="connected_text">Connected to the mixnet</string>
<string name="monitoring_desc_1">Help Nym developers to fix errors, crashes and improve the application by enabling this option. If errors occur or if the app crashes, it will automatically send a report. Also it tracks various performance metrics. We use sentry.io service to handle this.</string>
<string name="monitoring_desc_2">Note: A report can include your external IP, this can be useful to catch issues related to IP location.
All recorded data is used by Nym developers and for app development purposes only.</string>
<string name="monitoring_desc_3">You must restart the application for the change to take effect.</string>
<string name="monitoring_desc_2">You must restart the application for the change to take effect.</string>
</resources>
+1 -1
View File
@@ -1 +1 @@
16
18
+3 -1
View File
@@ -2,11 +2,13 @@
## [Unreleased]
## [v1.2.5] (2023-06-27)
## [v1.2.5] (2023-07-04)
- Wallet - add "Test my node" in the Node Settings and show its results ([#2314])
- Move client wasm to Wallet directory ([#3606])
[#2314]: https://github.com/nymtech/nym/issues/2314
[#3606]: https://github.com/nymtech/nym/pull/3606
## [v1.2.4] (2023-06-06)
+1 -1
View File
@@ -31,6 +31,7 @@
"@nymproject/mui-theme": "^1.0.0",
"@nymproject/react": "^1.0.0",
"@nymproject/types": "^1.0.0",
"@nymproject/sdk": "^1.1.8",
"@storybook/react": "^6.5.15",
"@tauri-apps/api": "^1.2.0",
"@tauri-apps/tauri-forage": "^1.0.0-beta.2",
@@ -41,7 +42,6 @@
"lodash": "^4.17.21",
"notistack": "^2.0.3",
"npm-run-all": "^4.1.5",
"nym-client-wasm": "1.1.1",
"qrcode.react": "^1.0.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
@@ -1,6 +1,6 @@
import React from 'react';
import { TestStatus } from '@nymproject/sdk';
import { Divider, Typography } from '@mui/material';
import { TestStatus } from 'src/pages/bonding/node-settings/node-test/types';
import { ResultsCard, ResultsCardDetail } from './ResultsCard';
export const Packets = ({
@@ -1,8 +1,8 @@
import React, { useEffect } from 'react';
import { Card, CardContent, CardHeader, Dialog, Divider } from '@mui/material';
import { NymLogo } from '@nymproject/react/logo/NymLogo';
import { ResultsCardDetail } from './ResultsCard';
import { sleep } from 'src/utils/sleep';
import { ResultsCardDetail } from './ResultsCard';
export const PrintResults = ({
packetsSent,
@@ -30,7 +30,7 @@ export const PrintResults = ({
asyncPrint();
window.addEventListener('afterprint', OnPrintRequestComplete);
() => window.removeEventListener('afterprint', OnPrintRequestComplete);
return () => window.removeEventListener('afterprint', OnPrintRequestComplete);
}, []);
return (
@@ -1,7 +1,6 @@
import React from 'react';
import { TestStatus } from '@nymproject/sdk';
import { Grid } from '@mui/material';
import { TestStatus } from 'src/pages/bonding/node-settings/node-test/types';
import { Packets } from './Packets';
import { NodeScore } from './NodeScore';
import { Overview } from './Overview';

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