Compare commits

..

53 Commits

Author SHA1 Message Date
Jędrzej Stuczyński 3e5923eaad merged with fbdf31b879 2022-06-10 09:56:35 +01:00
Jędrzej Stuczyński c5350f30aa Regenerated rust => ts types 2022-06-09 14:42:15 +01:00
Jędrzej Stuczyński 7ffc8b9999 More type-restrictive exported denom type 2022-06-09 11:49:12 +01:00
Jędrzej Stuczyński 7c9fbc9c73 Fixed conversion to display coin 2022-06-07 10:11:04 +01:00
Jędrzej Stuczyński 2bcdc4c3d0 Removed explicit Arc and RwLock from all tauri commands 2022-06-06 17:51:45 +01:00
Jędrzej Stuczyński 8300daa117 Minor post-merge fixes 2022-06-06 17:31:09 +01:00
Jędrzej Stuczyński a60de5764d merge with wallet-delegation-ui-squashed 2022-06-06 17:18:48 +01:00
Jędrzej Stuczyński 23b093349d Fixed up tests and made clippy happier 2022-06-06 17:09:30 +01:00
Jędrzej Stuczyński 8955ee0b1d More unification for conversion methods 2022-06-06 16:43:12 +01:00
Jędrzej Stuczyński 9ef87df573 Display for Fee 2022-06-06 16:24:49 +01:00
Jędrzej Stuczyński ce7717fb2a Finished purge of MajorCurrencyAmount 2022-06-06 16:18:33 +01:00
Jędrzej Stuczyński 24c146766d Merge with wallet-claim-rewards 2022-06-06 12:04:15 +01:00
Jędrzej Stuczyński b6ddaebe67 Attempt at dec-coinifying get_all_mix_delegations 2022-06-06 11:59:02 +01:00
durch 282b18660f PR comments 2022-06-06 12:38:33 +02:00
Jędrzej Stuczyński b248f2e4b5 Further replacements of MajorCurrencyAmount into DecCoin 2022-06-06 10:33:41 +01:00
durch 184dd7767d Sort CHANGELOG lines 2022-06-06 11:28:36 +02:00
durch 2483a545b7 CHANGELOG 2022-06-06 11:27:09 +02:00
durch df1926071a Add claim and compound wallet endpoints, proc_macro to generate execute and simulate 2022-06-06 11:21:35 +02:00
Jędrzej Stuczyński 81a206f6c0 Further WIP work on transforming usages of MajorCurrencyAmount into DecCoin 2022-06-01 17:25:27 +01:00
Jędrzej Stuczyński 87e8666b86 'New' API on 'send' 2022-06-01 16:52:26 +01:00
fmtabbara 3519d0c31d Merge branch 'develop' into feature/wallet-delegation-ui-squashed 2022-06-01 16:32:34 +01:00
Jędrzej Stuczyński dbbd94d64c Generating typescript type for DecCoin 2022-06-01 16:21:17 +01:00
Jędrzej Stuczyński 93705d83ab Denom registration + conversion 2022-06-01 16:18:17 +01:00
Jędrzej Stuczyński 66b71fe87b No longer exposing plain 'DENOM' 2022-06-01 13:44:54 +01:00
Jędrzej Stuczyński 4f20085c05 Introduced concept of denom details 2022-06-01 13:32:38 +01:00
fmtabbara a33c21d438 Merge branch 'develop' into feature/wallet-delegation-ui-squashed 2022-06-01 11:23:05 +01:00
Jędrzej Stuczyński 04d02b08bc Merged with develop 2022-06-01 11:15:41 +01:00
Jędrzej Stuczyński 9460276131 Bunch of temporary workaround to have wallet working-ish 2022-06-01 10:59:41 +01:00
Jędrzej Stuczyński 84c9394eba Broken, but compilable first stage of post-merging 2022-06-01 09:57:40 +01:00
fmtabbara 6030d3831f refresh on network or client details change 2022-05-31 15:54:31 +01:00
Jędrzej Stuczyński 241f0cf93a changelog 2022-05-31 11:48:29 +01:00
Jędrzej Stuczyński 11122635f9 Refactored missed coin-generic API methods 2022-05-31 11:43:04 +01:00
Jędrzej Stuczyński ea54a3edc2 Merge with develop 2022-05-31 10:50:02 +01:00
Jędrzej Stuczyński 985a38429d Fixed up tests and clippy 2022-05-31 10:43:17 +01:00
fmtabbara c9f821864a only return events table if there are events 2022-05-31 10:06:29 +01:00
fmtabbara 37d55f3a06 handle undelegation of locked tokens 2022-05-30 22:07:05 +01:00
fmtabbara b2ce142c17 integrate modal divider with modal component 2022-05-30 22:06:23 +01:00
Jędrzej Stuczyński 374baa5ec1 Fixed validator api 2022-05-30 16:13:48 +01:00
Jędrzej Stuczyński de1df74eb5 Simplified the API by removing the generics in favour of explicit Coin type 2022-05-30 16:09:37 +01:00
Jędrzej Stuczyński 766c31544e Made wallet compilable with the recent changes 2022-05-30 15:58:31 +01:00
Jędrzej Stuczyński ecca7e8479 CoinConverter trait 2022-05-30 14:51:12 +01:00
Jędrzej Stuczyński 84a42f6ed9 Changed client API to use the new coin type 2022-05-30 14:46:05 +01:00
Jędrzej Stuczyński 5925e85684 try_add 2022-05-30 11:37:18 +01:00
Jędrzej Stuczyński 972c60726c Additional From implementations plus a constructor 2022-05-30 11:31:58 +01:00
fmtabbara ece22b9703 spell delegations correctly! 2022-05-30 11:29:02 +01:00
Jędrzej Stuczyński 3f718feb41 Created nymd internal coin 2022-05-30 11:22:44 +01:00
fmtabbara b550c32db6 update wording 2022-05-30 11:20:11 +01:00
fmtabbara 83090c0a25 use token pool selector 2022-05-30 11:16:52 +01:00
fmtabbara 97ad1a2e46 fix duplicate key 2022-05-30 11:16:19 +01:00
fmtabbara 9fbefa34e8 get wallet balance after transactions 2022-05-30 09:06:16 +01:00
Mark Sinclair 0812296399 Integrate fees changes:
- make operations available as requests (typed with any for now, needs changing)
- move `FeeDetails` to `common/types`
- mock `getGasFee()`
2022-05-27 18:33:02 +01:00
Mark Sinclair 51b04081a3 Fix rebase errors 2022-05-27 17:44:52 +01:00
tommy 7f2027ca6b Delegation UI:
Update QA vars

fmt

re-map coin type for qa

add correct bech32 address as the network-explorer-api was complaining

clean up

fmt

Delegation components

Show delegation story on paper

Remove actions header from delegations list

Add copy to clipboard for delegation list node ids

Move tooltip

Modals

Extract modal styles

Fix exports

Rewards summary and redeem modal

Factor out simple modal

Delegations actions modals: delegate, delegate more, undelegate

Coin mark and move logo stories

Rust types

React components handle currency

Form field to enter and display an Identity Key

Fix up build order

Update README

Flat buttons

End adornment

Currency form field

Add more props

Export components

Add currency and mixnode fields

Group stories into folders and add flow

Change exports from shared packages to stop webpack bundling issues

Fix logo import

Add mock for tauri api in storybook that shows a console error for operations that are not mocked

Delegations views and routes for wallet

Delegations list show pending delegations and undelegations

wip - delegations page status

Add typescript type checking to storybook webpack config and more mocks for tauri

Add more interstitial states and confirmation modals

Copy change

Move config to inside source tree

Fix up `Console` typings

Add wrapper around Tauri `invoke` that logs operations in development mode

wip

wip

wip

ts-rs: remove old files

ts-rs: update paths to `ts-packages/types`

ts-rs: remove old files

ts-rs: export new types to `ts-packages/types`

Add `MajorCurrencyAmount` to convert to and from TS types for various backend currency types

New crate `nym-types` to provide types for frontend apps (wallet, explorer, etc)

wip

update type imports and fix some lint errors

update packages

update type imports

update type imports

update type imports

update type imports

start pulling out use of  minorMajor and majorMinor

update type imports

update import

Add missing types generated by ts-rs

fix types

Adding denom to account

type updates

Handle micro currency denoms

Fix type conversion mistake

Add clean target

eslint: formatting

Update React currency components to use `MajorCurrencyAmount`

Add separators and extra props to currency components

replace currency mapper with denom returning from service

Adjust type while generation is broken

start integrating new CurrencyFormField component

update balance and vesting on client change (not only client address)

Fix up conversion from cosmwasm coin to major currency for minor denoms

Fix up typings and validations to remove more `Coin` usage

fix conflict

fix delegations form

start fixing validation

type update

remove console log

tidy up

remove more unused types

remove more unused types

Fix `Coin` denom to be `minor`

Fix up to minor_cosmos_coin

Fix up send

Remove `Coin` type

Fix up exported types

start delegation UI

more UI work

close actions modal on action select

update label

fix old delegateion form

minor updates

undo change to currency in stringD

Fix up types

Add feature flag for generating typescript
Generate types behind feature flag

Use custom cli tool to export `ts-rs` types

`ts-rs-cli` moves files into place and fix up `Makefile`

Update generations target

Add missing types for generation

Generate typescript types

reorder imports

use make generate-typescript for new types + type import updates

update types

Add delegate with everything

Add get block to nymd client

More conversions

Get a big list of delegations with lots of stuff

Add `avg_uptime_percent`

component api updates

ui updates and fixes

Add delegation history and pending events

Fix up addition

Fix up pending delegation event types

Filter pending delegation events

add history and pending events

set total delegations

rebase

fix breaking type change on delegate page

Fix mixnode mapping

Add back refresh and set periodic refresh

upgrade to react router 6

Add logging
Export new types for gas and transactions

increase container size!

add sendtx type

update onOK to return MAjorCurrencyAmount

align table items

display dash if amount not availble

work on delegate and undelegate

Make serializable

More types

Fix up errors

align item icon

type updates

Add operation to get all pending delegation/undelegation events

Fix up logging

Add more logging

Fix undelegate error

get pending delegation events

remove unused import
2022-05-27 16:50:16 +01:00
568 changed files with 18904 additions and 35775 deletions
+4 -4
View File
@@ -19,10 +19,10 @@
Cargo.* @durch @futurechimp @jstuczyn @neacsu @octol
# JS rules:
*.js @mmsinclair @fmtabbara
*.ts @mmsinclair @fmtabbara
*.tsx @mmsinclair @fmtabbara
*.jsx @mmsinclair @fmtabbara
*.js @mmsinclair @fmtabbara @Aid19801
*.ts @mmsinclair @fmtabbara @Aid19801
*.tsx @mmsinclair @fmtabbara @Aid19801
*.jsx @mmsinclair @fmtabbara @Aid19801
# Something looking like possible documentation rules:
*.md @mfahampshire
+2 -2
View File
@@ -13,9 +13,9 @@ jobs:
- name: Install rsync
run: sudo apt-get install rsync
- uses: rlespinasse/github-slug-action@v3.x
- uses: actions/setup-node@v3
- uses: actions/setup-node@v2
with:
node-version: 16
node-version: '16'
- name: Setup yarn
run: npm install -g yarn
- name: Build
+1 -8
View File
@@ -41,13 +41,6 @@ jobs:
command: test
args: --workspace --all-features
- name: Run expensive tests
if: github.ref == 'refs/heads/develop' || github.event.pull_request.base.ref == 'develop' || github.event.pull_request.base.ref == 'master'
uses: actions-rs/cargo@v1
with:
command: test
args: --workspace --all-features -- --ignored
- name: Check formatting
uses: actions-rs/cargo@v1
with:
@@ -58,7 +51,7 @@ jobs:
name: Clippy checks
with:
token: ${{ secrets.GITHUB_TOKEN }}
args: --workspace --all-features
args: --all-features
- name: Run clippy
uses: actions-rs/cargo@v1
-56
View File
@@ -1,56 +0,0 @@
name: Nym Connect (rust)
on:
push:
paths-ignore:
- 'explorer/**'
jobs:
build:
runs-on: [ self-hosted, custom-linux ]
env:
RUSTC_WRAPPER: /home/ubuntu/.cargo/bin/sccache
steps:
- name: Install Dependencies (Linux)
run: sudo apt-get update && sudo apt-get -y install libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev squashfs-tools libayatana-appindicator3-dev
- name: Check out repository code
uses: actions/checkout@v2
- name: Install rust toolchain
uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
override: true
components: rustfmt, clippy
- name: Build all binaries
uses: actions-rs/cargo@v1
with:
command: build
args: --manifest-path nym-connect/Cargo.toml --workspace
- name: Run all tests
uses: actions-rs/cargo@v1
with:
command: test
args: --manifest-path nym-connect/Cargo.toml --workspace
- name: Check formatting
uses: actions-rs/cargo@v1
with:
command: fmt
args: --manifest-path nym-connect/Cargo.toml --all -- --check
- uses: actions-rs/clippy-check@v1
name: Clippy checks
with:
token: ${{ secrets.GITHUB_TOKEN }}
args: --manifest-path nym-connect/Cargo.toml --workspace --all-features
- name: Run clippy
uses: actions-rs/cargo@v1
with:
command: clippy
args: --manifest-path nym-connect/Cargo.toml --workspace --all-features -- -D warnings
-38
View File
@@ -1,38 +0,0 @@
name: Build release of Nym smart contracts
on:
workflow_dispatch:
defaults:
run:
working-directory: contracts
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Install Rust stable
uses: actions-rs/toolchain@v1
with:
toolchain: stable
target: wasm32-unknown-unknown
override: true
components: rustfmt, clippy
- name: Build release contracts
run: RUSTFLAGS='-C link-arg=-s' cargo build --release --target wasm32-unknown-unknown
- name: Upload Mixnet Contract Artifact
uses: actions/upload-artifact@v3
with:
name: mixnet_contract.wasm
path: contracts/target/wasm32-unknown-unknown/release/mixnet_contract.wasm
retention-days: 5
- name: Upload Vesting Contract Artifact
uses: actions/upload-artifact@v3
with:
name: vesting_contract.wasm
path: contracts/target/wasm32-unknown-unknown/release/vesting_contract.wasm
retention-days: 5
+2 -2
View File
@@ -14,9 +14,9 @@ jobs:
runs-on: custom-runner-linux
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v3
- uses: actions/setup-node@v2
with:
node-version: 16
node-version: '16'
- name: Setup yarn
run: npm install -g yarn
- name: Run ESLint
+2 -2
View File
@@ -17,9 +17,9 @@ jobs:
- name: Install rsync
run: sudo apt-get install rsync
- uses: rlespinasse/github-slug-action@v3.x
- uses: actions/setup-node@v3
- uses: actions/setup-node@v2
with:
node-version: 16
node-version: '16'
- name: Setup yarn
run: npm install -g yarn
continue-on-error: true
+3 -16
View File
@@ -2,7 +2,7 @@ name: Nightly builds
on:
schedule:
- cron: '14 1 * * *'
- cron: '14 4 * * *'
jobs:
matrix_prep:
runs-on: ubuntu-latest
@@ -50,19 +50,6 @@ jobs:
command: test
args: --workspace
- name: Reclaim some disk space (because Windows is being annoying)
uses: actions-rs/cargo@v1
if: ${{ matrix.os == 'windows-latest' }}
with:
command: clean
- name: Run expensive tests
if: github.ref == 'refs/heads/develop' || github.event.pull_request.base.ref == 'develop' || github.event.pull_request.base.ref == 'master'
uses: actions-rs/cargo@v1
with:
command: test
args: --workspace --all-features -- --ignored
- name: Check formatting
uses: actions-rs/cargo@v1
with:
@@ -88,9 +75,9 @@ jobs:
command: clippy
args: --workspace --all-targets -- -D warnings
- name: Reclaim some disk space
- name: Reclaim some disk space (because Windows is being annoying)
uses: actions-rs/cargo@v1
if: ${{ matrix.os == 'windows-latest' || matrix.os == 'ubuntu-latest' }}
if: ${{ matrix.os == 'windows-latest' }}
with:
command: clean
@@ -1,96 +0,0 @@
name: Publish Nym Connect (MacOS)
on:
workflow_dispatch:
release:
types: [created]
defaults:
run:
working-directory: nym-connect
jobs:
publish-tauri:
strategy:
fail-fast: false
matrix:
platform: [macos-latest]
runs-on: ${{ matrix.platform }}
steps:
- uses: actions/checkout@v2
- name: Check the release tag starts with `nym-connect-`
if: startsWith(github.ref, 'refs/tags/nym-connect-') == false && github.event_name != 'workflow_dispatch'
uses: actions/github-script@v3
with:
script: |
core.setFailed('Release tag did not start with nym-connect-...')
- name: Node v16
uses: actions/setup-node@v3
with:
node-version: 16
- name: Install Rust stable
uses: actions-rs/toolchain@v1
with:
toolchain: stable
- name: Install the Apple developer certificate for code signing
env:
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
run: |
# create variables
CERTIFICATE_PATH=$RUNNER_TEMP/build_certificate.p12
KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db
# import certificate and provisioning profile from secrets
echo -n "$APPLE_CERTIFICATE" | base64 --decode --output $CERTIFICATE_PATH
# create temporary keychain
security create-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
security set-keychain-settings -lut 21600 $KEYCHAIN_PATH
security unlock-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
# import certificate to keychain
security import $CERTIFICATE_PATH -P "$APPLE_CERTIFICATE_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH
security list-keychain -d user -s $KEYCHAIN_PATH
- name: Create env file
uses: timheuer/base64-to-file@v1.1
with:
fileName: '.env'
encodedString: ${{ secrets.WALLET_ADMIN_ADDRESS }}
- name: Install app dependencies and build it
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
ENABLE_CODE_SIGNING: ${{ secrets.APPLE_CERTIFICATE }}
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_IDENTITY_ID }}
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
run: yarn && yarn build
- name: Upload Artifact
uses: actions/upload-artifact@v3
with:
name: nym-connect_1.0.0_x64.dmg
path: nym-connect/target/release/bundle/dmg/nym-connect_1.0.0_x64.dmg
retention-days: 30
- name: Clean up keychain
if: ${{ always() }}
run: |
security delete-keychain $RUNNER_TEMP/app-signing.keychain-db
- name: Upload to release based on tag name
uses: softprops/action-gh-release@v1
if: github.event_name == 'release'
with:
files: |
nym-connect/target/release/bundle/dmg/*.dmg
nym-connect/target/release/bundle/macos/*.app.tar.gz*
@@ -1,68 +0,0 @@
name: Publish Nym Connect (Ubuntu)
on:
workflow_dispatch:
release:
types: [created]
defaults:
run:
working-directory: nym-connect
jobs:
publish-tauri:
strategy:
fail-fast: false
matrix:
platform: [ubuntu-latest]
runs-on: ${{ matrix.platform }}
steps:
- uses: actions/checkout@v2
- name: Tauri dependencies
run: >
sudo apt-get update &&
sudo apt-get install -y webkit2gtk-4.0 libayatana-appindicator3-dev
- name: Check the release tag starts with `nym-connect-`
if: startsWith(github.ref, 'refs/tags/nym-connect-') == false && github.event_name != 'workflow_dispatch'
uses: actions/github-script@v3
with:
script: |
core.setFailed('Release tag did not start with nym-connect-...')
- name: Node v16
uses: actions/setup-node@v3
with:
node-version: 16
- name: Install Rust stable
uses: actions-rs/toolchain@v1
with:
toolchain: stable
- name: Install app dependencies
run: yarn
- name: Create env file
uses: timheuer/base64-to-file@v1.1
with:
fileName: '.env'
encodedString: ${{ secrets.WALLET_ADMIN_ADDRESS }}
- name: Build app
run: yarn build
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-connect.AppImage.tar.gz
path: nym-connect/target/release/bundle/appimage/nym-connect_1.0.0_amd64.AppImage
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-connect/target/release/bundle/appimage/*.AppImage
nym-connect/target/release/bundle/appimage/*.AppImage.tar.gz*
@@ -1,90 +0,0 @@
name: Publish Nym Connect (Windows 10)
on:
workflow_dispatch:
release:
types: [created]
defaults:
run:
working-directory: nym-connect
jobs:
publish-tauri:
strategy:
fail-fast: false
matrix:
platform: [windows10]
runs-on: ${{ matrix.platform }}
steps:
- name: Clean up first
continue-on-error: true
working-directory: .
run: |
cd ..
del /s /q /A:H nym
rmdir /s /q nym
- uses: actions/checkout@v3
- name: Check the release tag starts with `nym-connect-`
if: startsWith(github.ref, 'refs/tags/nym-connect-') == false && github.event_name != 'workflow_dispatch'
uses: actions/github-script@v3
with:
script: |
core.setFailed('Release tag did not start with nym-connect-...')
- name: Import signing certificate
env:
WINDOWS_CERTIFICATE: ${{ secrets.WINDOWS_CERTIFICATE }}
WINDOWS_CERTIFICATE_PASSWORD: ${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }}
run: |
New-Item -ItemType directory -Path certificate
Set-Content -Path certificate/tempCert.txt -Value $env:WINDOWS_CERTIFICATE
certutil -decode certificate/tempCert.txt certificate/certificate.pfx
Remove-Item -path certificate -include tempCert.txt
Import-PfxCertificate -FilePath certificate/certificate.pfx -CertStoreLocation Cert:\CurrentUser\My -Password (ConvertTo-SecureString -String $env:WINDOWS_CERTIFICATE_PASSWORD -Force -AsPlainText)
- name: Node v16
uses: actions/setup-node@v3
with:
node-version: 16
- name: Install Rust stable
uses: actions-rs/toolchain@v1
with:
toolchain: stable
- name: Create env file
uses: timheuer/base64-to-file@v1.1
with:
fileName: '.env'
encodedString: ${{ secrets.WALLET_ADMIN_ADDRESS }}
- name: Install app dependencies
run: yarn
- name: Build and sign it
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
ENABLE_CODE_SIGNING: ${{ secrets.WINDOWS_CERTIFICATE }}
WINDOWS_CERTIFICATE: ${{ secrets.WINDOWS_CERTIFICATE }}
WINDOWS_CERTIFICATE_PASSWORD: ${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }}
TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
run: yarn build
- name: Upload Artifact
uses: actions/upload-artifact@v3
with:
name: nym-connect_1.0.0_x64_en-US.msi
path: nym-connect/target/release/bundle/msi/nym-connect_1.0.0_x64_en-US.msi
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-connect/target/release/bundle/msi/*.msi
nym-connect/target/release/bundle/msi/*.msi.zip*
-59
View File
@@ -1,59 +0,0 @@
name: CI for nym-connect
on:
push:
paths:
- 'nym-connect/**'
defaults:
run:
working-directory: nym-connect
jobs:
build:
runs-on: custom-runner-linux
steps:
- uses: actions/checkout@v2
- name: Install rsync
run: sudo apt-get install rsync
- uses: rlespinasse/github-slug-action@v3.x
- uses: actions/setup-node@v3
with:
node-version: 16
- name: Install Yarn
run: npm install -g yarn
- run: yarn
continue-on-error: true
- name: Set environment from the example
run: cp .env.sample .env
- run: yarn storybook:build
- name: Deploy branch to CI www
continue-on-error: true
uses: easingthemes/ssh-deploy@main
env:
SSH_PRIVATE_KEY: ${{ secrets.CI_WWW_SSH_PRIVATE_KEY }}
ARGS: "-rltgoDzvO --delete"
SOURCE: "nym-connect/storybook-static/"
REMOTE_HOST: ${{ secrets.CI_WWW_REMOTE_HOST }}
REMOTE_USER: ${{ secrets.CI_WWW_REMOTE_USER }}
TARGET: ${{ secrets.CI_WWW_REMOTE_TARGET }}/nym-connect-${{ env.GITHUB_REF_SLUG }}
EXCLUDE: "/dist/, /node_modules/"
- name: Keybase - Node Install
run: npm install
working-directory: .github/workflows/support-files
# - name: Keybase - Send Notification
# env:
# NYM_NOTIFICATION_KIND: nym-connect
# NYM_PROJECT_NAME: "nym-connect"
# NYM_CI_WWW_BASE: "${{ secrets.NYM_CI_WWW_BASE }}"
# NYM_CI_WWW_LOCATION: "nym-connect-${{ env.GITHUB_REF_SLUG }}"
# GIT_COMMIT_MESSAGE: "${{ github.event.head_commit.message }}"
# GIT_BRANCH: "${GITHUB_REF##*/}"
# KEYBASE_NYMBOT_USERNAME: "${{ secrets.KEYBASE_NYMBOT_USERNAME }}"
# KEYBASE_NYMBOT_PAPERKEY: "${{ secrets.KEYBASE_NYMBOT_PAPERKEY }}"
# KEYBASE_NYMBOT_TEAM: "${{ secrets.KEYBASE_NYMBOT_TEAM }}"
# KEYBASE_NYM_CHANNEL: "ci-nym-connect"
# IS_SUCCESS: "${{ job.status == 'success' }}"
# uses: docker://keybaseio/client:stable-node
# with:
# args: .github/workflows/support-files/notifications/entry_point.sh
+8 -23
View File
@@ -1,6 +1,5 @@
name: Publish Nym Wallet (MacOS)
on:
workflow_dispatch:
release:
types: [created]
@@ -20,16 +19,16 @@ jobs:
- uses: actions/checkout@v2
- name: Check the release tag starts with `nym-wallet-`
if: startsWith(github.ref, 'refs/tags/nym-wallet-') == false && github.event_name != 'workflow_dispatch'
if: startsWith(github.ref, 'refs/tags/nym-wallet-') == false
uses: actions/github-script@v3
with:
script: |
core.setFailed('Release tag did not start with nym-wallet-...')
- name: Node v16
uses: actions/setup-node@v3
uses: actions/setup-node@v1
with:
node-version: 16
node-version: 16.x
- name: Install Rust stable
uses: actions-rs/toolchain@v1
with:
@@ -56,12 +55,6 @@ jobs:
security import $CERTIFICATE_PATH -P "$APPLE_CERTIFICATE_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH
security list-keychain -d user -s $KEYCHAIN_PATH
- name: Create env file
uses: timheuer/base64-to-file@v1.1
with:
fileName: '.env'
encodedString: ${{ secrets.WALLET_ADMIN_ADDRESS }}
- name: Install app dependencies and build it
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -75,22 +68,14 @@ jobs:
TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
run: yarn && yarn build
- name: Upload Artifact
uses: actions/upload-artifact@v3
- name: Upload to release based on tag name
uses: softprops/action-gh-release@v1
with:
name: nym-wallet.app.tar.gz
path: nym-wallet/target/release/bundle/macos/nym-wallet.app.tar.gz
retention-days: 5
files: |
nym-wallet/target/release/bundle/dmg/*.dmg
nym-wallet/target/release/bundle/macos/*.app.tar.gz*
- name: Clean up keychain
if: ${{ always() }}
run: |
security delete-keychain $RUNNER_TEMP/app-signing.keychain-db
- 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/dmg/*.dmg
nym-wallet/target/release/bundle/macos/*.app.tar.gz*
@@ -30,21 +30,15 @@ jobs:
core.setFailed('Release tag did not start with nym-wallet-...')
- name: Node v16
uses: actions/setup-node@v3
uses: actions/setup-node@v1
with:
node-version: 16
node-version: 16.x
- name: Install Rust stable
uses: actions-rs/toolchain@v1
with:
toolchain: stable
- name: Install app dependencies
run: yarn
- name: Create env file
uses: timheuer/base64-to-file@v1.1
with:
fileName: '.env'
encodedString: ${{ secrets.WALLET_ADMIN_ADDRESS }}
- name: Build app
run: yarn build
env:
@@ -45,21 +45,15 @@ jobs:
Import-PfxCertificate -FilePath certificate/certificate.pfx -CertStoreLocation Cert:\CurrentUser\My -Password (ConvertTo-SecureString -String $env:WINDOWS_CERTIFICATE_PASSWORD -Force -AsPlainText)
- name: Node v16
uses: actions/setup-node@v3
uses: actions/setup-node@v1
with:
node-version: 16
node-version: 16.x
- name: Install Rust stable
uses: actions-rs/toolchain@v1
with:
toolchain: stable
- name: Create env file
uses: timheuer/base64-to-file@v1.1
with:
fileName: '.env'
encodedString: ${{ secrets.WALLET_ADMIN_ADDRESS }}
- name: Install app dependencies
run: yarn
-32
View File
@@ -1,32 +0,0 @@
name: Release Nym Wallet
on:
workflow_dispatch:
inputs:
nym_wallet_version:
description: 'The version of the Nym Wallet to release'
default: '1.0.x'
required: true
type: string
jobs:
create-release:
strategy:
fail-fast: false
matrix:
platform: [ubuntu-latest]
runs-on: ${{ matrix.platform }}
steps:
- uses: actions/checkout@v2
- name: Create release
uses: softprops/action-gh-release@v1
with:
body: >-
This is a pre-release
Download the wallet for your platform:
- [Linux](https://github.com/nymtech/nym/releases/download/nym-wallet-v${{ inputs.nym_wallet_version}}/nym-wallet_v${{ inputs.nym_wallet_version}}_amd64_ubuntu20.04.AppImage)
- [MacOS](https://github.com/nymtech/nym/releases/download/nym-wallet-v${{ inputs.nym_wallet_version}}/nym-wallet_v${{ inputs.nym_wallet_version}}_x64_macos_11.dmg)
- [Windows](https://github.com/nymtech/nym/releases/download/nym-wallet-v${{ inputs.nym_wallet_version}}/nym-wallet_v${{ inputs.nym_wallet_version}}_x64_windows.msi)
prerelease: true
name: Nym Wallet v${{ inputs.nym_wallet_version}}
tag_name: nym-wallet-v${{ inputs.nym_wallet_version}}
+2 -2
View File
@@ -13,9 +13,9 @@ jobs:
- name: Install rsync
run: sudo apt-get install rsync
- uses: rlespinasse/github-slug-action@v3.x
- uses: actions/setup-node@v3
- uses: actions/setup-node@v2
with:
node-version: 16
node-version: '16'
- name: Setup yarn
run: npm install -g yarn
- name: Build dependencies
+2 -2
View File
@@ -34,9 +34,9 @@ jobs:
toolchain: stable
- name: Node v16
uses: actions/setup-node@v3
uses: actions/setup-node@v1
with:
node-version: 16
node-version: 16.x
- name: Install yarn for building application
run: yarn install
@@ -3,7 +3,7 @@ require('dotenv').config();
const Bot = require('keybase-bot');
let context = {
kinds: ['nym-wallet', 'ts-packages', 'network-explorer', 'nightly', 'nym-connect'],
kinds: ['nym-wallet', 'ts-packages', 'network-explorer', 'nightly'],
};
/**
@@ -1,29 +0,0 @@
const Handlebars = require('handlebars');
const fs = require('fs');
const path = require('path');
async function addToContextAndValidate(context) {
if (!context.env.NYM_CI_WWW_LOCATION) {
throw new Error('Please ensure the env var NYM_CI_WWW_LOCATION is set');
}
if (!context.env.NYM_CI_WWW_BASE) {
throw new Error('Please ensure the env var NYM_CI_WWW_BASE is set');
}
}
async function getMessageBody(context) {
const source = fs
.readFileSync(
context.env.IS_SUCCESS === 'true'
? path.resolve(__dirname, 'templates', 'success')
: path.resolve(__dirname, 'templates', 'failure'),
)
.toString();
const template = Handlebars.compile(source);
return template(context);
}
module.exports = {
addToContextAndValidate,
getMessageBody,
};
@@ -1,11 +0,0 @@
🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥
> :rocket: {{ env.NYM_PROJECT_NAME }}
> 🔴 **FAILURE** :cry:
> `branch` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/tree/{{ env.GIT_BRANCH_NAME }}
> `commit` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/commit/{{ env.GITHUB_SHA }}
> `build ` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/actions/runs/{{ env.GITHUB_RUN_ID }}
Commit message:
```
{{ env.GIT_COMMIT_MESSAGE }}
```
@@ -1,11 +0,0 @@
🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩
> :rocket: {{ env.NYM_PROJECT_NAME }} ➡️➡️➡️➡️➡️ **View storybook:** https://{{ env.NYM_CI_WWW_LOCATION }}.{{ env.NYM_CI_WWW_BASE }}/
> ✅ **SUCCESS**
> `branch` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/tree/{{ env.GIT_BRANCH_NAME }}
> `commit` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/commit/{{ env.GITHUB_SHA }}
> `build ` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/actions/runs/{{ env.GITHUB_RUN_ID }}
Commit message by `{{ env.GITHUB_ACTOR }}` at {{ timestamp }}:
```
{{ env.GIT_COMMIT_MESSAGE }}
```
+29 -92
View File
@@ -2,81 +2,26 @@
Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
### Added
- socks5 client/websocket client: add `--force-register-gateway` flag, useful when rerunning init ([#1353])
- nym-connect: initial proof-of-concept of a UI around the socks5 client was added
- nym-connect: add ability to select network requester and gateway ([#1427]).
- all: added network compilation target to `--help` (or `--version`) commands ([#1256]).
- explorer-api: learned how to sum the delegations by owner in a new endpoint.
- explorer-api: add apy values to `mix_nodes` endpoint
- gateway: Added gateway coconut verifications and validator-api communication for double spending protection ([#1261])
- network-explorer-ui: Upgrade to React Router 6
- rewarding: replace circulating supply with staking supply in reward calculations ([#1324])
- validator-api: add `estimated_node_profit` and `estimated_operator_cost` to `reward-estimate` endpoint ([#1284])
- validator-api: add detailed mixnode bond endpoints, and explorer-api makes use of that data to append stake saturation
- validator-api: add Swagger to document the REST API ([#1249]).
- validator-api: Added new endpoints for coconut spending flow and communications with coconut & multisig contracts ([#1261])
- validator-api: add `uptime`, `estimated_operator_apy`, `estimated_delegators_apy` to `/mixnodes/detailed` endpoint ([#1393])
- network-statistics: a new mixnet service that aggregates and exposes anonymized data about mixnet services ([#1328])
- wallet: when simulating gas costs, an automatic adjustment is being used ([#1388]).
- mixnode: Added basic mixnode hardware reporting to the HTTP API ([#1308]).
- validator-api: endpoint, in coconut mode, for returning the validator-api cosmos address ([#1404]).
### Fixed
- mixnode, gateway: attempting to determine reconnection backoff to persistently failing mixnode could result in a crash ([#1260])
- mixnode: the mixnode learned how to shutdown gracefully
- mixnode: listen out for SIGTERM and SIGQUIT too, making it play nicely as a system service.
- native & socks5 clients: fail early when clients try to re-init with a different gateway, which is not supported yet ([#1322])
- native & socks5 clients: rerun init will now reuse previous gateway configuration instead of failing ([#1353])
- native & socks5 clients: deduplicate big chunks of init logic
- validator: fixed local docker-compose setup to work on Apple M1 ([#1329])
### Changed
- nym-connect: reuse config id instead of creating a new id on each connection.
- validator-client: created internal `Coin` type that replaces coins from `cosmrs` and `cosmwasm` for API entrypoints [[#1295]]
- all: updated all `cosmwasm`-related dependencies to `1.0.0` and `cw-storage-plus` to `0.13.4` [[#1318]]
- all: updated `rocket` to `0.5.0-rc.2`.
- network-requester: allow to voluntarily store and send statistical data about the number of bytes the proxied server serves ([#1328])
- gateway: allow to voluntarily send statistical data about the number of active inboxes served by a gateway ([#1376])
[#1249]: https://github.com/nymtech/nym/pull/1249
[#1256]: https://github.com/nymtech/nym/pull/1256
[#1260]: https://github.com/nymtech/nym/pull/1260
[#1261]: https://github.com/nymtech/nym/pull/1261
[#1267]: https://github.com/nymtech/nym/pull/1267
[#1278]: https://github.com/nymtech/nym/pull/1278
[#1295]: https://github.com/nymtech/nym/pull/1295
[#1302]: https://github.com/nymtech/nym/pull/1302
[#1308]: https://github.com/nymtech/nym/pull/1308
[#1318]: https://github.com/nymtech/nym/pull/1318
[#1322]: https://github.com/nymtech/nym/pull/1322
[#1324]: https://github.com/nymtech/nym/pull/1324
[#1328]: https://github.com/nymtech/nym/pull/1328
[#1329]: https://github.com/nymtech/nym/pull/1329
[#1353]: https://github.com/nymtech/nym/pull/1353
[#1376]: https://github.com/nymtech/nym/pull/1376
[#1388]: https://github.com/nymtech/nym/pull/1388
[#1393]: https://github.com/nymtech/nym/pull/1393
[#1404]: https://github.com/nymtech/nym/pull/1404
[#1427]: https://github.com/nymtech/nym/pull/1427
## [nym-contracts-v1.0.1](https://github.com/nymtech/nym/tree/nym-contracts-v1.0.1) (2022-06-22)
### Added
- mixnet-contract: Added ClaimOperatorReward and ClaimDelegatorReward messages ([#1292])
- mixnet-contract: Replace all naked `-` with `saturating_sub`.
- mixnet-contract: Added staking_supply field to ContractStateParams.
- mixnet-contract: Added a query to get MixnodeBond by identity key ([#1369]).
- mixnet-contract: Added a query to get GatewayBond by identity key ([#1369]).
- validator-api: add `estimated_node_profit` and `estimated_operator_cost` to `reward-estimate` endpoint ([#1284])
- validator-api: add detailed mixnode bond endpoints, and explorer-api makes use of that data to append stake saturation.
- validator-api: add Swagger to document the REST API ([#1249]).
- validator-api: Added new endpoints for coconut spending flow and communications with coconut & multisig contracts ([#1261])
- vesting-contract: Added ClaimOperatorReward and ClaimDelegatorReward messages ([#1292])
- vesting-contract: Added limit to the amount of tokens one can pledge ([#1331])
- wallet: add simple CLI tool for decrypting and recovering the wallet file.
- wallet: added support for multiple accounts ([#1265])
- wallet: compound and claim reward endpoints for operators and delegators ([#1302])
- wallet: require password to switch accounts
- wallet: the wallet backend learned how to keep track of validator name, either hardcoded or by querying the status endpoint.
- network-statistics: a new mixnet service that aggregates and exposes anonymized data about mixnet services ([#1328])
### Fixed
@@ -85,42 +30,34 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
- mixnet-contract: removed `expect` in `query_delegator_reward` and queries containing invalid proxy address should now return a more human-readable error ([#1257])
- mixnet-contract: replaced integer division with fixed for performance calculations ([#1284])
- mixnet-contract: Under certain circumstances nodes could not be unbonded ([#1255](https://github.com/nymtech/nym/issues/1255)) ([#1258])
- mixnet-contract: Using correct staking supply when distributing rewards. ([#1373])
- mixnode, gateway: attempting to determine reconnection backoff to persistently failing mixnode could result in a crash ([#1260])
- mixnode: the mixnode learned how to shutdown gracefully.
- vesting-contract: replaced `checked_sub` with `saturating_sub` to fix the underflow in `get_vesting_tokens` ([#1275])
- native & socks5 clients: fail early when clients try to re-init with a different gateway, which is not supported yet ([#1322])
### Changed
[#1255]: https://github.com/nymtech/nym/pull/1255
- validator-client: created internal `Coin` type that replaces coins from `cosmrs` and `cosmwasm` for API entrypoints [[#1295]]
- all: updated all `cosmwasm`-related dependencies to `1.0.0` and `cw-storage-plus` to `0.13.4` [[#1318]]
- network-requester: allow to voluntarily store and send statistical data about the number of bytes the proxied server serves ([#1328])
[#1249]: https://github.com/nymtech/nym/pull/1249
[#1256]: https://github.com/nymtech/nym/pull/1256
[#1257]: https://github.com/nymtech/nym/pull/1257
[#1258]: https://github.com/nymtech/nym/pull/1258
[#1260]: https://github.com/nymtech/nym/pull/1260
[#1261]: https://github.com/nymtech/nym/pull/1261
[#1265]: https://github.com/nymtech/nym/pull/1265
[#1267]: https://github.com/nymtech/nym/pull/1267
[#1275]: https://github.com/nymtech/nym/pull/1275
[#1278]: https://github.com/nymtech/nym/pull/1278
[#1284]: https://github.com/nymtech/nym/pull/1284
[#1292]: https://github.com/nymtech/nym/pull/1292
[#1331]: https://github.com/nymtech/nym/pull/1331
[#1369]: https://github.com/nymtech/nym/pull/1369
[#1373]: https://github.com/nymtech/nym/pull/1373
## [nym-wallet-v1.0.6](https://github.com/nymtech/nym/tree/nym-wallet-v1.0.6) (2022-06-21)
- wallet: undelegating now uses either the mixnet or vesting contract, or both, depending on how delegations were made
- wallet: redeeming and compounding now uses both the mixnet and vesting contract
- wallet: the wallet backend learned how to archive wallet files
- wallet: add ENABLE_QA_MODE environment variable to enable QA mode on built wallet
## [nym-wallet-v1.0.5](https://github.com/nymtech/nym/tree/nym-wallet-v1.0.5) (2022-06-14)
- wallet: add simple CLI tool for decrypting and recovering the wallet file.
- wallet: added support for multiple accounts ([#1265])
- wallet: compound and claim reward endpoints for operators and delegators ([#1302])
- wallet: require password to switch accounts
- wallet: the wallet backend learned how to keep track of validator name, either hardcoded or by querying the status endpoint.
- wallet: new delegation and rewards UI
- wallet: show version in nav bar
- wallet: contract admin route put back
- wallet: staking_supply field to StateParams
- wallet: show transaction hash for redeeming or compounding rewards
[#1265]: https://github.com/nymtech/nym/pull/1265
[#1295]: https://github.com/nymtech/nym/pull/1295
[#1302]: https://github.com/nymtech/nym/pull/1302
[#1318]: https://github.com/nymtech/nym/pull/1318
[#1322]: https://github.com/nymtech/nym/pull/1322
[#1328]: https://github.com/nymtech/nym/pull/1328
## [nym-wallet-v1.0.4](https://github.com/nymtech/nym/tree/nym-wallet-v1.0.4) (2022-05-04)
Generated
+211 -172
View File
@@ -14,15 +14,6 @@ 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.5",
]
[[package]]
name = "aes"
version = "0.7.5"
@@ -47,20 +38,6 @@ dependencies = [
"cpufeatures",
]
[[package]]
name = "aes-gcm"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df5f85a83a7d8b0442b6aa7b504b8212c1733da07b98aae43d4bc21b2cb3cdf6"
dependencies = [
"aead",
"aes 0.7.5",
"cipher 0.3.0",
"ctr 0.8.0",
"ghash",
"subtle 2.4.1",
]
[[package]]
name = "ahash"
version = "0.7.6"
@@ -221,6 +198,12 @@ dependencies = [
"serde",
]
[[package]]
name = "base-x"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4521f3e3d031370679b3b140beb36dfe4801b09ac77e30c61941f97df3ef28b"
[[package]]
name = "base16ct"
version = "0.1.1"
@@ -267,7 +250,7 @@ dependencies = [
"pbkdf2",
"rand_core 0.6.3",
"ripemd160",
"sha2 0.9.9",
"sha2",
"subtle 2.4.1",
"zeroize",
]
@@ -427,7 +410,7 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3"
dependencies = [
"sha2 0.9.9",
"sha2",
]
[[package]]
@@ -718,6 +701,12 @@ version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e4c78c047431fee22c1a7bb92e00ad095a02a983affe4d8a72e2a2c62c1b94f3"
[[package]]
name = "const_fn"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fbdcdcb6d86f71c5e97409ad45898af11cbc995b4ee8112d59095a28d376c935"
[[package]]
name = "constant_time_eq"
version = "0.1.5"
@@ -739,19 +728,12 @@ checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e"
[[package]]
name = "cookie"
version = "0.16.0"
version = "0.15.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94d4706de1b0fa5b132270cddffa8585166037822e260a944fe161acd137ca05"
checksum = "d5f1c7727e460397e56abc4bddc1d49e07a1ad78fc98eb2e1c8f032a58a2f80d"
dependencies = [
"aes-gcm",
"base64",
"hkdf 0.12.3",
"hmac 0.12.1",
"percent-encoding",
"rand 0.8.5",
"sha2 0.10.2",
"subtle 2.4.1",
"time 0.3.9",
"time 0.2.27",
"version_check",
]
@@ -924,7 +906,6 @@ dependencies = [
"rand 0.7.3",
"thiserror",
"url",
"validator-api-requests",
"validator-client",
]
@@ -1141,16 +1122,6 @@ dependencies = [
"cipher 0.4.3",
]
[[package]]
name = "cupid"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8bad352a84b567cc38a5854e3aa8ee903cb8519a25d0b799b739bafffd1f91a1"
dependencies = [
"gcc",
"rustc_version 0.2.3",
]
[[package]]
name = "curve25519-dalek"
version = "3.2.0"
@@ -1343,9 +1314,9 @@ dependencies = [
[[package]]
name = "dirs"
version = "4.0.0"
version = "3.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059"
checksum = "30baa043103c9d0c2a57cf537cc2f35623889dc0d405e6c3cccfadbc81c71309"
dependencies = [
"dirs-sys",
]
@@ -1361,6 +1332,12 @@ dependencies = [
"winapi",
]
[[package]]
name = "discard"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0"
[[package]]
name = "dkg"
version = "0.1.0"
@@ -1377,7 +1354,7 @@ dependencies = [
"rand_core 0.6.3",
"serde",
"serde_derive",
"sha2 0.9.9",
"sha2",
"thiserror",
"zeroize",
]
@@ -1433,7 +1410,7 @@ dependencies = [
"rand 0.7.3",
"serde",
"serde_bytes",
"sha2 0.9.9",
"sha2",
"zeroize",
]
@@ -1447,7 +1424,7 @@ dependencies = [
"hex",
"rand_core 0.6.3",
"serde",
"sha2 0.9.9",
"sha2",
"thiserror",
"zeroize",
]
@@ -1664,9 +1641,9 @@ dependencies = [
[[package]]
name = "fixed"
version = "1.15.0"
version = "1.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "36a65312835c1097a0c926ff3702df965285fadc33d948b87397ff8961bad881"
checksum = "86d3f4dd10ddfcb0bd2b2efe9f18aff37ed48265fda3e20e5d53f046aba9d50a"
dependencies = [
"az",
"bytemuck",
@@ -1977,12 +1954,6 @@ dependencies = [
"tungstenite",
]
[[package]]
name = "gcc"
version = "0.3.55"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2"
[[package]]
name = "generator"
version = "0.7.0"
@@ -2053,16 +2024,6 @@ dependencies = [
"syn",
]
[[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",
]
[[package]]
name = "git2"
version = "0.14.2"
@@ -2635,7 +2596,7 @@ dependencies = [
"ecdsa",
"elliptic-curve",
"sec1",
"sha2 0.9.9",
"sha2",
"sha3",
]
@@ -2891,7 +2852,6 @@ dependencies = [
"nymsphinx-types",
"rand 0.8.5",
"serde",
"task",
"tokio",
"tokio-util 0.7.3",
"url",
@@ -3113,7 +3073,6 @@ dependencies = [
"rand 0.7.3",
"serde",
"sqlx",
"statistics-common",
"subtle-encoding",
"thiserror",
"tokio",
@@ -3121,7 +3080,6 @@ dependencies = [
"tokio-tungstenite",
"tokio-util 0.7.3",
"url",
"validator-api-requests",
"validator-client",
"vergen",
"version-checker",
@@ -3138,7 +3096,6 @@ dependencies = [
"colored",
"config",
"crypto",
"cupid",
"dirs",
"dotenv",
"futures",
@@ -3156,7 +3113,7 @@ dependencies = [
"rand 0.7.3",
"rocket",
"serde",
"sysinfo",
"serial_test",
"task",
"tokio",
"tokio-util 0.7.3",
@@ -3172,7 +3129,6 @@ dependencies = [
name = "nym-network-requester"
version = "1.0.1"
dependencies = [
"async-trait",
"clap 2.34.0",
"dirs",
"futures",
@@ -3189,7 +3145,7 @@ dependencies = [
"serde",
"socks5-requests",
"sqlx",
"statistics-common",
"statistics",
"thiserror",
"tokio",
"tokio-tungstenite",
@@ -3206,7 +3162,7 @@ dependencies = [
"rocket",
"serde",
"sqlx",
"statistics-common",
"statistics",
"thiserror",
"tokio",
"tokio-tungstenite",
@@ -3364,7 +3320,7 @@ dependencies = [
"rand 0.8.5",
"serde",
"serde_derive",
"sha2 0.9.9",
"sha2",
"thiserror",
]
@@ -3895,18 +3851,6 @@ dependencies = [
"plotters-backend",
]
[[package]]
name = "polyval"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8419d2b623c7c0896ff2d5d96e2cb4ede590fed28fcc34934f4c33c036e620a1"
dependencies = [
"cfg-if 1.0.0",
"cpufeatures",
"opaque-debug 0.3.0",
"universal-hash",
]
[[package]]
name = "ppv-lite86"
version = "0.2.16"
@@ -3970,6 +3914,12 @@ dependencies = [
"version_check",
]
[[package]]
name = "proc-macro-hack"
version = "0.5.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5"
[[package]]
name = "proc-macro2"
version = "1.0.37"
@@ -4531,9 +4481,9 @@ dependencies = [
[[package]]
name = "rocket"
version = "0.5.0-rc.2"
version = "0.5.0-rc.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "98ead083fce4a405feb349cf09abdf64471c6077f14e0ce59364aa90d4b99317"
checksum = "0a71c18c42a0eb15bf3816831caf0dad11e7966f2a41aaf486a701979c4dd1f2"
dependencies = [
"async-stream",
"async-trait",
@@ -4549,7 +4499,7 @@ dependencies = [
"memchr",
"multer",
"num_cpus",
"parking_lot 0.12.0",
"parking_lot 0.11.2",
"pin-project-lite",
"rand 0.8.5",
"ref-cast",
@@ -4559,10 +4509,10 @@ dependencies = [
"serde_json",
"state",
"tempfile",
"time 0.3.9",
"time 0.2.27",
"tokio",
"tokio-stream",
"tokio-util 0.7.3",
"tokio-util 0.6.9",
"ubyte",
"version_check",
"yansi",
@@ -4570,9 +4520,9 @@ dependencies = [
[[package]]
name = "rocket_codegen"
version = "0.5.0-rc.2"
version = "0.5.0-rc.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d6aeb6bb9c61e9cd2c00d70ea267bf36f76a4cc615e5908b349c2f9d93999b47"
checksum = "66f5fa462f7eb958bba8710c17c5d774bbbd59809fa76fb1957af7e545aea8bb"
dependencies = [
"devise",
"glob",
@@ -4601,18 +4551,19 @@ dependencies = [
[[package]]
name = "rocket_http"
version = "0.5.0-rc.2"
version = "0.5.0-rc.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2ded65d127954de3c12471630bf4b81a2792f065984461e65b91d0fdaafc17a2"
checksum = "23c8b7d512d2fcac2316ebe590cde67573844b99e6cc9ee0f53375fa16e25ebd"
dependencies = [
"cookie",
"either",
"futures",
"http",
"hyper",
"indexmap",
"log",
"memchr",
"mime",
"parking_lot 0.11.2",
"pear",
"percent-encoding",
"pin-project-lite",
@@ -4621,16 +4572,16 @@ dependencies = [
"smallvec 1.8.0",
"stable-pattern",
"state",
"time 0.3.9",
"time 0.2.27",
"tokio",
"uncased",
]
[[package]]
name = "rocket_okapi"
version = "0.8.0-rc.2"
version = "0.8.0-rc.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "489f4f5b120762f7974e65b919fc462d0660fd8b839026d8985b850fe5acccb0"
checksum = "0025aa04994af8cd8e1fcdd5a73579a395c941ae090ecb0a39b41cca7e237a20"
dependencies = [
"either",
"log",
@@ -4644,9 +4595,9 @@ dependencies = [
[[package]]
name = "rocket_okapi_codegen"
version = "0.8.0-rc.2"
version = "0.8.0-rc.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "54f94d1ffe41472e08463d7a2674f1db04dc4df745285e8369b33d3cfd6b0308"
checksum = "dc114779fc27afb78179233e966f469e47fd7a98dc15181cff2574cdddb65612"
dependencies = [
"darling",
"proc-macro2",
@@ -4657,9 +4608,9 @@ dependencies = [
[[package]]
name = "rocket_sync_db_pools"
version = "0.1.0-rc.2"
version = "0.1.0-rc.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5fa48b6ab25013e9812f1b0c592741900b3a2a83c0936292e0565c0ac842f558"
checksum = "38cfdfebd552d075c368e641c88a5cd6ce1c58c5c710548aeb777abb48830f4b"
dependencies = [
"r2d2",
"rocket",
@@ -4670,9 +4621,9 @@ dependencies = [
[[package]]
name = "rocket_sync_db_pools_codegen"
version = "0.1.0-rc.2"
version = "0.1.0-rc.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "280ef2d232923e69cb93da156972eb5476a7cce5ba44843f6608f46a4abf7aab"
checksum = "5267808c094db5366e1d8925aaf9f2ce05ff9b3bd92cb18c7040a1fe219c2e25"
dependencies = [
"devise",
"quote",
@@ -4769,9 +4720,9 @@ dependencies = [
[[package]]
name = "schemars"
version = "0.8.10"
version = "0.8.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1847b767a3d62d95cbf3d8a9f0e421cf57a0d8aa4f411d4b16525afb0284d4ed"
checksum = "c6b5a3c80cea1ab61f4260238409510e814e38b4b563c06044edf91e7dc070e3"
dependencies = [
"dyn-clone",
"indexmap",
@@ -4782,9 +4733,9 @@ dependencies = [
[[package]]
name = "schemars_derive"
version = "0.8.10"
version = "0.8.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af4d7e1b012cb3d9129567661a63755ea4b8a7386d339dc945ae187e403c6743"
checksum = "41ae4dce13e8614c46ac3c38ef1c0d668b101df6ac39817aebdaa26642ddae9b"
dependencies = [
"proc-macro2",
"quote",
@@ -4963,9 +4914,9 @@ dependencies = [
[[package]]
name = "serde_derive_internals"
version = "0.26.0"
version = "0.25.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85bf8229e7920a9f636479437026331ce11aa132b4dde37d121944a44d6e5f3c"
checksum = "1dbab34ca63057a1f15280bdf3c39f2b1eb1b54c17e98360e511637aef7418c6"
dependencies = [
"proc-macro2",
"quote",
@@ -5018,6 +4969,28 @@ dependencies = [
"yaml-rust",
]
[[package]]
name = "serial_test"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e0bccbcf40c8938196944a3da0e133e031a33f4d6b72db3bda3cc556e361905d"
dependencies = [
"lazy_static",
"parking_lot 0.11.2",
"serial_test_derive",
]
[[package]]
name = "serial_test_derive"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2acd6defeddb41eb60bb468f8825d0cfd0c2a76bc03bfd235b6a1dc4f6a1ad5"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "sha-1"
version = "0.8.2"
@@ -5054,6 +5027,21 @@ dependencies = [
"digest 0.10.3",
]
[[package]]
name = "sha1"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1da05c97445caa12d05e848c4a4fcbbea29e748ac28f7e80e9b010392063770"
dependencies = [
"sha1_smol",
]
[[package]]
name = "sha1_smol"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012"
[[package]]
name = "sha2"
version = "0.9.9"
@@ -5067,17 +5055,6 @@ dependencies = [
"opaque-debug 0.3.0",
]
[[package]]
name = "sha2"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "55deaec60f81eefe3cce0dc50bda92d6d8e88f2a27df7c5033b42afeb1ed2676"
dependencies = [
"cfg-if 1.0.0",
"cpufeatures",
"digest 0.10.3",
]
[[package]]
name = "sha3"
version = "0.9.1"
@@ -5228,7 +5205,7 @@ dependencies = [
"log",
"rand 0.7.3",
"rand_distr",
"sha2 0.9.9",
"sha2",
"subtle 2.4.1",
]
@@ -5311,7 +5288,7 @@ dependencies = [
"paste",
"percent-encoding",
"rustls",
"sha2 0.9.9",
"sha2",
"smallvec 1.8.0",
"sqlformat",
"sqlx-rt",
@@ -5335,7 +5312,7 @@ dependencies = [
"once_cell",
"proc-macro2",
"quote",
"sha2 0.9.9",
"sha2",
"sqlx-core",
"sqlx-rt",
"syn",
@@ -5363,10 +5340,19 @@ dependencies = [
]
[[package]]
name = "state"
version = "0.5.3"
name = "standback"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dbe866e1e51e8260c9eed836a042a5e7f6726bb2b411dffeaa712e19c388f23b"
checksum = "e113fb6f3de07a243d434a56ec6f186dfd51cb08448239fe7bcae73f87ff28ff"
dependencies = [
"version_check",
]
[[package]]
name = "state"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87cf4f5369e6d3044b5e365c9690f451516ac8f0954084622b49ea3fde2f6de5"
dependencies = [
"loom",
]
@@ -5378,20 +5364,64 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
[[package]]
name = "statistics-common"
name = "statistics"
version = "1.0.1"
dependencies = [
"async-trait",
"log",
"network-defaults",
"reqwest",
"serde",
"serde_json",
"sqlx",
"thiserror",
"tokio",
]
[[package]]
name = "stdweb"
version = "0.4.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d022496b16281348b52d0e30ae99e01a73d737b2f45d38fed4edf79f9325a1d5"
dependencies = [
"discard",
"rustc_version 0.2.3",
"stdweb-derive",
"stdweb-internal-macros",
"stdweb-internal-runtime",
"wasm-bindgen",
]
[[package]]
name = "stdweb-derive"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c87a60a40fccc84bef0652345bbbbbe20a605bf5d0ce81719fc476f5c03b50ef"
dependencies = [
"proc-macro2",
"quote",
"serde",
"serde_derive",
"syn",
]
[[package]]
name = "stdweb-internal-macros"
version = "0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "58fa5ff6ad0d98d1ffa8cb115892b6e69d67799f6763e162a1c9db421dc22e11"
dependencies = [
"base-x",
"proc-macro2",
"quote",
"serde",
"serde_derive",
"serde_json",
"sha1",
"syn",
]
[[package]]
name = "stdweb-internal-runtime"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0"
[[package]]
name = "stringprep"
version = "0.1.2"
@@ -5480,21 +5510,6 @@ dependencies = [
"unicode-xid",
]
[[package]]
name = "sysinfo"
version = "0.24.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a6a8e71535da31837213ac114531d31def75d7aebd133264e420a3451fa7f703"
dependencies = [
"cfg-if 1.0.0",
"core-foundation-sys",
"libc",
"ntapi",
"once_cell",
"rayon",
"winapi",
]
[[package]]
name = "tap"
version = "1.0.1"
@@ -5546,7 +5561,7 @@ dependencies = [
"serde_bytes",
"serde_json",
"serde_repr",
"sha2 0.9.9",
"sha2",
"signature",
"subtle 2.4.1",
"subtle-encoding",
@@ -5684,6 +5699,21 @@ dependencies = [
"winapi",
]
[[package]]
name = "time"
version = "0.2.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4752a97f8eebd6854ff91f1c1824cd6160626ac4bd44287f7f4ea2035a02a242"
dependencies = [
"const_fn",
"libc",
"standback",
"stdweb",
"time-macros 0.1.1",
"version_check",
"winapi",
]
[[package]]
name = "time"
version = "0.3.9"
@@ -5694,7 +5724,17 @@ dependencies = [
"libc",
"num_threads",
"serde",
"time-macros",
"time-macros 0.2.4",
]
[[package]]
name = "time-macros"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "957e9c6e26f12cb6d0dd7fc776bb67a706312e7299aed74c8dd5b17ebb27e2f1"
dependencies = [
"proc-macro-hack",
"time-macros-impl",
]
[[package]]
@@ -5703,6 +5743,19 @@ version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42657b1a6f4d817cda8e7a0ace261fe0cc946cf3a80314390b22cc61ae080792"
[[package]]
name = "time-macros-impl"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd3c141a1b43194f3f56a1411225df8646c55781d5f26db825b3d98507eb482f"
dependencies = [
"proc-macro-hack",
"proc-macro2",
"quote",
"standback",
"syn",
]
[[package]]
name = "tiny-keccak"
version = "2.0.2"
@@ -6188,16 +6241,6 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e"
[[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.5",
"subtle 2.4.1",
]
[[package]]
name = "untrusted"
version = "0.7.1"
@@ -6233,10 +6276,6 @@ checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7"
name = "validator-api-requests"
version = "0.1.0"
dependencies = [
"bs58",
"coconut-interface",
"cosmrs",
"getset",
"mixnet-contract-common",
"schemars",
"serde",
@@ -6269,7 +6308,7 @@ dependencies = [
"reqwest",
"serde",
"serde_json",
"sha2 0.9.9",
"sha2",
"thiserror",
"tokio",
"ts-rs",
@@ -6329,7 +6368,7 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]]
name = "vesting-contract"
version = "1.0.1"
version = "1.0.0"
dependencies = [
"config",
"cosmwasm-std",
+1 -1
View File
@@ -81,4 +81,4 @@ default-members = [
"explorer-api",
]
exclude = ["explorer", "contracts", "tokenomics-py", "clients/webassembly", "nym-wallet", "nym-connect"]
exclude = ["explorer", "contracts", "tokenomics-py", "clients/webassembly", "nym-wallet"]
+5 -34
View File
@@ -1,13 +1,11 @@
test-all: test cargo-test-expensive
test: build clippy-all cargo-test wasm fmt
no-clippy: build cargo-test wasm fmt
happy: fmt clippy-happy test
clippy-all: clippy-all-main clippy-all-contracts clippy-all-wallet clippy-all-connect
clippy-happy: clippy-happy-main clippy-happy-contracts clippy-happy-wallet clippy-happy-connect
cargo-test: test-main test-contracts test-wallet test-connect
cargo-test-expensive: test-main-expensive test-contracts-expensive test-wallet-expensive test-connect-expensive
build: build-contracts build-wallet build-main build-connect
fmt: fmt-main fmt-contracts fmt-wallet fmt-connect
clippy-all: clippy-all-main clippy-all-contracts clippy-all-wallet
clippy-happy: clippy-happy-main clippy-happy-contracts clippy-happy-wallet
cargo-test: test-main test-contracts test-wallet
build: build-contracts build-wallet build-main
fmt: fmt-main fmt-contracts fmt-wallet
clippy-happy-main:
cargo clippy
@@ -18,9 +16,6 @@ clippy-happy-contracts:
clippy-happy-wallet:
cargo clippy --manifest-path nym-wallet/Cargo.toml
clippy-happy-connect:
cargo clippy --manifest-path nym-connect/Cargo.toml
clippy-all-main:
cargo clippy --workspace --all-features -- -D warnings
@@ -30,33 +25,15 @@ clippy-all-contracts:
clippy-all-wallet:
cargo clippy --workspace --manifest-path nym-wallet/Cargo.toml --all-features -- -D warnings
clippy-all-connect:
cargo clippy --workspace --manifest-path nym-connect/Cargo.toml --all-features -- -D warnings
test-main:
cargo test --all-features --workspace
test-main-expensive:
cargo test --all-features --workspace -- --ignored
test-contracts:
cargo test --manifest-path contracts/Cargo.toml --all-features
test-contracts-expensive:
cargo test --manifest-path contracts/Cargo.toml --all-features -- --ignored
test-wallet:
cargo test --manifest-path nym-wallet/Cargo.toml --all-features
test-wallet-expensive:
cargo test --manifest-path nym-wallet/Cargo.toml --all-features -- --ignored
test-connect:
cargo test --manifest-path nym-connect/Cargo.toml --all-features
test-connect-expensive:
cargo test --manifest-path nym-connect/Cargo.toml --all-features -- --ignored
build-main:
cargo build --workspace
@@ -66,9 +43,6 @@ build-contracts:
build-wallet:
cargo build --manifest-path nym-wallet/Cargo.toml --workspace
build-connect:
cargo build --manifest-path nym-connect/Cargo.toml --workspace
fmt-main:
cargo fmt --all
@@ -78,9 +52,6 @@ fmt-contracts:
fmt-wallet:
cargo fmt --manifest-path nym-wallet/Cargo.toml --all
fmt-connect:
cargo fmt --manifest-path nym-connect/Cargo.toml --all
wasm:
RUSTFLAGS='-C link-arg=-s' cargo build --manifest-path contracts/Cargo.toml --release --target wasm32-unknown-unknown
+2 -2
View File
@@ -9,8 +9,8 @@ The platform is composed of multiple Rust crates. Top-level executable binary cr
* nym-mixnode - shuffles [Sphinx](https://github.com/nymtech/sphinx) packets together to provide privacy against network-level attackers.
* nym-client - an executable which you can build into your own applications. Use it for interacting with Nym nodes.
* nym-socks5-client - a Socks5 proxy you can run on your machine and use with existing applications.
* 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-socks5-client - a Socks5 proxy you can run on your machine, and use with existing applications
* nym-gateway - acts sort of like a mailbox for mixnet messages, removing the need for directly 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.
-8
View File
@@ -1,8 +0,0 @@
Update fonts by doing the following:
1. Go to https://fonts.google.com/specimen/Open+Sans
2. Add all the styles you want and select `@import`
3. Copy the url (e.g. curl https://fonts.googleapis.com/css2\?family\=Open+Sans:ital,wght@0,300\;0,400\;0,500\;0,600\;0,700\;0,800\;1,300\;1,400\;1,500\;1,600\;1,700\;1,800\&display\=swap)
4. Run `curl curl https://fonts.googleapis.com/css2\?family\=Open+Sans:ital,wght@0,300\;0,400\;0,500\;0,600\;0,700\;0,800\;1,300\;1,400\;1,500\;1,600\;1,700\;1,800\&display\=swap`
5. Use the response as the CSS import directives and download the font files for each font weight
6. Remember to delete any old font files
-96
View File
@@ -1,96 +0,0 @@
@font-face {
font-family: 'Open Sans';
font-style: italic;
font-weight: 300;
font-stretch: normal;
font-display: swap;
src: url(./memQYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWq8tWZ0Pw86hd0Rk5hkaVc.ttf) format('truetype');
}
@font-face {
font-family: 'Open Sans';
font-style: italic;
font-weight: 400;
font-stretch: normal;
font-display: swap;
src: url(./memQYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWq8tWZ0Pw86hd0Rk8ZkaVc.ttf) format('truetype');
}
@font-face {
font-family: 'Open Sans';
font-style: italic;
font-weight: 500;
font-stretch: normal;
font-display: swap;
src: url(./memQYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWq8tWZ0Pw86hd0Rk_RkaVc.ttf) format('truetype');
}
@font-face {
font-family: 'Open Sans';
font-style: italic;
font-weight: 600;
font-stretch: normal;
font-display: swap;
src: url(./memQYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWq8tWZ0Pw86hd0RkxhjaVc.ttf) format('truetype');
}
@font-face {
font-family: 'Open Sans';
font-style: italic;
font-weight: 700;
font-stretch: normal;
font-display: swap;
src: url(./memQYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWq8tWZ0Pw86hd0RkyFjaVc.ttf) format('truetype');
}
@font-face {
font-family: 'Open Sans';
font-style: italic;
font-weight: 800;
font-stretch: normal;
font-display: swap;
src: url(./memQYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWq8tWZ0Pw86hd0Rk0ZjaVc.ttf) format('truetype');
}
@font-face {
font-family: 'Open Sans';
font-style: normal;
font-weight: 300;
font-stretch: normal;
font-display: swap;
src: url(./memSYaGs126MiZpBA-UvWbX2vVnXBbObj2OVZyOOSr4dVJWUgsiH0C4n.ttf) format('truetype');
}
@font-face {
font-family: 'Open Sans';
font-style: normal;
font-weight: 400;
font-stretch: normal;
font-display: swap;
src: url(./memSYaGs126MiZpBA-UvWbX2vVnXBbObj2OVZyOOSr4dVJWUgsjZ0C4n.ttf) format('truetype');
}
@font-face {
font-family: 'Open Sans';
font-style: normal;
font-weight: 500;
font-stretch: normal;
font-display: swap;
src: url(./memSYaGs126MiZpBA-UvWbX2vVnXBbObj2OVZyOOSr4dVJWUgsjr0C4n.ttf) format('truetype');
}
@font-face {
font-family: 'Open Sans';
font-style: normal;
font-weight: 600;
font-stretch: normal;
font-display: swap;
src: url(./memSYaGs126MiZpBA-UvWbX2vVnXBbObj2OVZyOOSr4dVJWUgsgH1y4n.ttf) format('truetype');
}
@font-face {
font-family: 'Open Sans';
font-style: normal;
font-weight: 700;
font-stretch: normal;
font-display: swap;
src: url(./memSYaGs126MiZpBA-UvWbX2vVnXBbObj2OVZyOOSr4dVJWUgsg-1y4n.ttf) format('truetype');
}
@font-face {
font-family: 'Open Sans';
font-style: normal;
font-weight: 800;
font-stretch: normal;
font-display: swap;
src: url(./memSYaGs126MiZpBA-UvWbX2vVnXBbObj2OVZyOOSr4dVJWUgshZ1y4n.ttf) format('truetype');
}
+2 -2
View File
@@ -7,7 +7,7 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
dirs = "4.0"
dirs = "3.0"
futures = "0.3"
humantime-serde = "1.0"
log = "0.4"
@@ -32,4 +32,4 @@ validator-client = { path = "../../common/client-libs/validator-client" }
tempfile = "3.1.0"
[features]
coconut = ["gateway-client/coconut", "gateway-requests/coconut"]
coconut = ["gateway-client/coconut", "gateway-requests/coconut"]
+15 -26
View File
@@ -114,8 +114,12 @@ impl<T: NymConfig> Config<T> {
self.client.disabled_credentials_mode = disabled_credentials_mode;
}
pub fn with_gateway_endpoint(&mut self, gateway_endpoint: GatewayEndpoint) {
self.client.gateway_endpoint = gateway_endpoint;
pub fn with_gateway_endpoint<S: Into<String>>(&mut self, id: S, owner: S, listener: S) {
self.client.gateway_endpoint = GatewayEndpoint {
gateway_id: id.into(),
gateway_owner: owner.into(),
gateway_listener: listener.into(),
};
}
pub fn with_gateway_id<S: Into<String>>(&mut self, id: S) {
@@ -138,7 +142,7 @@ impl<T: NymConfig> Config<T> {
pub fn set_high_default_traffic_volume(&mut self) {
self.debug.average_packet_delay = Duration::from_millis(10);
self.debug.loop_cover_traffic_average_delay = Duration::from_millis(2_000_000); // basically don't really send cover messages
self.debug.loop_cover_traffic_average_delay = Duration::from_millis(2000000); // basically don't really send cover messages
self.debug.message_sending_average_delay = Duration::from_millis(4); // 250 "real" messages / s
}
@@ -202,10 +206,6 @@ impl<T: NymConfig> Config<T> {
self.client.gateway_endpoint.gateway_listener.clone()
}
pub fn get_gateway_endpoint(&self) -> &GatewayEndpoint {
&self.client.gateway_endpoint
}
pub fn get_database_path(&self) -> PathBuf {
self.client.database_path.clone()
}
@@ -272,31 +272,20 @@ impl<T: NymConfig> Default for Config<T> {
}
}
#[derive(Clone, Debug, Default, Deserialize, PartialEq, Eq, Serialize)]
pub struct GatewayEndpoint {
#[derive(Debug, Default, Deserialize, PartialEq, Serialize)]
struct GatewayEndpoint {
/// gateway_id specifies ID of the gateway to which the client should send messages.
/// If initially omitted, a random gateway will be chosen from the available topology.
pub gateway_id: String,
gateway_id: String,
/// Address of the gateway owner to which the client should send messages.
pub gateway_owner: String,
gateway_owner: String,
/// Address of the gateway listener to which all client requests should be sent.
pub gateway_listener: String,
gateway_listener: String,
}
impl From<topology::gateway::Node> for GatewayEndpoint {
fn from(node: topology::gateway::Node) -> GatewayEndpoint {
let gateway_listener = node.clients_address();
GatewayEndpoint {
gateway_id: node.identity_key.to_base58_string(),
gateway_owner: node.owner,
gateway_listener,
}
}
}
#[derive(Debug, Deserialize, PartialEq, Eq, Serialize)]
#[derive(Debug, Deserialize, PartialEq, Serialize)]
pub struct Client<T> {
/// Version of the client for which this configuration was created.
#[serde(default = "missing_string_value")]
@@ -356,7 +345,7 @@ pub struct Client<T> {
nym_root_directory: PathBuf,
#[serde(skip)]
super_struct: PhantomData<T>,
super_struct: PhantomData<*const T>,
}
impl<T: NymConfig> Default for Client<T> {
@@ -419,7 +408,7 @@ impl<T: NymConfig> Client<T> {
}
}
#[derive(Debug, Default, Deserialize, PartialEq, Eq, Serialize)]
#[derive(Debug, Default, Deserialize, PartialEq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct Logging {}
-137
View File
@@ -1,137 +0,0 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
//! Collection of initialization steps used by client implementations
use std::{sync::Arc, time::Duration};
use config::NymConfig;
use crypto::asymmetric::{encryption, identity};
use gateway_client::GatewayClient;
use gateway_requests::registration::handshake::SharedKeys;
use nymsphinx::addressing::clients::Recipient;
use nymsphinx::addressing::nodes::NodeIdentity;
use rand::rngs::OsRng;
use rand::seq::SliceRandom;
use rand::thread_rng;
use topology::{filter::VersionFilterable, gateway};
use url::Url;
use crate::{
client::key_manager::KeyManager,
config::{persistence::key_pathfinder::ClientKeyPathfinder, Config},
};
pub async fn query_gateway_details(
validator_servers: Vec<Url>,
chosen_gateway_id: Option<&str>,
) -> gateway::Node {
let validator_api = validator_servers
.choose(&mut thread_rng())
.expect("The list of validator apis is empty");
let validator_client = validator_client::ApiClient::new(validator_api.clone());
log::trace!("Fetching list of gateways from: {}", validator_api);
let gateways = validator_client.get_cached_gateways().await.unwrap();
let valid_gateways = gateways
.into_iter()
.filter_map(|gateway| gateway.try_into().ok())
.collect::<Vec<gateway::Node>>();
let filtered_gateways = valid_gateways.filter_by_version(env!("CARGO_PKG_VERSION"));
// if we have chosen particular gateway - use it, otherwise choose a random one.
// (remember that in active topology all gateways have at least 100 reputation so should
// be working correctly)
if let Some(gateway_id) = chosen_gateway_id {
filtered_gateways
.iter()
.find(|gateway| gateway.identity_key.to_base58_string() == gateway_id)
.expect(&*format!("no gateway with id {} exists!", gateway_id))
.clone()
} else {
filtered_gateways
.choose(&mut rand::thread_rng())
.expect("there are no gateways on the network!")
.clone()
}
}
pub async fn register_with_gateway_and_store_keys<T>(
gateway_details: gateway::Node,
config: &Config<T>,
) where
T: NymConfig,
{
let mut rng = OsRng;
let mut key_manager = KeyManager::new(&mut rng);
let shared_keys = register_with_gateway(&gateway_details, key_manager.identity_keypair()).await;
key_manager.insert_gateway_shared_key(shared_keys);
let pathfinder = ClientKeyPathfinder::new_from_config(config);
key_manager
.store_keys(&pathfinder)
.expect("Failed to generated keys");
}
async fn register_with_gateway(
gateway: &gateway::Node,
our_identity: Arc<identity::KeyPair>,
) -> Arc<SharedKeys> {
let timeout = Duration::from_millis(1500);
let mut gateway_client = GatewayClient::new_init(
gateway.clients_address(),
gateway.identity_key,
gateway.owner.clone(),
our_identity.clone(),
timeout,
);
gateway_client
.establish_connection()
.await
.expect("failed to establish connection with the gateway!");
gateway_client
.perform_initial_authentication()
.await
.expect("failed to register with the gateway!")
}
pub fn show_address<T>(config: &Config<T>)
where
T: config::NymConfig,
{
fn load_identity_keys(pathfinder: &ClientKeyPathfinder) -> identity::KeyPair {
let identity_keypair: identity::KeyPair =
pemstore::load_keypair(&pemstore::KeyPairPath::new(
pathfinder.private_identity_key().to_owned(),
pathfinder.public_identity_key().to_owned(),
))
.expect("Failed to read stored identity key files");
identity_keypair
}
fn load_sphinx_keys(pathfinder: &ClientKeyPathfinder) -> encryption::KeyPair {
let sphinx_keypair: encryption::KeyPair =
pemstore::load_keypair(&pemstore::KeyPairPath::new(
pathfinder.private_encryption_key().to_owned(),
pathfinder.public_encryption_key().to_owned(),
))
.expect("Failed to read stored sphinx key files");
sphinx_keypair
}
let pathfinder = ClientKeyPathfinder::new_from_config(config);
let identity_keypair = load_identity_keys(&pathfinder);
let sphinx_keypair = load_sphinx_keys(&pathfinder);
let client_recipient = Recipient::new(
*identity_keypair.public_key(),
*sphinx_keypair.public_key(),
// TODO: below only works under assumption that gateway address == gateway id
// (which currently is true)
NodeIdentity::from_base58_string(config.get_gateway_id()).unwrap(),
);
println!("\nThe address of this client is: {}", client_recipient);
}
-1
View File
@@ -1,3 +1,2 @@
pub mod client;
pub mod config;
pub mod init;
+3453
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -26,4 +26,4 @@ pemstore = { path = "../../common/pemstore" }
validator-client = { path = "../../common/client-libs/validator-client", features = ["nymd-client"] }
[features]
coconut = ["credentials/coconut"]
coconut = ["credentials/coconut"]
+7 -7
View File
@@ -1,13 +1,14 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::error::Result;
use crate::{MNEMONIC, NYMD_URL};
use bip39::Mnemonic;
use network_defaults::{DEFAULT_NETWORK, MIX_DENOM, VOUCHER_INFO};
use std::str::FromStr;
use url::Url;
use validator_client::nymd;
use crate::error::Result;
use crate::{MNEMONIC, NYMD_URL};
use network_defaults::{DEFAULT_NETWORK, MIX_DENOM, VOUCHER_INFO};
use validator_client::nymd::traits::CoconutBandwidthSigningClient;
use validator_client::nymd::{Coin, Fee, NymdClient, SigningNymdClient};
@@ -19,10 +20,9 @@ impl Client {
pub fn new() -> Self {
let nymd_url = Url::from_str(NYMD_URL).unwrap();
let mnemonic = Mnemonic::from_str(MNEMONIC).unwrap();
let config = nymd::Config::try_from_nym_network_details(&DEFAULT_NETWORK.details())
.expect("failed to construct valid validator client config with the provided network");
let nymd_client =
NymdClient::connect_with_mnemonic(config, nymd_url.as_ref(), mnemonic, None).unwrap();
NymdClient::connect_with_mnemonic(DEFAULT_NETWORK, nymd_url.as_ref(), mnemonic, None)
.unwrap();
Client { nymd_client }
}
+2402
View File
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -20,7 +20,7 @@ futures = "0.3" # bunch of futures stuff, however, now that I think about it, it
url = "2.2"
clap = "2.33.0" # for the command line arguments
dirs = "4.0"
dirs = "3.0" # for determining default store directories in config
dotenv = "0.15.0" # for obtaining environmental variables (only used for RUST_LOG for time being)
log = "0.4" # self explanatory
pretty_env_logger = "0.4" # for formatting log messages
@@ -55,4 +55,4 @@ eth = []
serde_json = "1.0" # for the "textsend" example
[build-dependencies]
vergen = { version = "5", default-features = false, features = ["build", "git", "rustc", "cargo"] }
vergen = { version = "5", default-features = false, features = ["build", "git", "rustc", "cargo"] }
+2 -2
View File
@@ -11,7 +11,7 @@ use std::path::PathBuf;
mod template;
#[derive(Debug, Deserialize, PartialEq, Eq, Serialize, Clone, Copy)]
#[derive(Debug, Deserialize, PartialEq, Serialize, Clone, Copy)]
#[serde(deny_unknown_fields)]
pub enum SocketType {
WebSocket,
@@ -105,7 +105,7 @@ impl Config {
}
}
#[derive(Debug, Deserialize, PartialEq, Eq, Serialize)]
#[derive(Debug, Deserialize, PartialEq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct Socket {
socket_type: SocketType,
+153 -83
View File
@@ -2,8 +2,22 @@
// SPDX-License-Identifier: Apache-2.0
use clap::{App, Arg, ArgMatches};
use client_core::config::GatewayEndpoint;
use client_core::client::key_manager::KeyManager;
use client_core::config::persistence::key_pathfinder::ClientKeyPathfinder;
use config::NymConfig;
use crypto::asymmetric::{encryption, identity};
use gateway_client::GatewayClient;
use gateway_requests::registration::handshake::SharedKeys;
use nymsphinx::addressing::clients::Recipient;
use nymsphinx::addressing::nodes::NodeIdentity;
use rand::rngs::OsRng;
use rand::seq::SliceRandom;
use rand::thread_rng;
use std::convert::TryInto;
use std::sync::Arc;
use std::time::Duration;
use topology::{filter::VersionFilterable, gateway};
use url::Url;
use crate::client::config::Config;
use crate::commands::override_config;
@@ -28,11 +42,6 @@ pub fn command_args<'a, 'b>() -> clap::App<'a, 'b> {
.help("Id of the gateway we are going to connect to.")
.takes_value(true)
)
.arg(Arg::with_name("force-register-gateway")
.long("force-register-gateway")
.help("Force register gateway. WARNING: this will overwrite any existing keys for the given id, potentially causing loss of access.")
.takes_value(false)
)
.arg(Arg::with_name("validators")
.long("validators")
.help("Comma separated list of rest endpoints of the validators")
@@ -79,47 +88,161 @@ pub fn command_args<'a, 'b>() -> clap::App<'a, 'b> {
app
}
async fn register_with_gateway(
gateway: &gateway::Node,
our_identity: Arc<identity::KeyPair>,
) -> Arc<SharedKeys> {
let timeout = Duration::from_millis(1500);
let mut gateway_client = GatewayClient::new_init(
gateway.clients_address(),
gateway.identity_key,
gateway.owner.clone(),
our_identity.clone(),
timeout,
);
gateway_client
.establish_connection()
.await
.expect("failed to establish connection with the gateway!");
gateway_client
.perform_initial_authentication()
.await
.expect("failed to register with the gateway!")
}
async fn gateway_details(
validator_servers: Vec<Url>,
chosen_gateway_id: Option<&str>,
) -> gateway::Node {
let validator_api = validator_servers
.choose(&mut thread_rng())
.expect("The list of validator apis is empty");
let validator_client = validator_client::ApiClient::new(validator_api.clone());
log::trace!("Fetching list of gateways from: {}", validator_api);
let gateways = validator_client.get_cached_gateways().await.unwrap();
let valid_gateways = gateways
.into_iter()
.filter_map(|gateway| gateway.try_into().ok())
.collect::<Vec<gateway::Node>>();
let filtered_gateways = valid_gateways.filter_by_version(env!("CARGO_PKG_VERSION"));
// if we have chosen particular gateway - use it, otherwise choose a random one.
// (remember that in active topology all gateways have at least 100 reputation so should
// be working correctly)
if let Some(gateway_id) = chosen_gateway_id {
filtered_gateways
.iter()
.find(|gateway| gateway.identity_key.to_base58_string() == gateway_id)
.expect(&*format!("no gateway with id {} exists!", gateway_id))
.clone()
} else {
filtered_gateways
.choose(&mut rand::thread_rng())
.expect("there are no gateways on the network!")
.clone()
}
}
fn show_address(config: &Config) {
fn load_identity_keys(pathfinder: &ClientKeyPathfinder) -> identity::KeyPair {
let identity_keypair: identity::KeyPair =
pemstore::load_keypair(&pemstore::KeyPairPath::new(
pathfinder.private_identity_key().to_owned(),
pathfinder.public_identity_key().to_owned(),
))
.expect("Failed to read stored identity key files");
identity_keypair
}
fn load_sphinx_keys(pathfinder: &ClientKeyPathfinder) -> encryption::KeyPair {
let sphinx_keypair: encryption::KeyPair =
pemstore::load_keypair(&pemstore::KeyPairPath::new(
pathfinder.private_encryption_key().to_owned(),
pathfinder.public_encryption_key().to_owned(),
))
.expect("Failed to read stored sphinx key files");
sphinx_keypair
}
let pathfinder = ClientKeyPathfinder::new_from_config(config.get_base());
let identity_keypair = load_identity_keys(&pathfinder);
let sphinx_keypair = load_sphinx_keys(&pathfinder);
let client_recipient = Recipient::new(
*identity_keypair.public_key(),
*sphinx_keypair.public_key(),
// TODO: below only works under assumption that gateway address == gateway id
// (which currently is true)
NodeIdentity::from_base58_string(config.get_base().get_gateway_id()).unwrap(),
);
println!("\nThe address of this client is: {}", client_recipient);
}
pub async fn execute(matches: ArgMatches<'static>) {
println!("Initialising client...");
let id = matches.value_of("id").unwrap(); // required for now
let already_init = Config::default_config_file_path(Some(id)).exists();
if already_init {
println!(
"Client \"{}\" was already initialised before! \
Config information will be overwritten (but keys will be kept)!",
id
);
}
// Usually you only register with the gateway on the first init, however you can force
// re-registering if wanted.
let user_wants_force_register = matches.is_present("force-register-gateway");
// If the client was already initialized, don't generate new keys and don't re-register with
// the gateway (because this would create a new shared key).
// Unless the user really wants to.
let register_gateway = !already_init || user_wants_force_register;
// Attempt to use a user-provided gateway, if possible
let user_chosen_gateway_id = matches.value_of("gateway");
let already_init = if Config::default_config_file_path(Some(id)).exists() {
if matches.is_present("gateway") {
panic!("At the moment, gateway information can't be overwritten. If you want to point to a different gateway, client {}'s directory will need to be manually removed", id);
}
println!("Client \"{}\" was already initialised before! Config information will be overwritten (but keys will be kept)!", id);
true
} else {
false
};
let mut config = Config::new(id);
let mut rng = OsRng;
// TODO: ideally that should be the last thing that's being done to config.
// However, we are later further overriding it with gateway id
config = override_config(config, &matches);
if matches.is_present("fastmode") {
config.get_base_mut().set_high_default_traffic_volume();
}
let gateway = setup_gateway(id, register_gateway, user_chosen_gateway_id, &config).await;
config.get_base_mut().with_gateway_endpoint(gateway);
// if client was already initialised, don't generate new keys, not re-register with gateway
// (because this would create new shared key)
if !already_init {
// create identity, encryption and ack keys.
let mut key_manager = KeyManager::new(&mut rng);
let chosen_gateway_id = matches.value_of("gateway");
log::trace!("Chosen gateway: {:?}", chosen_gateway_id);
let gateway_details = gateway_details(
config.get_base().get_validator_api_endpoints(),
chosen_gateway_id,
)
.await;
log::trace!("Used gateway: {}", gateway_details);
let shared_keys =
register_with_gateway(&gateway_details, key_manager.identity_keypair()).await;
config.get_base_mut().with_gateway_endpoint(
gateway_details.identity_key.to_base58_string(),
gateway_details.owner.clone(),
gateway_details.clients_address(),
);
key_manager.insert_gateway_shared_key(shared_keys);
let pathfinder = ClientKeyPathfinder::new_from_config(config.get_base());
key_manager
.store_keys(&pathfinder)
.expect("Failed to generated keys");
println!("Saved all generated keys");
}
let config_save_location = config.get_config_file_save_location();
config
.save_to_file(None)
.expect("Failed to save the config file");
println!("Saved configuration file to {:?}", config_save_location);
println!("Using gateway: {}", config.get_base().get_gateway_id());
log::debug!("Gateway id: {}", config.get_base().get_gateway_id());
@@ -130,58 +253,5 @@ pub async fn execute(matches: ArgMatches<'static>) {
);
println!("Client configuration completed.");
client_core::init::show_address(config.get_base());
}
async fn setup_gateway(
id: &str,
register: bool,
user_chosen_gateway_id: Option<&str>,
config: &Config,
) -> GatewayEndpoint {
if register {
// Get the gateway details by querying the validator-api. Either pick one at random or use
// the chosen one if it's among the available ones.
println!("Configuring gateway");
let gateway = client_core::init::query_gateway_details(
config.get_base().get_validator_api_endpoints(),
user_chosen_gateway_id,
)
.await;
log::debug!("Querying gateway gives: {}", gateway);
// Registering with gateway by setting up and writing shared keys to disk
log::trace!("Registering gateway");
client_core::init::register_with_gateway_and_store_keys(gateway.clone(), config.get_base())
.await;
println!("Saved all generated keys");
gateway.into()
} else if user_chosen_gateway_id.is_some() {
// Just set the config, don't register or create any keys
// This assumes that the user knows what they are doing, and that the existing keys are
// valid for the gateway being used
println!("Using gateway provided by user, keeping existing keys");
let gateway = client_core::init::query_gateway_details(
config.get_base().get_validator_api_endpoints(),
user_chosen_gateway_id,
)
.await;
log::debug!("Querying gateway gives: {}", gateway);
gateway.into()
} else {
println!("Not registering gateway, will reuse existing config and keys");
match Config::load_from_file(Some(id)) {
Ok(existing_config) => existing_config.get_base().get_gateway_endpoint().clone(),
Err(err) => {
panic!(
"Unable to configure gateway: {err}. \n
Seems like the client was already initialized but it was not possible to read \
the existing configuration file. \n
CAUTION: Consider backing up your gateway keys and try force gateway registration, or \
removing the existing configuration and starting over."
)
}
}
}
show_address(&config);
}
+1 -1
View File
@@ -10,4 +10,4 @@ edition = "2021"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
nymsphinx = { path = "../../../common/nymsphinx" }
nymsphinx = { path = "../../../common/nymsphinx" }
@@ -5,7 +5,7 @@ use serde::{Deserialize, Serialize};
use std::fmt;
// no need to go fancy here like we've done in other places.
#[derive(PartialEq, Eq, Clone, Serialize, Deserialize)]
#[derive(PartialEq, Clone, Serialize, Deserialize)]
pub struct Error {
pub kind: ErrorKind,
pub message: String,
@@ -30,7 +30,7 @@ impl Error {
}
#[repr(u8)]
#[derive(PartialEq, Eq, Clone, Serialize, Deserialize)]
#[derive(PartialEq, Clone, Serialize, Deserialize)]
pub enum ErrorKind {
/// The received request contained no data.
EmptyRequest = 0x01,
+2 -2
View File
@@ -11,7 +11,7 @@ path = "src/lib.rs"
[dependencies]
clap = "2.33.0"
dirs = "4.0"
dirs = "3.0" # for determining default store directories in config
dotenv = "0.15.0"
futures = "0.3"
log = "0.4"
@@ -47,4 +47,4 @@ coconut = ["coconut-interface", "credentials", "gateway-requests/coconut", "gate
eth = []
[build-dependencies]
vergen = { version = "5", default-features = false, features = ["build", "git", "rustc", "cargo"] }
vergen = { version = "5", default-features = false, features = ["build", "git", "rustc", "cargo"] }
+1 -1
View File
@@ -89,7 +89,7 @@ impl Config {
}
}
#[derive(Debug, Deserialize, PartialEq, Eq, Serialize)]
#[derive(Debug, Deserialize, PartialEq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct Socks5 {
/// The port on which the client will be listening for incoming requests
+1 -26
View File
@@ -20,7 +20,6 @@ use client_core::client::topology_control::{
use client_core::config::persistence::key_pathfinder::ClientKeyPathfinder;
use crypto::asymmetric::identity;
use futures::channel::mpsc;
use futures::StreamExt;
use gateway_client::bandwidth::BandwidthController;
use gateway_client::{
AcknowledgementReceiver, AcknowledgementSender, GatewayClient, MixnetMessageReceiver,
@@ -36,17 +35,7 @@ use crate::socks::{
server::SphinxSocksServer,
};
pub mod config;
// Channels used to control the main task from outside
pub type Socks5ControlMessageSender = mpsc::UnboundedSender<Socks5ControlMessage>;
pub type Socks5ControlMessageReceiver = mpsc::UnboundedReceiver<Socks5ControlMessage>;
#[derive(Debug)]
pub enum Socks5ControlMessage {
/// Tell the main task to stop
Stop,
}
pub(crate) mod config;
pub struct NymClient {
/// Client configuration options, including, among other things, packet sending rates,
@@ -283,20 +272,6 @@ impl NymClient {
);
}
// Variant of `run_forever` that listends for remote control messages
pub async fn run_and_listen(&mut self, mut receiver: Socks5ControlMessageReceiver) {
self.start().await;
tokio::select! {
message = receiver.next() => match message {
Some(Socks5ControlMessage::Stop) => {
log::info!("Received: {:?}", message);
log::info!("Shutting down");
}
None => log::info!("none"),
}
}
}
pub async fn start(&mut self) {
info!("Starting nym client");
// channels for inter-component communication
+150 -91
View File
@@ -2,8 +2,20 @@
// SPDX-License-Identifier: Apache-2.0
use clap::{App, Arg, ArgMatches};
use client_core::config::GatewayEndpoint;
use client_core::client::key_manager::KeyManager;
use client_core::config::persistence::key_pathfinder::ClientKeyPathfinder;
use config::NymConfig;
use crypto::asymmetric::{encryption, identity};
use gateway_client::GatewayClient;
use gateway_requests::registration::handshake::SharedKeys;
use nymsphinx::addressing::clients::Recipient;
use nymsphinx::addressing::nodes::NodeIdentity;
use rand::{prelude::SliceRandom, rngs::OsRng, thread_rng};
use std::convert::TryInto;
use std::sync::Arc;
use std::time::Duration;
use topology::{filter::VersionFilterable, gateway};
use url::Url;
use crate::client::config::Config;
use crate::commands::override_config;
@@ -34,11 +46,6 @@ pub fn command_args<'a, 'b>() -> clap::App<'a, 'b> {
.help("Id of the gateway we are going to connect to.")
.takes_value(true)
)
.arg(Arg::with_name("force-register-gateway")
.long("force-register-gateway")
.help("Force register gateway. WARNING: this will overwrite any existing keys for the given id, potentially causing loss of access.")
.takes_value(false)
)
.arg(Arg::with_name("validators")
.long("validators")
.help("Comma separated list of rest endpoints of the validators")
@@ -81,110 +88,162 @@ pub fn command_args<'a, 'b>() -> clap::App<'a, 'b> {
app
}
async fn register_with_gateway(
gateway: &gateway::Node,
our_identity: Arc<identity::KeyPair>,
) -> Arc<SharedKeys> {
let timeout = Duration::from_millis(1500);
let mut gateway_client = GatewayClient::new_init(
gateway.clients_address(),
gateway.identity_key,
gateway.owner.clone(),
our_identity.clone(),
timeout,
);
gateway_client
.establish_connection()
.await
.expect("failed to establish connection with the gateway!");
gateway_client
.perform_initial_authentication()
.await
.expect("failed to register with the gateway!")
}
async fn gateway_details(
validator_servers: Vec<Url>,
chosen_gateway_id: Option<&str>,
) -> gateway::Node {
let validator_api = validator_servers
.choose(&mut thread_rng())
.expect("The list of validator apis is empty");
let validator_client = validator_client::ApiClient::new(validator_api.clone());
let gateways = validator_client.get_cached_gateways().await.unwrap();
let valid_gateways = gateways
.into_iter()
.filter_map(|gateway| gateway.try_into().ok())
.collect::<Vec<gateway::Node>>();
let filtered_gateways = valid_gateways.filter_by_version(env!("CARGO_PKG_VERSION"));
// if we have chosen particular gateway - use it, otherwise choose a random one.
// (remember that in active topology all gateways have at least 100 reputation so should
// be working correctly)
if let Some(gateway_id) = chosen_gateway_id {
filtered_gateways
.iter()
.find(|gateway| gateway.identity_key.to_base58_string() == gateway_id)
.expect(&*format!("no gateway with id {} exists!", gateway_id))
.clone()
} else {
filtered_gateways
.choose(&mut rand::thread_rng())
.expect("there are no gateways on the network!")
.clone()
}
}
fn show_address(config: &Config) {
fn load_identity_keys(pathfinder: &ClientKeyPathfinder) -> identity::KeyPair {
let identity_keypair: identity::KeyPair =
pemstore::load_keypair(&pemstore::KeyPairPath::new(
pathfinder.private_identity_key().to_owned(),
pathfinder.public_identity_key().to_owned(),
))
.expect("Failed to read stored identity key files");
identity_keypair
}
fn load_sphinx_keys(pathfinder: &ClientKeyPathfinder) -> encryption::KeyPair {
let sphinx_keypair: encryption::KeyPair =
pemstore::load_keypair(&pemstore::KeyPairPath::new(
pathfinder.private_encryption_key().to_owned(),
pathfinder.public_encryption_key().to_owned(),
))
.expect("Failed to read stored sphinx key files");
sphinx_keypair
}
let pathfinder = ClientKeyPathfinder::new_from_config(config.get_base());
let identity_keypair = load_identity_keys(&pathfinder);
let sphinx_keypair = load_sphinx_keys(&pathfinder);
let client_recipient = Recipient::new(
*identity_keypair.public_key(),
*sphinx_keypair.public_key(),
// TODO: below only works under assumption that gateway address == gateway id
// (which currently is true)
NodeIdentity::from_base58_string(config.get_base().get_gateway_id()).unwrap(),
);
println!("\nThe address of this client is: {}", client_recipient);
}
pub async fn execute(matches: ArgMatches<'static>) {
println!("Initialising client...");
let id = matches.value_of("id").unwrap(); // required for now
let provider_address = matches.value_of("provider").unwrap();
let already_init = Config::default_config_file_path(Some(id)).exists();
if already_init {
println!(
"SOCKS5 client \"{}\" was already initialised before! \
Config information will be overwritten (but keys will be kept)!",
id
);
}
// Usually you only register with the gateway on the first init, however you can force
// re-registering if wanted.
let user_wants_force_register = matches.is_present("force-register-gateway");
// If the client was already initialized, don't generate new keys and don't re-register with
// the gateway (because this would create a new shared key).
// Unless the user really wants to.
let register_gateway = !already_init || user_wants_force_register;
// Attempt to use a user-provided gateway, if possible
let user_chosen_gateway_id = matches.value_of("gateway");
let already_init = if Config::default_config_file_path(Some(id)).exists() {
if matches.is_present("gateway") {
panic!("At the moment, gateway information can't be overwritten. If you want to point to a different gateway, client {}'s directory will need to be manually removed", id);
}
println!("Socks5 client \"{}\" was already initialised before! Config information will be overwritten (but keys will be kept)!", id);
true
} else {
false
};
let mut config = Config::new(id, provider_address);
let mut rng = OsRng;
// TODO: ideally that should be the last thing that's being done to config.
// However, we are later further overriding it with gateway id
config = override_config(config, &matches);
if matches.is_present("fastmode") {
config.get_base_mut().set_high_default_traffic_volume();
}
let gateway = setup_gateway(id, register_gateway, user_chosen_gateway_id, &config).await;
config.get_base_mut().with_gateway_endpoint(gateway);
// if client was already initialised, don't generate new keys, not re-register with gateway
// (because this would create new shared key)
if !already_init {
// create identity, encryption and ack keys.
let mut key_manager = KeyManager::new(&mut rng);
let chosen_gateway_id = matches.value_of("gateway");
let gateway_details = gateway_details(
config.get_base().get_validator_api_endpoints(),
chosen_gateway_id,
)
.await;
let shared_keys =
register_with_gateway(&gateway_details, key_manager.identity_keypair()).await;
config.get_base_mut().with_gateway_endpoint(
gateway_details.identity_key.to_base58_string(),
gateway_details.owner.clone(),
gateway_details.clients_address(),
);
key_manager.insert_gateway_shared_key(shared_keys);
let pathfinder = ClientKeyPathfinder::new_from_config(config.get_base());
key_manager
.store_keys(&pathfinder)
.expect("Failed to generated keys");
println!("Saved all generated keys");
}
let config_save_location = config.get_config_file_save_location();
config
.save_to_file(None)
.expect("Failed to save the config file");
println!("Saved configuration file to {:?}", config_save_location);
println!("Using gateway: {}", config.get_base().get_gateway_id());
log::debug!("Gateway id: {}", config.get_base().get_gateway_id());
log::debug!("Gateway owner: {}", config.get_base().get_gateway_owner());
log::debug!(
"Gateway listener: {}",
config.get_base().get_gateway_listener()
);
println!("Client configuration completed.");
println!("Using gateway: {}", config.get_base().get_gateway_id(),);
println!("Client configuration completed.\n\n\n");
client_core::init::show_address(config.get_base());
}
async fn setup_gateway(
id: &str,
register: bool,
user_chosen_gateway_id: Option<&str>,
config: &Config,
) -> GatewayEndpoint {
if register {
// Get the gateway details by querying the validator-api. Either pick one at random or use
// the chosen one if it's among the available ones.
println!("Configuring gateway");
let gateway = client_core::init::query_gateway_details(
config.get_base().get_validator_api_endpoints(),
user_chosen_gateway_id,
)
.await;
log::debug!("Querying gateway gives: {}", gateway);
// Registering with gateway by setting up and writing shared keys to disk
log::trace!("Registering gateway");
client_core::init::register_with_gateway_and_store_keys(gateway.clone(), config.get_base())
.await;
println!("Saved all generated keys");
gateway.into()
} else if user_chosen_gateway_id.is_some() {
// Just set the config, don't register or create any keys
// This assumes that the user knows what they are doing, and that the existing keys are
// valid for the gateway being used
println!("Using gateway provided by user, keeping existing keys");
let gateway = client_core::init::query_gateway_details(
config.get_base().get_validator_api_endpoints(),
user_chosen_gateway_id,
)
.await;
log::debug!("Querying gateway gives: {}", gateway);
gateway.into()
} else {
println!("Not registering gateway, will reuse existing config and keys");
match Config::load_from_file(Some(id)) {
Ok(existing_config) => existing_config.get_base().get_gateway_endpoint().clone(),
Err(err) => {
panic!(
"Unable to configure gateway: {err}. \n
Seems like the client was already initialized but it was not possible to read \
the existing configuration file. \n
CAUTION: Consider backing up your gateway keys and try force gateway registration, or \
removing the existing configuration and starting over."
)
}
}
}
show_address(&config);
}
+1 -1
View File
@@ -5,7 +5,7 @@ use crate::client::config::Config;
use clap::ArgMatches;
use url::Url;
pub mod init;
pub(crate) mod init;
pub(crate) mod run;
pub(crate) mod upgrade;
+5 -5
View File
@@ -34,16 +34,16 @@ pub fn command_args<'a, 'b>() -> clap::App<'a, 'b> {
.help("Address of the socks5 provider to send messages to.")
.takes_value(true)
)
.arg(Arg::with_name("gateway")
.long("gateway")
.help("Id of the gateway we want to connect to. If overridden, it is user's responsibility to ensure prior registration happened")
.takes_value(true)
)
.arg(Arg::with_name("validators")
.long("validators")
.help("Comma separated list of rest endpoints of the validators")
.takes_value(true),
)
.arg(Arg::with_name("gateway")
.long("gateway")
.help("Id of the gateway we want to connect to. If overridden, it is user's responsibility to ensure prior registration happened")
.takes_value(true)
)
.arg(Arg::with_name("port")
.short("p")
.long("port")
-5
View File
@@ -2,9 +2,4 @@
// SPDX-License-Identifier: Apache-2.0
pub mod client;
// This is only used as we reach into the init functions in nym-connect. We need to refactor the
// init functions so that nym-connect can just call the same init function as the regular socks5
// client.
#[allow(unused)]
pub mod commands;
pub mod socks;
+1 -1
View File
@@ -9,7 +9,7 @@ pub(crate) enum AuthenticationMethods {
NoMethods = 0xFF,
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[derive(Clone, Debug, PartialEq)]
/// A socks5 user with a matching password.
pub struct User {
pub username: String,
+14 -14
View File
@@ -221,7 +221,7 @@
"@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2":
version "1.1.2"
resolved "https://registry.yarnpkg.com/@protobufjs/aspromise/-/aspromise-1.1.2.tgz#9b8b0cc663d669a7d8f6f5d0893a14d348f30fbf"
integrity sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==
integrity sha1-m4sMxmPWaafY9vXQiToU00jzD78=
"@protobufjs/base64@^1.1.2":
version "1.1.2"
@@ -236,12 +236,12 @@
"@protobufjs/eventemitter@^1.1.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz#355cbc98bafad5978f9ed095f397621f1d066b70"
integrity sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==
integrity sha1-NVy8mLr61ZePntCV85diHx0Ga3A=
"@protobufjs/fetch@^1.1.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@protobufjs/fetch/-/fetch-1.1.0.tgz#ba99fb598614af65700c1619ff06d454b0d84c45"
integrity sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==
integrity sha1-upn7WYYUr2VwDBYZ/wbUVLDYTEU=
dependencies:
"@protobufjs/aspromise" "^1.1.1"
"@protobufjs/inquire" "^1.1.0"
@@ -249,27 +249,27 @@
"@protobufjs/float@^1.0.2":
version "1.0.2"
resolved "https://registry.yarnpkg.com/@protobufjs/float/-/float-1.0.2.tgz#5e9e1abdcb73fc0a7cb8b291df78c8cbd97b87d1"
integrity sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==
integrity sha1-Xp4avctz/Ap8uLKR33jIy9l7h9E=
"@protobufjs/inquire@^1.1.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@protobufjs/inquire/-/inquire-1.1.0.tgz#ff200e3e7cf2429e2dcafc1140828e8cc638f089"
integrity sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==
integrity sha1-/yAOPnzyQp4tyvwRQIKOjMY48Ik=
"@protobufjs/path@^1.1.2":
version "1.1.2"
resolved "https://registry.yarnpkg.com/@protobufjs/path/-/path-1.1.2.tgz#6cc2b20c5c9ad6ad0dccfd21ca7673d8d7fbf68d"
integrity sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==
integrity sha1-bMKyDFya1q0NzP0hynZz2Nf79o0=
"@protobufjs/pool@^1.1.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@protobufjs/pool/-/pool-1.1.0.tgz#09fd15f2d6d3abfa9b65bc366506d6ad7846ff54"
integrity sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==
integrity sha1-Cf0V8tbTq/qbZbw2ZQbWrXhG/1Q=
"@protobufjs/utf8@^1.1.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@protobufjs/utf8/-/utf8-1.1.0.tgz#a777360b5b39a1a2e5106f8e858f2fd2d060c570"
integrity sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==
integrity sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=
"@types/json-schema@^7.0.9":
version "7.0.11"
@@ -282,9 +282,9 @@
integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4=
"@types/long@^4.0.1":
version "4.0.2"
resolved "https://registry.yarnpkg.com/@types/long/-/long-4.0.2.tgz#b74129719fc8d11c01868010082d483b7545591a"
integrity sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==
version "4.0.1"
resolved "https://registry.yarnpkg.com/@types/long/-/long-4.0.1.tgz#459c65fa1867dafe6a8f322c4c51695663cc55e9"
integrity sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w==
"@types/node@>=13.7.0":
version "17.0.23"
@@ -1642,9 +1642,9 @@ protobufjs@^6.8.8, protobufjs@~6.11.2:
long "^4.0.0"
protobufjs@~6.10.2:
version "6.10.3"
resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-6.10.3.tgz#11ed1dd02acbfcb330becf1611461d4b407f9eef"
integrity sha512-yvAslS0hNdBhlSKckI4R1l7wunVilX66uvrjzE4MimiAt7/qw1nLpMhZrn/ObuUTM/c3Xnfl01LYMdcSJe6dwg==
version "6.10.2"
resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-6.10.2.tgz#b9cb6bd8ec8f87514592ba3fdfd28e93f33a469b"
integrity sha512-27yj+04uF6ya9l+qfpH187aqEzfCF4+Uit0I9ZBQVqK09hk/SQzKa2MUqUpXaVa7LOFRg1TSSr3lVxGOk6c0SQ==
dependencies:
"@protobufjs/aspromise" "^1.1.2"
"@protobufjs/base64" "^1.1.2"
+1 -2
View File
@@ -24,8 +24,7 @@
},
"../pkg": {
"name": "@nymproject/nym-client-wasm",
"version": "1.0.1",
"license": "Apache-2.0"
"version": "0.0.1"
},
"node_modules/@discoveryjs/json-ext": {
"version": "0.5.7",
+2 -2
View File
@@ -5,7 +5,7 @@ use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
// Serializable structures for what we find in common/crypto
#[derive(Serialize, Deserialize, Copy, Clone, Debug, PartialEq, Eq, JsonSchema)]
#[derive(Serialize, Deserialize, Copy, Clone, Debug, PartialEq, JsonSchema)]
pub struct PublicKey([u8; 32]);
impl PublicKey {
@@ -24,7 +24,7 @@ impl AsRef<[u8]> for PublicKey {
}
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct Signature([u8; 32], [u8; 32]);
impl Signature {
+4 -4
View File
@@ -7,16 +7,16 @@ use serde::{Deserialize, Serialize};
use crate::keys::PublicKey;
use crate::payment::LinkPaymentData;
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct InstantiateMsg {}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum ExecuteMsg {
LinkPayment { data: LinkPaymentData },
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum QueryMsg {
GetPayments {
@@ -25,6 +25,6 @@ pub enum QueryMsg {
},
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub struct MigrateMsg {}
@@ -6,7 +6,7 @@ use serde::{Deserialize, Serialize};
use crate::keys::{PublicKey, Signature};
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)]
pub struct Payment {
verification_key: PublicKey,
gateway_identity: PublicKey,
@@ -27,7 +27,7 @@ impl Payment {
}
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct LinkPaymentData {
pub verification_key: PublicKey,
pub gateway_identity: PublicKey,
@@ -51,7 +51,7 @@ impl LinkPaymentData {
}
}
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)]
pub struct PagedPaymentResponse {
pub payments: Vec<Payment>,
pub per_page: usize,
+1 -1
View File
@@ -74,4 +74,4 @@ features = ["js"]
[features]
coconut = ["gateway-requests/coconut", "coconut-interface", "validator-client", "credentials/coconut"]
wasm = ["web3/wasm", "web3/http", "web3/signing"]
default = ["web3/default"]
default = ["web3/default"]
@@ -1,49 +1,47 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::error::GatewayClientError;
use std::str::FromStr;
#[cfg(target_arch = "wasm32")]
use crate::wasm_storage::Storage;
use crate::wasm_storage::{Storage, StorageError};
#[cfg(feature = "coconut")]
use coconut_interface::Base58;
#[cfg(feature = "coconut")]
#[cfg(not(target_arch = "wasm32"))]
use credential_storage::error::StorageError;
#[cfg(not(target_arch = "wasm32"))]
use credential_storage::storage::Storage;
#[cfg(all(target_arch = "wasm32", feature = "coconut"))]
use crate::wasm_storage::StorageError;
#[cfg(all(not(target_arch = "wasm32"), feature = "coconut"))]
use credential_storage::error::StorageError;
#[cfg(feature = "coconut")]
use {
coconut_interface::Base58,
credentials::coconut::{
bandwidth::prepare_for_spending, utils::obtain_aggregate_verification_key,
},
use credentials::coconut::{
bandwidth::prepare_for_spending, utils::obtain_aggregate_verification_key,
};
#[cfg(not(feature = "coconut"))]
use credentials::token::bandwidth::TokenCredential;
#[cfg(not(feature = "coconut"))]
use crypto::asymmetric::identity;
#[cfg(not(feature = "coconut"))]
use network_defaults::{
eth_contract::ETH_ERC20_JSON_ABI, eth_contract::ETH_JSON_ABI, BANDWIDTH_VALUE,
ETH_BURN_FUNCTION_NAME, ETH_CONTRACT_ADDRESS, ETH_ERC20_APPROVE_FUNCTION_NAME,
ETH_ERC20_CONTRACT_ADDRESS, ETH_MIN_BLOCK_DEPTH, TOKENS_TO_BURN, UTOKENS_TO_BURN,
};
#[cfg(not(feature = "coconut"))]
use pemstore::traits::PemStorableKeyPair;
#[cfg(not(feature = "coconut"))]
use rand::rngs::OsRng;
#[cfg(not(feature = "coconut"))]
use secp256k1::SecretKey;
use std::str::FromStr;
#[cfg(not(feature = "coconut"))]
use web3::{
contract::{Contract, Options},
ethabi::Token,
signing::{Key, SecretKeyRef},
transports::Http,
types::{Address, U256, U64},
Web3,
};
#[cfg(not(feature = "coconut"))]
use {
credentials::token::bandwidth::TokenCredential,
crypto::asymmetric::identity,
network_defaults::{
eth_contract::ETH_ERC20_JSON_ABI, eth_contract::ETH_JSON_ABI, BANDWIDTH_VALUE,
ETH_BURN_FUNCTION_NAME, ETH_CONTRACT_ADDRESS, ETH_ERC20_APPROVE_FUNCTION_NAME,
ETH_ERC20_CONTRACT_ADDRESS, ETH_MIN_BLOCK_DEPTH, TOKENS_TO_BURN, UTOKENS_TO_BURN,
},
pemstore::traits::PemStorableKeyPair,
rand::rngs::OsRng,
secp256k1::SecretKey,
web3::{
contract::{Contract, Options},
ethabi::Token,
signing::{Key, SecretKeyRef},
transports::Http,
types::{Address, U256, U64},
Web3,
},
};
use crate::error::GatewayClientError;
#[cfg(not(feature = "coconut"))]
pub fn eth_contract(web3: Web3<Http>) -> Contract<Http> {
@@ -27,7 +27,7 @@ futures = "0.3"
coconut-interface = { path = "../../coconut-interface" }
network-defaults = { path = "../../network-defaults" }
validator-api-requests = { path = "../../../validator-api/validator-api-requests", features = ["coconut"] }
validator-api-requests = { path = "../../../validator-api/validator-api-requests" }
# required for nymd-client
# at some point it might be possible to make it wasm-compatible
@@ -43,7 +43,6 @@ itertools = { version = "0.10", optional = true }
cosmwasm-std = { version = "1.0.0", optional = true }
execute = { path = "../../execute" }
[dev-dependencies]
ts-rs = "6.1.2"
[features]
@@ -2,24 +2,27 @@
// SPDX-License-Identifier: Apache-2.0
use crate::{validator_api, ValidatorClientError};
use mixnet_contract_common::{GatewayBond, IdentityKeyRef, MixNodeBond};
use url::Url;
use validator_api_requests::coconut::{
use coconut_interface::{
BlindSignRequestBody, BlindedSignatureResponse, ExecuteReleaseFundsRequestBody,
ProposeReleaseFundsRequestBody, ProposeReleaseFundsResponse, VerificationKeyResponse,
VerifyCredentialBody, VerifyCredentialResponse,
};
use mixnet_contract_common::{GatewayBond, IdentityKeyRef, MixNodeBond};
use url::Url;
use validator_api_requests::models::{
CoreNodeStatusResponse, MixnodeStatusResponse, RewardEstimationResponse,
StakeSaturationResponse,
};
#[cfg(feature = "nymd-client")]
use validator_api_requests::models::{MixNodeBondAnnotated, UptimeResponse};
#[cfg(feature = "nymd-client")]
use network_defaults::DEFAULT_NETWORK;
#[cfg(feature = "nymd-client")]
use crate::nymd::{
self, error::NymdError, CosmWasmClient, NymdClient, QueryNymdClient, SigningNymdClient,
error::NymdError, CosmWasmClient, NymdClient, QueryNymdClient, SigningNymdClient,
};
#[cfg(feature = "nymd-client")]
@@ -29,18 +32,18 @@ use mixnet_contract_common::{
RewardedSetUpdateDetails,
};
#[cfg(feature = "nymd-client")]
use network_defaults::{all::Network, NymNetworkDetails};
#[cfg(feature = "nymd-client")]
use std::collections::{HashMap, HashSet};
#[cfg(feature = "nymd-client")]
#[must_use]
#[derive(Debug, Clone)]
#[derive(Debug)]
pub struct Config {
network: network_defaults::all::Network,
api_url: Url,
nymd_url: Url,
nymd_config: nymd::Config,
mixnet_contract_address: cosmrs::AccountId,
vesting_contract_address: cosmrs::AccountId,
bandwidth_claim_contract_address: cosmrs::AccountId,
mixnode_page_limit: Option<u32>,
gateway_page_limit: Option<u32>,
@@ -50,44 +53,42 @@ pub struct Config {
#[cfg(feature = "nymd-client")]
impl Config {
pub fn try_from_nym_network_details(
details: &NymNetworkDetails,
) -> Result<Self, ValidatorClientError> {
let mut api_url = details
.endpoints
.iter()
.filter_map(|d| d.api_url.as_ref())
.map(|url| Url::parse(url))
.collect::<Result<Vec<_>, _>>()?;
if api_url.is_empty() {
return Err(ValidatorClientError::NoAPIUrlAvailable);
}
Ok(Config {
api_url: api_url.pop().unwrap(),
nymd_url: details.endpoints[0]
.nymd_url
pub fn new(network: network_defaults::all::Network, nymd_url: Url, api_url: Url) -> Self {
Config {
network,
nymd_url,
mixnet_contract_address: DEFAULT_NETWORK
.mixnet_contract_address()
.parse()
.map_err(ValidatorClientError::MalformedUrlProvided)?,
nymd_config: nymd::Config::try_from_nym_network_details(details)?,
.expect("Error parsing mixnet contract address"),
vesting_contract_address: DEFAULT_NETWORK
.vesting_contract_address()
.parse()
.expect("Error parsing vesting contract address"),
bandwidth_claim_contract_address: DEFAULT_NETWORK
.bandwidth_claim_contract_address()
.parse()
.expect("Error parsing bandwidth claim contract address"),
api_url,
mixnode_page_limit: None,
gateway_page_limit: None,
mixnode_delegations_page_limit: None,
rewarded_set_page_limit: None,
})
}
}
// TODO: this method shouldn't really exist as all information should be included immediately
// via `from_nym_network_details`, but it's here for, you guessed it, legacy compatibility
pub fn with_urls(mut self, nymd_url: Url, api_url: Url) -> Self {
self.nymd_url = nymd_url;
self.api_url = api_url;
pub fn with_mixnode_contract_address(mut self, address: cosmrs::AccountId) -> Self {
self.mixnet_contract_address = address;
self
}
pub fn with_nymd_url(mut self, nymd_url: Url) -> Self {
self.nymd_url = nymd_url;
pub fn with_vesting_contract_address(mut self, address: cosmrs::AccountId) -> Self {
self.vesting_contract_address = address;
self
}
pub fn with_bandwidth_claim_contract_address(mut self, address: cosmrs::AccountId) -> Self {
self.bandwidth_claim_contract_address = address;
self
}
@@ -114,11 +115,10 @@ impl Config {
#[cfg(feature = "nymd-client")]
pub struct Client<C> {
// compatibility : (
pub network: Network,
// TODO: we really shouldn't be storing a mnemonic here, but removing it would be
// non-trivial amount of work and it's out of scope of the current branch
pub network: network_defaults::all::Network,
mixnet_contract_address: cosmrs::AccountId,
vesting_contract_address: cosmrs::AccountId,
bandwidth_claim_contract_address: cosmrs::AccountId,
mnemonic: Option<bip39::Mnemonic>,
mixnode_page_limit: Option<u32>,
@@ -135,26 +135,29 @@ pub struct Client<C> {
impl Client<SigningNymdClient> {
pub fn new_signing(
config: Config,
// we need to provide network argument due to compatibility with other components (wallet...)
// that rely on its existence...
network: Network,
mnemonic: bip39::Mnemonic,
) -> Result<Client<SigningNymdClient>, ValidatorClientError> {
let validator_api_client = validator_api::Client::new(config.api_url.clone());
let nymd_client = NymdClient::connect_with_mnemonic(
config.nymd_config.clone(),
config.network,
config.nymd_url.as_str(),
mnemonic.clone(),
None,
)?;
)?
.with_mixnet_contract_address(config.mixnet_contract_address.clone())
.with_vesting_contract_address(config.vesting_contract_address.clone())
.with_bandwidth_claim_contract_address(config.bandwidth_claim_contract_address.clone());
Ok(Client {
network,
network: config.network,
mixnet_contract_address: config.mixnet_contract_address,
vesting_contract_address: config.vesting_contract_address,
bandwidth_claim_contract_address: config.bandwidth_claim_contract_address,
mnemonic: Some(mnemonic),
mixnode_page_limit: config.mixnode_page_limit,
gateway_page_limit: config.gateway_page_limit,
mixnode_delegations_page_limit: config.mixnode_delegations_page_limit,
rewarded_set_page_limit: config.rewarded_set_page_limit,
rewarded_set_page_limit: None,
validator_api: validator_api_client,
nymd: nymd_client,
})
@@ -162,11 +165,14 @@ impl Client<SigningNymdClient> {
pub fn change_nymd(&mut self, new_endpoint: Url) -> Result<(), ValidatorClientError> {
self.nymd = NymdClient::connect_with_mnemonic(
self.nymd.current_config().clone(),
self.network,
new_endpoint.as_ref(),
self.mnemonic.clone().unwrap(),
None,
)?;
)?
.with_mixnet_contract_address(self.mixnet_contract_address.clone())
.with_vesting_contract_address(self.vesting_contract_address.clone())
.with_bandwidth_claim_contract_address(self.bandwidth_claim_contract_address.clone());
Ok(())
}
@@ -177,18 +183,17 @@ impl Client<SigningNymdClient> {
#[cfg(feature = "nymd-client")]
impl Client<QueryNymdClient> {
pub fn new_query(
config: Config,
// we need to provide network argument due to compatibility with other components (wallet...)
// that rely on its existence...
network: Network,
) -> Result<Client<QueryNymdClient>, ValidatorClientError> {
pub fn new_query(config: Config) -> Result<Client<QueryNymdClient>, ValidatorClientError> {
let validator_api_client = validator_api::Client::new(config.api_url.clone());
let nymd_client =
NymdClient::connect(config.nymd_config.clone(), config.nymd_url.as_str())?;
let nymd_client = NymdClient::connect(config.nymd_url.as_str())?
.with_mixnet_contract_address(config.mixnet_contract_address.clone())
.with_vesting_contract_address(config.vesting_contract_address.clone());
Ok(Client {
network,
network: config.network,
mixnet_contract_address: config.mixnet_contract_address,
vesting_contract_address: config.vesting_contract_address,
bandwidth_claim_contract_address: config.bandwidth_claim_contract_address,
mnemonic: None,
mixnode_page_limit: config.mixnode_page_limit,
gateway_page_limit: config.gateway_page_limit,
@@ -200,7 +205,10 @@ impl Client<QueryNymdClient> {
}
pub fn change_nymd(&mut self, new_endpoint: Url) -> Result<(), ValidatorClientError> {
self.nymd = NymdClient::connect(self.nymd.current_config().clone(), new_endpoint.as_ref())?;
self.nymd = NymdClient::connect(new_endpoint.as_ref())?
.with_mixnet_contract_address(self.mixnet_contract_address.clone())
.with_vesting_contract_address(self.vesting_contract_address.clone())
.with_bandwidth_claim_contract_address(self.bandwidth_claim_contract_address.clone());
Ok(())
}
}
@@ -214,12 +222,11 @@ impl<C> Client<C> {
// use case: somebody initialised client without a contract in order to upload and initialise one
// and now they want to actually use it without making new client
pub fn set_mixnet_contract_address(&mut self, mixnet_contract_address: cosmrs::AccountId) {
self.nymd
.set_mixnet_contract_address(mixnet_contract_address)
self.mixnet_contract_address = mixnet_contract_address
}
pub fn get_mixnet_contract_address(&self) -> cosmrs::AccountId {
self.nymd.mixnet_contract_address().clone()
self.mixnet_contract_address.clone()
}
pub async fn get_cached_mixnodes(&self) -> Result<Vec<MixNodeBond>, ValidatorClientError> {
@@ -311,13 +318,6 @@ impl<C> Client<C> {
Ok(self.nymd.get_current_epoch().await?)
}
pub async fn get_current_operator_cost(&self) -> Result<u64, ValidatorClientError>
where
C: CosmWasmClient + Sync,
{
Ok(self.nymd.get_current_operator_cost().await?)
}
pub async fn get_mixnet_contract_version(&self) -> Result<MixnetContractVersion, NymdError>
where
C: CosmWasmClient + Sync,
@@ -1,5 +1,5 @@
use crate::nymd::error::NymdError;
use crate::nymd::{Config as ClientConfig, NymdClient, QueryNymdClient};
use crate::nymd::{NymdClient, QueryNymdClient};
use crate::ApiClient;
use network_defaults::all::Network;
@@ -54,20 +54,10 @@ fn setup_connection_tests<H: BuildHasher + 'static>(
.get(&network)
.expect("No configured contract address")
.clone();
let config = ClientConfig::try_from_nym_network_details(&network.details())
.expect("failed to create valid nymd client config");
if let Ok(mut client) = NymdClient::<QueryNymdClient>::connect(config, url.as_str()) {
// possibly redundant, but lets just leave it here
client.set_mixnet_contract_address(address);
Some(ClientForConnectionTest::Nymd(
network,
url,
Box::new(client),
))
} else {
None
}
NymdClient::<QueryNymdClient>::connect(url.as_str())
.map(|client| client.with_mixnet_contract_address(address))
.map(move |client| ClientForConnectionTest::Nymd(network, url, Box::new(client)))
.ok()
});
let api_connection_test_clients = api_urls.map(|(network, url)| {
@@ -86,7 +76,7 @@ fn extract_and_collect_results_into_map(
.filter(|c| &c.url_type() == url_type)
.map(|c| {
let (network, url, result) = c.result();
(network.clone(), (url.clone(), *result))
(*network, (url.clone(), *result))
})
.into_group_map()
}
@@ -18,7 +18,4 @@ pub enum ValidatorClientError {
#[cfg(feature = "nymd-client")]
#[error("There was an issue with the Nymd client - {0}")]
NymdError(#[from] crate::nymd::error::NymdError),
#[error("No validator API url has been provided")]
NoAPIUrlAvailable,
}
@@ -6,14 +6,14 @@ use std::fmt;
pub use cosmrs::Coin as CosmosCoin;
pub use cosmwasm_std::Coin as CosmWasmCoin;
#[derive(Serialize, Deserialize, Clone, Copy, Default, Debug, PartialEq, Eq)]
#[derive(Serialize, Deserialize, Clone, Copy, Default, Debug, PartialEq)]
pub struct MismatchedDenoms;
// the reason the coin is created here as opposed to different place in the codebase is that
// eventually we want to either publish the cosmwasm client separately or commit it to
// some other project, like cosmrs. Either way, in that case we can't really have
// a dependency on an internal type
#[derive(Serialize, Deserialize, Clone, Default, Debug, PartialEq, Eq)]
#[derive(Serialize, Deserialize, Clone, Default, Debug, PartialEq)]
pub struct Coin {
pub amount: u128,
pub denom: String,
@@ -26,7 +26,7 @@ use cosmrs::rpc::{self, HttpClient, Order};
use cosmrs::tendermint::abci::Code as AbciCode;
use cosmrs::tendermint::abci::Transaction;
use cosmrs::tendermint::{abci, block, chain};
use cosmrs::{tx, AccountId, Coin as CosmosCoin, Denom, Tx};
use cosmrs::{tx, AccountId, Coin as CosmosCoin, Tx};
use prost::Message;
use serde::{Deserialize, Serialize};
use std::convert::{TryFrom, TryInto};
@@ -121,7 +121,7 @@ pub trait CosmWasmClient: rpc::Client {
async fn get_balance(
&self,
address: &AccountId,
search_denom: Denom,
search_denom: String,
) -> Result<Option<Coin>, NymdError> {
let path = Some("/cosmos.bank.v1beta1.Query/Balance".parse().unwrap());
@@ -8,7 +8,7 @@ use crate::nymd::cosmwasm_client::types::*;
use crate::nymd::error::NymdError;
use crate::nymd::fee::{Fee, DEFAULT_SIMULATED_GAS_MULTIPLIER};
use crate::nymd::wallet::DirectSecp256k1HdWallet;
use crate::nymd::{Coin, GasAdjustable, GasPrice, TxResponse};
use crate::nymd::{Coin, GasPrice, TxResponse};
use async_trait::async_trait;
use cosmrs::bank::MsgSend;
use cosmrs::distribution::MsgWithdrawDelegatorReward;
@@ -490,35 +490,28 @@ pub trait SigningCosmWasmClient: CosmWasmClient {
fee: Fee,
memo: &String,
) -> Result<tx::Fee, NymdError> {
let auto_fee = |multiplier: Option<f32>| async move {
debug!("Trying to simulate gas costs...");
// from what I've seen in manual testing, gas estimation does not exist if transaction
// fails to get executed (for example if you send 'BondMixnode" with invalid signature)
let gas_estimation = self
.simulate(signer_address, messages.to_vec(), memo.clone())
.await?
.gas_info
.ok_or(NymdError::GasEstimationFailure)?
.gas_used;
let multiplier = multiplier.unwrap_or(DEFAULT_SIMULATED_GAS_MULTIPLIER);
let gas = gas_estimation.adjust_gas(multiplier);
debug!("Gas estimation: {}", gas_estimation);
debug!("Multiplying the estimation by {}", multiplier);
debug!("Final gas limit used: {}", gas);
let fee = self.gas_price() * gas;
Ok::<tx::Fee, NymdError>(tx::Fee::from_amount_and_gas(fee, gas))
};
let fee = match fee {
Fee::Manual(fee) => fee,
Fee::Auto(multiplier) => auto_fee(multiplier).await?,
Fee::PayerGranterAuto(multiplier, payer, granter) => {
let mut fee = auto_fee(multiplier).await?;
fee.payer = payer;
fee.granter = granter;
fee
Fee::Auto(multiplier) => {
debug!("Trying to simulate gas costs...");
// from what I've seen in manual testing, gas estimation does not exist if transaction
// fails to get executed (for example if you send 'BondMixnode" with invalid signature)
let gas_estimation = self
.simulate(signer_address, messages.to_vec(), memo.clone())
.await?
.gas_info
.ok_or(NymdError::GasEstimationFailure)?
.gas_used;
let multiplier = multiplier.unwrap_or(DEFAULT_SIMULATED_GAS_MULTIPLIER);
let gas = ((gas_estimation.value() as f32 * multiplier) as u64).into();
debug!("Gas estimation: {}", gas_estimation);
debug!("Multiplying the estimation by {}", multiplier);
debug!("Final gas limit used: {}", gas);
let fee = self.gas_price() * gas;
tx::Fee::from_amount_and_gas(fee, gas)
}
};
debug!("Fee used for the transaction: {:?}", fee);
@@ -130,9 +130,6 @@ pub enum NymdError {
#[error("Coconut interface error: {0}")]
CoconutInterfaceError(#[from] coconut_interface::error::CoconutInterfaceError),
#[error("Account had an unexpected bech32 prefix. Expected: {expected}, got: {got}")]
UnexpectedBech32Prefix { got: String, expected: String },
}
impl NymdError {
@@ -1,21 +1,53 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::nymd::Gas;
use cosmrs::{tx, AccountId};
use crate::nymd::Coin;
use cosmrs::tx;
use serde::{Deserialize, Serialize};
use std::fmt::{Display, Formatter};
pub mod gas_price;
pub type GasAdjustment = f32;
pub const DEFAULT_SIMULATED_GAS_MULTIPLIER: GasAdjustment = 1.3;
pub const DEFAULT_SIMULATED_GAS_MULTIPLIER: f32 = 1.3;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum Fee {
Manual(#[serde(with = "sealed::TxFee")] tx::Fee),
Auto(Option<GasAdjustment>),
PayerGranterAuto(Option<GasAdjustment>, Option<AccountId>, Option<AccountId>),
Auto(Option<f32>),
}
impl Display for Fee {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
Fee::Manual(fee) => {
write!(f, "Fee in manual mode with ")?;
for fee in &fee.amount {
write!(f, "{}{} paid in fees, ", fee.amount, fee.denom)?;
}
write!(f, "{} set as gas limit, ", fee.gas_limit)?;
if let Some(payer) = &fee.payer {
write!(f, "{payer} set as payer, ")?;
}
if let Some(granter) = &fee.granter {
write!(f, "{granter} set as granter")?;
}
Ok(())
}
Fee::Auto(Some(multiplier)) => {
write!(f, "Fee in auto mode with {multiplier} simulated multiplier")
}
Fee::Auto(None) => write!(f, "Fee in auto mode with no custom simulated multiplier"),
}
}
}
impl Fee {
pub fn try_get_manual_amount(&self) -> Option<Vec<Coin>> {
match self {
Fee::Manual(tx_fee) => Some(tx_fee.amount.iter().cloned().map(Into::into).collect()),
Fee::Auto(_) => None,
}
}
}
impl From<tx::Fee> for Fee {
@@ -24,8 +56,8 @@ impl From<tx::Fee> for Fee {
}
}
impl From<GasAdjustment> for Fee {
fn from(multiplier: GasAdjustment) -> Self {
impl From<f32> for Fee {
fn from(multiplier: f32) -> Self {
Fee::Auto(Some(multiplier))
}
}
@@ -36,21 +68,6 @@ impl Default for Fee {
}
}
pub trait GasAdjustable {
fn adjust_gas(&self, adjustment: GasAdjustment) -> Self;
}
impl GasAdjustable for Gas {
fn adjust_gas(&self, adjustment: GasAdjustment) -> Self {
if adjustment == 1.0 {
*self
} else {
let adjusted = (self.value() as f32 * adjustment).ceil();
(adjusted as u64).into()
}
}
}
// a workaround to provide serde implementation for tx::Fee. We don't want to ever expose any of those
// types to the public and ideally they will get replaced by proper implementation inside comrs
mod sealed {
@@ -15,19 +15,19 @@ use cosmrs::rpc::HttpClientUrl;
use cosmrs::tx::Msg;
use cosmwasm_std::Uint128;
use execute::execute;
pub use fee::gas_price::GasPrice;
use mixnet_contract_common::mixnode::DelegationEvent;
use mixnet_contract_common::{
ContractStateParams, Delegation, ExecuteMsg, Gateway, GatewayBond, GatewayBondResponse,
GatewayOwnershipResponse, IdentityKey, Interval, LayerDistribution, MixNode, MixNodeBond,
MixOwnershipResponse, MixnetContractVersion, MixnodeBondResponse,
MixnodeRewardingStatusResponse, PagedDelegatorDelegationsResponse, PagedGatewayResponse,
PagedMixDelegationsResponse, PagedMixnodeResponse, PagedRewardedSetResponse, QueryMsg,
RewardedSetUpdateDetails,
ContractStateParams, Delegation, ExecuteMsg, Gateway, GatewayBond, GatewayOwnershipResponse,
IdentityKey, Interval, LayerDistribution, MixNode, MixNodeBond, MixOwnershipResponse,
MixnetContractVersion, MixnodeRewardingStatusResponse, PagedDelegatorDelegationsResponse,
PagedGatewayResponse, PagedMixDelegationsResponse, PagedMixnodeResponse,
PagedRewardedSetResponse, QueryMsg, RewardedSetUpdateDetails,
};
use network_defaults::DEFAULT_NETWORK;
use serde::Serialize;
use std::convert::TryInto;
use vesting_contract_common::ExecuteMsg as VestingExecuteMsg;
use vesting_contract_common::QueryMsg as VestingQueryMsg;
pub use crate::nymd::cosmwasm_client::client::CosmWasmClient;
pub use crate::nymd::cosmwasm_client::signing_client::SigningCosmWasmClient;
@@ -48,8 +48,6 @@ pub use cosmrs::tx::{self, Gas};
pub use cosmrs::Coin as CosmosCoin;
pub use cosmrs::{bip32, AccountId, Decimal, Denom};
pub use cosmwasm_std::Coin as CosmWasmCoin;
pub use fee::{gas_price::GasPrice, GasAdjustable, GasAdjustment};
use network_defaults::{ChainDetails, NymNetworkDetails};
pub use signing_client::Client as SigningNymdClient;
pub use traits::{VestingQueryClient, VestingSigningClient};
@@ -60,92 +58,67 @@ pub mod fee;
pub mod traits;
pub mod wallet;
#[derive(Debug, Clone)]
pub struct Config {
pub(crate) chain_details: ChainDetails,
// I'd love to have used `NymContracts` struct directly here instead,
// however, I'd really prefer to use something more strongly typed (i.e. AccountId vs String)
pub(crate) mixnet_contract_address: Option<AccountId>,
pub(crate) vesting_contract_address: Option<AccountId>,
pub(crate) bandwidth_claim_contract_address: Option<AccountId>,
pub(crate) coconut_bandwidth_contract_address: Option<AccountId>,
pub(crate) multisig_contract_address: Option<AccountId>,
// TODO: add this in later commits
// pub(crate) gas_price: GasPrice,
}
impl Config {
fn parse_optional_account(
raw: Option<&String>,
expected_prefix: &str,
) -> Result<Option<AccountId>, NymdError> {
if let Some(address) = raw {
let parsed: AccountId = address
.parse()
.map_err(|_| NymdError::MalformedAccountAddress(address.clone()))?;
if parsed.prefix() != expected_prefix {
Err(NymdError::UnexpectedBech32Prefix {
got: parsed.prefix().into(),
expected: expected_prefix.into(),
})
} else {
Ok(Some(parsed))
}
} else {
Ok(None)
}
}
pub fn try_from_nym_network_details(details: &NymNetworkDetails) -> Result<Self, NymdError> {
let prefix = &details.chain_details.bech32_account_prefix;
Ok(Config {
chain_details: details.chain_details.clone(),
mixnet_contract_address: Self::parse_optional_account(
details.contracts.mixnet_contract_address.as_ref(),
prefix,
)?,
vesting_contract_address: Self::parse_optional_account(
details.contracts.vesting_contract_address.as_ref(),
prefix,
)?,
bandwidth_claim_contract_address: Self::parse_optional_account(
details.contracts.bandwidth_claim_contract_address.as_ref(),
prefix,
)?,
coconut_bandwidth_contract_address: Self::parse_optional_account(
details
.contracts
.coconut_bandwidth_contract_address
.as_ref(),
prefix,
)?,
multisig_contract_address: Self::parse_optional_account(
details.contracts.multisig_contract_address.as_ref(),
prefix,
)?,
})
}
}
#[derive(Debug)]
pub struct NymdClient<C> {
client: C,
config: Config,
mixnet_contract_address: AccountId,
vesting_contract_address: AccountId,
bandwidth_claim_contract_address: AccountId,
coconut_bandwidth_contract_address: AccountId,
multisig_contract_address: AccountId,
client_address: Option<Vec<AccountId>>,
simulated_gas_multiplier: f32,
}
impl<C> NymdClient<C> {
pub fn with_mixnet_contract_address(mut self, address: AccountId) -> Self {
self.mixnet_contract_address = address;
self
}
pub fn with_vesting_contract_address(mut self, address: AccountId) -> Self {
self.vesting_contract_address = address;
self
}
pub fn with_bandwidth_claim_contract_address(mut self, address: AccountId) -> Self {
self.bandwidth_claim_contract_address = address;
self
}
pub fn with_coconut_bandwidth_contract_address(mut self, address: AccountId) -> Self {
self.coconut_bandwidth_contract_address = address;
self
}
pub fn with_multisig_contract_address(mut self, address: AccountId) -> Self {
self.multisig_contract_address = address;
self
}
}
impl NymdClient<QueryNymdClient> {
pub fn connect<U>(config: Config, endpoint: U) -> Result<NymdClient<QueryNymdClient>, NymdError>
pub fn connect<U>(endpoint: U) -> Result<NymdClient<QueryNymdClient>, NymdError>
where
U: TryInto<HttpClientUrl, Error = TendermintRpcError>,
{
Ok(NymdClient {
client: QueryNymdClient::new(endpoint)?,
config,
client_address: None,
simulated_gas_multiplier: DEFAULT_SIMULATED_GAS_MULTIPLIER,
mixnet_contract_address: DEFAULT_NETWORK
.mixnet_contract_address()
.parse()
.expect("Error parsing mixnet contract address"),
vesting_contract_address: DEFAULT_NETWORK
.vesting_contract_address()
.parse()
.expect("Error parsing vesting contract address"),
bandwidth_claim_contract_address: DEFAULT_NETWORK
.bandwidth_claim_contract_address()
.parse()
.expect("Error parsing bandwidth claim contract address"),
coconut_bandwidth_contract_address: DEFAULT_NETWORK
.coconut_bandwidth_contract_address()
.parse()
.unwrap(),
multisig_contract_address: DEFAULT_NETWORK.multisig_contract_address().parse().unwrap(),
})
}
}
@@ -153,7 +126,6 @@ impl NymdClient<QueryNymdClient> {
impl NymdClient<SigningNymdClient> {
// maybe the wallet could be made into a generic, but for now, let's just have this one implementation
pub fn connect_with_signer<U: Clone>(
config: Config,
network: config::defaults::all::Network,
endpoint: U,
signer: DirectSecp256k1HdWallet,
@@ -162,24 +134,40 @@ impl NymdClient<SigningNymdClient> {
where
U: TryInto<HttpClientUrl, Error = TendermintRpcError>,
{
let denom = network.base_mix_denom();
let denom = network.mix_denom().base;
let client_address = signer
.try_derive_accounts()?
.into_iter()
.map(|account| account.address)
.collect();
let gas_price = gas_price.unwrap_or(GasPrice::new_with_default_price(&denom)?);
let gas_price = gas_price.unwrap_or(GasPrice::new_with_default_price(denom)?);
Ok(NymdClient {
client: SigningNymdClient::connect_with_signer(endpoint, signer, gas_price)?,
config,
client_address: Some(client_address),
simulated_gas_multiplier: DEFAULT_SIMULATED_GAS_MULTIPLIER,
mixnet_contract_address: DEFAULT_NETWORK
.mixnet_contract_address()
.parse()
.expect("Error parsing mixnet contract address"),
vesting_contract_address: DEFAULT_NETWORK
.vesting_contract_address()
.parse()
.expect("Error parsing vesting contract address"),
bandwidth_claim_contract_address: DEFAULT_NETWORK
.bandwidth_claim_contract_address()
.parse()
.expect("Error parsing bandwidth claim contract address"),
coconut_bandwidth_contract_address: DEFAULT_NETWORK
.coconut_bandwidth_contract_address()
.parse()
.unwrap(),
multisig_contract_address: DEFAULT_NETWORK.multisig_contract_address().parse().unwrap(),
})
}
pub fn connect_with_mnemonic<U: Clone>(
config: Config,
network: config::defaults::all::Network,
endpoint: U,
mnemonic: bip39::Mnemonic,
gas_price: Option<GasPrice>,
@@ -187,8 +175,8 @@ impl NymdClient<SigningNymdClient> {
where
U: TryInto<HttpClientUrl, Error = TendermintRpcError>,
{
let prefix = &config.chain_details.bech32_account_prefix;
let denom = &config.chain_details.mix_denom.base;
let prefix = network.bech32_prefix();
let denom = network.mix_denom().base;
let wallet = DirectSecp256k1HdWallet::from_mnemonic(prefix, mnemonic)?;
let client_address = wallet
.try_derive_accounts()?
@@ -199,82 +187,48 @@ impl NymdClient<SigningNymdClient> {
Ok(NymdClient {
client: SigningNymdClient::connect_with_signer(endpoint, wallet, gas_price)?,
config,
client_address: Some(client_address),
simulated_gas_multiplier: DEFAULT_SIMULATED_GAS_MULTIPLIER,
mixnet_contract_address: network
.mixnet_contract_address()
.parse()
.expect("Error parsing mixnet contract address"),
vesting_contract_address: network
.vesting_contract_address()
.parse()
.expect("Error parsing vesting contract address"),
bandwidth_claim_contract_address: network
.bandwidth_claim_contract_address()
.parse()
.expect("Error parsing bandwidth claim contract address"),
coconut_bandwidth_contract_address: network
.coconut_bandwidth_contract_address()
.parse()
.unwrap(),
multisig_contract_address: network.multisig_contract_address().parse().unwrap(),
})
}
}
impl<C> NymdClient<C> {
pub fn current_config(&self) -> &Config {
&self.config
}
pub fn set_mixnet_contract_address(&mut self, address: AccountId) {
self.config.mixnet_contract_address = Some(address);
}
pub fn set_vesting_contract_address(&mut self, address: AccountId) {
self.config.vesting_contract_address = Some(address);
}
pub fn set_bandwidth_claim_contract_address(&mut self, address: AccountId) {
self.config.bandwidth_claim_contract_address = Some(address);
}
pub fn set_coconut_bandwidth_contract_address(&mut self, address: AccountId) {
self.config.coconut_bandwidth_contract_address = Some(address);
}
pub fn set_multisig_contract_address(&mut self, address: AccountId) {
self.config.multisig_contract_address = Some(address);
}
// TODO: this should get changed into Result<&AccountId, NymdError> (or Option<&AccountId> in future commits
// note: what unwrap is doing here is just moving a failure that would have normally
// occurred in `connect` when attempting to parse an empty address,
// so it's not introducing new source of failure (just moves it)
pub fn mixnet_contract_address(&self) -> &AccountId {
self.config.mixnet_contract_address.as_ref().unwrap()
&self.mixnet_contract_address
}
// TODO: this should get changed into Result<&AccountId, NymdError> (or Option<&AccountId> in future commits
// note: what unwrap is doing here is just moving a failure that would have normally
// occurred in `connect` when attempting to parse an empty address,
// so it's not introducing new source of failure (just moves it)
pub fn vesting_contract_address(&self) -> &AccountId {
self.config.vesting_contract_address.as_ref().unwrap()
&self.vesting_contract_address
}
// TODO: this should get changed into Result<&AccountId, NymdError> (or Option<&AccountId> in future commits
// note: what unwrap is doing here is just moving a failure that would have normally
// occurred in `connect` when attempting to parse an empty address,
// so it's not introducing new source of failure (just moves it)
pub fn bandwidth_claim_contract_address(&self) -> &AccountId {
self.config
.bandwidth_claim_contract_address
.as_ref()
.unwrap()
&self.bandwidth_claim_contract_address
}
// TODO: this should get changed into Result<&AccountId, NymdError> (or Option<&AccountId> in future commits
// note: what unwrap is doing here is just moving a failure that would have normally
// occurred in `connect` when attempting to parse an empty address,
// so it's not introducing new source of failure (just moves it)
pub fn coconut_bandwidth_contract_address(&self) -> &AccountId {
self.config
.coconut_bandwidth_contract_address
.as_ref()
.unwrap()
&self.coconut_bandwidth_contract_address
}
// TODO: this should get changed into Result<&AccountId, NymdError> (or Option<&AccountId> in future commits
// note: what unwrap is doing here is just moving a failure that would have normally
// occurred in `connect` when attempting to parse an empty address,
// so it's not introducing new source of failure (just moves it)
pub fn multisig_contract_address(&self) -> &AccountId {
self.config.multisig_contract_address.as_ref().unwrap()
&self.multisig_contract_address
}
pub fn set_simulated_gas_multiplier(&mut self, multiplier: f32) {
@@ -314,10 +268,6 @@ impl<C> NymdClient<C> {
self.client.gas_price()
}
pub fn gas_adjustment(&self) -> GasAdjustment {
self.simulated_gas_multiplier
}
pub async fn account_sequence(&self) -> Result<SequenceResponse, NymdError>
where
C: SigningCosmWasmClient + Sync,
@@ -388,7 +338,7 @@ impl<C> NymdClient<C> {
pub async fn get_balance(
&self,
address: &AccountId,
denom: Denom,
denom: String,
) -> Result<Option<Coin>, NymdError>
where
C: CosmWasmClient + Sync,
@@ -430,16 +380,6 @@ impl<C> NymdClient<C> {
.await
}
pub async fn vesting_get_locked_pledge_cap(&self) -> Result<Uint128, NymdError>
where
C: CosmWasmClient + Sync,
{
let request = VestingQueryMsg::GetLockedPledgeCap {};
self.client
.query_contract_smart(self.vesting_contract_address(), &request)
.await
}
pub async fn get_delegator_rewards(
&self,
address: String,
@@ -486,16 +426,6 @@ impl<C> NymdClient<C> {
.await
}
pub async fn get_current_operator_cost(&self) -> Result<u64, NymdError>
where
C: CosmWasmClient + Sync,
{
let request = QueryMsg::GetCurrentOperatorCost {};
self.client
.query_contract_smart(self.mixnet_contract_address(), &request)
.await
}
pub async fn get_mixnet_contract_version(&self) -> Result<MixnetContractVersion, NymdError>
where
C: CosmWasmClient + Sync,
@@ -665,38 +595,6 @@ impl<C> NymdClient<C> {
Ok(response.gateway)
}
/// Checks whether there is a bonded mixnode associated with the provided identity key
pub async fn get_mixnode_bond(
&self,
identity: IdentityKey,
) -> Result<Option<MixNodeBond>, NymdError>
where
C: CosmWasmClient + Sync,
{
let request = QueryMsg::GetMixnodeBond { identity };
let response: MixnodeBondResponse = self
.client
.query_contract_smart(self.mixnet_contract_address(), &request)
.await?;
Ok(response.mixnode)
}
/// Checks whether there is a bonded gateway associated with the provided identity key
pub async fn get_gateway_bond(
&self,
identity: IdentityKey,
) -> Result<Option<GatewayBond>, NymdError>
where
C: CosmWasmClient + Sync,
{
let request = QueryMsg::GetGatewayBond { identity };
let response: GatewayBondResponse = self
.client
.query_contract_smart(self.mixnet_contract_address(), &request)
.await?;
Ok(response.gateway)
}
pub async fn get_mixnodes_paged(
&self,
start_after: Option<IdentityKey>,
@@ -1051,18 +949,6 @@ impl<C> NymdClient<C> {
)
}
#[execute("vesting")]
fn _vesting_update_locked_pledge_cap(
&self,
amount: Uint128,
fee: Option<Fee>,
) -> (VestingExecuteMsg, Option<Fee>)
where
C: SigningCosmWasmClient + Sync,
{
(VestingExecuteMsg::UpdateLockedPledgeCap { amount }, fee)
}
/// Announce a mixnode, paying a fee.
pub async fn bond_mixnode(
&self,
@@ -214,7 +214,7 @@ mod tests {
];
for prefix in prefixes {
let addrs = match prefix.as_ref() {
let addrs = match prefix {
"nymt" => vec![
"nymt1jw6mp7d5xqc7w6xm79lha27glmd0vdt339me94",
"nymt1h5hgn94nsq4kh99rjj794hr5h5q6yfm23rjshv",
@@ -229,7 +229,7 @@ mod tests {
};
for (idx, mnemonic) in mnemonics.iter().enumerate() {
let wallet =
DirectSecp256k1HdWallet::from_mnemonic(&prefix, mnemonic.parse().unwrap())
DirectSecp256k1HdWallet::from_mnemonic(prefix, mnemonic.parse().unwrap())
.unwrap();
assert_eq!(
wallet.try_derive_accounts().unwrap()[0].address,
@@ -3,15 +3,15 @@
use crate::validator_api::error::ValidatorAPIError;
use crate::validator_api::routes::{CORE_STATUS_COUNT, SINCE_ARG};
use coconut_interface::{
BlindSignRequestBody, BlindedSignatureResponse, ExecuteReleaseFundsRequestBody,
ProposeReleaseFundsRequestBody, ProposeReleaseFundsResponse, VerificationKeyResponse,
VerifyCredentialBody, VerifyCredentialResponse,
};
use mixnet_contract_common::{GatewayBond, IdentityKeyRef, MixNodeBond};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use url::Url;
use validator_api_requests::coconut::{
BlindSignRequestBody, BlindedSignatureResponse, CosmosAddressResponse,
ExecuteReleaseFundsRequestBody, ProposeReleaseFundsRequestBody, ProposeReleaseFundsResponse,
VerificationKeyResponse, VerifyCredentialBody, VerifyCredentialResponse,
};
use validator_api_requests::models::{
CoreNodeStatusResponse, InclusionProbabilityResponse, MixNodeBondAnnotated,
MixnodeStatusResponse, RewardEstimationResponse, StakeSaturationResponse, UptimeResponse,
@@ -376,19 +376,6 @@ impl Client {
.await
}
pub async fn get_cosmos_address(&self) -> Result<CosmosAddressResponse, ValidatorAPIError> {
self.query_validator_api(
&[
routes::API_VERSION,
routes::COCONUT_ROUTES,
routes::BANDWIDTH,
routes::COCONUT_COSMOS_ADDRESS,
],
NO_PARAMS,
)
.await
}
pub async fn verify_bandwidth_credential(
&self,
request_body: &VerifyCredentialBody,
@@ -17,7 +17,6 @@ pub const BANDWIDTH: &str = "bandwidth";
pub const COCONUT_BLIND_SIGN: &str = "blind-sign";
pub const COCONUT_PARTIAL_BANDWIDTH_CREDENTIAL: &str = "partial-bandwidth-credential";
pub const COCONUT_VERIFICATION_KEY: &str = "verification-key";
pub const COCONUT_COSMOS_ADDRESS: &str = "cosmos-address";
pub const COCONUT_VERIFY_BANDWIDTH_CREDENTIAL: &str = "verify-bandwidth-credential";
pub const COCONUT_PROPOSE_RELEASE_FUNDS: &str = "propose-release-funds";
pub const COCONUT_EXECUTE_RELEASE_FUNDS: &str = "execute-release-funds";
+166 -1
View File
@@ -10,7 +10,7 @@ use error::CoconutInterfaceError;
pub use nymcoconut::*;
#[derive(Debug, Serialize, Deserialize, Getters, CopyGetters, Clone, PartialEq, Eq)]
#[derive(Debug, Serialize, Deserialize, Getters, CopyGetters, Clone, PartialEq)]
pub struct Credential {
#[getset(get = "pub")]
n_params: u32,
@@ -127,6 +127,171 @@ impl Bytable for Credential {
impl Base58 for Credential {}
#[derive(Serialize, Deserialize, Getters, CopyGetters)]
pub struct VerifyCredentialBody {
#[getset(get = "pub")]
credential: Credential,
#[getset(get = "pub")]
proposal_id: u64,
}
impl VerifyCredentialBody {
pub fn new(credential: Credential, proposal_id: u64) -> VerifyCredentialBody {
VerifyCredentialBody {
credential,
proposal_id,
}
}
}
#[derive(Debug, Serialize, Deserialize)]
pub struct VerifyCredentialResponse {
pub verification_result: bool,
}
impl VerifyCredentialResponse {
pub fn new(verification_result: bool) -> Self {
VerifyCredentialResponse {
verification_result,
}
}
}
// All strings are base58 encoded representations of structs
#[derive(Clone, Serialize, Deserialize, Debug, Getters, CopyGetters)]
pub struct BlindSignRequestBody {
#[getset(get = "pub")]
blind_sign_request: BlindSignRequest,
#[getset(get = "pub")]
tx_hash: String,
#[getset(get = "pub")]
signature: String,
public_attributes: Vec<String>,
#[getset(get = "pub")]
public_attributes_plain: Vec<String>,
#[getset(get = "pub")]
total_params: u32,
}
impl BlindSignRequestBody {
pub fn new(
blind_sign_request: &BlindSignRequest,
tx_hash: String,
signature: String,
public_attributes: &[Attribute],
public_attributes_plain: Vec<String>,
total_params: u32,
) -> BlindSignRequestBody {
BlindSignRequestBody {
blind_sign_request: blind_sign_request.clone(),
tx_hash,
signature,
public_attributes: public_attributes
.iter()
.map(|attr| attr.to_bs58())
.collect(),
public_attributes_plain,
total_params,
}
}
pub fn public_attributes(&self) -> Vec<Attribute> {
self.public_attributes
.iter()
.map(|x| Attribute::try_from_bs58(x).unwrap())
.collect()
}
}
#[derive(Debug, Serialize, Deserialize)]
pub struct BlindedSignatureResponse {
pub remote_key: [u8; 32],
pub encrypted_signature: Vec<u8>,
}
impl BlindedSignatureResponse {
pub fn new(encrypted_signature: Vec<u8>, remote_key: [u8; 32]) -> BlindedSignatureResponse {
BlindedSignatureResponse {
encrypted_signature,
remote_key,
}
}
pub fn to_base58_string(&self) -> String {
bs58::encode(&self.to_bytes()).into_string()
}
pub fn from_base58_string<I: AsRef<[u8]>>(val: I) -> Result<Self, CoconutInterfaceError> {
let bytes = bs58::decode(val).into_vec()?;
Self::from_bytes(&bytes)
}
pub fn to_bytes(&self) -> Vec<u8> {
let mut bytes = self.remote_key.to_vec();
bytes.extend_from_slice(&self.encrypted_signature);
bytes
}
pub fn from_bytes(bytes: &[u8]) -> Result<Self, CoconutInterfaceError> {
if bytes.len() < 32 {
return Err(CoconutInterfaceError::InvalidByteLength(bytes.len(), 32));
}
let mut remote_key = [0u8; 32];
remote_key.copy_from_slice(&bytes[..32]);
let encrypted_signature = bytes[32..].to_vec();
Ok(BlindedSignatureResponse {
remote_key,
encrypted_signature,
})
}
}
#[derive(Serialize, Deserialize)]
pub struct VerificationKeyResponse {
pub key: VerificationKey,
}
impl VerificationKeyResponse {
pub fn new(key: VerificationKey) -> VerificationKeyResponse {
VerificationKeyResponse { key }
}
}
#[derive(Serialize, Deserialize, Getters, CopyGetters)]
pub struct ProposeReleaseFundsRequestBody {
#[getset(get = "pub")]
credential: Credential,
}
impl ProposeReleaseFundsRequestBody {
pub fn new(credential: Credential) -> Self {
ProposeReleaseFundsRequestBody { credential }
}
}
#[derive(Debug, Serialize, Deserialize)]
pub struct ProposeReleaseFundsResponse {
pub proposal_id: u64,
}
impl ProposeReleaseFundsResponse {
pub fn new(proposal_id: u64) -> Self {
ProposeReleaseFundsResponse { proposal_id }
}
}
#[derive(Debug, Serialize, Deserialize, Getters, CopyGetters)]
pub struct ExecuteReleaseFundsRequestBody {
#[getset(get = "pub")]
proposal_id: u64,
}
impl ExecuteReleaseFundsRequestBody {
pub fn new(proposal_id: u64) -> Self {
ExecuteReleaseFundsRequestBody { proposal_id }
}
}
#[cfg(test)]
mod tests {
use super::*;
@@ -4,7 +4,7 @@
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct DepositData {
deposit_info: String,
identity_key: String,
@@ -7,7 +7,7 @@ use serde::{Deserialize, Serialize};
use crate::deposit::DepositData;
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct InstantiateMsg {
pub multisig_addr: String,
pub pool_addr: String,
@@ -20,10 +20,10 @@ pub enum ExecuteMsg {
ReleaseFunds { funds: Coin },
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum QueryMsg {}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub struct MigrateMsg {}
@@ -33,7 +33,7 @@ pub struct Delegation {
pub node_identity: IdentityKey,
pub amount: Coin,
pub block_height: u64,
pub proxy: Option<Addr>, // proxy address used to delegate the funds on behalf of anouther address
pub proxy: Option<Addr>, // proxy address used to delegate the funds on behalf of another address
}
impl Eq for Delegation {}
@@ -123,7 +123,7 @@ impl Display for Delegation {
}
}
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)]
pub struct PagedMixDelegationsResponse {
pub delegations: Vec<Delegation>,
pub start_next_after: Option<(String, u64)>,
@@ -138,7 +138,7 @@ impl PagedMixDelegationsResponse {
}
}
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)]
pub struct PagedDelegatorDelegationsResponse {
pub delegations: Vec<Delegation>,
pub start_next_after: Option<IdentityKey>,
@@ -153,7 +153,7 @@ impl PagedDelegatorDelegationsResponse {
}
}
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)]
pub struct PagedAllDelegationsResponse {
pub delegations: Vec<Delegation>,
pub start_next_after: Option<(IdentityKey, Vec<u8>, u64)>,
@@ -8,7 +8,7 @@ use serde::{Deserialize, Serialize};
use std::cmp::Ordering;
use std::fmt::Display;
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, PartialOrd, Serialize, JsonSchema)]
#[derive(Clone, Debug, Deserialize, PartialEq, PartialOrd, Serialize, JsonSchema)]
pub struct Gateway {
pub host: String,
pub mix_port: u16,
@@ -136,12 +136,6 @@ pub struct GatewayOwnershipResponse {
pub gateway: Option<GatewayBond>,
}
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)]
pub struct GatewayBondResponse {
pub identity: IdentityKey,
pub gateway: Option<GatewayBond>,
}
#[cfg(test)]
mod tests {
use super::*;
@@ -59,7 +59,7 @@ pub(crate) mod string_rfc3339_offset_date_time {
}
}
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Eq, PartialOrd, Serialize)]
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, PartialOrd, Serialize)]
pub struct Interval {
id: u32,
#[serde(with = "string_rfc3339_offset_date_time")]
@@ -121,14 +121,6 @@ impl Interval {
self.start_unix_timestamp() <= block_time && block_time < self.end_unix_timestamp()
}
pub fn update_duration(&mut self, secs: u64) {
self.length = Duration::from_secs(secs);
}
pub const fn length_secs(&self) -> u64 {
self.length.as_secs()
}
/// Returns the next interval.
#[must_use]
pub fn next(&self) -> Self {
@@ -4,7 +4,7 @@
pub mod delegation;
pub mod error;
pub mod events;
pub mod gateway;
mod gateway;
mod interval;
pub mod mixnode;
mod msg;
@@ -18,13 +18,10 @@ pub use delegation::{
Delegation, PagedAllDelegationsResponse, PagedDelegatorDelegationsResponse,
PagedMixDelegationsResponse,
};
pub use gateway::{
Gateway, GatewayBond, GatewayBondResponse, GatewayOwnershipResponse, PagedGatewayResponse,
};
pub use gateway::{Gateway, GatewayBond, GatewayOwnershipResponse, PagedGatewayResponse};
pub use interval::Interval;
pub use mixnode::{
Layer, MixNode, MixNodeBond, MixOwnershipResponse, MixnodeBondResponse, PagedMixnodeResponse,
RewardedSetNodeStatus,
Layer, MixNode, MixNodeBond, MixOwnershipResponse, PagedMixnodeResponse, RewardedSetNodeStatus,
};
pub use msg::*;
pub use types::*;
@@ -19,7 +19,7 @@ use std::fmt::Display;
feature = "generate-ts",
ts(export_to = "ts-packages/types/src/types/rust/RewardedSetNodeStatus.ts")
)]
#[derive(Clone, Copy, Debug, Deserialize, Serialize, JsonSchema, PartialEq, Eq)]
#[derive(Clone, Copy, Debug, Deserialize, Serialize, JsonSchema, PartialEq)]
pub enum RewardedSetNodeStatus {
Active,
Standby,
@@ -37,6 +37,16 @@ pub enum DelegationEvent {
Undelegate(PendingUndelegate),
}
impl DelegationEvent {
pub fn delegation_amount(&self) -> Option<Coin> {
match self {
DelegationEvent::Delegate(delegation) => Some(delegation.amount.clone()),
// I think it would be nice to also expose an amount here to know how much we're undelegating
DelegationEvent::Undelegate(_) => None,
}
}
}
#[derive(Clone, Debug, Deserialize, Serialize, JsonSchema)]
pub struct PendingUndelegate {
mix_identity: IdentityKey,
@@ -106,7 +116,7 @@ impl PendingUndelegate {
}
}
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, PartialOrd, Serialize, JsonSchema)]
#[derive(Clone, Debug, Deserialize, PartialEq, PartialOrd, Serialize, JsonSchema)]
pub struct MixNode {
pub host: String,
pub mix_port: u16,
@@ -220,9 +230,9 @@ impl DelegatorRewardParams {
// change all values into their fixed representations
let delegation_amount = U128::from_num(delegation_amount.u128());
let staking_supply = U128::from_num(self.reward_params.staking_supply());
let circulating_supply = U128::from_num(self.reward_params.circulating_supply());
let scaled_delegation_amount = delegation_amount / staking_supply;
let scaled_delegation_amount = delegation_amount / circulating_supply;
// Div by zero checked above
let delegator_reward =
@@ -245,7 +255,7 @@ impl DelegatorRewardParams {
}
}
#[derive(Debug, Clone, JsonSchema, PartialEq, Eq, Serialize, Deserialize, Copy)]
#[derive(Debug, Clone, JsonSchema, PartialEq, Serialize, Deserialize, Copy)]
pub struct StoredNodeRewardResult {
reward: Uint128,
@@ -392,21 +402,22 @@ impl MixNodeBond {
self.total_delegation.clone()
}
pub fn stake_saturation(&self, staking_supply: u128, rewarded_set_size: u32) -> U128 {
self.total_bond_to_staking_supply(staking_supply) * U128::from_num(rewarded_set_size)
pub fn stake_saturation(&self, circulating_supply: u128, rewarded_set_size: u32) -> U128 {
self.total_bond_to_circulating_supply(circulating_supply)
* U128::from_num(rewarded_set_size)
}
// TODO: There is an effect here when adding accumulted rewards to the total bond, ie accumulated rewards will not
// affect lambda, but will affect sigma, in turn over time, if left unclaimed operator rewards will not compound, but
// behave similarly to delegations.
// The question is should this be taken into account when calculating operator rewards?
pub fn pledge_to_staking_supply(&self, staking_supply: u128) -> U128 {
U128::from_num(self.pledge_amount().amount.u128()) / U128::from_num(staking_supply)
pub fn pledge_to_circulating_supply(&self, circulating_supply: u128) -> U128 {
U128::from_num(self.pledge_amount().amount.u128()) / U128::from_num(circulating_supply)
}
pub fn total_bond_to_staking_supply(&self, staking_supply: u128) -> U128 {
pub fn total_bond_to_circulating_supply(&self, circulating_supply: u128) -> U128 {
U128::from_num(self.pledge_amount().amount.u128() + self.total_delegation().amount.u128())
/ U128::from_num(staking_supply)
/ U128::from_num(circulating_supply)
}
pub fn lambda_ticked(&self, params: &RewardParams) -> U128 {
@@ -416,7 +427,7 @@ impl MixNodeBond {
pub fn lambda(&self, params: &RewardParams) -> U128 {
// Ratio of a bond to the token circulating supply
self.pledge_to_staking_supply(params.staking_supply())
self.pledge_to_circulating_supply(params.circulating_supply())
}
pub fn sigma_ticked(&self, params: &RewardParams) -> U128 {
@@ -426,12 +437,11 @@ impl MixNodeBond {
pub fn sigma(&self, params: &RewardParams) -> U128 {
// Ratio of a delegation to the the token circulating supply
self.total_bond_to_staking_supply(params.staking_supply())
self.total_bond_to_circulating_supply(params.circulating_supply())
}
pub fn estimate_reward(
&self,
base_operator_cost: u64,
params: &RewardParams,
) -> Result<RewardEstimate, MixnetContractError> {
let total_node_reward = self
@@ -440,15 +450,15 @@ impl MixNodeBond {
.checked_to_num::<u128>()
.unwrap_or_default();
let node_profit = self
.node_profit(params, base_operator_cost)
.node_profit(params)
.checked_to_num::<u128>()
.unwrap_or_default();
let operator_cost = params
.node
.operator_cost(base_operator_cost)
.operator_cost()
.checked_to_num::<u128>()
.unwrap_or_default();
let operator_reward = self.operator_reward(params, base_operator_cost);
let operator_reward = self.operator_reward(params);
// Total reward has to be the sum of operator and delegator rewards
let delegators_reward = node_profit.saturating_sub(operator_reward);
@@ -480,25 +490,21 @@ impl MixNodeBond {
}
}
pub fn node_profit(&self, params: &RewardParams, base_operator_cost: u64) -> U128 {
pub fn node_profit(&self, params: &RewardParams) -> U128 {
self.reward(params)
.reward()
.saturating_sub(params.node.operator_cost(base_operator_cost))
.saturating_sub(params.node.operator_cost())
}
pub fn operator_reward(&self, params: &RewardParams, base_operator_cost: u64) -> u128 {
pub fn operator_reward(&self, params: &RewardParams) -> u128 {
let reward = self.reward(params);
if reward.sigma == 0u128 {
if reward.sigma == 0 {
return 0;
}
let profit = reward
.reward
.saturating_sub(params.node.operator_cost(base_operator_cost));
let profit = reward.reward.saturating_sub(params.node.operator_cost());
let operator_base_reward = reward
.reward
.min(params.node.operator_cost(base_operator_cost));
let operator_base_reward = reward.reward.min(params.node.operator_cost());
// Div by zero checked above
let operator_reward = (self.profit_margin()
+ (ONE - self.profit_margin()) * reward.lambda / reward.sigma)
@@ -519,23 +525,19 @@ impl MixNodeBond {
}
pub fn sigma_ratio(&self, params: &RewardParams) -> U128 {
if self.total_bond_to_staking_supply(params.staking_supply()) < params.one_over_k() {
self.total_bond_to_staking_supply(params.staking_supply())
if self.total_bond_to_circulating_supply(params.circulating_supply()) < params.one_over_k()
{
self.total_bond_to_circulating_supply(params.circulating_supply())
} else {
params.one_over_k()
}
}
pub fn reward_delegation(
&self,
delegation_amount: Uint128,
params: &RewardParams,
base_operator_cost: u64,
) -> u128 {
pub fn reward_delegation(&self, delegation_amount: Uint128, params: &RewardParams) -> u128 {
let reward_params = DelegatorRewardParams::new(
self.sigma(params),
self.profit_margin(),
self.node_profit(params, base_operator_cost),
self.node_profit(params),
params.to_owned(),
);
reward_params.determine_delegation_reward(delegation_amount)
@@ -645,12 +647,6 @@ pub struct MixOwnershipResponse {
pub mixnode: Option<MixNodeBond>,
}
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)]
pub struct MixnodeBondResponse {
pub identity: IdentityKey,
pub mixnode: Option<MixNodeBond>,
}
#[cfg(test)]
mod tests {
use super::*;
@@ -7,12 +7,12 @@ use crate::{Gateway, IdentityKey, MixNode};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct InstantiateMsg {
pub rewarding_validator_address: String,
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum ExecuteMsg {
UpdateRewardingValidatorAddress {
@@ -112,10 +112,9 @@ pub enum ExecuteMsg {
},
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum QueryMsg {
GetCurrentOperatorCost {},
GetRewardingValidatorAddress {},
GetAllDelegationKeys {},
DebugGetAllDelegationValues {},
@@ -134,12 +133,6 @@ pub enum QueryMsg {
OwnsGateway {
address: String,
},
GetMixnodeBond {
identity: IdentityKey,
},
GetGatewayBond {
identity: IdentityKey,
},
StateParams {},
// gets all [paged] delegations associated with particular mixnode
GetMixnodeDelegations {
@@ -166,7 +159,6 @@ pub enum QueryMsg {
LayerDistribution {},
GetRewardPool {},
GetCirculatingSupply {},
GetStakingSupply {},
GetIntervalRewardPercent {},
GetSybilResistancePercent {},
GetActiveSetWorkFactor {},
@@ -205,6 +197,6 @@ pub enum QueryMsg {
},
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub struct MigrateMsg {}
@@ -1,10 +1,11 @@
use crate::{error::MixnetContractError, mixnode::StoredNodeRewardResult, ONE, U128};
use az::CheckedCast;
use cosmwasm_std::Uint128;
use network_defaults::DEFAULT_OPERATOR_INTERVAL_COST;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, JsonSchema, PartialEq, Eq, Serialize, Deserialize, Copy)]
#[derive(Debug, Clone, JsonSchema, PartialEq, Serialize, Deserialize, Copy)]
pub struct NodeEpochRewards {
params: NodeRewardParams,
result: StoredNodeRewardResult,
@@ -40,23 +41,19 @@ impl NodeEpochRewards {
self.result.reward()
}
pub fn operator_cost(&self, base_operator_cost: u64) -> U128 {
self.params.operator_cost(base_operator_cost)
pub fn operator_cost(&self) -> U128 {
self.params.operator_cost()
}
pub fn node_profit(&self, base_operator_cost: u64) -> U128 {
pub fn node_profit(&self) -> U128 {
let reward = U128::from_num(self.reward().u128());
// if operating cost is higher then the reward node profit is 0
reward.saturating_sub(self.operator_cost(base_operator_cost))
reward.saturating_sub(self.operator_cost())
}
pub fn operator_reward(
&self,
profit_margin: U128,
base_operator_cost: u64,
) -> Result<Uint128, MixnetContractError> {
let reward = self.node_profit(base_operator_cost);
let operator_base_reward = reward.min(self.operator_cost(base_operator_cost));
pub fn operator_reward(&self, profit_margin: U128) -> Result<Uint128, MixnetContractError> {
let reward = self.node_profit();
let operator_base_reward = reward.min(self.operator_cost());
let div_by_zero_check = if let Some(value) = self.lambda().checked_div(self.sigma()) {
value
} else {
@@ -77,14 +74,13 @@ impl NodeEpochRewards {
&self,
delegation_amount: Uint128,
profit_margin: U128,
base_operator_cost: u64,
epoch_reward_params: EpochRewardParams,
) -> Result<Uint128, MixnetContractError> {
// change all values into their fixed representations
let delegation_amount = U128::from_num(delegation_amount.u128());
let staking_supply = U128::from_num(epoch_reward_params.staking_supply());
let circulating_supply = U128::from_num(epoch_reward_params.circulating_supply());
let scaled_delegation_amount = delegation_amount / staking_supply;
let scaled_delegation_amount = delegation_amount / circulating_supply;
let check_div_by_zero =
if let Some(value) = scaled_delegation_amount.checked_div(self.sigma()) {
@@ -93,8 +89,7 @@ impl NodeEpochRewards {
return Err(MixnetContractError::DivisionByZero);
};
let delegator_reward =
(ONE - profit_margin) * check_div_by_zero * self.node_profit(base_operator_cost);
let delegator_reward = (ONE - profit_margin) * check_div_by_zero * self.node_profit();
let reward = delegator_reward.max(U128::ZERO);
if let Some(int_reward) = reward.checked_cast() {
@@ -105,13 +100,12 @@ impl NodeEpochRewards {
}
}
#[derive(Debug, Clone, JsonSchema, PartialEq, Eq, Serialize, Deserialize, Copy)]
#[derive(Debug, Clone, JsonSchema, PartialEq, Serialize, Deserialize, Copy)]
pub struct EpochRewardParams {
epoch_reward_pool: Uint128,
rewarded_set_size: Uint128,
active_set_size: Uint128,
#[serde(alias = "circulating_supply")]
staking_supply: Uint128,
circulating_supply: Uint128,
sybil_resistance_percent: u8,
active_set_work_factor: u8,
}
@@ -121,7 +115,7 @@ impl EpochRewardParams {
epoch_reward_pool: u128,
rewarded_set_size: u128,
active_set_size: u128,
staking_supply: u128,
circulating_supply: u128,
sybil_resistance_percent: u8,
active_set_work_factor: u8,
) -> EpochRewardParams {
@@ -129,7 +123,7 @@ impl EpochRewardParams {
epoch_reward_pool: Uint128::new(epoch_reward_pool),
rewarded_set_size: Uint128::new(rewarded_set_size),
active_set_size: Uint128::new(active_set_size),
staking_supply: Uint128::new(staking_supply),
circulating_supply: Uint128::new(circulating_supply),
sybil_resistance_percent,
active_set_work_factor,
}
@@ -142,7 +136,7 @@ impl EpochRewardParams {
pub fn new_empty() -> Self {
EpochRewardParams {
epoch_reward_pool: Uint128::new(0),
staking_supply: Uint128::new(0),
circulating_supply: Uint128::new(0),
sybil_resistance_percent: 0,
rewarded_set_size: Uint128::new(0),
active_set_size: Uint128::new(0),
@@ -158,24 +152,16 @@ impl EpochRewardParams {
self.active_set_size.u128()
}
pub fn staking_supply(&self) -> u128 {
self.staking_supply.u128()
pub fn circulating_supply(&self) -> u128 {
self.circulating_supply.u128()
}
pub fn epoch_reward_pool(&self) -> u128 {
self.epoch_reward_pool.u128()
}
pub fn sybil_resistance_percent(&self) -> u8 {
self.sybil_resistance_percent
}
pub fn active_set_work_factor(&self) -> u8 {
self.active_set_work_factor
}
}
#[derive(Debug, Clone, JsonSchema, PartialEq, Eq, Serialize, Deserialize, Copy)]
#[derive(Debug, Clone, JsonSchema, PartialEq, Serialize, Deserialize, Copy)]
pub struct NodeRewardParams {
reward_blockstamp: u64,
uptime: Uint128,
@@ -191,8 +177,8 @@ impl NodeRewardParams {
}
}
pub fn operator_cost(&self, base_operator_cost: u64) -> U128 {
self.performance() * U128::from_num(base_operator_cost)
pub fn operator_cost(&self) -> U128 {
self.performance() * U128::from_num(DEFAULT_OPERATOR_INTERVAL_COST)
}
pub fn uptime(&self) -> Uint128 {
@@ -208,7 +194,7 @@ impl NodeRewardParams {
}
}
#[derive(Debug, Clone, JsonSchema, PartialEq, Eq, Serialize, Deserialize, Copy)]
#[derive(Debug, Clone, JsonSchema, PartialEq, Serialize, Deserialize, Copy)]
pub struct RewardParams {
pub epoch: EpochRewardParams,
pub node: NodeRewardParams,
@@ -266,8 +252,8 @@ impl RewardParams {
self.epoch.rewarded_set_size.u128()
}
pub fn staking_supply(&self) -> u128 {
self.epoch.staking_supply.u128()
pub fn circulating_supply(&self) -> u128 {
self.epoch.circulating_supply.u128()
}
pub fn reward_blockstamp(&self) -> u64 {
@@ -27,7 +27,7 @@ impl LayerDistribution {
}
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct ContractStateParams {
// so currently interval_length is being unused and validator API performs rewarding
// based on its own interval length config value. I guess that's fine for time being
@@ -43,7 +43,6 @@ pub struct ContractStateParams {
// subset of rewarded mixnodes that are actively receiving mix traffic
// used to handle shorter-term (e.g. hourly) fluctuations of demand
pub mixnode_active_set_size: u32,
pub staking_supply: Uint128,
}
impl Display for ContractStateParams {
@@ -72,7 +71,7 @@ impl Display for ContractStateParams {
}
}
#[derive(Default, Debug, Serialize, Deserialize, PartialEq, Eq)]
#[derive(Default, Debug, Serialize, Deserialize, PartialEq)]
pub struct RewardingResult {
pub node_reward: Uint128,
}
@@ -124,21 +123,21 @@ pub type IdentityKey = String;
pub type IdentityKeyRef<'a> = &'a str;
pub type SphinxKey = String;
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq, JsonSchema)]
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, JsonSchema)]
pub struct PagedRewardedSetResponse {
pub identities: Vec<(IdentityKey, RewardedSetNodeStatus)>,
pub start_next_after: Option<IdentityKey>,
pub at_height: u64,
}
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)]
pub struct RewardedSetUpdateDetails {
pub refresh_rate_blocks: u64,
pub last_refreshed_block: u64,
pub current_height: u64,
}
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)]
pub struct IntervalRewardedSetHeightsResponse {
pub interval_id: u32,
pub heights: Vec<u64>,
@@ -11,4 +11,4 @@ cw3 = { version = "0.13.1" }
cw4 = { version = "0.13.1" }
cosmwasm-std = "1.0.0"
schemars = "0.8"
serde = { version = "1.0.103", default-features = false, features = ["derive"] }
serde = { version = "1.0.103", default-features = false, features = ["derive"] }
@@ -44,7 +44,7 @@ pub enum ExecuteMsg {
}
// We can also add this as a cw3 extension
#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, JsonSchema, Debug)]
#[derive(Serialize, Deserialize, Clone, PartialEq, JsonSchema, Debug)]
#[serde(rename_all = "snake_case")]
pub enum QueryMsg {
/// Return ThresholdResponse
@@ -19,7 +19,7 @@ pub fn one_ucoin() -> Coin {
feature = "generate-ts",
ts(export_to = "ts-packages/types/src/types/rust/Period.ts")
)]
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Clone, JsonSchema)]
#[derive(Debug, PartialEq, Serialize, Deserialize, Clone, JsonSchema)]
pub enum Period {
Before,
In(usize),
@@ -28,8 +28,8 @@ pub enum Period {
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct PledgeData {
amount: Coin,
block_time: Timestamp,
pub amount: Coin,
pub block_time: Timestamp,
}
impl PledgeData {
@@ -48,9 +48,9 @@ impl PledgeData {
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct OriginalVestingResponse {
amount: Coin,
number_of_periods: usize,
period_duration: u64,
pub amount: Coin,
pub number_of_periods: usize,
pub period_duration: u64,
}
impl OriginalVestingResponse {
@@ -1,19 +1,19 @@
use cosmwasm_std::{Coin, Timestamp, Uint128};
use cosmwasm_std::{Coin, Timestamp};
use mixnet_contract_common::{Gateway, IdentityKey, MixNode};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub struct InitMsg {
pub mixnet_contract_address: String,
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub struct MigrateMsg {}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema, Default)]
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema, Default)]
pub struct VestingSpecification {
start_time: Option<u64>,
period_seconds: Option<u64>,
@@ -113,12 +113,9 @@ pub enum ExecuteMsg {
UpdateStakingAddress {
to_address: Option<String>,
},
UpdateLockedPledgeCap {
amount: Uint128,
},
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum QueryMsg {
LockedCoins {
@@ -166,5 +163,4 @@ pub enum QueryMsg {
GetCurrentVestingPeriod {
address: String,
},
GetLockedPledgeCap {},
}
+1 -1
View File
@@ -17,4 +17,4 @@ tokio = { version = "1.19.1", features = [ "rt-multi-thread", "net", "signal", "
[build-dependencies]
sqlx = { version = "0.5", features = ["runtime-tokio-rustls", "sqlite", "macros", "migrate"] }
tokio = { version = "1.19.1", features = ["rt-multi-thread", "macros"] }
tokio = { version = "1.19.1", features = ["rt-multi-thread", "macros"] }
+1 -2
View File
@@ -15,11 +15,10 @@ url = "2.2"
coconut-interface = { path = "../coconut-interface" }
crypto = { path = "../crypto", features = ["rand", "asymmetric", "symmetric", "hashing"] }
network-defaults = { path = "../network-defaults" }
validator-api-requests = { path = "../../validator-api/validator-api-requests" }
validator-client = { path = "../client-libs/validator-client" }
[dev-dependencies]
rand = "0.7.3"
[features]
coconut = ["cosmrs"]
coconut = ["cosmrs"]
+2 -2
View File
@@ -3,13 +3,13 @@
use coconut_interface::{
aggregate_signature_shares, aggregate_verification_keys, prove_bandwidth_credential, Attribute,
BlindedSignature, Credential, Parameters, Signature, SignatureShare, VerificationKey,
BlindSignRequestBody, BlindedSignature, Credential, Parameters, Signature, SignatureShare,
VerificationKey,
};
use crypto::asymmetric::encryption::PublicKey;
use crypto::shared_key::recompute_shared_key;
use crypto::symmetric::stream_cipher;
use url::Url;
use validator_api_requests::coconut::BlindSignRequestBody;
use crate::coconut::bandwidth::{BandwidthVoucher, PRIVATE_ATTRIBUTES, PUBLIC_ATTRIBUTES};
use crate::coconut::params::{

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