Compare commits

..

157 Commits

Author SHA1 Message Date
Bogdan-Ștefan Neacșu 28e330821e Try adding contract feature 2023-06-29 18:54:15 +03:00
Bogdan-Ștefan Neacșu f46ab0dc68 Merge remote-tracking branch 'origin' into feature/ephemera 2023-06-29 14:49:23 +03:00
Jon Häggblad 31568b544c Minor fixes to support harbourmaster beacon (#3618)
* wip

* wip
2023-06-29 12:38:03 +02:00
Bogdan-Ștefan Neacşu 7e0d016375 Umock contract membership of ephemera (#3574)
* Pass nyxd client to members provider

* Basic ephemera contract

* Add register peer tx

* Add query all peers

* Nyxd ephemera client

* Add registration of ephemera peer

* Replace epoch http api with actual contract

* Merge ephemera config into nym-api config

* Load cluster from contract
2023-06-28 19:00:52 +03:00
Jon Häggblad ed76000dd0 Remove unmaintained upgrade commands (#3599)
* Remove unmaintained upgrade commands

* Remove unused with_custom_version functions
2023-06-28 15:59:27 +02:00
Pierre Dommerc 0dfe1460e4 fix lint (#3612) 2023-06-28 13:43:43 +02:00
Dave Hrycyszyn e06087ad3f Made a few additions to upgrade notes 2023-06-28 12:24:21 +02:00
Pierre Dommerc 0a6a015987 feat(nc): monitoring update (#3609) 2023-06-28 12:20:29 +02:00
mx efd8ba5978 hotfix on broken releases page link 2023-06-27 16:09:59 +02:00
mx 0c7181a211 * updated libwasmvm.so linking instructions
* added note on upgrading to v0.31.1
2023-06-27 16:09:53 +02:00
Jon Häggblad f47a111640 Merge remote-tracking branch 'origin/release/v1.1.23' into develop 2023-06-27 15:52:03 +02:00
Bogdan-Ștefan Neacșu 13c6296c3f Merge remote-tracking branch 'origin/develop' into feature/ephemera 2023-06-27 14:56:59 +03:00
mx ae5a9ccc50 Merge pull request #3601 from nymtech/revert-3593-feature/release-1-1-22-docs
Revert "Feature/release 1 1 22 docs"
2023-06-27 09:29:14 +00:00
mx 40465665f0 Revert "Feature/release 1 1 22 docs" 2023-06-27 09:28:49 +00:00
mx 8c437ac964 Merge pull request #3593 from nymtech/feature/release-1-1-22-docs
Feature/release 1 1 22 docs
2023-06-27 09:28:33 +00:00
benedettadavico f3b17ad2f8 Revert contract version 2023-06-27 09:57:17 +02:00
benedettadavico 9121078576 Update versions and changelog for release v1.1.23 2023-06-27 09:48:35 +02:00
mx c505a00fac pulled in renamed example file 2023-06-26 17:37:01 +02:00
mx 09bad9c6b4 * updated libwasmvm.so linking instructions
* added note on upgrading to v0.31.1
2023-06-26 17:36:22 +02:00
pierre 597f5e9545 ci: fix typescript-lint.yml workflow 2023-06-26 16:21:37 +02:00
pierre 54cb7be1e1 chore: update copyright notice in comment headers 2023-06-26 16:09:24 +02:00
pierre 431c98e591 chore: update copyright notice date 2023-06-26 15:46:11 +02:00
Jon Häggblad 35f2e71202 Don't fully turn off background task when cover traffic is disabled (#3596)
* Don't fully turn off background task when cover traffic is disabled

* Leave no_cover function alone

* Add methods on config struct instead of explicitly setting options

* Add medium toggle to network-requester run command

* clippy

* rustfmt

* Unused
2023-06-26 15:36:07 +02:00
pierre 0134030341 build(nc-android): fix release build (sentry) 2023-06-26 12:08:41 +02:00
pierre 97c775bc68 build(nc-android): fix release build (sentry) 2023-06-26 11:59:59 +02:00
mx 62ba6b30ae updated link to releases page: now wallet version specific 2023-06-26 10:50:03 +02:00
mx 24354275d3 version bumps 2023-06-26 10:49:36 +02:00
mx 76335e9adc removed --wallet-address from commands 2023-06-26 10:32:28 +02:00
mx bab8eb746e version bump + included new wallet version var 2023-06-26 10:32:02 +02:00
Jon Häggblad f298f5d4fa Auto-upgrade nym-connect config files (#3589)
* nym-connect: auto-upgrade old config files

* Move upgrade functions to separate file
2023-06-26 10:09:45 +02:00
mx 85b078a3e8 Merge branches 'release/v1.1.21' and 'release/v1.1.22' of github.com:nymtech/nym into release/v1.1.22 2023-06-26 09:54:31 +02:00
Fouad 0115b02be3 Wallet - Node Tester (#3551)
* error handling + edge cases + types

* use bonded node id

* add UI and move feature to node-settings dir

* use error modal

* add type for postMessage arg

* add timeout for node test

* update storybook ci

* fix CI for typescript linting

* fix print node test results

* replace react-to-print lib with vanilla solution

* async print

* update wallet changelog
2023-06-23 14:00:28 +01:00
Jon Häggblad a4ffd135e7 Fix the medium toggle in nym-connect (#3590) 2023-06-22 16:30:25 +02:00
pierre bbce67902b ci(nc-android): disable release apk (unused) 2023-06-22 15:36:30 +02:00
pierre e6930046c4 ci(nc-android): disable release apk (unused) 2023-06-22 15:18:36 +02:00
pierre 0c9402503a Merge branch 'feature/nyms5-android-sentry' into develop 2023-06-22 14:23:33 +02:00
pierre 81e133b789 feat(nc-android): sentry integration and topbar navigation 2023-06-22 14:21:24 +02:00
Bogdan-Ștefan Neacșu 2f29e33f1e Merge remote-tracking branch 'origin/develop' into feature/ephemera 2023-06-22 13:36:37 +03:00
Jon Häggblad 7be07c29c1 Cargo.lock 2023-06-22 10:59:59 +02:00
Jon Häggblad 31bc439f65 Cargo.lock 2023-06-22 10:59:08 +02:00
Jon Häggblad 6479480cf7 Merge remote-tracking branch 'origin/release/v1.1.23' into develop 2023-06-22 10:57:52 +02:00
Jon Häggblad 4af70ef255 nym-connect: medium speed setting (#3585)
* Lock files

* Add flag to disable cover traffic

* Add flag to disable per hop delays

* Add flag to enable mixed size packets

* Add meta flag to set medium speed

* Special case zero averge hop delay to be exactly zero

* Extract out generate_hop_delays function
2023-06-22 10:55:35 +02:00
Jędrzej Stuczyński eba58f6451 NC: load old gateway configuration if we're not registering (#3586) 2023-06-22 08:49:00 +01:00
Jon Häggblad 35206655e0 Lock files 2023-06-21 09:01:47 +02:00
Jon Häggblad e14db00fc2 nym-cli: client identity signing support (#3575)
* Add client identity key signing to nym-cli

* Only load private key

* rustfmt

* Rename to identity key since it's generic

* Rename client_key to identity_key
2023-06-20 14:48:53 +02:00
benedettadavico 72b92784cc Merge remote-tracking branch 'origin/develop' into develop 2023-06-20 13:45:29 +02:00
benedettadavico 38b95c2673 nym connect version fix 2023-06-20 13:45:04 +02:00
Mark Sinclair f0f9899f82 Update package.json to fix build:dev target 2023-06-20 12:12:03 +01:00
benedettadavico 09c46e3403 Merge remote-tracking branch 'origin/master' into develop 2023-06-20 10:36:06 +02:00
benedettadavico 9fbab5aaad updating versions for release v1.1.22 2023-06-20 10:24:54 +02:00
benedettadavico 2032b3bdae updating versions for release v1.1.22 2023-06-20 09:51:28 +02:00
Jędrzej Stuczyński 8f57919571 optional id argument for NymNodeTester (#3555) 2023-06-16 11:19:40 +01:00
Jon Häggblad 3748ab77a1 Statically link openssl (#3504)
* Statically link openssl

* Fix wasm client build

* Enable openssl for nyxd-client feature
2023-06-16 11:27:25 +02:00
Bogdan-Ștefan Neacșu 8325001e8c Merge remote-tracking branch 'origin/develop' into feature/ephemera 2023-06-16 12:25:55 +03:00
pierre 3cdca0ad8d copy change 2023-06-16 11:20:20 +02:00
pierre 9cbb3dfa0e copy change 2023-06-16 11:19:44 +02:00
Pierre Dommerc 4071d30f3c feat(nc-desktop): add error reporting and monitoring setting (#3553) 2023-06-16 11:09:29 +02:00
Bogdan-Ștefan Neacşu 666c11cc28 Start ephemera components in nym-api (#3475)
* Start ephemera components in nym-api

* Pass nyxd client and use common metric structures

* Swap url endpoint with contract for sending rewarding messages

* Fix build after rebase

* Perform ephemera rewards computation before normal nym-api ones

* Remove contract mock from ephemera

* Take raw rewards from network monitor

* Remove ephemera old reward version

* Use nym shutdown procedure in ephemera

* Temporary fix for some warnings
2023-06-16 11:22:00 +03:00
pierre 4c13d91bfb fix(nyms5-android): add check for worker and proxy states desync 2023-06-16 10:08:57 +02:00
Pierre Dommerc 8355e6ce5e feat(nc-desktop): add error reporting and monitoring setting (#3553) 2023-06-15 19:23:23 +02:00
Bogdan-Ștefan Neacșu 04f910fbf3 Merge remote-tracking branch 'origin/develop' into feature/ephemera 2023-06-15 10:46:15 +03:00
Tommy Verrall dd33052f0e Merge pull request #3520 from nymtech/bugfix/incorrect-client-versions
bugfix #3434
2023-06-14 17:23:11 +01:00
Jędrzej Stuczyński a76a51e823 fixed config version of binaries depending on socks5 core configs 2023-06-14 17:16:07 +01:00
mx 4caa9390cf Merge pull request #3546 from twofaktor/patch-2
[UPDATE DOCS] socks5-client
2023-06-14 14:08:16 +00:00
Jon Häggblad b31d3c003f Cargo.lock 2023-06-14 15:04:37 +02:00
Jon Häggblad 21e11c9221 Merge remote-tracking branch 'origin/master' into release/v1.1.22 2023-06-14 14:55:30 +02:00
Jon Häggblad c9dcde0ee0 getrandom on workspace level 2023-06-14 13:26:09 +02:00
Jon Häggblad 3fcc16090a Update nym-outfox Cargo.toml in prep for publish to crates.io 2023-06-14 13:15:40 +02:00
Jędrzej Stuczyński bbb1e5e15a Feature/node tester disconnect (#3552)
* Ability to disconnect and reconnect GatewayClient

* usage of ibid. inside NodeTester

* example

* wasm-compatible `wait_for_shutdown` (for the future)
2023-06-13 17:25:42 +01:00
Drazen Urch 6d30e7ea8e Adjustments to cover traffic and ack handling (#3548) 2023-06-13 13:07:02 +02:00
Bogdan-Ștefan Neacșu 315652b26a Merge remote-tracking branch 'origin/develop' into feature/ephemera 2023-06-13 12:32:05 +03:00
farbanas 9288f71c5f Merge branch 'master' into develop 2023-06-13 11:16:17 +02:00
farbanas 79f5983c76 updating lock files 2023-06-13 11:04:36 +02:00
farbanas 335453b63c update versions and changelog for release v1.1.21 2023-06-13 10:54:01 +02:00
Jędrzej Stuczyński 4292a55614 explicitly setting up fresh gateway in native socks5 (#3547) 2023-06-12 17:01:05 +01:00
⚡️2FakTor⚡️ 92e902c81e Update socks5-client.md 2023-06-12 15:54:13 +02:00
⚡️2FakTor⚡️ c47bc174bc Update socks5-client.md 2023-06-12 15:47:28 +02:00
mx f97f0475e9 Merge pull request #3545 from nymtech/feature/docs-1-1-21
version bump for variables
2023-06-12 12:04:16 +00:00
mx 67a945a15f version bump for variables 2023-06-12 13:45:49 +02:00
Tommy Verrall d1a28826d5 Merge pull request #3535 from nymtech/feature/socks5-message-ordering
Feature/socks5 message ordering
2023-06-12 11:47:35 +01:00
Tommy Verrall 8f026ab6c6 Update build-and-upload-binaries-ci.yml
temp use rust version 1.69.0 for ci build uploads, will need to switch and use: cosmwasm/rust-optimizer in the near future
2023-06-12 11:07:22 +01:00
Jędrzej Stuczyński bdcdcf7f8b clippy 2023-06-12 10:20:13 +01:00
Jędrzej Stuczyński 182e147a86 fixed and updated related units tests 2023-06-12 10:20:13 +01:00
Jędrzej Stuczyński 687b437ea0 cargo fmt 2023-06-12 10:20:13 +01:00
Jędrzej Stuczyński f2c5dbb696 deadcode 2023-06-12 10:20:13 +01:00
Jędrzej Stuczyński a8bf690c17 tests 2023-06-12 10:20:13 +01:00
Jędrzej Stuczyński 1328ba35be removed original Ordered sender 2023-06-12 10:20:13 +01:00
Jędrzej Stuczyński 8b046d4139 split up functions a bit more 2023-06-12 10:20:13 +01:00
Jędrzej Stuczyński f4cd372808 simplified keeping track of message sequence 2023-06-12 10:20:13 +01:00
Jędrzej Stuczyński 7228331db6 removed OrderedMessage 2023-06-12 10:20:13 +01:00
Jędrzej Stuczyński 45f3f3ec01 cleanup 2023-06-12 10:20:13 +01:00
Jędrzej Stuczyński 5f9e54c83c buggy, but backwards compatible, explicit sequencing 2023-06-12 10:20:13 +01:00
Jędrzej Stuczyński f8c2f90502 initial work on putting data sequence explicitly inside socks5 request 2023-06-12 10:20:13 +01:00
Jon Häggblad 96e8bdfea4 Reduce number of surbs in nym-nr-query ping (#3540) 2023-06-12 09:53:47 +02:00
Jon Häggblad 0fa1961a04 nym-nr-query CLI tool for query network-requester (#3538)
* Initial version

* Add open_proxy request

* Start adding cli commands

* use commands

* Common response type

* json output

* Tidy

* Remove the All case

* Remove empty file

* Remove todo

* Add ping command

* Ping 4 times by default

* Logic for controlling number of loops

* Some print tweaks
2023-06-12 09:30:02 +02:00
pierre 88002969b7 ci(nyms5-android): add debug apk build 2023-06-09 22:46:04 +02:00
pierre b90dedf3ae build(android): fix repro build wip 2023-06-09 17:11:15 +02:00
pierre 582cb32223 build(android): fix repro build wip 2023-06-09 16:34:50 +02:00
Jędrzej Stuczyński 31b7921c68 bugfix #3434 2023-06-09 15:12:56 +01:00
Jędrzej Stuczyński 42a43a3709 Feature/extract gateway config (#3517)
* wip client core

* hashing shared key in persisted details

* native client using on-disk gateway details

* ibid for socks5

* ibid for NR

* nym sdk

* non-wasm fixes

* wasm

* missed cargo fmt

* fixed nym-connect build

* changed serialization of the key hash to be more human readable

* allowing some dead code

* fixed gateway details deserializtion

* removed needless borrow in wasm client

* removed deadcode

* exhaustive match on GatewaySetup after having loaded the keys
2023-06-09 15:12:29 +01:00
Jędrzej Stuczyński c5ad4006ae simplified construction of 'BaseClient' (#3513) 2023-06-09 15:11:45 +01:00
Tommy Verrall 71fb6a1ba1 Merge pull request #3516 from nymtech/feature/explorer-sp-extra-detail
Explorer - Extra detail for Service Providers
2023-06-09 10:01:59 +01:00
Jon Häggblad 68a37bc692 Merge remote-tracking branch 'origin/release/v1.1.21' into develop 2023-06-09 09:54:53 +02:00
Jon Häggblad 542fd92a46 Allow query network-requestor for open_proxy (#3531)
* wip: playing around

* WIP

* wip

* Add query request

* Create new example

* Restore control_requests example

* Remove ControlRequest::OpenProxy

* Remove Socks5RequestContent::OpenProxy

* Remove bunch of debug logging

* Remove more old leftovers

* Another few lines of leftovers to remove

* Disable logging in example

* Return error if incoming request if future version

* Serialization unit tests

* Network requester in example

* Cargo.lock
2023-06-09 09:54:21 +02:00
pierre 527c71d3df fix(nyms5-android): clean code 2023-06-08 18:45:02 +02:00
pierre 7ee47bdb4c fix(nyms5-android): fix notif channel creation on android prior to 12 2023-06-08 18:44:18 +02:00
pierre 9fa36b6393 add a log on channel creation 2023-06-08 11:06:14 +02:00
pierre 2b40b96aa1 wip 2023-06-08 11:06:14 +02:00
Jędrzej Stuczyński 9a68702d4d Feature/config refactor (#3498)
* revamping mixnode connfig

* wip

* native client config revamping

* wip

* building socks5

* using const for mixnnode config template

* compiling updated gateway

* nym-api

* nym-sdk

* everything compiling once more

but definitely not compatible with CI and older versions (yet)

* creating full directory structure on init

* renamed paths to storage_paths and fixed mixnode template

* mixnode config migration

* gateway config migration

* nym-api config migration

* native client config migration

* socks5 client config migration

* NR config migration

* removed deprecations (that will be resolved in the following PRs) + fixed clippy

* nym-connect clippy

* nym-connect config updates

* outfox fixes

* defined socks5 lib config

* clippy

* fixed wasm client build

* removed explicit packet_type argument when starting base client

it's known implicitly from the previously passed config struct

* Empty commit

* fixed re-using gateway information when client configs are re-initialised

* fixed borrowing id value in nym-connect

* post-rebase fixes

* updated 'old_config' versions

---------

Co-authored-by: Tommy Verrall <tommy@nymtech.net>
2023-06-07 17:06:35 +01:00
Drazen Urch bc5198768e Push traces to jaeger (#3522)
* Push traces to jaeger

* Remove default feature

* Update toolchain
2023-06-07 17:32:26 +02:00
Jon Häggblad 892653cd96 Remove gateway from detailed service provider type 2023-06-07 14:09:13 +02:00
Jon Häggblad a7471ef324 Replace fold with collect 2023-06-07 14:06:12 +02:00
fmtabbara 403141c1f5 add tooltip to sp routing score 2023-06-07 12:22:59 +01:00
fmtabbara d8c82bf6d0 use default sort order 2023-06-07 12:05:32 +01:00
fmtabbara dd86ba36dd use default success ping time - 120 mins 2023-06-07 11:56:44 +01:00
Tommy Verrall 42acbfe806 Update build-and-upload-binaries-ci.yml
temp use rust version 1.69.0 for ci build uploads, will need to switch and use: cosmwasm/rust-optimizer in the near future
2023-06-07 11:24:53 +02:00
farbanas 7c55483585 Merge branch 'master' into develop 2023-06-07 10:43:11 +02:00
fmtabbara 0320220219 refactor 2023-06-06 22:56:13 +01:00
fmtabbara e32ee2ccf3 add service-type and routing-scores to sps + allow sorting on routing scores 2023-06-06 22:45:09 +01:00
fmtabbara b8ca1762c2 allow sp routing score to be undefined 2023-06-06 22:45:07 +01:00
pierre d1e9fcf03a make routing score optional 2023-06-06 16:44:17 +02:00
pierre 303a774378 add some logs 2023-06-06 15:25:29 +02:00
pierre c9ca71f47b wip 2023-06-06 14:50:25 +02:00
pierre 92faf1e3d5 wip 2023-06-06 14:22:52 +02:00
fmtabbara e509989ac3 wip 2023-06-06 10:04:50 +01:00
farbanas c04cc9a4cf Merge branch 'release/v1.1.20' 2023-06-06 10:54:17 +02:00
farbanas 17258d1445 updated locks and versions bumped 2023-06-06 10:35:42 +02:00
farbanas 8f3d7606f5 bump crate versions 2023-06-06 10:07:06 +02:00
farbanas fd97f0e8ca update changelogs and version for release 2023-06-06 10:00:11 +02:00
Jędrzej Stuczyński d4ce1635a8 Fixed incorrect assertion when sending replies (#3515) 2023-06-05 14:36:44 +01:00
Jędrzej Stuczyński 2bc564ad01 updating managed keys after gateway registration (#3514) 2023-06-05 14:09:28 +01:00
Tommy Verrall 5910bcbc02 Update build-and-upload-binaries-ci.yml
add the service provider and name service contract to build output
2023-06-05 14:49:49 +02:00
Tommy Verrall 8c63fe9d0d Merge pull request #3507 from nymtech/jon/feat/reduce-shutdown-timeout-in-socks5
Reduce SHUTDOWN_TIMEOUT to 3 sec
2023-06-05 10:30:34 +01:00
Pierre Dommerc 6e5a1973da fix(wallet): fix bonding data refresh (#3499) 2023-06-05 11:07:23 +02:00
Pierre Dommerc 1aa11887aa fix(wallet): fix bonding data refresh (#3499) 2023-06-05 11:05:25 +02:00
Jon Häggblad 07740cbf08 Reduce SHUTDOWN_TIMEOUT to 3 sec
Can't think of a scenario where we don't want to close one at the same
time as the other, but let's be conservative and keep it a very low
number for now.
2023-06-05 10:42:38 +02:00
Jon Häggblad 87cb8a6b20 Sign when announcing service providers to the directory contract (#3459)
* create_payload and call from nym-cli

* Remove some commented out code

* wip

* Service announce now compiles

* Fix other compilation issues

* Move ServiceDetails into Service

* Move service_id inside Service type

* wip: start sorting out tests

* wip: sorting out testing

* wip: first announce test now works

* wip: more work on announce test

* Move nonce

* Add check for nonce

* Extract out some helpers to separate files

* reenable state::services tests

* wip: start going through the integration tests

* All integration tests reenabled

* Remove some unused stuff

* Iterate on integration tests

* More iteration on test setup

* Rename to test_setup.rs

* Add more tests specific to signing

* Tweak

* Another nonce test and reorg

* Rename to announce.rs and delete.rs

* Tidy

* Make some inner modules private

* Use IdentityKey alias

* Update nym-api contract cache

* Fix that nym-cli was asking for signing nonce from wrong contract

* Add sign comment to network-requester

* Uploaded updated service provider contract to qwerty

* Allow large enum variant

* lock files

* Remove dbg

* Move error.rs to service-provider common

* Update code for moving errors.rs to common crate

* Rename to SpContractError

* constants module not pub

* lock file

* rustfmt

* Move IdentityKey type to contract-common

* clippy
2023-06-05 10:32:58 +02:00
Jon Häggblad 2977b8f25f Fix clippy for 1.70 (#3505) 2023-06-05 08:54:18 +01:00
mx 019b3299f2 Merge pull request #3435 from Pawnflake/release/v1.1.19
mixnode documentation update
2023-06-02 09:40:50 +00:00
mx d684957423 Update documentation/docs/src/nodes/mix-node-setup.md
Co-authored-by: ️2FakTor️ <twofaktor@protonmail.com>
2023-06-02 09:20:56 +00:00
mx cb4eda4c62 Update documentation/docs/src/nodes/mix-node-setup.md
Co-authored-by: ️2FakTor️ <twofaktor@protonmail.com>
2023-06-02 09:20:42 +00:00
mx ac5f380ee2 Merge pull request #3485 from nymtech/feature/docs-1-1-20
removing hardcoded version numbers
2023-06-02 09:20:10 +00:00
mx 4e278ca07d reintroduced hardcoding for links for moment 2023-06-02 10:52:28 +02:00
mx cd6a725875 Merge pull request #3493 from twofaktor/patch-1
[BUG] network requester documentation update
2023-06-02 08:42:20 +00:00
⚡️2FakTor⚡️ d5514a060c Update network-requester-setup.md 2023-05-31 15:22:11 +02:00
mx 958b6d37ee Merge pull request #3481 from twofaktor/patch-1
[BUG] network requester documentation update
2023-05-30 14:40:33 +00:00
mx 5e36bb014c removing hardcoded versoin numbers 2023-05-30 16:10:15 +02:00
⚡️2FakTor⚡️ 8d821881ae Update network-requester-setup.md 2023-05-30 14:48:51 +02:00
mx fca9761145 Merge pull request #3141 from nymtech/chore/update-community-links-in-readme
updated readme with new developer chat links + new docs links
2023-05-30 12:05:14 +00:00
mx 11481e4d13 Merge branch 'release/v1.1.20' into chore/update-community-links-in-readme 2023-05-30 12:04:45 +00:00
Bogdan-Ștefan Neacșu 56a5d847c4 Merge remote-tracking branch 'origin/develop' into feature/ephemera 2023-05-30 14:09:04 +03:00
Bogdan-Ștefan Neacşu 29f95febe9 Feature/ephemera compile (#3437)
* Include ephemera node code in repo

* Upgrade deps

* Bump minor version of cosmwasm-std

* Include ephemera in nym-api dep and downgrade rusqlite

* Fix clippy and ephemera docs code

* More clippy on ephemera

---------

Co-authored-by: Andrus Salumets <andrus@nymtech.net>
2023-05-25 11:24:49 +03:00
Pawnflake c8b82a9553 removed comment http and https 2023-05-20 07:23:13 +08:00
mx 00c2f5359c Merge pull request #3428 from nymtech/feature/updated-sandbox-docs
added sandbox sync docs
2023-05-16 14:53:51 +00:00
mx 1a4e0f4e08 added sandbox sync docs 2023-05-16 16:44:39 +02:00
Pawnflake 69230a10cb Added ufw restart after adding ports and removed port 80 and 443 from the command 2023-05-16 10:10:41 +08:00
mx 3a0c8f3f4e updated readme with new developer chat links + new docs links 2023-03-03 13:32:44 +01:00
504 changed files with 31230 additions and 7499 deletions
@@ -107,6 +107,8 @@ jobs:
cp contracts/target/wasm32-unknown-unknown/release/nym_coconut_dkg.wasm $OUTPUT_DIR
cp contracts/target/wasm32-unknown-unknown/release/cw3_flex_multisig.wasm $OUTPUT_DIR
cp contracts/target/wasm32-unknown-unknown/release/cw4_group.wasm $OUTPUT_DIR
cp contracts/target/wasm32-unknown-unknown/release/nym_service_provider_directory.wasm $OUTPUT_DIR
cp contracts/target/wasm32-unknown-unknown/release/nym_name_service.wasm $OUTPUT_DIR
- name: Deploy branch to CI www
continue-on-error: true
@@ -19,6 +19,16 @@ jobs:
node-version: 16
- name: Setup yarn
run: npm install -g yarn
- name: Install Rust stable
uses: actions-rs/toolchain@v1
with:
toolchain: stable
- name: Install wasm-pack
run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
working-directory: clients/webassembly
- name: Build WASM
run: wasm-pack build
working-directory: clients/webassembly
- name: Build dependencies
run: yarn && yarn build
- name: Build storybook
+15 -6
View File
@@ -49,7 +49,7 @@ jobs:
"build-tools;$SDK_BUILDTOOLS_VERSION"
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
uses: dtolnay/rust-toolchain@1.70.0
- name: Install rust android targets
run: |
@@ -60,6 +60,7 @@ jobs:
working-directory: sdk/lib/socks5-listener/
env:
RELEASE: true
RUSTFLAGS: "-C link-args=-Wl,--hash-style=gnu"
# build for arm64 and x86_64
run: ./build-android.sh aarch64 x86_64
@@ -67,20 +68,27 @@ jobs:
working-directory: nym-connect/native/android
env:
ANDROID_SDK_ROOT: ${{ env.ANDROID_HOME }}
SENTRY_AUTH_TOKEN: ${{ secrets.NYMS5_ANDROID_SENTRY_AUTH_TOKEN }}
# build for arm64 and x86_64
run: ./gradlew :app:assembleArch64Release
run: |
echo "auth.token=$SENTRY_AUTH_TOKEN" | tee -a sentry.properties
./gradlew :app:assembleArch64Debug
./gradlew :app:assembleArch64Release
- name: Prepare APKs
run: |
mkdir apk
mv nym-connect/native/android/app/build/outputs/apk/arch64/debug/app-arch64-debug.apk \
apk/nyms5-arch64-debug.apk
mv nym-connect/native/android/app/build/outputs/apk/arch64/release/app-arch64-release-unsigned.apk \
apk/nyms5-arch64-release.apk
- name: Upload APKs
uses: actions/upload-artifact@v3
with:
name: nyms5-apk-arch64-release
name: nyms5-apk-arch64
path: |
apk/nyms5-arch64-debug.apk
apk/nyms5-arch64-release.apk
gh-release:
@@ -93,10 +101,11 @@ jobs:
- name: Download binary artifact
uses: actions/download-artifact@v3
with:
name: nyms5-apk-arch64-release
name: nyms5-apk-arch64
path: apk
- name: Release
uses: softprops/action-gh-release@v1
with:
files: apk/nyms5-arch64-release.apk
files: |
apk/nyms5-arch64-debug.apk
apk/nyms5-arch64-release.apk
+10
View File
@@ -36,6 +36,16 @@ jobs:
node-version: 16
- name: Setup yarn
run: npm install -g yarn
- name: Install Rust stable
uses: actions-rs/toolchain@v1
with:
toolchain: stable
- name: Install wasm-pack
run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
working-directory: clients/webassembly
- name: Build WASM
run: wasm-pack build
working-directory: clients/webassembly
- name: Install
run: yarn
- name: Build packages
+71
View File
@@ -4,6 +4,77 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
## [Unreleased]
## [1.1.23] (2023-06-27)
- nym-cli: add client identity key signing support ([#3576])
- Don't fully turn off background task when cover traffic is disabled ([#3596])
[#3576]: https://github.com/nymtech/nym/issues/3576
[#3596]: https://github.com/nymtech/nym/pull/3596
## [v1.1.22] (2023-06-20)
- CLI tool for querying network-requesters ([#3539])
- Statically link OpenSSL ([#3510])
- NymConnect - add sentry.io reporting ([#3421])
- init command does not change version number in config.toml ([#3336])
- [Bug] Config version does not correspond to binary version ([#3434])
[#3539]: https://github.com/nymtech/nym/issues/3539
[#3510]: https://github.com/nymtech/nym/issues/3510
[#3421]: https://github.com/nymtech/nym/issues/3421
[#3336]: https://github.com/nymtech/nym/issues/3336
[#3434]: https://github.com/nymtech/nym/issues/3434
## [v1.1.21] (2023-06-13)
- mixFetch: Change socks5 `SendRequest` to include OrderedMessage index as a field rather than making it serialized inside the `data` field
([#3534])
- Explorer - add more data columns to the Service Provider section: ([#3474])
- network-requester: support report if they run an open proxy using `ControlRequest` API ([#3461])
- Refactor client configs (London discussion) ([#3444])
- Increase `DEFAULT_MAXIMUM_CONNECTION_BUFFER_SIZE` to 2000 to improve reliability ([#3433])
- socks5: sender waits for lanes to clear even though the connection is closed ([#3366])
- version bump for variables ([#3545])
[#3534]: https://github.com/nymtech/nym/issues/3534
[#3474]: https://github.com/nymtech/nym/issues/3474
[#3461]: https://github.com/nymtech/nym/issues/3461
[#3444]: https://github.com/nymtech/nym/issues/3444
[#3433]: https://github.com/nymtech/nym/issues/3433
[#3366]: https://github.com/nymtech/nym/issues/3366
[#3545]: https://github.com/nymtech/nym/pull/3545
## [v1.1.20] (2023-06-06)
- Explorer - Fix SP supported apps list ([#3458])
- Investigate if we need to lower `SHUTDOWN_TIMEOUT` in socks5 to zero (or almost zero) ([#3438])
- Explorer - show all gateways in the default view regardless of the version number ([#3427])
- service-provider-directory: add signature check when announcing ([#3360])
- Support functionality for nym-name-service (nym-api, nym-cli, etc) ([#3355])
- Edit the nym-network-requester to support the enabled-credentials-mode flag ([#3101])
- [BUG] network requester documentation update ([#3493])
- removing hardcoded version numbers ([#3485])
- [BUG] network requester documentation update ([#3481])
- [BUG] network requester documentation update ([#3469])
- Sign when announcing service providers to the directory contract ([#3459])
- mixnode documentation update ([#3435])
- updated readme with new developer chat links + new docs links ([#3141])
[#3458]: https://github.com/nymtech/nym/issues/3458
[#3438]: https://github.com/nymtech/nym/issues/3438
[#3427]: https://github.com/nymtech/nym/issues/3427
[#3360]: https://github.com/nymtech/nym/issues/3360
[#3355]: https://github.com/nymtech/nym/issues/3355
[#3101]: https://github.com/nymtech/nym/issues/3101
[#3493]: https://github.com/nymtech/nym/pull/3493
[#3485]: https://github.com/nymtech/nym/pull/3485
[#3481]: https://github.com/nymtech/nym/pull/3481
[#3469]: https://github.com/nymtech/nym/pull/3469
[#3459]: https://github.com/nymtech/nym/pull/3459
[#3435]: https://github.com/nymtech/nym/pull/3435
[#3141]: https://github.com/nymtech/nym/pull/3141
## [v1.1.19] (2023-05-16)
- nym-name-service endpoint in nym-api ([#3403])
Generated
+3310 -160
View File
File diff suppressed because it is too large Load Diff
+17 -11
View File
@@ -34,6 +34,7 @@ members = [
"common/cosmwasm-smart-contracts/coconut-bandwidth-contract",
"common/cosmwasm-smart-contracts/coconut-dkg",
"common/cosmwasm-smart-contracts/contracts-common",
"common/cosmwasm-smart-contracts/ephemera",
"common/cosmwasm-smart-contracts/group-contract",
"common/cosmwasm-smart-contracts/mixnet-contract",
"common/cosmwasm-smart-contracts/multisig-contract",
@@ -87,6 +88,7 @@ members = [
"nym-api/nym-api-requests",
"nym-outfox",
"tools/nym-cli",
"tools/nym-nr-query",
"tools/ts-rs-cli"
]
@@ -112,22 +114,26 @@ edition = "2021"
license = "Apache-2.0"
[workspace.dependencies]
async-trait = "0.1.64"
anyhow = "1.0.71"
async-trait = "0.1.64"
bip39 = { version = "2.0.0", features = ["zeroize"] }
cfg-if = "1.0.0"
cosmwasm-derive = "=1.0.0"
cosmwasm-schema = "=1.0.0"
cosmwasm-std = "=1.0.0"
cosmwasm-storage = "=1.0.0"
cw-utils = "=0.13.4"
cw-storage-plus = "=0.13.4"
cw2 = { version = "=0.13.4" }
cw3 = { version = "=0.13.4" }
cw3-fixed-multisig = { version = "=0.13.4" }
cw4 = { version = "=0.13.4" }
cosmwasm-derive = "=1.2.5"
cosmwasm-schema = "=1.2.5"
cosmwasm-std = "=1.2.5"
cosmwasm-storage = "=1.2.5"
cosmrs = "=0.8.0"
cw-utils = "=1.0.1"
cw-storage-plus = "=1.0.1"
cw2 = { version = "=1.0.1" }
cw3 = { version = "=1.0.1" }
cw3-fixed-multisig = { version = "=1.0.1" }
cw4 = { version = "=1.0.1" }
cw-controllers = { version = "=1.0.1" }
dotenvy = "0.15.6"
generic-array = "0.14.7"
k256 = "0.11"
getrandom = "0.2.10"
lazy_static = "1.4.0"
log = "0.4"
once_cell = "1.7.2"
+7 -3
View File
@@ -21,8 +21,8 @@ The platform is composed of multiple Rust crates. Top-level executable binary cr
### Building
Platform build instructions are available on [our docs site](https://nymtech.net/docs/binaries/building-nym.html).
Wallet build instructions are also available on [our docs site](https://nymtech.net/docs/stable/nym-apps/wallet#for-developers).
Platform build instructions are available on [our docs site](https://nymtech.net/docs/binaries/build-nym.html).
Wallet build instructions are also available on [our docs site](https://nymtech.net/docs/wallet/desktop-wallet.html).
### Developing
@@ -32,7 +32,11 @@ For Typescript components, please see [ts-packages](./ts-packages).
### Developer chat
You can chat with us in [Keybase](https://keybase.io). Download their chat app, then click **Teams -> Join a team**. Type **nymtech.friends** into the team name and hit **continue**. For general chat, hang out in the **#general** channel. Our development takes place in the **#dev** channel. Node operators should be in the **#node-operators** channel.
> We used to use Keybase for developer chats, but we have since migrated to Matrix and Discord. We no longer check the old **nymtech.friends** Keybase team.
You can chat to us in two places:
* The #dev channel on [Matrix](https://matrix.to/#/#dev:nymtech.chat)
* The various developer channels on [Discord](https://discord.gg/nym)
### Rewards
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "nym-client"
version = "1.1.19"
version = "1.1.23"
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jędrzej Stuczyński <andrew@nymtech.net>"]
description = "Implementation of the Nym Client"
edition = "2021"
+16 -15
View File
@@ -20,7 +20,8 @@ pub use nym_client_core::config::Config as BaseClientConfig;
pub use nym_client_core::config::{DebugConfig, GatewayEndpointConfig};
pub mod old_config_v1_1_13;
pub mod old_config_v1_1_19;
pub mod old_config_v1_1_20;
pub mod old_config_v1_1_20_2;
mod persistence;
mod template;
@@ -52,19 +53,6 @@ pub fn default_data_directory<P: AsRef<Path>>(id: P) -> PathBuf {
.join(DEFAULT_DATA_DIR)
}
#[derive(Debug, Deserialize, PartialEq, Eq, Serialize, Clone, Copy)]
#[serde(deny_unknown_fields)]
pub enum SocketType {
WebSocket,
None,
}
impl SocketType {
pub fn is_websocket(&self) -> bool {
matches!(self, SocketType::WebSocket)
}
}
#[derive(Debug, Deserialize, PartialEq, Serialize)]
pub struct Config {
#[serde(flatten)]
@@ -87,7 +75,7 @@ impl NymConfigTemplate for Config {
impl Config {
pub fn new<S: AsRef<str>>(id: S) -> Self {
Config {
base: BaseClientConfig::new(id.as_ref()),
base: BaseClientConfig::new(id.as_ref(), env!("CARGO_PKG_VERSION")),
storage_paths: ClientPaths::new_default(default_data_directory(id.as_ref())),
logging: Default::default(),
socket: Default::default(),
@@ -187,6 +175,19 @@ impl Config {
// define_optional_set_inner!(Config, base, BaseClientConfig);
#[derive(Debug, Deserialize, PartialEq, Eq, Serialize, Clone, Copy)]
#[serde(deny_unknown_fields)]
pub enum SocketType {
WebSocket,
None,
}
impl SocketType {
pub fn is_websocket(&self) -> bool {
matches!(self, SocketType::WebSocket)
}
}
#[derive(Debug, Deserialize, PartialEq, Eq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct Socket {
@@ -1,7 +1,7 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::client::config::old_config_v1_1_19::{ConfigV1_1_19, SocketV1_1_19};
use crate::client::config::old_config_v1_1_20::{ConfigV1_1_20, SocketV1_1_20};
use nym_client_core::config::old_config_v1_1_13::OldConfigV1_1_13 as OldBaseConfigV1_1_13;
use nym_config::legacy_helpers::nym_config::MigrationNymConfig;
use serde::{Deserialize, Serialize};
@@ -13,7 +13,7 @@ pub struct OldConfigV1_1_13 {
#[serde(flatten)]
pub base: OldBaseConfigV1_1_13<OldConfigV1_1_13>,
pub socket: SocketV1_1_19,
pub socket: SocketV1_1_20,
}
impl MigrationNymConfig for OldConfigV1_1_13 {
@@ -25,9 +25,9 @@ impl MigrationNymConfig for OldConfigV1_1_13 {
}
}
impl From<OldConfigV1_1_13> for ConfigV1_1_19 {
impl From<OldConfigV1_1_13> for ConfigV1_1_20 {
fn from(value: OldConfigV1_1_13) -> Self {
ConfigV1_1_19 {
ConfigV1_1_20 {
base: value.base.into(),
socket: value.socket,
}
@@ -1,13 +1,16 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::client::config::persistence::ClientPaths;
use crate::client::config::{Config, Socket, SocketType};
use crate::client::config::old_config_v1_1_20_2::{
ClientPathsV1_1_20_2, ConfigV1_1_20_2, SocketTypeV1_1_20_2, SocketV1_1_20_2,
};
use nym_bin_common::logging::LoggingSettings;
use nym_client_core::config::disk_persistence::keys_paths::ClientKeysPaths;
use nym_client_core::config::disk_persistence::CommonClientPaths;
use nym_client_core::config::old_config_v1_1_19::ConfigV1_1_19 as BaseConfigV1_1_19;
use nym_client_core::config::{Client, Config as BaseConfig};
use nym_client_core::config::disk_persistence::old_v1_1_20_2::CommonClientPathsV1_1_20_2;
use nym_client_core::config::old_config_v1_1_20::ConfigV1_1_20 as BaseConfigV1_1_20;
use nym_client_core::config::old_config_v1_1_20_2::{
ClientV1_1_20_2, ConfigV1_1_20_2 as BaseConfigV1_1_20_2,
};
use nym_config::defaults::DEFAULT_WEBSOCKET_LISTENING_PORT;
use nym_config::legacy_helpers::nym_config::MigrationNymConfig;
use serde::{Deserialize, Serialize};
@@ -17,34 +20,34 @@ use std::path::PathBuf;
#[derive(Debug, Deserialize, PartialEq, Eq, Serialize, Clone, Copy)]
#[serde(deny_unknown_fields)]
pub enum SocketTypeV1_1_19 {
pub enum SocketTypeV1_1_20 {
WebSocket,
None,
}
impl From<SocketTypeV1_1_19> for SocketType {
fn from(value: SocketTypeV1_1_19) -> Self {
impl From<SocketTypeV1_1_20> for SocketTypeV1_1_20_2 {
fn from(value: SocketTypeV1_1_20) -> Self {
match value {
SocketTypeV1_1_19::WebSocket => SocketType::WebSocket,
SocketTypeV1_1_19::None => SocketType::None,
SocketTypeV1_1_20::WebSocket => SocketTypeV1_1_20_2::WebSocket,
SocketTypeV1_1_20::None => SocketTypeV1_1_20_2::None,
}
}
}
#[derive(Debug, Deserialize, PartialEq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct ConfigV1_1_19 {
pub struct ConfigV1_1_20 {
#[serde(flatten)]
pub base: BaseConfigV1_1_19<ConfigV1_1_19>,
pub base: BaseConfigV1_1_20<ConfigV1_1_20>,
pub socket: SocketV1_1_19,
pub socket: SocketV1_1_20,
}
impl From<ConfigV1_1_19> for Config {
fn from(value: ConfigV1_1_19) -> Self {
Config {
base: BaseConfig {
client: Client {
impl From<ConfigV1_1_20> for ConfigV1_1_20_2 {
fn from(value: ConfigV1_1_20) -> Self {
ConfigV1_1_20_2 {
base: BaseConfigV1_1_20_2 {
client: ClientV1_1_20_2 {
version: value.base.client.version,
id: value.base.client.id,
disabled_credentials_mode: value.base.client.disabled_credentials_mode,
@@ -55,8 +58,8 @@ impl From<ConfigV1_1_19> for Config {
debug: value.base.debug.into(),
},
socket: value.socket.into(),
storage_paths: ClientPaths {
common_paths: CommonClientPaths {
storage_paths: ClientPathsV1_1_20_2 {
common_paths: CommonClientPathsV1_1_20_2 {
keys: ClientKeysPaths {
private_identity_key_file: value.base.client.private_identity_key_file,
public_identity_key_file: value.base.client.public_identity_key_file,
@@ -74,7 +77,7 @@ impl From<ConfigV1_1_19> for Config {
}
}
impl MigrationNymConfig for ConfigV1_1_19 {
impl MigrationNymConfig for ConfigV1_1_20 {
fn default_root_directory() -> PathBuf {
dirs::home_dir()
.expect("Failed to evaluate $HOME value")
@@ -85,15 +88,15 @@ impl MigrationNymConfig for ConfigV1_1_19 {
#[derive(Debug, Deserialize, PartialEq, Eq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct SocketV1_1_19 {
socket_type: SocketTypeV1_1_19,
pub struct SocketV1_1_20 {
socket_type: SocketTypeV1_1_20,
host: IpAddr,
listening_port: u16,
}
impl From<SocketV1_1_19> for Socket {
fn from(value: SocketV1_1_19) -> Self {
Socket {
impl From<SocketV1_1_20> for SocketV1_1_20_2 {
fn from(value: SocketV1_1_20) -> Self {
SocketV1_1_20_2 {
socket_type: value.socket_type.into(),
host: value.host,
listening_port: value.listening_port,
@@ -101,10 +104,10 @@ impl From<SocketV1_1_19> for Socket {
}
}
impl Default for SocketV1_1_19 {
impl Default for SocketV1_1_20 {
fn default() -> Self {
SocketV1_1_19 {
socket_type: SocketTypeV1_1_19::WebSocket,
SocketV1_1_20 {
socket_type: SocketTypeV1_1_20::WebSocket,
host: IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)),
listening_port: DEFAULT_WEBSOCKET_LISTENING_PORT,
}
@@ -0,0 +1,103 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::client::config::persistence::ClientPaths;
use crate::client::config::{default_config_filepath, Config, Socket, SocketType};
use nym_bin_common::logging::LoggingSettings;
use nym_client_core::config::disk_persistence::old_v1_1_20_2::CommonClientPathsV1_1_20_2;
use nym_client_core::config::old_config_v1_1_20_2::ConfigV1_1_20_2 as BaseConfigV1_1_20_2;
use nym_client_core::config::GatewayEndpointConfig;
use nym_config::read_config_from_toml_file;
use nym_network_defaults::DEFAULT_WEBSOCKET_LISTENING_PORT;
use serde::{Deserialize, Serialize};
use std::io;
use std::net::{IpAddr, Ipv4Addr};
use std::path::Path;
#[derive(Debug, Deserialize, PartialEq, Eq, Serialize, Clone)]
pub struct ClientPathsV1_1_20_2 {
#[serde(flatten)]
pub common_paths: CommonClientPathsV1_1_20_2,
}
#[derive(Debug, Deserialize, PartialEq, Serialize)]
pub struct ConfigV1_1_20_2 {
#[serde(flatten)]
pub base: BaseConfigV1_1_20_2,
pub socket: SocketV1_1_20_2,
pub storage_paths: ClientPathsV1_1_20_2,
pub logging: LoggingSettings,
}
impl ConfigV1_1_20_2 {
pub fn read_from_toml_file<P: AsRef<Path>>(path: P) -> io::Result<Self> {
read_config_from_toml_file(path)
}
pub fn read_from_default_path<P: AsRef<Path>>(id: P) -> io::Result<Self> {
Self::read_from_toml_file(default_config_filepath(id))
}
// in this upgrade, gateway endpoint configuration was moved out of the config file,
// so its returned to be stored elsewhere.
pub fn upgrade(self) -> (Config, GatewayEndpointConfig) {
let gateway_details = self.base.client.gateway_endpoint.clone().into();
let config = Config {
base: self.base.into(),
socket: self.socket.into(),
storage_paths: ClientPaths {
common_paths: self.storage_paths.common_paths.upgrade_default(),
},
logging: self.logging,
};
(config, gateway_details)
}
}
#[derive(Debug, Deserialize, PartialEq, Eq, Serialize, Clone, Copy)]
#[serde(deny_unknown_fields)]
pub enum SocketTypeV1_1_20_2 {
WebSocket,
None,
}
impl From<SocketTypeV1_1_20_2> for SocketType {
fn from(value: SocketTypeV1_1_20_2) -> Self {
match value {
SocketTypeV1_1_20_2::WebSocket => SocketType::WebSocket,
SocketTypeV1_1_20_2::None => SocketType::None,
}
}
}
#[derive(Debug, Deserialize, PartialEq, Eq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct SocketV1_1_20_2 {
pub socket_type: SocketTypeV1_1_20_2,
pub host: IpAddr,
pub listening_port: u16,
}
impl From<SocketV1_1_20_2> for Socket {
fn from(value: SocketV1_1_20_2) -> Self {
Socket {
socket_type: value.socket_type.into(),
host: value.host,
listening_port: value.listening_port,
}
}
}
impl Default for SocketV1_1_20_2 {
fn default() -> Self {
SocketV1_1_20_2 {
socket_type: SocketTypeV1_1_20_2::WebSocket,
host: IpAddr::V4(Ipv4Addr::LOCALHOST),
listening_port: DEFAULT_WEBSOCKET_LISTENING_PORT,
}
}
}
+3 -12
View File
@@ -64,18 +64,9 @@ credentials_database = '{{ storage_paths.credentials_database }}'
# Path to the persistent store for received reply surbs, unused encryption keys and used sender tags.
reply_surb_database = '{{ storage_paths.reply_surb_database }}'
# DEPRECATED
[client.gateway_endpoint]
# ID of the gateway from which the client should be fetching messages.
gateway_id = '{{ client.gateway_endpoint.gateway_id }}'
# Address of the gateway owner to which the client should send messages.
gateway_owner = '{{ client.gateway_endpoint.gateway_owner }}'
# Address of the gateway listener to which all client requests should be sent.
gateway_listener = '{{ client.gateway_endpoint.gateway_listener }}'
# Path to the file containing information about gateway used by this client,
# i.e. details such as its public key, owner address or the network information.
gateway_details = '{{ storage_paths.gateway_details }}'
##### socket config options #####
+14 -31
View File
@@ -6,18 +6,15 @@ use crate::error::ClientError;
use crate::websocket;
use futures::channel::mpsc;
use log::*;
use nym_bandwidth_controller::BandwidthController;
use nym_client_core::client::base_client::non_wasm_helpers::create_bandwidth_controller;
use nym_client_core::client::base_client::non_wasm_helpers::default_query_dkg_client_from_config;
use nym_client_core::client::base_client::storage::OnDiskPersistent;
use nym_client_core::client::base_client::{
non_wasm_helpers, BaseClientBuilder, ClientInput, ClientOutput, ClientState,
BaseClientBuilder, ClientInput, ClientOutput, ClientState,
};
use nym_client_core::client::inbound_messages::InputMessage;
use nym_client_core::client::key_manager::persistence::OnDiskKeys;
use nym_client_core::client::received_buffer::{
ReceivedBufferMessage, ReceivedBufferRequestSender, ReconstructedMessagesReceiver,
};
use nym_credential_storage::persistent_storage::PersistentStorage;
use nym_sphinx::anonymous_replies::requests::AnonymousSenderTag;
use nym_sphinx::params::PacketType;
use nym_task::connections::TransmissionLane;
@@ -45,17 +42,6 @@ impl SocketClient {
SocketClient { config }
}
async fn create_bandwidth_controller(
config: &Config,
) -> BandwidthController<Client<QueryNyxdClient>, PersistentStorage> {
let storage = nym_credential_storage::initialise_persistent_storage(
&config.storage_paths.common_paths.credentials_database,
)
.await;
create_bandwidth_controller(&config.base, storage)
}
fn start_websocket_listener(
config: &Config,
client_input: ClientInput,
@@ -105,29 +91,26 @@ impl SocketClient {
res
}
fn key_store(&self) -> OnDiskKeys {
OnDiskKeys::new(self.config.storage_paths.common_paths.keys.clone())
async fn initialise_storage(&self) -> Result<OnDiskPersistent, ClientError> {
Ok(OnDiskPersistent::from_paths(
self.config.storage_paths.common_paths.clone(),
&self.config.base.debug,
)
.await?)
}
// TODO: see if this could also be shared with socks5 client / nym-sdk maybe
async fn create_base_client_builder(&self) -> Result<NativeClientBuilder, ClientError> {
// don't create bandwidth controller if credentials are disabled
let bandwidth_controller = if self.config.base.client.disabled_credentials_mode {
// don't create dkg client for the bandwidth controller if credentials are disabled
let dkg_query_client = if self.config.base.client.disabled_credentials_mode {
None
} else {
Some(Self::create_bandwidth_controller(&self.config).await)
Some(default_query_dkg_client_from_config(&self.config.base))
};
let base_client = BaseClientBuilder::new_from_base_config(
&self.config.base,
self.key_store(),
bandwidth_controller,
non_wasm_helpers::setup_fs_reply_surb_backend(
&self.config.storage_paths.common_paths.reply_surb_database,
&self.config.base.debug.reply_surbs,
)
.await?,
);
let storage = self.initialise_storage().await?;
let base_client = BaseClientBuilder::new(&self.config.base, storage, dkg_query_client);
Ok(base_client)
}
+18 -14
View File
@@ -12,7 +12,10 @@ use crate::{
};
use clap::Args;
use nym_bin_common::output_format::OutputFormat;
use nym_client_core::client::base_client::storage::gateway_details::OnDiskGatewayDetails;
use nym_client_core::client::key_manager::persistence::OnDiskKeys;
use nym_client_core::config::GatewayEndpointConfig;
use nym_client_core::init::GatewaySetup;
use nym_crypto::asymmetric::identity;
use nym_sphinx::addressing::clients::Recipient;
use serde::Serialize;
@@ -105,9 +108,9 @@ pub struct InitResults {
}
impl InitResults {
fn new(config: &Config, address: &Recipient) -> Self {
fn new(config: &Config, address: &Recipient, gateway: &GatewayEndpointConfig) -> Self {
Self {
client_core: nym_client_core::init::InitResults::new(&config.base, address),
client_core: nym_client_core::init::InitResults::new(&config.base, address, gateway),
client_listening_port: config.socket.listening_port,
client_address: address.to_string(),
}
@@ -157,25 +160,29 @@ pub(crate) async fn execute(args: &Init) -> Result<(), ClientError> {
// Attempt to use a user-provided gateway, if possible
let user_chosen_gateway_id = args.gateway;
let gateway_setup = GatewaySetup::new_fresh(
user_chosen_gateway_id.map(|id| id.to_base58_string()),
Some(args.latency_based_selection),
);
// Load and potentially override config
let mut config = override_config(Config::new(id), OverrideConfig::from(args.clone()));
let config = override_config(Config::new(id), OverrideConfig::from(args.clone()));
// Setup gateway by either registering a new one, or creating a new config from the selected
// one but with keys kept, or reusing the gateway configuration.
let key_store = OnDiskKeys::new(config.storage_paths.common_paths.keys.clone());
let gateway = nym_client_core::init::setup_gateway_from_config::<_>(
let details_store =
OnDiskGatewayDetails::new(&config.storage_paths.common_paths.gateway_details);
let init_details = nym_client_core::init::setup_gateway(
&gateway_setup,
&key_store,
&details_store,
register_gateway,
user_chosen_gateway_id,
&config.base,
args.latency_based_selection,
Some(&config.base.client.nym_api_urls),
)
.await
.tap_err(|err| eprintln!("Failed to setup gateway\nError: {err}"))?;
config.base.set_gateway_endpoint(gateway);
let config_save_location = config.default_location();
config.save_to_default_location().tap_err(|_| {
log::error!("Failed to save the config file");
@@ -185,14 +192,11 @@ pub(crate) async fn execute(args: &Init) -> Result<(), ClientError> {
config_save_location.display()
);
let address = nym_client_core::init::get_client_address_from_stored_ondisk_keys(
&config.storage_paths.common_paths.keys,
&config.base.client.gateway_endpoint,
)?;
let address = init_details.client_address()?;
eprintln!("Client configuration completed.\n");
let init_results = InitResults::new(&config, &address);
let init_results = InitResults::new(&config, &address, &init_details.gateway_details);
println!("{}", args.output.format(&init_results));
Ok(())
+78 -15
View File
@@ -2,7 +2,8 @@
// SPDX-License-Identifier: Apache-2.0
use crate::client::config::old_config_v1_1_13::OldConfigV1_1_13;
use crate::client::config::old_config_v1_1_19::ConfigV1_1_19;
use crate::client::config::old_config_v1_1_20::ConfigV1_1_20;
use crate::client::config::old_config_v1_1_20_2::ConfigV1_1_20_2;
use crate::client::config::{BaseClientConfig, Config};
use crate::error::ClientError;
use clap::CommandFactory;
@@ -11,13 +12,18 @@ use lazy_static::lazy_static;
use log::{error, info};
use nym_bin_common::build_information::BinaryBuildInformation;
use nym_bin_common::completions::{fig_generate, ArgShell};
use nym_client_core::client::base_client::storage::gateway_details::{
OnDiskGatewayDetails, PersistedGatewayDetails,
};
use nym_client_core::client::key_manager::persistence::OnDiskKeys;
use nym_client_core::config::GatewayEndpointConfig;
use nym_client_core::error::ClientCoreError;
use nym_config::OptionalSet;
use std::error::Error;
use std::net::IpAddr;
pub(crate) mod init;
pub(crate) mod run;
pub(crate) mod upgrade;
lazy_static! {
pub static ref PRETTY_BUILD_INFORMATION: String =
@@ -44,10 +50,9 @@ pub(crate) struct Cli {
pub(crate) enum Commands {
/// Initialise a Nym client. Do this first!
Init(init::Init),
/// Run the Nym client with provided configuration client optionally overriding set parameters
Run(run::Run),
/// Try to upgrade the client
Upgrade(upgrade::Upgrade),
/// Generate shell completions
Completions(ArgShell),
@@ -74,7 +79,6 @@ pub(crate) async fn execute(args: &Cli) -> Result<(), Box<dyn Error + Send + Syn
match &args.command {
Commands::Init(m) => init::execute(m).await?,
Commands::Run(m) => run::execute(m).await?,
Commands::Upgrade(m) => upgrade::execute(m),
Commands::Completions(s) => s.generate(&mut Cli::command(), bin_name),
Commands::GenerateFigSpec => fig_generate(&mut Cli::command(), bin_name),
}
@@ -109,6 +113,28 @@ pub(crate) fn override_config(config: Config, args: OverrideConfig) -> Config {
)
}
fn persist_gateway_details(
config: &Config,
details: GatewayEndpointConfig,
) -> Result<(), ClientError> {
let details_store =
OnDiskGatewayDetails::new(&config.storage_paths.common_paths.gateway_details);
let keys_store = OnDiskKeys::new(config.storage_paths.common_paths.keys.clone());
let shared_keys = keys_store.ephemeral_load_gateway_keys().map_err(|source| {
ClientError::ClientCoreError(ClientCoreError::KeyStoreError {
source: Box::new(source),
})
})?;
let persisted_details = PersistedGatewayDetails::new(details, &shared_keys);
details_store
.store_to_disk(&persisted_details)
.map_err(|source| {
ClientError::ClientCoreError(ClientCoreError::GatewayDetailsStoreError {
source: Box::new(source),
})
})
}
fn try_upgrade_v1_1_13_config(id: &str) -> Result<bool, ClientError> {
use nym_config::legacy_helpers::nym_config::MigrationNymConfig;
@@ -121,40 +147,77 @@ fn try_upgrade_v1_1_13_config(id: &str) -> Result<bool, ClientError> {
info!("It seems the client is using <= v1.1.13 config template.");
info!("It is going to get updated to the current specification.");
let updated_step1: ConfigV1_1_19 = old_config.into();
let updated: Config = updated_step1.into();
let updated_step1: ConfigV1_1_20 = old_config.into();
let updated_step2: ConfigV1_1_20_2 = updated_step1.into();
let (updated, gateway_config) = updated_step2.upgrade();
persist_gateway_details(&updated, gateway_config)?;
updated.save_to_default_location()?;
Ok(true)
}
fn try_upgrade_v1_1_19_config(id: &str) -> Result<bool, ClientError> {
fn try_upgrade_v1_1_20_config(id: &str) -> Result<bool, ClientError> {
use nym_config::legacy_helpers::nym_config::MigrationNymConfig;
// explicitly load it as v1.1.19 (which is incompatible with the current one, i.e. +1.1.20)
let Ok(old_config) = ConfigV1_1_19::load_from_file(id) else {
// explicitly load it as v1.1.20 (which is incompatible with the current one, i.e. +1.1.21)
let Ok(old_config) = ConfigV1_1_20::load_from_file(id) else {
// if we failed to load it, there might have been nothing to upgrade
// or maybe it was an even older file. in either way. just ignore it and carry on with our day
return Ok(false);
};
info!("It seems the client is using <= v1.1.19 config template.");
info!("It seems the client is using <= v1.1.20 config template.");
info!("It is going to get updated to the current specification.");
let updated: Config = old_config.into();
let updated_step1: ConfigV1_1_20_2 = old_config.into();
let (updated, gateway_config) = updated_step1.upgrade();
persist_gateway_details(&updated, gateway_config)?;
updated.save_to_default_location()?;
Ok(true)
}
fn try_upgrade_v1_1_20_2_config(id: &str) -> Result<bool, ClientError> {
// explicitly load it as v1.1.20_2 (which is incompatible with the current one, i.e. +1.1.21)
let Ok(old_config) = ConfigV1_1_20_2::read_from_default_path(id) else {
// if we failed to load it, there might have been nothing to upgrade
// or maybe it was an even older file. in either way. just ignore it and carry on with our day
return Ok(false);
};
info!("It seems the client is using <= v1.1.20_2 config template.");
info!("It is going to get updated to the current specification.");
let (updated, gateway_config) = old_config.upgrade();
persist_gateway_details(&updated, gateway_config)?;
updated.save_to_default_location()?;
Ok(true)
}
fn try_upgrade_config(id: &str) -> Result<(), ClientError> {
let upgraded = try_upgrade_v1_1_13_config(id)?;
if !upgraded {
try_upgrade_v1_1_19_config(id)?;
if try_upgrade_v1_1_13_config(id)? {
return Ok(());
}
if try_upgrade_v1_1_20_config(id)? {
return Ok(());
}
if try_upgrade_v1_1_20_2_config(id)? {
return Ok(());
}
Ok(())
}
fn try_load_current_config(id: &str) -> Result<Config, ClientError> {
// try to load the config as is
if let Ok(cfg) = Config::read_from_default_path(id) {
return if !cfg.validate() {
Err(ClientError::ConfigValidationFailure)
} else {
Ok(cfg)
};
}
// we couldn't load it - try upgrading it from older revisions
try_upgrade_config(id)?;
let config = match Config::read_from_default_path(id) {
-78
View File
@@ -1,78 +0,0 @@
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::client::config::Config;
use crate::commands::try_load_current_config;
use clap::Args;
use nym_bin_common::version_checker::Version;
use std::process;
fn unimplemented_upgrade(current_version: &Version, config_version: &Version) -> ! {
eprintln!("Cannot perform upgrade from {config_version} to {current_version} as it hasn't been implemented yet");
process::exit(1)
}
#[derive(Args, Clone)]
pub(crate) struct Upgrade {
/// Id of the nym-client we want to upgrade
#[clap(long)]
id: String,
}
fn parse_config_version(config: &Config) -> Version {
let version = Version::parse(&config.base.client.version).unwrap_or_else(|err| {
eprintln!("failed to parse client version! - {err}");
process::exit(1)
});
if version.is_prerelease() || !version.build.is_empty() {
eprintln!(
"Trying to upgrade from a non-released version {version}. This is not supported!"
);
process::exit(1)
}
version
}
fn parse_package_version() -> Version {
let version = Version::parse(env!("CARGO_PKG_VERSION")).unwrap();
// technically this is not a correct way of checking it as a released version might contain valid build identifiers
// however, we are not using them ourselves at the moment and hence it should be fine.
// if we change our mind, we could easily tweak this code
if version.is_prerelease() || !version.build.is_empty() {
eprintln!("Trying to upgrade to a non-released version {version}. This is not supported!");
process::exit(1)
}
version
}
fn do_upgrade(config: Config, _args: &Upgrade, package_version: &Version) {
let config_version = parse_config_version(&config);
if &config_version == package_version {
println!("You're using the most recent version!");
return;
}
unimplemented_upgrade(package_version, &config_version)
}
pub(crate) fn execute(args: &Upgrade) {
let package_version = parse_package_version();
let id = &args.id;
let existing_config = try_load_current_config(id).unwrap_or_else(|err| {
eprintln!("failed to load existing config file! - {err}");
process::exit(1)
});
if existing_config.base.client.version.is_empty() {
eprintln!("the existing configuration file does not seem to contain version number.");
process::exit(1);
}
do_upgrade(existing_config, args, &package_version)
}
@@ -1,4 +1,4 @@
// Copyright 2021-2022 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
// all variable size data is always prefixed with u64 length
@@ -1,4 +1,4 @@
// Copyright 2021-2022 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
// all variable size data is always prefixed with u64 length
@@ -1,4 +1,4 @@
// Copyright 2021-2022 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::error::ErrorKind;
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "nym-socks5-client"
version = "1.1.19"
version = "1.1.23"
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"
edition = "2021"
+23 -14
View File
@@ -11,7 +11,10 @@ use crate::{
};
use clap::Args;
use nym_bin_common::output_format::OutputFormat;
use nym_client_core::client::base_client::storage::gateway_details::OnDiskGatewayDetails;
use nym_client_core::client::key_manager::persistence::OnDiskKeys;
use nym_client_core::config::GatewayEndpointConfig;
use nym_client_core::init::GatewaySetup;
use nym_crypto::asymmetric::identity;
use nym_sphinx::addressing::clients::Recipient;
use serde::Serialize;
@@ -107,9 +110,13 @@ pub struct InitResults {
}
impl InitResults {
fn new(config: &Config, address: &Recipient) -> Self {
fn new(config: &Config, address: &Recipient, gateway: &GatewayEndpointConfig) -> Self {
Self {
client_core: nym_client_core::init::InitResults::new(&config.core.base, address),
client_core: nym_client_core::init::InitResults::new(
&config.core.base,
address,
gateway,
),
socks5_listening_port: config.core.socks5.listening_port,
client_address: address.to_string(),
}
@@ -160,9 +167,13 @@ pub(crate) async fn execute(args: &Init) -> Result<(), Socks5ClientError> {
// Attempt to use a user-provided gateway, if possible
let user_chosen_gateway_id = args.gateway;
let gateway_setup = GatewaySetup::new_fresh(
user_chosen_gateway_id.map(|id| id.to_base58_string()),
Some(args.latency_based_selection),
);
// Load and potentially override config
let mut config = override_config(
let config = override_config(
Config::new(id, &provider_address.to_string()),
OverrideConfig::from(args.clone()),
);
@@ -170,18 +181,18 @@ pub(crate) async fn execute(args: &Init) -> Result<(), Socks5ClientError> {
// Setup gateway by either registering a new one, or creating a new config from the selected
// one but with keys kept, or reusing the gateway configuration.
let key_store = OnDiskKeys::new(config.storage_paths.common_paths.keys.clone());
let gateway = nym_client_core::init::setup_gateway_from_config::<_>(
let details_store =
OnDiskGatewayDetails::new(&config.storage_paths.common_paths.gateway_details);
let init_details = nym_client_core::init::setup_gateway(
&gateway_setup,
&key_store,
&details_store,
register_gateway,
user_chosen_gateway_id,
&config.core.base,
args.latency_based_selection,
Some(&config.core.base.client.nym_api_urls),
)
.await
.tap_err(|err| eprintln!("Failed to setup gateway\nError: {err}"))?;
config.core.base.set_gateway_endpoint(gateway);
// TODO: ask the service provider we specified for its interface version and set it in the config
let config_save_location = config.default_location();
@@ -193,11 +204,9 @@ pub(crate) async fn execute(args: &Init) -> Result<(), Socks5ClientError> {
config_save_location.display()
);
let address = nym_client_core::init::get_client_address_from_stored_ondisk_keys(
&config.storage_paths.common_paths.keys,
&config.core.base.client.gateway_endpoint,
)?;
let init_results = InitResults::new(&config, &address);
let address = init_details.client_address()?;
let init_results = InitResults::new(&config, &address, &init_details.gateway_details);
println!("{}", args.output.format(&init_results));
Ok(())
+77 -16
View File
@@ -2,7 +2,8 @@
// SPDX-License-Identifier: Apache-2.0
use crate::config::old_config_v1_1_13::OldConfigV1_1_13;
use crate::config::old_config_v1_1_19::ConfigV1_1_19;
use crate::config::old_config_v1_1_20::ConfigV1_1_20;
use crate::config::old_config_v1_1_20_2::ConfigV1_1_20_2;
use crate::config::{BaseClientConfig, Config};
use crate::error::Socks5ClientError;
use clap::CommandFactory;
@@ -11,13 +12,18 @@ use lazy_static::lazy_static;
use log::{error, info};
use nym_bin_common::build_information::BinaryBuildInformation;
use nym_bin_common::completions::{fig_generate, ArgShell};
use nym_client_core::client::base_client::storage::gateway_details::{
OnDiskGatewayDetails, PersistedGatewayDetails,
};
use nym_client_core::client::key_manager::persistence::OnDiskKeys;
use nym_client_core::config::GatewayEndpointConfig;
use nym_client_core::error::ClientCoreError;
use nym_config::OptionalSet;
use nym_sphinx::params::PacketType;
use std::error::Error;
pub mod init;
pub(crate) mod run;
pub(crate) mod upgrade;
lazy_static! {
pub static ref PRETTY_BUILD_INFORMATION: String =
@@ -48,9 +54,6 @@ pub(crate) enum Commands {
/// Run the Nym client with provided configuration client optionally overriding set parameters
Run(run::Run),
/// Try to upgrade the client
Upgrade(upgrade::Upgrade),
/// Generate shell completions
Completions(ArgShell),
@@ -76,7 +79,6 @@ pub(crate) async fn execute(args: &Cli) -> Result<(), Box<dyn Error + Send + Syn
match &args.command {
Commands::Init(m) => init::execute(m).await?,
Commands::Run(m) => run::execute(m).await?,
Commands::Upgrade(m) => upgrade::execute(m),
Commands::Completions(s) => s.generate(&mut Cli::command(), bin_name),
Commands::GenerateFigSpec => fig_generate(&mut Cli::command(), bin_name),
}
@@ -116,6 +118,28 @@ pub(crate) fn override_config(config: Config, args: OverrideConfig) -> Config {
)
}
fn persist_gateway_details(
config: &Config,
details: GatewayEndpointConfig,
) -> Result<(), Socks5ClientError> {
let details_store =
OnDiskGatewayDetails::new(&config.storage_paths.common_paths.gateway_details);
let keys_store = OnDiskKeys::new(config.storage_paths.common_paths.keys.clone());
let shared_keys = keys_store.ephemeral_load_gateway_keys().map_err(|source| {
Socks5ClientError::ClientCoreError(ClientCoreError::KeyStoreError {
source: Box::new(source),
})
})?;
let persisted_details = PersistedGatewayDetails::new(details, &shared_keys);
details_store
.store_to_disk(&persisted_details)
.map_err(|source| {
Socks5ClientError::ClientCoreError(ClientCoreError::GatewayDetailsStoreError {
source: Box::new(source),
})
})
}
fn try_upgrade_v1_1_13_config(id: &str) -> Result<bool, Socks5ClientError> {
use nym_config::legacy_helpers::nym_config::MigrationNymConfig;
@@ -128,40 +152,77 @@ fn try_upgrade_v1_1_13_config(id: &str) -> Result<bool, Socks5ClientError> {
info!("It seems the client is using <= v1.1.13 config template.");
info!("It is going to get updated to the current specification.");
let updated_step1: ConfigV1_1_19 = old_config.into();
let updated: Config = updated_step1.into();
let updated_step1: ConfigV1_1_20 = old_config.into();
let updated_step2: ConfigV1_1_20_2 = updated_step1.into();
let (updated, gateway_config) = updated_step2.upgrade();
persist_gateway_details(&updated, gateway_config)?;
updated.save_to_default_location()?;
Ok(true)
}
fn try_upgrade_v1_1_19_config(id: &str) -> Result<bool, Socks5ClientError> {
fn try_upgrade_v1_1_20_config(id: &str) -> Result<bool, Socks5ClientError> {
use nym_config::legacy_helpers::nym_config::MigrationNymConfig;
// explicitly load it as v1.1.19 (which is incompatible with the current one, i.e. +1.1.20)
let Ok(old_config) = ConfigV1_1_19::load_from_file(id) else {
// explicitly load it as v1.1.20 (which is incompatible with the current one, i.e. +1.1.21)
let Ok(old_config) = ConfigV1_1_20::load_from_file(id) else {
// if we failed to load it, there might have been nothing to upgrade
// or maybe it was an even older file. in either way. just ignore it and carry on with our day
return Ok(false);
};
info!("It seems the client is using <= v1.1.19 config template.");
info!("It seems the client is using <= v1.1.20 config template.");
info!("It is going to get updated to the current specification.");
let updated: Config = old_config.into();
let updated_step1: ConfigV1_1_20_2 = old_config.into();
let (updated, gateway_config) = updated_step1.upgrade();
persist_gateway_details(&updated, gateway_config)?;
updated.save_to_default_location()?;
Ok(true)
}
fn try_upgrade_v1_1_20_2_config(id: &str) -> Result<bool, Socks5ClientError> {
// explicitly load it as v1.1.20_2 (which is incompatible with the current one, i.e. +1.1.21)
let Ok(old_config) = ConfigV1_1_20_2::read_from_default_path(id) else {
// if we failed to load it, there might have been nothing to upgrade
// or maybe it was an even older file. in either way. just ignore it and carry on with our day
return Ok(false);
};
info!("It seems the client is using <= v1.1.20_2 config template.");
info!("It is going to get updated to the current specification.");
let (updated, gateway_config) = old_config.upgrade();
persist_gateway_details(&updated, gateway_config)?;
updated.save_to_default_location()?;
Ok(true)
}
fn try_upgrade_config(id: &str) -> Result<(), Socks5ClientError> {
let upgraded = try_upgrade_v1_1_13_config(id)?;
if !upgraded {
try_upgrade_v1_1_19_config(id)?;
if try_upgrade_v1_1_13_config(id)? {
return Ok(());
}
if try_upgrade_v1_1_20_config(id)? {
return Ok(());
}
if try_upgrade_v1_1_20_2_config(id)? {
return Ok(());
}
Ok(())
}
fn try_load_current_config(id: &str) -> Result<Config, Socks5ClientError> {
// try to load the config as is
if let Ok(cfg) = Config::read_from_default_path(id) {
return if !cfg.validate() {
Err(Socks5ClientError::ConfigValidationFailure)
} else {
Ok(cfg)
};
}
// we couldn't load it - try upgrading it from older revisions
try_upgrade_config(id)?;
let config = match Config::read_from_default_path(id) {
-78
View File
@@ -1,78 +0,0 @@
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::commands::try_load_current_config;
use crate::config::Config;
use clap::Args;
use nym_bin_common::version_checker::Version;
use std::process;
fn unimplemented_upgrade(current_version: &Version, config_version: &Version) -> ! {
eprintln!("Cannot perform upgrade from {config_version} to {current_version} as it hasn't been implemented yet");
process::exit(1)
}
#[derive(Args, Clone)]
pub(crate) struct Upgrade {
/// Id of the nym-client we want to upgrade
#[clap(long)]
id: String,
}
fn parse_config_version(config: &Config) -> Version {
let version = Version::parse(&config.core.base.client.version).unwrap_or_else(|err| {
eprintln!("failed to parse client version! - {err}");
process::exit(1)
});
if version.is_prerelease() || !version.build.is_empty() {
eprintln!(
"Trying to upgrade from a non-released version {version}. This is not supported!"
);
process::exit(1)
}
version
}
fn parse_package_version() -> Version {
let version = Version::parse(env!("CARGO_PKG_VERSION")).unwrap();
// technically this is not a correct way of checking it as a released version might contain valid build identifiers
// however, we are not using them ourselves at the moment and hence it should be fine.
// if we change our mind, we could easily tweak this code
if version.is_prerelease() || !version.build.is_empty() {
eprintln!("Trying to upgrade to a non-released version {version}. This is not supported!");
process::exit(1)
}
version
}
fn do_upgrade(config: Config, _args: &Upgrade, package_version: &Version) {
let config_version = parse_config_version(&config);
if &config_version == package_version {
println!("You're using the most recent version!");
return;
}
unimplemented_upgrade(package_version, &config_version)
}
pub(crate) fn execute(args: &Upgrade) {
let package_version = parse_package_version();
let id = &args.id;
let existing_config = try_load_current_config(id).unwrap_or_else(|err| {
eprintln!("failed to load existing config file! - {err}");
process::exit(1)
});
if existing_config.core.base.client.version.is_empty() {
eprintln!("the existing configuration file does not seem to contain version number.");
process::exit(1);
}
do_upgrade(existing_config, args, &package_version)
}
+7 -2
View File
@@ -18,7 +18,8 @@ pub use nym_client_core::config::Config as BaseClientConfig;
pub use nym_socks5_client_core::config::Config as CoreConfig;
pub mod old_config_v1_1_13;
pub mod old_config_v1_1_19;
pub mod old_config_v1_1_20;
pub mod old_config_v1_1_20_2;
mod persistence;
mod template;
@@ -69,7 +70,11 @@ impl NymConfigTemplate for Config {
impl Config {
pub fn new<S: AsRef<str>>(id: S, provider_mix_address: S) -> Self {
Config {
core: CoreConfig::new(id.as_ref(), provider_mix_address.as_ref()),
core: CoreConfig::new(
id.as_ref(),
env!("CARGO_PKG_VERSION"),
provider_mix_address.as_ref(),
),
storage_paths: SocksClientPaths::new_default(default_data_directory(id.as_ref())),
logging: Default::default(),
}
@@ -1,7 +1,7 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::config::old_config_v1_1_19::{ConfigV1_1_19, Socks5V1_1_19};
use crate::config::old_config_v1_1_20::{ConfigV1_1_20, Socks5V1_1_20};
use nym_client_core::config::old_config_v1_1_13::OldConfigV1_1_13 as OldBaseConfigV1_1_13;
use nym_config::legacy_helpers::nym_config::MigrationNymConfig;
use nym_config::must_get_home;
@@ -14,7 +14,7 @@ pub struct OldConfigV1_1_13 {
#[serde(flatten)]
pub base: OldBaseConfigV1_1_13<OldConfigV1_1_13>,
pub socks5: Socks5V1_1_19,
pub socks5: Socks5V1_1_20,
}
impl MigrationNymConfig for OldConfigV1_1_13 {
@@ -28,9 +28,9 @@ impl MigrationNymConfig for OldConfigV1_1_13 {
}
}
impl From<OldConfigV1_1_13> for ConfigV1_1_19 {
impl From<OldConfigV1_1_13> for ConfigV1_1_20 {
fn from(value: OldConfigV1_1_13) -> Self {
ConfigV1_1_19 {
ConfigV1_1_20 {
base: value.base.into(),
socks5: value.socks5,
}
@@ -1,18 +1,20 @@
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::config::persistence::SocksClientPaths;
use crate::config::{BaseClientConfig, Config, CoreConfig};
use crate::config::old_config_v1_1_20_2::{
ConfigV1_1_20_2, CoreConfigV1_1_20_2, SocksClientPathsV1_1_20_2,
};
use nym_bin_common::logging::LoggingSettings;
use nym_client_core::config::disk_persistence::keys_paths::ClientKeysPaths;
use nym_client_core::config::disk_persistence::CommonClientPaths;
use nym_client_core::config::old_config_v1_1_19::ConfigV1_1_19 as BaseConfigV1_1_19;
use nym_client_core::config::Client;
use nym_client_core::config::disk_persistence::old_v1_1_20_2::CommonClientPathsV1_1_20_2;
use nym_client_core::config::old_config_v1_1_20::ConfigV1_1_20 as BaseConfigV1_1_20;
use nym_client_core::config::old_config_v1_1_20_2::ClientV1_1_20_2;
use nym_config::legacy_helpers::nym_config::MigrationNymConfig;
use nym_config::must_get_home;
use nym_socks5_client_core::config::{
ProviderInterfaceVersion, Socks5, Socks5Debug, Socks5ProtocolVersion,
use nym_socks5_client_core::config::old_config_v1_1_20_2::{
BaseClientConfigV1_1_20_2, Socks5DebugV1_1_20_2, Socks5V1_1_20_2,
};
use nym_socks5_client_core::config::{ProviderInterfaceVersion, Socks5ProtocolVersion};
use serde::{Deserialize, Serialize};
use std::fmt::Debug;
use std::path::PathBuf;
@@ -22,19 +24,19 @@ const DEFAULT_PER_REQUEST_SURBS: u32 = 3;
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct ConfigV1_1_19 {
pub struct ConfigV1_1_20 {
#[serde(flatten)]
pub base: BaseConfigV1_1_19<ConfigV1_1_19>,
pub base: BaseConfigV1_1_20<ConfigV1_1_20>,
pub socks5: Socks5V1_1_19,
pub socks5: Socks5V1_1_20,
}
impl From<ConfigV1_1_19> for Config {
fn from(value: ConfigV1_1_19) -> Self {
Config {
core: CoreConfig {
base: BaseClientConfig {
client: Client {
impl From<ConfigV1_1_20> for ConfigV1_1_20_2 {
fn from(value: ConfigV1_1_20) -> Self {
ConfigV1_1_20_2 {
core: CoreConfigV1_1_20_2 {
base: BaseClientConfigV1_1_20_2 {
client: ClientV1_1_20_2 {
version: value.base.client.version,
id: value.base.client.id,
disabled_credentials_mode: value.base.client.disabled_credentials_mode,
@@ -46,8 +48,8 @@ impl From<ConfigV1_1_19> for Config {
},
socks5: value.socks5.into(),
},
storage_paths: SocksClientPaths {
common_paths: CommonClientPaths {
storage_paths: SocksClientPathsV1_1_20_2 {
common_paths: CommonClientPathsV1_1_20_2 {
keys: ClientKeysPaths {
private_identity_key_file: value.base.client.private_identity_key_file,
public_identity_key_file: value.base.client.public_identity_key_file,
@@ -65,7 +67,7 @@ impl From<ConfigV1_1_19> for Config {
}
}
impl MigrationNymConfig for ConfigV1_1_19 {
impl MigrationNymConfig for ConfigV1_1_20 {
fn default_root_directory() -> PathBuf {
#[cfg(not(any(target_os = "android", target_os = "ios")))]
let base_dir = must_get_home();
@@ -78,7 +80,7 @@ impl MigrationNymConfig for ConfigV1_1_19 {
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct Socks5V1_1_19 {
pub struct Socks5V1_1_20 {
pub listening_port: u16,
pub provider_mix_address: String,
@@ -93,12 +95,12 @@ pub struct Socks5V1_1_19 {
pub send_anonymously: bool,
#[serde(default)]
pub socks5_debug: Socks5DebugV1_1_19,
pub socks5_debug: Socks5DebugV1_1_20,
}
impl From<Socks5V1_1_19> for Socks5 {
fn from(value: Socks5V1_1_19) -> Self {
Socks5 {
impl From<Socks5V1_1_20> for Socks5V1_1_20_2 {
fn from(value: Socks5V1_1_20) -> Self {
Socks5V1_1_20_2 {
listening_port: value.listening_port,
provider_mix_address: value.provider_mix_address,
provider_interface_version: value.provider_interface_version,
@@ -111,23 +113,23 @@ impl From<Socks5V1_1_19> for Socks5 {
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct Socks5DebugV1_1_19 {
pub struct Socks5DebugV1_1_20 {
connection_start_surbs: u32,
per_request_surbs: u32,
}
impl From<Socks5DebugV1_1_19> for Socks5Debug {
fn from(value: Socks5DebugV1_1_19) -> Self {
Socks5Debug {
impl From<Socks5DebugV1_1_20> for Socks5DebugV1_1_20_2 {
fn from(value: Socks5DebugV1_1_20) -> Self {
Socks5DebugV1_1_20_2 {
connection_start_surbs: value.connection_start_surbs,
per_request_surbs: value.per_request_surbs,
}
}
}
impl Default for Socks5DebugV1_1_19 {
impl Default for Socks5DebugV1_1_20 {
fn default() -> Self {
Socks5DebugV1_1_19 {
Socks5DebugV1_1_20 {
connection_start_surbs: DEFAULT_CONNECTION_START_SURBS,
per_request_surbs: DEFAULT_PER_REQUEST_SURBS,
}
@@ -0,0 +1,54 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::config::persistence::SocksClientPaths;
use crate::config::{default_config_filepath, Config};
use nym_bin_common::logging::LoggingSettings;
use nym_client_core::config::disk_persistence::old_v1_1_20_2::CommonClientPathsV1_1_20_2;
use nym_client_core::config::GatewayEndpointConfig;
use nym_config::read_config_from_toml_file;
pub use nym_socks5_client_core::config::old_config_v1_1_20_2::ConfigV1_1_20_2 as CoreConfigV1_1_20_2;
use serde::{Deserialize, Serialize};
use std::io;
use std::path::Path;
#[derive(Debug, Deserialize, PartialEq, Eq, Serialize, Clone)]
pub struct SocksClientPathsV1_1_20_2 {
#[serde(flatten)]
pub common_paths: CommonClientPathsV1_1_20_2,
}
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct ConfigV1_1_20_2 {
pub core: CoreConfigV1_1_20_2,
pub storage_paths: SocksClientPathsV1_1_20_2,
pub logging: LoggingSettings,
}
impl ConfigV1_1_20_2 {
pub fn read_from_toml_file<P: AsRef<Path>>(path: P) -> io::Result<Self> {
read_config_from_toml_file(path)
}
pub fn read_from_default_path<P: AsRef<Path>>(id: P) -> io::Result<Self> {
Self::read_from_toml_file(default_config_filepath(id))
}
// in this upgrade, gateway endpoint configuration was moved out of the config file,
// so its returned to be stored elsewhere.
pub fn upgrade(self) -> (Config, GatewayEndpointConfig) {
let gateway_details = self.core.base.client.gateway_endpoint.clone().into();
let config = Config {
core: self.core.into(),
storage_paths: SocksClientPaths {
common_paths: self.storage_paths.common_paths.upgrade_default(),
},
logging: self.logging,
};
(config, gateway_details)
}
}
+3 -11
View File
@@ -64,17 +64,9 @@ credentials_database = '{{ storage_paths.credentials_database }}'
# Path to the persistent store for received reply surbs, unused encryption keys and used sender tags.
reply_surb_database = '{{ storage_paths.reply_surb_database }}'
# DEPRECATED
[core.client.gateway_endpoint]
# ID of the gateway from which the client should be fetching messages.
gateway_id = '{{ core.client.gateway_endpoint.gateway_id }}'
# Address of the gateway owner to which the client should send messages.
gateway_owner = '{{ core.client.gateway_endpoint.gateway_owner }}'
# Address of the gateway listener to which all client requests should be sent.
gateway_listener = '{{ core.client.gateway_endpoint.gateway_listener }}'
# Path to the file containing information about gateway used by this client,
# i.e. details such as its public key, owner address or the network information.
gateway_details = '{{ storage_paths.gateway_details }}'
##### socket config options #####
+253 -109
View File
@@ -62,7 +62,7 @@ version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47"
dependencies = [
"getrandom 0.2.9",
"getrandom 0.2.10",
"once_cell",
"version_check",
]
@@ -225,9 +225,9 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
[[package]]
name = "base64"
version = "0.21.0"
version = "0.21.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a"
checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d"
[[package]]
name = "base64ct"
@@ -237,18 +237,18 @@ checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b"
[[package]]
name = "bip32"
version = "0.3.0"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "873faa4363bfc54c36a48321da034c92a0645a363eed34d948683ffc1706e37f"
checksum = "b30ed1d6f8437a487a266c8293aeb95b61a23261273e3e02912cdb8b68bf798b"
dependencies = [
"bs58",
"hmac 0.11.0",
"hmac 0.12.1",
"k256",
"once_cell",
"pbkdf2",
"rand_core 0.6.4",
"ripemd160",
"sha2 0.9.9",
"ripemd",
"sha2 0.10.6",
"subtle 2.4.1",
"zeroize",
]
@@ -332,7 +332,6 @@ version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4"
dependencies = [
"block-padding",
"generic-array 0.14.7",
]
@@ -345,12 +344,6 @@ dependencies = [
"generic-array 0.14.7",
]
[[package]]
name = "block-padding"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae"
[[package]]
name = "bls12_381"
version = "0.5.0"
@@ -577,9 +570,9 @@ dependencies = [
[[package]]
name = "const-oid"
version = "0.7.1"
version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e4c78c047431fee22c1a7bb92e00ad095a02a983affe4d8a72e2a2c62c1b94f3"
checksum = "520fbf3c07483f94e3e3ca9d0cfd913d7718ef2483d2cfd91c0d9e91474ab913"
[[package]]
name = "constant_time_eq"
@@ -605,8 +598,9 @@ checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa"
[[package]]
name = "cosmos-sdk-proto"
version = "0.12.3"
source = "git+https://github.com/neacsu/cosmos-rust?branch=neacsu/feegrant_support#f63ded63ec13e753ebe8bdafe9dc503df265d67d"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8bb61f3d2224c90ea78e1fa7444787761a549170c46b6b0ed09b93f9b7e4076a"
dependencies = [
"prost",
"prost-types",
@@ -615,14 +609,15 @@ dependencies = [
[[package]]
name = "cosmrs"
version = "0.7.1"
source = "git+https://github.com/neacsu/cosmos-rust?branch=neacsu/feegrant_support#f63ded63ec13e753ebe8bdafe9dc503df265d67d"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "20d5890dac07a62337e5841adb8f2074a66a962a098a48df9460f64d483beaf4"
dependencies = [
"bip32",
"cosmos-sdk-proto",
"ecdsa",
"eyre",
"getrandom 0.2.9",
"getrandom 0.2.10",
"k256",
"prost",
"prost-types",
@@ -637,11 +632,11 @@ dependencies = [
[[package]]
name = "cosmwasm-crypto"
version = "1.0.1"
version = "1.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "970d1d705862179b5d7a233ae36f02f21c4ec1b8075fe60c77fc5b43471331fa"
checksum = "75836a10cb9654c54e77ee56da94d592923092a10b369cdb0dbd56acefc16340"
dependencies = [
"digest 0.9.0",
"digest 0.10.6",
"ed25519-zebra",
"k256",
"rand_core 0.6.4",
@@ -650,26 +645,53 @@ dependencies = [
[[package]]
name = "cosmwasm-derive"
version = "1.0.0"
version = "1.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4b36e527620a2a3e00e46b6e731ab6c9b68d11069c986f7d7be8eba79ef081a4"
checksum = "1c9f7f0e51bfc7295f7b2664fe8513c966428642aa765dad8a74acdab5e0c773"
dependencies = [
"syn 1.0.109",
]
[[package]]
name = "cosmwasm-std"
version = "1.0.0"
name = "cosmwasm-schema"
version = "1.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "875994993c2082a6fcd406937bf0fca21c349e4a624f3810253a14fa83a3a195"
checksum = "0f00b363610218eea83f24bbab09e1a7c3920b79f068334fdfcc62f6129ef9fc"
dependencies = [
"cosmwasm-schema-derive",
"schemars",
"serde",
"serde_json",
"thiserror",
]
[[package]]
name = "cosmwasm-schema-derive"
version = "1.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae38f909b2822d32b275c9e2db9728497aa33ffe67dd463bc67c6a3b7092785c"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]]
name = "cosmwasm-std"
version = "1.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a49b85345e811c8e80ec55d0d091e4fcb4f00f97ab058f9be5f614c444a730cb"
dependencies = [
"base64 0.13.1",
"cosmwasm-crypto",
"cosmwasm-derive",
"derivative",
"forward_ref",
"hex",
"schemars",
"serde",
"serde-json-wasm",
"serde-json-wasm 0.5.1",
"sha2 0.10.6",
"thiserror",
"uint",
]
@@ -783,9 +805,9 @@ checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
[[package]]
name = "crypto-bigint"
version = "0.3.2"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03c6a1d5fa1de37e071642dfa44ec552ca5b299adb128fab16138e24b548fd21"
checksum = "ef2b4b23cddf68b89b8f8069890e8c270d54e2d5fe1b143820234805e4cb17ef"
dependencies = [
"generic-array 0.14.7",
"rand_core 0.6.4",
@@ -866,10 +888,25 @@ dependencies = [
]
[[package]]
name = "cw-storage-plus"
version = "0.13.4"
name = "cw-controllers"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "648b1507290bbc03a8d88463d7cd9b04b1fa0155e5eef366c4fa052b9caaac7a"
checksum = "91440ce8ec4f0642798bc8c8cb6b9b53c1926c6dadaf0eed267a5145cd529071"
dependencies = [
"cosmwasm-schema",
"cosmwasm-std",
"cw-storage-plus",
"cw-utils",
"schemars",
"serde",
"thiserror",
]
[[package]]
name = "cw-storage-plus"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "053a5083c258acd68386734f428a5a171b29f7d733151ae83090c6fcc9417ffa"
dependencies = [
"cosmwasm-std",
"schemars",
@@ -878,22 +915,26 @@ dependencies = [
[[package]]
name = "cw-utils"
version = "0.13.4"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9dbaecb78c8e8abfd6b4258c7f4fbeb5c49a5e45ee4d910d3240ee8e1d714e1b"
checksum = "c80e93d1deccb8588db03945016a292c3c631e6325d349ebb35d2db6f4f946f7"
dependencies = [
"cosmwasm-schema",
"cosmwasm-std",
"cw2",
"schemars",
"semver 1.0.17",
"serde",
"thiserror",
]
[[package]]
name = "cw2"
version = "0.13.4"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04cf4639517490dd36b333bbd6c4fbd92e325fd0acf4683b41753bc5eb63bfc1"
checksum = "8fb70cee2cf0b4a8ff7253e6bc6647107905e8eb37208f87d54f67810faa62f8"
dependencies = [
"cosmwasm-schema",
"cosmwasm-std",
"cw-storage-plus",
"schemars",
@@ -901,11 +942,12 @@ dependencies = [
]
[[package]]
name = "cw3"
version = "0.13.4"
name = "cw20"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe19462a7f644ba60c19d3443cb90d00c50d9b6b3b0a3a7fca93df8261af979b"
checksum = "91666da6c7b40c8dd5ff94df655a28114efc10c79b70b4d06f13c31e37d60609"
dependencies = [
"cosmwasm-schema",
"cosmwasm-std",
"cw-utils",
"schemars",
@@ -913,11 +955,27 @@ dependencies = [
]
[[package]]
name = "cw4"
version = "0.13.4"
name = "cw3"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0acc3549d5ce11c6901b3a676f2e2628684722197054d97cd0101ea174ed5cbd"
checksum = "2fe0b587008aa221cd2a2579a21990a28c4347dc53ad43167c68ad765f5b6efa"
dependencies = [
"cosmwasm-schema",
"cosmwasm-std",
"cw-utils",
"cw20",
"schemars",
"serde",
"thiserror",
]
[[package]]
name = "cw4"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c236e0bae02ce97e89235a681dd0e07d099524b369f1ef908d704db3e6b049b"
dependencies = [
"cosmwasm-schema",
"cosmwasm-std",
"cw-storage-plus",
"schemars",
@@ -939,11 +997,23 @@ dependencies = [
[[package]]
name = "der"
version = "0.5.1"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6919815d73839e7ad218de758883aae3a257ba6759ce7a9992501efbb53d705c"
checksum = "f1a467a65c5e759bce6e65eaf91cc29f466cdc57cb65777bd646872a8a1fd4de"
dependencies = [
"const-oid",
"zeroize",
]
[[package]]
name = "derivative"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]]
@@ -1036,9 +1106,9 @@ checksum = "68b0cf012f1230e43cd00ebb729c6bb58707ecfa8ad08b52ef3a4ccd2697fc30"
[[package]]
name = "ecdsa"
version = "0.13.4"
version = "0.14.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d0d69ae62e0ce582d56380743515fefaf1a8c70cec685d9677636d7e30ae9dc9"
checksum = "413301934810f597c1d19ca71c8710e99a3f1ba28a0d2ebc01551a2daeea3c5c"
dependencies = [
"der",
"elliptic-curve",
@@ -1094,16 +1164,18 @@ checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91"
[[package]]
name = "elliptic-curve"
version = "0.11.12"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25b477563c2bfed38a3b7a60964c49e058b2510ad3f12ba3483fd8f62c2306d6"
checksum = "e7bb888ab5300a19b8e5bceef25ac745ad065f3c9f7efc6de1b91958110891d3"
dependencies = [
"base16ct",
"crypto-bigint",
"der",
"ff 0.11.1",
"digest 0.10.6",
"ff 0.12.1",
"generic-array 0.14.7",
"group 0.11.0",
"group 0.12.1",
"pkcs8",
"rand_core 0.6.4",
"sec1",
"subtle 2.4.1",
@@ -1218,6 +1290,16 @@ dependencies = [
"subtle 2.4.1",
]
[[package]]
name = "ff"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d013fc25338cc558c5c2cfbad646908fb23591e2404481826742b651c9af7160"
dependencies = [
"rand_core 0.6.4",
"subtle 2.4.1",
]
[[package]]
name = "flate2"
version = "1.0.26"
@@ -1428,9 +1510,9 @@ dependencies = [
[[package]]
name = "getrandom"
version = "0.2.9"
version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4"
checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427"
dependencies = [
"cfg-if 1.0.0",
"js-sys",
@@ -1510,6 +1592,17 @@ dependencies = [
"subtle 2.4.1",
]
[[package]]
name = "group"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5dfbfb3a6cfbd390d5c9564ab283a0349b9b9fcd46a706c1eb10e0db70bfbac7"
dependencies = [
"ff 0.12.1",
"rand_core 0.6.4",
"subtle 2.4.1",
]
[[package]]
name = "h2"
version = "0.3.19"
@@ -1964,15 +2057,14 @@ dependencies = [
[[package]]
name = "k256"
version = "0.10.4"
version = "0.11.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19c3a5e0a0b8450278feda242592512e09f61c72e018b8cd5c859482802daf2d"
checksum = "72c1e0b51e7ec0a97369623508396067a486bd0cbed95a2659a4b863d28cfc8b"
dependencies = [
"cfg-if 1.0.0",
"ecdsa",
"elliptic-curve",
"sec1",
"sha2 0.9.9",
"sha2 0.10.6",
"sha3",
]
@@ -2226,7 +2318,7 @@ dependencies = [
[[package]]
name = "nym-bin-common"
version = "0.5.0"
version = "0.6.0"
dependencies = [
"atty",
"clap",
@@ -2241,9 +2333,10 @@ dependencies = [
[[package]]
name = "nym-client-core"
version = "1.1.14"
version = "1.1.15"
dependencies = [
"async-trait",
"base64 0.21.2",
"dashmap",
"dirs 4.0.0",
"futures",
@@ -2266,6 +2359,7 @@ dependencies = [
"rand 0.7.3",
"serde",
"serde_json",
"sha2 0.10.6",
"sqlx 0.6.3",
"tap",
"thiserror",
@@ -2284,7 +2378,7 @@ dependencies = [
[[package]]
name = "nym-client-wasm"
version = "1.1.0"
version = "1.1.1"
dependencies = [
"anyhow",
"async-trait",
@@ -2329,7 +2423,7 @@ dependencies = [
"bs58",
"digest 0.9.0",
"ff 0.11.1",
"getrandom 0.2.9",
"getrandom 0.2.10",
"group 0.11.0",
"itertools",
"nym-dkg",
@@ -2389,7 +2483,7 @@ dependencies = [
[[package]]
name = "nym-contracts-common"
version = "0.4.0"
version = "0.5.0"
dependencies = [
"bs58",
"cosmwasm-std",
@@ -2424,7 +2518,7 @@ dependencies = [
[[package]]
name = "nym-crypto"
version = "0.3.0"
version = "0.4.0"
dependencies = [
"aes 0.8.2",
"blake3",
@@ -2468,12 +2562,23 @@ dependencies = [
"zeroize",
]
[[package]]
name = "nym-ephemera-common"
version = "0.1.0"
dependencies = [
"cosmwasm-std",
"cw-utils",
"nym-contracts-common",
"schemars",
"serde",
]
[[package]]
name = "nym-gateway-client"
version = "0.1.0"
dependencies = [
"futures",
"getrandom 0.2.9",
"getrandom 0.2.10",
"log",
"nym-bandwidth-controller",
"nym-coconut-interface",
@@ -2524,6 +2629,8 @@ dependencies = [
name = "nym-group-contract-common"
version = "0.1.0"
dependencies = [
"cosmwasm-schema",
"cw-controllers",
"cw4",
"schemars",
"serde",
@@ -2531,7 +2638,7 @@ dependencies = [
[[package]]
name = "nym-mixnet-contract-common"
version = "0.5.0"
version = "0.6.0"
dependencies = [
"bs58",
"cosmwasm-std",
@@ -2540,7 +2647,7 @@ dependencies = [
"nym-contracts-common",
"schemars",
"serde",
"serde-json-wasm",
"serde-json-wasm 0.4.1",
"serde_repr",
"thiserror",
"time",
@@ -2550,7 +2657,9 @@ dependencies = [
name = "nym-multisig-contract-common"
version = "0.1.0"
dependencies = [
"cosmwasm-schema",
"cosmwasm-std",
"cw-storage-plus",
"cw-utils",
"cw3",
"cw4",
@@ -2620,7 +2729,7 @@ dependencies = [
"chacha20",
"chacha20poly1305",
"curve25519-dalek",
"getrandom 0.2.9",
"getrandom 0.2.10",
"log",
"rand 0.7.3",
"rayon",
@@ -2631,7 +2740,7 @@ dependencies = [
[[package]]
name = "nym-pemstore"
version = "0.2.0"
version = "0.3.0"
dependencies = [
"pem",
]
@@ -2641,8 +2750,12 @@ name = "nym-service-provider-directory-common"
version = "0.1.0"
dependencies = [
"cosmwasm-std",
"cw-controllers",
"cw-utils",
"nym-contracts-common",
"schemars",
"serde",
"thiserror",
]
[[package]]
@@ -2677,6 +2790,7 @@ dependencies = [
"nym-pemstore",
"nym-sphinx-addressing",
"nym-sphinx-params",
"nym-sphinx-routing",
"nym-sphinx-types",
"nym-topology",
"rand 0.7.3",
@@ -2703,6 +2817,7 @@ dependencies = [
"nym-crypto",
"nym-sphinx-addressing",
"nym-sphinx-params",
"nym-sphinx-routing",
"nym-sphinx-types",
"nym-topology",
"rand 0.7.3",
@@ -2733,6 +2848,7 @@ dependencies = [
"nym-sphinx-chunking",
"nym-sphinx-forwarding",
"nym-sphinx-params",
"nym-sphinx-routing",
"nym-sphinx-types",
"nym-topology",
"rand 0.7.3",
@@ -2796,7 +2912,7 @@ dependencies = [
"aes-gcm",
"argon2",
"generic-array 0.14.7",
"getrandom 0.2.9",
"getrandom 0.2.10",
"rand 0.8.5",
"serde",
"serde_json",
@@ -2856,6 +2972,7 @@ dependencies = [
"nym-coconut-interface",
"nym-config",
"nym-contracts-common",
"nym-ephemera-common",
"nym-group-contract-common",
"nym-mixnet-contract-common",
"nym-multisig-contract-common",
@@ -2864,6 +2981,7 @@ dependencies = [
"nym-service-provider-directory-common",
"nym-vesting-contract",
"nym-vesting-contract-common",
"openssl",
"prost",
"reqwest",
"serde",
@@ -2895,7 +3013,7 @@ dependencies = [
[[package]]
name = "nym-vesting-contract-common"
version = "0.6.0"
version = "0.7.0"
dependencies = [
"cosmwasm-std",
"nym-contracts-common",
@@ -2954,6 +3072,15 @@ version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
[[package]]
name = "openssl-src"
version = "111.26.0+1.1.1u"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "efc62c9f12b22b8f5208c23a7200a442b2e5999f8bdf80233852122b5a4f6f37"
dependencies = [
"cc",
]
[[package]]
name = "openssl-sys"
version = "0.9.87"
@@ -2962,6 +3089,7 @@ checksum = "8e17f59264b2809d77ae94f0e1ebabc434773f370d6ca667bd223ea10e06cc7e"
dependencies = [
"cc",
"libc",
"openssl-src",
"pkg-config",
"vcpkg",
]
@@ -3047,11 +3175,11 @@ checksum = "9f746c4065a8fa3fe23974dd82f15431cc8d40779821001404d10d2e79ca7d79"
[[package]]
name = "pbkdf2"
version = "0.9.0"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f05894bce6a1ba4be299d0c5f29563e08af2bc18bb7d48313113bed71e904739"
checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917"
dependencies = [
"crypto-mac 0.11.1",
"digest 0.10.6",
]
[[package]]
@@ -3176,13 +3304,12 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
name = "pkcs8"
version = "0.8.0"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7cabda3fb821068a9a4fab19a683eac3af12edf0f34b94a8be53c4972b8149d0"
checksum = "9eca2c590a5f85da82668fa685c09ce2888b9430e83299debf1f34b65fd4a4ba"
dependencies = [
"der",
"spki",
"zeroize",
]
[[package]]
@@ -3382,7 +3509,7 @@ version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
dependencies = [
"getrandom 0.2.9",
"getrandom 0.2.10",
]
[[package]]
@@ -3450,7 +3577,7 @@ version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b"
dependencies = [
"getrandom 0.2.9",
"getrandom 0.2.10",
"redox_syscall 0.2.16",
"thiserror",
]
@@ -3478,7 +3605,7 @@ version = "0.11.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cde824a14b7c14f85caff81225f411faacc04a2013f41670f41443742b1c1c55"
dependencies = [
"base64 0.21.0",
"base64 0.21.2",
"bytes",
"encoding_rs",
"futures-core",
@@ -3511,12 +3638,12 @@ dependencies = [
[[package]]
name = "rfc6979"
version = "0.1.0"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96ef608575f6392792f9ecf7890c00086591d29a83910939d430753f7c050525"
checksum = "7743f17af12fa0b03b803ba12cd6a8d9483a587e89c69445e3909655c0b9fabb"
dependencies = [
"crypto-bigint",
"hmac 0.11.0",
"hmac 0.12.1",
"zeroize",
]
@@ -3535,6 +3662,15 @@ dependencies = [
"winapi",
]
[[package]]
name = "ripemd"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd124222d17ad93a644ed9d011a40f4fb64aa54275c08cc216524a9ea82fb09f"
dependencies = [
"digest 0.10.6",
]
[[package]]
name = "ripemd160"
version = "0.9.1"
@@ -3612,7 +3748,7 @@ version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d194b56d58803a43635bdc398cd17e383d6f71f9182b9a192c127ca42494a59b"
dependencies = [
"base64 0.21.0",
"base64 0.21.2",
]
[[package]]
@@ -3704,10 +3840,11 @@ dependencies = [
[[package]]
name = "sec1"
version = "0.2.1"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08da66b8b0965a5555b6bd6639e68ccba85e1e2506f5fbb089e93f8a04e1a2d1"
checksum = "3be24c1842290c45df0a7bf069e0c268a747ad05a192f2fd7dcfdbc1cba40928"
dependencies = [
"base16ct",
"der",
"generic-array 0.14.7",
"pkcs8",
@@ -3780,6 +3917,15 @@ dependencies = [
"serde",
]
[[package]]
name = "serde-json-wasm"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "16a62a1fad1e1828b24acac8f2b468971dade7b8c3c2e672bcadefefb1f8c137"
dependencies = [
"serde",
]
[[package]]
name = "serde-wasm-bindgen"
version = "0.5.0"
@@ -3915,14 +4061,12 @@ dependencies = [
[[package]]
name = "sha3"
version = "0.9.1"
version = "0.10.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f81199417d4e5de3f04b1e871023acea7389672c4135918f05aa9cbf2f2fa809"
checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60"
dependencies = [
"block-buffer 0.9.0",
"digest 0.9.0",
"digest 0.10.6",
"keccak",
"opaque-debug 0.3.0",
]
[[package]]
@@ -3936,11 +4080,11 @@ dependencies = [
[[package]]
name = "signature"
version = "1.4.0"
version = "1.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02658e48d89f2bec991f9a78e69cfa4c316f8d6a6c4ec12fae1aeb263d486788"
checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c"
dependencies = [
"digest 0.9.0",
"digest 0.10.6",
"rand_core 0.6.4",
]
@@ -4010,9 +4154,9 @@ dependencies = [
[[package]]
name = "spki"
version = "0.5.4"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44d01ac02a6ccf3e07db148d2be087da624fea0221a16152ed01f0496a6b0a27"
checksum = "67cf02bbac7a337dc36e4f5a693db6c21e7863f45070f7064577eb4367a3212b"
dependencies = [
"base64ct",
"der",
@@ -4297,9 +4441,9 @@ dependencies = [
[[package]]
name = "tendermint"
version = "0.23.7"
version = "0.23.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ca881fa4dedd2b46334f13be7fbc8cc1549ba4be5a833fe4e73d1a1baaf7949"
checksum = "a199518e0366ba0aeb0d0e0a59dbd99ea0bdc14280f414ecc758c9228a454ad8"
dependencies = [
"async-trait",
"bytes",
@@ -4328,9 +4472,9 @@ dependencies = [
[[package]]
name = "tendermint-config"
version = "0.23.7"
version = "0.23.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6c56ee93f4e9b7e7daba86d171f44572e91b741084384d0ae00df7991873dfd"
checksum = "c6d8f6a64ae3b59ea3c73efad727271ee085b544b817d7f46901817ca6bb1773"
dependencies = [
"flex-error",
"serde",
@@ -4342,9 +4486,9 @@ dependencies = [
[[package]]
name = "tendermint-proto"
version = "0.23.7"
version = "0.23.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b71f925d74903f4abbdc4af0110635a307b3cb05b175fdff4a7247c14a4d0874"
checksum = "1b303d6387aaea38cea7ef924476d1f798573044e7b4f6ddd1166ac5184b2281"
dependencies = [
"bytes",
"flex-error",
@@ -4360,15 +4504,15 @@ dependencies = [
[[package]]
name = "tendermint-rpc"
version = "0.23.7"
version = "0.23.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a13e63f57ee05a1e927887191c76d1b139de9fa40c180b9f8727ee44377242a6"
checksum = "3036f0b65baa11e767dabd22a0663e842b595b0a1903f149b7b8b1e09b2b443d"
dependencies = [
"async-trait",
"bytes",
"flex-error",
"futures",
"getrandom 0.2.9",
"getrandom 0.2.10",
"http",
"hyper",
"hyper-proxy",
@@ -4768,7 +4912,7 @@ version = "1.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "345444e32442451b267fc254ae85a209c64be56d2890e601a0c37ff0c3c5ecd2"
dependencies = [
"getrandom 0.2.9",
"getrandom 0.2.10",
"wasm-bindgen",
]
@@ -4944,7 +5088,7 @@ name = "wasm-utils"
version = "0.1.0"
dependencies = [
"futures",
"getrandom 0.2.9",
"getrandom 0.2.10",
"indexed_db_futures",
"js-sys",
"nym-store-cipher",
+1 -1
View File
@@ -1,7 +1,7 @@
[package]
name = "nym-client-wasm"
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jedrzej Stuczynski <andrew@nymtech.net>"]
version = "1.1.0"
version = "1.1.1"
edition = "2021"
keywords = ["nym", "sphinx", "wasm", "webassembly", "privacy", "client"]
license = "Apache-2.0"
+3
View File
@@ -3,3 +3,6 @@ clippy:
test:
wasm-pack test --node
wasm-build:
wasm-pack build
@@ -8,6 +8,7 @@
},
"scripts": {
"build": "webpack --config webpack.config.js",
"build:wasm": "cd ../ && make wasm-build",
"start": "webpack-dev-server --port 8001"
},
"repository": {
@@ -36,4 +37,4 @@
"dependencies": {
"@nymproject/nym-client-wasm": "file:../pkg"
}
}
}
+302 -264
View File
@@ -12,333 +12,371 @@
// See the License for the specific language governing permissions and
// limitations under the License.
importScripts('nym_client_wasm.js');
importScripts("nym_client_wasm.js");
console.log('Initializing worker');
console.log("Initializing worker");
// wasm_bindgen creates a global variable (with the exports attached) that is in scope after `importScripts`
const {
NymNodeTester,
WasmGateway,
WasmMixNode,
WasmNymTopology,
default_debug,
NymClientBuilder,
NymClient,
set_panic_hook,
Config,
GatewayEndpointConfig,
ClientStorage,
current_network_topology,
make_key,
make_key2
NymNodeTester,
WasmGateway,
WasmMixNode,
WasmNymTopology,
default_debug,
NymClientBuilder,
NymClient,
set_panic_hook,
Config,
GatewayEndpointConfig,
ClientStorage,
current_network_topology,
make_key,
make_key2,
} = wasm_bindgen;
let client = null;
let tester = null;
const preferredGateway = "336yuXAeGEgedRfqTJZsG2YV7P13QH1bHv1SjCZYarc9";
function dummyTopology() {
const l1Mixnode = new WasmMixNode(
1,
'n1fzv4jc7fanl9s0qj02ge2ezk3kts545kjtek47',
'178.79.143.65',
1789,
'4Yr4qmEHd9sgsuQ83191FR2hD88RfsbMmB4tzhhZWriz',
'8ndjk5oZ6HxUZNScLJJ7hk39XtUqGexdKgW7hSX6kpWG',
1,
'1.10.0',
);
const l2Mixnode = new WasmMixNode(
2,
'n1z93z44vf8ssvdhujjvxcj4rd5e3lz0l60wdk70',
'109.74.197.180',
1789,
'7sVjiMrPYZrDWRujku9QLxgE8noT7NTgBAqizCsu7AoK',
'GepXwRnKZDd8x2nBWAajGGBVvF3mrpVMQBkgfrGuqRCN',
2,
'1.10.0',
);
const l3Mixnode = new WasmMixNode(
3,
'n1ptg680vnmef2cd8l0s9uyc4f0hgf3x8sed6w77',
'176.58.101.80',
1789,
'FoM5Mx9Pxk1g3zEqkS3APgtBeTtTo3M8k7Yu4bV6kK1R',
'DeYjrDC2AcQRVFshiKnbUo6bRvPyZ33QGYR2DLeFJ9qD',
3,
'1.10.0',
);
const l1Mixnode = new WasmMixNode(
1,
"n1fzv4jc7fanl9s0qj02ge2ezk3kts545kjtek47",
"178.79.143.65",
1789,
"4Yr4qmEHd9sgsuQ83191FR2hD88RfsbMmB4tzhhZWriz",
"8ndjk5oZ6HxUZNScLJJ7hk39XtUqGexdKgW7hSX6kpWG",
1,
"1.10.0"
);
const l2Mixnode = new WasmMixNode(
2,
"n1z93z44vf8ssvdhujjvxcj4rd5e3lz0l60wdk70",
"109.74.197.180",
1789,
"7sVjiMrPYZrDWRujku9QLxgE8noT7NTgBAqizCsu7AoK",
"GepXwRnKZDd8x2nBWAajGGBVvF3mrpVMQBkgfrGuqRCN",
2,
"1.10.0"
);
const l3Mixnode = new WasmMixNode(
3,
"n1ptg680vnmef2cd8l0s9uyc4f0hgf3x8sed6w77",
"176.58.101.80",
1789,
"FoM5Mx9Pxk1g3zEqkS3APgtBeTtTo3M8k7Yu4bV6kK1R",
"DeYjrDC2AcQRVFshiKnbUo6bRvPyZ33QGYR2DLeFJ9qD",
3,
"1.10.0"
);
const gateway = new WasmGateway(
'n16evnn8glr0sham3matj8rg2s24m6x56ayk87ts',
'85.159.212.96',
1789,
9000,
'336yuXAeGEgedRfqTJZsG2YV7P13QH1bHv1SjCZYarc9',
'BtYjoWihiuFihGKQypmpSspbhmWDPxzqeTVSd8ciCpWL',
'1.10.1',
);
const gateway = new WasmGateway(
"n16evnn8glr0sham3matj8rg2s24m6x56ayk87ts",
"85.159.212.96",
1789,
9000,
"336yuXAeGEgedRfqTJZsG2YV7P13QH1bHv1SjCZYarc9",
"BtYjoWihiuFihGKQypmpSspbhmWDPxzqeTVSd8ciCpWL",
"1.10.1"
);
const mixnodes = new Map();
mixnodes.set(1, [l1Mixnode]);
mixnodes.set(2, [l2Mixnode]);
mixnodes.set(3, [l3Mixnode]);
const mixnodes = new Map();
mixnodes.set(1, [l1Mixnode]);
mixnodes.set(2, [l2Mixnode]);
mixnodes.set(3, [l3Mixnode]);
const gateways = [gateway];
const gateways = [gateway];
return new WasmNymTopology(mixnodes, gateways)
return new WasmNymTopology(mixnodes, gateways);
}
function printAndDisplayTestResult(result) {
result.log_details();
result.log_details();
self.postMessage({
kind: 'DisplayTesterResults',
args: {
score: result.score(),
sentPackets: result.sent_packets,
receivedPackets: result.received_packets,
receivedAcks: result.received_acks,
duplicatePackets: result.duplicate_packets,
duplicateAcks: result.duplicate_acks,
},
});
self.postMessage({
kind: "DisplayTesterResults",
args: {
score: result.score(),
sentPackets: result.sent_packets,
receivedPackets: result.received_packets,
receivedAcks: result.received_acks,
duplicatePackets: result.duplicate_packets,
duplicateAcks: result.duplicate_acks,
},
});
}
async function testWithTester() {
const preferredGateway = "336yuXAeGEgedRfqTJZsG2YV7P13QH1bHv1SjCZYarc9";
// A) construct with hardcoded topology
const topology = dummyTopology();
const nodeTester = await new NymNodeTester(topology, preferredGateway);
// A) construct with hardcoded topology
const topology = dummyTopology()
const nodeTester = await new NymNodeTester(topology, preferredGateway);
// B) first get topology directly from nym-api
// const validator = 'https://qwerty-validator-api.qa.nymte.ch/api';
// const topology = await current_network_topology(validator)
// const nodeTester = await new NymNodeTester(topology, preferredGateway);
//
// C) use nym-api in the constructor (note: it does no filtering for 'good' nodes on other layers)
// const validator = 'https://qwerty-validator-api.qa.nymte.ch/api';
// const nodeTester = await NymNodeTester.new_with_api(validator, preferredGateway)
// B) first get topology directly from nym-api
// const validator = 'https://qwerty-validator-api.qa.nymte.ch/api';
// const topology = await current_network_topology(validator)
// const nodeTester = await new NymNodeTester(topology, preferredGateway);
//
// C) use nym-api in the constructor (note: it does no filtering for 'good' nodes on other layers)
// const validator = 'https://qwerty-validator-api.qa.nymte.ch/api';
// const nodeTester = await NymNodeTester.new_with_api(validator, preferredGateway)
// B) first get topology directly from nym-api
// const validator = 'https://qwerty-validator-api.qa.nymte.ch/api';
// const topology = await current_network_topology(validator)
// const nodeTester = await new NymNodeTester(topology, undefined, preferredGateway);
//
// C) use nym-api in the constructor (note: it does no filtering for 'good' nodes on other layers)
// const validator = 'https://qwerty-validator-api.qa.nymte.ch/api';
// const nodeTester = await NymNodeTester.new_with_api(validator, undefined, preferredGateway)
// D, E, F) you also don't have to specify the gateway. if you don't, a random one (from your topology) will be used
// const topology = dummyTopology()
// const nodeTester = await new NymNodeTester(topology);
// D, E, F) you also don't have to specify the gateway. if you don't, a random one (from your topology) will be used
// const topology = dummyTopology()
// const nodeTester = await new NymNodeTester(topology);
self.onmessage = async (event) => {
if (event.data && event.data.kind) {
switch (event.data.kind) {
case "TestPacket": {
const { mixnodeIdentity } = event.data.args;
console.log("starting node test...");
self.onmessage = async event => {
if (event.data && event.data.kind) {
switch (event.data.kind) {
case 'TestPacket': {
const {mixnodeIdentity} = event.data.args;
console.log("starting node test...");
let result = await nodeTester.test_node(mixnodeIdentity);
printAndDisplayTestResult(result)
}
}
let result = await nodeTester.test_node(mixnodeIdentity);
printAndDisplayTestResult(result);
}
};
}
}
};
}
async function testerReconnection() {
const validator = "https://qwerty-validator-api.qa.nymte.ch/api";
const nodeTester = await NymNodeTester.new_with_api(validator);
self.onmessage = async (event) => {
if (event.data && event.data.kind) {
switch (event.data.kind) {
case "TestPacket": {
const { mixnodeIdentity } = event.data.args;
console.log("starting node test...");
let result1 = await nodeTester.test_node(mixnodeIdentity);
console.log("sleeping for 5s");
await new Promise((r) => setTimeout(r, 5000));
await nodeTester.disconnect_from_gateway();
console.log("sleeping for 5s");
await new Promise((r) => setTimeout(r, 5000));
await nodeTester.reconnect_to_gateway();
let result2 = await nodeTester.test_node(mixnodeIdentity);
printAndDisplayTestResult(result1);
printAndDisplayTestResult(result2);
}
}
}
};
}
async function testWithNymClient() {
const preferredGateway = "336yuXAeGEgedRfqTJZsG2YV7P13QH1bHv1SjCZYarc9";
const topology = dummyTopology()
const topology = dummyTopology();
let received = 0
let received = 0;
const onMessageHandler = (message) => {
received += 1;
self.postMessage({
kind: 'ReceiveMessage',
args: {
message,
senderTag: undefined,
isTestPacket: true,
},
});
// it's really up to the user to create proper callback here...
console.log(`received ${received} packets so far`)
};
console.log('Instantiating WASM client...');
let clientBuilder = NymClientBuilder.new_tester(topology, onMessageHandler, preferredGateway)
console.log('Web worker creating WASM client...');
let local_client = await clientBuilder.start_client();
console.log('WASM client running!');
const selfAddress = local_client.self_address();
// set the global (I guess we don't have to anymore?)
client = local_client;
console.log(`Client address is ${selfAddress}`);
const onMessageHandler = (message) => {
received += 1;
self.postMessage({
kind: 'Ready',
args: {
selfAddress,
},
kind: "ReceiveMessage",
args: {
message,
senderTag: undefined,
isTestPacket: true,
},
});
// Set callback to handle messages passed to the worker.
self.onmessage = async event => {
console.log(event)
if (event.data && event.data.kind) {
switch (event.data.kind) {
case 'SendMessage': {
const {message, recipient} = event.data.args;
let uint8Array = new TextEncoder().encode(message);
await client.send_regular_message(uint8Array, recipient);
break;
}
case 'TestPacket': {
const {mixnodeIdentity} = event.data.args;
const req = await client.try_construct_test_packet_request(mixnodeIdentity);
await client.change_hardcoded_topology(req.injectable_topology());
await client.try_send_test_packets(req);
break;
}
}
// it's really up to the user to create proper callback here...
console.log(`received ${received} packets so far`);
};
console.log("Instantiating WASM client...");
let clientBuilder = NymClientBuilder.new_tester(
topology,
onMessageHandler,
preferredGateway
);
console.log("Web worker creating WASM client...");
let local_client = await clientBuilder.start_client();
console.log("WASM client running!");
const selfAddress = local_client.self_address();
// set the global (I guess we don't have to anymore?)
client = local_client;
console.log(`Client address is ${selfAddress}`);
self.postMessage({
kind: "Ready",
args: {
selfAddress,
},
});
// Set callback to handle messages passed to the worker.
self.onmessage = async (event) => {
console.log(event);
if (event.data && event.data.kind) {
switch (event.data.kind) {
case "SendMessage": {
const { message, recipient } = event.data.args;
let uint8Array = new TextEncoder().encode(message);
await client.send_regular_message(uint8Array, recipient);
break;
}
};
case "TestPacket": {
const { mixnodeIdentity } = event.data.args;
const req = await client.try_construct_test_packet_request(
mixnodeIdentity
);
await client.change_hardcoded_topology(req.injectable_topology());
await client.try_send_test_packets(req);
break;
}
}
}
};
}
async function normalNymClientUsage() {
self.postMessage({kind: 'DisableMagicTestButton'});
self.postMessage({ kind: "DisableMagicTestButton" });
// only really useful if you want to adjust some settings like traffic rate
// (if not needed you can just pass a null)
const debug = default_debug();
// only really useful if you want to adjust some settings like traffic rate
// (if not needed you can just pass a null)
const debug = default_debug();
debug.disable_main_poisson_packet_distribution = true;
debug.disable_loop_cover_traffic_stream = true;
debug.use_extended_packet_size = false;
// debug.average_packet_delay_ms = BigInt(10);
// debug.average_ack_delay_ms = BigInt(10);
// debug.ack_wait_addition_ms = BigInt(3000);
// debug.ack_wait_multiplier = 10;
debug.disable_main_poisson_packet_distribution = true;
debug.disable_loop_cover_traffic_stream = true;
debug.use_extended_packet_size = false;
// debug.average_packet_delay_ms = BigInt(10);
// debug.average_ack_delay_ms = BigInt(10);
// debug.ack_wait_addition_ms = BigInt(3000);
// debug.ack_wait_multiplier = 10;
debug.topology_refresh_rate_ms = BigInt(60000)
debug.topology_refresh_rate_ms = BigInt(60000);
const preferredGateway = "336yuXAeGEgedRfqTJZsG2YV7P13QH1bHv1SjCZYarc9";
const validator = 'https://qwerty-validator-api.qa.nymte.ch/api';
const preferredGateway = "336yuXAeGEgedRfqTJZsG2YV7P13QH1bHv1SjCZYarc9";
const validator = "https://qwerty-validator-api.qa.nymte.ch/api";
const config = new Config('my-awesome-wasm-client', validator, debug);
const config = new Config("my-awesome-wasm-client", validator, debug);
const onMessageHandler = (message) => {
console.log(message);
self.postMessage({
kind: 'ReceiveMessage',
args: {
message,
},
});
};
console.log('Instantiating WASM client...');
let localClient = await new NymClient(config, onMessageHandler)
console.log('WASM client running!');
const selfAddress = localClient.self_address();
// set the global (I guess we don't have to anymore?)
client = localClient;
console.log(`Client address is ${selfAddress}`);
const onMessageHandler = (message) => {
console.log(message);
self.postMessage({
kind: 'Ready',
args: {
selfAddress,
},
kind: "ReceiveMessage",
args: {
message,
},
});
};
// Set callback to handle messages passed to the worker.
self.onmessage = async event => {
console.log(event)
if (event.data && event.data.kind) {
switch (event.data.kind) {
case 'SendMessage': {
const {message, recipient} = event.data.args;
let uint8Array = new TextEncoder().encode(message);
await client.send_regular_message(uint8Array, recipient);
break;
}
}
console.log("Instantiating WASM client...");
let localClient = await new NymClient(config, onMessageHandler);
console.log("WASM client running!");
const selfAddress = localClient.self_address();
// set the global (I guess we don't have to anymore?)
client = localClient;
console.log(`Client address is ${selfAddress}`);
self.postMessage({
kind: "Ready",
args: {
selfAddress,
},
});
// Set callback to handle messages passed to the worker.
self.onmessage = async (event) => {
console.log(event);
if (event.data && event.data.kind) {
switch (event.data.kind) {
case "SendMessage": {
const { message, recipient } = event.data.args;
let uint8Array = new TextEncoder().encode(message);
await client.send_regular_message(uint8Array, recipient);
break;
}
};
}
}
};
}
async function messWithStorage() {
self.onmessage = async event => {
if (event.data && event.data.kind) {
switch (event.data.kind) {
case 'TestPacket': {
const { mixnodeIdentity } = event.data.args;
console.log("button clicked...", mixnodeIdentity);
self.onmessage = async (event) => {
if (event.data && event.data.kind) {
switch (event.data.kind) {
case "TestPacket": {
const { mixnodeIdentity } = event.data.args;
console.log("button clicked...", mixnodeIdentity);
let id1 = "one";
let id2 = "two";
let id1 = "one";
let id2 = "two";
console.log("making store1 NO-ENC");
let _storage1 = await ClientStorage.new_unencrypted(id1);
console.log("making store1 NO-ENC");
let _storage1 = await ClientStorage.new_unencrypted(id1);
console.log("making store2 ENC")
let _storage2 = await new ClientStorage(id2, "my-secret-password");
//
//
//
// console.log("attempting to use store1 WITH PASSWORD")
// let _storage1_alt = await new ClientStorage(id1, "password");
//
//
//
// console.log("attempting to use store2 WITHOUT PASSWORD")
// let _storage2_alt = await ClientStorage.new_unencrypted(id2);
//
//
//
// console.log("attempting to use store2 with WRONG PASSWORD")
// let _storage2_bad = await new ClientStorage(id2, "bad-password")
console.log("making store2 ENC");
let _storage2 = await new ClientStorage(id2, "my-secret-password");
//
//
//
// console.log("attempting to use store1 WITH PASSWORD")
// let _storage1_alt = await new ClientStorage(id1, "password");
//
//
//
// console.log("attempting to use store2 WITHOUT PASSWORD")
// let _storage2_alt = await ClientStorage.new_unencrypted(id2);
//
//
//
// console.log("attempting to use store2 with WRONG PASSWORD")
// let _storage2_bad = await new ClientStorage(id2, "bad-password")
//
// console.log("read1: ", await storage1.read());
// console.log("read2: ", await storage2.read());
//
// console.log("store1: ", await storage1.store("FOOMP"));
//
// console.log("read1: ", await storage1.read());
// console.log("read2: ", await storage2.read());
}
}
//
// console.log("read1: ", await storage1.read());
// console.log("read2: ", await storage2.read());
//
// console.log("store1: ", await storage1.store("FOOMP"));
//
// console.log("read1: ", await storage1.read());
// console.log("read2: ", await storage2.read());
}
};
}
}
};
}
async function main() {
// load WASM package
await wasm_bindgen('nym_client_wasm_bg.wasm');
console.log('Loaded WASM');
// load WASM package
await wasm_bindgen("nym_client_wasm_bg.wasm");
console.log("Loaded WASM");
// sets up better stack traces in case of in-rust panics
set_panic_hook();
// sets up better stack traces in case of in-rust panics
set_panic_hook();
// run test on simplified and dedicated tester:
// await testWithTester()
// show reconnection capabilities
// await testerReconnection()
// hook-up the whole client for testing
// await testWithNymClient()
// run test on simplified and dedicated tester:
await testWithTester();
// 'Normal' client setup (to send 'normal' messages)
await normalNymClientUsage()
// 'Normal' client setup (to send 'normal' messages)
// await normalNymClientUsage()
}
// Let's get started!
main();
main();
+2 -2
View File
@@ -29,7 +29,7 @@ impl Config {
#[wasm_bindgen(constructor)]
pub fn new(id: String, validator_server: String, debug: Option<DebugWasm>) -> Self {
Config {
base: BaseClientConfig::new(id)
base: BaseClientConfig::new(id, env!("CARGO_PKG_VERSION").to_string())
.with_custom_nyxd(vec![validator_server
.parse()
.expect("provided url was malformed")])
@@ -39,7 +39,7 @@ impl Config {
pub(crate) fn new_tester_config<S: Into<String>>(id: S) -> Self {
Config {
base: BaseClientConfig::new(id)
base: BaseClientConfig::new(id.into(), env!("CARGO_PKG_VERSION").to_string())
.with_disabled_credentials(true)
.with_disabled_cover_traffic(true)
.with_disabled_topology_refresh(true),
+26 -53
View File
@@ -7,7 +7,7 @@ use crate::client::response_pusher::ResponsePusher;
use crate::constants::NODE_TESTER_CLIENT_ID;
use crate::error::WasmClientError;
use crate::helpers::{
choose_gateway, gateway_from_topology, parse_recipient, parse_sender_tag,
parse_recipient, parse_sender_tag, setup_from_topology, setup_gateway_from_api,
setup_reply_surb_storage_backend,
};
use crate::storage::traits::FullWasmClientStorage;
@@ -15,13 +15,11 @@ use crate::storage::ClientStorage;
use crate::topology::WasmNymTopology;
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, ClientState, CredentialsToggle,
BaseClientBuilder, ClientInput, ClientOutput, ClientState,
};
use nym_client_core::client::inbound_messages::InputMessage;
use nym_client_core::client::replies::reply_storage::browser_backend;
use nym_credential_storage::ephemeral_storage::EphemeralStorage;
use nym_credential_storage::ephemeral_storage::EphemeralStorage as EphemeralCredentialStorage;
use nym_sphinx::params::PacketType;
use nym_task::connections::TransmissionLane;
use nym_task::TaskManager;
@@ -29,7 +27,7 @@ use nym_topology::provider_trait::{HardcodedTopologyProvider, TopologyProvider};
use nym_topology::NymTopology;
use nym_validator_client::client::IdentityKey;
use rand::rngs::OsRng;
use rand::{thread_rng, RngCore};
use rand::RngCore;
use std::sync::Arc;
use wasm_bindgen::prelude::*;
use wasm_bindgen_futures::future_to_promise;
@@ -63,14 +61,7 @@ pub struct NymClientBuilder {
preferred_gateway: Option<IdentityKey>,
storage_passphrase: Option<String>,
reply_surb_storage_backend: browser_backend::Backend,
on_message: js_sys::Function,
// unimplemented:
bandwidth_controller:
Option<BandwidthController<FakeClient<DirectSigningNyxdClient>, EphemeralStorage>>,
disabled_credentials: bool,
}
#[wasm_bindgen]
@@ -83,15 +74,10 @@ impl NymClientBuilder {
storage_passphrase: Option<String>,
) -> Self {
NymClientBuilder {
reply_surb_storage_backend: setup_reply_surb_storage_backend(
config.base.debug.reply_surbs,
),
config,
custom_topology: None,
storage_passphrase,
on_message,
bandwidth_controller: None,
disabled_credentials: true,
preferred_gateway,
}
}
@@ -114,14 +100,9 @@ impl NymClientBuilder {
let full_config = Config::new_tester_config(NODE_TESTER_CLIENT_ID);
NymClientBuilder {
reply_surb_storage_backend: setup_reply_surb_storage_backend(
full_config.base.debug.reply_surbs,
),
config: full_config,
custom_topology: Some(topology.into()),
on_message,
bandwidth_controller: None,
disabled_credentials: true,
storage_passphrase: None,
preferred_gateway: gateway,
}
@@ -139,15 +120,17 @@ impl NymClientBuilder {
}
}
fn initialise_storage(config: &Config, base_storage: ClientStorage) -> FullWasmClientStorage {
FullWasmClientStorage {
keys_and_gateway_store: base_storage,
reply_storage: setup_reply_surb_storage_backend(config.base.debug.reply_surbs),
credential_storage: EphemeralCredentialStorage::default(),
}
}
async fn start_client_async(mut self) -> Result<NymClient, WasmClientError> {
console_log!("Starting the wasm client");
let disabled_credentials = if self.disabled_credentials {
CredentialsToggle::Disabled
} else {
CredentialsToggle::Enabled
};
let nym_api_endpoints = self.config.base.client.nym_api_urls.clone();
// TODO: this will have to be re-used for surbs. but this is a problem for another PR.
@@ -155,35 +138,25 @@ impl NymClientBuilder {
ClientStorage::new_async(&self.config.base.client.id, self.storage_passphrase.take())
.await?;
let user_chosen = self.preferred_gateway.clone();
// if we provided hardcoded topology, get gateway from it, otherwise get it the 'standard' way
let gateway_endpoint = if let Some(topology) = &self.custom_topology {
gateway_from_topology(
&mut thread_rng(),
self.preferred_gateway.as_deref(),
topology,
&client_store,
)
.await?
if let Some(topology) = &self.custom_topology {
setup_from_topology(user_chosen, topology, &client_store).await?
} else {
choose_gateway(
&client_store,
self.preferred_gateway.clone(),
&nym_api_endpoints,
)
.await?
setup_gateway_from_api(&client_store, user_chosen, &nym_api_endpoints).await?
};
let packet_type = self.config.base.debug.traffic.packet_type;
let storage = Self::initialise_storage(&self.config, client_store);
let maybe_topology_provider = self.topology_provider();
let mut base_builder: BaseClientBuilder<_, FullWasmClientStorage> = BaseClientBuilder::new(
&gateway_endpoint,
&self.config.base.debug,
client_store,
self.bandwidth_controller,
self.reply_surb_storage_backend,
disabled_credentials,
nym_api_endpoints,
);
let mut base_builder: BaseClientBuilder<_, FullWasmClientStorage> =
BaseClientBuilder::<FakeClient<DirectSigningNyxdClient>, _>::new(
&self.config.base,
storage,
None,
);
if let Some(topology_provider) = maybe_topology_provider {
base_builder = base_builder.with_topology_provider(topology_provider);
}
@@ -202,7 +175,7 @@ impl NymClientBuilder {
client_state: Arc::new(started_client.client_state),
_full_topology: None,
_task_manager: started_client.task_manager,
packet_type: self.config.base.debug.traffic.packet_type,
packet_type,
})
}
+32 -83
View File
@@ -7,19 +7,18 @@ use crate::topology::WasmNymTopology;
use js_sys::Promise;
use nym_client_core::client::replies::reply_storage::browser_backend;
use nym_client_core::config;
use nym_client_core::config::GatewayEndpointConfig;
use nym_client_core::init::GatewaySetup;
use nym_crypto::asymmetric::identity;
use nym_client_core::init::helpers::current_gateways;
use nym_client_core::init::{setup_gateway_from, GatewaySetup, InitialisationDetails};
use nym_sphinx::addressing::clients::Recipient;
use nym_sphinx::anonymous_replies::requests::AnonymousSenderTag;
use nym_topology::NymTopology;
use nym_validator_client::client::{IdentityKey, IdentityKeyRef};
use nym_topology::{gateway, NymTopology};
use nym_validator_client::client::IdentityKey;
use nym_validator_client::NymApiClient;
use rand::{CryptoRng, Rng};
use rand::thread_rng;
use url::Url;
use wasm_bindgen::prelude::wasm_bindgen;
use wasm_bindgen_futures::future_to_promise;
use wasm_utils::{console_log, PromisableResult};
use wasm_utils::PromisableResult;
// don't get too excited about the name, under the hood it's just a big fat placeholder
// with no disk_persistence
@@ -79,87 +78,37 @@ pub fn current_network_topology(nym_api_url: String) -> Promise {
})
}
pub(crate) async fn choose_gateway(
async fn setup_gateway(
client_store: &ClientStorage,
chosen_gateway: Option<IdentityKey>,
gateways: &[gateway::Node],
) -> Result<InitialisationDetails, WasmClientError> {
let setup = if client_store.has_full_gateway_info().await? {
GatewaySetup::MustLoad
} else {
GatewaySetup::new_fresh(chosen_gateway.clone(), None)
};
setup_gateway_from(&setup, client_store, client_store, false, Some(gateways))
.await
.map_err(Into::into)
}
pub(crate) async fn setup_gateway_from_api(
client_store: &ClientStorage,
chosen_gateway: Option<IdentityKey>,
nym_apis: &[Url],
) -> Result<GatewayEndpointConfig, WasmClientError> {
let existing_gateway_config = client_store.read_gateway_config().await?;
console_log!("loaded: {:?}", existing_gateway_config);
if let Some(existing) = existing_gateway_config {
if let Some(provided) = &chosen_gateway {
if provided != &existing.gateway_id {
return Err(WasmClientError::AlreadyRegistered {
gateway_config: existing,
});
}
}
return Ok(existing);
};
// if NOTHING is specified nor available, choose gateway randomly.
let setup = GatewaySetup::new(None, chosen_gateway, None);
let config = setup.try_get_gateway_details(nym_apis).await?;
// perform registration + persist the new gateway info
// TODO: this is actually quite bad. we shouldn't be persisting gateway info here since we did not have persisted
// the shared key yet. this will only happen when we start the base client itself.
// but unfortunately, we can't do much more until we do a bit more refactoring.
client_store.store_gateway_config(&config).await?;
console_log!("stored: {:?}", config);
Ok(config)
) -> Result<InitialisationDetails, WasmClientError> {
let mut rng = thread_rng();
let gateways = current_gateways(&mut rng, nym_apis).await?;
setup_gateway(client_store, chosen_gateway, &gateways).await
}
pub(crate) async fn gateway_from_topology<R: Rng + CryptoRng>(
rng: &mut R,
explicit_gateway: Option<IdentityKeyRef<'_>>,
pub(crate) async fn setup_from_topology(
explicit_gateway: Option<IdentityKey>,
topology: &NymTopology,
client_store: &ClientStorage,
) -> Result<GatewayEndpointConfig, WasmClientError> {
let existing_gateway_config = client_store.read_gateway_config().await?;
console_log!("loaded: {:?}", existing_gateway_config);
let new_gateway: GatewayEndpointConfig = if let Some(provided) = explicit_gateway {
if let Some(existing) = existing_gateway_config {
// we have stored gateway info and explicitly provided identity key
//
// check if they match, otherwise return an error
return if provided != existing.gateway_id {
Err(WasmClientError::AlreadyRegistered {
gateway_config: existing,
})
} else {
Ok(existing)
};
} else {
// we have explicitly provided identity key and didn't have any prior stored data
//
// try to grab details from the topology
let gateway_identity = identity::PublicKey::from_base58_string(provided)
.map_err(|source| WasmClientError::InvalidGatewayIdentity { source })?;
if let Some(gateway) = topology.get_gateway(&gateway_identity) {
gateway.clone().into()
} else {
return Err(WasmClientError::NonExistentGateway {
gateway_identity: gateway_identity.to_base58_string(),
});
}
}
} else if let Some(existing) = existing_gateway_config {
// we have stored data and didn't provide anything separately - use what's stored!
return Ok(existing);
} else {
// we don't have anything stored nor we have provided anything
//
// just grab random gateway from our topology
topology.random_gateway(rng)?.clone().into()
};
console_log!("storing: {:?}", new_gateway);
client_store.store_gateway_config(&new_gateway).await?;
Ok(new_gateway)
) -> Result<InitialisationDetails, WasmClientError> {
let gateways = topology.gateways();
setup_gateway(client_store, explicit_gateway, gateways).await
}
@@ -16,6 +16,9 @@ pub enum ClientStorageError {
#[error("{typ} cryptographic key is not available in storage")]
CryptoKeyNotInStorage { typ: String },
#[error("the prior gateway details are not available in the storage")]
GatewayDetailsNotInStorage,
}
impl From<ClientStorageError> for JsValue {
+44 -10
View File
@@ -1,9 +1,10 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::client::config::Config;
use crate::storage::errors::ClientStorageError;
use js_sys::Promise;
use nym_client_core::config::GatewayEndpointConfig;
use nym_client_core::client::base_client::storage::gateway_details::PersistedGatewayDetails;
use nym_crypto::asymmetric::{encryption, identity};
use nym_gateway_client::SharedKeys;
use nym_sphinx::acknowledgements::AckKey;
@@ -27,8 +28,8 @@ mod v1 {
pub const CORE_STORE: &str = "core";
// keys
// TODO: to replace with FULL config
pub const GATEWAY_CONFIG: &str = "gateway_config";
pub const CONFIG: &str = "config";
pub const GATEWAY_DETAILS: &str = "gateway_details";
pub const ED25519_IDENTITY_KEYPAIR: &str = "ed25519_identity_keypair";
pub const X25519_ENCRYPTION_KEYPAIR: &str = "x25519_encryption_keypair";
@@ -110,15 +111,32 @@ impl ClientStorage {
})
}
pub(crate) async fn read_gateway_config(
&self,
) -> Result<Option<GatewayEndpointConfig>, ClientStorageError> {
// TODO: persist client's config
#[allow(dead_code)]
pub(crate) async fn read_config(&self) -> Result<Option<Config>, ClientStorageError> {
self.inner
.read_value(v1::CORE_STORE, JsValue::from_str(v1::GATEWAY_CONFIG))
.read_value(v1::CORE_STORE, JsValue::from_str(v1::CONFIG))
.await
.map_err(Into::into)
}
pub(crate) async fn may_read_gateway_details(
&self,
) -> Result<Option<PersistedGatewayDetails>, ClientStorageError> {
self.inner
.read_value(v1::CORE_STORE, JsValue::from_str(v1::GATEWAY_DETAILS))
.await
.map_err(Into::into)
}
pub(crate) async fn must_read_gateway_details(
&self,
) -> Result<PersistedGatewayDetails, ClientStorageError> {
self.may_read_gateway_details()
.await?
.ok_or(ClientStorageError::GatewayDetailsNotInStorage)
}
async fn may_read_identity_keypair(
&self,
) -> Result<Option<identity::KeyPair>, ClientStorageError> {
@@ -244,17 +262,33 @@ impl ClientStorage {
.map_err(Into::into)
}
pub(crate) async fn store_gateway_config(
pub(crate) async fn store_gateway_details(
&self,
gateway_endpoint: &GatewayEndpointConfig,
gateway_endpoint: &PersistedGatewayDetails,
) -> Result<(), ClientStorageError> {
self.inner
.store_value(
v1::CORE_STORE,
JsValue::from_str(v1::GATEWAY_CONFIG),
JsValue::from_str(v1::GATEWAY_DETAILS),
gateway_endpoint,
)
.await
.map_err(Into::into)
}
// TODO: persist client's config
#[allow(dead_code)]
pub(crate) async fn store_config(&self, config: &Config) -> Result<(), ClientStorageError> {
self.inner
.store_value(v1::CORE_STORE, JsValue::from_str(v1::CONFIG), config)
.await
.map_err(Into::into)
}
pub(crate) async fn has_full_gateway_info(&self) -> Result<bool, ClientStorageError> {
let has_keys = self.may_read_gateway_shared_key().await?.is_some();
let has_details = self.may_read_gateway_details().await?.is_some();
Ok(has_keys && has_details)
}
}
+31 -6
View File
@@ -4,6 +4,9 @@
use crate::storage::errors::ClientStorageError;
use crate::storage::ClientStorage;
use async_trait::async_trait;
use nym_client_core::client::base_client::storage::gateway_details::{
GatewayDetailsStore, PersistedGatewayDetails,
};
use nym_client_core::client::base_client::storage::MixnetClientStorage;
use nym_client_core::client::key_manager::persistence::KeyStore;
use nym_client_core::client::key_manager::KeyManager;
@@ -14,9 +17,9 @@ use wasm_utils::console_log;
// temporary until other variants are properly implemented (probably it should get changed into `ClientStorage`
// implementing all traits and everything getting combined
pub struct FullWasmClientStorage {
key_store: ClientStorage,
reply_storage: browser_backend::Backend,
credential_storage: EphemeralCredentialStorage,
pub(crate) keys_and_gateway_store: ClientStorage,
pub(crate) reply_storage: browser_backend::Backend,
pub(crate) credential_storage: EphemeralCredentialStorage,
}
impl MixnetClientStorage for FullWasmClientStorage {
@@ -24,12 +27,14 @@ impl MixnetClientStorage for FullWasmClientStorage {
type ReplyStore = browser_backend::Backend;
type CredentialStore = EphemeralCredentialStorage;
fn into_split(self) -> (Self::KeyStore, Self::ReplyStore, Self::CredentialStore) {
(self.key_store, self.reply_storage, self.credential_storage)
type GatewayDetailsStore = ClientStorage;
fn into_runtime_stores(self) -> (Self::ReplyStore, Self::CredentialStore) {
(self.reply_storage, self.credential_storage)
}
fn key_store(&self) -> &Self::KeyStore {
&self.key_store
&self.keys_and_gateway_store
}
fn reply_store(&self) -> &Self::ReplyStore {
@@ -39,6 +44,10 @@ impl MixnetClientStorage for FullWasmClientStorage {
fn credential_store(&self) -> &Self::CredentialStore {
&self.credential_storage
}
fn gateway_details_store(&self) -> &Self::GatewayDetailsStore {
&self.keys_and_gateway_store
}
}
#[async_trait(?Send)]
@@ -74,3 +83,19 @@ impl KeyStore for ClientStorage {
.await
}
}
#[async_trait(?Send)]
impl GatewayDetailsStore for ClientStorage {
type StorageError = ClientStorageError;
async fn load_gateway_details(&self) -> Result<PersistedGatewayDetails, Self::StorageError> {
self.must_read_gateway_details().await
}
async fn store_gateway_details(
&self,
details: &PersistedGatewayDetails,
) -> Result<(), Self::StorageError> {
self.store_gateway_details(details).await
}
}
+38
View File
@@ -4,6 +4,9 @@
// due to expansion of #[wasm_bindgen] macro on NodeTestResult
#![allow(clippy::drop_non_drop)]
use crate::error::WasmClientError;
use crate::tester::LockedGatewayClient;
use js_sys::Promise;
use nym_node_tester_utils::processor::Received;
use nym_node_tester_utils::receiver::ReceivedReceiver;
use serde::{Deserialize, Serialize};
@@ -12,6 +15,7 @@ use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use tokio::sync::{Mutex as AsyncMutex, MutexGuard as AsyncMutexGuard};
use wasm_bindgen::prelude::*;
use wasm_bindgen_futures::future_to_promise;
use wasm_utils::{console_log, console_warn};
#[derive(Clone)]
@@ -107,3 +111,37 @@ impl Drop for TestMarker {
self.value.store(false, Ordering::SeqCst)
}
}
pub(crate) trait GatewayReconnection {
fn disconnect_from_gateway(&self) -> Promise;
fn reconnect_to_gateway(&self) -> Promise;
}
impl GatewayReconnection for LockedGatewayClient {
fn disconnect_from_gateway(&self) -> Promise {
let this = self.clone();
future_to_promise(async move {
let mut guard = this.lock().await;
guard
.disconnect()
.await
.map_err(|err| JsValue::from(WasmClientError::from(err)))?;
Ok(JsValue::undefined())
})
}
fn reconnect_to_gateway(&self) -> Promise {
let this = self.clone();
future_to_promise(async move {
let mut guard = this.lock().await;
guard
.try_reconnect()
.await
.map_err(|err| JsValue::from(WasmClientError::from(err)))?;
Ok(JsValue::undefined())
})
}
}
+56 -32
View File
@@ -3,11 +3,11 @@
use crate::constants::NODE_TESTER_ID;
use crate::error::WasmClientError;
use crate::helpers::{current_network_topology_async, gateway_from_topology};
use crate::helpers::{current_network_topology_async, setup_from_topology};
use crate::storage::ClientStorage;
use crate::tester::ephemeral_receiver::EphemeralTestReceiver;
use crate::tester::helpers::{
NodeTestResult, ReceivedReceiverWrapper, TestMarker, WasmTestMessageExt,
GatewayReconnection, NodeTestResult, ReceivedReceiverWrapper, TestMarker, WasmTestMessageExt,
};
use crate::topology::WasmNymTopology;
use futures::channel::mpsc;
@@ -15,7 +15,7 @@ use js_sys::Promise;
use nym_bandwidth_controller::wasm_mockups::{Client as FakeClient, DirectSigningNyxdClient};
use nym_bandwidth_controller::BandwidthController;
use nym_client_core::client::key_manager::ManagedKeys;
use nym_client_core::config::GatewayEndpointConfig;
use nym_client_core::init::InitialisationDetails;
use nym_credential_storage::ephemeral_storage::EphemeralStorage;
use nym_gateway_client::GatewayClient;
use nym_node_tester_utils::receiver::SimpleMessageReceiver;
@@ -28,7 +28,6 @@ use nym_task::TaskManager;
use nym_topology::NymTopology;
use nym_validator_client::client::IdentityKey;
use rand::rngs::OsRng;
use rand::{CryptoRng, Rng};
use std::collections::HashSet;
use std::sync::atomic::{AtomicBool, AtomicU32, Ordering};
use std::sync::{Arc, Mutex as SyncMutex};
@@ -74,6 +73,7 @@ pub struct NymNodeTester {
#[wasm_bindgen]
pub struct NymNodeTesterBuilder {
gateway: Option<IdentityKey>,
id: Option<String>,
base_topology: NymTopology,
@@ -95,9 +95,11 @@ impl NymNodeTesterBuilder {
#[wasm_bindgen(constructor)]
pub fn new(
base_topology: WasmNymTopology,
id: Option<String>,
gateway: Option<IdentityKey>,
) -> NymNodeTesterBuilder {
NymNodeTesterBuilder {
id,
gateway,
base_topology: base_topology.into(),
bandwidth_controller: None,
@@ -106,43 +108,51 @@ impl NymNodeTesterBuilder {
async fn _new_with_api(
api_url: String,
id: Option<String>,
gateway: Option<IdentityKey>,
) -> Result<Self, WasmClientError> {
let topology = current_network_topology_async(api_url).await?;
Ok(NymNodeTesterBuilder::new(topology, gateway))
Ok(NymNodeTesterBuilder::new(topology, id, gateway))
}
pub fn new_with_api(gateway: Option<IdentityKey>, api_url: String) -> Promise {
pub fn new_with_api(
api_url: String,
id: Option<String>,
gateway: Option<IdentityKey>,
) -> Promise {
future_to_promise(async move {
Self::_new_with_api(api_url, gateway)
Self::_new_with_api(api_url, id, gateway)
.await
.into_promise_result()
})
}
async fn gateway_info<R: Rng + CryptoRng>(
async fn gateway_info(
&self,
rng: &mut R,
client_store: &ClientStorage,
) -> Result<GatewayEndpointConfig, WasmClientError> {
gateway_from_topology(
rng,
self.gateway.as_deref(),
&self.base_topology,
client_store,
)
.await
) -> Result<InitialisationDetails, WasmClientError> {
if let Ok(loaded) = InitialisationDetails::try_load(client_store, client_store).await {
Ok(loaded)
} else {
setup_from_topology(self.gateway.clone(), &self.base_topology, client_store).await
}
}
async fn _setup_client(mut self) -> Result<NymNodeTester, WasmClientError> {
let mut rng = OsRng;
let task_manager = TaskManager::default();
let client_store = ClientStorage::new_async(NODE_TESTER_ID, None).await?;
let storage_id = if let Some(client_id) = &self.id {
format!("{NODE_TESTER_ID}-{client_id}")
} else {
NODE_TESTER_ID.to_owned()
};
let gateway_endpoint = self.gateway_info(&mut rng, &client_store).await?;
let client_store = ClientStorage::new_async(&storage_id, None).await?;
let init_details = self.gateway_info(&client_store).await?;
let gateway_endpoint = init_details.gateway_details;
let gateway_identity = gateway_endpoint.try_get_gateway_identity_key()?;
let mut managed_keys = ManagedKeys::load_or_generate(&mut rng, &client_store).await;
let managed_keys = init_details.managed_keys;
let (mixnet_message_sender, mixnet_message_receiver) = mpsc::unbounded();
let (ack_sender, ack_receiver) = mpsc::unbounded();
@@ -151,7 +161,7 @@ impl NymNodeTesterBuilder {
gateway_endpoint.gateway_listener,
managed_keys.identity_keypair(),
gateway_identity,
managed_keys.gateway_shared_key(),
Some(managed_keys.must_get_gateway_shared_key()),
mixnet_message_sender,
ack_sender,
Duration::from_secs(10),
@@ -160,14 +170,11 @@ impl NymNodeTesterBuilder {
);
gateway_client.set_disabled_credentials_mode(true);
let shared_keys = gateway_client.authenticate_and_start().await?;
managed_keys
.deal_with_gateway_key(shared_keys, &client_store)
.await?;
gateway_client.authenticate_and_start().await?;
// TODO: make those values configurable later
let tester = NodeTester::new(
rng,
OsRng,
self.base_topology,
Some(address(&managed_keys, gateway_identity)),
PacketSize::default(),
@@ -241,29 +248,46 @@ async fn test_mixnode(
impl NymNodeTester {
#[wasm_bindgen(constructor)]
#[allow(clippy::new_ret_no_self)]
pub fn new(topology: WasmNymTopology, gateway: Option<IdentityKey>) -> Promise {
pub fn new(
topology: WasmNymTopology,
id: Option<String>,
gateway: Option<IdentityKey>,
) -> Promise {
console_log!("constructing node tester!");
NymNodeTesterBuilder::new(topology, gateway).setup_client()
NymNodeTesterBuilder::new(topology, id, gateway).setup_client()
}
async fn _new_with_api(
api_url: String,
id: Option<String>,
gateway: Option<IdentityKey>,
) -> Result<Self, WasmClientError> {
NymNodeTesterBuilder::_new_with_api(api_url, gateway)
NymNodeTesterBuilder::_new_with_api(api_url, id, gateway)
.await?
._setup_client()
.await
}
pub fn new_with_api(api_url: String, gateway: Option<IdentityKey>) -> Promise {
pub fn new_with_api(
api_url: String,
id: Option<String>,
gateway: Option<IdentityKey>,
) -> Promise {
future_to_promise(async move {
Self::_new_with_api(api_url, gateway)
Self::_new_with_api(api_url, id, gateway)
.await
.into_promise_result()
})
}
pub fn disconnect_from_gateway(&self) -> Promise {
self.gateway_client.disconnect_from_gateway()
}
pub fn reconnect_to_gateway(&self) -> Promise {
self.gateway_client.reconnect_to_gateway()
}
fn prepare_test_packets(
&self,
mixnode_identity: String,
+15 -3
View File
@@ -1,6 +1,6 @@
[package]
name = "nym-bin-common"
version = "0.5.0"
version = "0.6.0"
description = "Common code for nym binaries"
edition = { workspace = true }
authors = { workspace = true }
@@ -19,11 +19,17 @@ serde = { workspace = true, features = ["derive"] }
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 }
opentelemetry-jaeger = { version = "0.18.0", optional = true, features = [
"rt-tokio",
"collector_client",
"isahc_collector_client",
] }
tracing-opentelemetry = { version = "0.19.0", optional = true }
opentelemetry = { version = "0.19.0", optional = true, features = ["rt-tokio"] }
[build-dependencies]
@@ -37,4 +43,10 @@ vergen = { version = "=7.4.3", default-features = false, features = [
[features]
default = []
output_format = ["serde_json"]
tracing = ["tracing-appender", "tracing-subscriber", "tracing-tree"]
tracing = [
"tracing-subscriber",
"tracing-tree",
"opentelemetry-jaeger",
"tracing-opentelemetry",
"opentelemetry",
]
@@ -101,7 +101,7 @@ impl BinaryBuildInformation {
}
}
#[derive(Debug, Serialize, Deserialize)]
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct BinaryBuildInformationOwned {
// VERGEN_BUILD_TIMESTAMP
/// Provides the build timestamp, for example `2021-02-23T20:14:46.558472672+00:00`.
+25 -13
View File
@@ -4,7 +4,11 @@
use serde::{Deserialize, Serialize};
#[cfg(feature = "tracing")]
pub use tracing_appender;
pub use opentelemetry;
#[cfg(feature = "tracing")]
pub use opentelemetry_jaeger;
#[cfg(feature = "tracing")]
pub use tracing_opentelemetry;
#[cfg(feature = "tracing")]
pub use tracing_subscriber;
#[cfg(feature = "tracing")]
@@ -43,27 +47,35 @@ pub fn setup_logging() {
#[cfg(feature = "tracing")]
#[macro_export]
macro_rules! setup_tracing {
($file_name: expr) => {
($service_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()
let registry = 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),
);
let tracer = nym_bin_common::logging::opentelemetry_jaeger::new_collector_pipeline()
.with_endpoint("http://44.199.230.10:14268/api/traces")
.with_service_name($service_name)
.with_isahc()
.with_trace_config(
nym_bin_common::logging::opentelemetry::sdk::trace::config().with_sampler(
nym_bin_common::logging::opentelemetry::sdk::trace::Sampler::TraceIdRatioBased(
0.1,
),
),
)
.init();
.install_batch(nym_bin_common::logging::opentelemetry::runtime::Tokio)
.expect("Could not init tracer");
let telemetry = nym_bin_common::logging::tracing_opentelemetry::layer().with_tracer(tracer);
registry.with(telemetry).init();
};
}
+3 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "nym-client-core"
version = "1.1.14"
version = "1.1.15"
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"]
edition = "2021"
rust-version = "1.66"
@@ -9,6 +9,7 @@ rust-version = "1.66"
[dependencies]
async-trait = { workspace = true }
base64 = "0.21.2"
dirs = "4.0"
dashmap = "5.4.0"
futures = "0.3"
@@ -17,6 +18,7 @@ log = { workspace = true }
rand = { version = "0.7.3", features = ["wasm-bindgen"] }
serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true }
sha2 = "0.10.6"
tap = "1.0.1"
thiserror = "1.0.34"
url = { version ="2.2", features = ["serde"] }
@@ -42,7 +42,6 @@ use nym_sphinx::receiver::{ReconstructedMessage, SphinxMessageReceiver};
use nym_task::connections::{ConnectionCommandReceiver, ConnectionCommandSender, LaneQueueLengths};
use nym_task::{TaskClient, TaskManager};
use nym_topology::provider_trait::TopologyProvider;
use rand::rngs::OsRng;
use std::sync::Arc;
use tap::TapFallible;
use url::Url;
@@ -50,6 +49,8 @@ use url::Url;
#[cfg(target_arch = "wasm32")]
use nym_bandwidth_controller::wasm_mockups::DkgQueryClient;
use crate::client::base_client::storage::gateway_details::GatewayDetailsStore;
use crate::init::{setup_gateway, GatewaySetup, InitialisationDetails};
#[cfg(not(target_arch = "wasm32"))]
use nym_validator_client::nyxd::traits::DkgQueryClient;
@@ -157,17 +158,11 @@ impl From<bool> for CredentialsToggle {
}
pub struct BaseClientBuilder<'a, C, S: MixnetClientStorage> {
// due to wasm limitations I had to split it like this : (
gateway_config: &'a GatewayEndpointConfig,
debug_config: &'a DebugConfig,
disabled_credentials: bool,
nym_api_endpoints: Vec<Url>,
reply_storage_backend: S::ReplyStore,
key_store: S::KeyStore,
config: &'a Config,
client_store: S,
dkg_query_client: Option<C>,
custom_topology_provider: Option<Box<dyn TopologyProvider + Send + Sync>>,
bandwidth_controller: Option<BandwidthController<C, S::CredentialStore>>,
managed_keys: ManagedKeys,
setup_method: GatewaySetup,
}
impl<'a, C, S> BaseClientBuilder<'a, C, S>
@@ -175,47 +170,23 @@ where
S: MixnetClientStorage + 'static,
C: DkgQueryClient + Send + Sync + 'static,
{
// TODO: combine all storages
pub fn new_from_base_config(
pub fn new(
base_config: &'a Config,
key_store: S::KeyStore,
bandwidth_controller: Option<BandwidthController<C, S::CredentialStore>>,
reply_storage_backend: S::ReplyStore,
client_store: S,
dkg_query_client: Option<C>,
) -> BaseClientBuilder<'a, C, S> {
BaseClientBuilder {
gateway_config: base_config.get_gateway_endpoint_config(),
debug_config: &base_config.debug,
disabled_credentials: base_config.get_disabled_credentials_mode(),
nym_api_endpoints: base_config.get_nym_api_endpoints(),
bandwidth_controller,
reply_storage_backend,
key_store,
managed_keys: ManagedKeys::Invalidated,
config: base_config,
client_store,
dkg_query_client,
custom_topology_provider: None,
setup_method: GatewaySetup::MustLoad,
}
}
// TODO: combine all storages
pub fn new(
gateway_config: &'a GatewayEndpointConfig,
debug_config: &'a DebugConfig,
key_store: S::KeyStore,
bandwidth_controller: Option<BandwidthController<C, S::CredentialStore>>,
reply_storage_backend: S::ReplyStore,
credentials_toggle: CredentialsToggle,
nym_api_endpoints: Vec<Url>,
) -> BaseClientBuilder<'a, C, S> {
BaseClientBuilder {
gateway_config,
debug_config,
disabled_credentials: credentials_toggle.is_disabled(),
nym_api_endpoints,
reply_storage_backend,
custom_topology_provider: None,
bandwidth_controller,
key_store,
managed_keys: ManagedKeys::Invalidated,
}
pub fn with_gateway_setup(mut self, setup: GatewaySetup) -> Self {
self.setup_method = setup;
self
}
pub fn with_topology_provider(
@@ -228,13 +199,16 @@ where
// note: do **NOT** make this method public as its only valid usage is from within `start_base`
// because it relies on the crypto keys being already loaded
fn as_mix_recipient(&self) -> Recipient {
fn mix_address(
managed_keys: &ManagedKeys,
gateway_config: &GatewayEndpointConfig,
) -> Recipient {
Recipient::new(
*self.managed_keys.identity_public_key(),
*self.managed_keys.encryption_public_key(),
*managed_keys.identity_public_key(),
*managed_keys.encryption_public_key(),
// TODO: below only works under assumption that gateway address == gateway id
// (which currently is true)
NodeIdentity::from_base58_string(&self.gateway_config.gateway_id).unwrap(),
NodeIdentity::from_base58_string(&gateway_config.gateway_id).unwrap(),
)
}
@@ -318,7 +292,10 @@ where
}
async fn start_gateway_client(
&mut self,
config: &Config,
gateway_config: GatewayEndpointConfig,
managed_keys: &ManagedKeys,
bandwidth_controller: Option<BandwidthController<C, S::CredentialStore>>,
mixnet_message_sender: MixnetMessageSender,
ack_sender: AcknowledgementSender,
shutdown: TaskClient,
@@ -327,33 +304,26 @@ where
<S::KeyStore as KeyStore>::StorageError: Send + Sync + 'static,
<S::CredentialStore as CredentialStorage>::StorageError: Send + Sync + 'static,
{
let gateway_id = self.gateway_config.gateway_id.clone();
if gateway_id.is_empty() {
return Err(ClientCoreError::GatewayIdUnknown);
}
let gateway_address = self.gateway_config.gateway_listener.clone();
if gateway_address.is_empty() {
return Err(ClientCoreError::GatewayAddressUnknown);
}
let gateway_address = gateway_config.gateway_listener.clone();
let gateway_id = gateway_config.gateway_id;
// TODO: in theory, at this point, this should be infallible
let gateway_identity = identity::PublicKey::from_base58_string(gateway_id)
.map_err(ClientCoreError::UnableToCreatePublicKeyFromGatewayId)?;
let mut gateway_client = GatewayClient::new(
gateway_address,
self.managed_keys.identity_keypair(),
managed_keys.identity_keypair(),
gateway_identity,
self.managed_keys.gateway_shared_key(),
Some(managed_keys.must_get_gateway_shared_key()),
mixnet_message_sender,
ack_sender,
self.debug_config
.gateway_connection
.gateway_response_timeout,
self.bandwidth_controller.take(),
config.debug.gateway_connection.gateway_response_timeout,
bandwidth_controller,
shutdown,
);
gateway_client.set_disabled_credentials_mode(self.disabled_credentials);
gateway_client.set_disabled_credentials_mode(config.client.disabled_credentials_mode);
let shared_key = gateway_client
.authenticate_and_start()
@@ -362,12 +332,7 @@ where
log::error!("Could not authenticate and start up the gateway connection - {err}")
})?;
self.managed_keys
.deal_with_gateway_key(shared_key, &self.key_store)
.await
.map_err(|source| ClientCoreError::KeyStoreError {
source: Box::new(source),
})?;
managed_keys.ensure_gateway_key(shared_key);
Ok(gateway_client)
}
@@ -473,21 +438,41 @@ where
Ok(mem_store)
}
async fn initial_key_setup(&mut self) {
assert!(!self.managed_keys.is_valid());
let mut rng = OsRng;
self.managed_keys = ManagedKeys::load_or_generate(&mut rng, &self.key_store).await;
async fn initialise_keys_and_gateway(&self) -> Result<InitialisationDetails, ClientCoreError>
where
<S::KeyStore as KeyStore>::StorageError: Sync + Send,
<S::GatewayDetailsStore as GatewayDetailsStore>::StorageError: Sync + Send,
{
setup_gateway(
&self.setup_method,
self.client_store.key_store(),
self.client_store.gateway_details_store(),
false,
Some(&self.config.client.nym_api_urls),
)
.await
}
pub async fn start_base(mut self) -> Result<BaseClient, ClientCoreError>
where
<S::ReplyStore as ReplyStorageBackend>::StorageError: Sync + Send,
S::ReplyStore: Send + Sync,
<S::KeyStore as KeyStore>::StorageError: Send + Sync,
<S::ReplyStore as ReplyStorageBackend>::StorageError: Sync + Send,
<S::CredentialStore as CredentialStorage>::StorageError: Send + Sync + 'static,
<S::GatewayDetailsStore as GatewayDetailsStore>::StorageError: Sync + Send,
{
info!("Starting nym client");
self.initial_key_setup().await;
// derive (or load) client keys and gateway configuration
let details = self.initialise_keys_and_gateway().await?;
let gateway_config = details.gateway_details;
let managed_keys = details.managed_keys;
let (reply_storage_backend, credential_store) = self.client_store.into_runtime_stores();
let bandwidth_controller = self
.dkg_query_client
.map(|client| BandwidthController::new(credential_store, client));
// channels for inter-component communication
// TODO: make the channels be internally created by the relevant components
@@ -515,34 +500,39 @@ where
let (reply_controller_sender, reply_controller_receiver) =
reply_controller::requests::new_control_channels();
let self_address = self.as_mix_recipient();
let self_address = Self::mix_address(&managed_keys, &gateway_config);
// the components are started in very specific order. Unless you know what you are doing,
// do not change that.
let gateway_client = self
.start_gateway_client(mixnet_messages_sender, ack_sender, task_manager.subscribe())
.await?;
let reply_storage = Self::setup_persistent_reply_storage(
self.reply_storage_backend,
let gateway_client = Self::start_gateway_client(
self.config,
gateway_config,
&managed_keys,
bandwidth_controller,
mixnet_messages_sender,
ack_sender,
task_manager.subscribe(),
)
.await?;
let reply_storage =
Self::setup_persistent_reply_storage(reply_storage_backend, task_manager.subscribe())
.await?;
let topology_provider = Self::setup_topology_provider(
self.custom_topology_provider.take(),
self.nym_api_endpoints,
self.config.get_nym_api_endpoints(),
);
Self::start_topology_refresher(
topology_provider,
self.debug_config.topology,
self.config.debug.topology,
shared_topology_accessor.clone(),
task_manager.subscribe(),
)
.await?;
Self::start_received_messages_buffer_controller(
self.managed_keys.encryption_keypair(),
managed_keys.encryption_keypair(),
received_buffer_request_receiver,
mixnet_messages_receiver,
reply_storage.key_storage(),
@@ -566,8 +556,8 @@ where
let shared_lane_queue_lengths = LaneQueueLengths::new();
let controller_config = real_messages_control::Config::new(
self.debug_config,
self.managed_keys.ack_key(),
&self.config.debug,
managed_keys.ack_key(),
self_address,
);
@@ -583,17 +573,18 @@ where
shared_lane_queue_lengths.clone(),
client_connection_rx,
task_manager.subscribe(),
self.debug_config.traffic.packet_type,
self.config.debug.traffic.packet_type,
);
if !self
.debug_config
.config
.debug
.cover_traffic
.disable_loop_cover_traffic_stream
{
Self::start_cover_traffic_stream(
self.debug_config,
self.managed_keys.ack_key(),
&self.config.debug,
managed_keys.ack_key(),
self_address,
shared_topology_accessor.clone(),
message_sender,
@@ -122,13 +122,30 @@ pub fn create_bandwidth_controller_with_urls<St: CredentialStorage>(
nym_api_url: Url,
storage: St,
) -> BandwidthController<Client<QueryNyxdClient>, St> {
let client = default_query_dkg_client(nyxd_url, nym_api_url);
BandwidthController::new(storage, client)
}
pub fn default_query_dkg_client_from_config(config: &Config) -> Client<QueryNyxdClient> {
let nyxd_url = config
.get_validator_endpoints()
.pop()
.expect("No nyxd validator endpoint provided");
let api_url = config
.get_nym_api_endpoints()
.pop()
.expect("No validator api endpoint provided");
default_query_dkg_client(nyxd_url, api_url)
}
pub fn default_query_dkg_client(nyxd_url: Url, nym_api_url: Url) -> Client<QueryNyxdClient> {
let details = nym_network_defaults::NymNetworkDetails::new_from_env();
let mut client_config = nym_validator_client::Config::try_from_nym_network_details(&details)
.expect("failed to construct validator client config");
// overwrite env configuration with config URLs
client_config = client_config.with_urls(nyxd_url, nym_api_url);
let client = nym_validator_client::Client::new_query(client_config)
.expect("Could not construct query client");
BandwidthController::new(storage, client)
nym_validator_client::Client::new_query(client_config)
.expect("Could not construct query client")
}
@@ -0,0 +1,201 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::config::GatewayEndpointConfig;
use async_trait::async_trait;
use nym_gateway_requests::registration::handshake::SharedKeys;
use serde::{Deserialize, Serialize};
use sha2::{Digest, Sha256};
use std::error::Error;
use std::ops::Deref;
use tokio::sync::Mutex;
use zeroize::Zeroizing;
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
pub trait GatewayDetailsStore {
type StorageError: Error;
async fn load_gateway_details(&self) -> Result<PersistedGatewayDetails, Self::StorageError>;
async fn store_gateway_details(
&self,
details: &PersistedGatewayDetails,
) -> Result<(), Self::StorageError>;
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PersistedGatewayDetails {
// TODO: should we also verify correctness of the details themselves?
// i.e. we could include a checksum or tag (via the shared keys)
// counterargument: if we wanted to modify, say, the host information in the stored file on disk,
// in order to actually use it, we'd have to recompute the whole checksum which would be a huge pain.
/// The hash of the shared keys to ensure the correct ones are used with those gateway details.
#[serde(with = "base64")]
key_hash: Vec<u8>,
/// Actual gateway details being persisted.
pub(crate) details: GatewayEndpointConfig,
}
impl From<PersistedGatewayDetails> for GatewayEndpointConfig {
fn from(value: PersistedGatewayDetails) -> Self {
value.details
}
}
impl PersistedGatewayDetails {
pub fn new(details: GatewayEndpointConfig, shared_key: &SharedKeys) -> Self {
let key_bytes = Zeroizing::new(shared_key.to_bytes());
let mut key_hasher = Sha256::new();
key_hasher.update(&key_bytes);
let key_hash = key_hasher.finalize().to_vec();
PersistedGatewayDetails { key_hash, details }
}
pub fn verify(&self, shared_key: &SharedKeys) -> bool {
let key_bytes = Zeroizing::new(shared_key.to_bytes());
let mut key_hasher = Sha256::new();
key_hasher.update(&key_bytes);
let key_hash = key_hasher.finalize();
self.key_hash == key_hash.deref()
}
}
// helper to make Vec<u8> serialization use base64 representation to make it human readable
// so that it would be easier for users to copy contents from the disk if they wanted to use it elsewhere
mod base64 {
use base64::{engine::general_purpose::STANDARD, Engine as _};
use serde::{Deserialize, Deserializer, Serializer};
pub fn serialize<S: Serializer>(bytes: &[u8], serializer: S) -> Result<S::Ok, S::Error> {
serializer.serialize_str(&STANDARD.encode(bytes))
}
pub fn deserialize<'de, D: Deserializer<'de>>(deserializer: D) -> Result<Vec<u8>, D::Error> {
let s = <String>::deserialize(deserializer)?;
STANDARD.decode(s).map_err(serde::de::Error::custom)
}
}
#[cfg(not(target_arch = "wasm32"))]
#[derive(Debug, thiserror::Error)]
pub enum OnDiskGatewayDetailsError {
#[error("JSON failure: {0}")]
SerializationFailure(#[from] serde_json::Error),
#[error("failed to store gateway details to {path}: {err}")]
StoreFailure {
path: String,
#[source]
err: std::io::Error,
},
#[error("failed to load gateway details from {path}: {err}")]
LoadFailure {
path: String,
#[source]
err: std::io::Error,
},
}
#[cfg(not(target_arch = "wasm32"))]
pub struct OnDiskGatewayDetails {
file_location: std::path::PathBuf,
}
#[cfg(not(target_arch = "wasm32"))]
impl OnDiskGatewayDetails {
pub fn new<P: AsRef<std::path::Path>>(path: P) -> Self {
OnDiskGatewayDetails {
file_location: path.as_ref().to_owned(),
}
}
pub fn load_from_disk(&self) -> Result<PersistedGatewayDetails, OnDiskGatewayDetailsError> {
let file = std::fs::File::open(&self.file_location).map_err(|err| {
OnDiskGatewayDetailsError::LoadFailure {
path: self.file_location.display().to_string(),
err,
}
})?;
Ok(serde_json::from_reader(file)?)
}
pub fn store_to_disk(
&self,
details: &PersistedGatewayDetails,
) -> Result<(), OnDiskGatewayDetailsError> {
// ensure the whole directory structure exists
if let Some(parent_dir) = &self.file_location.parent() {
std::fs::create_dir_all(parent_dir).map_err(|err| {
OnDiskGatewayDetailsError::StoreFailure {
path: self.file_location.display().to_string(),
err,
}
})?
}
let file = std::fs::File::create(&self.file_location).map_err(|err| {
OnDiskGatewayDetailsError::StoreFailure {
path: self.file_location.display().to_string(),
err,
}
})?;
Ok(serde_json::to_writer_pretty(file, details)?)
}
}
#[cfg(not(target_arch = "wasm32"))]
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
impl GatewayDetailsStore for OnDiskGatewayDetails {
type StorageError = OnDiskGatewayDetailsError;
async fn load_gateway_details(&self) -> Result<PersistedGatewayDetails, Self::StorageError> {
self.load_from_disk()
}
async fn store_gateway_details(
&self,
gateway_details: &PersistedGatewayDetails,
) -> Result<(), Self::StorageError> {
self.store_to_disk(gateway_details)
}
}
#[derive(Default)]
pub struct InMemGatewayDetails {
details: Mutex<Option<PersistedGatewayDetails>>,
}
#[derive(Debug, thiserror::Error)]
#[error("old ephemeral gateway details can't be loaded from storage")]
pub struct EphemeralGatewayDetailsError;
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
impl GatewayDetailsStore for InMemGatewayDetails {
type StorageError = EphemeralGatewayDetailsError;
async fn load_gateway_details(&self) -> Result<PersistedGatewayDetails, Self::StorageError> {
self.details
.lock()
.await
.clone()
.ok_or(EphemeralGatewayDetailsError)
}
async fn store_gateway_details(
&self,
gateway_details: &PersistedGatewayDetails,
) -> Result<(), Self::StorageError> {
*self.details.lock().await = Some(gateway_details.clone());
Ok(())
}
}
@@ -4,17 +4,20 @@
// TODO: combine those more closely. Perhaps into a single underlying store.
// Like for persistent, on-disk, storage, what's the point of having 3 different databases?
use crate::client::base_client::storage::gateway_details::{
GatewayDetailsStore, InMemGatewayDetails,
};
use crate::client::key_manager::persistence::{InMemEphemeralKeys, KeyStore};
use crate::client::replies::reply_storage;
use crate::client::replies::reply_storage::ReplyStorageBackend;
use nym_credential_storage::ephemeral_storage::{
EphemeralStorage as EphemeralCredentialStorage, EphemeralStorage,
};
use nym_credential_storage::ephemeral_storage::EphemeralStorage as EphemeralCredentialStorage;
use nym_credential_storage::storage::Storage as CredentialStorage;
#[cfg(all(not(target_arch = "wasm32"), feature = "fs-surb-storage"))]
use crate::client::base_client::non_wasm_helpers;
#[cfg(all(not(target_arch = "wasm32"), feature = "fs-surb-storage"))]
use crate::client::base_client::storage::gateway_details::OnDiskGatewayDetails;
#[cfg(all(not(target_arch = "wasm32"), feature = "fs-surb-storage"))]
use crate::client::key_manager::persistence::OnDiskKeys;
#[cfg(all(not(target_arch = "wasm32"), feature = "fs-surb-storage"))]
use crate::client::replies::reply_storage::fs_backend;
@@ -25,24 +28,33 @@ use crate::error::ClientCoreError;
#[cfg(all(not(target_arch = "wasm32"), feature = "fs-surb-storage"))]
use nym_credential_storage::persistent_storage::PersistentStorage as PersistentCredentialStorage;
pub mod gateway_details;
// TODO: ideally this should be changed into
// `MixnetClientStorage: KeyStore + ReplyStorageBackend + CredentialStorage + GatewayDetailsStore`
pub trait MixnetClientStorage {
type KeyStore: KeyStore;
type ReplyStore: ReplyStorageBackend;
type CredentialStore: CredentialStorage;
type GatewayDetailsStore: GatewayDetailsStore;
// this is a TERRIBLE name...
fn into_split(self) -> (Self::KeyStore, Self::ReplyStore, Self::CredentialStore);
// fn into_split(self) -> (Self::KeyStore, Self::ReplyStore, Self::CredentialStore, Self::GatewayDetailsStore);
fn into_runtime_stores(self) -> (Self::ReplyStore, Self::CredentialStore);
fn key_store(&self) -> &Self::KeyStore;
fn reply_store(&self) -> &Self::ReplyStore;
fn credential_store(&self) -> &Self::CredentialStore;
fn gateway_details_store(&self) -> &Self::GatewayDetailsStore;
}
#[derive(Default)]
pub struct Ephemeral {
key_store: InMemEphemeralKeys,
reply_store: reply_storage::Empty,
credential_store: EphemeralStorage,
credential_store: EphemeralCredentialStorage,
gateway_details_store: InMemGatewayDetails,
}
impl Ephemeral {
@@ -55,9 +67,10 @@ impl MixnetClientStorage for Ephemeral {
type KeyStore = InMemEphemeralKeys;
type ReplyStore = reply_storage::Empty;
type CredentialStore = EphemeralCredentialStorage;
type GatewayDetailsStore = InMemGatewayDetails;
fn into_split(self) -> (Self::KeyStore, Self::ReplyStore, Self::CredentialStore) {
(self.key_store, self.reply_store, self.credential_store)
fn into_runtime_stores(self) -> (Self::ReplyStore, Self::CredentialStore) {
(self.reply_store, self.credential_store)
}
fn key_store(&self) -> &Self::KeyStore {
@@ -71,6 +84,10 @@ impl MixnetClientStorage for Ephemeral {
fn credential_store(&self) -> &Self::CredentialStore {
&self.credential_store
}
fn gateway_details_store(&self) -> &Self::GatewayDetailsStore {
&self.gateway_details_store
}
}
#[cfg(all(not(target_arch = "wasm32"), feature = "fs-surb-storage"))]
@@ -78,6 +95,7 @@ pub struct OnDiskPersistent {
pub(crate) key_store: OnDiskKeys,
pub(crate) reply_store: fs_backend::Backend,
pub(crate) credential_store: PersistentCredentialStorage,
pub(crate) gateway_details_store: OnDiskGatewayDetails,
}
#[cfg(all(not(target_arch = "wasm32"), feature = "fs-surb-storage"))]
@@ -86,11 +104,13 @@ impl OnDiskPersistent {
key_store: OnDiskKeys,
reply_store: fs_backend::Backend,
credential_store: PersistentCredentialStorage,
gateway_details_store: OnDiskGatewayDetails,
) -> Self {
Self {
key_store,
reply_store,
credential_store,
gateway_details_store,
}
}
@@ -109,10 +129,13 @@ impl OnDiskPersistent {
let credential_store =
nym_credential_storage::initialise_persistent_storage(paths.credentials_database).await;
let gateway_details_store = OnDiskGatewayDetails::new(paths.gateway_details);
Ok(OnDiskPersistent {
key_store,
reply_store,
credential_store,
gateway_details_store,
})
}
}
@@ -122,9 +145,10 @@ impl MixnetClientStorage for OnDiskPersistent {
type KeyStore = OnDiskKeys;
type ReplyStore = fs_backend::Backend;
type CredentialStore = PersistentCredentialStorage;
type GatewayDetailsStore = OnDiskGatewayDetails;
fn into_split(self) -> (Self::KeyStore, Self::ReplyStore, Self::CredentialStore) {
(self.key_store, self.reply_store, self.credential_store)
fn into_runtime_stores(self) -> (Self::ReplyStore, Self::CredentialStore) {
(self.reply_store, self.credential_store)
}
fn key_store(&self) -> &Self::KeyStore {
@@ -138,4 +162,8 @@ impl MixnetClientStorage for OnDiskPersistent {
fn credential_store(&self) -> &Self::CredentialStore {
&self.credential_store
}
fn gateway_details_store(&self) -> &Self::GatewayDetailsStore {
&self.gateway_details_store
}
}
@@ -10,7 +10,7 @@ use log::*;
use nym_sphinx::acknowledgements::AckKey;
use nym_sphinx::addressing::clients::Recipient;
use nym_sphinx::cover::generate_loop_cover_packet;
use nym_sphinx::params::PacketSize;
use nym_sphinx::params::{PacketSize, PacketType};
use nym_sphinx::utils::sample_poisson_duration;
use rand::{rngs::OsRng, CryptoRng, Rng};
use std::pin::Pin;
@@ -63,6 +63,8 @@ where
/// Optional secondary predefined packet size used for the loop cover messages.
secondary_packet_size: Option<PacketSize>,
packet_type: PacketType,
}
impl<R> Stream for LoopCoverTrafficStream<R>
@@ -135,6 +137,7 @@ impl LoopCoverTrafficStream<OsRng> {
topology_access,
primary_packet_size: traffic_config.primary_packet_size,
secondary_packet_size: traffic_config.secondary_packet_size,
packet_type: traffic_config.packet_type,
}
}
@@ -194,7 +197,7 @@ impl LoopCoverTrafficStream<OsRng> {
self.average_ack_delay,
self.cover_traffic.loop_cover_traffic_average_delay,
cover_traffic_packet_size,
nym_sphinx::params::PacketType::Mix,
self.packet_type,
)
.expect("Somehow failed to generate a loop cover message with a valid topology");
@@ -6,6 +6,7 @@ use nym_crypto::asymmetric::{encryption, identity};
use nym_gateway_requests::registration::handshake::SharedKeys;
use nym_sphinx::acknowledgements::AckKey;
use rand::{CryptoRng, RngCore};
use std::fmt::{Debug, Formatter};
use std::sync::Arc;
use zeroize::ZeroizeOnDrop;
@@ -20,6 +21,16 @@ pub enum ManagedKeys {
Invalidated,
}
impl Debug for ManagedKeys {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
ManagedKeys::Initial(_) => write!(f, "initial"),
ManagedKeys::FullyDerived(_) => write!(f, "fully derived"),
ManagedKeys::Invalidated => write!(f, "invalidated"),
}
}
}
impl From<KeyManagerBuilder> for ManagedKeys {
fn from(value: KeyManagerBuilder) -> Self {
ManagedKeys::Initial(value)
@@ -84,6 +95,11 @@ impl ManagedKeys {
}
}
pub fn must_get_gateway_shared_key(&self) -> Arc<SharedKeys> {
self.gateway_shared_key()
.expect("failed to extract gateway shared key")
}
pub fn gateway_shared_key(&self) -> Option<Arc<SharedKeys>> {
match self {
ManagedKeys::Initial(_) => None,
@@ -108,6 +124,17 @@ impl ManagedKeys {
}
}
pub fn ensure_gateway_key(&self, gateway_shared_key: Arc<SharedKeys>) {
if let ManagedKeys::FullyDerived(key_manager) = &self {
if !Arc::ptr_eq(&key_manager.gateway_shared_key, &gateway_shared_key)
|| key_manager.gateway_shared_key != gateway_shared_key
{
// this should NEVER happen thus panic here
panic!("derived fresh gateway shared key whilst already holding one!")
}
}
}
pub async fn deal_with_gateway_key<S: KeyStore>(
&mut self,
gateway_shared_key: Arc<SharedKeys>,
@@ -120,12 +147,7 @@ impl ManagedKeys {
key_manager
}
ManagedKeys::FullyDerived(key_manager) => {
if !Arc::ptr_eq(&key_manager.gateway_shared_key, &gateway_shared_key)
|| key_manager.gateway_shared_key != gateway_shared_key
{
// this should NEVER happen thus panic here
panic!("derived fresh gateway shared key whilst already holding one!")
}
self.ensure_gateway_key(gateway_shared_key);
key_manager
}
ManagedKeys::Invalidated => unreachable!("the managed keys got invalidated"),
@@ -4,6 +4,7 @@
use crate::client::key_manager::KeyManager;
use async_trait::async_trait;
use std::error::Error;
use tokio::sync::Mutex;
#[cfg(not(target_arch = "wasm32"))]
use crate::config::disk_persistence::keys_paths::ClientKeysPaths;
@@ -36,6 +37,7 @@ pub enum OnDiskKeysError {
KeyPairLoadFailure {
keys: String,
paths: nym_pemstore::KeyPairPath,
#[source]
err: std::io::Error,
},
@@ -43,6 +45,7 @@ pub enum OnDiskKeysError {
KeyPairStoreFailure {
keys: String,
paths: nym_pemstore::KeyPairPath,
#[source]
err: std::io::Error,
},
@@ -50,6 +53,7 @@ pub enum OnDiskKeysError {
KeyLoadFailure {
key: String,
path: String,
#[source]
err: std::io::Error,
},
@@ -57,6 +61,7 @@ pub enum OnDiskKeysError {
KeyStoreFailure {
key: String,
path: String,
#[source]
err: std::io::Error,
},
}
@@ -79,6 +84,26 @@ impl OnDiskKeys {
OnDiskKeys { paths }
}
#[doc(hidden)]
pub fn ephemeral_load_gateway_keys(
&self,
) -> Result<zeroize::Zeroizing<SharedKeys>, OnDiskKeysError> {
self.load_key(self.paths.gateway_shared_key(), "gateway shared keys")
.map(zeroize::Zeroizing::new)
}
#[doc(hidden)]
pub fn load_encryption_keypair(&self) -> Result<encryption::KeyPair, OnDiskKeysError> {
let encryption_paths = self.paths.encryption_key_pair_path();
self.load_keypair(encryption_paths, "encryption keys")
}
#[doc(hidden)]
pub fn load_identity_keypair(&self) -> Result<identity::KeyPair, OnDiskKeysError> {
let identity_paths = self.paths.identity_key_pair_path();
self.load_keypair(identity_paths, "identity keys")
}
fn load_key<T: PemStorableKey>(
&self,
path: &std::path::Path,
@@ -132,13 +157,8 @@ impl OnDiskKeys {
}
fn load_keys(&self) -> Result<KeyManager, OnDiskKeysError> {
let identity_paths = self.paths.identity_key_pair_path();
let encryption_paths = self.paths.encryption_key_pair_path();
let identity_keypair: identity::KeyPair =
self.load_keypair(identity_paths, "identity keys")?;
let encryption_keypair: encryption::KeyPair =
self.load_keypair(encryption_paths, "encryption keys")?;
let identity_keypair = self.load_identity_keypair()?;
let encryption_keypair = self.load_encryption_keypair()?;
let ack_key: AckKey = self.load_key(self.paths.ack_key(), "ack key")?;
let gateway_shared_key: SharedKeys =
@@ -193,10 +213,12 @@ impl KeyStore for OnDiskKeys {
}
#[derive(Default)]
pub struct InMemEphemeralKeys;
pub struct InMemEphemeralKeys {
keys: Mutex<Option<KeyManager>>,
}
#[derive(Debug, thiserror::Error)]
#[error("ephemeral keys can't be loaded from storage")]
#[error("old ephemeral keys can't be loaded from storage")]
pub struct EphemeralKeysError;
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
@@ -205,10 +227,11 @@ impl KeyStore for InMemEphemeralKeys {
type StorageError = EphemeralKeysError;
async fn load_keys(&self) -> Result<KeyManager, Self::StorageError> {
Err(EphemeralKeysError)
self.keys.lock().await.clone().ok_or(EphemeralKeysError)
}
async fn store_keys(&self, _keys: &KeyManager) -> Result<(), Self::StorageError> {
async fn store_keys(&self, keys: &KeyManager) -> Result<(), Self::StorageError> {
*self.keys.lock().await = Some(keys.clone());
Ok(())
}
}
@@ -1,4 +1,4 @@
// Copyright 2021-2022 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::client::inbound_messages::{InputMessage, InputMessageReceiver};
@@ -1,4 +1,4 @@
// Copyright 2021-2022 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use super::{
@@ -565,7 +565,7 @@ where
fragments: Vec<Fragment>,
reply_surbs: Vec<ReplySurb>,
) -> Result<Vec<PreparedFragment>, SurbWrappedPreparationError> {
debug_assert_ne!(
debug_assert_eq!(
fragments.len(),
reply_surbs.len(),
"attempted to send {} fragments with {} reply surbs",
@@ -6,16 +6,21 @@ use serde::{Deserialize, Serialize};
use std::path::{Path, PathBuf};
pub mod keys_paths;
pub mod old_v1_1_20_2;
pub const DEFAULT_GATEWAY_DETAILS_FILENAME: &str = "gateway_details.json";
pub const DEFAULT_REPLY_SURB_DB_FILENAME: &str = "persistent_reply_store.sqlite";
pub const DEFAULT_CREDENTIALS_DB_FILENAME: &str = "credentials_database.db";
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct CommonClientPaths {
pub keys: ClientKeysPaths,
// TODO:
// pub gateway_config_pathfinder: (),
/// Path to the file containing information about gateway used by this client,
/// i.e. details such as its public key, owner address or the network information.
pub gateway_details: PathBuf,
/// Path to the database containing bandwidth credentials of this client.
pub credentials_database: PathBuf,
@@ -30,6 +35,7 @@ impl CommonClientPaths {
CommonClientPaths {
credentials_database: base_dir.join(DEFAULT_CREDENTIALS_DB_FILENAME),
reply_surb_database: base_dir.join(DEFAULT_REPLY_SURB_DB_FILENAME),
gateway_details: base_dir.join(DEFAULT_GATEWAY_DETAILS_FILENAME),
keys: ClientKeysPaths::new_default(base_data_directory),
}
}
@@ -0,0 +1,30 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::config::disk_persistence::keys_paths::ClientKeysPaths;
use crate::config::disk_persistence::{CommonClientPaths, DEFAULT_GATEWAY_DETAILS_FILENAME};
use serde::{Deserialize, Serialize};
use std::path::PathBuf;
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct CommonClientPathsV1_1_20_2 {
pub keys: ClientKeysPaths,
pub credentials_database: PathBuf,
pub reply_surb_database: PathBuf,
}
impl CommonClientPathsV1_1_20_2 {
pub fn upgrade_default(self) -> CommonClientPaths {
let data_dir = self
.reply_surb_database
.parent()
.expect("client paths upgrade failure");
CommonClientPaths {
keys: self.keys,
gateway_details: data_dir.join(DEFAULT_GATEWAY_DETAILS_FILENAME),
credentials_database: self.credentials_database,
reply_surb_database: self.reply_surb_database,
}
}
}
+63 -49
View File
@@ -14,7 +14,8 @@ use wasm_bindgen::prelude::*;
pub mod disk_persistence;
pub mod old_config_v1_1_13;
pub mod old_config_v1_1_19;
pub mod old_config_v1_1_20;
pub mod old_config_v1_1_20_2;
// 'DEBUG'
const DEFAULT_ACK_WAIT_MULTIPLIER: f64 = 1.5;
@@ -65,15 +66,19 @@ pub struct Config {
}
impl Config {
pub fn new<S: Into<String>>(id: S) -> Self {
pub fn new<S: Into<String>>(id: S, version: S) -> Self {
Config {
client: Client::new_default(id),
client: Client::new_default(id, version),
debug: Default::default(),
}
}
pub fn from_client_config(client: Client, debug: DebugConfig) -> Self {
Config { client, debug }
}
pub fn validate(&self) -> bool {
self.client.validate() && self.debug.validate()
self.debug.validate()
}
pub fn with_debug_config(mut self, debug: DebugConfig) -> Self {
@@ -86,19 +91,6 @@ impl Config {
self
}
pub fn set_gateway_endpoint(&mut self, gateway_endpoint: GatewayEndpointConfig) {
self.client.gateway_endpoint = gateway_endpoint;
}
pub fn with_gateway_endpoint(mut self, gateway_endpoint: GatewayEndpointConfig) -> Self {
self.client.gateway_endpoint = gateway_endpoint;
self
}
pub fn with_gateway_id<S: Into<String>>(&mut self, id: S) {
self.client.gateway_endpoint.gateway_id = id.into();
}
pub fn with_custom_nyxd(mut self, urls: Vec<Url>) -> Self {
self.client.nyxd_urls = urls;
self
@@ -145,14 +137,46 @@ impl Config {
self
}
pub fn set_no_cover_traffic(&mut self) {
self.debug.cover_traffic.disable_loop_cover_traffic_stream = true;
self.debug.traffic.disable_main_poisson_packet_distribution = true;
}
pub fn with_disabled_cover_traffic_with_keepalive(mut self, disabled: bool) -> Self {
if disabled {
self.set_no_cover_traffic_with_keepalive()
}
self
}
pub fn set_no_cover_traffic_with_keepalive(&mut self) {
self.debug.traffic.disable_main_poisson_packet_distribution = true;
self.debug.cover_traffic.loop_cover_traffic_average_delay = Duration::from_secs(5);
}
pub fn with_disabled_topology_refresh(mut self, disable_topology_refresh: bool) -> Self {
self.debug.topology.disable_refreshing = disable_topology_refresh;
self
}
pub fn set_no_cover_traffic(&mut self) {
self.debug.cover_traffic.disable_loop_cover_traffic_stream = true;
self.debug.traffic.disable_main_poisson_packet_distribution = true;
pub fn with_no_per_hop_delays(mut self, no_per_hop_delays: bool) -> Self {
if no_per_hop_delays {
self.set_no_per_hop_delays()
}
self
}
pub fn set_no_per_hop_delays(&mut self) {
self.debug.traffic.average_packet_delay = Duration::ZERO;
self.debug.acknowledgements.average_ack_delay = Duration::ZERO;
}
pub fn with_secondary_packet_size(mut self, secondary_packet_size: Option<PacketSize>) -> Self {
self.set_secondary_packet_size(secondary_packet_size);
self
}
pub fn set_secondary_packet_size(&mut self, secondary_packet_size: Option<PacketSize>) {
self.debug.traffic.secondary_packet_size = secondary_packet_size;
}
pub fn set_custom_version(&mut self, version: &str) {
@@ -174,22 +198,6 @@ impl Config {
pub fn get_nym_api_endpoints(&self) -> Vec<Url> {
self.client.nym_api_urls.clone()
}
pub fn get_gateway_id(&self) -> String {
self.client.gateway_endpoint.gateway_id.clone()
}
pub fn get_gateway_owner(&self) -> String {
self.client.gateway_endpoint.gateway_owner.clone()
}
pub fn get_gateway_listener(&self) -> String {
self.client.gateway_endpoint.gateway_listener.clone()
}
pub fn get_gateway_endpoint_config(&self) -> &GatewayEndpointConfig {
&self.client.gateway_endpoint
}
}
#[derive(Clone, Debug, Default, Deserialize, PartialEq, Eq, Serialize)]
@@ -242,6 +250,8 @@ impl From<nym_topology::gateway::Node> for GatewayEndpointConfig {
}
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
// note: the deny_unknown_fields is VITAL here to allow upgrades from v1.1.20_2
#[serde(deny_unknown_fields)]
pub struct Client {
/// Version of the client for which this configuration was created.
pub version: String,
@@ -251,6 +261,7 @@ pub struct Client {
/// Indicates whether this client is running in a disabled credentials mode, thus attempting
/// to claim bandwidth without presenting bandwidth credentials.
// TODO: this should be moved to `debug.gateway_connection`
#[serde(default)]
pub disabled_credentials_mode: bool,
@@ -261,15 +272,10 @@ pub struct Client {
/// Addresses to APIs running on validator from which the client gets the view of the network.
#[serde(alias = "validator_api_urls")]
pub nym_api_urls: Vec<Url>,
/// Information regarding how the client should send data to gateway.
// #[deprecated(note = "this shall be moved to separate file because it doesn't belong here...")]
// TODO: this should be removed from config files and be moved to separate file instead
pub gateway_endpoint: GatewayEndpointConfig,
}
impl Client {
pub fn new_default<S: Into<String>>(id: S) -> Self {
pub fn new_default<S: Into<String>>(id: S, version: S) -> Self {
let network = NymNetworkDetails::new_mainnet();
let nyxd_urls = network
.endpoints
@@ -283,24 +289,32 @@ impl Client {
.collect::<Vec<_>>();
Client {
version: env!("CARGO_PKG_VERSION").to_string(),
version: version.into(),
id: id.into(),
disabled_credentials_mode: true,
nyxd_urls,
nym_api_urls,
gateway_endpoint: Default::default(),
}
}
pub fn validate(&self) -> bool {
!self.gateway_endpoint.gateway_id.is_empty()
&& !self.gateway_endpoint.gateway_owner.is_empty()
&& !self.gateway_endpoint.gateway_owner.is_empty()
pub fn new<S: Into<String>>(
id: S,
disabled_credentials_mode: bool,
nyxd_urls: Vec<Url>,
nym_api_urls: Vec<Url>,
) -> Self {
Client {
version: env!("CARGO_PKG_VERSION").to_string(),
id: id.into(),
disabled_credentials_mode,
nyxd_urls,
nym_api_urls,
}
}
}
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
#[serde(default)]
#[serde(default, deny_unknown_fields)]
pub struct Traffic {
/// The parameter of Poisson distribution determining how long, on average,
/// sent packet is going to be delayed at any given mix node.
@@ -1,9 +1,9 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::config::old_config_v1_1_19::{
AcknowledgementsV1_1_19, ClientV1_1_19, ConfigV1_1_19, CoverTrafficV1_1_19, DebugConfigV1_1_19,
GatewayConnectionV1_1_19, LoggingV1_1_19, ReplySurbsV1_1_19, TopologyV1_1_19, TrafficV1_1_19,
use crate::config::old_config_v1_1_20::{
AcknowledgementsV1_1_20, ClientV1_1_20, ConfigV1_1_20, CoverTrafficV1_1_20, DebugConfigV1_1_20,
GatewayConnectionV1_1_20, LoggingV1_1_20, ReplySurbsV1_1_20, TopologyV1_1_20, TrafficV1_1_20,
DEFAULT_ACK_WAIT_ADDITION, DEFAULT_ACK_WAIT_MULTIPLIER, DEFAULT_AVERAGE_PACKET_DELAY,
DEFAULT_GATEWAY_RESPONSE_TIMEOUT, DEFAULT_LOOP_COVER_STREAM_AVERAGE_DELAY,
DEFAULT_MAXIMUM_ALLOWED_SURB_REQUEST_SIZE, DEFAULT_MAXIMUM_REPLY_KEY_AGE,
@@ -39,7 +39,7 @@ impl From<ExtendedPacketSize> for PacketSize {
#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct OldConfigV1_1_13<T> {
pub client: ClientV1_1_19<T>,
pub client: ClientV1_1_20<T>,
#[serde(default)]
pub logging: OldLoggingV1_1_13,
@@ -51,9 +51,9 @@ pub struct OldConfigV1_1_13<T> {
#[serde(deny_unknown_fields)]
pub struct OldLoggingV1_1_13 {}
impl From<OldLoggingV1_1_13> for LoggingV1_1_19 {
impl From<OldLoggingV1_1_13> for LoggingV1_1_20 {
fn from(_value: OldLoggingV1_1_13) -> Self {
LoggingV1_1_19 {}
LoggingV1_1_20 {}
}
}
@@ -114,10 +114,10 @@ pub struct OldDebugConfigV1_1_13 {
pub maximum_reply_key_age: Duration,
}
impl From<OldDebugConfigV1_1_13> for DebugConfigV1_1_19 {
impl From<OldDebugConfigV1_1_13> for DebugConfigV1_1_20 {
fn from(value: OldDebugConfigV1_1_13) -> Self {
DebugConfigV1_1_19 {
traffic: TrafficV1_1_19 {
DebugConfigV1_1_20 {
traffic: TrafficV1_1_20 {
average_packet_delay: value.average_packet_delay,
message_sending_average_delay: value.message_sending_average_delay,
disable_main_poisson_packet_distribution: value
@@ -125,25 +125,25 @@ impl From<OldDebugConfigV1_1_13> for DebugConfigV1_1_19 {
primary_packet_size: PacketSize::RegularPacket,
secondary_packet_size: value.use_extended_packet_size.map(Into::into),
},
cover_traffic: CoverTrafficV1_1_19 {
cover_traffic: CoverTrafficV1_1_20 {
loop_cover_traffic_average_delay: value.loop_cover_traffic_average_delay,
disable_loop_cover_traffic_stream: value.disable_loop_cover_traffic_stream,
..CoverTrafficV1_1_19::default()
..CoverTrafficV1_1_20::default()
},
gateway_connection: GatewayConnectionV1_1_19 {
gateway_connection: GatewayConnectionV1_1_20 {
gateway_response_timeout: value.gateway_response_timeout,
},
acknowledgements: AcknowledgementsV1_1_19 {
acknowledgements: AcknowledgementsV1_1_20 {
average_ack_delay: value.average_ack_delay,
ack_wait_multiplier: value.ack_wait_multiplier,
ack_wait_addition: value.ack_wait_addition,
},
topology: TopologyV1_1_19 {
topology: TopologyV1_1_20 {
topology_refresh_rate: value.topology_refresh_rate,
topology_resolution_timeout: value.topology_resolution_timeout,
disable_refreshing: false,
},
reply_surbs: ReplySurbsV1_1_19 {
reply_surbs: ReplySurbsV1_1_20 {
minimum_reply_surb_storage_threshold: value.minimum_reply_surb_storage_threshold,
maximum_reply_surb_storage_threshold: value.maximum_reply_surb_storage_threshold,
minimum_reply_surb_request_size: value.minimum_reply_surb_request_size,
@@ -190,10 +190,10 @@ impl Default for OldDebugConfigV1_1_13 {
}
}
impl<T, U> From<OldConfigV1_1_13<T>> for ConfigV1_1_19<U> {
impl<T, U> From<OldConfigV1_1_13<T>> for ConfigV1_1_20<U> {
fn from(value: OldConfigV1_1_13<T>) -> Self {
ConfigV1_1_19 {
client: ClientV1_1_19 {
ConfigV1_1_20 {
client: ClientV1_1_20 {
version: value.client.version,
id: value.client.id,
disabled_credentials_mode: value.client.disabled_credentials_mode,
@@ -1,9 +1,10 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::config::{
Acknowledgements, CoverTraffic, DebugConfig, GatewayConnection, GatewayEndpointConfig,
ReplySurbs, Topology, Traffic,
use crate::config::old_config_v1_1_20_2::{
AcknowledgementsV1_1_20_2, CoverTrafficV1_1_20_2, DebugConfigV1_1_20_2,
GatewayConnectionV1_1_20_2, GatewayEndpointConfigV1_1_20_2, ReplySurbsV1_1_20_2,
TopologyV1_1_20_2, TrafficV1_1_20_2,
};
use nym_sphinx::params::{PacketSize, PacketType};
use serde::{Deserialize, Serialize};
@@ -55,25 +56,25 @@ pub(crate) const DEFAULT_MAXIMUM_REPLY_KEY_AGE: Duration = Duration::from_secs(2
#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct ConfigV1_1_19<T> {
pub client: ClientV1_1_19<T>,
pub struct ConfigV1_1_20<T> {
pub client: ClientV1_1_20<T>,
#[serde(default)]
pub logging: LoggingV1_1_19,
pub logging: LoggingV1_1_20,
#[serde(default)]
pub debug: DebugConfigV1_1_19,
pub debug: DebugConfigV1_1_20,
}
#[derive(Clone, Debug, Default, Deserialize, PartialEq, Eq, Serialize)]
pub struct GatewayEndpointConfigV1_1_19 {
pub struct GatewayEndpointConfigV1_1_20 {
pub gateway_id: String,
pub gateway_owner: String,
pub gateway_listener: String,
}
impl From<GatewayEndpointConfigV1_1_19> for GatewayEndpointConfig {
fn from(value: GatewayEndpointConfigV1_1_19) -> Self {
GatewayEndpointConfig {
impl From<GatewayEndpointConfigV1_1_20> for GatewayEndpointConfigV1_1_20_2 {
fn from(value: GatewayEndpointConfigV1_1_20) -> Self {
GatewayEndpointConfigV1_1_20_2 {
gateway_id: value.gateway_id,
gateway_owner: value.gateway_owner,
gateway_listener: value.gateway_listener,
@@ -82,7 +83,7 @@ impl From<GatewayEndpointConfigV1_1_19> for GatewayEndpointConfig {
}
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
pub struct ClientV1_1_19<T> {
pub struct ClientV1_1_20<T> {
pub version: String,
pub id: String,
#[serde(default)]
@@ -97,7 +98,7 @@ pub struct ClientV1_1_19<T> {
pub public_encryption_key_file: PathBuf,
pub gateway_shared_key_file: PathBuf,
pub ack_key_file: PathBuf,
pub gateway_endpoint: GatewayEndpointConfigV1_1_19,
pub gateway_endpoint: GatewayEndpointConfigV1_1_20,
pub database_path: PathBuf,
#[serde(default)]
pub reply_surb_database_path: PathBuf,
@@ -109,11 +110,11 @@ pub struct ClientV1_1_19<T> {
#[derive(Debug, Clone, Default, Deserialize, PartialEq, Eq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct LoggingV1_1_19 {}
pub struct LoggingV1_1_20 {}
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
#[serde(default)]
pub struct TrafficV1_1_19 {
pub struct TrafficV1_1_20 {
#[serde(with = "humantime_serde")]
pub average_packet_delay: Duration,
#[serde(with = "humantime_serde")]
@@ -123,9 +124,9 @@ pub struct TrafficV1_1_19 {
pub secondary_packet_size: Option<PacketSize>,
}
impl From<TrafficV1_1_19> for Traffic {
fn from(value: TrafficV1_1_19) -> Self {
Traffic {
impl From<TrafficV1_1_20> for TrafficV1_1_20_2 {
fn from(value: TrafficV1_1_20) -> Self {
TrafficV1_1_20_2 {
average_packet_delay: value.average_packet_delay,
message_sending_average_delay: value.message_sending_average_delay,
disable_main_poisson_packet_distribution: value
@@ -137,9 +138,9 @@ impl From<TrafficV1_1_19> for Traffic {
}
}
impl Default for TrafficV1_1_19 {
impl Default for TrafficV1_1_20 {
fn default() -> Self {
TrafficV1_1_19 {
TrafficV1_1_20 {
average_packet_delay: DEFAULT_AVERAGE_PACKET_DELAY,
message_sending_average_delay: DEFAULT_MESSAGE_STREAM_AVERAGE_DELAY,
disable_main_poisson_packet_distribution: false,
@@ -151,16 +152,16 @@ impl Default for TrafficV1_1_19 {
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct CoverTrafficV1_1_19 {
pub struct CoverTrafficV1_1_20 {
#[serde(with = "humantime_serde")]
pub loop_cover_traffic_average_delay: Duration,
pub cover_traffic_primary_size_ratio: f64,
pub disable_loop_cover_traffic_stream: bool,
}
impl From<CoverTrafficV1_1_19> for CoverTraffic {
fn from(value: CoverTrafficV1_1_19) -> Self {
CoverTraffic {
impl From<CoverTrafficV1_1_20> for CoverTrafficV1_1_20_2 {
fn from(value: CoverTrafficV1_1_20) -> Self {
CoverTrafficV1_1_20_2 {
loop_cover_traffic_average_delay: value.loop_cover_traffic_average_delay,
cover_traffic_primary_size_ratio: value.cover_traffic_primary_size_ratio,
disable_loop_cover_traffic_stream: value.disable_loop_cover_traffic_stream,
@@ -168,9 +169,9 @@ impl From<CoverTrafficV1_1_19> for CoverTraffic {
}
}
impl Default for CoverTrafficV1_1_19 {
impl Default for CoverTrafficV1_1_20 {
fn default() -> Self {
CoverTrafficV1_1_19 {
CoverTrafficV1_1_20 {
loop_cover_traffic_average_delay: DEFAULT_LOOP_COVER_STREAM_AVERAGE_DELAY,
cover_traffic_primary_size_ratio: DEFAULT_COVER_TRAFFIC_PRIMARY_SIZE_RATIO,
disable_loop_cover_traffic_stream: false,
@@ -180,22 +181,22 @@ impl Default for CoverTrafficV1_1_19 {
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct GatewayConnectionV1_1_19 {
pub struct GatewayConnectionV1_1_20 {
#[serde(with = "humantime_serde")]
pub gateway_response_timeout: Duration,
}
impl From<GatewayConnectionV1_1_19> for GatewayConnection {
fn from(value: GatewayConnectionV1_1_19) -> Self {
GatewayConnection {
impl From<GatewayConnectionV1_1_20> for GatewayConnectionV1_1_20_2 {
fn from(value: GatewayConnectionV1_1_20) -> Self {
GatewayConnectionV1_1_20_2 {
gateway_response_timeout: value.gateway_response_timeout,
}
}
}
impl Default for GatewayConnectionV1_1_19 {
impl Default for GatewayConnectionV1_1_20 {
fn default() -> Self {
GatewayConnectionV1_1_19 {
GatewayConnectionV1_1_20 {
gateway_response_timeout: DEFAULT_GATEWAY_RESPONSE_TIMEOUT,
}
}
@@ -203,7 +204,7 @@ impl Default for GatewayConnectionV1_1_19 {
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct AcknowledgementsV1_1_19 {
pub struct AcknowledgementsV1_1_20 {
#[serde(with = "humantime_serde")]
pub average_ack_delay: Duration,
pub ack_wait_multiplier: f64,
@@ -211,9 +212,9 @@ pub struct AcknowledgementsV1_1_19 {
pub ack_wait_addition: Duration,
}
impl From<AcknowledgementsV1_1_19> for Acknowledgements {
fn from(value: AcknowledgementsV1_1_19) -> Self {
Acknowledgements {
impl From<AcknowledgementsV1_1_20> for AcknowledgementsV1_1_20_2 {
fn from(value: AcknowledgementsV1_1_20) -> Self {
AcknowledgementsV1_1_20_2 {
average_ack_delay: value.average_ack_delay,
ack_wait_multiplier: value.ack_wait_multiplier,
ack_wait_addition: value.ack_wait_addition,
@@ -221,9 +222,9 @@ impl From<AcknowledgementsV1_1_19> for Acknowledgements {
}
}
impl Default for AcknowledgementsV1_1_19 {
impl Default for AcknowledgementsV1_1_20 {
fn default() -> Self {
AcknowledgementsV1_1_19 {
AcknowledgementsV1_1_20 {
average_ack_delay: DEFAULT_AVERAGE_PACKET_DELAY,
ack_wait_multiplier: DEFAULT_ACK_WAIT_MULTIPLIER,
ack_wait_addition: DEFAULT_ACK_WAIT_ADDITION,
@@ -233,7 +234,7 @@ impl Default for AcknowledgementsV1_1_19 {
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct TopologyV1_1_19 {
pub struct TopologyV1_1_20 {
#[serde(with = "humantime_serde")]
pub topology_refresh_rate: Duration,
#[serde(with = "humantime_serde")]
@@ -241,9 +242,9 @@ pub struct TopologyV1_1_19 {
pub disable_refreshing: bool,
}
impl From<TopologyV1_1_19> for Topology {
fn from(value: TopologyV1_1_19) -> Self {
Topology {
impl From<TopologyV1_1_20> for TopologyV1_1_20_2 {
fn from(value: TopologyV1_1_20) -> Self {
TopologyV1_1_20_2 {
topology_refresh_rate: value.topology_refresh_rate,
topology_resolution_timeout: value.topology_resolution_timeout,
disable_refreshing: value.disable_refreshing,
@@ -251,9 +252,9 @@ impl From<TopologyV1_1_19> for Topology {
}
}
impl Default for TopologyV1_1_19 {
impl Default for TopologyV1_1_20 {
fn default() -> Self {
TopologyV1_1_19 {
TopologyV1_1_20 {
topology_refresh_rate: DEFAULT_TOPOLOGY_REFRESH_RATE,
topology_resolution_timeout: DEFAULT_TOPOLOGY_RESOLUTION_TIMEOUT,
disable_refreshing: false,
@@ -263,7 +264,7 @@ impl Default for TopologyV1_1_19 {
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct ReplySurbsV1_1_19 {
pub struct ReplySurbsV1_1_20 {
pub minimum_reply_surb_storage_threshold: usize,
pub maximum_reply_surb_storage_threshold: usize,
pub minimum_reply_surb_request_size: u32,
@@ -279,9 +280,9 @@ pub struct ReplySurbsV1_1_19 {
pub maximum_reply_key_age: Duration,
}
impl From<ReplySurbsV1_1_19> for ReplySurbs {
fn from(value: ReplySurbsV1_1_19) -> Self {
ReplySurbs {
impl From<ReplySurbsV1_1_20> for ReplySurbsV1_1_20_2 {
fn from(value: ReplySurbsV1_1_20) -> Self {
ReplySurbsV1_1_20_2 {
minimum_reply_surb_storage_threshold: value.minimum_reply_surb_storage_threshold,
maximum_reply_surb_storage_threshold: value.maximum_reply_surb_storage_threshold,
minimum_reply_surb_request_size: value.minimum_reply_surb_request_size,
@@ -296,9 +297,9 @@ impl From<ReplySurbsV1_1_19> for ReplySurbs {
}
}
impl Default for ReplySurbsV1_1_19 {
impl Default for ReplySurbsV1_1_20 {
fn default() -> Self {
ReplySurbsV1_1_19 {
ReplySurbsV1_1_20 {
minimum_reply_surb_storage_threshold: DEFAULT_MINIMUM_REPLY_SURB_STORAGE_THRESHOLD,
maximum_reply_surb_storage_threshold: DEFAULT_MAXIMUM_REPLY_SURB_STORAGE_THRESHOLD,
minimum_reply_surb_request_size: DEFAULT_MINIMUM_REPLY_SURB_REQUEST_SIZE,
@@ -313,20 +314,20 @@ impl Default for ReplySurbsV1_1_19 {
}
}
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
#[derive(Debug, Default, Clone, Copy, Deserialize, PartialEq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct DebugConfigV1_1_19 {
pub traffic: TrafficV1_1_19,
pub cover_traffic: CoverTrafficV1_1_19,
pub gateway_connection: GatewayConnectionV1_1_19,
pub acknowledgements: AcknowledgementsV1_1_19,
pub topology: TopologyV1_1_19,
pub reply_surbs: ReplySurbsV1_1_19,
pub struct DebugConfigV1_1_20 {
pub traffic: TrafficV1_1_20,
pub cover_traffic: CoverTrafficV1_1_20,
pub gateway_connection: GatewayConnectionV1_1_20,
pub acknowledgements: AcknowledgementsV1_1_20,
pub topology: TopologyV1_1_20,
pub reply_surbs: ReplySurbsV1_1_20,
}
impl From<DebugConfigV1_1_19> for DebugConfig {
fn from(value: DebugConfigV1_1_19) -> Self {
DebugConfig {
impl From<DebugConfigV1_1_20> for DebugConfigV1_1_20_2 {
fn from(value: DebugConfigV1_1_20) -> Self {
DebugConfigV1_1_20_2 {
traffic: value.traffic.into(),
cover_traffic: value.cover_traffic.into(),
gateway_connection: value.gateway_connection.into(),
@@ -336,19 +337,3 @@ impl From<DebugConfigV1_1_19> for DebugConfig {
}
}
}
// it could be derived, sure, but I'd rather have an explicit implementation in case we had to change
// something manually at some point
#[allow(clippy::derivable_impls)]
impl Default for DebugConfigV1_1_19 {
fn default() -> Self {
DebugConfigV1_1_19 {
traffic: Default::default(),
cover_traffic: Default::default(),
gateway_connection: Default::default(),
acknowledgements: Default::default(),
topology: Default::default(),
reply_surbs: Default::default(),
}
}
}
@@ -0,0 +1,348 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::config::{
Acknowledgements, Client, Config, CoverTraffic, DebugConfig, GatewayConnection,
GatewayEndpointConfig, ReplySurbs, Topology, Traffic,
};
use nym_sphinx::params::{PacketSize, PacketType};
use serde::{Deserialize, Serialize};
use std::time::Duration;
use url::Url;
// 'DEBUG'
const DEFAULT_ACK_WAIT_MULTIPLIER: f64 = 1.5;
const DEFAULT_ACK_WAIT_ADDITION: Duration = Duration::from_millis(1_500);
const DEFAULT_LOOP_COVER_STREAM_AVERAGE_DELAY: Duration = Duration::from_millis(200);
const DEFAULT_MESSAGE_STREAM_AVERAGE_DELAY: Duration = Duration::from_millis(20);
const DEFAULT_AVERAGE_PACKET_DELAY: Duration = Duration::from_millis(50);
const DEFAULT_TOPOLOGY_REFRESH_RATE: Duration = Duration::from_secs(5 * 60); // every 5min
const DEFAULT_TOPOLOGY_RESOLUTION_TIMEOUT: Duration = Duration::from_millis(5_000);
// Set this to a high value for now, so that we don't risk sporadic timeouts that might cause
// bought bandwidth tokens to not have time to be spent; Once we remove the gateway from the
// bandwidth bridging protocol, we can come back to a smaller timeout value
const DEFAULT_GATEWAY_RESPONSE_TIMEOUT: Duration = Duration::from_secs(5 * 60);
const DEFAULT_COVER_TRAFFIC_PRIMARY_SIZE_RATIO: f64 = 0.70;
// reply-surbs related:
// define when to request
// clients/client-core/src/client/replies/reply_storage/surb_storage.rs
const DEFAULT_MINIMUM_REPLY_SURB_STORAGE_THRESHOLD: usize = 10;
const DEFAULT_MAXIMUM_REPLY_SURB_STORAGE_THRESHOLD: usize = 200;
// define how much to request at once
// clients/client-core/src/client/replies/reply_controller.rs
const DEFAULT_MINIMUM_REPLY_SURB_REQUEST_SIZE: u32 = 10;
const DEFAULT_MAXIMUM_REPLY_SURB_REQUEST_SIZE: u32 = 100;
const DEFAULT_MAXIMUM_ALLOWED_SURB_REQUEST_SIZE: u32 = 500;
const DEFAULT_MAXIMUM_REPLY_SURB_REREQUEST_WAITING_PERIOD: Duration = Duration::from_secs(10);
const DEFAULT_MAXIMUM_REPLY_SURB_DROP_WAITING_PERIOD: Duration = Duration::from_secs(5 * 60);
// 12 hours
const DEFAULT_MAXIMUM_REPLY_SURB_AGE: Duration = Duration::from_secs(12 * 60 * 60);
// 24 hours
const DEFAULT_MAXIMUM_REPLY_KEY_AGE: Duration = Duration::from_secs(24 * 60 * 60);
#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct ConfigV1_1_20_2 {
pub client: ClientV1_1_20_2,
#[serde(default)]
pub debug: DebugConfigV1_1_20_2,
}
impl From<ConfigV1_1_20_2> for Config {
fn from(value: ConfigV1_1_20_2) -> Self {
Config {
client: value.client.into(),
debug: value.debug.into(),
}
}
}
#[derive(Clone, Debug, Default, Deserialize, PartialEq, Eq, Serialize)]
pub struct GatewayEndpointConfigV1_1_20_2 {
/// gateway_id specifies ID of the gateway to which the client should send messages.
/// If initially omitted, a random gateway will be chosen from the available topology.
pub gateway_id: String,
/// Address of the gateway owner to which the client should send messages.
pub gateway_owner: String,
/// Address of the gateway listener to which all client requests should be sent.
pub gateway_listener: String,
}
impl From<GatewayEndpointConfigV1_1_20_2> for GatewayEndpointConfig {
fn from(value: GatewayEndpointConfigV1_1_20_2) -> Self {
GatewayEndpointConfig {
gateway_id: value.gateway_id,
gateway_owner: value.gateway_owner,
gateway_listener: value.gateway_listener,
}
}
}
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
pub struct ClientV1_1_20_2 {
pub version: String,
pub id: String,
#[serde(default)]
pub disabled_credentials_mode: bool,
#[serde(alias = "validator_urls")]
pub nyxd_urls: Vec<Url>,
#[serde(alias = "validator_api_urls")]
pub nym_api_urls: Vec<Url>,
pub gateway_endpoint: GatewayEndpointConfigV1_1_20_2,
}
impl From<ClientV1_1_20_2> for Client {
fn from(value: ClientV1_1_20_2) -> Self {
Client {
version: value.version,
id: value.id,
disabled_credentials_mode: value.disabled_credentials_mode,
nyxd_urls: value.nyxd_urls,
nym_api_urls: value.nym_api_urls,
}
}
}
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
#[serde(default)]
pub struct TrafficV1_1_20_2 {
#[serde(with = "humantime_serde")]
pub average_packet_delay: Duration,
#[serde(with = "humantime_serde")]
pub message_sending_average_delay: Duration,
pub disable_main_poisson_packet_distribution: bool,
pub primary_packet_size: PacketSize,
pub secondary_packet_size: Option<PacketSize>,
pub packet_type: PacketType,
}
impl From<TrafficV1_1_20_2> for Traffic {
fn from(value: TrafficV1_1_20_2) -> Self {
Traffic {
average_packet_delay: value.average_packet_delay,
message_sending_average_delay: value.message_sending_average_delay,
disable_main_poisson_packet_distribution: value
.disable_main_poisson_packet_distribution,
primary_packet_size: value.primary_packet_size,
secondary_packet_size: value.secondary_packet_size,
packet_type: PacketType::Mix,
}
}
}
impl Default for TrafficV1_1_20_2 {
fn default() -> Self {
TrafficV1_1_20_2 {
average_packet_delay: DEFAULT_AVERAGE_PACKET_DELAY,
message_sending_average_delay: DEFAULT_MESSAGE_STREAM_AVERAGE_DELAY,
disable_main_poisson_packet_distribution: false,
primary_packet_size: PacketSize::RegularPacket,
secondary_packet_size: None,
packet_type: PacketType::Mix,
}
}
}
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct CoverTrafficV1_1_20_2 {
#[serde(with = "humantime_serde")]
pub loop_cover_traffic_average_delay: Duration,
pub cover_traffic_primary_size_ratio: f64,
pub disable_loop_cover_traffic_stream: bool,
}
impl From<CoverTrafficV1_1_20_2> for CoverTraffic {
fn from(value: CoverTrafficV1_1_20_2) -> Self {
CoverTraffic {
loop_cover_traffic_average_delay: value.loop_cover_traffic_average_delay,
cover_traffic_primary_size_ratio: value.cover_traffic_primary_size_ratio,
disable_loop_cover_traffic_stream: value.disable_loop_cover_traffic_stream,
}
}
}
impl Default for CoverTrafficV1_1_20_2 {
fn default() -> Self {
CoverTrafficV1_1_20_2 {
loop_cover_traffic_average_delay: DEFAULT_LOOP_COVER_STREAM_AVERAGE_DELAY,
cover_traffic_primary_size_ratio: DEFAULT_COVER_TRAFFIC_PRIMARY_SIZE_RATIO,
disable_loop_cover_traffic_stream: false,
}
}
}
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct GatewayConnectionV1_1_20_2 {
#[serde(with = "humantime_serde")]
pub gateway_response_timeout: Duration,
}
impl From<GatewayConnectionV1_1_20_2> for GatewayConnection {
fn from(value: GatewayConnectionV1_1_20_2) -> Self {
GatewayConnection {
gateway_response_timeout: value.gateway_response_timeout,
}
}
}
impl Default for GatewayConnectionV1_1_20_2 {
fn default() -> Self {
GatewayConnectionV1_1_20_2 {
gateway_response_timeout: DEFAULT_GATEWAY_RESPONSE_TIMEOUT,
}
}
}
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct AcknowledgementsV1_1_20_2 {
#[serde(with = "humantime_serde")]
pub average_ack_delay: Duration,
pub ack_wait_multiplier: f64,
#[serde(with = "humantime_serde")]
pub ack_wait_addition: Duration,
}
impl From<AcknowledgementsV1_1_20_2> for Acknowledgements {
fn from(value: AcknowledgementsV1_1_20_2) -> Self {
Acknowledgements {
average_ack_delay: value.average_ack_delay,
ack_wait_multiplier: value.ack_wait_multiplier,
ack_wait_addition: value.ack_wait_addition,
}
}
}
impl Default for AcknowledgementsV1_1_20_2 {
fn default() -> Self {
AcknowledgementsV1_1_20_2 {
average_ack_delay: DEFAULT_AVERAGE_PACKET_DELAY,
ack_wait_multiplier: DEFAULT_ACK_WAIT_MULTIPLIER,
ack_wait_addition: DEFAULT_ACK_WAIT_ADDITION,
}
}
}
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct TopologyV1_1_20_2 {
#[serde(with = "humantime_serde")]
pub topology_refresh_rate: Duration,
#[serde(with = "humantime_serde")]
pub topology_resolution_timeout: Duration,
pub disable_refreshing: bool,
}
impl Default for TopologyV1_1_20_2 {
fn default() -> Self {
TopologyV1_1_20_2 {
topology_refresh_rate: DEFAULT_TOPOLOGY_REFRESH_RATE,
topology_resolution_timeout: DEFAULT_TOPOLOGY_RESOLUTION_TIMEOUT,
disable_refreshing: false,
}
}
}
impl From<TopologyV1_1_20_2> for Topology {
fn from(value: TopologyV1_1_20_2) -> Self {
Topology {
topology_refresh_rate: value.topology_refresh_rate,
topology_resolution_timeout: value.topology_resolution_timeout,
disable_refreshing: value.disable_refreshing,
}
}
}
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct ReplySurbsV1_1_20_2 {
pub minimum_reply_surb_storage_threshold: usize,
pub maximum_reply_surb_storage_threshold: usize,
pub minimum_reply_surb_request_size: u32,
pub maximum_reply_surb_request_size: u32,
pub maximum_allowed_reply_surb_request_size: u32,
#[serde(with = "humantime_serde")]
pub maximum_reply_surb_rerequest_waiting_period: Duration,
#[serde(with = "humantime_serde")]
pub maximum_reply_surb_drop_waiting_period: Duration,
#[serde(with = "humantime_serde")]
pub maximum_reply_surb_age: Duration,
#[serde(with = "humantime_serde")]
pub maximum_reply_key_age: Duration,
}
impl Default for ReplySurbsV1_1_20_2 {
fn default() -> Self {
ReplySurbsV1_1_20_2 {
minimum_reply_surb_storage_threshold: DEFAULT_MINIMUM_REPLY_SURB_STORAGE_THRESHOLD,
maximum_reply_surb_storage_threshold: DEFAULT_MAXIMUM_REPLY_SURB_STORAGE_THRESHOLD,
minimum_reply_surb_request_size: DEFAULT_MINIMUM_REPLY_SURB_REQUEST_SIZE,
maximum_reply_surb_request_size: DEFAULT_MAXIMUM_REPLY_SURB_REQUEST_SIZE,
maximum_allowed_reply_surb_request_size: DEFAULT_MAXIMUM_ALLOWED_SURB_REQUEST_SIZE,
maximum_reply_surb_rerequest_waiting_period:
DEFAULT_MAXIMUM_REPLY_SURB_REREQUEST_WAITING_PERIOD,
maximum_reply_surb_drop_waiting_period: DEFAULT_MAXIMUM_REPLY_SURB_DROP_WAITING_PERIOD,
maximum_reply_surb_age: DEFAULT_MAXIMUM_REPLY_SURB_AGE,
maximum_reply_key_age: DEFAULT_MAXIMUM_REPLY_KEY_AGE,
}
}
}
impl From<ReplySurbsV1_1_20_2> for ReplySurbs {
fn from(value: ReplySurbsV1_1_20_2) -> Self {
ReplySurbs {
minimum_reply_surb_storage_threshold: value.minimum_reply_surb_storage_threshold,
maximum_reply_surb_storage_threshold: value.maximum_reply_surb_storage_threshold,
minimum_reply_surb_request_size: value.minimum_reply_surb_request_size,
maximum_reply_surb_request_size: value.maximum_reply_surb_request_size,
maximum_allowed_reply_surb_request_size: value.maximum_allowed_reply_surb_request_size,
maximum_reply_surb_rerequest_waiting_period: value
.maximum_reply_surb_rerequest_waiting_period,
maximum_reply_surb_drop_waiting_period: value.maximum_reply_surb_drop_waiting_period,
maximum_reply_surb_age: value.maximum_reply_surb_age,
maximum_reply_key_age: value.maximum_reply_key_age,
}
}
}
#[derive(Debug, Default, Clone, Copy, Deserialize, PartialEq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct DebugConfigV1_1_20_2 {
pub traffic: TrafficV1_1_20_2,
pub cover_traffic: CoverTrafficV1_1_20_2,
pub gateway_connection: GatewayConnectionV1_1_20_2,
pub acknowledgements: AcknowledgementsV1_1_20_2,
pub topology: TopologyV1_1_20_2,
pub reply_surbs: ReplySurbsV1_1_20_2,
}
impl From<DebugConfigV1_1_20_2> for DebugConfig {
fn from(value: DebugConfigV1_1_20_2) -> Self {
DebugConfig {
traffic: value.traffic.into(),
cover_traffic: value.cover_traffic.into(),
gateway_connection: value.gateway_connection.into(),
acknowledgements: value.acknowledgements.into(),
topology: value.topology.into(),
reply_surbs: value.reply_surbs.into(),
}
}
}
+19
View File
@@ -50,6 +50,11 @@ pub enum ClientCoreError {
source: Box<dyn Error + Send + Sync>,
},
#[error("experienced a failure with our gateway details storage: {source}")]
GatewayDetailsStoreError {
source: Box<dyn Error + Send + Sync>,
},
#[error("The gateway id is invalid - {0}")]
UnableToCreatePublicKeyFromGatewayId(Ed25519RecoveryError),
@@ -97,6 +102,20 @@ pub enum ClientCoreError {
"This operation would have resulted in clients keys being overwritten without permission"
)]
ForbiddenKeyOverwrite,
#[error("gateway details are unavailable")]
UnavailableGatewayDetails {
source: Box<dyn Error + Send + Sync>,
},
#[error("gateway shared key is unavailable whilst we have full node information")]
UnavailableSharedKey,
#[error("attempted to obtain fresh gateway details whilst already knowing about one")]
UnexpectedGatewayDetails,
#[error("the provided gateway details (for gateway {gateway_id}) do not correspond to the shared keys")]
MismatchedGatewayDetails { gateway_id: String },
}
/// Set of messages that the client can send to listeners via the task manager
+9 -9
View File
@@ -44,18 +44,18 @@ const MEASUREMENTS: usize = 3;
const CONN_TIMEOUT: Duration = Duration::from_millis(1500);
const PING_TIMEOUT: Duration = Duration::from_millis(1000);
struct GatewayWithLatency {
gateway: gateway::Node,
struct GatewayWithLatency<'a> {
gateway: &'a gateway::Node,
latency: Duration,
}
impl GatewayWithLatency {
fn new(gateway: gateway::Node, latency: Duration) -> Self {
impl<'a> GatewayWithLatency<'a> {
fn new(gateway: &'a gateway::Node, latency: Duration) -> Self {
GatewayWithLatency { gateway, latency }
}
}
pub(super) async fn current_gateways<R: Rng>(
pub async fn current_gateways<R: Rng>(
rng: &mut R,
nym_apis: &[Url],
) -> Result<Vec<gateway::Node>, ClientCoreError> {
@@ -64,7 +64,7 @@ pub(super) async fn current_gateways<R: Rng>(
.ok_or(ClientCoreError::ListOfNymApisIsEmpty)?;
let client = nym_validator_client::client::NymApiClient::new(nym_api.clone());
log::trace!("Fetching list of gateways from: {}", nym_api);
log::trace!("Fetching list of gateways from: {nym_api}");
let gateways = client.get_cached_gateways().await?;
let valid_gateways = gateways
@@ -91,7 +91,7 @@ async fn connect(endpoint: &str) -> Result<WsConn, ClientCoreError> {
JSWebsocket::new(endpoint).map_err(|_| ClientCoreError::GatewayJsConnectionFailure)
}
async fn measure_latency(gateway: gateway::Node) -> Result<GatewayWithLatency, ClientCoreError> {
async fn measure_latency(gateway: &gateway::Node) -> Result<GatewayWithLatency, ClientCoreError> {
let addr = gateway.clients_address();
trace!(
"establishing connection to {} ({addr})...",
@@ -156,7 +156,7 @@ async fn measure_latency(gateway: gateway::Node) -> Result<GatewayWithLatency, C
pub(super) async fn choose_gateway_by_latency<R: Rng>(
rng: &mut R,
gateways: Vec<gateway::Node>,
gateways: &[gateway::Node],
) -> Result<gateway::Node, ClientCoreError> {
info!("choosing gateway by latency...");
@@ -189,7 +189,7 @@ pub(super) async fn choose_gateway_by_latency<R: Rng>(
pub(super) fn uniformly_random_gateway<R: Rng>(
rng: &mut R,
gateways: Vec<gateway::Node>,
gateways: &[gateway::Node],
) -> Result<gateway::Node, ClientCoreError> {
gateways
.choose(rng)
+273 -145
View File
@@ -3,26 +3,82 @@
//! Collection of initialization steps used by client implementations
use crate::client::base_client::storage::MixnetClientStorage;
use crate::client::base_client::storage::gateway_details::{
GatewayDetailsStore, PersistedGatewayDetails,
};
use crate::client::key_manager::persistence::KeyStore;
use crate::client::key_manager::{KeyManager, ManagedKeys};
use crate::client::key_manager::ManagedKeys;
use crate::init::helpers::{choose_gateway_by_latency, current_gateways, uniformly_random_gateway};
use crate::{
config::{disk_persistence::keys_paths::ClientKeysPaths, Config, GatewayEndpointConfig},
config::{Config, GatewayEndpointConfig},
error::ClientCoreError,
};
use nym_crypto::asymmetric::{encryption, identity};
use nym_crypto::asymmetric::identity;
use nym_sphinx::addressing::{clients::Recipient, nodes::NodeIdentity};
use nym_topology::gateway;
use nym_validator_client::client::IdentityKey;
use rand::rngs::OsRng;
use serde::Serialize;
use std::fmt::{Debug, Display};
use url::Url;
mod helpers;
pub mod helpers;
#[derive(Clone)]
// TODO: rename to something better...
#[derive(Debug)]
pub struct InitialisationDetails {
pub gateway_details: GatewayEndpointConfig,
pub managed_keys: ManagedKeys,
}
impl InitialisationDetails {
pub fn new(gateway_details: GatewayEndpointConfig, managed_keys: ManagedKeys) -> Self {
InitialisationDetails {
gateway_details,
managed_keys,
}
}
pub async fn try_load<K, D>(key_store: &K, details_store: &D) -> Result<Self, ClientCoreError>
where
K: KeyStore,
D: GatewayDetailsStore,
K::StorageError: Send + Sync + 'static,
D::StorageError: Send + Sync + 'static,
{
let loaded_details = _load_gateway_details(details_store).await?;
let loaded_keys = _load_managed_keys(key_store).await?;
if !loaded_details.verify(&loaded_keys.must_get_gateway_shared_key()) {
return Err(ClientCoreError::MismatchedGatewayDetails {
gateway_id: loaded_details.details.gateway_id,
});
}
Ok(InitialisationDetails {
gateway_details: loaded_details.into(),
managed_keys: loaded_keys,
})
}
pub fn client_address(&self) -> Result<Recipient, ClientCoreError> {
let client_recipient = Recipient::new(
*self.managed_keys.identity_public_key(),
*self.managed_keys.encryption_public_key(),
// TODO: below only works under assumption that gateway address == gateway id
// (which currently is true)
NodeIdentity::from_base58_string(&self.gateway_details.gateway_id)?,
);
Ok(client_recipient)
}
}
#[derive(Debug, Clone)]
pub enum GatewaySetup {
/// The gateway specification MUST BE loaded from the underlying storage.
MustLoad,
/// Specifies usage of a new, random, gateway.
New {
/// Should the new gateway be selected based on latency.
@@ -34,13 +90,13 @@ pub enum GatewaySetup {
},
Predefined {
/// Full gateway configuration
config: GatewayEndpointConfig,
details: PersistedGatewayDetails,
},
}
impl From<GatewayEndpointConfig> for GatewaySetup {
fn from(config: GatewayEndpointConfig) -> Self {
GatewaySetup::Predefined { config }
impl From<PersistedGatewayDetails> for GatewaySetup {
fn from(details: PersistedGatewayDetails) -> Self {
GatewaySetup::Predefined { details }
}
}
@@ -57,14 +113,11 @@ impl Default for GatewaySetup {
}
impl GatewaySetup {
pub fn new(
full_config: Option<GatewayEndpointConfig>,
gateway_identity: Option<IdentityKey>,
pub fn new_fresh(
gateway_identity: Option<String>,
latency_based_selection: Option<bool>,
) -> Self {
if let Some(config) = full_config {
GatewaySetup::Predefined { config }
} else if let Some(gateway_identity) = gateway_identity {
if let Some(gateway_identity) = gateway_identity {
GatewaySetup::Specified { gateway_identity }
} else {
GatewaySetup::New {
@@ -73,15 +126,22 @@ impl GatewaySetup {
}
}
pub async fn try_get_gateway_details(
self,
validator_servers: &[Url],
pub fn is_must_load(&self) -> bool {
matches!(self, GatewaySetup::MustLoad)
}
pub fn has_full_details(&self) -> bool {
matches!(self, GatewaySetup::Predefined { .. }) || self.is_must_load()
}
pub async fn choose_gateway(
&self,
gateways: &[gateway::Node],
) -> Result<GatewayEndpointConfig, ClientCoreError> {
match self {
GatewaySetup::New { by_latency } => {
let mut rng = OsRng;
let gateways = current_gateways(&mut rng, validator_servers).await?;
if by_latency {
if *by_latency {
choose_gateway_by_latency(&mut rng, gateways).await
} else {
uniformly_random_gateway(&mut rng, gateways)
@@ -89,20 +149,28 @@ impl GatewaySetup {
}
.map(Into::into),
GatewaySetup::Specified { gateway_identity } => {
let user_gateway = identity::PublicKey::from_base58_string(&gateway_identity)
let user_gateway = identity::PublicKey::from_base58_string(gateway_identity)
.map_err(ClientCoreError::UnableToCreatePublicKeyFromGatewayId)?;
let mut rng = OsRng;
let gateways = current_gateways(&mut rng, validator_servers).await?;
gateways
.into_iter()
.iter()
.find(|gateway| gateway.identity_key == user_gateway)
.ok_or_else(|| ClientCoreError::NoGatewayWithId(gateway_identity.to_string()))
.cloned()
}
.map(Into::into),
GatewaySetup::Predefined { config } => Ok(config),
_ => Err(ClientCoreError::UnexpectedGatewayDetails),
}
}
pub async fn try_get_new_gateway_details(
&self,
validator_servers: &[Url],
) -> Result<GatewayEndpointConfig, ClientCoreError> {
let mut rng = OsRng;
let gateways = current_gateways(&mut rng, validator_servers).await?;
self.choose_gateway(&gateways).await
}
}
/// Struct describing the results of the client initialization procedure.
@@ -117,14 +185,14 @@ pub struct InitResults {
}
impl InitResults {
pub fn new(config: &Config, address: &Recipient) -> Self {
pub fn new(config: &Config, address: &Recipient, gateway: &GatewayEndpointConfig) -> Self {
Self {
version: config.client.version.clone(),
id: config.client.id.clone(),
identity_key: address.identity().to_base58_string(),
encryption_key: address.encryption_key().to_base58_string(),
gateway_id: config.get_gateway_id(),
gateway_listener: config.get_gateway_listener(),
gateway_id: gateway.gateway_id.clone(),
gateway_listener: gateway.gateway_listener.clone(),
}
}
}
@@ -140,38 +208,164 @@ impl Display for InitResults {
}
}
/// Recovers the already present gateway information or attempts to register with new gateway
/// and stores the newly obtained key
pub async fn get_registered_gateway<S>(
validator_servers: Vec<Url>,
key_store: &S::KeyStore,
setup: GatewaySetup,
overwrite_keys: bool,
) -> Result<GatewayEndpointConfig, ClientCoreError>
// helpers for error wrapping
async fn _store_gateway_details<D>(
details_store: &D,
details: &PersistedGatewayDetails,
) -> Result<(), ClientCoreError>
where
S: MixnetClientStorage,
<S::KeyStore as KeyStore>::StorageError: Send + Sync + 'static,
D: GatewayDetailsStore,
D::StorageError: Send + Sync + 'static,
{
details_store
.store_gateway_details(details)
.await
.map_err(|source| ClientCoreError::GatewayDetailsStoreError {
source: Box::new(source),
})
}
async fn _load_gateway_details<D>(
details_store: &D,
) -> Result<PersistedGatewayDetails, ClientCoreError>
where
D: GatewayDetailsStore,
D::StorageError: Send + Sync + 'static,
{
details_store
.load_gateway_details()
.await
.map_err(|source| ClientCoreError::UnavailableGatewayDetails {
source: Box::new(source),
})
}
async fn _load_managed_keys<K>(key_store: &K) -> Result<ManagedKeys, ClientCoreError>
where
K: KeyStore,
K::StorageError: Send + Sync + 'static,
{
ManagedKeys::try_load(key_store)
.await
.map_err(|source| ClientCoreError::KeyStoreError {
source: Box::new(source),
})
}
fn ensure_valid_details(
details: &PersistedGatewayDetails,
loaded_keys: &ManagedKeys,
) -> Result<(), ClientCoreError> {
if !details.verify(&loaded_keys.must_get_gateway_shared_key()) {
Err(ClientCoreError::MismatchedGatewayDetails {
gateway_id: details.details.gateway_id.clone(),
})
} else {
Ok(())
}
}
pub async fn setup_gateway_from<K, D>(
setup: &GatewaySetup,
key_store: &K,
details_store: &D,
overwrite_data: bool,
gateways: Option<&[gateway::Node]>,
) -> Result<InitialisationDetails, ClientCoreError>
where
K: KeyStore,
D: GatewayDetailsStore,
K::StorageError: Send + Sync + 'static,
D::StorageError: Send + Sync + 'static,
{
let mut rng = OsRng;
// try load keys
// try load gateway details
let loaded_details = _load_gateway_details(details_store).await;
// try load keys and decide what to do based on the GatewaySetup
let mut managed_keys = match ManagedKeys::try_load(key_store).await {
Ok(_) => {
// if we loaded something and we don't have full gateway details, check if we can overwrite the data
if let GatewaySetup::Predefined { config } = setup {
// we already have defined gateway details AND a shared key, so nothing more for us to do
return Ok(config);
} else if overwrite_keys {
ManagedKeys::generate_new(&mut rng)
} else {
return Err(ClientCoreError::ForbiddenKeyOverwrite);
Ok(loaded_keys) => {
match setup {
GatewaySetup::MustLoad => {
// get EVERYTHING from the storage
let details = loaded_details?;
ensure_valid_details(&details, &loaded_keys)?;
// no need to persist anything as we got everything from the storage
return Ok(InitialisationDetails::new(details.into(), loaded_keys));
}
GatewaySetup::Predefined { details } => {
// we already have defined gateway details AND a shared key
ensure_valid_details(details, &loaded_keys)?;
// if nothing was stored or we're allowed to overwrite what's there, just persist the passed data
if overwrite_data || loaded_details.is_err() {
_store_gateway_details(details_store, details).await?;
}
return Ok(InitialisationDetails::new(
details.clone().into(),
loaded_keys,
));
}
GatewaySetup::Specified { gateway_identity } => {
// if that data was already stored...
if let Ok(existing_gateway) = loaded_details {
ensure_valid_details(&existing_gateway, &loaded_keys)?;
if &existing_gateway.details.gateway_id != gateway_identity
&& !overwrite_data
{
// if our loaded details don't match requested value and we CANT overwrite it...
return Err(ClientCoreError::UnexpectedGatewayDetails);
} else if &existing_gateway.details.gateway_id == gateway_identity {
// if they do match up, just return it
return Ok(InitialisationDetails::new(
existing_gateway.into(),
loaded_keys,
));
}
}
// we didn't get full details from the store and we have loaded some keys
// so we can only continue if we're allowed to overwrite keys
if overwrite_data {
ManagedKeys::generate_new(&mut rng)
} else {
return Err(ClientCoreError::ForbiddenKeyOverwrite);
}
}
GatewaySetup::New { .. } => {
if let Ok(existing_gateway) = loaded_details {
ensure_valid_details(&existing_gateway, &loaded_keys)?;
return Ok(InitialisationDetails::new(
existing_gateway.into(),
loaded_keys,
));
}
// we didn't get full details from the store and we have loaded some keys
// so we can only continue if we're allowed to overwrite keys
if overwrite_data {
ManagedKeys::generate_new(&mut rng)
} else {
return Err(ClientCoreError::ForbiddenKeyOverwrite);
}
}
}
}
Err(_) => ManagedKeys::generate_new(&mut rng),
Err(_) => {
// if we failed to load the keys, ensure we didn't provide gateway details in some form
// (in that case we CAN'T generate new keys
if setup.has_full_details() {
return Err(ClientCoreError::UnavailableSharedKey);
}
ManagedKeys::generate_new(&mut rng)
}
};
// choose gateway
let gateway_details = setup.try_get_gateway_details(&validator_servers).await?;
let gateway_details = setup.choose_gateway(gateways.unwrap_or_default()).await?;
// get our identity key
let our_identity = managed_keys.identity_keypair();
@@ -179,6 +373,9 @@ where
// Establish connection, authenticate and generate keys for talking with the gateway
let shared_keys = helpers::register_with_gateway(&gateway_details, our_identity).await?;
let persisted_details = PersistedGatewayDetails::new(gateway_details, &shared_keys);
// persist gateway keys
managed_keys
.deal_with_gateway_key(shared_keys, key_store)
.await
@@ -186,108 +383,39 @@ where
source: Box::new(source),
})?;
// TODO: here we should be probably persisting gateway details as opposed to returning them
// persist gateway config
_store_gateway_details(details_store, &persisted_details).await?;
Ok(gateway_details)
Ok(InitialisationDetails::new(
persisted_details.into(),
managed_keys,
))
}
/// Convenience function for setting up the gateway for a client given a `Config`. Depending on the
/// arguments given it will do the sensible thing. Either it will
///
/// a. Reuse existing gateway configuration from storage.
/// b. Create a new gateway configuration but keep existing keys. This assumes that the caller
/// knows what they are doing and that the keys match the requested gateway.
/// c. Create a new gateway configuration with a newly registered gateway and keys.
pub async fn setup_gateway_from_config<KSt>(
key_store: &KSt,
register_gateway: bool,
user_chosen_gateway_id: Option<identity::PublicKey>,
config: &Config,
by_latency: bool,
) -> Result<GatewayEndpointConfig, ClientCoreError>
pub async fn setup_gateway<K, D>(
setup: &GatewaySetup,
key_store: &K,
details_store: &D,
overwrite_data: bool,
validator_servers: Option<&[Url]>,
) -> Result<InitialisationDetails, ClientCoreError>
where
KSt: KeyStore,
<KSt as KeyStore>::StorageError: Send + Sync + 'static,
K: KeyStore,
D: GatewayDetailsStore,
K::StorageError: Send + Sync + 'static,
D::StorageError: Send + Sync + 'static,
{
// If we are not going to register gateway, and an explicitly chosen gateway is not passed in,
// load the existing configuration file
if !register_gateway && user_chosen_gateway_id.is_none() {
eprintln!("Not registering gateway, will reuse existing config and keys");
return Ok(config.client.gateway_endpoint.clone());
}
let gateway_setup = GatewaySetup::new(
None,
user_chosen_gateway_id.map(|id| id.to_base58_string()),
Some(by_latency),
);
// Else, we proceed by querying the nym-api
let gateway = gateway_setup
.try_get_gateway_details(&config.get_nym_api_endpoints())
.await?;
log::debug!("Querying gateway gives: {:?}", gateway);
// If we are not registering, just return this and assume the caller has the keys already and
// wants to keep the,
if !register_gateway && user_chosen_gateway_id.is_some() {
eprintln!("Using gateway provided by user, keeping existing keys");
return Ok(gateway);
}
let mut rng = OsRng;
let mut managed_keys =
crate::client::key_manager::ManagedKeys::load_or_generate(&mut rng, key_store).await;
let gateways = current_gateways(&mut rng, validator_servers.unwrap_or_default()).await?;
// Create new keys and derive our identity
let our_identity = managed_keys.identity_keypair();
// Establish connection, authenticate and generate keys for talking with the gateway
eprintln!("Registering with new gateway");
let shared_keys = helpers::register_with_gateway(&gateway, our_identity).await?;
managed_keys
.deal_with_gateway_key(shared_keys, key_store)
.await
.map_err(|source| ClientCoreError::KeyStoreError {
source: Box::new(source),
})?;
Ok(gateway)
}
/// Get the full client address from the client keys and the gateway identity
pub fn get_client_address(
key_manager: &KeyManager,
gateway_config: &GatewayEndpointConfig,
) -> Recipient {
Recipient::new(
*key_manager.identity_keypair().public_key(),
*key_manager.encryption_keypair().public_key(),
// TODO: below only works under assumption that gateway address == gateway id
// (which currently is true)
NodeIdentity::from_base58_string(&gateway_config.gateway_id).unwrap(),
setup_gateway_from(
setup,
key_store,
details_store,
overwrite_data,
Some(&gateways),
)
}
/// Get the client address by loading the keys from stored files.
// TODO: rethink that sucker
pub fn get_client_address_from_stored_ondisk_keys(
keys_paths: &ClientKeysPaths,
gateway_config: &GatewayEndpointConfig,
) -> Result<Recipient, ClientCoreError> {
let public_identity: identity::PublicKey =
nym_pemstore::load_key(&keys_paths.public_identity_key_file)?;
let public_encryption: encryption::PublicKey =
nym_pemstore::load_key(&keys_paths.public_encryption_key_file)?;
let client_recipient = Recipient::new(
public_identity,
public_encryption,
// TODO: below only works under assumption that gateway address == gateway id
// (which currently is true)
NodeIdentity::from_base58_string(&gateway_config.gateway_id)?,
);
Ok(client_recipient)
.await
}
pub fn output_to_json<T: Serialize>(init_results: &T, output_file: &str) {
@@ -724,7 +724,7 @@ impl<C, St> GatewayClient<C, St> {
Ok(())
}
async fn try_reconnect(&mut self) -> Result<(), GatewayClientError> {
pub async fn try_reconnect(&mut self) -> Result<(), GatewayClientError> {
if !self.connection.is_established() {
self.establish_connection().await?;
}
@@ -738,6 +738,12 @@ impl<C, St> GatewayClient<C, St> {
Ok(())
}
pub async fn disconnect(&mut self) -> Result<(), GatewayClientError> {
self.recover_socket_connection().await?;
self.connection = SocketState::NotConnected;
Ok(())
}
pub async fn authenticate_and_start(&mut self) -> Result<Arc<SharedKeys>, GatewayClientError>
where
C: DkgQueryClient + Send + Sync,
@@ -48,17 +48,21 @@ impl PacketRouter {
// data he takes the SURB-ACK and first hop address.
// currently SURB-ACKs are attached in EVERY packet, even cover, so this is always true
let ack_overhead = PacketSize::AckPacket.size() + MAX_NODE_ADDRESS_UNPADDED_LEN;
let outfox_ack_overhead =
PacketSize::OutfoxAckPacket.size() + MAX_NODE_ADDRESS_UNPADDED_LEN;
for received_packet in unwrapped_packets {
if received_packet.len() == PacketSize::AckPacket.plaintext_size()
|| received_packet.len() == PacketSize::OutfoxAckPacket.plaintext_size()
// we don't know the real size of the payload, it could be anything <= 48 bytes
|| received_packet.len() <= PacketSize::OutfoxAckPacket.plaintext_size()
{
received_acks.push(received_packet);
} else if received_packet.len()
== PacketSize::RegularPacket.plaintext_size() - ack_overhead
|| received_packet.len()
== PacketSize::OutfoxRegularPacket.plaintext_size() - ack_overhead
|| received_packet.len() == PacketSize::OutfoxRegularPacket.size() - 6
== PacketSize::OutfoxRegularPacket.plaintext_size() - outfox_ack_overhead
|| received_packet.len()
== PacketSize::OutfoxRegularPacket.size() - outfox_ack_overhead
{
trace!("routing regular packet");
received_messages.push(received_packet);
@@ -1,4 +1,4 @@
// Copyright 2021-2022 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::error::GatewayClientError;
@@ -13,6 +13,7 @@ colored = "2.0"
nym-coconut-dkg-common = { path = "../../cosmwasm-smart-contracts/coconut-dkg" }
nym-contracts-common = { path = "../../cosmwasm-smart-contracts/contracts-common" }
nym-ephemera-common = { path = "../../cosmwasm-smart-contracts/ephemera" }
nym-mixnet-contract-common = { path = "../../cosmwasm-smart-contracts/mixnet-contract" }
nym-vesting-contract-common = { path = "../../cosmwasm-smart-contracts/vesting-contract" }
nym-coconut-bandwidth-contract-common = { path = "../../cosmwasm-smart-contracts/coconut-bandwidth-contract" }
@@ -29,6 +30,7 @@ log = { workspace = true }
url = { version = "2.2", features = ["serde"] }
tokio = { version = "1.24.1", features = ["sync", "time"] }
futures = "0.3"
openssl = { version = "0.10", features = ["vendored"], optional = true }
nym-coconut-interface = { path = "../../coconut-interface" }
nym-network-defaults = { path = "../../network-defaults" }
@@ -40,7 +42,7 @@ nym-api-requests = { path = "../../../nym-api/nym-api-requests" }
async-trait = { workspace = true, optional = true }
bip39 = { workspace = true, features = ["rand"], optional = true }
nym-config = { path = "../../config", optional = true }
cosmrs = { git = "https://github.com/neacsu/cosmos-rust", branch = "neacsu/feegrant_support", features = ["rpc", "bip32", "cosmwasm"], optional = true }
cosmrs = { workspace = true, features = ["rpc", "bip32", "cosmwasm"], optional = true }
# note that this has the same version as used by cosmrs
eyre = { version = "0.6", optional = true }
cw3 = { workspace = true, optional = true }
@@ -54,7 +56,7 @@ cosmwasm-std = { workspace = true, optional = true }
[dev-dependencies]
bip39 = { workspace = true }
cosmrs = { git = "https://github.com/neacsu/cosmos-rust", branch = "neacsu/feegrant_support", features = ["rpc", "bip32"] }
cosmrs = { workspace = true, features = ["rpc", "bip32"] }
tokio = { version = "1.24.1", features = ["rt-multi-thread", "macros"] }
ts-rs = "6.1.2"
@@ -77,13 +79,14 @@ required-features = ["nyxd-client"]
nyxd-client = [
"async-trait",
"cosmrs",
"cosmwasm-std",
"cw3",
"cw4",
"prost",
"flate2",
"sha2",
"itertools",
"cosmwasm-std",
"openssl",
"prost",
"sha2",
"signing"
]
signing = [
@@ -1,4 +1,4 @@
// Copyright 2021-2022 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::{nym_api, ValidatorClientError};
@@ -17,7 +17,7 @@ pub use nym_mixnet_contract_common::{
use url::Url;
#[cfg(feature = "nyxd-client")]
use crate::nyxd::traits::{DkgQueryClient, MixnetQueryClient};
use crate::nyxd::traits::{DkgQueryClient, EphemeraQueryClient, MixnetQueryClient};
#[cfg(feature = "nyxd-client")]
use crate::nyxd::{self, CosmWasmClient, NyxdClient, QueryNyxdClient, SigningNyxdClient};
#[cfg(feature = "nyxd-client")]
@@ -29,6 +29,8 @@ use nym_coconut_dkg_common::{types::EpochId, verification_key::ContractVKShare};
#[cfg(feature = "nyxd-client")]
use nym_coconut_interface::Base58;
#[cfg(feature = "nyxd-client")]
use nym_ephemera_common::types::JsonPeerInfo;
#[cfg(feature = "nyxd-client")]
use nym_mixnet_contract_common::{
families::{Family, FamilyHead},
mixnode::MixNodeBond,
@@ -569,6 +571,26 @@ impl<C> Client<C> {
Ok(events)
}
pub async fn get_all_ephemera_peers(&self) -> Result<Vec<JsonPeerInfo>, ValidatorClientError>
where
C: CosmWasmClient + Sync + Send,
{
let mut peers = Vec::new();
let mut start_after = None;
loop {
let mut paged_response = self.get_peers_paged(start_after.take(), None).await?;
peers.append(&mut paged_response.peers);
if let Some(start_after_res) = paged_response.start_next_after {
start_after = Some(start_after_res.to_string())
} else {
break;
}
}
Ok(peers)
}
}
// validator-api wrappers
@@ -1,4 +1,4 @@
// Copyright 2021-2022 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::nym_api::error::NymAPIError;
@@ -1,4 +1,4 @@
// Copyright 2021-2022 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
// TODO: There's a significant argument to pull those out of the package and make a PR on https://github.com/cosmos/cosmos-rust/
@@ -127,7 +127,7 @@ impl GasAdjustable for Gas {
mod sealed {
use cosmrs::tx::{self, Gas};
use cosmrs::Coin as CosmosCoin;
use cosmrs::{AccountId, Decimal as CosmosDecimal, Denom as CosmosDenom};
use cosmrs::{AccountId, Denom as CosmosDenom};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
fn cosmos_denom_inner_getter(val: &CosmosDenom) -> String {
@@ -144,29 +144,11 @@ mod sealed {
}
}
fn cosmos_decimal_inner_getter(val: &CosmosDecimal) -> u64 {
// haha, this code is so disgusting. I'll make a PR on cosmrs to slightly alleviate those issues...
// note: unwrap here is fine as the to_string is just returning a stringified u64 which, well, is a valid u64
val.to_string().parse().unwrap()
}
// at the time of writing it the current cosmrs' Decimal is extremely limited...
#[derive(Serialize, Deserialize)]
#[serde(remote = "CosmosDecimal")]
struct Decimal(#[serde(getter = "cosmos_decimal_inner_getter")] u64);
impl From<Decimal> for CosmosDecimal {
fn from(val: Decimal) -> Self {
val.0.into()
}
}
#[derive(Serialize, Deserialize, Clone)]
struct Coin {
#[serde(with = "Denom")]
denom: CosmosDenom,
#[serde(with = "Decimal")]
amount: CosmosDecimal,
amount: u128,
}
impl From<Coin> for CosmosCoin {
@@ -39,7 +39,7 @@ pub use cosmrs::tendermint::validator::Info as TendermintValidatorInfo;
pub use cosmrs::tendermint::Time as TendermintTime;
pub use cosmrs::tx::{self, Gas};
pub use cosmrs::Coin as CosmosCoin;
pub use cosmrs::{bip32, AccountId, Decimal, Denom};
pub use cosmrs::{bip32, AccountId, Denom};
use cosmwasm_std::Addr;
pub use cosmwasm_std::Coin as CosmWasmCoin;
pub use fee::{gas_price::GasPrice, GasAdjustable, GasAdjustment};
@@ -67,6 +67,7 @@ pub struct Config {
pub(crate) group_contract_address: Option<AccountId>,
pub(crate) multisig_contract_address: Option<AccountId>,
pub(crate) coconut_dkg_contract_address: Option<AccountId>,
pub(crate) ephemera_contract_address: Option<AccountId>,
pub(crate) service_provider_contract_address: Option<AccountId>,
pub(crate) name_service_contract_address: Option<AccountId>,
// TODO: add this in later commits
@@ -133,6 +134,10 @@ impl Config {
details.contracts.coconut_dkg_contract_address.as_ref(),
prefix,
)?,
ephemera_contract_address: Self::parse_optional_account(
details.contracts.ephemera_contract_address.as_ref(),
prefix,
)?,
service_provider_contract_address: Self::parse_optional_account(
details
.contracts
@@ -263,6 +268,10 @@ impl<C> NyxdClient<C> {
self.config.service_provider_contract_address = Some(address);
}
pub fn set_ephemera_contract_address(&mut self, address: AccountId) {
self.config.ephemera_contract_address = Some(address);
}
// TODO: this should get changed into Result<&AccountId, NyxdError> (or Option<&AccountId> in future commits
// note: what unwrap is doing here is just moving a failure that would have normally
// occurred in `connect` when attempting to parse an empty address,
@@ -321,6 +330,14 @@ impl<C> NyxdClient<C> {
self.config.coconut_dkg_contract_address.as_ref().unwrap()
}
// TODO: this should get changed into Result<&AccountId, NyxdError> (or Option<&AccountId> in future commits
// note: what unwrap is doing here is just moving a failure that would have normally
// occurred in `connect` when attempting to parse an empty address,
// so it's not introducing new source of failure (just moves it)
pub fn ephemera_contract_address(&self) -> &AccountId {
self.config.ephemera_contract_address.as_ref().unwrap()
}
// The service provider directory contract is optional, so we return an Option not a Result
pub fn service_provider_contract_address(&self) -> Option<&AccountId> {
self.config.service_provider_contract_address.as_ref()
@@ -0,0 +1,53 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::nyxd::error::NyxdError;
use crate::nyxd::{CosmWasmClient, NyxdClient};
use async_trait::async_trait;
use nym_ephemera_common::msg::QueryMsg as EphemeraQueryMsg;
use nym_ephemera_common::peers::PagedPeerResponse;
use serde::Deserialize;
#[async_trait]
pub trait EphemeraQueryClient {
async fn query_ephemera_contract<T>(&self, query: EphemeraQueryMsg) -> Result<T, NyxdError>
where
for<'a> T: Deserialize<'a>;
async fn get_peers_paged(
&self,
start_after: Option<String>,
limit: Option<u32>,
) -> Result<PagedPeerResponse, NyxdError> {
let request = EphemeraQueryMsg::GetPeers { start_after, limit };
self.query_ephemera_contract(request).await
}
}
#[async_trait]
impl<C> EphemeraQueryClient for NyxdClient<C>
where
C: CosmWasmClient + Send + Sync,
{
async fn query_ephemera_contract<T>(&self, query: EphemeraQueryMsg) -> Result<T, NyxdError>
where
for<'a> T: Deserialize<'a>,
{
self.client
.query_contract_smart(self.ephemera_contract_address(), &query)
.await
}
}
#[async_trait]
impl<C> EphemeraQueryClient for crate::Client<C>
where
C: CosmWasmClient + Sync + Send,
{
async fn query_ephemera_contract<T>(&self, query: EphemeraQueryMsg) -> Result<T, NyxdError>
where
for<'a> T: Deserialize<'a>,
{
self.nyxd.query_ephemera_contract(query).await
}
}
@@ -0,0 +1,43 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::nyxd::cosmwasm_client::types::ExecuteResult;
use crate::nyxd::error::NyxdError;
use crate::nyxd::{Fee, NyxdClient, SigningCosmWasmClient};
use async_trait::async_trait;
use nym_ephemera_common::msg::ExecuteMsg as EphemeraExecuteMsg;
use nym_ephemera_common::types::JsonPeerInfo;
#[async_trait]
pub trait EphemeraSigningClient {
async fn register_as_peer(
&self,
peer_info: JsonPeerInfo,
fee: Option<Fee>,
) -> Result<ExecuteResult, NyxdError>;
}
#[async_trait]
impl<C> EphemeraSigningClient for NyxdClient<C>
where
C: SigningCosmWasmClient + Send + Sync,
{
async fn register_as_peer(
&self,
peer_info: JsonPeerInfo,
fee: Option<Fee>,
) -> Result<ExecuteResult, NyxdError> {
let req = EphemeraExecuteMsg::RegisterPeer { peer_info };
self.client
.execute(
self.address(),
self.ephemera_contract_address(),
&req,
fee.unwrap_or_default(),
format!("registering {} as an ephemera peer", self.address()),
vec![],
)
.await
}
}
@@ -1,10 +1,12 @@
// Copyright 2021-2022 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
// TODO: expose query-related capabilities to wasm client...
mod coconut_bandwidth_query_client;
mod dkg_query_client;
mod ephemera_query_client;
mod ephemera_signing_client;
mod group_query_client;
mod mixnet_query_client;
mod multisig_query_client;
@@ -24,6 +26,7 @@ mod name_service_signing_client;
pub use coconut_bandwidth_query_client::CoconutBandwidthQueryClient;
pub use dkg_query_client::DkgQueryClient;
pub use ephemera_query_client::EphemeraQueryClient;
pub use group_query_client::GroupQueryClient;
pub use mixnet_query_client::MixnetQueryClient;
pub use multisig_query_client::MultisigQueryClient;
@@ -33,6 +36,7 @@ pub use vesting_query_client::VestingQueryClient;
pub use coconut_bandwidth_signing_client::CoconutBandwidthSigningClient;
pub use dkg_signing_client::DkgSigningClient;
pub use ephemera_signing_client::EphemeraSigningClient;
pub use mixnet_signing_client::MixnetSigningClient;
pub use multisig_signing_client::MultisigSigningClient;
pub use name_service_signing_client::NameServiceSigningClient;
@@ -1,12 +1,12 @@
use async_trait::async_trait;
use cosmrs::AccountId;
use nym_contracts_common::ContractBuildInformation;
use nym_contracts_common::{signing::Nonce, ContractBuildInformation};
use nym_service_provider_directory_common::{
msg::QueryMsg as SpQueryMsg,
response::{
ConfigResponse, PagedServicesListResponse, ServiceInfoResponse, ServicesListResponse,
},
NymAddress, ServiceId, ServiceInfo,
NymAddress, Service, ServiceId,
};
use serde::Deserialize;
@@ -63,17 +63,14 @@ pub trait SpDirectoryQueryClient {
.await
}
async fn get_all_services(&self) -> Result<Vec<ServiceInfo>, NyxdError> {
async fn get_all_services(&self) -> Result<Vec<Service>, NyxdError> {
let mut services = Vec::new();
let mut start_after = None;
loop {
let mut paged_response = self.get_services_paged(start_after.take(), None).await?;
let last_id = paged_response.services.last().map(|serv| serv.service_id);
services.append(&mut paged_response.services);
if let Some(start_after_res) = last_id {
if let Some(start_after_res) = paged_response.start_next_after {
start_after = Some(start_after_res)
} else {
break;
@@ -82,6 +79,13 @@ pub trait SpDirectoryQueryClient {
Ok(services)
}
async fn get_service_signing_nonce(&self, address: &AccountId) -> Result<Nonce, NyxdError> {
self.query_service_provider_contract(SpQueryMsg::SigningNonce {
address: address.to_string(),
})
.await
}
}
#[async_trait]
@@ -2,8 +2,9 @@
// SPDX-License-Identifier: Apache-2.0
use async_trait::async_trait;
use nym_contracts_common::signing::MessageSignature;
use nym_service_provider_directory_common::{
msg::ExecuteMsg as SpExecuteMsg, NymAddress, ServiceId, ServiceType,
msg::ExecuteMsg as SpExecuteMsg, NymAddress, ServiceDetails, ServiceId,
};
use crate::nyxd::{
@@ -22,16 +23,16 @@ pub trait SpDirectorySigningClient {
async fn announce_service_provider(
&self,
nym_address: NymAddress,
service_type: ServiceType,
service: ServiceDetails,
owner_signature: MessageSignature,
deposit: Coin,
fee: Option<Fee>,
) -> Result<ExecuteResult, NyxdError> {
self.execute_service_provider_directory_contract(
fee,
SpExecuteMsg::Announce {
nym_address,
service_type,
service,
owner_signature,
},
vec![deposit],
)
+6 -2
View File
@@ -14,7 +14,7 @@ clap = { version = "4.0", features = ["derive"] }
cw-utils = { workspace = true }
handlebars = "3.0.1"
humantime-serde = "1.0"
k256 = { version = "0.10", features = ["ecdsa", "sha256"] }
k256 = { workspace = true, features = ["ecdsa", "sha256"] }
log = { workspace = true }
rand = {version = "0.6", features = ["std"] }
serde = { version = "1.0", features = ["derive"] }
@@ -25,7 +25,7 @@ toml = "0.5.6"
url = "2.2"
tap = "1"
cosmrs = { git = "https://github.com/neacsu/cosmos-rust", branch = "neacsu/feegrant_support" }
cosmrs = { workspace = true }
cosmwasm-std = { workspace = true }
nym-validator-client = { path = "../client-libs/validator-client", features = ["nyxd-client"] }
@@ -40,3 +40,7 @@ nym-coconut-dkg-common = { path = "../cosmwasm-smart-contracts/coconut-dkg" }
nym-multisig-contract-common = { path = "../cosmwasm-smart-contracts/multisig-contract" }
nym-service-provider-directory-common = { path = "../cosmwasm-smart-contracts/service-provider-directory" }
nym-name-service-common = { path = "../cosmwasm-smart-contracts/name-service" }
nym-sphinx = { path = "../../common/nymsphinx" }
nym-pemstore = { path = "../../common/pemstore", version = "0.3.0" }
nym-types = { path = "../../common/types" }
@@ -56,6 +56,8 @@ pub async fn generate(args: Args) {
.expect("threshold can't be converted to Decimal"),
},
max_voting_period: Duration::Time(args.max_voting_period),
executor: None,
proposal_deposit: None,
coconut_bandwidth_contract_address: coconut_bandwidth_contract_address.to_string(),
coconut_dkg_contract_address: coconut_dkg_contract_address.to_string(),
};
@@ -14,6 +14,7 @@ pub struct Mixnet {
pub command: MixnetCommands,
}
#[allow(clippy::large_enum_variant)]
#[derive(Debug, Subcommand)]
pub enum MixnetCommands {
/// Query the mixnet directory
@@ -0,0 +1,68 @@
use clap::{Args, Parser, Subcommand};
use nym_bin_common::output_format::OutputFormat;
use nym_crypto::asymmetric::identity;
use nym_types::helpers::ConsoleSigningOutput;
use nym_validator_client::nyxd::error::NyxdError;
use std::path::PathBuf;
#[derive(Debug, Args)]
#[clap(args_conflicts_with_subcommands = true, subcommand_required = true)]
pub struct MixnetOperatorsIdentityKey {
#[clap(subcommand)]
pub command: MixnetOperatorsIdentityKeyCommands,
}
#[derive(Debug, Subcommand)]
pub enum MixnetOperatorsIdentityKeyCommands {
/// Register a name alias for a nym address
Sign(SignArgs),
}
#[derive(Debug, Parser)]
pub struct SignArgs {
/// Path to private identity key (example: private_identity_key.pem)
#[clap(long)]
private_key: PathBuf,
/// Base58 encoded message to sign
#[clap(long)]
base58_msg: String,
#[clap(short, long, default_value_t = OutputFormat::default())]
output: OutputFormat,
}
pub async fn sign(args: SignArgs) -> Result<(), NyxdError> {
eprintln!(">>> loading: {}", args.private_key.display());
let private_identity_key: identity::PrivateKey =
nym_pemstore::load_key(args.private_key).expect("failed to load key");
print_signed_msg(&private_identity_key, &args.base58_msg, args.output);
Ok(())
}
fn print_signed_msg(private_key: &identity::PrivateKey, raw_msg: &str, output: OutputFormat) {
let trimmed = raw_msg.trim();
eprintln!(">>> attempting to sign: {trimmed}");
let Ok(decoded) = bs58::decode(trimmed).into_vec() else {
println!("failed to base58 decode the message, did you copy it correctly?");
return;
};
eprintln!(">>> decoding the message...");
// we don't really care about what particular information is embedded inside of it,
// we just want to know if user correctly copied the string, i.e. whether it's a valid bs58 encoded json
if serde_json::from_slice::<serde_json::Value>(&decoded).is_err() {
println!("failed to parse the message after decoding, did you copy it correctly?");
return;
};
// if this is a valid json, it MUST be a valid string
let decoded_string = String::from_utf8(decoded.clone()).unwrap();
let signature = private_key.sign(&decoded).to_base58_string();
let sign_output = ConsoleSigningOutput::new(decoded_string, signature);
println!("{}", output.format(&sign_output));
}
@@ -4,6 +4,7 @@
use clap::{Args, Subcommand};
pub mod gateway;
pub mod identity_key;
pub mod mixnode;
pub mod name;
pub mod service;
@@ -15,6 +16,7 @@ pub struct MixnetOperators {
pub command: MixnetOperatorsCommands,
}
#[allow(clippy::large_enum_variant)]
#[derive(Debug, Subcommand)]
pub enum MixnetOperatorsCommands {
/// Manage your mixnode
@@ -25,4 +27,6 @@ pub enum MixnetOperatorsCommands {
ServiceProvider(service::MixnetOperatorsService),
/// Manage your registered name
Name(name::MixnetOperatorsName),
/// Sign messages using your private identity key
IdentityKey(identity_key::MixnetOperatorsIdentityKey),
}
@@ -1,6 +1,7 @@
use clap::Parser;
use log::info;
use nym_service_provider_directory_common::{Coin, NymAddress, ServiceType};
use nym_contracts_common::signing::MessageSignature;
use nym_service_provider_directory_common::{Coin, NymAddress, ServiceDetails, ServiceType};
use nym_validator_client::nyxd::traits::SpDirectorySigningClient;
use crate::context::SigningClient;
@@ -10,9 +11,15 @@ pub struct Args {
#[clap(long)]
pub nym_address: String,
#[clap(long)]
pub signature: MessageSignature,
/// Deposit to be made to the service provider directory, in curent DENOMINATION (e.g. 'unym')
#[clap(long)]
pub deposit: u128,
#[clap(long)]
pub identity_key: String,
}
pub async fn announce(args: Args, client: SigningClient) {
@@ -20,12 +27,17 @@ pub async fn announce(args: Args, client: SigningClient) {
let nym_address = NymAddress::Address(args.nym_address);
let service_type = ServiceType::NetworkRequester;
let service = ServiceDetails {
nym_address,
service_type,
identity_key: args.identity_key,
};
let denom = client.current_chain_details().mix_denom.base.as_str();
let deposit = Coin::new(args.deposit, denom);
let res = client
.announce_service_provider(nym_address, service_type, deposit.into(), None)
.announce_service_provider(service, args.signature, deposit.into(), None)
.await
.expect("Failed to announce service provider");
@@ -0,0 +1,61 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::{
context::SigningClient,
utils::{account_id_to_cw_addr, DataWrapper},
};
use clap::Parser;
use cosmwasm_std::Coin;
use nym_bin_common::output_format::OutputFormat;
use nym_service_provider_directory_common::{
signing_types::construct_service_provider_announce_sign_payload, NymAddress,
ServiceType::NetworkRequester,
};
use nym_sphinx::addressing::clients::Recipient;
use nym_validator_client::nyxd::traits::SpDirectoryQueryClient;
#[derive(Debug, Parser)]
pub struct Args {
#[clap(long)]
pub nym_address: Recipient,
#[clap(long)]
pub amount: u128,
#[clap(long)]
pub identity_key: String,
#[clap(short, long, default_value_t = OutputFormat::default())]
output: OutputFormat,
}
pub async fn create_payload(args: Args, client: SigningClient) {
let service = nym_service_provider_directory_common::ServiceDetails {
nym_address: NymAddress::new(&args.nym_address.to_string()),
service_type: NetworkRequester,
identity_key: args.identity_key,
};
let denom = client.current_chain_details().mix_denom.base.as_str();
let deposit = Coin::new(args.amount, denom);
let nonce = match client.get_service_signing_nonce(client.address()).await {
Ok(nonce) => nonce,
Err(err) => {
eprint!(
"failed to query for the signing nonce of {}: {err}",
client.address()
);
return;
}
};
let address = account_id_to_cw_addr(client.address());
let payload =
construct_service_provider_announce_sign_payload(nonce, address, deposit, service);
let wrapper = DataWrapper::new(payload.to_base58_string().unwrap());
println!("{}", args.output.format(&wrapper))
}
@@ -1,6 +1,7 @@
use clap::{Args, Subcommand};
pub mod announce;
pub mod announce_sign_payload;
pub mod delete;
#[derive(Debug, Args)]
@@ -10,10 +11,13 @@ pub struct MixnetOperatorsService {
pub command: MixnetOperatorsServiceCommands,
}
#[allow(clippy::large_enum_variant)]
#[derive(Debug, Subcommand)]
pub enum MixnetOperatorsServiceCommands {
/// Announce service provider to the world
Announce(announce::Args),
/// Delete entry for service provider from the directory
Delete(delete::Args),
/// Create base58-encoded payload required for producing valid announce signature.
CreateServiceAnnounceSignPayload(announce_sign_payload::Args),
}
@@ -37,7 +37,7 @@ pub async fn query(args: Args, client: &QueryClientWithNyxd) {
for service in res.services {
table.add_row(vec![
service.service_id.to_string(),
service.service.announcer.to_string(),
service.announcer.to_string(),
service.service.service_type.to_string(),
service.service.nym_address.to_string(),
]);
+1
View File
@@ -17,6 +17,7 @@ pub mod helpers;
pub mod legacy_helpers;
pub const NYM_DIR: &str = ".nym";
pub const DEFAULT_NYM_APIS_DIR: &str = "nym-api";
pub const DEFAULT_CONFIG_DIR: &str = "config";
pub const DEFAULT_DATA_DIR: &str = "data";
pub const DEFAULT_CONFIG_FILENAME: &str = "config.toml";
@@ -14,7 +14,7 @@ pub struct InstantiateMsg {
pub mix_denom: String,
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum ExecuteMsg {
DepositFunds { data: DepositData },
@@ -8,7 +8,7 @@ use serde::{Deserialize, Serialize};
use crate::msg::ExecuteMsg;
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
pub struct SpendCredentialData {
funds: Coin,
blinded_serial_number: String,
@@ -43,7 +43,7 @@ pub enum SpendCredentialStatus {
Spent,
}
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)]
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
pub struct SpendCredential {
funds: Coin,
blinded_serial_number: String,
@@ -74,7 +74,7 @@ impl SpendCredential {
}
}
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)]
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
pub struct PagedSpendCredentialResponse {
pub spend_credentials: Vec<SpendCredential>,
pub per_page: usize,
@@ -95,7 +95,7 @@ impl PagedSpendCredentialResponse {
}
}
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)]
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
pub struct SpendCredentialResponse {
pub spend_credential: Option<SpendCredential>,
}
@@ -1,6 +1,6 @@
[package]
name = "nym-contracts-common"
version = "0.4.0"
version = "0.5.0"
description = "Common library for Nym cosmwasm contracts"
edition = { workspace = true }
authors = { workspace = true }
@@ -15,7 +15,7 @@ pub type Nonce = u32;
// define this type explicitly for [hopefully] better usability
// (so you wouldn't need to worry about whether you should use bytes, bs58, etc.)
#[derive(Clone, Debug, PartialEq, JsonSchema)]
#[derive(Clone, Debug, PartialEq, Eq, JsonSchema)]
pub struct MessageSignature(Vec<u8>);
impl MessageSignature {
@@ -11,6 +11,9 @@ use std::ops::Mul;
use std::str::FromStr;
use thiserror::Error;
pub type IdentityKey = String;
pub type IdentityKeyRef<'a> = &'a str;
pub fn truncate_decimal(amount: Decimal) -> Uint128 {
amount * Uint128::new(1)
}
@@ -0,0 +1,14 @@
[package]
name = "nym-ephemera-common"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
cosmwasm-std = { workspace = true }
cw-utils = { workspace = true }
schemars = "0.8"
serde = { version = "1.0.103", default-features = false, features = ["derive"] }
contracts-common = { path = "../contracts-common", package = "nym-contracts-common" }
@@ -0,0 +1,3 @@
pub mod msg;
pub mod peers;
pub mod types;
@@ -0,0 +1,31 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::types::JsonPeerInfo;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
pub struct InstantiateMsg {
pub group_addr: String,
pub mix_denom: String,
}
#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum ExecuteMsg {
RegisterPeer { peer_info: JsonPeerInfo },
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum QueryMsg {
GetPeers {
limit: Option<u32>,
start_after: Option<String>,
},
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub struct MigrateMsg {}
@@ -0,0 +1,24 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::types::JsonPeerInfo;
use cosmwasm_std::Addr;
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
#[serde(rename_all = "snake_case")]
pub struct PagedPeerResponse {
pub peers: Vec<JsonPeerInfo>,
pub per_page: usize,
pub start_next_after: Option<Addr>,
}
impl PagedPeerResponse {
pub fn new(peers: Vec<JsonPeerInfo>, per_page: usize, start_next_after: Option<Addr>) -> Self {
PagedPeerResponse {
peers,
per_page,
start_next_after,
}
}
}
@@ -0,0 +1,30 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use cosmwasm_std::Addr;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema)]
pub struct JsonPeerInfo {
/// The cosmos address of the peer, used in interacting with the chain.
pub cosmos_address: Addr,
/// The TCP/IP address of the peer.
/// Expected formats:
/// 1. `<IP>:<PORT>`
/// 2. `/ip4/<IP>/tcp/<PORT>` - this is the format used by libp2p multiaddr
pub ip_address: String,
///Serialized public key.
pub public_key: String,
}
impl JsonPeerInfo {
#[must_use]
pub fn new(cosmos_address: Addr, ip_address: String, public_key: String) -> Self {
Self {
cosmos_address,
ip_address,
public_key,
}
}
}

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