Compare commits

...

184 Commits

Author SHA1 Message Date
mx 7e7200a7c8 added note that operators can decrease self bond via wallet 2023-04-24 15:07:41 +02:00
Jon Häggblad 3f0d4846df Fix a few clippy warnings in contract test code (#3340)
* ci: don't fail fast for contracts

* contracts: fix clippy in tests
2023-04-24 10:30:22 +02:00
Jon Häggblad 9bfcdbe8e2 Add --all-targets to clippy for contracts (#3337) 2023-04-21 11:47:43 +02:00
Tommy Verrall 8c4885ce2c Merge pull request #3294 from nymtech/feature/fix-clippy-warnings
A branch with all clippy warnings dealt with in contracts
2023-04-21 10:37:33 +01:00
Tommy Verrall 926389df89 Merge pull request #3300 from nymtech/bugfix/empty-ack-stream-map
make sure to clear inner 'ack_map' in 'GatewaysReader'
2023-04-20 08:31:31 +01:00
Tommy Verrall b55db00408 Merge pull request #3324 from nymtech/bugfix/nym-cli-gateway-commands
exposed missing gateway commands in nym-cli
2023-04-20 07:55:56 +01:00
Jędrzej Stuczyński cfcb64f7e5 Feature/reduce pledge (#3254)
* basic contract work for 'decrease_pledge' functionality

note: it doesn't yet return tokens back to the operator

* returning extra tokens after decreasing pledge

* added vesting message to track pledge decrease

* attaching the track message when processing delegation decrease

* checking for zero value request

* fixed event test

* allowing to decrease pledge from the vesting contract

* integration test for the feature

* reorganised the integration tests

* updated nyxd client traits

* wallet support

* typescript helpers

* moved 'pledge more' functionality to operator commands

* cli commands for decreasing pledge

* changed error variant to make clippy happier

* removed unused import

* eslint

* fixed post-rebase imports

* added cargo config

* added PendingMixNodeChanges to MixNodeDetails

* returning event id after creating it

* Streamlined getting mixnode details by identity key

* setting pending pledge changes on increase/decrease

* clearing the value on resolving the event

* checking for correct invariants when clearing events

* further pending events unit tests fixes

* new unit tests for tx endpoints

* queries for pending events (by id)

* migration code

* using default value for pending changes if unavailable

* improved integration test assertions
2023-04-20 07:52:10 +01:00
Jon Häggblad 9c6c5f5170 Add --all-targets to nym-wallet CI clippy (#3326) 2023-04-19 10:44:46 +02:00
Jon Häggblad f28888e3e7 Update Cargo.lock files after bumping internal versions during 1.1.15 release 2023-04-19 09:41:03 +02:00
Jędrzej Stuczyński 9549bed8bb exposed missing gateway commands in nym-cli 2023-04-18 16:28:13 +01:00
Tommy Verrall 7c65d61d91 Merge pull request #3321 from nymtech/bug/explorer-fix-stake-saturation-sorting
Convert stake saturation string to number type
2023-04-18 13:57:07 +01:00
farbanas ad2efb7e62 Merge branch 'master' into develop 2023-04-18 14:35:56 +02:00
Drazen Urch a50c9bfa1a Outfox compatibility layer (#3317)
* Outfox compatibility layer

* Lint
2023-04-18 14:07:34 +02:00
mx 30cdbf535a added polkachu snapshot links 2023-04-18 13:26:02 +02:00
mx f5365cbca9 reintroduced laddr change to config setup instructions 2023-04-18 13:11:13 +02:00
mx 22e7cb887b final tweaks 2023-04-18 13:08:21 +02:00
fmtabbara b571f1a881 convert stake saturation string to number type 2023-04-18 11:32:35 +01:00
mx b1c4e3ded7 hotfix on sandbox testnet naming 2023-04-18 12:30:44 +02:00
mx 4694ded8bd updated platform release version variable 2023-04-18 12:17:47 +02:00
mx 7971573026 hotfix on sandbox testnet naming 2023-04-18 12:16:49 +02:00
Jon Häggblad c4780c8af2 Rework Poisson process throttling to more aggressively up-regulate (#3298)
* Rework Poisson process throttling

* Tweak parameters
2023-04-18 12:07:54 +02:00
farbanas 246f0b3f52 fix: nym-wallet CHANGELOG version 2023-04-18 11:43:10 +02:00
Jon Häggblad 7879d76592 Reduce logging of warnings associated with Poisson process throttling (#3314)
* Reduce logging of warnings associated with Poisson process throttling

* More granularity when logging about slow gateway

* Refine logging of elevated delay multiplier

* clippy

* Tweak output when printing address

* rustfmt

* Fix initial delay
2023-04-18 11:40:50 +02:00
Bogdan-Ștefan Neacşu 0f62ea25d8 Fix nym-cli clap requirement (#3303) 2023-04-18 12:31:42 +03:00
mx 6dbe8205d6 updated version var in book.toml 2023-04-18 11:14:29 +02:00
mx 1b94ad5c4c Merge pull request #3291 from nymtech/feature/add-docs-to-monorepo
Feature/add docs to monorepo
2023-04-18 09:03:41 +00:00
mx 37be99ab8f Merge branch 'release/v1.1.15' into feature/add-docs-to-monorepo 2023-04-18 09:02:59 +00:00
farbanas 6f5cee8c36 chore: updated changelogs, revert change to nym-connect version as there were no changes 2023-04-18 10:54:57 +02:00
farbanas 58d805ab72 chore: update contract versions in preparation for release v1.1.15 2023-04-18 10:27:43 +02:00
farbanas 68ad75f737 chore: update contract versions in preparation for release v1.1.15 2023-04-18 10:25:52 +02:00
farbanas 73ea2b5fec chore: update versions in preparation for release v1.1.15 2023-04-18 10:15:24 +02:00
pierre a0b37daeb0 build: fix clippy ci 2023-04-18 09:48:28 +02:00
Pierre Dommerc c9972047f6 feat(wallet): app version check (#3308) (#3319)
* feat(wallet): app version check (#3308)

* wrap tauri calls to check version into try/catch
2023-04-17 18:19:23 +02:00
mx ccdf698380 added docs and devportal import to changelog 2023-04-17 17:23:19 +02:00
Raphaël Walther c10ed5a2f3 Enable dependabot on github actions 2023-04-17 17:23:19 +02:00
Raphaël Walther 600b6d2b03 Move workflow broken link check 2023-04-17 17:23:19 +02:00
Raphaël Walther b1391bbb17 Move workflow broken link check 2023-04-17 17:23:19 +02:00
Raphaël Walther a171103a80 Move workflow broken link check 2023-04-17 17:23:19 +02:00
mx 3e2009aa9d small tweaks 2023-04-17 17:23:19 +02:00
mx 4b6e942667 small tweak to make generic 2023-04-17 17:23:19 +02:00
mx a6723044b9 removed accidental hyperlink 2023-04-17 17:23:19 +02:00
mx f60a25ee2d * added sandbox makefile env
* updated sandbox persistent peer address
2023-04-17 17:23:19 +02:00
Raphaël Walther 770baefe35 Add workflow for dev-portal deployment 2023-04-17 17:23:19 +02:00
Raphaël Walther 1c3403d7e6 Add workflow for dev-portal deployment 2023-04-17 17:23:19 +02:00
Raphaël Walther 342fd869a2 Add workflow for dev-portal deployment 2023-04-17 17:23:19 +02:00
Raphaël Walther 6f7db4172f Add workflow for dev-portal deployment 2023-04-17 17:23:19 +02:00
Raphaël Walther 55fd7b8890 Add workflow for dev-portal deployment 2023-04-17 17:23:19 +02:00
Raphaël Walther a14b4dc80c Add workflow for dev-portal deployment 2023-04-17 17:23:19 +02:00
Raoul c81f6962d7 fix a minor issue in mkdir/touch paths 2023-04-17 17:23:19 +02:00
Raphaël Walther 9f4ef6842b Add workflow for docs deployment 2023-04-17 17:23:19 +02:00
Raphaël Walther 7ca0c06c87 Add workflow for docs deployment 2023-04-17 17:23:19 +02:00
Raphaël Walther 57aa763a84 Add workflow for docs deployment 2023-04-17 17:23:19 +02:00
Raphaël Walther ba5fecf6b3 Add workflow for docs deployment 2023-04-17 17:23:19 +02:00
Raphaël Walther 35343509f9 Add workflow for docs deployment 2023-04-17 17:23:19 +02:00
Raphaël Walther 42d8b06346 Add workflow for docs deployment 2023-04-17 17:23:19 +02:00
Raphaël Walther f30f0e8316 Add workflow for docs deployment 2023-04-17 17:23:19 +02:00
Raphaël Walther e1aaf509d1 Add workflow for docs deployment 2023-04-17 17:23:19 +02:00
Raphaël Walther 8db5eadea6 Add workflow for docs deployment 2023-04-17 17:23:19 +02:00
Raphaël Walther 4dda824d37 Add workflow for docs deployment 2023-04-17 17:23:19 +02:00
mx 0579b3afb0 Update validator-setup.md 2023-04-17 17:23:19 +02:00
mx d328c458e6 updated readmes 2023-04-17 17:23:19 +02:00
mx c8651cddbb removed comment on NR 2023-04-17 17:23:19 +02:00
mx cde2a1ab26 tried to get run autocommands to work. 2023-04-17 17:23:19 +02:00
mx 8d78c92c03 format tweaking validator 2023-04-17 17:23:19 +02:00
mx af311c3d33 checked over devportal 2023-04-17 17:23:19 +02:00
mx 906bcf1634 added websocket client cmdrun automation 2023-04-17 17:23:19 +02:00
mx 843bd4f4fa some final cmdrun cleanup 2023-04-17 17:23:19 +02:00
mx 9bbe4a96d0 temp commit 2023-04-17 17:23:19 +02:00
mx 974ac0691c pushed dev-portal theme to remote for rebase to autodeploy working branch 2023-04-17 17:23:19 +02:00
mx 1188e48313 pushed theme to remote for rebase to autodeploy working branch 2023-04-17 17:23:19 +02:00
mx e7ed5f3de3 changed default theme build behaviour in book.toml for autodeploy 2023-04-17 17:23:19 +02:00
mx d45b2de241 pulled in missed out upgrade path info 2023-04-17 17:23:19 +02:00
mx 3d9cbf351f * started adding cmdrun command inputs instead of hardcoded command
outputs
2023-04-17 17:23:19 +02:00
mx 844e22d94d precommit before trying to import autocommands 2023-04-17 17:23:18 +02:00
mx 09c905910e added link to mdbook docs 2023-04-17 17:23:18 +02:00
mx 8fd8bf8792 * deleted old ama layout css
* edited gitignore files
2023-04-17 17:23:18 +02:00
mx 243658637c * changed manual devrel ama links to playlist embed
* removed 'coming soon' from intro links
2023-04-17 17:23:18 +02:00
mx 5603a79d49 cleanup validator docs: makefile instructions + general tweak 2023-04-17 17:23:18 +02:00
mx 0007a4cc74 * updated software prerequisites
* added arch based prereq instructions to validator nodes
2023-04-17 17:23:18 +02:00
mx 3dafe02f0e first commit of moving docs and dev portal to monorepo 2023-04-17 17:23:18 +02:00
Pierre Dommerc e62e9cde02 feat(wallet): add security settings (#3262) 2023-04-17 16:38:17 +02:00
Pierre Dommerc cde53c02e7 feat(wallet): add security settings (#3262) 2023-04-17 16:36:39 +02:00
Pierre Dommerc de64da8e20 feat(wallet): app version check (#3308) 2023-04-17 15:12:26 +02:00
Jon Häggblad 683790b068 Merge remote-tracking branch 'origin/master' into release/v1.1.15 2023-04-17 15:05:03 +02:00
Tommy Verrall f9c24c8a23 Merge pull request #3318 from nymtech/fix/wallet-bonding-signature
Wallet - fix bonding signature issue with vesting acc
2023-04-17 13:06:19 +01:00
pierre 886bb95e18 fix bonding signature issue 2023-04-17 13:30:25 +02:00
Jon Häggblad 214fd0caf5 Fix issue where nr run failed on fresh init (#3316) 2023-04-17 12:25:20 +02:00
Jędrzej Stuczyński 4aeac1acd2 Revert "another broken test"
This reverts commit 679be24074.
2023-04-14 16:56:26 +01:00
Jędrzej Stuczyński 679be24074 another broken test 2023-04-14 16:52:24 +01:00
Nadim Kobeissi 36e07f546d Merge pull request #3304 from nymtech/nadimkobeissi-fix-readme
Update README.md
2023-04-14 11:19:30 +02:00
Nadim Kobeissi d264feaf22 Update README.md
The link for build instructions was incorrect.
2023-04-14 11:19:11 +02:00
Dave Hrycyszyn 32b7b7afdc Update SECURITY.md 2023-04-13 12:23:01 +01:00
Jędrzej Stuczyński 7a50f0c3b2 make sure to clear inner 'ack_map' in 'GatewaysReader' 2023-04-13 10:51:03 +01:00
Jon Häggblad 091382ef30 Tidy the service provider directory contract (#3295)
Tidy the service provider directory contract after implementing query
methods on the validator-client.

- split out response types and use consistently
- query msg use "By" prefix
- pass address as String and validator
2023-04-12 09:22:35 +02:00
Dave Hrycyszyn 2da6a2fbfa Adding a clippy.toml so we can see correct warnings in mixnet contract 2023-04-11 14:57:04 +01:00
Dave Hrycyszyn d910a4e0ee The make test target seems to be wrapping differently than local 2023-04-11 14:53:51 +01:00
Dave Hrycyszyn 672ab79421 A branch with all clippy warnings dealt with in contracts 2023-04-11 14:46:45 +01:00
Bogdan-Ștefan Neacşu 1ad97adc7c Feature/sdk coconut (#3273)
* Replace expect with error

* Move PersistentStorage in separate file

* Add in-memory cred manager

* Make wasm and mobile build

* Unify wasm and mobile cred storage

* Network defaults has mainnet default

* Add network_details to SDK

* Move BandwidthController in its own crate

* Move out credential into lib crate

* Remove nyxd arg in credential binary

* Use acquire cred in sdk

* Add example file, in sandbox

* Mobile lock file

* Update changelog

* Clearer builder methods and more documentation for them

* Sign only amount, without denom

* Toggle credentials mode on when enabled
2023-04-11 16:17:35 +03:00
benedettadavico 2bd585a0ff Empty commit 2023-04-11 12:55:59 +02:00
Jon Häggblad df0b0367a4 Rename service provider owner to announcer (#3290) 2023-04-11 10:39:03 +02:00
Jon Häggblad bb9e26d745 Add build-release command to Makefile and tidy (#3288) 2023-04-11 08:03:30 +02:00
Jon Häggblad dc5c765ecb Last set of crates to add the nym- prefix to (#3286)
* Add nym- prefix to mixnode-common

* Add nym- prefix to mixnet-client

* Add nym-client- prefix to websocket-requests

* Makefile: add check target

* Rename to nym-credential-client

* rustfmt

* update to nym-credential-client in github workflow
2023-04-07 21:25:28 +02:00
Jon Häggblad 95e2e3d0d2 Comment out unused code that breaks clippy (#3287) 2023-04-06 23:05:47 +02:00
Jon Häggblad 690c4164a7 Cargo.lock 2023-04-06 15:15:24 +02:00
Jon Häggblad ee656aa3ef clippy: allow unused generic parameter 2023-04-06 12:47:19 +02:00
Tommy Verrall 3d4123aca5 Merge pull request #3217 from nymtech/feature/dual_packet_sizes 2023-04-06 11:09:28 +01:00
Jędrzej Stuczyński 29a8e23f72 added additional logs 2023-04-06 10:52:45 +01:00
Jędrzej Stuczyński a4c5407b04 removed redundant disconnect in simple.rs 2023-04-06 10:52:45 +01:00
Jędrzej Stuczyński 75bc36a9e6 post-rebase wasm fixes 2023-04-06 10:52:45 +01:00
Jędrzej Stuczyński b8e2fb46fb added config validation to network requester 2023-04-06 10:52:45 +01:00
Jędrzej Stuczyński eff931f9ca fixed network monitor 2023-04-06 10:52:45 +01:00
Jędrzej Stuczyński e4d8d721c0 adjusted message handler to allow for dual packet sizes 2023-04-06 10:52:45 +01:00
Jędrzej Stuczyński 21335b5ff1 ibid for the cover traffic stream 2023-04-06 10:52:45 +01:00
Jędrzej Stuczyński dadfdacf14 weighted decision on cover traffic packet size ('real traffic stream') 2023-04-06 10:52:45 +01:00
Jędrzej Stuczyński e3eeef4301 removed old deprecated 'extended_packet_size' 2023-04-06 10:52:45 +01:00
Jędrzej Stuczyński 6a519f4a1a message handler choosing packet size based on serialized size 2023-04-06 10:52:45 +01:00
Jędrzej Stuczyński fde8bd89b6 Ord and PartialOrd for PacketSize 2023-04-06 10:52:45 +01:00
Jędrzej Stuczyński 099013bc6d propagating packet size information to message preparer 2023-04-06 10:52:45 +01:00
Jędrzej Stuczyński 11eef024ea simplified real_messages_control config 2023-04-06 10:52:45 +01:00
Jędrzej Stuczyński cc6017db3b added packet size configuration to client config files 2023-04-06 10:52:42 +01:00
Jon Häggblad 84c1679973 Add more nym- crate prefixes (#3284)
* Add nym- prefix to nymcoconut

* Add nym- prefix to validator-client

* Add nym- prefix to gateway-requests

* Add nym- prefix to mobile-storage

* Add nym- prefix to gateway-client

* Add nym- prefix to client-core

* rustfmt
2023-04-06 09:04:49 +02:00
Jon Häggblad b1d18a5974 Makefile: invert NYM_NO_MOBILE flag (#3280) 2023-04-05 17:55:23 +02:00
Jon Häggblad 5019b4b266 Fix comments in nym-sdk builder_with_storage example (#3283) 2023-04-05 14:30:58 +02:00
Drazen Urch 790e7a0e1e Sphinx packet processing CPU cycles measurement (#3247)
* POC measurement

* parent ce76790761
author durch <durch@users.noreply.github.com> 1680116778 +0200
committer durch <durch@users.noreply.github.com> 1680683399 +0200

Instrument packet processing

* Cleanup and format

* Feature gate tracing

* Add .gitkeep to wallet dist

* Squashed commit of the following:

commit 0b1b6947e8
Author: Jon Häggblad <jon.haggblad@gmail.com>
Date:   Wed Apr 5 11:28:28 2023 +0200

    Replace mobile flag with target_os = android (#3278)

    * Remove old lock file

    * Start replacing mobile with android

    * Regex replace all mobile with android

    * Remove the mobile feature flag

    * keep the cfg mobile in tauri

commit c79b2cfb78
Author: Jon Häggblad <jon.haggblad@gmail.com>
Date:   Wed Apr 5 11:27:38 2023 +0200

    Service provider directory contract (#3220)

    * first commit of service provider directory contract proof of concept

    * *added config set on instantiation,
    *removed greetQuery test function

    * commit before mapping change

    * *changed mapping of service to use client address instead of cosmos addr

    * commit before mapping change

    * added acl to delete()

    * added test for acl in delete()

    * changed whitelist<vec> to standrd_whitelist bool in Service struct

    * removed old comments and commented out code

    * rustfmt

    * wup

    * wup

    * Older version of cw-multi-test that works with 1.0.0

    * wip

    * Remove .gitignore

    * Basic tests for announce and query now works

    * Restore tests for delete as well

    * Consolidate tests

    * Tidy

    * fmt

    * Start reworking test helpers

    * Tidy tests

    * More test work

    * More test improvements

    * More work on tests

    * Tweaks

    * Further tests

    * rustfmt

    * Add some comments

    * Initial work on requiring deposit

    * wip

    * Work on updating tests for handling funds

    * Start updating integration tests

    * Integration tests updated

    * merge test mods in state

    * Address review comments

    * Enable wasm-opt

    * Unify Result type

    * consistent amount in error type

    * WIP: paging output

    * IndexedMap working

    * extract to config file

    * WIP: middle of extracting out types

    * Extract types

    * wip

    * Types now extracted out:

    * Paged response type too

    * rustfmt

    * Start working on switching to cw Admin

    * Complete switch to Admin

    * Remove owner from announce msg

    * remove unused imports

    * Assert owner

    * Extract out types to common crate

    * Fix test compilation

    * Add query by owner and nym address

    * Move msg to common crate

    * rustfmt

    * tests for service id

    * service storage tests

    * state services tests

    * function rename

    * tidy

    * Fix clippy warning

    * User ServiceId instead and not u32

    * Delete by nym address

    * Emit explicit events

    * Swap ToString for Display

    * Move all storage keys to constants.rs

    * clippy

    * Test for deleting by name

    * Tidy integration tests

    * Remove to_string

    * Some comments to tests

    * Integration test for paging

    * serde snake_csae for NymAddress and ServiceType

    * Add migrate entry point

    * Add query contract version

    * A few more asserts for balance

    * Make MigrateMsg a struct

    ---------

    Co-authored-by: mx <maxhampshire@pm.me>

commit dd699bce9a
Merge: 5ce017ef3 e6957e7a9
Author: Tommy Verrall <60836166+tommyv1987@users.noreply.github.com>
Date:   Wed Apr 5 10:18:16 2023 +0100

    Merge pull request #3235 from nymtech/feature/performance-active-set-selection

    Feature/performance active set selection

commit 5ce017ef3d
Author: benedetta davico <46782255+benedettadavico@users.noreply.github.com>
Date:   Wed Apr 5 10:57:45 2023 +0200

    adding vesting tests (#3279)

commit 59c1ce2639
Merge: 4fb63d889 276edfd56
Author: Tommy Verrall <60836166+tommyv1987@users.noreply.github.com>
Date:   Wed Apr 5 09:50:53 2023 +0100

    Merge pull request #3261 from nymtech/feature/refresh-allow-list

    Feature/refresh allow list

commit 4fb63d8892
Author: Jędrzej Stuczyński <jedrzej.stuczynski@gmail.com>
Date:   Wed Apr 5 09:22:43 2023 +0100

    Feature/vesting delegation amount query (#3229)

    * moved queries and transactions out of contract.rs

    * added queries for vesting delegation details

    * nyxd_client support

commit 276edfd562
Author: Jędrzej Stuczyński <jedrzej.stuczynski@gmail.com>
Date:   Fri Mar 31 15:56:21 2023 +0100

    clippy

commit 605f8fcde3
Author: Jędrzej Stuczyński <jedrzej.stuczynski@gmail.com>
Date:   Fri Mar 31 15:06:12 2023 +0100

    updated and cleaned up tests

commit f0e4d1a7cf
Author: Jędrzej Stuczyński <jedrzej.stuczynski@gmail.com>
Date:   Fri Mar 31 14:01:36 2023 +0100

    configurable stored lists locations

commit 055ec4bdd5
Author: Jędrzej Stuczyński <jedrzej.stuczynski@gmail.com>
Date:   Fri Mar 31 12:57:02 2023 +0100

    updating stored allow list on file changes

commit 5761f9ac7f
Author: Jędrzej Stuczyński <jedrzej.stuczynski@gmail.com>
Date:   Fri Mar 31 12:15:45 2023 +0100

    file watcher

commit 32620fd55f
Author: Jędrzej Stuczyński <jedrzej.stuczynski@gmail.com>
Date:   Thu Mar 30 17:47:12 2023 +0100

    updating standard list in a timer

commit abb5cdbe06
Author: Jędrzej Stuczyński <jedrzej.stuczynski@gmail.com>
Date:   Thu Mar 30 16:43:58 2023 +0100

    extracted domain and ipnet information to separate struct

commit e6957e7a99
Author: Jędrzej Stuczyński <jedrzej.stuczynski@gmail.com>
Date:   Tue Mar 28 11:25:43 2023 +0100

    use combination of stake and performance for rewarded set selection

commit de2406a2c7
Author: Jędrzej Stuczyński <jedrzej.stuczynski@gmail.com>
Date:   Tue Mar 28 10:54:14 2023 +0100

    Moved MixnodeWithPerformance to helpers

* Squashed commit of the following:

commit 0b1b6947e8
Author: Jon Häggblad <jon.haggblad@gmail.com>
Date:   Wed Apr 5 11:28:28 2023 +0200

    Replace mobile flag with target_os = android (#3278)

    * Remove old lock file

    * Start replacing mobile with android

    * Regex replace all mobile with android

    * Remove the mobile feature flag

    * keep the cfg mobile in tauri

commit c79b2cfb78
Author: Jon Häggblad <jon.haggblad@gmail.com>
Date:   Wed Apr 5 11:27:38 2023 +0200

    Service provider directory contract (#3220)

    * first commit of service provider directory contract proof of concept

    * *added config set on instantiation,
    *removed greetQuery test function

    * commit before mapping change

    * *changed mapping of service to use client address instead of cosmos addr

    * commit before mapping change

    * added acl to delete()

    * added test for acl in delete()

    * changed whitelist<vec> to standrd_whitelist bool in Service struct

    * removed old comments and commented out code

    * rustfmt

    * wup

    * wup

    * Older version of cw-multi-test that works with 1.0.0

    * wip

    * Remove .gitignore

    * Basic tests for announce and query now works

    * Restore tests for delete as well

    * Consolidate tests

    * Tidy

    * fmt

    * Start reworking test helpers

    * Tidy tests

    * More test work

    * More test improvements

    * More work on tests

    * Tweaks

    * Further tests

    * rustfmt

    * Add some comments

    * Initial work on requiring deposit

    * wip

    * Work on updating tests for handling funds

    * Start updating integration tests

    * Integration tests updated

    * merge test mods in state

    * Address review comments

    * Enable wasm-opt

    * Unify Result type

    * consistent amount in error type

    * WIP: paging output

    * IndexedMap working

    * extract to config file

    * WIP: middle of extracting out types

    * Extract types

    * wip

    * Types now extracted out:

    * Paged response type too

    * rustfmt

    * Start working on switching to cw Admin

    * Complete switch to Admin

    * Remove owner from announce msg

    * remove unused imports

    * Assert owner

    * Extract out types to common crate

    * Fix test compilation

    * Add query by owner and nym address

    * Move msg to common crate

    * rustfmt

    * tests for service id

    * service storage tests

    * state services tests

    * function rename

    * tidy

    * Fix clippy warning

    * User ServiceId instead and not u32

    * Delete by nym address

    * Emit explicit events

    * Swap ToString for Display

    * Move all storage keys to constants.rs

    * clippy

    * Test for deleting by name

    * Tidy integration tests

    * Remove to_string

    * Some comments to tests

    * Integration test for paging

    * serde snake_csae for NymAddress and ServiceType

    * Add migrate entry point

    * Add query contract version

    * A few more asserts for balance

    * Make MigrateMsg a struct

    ---------

    Co-authored-by: mx <maxhampshire@pm.me>

commit dd699bce9a
Merge: 5ce017ef3 e6957e7a9
Author: Tommy Verrall <60836166+tommyv1987@users.noreply.github.com>
Date:   Wed Apr 5 10:18:16 2023 +0100

    Merge pull request #3235 from nymtech/feature/performance-active-set-selection

    Feature/performance active set selection

commit 5ce017ef3d
Author: benedetta davico <46782255+benedettadavico@users.noreply.github.com>
Date:   Wed Apr 5 10:57:45 2023 +0200

    adding vesting tests (#3279)

commit 59c1ce2639
Merge: 4fb63d889 276edfd56
Author: Tommy Verrall <60836166+tommyv1987@users.noreply.github.com>
Date:   Wed Apr 5 09:50:53 2023 +0100

    Merge pull request #3261 from nymtech/feature/refresh-allow-list

    Feature/refresh allow list

commit 4fb63d8892
Author: Jędrzej Stuczyński <jedrzej.stuczynski@gmail.com>
Date:   Wed Apr 5 09:22:43 2023 +0100

    Feature/vesting delegation amount query (#3229)

    * moved queries and transactions out of contract.rs

    * added queries for vesting delegation details

    * nyxd_client support

commit 276edfd562
Author: Jędrzej Stuczyński <jedrzej.stuczynski@gmail.com>
Date:   Fri Mar 31 15:56:21 2023 +0100

    clippy

commit 605f8fcde3
Author: Jędrzej Stuczyński <jedrzej.stuczynski@gmail.com>
Date:   Fri Mar 31 15:06:12 2023 +0100

    updated and cleaned up tests

commit f0e4d1a7cf
Author: Jędrzej Stuczyński <jedrzej.stuczynski@gmail.com>
Date:   Fri Mar 31 14:01:36 2023 +0100

    configurable stored lists locations

commit 055ec4bdd5
Author: Jędrzej Stuczyński <jedrzej.stuczynski@gmail.com>
Date:   Fri Mar 31 12:57:02 2023 +0100

    updating stored allow list on file changes

commit 5761f9ac7f
Author: Jędrzej Stuczyński <jedrzej.stuczynski@gmail.com>
Date:   Fri Mar 31 12:15:45 2023 +0100

    file watcher

commit 32620fd55f
Author: Jędrzej Stuczyński <jedrzej.stuczynski@gmail.com>
Date:   Thu Mar 30 17:47:12 2023 +0100

    updating standard list in a timer

commit abb5cdbe06
Author: Jędrzej Stuczyński <jedrzej.stuczynski@gmail.com>
Date:   Thu Mar 30 16:43:58 2023 +0100

    extracted domain and ipnet information to separate struct

commit e6957e7a99
Author: Jędrzej Stuczyński <jedrzej.stuczynski@gmail.com>
Date:   Tue Mar 28 11:25:43 2023 +0100

    use combination of stake and performance for rewarded set selection

commit de2406a2c7
Author: Jędrzej Stuczyński <jedrzej.stuczynski@gmail.com>
Date:   Tue Mar 28 10:54:14 2023 +0100

    Moved MixnodeWithPerformance to helpers
2023-04-05 12:29:41 +02:00
Jon Häggblad 0b1b6947e8 Replace mobile flag with target_os = android (#3278)
* Remove old lock file

* Start replacing mobile with android

* Regex replace all mobile with android

* Remove the mobile feature flag

* keep the cfg mobile in tauri
2023-04-05 11:28:28 +02:00
Jon Häggblad c79b2cfb78 Service provider directory contract (#3220)
* first commit of service provider directory contract proof of concept

* *added config set on instantiation,
*removed greetQuery test function

* commit before mapping change

* *changed mapping of service to use client address instead of cosmos addr

* commit before mapping change

* added acl to delete()

* added test for acl in delete()

* changed whitelist<vec> to standrd_whitelist bool in Service struct

* removed old comments and commented out code

* rustfmt

* wup

* wup

* Older version of cw-multi-test that works with 1.0.0

* wip

* Remove .gitignore

* Basic tests for announce and query now works

* Restore tests for delete as well

* Consolidate tests

* Tidy

* fmt

* Start reworking test helpers

* Tidy tests

* More test work

* More test improvements

* More work on tests

* Tweaks

* Further tests

* rustfmt

* Add some comments

* Initial work on requiring deposit

* wip

* Work on updating tests for handling funds

* Start updating integration tests

* Integration tests updated

* merge test mods in state

* Address review comments

* Enable wasm-opt

* Unify Result type

* consistent amount in error type

* WIP: paging output

* IndexedMap working

* extract to config file

* WIP: middle of extracting out types

* Extract types

* wip

* Types now extracted out:

* Paged response type too

* rustfmt

* Start working on switching to cw Admin

* Complete switch to Admin

* Remove owner from announce msg

* remove unused imports

* Assert owner

* Extract out types to common crate

* Fix test compilation

* Add query by owner and nym address

* Move msg to common crate

* rustfmt

* tests for service id

* service storage tests

* state services tests

* function rename

* tidy

* Fix clippy warning

* User ServiceId instead and not u32

* Delete by nym address

* Emit explicit events

* Swap ToString for Display

* Move all storage keys to constants.rs

* clippy

* Test for deleting by name

* Tidy integration tests

* Remove to_string

* Some comments to tests

* Integration test for paging

* serde snake_csae for NymAddress and ServiceType

* Add migrate entry point

* Add query contract version

* A few more asserts for balance

* Make MigrateMsg a struct

---------

Co-authored-by: mx <maxhampshire@pm.me>
2023-04-05 11:27:38 +02:00
Tommy Verrall dd699bce9a Merge pull request #3235 from nymtech/feature/performance-active-set-selection
Feature/performance active set selection
2023-04-05 10:18:16 +01:00
benedetta davico 5ce017ef3d adding vesting tests (#3279) 2023-04-05 10:57:45 +02:00
Tommy Verrall 59c1ce2639 Merge pull request #3261 from nymtech/feature/refresh-allow-list
Feature/refresh allow list
2023-04-05 09:50:53 +01:00
Jędrzej Stuczyński 4fb63d8892 Feature/vesting delegation amount query (#3229)
* moved queries and transactions out of contract.rs

* added queries for vesting delegation details

* nyxd_client support
2023-04-05 09:22:43 +01:00
Jon Häggblad a3b4d04d02 fix clippy in beta toolchain (#3276) 2023-04-05 08:31:38 +02:00
Jędrzej Stuczyński aa3af8faea removed stake and location fields from gateway::Node (#3272)
* removed stake and location fields from gateway::Node

* fixed unused test fixture
2023-04-04 15:16:49 +01:00
Tommy Verrall 0d65ca78c4 Merge pull request #3260 from nymtech/feature/standarise-output-json
Feature/standarise output json
2023-04-04 10:29:50 +01:00
Jędrzej Stuczyński 0505a4807d using string representation of 'Recipient' for 'InitResults' 2023-04-04 10:27:48 +01:00
Jędrzej Stuczyński 01aa06e488 standarise printing of banner based on tty 2023-04-04 10:27:38 +01:00
Jędrzej Stuczyński 3b8dd1f4a5 using stderr when registering gateway 2023-04-04 10:27:38 +01:00
Jędrzej Stuczyński 4a837ce28c added output argument for generating gateway sign payload 2023-04-04 10:27:38 +01:00
Jędrzej Stuczyński 696f6c399c feature cleanup + added the capability to few nym-cli commands 2023-04-04 10:27:38 +01:00
Jędrzej Stuczyński ac9290de27 clippy 2023-04-04 10:27:38 +01:00
Jędrzej Stuczyński b026e9107f standarised output-json in client init 2023-04-04 10:27:35 +01:00
Jędrzej Stuczyński 1347535e8f mixnode: ibid 2023-04-04 10:26:41 +01:00
Jędrzej Stuczyński 479327849a gateway: added --output to commands that strictly require it 2023-04-04 10:26:41 +01:00
Pierre Dommerc 4feb168cf7 chore: update prettier and unpin version (#3265) 2023-04-03 15:52:51 +02:00
Tommy Verrall 50e3f2be38 Merge pull request #3246 from nymtech/bug/explorer-remove-sandbox-sps
Dont fetch Service Provider list on Testnet Explorer
2023-04-03 10:05:52 +01:00
Jędrzej Stuczyński 276edfd562 clippy 2023-03-31 15:56:21 +01:00
Jędrzej Stuczyński 605f8fcde3 updated and cleaned up tests 2023-03-31 15:06:12 +01:00
Bogdan-Ștefan Neacşu 645c9b5e67 Feature/sdk socks5 (#3255)
* Use full socks5 config when setting client config

Also move socks5 setup sleep inside the sdk function

* SDK Socks5 Mixnet Client

* Remove NymClientConfig from sdk

* Update changelog

* Remove pub modifier

* Replace sleep with waiting on the control channel

* Add error on simple connect if socks5 configured
2023-03-31 16:34:07 +03:00
Jędrzej Stuczyński f0e4d1a7cf configurable stored lists locations 2023-03-31 14:01:36 +01:00
Jędrzej Stuczyński 055ec4bdd5 updating stored allow list on file changes 2023-03-31 12:57:02 +01:00
Jędrzej Stuczyński 5761f9ac7f file watcher 2023-03-31 12:15:45 +01:00
Jędrzej Stuczyński 32620fd55f updating standard list in a timer 2023-03-30 17:47:12 +01:00
Jędrzej Stuczyński abb5cdbe06 extracted domain and ipnet information to separate struct 2023-03-30 16:43:58 +01:00
Jędrzej Stuczyński 8cad2b0076 removed lock files from the old basic bandwidth generator (#3259) 2023-03-30 14:56:30 +01:00
dependabot[bot] bcd6c19a97 Bump webpack in /clients/native/examples/js-examples/websocket (#3185)
Bumps [webpack](https://github.com/webpack/webpack) from 5.70.0 to 5.76.0.
- [Release notes](https://github.com/webpack/webpack/releases)
- [Commits](https://github.com/webpack/webpack/compare/v5.70.0...v5.76.0)

---
updated-dependencies:
- dependency-name: webpack
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-03-30 14:47:39 +01:00
dependabot[bot] 764a3a6228 Bump webpack from 5.75.0 to 5.76.0 (#3186)
Bumps [webpack](https://github.com/webpack/webpack) from 5.75.0 to 5.76.0.
- [Release notes](https://github.com/webpack/webpack/releases)
- [Commits](https://github.com/webpack/webpack/compare/v5.75.0...v5.76.0)

---
updated-dependencies:
- dependency-name: webpack
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-03-30 14:47:26 +01:00
Jędrzej Stuczyński d17aa72829 chore: clippy 2023-03-30 14:17:37 +01:00
Jędrzej Stuczyński d62658f515 added --output json|text to mixnode and gateway 'sign' commands (#3251) 2023-03-30 10:23:53 +01:00
Pierre Dommerc e6d4095bf9 feat(wallet): main settings (#3253) 2023-03-30 11:02:49 +02:00
Tommy Verrall 9ace9d6960 Merge pull request #3252 from nymtech/bugfix/unstuck_verloc
Bugfix/unstuck verloc
2023-03-30 09:25:24 +01:00
Tommy Verrall 6c32ff9708 fix ci 2023-03-30 09:42:44 +02:00
Tommy Verrall 5eae62ae33 commit 2023-03-30 09:37:35 +02:00
Jędrzej Stuczyński 331483f86a breaking out of measurement loop on exhausted stream 2023-03-29 16:38:13 +01:00
Jędrzej Stuczyński 4ee0aeb2b1 disabling shutdown on drop for verloc measurement 2023-03-29 16:33:26 +01:00
Bogdan-Ștefan Neacşu 08354f7651 Feature/socks5 crate (#3226)
* Move client-core to common dir

* Factor out socks5-client in its own crate

* Possible sdk-socks5 integration

* Update changelog

* Remove socks5 client lib

* Rename crate to include nym- prefix

* Trim the socks5 wrapped message so that it's printable

* Fix intellij auto refactoring

* Post merge fixes
2023-03-29 13:31:24 +03:00
Jędrzej Stuczyński f1f599dd09 log % of wasted space when padding NymMessage (#3243) 2023-03-29 10:48:00 +01:00
fmtabbara 51251668e3 dont fetch service providers on testnet 2023-03-28 15:47:36 +01:00
Bogdan-Ștefan Neacşu 6e72433f99 Feature/coconut hash (#3231)
* Hash over public attributes too

* Improve and fix api unit test

* Rename hash function
2023-03-28 15:08:54 +03:00
Jędrzej Stuczyński e6957e7a99 use combination of stake and performance for rewarded set selection 2023-03-28 11:25:43 +01:00
Jędrzej Stuczyński de2406a2c7 Moved MixnodeWithPerformance to helpers 2023-03-28 10:54:14 +01:00
Jon Häggblad 956a264106 nym-connect lock files 2023-03-28 11:53:55 +02:00
Jędrzej Stuczyński 9b62d18101 Merge remote-tracking branch 'origin/release/v1.1.14' into develop 2023-03-28 10:28:11 +01:00
Pierre Dommerc 390730f304 refactor(wallet): balance grid ui (#3230) 2023-03-28 10:33:33 +02:00
pierre e134ef8e15 build(nc-mobile): remove webpack favicon plugin 2023-03-28 09:26:42 +02:00
Drazen Urch 7bd1550195 libcpucycles (#3219)
* Checkpoint

* cpu cycle ffi

* Rename

* mixnode feature

* Bundle libcpucycles
2023-03-27 16:34:10 +02:00
Bogdan-Ștefan Neacșu f211b1e366 Add sandbox.env and update credential readme 2023-03-27 13:49:14 +03:00
Bogdan-Ștefan Neacşu b2db208e6e Add README for credential binary (#3221) 2023-03-27 13:33:00 +03:00
Jędrzej Stuczyński c9c0de1fba Offline signing (#3175)
* renamed secp265k1 to secp256k1

* added optional 'explicit_signer_data' argument for sign method

* wip

* made client signer generic

which required to undertake an adventure into coconut bandwidth trait bounds...

* separate wrapper for TxSigner

* moves signing-related features to separate module

* fixed build of binaries from outside default workspace

* offline signing example

* fixed wallet build

* post rebasing formatting

* fixed bity integration build

* making clippy happier

* fixed post-rebase bip39 dependency version
2023-03-27 10:15:30 +01:00
Drazen Urch 0f7e3fe53e Fix Reconstructor (#3218) 2023-03-24 16:21:31 +01:00
benedetta davico e0d98af04f Feature/nym api tests (#3216)
* some edits

* more edits

* adding unfiltered tests, cleaning up

* "name change"
2023-03-24 12:22:03 +01:00
pierre 81e31c0550 build(nc-mobile): remove webpack-favicons plugin 2023-03-24 12:21:03 +01:00
Tommy Verrall 1c771df941 Merge pull request #3211 from nymtech/feature/no_creds_err_msg
Better error log for lacking credential in db
2023-03-24 11:18:41 +03:00
benedetta davico 17c2aecd99 starting to add vesting tests (#3134)
* starting to add vesting tests

* adding more vesting client tests

* starting to add vesting tests & merging develop

* adding more vesting client tests

* fix linting

* Revert "Merge conflicts"

This reverts commit 0beb025a62.

* fix linting errors

* fix linting errors

* removing only adding skip

---------

Co-authored-by: fmtabbara <fmtabbara@hotmail.co.uk>
2023-03-22 18:30:07 +01:00
Bogdan-Ștefan Neacșu 85074f3ac8 Better error log for lacking credential in db 2023-03-22 17:21:20 +02:00
Bogdan-Ștefan Neacşu c7020da81c Use nym task crate for network statistics signal handle (#3209)
* Use nym task crate for network statistics signal handle

* Update changelog
2023-03-22 16:43:00 +02:00
860 changed files with 32910 additions and 41472 deletions
+16
View File
@@ -0,0 +1,16 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
version: 2
updates:
# Maintain dependencies for GitHub Actions
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "daily"
commit-message:
prefix: build
prefix-development: chore
include: scope
@@ -98,7 +98,7 @@ jobs:
cp target/release/nym-network-requester $OUTPUT_DIR cp target/release/nym-network-requester $OUTPUT_DIR
cp target/release/nym-network-statistics $OUTPUT_DIR cp target/release/nym-network-statistics $OUTPUT_DIR
cp target/release/nym-cli $OUTPUT_DIR cp target/release/nym-cli $OUTPUT_DIR
cp target/release/credential $OUTPUT_DIR cp target/release/nym-credential-client $OUTPUT_DIR
cp target/release/explorer-api $OUTPUT_DIR cp target/release/explorer-api $OUTPUT_DIR
cp contracts/target/wasm32-unknown-unknown/release/mixnet_contract.wasm $OUTPUT_DIR cp contracts/target/wasm32-unknown-unknown/release/mixnet_contract.wasm $OUTPUT_DIR
+76
View File
@@ -0,0 +1,76 @@
name: CD dev-portal
on:
push:
branches: master
paths:
- 'documentation/dev-portal/**'
jobs:
build:
runs-on: custom-runner-linux
steps:
- uses: actions/checkout@v3
- name: Install rsync
run: sudo apt-get install rsync
- uses: rlespinasse/github-slug-action@v3.x
- uses: actions/setup-node@v3
with:
node-version: "16"
- name: Install Rust stable
uses: actions-rs/toolchain@v1
with:
toolchain: stable
- name: Install mdbook
run: (test -x $HOME/.cargo/bin/mdbook || cargo install --vers "^0.4" mdbook)
- name: Install mdbook plugins
run: |
cargo install --vers "^0.2.0" mdbook-variables && cargo install \
--vers "^1.8.0" mdbook-admonish && cargo install --vers \
"^0.1.2" mdbook-last-changed && cargo install --vers "^0.1.2" \
mdbook-theme && cargo install --vers "^0.7.7" mdbook-linkcheck
- name: Clean website
run: cd documentation/dev-portal && mdbook clean
- name: Build website
run: cd documentation/dev-portal && mdbook build
- name: Deploy branch master to dev
continue-on-error: true
uses: easingthemes/ssh-deploy@main
env:
SSH_PRIVATE_KEY: ${{ secrets.CD_WWW_SSH_PRIVATE_KEY }}
ARGS: "-rltgoDzvO --delete"
SOURCE: "documentation/dev-portal/book/html/"
REMOTE_HOST: ${{ secrets.CD_WWW_REMOTE_HOST_DEV }}
REMOTE_USER: ${{ secrets.CD_WWW_REMOTE_USER }}
TARGET: ${{ secrets.CD_WWW_REMOTE_TARGET_DEVP }}/
EXCLUDE: "/dist/, /node_modules/"
- name: Deploy branch master to prod
uses: easingthemes/ssh-deploy@main
env:
SSH_PRIVATE_KEY: ${{ secrets.CD_WWW_SSH_PRIVATE_KEY }}
ARGS: "-rltgoDzvO --delete"
SOURCE: "documentation/dev-portal/book/html/"
REMOTE_HOST: ${{ secrets.CD_WWW_REMOTE_HOST_PROD }}
REMOTE_USER: ${{ secrets.CD_WWW_REMOTE_USER }}
TARGET: ${{ secrets.CD_WWW_REMOTE_TARGET_DEVP }}/
EXCLUDE: "/dist/, /node_modules/"
- name: Matrix - Node Install
run: npm install
working-directory: .github/workflows/support-files
- name: Matrix - Send Notification
env:
NYM_NOTIFICATION_KIND: cd-dev
NYM_PROJECT_NAME: "Dev portal CD"
NYM_CI_WWW_BASE: "${{ secrets.NYM_CD_WWW_BASE }}"
NYM_CI_WWW_LOCATION: "${{ env.GITHUB_REF_SLUG }}"
GIT_COMMIT_MESSAGE: "${{ github.event.head_commit.message }}"
GIT_BRANCH: "${GITHUB_REF##*/}"
MATRIX_SERVER: "${{ secrets.MATRIX_SERVER }}"
MATRIX_ROOM: "${{ secrets.MATRIX_ROOM_DEVP }}"
MATRIX_USER_ID: "${{ secrets.MATRIX_USER_ID }}"
MATRIX_TOKEN: "${{ secrets.MATRIX_TOKEN }}"
MATRIX_DEVICE_ID: "${{ secrets.MATRIX_DEVICE_ID }}"
IS_SUCCESS: "${{ job.status == 'success' }}"
uses: docker://keybaseio/client:stable-node
with:
args: .github/workflows/support-files/notifications/entry_point.sh
+82
View File
@@ -0,0 +1,82 @@
name: CD docs
on:
push:
branches: master
paths:
- 'documentation/docs/**'
jobs:
build:
runs-on: custom-runner-linux
steps:
- uses: actions/checkout@v3
- name: Install rsync
run: sudo apt-get install rsync
- uses: rlespinasse/github-slug-action@v3.x
- uses: actions/setup-node@v3
with:
node-version: "16"
- name: Install Rust stable
uses: actions-rs/toolchain@v1
with:
toolchain: stable
- name: Build all binaries
uses: actions-rs/cargo@v1
with:
command: build
args: --workspace --release --all
- name: Install mdbook
run: (test -x $HOME/.cargo/bin/mdbook || cargo install --vers "^0.4" mdbook)
- name: Install mdbook plugins
run: |
cargo install --vers "^0.2.0" mdbook-variables && cargo install \
--vers "^1.8.0" mdbook-admonish && cargo install --vers \
"^0.1.2" mdbook-last-changed && cargo install --vers "^0.1.2" \
mdbook-theme && cargo install --vers "^0.7.7" mdbook-linkcheck && \
cargo install --vers "^0.5.0" mdbook-cmdrun
- name: Clean website
run: cd documentation/docs && mdbook clean
- name: Build website
run: cd documentation/docs && mdbook build
- name: Deploy branch master to dev
continue-on-error: true
uses: easingthemes/ssh-deploy@main
env:
SSH_PRIVATE_KEY: ${{ secrets.CD_WWW_SSH_PRIVATE_KEY }}
ARGS: "-rltgoDzvO --delete"
SOURCE: "documentation/docs/book/"
REMOTE_HOST: ${{ secrets.CD_WWW_REMOTE_HOST_DEV }}
REMOTE_USER: ${{ secrets.CD_WWW_REMOTE_USER }}
TARGET: ${{ secrets.CD_WWW_REMOTE_TARGET }}/
EXCLUDE: "/dist/, /node_modules/"
- name: Deploy branch master to prod
uses: easingthemes/ssh-deploy@main
env:
SSH_PRIVATE_KEY: ${{ secrets.CD_WWW_SSH_PRIVATE_KEY }}
ARGS: "-rltgoDzvO --delete"
SOURCE: "documentation/docs/book/"
REMOTE_HOST: ${{ secrets.CD_WWW_REMOTE_HOST_PROD }}
REMOTE_USER: ${{ secrets.CD_WWW_REMOTE_USER }}
TARGET: ${{ secrets.CD_WWW_REMOTE_TARGET }}/
EXCLUDE: "/dist/, /node_modules/"
- name: Matrix - Node Install
run: npm install
working-directory: .github/workflows/support-files
- name: Matrix - Send Notification
env:
NYM_NOTIFICATION_KIND: cd-docs
NYM_PROJECT_NAME: "Docs CD"
NYM_CI_WWW_BASE: "${{ secrets.NYM_CD_WWW_BASE }}"
NYM_CI_WWW_LOCATION: "${{ env.GITHUB_REF_SLUG }}"
GIT_COMMIT_MESSAGE: "${{ github.event.head_commit.message }}"
GIT_BRANCH: "${GITHUB_REF##*/}"
MATRIX_SERVER: "${{ secrets.MATRIX_SERVER }}"
MATRIX_ROOM: "${{ secrets.MATRIX_ROOM_DOCS }}"
MATRIX_USER_ID: "${{ secrets.MATRIX_USER_ID }}"
MATRIX_TOKEN: "${{ secrets.MATRIX_TOKEN }}"
MATRIX_DEVICE_ID: "${{ secrets.MATRIX_DEVICE_ID }}"
IS_SUCCESS: "${{ job.status == 'success' }}"
uses: docker://keybaseio/client:stable-node
with:
args: .github/workflows/support-files/notifications/entry_point.sh
+66
View File
@@ -0,0 +1,66 @@
name: CI dev-portal
on:
push:
branches-ignore: master
paths:
- 'documentation/dev-portal/**'
jobs:
build:
runs-on: custom-runner-linux
steps:
- uses: actions/checkout@v3
- name: Install rsync
run: sudo apt-get install rsync
- uses: rlespinasse/github-slug-action@v3.x
- uses: actions/setup-node@v3
with:
node-version: "16"
- name: Install Rust stable
uses: actions-rs/toolchain@v1
with:
toolchain: stable
- name: Install mdbook
run: (test -x $HOME/.cargo/bin/mdbook || cargo install --vers "^0.4" mdbook)
- name: Install mdbook plugins
run: |
cargo install --vers "^0.2.0" mdbook-variables && cargo install \
--vers "^1.8.0" mdbook-admonish && cargo install --vers \
"^0.1.2" mdbook-last-changed && cargo install --vers "^0.1.2" mdbook-theme \
&& cargo install --vers "^0.7.7" mdbook-linkcheck
- name: Clean website
run: cd documentation/dev-portal && mdbook clean
- name: Build website
run: cd documentation/dev-portal && mdbook build
- name: Deploy branch to CI www
continue-on-error: true
uses: easingthemes/ssh-deploy@main
env:
SSH_PRIVATE_KEY: ${{ secrets.CI_WWW_SSH_PRIVATE_KEY }}
ARGS: "-rltgoDzvO --delete"
SOURCE: "documentation/dev-portal/book/html/"
REMOTE_HOST: ${{ secrets.CI_WWW_REMOTE_HOST }}
REMOTE_USER: ${{ secrets.CI_WWW_REMOTE_USER }}
TARGET: ${{ secrets.CI_WWW_REMOTE_TARGET }}/dev-portal-${{ env.GITHUB_REF_SLUG }}
EXCLUDE: "/dist/, /node_modules/"
- name: Matrix - Node Install
run: npm install
working-directory: .github/workflows/support-files
- name: Matrix - Send Notification
env:
NYM_NOTIFICATION_KIND: ci-dev
NYM_PROJECT_NAME: "Dev portal CI"
NYM_CI_WWW_BASE: "${{ secrets.NYM_CI_WWW_BASE }}"
NYM_CI_WWW_LOCATION: "dev-portal-${{ env.GITHUB_REF_SLUG }}"
GIT_COMMIT_MESSAGE: "${{ github.event.head_commit.message }}"
GIT_BRANCH: "${GITHUB_REF##*/}"
MATRIX_SERVER: "${{ secrets.MATRIX_SERVER }}"
MATRIX_ROOM: "${{ secrets.MATRIX_ROOM_DEVP }}"
MATRIX_USER_ID: "${{ secrets.MATRIX_USER_ID }}"
MATRIX_TOKEN: "${{ secrets.MATRIX_TOKEN }}"
MATRIX_DEVICE_ID: "${{ secrets.MATRIX_DEVICE_ID }}"
IS_SUCCESS: "${{ job.status == 'success' }}"
uses: docker://keybaseio/client:stable-node
with:
args: .github/workflows/support-files/notifications/entry_point.sh
+72
View File
@@ -0,0 +1,72 @@
name: CI docs
on:
push:
branches-ignore: master
paths:
- 'documentation/docs/**'
jobs:
build:
runs-on: custom-runner-linux
steps:
- uses: actions/checkout@v3
- name: Install rsync
run: sudo apt-get install rsync
- uses: rlespinasse/github-slug-action@v3.x
- uses: actions/setup-node@v3
with:
node-version: "16"
- name: Install Rust stable
uses: actions-rs/toolchain@v1
with:
toolchain: stable
- name: Build all binaries
uses: actions-rs/cargo@v1
with:
command: build
args: --workspace --release --all
- name: Install mdbook
run: (test -x $HOME/.cargo/bin/mdbook || cargo install --vers "^0.4" mdbook)
- name: Install mdbook plugins
run: |
cargo install --vers "^0.2.0" mdbook-variables && cargo install \
--vers "^1.8.0" mdbook-admonish && cargo install --vers \
"^0.1.2" mdbook-last-changed && cargo install --vers "^0.1.2" \
mdbook-theme && cargo install --vers "^0.7.7" mdbook-linkcheck && \
cargo install --vers "^0.5.0" mdbook-cmdrun
- name: Clean website
run: cd documentation/docs && mdbook clean
- name: Build website
run: cd documentation/docs && mdbook build
- name: Deploy branch to CI www
continue-on-error: true
uses: easingthemes/ssh-deploy@main
env:
SSH_PRIVATE_KEY: ${{ secrets.CI_WWW_SSH_PRIVATE_KEY }}
ARGS: "-rltgoDzvO --delete"
SOURCE: "documentation/docs/book/"
REMOTE_HOST: ${{ secrets.CI_WWW_REMOTE_HOST }}
REMOTE_USER: ${{ secrets.CI_WWW_REMOTE_USER }}
TARGET: ${{ secrets.CI_WWW_REMOTE_TARGET }}/docs-${{ env.GITHUB_REF_SLUG }}
EXCLUDE: "/dist/, /node_modules/"
- name: Matrix - Node Install
run: npm install
working-directory: .github/workflows/support-files
- name: Matrix - Send Notification
env:
NYM_NOTIFICATION_KIND: ci-docs
NYM_PROJECT_NAME: "Docs CI"
NYM_CI_WWW_BASE: "${{ secrets.NYM_CI_WWW_BASE }}"
NYM_CI_WWW_LOCATION: "docs-${{ env.GITHUB_REF_SLUG }}"
GIT_COMMIT_MESSAGE: "${{ github.event.head_commit.message }}"
GIT_BRANCH: "${GITHUB_REF##*/}"
MATRIX_SERVER: "${{ secrets.MATRIX_SERVER }}"
MATRIX_ROOM: "${{ secrets.MATRIX_ROOM_DOCS }}"
MATRIX_USER_ID: "${{ secrets.MATRIX_USER_ID }}"
MATRIX_TOKEN: "${{ secrets.MATRIX_TOKEN }}"
MATRIX_DEVICE_ID: "${{ secrets.MATRIX_DEVICE_ID }}"
IS_SUCCESS: "${{ job.status == 'success' }}"
uses: docker://keybaseio/client:stable-node
with:
args: .github/workflows/support-files/notifications/entry_point.sh
+2 -1
View File
@@ -30,6 +30,7 @@ jobs:
continue-on-error: ${{ matrix.rust == 'nightly' }} continue-on-error: ${{ matrix.rust == 'nightly' }}
needs: matrix_prep needs: matrix_prep
strategy: strategy:
fail-fast: false
matrix: ${{fromJson(needs.matrix_prep.outputs.matrix)}} matrix: ${{fromJson(needs.matrix_prep.outputs.matrix)}}
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
@@ -63,4 +64,4 @@ jobs:
if: ${{ matrix.rust != 'nightly' }} if: ${{ matrix.rust != 'nightly' }}
with: with:
command: clippy command: clippy
args: --manifest-path contracts/Cargo.toml --workspace -- -D warnings args: --manifest-path contracts/Cargo.toml --workspace --all-targets -- -D warnings
+13
View File
@@ -0,0 +1,13 @@
name: Greetings
on: [pull_request_target, issues]
jobs:
greeting:
runs-on: ubuntu-latest
steps:
- uses: actions/first-interaction@v1
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
issue-message: 'Thank you for raising this issue'
pr-message: 'Thank you for making this first PR'
@@ -0,0 +1,29 @@
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,
};
@@ -0,0 +1,17 @@
🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥
> :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 }}
```
@@ -0,0 +1,17 @@
🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩
> :rocket: {{ env.NYM_PROJECT_NAME }} ➡️➡️➡️➡️➡️ **View output:** https://{{ env.NYM_CI_WWW_BASE }}/developers/
>
> ✅ **SUCCESS**
>
> `branch` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/tree/{{ env.GIT_BRANCH_NAME }}
>
> `commit` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/commit/{{ env.GITHUB_SHA }}
>
> `build ` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/actions/runs/{{ env.GITHUB_RUN_ID }}
>
Commit message by `{{ env.GITHUB_ACTOR }}` at {{ timestamp }}:
```
{{ env.GIT_COMMIT_MESSAGE }}
```
@@ -0,0 +1,29 @@
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,
};
@@ -0,0 +1,11 @@
🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥
> :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 }}
```
@@ -0,0 +1,17 @@
🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩
> :rocket: {{ env.NYM_PROJECT_NAME }} ➡️➡️➡️➡️➡️ **View output:** https://{{ env.NYM_CI_WWW_BASE }}/docs/
>
> ✅ **SUCCESS**
>
> `branch` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/tree/{{ env.GIT_BRANCH_NAME }}
>
> `commit` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/commit/{{ env.GITHUB_SHA }}
>
> `build ` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/actions/runs/{{ env.GITHUB_RUN_ID }}
>
Commit message by `{{ env.GITHUB_ACTOR }}` at {{ timestamp }}:
```
{{ env.GIT_COMMIT_MESSAGE }}
```
@@ -0,0 +1,29 @@
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,
};
@@ -0,0 +1,17 @@
🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥
> :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 }}
```
@@ -0,0 +1,17 @@
🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩
> :rocket: {{ env.NYM_PROJECT_NAME }} ➡️➡️➡️➡️➡️ **View output:** https://{{ env.NYM_CI_WWW_LOCATION }}.{{ env.NYM_CI_WWW_BASE }}/
>
> ✅ **SUCCESS**
>
> `branch` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/tree/{{ env.GIT_BRANCH_NAME }}
>
> `commit` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/commit/{{ env.GITHUB_SHA }}
>
> `build ` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/actions/runs/{{ env.GITHUB_RUN_ID }}
>
Commit message by `{{ env.GITHUB_ACTOR }}` at {{ timestamp }}:
```
{{ env.GIT_COMMIT_MESSAGE }}
```
@@ -0,0 +1,29 @@
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,
};
@@ -0,0 +1,17 @@
🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥
> :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 }}
```
@@ -0,0 +1,17 @@
🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩
> :rocket: {{ env.NYM_PROJECT_NAME }} ➡️➡️➡️➡️➡️ **View output:** https://{{ env.NYM_CI_WWW_LOCATION }}.{{ env.NYM_CI_WWW_BASE }}/
>
> ✅ **SUCCESS**
>
> `branch` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/tree/{{ env.GIT_BRANCH_NAME }}
>
> `commit` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/commit/{{ env.GITHUB_SHA }}
>
> `build ` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/actions/runs/{{ env.GITHUB_RUN_ID }}
>
Commit message by `{{ env.GITHUB_ACTOR }}` at {{ timestamp }}:
```
{{ env.GIT_COMMIT_MESSAGE }}
```
@@ -3,7 +3,7 @@ require('dotenv').config();
const { sendMatrixMessage } = require('./send_message_to_matrix'); const { sendMatrixMessage } = require('./send_message_to_matrix');
let context = { let context = {
kinds: ['nym-wallet', 'ts-packages', 'network-explorer', 'nightly', 'nym-connect','security'], kinds: ['nym-wallet', 'ts-packages', 'network-explorer', 'nightly', 'nym-connect','security','ci-docs','cd-docs','ci-dev','cd-dev'],
}; };
/** /**
+1 -1
View File
@@ -22,6 +22,6 @@
"unified": "^9.2.2" "unified": "^9.2.2"
}, },
"devDependencies": { "devDependencies": {
"prettier": "2.3.2" "prettier": "^2.8.7"
} }
} }
+1 -1
View File
@@ -64,4 +64,4 @@ jobs:
uses: actions-rs/cargo@v1 uses: actions-rs/cargo@v1
with: with:
command: clippy command: clippy
args: --manifest-path nym-wallet/Cargo.toml --workspace --all-features -- -D warnings args: --manifest-path nym-wallet/Cargo.toml --workspace --all-features --all-targets -- -D warnings
+1
View File
@@ -41,3 +41,4 @@ storybook-static
envs/qwerty.env envs/qwerty.env
.parcel-cache .parcel-cache
**/.DS_Store **/.DS_Store
cpu-cycles/libcpucycles/build
+34
View File
@@ -4,6 +4,39 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
## [Unreleased] ## [Unreleased]
- nym-network-statistics properly handles signals ([#3209])
- add socks5 support for Rust SDK ([#3226], [#3255])
- add coconut bandwidth credential support for Rust SDK ([#3273])
[#3209]: https://github.com/nymtech/nym/issues/3209
[#3226]: https://github.com/nymtech/nym/pull/3226
[#3255]: https://github.com/nymtech/nym/pull/3255
[#3273]: https://github.com/nymtech/nym/pull/3273
## [v1.1.15] (2023-04-18)
- Fix verloc being stuck waiting for shutdown signal ([#3250])
- Introduce `--output json` flag to `sign` command to allow to more easily capture the output ([#3249])
- Explorer - Dont fetch Service Provider list on Testnet ([#3245])
- When determining active set, rather than weighting the nodes by just the `stake`, use `stake * performance` ([#3234])
- Introduce dual packet sizes to our clients (as in use two packet sizes at the same time depending on message size) ([#3189])
- Experiment with offline signing in our validator client ([#3174])
- Modify network requester binary to reload `allowed.list` periodically to pull in any changes made upstream without having to restart the service ([#3149])
- Standardise all `--output json` on binary inits, we pass the output json at different points for different binaries. ([#3080])
- Service provider directory contract: initial version ([#2759])
- Fix issue where network-requester run failed on fresh init due to missing allow file ([#3316])
[#3250]: https://github.com/nymtech/nym/issues/3250
[#3249]: https://github.com/nymtech/nym/issues/3249
[#3245]: https://github.com/nymtech/nym/issues/3245
[#3234]: https://github.com/nymtech/nym/issues/3234
[#3189]: https://github.com/nymtech/nym/issues/3189
[#3174]: https://github.com/nymtech/nym/issues/3174
[#3149]: https://github.com/nymtech/nym/issues/3149
[#3080]: https://github.com/nymtech/nym/issues/3080
[#2759]: https://github.com/nymtech/nym/issues/2759
[#3316]: https://github.com/nymtech/nym/pull/3316
## [v1.1.14] (2023-04-04) ## [v1.1.14] (2023-04-04)
- Investigate cause of qwerty validator being in invalid rewarding state ([#3224]) - Investigate cause of qwerty validator being in invalid rewarding state ([#3224])
@@ -17,6 +50,7 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
[#3187]: https://github.com/nymtech/nym/issues/3187 [#3187]: https://github.com/nymtech/nym/issues/3187
[#3203]: https://github.com/nymtech/nym/pull/3203 [#3203]: https://github.com/nymtech/nym/pull/3203
[#3199]: https://github.com/nymtech/nym/pull/3199 [#3199]: https://github.com/nymtech/nym/pull/3199
>>>>>>> master
## [v1.1.13] (2023-03-15) ## [v1.1.13] (2023-03-15)
Generated
+637 -334
View File
File diff suppressed because it is too large Load Diff
+6 -3
View File
@@ -17,12 +17,14 @@ opt-level = 3
resolver = "2" resolver = "2"
members = [ members = [
"clients/client-core",
"clients/credential", "clients/credential",
"clients/native", "clients/native",
"clients/native/websocket-requests", "clients/native/websocket-requests",
"clients/socks5", "clients/socks5",
"common/async-file-watcher",
"common/bandwidth-controller",
"common/bin-common", "common/bin-common",
"common/client-core",
"common/client-libs/gateway-client", "common/client-libs/gateway-client",
"common/client-libs/mixnet-client", "common/client-libs/mixnet-client",
"common/client-libs/validator-client", "common/client-libs/validator-client",
@@ -35,8 +37,8 @@ members = [
"common/cosmwasm-smart-contracts/group-contract", "common/cosmwasm-smart-contracts/group-contract",
"common/cosmwasm-smart-contracts/mixnet-contract", "common/cosmwasm-smart-contracts/mixnet-contract",
"common/cosmwasm-smart-contracts/multisig-contract", "common/cosmwasm-smart-contracts/multisig-contract",
"common/cosmwasm-smart-contracts/service-provider-directory",
"common/cosmwasm-smart-contracts/vesting-contract", "common/cosmwasm-smart-contracts/vesting-contract",
"common/mobile-storage",
"common/credential-storage", "common/credential-storage",
"common/credentials", "common/credentials",
"common/crypto", "common/crypto",
@@ -59,6 +61,7 @@ members = [
"common/nymsphinx/params", "common/nymsphinx/params",
"common/nymsphinx/types", "common/nymsphinx/types",
"common/pemstore", "common/pemstore",
"common/socks5-client-core",
"common/socks5/proxy-helpers", "common/socks5/proxy-helpers",
"common/socks5/requests", "common/socks5/requests",
"common/statistics", "common/statistics",
@@ -93,7 +96,7 @@ default-members = [
"explorer-api", "explorer-api",
] ]
exclude = ["explorer", "contracts", "clients/webassembly", "nym-wallet", "nym-connect/mobile/src-tauri", "nym-connect/desktop"] exclude = ["explorer", "contracts", "clients/webassembly", "nym-wallet", "nym-connect/mobile/src-tauri", "nym-connect/desktop", "cpu-cycles"]
[workspace.package] [workspace.package]
authors = ["Nym Technologies SA"] authors = ["Nym Technologies SA"]
+36 -10
View File
@@ -9,6 +9,10 @@ no-clippy: build cargo-test wasm fmt
happy: fmt clippy-happy test happy: fmt clippy-happy test
# Building release binaries is a little manual as we can't just build --release
# on all workspaces.
build-release: build-release-main wasm
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
# Define targets for a given workspace # Define targets for a given workspace
# $(1): name # $(1): name
@@ -23,29 +27,37 @@ clippy-happy-$(1):
clippy-$(1): clippy-$(1):
cargo clippy --manifest-path $(2)/Cargo.toml --workspace $(3) -- -D warnings cargo clippy --manifest-path $(2)/Cargo.toml --workspace $(3) -- -D warnings
clippy-$(1)-examples: clippy-examples-$(1):
cargo clippy --manifest-path $(2)/Cargo.toml --workspace --examples -- -D warnings cargo clippy --manifest-path $(2)/Cargo.toml --workspace --examples -- -D warnings
check-$(1):
cargo check --manifest-path $(2)/Cargo.toml --workspace $(3)
test-$(1): test-$(1):
cargo test --manifest-path $(2)/Cargo.toml --workspace cargo test --manifest-path $(2)/Cargo.toml --workspace
test-$(1)-expensive: test-expensive-$(1):
cargo test --manifest-path $(2)/Cargo.toml --workspace -- --ignored cargo test --manifest-path $(2)/Cargo.toml --workspace -- --ignored
build-$(1): build-$(1):
cargo build --manifest-path $(2)/Cargo.toml --workspace $(3) cargo build --manifest-path $(2)/Cargo.toml --workspace $(3)
build-$(1)-examples: build-examples-$(1):
cargo build --manifest-path $(2)/Cargo.toml --workspace --examples cargo build --manifest-path $(2)/Cargo.toml --workspace --examples
build-release-$(1):
cargo build --manifest-path $(2)/Cargo.toml --workspace --release $(3)
fmt-$(1): fmt-$(1):
cargo fmt --manifest-path $(2)/Cargo.toml --all cargo fmt --manifest-path $(2)/Cargo.toml --all
clippy-happy: clippy-happy-$(1) clippy-happy: clippy-happy-$(1)
clippy-all: clippy-$(1) clippy-$(1)-examples clippy-all: clippy-$(1) clippy-examples-$(1)
check: check-$(1)
cargo-test: test-$(1) cargo-test: test-$(1)
cargo-test-expensive: test-$(1)-expensive cargo-test-expensive: test-expensive-$(1)
build: build-$(1) build-$(1)-examples build: build-$(1) build-$(1)-examples
build-release-all: build-release-$(1)
fmt: fmt-$(1) fmt: fmt-$(1)
endef endef
@@ -61,7 +73,7 @@ $(eval $(call add_cargo_workspace,contracts,contracts,--target wasm32-unknown-un
$(eval $(call add_cargo_workspace,wasm-client,clients/webassembly,--target wasm32-unknown-unknown)) $(eval $(call add_cargo_workspace,wasm-client,clients/webassembly,--target wasm32-unknown-unknown))
$(eval $(call add_cargo_workspace,wallet,nym-wallet,)) $(eval $(call add_cargo_workspace,wallet,nym-wallet,))
$(eval $(call add_cargo_workspace,connect,nym-connect/desktop)) $(eval $(call add_cargo_workspace,connect,nym-connect/desktop))
ifndef NYM_NO_MOBILE ifdef NYM_MOBILE
$(eval $(call add_cargo_workspace,connect-mobile,nym-connect/mobile/src-tauri)) $(eval $(call add_cargo_workspace,connect-mobile,nym-connect/mobile/src-tauri))
endif endif
@@ -76,13 +88,27 @@ build-nym-cli:
cargo build -p nym-cli --release cargo build -p nym-cli --release
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
# Misc # Build contracts ready for deploy
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
wasm: CONTRACTS_OUT_DIR=contracts/target/wasm32-unknown-unknown/release
VESTING_CONTRACT=$(CONTRACTS_OUT_DIR)/vesting_contract.wasm
MIXNET_CONTRACT=$(CONTRACTS_OUT_DIR)/mixnet_contract.wasm
SERVICE_PROVIDER_DIRECTORY_CONTRACT=$(CONTRACTS_OUT_DIR)/nym_service_provider_directory.wasm
wasm: wasm-build wasm-opt
wasm-build:
RUSTFLAGS='-C link-arg=-s' cargo build --manifest-path contracts/Cargo.toml --release --target wasm32-unknown-unknown RUSTFLAGS='-C link-arg=-s' cargo build --manifest-path contracts/Cargo.toml --release --target wasm32-unknown-unknown
wasm-opt --disable-sign-ext -Os contracts/target/wasm32-unknown-unknown/release/vesting_contract.wasm -o contracts/target/wasm32-unknown-unknown/release/vesting_contract.wasm
wasm-opt --disable-sign-ext -Os contracts/target/wasm32-unknown-unknown/release/mixnet_contract.wasm -o contracts/target/wasm32-unknown-unknown/release/mixnet_contract.wasm wasm-opt:
wasm-opt --disable-sign-ext -Os $(VESTING_CONTRACT) -o $(VESTING_CONTRACT)
wasm-opt --disable-sign-ext -Os $(MIXNET_CONTRACT) -o $(MIXNET_CONTRACT)
wasm-opt --disable-sign-ext -Os $(SERVICE_PROVIDER_DIRECTORY_CONTRACT) -o $(SERVICE_PROVIDER_DIRECTORY_CONTRACT)
# -----------------------------------------------------------------------------
# Misc
# -----------------------------------------------------------------------------
# NOTE: this seems deprecated an not needed anymore? # NOTE: this seems deprecated an not needed anymore?
mixnet-opt: wasm mixnet-opt: wasm
+1 -1
View File
@@ -21,7 +21,7 @@ The platform is composed of multiple Rust crates. Top-level executable binary cr
### Building ### Building
Platform build instructions are available on [our docs site](https://nymtech.net/docs/stable/run-nym-nodes/build-nym). Platform build instructions are available on [our docs site](https://nymtech.net/docs/binaries/building-nym.html).
Wallet build instructions are also available on [our docs site](https://nymtech.net/docs/stable/nym-apps/wallet#for-developers). Wallet build instructions are also available on [our docs site](https://nymtech.net/docs/stable/nym-apps/wallet#for-developers).
### Developing ### Developing
+3 -3
View File
@@ -3,8 +3,8 @@ Critical bug or security issue 💥
If you're here because you're trying to figure out how to notify us of a security issue, go to Discord, and alert the core engineers: If you're here because you're trying to figure out how to notify us of a security issue, go to Discord, and alert the core engineers:
Dave Hrycyszyn futurechimp#5430 Dave Hrycyszyn futurechimp#5430
Drazen Urch drazen#4873
Jedrzej Stuczynski "Jedrzej | Nym#5666" Jedrzej Stuczynski "Jedrzej | Nym#5666"
Fran Arbanas | franarbanas#0995
Mark Sinclair | marknym#8088
Please avoid opening public issues on GitHub that contain information about a potential security vulnerability as this makes it difficult to reduce the impact and harm of valid security issues.
Please avoid opening public issues on GitHub that contain information about a potential security vulnerability as this makes it difficult to reduce the impact and harm of valid security issues.
+4 -8
View File
@@ -1,27 +1,23 @@
[package] [package]
name = "credential" name = "nym-credential-client"
version = "0.1.0" version = "0.1.0"
edition = "2021" edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
bip39 = { workspace = true }
clap = { version = "4.0", features = ["cargo", "derive"] } clap = { version = "4.0", features = ["cargo", "derive"] }
log = "0.4" log = "0.4"
rand = "0.7.3" serde = { workspace = true, features = ["derive"] }
serde = { version = "1.0", features = ["derive"] }
thiserror = "1.0" thiserror = "1.0"
url = "2.2"
tokio = { version = "1.24.1", features = ["rt-multi-thread", "net", "signal", "macros"] } # async runtime tokio = { version = "1.24.1", features = ["rt-multi-thread", "net", "signal", "macros"] } # async runtime
nym-coconut-interface = { path = "../../common/coconut-interface" } nym-bandwidth-controller = { path = "../../common/bandwidth-controller" }
nym-config = { path = "../../common/config" } nym-config = { path = "../../common/config" }
nym-credentials = { path = "../../common/credentials" } nym-credentials = { path = "../../common/credentials" }
nym-credential-storage = { path = "../../common/credential-storage" } nym-credential-storage = { path = "../../common/credential-storage" }
nym-crypto = { path = "../../common/crypto", features = ["rand", "asymmetric", "symmetric", "aes", "hashing"] }
nym-bin-common = { path = "../../common/bin-common"} nym-bin-common = { path = "../../common/bin-common"}
nym-network-defaults = { path = "../../common/network-defaults" } nym-network-defaults = { path = "../../common/network-defaults" }
nym-pemstore = { path = "../../common/pemstore" } nym-pemstore = { path = "../../common/pemstore" }
validator-client = { path = "../../common/client-libs/validator-client", features = ["nyxd-client"] } nym-validator-client = { path = "../../common/client-libs/validator-client", features = ["nyxd-client"] }
+32
View File
@@ -0,0 +1,32 @@
<!--
Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
SPDX-License-Identifier: Apache-2.0
-->
## Credential binary
The credential binary is used to acquire coconut bandwidth credentials in exchange for nym tokens. Those credentials are stored in the client's `data` directory, so that they can be used as the client sees fit.
### Warning
The credential binary is still experimental software. The infrastructure for using it is not yet deployed to mainnet and it's still in the process of being deployed to sandbox.
### Building
From the project's root directory, run:
```
cargo build -p credential
```
which generates the `credential` binary in `target/debug/credential`.
### Running
For example, you can get a credential worth 3 nym (3000000 unym) in a socks5 client that was already initialized like so:
```
./target/debug/credential --config-env-file envs/sandbox.env --client-home-directory ~/.nym/socks5-clients/cred_client --nyxd-url https://sandbox-validator1.nymtech.net --mnemonic $MNEMONIC --recovery-dir /tmp/recovery --amount 3000000
```
More information regarding how to run the binary can be found by running it with the `--help` argument.
+4 -4
View File
@@ -4,14 +4,14 @@
use crate::error::Result; use crate::error::Result;
use bip39::Mnemonic; use bip39::Mnemonic;
use nym_network_defaults::{NymNetworkDetails, VOUCHER_INFO}; use nym_network_defaults::{NymNetworkDetails, VOUCHER_INFO};
use nym_validator_client::nyxd;
use nym_validator_client::nyxd::traits::CoconutBandwidthSigningClient;
use nym_validator_client::nyxd::{Coin, DirectSigningNyxdClient, Fee, NyxdClient};
use std::str::FromStr; use std::str::FromStr;
use url::Url; use url::Url;
use validator_client::nyxd;
use validator_client::nyxd::traits::CoconutBandwidthSigningClient;
use validator_client::nyxd::{Coin, Fee, NyxdClient, SigningNyxdClient};
pub(crate) struct Client { pub(crate) struct Client {
nyxd_client: NyxdClient<SigningNyxdClient>, nyxd_client: NyxdClient<DirectSigningNyxdClient>,
mix_denom_base: String, mix_denom_base: String,
} }
+11 -94
View File
@@ -3,26 +3,13 @@
use clap::{ArgGroup, Args, Subcommand}; use clap::{ArgGroup, Args, Subcommand};
use log::*; use log::*;
use nym_bandwidth_controller::acquire::state::State;
use nym_bin_common::completions::ArgShell; use nym_bin_common::completions::ArgShell;
use rand::rngs::OsRng; use nym_credential_storage::persistent_storage::PersistentStorage;
use std::str::FromStr; use nym_validator_client::nyxd::traits::DkgQueryClient;
use nym_coconut_interface::{Base58, Parameters}; use crate::error::Result;
use nym_credential_storage::storage::Storage;
use nym_credential_storage::PersistentStorage;
use nym_credentials::coconut::bandwidth::{BandwidthVoucher, TOTAL_ATTRIBUTES};
use nym_credentials::coconut::utils::obtain_aggregate_signature;
use nym_crypto::asymmetric::{encryption, identity};
use nym_network_defaults::VOUCHER_INFO;
use validator_client::nyxd::traits::DkgQueryClient;
use validator_client::nyxd::tx::Hash;
use validator_client::nyxd::CosmWasmClient;
use validator_client::CoconutApiClient;
use crate::client::Client;
use crate::error::{CredentialClientError, Result};
use crate::recovery_storage::RecoveryStorage; use crate::recovery_storage::RecoveryStorage;
use crate::state::{KeyPair, State};
#[derive(Subcommand)] #[derive(Subcommand)]
pub(crate) enum Command { pub(crate) enum Command {
@@ -47,10 +34,6 @@ pub(crate) struct Run {
#[clap(long)] #[clap(long)]
pub(crate) client_home_directory: std::path::PathBuf, pub(crate) client_home_directory: std::path::PathBuf,
/// The nyxd URL that should be used
#[clap(long)]
pub(crate) nyxd_url: String,
/// A mnemonic for the account that buys the credential /// A mnemonic for the account that buys the credential
#[clap(long)] #[clap(long)]
pub(crate) mnemonic: String, pub(crate) mnemonic: String,
@@ -69,82 +52,16 @@ pub(crate) struct Run {
pub(crate) recovery_mode: bool, pub(crate) recovery_mode: bool,
} }
pub(crate) async fn deposit(nyxd_url: &str, mnemonic: &str, amount: u64) -> Result<State> { pub(crate) async fn recover_credentials<C: DkgQueryClient + Send + Sync>(
let mut rng = OsRng; client: &C,
let signing_keypair = KeyPair::from(identity::KeyPair::new(&mut rng));
let encryption_keypair = KeyPair::from(encryption::KeyPair::new(&mut rng));
let params = Parameters::new(TOTAL_ATTRIBUTES).unwrap();
let client = Client::new(nyxd_url, mnemonic);
let tx_hash = client
.deposit(
amount,
signing_keypair.public_key.clone(),
encryption_keypair.public_key.clone(),
None,
)
.await?;
let voucher = BandwidthVoucher::new(
&params,
amount.to_string(),
VOUCHER_INFO.to_string(),
Hash::from_str(&tx_hash).map_err(|_| CredentialClientError::InvalidTxHash)?,
identity::PrivateKey::from_base58_string(&signing_keypair.private_key)?,
encryption::PrivateKey::from_base58_string(&encryption_keypair.private_key)?,
);
let state = State { voucher, params };
Ok(state)
}
pub(crate) async fn get_credential<C: Clone + CosmWasmClient + Send + Sync>(
state: &State,
client: validator_client::Client<C>,
shared_storage: PersistentStorage,
) -> Result<()> {
let epoch_id = client.nyxd.get_current_epoch().await?.epoch_id;
let threshold = client
.nyxd
.get_current_epoch_threshold()
.await?
.ok_or(CredentialClientError::NoThreshold)?;
let coconut_api_clients = CoconutApiClient::all_coconut_api_clients(&client, epoch_id).await?;
let signature = obtain_aggregate_signature(
&state.params,
&state.voucher,
&coconut_api_clients,
threshold,
)
.await?;
info!("Signature: {:?}", signature.to_bs58());
shared_storage
.insert_coconut_credential(
state.voucher.get_voucher_value(),
VOUCHER_INFO.to_string(),
state.voucher.get_private_attributes()[0].to_bs58(),
state.voucher.get_private_attributes()[1].to_bs58(),
signature.to_bs58(),
epoch_id.to_string(),
)
.await?;
Ok(())
}
pub(crate) async fn recover_credentials<C: Clone + CosmWasmClient + Send + Sync>(
client: validator_client::Client<C>,
recovery_storage: &RecoveryStorage, recovery_storage: &RecoveryStorage,
shared_storage: PersistentStorage, shared_storage: &PersistentStorage,
) -> Result<()> { ) -> Result<()> {
for voucher in recovery_storage.unconsumed_vouchers()? { for voucher in recovery_storage.unconsumed_vouchers()? {
let state = State { let state = State::new(voucher);
voucher, if let Err(e) =
params: Parameters::new(TOTAL_ATTRIBUTES).unwrap(), nym_bandwidth_controller::acquire::get_credential(&state, client, shared_storage).await
}; {
if let Err(e) = get_credential(&state, client.clone(), shared_storage.clone()).await {
error!( error!(
"Could not recover deposit {} due to {:?}, try again later", "Could not recover deposit {} due to {:?}, try again later",
state.voucher.tx_hash(), state.voucher.tx_hash(),
+5 -16
View File
@@ -6,10 +6,8 @@ use thiserror::Error;
use nym_credential_storage::error::StorageError; use nym_credential_storage::error::StorageError;
use nym_credentials::error::Error as CredentialError; use nym_credentials::error::Error as CredentialError;
use nym_crypto::asymmetric::encryption::KeyRecoveryError; use nym_validator_client::nyxd::error::NyxdError;
use nym_crypto::asymmetric::identity::Ed25519RecoveryError; use nym_validator_client::ValidatorClientError;
use validator_client::nyxd::error::NyxdError;
use validator_client::ValidatorClientError;
pub type Result<T> = std::result::Result<T, CredentialClientError>; pub type Result<T> = std::result::Result<T, CredentialClientError>;
@@ -18,6 +16,9 @@ pub enum CredentialClientError {
#[error("IO error: {0}")] #[error("IO error: {0}")]
IOError(#[from] std::io::Error), IOError(#[from] std::io::Error),
#[error("Bandwidth controller error: {0}")]
BandwidthControllerError(#[from] nym_bandwidth_controller::error::BandwidthControllerError),
#[error("Nyxd error: {0}")] #[error("Nyxd error: {0}")]
Nyxd(#[from] NyxdError), Nyxd(#[from] NyxdError),
@@ -27,21 +28,9 @@ pub enum CredentialClientError {
#[error("Credential error: {0}")] #[error("Credential error: {0}")]
Credential(#[from] CredentialError), Credential(#[from] CredentialError),
#[error("The tx hash provided is not valid")]
InvalidTxHash,
#[error("Could not parse Ed25519 data")]
Ed25519ParseError(#[from] Ed25519RecoveryError),
#[error("Could not parse X25519 data")]
X25519ParseError(#[from] KeyRecoveryError),
#[error("Could not use shared storage")] #[error("Could not use shared storage")]
SharedStorageError(#[from] StorageError), SharedStorageError(#[from] StorageError),
#[error("Could not get system time")] #[error("Could not get system time")]
SysTimeError(#[from] SystemTimeError), SysTimeError(#[from] SystemTimeError),
#[error("Threshold not set yet")]
NoThreshold,
} }
+28 -17
View File
@@ -1,11 +1,9 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net> // Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
mod client;
mod commands; mod commands;
mod error; mod error;
mod recovery_storage; mod recovery_storage;
mod state;
use commands::*; use commands::*;
use error::Result; use error::Result;
@@ -18,9 +16,9 @@ use std::time::{Duration, SystemTime};
use clap::{CommandFactory, Parser}; use clap::{CommandFactory, Parser};
use nym_bin_common::logging::setup_logging; use nym_bin_common::logging::setup_logging;
use validator_client::nyxd::traits::DkgQueryClient; use nym_validator_client::nyxd::traits::DkgQueryClient;
use validator_client::nyxd::CosmWasmClient; use nym_validator_client::nyxd::{Coin, CosmWasmClient};
use validator_client::Config; use nym_validator_client::Config;
const SAFETY_BUFFER_SECS: u64 = 60; // 1 minute const SAFETY_BUFFER_SECS: u64 = 60; // 1 minute
@@ -35,8 +33,8 @@ struct Cli {
pub(crate) command: Command, pub(crate) command: Command,
} }
async fn block_until_coconut_is_available<C: Clone + CosmWasmClient + Send + Sync>( async fn block_until_coconut_is_available<C: CosmWasmClient + Send + Sync>(
client: &validator_client::Client<C>, client: &nym_validator_client::Client<C>,
) -> Result<()> { ) -> Result<()> {
loop { loop {
let epoch = client.nyxd.get_current_epoch().await?; let epoch = client.nyxd.get_current_epoch().await?;
@@ -77,21 +75,34 @@ async fn main() -> Result<()> {
.client_home_directory .client_home_directory
.join(DATA_DIR) .join(DATA_DIR)
.join(CRED_DB_FILE_NAME); .join(CRED_DB_FILE_NAME);
let shared_storage = nym_credential_storage::initialise_storage(db_path).await; let shared_storage =
nym_credential_storage::initialise_persistent_storage(db_path).await;
let recovery_storage = recovery_storage::RecoveryStorage::new(r.recovery_dir)?; let recovery_storage = recovery_storage::RecoveryStorage::new(r.recovery_dir)?;
let network_details = NymNetworkDetails::new_from_env(); let network_details = NymNetworkDetails::new_from_env();
let config = Config::try_from_nym_network_details(&network_details)?; let config = Config::try_from_nym_network_details(&network_details).expect(
let client = validator_client::Client::new_query(config)?; "failed to construct valid validator client config with the provided network",
);
let amount = Coin::new(
r.amount as u128,
network_details.chain_details.mix_denom.base,
);
let client =
nym_validator_client::Client::new_signing(config, r.mnemonic.parse().unwrap())?;
block_until_coconut_is_available(&client).await?; block_until_coconut_is_available(&client).await?;
info!("Starting depositing funds, don't kill the process"); info!("Starting depositing funds, don't kill the process");
if !r.recovery_mode { if !r.recovery_mode {
let state = deposit(&r.nyxd_url, &r.mnemonic, r.amount).await?; let state =
if get_credential(&state, client, shared_storage) nym_bandwidth_controller::acquire::deposit(&client.nyxd, amount).await?;
.await if nym_bandwidth_controller::acquire::get_credential(
.is_err() &state,
&client,
&shared_storage,
)
.await
.is_err()
{ {
warn!("Failed to obtain credential. Dumping recovery data.",); warn!("Failed to obtain credential. Dumping recovery data.",);
match recovery_storage.insert_voucher(&state.voucher) { match recovery_storage.insert_voucher(&state.voucher) {
@@ -104,11 +115,11 @@ async fn main() -> Result<()> {
} }
} }
} else { } else {
recover_credentials(client, &recovery_storage, shared_storage).await?; recover_credentials(&client.nyxd, &recovery_storage, &shared_storage).await?;
} }
} }
Command::Completions(c) => c.generate(&mut crate::Cli::command(), bin_name), Command::Completions(c) => c.generate(&mut Cli::command(), bin_name),
Command::GenerateFigSpec => fig_generate(&mut crate::Cli::command(), bin_name), Command::GenerateFigSpec => fig_generate(&mut Cli::command(), bin_name),
} }
Ok(()) Ok(())
+9 -10
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "nym-client" name = "nym-client"
version = "1.1.14" version = "1.1.15"
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jędrzej Stuczyński <andrew@nymtech.net>"] authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jędrzej Stuczyński <andrew@nymtech.net>"]
description = "Implementation of the Nym Client" description = "Implementation of the Nym Client"
edition = "2021" edition = "2021"
@@ -26,30 +26,29 @@ lazy_static = "1.4.0"
log = { workspace = true } # self explanatory log = { workspace = true } # self explanatory
pretty_env_logger = "0.4" # for formatting log messages pretty_env_logger = "0.4" # for formatting log messages
rand = { version = "0.7.3", features = ["wasm-bindgen"] } # rng-related traits + some rng implementation to use rand = { version = "0.7.3", features = ["wasm-bindgen"] } # rng-related traits + some rng implementation to use
serde = { version = "1.0.104", features = ["derive"] } # for config serialization/deserialization serde = { workspace = true, features = ["derive"] } # for config serialization/deserialization
serde_json = "1.0" serde_json = { workspace = true }
thiserror = "1.0.34" thiserror = "1.0.34"
tap = "1.0.1" tap = "1.0.1"
tokio = { version = "1.24.1", features = ["rt-multi-thread", "net", "signal"] } # async runtime tokio = { version = "1.24.1", features = ["rt-multi-thread", "net", "signal"] } # async runtime
tokio-tungstenite = "0.14" # websocket tokio-tungstenite = "0.14" # websocket
## internal ## internal
nym-bin-common = { path = "../../common/bin-common" } nym-bandwidth-controller = { path = "../../common/bandwidth-controller" }
client-core = { path = "../client-core", features = ["fs-surb-storage"] } nym-bin-common = { path = "../../common/bin-common", features = ["output_format"] }
nym-client-core = { path = "../../common/client-core", features = ["fs-surb-storage"] }
nym-coconut-interface = { path = "../../common/coconut-interface" } nym-coconut-interface = { path = "../../common/coconut-interface" }
nym-config = { path = "../../common/config" } nym-config = { path = "../../common/config" }
nym-credential-storage = { path = "../../common/credential-storage" } nym-credential-storage = { path = "../../common/credential-storage" }
nym-credentials = { path = "../../common/credentials" } nym-credentials = { path = "../../common/credentials" }
nym-crypto = { path = "../../common/crypto" } nym-crypto = { path = "../../common/crypto" }
gateway-client = { path = "../../common/client-libs/gateway-client" } nym-gateway-requests = { path = "../../gateway/gateway-requests" }
gateway-requests = { path = "../../gateway/gateway-requests" }
nym-network-defaults = { path = "../../common/network-defaults" } nym-network-defaults = { path = "../../common/network-defaults" }
nym-sphinx = { path = "../../common/nymsphinx" } nym-sphinx = { path = "../../common/nymsphinx" }
nym-pemstore = { path = "../../common/pemstore" } nym-pemstore = { path = "../../common/pemstore" }
nym-task = { path = "../../common/task" } nym-task = { path = "../../common/task" }
nym-topology = { path = "../../common/topology" } nym-topology = { path = "../../common/topology" }
validator-client = { path = "../../common/client-libs/validator-client", features = ["nyxd-client"] } nym-validator-client = { path = "../../common/client-libs/validator-client", features = ["nyxd-client"] }
websocket-requests = { path = "websocket-requests" } nym-client-websocket-requests = { path = "websocket-requests" }
[dev-dependencies] [dev-dependencies]
serde_json = "1.0" # for the "textsend" example
@@ -13,7 +13,7 @@
}, },
"devDependencies": { "devDependencies": {
"clean-webpack-plugin": "^4.0.0", "clean-webpack-plugin": "^4.0.0",
"webpack": "^5.70.0", "webpack": "^5.76.0",
"webpack-cli": "^4.9.2", "webpack-cli": "^4.9.2",
"webpack-dev-server": "^4.7.4" "webpack-dev-server": "^4.7.4"
} }
@@ -490,9 +490,9 @@
} }
}, },
"node_modules/acorn": { "node_modules/acorn": {
"version": "8.7.0", "version": "8.8.2",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz",
"integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==",
"bin": { "bin": {
"acorn": "bin/acorn" "acorn": "bin/acorn"
}, },
@@ -1327,9 +1327,9 @@
} }
}, },
"node_modules/enhanced-resolve": { "node_modules/enhanced-resolve": {
"version": "5.9.2", "version": "5.12.0",
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.9.2.tgz", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz",
"integrity": "sha512-GIm3fQfwLJ8YZx2smuHpBKkXC1yOk+OBEmKckVyL0i/ea8mqDEykK3ld5dgH1QYPNyT/lIllxV2LULnxCHaHkA==", "integrity": "sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ==",
"dependencies": { "dependencies": {
"graceful-fs": "^4.2.4", "graceful-fs": "^4.2.4",
"tapable": "^2.2.0" "tapable": "^2.2.0"
@@ -2380,10 +2380,10 @@
"node": ">= 10.13.0" "node": ">= 10.13.0"
} }
}, },
"node_modules/json-parse-better-errors": { "node_modules/json-parse-even-better-errors": {
"version": "1.0.2", "version": "2.3.1",
"resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
"integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==" "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w=="
}, },
"node_modules/json-schema-traverse": { "node_modules/json-schema-traverse": {
"version": "0.4.1", "version": "0.4.1",
@@ -3824,9 +3824,9 @@
} }
}, },
"node_modules/watchpack": { "node_modules/watchpack": {
"version": "2.3.1", "version": "2.4.0",
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.3.1.tgz", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz",
"integrity": "sha512-x0t0JuydIo8qCNctdDrn1OzH/qDzk2+rdCOC3YzumZ42fiMqmQ7T3xQurykYMhYfHaPHTp4ZxAx2NfUo1K6QaA==", "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==",
"dependencies": { "dependencies": {
"glob-to-regexp": "^0.4.1", "glob-to-regexp": "^0.4.1",
"graceful-fs": "^4.1.2" "graceful-fs": "^4.1.2"
@@ -3845,33 +3845,33 @@
} }
}, },
"node_modules/webpack": { "node_modules/webpack": {
"version": "5.70.0", "version": "5.76.0",
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.70.0.tgz", "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.76.0.tgz",
"integrity": "sha512-ZMWWy8CeuTTjCxbeaQI21xSswseF2oNOwc70QSKNePvmxE7XW36i7vpBMYZFAUHPwQiEbNGCEYIOOlyRbdGmxw==", "integrity": "sha512-l5sOdYBDunyf72HW8dF23rFtWq/7Zgvt/9ftMof71E/yUb1YLOBmTgA2K4vQthB3kotMrSj609txVE0dnr2fjA==",
"dependencies": { "dependencies": {
"@types/eslint-scope": "^3.7.3", "@types/eslint-scope": "^3.7.3",
"@types/estree": "^0.0.51", "@types/estree": "^0.0.51",
"@webassemblyjs/ast": "1.11.1", "@webassemblyjs/ast": "1.11.1",
"@webassemblyjs/wasm-edit": "1.11.1", "@webassemblyjs/wasm-edit": "1.11.1",
"@webassemblyjs/wasm-parser": "1.11.1", "@webassemblyjs/wasm-parser": "1.11.1",
"acorn": "^8.4.1", "acorn": "^8.7.1",
"acorn-import-assertions": "^1.7.6", "acorn-import-assertions": "^1.7.6",
"browserslist": "^4.14.5", "browserslist": "^4.14.5",
"chrome-trace-event": "^1.0.2", "chrome-trace-event": "^1.0.2",
"enhanced-resolve": "^5.9.2", "enhanced-resolve": "^5.10.0",
"es-module-lexer": "^0.9.0", "es-module-lexer": "^0.9.0",
"eslint-scope": "5.1.1", "eslint-scope": "5.1.1",
"events": "^3.2.0", "events": "^3.2.0",
"glob-to-regexp": "^0.4.1", "glob-to-regexp": "^0.4.1",
"graceful-fs": "^4.2.9", "graceful-fs": "^4.2.9",
"json-parse-better-errors": "^1.0.2", "json-parse-even-better-errors": "^2.3.1",
"loader-runner": "^4.2.0", "loader-runner": "^4.2.0",
"mime-types": "^2.1.27", "mime-types": "^2.1.27",
"neo-async": "^2.6.2", "neo-async": "^2.6.2",
"schema-utils": "^3.1.0", "schema-utils": "^3.1.0",
"tapable": "^2.1.1", "tapable": "^2.1.1",
"terser-webpack-plugin": "^5.1.3", "terser-webpack-plugin": "^5.1.3",
"watchpack": "^2.3.1", "watchpack": "^2.4.0",
"webpack-sources": "^3.2.3" "webpack-sources": "^3.2.3"
}, },
"bin": { "bin": {
@@ -4894,9 +4894,9 @@
} }
}, },
"acorn": { "acorn": {
"version": "8.7.0", "version": "8.8.2",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz",
"integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==" "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw=="
}, },
"acorn-import-assertions": { "acorn-import-assertions": {
"version": "1.8.0", "version": "1.8.0",
@@ -5527,9 +5527,9 @@
"dev": true "dev": true
}, },
"enhanced-resolve": { "enhanced-resolve": {
"version": "5.9.2", "version": "5.12.0",
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.9.2.tgz", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz",
"integrity": "sha512-GIm3fQfwLJ8YZx2smuHpBKkXC1yOk+OBEmKckVyL0i/ea8mqDEykK3ld5dgH1QYPNyT/lIllxV2LULnxCHaHkA==", "integrity": "sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ==",
"requires": { "requires": {
"graceful-fs": "^4.2.4", "graceful-fs": "^4.2.4",
"tapable": "^2.2.0" "tapable": "^2.2.0"
@@ -6305,10 +6305,10 @@
"supports-color": "^8.0.0" "supports-color": "^8.0.0"
} }
}, },
"json-parse-better-errors": { "json-parse-even-better-errors": {
"version": "1.0.2", "version": "2.3.1",
"resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
"integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==" "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w=="
}, },
"json-schema-traverse": { "json-schema-traverse": {
"version": "0.4.1", "version": "0.4.1",
@@ -7396,9 +7396,9 @@
"dev": true "dev": true
}, },
"watchpack": { "watchpack": {
"version": "2.3.1", "version": "2.4.0",
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.3.1.tgz", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz",
"integrity": "sha512-x0t0JuydIo8qCNctdDrn1OzH/qDzk2+rdCOC3YzumZ42fiMqmQ7T3xQurykYMhYfHaPHTp4ZxAx2NfUo1K6QaA==", "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==",
"requires": { "requires": {
"glob-to-regexp": "^0.4.1", "glob-to-regexp": "^0.4.1",
"graceful-fs": "^4.1.2" "graceful-fs": "^4.1.2"
@@ -7414,33 +7414,33 @@
} }
}, },
"webpack": { "webpack": {
"version": "5.70.0", "version": "5.76.0",
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.70.0.tgz", "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.76.0.tgz",
"integrity": "sha512-ZMWWy8CeuTTjCxbeaQI21xSswseF2oNOwc70QSKNePvmxE7XW36i7vpBMYZFAUHPwQiEbNGCEYIOOlyRbdGmxw==", "integrity": "sha512-l5sOdYBDunyf72HW8dF23rFtWq/7Zgvt/9ftMof71E/yUb1YLOBmTgA2K4vQthB3kotMrSj609txVE0dnr2fjA==",
"requires": { "requires": {
"@types/eslint-scope": "^3.7.3", "@types/eslint-scope": "^3.7.3",
"@types/estree": "^0.0.51", "@types/estree": "^0.0.51",
"@webassemblyjs/ast": "1.11.1", "@webassemblyjs/ast": "1.11.1",
"@webassemblyjs/wasm-edit": "1.11.1", "@webassemblyjs/wasm-edit": "1.11.1",
"@webassemblyjs/wasm-parser": "1.11.1", "@webassemblyjs/wasm-parser": "1.11.1",
"acorn": "^8.4.1", "acorn": "^8.7.1",
"acorn-import-assertions": "^1.7.6", "acorn-import-assertions": "^1.7.6",
"browserslist": "^4.14.5", "browserslist": "^4.14.5",
"chrome-trace-event": "^1.0.2", "chrome-trace-event": "^1.0.2",
"enhanced-resolve": "^5.9.2", "enhanced-resolve": "^5.10.0",
"es-module-lexer": "^0.9.0", "es-module-lexer": "^0.9.0",
"eslint-scope": "5.1.1", "eslint-scope": "5.1.1",
"events": "^3.2.0", "events": "^3.2.0",
"glob-to-regexp": "^0.4.1", "glob-to-regexp": "^0.4.1",
"graceful-fs": "^4.2.9", "graceful-fs": "^4.2.9",
"json-parse-better-errors": "^1.0.2", "json-parse-even-better-errors": "^2.3.1",
"loader-runner": "^4.2.0", "loader-runner": "^4.2.0",
"mime-types": "^2.1.27", "mime-types": "^2.1.27",
"neo-async": "^2.6.2", "neo-async": "^2.6.2",
"schema-utils": "^3.1.0", "schema-utils": "^3.1.0",
"tapable": "^2.1.1", "tapable": "^2.1.1",
"terser-webpack-plugin": "^5.1.3", "terser-webpack-plugin": "^5.1.3",
"watchpack": "^2.3.1", "watchpack": "^2.4.0",
"webpack-sources": "^3.2.3" "webpack-sources": "^3.2.3"
} }
}, },
@@ -19,7 +19,7 @@
"license": "Apache-2.0", "license": "Apache-2.0",
"devDependencies": { "devDependencies": {
"clean-webpack-plugin": "^4.0.0", "clean-webpack-plugin": "^4.0.0",
"webpack": "^5.70.0", "webpack": "^5.76.0",
"webpack-cli": "^4.9.2", "webpack-cli": "^4.9.2",
"webpack-dev-server": "^4.7.4" "webpack-dev-server": "^4.7.4"
}, },
@@ -1,10 +1,10 @@
use futures::{SinkExt, StreamExt}; use futures::{SinkExt, StreamExt};
use nym_client_websocket_requests::{requests::ClientRequest, responses::ServerResponse};
use nym_sphinx::addressing::clients::Recipient; use nym_sphinx::addressing::clients::Recipient;
use tokio::net::TcpStream; use tokio::net::TcpStream;
use tokio_tungstenite::{ use tokio_tungstenite::{
connect_async, tungstenite::protocol::Message, MaybeTlsStream, WebSocketStream, connect_async, tungstenite::protocol::Message, MaybeTlsStream, WebSocketStream,
}; };
use websocket_requests::{requests::ClientRequest, responses::ServerResponse};
// just helpers functions that work in this very particular context because we are sending to ourselves // just helpers functions that work in this very particular context because we are sending to ourselves
// and hence will always get a response back (i.e. the message we sent) // and hence will always get a response back (i.e. the message we sent)
+10 -5
View File
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use crate::client::config::template::config_template; use crate::client::config::template::config_template;
use client_core::config::ClientCoreConfigTrait; use nym_client_core::config::ClientCoreConfigTrait;
use nym_config::defaults::DEFAULT_WEBSOCKET_LISTENING_PORT; use nym_config::defaults::DEFAULT_WEBSOCKET_LISTENING_PORT;
use nym_config::{NymConfig, OptionalSet}; use nym_config::{NymConfig, OptionalSet};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@@ -11,9 +11,9 @@ use std::net::{IpAddr, Ipv4Addr};
use std::path::PathBuf; use std::path::PathBuf;
use std::str::FromStr; use std::str::FromStr;
pub use client_core::config::Config as BaseConfig; pub use nym_client_core::config::Config as BaseConfig;
pub use client_core::config::MISSING_VALUE; pub use nym_client_core::config::MISSING_VALUE;
pub use client_core::config::{DebugConfig, GatewayEndpointConfig}; pub use nym_client_core::config::{DebugConfig, GatewayEndpointConfig};
pub mod old_config_v1_1_13; pub mod old_config_v1_1_13;
mod template; mod template;
@@ -81,7 +81,7 @@ impl NymConfig for Config {
} }
impl ClientCoreConfigTrait for Config { impl ClientCoreConfigTrait for Config {
fn get_gateway_endpoint(&self) -> &client_core::config::GatewayEndpointConfig { fn get_gateway_endpoint(&self) -> &nym_client_core::config::GatewayEndpointConfig {
self.base.get_gateway_endpoint() self.base.get_gateway_endpoint()
} }
} }
@@ -94,6 +94,11 @@ impl Config {
} }
} }
pub fn validate(&self) -> bool {
// no other sections have explicit requirements (yet)
self.base.validate()
}
pub fn with_socket(mut self, socket_type: SocketType) -> Self { pub fn with_socket(mut self, socket_type: SocketType) -> Self {
self.socket.socket_type = socket_type; self.socket.socket_type = socket_type;
self self
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use crate::client::config::{Config, Socket}; use crate::client::config::{Config, Socket};
use client_core::config::old_config_v1_1_13::OldConfigV1_1_13 as OldBaseConfigV1_1_13; use nym_client_core::config::old_config_v1_1_13::OldConfigV1_1_13 as OldBaseConfigV1_1_13;
use nym_config::NymConfig; use nym_config::NymConfig;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::path::PathBuf; use std::path::PathBuf;
+24 -16
View File
@@ -1,31 +1,33 @@
// Copyright 2021-2022 - Nym Technologies SA <contact@nymtech.net> // Copyright 2021-2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use std::error::Error;
use crate::client::config::Config; use crate::client::config::Config;
use crate::error::ClientError; use crate::error::ClientError;
use crate::websocket; use crate::websocket;
use client_core::client::base_client::{ use futures::channel::mpsc;
use log::*;
use nym_bandwidth_controller::BandwidthController;
use nym_client_core::client::base_client::{
non_wasm_helpers, BaseClientBuilder, ClientInput, ClientOutput, ClientState, non_wasm_helpers, BaseClientBuilder, ClientInput, ClientOutput, ClientState,
}; };
use client_core::client::inbound_messages::InputMessage; use nym_client_core::client::inbound_messages::InputMessage;
use client_core::client::received_buffer::{ use nym_client_core::client::received_buffer::{
ReceivedBufferMessage, ReceivedBufferRequestSender, ReconstructedMessagesReceiver, ReceivedBufferMessage, ReceivedBufferRequestSender, ReconstructedMessagesReceiver,
}; };
use client_core::config::persistence::key_pathfinder::ClientKeyPathfinder; use nym_client_core::config::persistence::key_pathfinder::ClientKeyPathfinder;
use futures::channel::mpsc;
use gateway_client::bandwidth::BandwidthController;
use log::*;
use nym_sphinx::anonymous_replies::requests::AnonymousSenderTag; use nym_sphinx::anonymous_replies::requests::AnonymousSenderTag;
use nym_task::connections::TransmissionLane; use nym_task::connections::TransmissionLane;
use nym_task::TaskManager; use nym_task::TaskManager;
use nym_validator_client::nyxd::QueryNyxdClient;
use std::error::Error;
use tokio::sync::watch::error::SendError; use tokio::sync::watch::error::SendError;
use validator_client::nyxd::QueryNyxdClient;
pub use client_core::client::key_manager::KeyManager; pub use nym_client_core::client::key_manager::KeyManager;
use nym_credential_storage::persistent_storage::PersistentStorage;
pub use nym_sphinx::addressing::clients::Recipient; pub use nym_sphinx::addressing::clients::Recipient;
pub use nym_sphinx::receiver::ReconstructedMessage; pub use nym_sphinx::receiver::ReconstructedMessage;
use nym_validator_client::Client;
pub mod config; pub mod config;
pub struct SocketClient { pub struct SocketClient {
@@ -55,10 +57,13 @@ impl SocketClient {
} }
} }
async fn create_bandwidth_controller(config: &Config) -> BandwidthController<QueryNyxdClient> { async fn create_bandwidth_controller(
config: &Config,
) -> BandwidthController<Client<QueryNyxdClient>, PersistentStorage> {
let details = nym_network_defaults::NymNetworkDetails::new_from_env(); let details = nym_network_defaults::NymNetworkDetails::new_from_env();
let mut client_config = validator_client::Config::try_from_nym_network_details(&details) let mut client_config =
.expect("failed to construct validator client config"); nym_validator_client::Config::try_from_nym_network_details(&details)
.expect("failed to construct validator client config");
let nyxd_url = config let nyxd_url = config
.get_base() .get_base()
.get_validator_endpoints() .get_validator_endpoints()
@@ -71,10 +76,13 @@ impl SocketClient {
.expect("No validator api endpoint provided"); .expect("No validator api endpoint provided");
// overwrite env configuration with config URLs // overwrite env configuration with config URLs
client_config = client_config.with_urls(nyxd_url, api_url); client_config = client_config.with_urls(nyxd_url, api_url);
let client = validator_client::Client::new_query(client_config) let client = nym_validator_client::Client::new_query(client_config)
.expect("Could not construct query client"); .expect("Could not construct query client");
BandwidthController::new( BandwidthController::new(
nym_credential_storage::initialise_storage(config.get_base().get_database_path()).await, nym_credential_storage::initialise_persistent_storage(
config.get_base().get_database_path(),
)
.await,
client, client,
) )
} }
+19 -21
View File
@@ -8,7 +8,9 @@ use crate::{
error::ClientError, error::ClientError,
}; };
use clap::Args; use clap::Args;
use nym_bin_common::output_format::OutputFormat;
use nym_config::NymConfig; use nym_config::NymConfig;
use nym_credential_storage::persistent_storage::PersistentStorage;
use nym_crypto::asymmetric::identity; use nym_crypto::asymmetric::identity;
use nym_sphinx::addressing::clients::Recipient; use nym_sphinx::addressing::clients::Recipient;
use serde::Serialize; use serde::Serialize;
@@ -71,9 +73,8 @@ pub(crate) struct Init {
#[clap(long, hide = true)] #[clap(long, hide = true)]
enabled_credentials_mode: Option<bool>, enabled_credentials_mode: Option<bool>,
/// Save a summary of the initialization to a json file #[clap(short, long, default_value_t = OutputFormat::default())]
#[clap(long)] output: OutputFormat,
output_json: bool,
} }
impl From<Init> for OverrideConfig { impl From<Init> for OverrideConfig {
@@ -95,15 +96,17 @@ impl From<Init> for OverrideConfig {
#[derive(Debug, Serialize)] #[derive(Debug, Serialize)]
pub struct InitResults { pub struct InitResults {
#[serde(flatten)] #[serde(flatten)]
client_core: client_core::init::InitResults, client_core: nym_client_core::init::InitResults,
client_listening_port: String, client_listening_port: String,
client_address: String,
} }
impl InitResults { impl InitResults {
fn new(config: &Config, address: &Recipient) -> Self { fn new(config: &Config, address: &Recipient) -> Self {
Self { Self {
client_core: client_core::init::InitResults::new(config.get_base(), address), client_core: nym_client_core::init::InitResults::new(config.get_base(), address),
client_listening_port: config.get_listening_port().to_string(), client_listening_port: config.get_listening_port().to_string(),
client_address: address.to_string(),
} }
} }
} }
@@ -111,12 +114,13 @@ impl InitResults {
impl Display for InitResults { impl Display for InitResults {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
writeln!(f, "{}", self.client_core)?; writeln!(f, "{}", self.client_core)?;
write!(f, "Client listening port: {}", self.client_listening_port) writeln!(f, "Client listening port: {}", self.client_listening_port)?;
write!(f, "Address of this client: {}", self.client_address)
} }
} }
pub(crate) async fn execute(args: &Init) -> Result<(), ClientError> { pub(crate) async fn execute(args: &Init) -> Result<(), ClientError> {
println!("Initialising client..."); eprintln!("Initialising client...");
let id = &args.id; let id = &args.id;
@@ -125,14 +129,14 @@ pub(crate) async fn execute(args: &Init) -> Result<(), ClientError> {
// in case we're using old config, try to upgrade it // in case we're using old config, try to upgrade it
// (if we're using the current version, it's a no-op) // (if we're using the current version, it's a no-op)
try_upgrade_v1_1_13_config(id)?; try_upgrade_v1_1_13_config(id)?;
println!("Client \"{id}\" was already initialised before"); eprintln!("Client \"{id}\" was already initialised before");
} }
// Usually you only register with the gateway on the first init, however you can force // Usually you only register with the gateway on the first init, however you can force
// re-registering if wanted. // re-registering if wanted.
let user_wants_force_register = args.force_register_gateway; let user_wants_force_register = args.force_register_gateway;
if user_wants_force_register { if user_wants_force_register {
println!("Instructed to force registering gateway. This might overwrite keys!"); eprintln!("Instructed to force registering gateway. This might overwrite keys!");
} }
// If the client was already initialized, don't generate new keys and don't re-register with // If the client was already initialized, don't generate new keys and don't re-register with
@@ -148,7 +152,7 @@ pub(crate) async fn execute(args: &Init) -> Result<(), ClientError> {
// Setup gateway by either registering a new one, or creating a new config from the selected // Setup gateway by either registering a new one, or creating a new config from the selected
// one but with keys kept, or reusing the gateway configuration. // one but with keys kept, or reusing the gateway configuration.
let gateway = client_core::init::setup_gateway_from_config::<Config, _>( let gateway = nym_client_core::init::setup_gateway_from_config::<Config, _, PersistentStorage>(
register_gateway, register_gateway,
user_chosen_gateway_id, user_chosen_gateway_id,
config.get_base(), config.get_base(),
@@ -165,28 +169,22 @@ pub(crate) async fn execute(args: &Init) -> Result<(), ClientError> {
print_saved_config(&config); print_saved_config(&config);
let address = client_core::init::get_client_address_from_stored_keys(config.get_base())?; let address = nym_client_core::init::get_client_address_from_stored_keys(config.get_base())?;
let init_results = InitResults::new(&config, &address); let init_results = InitResults::new(&config, &address);
println!("{init_results}"); println!("{}", args.output.format(&init_results));
// Output summary to a json file, if specified
if args.output_json {
client_core::init::output_to_json(&init_results, "client_init_results.json");
}
println!("\nThe address of this client is: {address}\n");
Ok(()) Ok(())
} }
fn print_saved_config(config: &Config) { fn print_saved_config(config: &Config) {
let config_save_location = config.get_config_file_save_location(); let config_save_location = config.get_config_file_save_location();
println!("Saved configuration file to {config_save_location:?}"); eprintln!("Saved configuration file to {config_save_location:?}");
println!("Using gateway: {}", config.get_base().get_gateway_id()); eprintln!("Using gateway: {}", config.get_base().get_gateway_id());
log::debug!("Gateway id: {}", config.get_base().get_gateway_id()); log::debug!("Gateway id: {}", config.get_base().get_gateway_id());
log::debug!("Gateway owner: {}", config.get_base().get_gateway_owner()); log::debug!("Gateway owner: {}", config.get_base().get_gateway_owner());
log::debug!( log::debug!(
"Gateway listener: {}", "Gateway listener: {}",
config.get_base().get_gateway_listener() config.get_base().get_gateway_listener()
); );
println!("Client configuration completed.\n"); eprintln!("Client configuration completed.\n");
} }
+4
View File
@@ -112,6 +112,10 @@ pub(crate) async fn execute(args: &Run) -> Result<(), Box<dyn Error + Send + Syn
} }
}; };
if !config.validate() {
return Err(Box::new(ClientError::ConfigValidationFailure));
}
let override_config_fields = OverrideConfig::from(args.clone()); let override_config_fields = OverrideConfig::from(args.clone());
config = override_config(config, override_config_fields); config = override_config(config, override_config_fields);
+5 -1
View File
@@ -1,4 +1,4 @@
use client_core::error::ClientCoreError; use nym_client_core::error::ClientCoreError;
#[derive(thiserror::Error, Debug)] #[derive(thiserror::Error, Debug)]
pub enum ClientError { pub enum ClientError {
@@ -11,6 +11,10 @@ pub enum ClientError {
#[error("Failed to load config for: {0}")] #[error("Failed to load config for: {0}")]
FailedToLoadConfig(String), FailedToLoadConfig(String),
// TODO: add more details here
#[error("Failed to validate the loaded config")]
ConfigValidationFailure,
#[error("Failed local version check, client and config mismatch")] #[error("Failed local version check, client and config mismatch")]
FailedLocalVersionCheck, FailedLocalVersionCheck,
+2 -2
View File
@@ -4,7 +4,7 @@
use std::error::Error; use std::error::Error;
use clap::{crate_name, crate_version, Parser}; use clap::{crate_name, crate_version, Parser};
use nym_bin_common::logging::{banner, setup_logging}; use nym_bin_common::logging::{maybe_print_banner, setup_logging};
use nym_network_defaults::setup_env; use nym_network_defaults::setup_env;
pub mod client; pub mod client;
@@ -15,7 +15,7 @@ pub mod websocket;
#[tokio::main] #[tokio::main]
async fn main() -> Result<(), Box<dyn Error + Send + Sync>> { async fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
setup_logging(); setup_logging();
println!("{}", banner(crate_name!(), crate_version!())); maybe_print_banner(crate_name!(), crate_version!());
let args = commands::Cli::parse(); let args = commands::Cli::parse();
setup_env(args.config_env_file.as_ref()); setup_env(args.config_env_file.as_ref());
+6 -6
View File
@@ -1,16 +1,17 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net> // Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use client_core::client::replies::reply_controller::requests::ReplyControllerSender; use futures::channel::mpsc;
use client_core::client::{ use futures::{SinkExt, StreamExt};
use log::*;
use nym_client_core::client::replies::reply_controller::requests::ReplyControllerSender;
use nym_client_core::client::{
inbound_messages::{InputMessage, InputMessageSender}, inbound_messages::{InputMessage, InputMessageSender},
received_buffer::{ received_buffer::{
ReceivedBufferMessage, ReceivedBufferRequestSender, ReconstructedMessagesReceiver, ReceivedBufferMessage, ReceivedBufferRequestSender, ReconstructedMessagesReceiver,
}, },
}; };
use futures::channel::mpsc; use nym_client_websocket_requests::{requests::ClientRequest, responses::ServerResponse};
use futures::{SinkExt, StreamExt};
use log::*;
use nym_sphinx::addressing::clients::Recipient; use nym_sphinx::addressing::clients::Recipient;
use nym_sphinx::anonymous_replies::requests::AnonymousSenderTag; use nym_sphinx::anonymous_replies::requests::AnonymousSenderTag;
use nym_sphinx::receiver::ReconstructedMessage; use nym_sphinx::receiver::ReconstructedMessage;
@@ -25,7 +26,6 @@ use tokio_tungstenite::{
tungstenite::{protocol::Message as WsMessage, Error as WsError}, tungstenite::{protocol::Message as WsMessage, Error as WsError},
WebSocketStream, WebSocketStream,
}; };
use websocket_requests::{requests::ClientRequest, responses::ServerResponse};
#[derive(Default)] #[derive(Default)]
enum ReceivedResponseType { enum ReceivedResponseType {
+3 -3
View File
@@ -1,5 +1,5 @@
[package] [package]
name = "websocket-requests" name = "nym-client-websocket-requests"
version = "0.1.0" version = "0.1.0"
authors = ["Jędrzej Stuczyński <andrew@nymtech.net>"] authors = ["Jędrzej Stuczyński <andrew@nymtech.net>"]
edition = "2021" edition = "2021"
@@ -7,7 +7,7 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
serde = { version = "1.0", features = ["derive"] } serde = { workspace = true, features = ["derive"] }
serde_json = "1.0" serde_json = { workspace = true }
nym-sphinx = { path = "../../../common/nymsphinx" } nym-sphinx = { path = "../../../common/nymsphinx" }
+7 -22
View File
@@ -1,24 +1,16 @@
[package] [package]
name = "nym-socks5-client" name = "nym-socks5-client"
version = "1.1.14" version = "1.1.15"
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"] authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"]
description = "A SOCKS5 localhost proxy that converts incoming messages to Sphinx and sends them to a Nym address" description = "A SOCKS5 localhost proxy that converts incoming messages to Sphinx and sends them to a Nym address"
edition = "2021" edition = "2021"
rust-version = "1.56" rust-version = "1.56"
[lib]
name = "nym_socks5"
path = "src/lib.rs"
[dependencies] [dependencies]
clap = { version = "4.0", features = ["cargo", "derive"] } clap = { version = "4.0", features = ["cargo", "derive"] }
dirs = "4.0"
futures = "0.3"
lazy_static = "1.4.0" lazy_static = "1.4.0"
log = { workspace = true } log = { workspace = true }
pin-project = "1.0"
pretty_env_logger = "0.4" pretty_env_logger = "0.4"
rand = { version = "0.7.3", features = ["wasm-bindgen"] }
serde = { workspace = true, features = ["derive"] } # for config serialization/deserialization serde = { workspace = true, features = ["derive"] } # for config serialization/deserialization
serde_json = { workspace = true } serde_json = { workspace = true }
tap = "1.0.1" tap = "1.0.1"
@@ -27,28 +19,21 @@ tokio = { version = "1.24.1", features = ["rt-multi-thread", "net", "signal"] }
url = "2.2" url = "2.2"
# internal # internal
nym-bin-common = { path = "../../common/bin-common" } nym-bin-common = { path = "../../common/bin-common", features = ["output_format"] }
client-core = { path = "../client-core", features = ["fs-surb-storage"] } nym-client-core = { path = "../../common/client-core", features = ["fs-surb-storage"] }
nym-coconut-interface = { path = "../../common/coconut-interface" } nym-coconut-interface = { path = "../../common/coconut-interface" }
nym-config = { path = "../../common/config" } nym-config = { path = "../../common/config" }
nym-credential-storage = { path = "../../common/credential-storage", optional = true }
mobile-storage = { path = "../../common/mobile-storage", optional = true }
nym-credentials = { path = "../../common/credentials" } nym-credentials = { path = "../../common/credentials" }
nym-crypto = { path = "../../common/crypto" } nym-crypto = { path = "../../common/crypto" }
gateway-client = { path = "../../common/client-libs/gateway-client" } nym-gateway-requests = { path = "../../gateway/gateway-requests" }
gateway-requests = { path = "../../gateway/gateway-requests" } nym-credential-storage = { path = "../../common/credential-storage" }
nym-network-defaults = { path = "../../common/network-defaults" } nym-network-defaults = { path = "../../common/network-defaults" }
nym-sphinx = { path = "../../common/nymsphinx" } nym-sphinx = { path = "../../common/nymsphinx" }
nym-ordered-buffer = { path = "../../common/socks5/ordered-buffer" } nym-ordered-buffer = { path = "../../common/socks5/ordered-buffer" }
nym-pemstore = { path = "../../common/pemstore" } nym-pemstore = { path = "../../common/pemstore" }
nym-socks5-proxy-helpers = { path = "../../common/socks5/proxy-helpers" }
nym-service-providers-common = { path = "../../service-providers/common" }
nym-socks5-requests = { path = "../../common/socks5/requests" }
nym-task = { path = "../../common/task" }
nym-topology = { path = "../../common/topology" } nym-topology = { path = "../../common/topology" }
validator-client = { path = "../../common/client-libs/validator-client", features = ["nyxd-client"] } nym-socks5-client-core = { path = "../../common/socks5-client-core" }
[features] [features]
default = ["nym-credential-storage"] default = []
eth = [] eth = []
mobile = ["mobile-storage", "gateway-client/mobile"]
+22 -24
View File
@@ -1,15 +1,17 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net> // Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use crate::commands::try_upgrade_v1_1_13_config; use crate::commands::try_upgrade_v1_1_13_config;
use crate::{ use crate::{
client::config::Config,
commands::{override_config, OverrideConfig}, commands::{override_config, OverrideConfig},
error::Socks5ClientError, error::Socks5ClientError,
}; };
use clap::Args; use clap::Args;
use nym_bin_common::output_format::OutputFormat;
use nym_config::NymConfig; use nym_config::NymConfig;
use nym_credential_storage::persistent_storage::PersistentStorage;
use nym_crypto::asymmetric::identity; use nym_crypto::asymmetric::identity;
use nym_socks5_client_core::config::Config;
use nym_sphinx::addressing::clients::Recipient; use nym_sphinx::addressing::clients::Recipient;
use serde::Serialize; use serde::Serialize;
use std::fmt::Display; use std::fmt::Display;
@@ -75,9 +77,8 @@ pub(crate) struct Init {
#[clap(long, hide = true)] #[clap(long, hide = true)]
enabled_credentials_mode: Option<bool>, enabled_credentials_mode: Option<bool>,
/// Save a summary of the initialization to a json file #[clap(short, long, default_value_t = OutputFormat::default())]
#[clap(long)] output: OutputFormat,
output_json: bool,
} }
impl From<Init> for OverrideConfig { impl From<Init> for OverrideConfig {
@@ -97,15 +98,17 @@ impl From<Init> for OverrideConfig {
#[derive(Debug, Serialize)] #[derive(Debug, Serialize)]
pub struct InitResults { pub struct InitResults {
#[serde(flatten)] #[serde(flatten)]
client_core: client_core::init::InitResults, client_core: nym_client_core::init::InitResults,
socks5_listening_port: String, socks5_listening_port: String,
client_address: String,
} }
impl InitResults { impl InitResults {
fn new(config: &Config, address: &Recipient) -> Self { fn new(config: &Config, address: &Recipient) -> Self {
Self { Self {
client_core: client_core::init::InitResults::new(config.get_base(), address), client_core: nym_client_core::init::InitResults::new(config.get_base(), address),
socks5_listening_port: config.get_listening_port().to_string(), socks5_listening_port: config.get_socks5().get_listening_port().to_string(),
client_address: address.to_string(),
} }
} }
} }
@@ -113,12 +116,13 @@ impl InitResults {
impl Display for InitResults { impl Display for InitResults {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
writeln!(f, "{}", self.client_core)?; writeln!(f, "{}", self.client_core)?;
write!(f, "SOCKS5 listening port: {}", self.socks5_listening_port) writeln!(f, "SOCKS5 listening port: {}", self.socks5_listening_port)?;
write!(f, "Address of this client: {}", self.client_address)
} }
} }
pub(crate) async fn execute(args: &Init) -> Result<(), Socks5ClientError> { pub(crate) async fn execute(args: &Init) -> Result<(), Socks5ClientError> {
println!("Initialising client..."); eprintln!("Initialising client...");
let id = &args.id; let id = &args.id;
let provider_address = &args.provider; let provider_address = &args.provider;
@@ -128,14 +132,14 @@ pub(crate) async fn execute(args: &Init) -> Result<(), Socks5ClientError> {
// in case we're using old config, try to upgrade it // in case we're using old config, try to upgrade it
// (if we're using the current version, it's a no-op) // (if we're using the current version, it's a no-op)
try_upgrade_v1_1_13_config(id)?; try_upgrade_v1_1_13_config(id)?;
println!("SOCKS5 client \"{id}\" was already initialised before"); eprintln!("SOCKS5 client \"{id}\" was already initialised before");
} }
// Usually you only register with the gateway on the first init, however you can force // Usually you only register with the gateway on the first init, however you can force
// re-registering if wanted. // re-registering if wanted.
let user_wants_force_register = args.force_register_gateway; let user_wants_force_register = args.force_register_gateway;
if user_wants_force_register { if user_wants_force_register {
println!("Instructed to force registering gateway. This might overwrite keys!"); eprintln!("Instructed to force registering gateway. This might overwrite keys!");
} }
// If the client was already initialized, don't generate new keys and don't re-register with // If the client was already initialized, don't generate new keys and don't re-register with
@@ -154,7 +158,7 @@ pub(crate) async fn execute(args: &Init) -> Result<(), Socks5ClientError> {
// Setup gateway by either registering a new one, or creating a new config from the selected // Setup gateway by either registering a new one, or creating a new config from the selected
// one but with keys kept, or reusing the gateway configuration. // one but with keys kept, or reusing the gateway configuration.
let gateway = client_core::init::setup_gateway_from_config::<Config, _>( let gateway = nym_client_core::init::setup_gateway_from_config::<Config, _, PersistentStorage>(
register_gateway, register_gateway,
user_chosen_gateway_id, user_chosen_gateway_id,
config.get_base(), config.get_base(),
@@ -173,28 +177,22 @@ pub(crate) async fn execute(args: &Init) -> Result<(), Socks5ClientError> {
print_saved_config(&config); print_saved_config(&config);
let address = client_core::init::get_client_address_from_stored_keys(config.get_base())?; let address = nym_client_core::init::get_client_address_from_stored_keys(config.get_base())?;
let init_results = InitResults::new(&config, &address); let init_results = InitResults::new(&config, &address);
println!("{}", init_results); println!("{}", args.output.format(&init_results));
// Output summary to a json file, if specified
if args.output_json {
client_core::init::output_to_json(&init_results, "socks5_client_init_results.json");
}
println!("\nThe address of this client is: {}\n", address);
Ok(()) Ok(())
} }
fn print_saved_config(config: &Config) { fn print_saved_config(config: &Config) {
let config_save_location = config.get_config_file_save_location(); let config_save_location = config.get_config_file_save_location();
println!("Saved configuration file to {:?}", config_save_location); eprintln!("Saved configuration file to {:?}", config_save_location);
println!("Using gateway: {}", config.get_base().get_gateway_id()); eprintln!("Using gateway: {}", config.get_base().get_gateway_id());
log::debug!("Gateway id: {}", config.get_base().get_gateway_id()); log::debug!("Gateway id: {}", config.get_base().get_gateway_id());
log::debug!("Gateway owner: {}", config.get_base().get_gateway_owner()); log::debug!("Gateway owner: {}", config.get_base().get_gateway_owner());
log::debug!( log::debug!(
"Gateway listener: {}", "Gateway listener: {}",
config.get_base().get_gateway_listener() config.get_base().get_gateway_listener()
); );
println!("Client configuration completed.\n"); eprintln!("Client configuration completed.\n");
} }
+2 -2
View File
@@ -1,8 +1,6 @@
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net> // Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use crate::client::config::old_config_v1_1_13::OldConfigV1_1_13;
use crate::client::config::{BaseConfig, Config};
use clap::CommandFactory; use clap::CommandFactory;
use clap::{Parser, Subcommand}; use clap::{Parser, Subcommand};
use lazy_static::lazy_static; use lazy_static::lazy_static;
@@ -10,6 +8,8 @@ use log::info;
use nym_bin_common::build_information::BinaryBuildInformation; use nym_bin_common::build_information::BinaryBuildInformation;
use nym_bin_common::completions::{fig_generate, ArgShell}; use nym_bin_common::completions::{fig_generate, ArgShell};
use nym_config::{NymConfig, OptionalSet}; use nym_config::{NymConfig, OptionalSet};
use nym_socks5_client_core::config::old_config_v1_1_13::OldConfigV1_1_13;
use nym_socks5_client_core::config::{BaseConfig, Config};
use std::error::Error; use std::error::Error;
pub mod init; pub mod init;
+5 -1
View File
@@ -3,7 +3,6 @@
use crate::commands::try_upgrade_v1_1_13_config; use crate::commands::try_upgrade_v1_1_13_config;
use crate::{ use crate::{
client::{config::Config, NymClient},
commands::{override_config, OverrideConfig}, commands::{override_config, OverrideConfig},
error::Socks5ClientError, error::Socks5ClientError,
}; };
@@ -12,6 +11,7 @@ use log::*;
use nym_bin_common::version_checker::is_minor_version_compatible; use nym_bin_common::version_checker::is_minor_version_compatible;
use nym_config::NymConfig; use nym_config::NymConfig;
use nym_crypto::asymmetric::identity; use nym_crypto::asymmetric::identity;
use nym_socks5_client_core::{config::Config, NymClient};
use nym_sphinx::addressing::clients::Recipient; use nym_sphinx::addressing::clients::Recipient;
#[derive(Args, Clone)] #[derive(Args, Clone)]
@@ -122,6 +122,10 @@ pub(crate) async fn execute(args: &Run) -> Result<(), Box<dyn std::error::Error
} }
}; };
if !config.validate() {
return Err(Box::new(Socks5ClientError::ConfigValidationFailure));
}
let override_config_fields = OverrideConfig::from(args.clone()); let override_config_fields = OverrideConfig::from(args.clone());
config = override_config(config, override_config_fields); config = override_config(config, override_config_fields);
+1 -2
View File
@@ -1,10 +1,9 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net> // Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use crate::client::config::{Config, MISSING_VALUE};
use nym_bin_common::version_checker::Version; use nym_bin_common::version_checker::Version;
use nym_config::NymConfig; use nym_config::NymConfig;
use nym_socks5_client_core::config::{Config, MISSING_VALUE};
use clap::Args; use clap::Args;
use std::{fmt::Display, process}; use std::{fmt::Display, process};
+7 -23
View File
@@ -1,39 +1,23 @@
use crate::socks::types::SocksProxyError; use nym_client_core::error::ClientCoreError;
use client_core::error::ClientCoreError;
use nym_socks5_requests::{ConnectionError, ConnectionId};
#[derive(thiserror::Error, Debug)] #[derive(thiserror::Error, Debug)]
pub enum Socks5ClientError { pub enum Socks5ClientError {
#[error("I/O error: {0}")] #[error("I/O error: {0}")]
IoError(#[from] std::io::Error), IoError(#[from] std::io::Error),
#[error("client-core error: {0}")]
ClientCoreError(#[from] ClientCoreError),
#[error("SOCKS proxy error")]
SocksProxyError(SocksProxyError),
#[error("Failed to load config for: {0}")] #[error("Failed to load config for: {0}")]
FailedToLoadConfig(String), FailedToLoadConfig(String),
// TODO: add more details here
#[error("Failed to validate the loaded config")]
ConfigValidationFailure,
#[error("Failed local version check, client and config mismatch")] #[error("Failed local version check, client and config mismatch")]
FailedLocalVersionCheck, FailedLocalVersionCheck,
#[error("Fail to bind address")] #[error("Fail to bind address")]
FailToBindAddress, FailToBindAddress,
#[error("Network requester: connection id {connection_id}: {error}")] #[error("client-core error: {0}")]
NetworkRequesterError { ClientCoreError(#[from] ClientCoreError),
connection_id: ConnectionId,
error: String,
},
}
impl From<ConnectionError> for Socks5ClientError {
fn from(value: ConnectionError) -> Self {
Socks5ClientError::NetworkRequesterError {
connection_id: value.connection_id,
error: value.network_requester_error,
}
}
} }
-6
View File
@@ -1,6 +0,0 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
pub mod client;
pub mod error;
pub mod socks;
+2 -4
View File
@@ -4,18 +4,16 @@
use std::error::Error; use std::error::Error;
use clap::{crate_name, crate_version, Parser}; use clap::{crate_name, crate_version, Parser};
use nym_bin_common::logging::{banner, setup_logging}; use nym_bin_common::logging::{maybe_print_banner, setup_logging};
use nym_network_defaults::setup_env; use nym_network_defaults::setup_env;
pub mod client;
mod commands; mod commands;
pub mod error; pub mod error;
pub mod socks;
#[tokio::main] #[tokio::main]
async fn main() -> Result<(), Box<dyn Error + Send + Sync>> { async fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
setup_logging(); setup_logging();
println!("{}", banner(crate_name!(), crate_version!())); maybe_print_banner(crate_name!(), crate_version!());
let args = commands::Cli::parse(); let args = commands::Cli::parse();
setup_env(args.config_env_file.as_ref()); setup_env(args.config_env_file.as_ref());
+1 -1
View File
@@ -48,7 +48,7 @@
"eslint-plugin-mocha": "^10.0.3", "eslint-plugin-mocha": "^10.0.3",
"eslint-plugin-prettier": "^4.0.0", "eslint-plugin-prettier": "^4.0.0",
"mocha": "^10.0.0", "mocha": "^10.0.0",
"prettier": "^2.5.1", "prettier": "^2.8.7",
"ts-mocha": "^10.0.0", "ts-mocha": "^10.0.0",
"typedoc": "^0.22.13", "typedoc": "^0.22.13",
"typescript": "^4.6.2", "typescript": "^4.6.2",
+111 -7
View File
@@ -22,6 +22,7 @@ import {
MixNodeDetails, MixNodeDetails,
MixNodeRewarding, MixNodeRewarding,
MixOwnershipResponse, MixOwnershipResponse,
OriginalVestingResponse,
PagedAllDelegationsResponse, PagedAllDelegationsResponse,
PagedDelegatorDelegationsResponse, PagedDelegatorDelegationsResponse,
PagedGatewayResponse, PagedGatewayResponse,
@@ -32,10 +33,12 @@ import {
RewardingParams, RewardingParams,
StakeSaturationResponse, StakeSaturationResponse,
UnbondedMixnodeResponse, UnbondedMixnodeResponse,
VestingAccountInfo,
ContractState, VestingAccountsCoinPaged, VestingAccountsPaged, DelegationTimes, Delegations, Period, VestingAccountNode, DelegationBlock
} from '@nymproject/types'; } from '@nymproject/types';
import QueryClient from './query-client'; import QueryClient from './query-client';
import SigningClient, { ISigningClient } from './signing-client'; import SigningClient, { ISigningClient } from './signing-client';
import { ContractState } from './types/shared'; // import { DelegationBlock } from './types/shared';
export interface INymClient { export interface INymClient {
readonly mixnetContract: string; readonly mixnetContract: string;
@@ -204,7 +207,7 @@ export default class ValidatorClient implements INymClient {
let mixNodes: UnbondedMixnodeResponse[] = []; let mixNodes: UnbondedMixnodeResponse[] = [];
const limit = 50; const limit = 50;
let startAfter; let startAfter;
for (;;) { for (; ;) {
// eslint-disable-next-line no-await-in-loop // eslint-disable-next-line no-await-in-loop
const pagedResponse: PagedUnbondedMixnodesResponse = await this.client.getUnbondedMixNodes( const pagedResponse: PagedUnbondedMixnodesResponse = await this.client.getUnbondedMixNodes(
this.mixnetContract, this.mixnetContract,
@@ -227,7 +230,7 @@ export default class ValidatorClient implements INymClient {
let mixNodes: MixNodeBond[] = []; let mixNodes: MixNodeBond[] = [];
const limit = 50; const limit = 50;
let startAfter; let startAfter;
for (;;) { for (; ;) {
// eslint-disable-next-line no-await-in-loop // eslint-disable-next-line no-await-in-loop
const pagedResponse: PagedMixNodeBondResponse = await this.client.getMixNodeBonds( const pagedResponse: PagedMixNodeBondResponse = await this.client.getMixNodeBonds(
this.mixnetContract, this.mixnetContract,
@@ -249,7 +252,7 @@ export default class ValidatorClient implements INymClient {
let mixNodes: MixNodeDetails[] = []; let mixNodes: MixNodeDetails[] = [];
const limit = 50; const limit = 50;
let startAfter; let startAfter;
for (;;) { for (; ;) {
// eslint-disable-next-line no-await-in-loop // eslint-disable-next-line no-await-in-loop
const pagedResponse: PagedMixNodeDetailsResponse = await this.client.getMixNodesDetailed( const pagedResponse: PagedMixNodeDetailsResponse = await this.client.getMixNodesDetailed(
this.mixnetContract, this.mixnetContract,
@@ -281,7 +284,7 @@ export default class ValidatorClient implements INymClient {
let delegations: Delegation[] = []; let delegations: Delegation[] = [];
const limit = 250; const limit = 250;
let startAfter; let startAfter;
for (;;) { for (; ;) {
// eslint-disable-next-line no-await-in-loop // eslint-disable-next-line no-await-in-loop
const pagedResponse: PagedMixDelegationsResponse = await this.client.getMixNodeDelegationsPaged( const pagedResponse: PagedMixDelegationsResponse = await this.client.getMixNodeDelegationsPaged(
this.mixnetContract, this.mixnetContract,
@@ -304,7 +307,7 @@ export default class ValidatorClient implements INymClient {
let delegations: Delegation[] = []; let delegations: Delegation[] = [];
const limit = 250; const limit = 250;
let startAfter; let startAfter;
for (;;) { for (; ;) {
// eslint-disable-next-line no-await-in-loop // eslint-disable-next-line no-await-in-loop
const pagedResponse: PagedDelegatorDelegationsResponse = await this.client.getDelegatorDelegationsPaged( const pagedResponse: PagedDelegatorDelegationsResponse = await this.client.getDelegatorDelegationsPaged(
this.mixnetContract, this.mixnetContract,
@@ -327,7 +330,7 @@ export default class ValidatorClient implements INymClient {
let delegations: Delegation[] = []; let delegations: Delegation[] = [];
const limit = 250; const limit = 250;
let startAfter; let startAfter;
for (;;) { for (; ;) {
// eslint-disable-next-line no-await-in-loop // eslint-disable-next-line no-await-in-loop
const pagedResponse: PagedAllDelegationsResponse = await this.client.getAllDelegationsPaged( const pagedResponse: PagedAllDelegationsResponse = await this.client.getAllDelegationsPaged(
this.mixnetContract, this.mixnetContract,
@@ -514,4 +517,105 @@ export default class ValidatorClient implements INymClient {
this.assertSigning(); this.assertSigning();
return (this.client as ISigningClient).updateContractStateParams(this.mixnetContract, newParams, fee, memo); return (this.client as ISigningClient).updateContractStateParams(this.mixnetContract, newParams, fee, memo);
} }
// VESTING
// TODO - MOVE TO A DIFFERENT FILE
public async getVestingAccountsPaged(): Promise<VestingAccountsPaged> {
return this.client.getVestingAccountsPaged(this.vestingContract);
}
public async getVestingAmountsAccountsPaged(): Promise<VestingAccountsCoinPaged> {
return this.client.getVestingAmountsAccountsPaged(this.vestingContract);
}
public async getLockedTokens(vestingAccountAddress: string): Promise<Coin> {
return this.client.getLockedTokens(this.vestingContract, vestingAccountAddress);
}
public async getSpendableTokens(vestingAccountAddress: string): Promise<Coin> {
return this.client.getSpendableTokens(this.vestingContract, vestingAccountAddress);
}
public async getVestedTokens(vestingAccountAddress: string): Promise<Coin> {
return this.client.getVestedTokens(this.vestingContract, vestingAccountAddress);
}
public async getVestingTokens(vestingAccountAddress: string): Promise<Coin> {
return this.client.getVestingTokens(this.vestingContract, vestingAccountAddress);
}
public async getSpendableVestedTokens(vestingAccountAddress: string): Promise<Coin> {
return this.client.getSpendableVestedTokens(this.vestingContract, vestingAccountAddress);
}
public async getSpendableRewards(vestingAccountAddress: string): Promise<Coin> {
return this.client.getSpendableRewards(this.vestingContract, vestingAccountAddress);
}
public async getDelegatedCoins(vestingAccountAddress: string): Promise<Coin> {
return this.client.getDelegatedCoins(this.vestingContract, vestingAccountAddress);
}
public async getPledgedCoins(vestingAccountAddress: string): Promise<Coin> {
return this.client.getPledgedCoins(this.vestingContract, vestingAccountAddress);
}
public async getStakedCoins(vestingAccountAddress: string): Promise<Coin> {
return this.client.getStakedCoins(this.vestingContract, vestingAccountAddress);
}
public async getWithdrawnCoins(vestingAccountAddress: string): Promise<Coin> {
return this.client.getWithdrawnCoins(this.vestingContract, vestingAccountAddress);
}
public async getStartTime(vestingAccountAddress: string): Promise<string> {
return this.client.getStartTime(this.vestingContract, vestingAccountAddress);
}
public async getEndTime(vestingAccountAddress: string): Promise<string> {
return this.client.getEndTime(this.vestingContract, vestingAccountAddress);
}
public async getOriginalVestingDetails(vestingAccountAddress: string): Promise<OriginalVestingResponse> {
return this.client.getOriginalVestingDetails(this.vestingContract, vestingAccountAddress);
}
public async getHistoricStakingRewards(vestingAccountAddress: string): Promise<Coin> {
return this.client.getHistoricStakingRewards(this.vestingContract, vestingAccountAddress);
}
public async getAccountDetails(address: string): Promise<VestingAccountInfo> {
return this.client.getAccountDetails(this.vestingContract, address);
}
public async getMixnode(address: string): Promise<VestingAccountNode> {
return this.client.getMixnode(this.vestingContract, address);
}
public async getGateway(address: string): Promise<VestingAccountNode> {
return this.client.getGateway(this.vestingContract, address);
}
public async getDelegationTimes(mix_id: number, delegatorAddress: string): Promise<DelegationTimes> {
return this.client.getDelegationTimes(this.vestingContract, mix_id, delegatorAddress);
}
public async getAllDelegations(): Promise<Delegations> {
return this.client.getAllDelegations(this.vestingContract);
}
public async getDelegation(address: string, mix_id: number): Promise<DelegationBlock> {
return this.client.getDelegation(this.vestingContract, address, mix_id );
}
public async getTotalDelegationAmount(address: string, mix_id: number, block_timestamp_sec: number): Promise<Coin> {
return this.client.getTotalDelegationAmount(this.vestingContract, address, mix_id, block_timestamp_sec);
}
public async getCurrentVestingPeriod(address: string): Promise<Period> {
return this.client.getCurrentVestingPeriod(this.vestingContract, address);
}
} }
+148 -2
View File
@@ -4,8 +4,8 @@
*/ */
// eslint-disable-next-line import/no-cycle // eslint-disable-next-line import/no-cycle
import { INyxdQuery } from './query-client'; import { INyxdQuery } from './query-client';
import { Delegation, RewardingParams, StakeSaturationResponse } from '@nymproject/types';
import { import {
Delegation, OriginalVestingResponse, RewardingParams, StakeSaturationResponse, VestingAccountInfo,
UnbondedMixnodeResponse, UnbondedMixnodeResponse,
GatewayOwnershipResponse, GatewayOwnershipResponse,
MixnetContractVersion, MixnetContractVersion,
@@ -18,8 +18,10 @@ import {
PagedMixNodeDetailsResponse, PagedMixNodeDetailsResponse,
PagedUnbondedMixnodesResponse, PagedUnbondedMixnodesResponse,
LayerDistribution, LayerDistribution,
ContractState, VestingAccountsCoinPaged, VestingAccountsPaged, DelegationTimes, Delegations, Period, VestingAccountNode, DelegationBlock
} from '@nymproject/types'; } from '@nymproject/types';
import { ContractState, SmartContractQuery } from './types/shared'; import { SmartContractQuery } from './types/shared';
import { Coin } from 'cosmjs-types/cosmos/base/v1beta1/coin';
export default class NyxdQuerier implements INyxdQuery { export default class NyxdQuerier implements INyxdQuery {
client: SmartContractQuery; client: SmartContractQuery;
@@ -188,4 +190,148 @@ export default class NyxdQuerier implements INyxdQuery {
vesting_account_address: vestingAccountAddress, vesting_account_address: vestingAccountAddress,
}); });
} }
getVestingAccountsPaged(vestingContractAddress: string): Promise<VestingAccountsPaged> {
return this.client.queryContractSmart(vestingContractAddress, {
get_accounts_paged: {}
});
}
getVestingAmountsAccountsPaged(vestingContractAddress: string): Promise<VestingAccountsCoinPaged> {
return this.client.queryContractSmart(vestingContractAddress, {
get_accounts_vesting_coins_paged: {}
});
}
getLockedTokens(vestingContractAddress: string, vestingAccountAddress: string): Promise<Coin> {
return this.client.queryContractSmart(vestingContractAddress, {
locked_coins: { vesting_account_address: vestingAccountAddress }
});
}
getSpendableTokens(vestingContractAddress: string, vestingAccountAddress: string): Promise<Coin> {
return this.client.queryContractSmart(vestingContractAddress, {
spendable_coins: { vesting_account_address: vestingAccountAddress }
});
}
getVestedTokens(vestingContractAddress: string, vestingAccountAddress: string): Promise<Coin> {
return this.client.queryContractSmart(vestingContractAddress, {
get_vested_coins: { vesting_account_address: vestingAccountAddress }
});
}
getVestingTokens(vestingContractAddress: string, vestingAccountAddress: string): Promise<Coin> {
return this.client.queryContractSmart(vestingContractAddress, {
get_vesting_coins: { vesting_account_address: vestingAccountAddress }
});
}
getSpendableVestedTokens(vestingContractAddress: string, vestingAccountAddress: string): Promise<Coin> {
return this.client.queryContractSmart(vestingContractAddress, {
get_spendable_vested_coins: { vesting_account_address: vestingAccountAddress }
});
}
getSpendableRewards(vestingContractAddress: string, vestingAccountAddress: string): Promise<Coin> {
return this.client.queryContractSmart(vestingContractAddress, {
get_spendable_reward_coins: { vesting_account_address: vestingAccountAddress }
});
}
getDelegatedCoins(vestingContractAddress: string, vestingAccountAddress: string): Promise<Coin> {
return this.client.queryContractSmart(vestingContractAddress, {
get_delegated_coins: { vesting_account_address: vestingAccountAddress }
});
}
getPledgedCoins(vestingContractAddress: string, vestingAccountAddress: string): Promise<Coin> {
return this.client.queryContractSmart(vestingContractAddress, {
get_pledged_coins: { vesting_account_address: vestingAccountAddress }
});
}
getStakedCoins(vestingContractAddress: string, vestingAccountAddress: string): Promise<Coin> {
return this.client.queryContractSmart(vestingContractAddress, {
get_staked_coins: { vesting_account_address: vestingAccountAddress }
});
}
getWithdrawnCoins(vestingContractAddress: string, vestingAccountAddress: string): Promise<Coin> {
return this.client.queryContractSmart(vestingContractAddress, {
get_withdrawn_coins: { vesting_account_address: vestingAccountAddress }
});
}
getStartTime(vestingContractAddress: string, vestingAccountAddress: string): Promise<string> {
return this.client.queryContractSmart(vestingContractAddress, {
get_start_time: { vesting_account_address: vestingAccountAddress }
});
}
getEndTime(vestingContractAddress: string, vestingAccountAddress: string): Promise<string> {
return this.client.queryContractSmart(vestingContractAddress, {
get_end_time: { vesting_account_address: vestingAccountAddress }
});
}
getOriginalVestingDetails(vestingContractAddress: string, vestingAccountAddress: string): Promise<OriginalVestingResponse> {
return this.client.queryContractSmart(vestingContractAddress, {
get_original_vesting: { vesting_account_address: vestingAccountAddress }
});
}
getHistoricStakingRewards(vestingContractAddress: string, vestingAccountAddress: string): Promise<Coin> {
return this.client.queryContractSmart(vestingContractAddress, {
get_historical_vesting_staking_reward: { vesting_account_address: vestingAccountAddress }
});
}
getAccountDetails(vestingContractAddress: string, address: string): Promise<VestingAccountInfo> {
return this.client.queryContractSmart(vestingContractAddress, {
get_account: { address: address }
});
}
getMixnode(vestingContractAddress: string, address: string): Promise<VestingAccountNode> {
return this.client.queryContractSmart(vestingContractAddress, {
get_mixnode: { address: address }
});
}
getGateway(vestingContractAddress: string, address: string): Promise<VestingAccountNode> {
return this.client.queryContractSmart(vestingContractAddress, {
get_gateway: { address: address }
});
}
getDelegationTimes(vestingContractAddress: string, mix_id: number, address: string): Promise<DelegationTimes> {
return this.client.queryContractSmart(vestingContractAddress, {
get_delegation_times: { mix_id: mix_id, address: address }
});
}
getAllDelegations(vestingContractAddress: string): Promise<Delegations> {
return this.client.queryContractSmart(vestingContractAddress, {
get_all_delegations: {}
});
}
getDelegation(vestingContractAddress: string, address: string, mix_id: number): Promise<DelegationBlock> {
return this.client.queryContractSmart(vestingContractAddress, {
get_all_delegations: {address: address, mix_id: mix_id}
});
}
getTotalDelegationAmount(vestingContractAddress: string, address: string, mix_id: number, block_timestamp_sec: number): Promise<Coin> {
return this.client.queryContractSmart(vestingContractAddress, {
get_all_delegations: {address: address, mix_id: mix_id, block_timestamp_sec: block_timestamp_sec}
});
}
getCurrentVestingPeriod(vestingContractAddress: string, address: string): Promise<Period> {
return this.client.queryContractSmart(vestingContractAddress, {
get_current_vesting_period: { address: address }
});
}
} }
+102 -2
View File
@@ -20,11 +20,15 @@ import {
UnbondedMixnodeResponse, UnbondedMixnodeResponse,
MixNodeBond, MixNodeBond,
MixNodeRewarding, MixNodeRewarding,
OriginalVestingResponse,
VestingAccountInfo,
ContractState, VestingAccountsCoinPaged, VestingAccountsPaged, DelegationTimes, Delegations, Period, VestingAccountNode, DelegationBlock
} from '@nymproject/types'; } from '@nymproject/types';
import NymApiQuerier, { INymApiQuery } from './nym-api-querier'; import NymApiQuerier, { INymApiQuery } from './nym-api-querier';
import { ContractState, ICosmWasmQuery } from './types/shared'; import { ICosmWasmQuery } from './types/shared';
import { RewardingParams } from '@nymproject/types'; import { RewardingParams } from '@nymproject/types';
import { Tendermint34Client } from '@cosmjs/tendermint-rpc'; import { Tendermint34Client } from '@cosmjs/tendermint-rpc';
import { Coin } from 'cosmjs-types/cosmos/base/v1beta1/coin';
export interface INyxdQuery { export interface INyxdQuery {
// nym-specific implemented inside NymQuerier // nym-specific implemented inside NymQuerier
@@ -68,7 +72,7 @@ export interface INyxdQuery {
getMixnodeRewardingDetails(mixnetContractAddress: string, mixId: number): Promise<MixNodeRewarding>; getMixnodeRewardingDetails(mixnetContractAddress: string, mixId: number): Promise<MixNodeRewarding>;
} }
export interface IQueryClient extends ICosmWasmQuery, INyxdQuery, INymApiQuery {} export interface IQueryClient extends ICosmWasmQuery, INyxdQuery, INymApiQuery { }
export default class QueryClient extends CosmWasmClient implements IQueryClient { export default class QueryClient extends CosmWasmClient implements IQueryClient {
private nyxdQuerier: NyxdQuerier; private nyxdQuerier: NyxdQuerier;
@@ -199,4 +203,100 @@ export default class QueryClient extends CosmWasmClient implements IQueryClient
getSpendableCoins(vestingContractAddress: string, vestingAccountAddress: string): Promise<any> { getSpendableCoins(vestingContractAddress: string, vestingAccountAddress: string): Promise<any> {
return this.nyxdQuerier.getSpendableCoins(vestingContractAddress, vestingAccountAddress); return this.nyxdQuerier.getSpendableCoins(vestingContractAddress, vestingAccountAddress);
} }
getVestingAccountsPaged(vestingContractAddress: string): Promise<VestingAccountsPaged> {
return this.nyxdQuerier.getVestingAccountsPaged(vestingContractAddress);
}
getVestingAmountsAccountsPaged(vestingContractAddress: string): Promise<VestingAccountsCoinPaged> {
return this.nyxdQuerier.getVestingAmountsAccountsPaged(vestingContractAddress);
}
getLockedTokens(vestingContractAddress: string, vestingAccountAddress: string): Promise<Coin> {
return this.nyxdQuerier.getLockedTokens(vestingContractAddress, vestingAccountAddress);
}
getSpendableTokens(vestingContractAddress: string, vestingAccountAddress: string): Promise<Coin> {
return this.nyxdQuerier.getSpendableTokens(vestingContractAddress, vestingAccountAddress);
}
getVestedTokens(vestingContractAddress: string, vestingAccountAddress: string): Promise<Coin> {
return this.nyxdQuerier.getVestedTokens(vestingContractAddress, vestingAccountAddress);
}
getVestingTokens(vestingContractAddress: string, vestingAccountAddress: string): Promise<Coin> {
return this.nyxdQuerier.getVestingTokens(vestingContractAddress, vestingAccountAddress);
}
getSpendableVestedTokens(vestingContractAddress: string, vestingAccountAddress: string): Promise<Coin> {
return this.nyxdQuerier.getSpendableVestedTokens(vestingContractAddress, vestingAccountAddress);
}
getSpendableRewards(vestingContractAddress: string, vestingAccountAddress: string): Promise<Coin> {
return this.nyxdQuerier.getSpendableRewards(vestingContractAddress, vestingAccountAddress);
}
getDelegatedCoins(vestingContractAddress: string, vestingAccountAddress: string): Promise<Coin> {
return this.nyxdQuerier.getDelegatedCoins(vestingContractAddress, vestingAccountAddress);
}
getPledgedCoins(vestingContractAddress: string, vestingAccountAddress: string): Promise<Coin> {
return this.nyxdQuerier.getPledgedCoins(vestingContractAddress, vestingAccountAddress);
}
getStakedCoins(vestingContractAddress: string, vestingAccountAddress: string): Promise<Coin> {
return this.nyxdQuerier.getStakedCoins(vestingContractAddress, vestingAccountAddress);
}
getWithdrawnCoins(vestingContractAddress: string, vestingAccountAddress: string): Promise<Coin> {
return this.nyxdQuerier.getWithdrawnCoins(vestingContractAddress, vestingAccountAddress);
}
getStartTime(vestingContractAddress: string, vestingAccountAddress: string): Promise<string> {
return this.nyxdQuerier.getStartTime(vestingContractAddress, vestingAccountAddress);
}
getEndTime(vestingContractAddress: string, vestingAccountAddress: string): Promise<string> {
return this.nyxdQuerier.getEndTime(vestingContractAddress, vestingAccountAddress);
}
getOriginalVestingDetails(vestingContractAddress: string, vestingAccountAddress: string): Promise<OriginalVestingResponse> {
return this.nyxdQuerier.getOriginalVestingDetails(vestingContractAddress, vestingAccountAddress);
}
getHistoricStakingRewards(vestingContractAddress: string, vestingAccountAddress: string): Promise<Coin> {
return this.nyxdQuerier.getHistoricStakingRewards(vestingContractAddress, vestingAccountAddress);
}
getAccountDetails(vestingContractAddress: string, address: string): Promise<VestingAccountInfo> {
return this.nyxdQuerier.getAccountDetails(vestingContractAddress, address);
}
getMixnode(vestingContractAddress: string, address: string): Promise<VestingAccountNode> {
return this.nyxdQuerier.getMixnode(vestingContractAddress, address);
}
getGateway(vestingContractAddress: string, address: string): Promise<VestingAccountNode> {
return this.nyxdQuerier.getGateway(vestingContractAddress, address);
}
getDelegationTimes(vestingContractAddress: string, mix_id: number, delegatorAddress: string): Promise<DelegationTimes> {
return this.nyxdQuerier.getDelegationTimes(vestingContractAddress, mix_id, delegatorAddress);
}
getAllDelegations(vestingContractAddress: string): Promise<Delegations> {
return this.nyxdQuerier.getAllDelegations(vestingContractAddress);
}
getDelegation(vestingContractAddress: string, vestingAccountAddress: string, mix_id: number): Promise<DelegationBlock> {
return this.nyxdQuerier.getDelegation(vestingContractAddress, vestingAccountAddress, mix_id);
}
getTotalDelegationAmount(vestingContractAddress: string, vestingAccountAddress: string, mix_id: number, block_timestamp_sec: number): Promise<Coin> {
return this.nyxdQuerier.getTotalDelegationAmount(vestingContractAddress, vestingAccountAddress, mix_id, block_timestamp_sec);
}
getCurrentVestingPeriod(vestingContractAddress: string, address: string): Promise<Period> {
return this.nyxdQuerier.getCurrentVestingPeriod(vestingContractAddress, address);
}
} }
+102 -2
View File
@@ -29,6 +29,7 @@ import {
MixNodeDetails, MixNodeDetails,
MixNodeRewarding, MixNodeRewarding,
MixOwnershipResponse, MixOwnershipResponse,
OriginalVestingResponse,
PagedAllDelegationsResponse, PagedAllDelegationsResponse,
PagedDelegatorDelegationsResponse, PagedDelegatorDelegationsResponse,
PagedGatewayResponse, PagedGatewayResponse,
@@ -38,9 +39,10 @@ import {
PagedUnbondedMixnodesResponse, PagedUnbondedMixnodesResponse,
RewardingParams, RewardingParams,
UnbondedMixnodeResponse, UnbondedMixnodeResponse,
VestingAccountInfo,
ContractState, VestingAccountsCoinPaged, VestingAccountsPaged, DelegationTimes, Delegations, Period, VestingAccountNode, DelegationBlock
} from '@nymproject/types'; } from '@nymproject/types';
import NymApiQuerier from './nym-api-querier'; import NymApiQuerier from './nym-api-querier';
import { ContractState } from './types/shared';
// methods exposed by `SigningCosmWasmClient` // methods exposed by `SigningCosmWasmClient`
export interface ICosmWasmSigning { export interface ICosmWasmSigning {
@@ -243,7 +245,7 @@ export default class SigningClient extends SigningCosmWasmClient implements ISig
// query related: // query related:
getContractVersion(mixnetContractAddress: string): Promise<MixnetContractVersion> { getContractVersion(mixnetContractAddress: string): Promise<MixnetContractVersion> {
return this.getContractVersion(mixnetContractAddress); return this.nyxdQuerier.getContractVersion(mixnetContractAddress);
} }
getMixNodeBonds( getMixNodeBonds(
@@ -508,4 +510,102 @@ export default class SigningClient extends SigningCosmWasmClient implements ISig
memo, memo,
); );
} }
// vesting related
getVestingAccountsPaged(vestingContractAddress: string): Promise<VestingAccountsPaged> {
return this.nyxdQuerier.getVestingAccountsPaged(vestingContractAddress);
};
getVestingAmountsAccountsPaged(vestingContractAddress: string): Promise<VestingAccountsCoinPaged> {
return this.nyxdQuerier.getVestingAmountsAccountsPaged(vestingContractAddress);
}
getLockedTokens(vestingContractAddress: string, vestingAccountAddress: string): Promise<Coin> {
return this.nyxdQuerier.getLockedTokens(vestingContractAddress, vestingAccountAddress);
}
getSpendableTokens(vestingContractAddress: string, vestingAccountAddress: string): Promise<Coin> {
return this.nyxdQuerier.getSpendableTokens(vestingContractAddress, vestingAccountAddress);
}
getVestedTokens(vestingContractAddress: string, vestingAccountAddress: string): Promise<Coin> {
return this.nyxdQuerier.getVestedTokens(vestingContractAddress, vestingAccountAddress);
}
getVestingTokens(vestingContractAddress: string, vestingAccountAddress: string): Promise<Coin> {
return this.nyxdQuerier.getVestingTokens(vestingContractAddress, vestingAccountAddress);
}
getSpendableVestedTokens(vestingContractAddress: string, vestingAccountAddress: string): Promise<Coin> {
return this.nyxdQuerier.getSpendableVestedTokens(vestingContractAddress, vestingAccountAddress);
}
getSpendableRewards(vestingContractAddress: string, vestingAccountAddress: string): Promise<Coin> {
return this.nyxdQuerier.getSpendableRewards(vestingContractAddress, vestingAccountAddress);
}
getDelegatedCoins(vestingContractAddress: string, vestingAccountAddress: string): Promise<Coin> {
return this.nyxdQuerier.getDelegatedCoins(vestingContractAddress, vestingAccountAddress);
}
getPledgedCoins(vestingContractAddress: string, vestingAccountAddress: string): Promise<Coin> {
return this.nyxdQuerier.getPledgedCoins(vestingContractAddress, vestingAccountAddress);
}
getStakedCoins(vestingContractAddress: string, vestingAccountAddress: string): Promise<Coin> {
return this.nyxdQuerier.getStakedCoins(vestingContractAddress, vestingAccountAddress);
}
getWithdrawnCoins(vestingContractAddress: string, vestingAccountAddress: string): Promise<Coin> {
return this.nyxdQuerier.getWithdrawnCoins(vestingContractAddress, vestingAccountAddress);
}
getStartTime(vestingContractAddress: string, vestingAccountAddress: string): Promise<string> {
return this.nyxdQuerier.getStartTime(vestingContractAddress, vestingAccountAddress);
}
getEndTime(vestingContractAddress: string, vestingAccountAddress: string): Promise<string> {
return this.nyxdQuerier.getEndTime(vestingContractAddress, vestingAccountAddress);
}
getOriginalVestingDetails(vestingContractAddress: string, vestingAccountAddress: string): Promise<OriginalVestingResponse> {
return this.nyxdQuerier.getOriginalVestingDetails(vestingContractAddress, vestingAccountAddress);
}
getHistoricStakingRewards(vestingContractAddress: string, vestingAccountAddress: string): Promise<Coin> {
return this.nyxdQuerier.getHistoricStakingRewards(vestingContractAddress, vestingAccountAddress);
}
getAccountDetails(vestingContractAddress: string, address: string): Promise<VestingAccountInfo> {
return this.nyxdQuerier.getAccountDetails(vestingContractAddress, address);
}
getMixnode(vestingContractAddress: string, address: string): Promise<VestingAccountNode> {
return this.nyxdQuerier.getMixnode(vestingContractAddress, address);
}
getGateway(vestingContractAddress: string, address: string): Promise<VestingAccountNode> {
return this.nyxdQuerier.getGateway(vestingContractAddress, address);
}
getDelegationTimes(vestingContractAddress: string, mix_id: number, delegatorAddress: string): Promise<DelegationTimes> {
return this.nyxdQuerier.getDelegationTimes(vestingContractAddress, mix_id, delegatorAddress);
}
getAllDelegations(vestingContractAddress: string): Promise<Delegations> {
return this.nyxdQuerier.getAllDelegations(vestingContractAddress);
}
getDelegation(vestingContractAddress: string, vestingAccountAddress: string, mix_id: number): Promise<DelegationBlock> {
return this.nyxdQuerier.getDelegation(vestingContractAddress, vestingAccountAddress, mix_id);
}
getTotalDelegationAmount(vestingContractAddress: string, vestingAccountAddress: string, mix_id: number, block_timestamp_sec: number): Promise<Coin> {
return this.nyxdQuerier.getTotalDelegationAmount(vestingContractAddress, vestingAccountAddress, mix_id, block_timestamp_sec);
}
getCurrentVestingPeriod(vestingContractAddress: string, address: string): Promise<Period> {
return this.nyxdQuerier.getCurrentVestingPeriod(vestingContractAddress, address);
}
} }
@@ -1,8 +1,9 @@
import { Coin } from 'cosmjs-types/cosmos/base/v1beta1/coin';
import expect from 'expect'; import expect from 'expect';
export const amountDemon = { export const amountDemon = {
amount: expect.any(String), denom: expect.any(String),
denom: expect.any(String) amount: expect.any(String)
} }
export const delegation = { export const delegation = {
@@ -159,7 +160,6 @@ export const layerDistribution = {
layer3: expect.any(Number) layer3: expect.any(Number)
} }
export const intervalRewardParams = { export const intervalRewardParams = {
reward_pool: expect.any(Number), reward_pool: expect.any(Number),
staking_supply: expect.any(Number), staking_supply: expect.any(Number),
@@ -176,3 +176,79 @@ export const rewardingParams = {
rewarded_set_size: expect.any(Number), rewarded_set_size: expect.any(Number),
active_set_size: expect.any(Number) active_set_size: expect.any(Number)
} }
export const VestAccounts = [{
account_id: expect.any(String),
owner: expect.any(String)
}]
export const VestAccountCoin = [{
account_id: expect.any(String),
owner: expect.any(String),
still_vesting: Coin
}]
export const vestingAccountsPaged = {
accounts: VestAccounts,
start_next_after: expect.any(String)
}
export const VestingCoinAccounts = {
accounts: VestAccountCoin,
start_next_after: expect.any(String)
}
export const OriginalVestingDetails = {
amount: Coin,
number_of_periods: expect.any(Number),
period_duration: expect.any(Number)
}
export const PledgeCap = {
percent: expect.any(String) || null,
};
export const Periods = [{
period_seconds: expect.any(Number),
start_time: expect.any(Number),
}]
export const VestingAccountDetails = {
owner_address: expect.any(String),
staking_address: expect.any(String) || null,
start_time: expect.any(String),
periods: Periods,
coin: Coin,
storage_key: expect.any(Number),
pledge_cap: PledgeCap
}
export const Node = {
amount: Coin,
block_time: expect.any(String)
}
export type VestingPeriod = 'Before' | { In: number } | 'After';
export const DelegationTimestamps = [
expect.any(Number)
]
export const DelegatorTimes = {
owner: expect.any(String),
account_id: expect.any(Number),
mix_id: expect.any(Number),
delegation_timestamps: DelegationTimestamps
}
export const DelegationBlock = [{
account_id: expect.any(Number),
amount: expect.any(String),
block_timestamp: expect.any(Number),
mix_id: expect.any(Number)
}]
export const Delegations = {
delegations: DelegationBlock,
start_next_after: expect.any(String) || null
}
@@ -1,5 +1,6 @@
import expect from 'expect'; import expect from 'expect';
import ValidatorClient from '../../index'; import ValidatorClient from '../../index';
import { amountDemon, Delegations, DelegatorTimes, Node, OriginalVestingDetails, VestingAccountDetails, vestingAccountsPaged, VestingCoinAccounts, VestingPeriod } from '../expectedResponses';
const dotenv = require('dotenv'); const dotenv = require('dotenv');
@@ -19,10 +20,149 @@ describe('Vesting queries', () => {
); );
}); });
const vesting_account_address = 'n14juvj7llvx8eppypnqj6xlrgwss9wfrcuy0nkv';
const mixnodeowner = 'n1z93z44vf8ssvdhujjvxcj4rd5e3lz0l60wdk70';
const gatewayowner = 'n1un9cuvw9e3xqratmde4j55ucksev0dkeruq800';
const mix_id = 79;
it('can query for contract version', async () => { it('can query for contract version', async () => {
const contract = await client.getVestingContractVersion(); const contract = await client.getVestingContractVersion();
expect(contract).toBeTruthy(); expect(contract).toBeTruthy();
}); });
it('can get the balance on the account', () => {}); // TODO see if we can use AccountEntry type here instead
it('can get all accounts paged', async () => {
const accounts = await client.getVestingAccountsPaged();
expect(Object.keys(accounts)).toEqual(Object.keys(vestingAccountsPaged));
expect(accounts).toBeTruthy();
});
it('can get coins for all accounts paged', async () => {
const accounts = await client.getVestingAmountsAccountsPaged();
expect(Object.keys(accounts)).toEqual(Object.keys(VestingCoinAccounts));
expect(accounts).toBeTruthy();
});
it('can get locked tokens for an account', async () => {
const locked = await client.getLockedTokens(vesting_account_address);
expect(Object.keys(locked)).toEqual(Object.keys(amountDemon));
expect(locked).toBeTruthy();
});
it('can get spendable tokens for an account', async () => {
const spendable = await client.getSpendableTokens(vesting_account_address);
expect(Object.keys(spendable)).toEqual(Object.keys(amountDemon));
expect(spendable).toBeTruthy();
});
it('can get vested tokens for an account', async () => {
const vested = await client.getVestedTokens(vesting_account_address);
expect(Object.keys(vested)).toEqual(Object.keys(amountDemon));
expect(vested).toBeTruthy();
});
it('can get vesting tokens for an account', async () => {
const vesting = await client.getVestingTokens(vesting_account_address);
expect(Object.keys(vesting)).toEqual(Object.keys(amountDemon));
expect(vesting).toBeTruthy();
});
it('can get spendable vested tokens for an account', async () => {
const spendable = await client.getSpendableVestedTokens(vesting_account_address);
expect(Object.keys(spendable)).toEqual(Object.keys(amountDemon));
expect(spendable).toBeTruthy();
});
it('can get spendable rewards for an account', async () => {
const rewards = await client.getSpendableRewards(vesting_account_address);
expect(Object.keys(rewards)).toEqual(Object.keys(amountDemon));
expect(rewards).toBeTruthy();
});
it('can get delegated coins', async () => {
const delegated = await client.getDelegatedCoins(vesting_account_address);
expect(Object.keys(delegated)).toEqual(Object.keys(amountDemon));
expect(delegated).toBeTruthy();
});
it('can get pledged coins', async () => {
const pledged = await client.getPledgedCoins(vesting_account_address);
expect(Object.keys(pledged)).toEqual(Object.keys(amountDemon));
expect(pledged).toBeTruthy();
});
it('can get staked coins', async () => {
const staked = await client.getStakedCoins(vesting_account_address);
expect(Object.keys(staked)).toEqual(Object.keys(amountDemon));
expect(staked).toBeTruthy();
});
it('can get withdrawn coins', async () => {
const withdrawn = await client.getWithdrawnCoins(vesting_account_address);
expect(Object.keys(withdrawn)).toEqual(Object.keys(amountDemon));
expect(withdrawn).toBeTruthy();
});
it('can get start time of an account', async () => {
const time = await client.getStartTime(vesting_account_address);
expect(typeof time).toBe("string");
expect(time).toBeTruthy();
});
it('can get end time of an account', async () => {
const time = await client.getEndTime(vesting_account_address);
expect(typeof time).toBe("string");
expect(time).toBeTruthy();
});
it('can get account original vesting details', async () => {
const original = await client.getOriginalVestingDetails(vesting_account_address);
expect(Object.keys(original)).toEqual(Object.keys(OriginalVestingDetails));
expect(original).toBeTruthy();
});
it('can get historic vesting staking rewards', async () => {
const rewards = await client.getHistoricStakingRewards(vesting_account_address);
expect(Object.keys(rewards)).toEqual(Object.keys(amountDemon));
expect(rewards).toBeTruthy();
});
// TODO see if we can use "VestingAccountInfo" type here instead
it('can get account details', async () => {
const account = await client.getAccountDetails(vesting_account_address);
expect(Object.keys(account)).toEqual(Object.keys(VestingAccountDetails));
expect(account).toBeTruthy();
});
// TODO add option for if account has no mixnode and expected is null
it('can get mixnode', async () => {
const mixnode = await client.getMixnode(mixnodeowner);
expect(Object.keys(mixnode)).toEqual(Object.keys(Node));
expect(mixnode).toBeTruthy();
});
// TODO add option for if account has no gateway and expected is null
it.skip('can get gateway', async () => {
const gateway = await client.getGateway(gatewayowner);
expect(Object.keys(gateway)).toEqual(Object.keys(Node));
expect(gateway).toBeTruthy();
});
it('can get delegations times', async () => {
const delegation = await client.getDelegationTimes(mix_id, mixnodeowner);
expect(Object.keys(delegation)).toEqual(Object.keys(DelegatorTimes));
expect(delegation).toBeTruthy();
});
it('can get all delegations', async () => {
const delegation = await client.getAllDelegations();
expect(Object.keys(delegation)).toEqual(Object.keys(Delegations));
expect(delegation).toBeTruthy();
});
it('can get current vesting period', async () => {
const period = await client.getCurrentVestingPeriod(gatewayowner);
expect(period).toEqual(expect.anything() as unknown as VestingPeriod);
expect(period).toBeTruthy();
});
}); });
+4 -3
View File
@@ -30,13 +30,14 @@ wasm-bindgen = { version = "=0.2.83", features = ["serde-serialize"] }
wasm-bindgen-futures = "0.4" wasm-bindgen-futures = "0.4"
# internal # internal
client-core = { path = "../client-core", default-features = false, features = ["wasm"] } nym-client-core = { path = "../../common/client-core", default-features = false, features = ["wasm"] }
nym-bandwidth-controller = { path = "../../common/bandwidth-controller" }
nym-coconut-interface = { path = "../../common/coconut-interface" } nym-coconut-interface = { path = "../../common/coconut-interface" }
nym-credentials = { path = "../../common/credentials" } nym-credentials = { path = "../../common/credentials" }
nym-credential-storage = { path = "../../common/credential-storage" }
nym-crypto = { path = "../../common/crypto" } nym-crypto = { path = "../../common/crypto" }
nym-sphinx = { path = "../../common/nymsphinx" } nym-sphinx = { path = "../../common/nymsphinx" }
gateway-client = { path = "../../common/client-libs/gateway-client", default-features = false, features = ["wasm"] } nym-validator-client = { path = "../../common/client-libs/validator-client", default-features = false }
validator-client = { path = "../../common/client-libs/validator-client", default-features = false }
wasm-utils = { path = "../../common/wasm-utils" } wasm-utils = { path = "../../common/wasm-utils" }
nym-task = { path = "../../common/task" } nym-task = { path = "../../common/task" }
# The `console_error_panic_hook` crate provides better debugging of panics by # The `console_error_panic_hook` crate provides better debugging of panics by
+13 -5
View File
@@ -6,12 +6,13 @@
// another issue due to #[wasm_bindgen] and `Copy` trait // another issue due to #[wasm_bindgen] and `Copy` trait
#![allow(clippy::drop_copy)] #![allow(clippy::drop_copy)]
use client_core::config::{ use nym_client_core::config::{
Acknowledgements as ConfigAcknowledgements, CoverTraffic as ConfigCoverTraffic, Acknowledgements as ConfigAcknowledgements, CoverTraffic as ConfigCoverTraffic,
DebugConfig as ConfigDebug, ExtendedPacketSize, GatewayConnection as ConfigGatewayConnection, DebugConfig as ConfigDebug, GatewayConnection as ConfigGatewayConnection,
GatewayEndpointConfig, ReplySurbs as ConfigReplySurbs, Topology as ConfigTopology, GatewayEndpointConfig, ReplySurbs as ConfigReplySurbs, Topology as ConfigTopology,
Traffic as ConfigTraffic, Traffic as ConfigTraffic,
}; };
use nym_sphinx::params::PacketSize;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::time::Duration; use std::time::Duration;
use url::Url; use url::Url;
@@ -82,7 +83,7 @@ impl From<Traffic> for ConfigTraffic {
fn from(traffic: Traffic) -> Self { fn from(traffic: Traffic) -> Self {
let use_extended_packet_size = traffic let use_extended_packet_size = traffic
.use_extended_packet_size .use_extended_packet_size
.then(|| ExtendedPacketSize::Extended32); .then(|| PacketSize::ExtendedPacket32);
ConfigTraffic { ConfigTraffic {
average_packet_delay: Duration::from_millis(traffic.average_packet_delay_ms), average_packet_delay: Duration::from_millis(traffic.average_packet_delay_ms),
@@ -91,7 +92,8 @@ impl From<Traffic> for ConfigTraffic {
), ),
disable_main_poisson_packet_distribution: traffic disable_main_poisson_packet_distribution: traffic
.disable_main_poisson_packet_distribution, .disable_main_poisson_packet_distribution,
use_extended_packet_size, primary_packet_size: PacketSize::RegularPacket,
secondary_packet_size: use_extended_packet_size,
} }
} }
} }
@@ -104,7 +106,7 @@ impl From<ConfigTraffic> for Traffic {
as u64, as u64,
disable_main_poisson_packet_distribution: traffic disable_main_poisson_packet_distribution: traffic
.disable_main_poisson_packet_distribution, .disable_main_poisson_packet_distribution,
use_extended_packet_size: traffic.use_extended_packet_size.is_some(), use_extended_packet_size: traffic.secondary_packet_size.is_some(),
} }
} }
} }
@@ -116,6 +118,10 @@ pub struct CoverTraffic {
/// it is going to take for another loop cover traffic message to be sent. /// it is going to take for another loop cover traffic message to be sent.
pub loop_cover_traffic_average_delay_ms: u64, pub loop_cover_traffic_average_delay_ms: u64,
/// Specifies the ratio of `primary_packet_size` to `secondary_packet_size` used in cover traffic.
/// Only applicable if `secondary_packet_size` is enabled.
pub cover_traffic_primary_size_ratio: f64,
/// Controls whether the dedicated loop cover traffic stream should be enabled. /// Controls whether the dedicated loop cover traffic stream should be enabled.
/// (and sending packets, on average, every [Self::loop_cover_traffic_average_delay]) /// (and sending packets, on average, every [Self::loop_cover_traffic_average_delay])
pub disable_loop_cover_traffic_stream: bool, pub disable_loop_cover_traffic_stream: bool,
@@ -127,6 +133,7 @@ impl From<CoverTraffic> for ConfigCoverTraffic {
loop_cover_traffic_average_delay: Duration::from_millis( loop_cover_traffic_average_delay: Duration::from_millis(
cover_traffic.loop_cover_traffic_average_delay_ms, cover_traffic.loop_cover_traffic_average_delay_ms,
), ),
cover_traffic_primary_size_ratio: cover_traffic.cover_traffic_primary_size_ratio,
disable_loop_cover_traffic_stream: cover_traffic.disable_loop_cover_traffic_stream, disable_loop_cover_traffic_stream: cover_traffic.disable_loop_cover_traffic_stream,
} }
} }
@@ -138,6 +145,7 @@ impl From<ConfigCoverTraffic> for CoverTraffic {
loop_cover_traffic_average_delay_ms: cover_traffic loop_cover_traffic_average_delay_ms: cover_traffic
.loop_cover_traffic_average_delay .loop_cover_traffic_average_delay
.as_millis() as u64, .as_millis() as u64,
cover_traffic_primary_size_ratio: cover_traffic.cover_traffic_primary_size_ratio,
disable_loop_cover_traffic_stream: cover_traffic.disable_loop_cover_traffic_stream, disable_loop_cover_traffic_stream: cover_traffic.disable_loop_cover_traffic_stream,
} }
} }
+2 -2
View File
@@ -1,9 +1,9 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net> // Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use client_core::client::base_client::ClientInput;
use client_core::client::inbound_messages::InputMessage;
use js_sys::Promise; use js_sys::Promise;
use nym_client_core::client::base_client::ClientInput;
use nym_client_core::client::inbound_messages::InputMessage;
use std::sync::Arc; use std::sync::Arc;
use wasm_bindgen::JsValue; use wasm_bindgen::JsValue;
use wasm_bindgen_futures::future_to_promise; use wasm_bindgen_futures::future_to_promise;
+9 -7
View File
@@ -4,14 +4,15 @@
use self::config::Config; use self::config::Config;
use crate::client::helpers::InputSender; use crate::client::helpers::InputSender;
use crate::client::response_pusher::ResponsePusher; use crate::client::response_pusher::ResponsePusher;
use client_core::client::base_client::{ use js_sys::Promise;
use nym_bandwidth_controller::wasm_mockups::{Client as FakeClient, DirectSigningNyxdClient};
use nym_bandwidth_controller::BandwidthController;
use nym_client_core::client::base_client::{
BaseClientBuilder, ClientInput, ClientOutput, CredentialsToggle, BaseClientBuilder, ClientInput, ClientOutput, CredentialsToggle,
}; };
use client_core::client::replies::reply_storage::browser_backend; use nym_client_core::client::replies::reply_storage::browser_backend;
use client_core::client::{inbound_messages::InputMessage, key_manager::KeyManager}; use nym_client_core::client::{inbound_messages::InputMessage, key_manager::KeyManager};
use gateway_client::bandwidth::BandwidthController; use nym_credential_storage::ephemeral_storage::EphemeralStorage;
use gateway_client::wasm_mockups::SigningNyxdClient;
use js_sys::Promise;
use nym_sphinx::addressing::clients::Recipient; use nym_sphinx::addressing::clients::Recipient;
use nym_sphinx::anonymous_replies::requests::AnonymousSenderTag; use nym_sphinx::anonymous_replies::requests::AnonymousSenderTag;
use nym_task::connections::TransmissionLane; use nym_task::connections::TransmissionLane;
@@ -48,7 +49,8 @@ pub struct NymClientBuilder {
on_message: js_sys::Function, on_message: js_sys::Function,
// unimplemented: // unimplemented:
bandwidth_controller: Option<BandwidthController<SigningNyxdClient>>, bandwidth_controller:
Option<BandwidthController<FakeClient<DirectSigningNyxdClient>, EphemeralStorage>>,
disabled_credentials: bool, disabled_credentials: bool,
} }
@@ -1,11 +1,13 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net> // Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use client_core::client::base_client::ClientOutput;
use client_core::client::received_buffer::{ReceivedBufferMessage, ReconstructedMessagesReceiver};
use futures::channel::mpsc; use futures::channel::mpsc;
use futures::StreamExt; use futures::StreamExt;
use js_sys::Uint8Array; use js_sys::Uint8Array;
use nym_client_core::client::base_client::ClientOutput;
use nym_client_core::client::received_buffer::{
ReceivedBufferMessage, ReconstructedMessagesReceiver,
};
use wasm_bindgen::JsValue; use wasm_bindgen::JsValue;
use wasm_bindgen_futures::spawn_local; use wasm_bindgen_futures::spawn_local;
use wasm_utils::console_error; use wasm_utils::console_error;
+3 -2
View File
@@ -1,12 +1,13 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net> // Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use client_core::config::GatewayEndpointConfig; use nym_client_core::config::GatewayEndpointConfig;
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;
#[wasm_bindgen] #[wasm_bindgen]
pub async fn get_gateway(api_server: String, preferred: Option<String>) -> GatewayEndpointConfig { pub async fn get_gateway(api_server: String, preferred: Option<String>) -> GatewayEndpointConfig {
let validator_client = validator_client::client::NymApiClient::new(api_server.parse().unwrap()); let validator_client =
nym_validator_client::client::NymApiClient::new(api_server.parse().unwrap());
let gateways = match validator_client.get_cached_gateways().await { let gateways = match validator_client.get_cached_gateways().await {
Err(err) => panic!("failed to obtain list of all gateways - {err}"), Err(err) => panic!("failed to obtain list of all gateways - {err}"),
+12
View File
@@ -0,0 +1,12 @@
[package]
name = "async-file-watcher"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
log = "0.4"
tokio = { workspace = true, features = ["time"] }
futures = "0.3"
notify = "5.1.0"
+158
View File
@@ -0,0 +1,158 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use futures::channel::mpsc;
use futures::StreamExt;
use notify::event::{DataChange, MetadataKind, ModifyKind};
use notify::{Config, Event, EventKind, RecommendedWatcher, RecursiveMode, Watcher};
use std::collections::HashMap;
use std::path::{Path, PathBuf};
use std::time::Duration;
use tokio::time::Instant;
pub type FileWatcherEventSender = mpsc::UnboundedSender<Event>;
pub type FileWatcherEventReceiver = mpsc::UnboundedReceiver<Event>;
/// Simple file watcher that sends a notification whenever there was any changed in the watched file.
pub struct AsyncFileWatcher {
path: PathBuf,
watcher: RecommendedWatcher,
is_watching: bool,
filters: Option<Vec<EventKind>>,
last_received: HashMap<EventKind, Instant>,
tick_duration: Duration,
inner_rx: mpsc::UnboundedReceiver<notify::Result<Event>>,
event_sender: FileWatcherEventSender,
}
impl AsyncFileWatcher {
pub fn new_file_changes_watcher<P: AsRef<Path>>(
path: P,
event_sender: FileWatcherEventSender,
) -> notify::Result<Self> {
Self::new(
path,
event_sender,
Some(vec![
EventKind::Modify(ModifyKind::Data(DataChange::Content)),
EventKind::Modify(ModifyKind::Data(DataChange::Any)),
EventKind::Modify(ModifyKind::Metadata(MetadataKind::Any)),
]),
None,
)
}
pub fn new<P: AsRef<Path>>(
path: P,
event_sender: FileWatcherEventSender,
filters: Option<Vec<EventKind>>,
tick_duration: Option<Duration>,
) -> notify::Result<Self> {
let watcher_config = Config::default();
let (inner_tx, inner_rx) = mpsc::unbounded();
let watcher = RecommendedWatcher::new(
move |res| {
if let Err(_err) = inner_tx.unbounded_send(res) {
// I guess it's theoretically possible during shutdown?
log::error!(
"failed to send watched file event - the received must have been dropped!"
);
}
},
watcher_config,
)?;
Ok(AsyncFileWatcher {
path: path.as_ref().to_path_buf(),
watcher,
is_watching: false,
filters,
last_received: HashMap::new(),
tick_duration: tick_duration.unwrap_or(Duration::from_secs(5)),
inner_rx,
event_sender,
})
}
pub fn with_filters(mut self, filters: Option<Vec<EventKind>>) -> Self {
self.filters = filters;
self
}
pub fn with_filter(mut self, filter: EventKind) -> Self {
match &mut self.filters {
None => {
self.filters = Some(vec![filter]);
}
Some(filters) => filters.push(filter),
}
self
}
fn should_propagate(&self, event: &Event, now: Instant) -> bool {
// when testing I was consistently getting two `Modify(Data(Any))` events in quick succession
// (probably to modify content and metadata).
// we really only want to propagate one of them
if let Some(previous) = self.last_received.get(&event.kind) {
if now.duration_since(*previous) < self.tick_duration {
return false;
}
}
let Some(filters) = &self.filters else {
return true
};
for filter in filters {
if &event.kind == filter {
return true;
}
}
false
}
fn start_watching(&mut self) -> notify::Result<()> {
self.is_watching = true;
self.watcher.watch(&self.path, RecursiveMode::NonRecursive)
}
fn stop_watching(&mut self) -> notify::Result<()> {
self.is_watching = false;
self.watcher.unwatch(&self.path)
}
pub async fn watch(&mut self) -> notify::Result<()> {
self.start_watching()?;
while let Some(event) = self.inner_rx.next().await {
match event {
Ok(event) => {
let now = Instant::now();
if self.should_propagate(&event, now) {
self.last_received.insert(event.kind.clone(), now);
if let Err(_err) = self.event_sender.unbounded_send(event) {
log::error!("the file watcher receiver has been dropped!");
}
} else {
log::debug!("will not propagate information about {:?}", event);
}
}
Err(err) => {
// TODO: to be determined if this should stop the whole thing or not
// (need to know what kind of errors can be returned)
log::error!(
"encountered an error while watching {:?}: {err}",
self.path.as_path()
);
}
}
}
self.stop_watching()
}
pub fn is_watching(&self) -> bool {
self.is_watching
}
}
+24
View File
@@ -0,0 +1,24 @@
[package]
name = "nym-bandwidth-controller"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
bip39 = { workspace = true }
rand = "0.7.3"
thiserror = "1.0"
url = "2.2"
nym-coconut-interface = { path = "../coconut-interface" }
nym-credential-storage = { path = "../credential-storage" }
nym-credentials = { path = "../credentials" }
nym-crypto = { path = "../crypto", features = ["rand", "asymmetric", "symmetric", "aes", "hashing"] }
nym-network-defaults = { path = "../network-defaults" }
nym-validator-client = { path = "../client-libs/validator-client", default-features = false }
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.nym-validator-client]
path = "../client-libs/validator-client"
features = ["nyxd-client"]
@@ -0,0 +1,89 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::error::BandwidthControllerError;
use nym_coconut_interface::{Base58, Parameters};
use nym_credential_storage::storage::Storage;
use nym_credentials::coconut::bandwidth::{BandwidthVoucher, TOTAL_ATTRIBUTES};
use nym_credentials::coconut::utils::obtain_aggregate_signature;
use nym_crypto::asymmetric::{encryption, identity};
use nym_network_defaults::VOUCHER_INFO;
use nym_validator_client::nyxd::traits::CoconutBandwidthSigningClient;
use nym_validator_client::nyxd::traits::DkgQueryClient;
use nym_validator_client::nyxd::tx::Hash;
use nym_validator_client::nyxd::Coin;
use nym_validator_client::CoconutApiClient;
use rand::rngs::OsRng;
use state::{KeyPair, State};
use std::str::FromStr;
pub mod state;
pub async fn deposit<C>(client: &C, amount: Coin) -> Result<State, BandwidthControllerError>
where
C: CoconutBandwidthSigningClient,
{
let mut rng = OsRng;
let signing_keypair = KeyPair::from(identity::KeyPair::new(&mut rng));
let encryption_keypair = KeyPair::from(encryption::KeyPair::new(&mut rng));
let params = Parameters::new(TOTAL_ATTRIBUTES).unwrap();
let voucher_value = amount.amount.to_string();
let tx_hash = client
.deposit(
amount,
String::from(VOUCHER_INFO),
signing_keypair.public_key.clone(),
encryption_keypair.public_key.clone(),
None,
)
.await?
.transaction_hash
.to_string();
let voucher = BandwidthVoucher::new(
&params,
voucher_value,
VOUCHER_INFO.to_string(),
Hash::from_str(&tx_hash).map_err(|_| BandwidthControllerError::InvalidTxHash)?,
identity::PrivateKey::from_base58_string(&signing_keypair.private_key)?,
encryption::PrivateKey::from_base58_string(&encryption_keypair.private_key)?,
);
let state = State { voucher, params };
Ok(state)
}
pub async fn get_credential<C: DkgQueryClient + Send + Sync, St: Storage>(
state: &State,
client: &C,
storage: &St,
) -> Result<(), BandwidthControllerError> {
let epoch_id = client.get_current_epoch().await?.epoch_id;
let threshold = client
.get_current_epoch_threshold()
.await?
.ok_or(BandwidthControllerError::NoThreshold)?;
let coconut_api_clients = CoconutApiClient::all_coconut_api_clients(client, epoch_id).await?;
let signature = obtain_aggregate_signature(
&state.params,
&state.voucher,
&coconut_api_clients,
threshold,
)
.await?;
storage
.insert_coconut_credential(
state.voucher.get_voucher_value(),
VOUCHER_INFO.to_string(),
state.voucher.get_private_attributes()[0].to_bs58(),
state.voucher.get_private_attributes()[1].to_bs58(),
signature.to_bs58(),
epoch_id.to_string(),
)
.await?;
Ok(())
}
@@ -1,8 +1,8 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net> // Copyright 2022-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use nym_coconut_interface::Parameters; use nym_coconut_interface::Parameters;
use nym_credentials::coconut::bandwidth::BandwidthVoucher; use nym_credentials::coconut::bandwidth::{BandwidthVoucher, TOTAL_ATTRIBUTES};
use nym_crypto::asymmetric::{encryption, identity}; use nym_crypto::asymmetric::{encryption, identity};
@@ -29,7 +29,16 @@ impl From<encryption::KeyPair> for KeyPair {
} }
} }
pub(crate) struct State { pub struct State {
pub voucher: BandwidthVoucher, pub voucher: BandwidthVoucher,
pub params: Parameters, pub params: Parameters,
} }
impl State {
pub fn new(voucher: BandwidthVoucher) -> Self {
State {
voucher,
params: Parameters::new(TOTAL_ATTRIBUTES).unwrap(),
}
}
}
+41
View File
@@ -0,0 +1,41 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use nym_coconut_interface::CoconutError;
use nym_credential_storage::error::StorageError;
use nym_credentials::error::Error as CredentialsError;
use nym_crypto::asymmetric::encryption::KeyRecoveryError;
use nym_crypto::asymmetric::identity::Ed25519RecoveryError;
use nym_validator_client::error::ValidatorClientError;
use thiserror::Error;
#[derive(Debug, Error)]
pub enum BandwidthControllerError {
#[cfg(not(target_arch = "wasm32"))]
#[error("Nyxd error: {0}")]
Nyxd(#[from] nym_validator_client::nyxd::error::NyxdError),
#[error("There was a credential storage error - {0}")]
CredentialStorageError(#[from] StorageError),
#[error("Coconut error - {0}")]
CoconutError(#[from] CoconutError),
#[error("Validator client error - {0}")]
ValidatorError(#[from] ValidatorClientError),
#[error("Credential error - {0}")]
CredentialError(#[from] CredentialsError),
#[error("Could not parse Ed25519 data")]
Ed25519ParseError(#[from] Ed25519RecoveryError),
#[error("Could not parse X25519 data")]
X25519ParseError(#[from] KeyRecoveryError),
#[error("The tx hash provided is not valid")]
InvalidTxHash,
#[error("Threshold not set yet")]
NoThreshold,
}
@@ -1,34 +1,12 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net> // Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use crate::error::GatewayClientError; use crate::error::BandwidthControllerError;
#[cfg(target_arch = "wasm32")] use nym_credential_storage::error::StorageError;
use crate::wasm_mockups::Storage;
#[cfg(not(target_arch = "wasm32"))]
#[cfg(not(feature = "mobile"))]
use nym_credential_storage::storage::Storage; use nym_credential_storage::storage::Storage;
#[cfg(not(target_arch = "wasm32"))]
#[cfg(feature = "mobile")]
use mobile_storage::Storage;
#[cfg(not(target_arch = "wasm32"))]
#[cfg(feature = "mobile")]
use mobile_storage::StorageError;
#[cfg(target_arch = "wasm32")]
use crate::wasm_mockups::StorageError;
#[cfg(not(target_arch = "wasm32"))]
#[cfg(not(feature = "mobile"))]
use nym_credential_storage::error::StorageError;
#[cfg(target_arch = "wasm32")]
use crate::wasm_mockups::{Client, CosmWasmClient};
use std::str::FromStr; use std::str::FromStr;
#[cfg(not(target_arch = "wasm32"))]
use validator_client::{nyxd::CosmWasmClient, Client};
use { use {
nym_coconut_interface::Base58, nym_coconut_interface::Base58,
nym_credentials::coconut::{ nym_credentials::coconut::{
@@ -36,40 +14,38 @@ use {
}, },
}; };
// TODO: make it nicer for wasm (I don't want to touch it for this experiment) #[cfg(not(target_arch = "wasm32"))]
use nym_validator_client::nyxd::traits::DkgQueryClient;
#[cfg(target_arch = "wasm32")] #[cfg(target_arch = "wasm32")]
use crate::wasm_mockups::PersistentStorage; use crate::wasm_mockups::DkgQueryClient;
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
#[cfg(not(feature = "mobile"))] pub mod acquire;
use nym_credential_storage::PersistentStorage; pub mod error;
#[cfg(target_arch = "wasm32")]
pub mod wasm_mockups;
#[cfg(not(target_arch = "wasm32"))] pub struct BandwidthController<C, St: Storage> {
#[cfg(feature = "mobile")]
use mobile_storage::PersistentStorage;
#[derive(Clone)]
#[allow(dead_code)]
pub struct BandwidthController<C: Clone, St: Storage = PersistentStorage> {
storage: St, storage: St,
nyxd_client: Client<C>, client: C,
} }
impl<C, St> BandwidthController<C, St> impl<C, St: Storage> BandwidthController<C, St> {
where pub fn new(storage: St, client: C) -> Self {
C: CosmWasmClient + Sync + Send + Clone, BandwidthController { storage, client }
St: Storage + Clone + 'static, }
{
pub fn new(storage: St, nyxd_client: Client<C>) -> Self { pub fn storage(&self) -> &St {
BandwidthController { &self.storage
storage,
nyxd_client,
}
} }
pub async fn prepare_coconut_credential( pub async fn prepare_coconut_credential(
&self, &self,
) -> Result<(nym_coconut_interface::Credential, i64), GatewayClientError> { ) -> Result<(nym_coconut_interface::Credential, i64), BandwidthControllerError>
where
C: DkgQueryClient + Sync + Send,
{
let bandwidth_credential = self.storage.get_next_coconut_credential().await?; let bandwidth_credential = self.storage.get_next_coconut_credential().await?;
let voucher_value = u64::from_str(&bandwidth_credential.voucher_value) let voucher_value = u64::from_str(&bandwidth_credential.voucher_value)
.map_err(|_| StorageError::InconsistentData)?; .map_err(|_| StorageError::InconsistentData)?;
@@ -84,12 +60,9 @@ where
.map_err(|_| StorageError::InconsistentData)?; .map_err(|_| StorageError::InconsistentData)?;
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
let coconut_api_clients = validator_client::CoconutApiClient::all_coconut_api_clients( let coconut_api_clients =
&self.nyxd_client, nym_validator_client::CoconutApiClient::all_coconut_api_clients(&self.client, epoch_id)
epoch_id, .await?;
)
.await
.expect("Could not query api clients");
#[cfg(target_arch = "wasm32")] #[cfg(target_arch = "wasm32")]
let coconut_api_clients = vec![]; let coconut_api_clients = vec![];
let verification_key = obtain_aggregate_verification_key(&coconut_api_clients).await?; let verification_key = obtain_aggregate_verification_key(&coconut_api_clients).await?;
@@ -109,7 +82,22 @@ where
)) ))
} }
pub async fn consume_credential(&self, id: i64) -> Result<(), GatewayClientError> { pub async fn consume_credential(&self, id: i64) -> Result<(), BandwidthControllerError> {
// JS: shouldn't we send some contract/validator/gateway message here to actually, you know,
// consume it?
Ok(self.storage.consume_coconut_credential(id).await?) Ok(self.storage.consume_coconut_credential(id).await?)
} }
} }
impl<C, St> Clone for BandwidthController<C, St>
where
C: Clone,
St: Storage + Clone,
{
fn clone(&self) -> Self {
BandwidthController {
storage: self.storage.clone(),
client: self.client.clone(),
}
}
}
@@ -0,0 +1,17 @@
// Copyright 2022-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use std::marker::PhantomData;
pub struct DirectSigningNyxdClient {}
pub trait DkgQueryClient {}
// impl CosmWasmClient for DirectSigningNyxdClient {}
#[derive(Clone)]
pub struct Client<C> {
_phantom: PhantomData<C>,
}
impl<C> DkgQueryClient for Client<C> {}
+19 -2
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "nym-bin-common" name = "nym-bin-common"
version = "0.4.0" version = "0.5.0"
description = "Common code for nym binaries" description = "Common code for nym binaries"
edition = { workspace = true } edition = { workspace = true }
authors = { workspace = true } authors = { workspace = true }
@@ -8,6 +8,7 @@ license = { workspace = true }
repository = { workspace = true } repository = { workspace = true }
[dependencies] [dependencies]
atty = "0.2"
clap = { version = "4.0", features = ["derive"] } clap = { version = "4.0", features = ["derive"] }
clap_complete = "4.0" clap_complete = "4.0"
clap_complete_fig = "4.0" clap_complete_fig = "4.0"
@@ -15,9 +16,25 @@ log = { workspace = true }
pretty_env_logger = "0.4.0" pretty_env_logger = "0.4.0"
semver = "0.11" semver = "0.11"
serde = { workspace = true, features = ["derive"], optional = true } serde = { workspace = true, features = ["derive"], optional = true }
serde_json = { workspace = true, optional = true }
## tracing
tracing-appender = { version = "0.2.2", optional = true }
tracing-subscriber = { version = "0.3.16", features = [
"env-filter",
], optional = true }
tracing-tree = { version = "0.2.2", optional = true }
[build-dependencies] [build-dependencies]
vergen = { version = "=7.4.3", default-features = false, features = ["build", "git", "rustc", "cargo"] } vergen = { version = "=7.4.3", default-features = false, features = [
"build",
"git",
"rustc",
"cargo",
] }
[features] [features]
default = [] default = []
output_format = ["serde", "serde_json"]
tracing = ["tracing-appender", "tracing-subscriber", "tracing-tree"]
+1
View File
@@ -4,4 +4,5 @@
pub mod build_information; pub mod build_information;
pub mod completions; pub mod completions;
pub mod logging; pub mod logging;
pub mod output_format;
pub mod version_checker; pub mod version_checker;
+45
View File
@@ -1,5 +1,16 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net> // Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
// use tracing_subscriber::{
// fmt::Layer, layer::SubscriberExt, util::SubscriberInitExt, EnvFilter, Registry,
// };
// use tracing_tree::HierarchicalLayer;
#[cfg(feature = "tracing")]
pub use tracing_appender;
#[cfg(feature = "tracing")]
pub use tracing_subscriber;
#[cfg(feature = "tracing")]
pub use tracing_tree;
// I'd argue we should start transitioning from `log` to `tracing` // I'd argue we should start transitioning from `log` to `tracing`
pub fn setup_logging() { pub fn setup_logging() {
@@ -24,6 +35,34 @@ pub fn setup_logging() {
.init(); .init();
} }
// TODO: This has to be a macro, running it as a function does not work for the file_appender for some reason
#[cfg(feature = "tracing")]
#[macro_export]
macro_rules! setup_tracing {
($file_name: expr) => {
use nym_bin_common::logging::tracing_subscriber::layer::SubscriberExt;
use nym_bin_common::logging::tracing_subscriber::util::SubscriberInitExt;
let file_appender =
nym_bin_common::logging::tracing_appender::rolling::hourly($file_name, "log");
let (non_blocking, _guard) =
nym_bin_common::logging::tracing_appender::non_blocking(file_appender);
let appender_layer = nym_bin_common::logging::tracing_subscriber::fmt::Layer::new()
.with_ansi(false)
.with_writer(non_blocking);
nym_bin_common::logging::tracing_subscriber::Registry::default()
.with(nym_bin_common::logging::tracing_subscriber::EnvFilter::from_default_env())
.with(appender_layer)
.with(
nym_bin_common::logging::tracing_tree::HierarchicalLayer::new(4)
.with_targets(true)
.with_bracketed_fields(true),
)
.init();
};
}
pub fn banner(crate_name: &str, crate_version: &str) -> String { pub fn banner(crate_name: &str, crate_version: &str) -> String {
format!( format!(
r#" r#"
@@ -39,3 +78,9 @@ pub fn banner(crate_name: &str, crate_version: &str) -> String {
"# "#
) )
} }
pub fn maybe_print_banner(crate_name: &str, crate_version: &str) {
if atty::is(atty::Stream::Stdout) {
println!("{}", banner(crate_name, crate_version))
}
}
@@ -0,0 +1,35 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use clap::ValueEnum;
use std::fmt::{Display, Formatter};
#[derive(Default, Copy, Debug, Clone, ValueEnum)]
pub enum OutputFormat {
#[default]
Text,
Json,
}
impl Display for OutputFormat {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
OutputFormat::Text => write!(f, "text"),
OutputFormat::Json => write!(f, "json"),
}
}
}
impl OutputFormat {
pub fn is_text(&self) -> bool {
matches!(self, OutputFormat::Text)
}
#[cfg(feature = "output_format")]
pub fn format<T: serde::Serialize + ToString>(&self, data: &T) -> String {
match self {
OutputFormat::Text => data.to_string(),
OutputFormat::Json => serde_json::to_string(data).unwrap(),
}
}
}
@@ -1,5 +1,5 @@
[package] [package]
name = "client-core" name = "nym-client-core"
version = "1.1.14" version = "1.1.14"
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"] authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"]
edition = "2021" edition = "2021"
@@ -15,8 +15,8 @@ futures = "0.3"
humantime-serde = "1.0" humantime-serde = "1.0"
log = { workspace = true } log = { workspace = true }
rand = { version = "0.7.3", features = ["wasm-bindgen"] } rand = { version = "0.7.3", features = ["wasm-bindgen"] }
serde = { version = "1.0", features = ["derive"] } serde = { workspace = true, features = ["derive"] }
serde_json = "1.0.89" serde_json = { workspace = true }
tap = "1.0.1" tap = "1.0.1"
thiserror = "1.0.34" thiserror = "1.0.34"
url = { version ="2.2", features = ["serde"] } url = { version ="2.2", features = ["serde"] }
@@ -25,20 +25,22 @@ tokio = { version = "1.24.1", features = ["macros"]}
time = "0.3.17" time = "0.3.17"
# internal # internal
nym-config = { path = "../../common/config" } nym-bandwidth-controller = { path = "../bandwidth-controller" }
nym-crypto = { path = "../../common/crypto" } nym-config = { path = "../config" }
gateway-client = { path = "../../common/client-libs/gateway-client" } nym-crypto = { path = "../crypto" }
nym-gateway-client = { path = "../client-libs/gateway-client" }
#gateway-client = { path = "../../common/client-libs/gateway-client", default-features = false, features = ["wasm", "coconut"] } #gateway-client = { path = "../../common/client-libs/gateway-client", default-features = false, features = ["wasm", "coconut"] }
gateway-requests = { path = "../../gateway/gateway-requests" } nym-gateway-requests = { path = "../../gateway/gateway-requests" }
nym-nonexhaustive-delayqueue = { path = "../../common/nonexhaustive-delayqueue" } nym-nonexhaustive-delayqueue = { path = "../nonexhaustive-delayqueue" }
nym-sphinx = { path = "../../common/nymsphinx" } nym-sphinx = { path = "../nymsphinx" }
nym-pemstore = { path = "../../common/pemstore" } nym-pemstore = { path = "../pemstore" }
nym-topology = { path = "../../common/topology" } nym-topology = { path = "../topology" }
validator-client = { path = "../../common/client-libs/validator-client", default-features = false } nym-validator-client = { path = "../client-libs/validator-client", default-features = false }
nym-task = { path = "../../common/task" } nym-task = { path = "../task" }
nym-credential-storage = { path = "../credential-storage" }
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.validator-client] [target."cfg(not(target_arch = \"wasm32\"))".dependencies.nym-validator-client]
path = "../../common/client-libs/validator-client" path = "../client-libs/validator-client"
features = ["nyxd-client"] features = ["nyxd-client"]
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.tokio-stream] [target."cfg(not(target_arch = \"wasm32\"))".dependencies.tokio-stream]
@@ -72,7 +74,7 @@ version = "0.2.4"
features = ["futures"] features = ["futures"]
[target."cfg(target_arch = \"wasm32\")".dependencies.wasm-utils] [target."cfg(target_arch = \"wasm32\")".dependencies.wasm-utils]
path = "../../common/wasm-utils" path = "../wasm-utils"
features = ["websocket"] features = ["websocket"]
[target."cfg(target_arch = \"wasm32\")".dependencies.time] [target."cfg(target_arch = \"wasm32\")".dependencies.time]
@@ -89,5 +91,5 @@ sqlx = { version = "0.6.2", features = ["runtime-tokio-rustls", "sqlite", "macro
[features] [features]
default = [] default = []
fs-surb-storage = ["sqlx"] fs-surb-storage = ["sqlx"]
wasm = ["gateway-client/wasm"] wasm = ["nym-gateway-client/wasm"]
@@ -1,6 +1,7 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net> // Copyright 2022-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use super::received_buffer::ReceivedBufferMessage;
use crate::client::cover_traffic_stream::LoopCoverTrafficStream; use crate::client::cover_traffic_stream::LoopCoverTrafficStream;
use crate::client::inbound_messages::{InputMessage, InputMessageReceiver, InputMessageSender}; use crate::client::inbound_messages::{InputMessage, InputMessageReceiver, InputMessageSender};
use crate::client::key_manager::KeyManager; use crate::client::key_manager::KeyManager;
@@ -23,15 +24,13 @@ use crate::config::{Config, DebugConfig, GatewayEndpointConfig};
use crate::error::ClientCoreError; use crate::error::ClientCoreError;
use crate::spawn_future; use crate::spawn_future;
use futures::channel::mpsc; use futures::channel::mpsc;
use gateway_client::bandwidth::BandwidthController; use log::{debug, info};
#[cfg(target_arch = "wasm32")] use nym_bandwidth_controller::BandwidthController;
use gateway_client::wasm_mockups::CosmWasmClient; use nym_crypto::asymmetric::{encryption, identity};
use gateway_client::{ use nym_gateway_client::{
AcknowledgementReceiver, AcknowledgementSender, GatewayClient, MixnetMessageReceiver, AcknowledgementReceiver, AcknowledgementSender, GatewayClient, MixnetMessageReceiver,
MixnetMessageSender, MixnetMessageSender,
}; };
use log::{debug, info};
use nym_crypto::asymmetric::{encryption, identity};
use nym_sphinx::acknowledgements::AckKey; use nym_sphinx::acknowledgements::AckKey;
use nym_sphinx::addressing::clients::Recipient; use nym_sphinx::addressing::clients::Recipient;
use nym_sphinx::addressing::nodes::NodeIdentity; use nym_sphinx::addressing::nodes::NodeIdentity;
@@ -44,10 +43,12 @@ use std::time::Duration;
use tap::TapFallible; use tap::TapFallible;
use url::Url; use url::Url;
use nym_credential_storage::storage::Storage;
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
use validator_client::nyxd::CosmWasmClient; use nym_validator_client::nyxd::traits::DkgQueryClient;
use super::received_buffer::ReceivedBufferMessage; #[cfg(target_arch = "wasm32")]
use nym_bandwidth_controller::wasm_mockups::DkgQueryClient;
#[cfg(all(not(target_arch = "wasm32"), feature = "fs-surb-storage"))] #[cfg(all(not(target_arch = "wasm32"), feature = "fs-surb-storage"))]
pub mod non_wasm_helpers; pub mod non_wasm_helpers;
@@ -90,6 +91,7 @@ impl ClientOutput {
} }
} }
#[derive(Clone, Debug)]
pub struct ClientState { pub struct ClientState {
pub shared_lane_queue_lengths: LaneQueueLengths, pub shared_lane_queue_lengths: LaneQueueLengths,
pub reply_controller_sender: ReplyControllerSender, pub reply_controller_sender: ReplyControllerSender,
@@ -150,7 +152,7 @@ impl From<bool> for CredentialsToggle {
} }
} }
pub struct BaseClientBuilder<'a, B, C: Clone> { pub struct BaseClientBuilder<'a, B, C, St: Storage> {
// due to wasm limitations I had to split it like this : ( // due to wasm limitations I had to split it like this : (
gateway_config: &'a GatewayEndpointConfig, gateway_config: &'a GatewayEndpointConfig,
debug_config: &'a DebugConfig, debug_config: &'a DebugConfig,
@@ -159,21 +161,22 @@ pub struct BaseClientBuilder<'a, B, C: Clone> {
reply_storage_backend: B, reply_storage_backend: B,
custom_topology_provider: Option<Box<dyn TopologyProvider>>, custom_topology_provider: Option<Box<dyn TopologyProvider>>,
bandwidth_controller: Option<BandwidthController<C>>, bandwidth_controller: Option<BandwidthController<C, St>>,
key_manager: KeyManager, key_manager: KeyManager,
} }
impl<'a, B, C> BaseClientBuilder<'a, B, C> impl<'a, B, C, St> BaseClientBuilder<'a, B, C, St>
where where
B: ReplyStorageBackend + Send + Sync + 'static, B: ReplyStorageBackend + Send + Sync + 'static,
C: CosmWasmClient + Sync + Send + Clone + 'static, C: DkgQueryClient + Sync + Send + 'static,
St: Storage + 'static,
{ {
pub fn new_from_base_config<T>( pub fn new_from_base_config<T>(
base_config: &'a Config<T>, base_config: &'a Config<T>,
key_manager: KeyManager, key_manager: KeyManager,
bandwidth_controller: Option<BandwidthController<C>>, bandwidth_controller: Option<BandwidthController<C, St>>,
reply_storage_backend: B, reply_storage_backend: B,
) -> BaseClientBuilder<'a, B, C> { ) -> BaseClientBuilder<'a, B, C, St> {
BaseClientBuilder { BaseClientBuilder {
gateway_config: base_config.get_gateway_endpoint_config(), gateway_config: base_config.get_gateway_endpoint_config(),
debug_config: base_config.get_debug_config(), debug_config: base_config.get_debug_config(),
@@ -190,11 +193,11 @@ where
gateway_config: &'a GatewayEndpointConfig, gateway_config: &'a GatewayEndpointConfig,
debug_config: &'a DebugConfig, debug_config: &'a DebugConfig,
key_manager: KeyManager, key_manager: KeyManager,
bandwidth_controller: Option<BandwidthController<C>>, bandwidth_controller: Option<BandwidthController<C, St>>,
reply_storage_backend: B, reply_storage_backend: B,
credentials_toggle: CredentialsToggle, credentials_toggle: CredentialsToggle,
nym_api_endpoints: Vec<Url>, nym_api_endpoints: Vec<Url>,
) -> BaseClientBuilder<'a, B, C> { ) -> BaseClientBuilder<'a, B, C, St> {
BaseClientBuilder { BaseClientBuilder {
gateway_config, gateway_config,
debug_config, debug_config,
@@ -234,21 +237,16 @@ where
) { ) {
info!("Starting loop cover traffic stream..."); info!("Starting loop cover traffic stream...");
let mut stream = LoopCoverTrafficStream::new( let stream = LoopCoverTrafficStream::new(
ack_key, ack_key,
debug_config.acknowledgements.average_ack_delay, debug_config.acknowledgements.average_ack_delay,
debug_config.traffic.average_packet_delay,
debug_config.cover_traffic.loop_cover_traffic_average_delay,
mix_tx, mix_tx,
self_address, self_address,
topology_accessor, topology_accessor,
debug_config.traffic,
debug_config.cover_traffic,
); );
if let Some(size) = debug_config.traffic.use_extended_packet_size {
log::debug!("Setting extended packet size: {:?}", size);
stream.set_custom_packet_size(size.into());
}
stream.start_with_shutdown(shutdown); stream.start_with_shutdown(shutdown);
} }
@@ -310,7 +308,7 @@ where
mixnet_message_sender: MixnetMessageSender, mixnet_message_sender: MixnetMessageSender,
ack_sender: AcknowledgementSender, ack_sender: AcknowledgementSender,
shutdown: TaskClient, shutdown: TaskClient,
) -> Result<GatewayClient<C>, ClientCoreError> { ) -> Result<GatewayClient<C, St>, ClientCoreError> {
let gateway_id = self.gateway_config.gateway_id.clone(); let gateway_id = self.gateway_config.gateway_id.clone();
if gateway_id.is_empty() { if gateway_id.is_empty() {
return Err(ClientCoreError::GatewayIdUnknown); return Err(ClientCoreError::GatewayIdUnknown);
@@ -407,7 +405,7 @@ where
// over it. Perhaps GatewayClient needs to be thread-shareable or have some channel for // over it. Perhaps GatewayClient needs to be thread-shareable or have some channel for
// requests? // requests?
fn start_mix_traffic_controller( fn start_mix_traffic_controller(
gateway_client: GatewayClient<C>, gateway_client: GatewayClient<C, St>,
shutdown: TaskClient, shutdown: TaskClient,
) -> BatchMixMessageSender { ) -> BatchMixMessageSender {
info!("Starting mix traffic controller..."); info!("Starting mix traffic controller...");
@@ -532,17 +530,12 @@ where
// primarily to throttle incoming connections (e.g socks5 for attached network-requesters) // primarily to throttle incoming connections (e.g socks5 for attached network-requesters)
let shared_lane_queue_lengths = LaneQueueLengths::new(); let shared_lane_queue_lengths = LaneQueueLengths::new();
let mut controller_config = real_messages_control::Config::new( let controller_config = real_messages_control::Config::new(
self.debug_config, self.debug_config,
self.key_manager.ack_key(), self.key_manager.ack_key(),
self_address, self_address,
); );
if let Some(size) = self.debug_config.traffic.use_extended_packet_size {
log::debug!("Setting extended packet size: {:?}", size);
controller_config.set_custom_packet_size(size.into());
}
Self::start_real_traffic_controller( Self::start_real_traffic_controller(
controller_config, controller_config,
shared_topology_accessor.clone(), shared_topology_accessor.clone(),
@@ -3,7 +3,7 @@
use crate::client::mix_traffic::BatchMixMessageSender; use crate::client::mix_traffic::BatchMixMessageSender;
use crate::client::topology_control::TopologyAccessor; use crate::client::topology_control::TopologyAccessor;
use crate::spawn_future; use crate::{config, spawn_future};
use futures::task::{Context, Poll}; use futures::task::{Context, Poll};
use futures::{Future, Stream, StreamExt}; use futures::{Future, Stream, StreamExt};
use log::*; use log::*;
@@ -34,11 +34,8 @@ where
/// Average delay an acknowledgement packet is going to get delay at a single mixnode. /// Average delay an acknowledgement packet is going to get delay at a single mixnode.
average_ack_delay: Duration, average_ack_delay: Duration,
/// Average delay a data packet is going to get delay at a single mixnode. /// Defines configuration options related to cover traffic.
average_packet_delay: Duration, cover_traffic: config::CoverTraffic,
/// Average delay between sending subsequent cover packets.
average_cover_message_sending_delay: Duration,
/// Internal state, determined by `average_message_sending_delay`, /// Internal state, determined by `average_message_sending_delay`,
/// used to keep track of when a next packet should be sent out. /// used to keep track of when a next packet should be sent out.
@@ -61,8 +58,11 @@ where
/// Accessor to the common instance of network topology. /// Accessor to the common instance of network topology.
topology_access: TopologyAccessor, topology_access: TopologyAccessor,
/// Predefined packet size used for the loop cover messages. /// Primary predefined packet size used for the loop cover messages.
packet_size: PacketSize, primary_packet_size: PacketSize,
/// Optional secondary predefined packet size used for the loop cover messages.
secondary_packet_size: Option<PacketSize>,
} }
impl<R> Stream for LoopCoverTrafficStream<R> impl<R> Stream for LoopCoverTrafficStream<R>
@@ -83,7 +83,7 @@ where
// we know it's time to send a message, so let's prepare delay for the next one // we know it's time to send a message, so let's prepare delay for the next one
// Get the `now` by looking at the current `delay` deadline // Get the `now` by looking at the current `delay` deadline
let avg_delay = self.average_cover_message_sending_delay; let avg_delay = self.cover_traffic.loop_cover_traffic_average_delay;
let next_poisson_delay = sample_poisson_duration(&mut self.rng, avg_delay); let next_poisson_delay = sample_poisson_duration(&mut self.rng, avg_delay);
// The next interval value is `next_poisson_delay` after the one that just // The next interval value is `next_poisson_delay` after the one that just
@@ -107,15 +107,14 @@ where
// obviously when we finally make shared rng that is on 'higher' level, this should become // obviously when we finally make shared rng that is on 'higher' level, this should become
// generic `R` // generic `R`
impl LoopCoverTrafficStream<OsRng> { impl LoopCoverTrafficStream<OsRng> {
#[allow(clippy::too_many_arguments)]
pub fn new( pub fn new(
ack_key: Arc<AckKey>, ack_key: Arc<AckKey>,
average_ack_delay: Duration, average_ack_delay: Duration,
average_packet_delay: Duration,
average_cover_message_sending_delay: Duration,
mix_tx: BatchMixMessageSender, mix_tx: BatchMixMessageSender,
our_full_destination: Recipient, our_full_destination: Recipient,
topology_access: TopologyAccessor, topology_access: TopologyAccessor,
traffic_config: config::Traffic,
cover_config: config::CoverTraffic,
) -> Self { ) -> Self {
let rng = OsRng; let rng = OsRng;
@@ -128,21 +127,17 @@ impl LoopCoverTrafficStream<OsRng> {
LoopCoverTrafficStream { LoopCoverTrafficStream {
ack_key, ack_key,
average_ack_delay, average_ack_delay,
average_packet_delay, cover_traffic: cover_config,
average_cover_message_sending_delay,
next_delay, next_delay,
mix_tx, mix_tx,
our_full_destination, our_full_destination,
rng, rng,
topology_access, topology_access,
packet_size: Default::default(), primary_packet_size: traffic_config.primary_packet_size,
secondary_packet_size: traffic_config.secondary_packet_size,
} }
} }
pub fn set_custom_packet_size(&mut self, packet_size: PacketSize) {
self.packet_size = packet_size;
}
fn set_next_delay(&mut self, amount: Duration) { fn set_next_delay(&mut self, amount: Duration) {
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
let next_delay = Box::pin(time::sleep(amount)); let next_delay = Box::pin(time::sleep(amount));
@@ -153,9 +148,28 @@ impl LoopCoverTrafficStream<OsRng> {
self.next_delay = next_delay; self.next_delay = next_delay;
} }
fn loop_cover_message_size(&mut self) -> PacketSize {
let Some(secondary_packet_size) = self.secondary_packet_size else {
return self.primary_packet_size
};
let use_primary = self
.rng
.gen_bool(self.cover_traffic.cover_traffic_primary_size_ratio);
if use_primary {
self.primary_packet_size
} else {
secondary_packet_size
}
}
async fn on_new_message(&mut self) { async fn on_new_message(&mut self) {
trace!("next cover message!"); trace!("next cover message!");
let cover_traffic_packet_size = self.loop_cover_message_size();
trace!("the next loop cover message will be put in a {cover_traffic_packet_size} packet");
// TODO for way down the line: in very rare cases (during topology update) we might have // TODO for way down the line: in very rare cases (during topology update) we might have
// to wait a really tiny bit before actually obtaining the permit hence messing with our // to wait a really tiny bit before actually obtaining the permit hence messing with our
// poisson delay, but is it really a problem? // poisson delay, but is it really a problem?
@@ -178,8 +192,8 @@ impl LoopCoverTrafficStream<OsRng> {
&self.ack_key, &self.ack_key,
&self.our_full_destination, &self.our_full_destination,
self.average_ack_delay, self.average_ack_delay,
self.average_packet_delay, self.cover_traffic.loop_cover_traffic_average_delay,
self.packet_size, cover_traffic_packet_size,
) )
.expect("Somehow failed to generate a loop cover message with a valid topology"); .expect("Somehow failed to generate a loop cover message with a valid topology");
@@ -189,10 +203,6 @@ impl LoopCoverTrafficStream<OsRng> {
// This isn't a problem, if the channel is full means we're already sending the // This isn't a problem, if the channel is full means we're already sending the
// max amount of messages downstream can handle. // max amount of messages downstream can handle.
log::debug!("Failed to send cover message - channel full"); log::debug!("Failed to send cover message - channel full");
// However it's still useful to alert the user that the gateway or the link to
// the gateway can't keep up. Either due to insufficient bandwidth on the
// client side, or that the gateway is overloaded.
log::warn!("Failed to send sphinx packet - gateway or connection to gateway can't keep up");
} }
TrySendError::Closed(_) => { TrySendError::Closed(_) => {
log::warn!("Failed to send cover message - channel closed"); log::warn!("Failed to send cover message - channel closed");
@@ -214,9 +224,17 @@ impl LoopCoverTrafficStream<OsRng> {
} }
pub fn start_with_shutdown(mut self, mut shutdown: nym_task::TaskClient) { pub fn start_with_shutdown(mut self, mut shutdown: nym_task::TaskClient) {
if self.cover_traffic.disable_loop_cover_traffic_stream {
// we should have never got here in the first place - the task should have never been created to begin with
// so panic and review the code that lead to this branch
panic!("attempted to start LoopCoverTrafficStream while config explicitly disabled it.")
}
// we should set initial delay only when we actually start the stream // we should set initial delay only when we actually start the stream
let sampled = let sampled = sample_poisson_duration(
sample_poisson_duration(&mut self.rng, self.average_cover_message_sending_delay); &mut self.rng,
self.cover_traffic.loop_cover_traffic_average_delay,
);
self.set_next_delay(sampled); self.set_next_delay(sampled);
spawn_future(async move { spawn_future(async move {
@@ -2,9 +2,9 @@
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use crate::config::persistence::key_pathfinder::ClientKeyPathfinder; use crate::config::persistence::key_pathfinder::ClientKeyPathfinder;
use gateway_requests::registration::handshake::SharedKeys;
use log::*; use log::*;
use nym_crypto::asymmetric::{encryption, identity}; use nym_crypto::asymmetric::{encryption, identity};
use nym_gateway_requests::registration::handshake::SharedKeys;
use nym_sphinx::acknowledgements::AckKey; use nym_sphinx::acknowledgements::AckKey;
use rand::{CryptoRng, RngCore}; use rand::{CryptoRng, RngCore};
use std::io; use std::io;
@@ -2,13 +2,16 @@
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use crate::spawn_future; use crate::spawn_future;
#[cfg(target_arch = "wasm32")]
use gateway_client::wasm_mockups::CosmWasmClient;
use gateway_client::GatewayClient;
use log::*; use log::*;
use nym_gateway_client::GatewayClient;
use nym_sphinx::forwarding::packet::MixPacket; use nym_sphinx::forwarding::packet::MixPacket;
use nym_credential_storage::storage::Storage;
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
use validator_client::nyxd::CosmWasmClient; use nym_validator_client::nyxd::traits::DkgQueryClient;
#[cfg(target_arch = "wasm32")]
use nym_bandwidth_controller::wasm_mockups::DkgQueryClient;
pub type BatchMixMessageSender = tokio::sync::mpsc::Sender<Vec<MixPacket>>; pub type BatchMixMessageSender = tokio::sync::mpsc::Sender<Vec<MixPacket>>;
pub type BatchMixMessageReceiver = tokio::sync::mpsc::Receiver<Vec<MixPacket>>; pub type BatchMixMessageReceiver = tokio::sync::mpsc::Receiver<Vec<MixPacket>>;
@@ -17,10 +20,10 @@ pub type BatchMixMessageReceiver = tokio::sync::mpsc::Receiver<Vec<MixPacket>>;
pub const MIX_MESSAGE_RECEIVER_BUFFER_SIZE: usize = 32; pub const MIX_MESSAGE_RECEIVER_BUFFER_SIZE: usize = 32;
const MAX_FAILURE_COUNT: usize = 100; const MAX_FAILURE_COUNT: usize = 100;
pub struct MixTrafficController<C: Clone> { pub struct MixTrafficController<C, St: Storage> {
// TODO: most likely to be replaced by some higher level construct as // TODO: most likely to be replaced by some higher level construct as
// later on gateway_client will need to be accessible by other entities // later on gateway_client will need to be accessible by other entities
gateway_client: GatewayClient<C>, gateway_client: GatewayClient<C, St>,
mix_rx: BatchMixMessageReceiver, mix_rx: BatchMixMessageReceiver,
// TODO: this is temporary work-around. // TODO: this is temporary work-around.
@@ -28,13 +31,14 @@ pub struct MixTrafficController<C: Clone> {
consecutive_gateway_failure_count: usize, consecutive_gateway_failure_count: usize,
} }
impl<C> MixTrafficController<C> impl<C, St> MixTrafficController<C, St>
where where
C: CosmWasmClient + Sync + Send + Clone + 'static, C: DkgQueryClient + Sync + Send + 'static,
St: Storage + 'static,
{ {
pub fn new( pub fn new(
gateway_client: GatewayClient<C>, gateway_client: GatewayClient<C, St>,
) -> (MixTrafficController<C>, BatchMixMessageSender) { ) -> (MixTrafficController<C, St>, BatchMixMessageSender) {
let (sphinx_message_sender, sphinx_message_receiver) = let (sphinx_message_sender, sphinx_message_receiver) =
tokio::sync::mpsc::channel(MIX_MESSAGE_RECEIVER_BUFFER_SIZE); tokio::sync::mpsc::channel(MIX_MESSAGE_RECEIVER_BUFFER_SIZE);
( (
@@ -3,8 +3,8 @@
use super::action_controller::{AckActionSender, Action}; use super::action_controller::{AckActionSender, Action};
use futures::StreamExt; use futures::StreamExt;
use gateway_client::AcknowledgementReceiver;
use log::*; use log::*;
use nym_gateway_client::AcknowledgementReceiver;
use nym_sphinx::{ use nym_sphinx::{
acknowledgements::{identifier::recover_identifier, AckKey}, acknowledgements::{identifier::recover_identifier, AckKey},
chunking::fragment::{FragmentIdentifier, COVER_FRAG_ID}, chunking::fragment::{FragmentIdentifier, COVER_FRAG_ID},
@@ -13,8 +13,8 @@ use crate::client::replies::reply_controller::ReplyControllerSender;
use crate::spawn_future; use crate::spawn_future;
use action_controller::AckActionReceiver; use action_controller::AckActionReceiver;
use futures::channel::mpsc; use futures::channel::mpsc;
use gateway_client::AcknowledgementReceiver;
use log::*; use log::*;
use nym_gateway_client::AcknowledgementReceiver;
use nym_sphinx::anonymous_replies::requests::AnonymousSenderTag; use nym_sphinx::anonymous_replies::requests::AnonymousSenderTag;
use nym_sphinx::params::PacketSize; use nym_sphinx::params::PacketSize;
use nym_sphinx::{ use nym_sphinx::{

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