Compare commits

...

164 Commits

Author SHA1 Message Date
Tommy Verrall 07b566071b supress output 2023-02-03 16:11:15 -01:00
Tommy Verrall 5f231e3eac last check 2023-02-03 15:50:38 -01:00
Tommy Verrall 9d3cad2771 directories 2023-02-03 15:41:17 -01:00
Tommy Verrall ae0f9b1b7b move the files to the correct place 2023-02-03 15:31:50 -01:00
Tommy Verrall 8a1e225365 write to file 2023-02-03 15:22:54 -01:00
Tommy Verrall 2a6d0f3113 quotes 2023-02-03 15:03:10 -01:00
Tommy Verrall d81e1fe44d operator 2023-02-03 15:01:58 -01:00
Tommy Verrall ef62ec6560 check output 2023-02-03 14:57:03 -01:00
Tommy Verrall 6649f859e6 wrong positioning 2023-02-03 14:47:39 -01:00
Tommy Verrall 617113555b print for debugging existing and after to check 2023-02-03 14:43:05 -01:00
Tommy Verrall b9e8ba3215 the version is always due to change, everything else should be okay 2023-02-03 14:36:38 -01:00
Tommy Verrall 2693ccafd1 format 2023-02-03 14:31:07 -01:00
Tommy Verrall 8d78d23060 update the config 2023-02-03 14:29:41 -01:00
Tommy Verrall 9543247def try diffing the files 2023-02-03 14:28:02 -01:00
Tommy Verrall 618c54ede3 format 2023-02-03 13:51:14 -01:00
Tommy Verrall c91b63a6f8 tidy up now it's passing now validate against new binary 2023-02-03 13:40:01 -01:00
Tommy Verrall 4e63f2ce60 try assertion command via outputting via echo 2023-02-03 13:35:04 -01:00
Tommy Verrall bc80511863 weird behaviour from local to machine 2023-02-03 13:25:41 -01:00
Tommy Verrall bc08b26ed4 more debug 2023-02-03 13:17:10 -01:00
Tommy Verrall 81c5cafc60 binary add 2023-02-03 13:16:19 -01:00
Tommy Verrall a9f25c2492 debugging 2023-02-03 13:09:21 -01:00
Tommy Verrall 0ab5320656 fix var 2023-02-03 12:25:45 -01:00
Tommy Verrall 28e7ce11e3 input assertion again 2023-02-03 10:19:05 -01:00
Tommy Verrall 03364b848b bad variable placement 2023-02-03 10:16:34 -01:00
Tommy Verrall 8926d622b3 wrap the var name 2023-02-03 10:13:11 -01:00
Tommy Verrall a58d3dc6b2 fixing up 2023-02-03 10:12:28 -01:00
Tommy Verrall ece189773d typo on the function 2023-02-03 10:09:00 -01:00
Tommy Verrall de2c3851ee change output 2023-02-03 10:05:18 -01:00
Tommy Verrall 6869de5640 install the binaries from github and run it against specific branch 2023-02-03 09:57:05 -01:00
Tommy Verrall 580b677489 Binary checker, introduction 2023-02-03 08:46:40 -01:00
Jędrzej Stuczyński 2093789c5c Added an option to set custom 'host' for the native client (#2939)
* Added an option to set custom 'host' for the native client

* Changelog entry
2023-02-02 16:38:39 +00:00
Pierre Dommerc d09864b99f build(nc-android): prepare for apk release (#2943)
* chore(nc-android): prepare for production build

* refactor(nc-android): remove dead code

* feat(nc-android): update native color theme

* feat(nc-android): update native color theme

* build(nc-android): fix rfd version issue

* build(nc-android): fix dist dir no such file error

* fix(nc-android): post rebase changes
2023-02-02 15:18:58 +01:00
Bogdan-Ștefan Neacşu f6e8278592 Fix typo during merge back to develop (#2956) 2023-02-02 13:55:58 +02:00
cgi-bin/ b085a8a636 typo: electrum (#2954) 2023-02-02 09:34:08 +00:00
farbanas e6ce531aeb fix: formatting 2023-02-01 17:16:53 +01:00
farbanas 1a860eb3f5 fix: wrong parameter type for addresses in generator commands (should be AccountId instead of String) 2023-02-01 12:45:51 +01:00
Fran Arbanas 09cfd9ff05 Update CHANGELOG.md 2023-01-31 14:42:16 +00:00
Bogdan-Ștefan Neacșu 2c88ca137a Resolve merge conflict 2023-01-31 16:19:34 +02:00
farbanas ca3bfc859a merge conflicts 2023-01-31 15:09:35 +01:00
Pierre Dommerc dc2b25f152 fix(nc-android): panic on socks5 client connect (#2929) 2023-01-31 12:08:57 +01:00
Bogdan-Ștefan Neacșu 5370bb9c47 Fix clippy 2023-01-30 17:56:27 +02:00
Jędrzej Stuczyński cd3c951572 drop pending messages if we dont have enough surbs and we havent gotten any in long time (#2937)
* drop pending messages if we dont have enough surbs and we havent gotten any in long time

* missing changes to wasm client
2023-01-30 15:39:26 +00:00
Jon Häggblad 7e43ce1aed nym-connect-android: fix CI (#2930) 2023-01-30 11:38:14 +01:00
Jon Häggblad 0669369c77 fix commit 044fa93eec 2023-01-28 20:48:50 +01:00
Pierre Dommerc 6f94ab4937 ci(nc-android): try fix (#2928) 2023-01-28 00:12:53 +01:00
Pierre Dommerc 0d3ca99dfa docs(nc-android): update readme (#2924)
* docs(nc-android): update readme

* docs(nc-android): update readme
2023-01-27 21:18:43 +01:00
Pierre Dommerc 509391cde4 ci(nc-android): add gh workflow (#2927)
* ci(nc-android): add gh workflow

* ci(nc-android): fix cargo.toml path
2023-01-27 21:05:50 +01:00
Mark Sinclair 0fc0292b18 WASM client changes (#2925)
* Add rollup config to output CommonJS and ESM packages, simplified interface

* Remove examples from monorepo

---------

Co-authored-by: Mark Sinclair <mmsinclair@users.noreply.github.com>
2023-01-27 16:48:10 +00:00
Jędrzej Stuczyński 9a2a99e581 removed migrated vesting contract code (#2914) 2023-01-27 14:22:11 +00:00
Jon Häggblad 5ec7beec8a Remove .DS_Store and add to .gitignore 2023-01-27 14:05:08 +01:00
Jon Häggblad 044fa93eec ci: fix nightly clippy
Remove `--all-features` from the clippy command because

1. with the removal of `cocunut` it's not really needed
2. the new `mobile` flag is a bit hacky and mutually incompatible with
   some existing configs
2023-01-27 09:46:37 +01:00
Pierre Dommerc 3e6188ed13 nym-connect-android initial version (#2907)
* feat(nym-connect): add android support

* fix(nym-connect): android linker issue with sqlite3

get rid of sqlite refs as temporary workaround

* fix(nc): fix index.ts (post rebase)

* feat(nc-android): wip

* hack in config removal of read/write

* fix(nc-android): remove more fs read/write calls

* wip

* chore: remove debug comments

* Register gateway

* client-core: remove unneeded changes

* build: revert crate name change

* refactor(socks5-client): add feature mobile

* refactor(gateway-client): rename mobile feature

* socks5: restore default_root_directory

* client-core: further simplifications

* get_config_file_location just return error

* fix(nc-mobile): fix ui mobile

* socks5: minor tweak to default_root_directory

* remove unneeded changes

* nym-connect build fixes

* Use default feature for normal credential storage

* rustfmt

* rustfmt: nym-connect

* restore Cargo.toml

* Remove --all-features from workflow

* Remove some unused use

* Remove two move --all-features from build workflow

* Allow unused

* Add continue-on-error

* another clippy --all-features remove

* remove --all-features from clippy nightly

* fix(nc-mobile): frontend code errors

* feat: restore nc, move mobile under its own dir

* fix(nc-android): build

* fix(nc-android): lint errors

Co-authored-by: Jon Häggblad <jon.haggblad@gmail.com>
2023-01-26 14:17:29 +01:00
Tommy Verrall 45c51636a8 Merge pull request #2920 from nymtech/feature/nym-api-tests
nym-api tests
2023-01-26 13:03:43 +01:00
Tommy Verrall 975af0c79b remove the empty interface and return the array instead 2023-01-26 12:00:25 +00:00
benedettadavico 8d82a11b00 Merge conflicts 2023-01-26 12:50:47 +01:00
Tommy Verrall 854d548c20 Delete yarn-stable-temp.cjs 2023-01-26 12:50:35 +01:00
benedettadavico de55ffd944 pretty 2023-01-26 12:49:43 +01:00
Tommy Verrall c8866b1af2 Delete yarn-stable-temp.cjs 2023-01-26 12:27:59 +01:00
benedettadavico eb31e47e68 nym-api tests 2023-01-26 12:22:07 +01:00
Jon Häggblad 0bcdf99475 ci: update build arguments and some tidy (#2919)
* ci: remove --all-targets where it doesn't make sense anymore

* ci: add cargo clean step for ubuntu

* sdk: add note about the existance of a rust sdk
2023-01-26 09:13:39 +01:00
Jon Häggblad b8e2997c73 nym-connect: connectivity status improvements (#2915)
* connect: keep track of connectivity state

* nym-connect: query connection state

* nym-connect: function for kicking of the health check task

* rustfmt

* nym-connect: extract out into function

* nym-connect: extract out events.rs
2023-01-25 20:55:55 +01:00
Bogdan-Ștefan Neacşu 8336d0612a Remove coconut feature (#2890)
* Remove coconut feature

* Remove github workflow remainings

* Only run dkg if coconut enabled

* Fix typo

* Update changelog
2023-01-25 15:59:37 +02:00
Jędrzej Stuczyński 33d044dd5a Merge branch 'master' into develop 2023-01-25 13:39:33 +00:00
farbanas c2d28740a5 bump mixnode version 2023-01-25 14:06:11 +01:00
farbanas 58b5f113c6 feat: add a workflow for building and publishing binaries to the artifact storage without attaching them to a release 2023-01-25 13:27:04 +01:00
farbanas 9ab3a133d9 feat: add a workflow for building and publishing binaries to the artifact storage without attaching them to a release 2023-01-25 13:25:06 +01:00
Fran Arbanas 7a9fbbccc6 Merge pull request #2864 from nymtech/2733-hosted-runners-releasing
[#2733] Releasing on our self-hosted runners and less failing actions
2023-01-25 13:12:52 +01:00
farbanas f3b82fa032 updated changelog for the new version of contracts 2023-01-25 13:08:54 +01:00
Drazen Urch 49b8a843a4 Vesting cap (#2903)
* Locked coins definition change

* Adapt tests to new locked

* Typo

* More tests

* Fix withdraw test

* Rollback changes

* Cleanup
2023-01-25 12:36:58 +01:00
Jędrzej Stuczyński 5d385ba10f don't trigger global shutdown upon finishing sending verloc packets (#2910) 2023-01-25 10:40:57 +00:00
Mark Sinclair da9468c36a Update package.json 2023-01-24 16:26:37 +00:00
Fran Arbanas 2bd679c91f feat: refactored GH actions (#2894) 2023-01-24 16:11:01 +00:00
joeiacono2021 f4d0a120bb Merge pull request #2902 from nymtech/release/v1.1.7
Release/v1.1.7
2023-01-24 13:04:53 +00:00
joeiacono2021 027b0dbc39 Merge pull request #2901 from nymtech/release/v1.1.7
Release/v1.1.7
2023-01-24 13:04:22 +00:00
farbanas 130ac50834 Regenerated Cargo.lock and resolved conflicts 2023-01-24 14:03:21 +01:00
Fran Arbanas 5711230ae3 Merge branch 'develop' into release/v1.1.7 2023-01-24 13:53:29 +01:00
joeiacono2021 4db656d074 Version changes for 1.1.7 release , edited versions and changelogs. 2023-01-24 12:41:59 +00:00
farbanas 538bcf1d0a merge resolve 2023-01-24 13:25:25 +01:00
Jon Häggblad 95080c3ecc nym-connect: add connection health test (#2883)
* nym-connect: add connect health test

* nym-connect: redo connection test

* nym-connect: strongly typed response

* Fix clippy

* nym-connect: also send event on connection check success

* nym-connect: tidy
2023-01-24 11:04:30 +01:00
Fouad 17771b5742 Fix NC Build (#2893)
* check if sx prop is array or not

fix sx prop breakage

yarn lock update

* return dist folder

* update lock file
2023-01-24 09:27:38 +01:00
Pierre Dommerc 48af0ae6b4 feat(explorer): copy changes (#2892) 2023-01-24 09:15:07 +01:00
Jon Häggblad 4c19187c78 rust-sdk: start adding rustdoc (#2895)
* rust-sdk: start adding some rustdoc

* rust-sdk: whole bunch of rustdoc

* rustfmt
2023-01-24 08:50:59 +01:00
Fouad e1ec3594ea Fix delegations sorting (#2885)
* map and sort delegations

* allow sorting on profit margin and operator cost

* update wallet changelog
2023-01-23 17:33:53 +01:00
farbanas ded7e51071 fix: add continue-on-error: true to all apt calls since if it fails due to lock those packages most likely already exist 2023-01-23 15:47:42 +01:00
farbanas b75199e4dc added yarn tsc to typescript check 2023-01-23 15:43:49 +01:00
Dave Hrycyszyn a0ed1c8edd Added a few items to the nym-api README 2023-01-23 12:33:53 +00:00
Jędrzej Stuczyński a693fa9190 Handling edge-case for when no vesting accounts exist (#2888) 2023-01-23 11:58:07 +01:00
farbanas e83e83abed Since we have two runners on the same machine apt might get locked. This will allow it to fail, maybe those deps are already installed 2023-01-23 11:56:02 +01:00
Jon Häggblad d03f769b14 nym-api: add endpoint for a list of GatewayBondAnnotated (#2833) 2023-01-23 09:04:23 +01:00
Mark Sinclair 86e9463c42 Typescript: fix eslint errors and add GitHub Action for linting (#2886)
* Fix eslint errors

* GitHub Actions: add Typescript project linting

* Fix dependency

* Revert changes and exclude rule

Co-authored-by: Mark Sinclair <mmsinclair@users.noreply.github.com>
2023-01-20 18:17:15 +00:00
Mark Sinclair 5376c2a4ba WASM Client: use rollup to bundle web worker (#2884)
* WASM Client: simplify sending of custom messages by always setting headers and a mime-type for the content

* Use rollup to bundle the web worker script to support more downstream bundlers

The WASM bundle is embedded as a base64 encoded resource and loaded synchronously, because this is the only mechanism widely supported to load WASM inside a web worker currently. Hopefully in the future this can be changed to pure modules.

* Suppress errors in build script

* Add Parcel 2.0 example

* WASM client: fix tests

* Update SDK docs and images

* wasm-client: add method to validate a recipient's address

* Revert "Removing unused prestart"

This reverts commit cbeac10383.

* Revert "Removing pointless dependency build command from TypeScript SDK example"

This reverts commit 0e0a62938d.

* Add typing for React 18

* Improve README files

Co-authored-by: Mark Sinclair <mmsinclair@users.noreply.github.com>
2023-01-20 16:46:52 +00:00
Dave Hrycyszyn cbeac10383 Removing unused prestart 2023-01-20 13:30:58 +00:00
Dave Hrycyszyn 63a4bdf5a6 Merge branch 'release/v1.1.6' into develop 2023-01-20 12:38:29 +00:00
Dave Hrycyszyn 0e0a62938d Removing pointless dependency build command from TypeScript SDK example 2023-01-20 12:38:01 +00:00
Bogdan-Ștefan Neacşu f1d0bd0bf4 Feature/dkg rerun tests (#2875)
* Some contract unit tests

* Hook for group queries

* Test epoch advancement

* Use separate process for tests using group global var
2023-01-20 14:03:19 +02:00
Raphaël Walther 404473c128 Github Actions: install npm 2023-01-20 09:05:59 +01:00
Jon Häggblad a980d6f804 rust-sdk: enable reply-SURBs by default (#2874)
* rust-sdk: enable SURBs by default

* changelog: update

* rustfmt
2023-01-19 15:21:02 +01:00
Jon Häggblad c6a5e08188 rust-sdk: handle surb storage (#2870)
* clients: make surb storage more flexible

- in the rust-sdk we make the surb storage generic and pluggable, with
  the fs_backend the default.
- make it possible to disable fs_backend at runtime

* Add comment

* changelog: add note

* client-core: tidy up some minor things
2023-01-19 13:30:43 +01:00
Fouad b2ed078e0f Remove test and earn (#2869)
* remove test and earn

* update changelog
2023-01-19 11:40:37 +01:00
Jon Häggblad 886e2ed5e7 nym-sdk: add nyxd-client feature dependency (#2872) 2023-01-19 11:17:37 +01:00
Dave Hrycyszyn aa545ee6c6 Changing comment to nym-api 2023-01-19 10:09:45 +00:00
Jon Häggblad 62741889bc ci: build rust examples (#2871) 2023-01-19 11:04:12 +01:00
Bogdan-Ștefan Neacşu 64c963e36e Feature/dkg rerun (#2839)
* Reset contract state when dkg needs rerun

* Reset nym-api for rerun

* Gateway updates signer APIs at runtime

* Fix clippy

* Add epoch id

* Use IndexedMap for shares

* Query with epoch id

* Add Clone to client traits

* Pass nyxd client instead of api data

* Get the specific epoch vk

* Make wasm work

* Remove wasm test runs

As there are no wasm tests and the target_arch macros are not compatible
with the cargo test environment, we can safely remove (for now) the wasm
test target runs.

* Put epoch_id in storage pk

* Gateway uses old keys but current verifiers

* Add group contract to env

* Move group msg in common

* Only run DKG if part of group

* Clippy test

* Rename wasm_storage to wasm_mockups

* Update changelog
2023-01-19 11:15:07 +02:00
Raphaël Walther d6f87c40ed Github Actions: fix notifications 2023-01-18 17:36:25 +01:00
Fran Arbanas 39562e653a Merge pull request #2837 from nymtech/ci-clippy-update
chore: added --all-targets --all-features to clippy
2023-01-18 13:17:05 +01:00
Jon Häggblad e548d6f1f8 cargo: try out inheriting workspace metadata (#2853)
* cargo: add log as a workspace dependency

* cargo: add authors to top-level workspace

* cargo: add a few more entried to workspace package
2023-01-18 10:13:11 +01:00
Jon Häggblad 48def795d9 common/logging: fix clippy (#2866)
* common/logging: fix clippy

* network-requester: clippy
2023-01-18 09:55:56 +01:00
farbanas e849cc065a move contracts build to our custom runner 2023-01-17 16:43:36 +01:00
farbanas 95b95b2892 fix: contracts build shouldn't fail on wrong tag 2023-01-17 16:24:03 +01:00
farbanas df4587be62 chore: whitespace 2023-01-17 15:47:46 +01:00
Dave Hrycyszyn 80017d258d Merge branch 'release/v1.1.6' into develop 2023-01-17 14:10:15 +00:00
Bogdan-Ștefan Neacşu 6d6d9d4359 Apply rename refactoring to env files (#2854) 2023-01-17 15:02:22 +02:00
farbanas 59185f3b87 merge resolve 2023-01-17 13:41:56 +01:00
durch c708a7cc12 Merge branch 'release/v1.1.6' of https://github.com/nymtech/nym into release/v1.1.6 2023-01-17 13:39:56 +01:00
durch ea35a37d4c Replace println with eprintln! 2023-01-17 13:39:49 +01:00
farbanas e40d25a97b nym-validator-api -> nym-api 2023-01-17 13:33:30 +01:00
farbanas cf903aa2e5 updated changelogs 2023-01-17 13:30:31 +01:00
farbanas 0a2e0d6a8f bump version for release 2023-01-17 13:17:15 +01:00
Fran Arbanas 8eb3dbd191 Merge pull request #2849 from nymtech/workflows-nym-api
fix: rename validator-api to nym-api
2023-01-17 13:07:24 +01:00
farbanas 58d15429de feat: change Github hosted ubuntu-20.04 runners for our own custom-runner-linux 2023-01-17 13:05:35 +01:00
Raphaël Walther a0661fecb2 Github Actions: fix notifications 2023-01-17 10:38:34 +01:00
Jędrzej Stuczyński ea68d42886 bugfix: set default value for nym-api (and nyxd) for clients (#2822)
* setting default urls in client config

* using the same environmental variable for verloc
2023-01-17 10:27:55 +01:00
Dave Hrycyszyn d4298c61a0 Feature/centralized allow list (#2835)
* Changed `listening_address` to `websocket_address` to make things a bit more clear

Stricly speaking, service providers don't "listen" on a port, they make
an outbound connection to a websocket which is already listening on the
provided port on localhost.

* Using un-imported network_defaults module name as it fits nicely

and reduces guessing as to what's going on in the code

* Using full module path for logs

* Some minor renames and extractions

* Fixing a few clippy warnings about double references

* Ripped the allowed_hosts module out into separate module files

* Removing old comment

* Removing unused import

* Knocking down visibility on function

* Docs on OutboundRequestFilter

* Removing a function that doesn't justify its existence

* Keeping struct with its impl

* Renamed a few modules

* Smoothing and rearranging code, no big changes

* It's now possible to inject a standard allowed_list

* Logging all standard allowed domains at network requester startup

* Fixing printed comment
2023-01-16 15:20:24 +00:00
farbanas 65ed611c24 fix: changelog cleanup and added a UNRELEASED section 2023-01-16 16:00:58 +01:00
Raphaël Walther d713b926f8 Github Actions: fix notifications 2023-01-16 15:31:47 +01:00
Gala f305901a18 Changing the explorers guru link (#2820) 2023-01-16 15:27:44 +01:00
Raphaël Walther 082a8ad8ee Github Actions: fix notifications 2023-01-16 14:38:02 +01:00
farbanas 031092815b fix: rename validator-api to nym-api 2023-01-16 14:05:00 +01:00
farbanas ca8a6150c9 fix: moved the if step to the root of the job, removed unused workflows 2023-01-16 14:01:20 +01:00
Jess 645cb88074 Update CHANGELOG.md 2023-01-16 12:42:51 +00:00
Jędrzej Stuczyński 6b96e474f7 made most of cli boolean arguments optional (#2819)
so that if not provided, they would not overwrite config values
2023-01-16 12:52:29 +01:00
Raphaël Walther f4fd08f64e Github Actions: add audit workflow on trigger 2023-01-16 11:25:28 +01:00
Fouad 78247b973b upgrade storybook to latest (#2840) 2023-01-16 09:49:08 +00:00
Jon Häggblad 6b52132501 gateway: don't shutdown on connection handler drop (#2848) 2023-01-16 10:31:01 +01:00
Raphaël Walther d2f33180e2 Github Actions: fix notifications 2023-01-16 09:40:05 +01:00
Jon Häggblad dc71f6e94d common: dedup and move banner to common/logging (#2846) 2023-01-16 08:32:35 +01:00
Raphaël Walther cc7161c113 Github Actions: fix notifications 2023-01-13 16:54:09 +01:00
Jędrzej Stuczyński bbb46ebd90 chore: upgrade tokio to 1.24.1 (+ tokio-util and tokio-stream) (#2843)
* updated 'tokio' to 1.24.1 in the whole codebase

* ibid for 'tokio-stream'

* ibid for 'tokio-util'

* Removed lock file from verify-signature example
2023-01-13 14:46:10 +00:00
Jon Häggblad bc3fd236d8 client-core: fix bug with force-register-gateway (#2844) 2023-01-13 15:43:29 +01:00
dependabot[bot] ea95288940 build(deps): bump minimatch from 3.0.4 to 3.1.2 in /testnet-faucet (#2775)
Bumps [minimatch](https://github.com/isaacs/minimatch) from 3.0.4 to 3.1.2.
- [Release notes](https://github.com/isaacs/minimatch/releases)
- [Changelog](https://github.com/isaacs/minimatch/blob/main/changelog.md)
- [Commits](https://github.com/isaacs/minimatch/compare/v3.0.4...v3.1.2)

---
updated-dependencies:
- dependency-name: minimatch
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-13 13:37:36 +00:00
dependabot[bot] b182ed6925 build(deps): bump luxon from 2.4.0 to 2.5.2 (#2792)
Bumps [luxon](https://github.com/moment/luxon) from 2.4.0 to 2.5.2.
- [Release notes](https://github.com/moment/luxon/releases)
- [Changelog](https://github.com/moment/luxon/blob/master/CHANGELOG.md)
- [Commits](https://github.com/moment/luxon/compare/2.4.0...2.5.2)

---
updated-dependencies:
- dependency-name: luxon
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-13 13:36:20 +00:00
Fouad 017c9d2504 upgrade tauri to 1.2.3 (#2842) 2023-01-13 13:34:56 +00:00
Jędrzej Stuczyński 50c7d717c0 chore: fixed clippy warnings from the nightly toolchain (#2838) 2023-01-13 13:16:47 +00:00
Jędrzej Stuczyński b473aeb3be Feature/gateway graceful shutdown (#2834)
* task dependency

* unifying some startup code and passing TaskClient around

* graceful shutdown handling for mix socket listener

* graceful shutdown handling for clients listener

* graceful shutdown handling for packet forwarding

* unified waiting for interrupt across binaries

* made 'validate_bech32_address_or_exit' into a function that returns proper Result

* printing formatted message on main error

* fixed failing test

* removed duplicate code that should have been gone ages ago

* ibid

* removed biased selection for authenticated handler

* minor refactoring to 'ensure_config_version_compatibility'
2023-01-13 11:56:37 +00:00
farbanas ac10e03aec chore: added --all-targets --all-features to clippy 2023-01-13 10:31:19 +01:00
Fran Arbanas fe2e1c29a2 Merge pull request #2828 from nymtech/2811-fix-clippy-check-failing
[2811] Fix dependabot clippy-check fails
2023-01-13 10:28:26 +01:00
Fouad 2eee5195cc React / React DOM / Types upgrade to version 18 (#2830)
* new react and reactdom packages in wallet

* new react and reactdom packages in root

* new react and reactdom packages in nym connect

* new react and reactdom packages in root

* update react and reactdom for explorer

* react and react-dom upgrade for ts-packages

remove unused import

fix linting error

* use custom FC typing

move typings folder

* fix type error
2023-01-12 17:15:31 +00:00
Jon Häggblad 3bd4343a39 client-core: tidy by removing some allow dead_code (#2832) 2023-01-12 14:18:46 +01:00
Jon Häggblad 74feb065f9 outfox: fix some clippy warnings in tests (#2831) 2023-01-12 14:03:26 +01:00
Mark Sinclair 65b819c649 GitHub Actions: add directory to fix error on runners with read-only file systems 2023-01-12 12:52:31 +00:00
Jon Häggblad bd12305a68 client-core: add note about msg string 2023-01-12 12:35:40 +01:00
Fouad 4854e929ed link to the ng mixnet explorer for account info (#2823) 2023-01-12 12:33:28 +01:00
Jędrzej Stuczyński 5709c45a50 Feature/circulating supply (#2814)
* Fixed typo in node_status_cache constant

* ibid

* Moved some caching stuff around so I can see what depends on what

* Finishing merge of conflicted files

* Minor smoothing

* Got cache reads working for circ supply and refactored common cache

* Refactored nyxd client usages to make things bit more clear

* Moved caching support stuff into the support folder

* Moved storage code into support module

* Removed dead code

* Tweaks

* Handling cases a little more nicely in circulating supply api

* Renamed nymd_client to nyxd_client

* Pulled CacheNotification into the caching support module

* Pulled some domain-specific helpers out of cache refresher

* Moving some more helper methods out of the cache refresher

* Deleting unused code

* Extracted a few more functions out of the cache refresher

* A few comments as breadcrumbs

* Renaming the anemic "helpers" to "node_sets"

* Renaming the validator_cache module to nym_contract_cache

* Renaming nym contract cache stuff to make things clearer

* Renamging a few things in comments

* Renaming validator_cache to nym_contract_cache

* foomp

* Started refactoring http and cli

* Extracted cli arg parsing into its own module

* Cleanup

* Extracted start methods into various modules to clean main up

* WIP commit

* Build working, swagger not

* Fixed swagger docs metadata

* Removed log statement

* Circulating supply cache now working with simple logic

* Fixed up circulating supply method names

* Starting to work in some (wrong) constants

* Documented the cache

* Renaming circulating-supply route

* nym-api compiling after the rebasing

but most likely not fully working yet

* removed unused imports

* only starting RewardedSetUpdater if the config flag is set

* nym-api compiling with coconut feature

* removed redundant process_runner

* removed generic aspect of nym-api nyxd::Client

* signle entry point for starting nym_contract_cache

* do not eagerly grab instances of managed state

* inlining openapi route spec

* CirculatingSupplyResponse type

* fixed compilation of coconut tests

* calculating circulating supply based on mixmining reserve and vesting tokens

* separated different variants of caching intervals

* allow nym-api to specify address of the vesting contract

* fixed types export

* renamed the query on the vesting contract

* reorganised startup procedure and made all start methods independent from rocket

* cleaned up startup procedure for nym-api

* startup checks for rewarding permisssions

* updated changelog

* added config flag to control whether circulating supply should be updated

Co-authored-by: Dave Hrycyszyn <futurechimp@users.noreply.github.com>
2023-01-12 10:39:21 +00:00
Jon Häggblad a7f1242961 client-core: clean up gateway registration (#2827)
* client-core: clean up gateway registration

* client-core: tidy docs and clippy

* clients: tidy output
2023-01-12 11:35:34 +01:00
Jon Häggblad 8b14321c4a connect,wallet: make fern use same colors as env_pretty_logger (#2829) 2023-01-12 11:35:11 +01:00
Fouad 5f88517e1d Feature/nym connect gateway performance (#2824)
* set up ui for gateway performance in nym-connect

remove duplicated imports

* set and reset (when necessary) gateway performance

* remove unneeded useEffect

* remove log
2023-01-12 10:47:58 +01:00
farbanas dddc6eae57 fix: added continue-on-error for clippy-check since they fail on forked repositories due to permission errors which we won't solve 2023-01-12 10:45:27 +01:00
Fouad c7d8f3af97 Feature/nym connect gateway performance (#2815)
* set up ui for gateway performance in nym-connect

* reset gateway performance state periodically

* remove duplicated imports

* set and reset (when necessary) gateway performance

* align gateway performance text left
2023-01-11 14:19:59 +01:00
Gala 1e84f87bf5 Revert "Changing the explorers guru link"
This reverts commit 70ae45b6c9.
2023-01-11 13:33:26 +01:00
Gala 70ae45b6c9 Changing the explorers guru link 2023-01-11 12:59:16 +01:00
farbanas 96444509d0 fix: updated changelog for binaries with the version of the release 2023-01-10 13:53:02 +01:00
farbanas aab91e424e Merge resolve 2023-01-10 13:48:04 +01:00
Fouad 0628565684 Feature/node settings apy playground (#1677) (#2738)
* initial ui for test my node

use svg for node path

add stories for test my node

* add initial rewards calculation

* update validation for rewards playground

* init playground with default values

* get node uptime

* get mixnode reward estimation

* calculate saturation

calculate stake saturation

* Make ComputeRewardEstParam derive Debug

* set active set to be always true

Co-authored-by: Jon Häggblad <jon.haggblad@gmail.com>

Co-authored-by: Jon Häggblad <jon.haggblad@gmail.com>
2022-12-22 15:33:27 +01:00
farbanas 280ac34115 feat: release v1.1.5 of nym-wallet 2022-12-22 12:12:46 +01:00
920 changed files with 34002 additions and 16667 deletions
+5 -1
View File
@@ -26,7 +26,7 @@ jobs:
path: .github/workflows/support-files/notifications/deny.message
notification:
needs: cargo-deny
runs-on: ubuntu-20.04
runs-on: custom-runner-linux
steps:
- name: Check out repository code
uses: actions/checkout@v2
@@ -35,6 +35,10 @@ jobs:
with:
name: report
path: .github/workflows/support-files/notifications
- name: install npm
uses: actions/setup-node@v3
with:
node-version: 16
- name: Keybase - Node Install
run: npm install
working-directory: .github/workflows/support-files
@@ -0,0 +1,59 @@
name: Build and upload binaries to artifact storage
on:
workflow_dispatch:
inputs:
add_tokio_unstable:
description: 'True to add RUSTFLAGS="--cfg tokio_unstable"'
required: true
default: false
type: boolean
env:
NETWORK: mainnet
jobs:
publish-nym:
strategy:
fail-fast: false
matrix:
platform: [ubuntu-20.04]
runs-on: ${{ matrix.platform }}
steps:
- uses: actions/checkout@v3
- name: Install Dependencies (Linux)
run: sudo apt-get update && sudo apt-get -y install libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev libudev-dev squashfs-tools
continue-on-error: true
- name: Sets env vars for tokio if set in manual dispatch inputs
run: |
echo 'RUSTFLAGS="--cfg tokio_unstable"' >> $GITHUB_ENV
if: github.event_name == 'workflow_dispatch' && inputs.add_tokio_unstable == true
- name: Install Rust stable
uses: actions-rs/toolchain@v1
with:
toolchain: stable
- name: Build all binaries
uses: actions-rs/cargo@v1
with:
command: build
args: --workspace --release
- name: Upload Artifact
uses: actions/upload-artifact@v3
with:
name: nym-binaries-artifacts
path: |
target/release/nym-client
target/release/nym-gateway
target/release/nym-mixnode
target/release/nym-socks5-client
target/release/nym-api
target/release/nym-network-requester
target/release/nym-network-statistics
target/release/nym-cli
retention-days: 30
+1
View File
@@ -12,6 +12,7 @@ jobs:
- uses: actions/checkout@v2
- name: Install rsync
run: sudo apt-get install rsync
continue-on-error: true
- uses: rlespinasse/github-slug-action@v3.x
- uses: actions/setup-node@v3
with:
+38 -28
View File
@@ -2,11 +2,33 @@ name: Continuous integration
on:
push:
paths-ignore:
- 'explorer/**'
paths:
- 'clients/**'
- 'common/**'
- 'explorer-api/**'
- 'gateway/**'
- 'integrations/**'
- 'mixnode/**'
- 'sdk/rust/nym-sdk/**'
- 'service-providers/**'
- 'nym-api/**'
- 'nym-outfox/**'
- 'tools/nym-cli/**'
- 'tools/ts-rs-cli/**'
pull_request:
paths-ignore:
- 'explorer/**'
paths:
- 'clients/**'
- 'common/**'
- 'explorer-api/**'
- 'gateway/**'
- 'integrations/**'
- 'mixnode/**'
- 'sdk/rust/nym-sdk/**'
- 'service-providers/**'
- 'nym-api/**'
- 'nym-outfox/**'
- 'tools/nym-cli/**'
- 'tools/ts-rs-cli/**'
jobs:
build:
@@ -17,6 +39,7 @@ jobs:
steps:
- name: Install Dependencies (Linux)
run: sudo apt-get update && sudo apt-get -y install libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev libudev-dev squashfs-tools
continue-on-error: true
- name: Check out repository code
uses: actions/checkout@v2
@@ -41,47 +64,34 @@ jobs:
command: build
args: --workspace
- name: Build all examples
uses: actions-rs/cargo@v1
with:
command: build
args: --workspace --examples
- name: Run all tests
uses: actions-rs/cargo@v1
with:
command: test
args: --workspace --all-features
args: --workspace
- name: Run expensive tests
if: github.ref == 'refs/heads/develop' || github.event.pull_request.base.ref == 'develop' || github.event.pull_request.base.ref == 'master'
uses: actions-rs/cargo@v1
with:
command: test
args: --workspace --all-features -- --ignored
args: --workspace -- --ignored
- uses: actions-rs/clippy-check@v1
name: Clippy checks
continue-on-error: true
with:
token: ${{ secrets.GITHUB_TOKEN }}
args: --workspace --all-features
args: --workspace
- name: Run clippy
uses: actions-rs/cargo@v1
with:
command: clippy
args: --workspace -- -D warnings
# COCONUT stuff
- name: Build all binaries with coconut enabled
uses: actions-rs/cargo@v1
with:
command: build
args: --workspace --features=coconut
- name: Run all tests with coconut enabled
uses: actions-rs/cargo@v1
with:
command: test
args: --workspace --features=coconut
- name: Run clippy with coconut enabled
uses: actions-rs/cargo@v1
with:
command: clippy
args: --all-targets --features=coconut -- -D warnings
args: --workspace --all-targets -- -D warnings
+70
View File
@@ -0,0 +1,70 @@
name: Nym Connect for Android (rust)
on:
push:
paths:
- "nym-connect-android/src-tauri/**"
- "clients/client-core/**"
- "clients/socks5/**"
- "common/**"
- "gateway/gateway-requests/**"
- "contracts/vesting/**"
- "nym-api/nym-api-requests/**"
pull_request:
paths:
- "nym-connect-android/src-tauri/**"
- "clients/client-core/**"
- "clients/socks5/**"
- "common/**"
- "gateway/gateway-requests/**"
- "contracts/vesting/**"
- "nym-api/nym-api-requests/**"
jobs:
build:
#runs-on: [self-hosted, custom-linux]
runs-on: ubuntu-22.04
#env:
#RUSTC_WRAPPER: /home/ubuntu/.cargo/bin/sccache
#defaults:
#run:
#working-directory: nym-connect-android/src-tauri/
steps:
- name: Install Dependencies (Linux)
if: ${{ !env.ACT }}
run: |
sudo apt-get update
sudo apt-get -y install \
libwebkit2gtk-4.1-dev \
build-essential \
curl \
wget \
libssl-dev \
libgtk-3-dev \
squashfs-tools \
libayatana-appindicator3-dev \
librsvg2-dev \
libsoup-3.0-dev \
libjavascriptcoregtk-4.1-dev
#continue-on-error: true
- name: Checkout
uses: actions/checkout@v3
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@master
with:
toolchain: stable
components: clippy, rustfmt
- name: Check formatting
run: cargo fmt --manifest-path nym-connect-android/src-tauri/Cargo.toml -- --check
- name: Build all binaries
run: cargo build --manifest-path nym-connect-android/src-tauri/Cargo.toml
- name: Run all tests
run: cargo test --manifest-path nym-connect-android/src-tauri/Cargo.toml
- name: Clippy
run: cargo clippy --manifest-path nym-connect-android/src-tauri/Cargo.toml --all-targets -- -D warnings
+19 -2
View File
@@ -2,8 +2,23 @@ name: Nym Connect (rust)
on:
push:
paths-ignore:
- 'explorer/**'
paths:
- 'nym-connect/**'
- 'clients/client-core/**'
- 'clients/socks5/**'
- 'common/**'
- 'gateway/gateway-requests/**'
- 'contracts/vesting/**'
- 'nym-api/nym-api-requests/**'
pull_request:
paths:
- 'nym-connect/**'
- 'clients/client-core/**'
- 'clients/socks5/**'
- 'common/**'
- 'gateway/gateway-requests/**'
- 'contracts/vesting/**'
- 'nym-api/nym-api-requests/**'
jobs:
build:
@@ -13,6 +28,7 @@ jobs:
steps:
- name: Install Dependencies (Linux)
run: sudo apt-get update && sudo apt-get -y install libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev squashfs-tools libayatana-appindicator3-dev
continue-on-error: true
- name: Check out repository code
uses: actions/checkout@v2
@@ -45,6 +61,7 @@ jobs:
- uses: actions-rs/clippy-check@v1
name: Clippy checks
continue-on-error: true
with:
token: ${{ secrets.GITHUB_TOKEN }}
args: --manifest-path nym-connect/Cargo.toml --workspace --all-features
+2 -8
View File
@@ -6,17 +6,11 @@ on:
jobs:
build:
runs-on: ubuntu-20.04
if: ${{ startsWith(github.ref, 'refs/tags/nym-contracts-') && github.event_name == 'release' }}
runs-on: [self-hosted, custom-runner-linux]
steps:
- uses: actions/checkout@v2
- name: Check the release tag starts with `nym-contracts-`
if: startsWith(github.ref, 'refs/tags/nym-contracts-') == false && github.event_name != 'workflow_dispatch'
uses: actions/github-script@v3
with:
script: |
core.setFailed('Release tag did not start with nym-contracts-...')
- name: Install Rust stable
uses: actions-rs/toolchain@v1
with:
+5 -3
View File
@@ -2,11 +2,13 @@ name: Contracts
on:
push:
paths-ignore:
- 'explorer/**'
paths:
- 'contracts/**'
- 'common/**'
pull_request:
paths-ignore:
- 'explorer/**'
- 'contracts/**'
- 'common/**'
jobs:
matrix_prep:
+2 -1
View File
@@ -10,6 +10,7 @@ env:
jobs:
publish-nym:
if: ${{ startsWith(github.ref, 'refs/tags/nym-explorer-api-') && (github.event_name == 'release' || github.event_name == 'workflow_dispatch') }}
strategy:
fail-fast: false
matrix:
@@ -21,9 +22,9 @@ jobs:
- name: Install Dependencies (Linux)
run: sudo apt-get update && sudo apt-get -y install libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev libudev-dev squashfs-tools
continue-on-error: true
- name: Check the release tag starts with `nym-explorer-api-`
if: startsWith(github.ref, 'refs/tags/nym-explorer-api-') == false && github.event_name != 'workflow_dispatch'
uses: actions/github-script@v3
with:
script: |
+1
View File
@@ -17,6 +17,7 @@ jobs:
- uses: actions/checkout@v2
- name: Install rsync
run: sudo apt-get install rsync
continue-on-error: true
- uses: rlespinasse/github-slug-action@v3.x
- uses: actions/setup-node@v3
with:
+29 -42
View File
@@ -25,6 +25,7 @@ jobs:
steps:
- name: Install Dependencies (Linux)
run: sudo apt-get update && sudo apt-get install libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev libudev-dev squashfs-tools
continue-on-error: true
if: matrix.os == 'ubuntu-20.04'
- name: Check out repository code
@@ -38,6 +39,12 @@ jobs:
override: true
components: rustfmt, clippy
- name: Check formatting
uses: actions-rs/cargo@v1
with:
command: fmt
args: --all -- --check
- name: Build all binaries
uses: actions-rs/cargo@v1
with:
@@ -50,6 +57,18 @@ jobs:
with:
command: clean
- name: Build all examples
uses: actions-rs/cargo@v1
with:
command: build
args: --workspace --examples
- name: Reclaim some disk space (because Windows is being annoying)
uses: actions-rs/cargo@v1
if: ${{ matrix.os == 'windows-latest' }}
with:
command: clean
- name: Run all tests
uses: actions-rs/cargo@v1
with:
@@ -58,7 +77,7 @@ jobs:
- name: Reclaim some disk space (because Windows is being annoying)
uses: actions-rs/cargo@v1
if: ${{ matrix.os == 'windows-latest' }}
if: ${{ matrix.os == 'windows-latest' || matrix.os == 'ubuntu-20.04' }}
with:
command: clean
@@ -67,13 +86,7 @@ jobs:
uses: actions-rs/cargo@v1
with:
command: test
args: --workspace --all-features -- --ignored
- name: Check formatting
uses: actions-rs/cargo@v1
with:
command: fmt
args: --all -- --check
args: --workspace -- --ignored
- name: Reclaim some disk space (because Windows is being annoying)
uses: actions-rs/cargo@v1
@@ -83,9 +96,10 @@ jobs:
- uses: actions-rs/clippy-check@v1
name: Clippy checks
continue-on-error: true
with:
token: ${{ secrets.GITHUB_TOKEN }}
args: --all-features
args: --workspace
- name: Run clippy
uses: actions-rs/cargo@v1
@@ -100,38 +114,6 @@ jobs:
with:
command: clean
# COCONUT stuff
- name: Build all binaries with coconut enabled
uses: actions-rs/cargo@v1
with:
command: build
args: --workspace --features=coconut
- name: Reclaim some disk space (because Windows is being annoying)
uses: actions-rs/cargo@v1
if: ${{ matrix.os == 'windows-latest' }}
with:
command: clean
- name: Run all tests with coconut enabled
uses: actions-rs/cargo@v1
with:
command: test
args: --workspace --features=coconut
- name: Reclaim some disk space (because Windows is being annoying)
uses: actions-rs/cargo@v1
if: ${{ matrix.os == 'windows-latest' }}
with:
command: clean
- name: Run clippy with coconut enabled
uses: actions-rs/cargo@v1
if: ${{ matrix.rust != 'nightly' }}
with:
command: clippy
args: --workspace --all-targets --features=coconut -- -D warnings
# nym-wallet (the rust part)
- name: Build nym-wallet rust code
uses: actions-rs/cargo@v1
@@ -160,12 +142,17 @@ jobs:
notification:
needs: build
runs-on: ubuntu-20.04
runs-on: custom-runner-linux
steps:
- name: Collect jobs status
uses: technote-space/workflow-conclusion-action@v2
- name: Check out repository code
uses: actions/checkout@v2
- name: install npm
uses: actions/setup-node@v3
if: env.WORKFLOW_CONCLUSION == 'failure'
with:
node-version: 16
- name: Keybase - Node Install
if: env.WORKFLOW_CONCLUSION == 'failure'
run: npm install
+8 -33
View File
@@ -38,6 +38,7 @@ jobs:
steps:
- name: Install Dependencies (Linux)
run: sudo apt-get update && sudo apt-get install libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev libudev-dev squashfs-tools
continue-on-error: true
if: matrix.os == 'ubuntu-20.04'
- name: Check out latest release branch
@@ -98,6 +99,7 @@ jobs:
- uses: actions-rs/clippy-check@v1
name: Clippy checks
continue-on-error: true
with:
token: ${{ secrets.GITHUB_TOKEN }}
args: --all-features
@@ -115,38 +117,6 @@ jobs:
with:
command: clean
# COCONUT stuff
- name: Build all binaries with coconut enabled
uses: actions-rs/cargo@v1
with:
command: build
args: --workspace --features=coconut
- name: Reclaim some disk space (because Windows is being annoying)
uses: actions-rs/cargo@v1
if: ${{ matrix.os == 'windows-latest' }}
with:
command: clean
- name: Run all tests with coconut enabled
uses: actions-rs/cargo@v1
with:
command: test
args: --workspace --features=coconut
- name: Reclaim some disk space (because Windows is being annoying)
uses: actions-rs/cargo@v1
if: ${{ matrix.os == 'windows-latest' }}
with:
command: clean
- name: Run clippy with coconut enabled
uses: actions-rs/cargo@v1
if: ${{ matrix.rust != 'nightly' }}
with:
command: clippy
args: --workspace --all-targets --features=coconut -- -D warnings
# nym-wallet (the rust part)
- name: Build nym-wallet rust code
uses: actions-rs/cargo@v1
@@ -175,12 +145,17 @@ jobs:
notification:
needs: [build,get_release]
runs-on: ubuntu-20.04
runs-on: custom-runner-linux
steps:
- name: Collect jobs status
uses: technote-space/workflow-conclusion-action@v2
- name: Check out repository code
uses: actions/checkout@v3
- name: install npm
uses: actions/setup-node@v3
if: env.WORKFLOW_CONCLUSION == 'failure'
with:
node-version: 16
- name: Keybase - Node Install
if: env.WORKFLOW_CONCLUSION == 'failure'
run: npm install
+8 -33
View File
@@ -38,6 +38,7 @@ jobs:
steps:
- name: Install Dependencies (Linux)
run: sudo apt-get update && sudo apt-get install libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev libudev-dev squashfs-tools
continue-on-error: true
if: matrix.os == 'ubuntu-20.04'
- name: Check out latest release branch
@@ -98,6 +99,7 @@ jobs:
- uses: actions-rs/clippy-check@v1
name: Clippy checks
continue-on-error: true
with:
token: ${{ secrets.GITHUB_TOKEN }}
args: --all-features
@@ -115,38 +117,6 @@ jobs:
with:
command: clean
# COCONUT stuff
- name: Build all binaries with coconut enabled
uses: actions-rs/cargo@v1
with:
command: build
args: --workspace --features=coconut
- name: Reclaim some disk space (because Windows is being annoying)
uses: actions-rs/cargo@v1
if: ${{ matrix.os == 'windows-latest' }}
with:
command: clean
- name: Run all tests with coconut enabled
uses: actions-rs/cargo@v1
with:
command: test
args: --workspace --features=coconut
- name: Reclaim some disk space (because Windows is being annoying)
uses: actions-rs/cargo@v1
if: ${{ matrix.os == 'windows-latest' }}
with:
command: clean
- name: Run clippy with coconut enabled
uses: actions-rs/cargo@v1
if: ${{ matrix.rust != 'nightly' }}
with:
command: clippy
args: --workspace --all-targets --features=coconut -- -D warnings
# nym-wallet (the rust part)
- name: Build nym-wallet rust code
uses: actions-rs/cargo@v1
@@ -175,12 +145,17 @@ jobs:
notification:
needs: [build,get_release]
runs-on: ubuntu-20.04
runs-on: custom-runner-linux
steps:
- name: Collect jobs status
uses: technote-space/workflow-conclusion-action@v2
- name: Check out repository code
uses: actions/checkout@v3
- name: install npm
uses: actions/setup-node@v3
if: env.WORKFLOW_CONCLUSION == 'failure'
with:
node-version: 16
- name: Keybase - Node Install
if: env.WORKFLOW_CONCLUSION == 'failure'
run: npm install
+1 -1
View File
@@ -10,6 +10,7 @@ env:
jobs:
publish-nym-cli:
if: ${{ startsWith(github.ref, 'refs/tags/nym-cli-') && (github.event_name == 'release' || github.event_name = 'workflow_dispatch') }}
strategy:
fail-fast: false
matrix:
@@ -20,7 +21,6 @@ jobs:
- uses: actions/checkout@v3
- name: Check the release tag starts with `nym-cli-`
if: startsWith(github.ref, 'refs/tags/nym-cli-') == false && github.event_name != 'workflow_dispatch'
uses: actions/github-script@v3
with:
script: |
@@ -10,6 +10,7 @@ defaults:
jobs:
publish-tauri:
if: ${{ startsWith(github.ref, 'refs/tags/nym-connect-') && github.event_name == 'release' }}
strategy:
fail-fast: false
matrix:
@@ -19,13 +20,6 @@ jobs:
steps:
- uses: actions/checkout@v2
- name: Check the release tag starts with `nym-connect-`
if: startsWith(github.ref, 'refs/tags/nym-connect-') == false && github.event_name != 'workflow_dispatch'
uses: actions/github-script@v3
with:
script: |
core.setFailed('Release tag did not start with nym-connect-...')
- name: Node v16
uses: actions/setup-node@v3
with:
@@ -10,10 +10,11 @@ defaults:
jobs:
publish-tauri:
if: ${{ startsWith(github.ref, 'refs/tags/nym-connect-') && github.event_name == 'release' }}
strategy:
fail-fast: false
matrix:
platform: [ubuntu-20.04]
platform: [custom-runner-linux]
runs-on: ${{ matrix.platform }}
steps:
@@ -23,17 +24,13 @@ jobs:
run: >
sudo apt-get update &&
sudo apt-get install -y webkit2gtk-4.0 libayatana-appindicator3-dev
- name: Check the release tag starts with `nym-connect-`
if: startsWith(github.ref, 'refs/tags/nym-connect-') == false && github.event_name != 'workflow_dispatch'
uses: actions/github-script@v3
with:
script: |
core.setFailed('Release tag did not start with nym-connect-...')
continue-on-error: true
- name: Node v16
uses: actions/setup-node@v3
with:
node-version: 16
- name: Install Rust stable
uses: actions-rs/toolchain@v1
with:
@@ -10,6 +10,7 @@ defaults:
jobs:
publish-tauri:
if: ${{ startsWith(github.ref, 'refs/tags/nym-connect-') && github.event_name == 'release' }}
strategy:
fail-fast: false
matrix:
@@ -27,13 +28,6 @@ jobs:
- uses: actions/checkout@v3
- name: Check the release tag starts with `nym-connect-`
if: startsWith(github.ref, 'refs/tags/nym-connect-') == false && github.event_name != 'workflow_dispatch'
uses: actions/github-script@v3
with:
script: |
core.setFailed('Release tag did not start with nym-connect-...')
- name: Import signing certificate
env:
WINDOWS_CERTIFICATE: ${{ secrets.WINDOWS_CERTIFICATE }}
+1
View File
@@ -16,6 +16,7 @@ jobs:
- uses: actions/checkout@v2
- name: Install rsync
run: sudo apt-get install rsync
continue-on-error: true
- uses: rlespinasse/github-slug-action@v3.x
- uses: actions/setup-node@v3
with:
+7 -10
View File
@@ -16,10 +16,11 @@ env:
jobs:
publish-nym:
if: ${{ startsWith(github.ref, 'refs/tags/nym-binaries-') && github.event_name == 'release' }}
strategy:
fail-fast: false
matrix:
platform: [ubuntu-20.04]
platform: [custom-runner-linux]
runs-on: ${{ matrix.platform }}
steps:
@@ -27,13 +28,7 @@ jobs:
- name: Install Dependencies (Linux)
run: sudo apt-get update && sudo apt-get -y install libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev libudev-dev squashfs-tools
- name: Check the release tag starts with `nym-binaries-`
if: startsWith(github.ref, 'refs/tags/nym-binaries-') == false && github.event_name != 'workflow_dispatch'
uses: actions/github-script@v3
with:
script: |
core.setFailed('Release tag did not start with nym-binaries-...')
continue-on-error: true
- name: Sets env vars for tokio if set in manual dispatch inputs
run: |
@@ -56,11 +51,12 @@ jobs:
with:
name: my-artifact
path: |
target/release/explorer-api
target/release/nym-client
target/release/nym-gateway
target/release/nym-mixnode
target/release/nym-socks5-client
target/release/nym-validator-api
target/release/nym-api
target/release/nym-network-requester
target/release/nym-network-statistics
target/release/nym-cli
@@ -71,11 +67,12 @@ jobs:
if: github.event_name == 'release'
with:
files: |
target/release/explorer-api
target/release/nym-client
target/release/nym-gateway
target/release/nym-mixnode
target/release/nym-socks5-client
target/release/nym-validator-api
target/release/nym-api
target/release/nym-network-requester
target/release/nym-network-statistics
target/release/nym-cli
@@ -10,6 +10,7 @@ defaults:
jobs:
publish-tauri:
if: ${{ startsWith(github.ref, 'refs/tags/nym-wallet-') && github.event_name == 'release' }}
strategy:
fail-fast: false
matrix:
@@ -19,13 +20,6 @@ jobs:
steps:
- uses: actions/checkout@v2
- name: Check the release tag starts with `nym-wallet-`
if: startsWith(github.ref, 'refs/tags/nym-wallet-') == false && github.event_name != 'workflow_dispatch'
uses: actions/github-script@v3
with:
script: |
core.setFailed('Release tag did not start with nym-wallet-...')
- name: Node v16
uses: actions/setup-node@v3
with:
@@ -9,10 +9,11 @@ defaults:
jobs:
publish-tauri:
if: ${{ startsWith(github.ref, 'refs/tags/nym-wallet-') && github.event_name == 'release' }}
strategy:
fail-fast: false
matrix:
platform: [ubuntu-20.04]
platform: [custom-runner-linux]
runs-on: ${{ matrix.platform }}
steps:
@@ -22,17 +23,13 @@ jobs:
run: >
sudo apt-get update &&
sudo apt-get install -y webkit2gtk-4.0
- name: Check the release tag starts with `nym-wallet-`
if: startsWith(github.ref, 'refs/tags/nym-wallet-') == false
uses: actions/github-script@v3
with:
script: |
core.setFailed('Release tag did not start with nym-wallet-...')
continue-on-error: true
- name: Node v16
uses: actions/setup-node@v3
with:
node-version: 16
- name: Install Rust stable
uses: actions-rs/toolchain@v1
with:
@@ -9,6 +9,7 @@ defaults:
jobs:
publish-tauri:
if: ${{ startsWith(github.ref, 'refs/tags/nym-wallet-') && github.event_name == 'release' }}
strategy:
fail-fast: false
matrix:
@@ -26,13 +27,6 @@ jobs:
- uses: actions/checkout@v3
- name: Check the release tag starts with `nym-wallet-`
if: startsWith(github.ref, 'refs/tags/nym-wallet-') == false
uses: actions/github-script@v3
with:
script: |
core.setFailed('Release tag did not start with nym-wallet-...')
- name: Import signing certificate
env:
WINDOWS_CERTIFICATE: ${{ secrets.WINDOWS_CERTIFICATE }}
@@ -12,6 +12,7 @@ jobs:
- uses: actions/checkout@v2
- name: Install rsync
run: sudo apt-get install rsync
continue-on-error: true
- uses: rlespinasse/github-slug-action@v3.x
- uses: actions/setup-node@v3
with:
+1
View File
@@ -26,6 +26,7 @@ jobs:
libappindicator3-dev
webkit2gtk-driver
xvfb
continue-on-error: true
- name: Install minimal stable
uses: actions-rs/toolchain@v1
+51
View File
@@ -0,0 +1,51 @@
name: CI for linting Typescript
on:
push:
paths:
- 'ts-packages/**'
- 'sdk/typescript/**'
- nym-connect
- nym-connect-android
- nym-wallet
jobs:
build:
runs-on: custom-runner-linux
steps:
- uses: actions/checkout@v2
- name: Install rsync
run: sudo apt-get install rsync
continue-on-error: true
- uses: rlespinasse/github-slug-action@v3.x
- uses: actions/setup-node@v3
with:
node-version: 16
- name: Setup yarn
run: npm install -g yarn
- name: Lint
run: yarn && yarn lint && yarn tsc
- name: Keybase - Node Install
run: npm install
working-directory: .github/workflows/support-files
- name: Keybase - Send Notification
env:
NYM_NOTIFICATION_KIND: ts-packages
NYM_PROJECT_NAME: "ts-packages"
NYM_CI_WWW_BASE: "${{ secrets.NYM_CI_WWW_BASE }}"
NYM_CI_WWW_LOCATION: "ts-${{ env.GITHUB_REF_SLUG }}"
GIT_COMMIT_MESSAGE: "${{ github.event.head_commit.message }}"
GIT_BRANCH: "${GITHUB_REF##*/}"
KEYBASE_NYMBOT_USERNAME: "${{ secrets.KEYBASE_NYMBOT_USERNAME }}"
KEYBASE_NYMBOT_PAPERKEY: "${{ secrets.KEYBASE_NYMBOT_PAPERKEY }}"
KEYBASE_NYMBOT_TEAM: "${{ secrets.KEYBASE_NYMBOT_TEAM }}"
KEYBASE_NYM_CHANNEL: "ci-ts-packages"
IS_SUCCESS: "${{ job.status == 'success' }}"
MATRIX_SERVER: "${{ secrets.MATRIX_SERVER }}"
MATRIX_ROOM: "${{ secrets.MATRIX_ROOM }}"
MATRIX_USER_ID: "${{ secrets.MATRIX_USER_ID }}"
MATRIX_TOKEN: "${{ secrets.MATRIX_TOKEN }}"
MATRIX_DEVICE_ID: "${{ secrets.MATRIX_DEVICE_ID }}"
uses: docker://keybaseio/client:stable-node
with:
args: .github/workflows/support-files/notifications/entry_point.sh
+12 -4
View File
@@ -2,11 +2,17 @@ name: Nym Wallet (rust)
on:
push:
paths-ignore:
- 'explorer/**'
paths:
- 'nym-wallet/**'
- 'common/**'
- 'contracts/vesting/**'
- 'nym-api/nym-api-requests/**'
pull_request:
paths-ignore:
- 'explorer/**'
paths:
- 'nym-wallet/**'
- 'common/**'
- 'contracts/vesting/**'
- 'nym-api/nym-api-requests/**'
jobs:
build:
@@ -16,6 +22,7 @@ jobs:
steps:
- name: Install Dependencies (Linux)
run: sudo apt-get update && sudo apt-get -y install libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev squashfs-tools
continue-on-error: true
- name: Check out repository code
uses: actions/checkout@v2
@@ -48,6 +55,7 @@ jobs:
- uses: actions-rs/clippy-check@v1
name: Clippy checks
continue-on-error: true
with:
token: ${{ secrets.GITHUB_TOKEN }}
args: --manifest-path nym-wallet/Cargo.toml --workspace --all-features
+7 -12
View File
@@ -2,8 +2,13 @@ name: Wasm Client
on:
pull_request:
paths-ignore:
- 'explorer/**'
paths:
- 'clients/webassembly/**'
- 'clients/client-core/**'
- 'common/**'
- 'contracts/**'
- 'gateway/gateway-requests/**'
- 'nym-api/nym-api-requests/**'
jobs:
wasm:
@@ -24,16 +29,6 @@ jobs:
command: build
args: --manifest-path clients/webassembly/Cargo.toml --target wasm32-unknown-unknown
- uses: actions-rs/cargo@v1
with:
command: build
args: --manifest-path clients/webassembly/Cargo.toml --target wasm32-unknown-unknown --features=coconut
- uses: actions-rs/cargo@v1
with:
command: test
args: --manifest-path clients/webassembly/Cargo.toml
- uses: actions-rs/cargo@v1
with:
command: fmt
+2
View File
@@ -41,3 +41,5 @@ storybook-static
envs/qwerty.env
Cargo.lock
nym-connect/Cargo.lock
.parcel-cache
.DS_Store
+72 -3
View File
@@ -2,26 +2,95 @@
Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
# [Unreleased]
### Added
- remove coconut feature and unify builds ([#2890])
- native-client: is now capable of listening for requests on sockets different than `127.0.0.1` ([#2939]). This can be specified via `--host` flag during `init` or `run`. Alternatively a custom `host` can be set in `config.toml` file under `socket` section.
[#2890]: https://github.com/nymtech/nym/pull/2890
[#2939]: https://github.com/nymtech/nym/pull/2939
# [v1.1.8] (2023-01-31)
### Added
- Rust SDK - Support SURBS (anonymous send + storage) ([#2754])
- dkg rerun from scratch and dkg-specific epochs ([#2810])
- Rename `'initial_supply'` field to `'total_supply'` in the circulating supply endpoint ([#2931])
- Circulating supply api endpoint (read the note inside before testing/deploying) ([#1902])
### Changed
- nym-api: an `--id` flag is now always explicitly required ([#2873])
[#2754]: https://github.com/nymtech/nym/issues/2754
[#2810]: https://github.com/nymtech/nym/issues/2810
[#2931]: https://github.com/nymtech/nym/issues/2931
[#1902]: https://github.com/nymtech/nym/issues/1902
[#2873]: https://github.com/nymtech/nym/issues/2873
# [v1.1.7] (2023-01-24)
### Added
- Gateways now shut down gracefully ([#2019]).
- Rust SDK - Initial version for nym-client ([#2669]).
- Introduce vesting contract query for addresses of all vesting accounts (required for the circulating supply calculation) ([#2778]).
- Add threshold value to the contract storage ([#1893])
### Changed
- Refactor vesting account storage (and in particular, ACCOUNTS saving) ([#2795]).
- Move from manual advancing DKG state to an automatic process ([#2670]).
### Fixed
- Gateways now shut down gracefully ([#2019]).
[#2019]: https://github.com/nymtech/nym/issues/2019
[#2669]: https://github.com/nymtech/nym/issues/2669
[#2795]: https://github.com/nymtech/nym/issues/2795
[#2778]: https://github.com/nymtech/nym/issues/2778
[#2670]: https://github.com/nymtech/nym/issues/2670
[#1893]: https://github.com/nymtech/nym/issues/1893
## [v1.1.6] (2023-01-17)
### Added
- nym-sdk: added initial version of a Rust client sdk
- nym-api: added `/circulating-supply` endpoint ([#2814])
- nym-api: add endpoint listing detailed gateway info by @octol in https://github.com/nymtech/nym/pull/2833
### Changed
- streamline override_config functions -> there's a lot of duplicate if statements everywhere ([#2774])
- clean-up nym-api startup arguments/flags to use clap 3 and its macro-derived arguments ([#2772])
- renamed all references to validator_api to nym_api
- renamed all references to nymd to nyxd
- renamed all references to nymd to nyxd ([#2696])
- all-binaries: standarised argument names (note: old names should still be accepted) ([#2762]
### Fixed
- nym-api: should now correctly use `rewarding.enabled` config flag ([#2753])
[#2696]: https://github.com/nymtech/nym/pull/2696
[#2753]: https://github.com/nymtech/nym/pull/2753
[#2762]: https://github.com/nymtech/nym/pull/2762
[#2814]: https://github.com/nymtech/nym/pull/2814
[#2772]: https://github.com/nymtech/nym/pull/2772
[#2774]: https://github.com/nymtech/nym/pull/2774
## [v1.1.5] (2022-01-10)
## [v1.1.5] (2023-01-10)
### Added
### Changed
## [v1.1.5] (2023-01-10)
### Added
Generated
+1050 -855
View File
File diff suppressed because it is too large Load Diff
+12 -1
View File
@@ -34,9 +34,11 @@ members = [
"common/cosmwasm-smart-contracts/coconut-bandwidth-contract",
"common/cosmwasm-smart-contracts/coconut-dkg",
"common/cosmwasm-smart-contracts/contracts-common",
"common/cosmwasm-smart-contracts/group-contract",
"common/cosmwasm-smart-contracts/mixnet-contract",
"common/cosmwasm-smart-contracts/multisig-contract",
"common/cosmwasm-smart-contracts/vesting-contract",
"common/mobile-storage",
"common/credential-storage",
"common/credentials",
"common/crypto",
@@ -94,4 +96,13 @@ default-members = [
"explorer-api",
]
exclude = ["explorer", "contracts", "clients/webassembly", "nym-wallet", "nym-connect"]
exclude = ["explorer", "contracts", "clients/webassembly", "nym-wallet", "nym-connect", "nym-connect-android"]
[workspace.package]
authors = ["Nym Technologies SA"]
repository = "https://github.com/nymtech/nym"
homepage = "https://nymtech.net"
edition = "2021"
[workspace.dependencies]
log = "0.4"
+6 -16
View File
@@ -2,10 +2,10 @@ test: clippy-all cargo-test wasm fmt
test-all: test cargo-test-expensive
no-clippy: build cargo-test wasm fmt
happy: fmt clippy-happy test
clippy-all: clippy-main clippy-coconut clippy-all-contracts clippy-all-wallet clippy-all-connect clippy-all-wasm-client
clippy-all: clippy-main clippy-all-contracts clippy-all-wallet clippy-all-connect clippy-all-wasm-client
clippy-happy: clippy-happy-main clippy-happy-contracts clippy-happy-wallet clippy-happy-connect
cargo-test: test-main test-contracts test-wallet test-connect test-coconut test-wasm-client
cargo-test-expensive: test-main-expensive test-contracts-expensive test-wallet-expensive test-connect-expensive test-coconut-expensive
cargo-test: test-main test-contracts test-wallet test-connect
cargo-test-expensive: test-main-expensive test-contracts-expensive test-wallet-expensive test-connect-expensive
build: build-contracts build-wallet build-main build-connect build-wasm-client
fmt: fmt-main fmt-contracts fmt-wallet fmt-connect fmt-wasm-client
@@ -24,9 +24,6 @@ clippy-happy-connect:
clippy-main:
cargo clippy --workspace -- -D warnings
clippy-coconut:
cargo clippy --workspace --features coconut -- -D warnings
clippy-wasm:
cargo clippy --manifest-path clients/webassembly/Cargo.toml --target wasm32-unknown-unknown --workspace -- -D warnings
@@ -46,16 +43,9 @@ clippy-all-wasm-client:
test-main:
cargo test --workspace
test-coconut:
cargo test --workspace --features coconut
test-main-expensive:
cargo test --workspace -- --ignored
test-coconut-expensive:
cargo test --workspace --features coconut -- --ignored
test-contracts:
cargo test --manifest-path contracts/Cargo.toml --all-features
@@ -68,9 +58,6 @@ test-wallet:
test-wallet-expensive:
cargo test --manifest-path nym-wallet/Cargo.toml --all-features -- --ignored
test-wasm-client:
cargo test --workspace --manifest-path clients/webassembly/Cargo.toml --all-features
test-connect:
cargo test --manifest-path nym-connect/Cargo.toml --all-features
@@ -122,3 +109,6 @@ mixnet-opt: wasm
generate-typescript:
cd tools/ts-rs-cli && cargo run && cd ../..
yarn types:lint:fix
run-validator-tests:
cd nym-api/tests/functional_test && yarn test:qa
BIN
View File
Binary file not shown.
+6 -7
View File
@@ -1,6 +1,6 @@
[package]
name = "client-core"
version = "1.1.5"
version = "1.1.8"
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"]
edition = "2021"
rust-version = "1.66"
@@ -13,14 +13,14 @@ dirs = "4.0"
dashmap = "5.4.0"
futures = "0.3"
humantime-serde = "1.0"
log = "0.4"
log = { workspace = true }
rand = { version = "0.7.3", features = ["wasm-bindgen"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0.89"
tap = "1.0.1"
thiserror = "1.0.34"
url = { version ="2.2", features = ["serde"] }
tokio = { version = "1.21.2", features = ["macros"]}
tokio = { version = "1.24.1", features = ["macros"]}
time = "0.3.17"
# internal
@@ -38,11 +38,11 @@ validator-client = { path = "../../common/client-libs/validator-client", default
task = { path = "../../common/task" }
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.tokio-stream]
version = "0.1.9"
version = "0.1.11"
features = ["time"]
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.tokio]
version = "1.21.2"
version = "1.24.1"
features = ["time"]
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.sqlx]
@@ -75,12 +75,11 @@ features = ["wasm-bindgen"]
tempfile = "3.1.0"
[build-dependencies]
tokio = { version = "1.21.2", features = ["rt-multi-thread", "macros"] }
tokio = { version = "1.24.1", features = ["rt-multi-thread", "macros"] }
sqlx = { version = "0.6.2", features = ["runtime-tokio-rustls", "sqlite", "macros", "migrate"] }
[features]
default = []
fs-surb-storage = ["sqlx"]
wasm = ["gateway-client/wasm"]
coconut = ["gateway-client/coconut", "gateway-requests/coconut"]
+2 -2
View File
@@ -9,9 +9,9 @@ async fn main() {
use std::env;
let out_dir = env::var("OUT_DIR").unwrap();
let database_path = format!("{}/fs-surbs-example.sqlite", out_dir);
let database_path = format!("{out_dir}/fs-surbs-example.sqlite");
let mut conn = SqliteConnection::connect(&format!("sqlite://{}?mode=rwc", database_path))
let mut conn = SqliteConnection::connect(&format!("sqlite://{database_path}?mode=rwc"))
.await
.expect("Failed to create SQLx database connection");
@@ -0,0 +1,11 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
//
use crate::{client::replies::reply_storage, config::DebugConfig};
pub fn setup_empty_reply_surb_backend(debug_config: &DebugConfig) -> reply_storage::Empty {
reply_storage::Empty {
min_surb_threshold: debug_config.minimum_reply_surb_storage_threshold,
max_surb_threshold: debug_config.maximum_reply_surb_storage_threshold,
}
}
@@ -25,6 +25,8 @@ use client_connections::{ConnectionCommandReceiver, ConnectionCommandSender, Lan
use crypto::asymmetric::{encryption, identity};
use futures::channel::mpsc;
use gateway_client::bandwidth::BandwidthController;
#[cfg(target_arch = "wasm32")]
use gateway_client::wasm_mockups::CosmWasmClient;
use gateway_client::{
AcknowledgementReceiver, AcknowledgementSender, GatewayClient, MixnetMessageReceiver,
MixnetMessageSender,
@@ -39,12 +41,16 @@ use std::time::Duration;
use tap::TapFallible;
use task::{TaskClient, TaskManager};
use url::Url;
#[cfg(not(target_arch = "wasm32"))]
use validator_client::nyxd::CosmWasmClient;
use super::received_buffer::ReceivedBufferMessage;
#[cfg(all(not(target_arch = "wasm32"), feature = "fs-surb-storage"))]
pub mod non_wasm_helpers;
pub mod helpers;
pub struct ClientInput {
pub connection_command_sender: ConnectionCommandSender,
pub input_sender: InputMessageSender,
@@ -129,7 +135,7 @@ impl From<bool> for CredentialsToggle {
}
}
pub struct BaseClientBuilder<'a, B> {
pub struct BaseClientBuilder<'a, B, C: Clone> {
// due to wasm limitations I had to split it like this : (
gateway_config: &'a GatewayEndpointConfig,
debug_config: &'a DebugConfig,
@@ -137,20 +143,21 @@ pub struct BaseClientBuilder<'a, B> {
nym_api_endpoints: Vec<Url>,
reply_storage_backend: B,
bandwidth_controller: Option<BandwidthController>,
bandwidth_controller: Option<BandwidthController<C>>,
key_manager: KeyManager,
}
impl<'a, B> BaseClientBuilder<'a, B>
impl<'a, B, C> BaseClientBuilder<'a, B, C>
where
B: ReplyStorageBackend + Send + Sync + 'static,
C: CosmWasmClient + Sync + Send + Clone + 'static,
{
pub fn new_from_base_config<T>(
base_config: &'a Config<T>,
key_manager: KeyManager,
bandwidth_controller: Option<BandwidthController>,
bandwidth_controller: Option<BandwidthController<C>>,
reply_storage_backend: B,
) -> BaseClientBuilder<'a, B> {
) -> BaseClientBuilder<'a, B, C> {
BaseClientBuilder {
gateway_config: base_config.get_gateway_endpoint_config(),
debug_config: base_config.get_debug_config(),
@@ -166,11 +173,11 @@ where
gateway_config: &'a GatewayEndpointConfig,
debug_config: &'a DebugConfig,
key_manager: KeyManager,
bandwidth_controller: Option<BandwidthController>,
bandwidth_controller: Option<BandwidthController<C>>,
reply_storage_backend: B,
credentials_toggle: CredentialsToggle,
nym_api_endpoints: Vec<Url>,
) -> BaseClientBuilder<'a, B> {
) -> BaseClientBuilder<'a, B, C> {
BaseClientBuilder {
gateway_config,
debug_config,
@@ -279,15 +286,11 @@ where
mixnet_message_sender: MixnetMessageSender,
ack_sender: AcknowledgementSender,
shutdown: TaskClient,
) -> Result<GatewayClient, ClientCoreError> {
) -> Result<GatewayClient<C>, ClientCoreError> {
let gateway_id = self.gateway_config.gateway_id.clone();
if gateway_id.is_empty() {
return Err(ClientCoreError::GatewayIdUnknown);
}
let gateway_owner = self.gateway_config.gateway_owner.clone();
if gateway_owner.is_empty() {
return Err(ClientCoreError::GatewayOwnerUnknown);
}
let gateway_address = self.gateway_config.gateway_listener.clone();
if gateway_address.is_empty() {
return Err(ClientCoreError::GatwayAddressUnknown);
@@ -307,7 +310,6 @@ where
gateway_address,
self.key_manager.identity_keypair(),
gateway_identity,
gateway_owner,
shared_key,
mixnet_message_sender,
ack_sender,
@@ -365,7 +367,7 @@ where
// over it. Perhaps GatewayClient needs to be thread-shareable or have some channel for
// requests?
fn start_mix_traffic_controller(
gateway_client: GatewayClient,
gateway_client: GatewayClient<C>,
shutdown: TaskClient,
) -> BatchMixMessageSender {
info!("Starting mix traffic controller...");
@@ -381,22 +383,32 @@ where
where
<B as ReplyStorageBackend>::StorageError: Sync + Send,
{
let persistent_storage = PersistentReplyStorage::new(backend);
let mem_store = persistent_storage
.load_state_from_backend()
.await
.map_err(|err| ClientCoreError::SurbStorageError {
source: Box::new(err),
})?;
let store_clone = mem_store.clone();
spawn_future(async move {
persistent_storage
.flush_on_shutdown(store_clone, shutdown)
if backend.is_active() {
log::trace!("Setup persistent reply storage");
let persistent_storage = PersistentReplyStorage::new(backend);
let mem_store = persistent_storage
.load_state_from_backend()
.await
});
.map_err(|err| ClientCoreError::SurbStorageError {
source: Box::new(err),
})?;
Ok(mem_store)
let store_clone = mem_store.clone();
spawn_future(async move {
persistent_storage
.flush_on_shutdown(store_clone, shutdown)
.await
});
Ok(mem_store)
} else {
log::trace!("Setup inactive reply storage");
Ok(backend
.get_inactive_storage()
.map_err(|err| ClientCoreError::SurbStorageError {
source: Box::new(err),
})?)
}
}
pub async fn start_base(mut self) -> Result<BaseClient, ClientCoreError>
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
use crate::client::replies::reply_storage::{
self, fs_backend, CombinedReplyStorage, ReplyStorageBackend,
fs_backend, CombinedReplyStorage, ReplyStorageBackend,
};
use crate::config::DebugConfig;
use crate::error::ClientCoreError;
@@ -43,6 +43,14 @@ async fn setup_fresh_backend<P: AsRef<Path>>(
Ok(storage_backend)
}
fn setup_inactive_backend(debug_config: &DebugConfig) -> fs_backend::Backend {
info!("creating inactive surb database");
fs_backend::Backend::new_inactive(
debug_config.minimum_reply_surb_storage_threshold,
debug_config.maximum_reply_surb_storage_threshold,
)
}
fn archive_corrupted_database<P: AsRef<Path>>(db_path: P) -> io::Result<()> {
let db_path = db_path.as_ref();
debug_assert!(db_path.exists());
@@ -53,7 +61,7 @@ fn archive_corrupted_database<P: AsRef<Path>>(db_path: P) -> io::Result<()> {
let new_extension =
if let Some(existing_extension) = db_path.extension().and_then(|ext| ext.to_str()) {
format!("{existing_extension}.{}", suffix)
format!("{existing_extension}.{suffix}")
} else {
suffix
};
@@ -65,30 +73,28 @@ fn archive_corrupted_database<P: AsRef<Path>>(db_path: P) -> io::Result<()> {
}
pub async fn setup_fs_reply_surb_backend<P: AsRef<Path>>(
db_path: P,
db_path: Option<P>,
debug_config: &DebugConfig,
) -> Result<fs_backend::Backend, ClientCoreError> {
// if the database file doesnt exist, initialise fresh storage, otherwise attempt to load the existing one
let db_path = db_path.as_ref();
if db_path.exists() {
info!("loading existing surb database");
match fs_backend::Backend::try_load(db_path).await {
Ok(backend) => Ok(backend),
Err(err) => {
error!("failed to setup persistent storage backend for our reply needs: {err}. We're going to create a fresh database instead. This behaviour might change in the future");
if let Some(db_path) = db_path {
// if the database file doesnt exist, initialise fresh storage, otherwise attempt to load
// the existing one
let db_path = db_path.as_ref();
if db_path.exists() {
info!("loading existing surb database");
match fs_backend::Backend::try_load(db_path).await {
Ok(backend) => Ok(backend),
Err(err) => {
error!("failed to setup persistent storage backend for our reply needs: {err}. We're going to create a fresh database instead. This behaviour might change in the future");
archive_corrupted_database(db_path)?;
setup_fresh_backend(db_path, debug_config).await
archive_corrupted_database(db_path)?;
setup_fresh_backend(db_path, debug_config).await
}
}
} else {
setup_fresh_backend(db_path, debug_config).await
}
} else {
setup_fresh_backend(db_path, debug_config).await
}
}
pub fn setup_empty_reply_surb_backend(debug_config: &DebugConfig) -> reply_storage::Empty {
reply_storage::Empty {
min_surb_threshold: debug_config.minimum_reply_surb_storage_threshold,
max_surb_threshold: debug_config.maximum_reply_surb_storage_threshold,
Ok(setup_inactive_backend(debug_config))
}
}
@@ -42,9 +42,6 @@ pub struct KeyManager {
*/
impl KeyManager {
// this is actually **NOT** dead code
// I have absolutely no idea why the compiler insists it's unused. The call happens during client::init::execute
#[allow(dead_code)]
/// Creates new instance of a [`KeyManager`]
pub fn new<R>(rng: &mut R) -> Self
where
@@ -130,9 +127,6 @@ impl KeyManager {
Ok(key_manager)
}
// this is actually **NOT** dead code
// I have absolutely no idea why the compiler insists it's unused. The call happens during client::init::execute
#[allow(dead_code)]
/// Stores all available keys on the disk.
// While perhaps there is no much point in storing the `AckKey` on the disk,
// it is done so for the consistency sake so that you wouldn't require an rng instance
@@ -211,9 +205,6 @@ impl KeyManager {
Arc::clone(&self.ack_key)
}
// this is actually **NOT** dead code
// I have absolutely no idea why the compiler insists it's unused. The call happens during client::init::execute
#[allow(dead_code)]
/// After shared key with the gateway is derived, puts its ownership to this instance of a [`KeyManager`].
pub fn insert_gateway_shared_key(&mut self, gateway_shared_key: Arc<SharedKeys>) {
self.gateway_shared_key = Some(gateway_shared_key)
+14 -5
View File
@@ -2,9 +2,13 @@
// SPDX-License-Identifier: Apache-2.0
use crate::spawn_future;
#[cfg(target_arch = "wasm32")]
use gateway_client::wasm_mockups::CosmWasmClient;
use gateway_client::GatewayClient;
use log::*;
use nymsphinx::forwarding::packet::MixPacket;
#[cfg(not(target_arch = "wasm32"))]
use validator_client::nyxd::CosmWasmClient;
pub type BatchMixMessageSender = tokio::sync::mpsc::Sender<Vec<MixPacket>>;
pub type BatchMixMessageReceiver = tokio::sync::mpsc::Receiver<Vec<MixPacket>>;
@@ -13,10 +17,10 @@ pub type BatchMixMessageReceiver = tokio::sync::mpsc::Receiver<Vec<MixPacket>>;
pub const MIX_MESSAGE_RECEIVER_BUFFER_SIZE: usize = 32;
const MAX_FAILURE_COUNT: usize = 100;
pub struct MixTrafficController {
pub struct MixTrafficController<C: Clone> {
// TODO: most likely to be replaced by some higher level construct as
// later on gateway_client will need to be accessible by other entities
gateway_client: GatewayClient,
gateway_client: GatewayClient<C>,
mix_rx: BatchMixMessageReceiver,
// TODO: this is temporary work-around.
@@ -24,8 +28,13 @@ pub struct MixTrafficController {
consecutive_gateway_failure_count: usize,
}
impl MixTrafficController {
pub fn new(gateway_client: GatewayClient) -> (MixTrafficController, BatchMixMessageSender) {
impl<C> MixTrafficController<C>
where
C: CosmWasmClient + Sync + Send + Clone + 'static,
{
pub fn new(
gateway_client: GatewayClient<C>,
) -> (MixTrafficController<C>, BatchMixMessageSender) {
let (sphinx_message_sender, sphinx_message_receiver) =
tokio::sync::mpsc::channel(MIX_MESSAGE_RECEIVER_BUFFER_SIZE);
(
@@ -57,7 +66,7 @@ impl MixTrafficController {
if self.consecutive_gateway_failure_count == MAX_FAILURE_COUNT {
// todo: in the future this should initiate a 'graceful' shutdown or try
// to reconnect?
panic!("failed to send sphinx packet to the gateway {} times in a row - assuming the gateway is dead. Can't do anything about it yet :(", MAX_FAILURE_COUNT)
panic!("failed to send sphinx packet to the gateway {MAX_FAILURE_COUNT} times in a row - assuming the gateway is dead. Can't do anything about it yet :(")
}
}
Ok(_) => {
@@ -81,7 +81,11 @@ pub struct Config {
/// Defines maximum amount of time the client is going to wait for reply surbs before explicitly asking
/// for more even though in theory they wouldn't need to.
maximum_reply_surb_waiting_period: Duration,
maximum_reply_surb_rerequest_waiting_period: Duration,
/// Defines maximum amount of time the client is going to wait for reply surbs before
/// deciding it's never going to get them and would drop all pending messages
maximum_reply_surb_drop_waiting_period: Duration,
/// Defines maximum amount of time given reply surb is going to be valid for.
/// This is going to be superseded by key rotation once implemented.
@@ -119,7 +123,8 @@ impl<'a> From<&'a Config> for reply_controller::Config {
cfg.minimum_reply_surb_request_size,
cfg.maximum_reply_surb_request_size,
cfg.maximum_allowed_reply_surb_request_size,
cfg.maximum_reply_surb_waiting_period,
cfg.maximum_reply_surb_rerequest_waiting_period,
cfg.maximum_reply_surb_drop_waiting_period,
cfg.maximum_reply_surb_age,
cfg.maximum_reply_key_age,
)
@@ -161,8 +166,10 @@ impl Config {
.maximum_reply_surb_request_size,
maximum_allowed_reply_surb_request_size: base_client_debug_config
.maximum_allowed_reply_surb_request_size,
maximum_reply_surb_waiting_period: base_client_debug_config
.maximum_reply_surb_waiting_period,
maximum_reply_surb_rerequest_waiting_period: base_client_debug_config
.maximum_reply_surb_rerequest_waiting_period,
maximum_reply_surb_drop_waiting_period: base_client_debug_config
.maximum_reply_surb_drop_waiting_period,
maximum_reply_surb_age: base_client_debug_config.maximum_reply_surb_age,
maximum_reply_key_age: base_client_debug_config.maximum_reply_key_age,
}
@@ -471,14 +471,10 @@ where
let mult = self.sending_delay_controller.current_multiplier();
let delay = self.current_average_message_sending_delay().as_millis();
let status_str = if self.config.disable_poisson_packet_distribution {
format!(
"Status: {lanes} lanes, backlog: {:.2} kiB ({packets}), no delay",
backlog
)
format!("Status: {lanes} lanes, backlog: {backlog:.2} kiB ({packets}), no delay")
} else {
format!(
"Status: {lanes} lanes, backlog: {:.2} kiB ({packets}), avg delay: {}ms ({mult})",
backlog, delay
"Status: {lanes} lanes, backlog: {backlog:.2} kiB ({packets}), avg delay: {delay}ms ({mult})"
)
};
if packets > 1000 {
@@ -30,7 +30,8 @@ pub struct Config {
min_surb_request_size: u32,
max_surb_request_size: u32,
maximum_allowed_reply_surb_request_size: u32,
max_surb_waiting_period: Duration,
max_surb_rerequest_waiting_period: Duration,
max_surb_drop_waiting_period: Duration,
max_reply_surb_age: Duration,
max_reply_key_age: Duration,
}
@@ -40,7 +41,8 @@ impl Config {
min_surb_request_size: u32,
max_surb_request_size: u32,
maximum_allowed_reply_surb_request_size: u32,
max_surb_waiting_period: Duration,
max_surb_rerequest_waiting_period: Duration,
max_surb_drop_waiting_period: Duration,
max_reply_surb_age: Duration,
max_reply_key_age: Duration,
) -> Self {
@@ -48,7 +50,8 @@ impl Config {
min_surb_request_size,
max_surb_request_size,
maximum_allowed_reply_surb_request_size,
max_surb_waiting_period,
max_surb_rerequest_waiting_period,
max_surb_drop_waiting_period,
max_reply_surb_age,
max_reply_key_age,
}
@@ -742,9 +745,13 @@ where
let diff = now - last_received_time;
if diff > self.config.max_surb_waiting_period {
warn!("We haven't received any surbs in {:?} from {pending_reply_target}. Going to explicitly ask for more", diff);
to_request.push(*pending_reply_target);
if diff > self.config.max_surb_rerequest_waiting_period {
if diff > self.config.max_surb_drop_waiting_period {
to_remove.push(*pending_reply_target)
} else {
debug!("We haven't received any surbs in {:?} from {pending_reply_target}. Going to explicitly ask for more", diff);
to_request.push(*pending_reply_target);
}
}
}
@@ -41,4 +41,8 @@ impl ReplyStorageBackend for Backend {
async fn load_surb_storage(&self) -> Result<CombinedReplyStorage, Self::StorageError> {
self.empty.load_surb_storage().await
}
fn get_inactive_storage(&self) -> Result<CombinedReplyStorage, Self::StorageError> {
self.empty.get_inactive_storage()
}
}
@@ -10,6 +10,12 @@ pub enum StorageError {
#[error("the provided database path doesn't have a filename defined")]
DatabasePathWithoutFilename { provided_path: PathBuf },
#[error("unable to create the directory for the database")]
DatabasePathUnableToCreateParentDirectory {
provided_path: PathBuf,
source: io::Error,
},
#[error("failed to rename our databse file - {source}")]
DatabaseRenameError {
#[source]
@@ -20,6 +20,16 @@ impl StorageManager {
database_path: P,
fresh: bool,
) -> Result<Self, StorageError> {
// ensure the whole directory structure exists
if let Some(parent_dir) = database_path.as_ref().parent() {
std::fs::create_dir_all(parent_dir).map_err(|source| {
StorageError::DatabasePathUnableToCreateParentDirectory {
provided_path: database_path.as_ref().to_path_buf(),
source,
}
})?;
}
let mut opts = sqlx::sqlite::SqliteConnectOptions::new()
.filename(database_path)
.create_if_missing(fresh);
@@ -22,11 +22,49 @@ mod error;
mod manager;
mod models;
#[derive(Debug)]
enum StorageManagerState {
Storage(StorageManager),
Inactive(InactiveMetadata),
}
// When the storage backaed is initialized as inactive, it will still contain metadata parameters
// that will be needed when the in-mem storage is fetched for use.
#[derive(Debug)]
struct InactiveMetadata {
pub minimum_reply_surb_storage_threshold: usize,
pub maximum_reply_surb_storage_threshold: usize,
}
impl StorageManagerState {
fn get(&self) -> &StorageManager {
match self {
StorageManagerState::Storage(manager) => manager,
StorageManagerState::Inactive(_) => {
panic!("tried to get storage of an inactive backend")
}
}
}
fn get_mut(&mut self) -> &mut StorageManager {
match self {
StorageManagerState::Storage(manager) => manager,
StorageManagerState::Inactive(_) => {
panic!("tried to get storage of an inactive backend")
}
}
}
fn is_active(&self) -> bool {
matches!(self, StorageManagerState::Storage(_))
}
}
#[derive(Debug)]
pub struct Backend {
temporary_old_path: Option<PathBuf>,
database_path: PathBuf,
manager: StorageManager,
manager: StorageManagerState,
}
impl Backend {
@@ -40,17 +78,32 @@ impl Backend {
});
}
let manager = StorageManager::init(database_path, true).await?;
manager.create_status_table().await?;
let backend = Backend {
temporary_old_path: None,
database_path: owned_path,
manager: StorageManager::init(database_path, true).await?,
manager: StorageManagerState::Storage(manager),
};
backend.manager.create_status_table().await?;
Ok(backend)
}
pub fn new_inactive(
minimum_reply_surb_storage_threshold: usize,
maximum_reply_surb_storage_threshold: usize,
) -> Self {
Backend {
temporary_old_path: None,
database_path: PathBuf::new(),
manager: StorageManagerState::Inactive(InactiveMetadata {
minimum_reply_surb_storage_threshold,
maximum_reply_surb_storage_threshold,
}),
}
}
pub async fn try_load<P: AsRef<Path>>(database_path: P) -> Result<Self, StorageError> {
let owned_path: PathBuf = database_path.as_ref().into();
if owned_path.file_name().is_none() {
@@ -119,12 +172,12 @@ impl Backend {
Ok(Backend {
temporary_old_path: None,
database_path: owned_path,
manager,
manager: StorageManagerState::Storage(manager),
})
}
async fn close_pool(&mut self) {
self.manager.connection_pool.close().await;
self.manager.get_mut().connection_pool.close().await;
}
async fn rotate(&mut self) -> Result<(), StorageError> {
@@ -143,8 +196,9 @@ impl Backend {
fs::rename(&self.database_path, &temp_old)
.map_err(|err| StorageError::DatabaseRenameError { source: err })?;
self.manager = StorageManager::init(&self.database_path, true).await?;
self.manager.create_status_table().await?;
self.manager =
StorageManagerState::Storage(StorageManager::init(&self.database_path, true).await?);
self.manager.get_mut().create_status_table().await?;
self.temporary_old_path = Some(temp_old);
Ok(())
@@ -161,26 +215,27 @@ impl Backend {
}
async fn start_storage_flush(&self) -> Result<(), StorageError> {
Ok(self.manager.set_flush_status(true).await?)
Ok(self.manager.get().set_flush_status(true).await?)
}
async fn end_storage_flush(&self) -> Result<(), StorageError> {
self.manager
.get()
.set_previous_flush_timestamp(OffsetDateTime::now_utc().unix_timestamp())
.await?;
Ok(self.manager.set_flush_status(false).await?)
Ok(self.manager.get().set_flush_status(false).await?)
}
async fn start_client_use(&self) -> Result<(), StorageError> {
Ok(self.manager.set_client_in_use_status(true).await?)
Ok(self.manager.get().set_client_in_use_status(true).await?)
}
async fn stop_client_use(&self) -> Result<(), StorageError> {
Ok(self.manager.set_client_in_use_status(false).await?)
Ok(self.manager.get().set_client_in_use_status(false).await?)
}
async fn get_stored_tags(&self) -> Result<UsedSenderTags, StorageError> {
let stored = self.manager.get_tags().await?;
let stored = self.manager.get().get_tags().await?;
// stop at the first instance of corruption. if even a single entry is malformed,
// something weird has happened and we can't trust the rest of the data
@@ -196,6 +251,7 @@ impl Backend {
for map_ref in tags.as_raw_iter() {
let (recipient, tag) = map_ref.pair();
self.manager
.get()
.insert_tag(StoredSenderTag::new(*recipient, *tag))
.await?;
}
@@ -203,7 +259,7 @@ impl Backend {
}
async fn get_stored_reply_keys(&self) -> Result<SentReplyKeys, StorageError> {
let stored = self.manager.get_reply_keys().await?;
let stored = self.manager.get().get_reply_keys().await?;
// stop at the first instance of corruption. if even a single entry is malformed,
// something weird has happened and we can't trust the rest of the data
@@ -219,6 +275,7 @@ impl Backend {
for map_ref in reply_keys.as_raw_iter() {
let (digest, key) = map_ref.pair();
self.manager
.get()
.insert_reply_key(StoredReplyKey::new(*digest, *key))
.await?;
}
@@ -226,7 +283,7 @@ impl Backend {
}
async fn get_stored_reply_surbs(&self) -> Result<ReceivedReplySurbsMap, StorageError> {
let surb_senders = self.manager.get_surb_senders().await?;
let surb_senders = self.manager.get().get_surb_senders().await?;
let metadata = self.get_reply_surb_storage_metadata().await?;
let mut received_surbs = Vec::with_capacity(surb_senders.len());
@@ -236,6 +293,7 @@ impl Backend {
sender.try_into()?;
let stored_surbs = self
.manager
.get()
.get_reply_surbs(sender_id)
.await?
.into_iter()
@@ -263,6 +321,7 @@ impl Backend {
let (tag, received_surbs) = map_ref.pair();
let sender_id = self
.manager
.get()
.insert_surb_sender(StoredSurbSender::new(
*tag,
received_surbs.surbs_last_received_at(),
@@ -271,6 +330,7 @@ impl Backend {
for reply_surb in received_surbs.surbs_ref() {
self.manager
.get()
.insert_reply_surb(StoredReplySurb::new(sender_id, reply_surb))
.await?
}
@@ -282,6 +342,7 @@ impl Backend {
&self,
) -> Result<ReplySurbStorageMetadata, StorageError> {
self.manager
.get()
.get_reply_surb_storage_metadata()
.await
.map_err(Into::into)
@@ -292,6 +353,7 @@ impl Backend {
reply_surbs: &ReceivedReplySurbsMap,
) -> Result<(), StorageError> {
self.manager
.get()
.insert_reply_surb_storage_metadata(ReplySurbStorageMetadata::new(
reply_surbs.min_surb_threshold(),
reply_surbs.max_surb_threshold(),
@@ -305,6 +367,10 @@ impl Backend {
impl ReplyStorageBackend for Backend {
type StorageError = error::StorageError;
fn is_active(&self) -> bool {
self.manager.is_active()
}
async fn start_storage_session(&self) -> Result<(), Self::StorageError> {
self.start_client_use().await
}
@@ -342,6 +408,18 @@ impl ReplyStorageBackend for Backend {
Ok(CombinedReplyStorage::load(reply_keys, reply_surbs, tags))
}
fn get_inactive_storage(&self) -> Result<CombinedReplyStorage, Self::StorageError> {
match self.manager {
StorageManagerState::Storage(_) => {
panic!("tried to get inactive storage from an active storage backend")
}
StorageManagerState::Inactive(ref state) => Ok(CombinedReplyStorage::new(
state.minimum_reply_surb_storage_threshold,
state.maximum_reply_surb_storage_threshold,
)),
}
}
async fn stop_storage_session(self) -> Result<(), Self::StorageError> {
self.stop_client_use().await
}
@@ -44,8 +44,7 @@ impl TryFrom<StoredSenderTag> for (RecipientBytes, AnonymousSenderTag) {
let Ok(sender_tag_bytes) = value.tag.try_into() else {
return Err(StorageError::CorruptedData {
details: format!(
"the retrieved sender tag has length of {tag_len} while {} was expected",
SENDER_TAG_SIZE
"the retrieved sender tag has length of {tag_len} while {SENDER_TAG_SIZE} was expected",
),
});
};
@@ -132,8 +131,7 @@ impl TryFrom<StoredSurbSender> for (AnonymousSenderTag, i64) {
let Ok(sender_tag_bytes) = value.tag.try_into() else {
return Err(StorageError::CorruptedData {
details: format!(
"the retrieved sender tag has length of {tag_len} while {} was expected",
SENDER_TAG_SIZE
"the retrieved sender tag has length of {tag_len} while {SENDER_TAG_SIZE} was expected",
),
});
};
@@ -50,12 +50,23 @@ impl ReplyStorageBackend for Empty {
self.max_surb_threshold,
))
}
fn get_inactive_storage(&self) -> Result<CombinedReplyStorage, Self::StorageError> {
Ok(CombinedReplyStorage::new(
self.min_surb_threshold,
self.max_surb_threshold,
))
}
}
#[async_trait]
pub trait ReplyStorageBackend: Sized {
type StorageError: Error + 'static;
fn is_active(&self) -> bool {
true
}
async fn start_storage_session(&self) -> Result<(), Self::StorageError> {
Ok(())
}
@@ -73,6 +84,11 @@ pub trait ReplyStorageBackend: Sized {
async fn load_surb_storage(&self) -> Result<CombinedReplyStorage, Self::StorageError>;
/// In the case the storage backend is initialized in an inactive state (persisting data is
/// disabled), we might still need to fetch the (in-mem) storage and the parameters it was
/// created with.
fn get_inactive_storage(&self) -> Result<CombinedReplyStorage, Self::StorageError>;
async fn stop_storage_session(self) -> Result<(), Self::StorageError> {
Ok(())
}
+26 -13
View File
@@ -45,7 +45,8 @@ const DEFAULT_MAXIMUM_REPLY_SURB_REQUEST_SIZE: u32 = 100;
const DEFAULT_MAXIMUM_ALLOWED_SURB_REQUEST_SIZE: u32 = 500;
const DEFAULT_MAXIMUM_REPLY_SURB_WAITING_PERIOD: Duration = Duration::from_secs(10);
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);
@@ -88,6 +89,7 @@ impl<T> Config<T> {
Config::default().with_id(id)
}
#[must_use]
pub fn with_id<S: Into<String>>(mut self, id: S) -> Self
where
T: NymConfig,
@@ -371,8 +373,12 @@ impl<T> Config<T> {
self.debug.maximum_allowed_reply_surb_request_size
}
pub fn get_maximum_reply_surb_waiting_period(&self) -> Duration {
self.debug.maximum_reply_surb_waiting_period
pub fn get_maximum_reply_surb_rerequest_waiting_period(&self) -> Duration {
self.debug.maximum_reply_surb_rerequest_waiting_period
}
pub fn get_maximum_reply_surb_drop_waiting_period(&self) -> Duration {
self.debug.maximum_reply_surb_drop_waiting_period
}
pub fn get_maximum_reply_surb_age(&self) -> Duration {
@@ -540,35 +546,35 @@ impl<T: NymConfig> Default for Client<T> {
impl<T: NymConfig> Client<T> {
fn default_private_identity_key_file(id: &str) -> PathBuf {
T::default_data_directory(Some(id)).join("private_identity.pem")
T::default_data_directory(id).join("private_identity.pem")
}
fn default_public_identity_key_file(id: &str) -> PathBuf {
T::default_data_directory(Some(id)).join("public_identity.pem")
T::default_data_directory(id).join("public_identity.pem")
}
fn default_private_encryption_key_file(id: &str) -> PathBuf {
T::default_data_directory(Some(id)).join("private_encryption.pem")
T::default_data_directory(id).join("private_encryption.pem")
}
fn default_public_encryption_key_file(id: &str) -> PathBuf {
T::default_data_directory(Some(id)).join("public_encryption.pem")
T::default_data_directory(id).join("public_encryption.pem")
}
fn default_gateway_shared_key_file(id: &str) -> PathBuf {
T::default_data_directory(Some(id)).join("gateway_shared.pem")
T::default_data_directory(id).join("gateway_shared.pem")
}
fn default_ack_key_file(id: &str) -> PathBuf {
T::default_data_directory(Some(id)).join("ack_key.pem")
T::default_data_directory(id).join("ack_key.pem")
}
fn default_reply_surb_database_path(id: &str) -> PathBuf {
T::default_data_directory(Some(id)).join("persistent_reply_store.sqlite")
T::default_data_directory(id).join("persistent_reply_store.sqlite")
}
fn default_database_path(id: &str) -> PathBuf {
T::default_data_directory(Some(id)).join(DB_FILE_NAME)
T::default_data_directory(id).join(DB_FILE_NAME)
}
}
@@ -662,7 +668,12 @@ pub struct DebugConfig {
/// Defines maximum amount of time the client is going to wait for reply surbs before explicitly asking
/// for more even though in theory they wouldn't need to.
#[serde(with = "humantime_serde")]
pub maximum_reply_surb_waiting_period: Duration,
pub maximum_reply_surb_rerequest_waiting_period: Duration,
/// Defines maximum amount of time the client is going to wait for reply surbs before
/// deciding it's never going to get them and would drop all pending messages
#[serde(with = "humantime_serde")]
pub maximum_reply_surb_drop_waiting_period: Duration,
/// Defines maximum amount of time given reply surb is going to be valid for.
/// This is going to be superseded by key rotation once implemented.
@@ -703,7 +714,9 @@ impl Default for DebugConfig {
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_waiting_period: DEFAULT_MAXIMUM_REPLY_SURB_WAITING_PERIOD,
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,
}
+2
View File
@@ -65,8 +65,10 @@ pub enum ClientCoreError {
/// Set of messages that the client can send to listeners via the task manager
#[derive(thiserror::Error, Debug)]
pub enum ClientCoreStatusMessage {
// NOTE: The nym-connect frontend listens for these strings, so don't change them until we have a more robust mechanism in place
#[error("The connected gateway is slow, or the connection to it is slow")]
GatewayIsSlow,
// NOTE: The nym-connect frontend listens for these strings, so don't change them until we have a more robust mechanism in place
#[error("The connected gateway is very slow, or the connection to it is very slow")]
GatewayIsVerySlow,
}
+7 -4
View File
@@ -8,6 +8,8 @@ use crate::{
};
use config::NymConfig;
use crypto::asymmetric::identity;
#[cfg(target_arch = "wasm32")]
use gateway_client::wasm_mockups::SigningNyxdClient;
use gateway_client::GatewayClient;
use gateway_requests::registration::handshake::SharedKeys;
use rand::{seq::SliceRandom, thread_rng};
@@ -15,10 +17,12 @@ use std::{sync::Arc, time::Duration};
use tap::TapFallible;
use topology::{filter::VersionFilterable, gateway};
use url::Url;
#[cfg(not(target_arch = "wasm32"))]
use validator_client::nyxd::SigningNyxdClient;
pub(super) async fn query_gateway_details(
validator_servers: Vec<Url>,
chosen_gateway_id: Option<String>,
chosen_gateway_id: Option<identity::PublicKey>,
) -> Result<gateway::Node, ClientCoreError> {
let nym_api = validator_servers
.choose(&mut thread_rng())
@@ -40,7 +44,7 @@ pub(super) async fn query_gateway_details(
if let Some(gateway_id) = chosen_gateway_id {
filtered_gateways
.iter()
.find(|gateway| gateway.identity_key.to_base58_string() == gateway_id)
.find(|gateway| gateway.identity_key == gateway_id)
.ok_or_else(|| ClientCoreError::NoGatewayWithId(gateway_id.to_string()))
.cloned()
} else {
@@ -56,10 +60,9 @@ pub(super) async fn register_with_gateway(
our_identity: Arc<identity::KeyPair>,
) -> Result<Arc<SharedKeys>, ClientCoreError> {
let timeout = Duration::from_millis(1500);
let mut gateway_client = GatewayClient::new_init(
let mut gateway_client: GatewayClient<SigningNyxdClient> = GatewayClient::new_init(
gateway.clients_address(),
gateway.identity_key,
gateway.owner.clone(),
our_identity.clone(),
timeout,
);
+54 -70
View File
@@ -69,42 +69,21 @@ pub fn new_client_keys() -> KeyManager {
KeyManager::new(&mut rng)
}
/// Convenience function for setting up the gateway for a client. Depending on the arguments given
/// it will do the sensible thing.
pub async fn setup_gateway<C, T>(
register_gateway: bool,
// TODO: this should get refactored to instead take Option<identity::PublicKey>
user_chosen_gateway_id: Option<String>,
config: &Config<T>,
) -> Result<GatewayEndpointConfig, ClientCoreError>
where
C: NymConfig + ClientCoreConfigTrait,
T: NymConfig,
{
let id = config.get_id();
if register_gateway {
register_with_gateway_and_store(user_chosen_gateway_id, config).await
} else if let Some(user_chosen_gateway_id) = user_chosen_gateway_id {
config_gateway_with_existing_keys(user_chosen_gateway_id, config).await
} else {
reuse_existing_gateway_config::<C>(&id)
}
}
/// Get the gateway details by querying the validator-api. Either pick one at random or use
/// the chosen one if it's among the available ones.
/// Authenticate and register with a gateway.
/// Either pick one at random by querying the available gateways from the nym-api, or use the
/// chosen one if it's among the available ones.
/// The shared key is added to the supplied `KeyManager` and the endpoint details are returned.
pub async fn register_with_gateway(
key_manager: &mut KeyManager,
nym_api_endpoints: Vec<Url>,
chosen_gateway_id: Option<String>,
chosen_gateway_id: Option<identity::PublicKey>,
) -> Result<GatewayEndpointConfig, ClientCoreError> {
// Our identity is derived from our key
let our_identity = key_manager.identity_keypair();
// Get the gateway details of the gateway we will use
let gateway = helpers::query_gateway_details(nym_api_endpoints, chosen_gateway_id).await?;
log::debug!("Querying gateway gives: {}", gateway);
let our_identity = key_manager.identity_keypair();
// Establish connection, authenticate and generate keys for talking with the gateway
let shared_keys = helpers::register_with_gateway(&gateway, our_identity).await?;
key_manager.insert_gateway_shared_key(shared_keys);
@@ -112,60 +91,65 @@ pub async fn register_with_gateway(
Ok(gateway.into())
}
/// Get the gateway details by querying the validator-api. Either pick one at random or use
/// the chosen one if it's among the available ones.
/// Saves keys to disk, specified by the paths in `config`.
pub async fn register_with_gateway_and_store<T>(
chosen_gateway_id: Option<String>,
/// Convenience function for setting up the gateway for a client given a `Config`. Depending on the
/// arguments given it will do the sensible thing. Either it will
///
/// a. Reuse existing gateway configuration from storage.
/// b. Create a new gateway configuration but keep existing keys. This assumes that the caller
/// knows what they are doing and that the keys match the requested gateway.
/// c. Create a new gateway configuration with a newly registered gateway and keys.
pub async fn setup_gateway_from_config<C, T>(
register_gateway: bool,
user_chosen_gateway_id: Option<identity::PublicKey>,
config: &Config<T>,
) -> Result<GatewayEndpointConfig, ClientCoreError>
where
C: NymConfig + ClientCoreConfigTrait,
T: NymConfig,
{
println!("Configuring gateway");
let mut key_manager = new_client_keys();
let id = config.get_id();
let gateway = register_with_gateway(
&mut key_manager,
config.get_nym_api_endpoints(),
chosen_gateway_id,
)
.await?;
// If we are not going to register gateway, and an explicitly chosed gateway is not passed in,
// load the existing configuration file
if !register_gateway && user_chosen_gateway_id.is_none() {
println!("Not registering gateway, will reuse existing config and keys");
return load_existing_gateway_config::<C>(&id);
}
helpers::store_keys(&key_manager, config)?;
println!("Saved all generated keys");
Ok(gateway)
}
/// Set the gateway using the usual procedue of querying the validator-api, but don't register or
/// create any keys.
/// This assumes that the user knows what they are doing, and that the existing keys are valid for
/// the gateway being used
pub async fn config_gateway_with_existing_keys<T>(
user_chosen_gateway_id: String,
config: &Config<T>,
) -> Result<GatewayEndpointConfig, ClientCoreError>
where
T: NymConfig,
{
println!("Using gateway provided by user, keeping existing keys");
let gateway = helpers::query_gateway_details(
config.get_nym_api_endpoints(),
Some(user_chosen_gateway_id),
)
.await?;
// Else, we preceed by querying the nym-api
let gateway =
helpers::query_gateway_details(config.get_nym_api_endpoints(), user_chosen_gateway_id)
.await?;
log::debug!("Querying gateway gives: {}", gateway);
// If we are not registering, just return this and assume the caller has the keys already and
// wants to keep the,
if !register_gateway && user_chosen_gateway_id.is_some() {
println!("Using gateway provided by user, keeping existing keys");
return Ok(gateway.into());
}
// Create new keys and derive our identity
let mut key_manager = new_client_keys();
let our_identity = key_manager.identity_keypair();
// Establish connection, authenticate and generate keys for talking with the gateway
println!("Registering with new gateway");
let shared_keys = helpers::register_with_gateway(&gateway, our_identity).await?;
key_manager.insert_gateway_shared_key(shared_keys);
// Write all keys to storage and just return the gateway endpoint config. It is assumed that we
// will load keys from storage when actually connecting.
helpers::store_keys(&key_manager, config)?;
Ok(gateway.into())
}
/// Read and reuse the existing gateway configuration from a file that was generate earlier.
pub fn reuse_existing_gateway_config<T>(id: &str) -> Result<GatewayEndpointConfig, ClientCoreError>
pub fn load_existing_gateway_config<T>(id: &str) -> Result<GatewayEndpointConfig, ClientCoreError>
where
T: NymConfig + ClientCoreConfigTrait,
{
println!("Not registering gateway, will reuse existing config and keys");
T::load_from_file(Some(id))
T::load_from_file(id)
.map(|existing_config| existing_config.get_gateway_endpoint().clone())
.map_err(|err| {
log::error!(
@@ -242,9 +226,9 @@ where
pub fn output_to_json<T: Serialize>(init_results: &T, output_file: &str) {
match std::fs::File::create(output_file) {
Ok(file) => match serde_json::to_writer_pretty(file, init_results) {
Ok(_) => println!("Saved: {}", output_file),
Err(err) => eprintln!("Could not save {}: {err}", output_file),
Ok(_) => println!("Saved: {output_file}"),
Err(err) => eprintln!("Could not save {output_file}: {err}"),
},
Err(err) => eprintln!("Could not save {}: {err}", output_file),
Err(err) => eprintln!("Could not save {output_file}: {err}"),
}
}
+1 -4
View File
@@ -7,13 +7,12 @@ edition = "2021"
[dependencies]
bip39 = "1.0.1"
cfg-if = "0.1"
clap = { version = "4.0", features = ["cargo", "derive"] }
rand = "0.7.3"
serde = { version = "1.0", features = ["derive"] }
thiserror = "1.0"
url = "2.2"
tokio = { version = "1.21.2", features = ["rt-multi-thread", "net", "signal", "macros"] } # async runtime
tokio = { version = "1.24.1", features = ["rt-multi-thread", "net", "signal", "macros"] } # async runtime
coconut-interface = { path = "../../common/coconut-interface" }
config = { path = "../../common/config" }
@@ -25,5 +24,3 @@ network-defaults = { path = "../../common/network-defaults" }
pemstore = { path = "../../common/pemstore" }
validator-client = { path = "../../common/client-libs/validator-client", features = ["nyxd-client"] }
[features]
coconut = ["credentials/coconut"]
+4 -1
View File
@@ -13,6 +13,7 @@ use credentials::coconut::bandwidth::{BandwidthVoucher, TOTAL_ATTRIBUTES};
use credentials::coconut::utils::obtain_aggregate_signature;
use crypto::asymmetric::{encryption, identity};
use network_defaults::{NymNetworkDetails, VOUCHER_INFO};
use validator_client::nyxd::traits::DkgQueryClient;
use validator_client::nyxd::tx::Hash;
use validator_client::{CoconutApiClient, Config};
@@ -80,7 +81,8 @@ pub(crate) async fn get_credential(state: &State, shared_storage: PersistentStor
let network_details = NymNetworkDetails::new_from_env();
let config = Config::try_from_nym_network_details(&network_details)?;
let client = validator_client::Client::new_query(config)?;
let coconut_api_clients = CoconutApiClient::all_coconut_api_clients(&client).await?;
let epoch_id = client.nyxd.get_current_epoch().await?.epoch_id;
let coconut_api_clients = CoconutApiClient::all_coconut_api_clients(&client, epoch_id).await?;
let params = Parameters::new(TOTAL_ATTRIBUTES).unwrap();
let bandwidth_credential_attributes = BandwidthVoucher::new(
@@ -106,6 +108,7 @@ pub(crate) async fn get_credential(state: &State, shared_storage: PersistentStor
bandwidth_credential_attributes.get_private_attributes()[0].to_bs58(),
bandwidth_credential_attributes.get_private_attributes()[1].to_bs58(),
signature.to_bs58(),
epoch_id.to_string(),
)
.await?;
+39 -48
View File
@@ -1,56 +1,47 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
cfg_if::cfg_if! {
if #[cfg(feature = "coconut")] {
mod client;
mod commands;
mod error;
mod state;
mod client;
mod commands;
mod error;
mod state;
use commands::*;
use completions::fig_generate;
use config::{DATA_DIR, DB_FILE_NAME};
use error::Result;
use network_defaults::setup_env;
use error::Result;
use network_defaults::setup_env;
use completions::fig_generate;
use commands::*;
use config::{DATA_DIR, DB_FILE_NAME};
use clap::{CommandFactory, Parser};
use clap::{CommandFactory, Parser};
#[derive(Parser)]
#[clap(author = "Nymtech", version, about)]
struct Cli {
/// Path pointing to an env file that configures the client.
#[clap(short, long)]
pub(crate) config_env_file: Option<std::path::PathBuf>,
#[derive(Parser)]
#[clap(author = "Nymtech", version, about)]
struct Cli {
/// Path pointing to an env file that configures the client.
#[clap(short, long)]
pub(crate) config_env_file: Option<std::path::PathBuf>,
#[clap(subcommand)]
pub(crate) command: Command,
}
#[tokio::main]
async fn main() -> Result<()> {
let args = Cli::parse();
setup_env(args.config_env_file.as_ref());
let bin_name = "nym-credential-client";
match args.command {
Command::Run(r) => {
let db_path = r.client_home_directory.join(DATA_DIR).join(DB_FILE_NAME);
let shared_storage = credential_storage::initialise_storage(db_path).await;
let state = deposit(&r.nyxd_url, &r.mnemonic, r.amount).await?;
get_credential(&state, shared_storage).await?;
}
Command::Completions(c) => c.generate(&mut crate::Cli::command(), bin_name),
Command::GenerateFigSpec => fig_generate(&mut crate::Cli::command(), bin_name)
}
Ok(())
}
} else {
fn main() {
println!("Crate only designed for coconut feature");
}
}
#[clap(subcommand)]
pub(crate) command: Command,
}
#[tokio::main]
async fn main() -> Result<()> {
let args = Cli::parse();
setup_env(args.config_env_file.as_ref());
let bin_name = "nym-credential-client";
match args.command {
Command::Run(r) => {
let db_path = r.client_home_directory.join(DATA_DIR).join(DB_FILE_NAME);
let shared_storage = credential_storage::initialise_storage(db_path).await;
let state = deposit(&r.nyxd_url, &r.mnemonic, r.amount).await?;
get_credential(&state, shared_storage).await?;
}
Command::Completions(c) => c.generate(&mut crate::Cli::command(), bin_name),
Command::GenerateFigSpec => fig_generate(&mut crate::Cli::command(), bin_name),
}
Ok(())
}
+5 -8
View File
@@ -1,6 +1,6 @@
[package]
name = "nym-client"
version = "1.1.5"
version = "1.1.8"
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jędrzej Stuczyński <andrew@nymtech.net>"]
description = "Implementation of the Nym Client"
edition = "2021"
@@ -23,25 +23,25 @@ url = "2.2"
clap = { version = "4.0", features = ["cargo", "derive"] }
dirs = "4.0"
lazy_static = "1.4.0"
log = "0.4" # self explanatory
log = { workspace = true } # self explanatory
pretty_env_logger = "0.4" # for formatting log messages
rand = { version = "0.7.3", features = ["wasm-bindgen"] } # rng-related traits + some rng implementation to use
serde = { version = "1.0.104", features = ["derive"] } # for config serialization/deserialization
serde_json = "1.0"
thiserror = "1.0.34"
tap = "1.0.1"
tokio = { version = "1.21.2", features = ["rt-multi-thread", "net", "signal"] } # async runtime
tokio = { version = "1.24.1", features = ["rt-multi-thread", "net", "signal"] } # async runtime
tokio-tungstenite = "0.14" # websocket
## internal
build-information = { path = "../../common/build-information" }
client-core = { path = "../client-core", features = ["fs-surb-storage"] }
client-connections = { path = "../../common/client-connections" }
coconut-interface = { path = "../../common/coconut-interface", optional = true }
coconut-interface = { path = "../../common/coconut-interface" }
config = { path = "../../common/config" }
completions = { path = "../../common/completions" }
credential-storage = { path = "../../common/credential-storage" }
credentials = { path = "../../common/credentials", optional = true }
credentials = { path = "../../common/credentials" }
crypto = { path = "../../common/crypto" }
logging = { path = "../../common/logging"}
gateway-client = { path = "../../common/client-libs/gateway-client" }
@@ -55,8 +55,5 @@ validator-client = { path = "../../common/client-libs/validator-client", feature
version-checker = { path = "../../common/version-checker" }
websocket-requests = { path = "websocket-requests" }
[features]
coconut = ["coconut-interface", "credentials", "credentials/coconut", "gateway-requests/coconut", "gateway-client/coconut", "client-core/coconut"]
[dev-dependencies]
serde_json = "1.0" # for the "textsend" example
@@ -85,7 +85,7 @@ async fn send_file_without_reply() {
let (mut ws_stream, _) = connect_async(uri).await.unwrap();
let recipient = get_self_address(&mut ws_stream).await;
println!("our full address is: {}", recipient);
println!("our full address is: {recipient}");
let read_data = std::fs::read("examples/dummy_file").unwrap();
+5 -14
View File
@@ -36,7 +36,7 @@ async fn send_text_with_reply() {
let (mut ws_stream, _) = connect_async(uri).await.unwrap();
let recipient = get_self_address(&mut ws_stream).await;
println!("our full address is: {}", recipient);
println!("our full address is: {recipient}");
let send_request = json!({
"type" : "send",
@@ -45,10 +45,7 @@ async fn send_text_with_reply() {
"withReplySurb": true,
});
println!(
"sending {:?} (*with* reply SURB) over the mix network...",
message
);
println!("sending {message:?} (*with* reply SURB) over the mix network...");
let response =
send_message_and_get_json_response(&mut ws_stream, send_request.to_string()).await;
@@ -59,10 +56,7 @@ async fn send_text_with_reply() {
"replySurb": response["replySurb"]
});
println!(
"sending {:?} (using reply SURB!) over the mix network...",
reply_message
);
println!("sending {reply_message:?} (using reply SURB!) over the mix network...");
let response =
send_message_and_get_json_response(&mut ws_stream, reply_request.to_string()).await;
@@ -76,7 +70,7 @@ async fn send_text_without_reply() {
let (mut ws_stream, _) = connect_async(uri).await.unwrap();
let recipient = get_self_address(&mut ws_stream).await;
println!("our full address is: {}", recipient);
println!("our full address is: {recipient}");
let send_request = json!({
"type" : "send",
@@ -85,10 +79,7 @@ async fn send_text_without_reply() {
"withReplySurb": false,
});
println!(
"sending {:?} (*without* reply SURB) over the mix network...",
message
);
println!("sending {message:?} (*without* reply SURB) over the mix network...");
let response =
send_message_and_get_json_response(&mut ws_stream, send_request.to_string()).await;
+13 -1
View File
@@ -9,6 +9,7 @@ use config::defaults::DEFAULT_WEBSOCKET_LISTENING_PORT;
use config::{NymConfig, OptionalSet};
use serde::{Deserialize, Serialize};
use std::fmt::Debug;
use std::net::{IpAddr, Ipv4Addr};
use std::path::PathBuf;
use std::str::FromStr;
@@ -104,6 +105,11 @@ impl Config {
self
}
pub fn with_host(mut self, host: IpAddr) -> Self {
self.socket.host = host;
self
}
pub fn with_port(mut self, port: u16) -> Self {
self.socket.listening_port = port;
self
@@ -130,6 +136,10 @@ impl Config {
self.socket.socket_type
}
pub fn get_listening_ip(&self) -> IpAddr {
self.socket.host
}
pub fn get_listening_port(&self) -> u16 {
self.socket.listening_port
}
@@ -180,9 +190,10 @@ impl Config {
}
#[derive(Debug, Deserialize, PartialEq, Eq, Serialize)]
#[serde(deny_unknown_fields)]
#[serde(default, deny_unknown_fields)]
pub struct Socket {
socket_type: SocketType,
host: IpAddr,
listening_port: u16,
}
@@ -190,6 +201,7 @@ impl Default for Socket {
fn default() -> Self {
Socket {
socket_type: SocketType::WebSocket,
host: IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)),
listening_port: DEFAULT_WEBSOCKET_LISTENING_PORT,
}
}
@@ -93,6 +93,9 @@ socket_type = '{{ socket.socket_type }}'
# will be listening for incoming requests
listening_port = {{ socket.listening_port }}
# if applicable (for the case of 'WebSocket'), the ip address on which the client
# will be listening for incoming requests
host = '{{ socket.host }}'
##### logging configuration options #####
+27 -46
View File
@@ -21,6 +21,7 @@ use nymsphinx::addressing::clients::Recipient;
use nymsphinx::anonymous_replies::requests::AnonymousSenderTag;
use nymsphinx::receiver::ReconstructedMessage;
use task::TaskManager;
use validator_client::nyxd::QueryNyxdClient;
pub(crate) mod config;
@@ -44,42 +45,28 @@ impl SocketClient {
}
}
async fn create_bandwidth_controller(config: &Config) -> BandwidthController {
#[cfg(feature = "coconut")]
let bandwidth_controller = {
let details = network_defaults::NymNetworkDetails::new_from_env();
let mut client_config =
validator_client::Config::try_from_nym_network_details(&details)
.expect("failed to construct validator client config");
let nyxd_url = config
.get_base()
.get_validator_endpoints()
.pop()
.expect("No nyxd validator endpoint provided");
let api_url = config
.get_base()
.get_nym_api_endpoints()
.pop()
.expect("No validator api endpoint provided");
// overwrite env configuration with config URLs
client_config = client_config.with_urls(nyxd_url, api_url);
let client = validator_client::Client::new_query(client_config)
.expect("Could not construct query client");
let coconut_api_clients =
validator_client::CoconutApiClient::all_coconut_api_clients(&client)
.await
.expect("Could not query api clients");
BandwidthController::new(
credential_storage::initialise_storage(config.get_base().get_database_path()).await,
coconut_api_clients,
)
};
#[cfg(not(feature = "coconut"))]
let bandwidth_controller = BandwidthController::new(
async fn create_bandwidth_controller(config: &Config) -> BandwidthController<QueryNyxdClient> {
let details = network_defaults::NymNetworkDetails::new_from_env();
let mut client_config = validator_client::Config::try_from_nym_network_details(&details)
.expect("failed to construct validator client config");
let nyxd_url = config
.get_base()
.get_validator_endpoints()
.pop()
.expect("No nyxd validator endpoint provided");
let api_url = config
.get_base()
.get_nym_api_endpoints()
.pop()
.expect("No validator api endpoint provided");
// overwrite env configuration with config URLs
client_config = client_config.with_urls(nyxd_url, api_url);
let client = validator_client::Client::new_query(client_config)
.expect("Could not construct query client");
BandwidthController::new(
credential_storage::initialise_storage(config.get_base().get_database_path()).await,
client,
)
.expect("Could not create bandwidth controller");
bandwidth_controller
}
fn start_websocket_listener(
@@ -115,21 +102,15 @@ impl SocketClient {
reply_controller_sender,
);
websocket::Listener::new(config.get_listening_port()).start(websocket_handler, shutdown);
websocket::Listener::new(config.get_listening_ip(), config.get_listening_port())
.start(websocket_handler, shutdown);
}
/// blocking version of `start_socket` method. Will run forever (or until SIGINT is sent)
pub async fn run_socket_forever(self) -> Result<(), Box<dyn Error + Send + Sync>> {
let mut shutdown = self.start_socket().await?;
let res = task::wait_for_signal_and_error(&mut shutdown).await;
log::info!("Sending shutdown");
shutdown.signal_shutdown().ok();
log::info!("Waiting for tasks to finish... (Press ctrl-c to force)");
shutdown.wait_for_shutdown().await;
let shutdown = self.start_socket().await?;
let res = shutdown.catch_interrupt().await;
log::info!("Stopping nym-client");
res
}
@@ -144,7 +125,7 @@ impl SocketClient {
self.key_manager,
Some(Self::create_bandwidth_controller(&self.config).await),
non_wasm_helpers::setup_fs_reply_surb_backend(
self.config.get_base().get_reply_surb_database_path(),
Some(self.config.get_base().get_reply_surb_database_path()),
self.config.get_debug_settings(),
)
.await?,
@@ -181,7 +162,7 @@ impl SocketClient {
self.key_manager,
Some(Self::create_bandwidth_controller(&self.config).await),
non_wasm_helpers::setup_fs_reply_surb_backend(
self.config.get_base().get_reply_surb_database_path(),
Some(self.config.get_base().get_reply_surb_database_path()),
self.config.get_debug_settings(),
)
.await?,
+14 -13
View File
@@ -12,6 +12,7 @@ use crypto::asymmetric::identity;
use nymsphinx::addressing::clients::Recipient;
use serde::Serialize;
use std::fmt::Display;
use std::net::IpAddr;
use tap::TapFallible;
#[derive(Args, Clone)]
@@ -30,7 +31,6 @@ pub(crate) struct Init {
force_register_gateway: bool,
/// Comma separated list of rest endpoints of the nyxd validators
#[cfg(feature = "coconut")]
#[clap(long, alias = "nymd_validators", value_delimiter = ',')]
nyxd_urls: Option<Vec<url::Url>>,
@@ -47,6 +47,10 @@ pub(crate) struct Init {
#[clap(short, long)]
port: Option<u16>,
/// Ip for the socket (if applicable) to listen for requests.
#[clap(long)]
host: Option<IpAddr>,
/// Mostly debug-related option to increase default traffic rate so that you would not need to
/// modify config post init
#[clap(long, hide = true)]
@@ -58,7 +62,6 @@ pub(crate) struct Init {
/// Set this client to work in a enabled credentials mode that would attempt to use gateway
/// with bandwidth credential requirement.
#[cfg(feature = "coconut")]
#[clap(long)]
enabled_credentials_mode: Option<bool>,
@@ -73,12 +76,11 @@ impl From<Init> for OverrideConfig {
nym_apis: init_config.nym_apis,
disable_socket: init_config.disable_socket,
port: init_config.port,
host: init_config.host,
fastmode: init_config.fastmode,
no_cover: init_config.no_cover,
#[cfg(feature = "coconut")]
nyxd_urls: init_config.nyxd_urls,
#[cfg(feature = "coconut")]
enabled_credentials_mode: init_config.enabled_credentials_mode,
}
}
@@ -112,18 +114,17 @@ pub(crate) async fn execute(args: &Init) -> Result<(), ClientError> {
let id = &args.id;
let already_init = Config::default_config_file_path(Some(id)).exists();
let already_init = Config::default_config_file_path(id).exists();
if already_init {
println!(
"Client \"{}\" was already initialised before! \
Config information will be overwritten (but keys will be kept)!",
id
);
println!("Client \"{id}\" was already initialised before");
}
// Usually you only register with the gateway on the first init, however you can force
// re-registering if wanted.
let user_wants_force_register = args.force_register_gateway;
if user_wants_force_register {
println!("Instructed to force registering gateway. This might overwrite keys!");
}
// If the client was already initialized, don't generate new keys and don't re-register with
// the gateway (because this would create a new shared key).
@@ -138,9 +139,9 @@ pub(crate) async fn execute(args: &Init) -> Result<(), ClientError> {
// Setup gateway by either registering a new one, or creating a new config from the selected
// one but with keys kept, or reusing the gateway configuration.
let gateway = client_core::init::setup_gateway::<Config, _>(
let gateway = client_core::init::setup_gateway_from_config::<Config, _>(
register_gateway,
user_chosen_gateway_id.map(|id| id.to_base58_string()),
user_chosen_gateway_id,
config.get_base(),
)
.await
@@ -169,7 +170,7 @@ pub(crate) async fn execute(args: &Init) -> Result<(), ClientError> {
fn print_saved_config(config: &Config) {
let config_save_location = config.get_config_file_save_location();
println!("Saved configuration file to {:?}", config_save_location);
println!("Saved configuration file to {config_save_location:?}");
println!("Using gateway: {}", config.get_base().get_gateway_id());
log::debug!("Gateway id: {}", config.get_base().get_gateway_id());
log::debug!("Gateway owner: {}", config.get_base().get_gateway_owner());
+16 -23
View File
@@ -9,6 +9,7 @@ use completions::{fig_generate, ArgShell};
use config::OptionalSet;
use lazy_static::lazy_static;
use std::error::Error;
use std::net::IpAddr;
pub(crate) mod init;
pub(crate) mod run;
@@ -56,12 +57,10 @@ pub(crate) struct OverrideConfig {
nym_apis: Option<Vec<url::Url>>,
disable_socket: Option<bool>,
port: Option<u16>,
host: Option<IpAddr>,
fastmode: bool,
no_cover: bool,
#[cfg(feature = "coconut")]
nyxd_urls: Option<Vec<url::Url>>,
#[cfg(feature = "coconut")]
enabled_credentials_mode: Option<bool>,
}
@@ -78,35 +77,29 @@ pub(crate) async fn execute(args: &Cli) -> Result<(), Box<dyn Error + Send + Syn
Ok(())
}
pub(crate) fn override_config(mut config: Config, args: OverrideConfig) -> Config {
config = config
pub(crate) fn override_config(config: Config, args: OverrideConfig) -> Config {
config
.with_optional(Config::with_disabled_socket, args.disable_socket)
.with_base(BaseConfig::with_high_default_traffic_volume, args.fastmode)
.with_base(BaseConfig::with_disabled_cover_traffic, args.no_cover)
.with_optional(Config::with_port, args.port)
.with_optional(Config::with_host, args.host)
.with_optional_custom_env_ext(
BaseConfig::with_custom_nym_apis,
args.nym_apis,
network_defaults::var_names::NYM_API,
config::parse_urls,
);
#[cfg(feature = "coconut")]
{
config = config
.with_optional_custom_env_ext(
BaseConfig::with_custom_nyxd,
args.nyxd_urls,
network_defaults::var_names::NYXD,
config::parse_urls,
)
.with_optional_ext(
BaseConfig::with_disabled_credentials,
args.enabled_credentials_mode.map(|b| !b),
);
}
config
)
.with_optional_custom_env_ext(
BaseConfig::with_custom_nyxd,
args.nyxd_urls,
network_defaults::var_names::NYXD,
config::parse_urls,
)
.with_optional_ext(
BaseConfig::with_disabled_credentials,
args.enabled_credentials_mode.map(|b| !b),
)
}
#[cfg(test)]
+7 -6
View File
@@ -2,6 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
use std::error::Error;
use std::net::IpAddr;
use crate::{
client::{config::Config, SocketClient},
@@ -22,7 +23,6 @@ pub(crate) struct Run {
id: String,
/// Comma separated list of rest endpoints of the nyxd validators
#[cfg(feature = "coconut")]
#[clap(long, alias = "nymd_validators", value_delimiter = ',')]
nyxd_urls: Option<Vec<url::Url>>,
@@ -44,6 +44,10 @@ pub(crate) struct Run {
#[clap(short, long)]
port: Option<u16>,
/// Ip for the socket (if applicable) to listen for requests.
#[clap(long)]
host: Option<IpAddr>,
/// Mostly debug-related option to increase default traffic rate so that you would not need to
/// modify config post init
#[clap(long, hide = true)]
@@ -55,7 +59,6 @@ pub(crate) struct Run {
/// Set this client to work in a enabled credentials mode that would attempt to use gateway
/// with bandwidth credential requirement.
#[cfg(feature = "coconut")]
#[clap(long)]
enabled_credentials_mode: Option<bool>,
}
@@ -66,12 +69,10 @@ impl From<Run> for OverrideConfig {
nym_apis: run_config.nym_apis,
disable_socket: run_config.disable_socket,
port: run_config.port,
host: run_config.host,
fastmode: run_config.fastmode,
no_cover: run_config.no_cover,
#[cfg(feature = "coconut")]
nyxd_urls: run_config.nyxd_urls,
#[cfg(feature = "coconut")]
enabled_credentials_mode: run_config.enabled_credentials_mode,
}
}
@@ -99,7 +100,7 @@ fn version_check(cfg: &Config) -> bool {
pub(crate) async fn execute(args: &Run) -> Result<(), Box<dyn Error + Send + Sync>> {
let id = &args.id;
let mut config = match Config::load_from_file(Some(id)) {
let mut config = match Config::load_from_file(id) {
Ok(cfg) => cfg,
Err(err) => {
error!("Failed to load config for {}. Are you sure you have run `init` before? (Error was: {err})", id);
+8 -22
View File
@@ -17,36 +17,26 @@ fn fail_upgrade<D1: Display, D2: Display>(from_version: D1, to_version: D2) -> !
}
fn print_start_upgrade<D1: Display, D2: Display>(from: D1, to: D2) {
println!(
"\n==================\nTrying to upgrade client from {} to {} ...",
from, to
);
println!("\n==================\nTrying to upgrade client from {from} to {to} ...");
}
fn print_failed_upgrade<D1: Display, D2: Display>(from: D1, to: D2) {
eprintln!(
"Upgrade from {} to {} failed!\n==================\n",
from, to
);
eprintln!("Upgrade from {from} to {to} failed!\n==================\n");
}
fn print_successful_upgrade<D1: Display, D2: Display>(from: D1, to: D2) {
println!(
"Upgrade from {} to {} was successful!\n==================\n",
from, to
);
println!("Upgrade from {from} to {to} was successful!\n==================\n");
}
fn outdated_upgrade(config_version: &Version, package_version: &Version) -> ! {
eprintln!(
"Cannot perform upgrade from {} to {}. Your version is too old to perform the upgrade.!",
config_version, package_version
"Cannot perform upgrade from {config_version} to {package_version}. Your version is too old to perform the upgrade.!"
);
process::exit(1)
}
fn unsupported_upgrade(current_version: &Version, config_version: &Version) -> ! {
eprintln!("Cannot perform upgrade from {} to {}. Please let the developers know about this issue if you expected it to work!", config_version, current_version);
eprintln!("Cannot perform upgrade from {config_version} to {current_version}. Please let the developers know about this issue if you expected it to work!");
process::exit(1)
}
@@ -65,8 +55,7 @@ fn parse_config_version(config: &Config) -> Version {
if version.is_prerelease() || !version.build.is_empty() {
eprintln!(
"Trying to upgrade from a non-released version {}. This is not supported!",
version
"Trying to upgrade from a non-released version {version}. This is not supported!"
);
process::exit(1)
}
@@ -81,10 +70,7 @@ fn parse_package_version() -> Version {
// however, we are not using them ourselves at the moment and hence it should be fine.
// if we change our mind, we could easily tweak this code
if version.is_prerelease() || !version.build.is_empty() {
eprintln!(
"Trying to upgrade to a non-released version {}. This is not supported!",
version
);
eprintln!("Trying to upgrade to a non-released version {version}. This is not supported!");
process::exit(1)
}
@@ -145,7 +131,7 @@ pub(crate) fn execute(args: &Upgrade) {
let id = &args.id;
let existing_config = Config::load_from_file(Some(id)).unwrap_or_else(|err| {
let existing_config = Config::load_from_file(id).unwrap_or_else(|err| {
eprintln!("failed to load existing config file! - {err}");
process::exit(1)
});
+2 -19
View File
@@ -3,7 +3,7 @@
use std::error::Error;
use clap::{crate_version, Parser};
use clap::{crate_name, crate_version, Parser};
use logging::setup_logging;
use network_defaults::setup_env;
@@ -15,26 +15,9 @@ pub mod websocket;
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
setup_logging();
println!("{}", banner());
println!("{}", logging::banner(crate_name!(), crate_version!()));
let args = commands::Cli::parse();
setup_env(args.config_env_file.as_ref());
commands::execute(&args).await
}
fn banner() -> String {
format!(
r#"
_ __ _ _ _ __ ___
| '_ \| | | | '_ \ _ \
| | | | |_| | | | | | |
|_| |_|\__, |_| |_| |_|
|___/
(client - version {:})
"#,
crate_version!()
)
}
+2 -6
View File
@@ -27,17 +27,13 @@ use tokio_tungstenite::{
};
use websocket_requests::{requests::ClientRequest, responses::ServerResponse};
#[derive(Default)]
enum ReceivedResponseType {
#[default]
Binary,
Text,
}
impl Default for ReceivedResponseType {
fn default() -> Self {
ReceivedResponseType::Binary
}
}
pub(crate) struct HandlerBuilder {
msg_input: InputMessageSender,
client_connection_tx: ConnectionCommandSender,
+3 -3
View File
@@ -3,6 +3,7 @@
use super::handler::HandlerBuilder;
use log::*;
use std::net::IpAddr;
use std::{net::SocketAddr, process, sync::Arc};
use tokio::io::AsyncWriteExt;
use tokio::{sync::Notify, task::JoinHandle};
@@ -24,10 +25,9 @@ pub(crate) struct Listener {
}
impl Listener {
pub(crate) fn new(port: u16) -> Self {
pub(crate) fn new(host: IpAddr, port: u16) -> Self {
Listener {
// unless we find compelling reason not to, just listen on local only
address: SocketAddr::new("127.0.0.1".parse().unwrap(), port),
address: SocketAddr::new(host, port),
state: State::AwaitingConnection,
}
}
@@ -84,7 +84,7 @@ impl TryFrom<u8> for ErrorKind {
n => Err(Error::new(
ErrorKind::MalformedResponse,
format!("invalid error code {}", n),
format!("invalid error code {n}"),
)),
}
}
+9 -7
View File
@@ -1,6 +1,6 @@
[package]
name = "nym-socks5-client"
version = "1.1.5"
version = "1.1.8"
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"
@@ -15,7 +15,7 @@ clap = { version = "4.0", features = ["cargo", "derive"] }
dirs = "4.0"
futures = "0.3"
lazy_static = "1.4.0"
log = "0.4"
log = { workspace = true }
pin-project = "1.0"
pretty_env_logger = "0.4"
rand = { version = "0.7.3", features = ["wasm-bindgen"] }
@@ -23,18 +23,19 @@ serde = { version = "1.0", features = ["derive"] } # for config serialization/de
serde_json = "1.0.89"
tap = "1.0.1"
thiserror = "1.0.34"
tokio = { version = "1.21.2", features = ["rt-multi-thread", "net", "signal"] }
tokio = { version = "1.24.1", features = ["rt-multi-thread", "net", "signal"] }
url = "2.2"
# internal
build-information = { path = "../../common/build-information" }
client-core = { path = "../client-core", features = ["fs-surb-storage"] }
client-connections = { path = "../../common/client-connections" }
coconut-interface = { path = "../../common/coconut-interface", optional = true }
coconut-interface = { path = "../../common/coconut-interface" }
config = { path = "../../common/config" }
completions = { path = "../../common/completions" }
credential-storage = { path = "../../common/credential-storage" }
credentials = { path = "../../common/credentials", optional = true }
credential-storage = { path = "../../common/credential-storage", optional = true }
mobile-storage = { path = "../../common/mobile-storage", optional = true }
credentials = { path = "../../common/credentials" }
crypto = { path = "../../common/crypto" }
logging = { path = "../../common/logging"}
gateway-client = { path = "../../common/client-libs/gateway-client" }
@@ -51,5 +52,6 @@ validator-client = { path = "../../common/client-libs/validator-client", feature
version-checker = { path = "../../common/version-checker" }
[features]
coconut = ["coconut-interface", "credentials", "gateway-requests/coconut", "gateway-client/coconut", "credentials/coconut", "client-core/coconut"]
default = ["credential-storage"]
eth = []
mobile = ["mobile-storage", "gateway-client/mobile"]
+9 -7
View File
@@ -18,7 +18,7 @@ mod template;
const DEFAULT_CONNECTION_START_SURBS: u32 = 20;
const DEFAULT_PER_REQUEST_SURBS: u32 = 3;
#[derive(Debug, Default, Deserialize, PartialEq, Serialize)]
#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct Config {
#[serde(flatten)]
@@ -36,10 +36,12 @@ impl NymConfig for Config {
}
fn default_root_directory() -> PathBuf {
dirs::home_dir()
.expect("Failed to evaluate $HOME value")
.join(".nym")
.join("socks5-clients")
#[cfg(not(feature = "mobile"))]
let base_dir = dirs::home_dir().expect("Failed to evaluate $HOME value");
#[cfg(feature = "mobile")]
let base_dir = PathBuf::from("/tmp");
base_dir.join(".nym").join("socks5-clients")
}
fn try_default_root_directory() -> Option<PathBuf> {
@@ -176,7 +178,7 @@ impl Config {
}
}
#[derive(Debug, Deserialize, PartialEq, Eq, Serialize)]
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct Socks5 {
/// The port on which the client will be listening for incoming requests
@@ -214,7 +216,7 @@ impl Default for Socks5 {
}
}
#[derive(Debug, Deserialize, PartialEq, Eq, Serialize)]
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct Socks5Debug {
/// Number of reply SURBs attached to each `Request::Connect` message.
+59 -50
View File
@@ -8,9 +8,12 @@ use crate::socks::{
authentication::{AuthenticationMethods, Authenticator, User},
server::SphinxSocksServer,
};
use client_core::client::base_client::{
non_wasm_helpers, BaseClientBuilder, ClientInput, ClientOutput, ClientState,
};
#[cfg(feature = "mobile")]
use client_core::client::base_client::helpers::setup_empty_reply_surb_backend;
#[cfg(not(feature = "mobile"))]
use client_core::client::base_client::non_wasm_helpers;
use client_core::client::base_client::{BaseClientBuilder, ClientInput, ClientOutput, ClientState};
use client_core::client::key_manager::KeyManager;
use client_core::config::persistence::key_pathfinder::ClientKeyPathfinder;
use futures::channel::mpsc;
@@ -19,7 +22,8 @@ use gateway_client::bandwidth::BandwidthController;
use log::*;
use nymsphinx::addressing::clients::Recipient;
use std::error::Error;
use task::{wait_for_signal_and_error, TaskClient, TaskManager};
use task::{TaskClient, TaskManager};
use validator_client::nyxd::QueryNyxdClient;
pub mod config;
@@ -53,42 +57,45 @@ impl NymClient {
}
}
async fn create_bandwidth_controller(config: &Config) -> BandwidthController {
#[cfg(feature = "coconut")]
let bandwidth_controller = {
let details = network_defaults::NymNetworkDetails::new_from_env();
let mut client_config =
validator_client::Config::try_from_nym_network_details(&details)
.expect("failed to construct validator client config");
let nyxd_url = config
.get_base()
.get_validator_endpoints()
.pop()
.expect("No nyxd validator endpoint provided");
let api_url = config
.get_base()
.get_nym_api_endpoints()
.pop()
.expect("No validator api endpoint provided");
// overwrite env configuration with config URLs
client_config = client_config.with_urls(nyxd_url, api_url);
let client = validator_client::Client::new_query(client_config)
.expect("Could not construct query client");
let coconut_api_clients =
validator_client::CoconutApiClient::all_coconut_api_clients(&client)
.await
.expect("Could not query api clients");
BandwidthController::new(
credential_storage::initialise_storage(config.get_base().get_database_path()).await,
coconut_api_clients,
)
};
#[cfg(not(feature = "coconut"))]
let bandwidth_controller = BandwidthController::new(
credential_storage::initialise_storage(config.get_base().get_database_path()).await,
)
.expect("Could not create bandwidth controller");
bandwidth_controller
pub fn new_with_keys(config: Config, key_manager: Option<KeyManager>) -> Self {
let key_manager = key_manager.unwrap_or_else(|| {
let pathfinder = ClientKeyPathfinder::new_from_config(config.get_base());
KeyManager::load_keys(&pathfinder).expect("failed to load stored keys")
});
NymClient {
config,
key_manager,
}
}
async fn create_bandwidth_controller(config: &Config) -> BandwidthController<QueryNyxdClient> {
let details = network_defaults::NymNetworkDetails::new_from_env();
let mut client_config = validator_client::Config::try_from_nym_network_details(&details)
.expect("failed to construct validator client config");
let nyxd_url = config
.get_base()
.get_validator_endpoints()
.pop()
.expect("No nyxd validator endpoint provided");
let api_url = config
.get_base()
.get_nym_api_endpoints()
.pop()
.expect("No validator api endpoint provided");
// overwrite env configuration with config URLs
client_config = client_config.with_urls(nyxd_url, api_url);
let client = validator_client::Client::new_query(client_config)
.expect("Could not construct query client");
#[cfg(not(feature = "mobile"))]
let storage =
credential_storage::initialise_storage(config.get_base().get_database_path()).await;
#[cfg(feature = "mobile")]
let storage = mobile_storage::PersistentStorage {};
BandwidthController::new(storage, client)
}
fn start_socks5_listener(
@@ -147,16 +154,9 @@ impl NymClient {
/// blocking version of `start` method. Will run forever (or until SIGINT is sent)
pub async fn run_forever(self) -> Result<(), Box<dyn Error + Send + Sync>> {
let mut shutdown = self.start().await?;
let res = wait_for_signal_and_error(&mut shutdown).await;
log::info!("Sending shutdown");
shutdown.signal_shutdown().ok();
log::info!("Waiting for tasks to finish... (Press ctrl-c to force)");
shutdown.wait_for_shutdown().await;
let shutdown = self.start().await?;
let res = shutdown.catch_interrupt().await;
log::info!("Stopping nym-socks5-client");
res
}
@@ -208,17 +208,26 @@ impl NymClient {
}
pub async fn start(self) -> Result<TaskManager, Socks5ClientError> {
#[cfg(not(feature = "mobile"))]
let base_builder = BaseClientBuilder::new_from_base_config(
self.config.get_base(),
self.key_manager,
Some(Self::create_bandwidth_controller(&self.config).await),
non_wasm_helpers::setup_fs_reply_surb_backend(
self.config.get_base().get_reply_surb_database_path(),
Some(self.config.get_base().get_reply_surb_database_path()),
self.config.get_debug_settings(),
)
.await?,
);
#[cfg(feature = "mobile")]
let base_builder = BaseClientBuilder::<_, QueryNyxdClient>::new_from_base_config(
self.config.get_base(),
self.key_manager,
None,
setup_empty_reply_surb_backend(self.config.get_debug_settings()),
);
let self_address = base_builder.as_mix_recipient();
let mut started_client = base_builder.start_base().await?;
let client_input = started_client.client_input.register_producer();
+7 -13
View File
@@ -43,7 +43,6 @@ pub(crate) struct Init {
force_register_gateway: bool,
/// Comma separated list of rest endpoints of the nyxd validators
#[cfg(feature = "coconut")]
#[clap(long, alias = "nymd_validators", value_delimiter = ',')]
nyxd_urls: Option<Vec<url::Url>>,
@@ -67,7 +66,6 @@ pub(crate) struct Init {
/// Set this client to work in a enabled credentials mode that would attempt to use gateway
/// with bandwidth credential requirement.
#[cfg(feature = "coconut")]
#[clap(long)]
enabled_credentials_mode: Option<bool>,
@@ -84,10 +82,7 @@ impl From<Init> for OverrideConfig {
use_anonymous_replies: init_config.use_reply_surbs,
fastmode: init_config.fastmode,
no_cover: init_config.no_cover,
#[cfg(feature = "coconut")]
nyxd_urls: init_config.nyxd_urls,
#[cfg(feature = "coconut")]
enabled_credentials_mode: init_config.enabled_credentials_mode,
}
}
@@ -122,18 +117,17 @@ pub(crate) async fn execute(args: &Init) -> Result<(), Socks5ClientError> {
let id = &args.id;
let provider_address = &args.provider;
let already_init = Config::default_config_file_path(Some(id)).exists();
let already_init = Config::default_config_file_path(id).exists();
if already_init {
println!(
"SOCKS5 client \"{}\" was already initialised before! \
Config information will be overwritten (but keys will be kept)!",
id
);
println!("SOCKS5 client \"{id}\" was already initialised before");
}
// Usually you only register with the gateway on the first init, however you can force
// re-registering if wanted.
let user_wants_force_register = args.force_register_gateway;
if user_wants_force_register {
println!("Instructed to force registering gateway. This might overwrite keys!");
}
// If the client was already initialized, don't generate new keys and don't re-register with
// the gateway (because this would create a new shared key).
@@ -151,9 +145,9 @@ pub(crate) async fn execute(args: &Init) -> Result<(), Socks5ClientError> {
// Setup gateway by either registering a new one, or creating a new config from the selected
// one but with keys kept, or reusing the gateway configuration.
let gateway = client_core::init::setup_gateway::<Config, _>(
let gateway = client_core::init::setup_gateway_from_config::<Config, _>(
register_gateway,
user_chosen_gateway_id.map(|id| id.to_base58_string()),
user_chosen_gateway_id,
config.get_base(),
)
.await
+13 -23
View File
@@ -60,10 +60,7 @@ pub(crate) struct OverrideConfig {
use_anonymous_replies: Option<bool>,
fastmode: bool,
no_cover: bool,
#[cfg(feature = "coconut")]
nyxd_urls: Option<Vec<url::Url>>,
#[cfg(feature = "coconut")]
enabled_credentials_mode: Option<bool>,
}
@@ -80,8 +77,8 @@ pub(crate) async fn execute(args: &Cli) -> Result<(), Box<dyn Error + Send + Syn
Ok(())
}
pub(crate) fn override_config(mut config: Config, args: OverrideConfig) -> Config {
config = config
pub(crate) fn override_config(config: Config, args: OverrideConfig) -> Config {
config
.with_base(BaseConfig::with_high_default_traffic_volume, args.fastmode)
.with_base(BaseConfig::with_disabled_cover_traffic, args.no_cover)
.with_optional(Config::with_anonymous_replies, args.use_anonymous_replies)
@@ -91,24 +88,17 @@ pub(crate) fn override_config(mut config: Config, args: OverrideConfig) -> Confi
args.nym_apis,
network_defaults::var_names::NYM_API,
config::parse_urls,
);
#[cfg(feature = "coconut")]
{
config = config
.with_optional_custom_env_ext(
BaseConfig::with_custom_nyxd,
args.nyxd_urls,
network_defaults::var_names::NYXD,
config::parse_urls,
)
.with_optional_ext(
BaseConfig::with_disabled_credentials,
args.enabled_credentials_mode.map(|b| !b),
);
}
config
)
.with_optional_custom_env_ext(
BaseConfig::with_custom_nyxd,
args.nyxd_urls,
network_defaults::var_names::NYXD,
config::parse_urls,
)
.with_optional_ext(
BaseConfig::with_disabled_credentials,
args.enabled_credentials_mode.map(|b| !b),
)
}
#[cfg(test)]
+1 -6
View File
@@ -43,7 +43,6 @@ pub(crate) struct Run {
gateway: Option<identity::PublicKey>,
/// Comma separated list of rest endpoints of the nyxd validators
#[cfg(feature = "coconut")]
#[clap(long, alias = "nymd_validators", value_delimiter = ',')]
nyxd_urls: Option<Vec<url::Url>>,
@@ -66,7 +65,6 @@ pub(crate) struct Run {
/// Set this client to work in a enabled credentials mode that would attempt to use gateway
/// with bandwidth credential requirement.
#[cfg(feature = "coconut")]
#[clap(long)]
enabled_credentials_mode: Option<bool>,
}
@@ -79,10 +77,7 @@ impl From<Run> for OverrideConfig {
use_anonymous_replies: run_config.use_anonymous_replies,
fastmode: run_config.fastmode,
no_cover: run_config.no_cover,
#[cfg(feature = "coconut")]
nyxd_urls: run_config.nyxd_urls,
#[cfg(feature = "coconut")]
enabled_credentials_mode: run_config.enabled_credentials_mode,
}
}
@@ -113,7 +108,7 @@ fn version_check(cfg: &Config) -> bool {
pub(crate) async fn execute(args: &Run) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
let id = &args.id;
let mut config = match Config::load_from_file(Some(id)) {
let mut config = match Config::load_from_file(id) {
Ok(cfg) => cfg,
Err(err) => {
error!("Failed to load config for {}. Are you sure you have run `init` before? (Error was: {err})", id);
+1 -1
View File
@@ -144,7 +144,7 @@ pub(crate) fn execute(args: &Upgrade) {
let id = &args.id;
let existing_config = Config::load_from_file(Some(id)).unwrap_or_else(|err| {
let existing_config = Config::load_from_file(id).unwrap_or_else(|err| {
eprintln!("failed to load existing config file! - {err}");
process::exit(1)
});
+2 -19
View File
@@ -3,7 +3,7 @@
use std::error::Error;
use clap::{crate_version, Parser};
use clap::{crate_name, crate_version, Parser};
use logging::setup_logging;
use network_defaults::setup_env;
@@ -15,26 +15,9 @@ pub mod socks;
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
setup_logging();
println!("{}", banner());
println!("{}", logging::banner(crate_name!(), crate_version!()));
let args = commands::Cli::parse();
setup_env(args.config_env_file.as_ref());
commands::execute(&args).await
}
fn banner() -> String {
format!(
r#"
_ __ _ _ _ __ ___
| '_ \| | | | '_ \ _ \
| | | | |_| | | | | | |
|_| |_|\__, |_| |_| |_|
|___/
(socks5 proxy - version {:})
"#,
crate_version!()
)
}
+6 -5
View File
@@ -15,15 +15,16 @@ crate-type = ["cdylib", "rlib"]
[features]
default = ["console_error_panic_hook"]
offline-test = []
coconut = ["coconut-interface", "credentials", "gateway-client/coconut"]
[dependencies]
futures = "0.3"
js-sys = "0.3"
rand = { version = "0.7.3", features = ["wasm-bindgen"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
anyhow = "1.0"
serde-wasm-bindgen = "0.4"
tokio = { version = "1.21.2", features = ["sync"] }
tokio = { version = "1.24.1", features = ["sync"] }
url = "2.2"
wasm-bindgen = { version = "=0.2.83", features = ["serde-serialize"] }
wasm-bindgen-futures = "0.4"
@@ -31,12 +32,12 @@ wasm-bindgen-futures = "0.4"
# internal
client-core = { path = "../client-core", default-features = false, features = ["wasm"] }
client-connections = { path = "../../common/client-connections" }
coconut-interface = { path = "../../common/coconut-interface", optional = true }
credentials = { path = "../../common/credentials", optional = true }
coconut-interface = { path = "../../common/coconut-interface" }
credentials = { path = "../../common/credentials" }
crypto = { path = "../../common/crypto" }
nymsphinx = { path = "../../common/nymsphinx" }
topology = { path = "../../common/topology" }
gateway-client = { path = "../../common/client-libs/gateway-client", default-features = false, features = ["wasm", "coconut"] }
gateway-client = { path = "../../common/client-libs/gateway-client", default-features = false, features = ["wasm"] }
validator-client = { path = "../../common/client-libs/validator-client", default-features = false }
wasm-utils = { path = "../../common/wasm-utils" }
task = { path = "../../common/task" }
+9 -8
View File
@@ -16,11 +16,7 @@ They should be implemented soon. You can build your applications, but don't rely
## Using it
See the [Nym docs](https://nymtech.net/docs).
### Demo
There's a demo web application in the `js-example` folder. To run it, first make sure you've got a recent `npm` installed, then follow the instructions in its README.
See the [SDK directory](../../sdk/typescript/examples) for examples on how to use it and the NPM packages available.
## Developing
@@ -36,8 +32,13 @@ To be clear, this is not something that most JS developers need to worry about,
### Packaging
If you're a Nym platform developer who's made changes to the Rust (or JS) files and wants to re-publish the package to NPM, here's how you do it:
If you're a Nym platform developer who's made changes to the Rust files and wants to re-publish the package to NPM, here's how you do it:
1. bump version numbers as necessary for SemVer
2. `wasm-pack build --scope nymproject` builds the wasm binaries into the `pkg` directory (not in source control)
3. `cd pkg && npm publish --access=public` will publish your changed package to NPM
2. go the `sdk/typescript` directory (off the project root)
3. run:
```
yarn
yarn build
yarn publish
```
@@ -1,217 +0,0 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use serde::{Deserialize, Serialize};
use wasm_bindgen::prelude::*;
use wasm_bindgen::JsCast;
#[wasm_bindgen(typescript_custom_section)]
const TS_DEFS: &'static str = r#"
export interface BinaryMessage {
kind: number,
payload: Uint8Array;
headers: string,
}
export interface StringMessage {
kind: number,
payload: string;
}
"#;
#[wasm_bindgen]
extern "C" {
#[wasm_bindgen(typescript_type = "BinaryMessage")]
pub type IBinaryMessage;
#[wasm_bindgen(typescript_type = "StringMessage")]
pub type IStringMessage;
}
#[derive(Serialize, Deserialize)]
pub struct BinaryMessage {
pub kind: u8,
pub payload: Vec<u8>,
pub headers: String,
}
#[derive(Serialize, Deserialize)]
pub struct StringMessage {
pub kind: u8,
pub payload: String,
}
/// Create a new binary message with a user-specified `kind`.
#[wasm_bindgen]
pub fn create_binary_message(kind: u8, payload: Vec<u8>) -> Vec<u8> {
create_binary_message_with_headers(kind, payload, "".to_string())
}
/// Create a new message with a UTF-8 encoded string `payload` and a user-specified `kind`.
#[wasm_bindgen]
pub fn create_binary_message_from_string(kind: u8, payload: String) -> Vec<u8> {
create_binary_message_with_headers(kind, payload.as_bytes().to_vec(), "".to_string())
}
/// Create a new binary message with a user-specified `kind`, and `headers` as a string.
#[wasm_bindgen]
pub fn create_binary_message_with_headers(kind: u8, payload: Vec<u8>, headers: String) -> Vec<u8> {
let headers = headers.as_bytes().to_vec();
let size = (headers.len() as u64).to_be_bytes().to_vec();
vec![vec![kind], size, headers, payload].concat()
}
/// Parse the `kind` and byte array `payload` from a byte array
#[wasm_bindgen]
pub async fn parse_binary_message(message: Vec<u8>) -> Result<IBinaryMessage, JsError> {
if message.len() < 2 {
return Err(JsError::new(
"Could not parse message, as less than 2 bytes long",
));
}
let (kind, _headers, payload) = parse_binary_payload(&message);
Ok(serde_wasm_bindgen::to_value(&BinaryMessage {
kind,
payload: payload.to_vec(),
headers: "".to_string(),
})
.unwrap()
.unchecked_into::<IBinaryMessage>())
}
/// Parse the `kind` and byte array `payload` from a byte array with headers
#[wasm_bindgen]
pub async fn parse_binary_message_with_headers(
message: Vec<u8>,
) -> Result<IBinaryMessage, JsError> {
if message.len() < 2 {
return Err(JsError::new(
"Could not parse message, as less than 2 bytes long",
));
}
let (kind, headers, payload) = parse_binary_payload(&message);
Ok(serde_wasm_bindgen::to_value(&BinaryMessage {
kind,
payload: payload.to_vec(),
headers,
})
.unwrap()
.unchecked_into::<IBinaryMessage>())
}
/// Parse the `kind` and UTF-8 string `payload` from a byte array with headers
#[wasm_bindgen]
pub async fn parse_string_message_with_headers(
message: Vec<u8>,
) -> Result<IStringMessage, JsError> {
if message.len() < 2 {
return Err(JsError::new(
"Could not parse message, as less than 2 bytes long",
));
}
let (kind, _headers, payload) = parse_binary_payload(&message);
let payload = String::from_utf8_lossy(payload).into_owned();
Ok(
serde_wasm_bindgen::to_value(&StringMessage { kind, payload })
.unwrap()
.unchecked_into::<IStringMessage>(),
)
}
pub(crate) fn parse_binary_payload(message: &[u8]) -> (u8, String, &[u8]) {
// 1st byte is the kind
let kind = message[0];
// then the size as u64 big endian
let mut size = [0u8; 8];
size.clone_from_slice(&message[1..9]);
let size = u64::from_be_bytes(size) as usize;
// then the headers
let headers = String::from_utf8_lossy(&message[9..9 + size]).into_owned();
// finally the payload
let payload = &message[9 + size..];
(kind, headers, payload)
}
/// Parse the `kind` and UTF-8 string `payload` from a byte array
#[wasm_bindgen]
pub async fn parse_string_message(message: Vec<u8>) -> Result<IStringMessage, JsError> {
if message.len() < 2 {
return Err(JsError::new(
"Could not parse message, as less than 2 bytes long",
));
}
let kind = message[0];
let payload = String::from_utf8_lossy(&message[1..]).into_owned();
Ok(
serde_wasm_bindgen::to_value(&StringMessage { kind, payload })
.unwrap()
.unchecked_into::<IStringMessage>(),
)
}
#[cfg(test)]
mod tests {
use super::{create_binary_message_with_headers, parse_binary_payload};
use wasm_bindgen_test::*;
#[wasm_bindgen_test]
fn test_binary_with_headers() {
let message_as_bytes = create_binary_message_with_headers(
42u8,
vec![0u8, 1u8, 2u8],
"test headers".to_string(),
);
// calculate header size
let headers = "test headers".as_bytes().to_vec();
let size = headers.len();
// the expected size
let expected_size = 12;
assert_eq!(size, expected_size);
assert_eq!(message_as_bytes[0], 42u8);
assert_eq!(message_as_bytes[1..9], 12u64.to_be_bytes());
assert_eq!(
message_as_bytes[9 + expected_size..9 + expected_size + 3],
vec![0u8, 1u8, 2u8]
);
let res = parse_binary_payload(&message_as_bytes);
assert_eq!(res.0, 42u8);
assert_eq!(res.1, "test headers".to_string());
assert_eq!(res.2, vec![0u8, 1u8, 2u8]);
}
#[wasm_bindgen_test]
fn test_binary_with_empty_headers() {
let message_as_bytes =
create_binary_message_with_headers(42u8, vec![0u8, 1u8, 2u8], "".to_string());
let expected_size = 0;
assert_eq!(message_as_bytes[0], 42u8);
assert_eq!(message_as_bytes[1..9], 0u64.to_be_bytes());
assert_eq!(
message_as_bytes[9 + expected_size..9 + expected_size + 3],
vec![0u8, 1u8, 2u8]
);
let res = parse_binary_payload(&message_as_bytes);
assert_eq!(res.0, 42u8);
assert_eq!(res.1, "".to_string());
assert_eq!(res.2, vec![0u8, 1u8, 2u8]);
}
}
+15 -5
View File
@@ -125,7 +125,11 @@ pub struct Debug {
/// Defines maximum amount of time the client is going to wait for reply surbs before explicitly asking
/// for more even though in theory they wouldn't need to.
pub maximum_reply_surb_waiting_period_ms: u64,
pub maximum_reply_surb_rerequest_waiting_period_ms: u64,
/// Defines maximum amount of time the client is going to wait for reply surbs before
/// deciding it's never going to get them and would drop all pending messages
pub maximum_reply_surb_drop_waiting_period_ms: u64,
/// Defines maximum amount of time given reply surb is going to be valid for.
/// This is going to be superseded by key rotation once implemented.
@@ -168,8 +172,11 @@ impl From<Debug> for ConfigDebug {
minimum_reply_surb_request_size: debug.minimum_reply_surb_request_size,
maximum_reply_surb_request_size: debug.maximum_reply_surb_request_size,
maximum_allowed_reply_surb_request_size: debug.maximum_allowed_reply_surb_request_size,
maximum_reply_surb_waiting_period: Duration::from_millis(
debug.maximum_reply_surb_waiting_period_ms,
maximum_reply_surb_rerequest_waiting_period: Duration::from_millis(
debug.maximum_reply_surb_rerequest_waiting_period_ms,
),
maximum_reply_surb_drop_waiting_period: Duration::from_millis(
debug.maximum_reply_surb_drop_waiting_period_ms,
),
maximum_reply_surb_age: Duration::from_millis(debug.maximum_reply_surb_age_ms),
maximum_reply_key_age: Duration::from_millis(debug.maximum_reply_key_age_ms),
@@ -200,8 +207,11 @@ impl From<ConfigDebug> for Debug {
minimum_reply_surb_request_size: debug.minimum_reply_surb_request_size,
maximum_reply_surb_request_size: debug.maximum_reply_surb_request_size,
maximum_allowed_reply_surb_request_size: debug.maximum_allowed_reply_surb_request_size,
maximum_reply_surb_waiting_period_ms: debug
.maximum_reply_surb_waiting_period
maximum_reply_surb_rerequest_waiting_period_ms: debug
.maximum_reply_surb_rerequest_waiting_period
.as_millis() as u64,
maximum_reply_surb_drop_waiting_period_ms: debug
.maximum_reply_surb_drop_waiting_period
.as_millis() as u64,
maximum_reply_surb_age_ms: debug.maximum_reply_surb_age.as_millis() as u64,
maximum_reply_key_age_ms: debug.maximum_reply_key_age.as_millis() as u64,
+2 -1
View File
@@ -11,6 +11,7 @@ use client_core::client::base_client::{
use client_core::client::replies::reply_storage::browser_backend;
use client_core::client::{inbound_messages::InputMessage, key_manager::KeyManager};
use gateway_client::bandwidth::BandwidthController;
use gateway_client::wasm_mockups::SigningNyxdClient;
use js_sys::Promise;
use nymsphinx::addressing::clients::Recipient;
use nymsphinx::anonymous_replies::requests::AnonymousSenderTag;
@@ -47,7 +48,7 @@ pub struct NymClientBuilder {
on_message: js_sys::Function,
// unimplemented:
bandwidth_controller: Option<BandwidthController>,
bandwidth_controller: Option<BandwidthController<SigningNyxdClient>>,
disabled_credentials: bool,
}
@@ -0,0 +1,238 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use serde::{Deserialize, Serialize};
use wasm_bindgen::prelude::*;
use wasm_bindgen::JsCast;
#[wasm_bindgen(typescript_custom_section)]
const TS_DEFS: &'static str = r#"
export interface EncodedPayload {
mimeType: string,
payload: Uint8Array;
headers: string,
}
"#;
#[wasm_bindgen]
extern "C" {
#[wasm_bindgen(typescript_type = "EncodedPayload")]
pub type IEncodedPayload;
}
#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct EncodedPayload {
pub mime_type: String,
pub payload: Vec<u8>,
pub headers: Option<String>,
}
#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct EncodedPayloadMetadata {
pub mime_type: String,
pub headers: Option<String>,
}
/// Encode a payload
#[wasm_bindgen]
pub fn encode_payload(mime_type: String, payload: Vec<u8>) -> Result<Vec<u8>, JsValue> {
encode_payload_with_headers(mime_type, payload, None)
}
/// Create a new binary message with a user-specified `kind`, and `headers` as a string.
#[wasm_bindgen]
pub fn encode_payload_with_headers(
mime_type: String,
payload: Vec<u8>,
headers: Option<String>,
) -> Result<Vec<u8>, JsValue> {
match serde_json::to_string(&EncodedPayloadMetadata { mime_type, headers }) {
Ok(metadata) => {
let metadata = metadata.as_bytes().to_vec();
let size = (metadata.len() as u64).to_be_bytes().to_vec();
Ok(vec![size, metadata, payload].concat())
}
Err(e) => Err(JsValue::from(JsError::new(
format!("Could not encode message: {}", e).as_str(),
))),
}
}
/// Parse the `kind` and byte array `payload` from a byte array
#[wasm_bindgen]
pub fn decode_payload(message: Vec<u8>) -> Result<IEncodedPayload, JsValue> {
if message.len() < 8 {
return Err(JsValue::from(JsError::new(
"Could not parse message, as less than 8 bytes long",
)));
}
match parse_payload(&message) {
Ok((metadata, payload)) => Ok(serde_wasm_bindgen::to_value(&EncodedPayload {
mime_type: metadata.mime_type,
payload: payload.to_vec(),
headers: metadata.headers,
})
.unwrap()
.unchecked_into::<IEncodedPayload>()),
Err(e) => Err(JsValue::from(JsError::new(
format!("Could not parse message: {}", e).as_str(),
))),
}
}
pub(crate) fn parse_payload(message: &[u8]) -> anyhow::Result<(EncodedPayloadMetadata, &[u8])> {
// 1st 8 bytes are the size (as u64 big endian)
let mut size = [0u8; 8];
size.clone_from_slice(&message[0..8]);
let size = u64::from_be_bytes(size) as usize;
// then the metadata
let metadata = String::from_utf8_lossy(&message[8..8 + size]).into_owned();
let metadata: EncodedPayloadMetadata = serde_json::from_str(metadata.as_str())?;
// finally the payload
let payload = &message[8 + size..];
Ok((metadata, payload))
}
/// Try parse a UTF-8 string from an array of bytes
#[wasm_bindgen]
pub fn parse_utf8_string(payload: Vec<u8>) -> String {
String::from_utf8_lossy(&payload).into_owned()
}
/// Converts a UTF-8 string into an array of bytes
///
/// This method is provided as a replacement for the mess of `atob`
/// (https://developer.mozilla.org/en-US/docs/Web/API/atob) helpers provided by browsers and NodeJS.
///
/// Feel free to use `atob` if you know you won't have problems with polyfills or encoding issues.
#[wasm_bindgen]
pub fn utf8_string_to_byte_array(message: String) -> Vec<u8> {
message.into_bytes()
}
#[cfg(test)]
mod tests {
use super::*;
use wasm_bindgen_test::*;
#[wasm_bindgen_test]
async fn test_encode_payload_with_headers() {
let message_as_bytes = encode_payload_with_headers(
"text/plain".to_string(),
vec![0u8, 1u8, 2u8],
Some("test headers".to_string()),
)
.unwrap();
// the expected message size
let size = message_as_bytes.len();
let expected_size = 61;
assert_eq!(size, expected_size);
let expected_header_size = 50usize;
assert_eq!(
message_as_bytes[0..8],
(expected_header_size as u64).to_be_bytes()
);
assert_eq!(
message_as_bytes[8 + expected_header_size..8 + expected_header_size + 3],
vec![0u8, 1u8, 2u8]
);
let res = parse_payload(&message_as_bytes).unwrap();
assert_eq!(res.0.mime_type, "text/plain");
assert_eq!(res.0.headers.unwrap(), "test headers".to_string());
assert_eq!(res.1, vec![0u8, 1u8, 2u8]);
}
#[wasm_bindgen_test]
async fn test_encode_payload_with_empty_headers() {
let message_as_bytes =
encode_payload_with_headers("text/plain".to_string(), vec![0u8, 1u8, 2u8], None)
.unwrap();
// the expected message size
let size = message_as_bytes.len();
let expected_size = 51;
assert_eq!(size, expected_size);
let expected_header_size = 40usize;
assert_eq!(
message_as_bytes[0..8],
(expected_header_size as u64).to_be_bytes()
);
assert_eq!(
message_as_bytes[8 + expected_header_size..8 + expected_header_size + 3],
vec![0u8, 1u8, 2u8]
);
let res = parse_payload(&message_as_bytes).unwrap();
assert_eq!(res.0.mime_type, "text/plain");
assert_eq!(res.0.headers, None);
assert_eq!(res.1, vec![0u8, 1u8, 2u8]);
}
#[wasm_bindgen_test]
async fn test_encode_payload_with_empty_headers_and_empty_mime_type() {
let message_as_bytes =
encode_payload_with_headers("".to_string(), vec![0u8, 1u8, 2u8], None).unwrap();
// the expected message size
let size = message_as_bytes.len();
let expected_size = 41;
assert_eq!(size, expected_size);
let expected_header_size = 30usize;
assert_eq!(
message_as_bytes[0..8],
(expected_header_size as u64).to_be_bytes()
);
assert_eq!(
message_as_bytes[8 + expected_header_size..8 + expected_header_size + 3],
vec![0u8, 1u8, 2u8]
);
let res = parse_payload(&message_as_bytes).unwrap();
assert_eq!(res.0.mime_type, "");
assert_eq!(res.0.headers, None);
assert_eq!(res.1, vec![0u8, 1u8, 2u8]);
}
#[wasm_bindgen_test]
async fn test_encode_payload_with_all_empty() {
let empty: Vec<u8> = vec![];
let message_as_bytes =
encode_payload_with_headers("".to_string(), empty.clone(), None).unwrap();
// the expected message size
let size = message_as_bytes.len();
let expected_size = 38;
assert_eq!(size, expected_size);
let expected_header_size = 30usize;
assert_eq!(
message_as_bytes[0..8],
(expected_header_size as u64).to_be_bytes()
);
assert_eq!(
message_as_bytes[8 + expected_header_size..8 + expected_header_size],
empty
);
let res = parse_payload(&message_as_bytes).unwrap();
assert_eq!(res.0.mime_type, "");
assert_eq!(res.0.headers, None);
assert_eq!(res.1, empty);
}
}
+4 -2
View File
@@ -3,12 +3,14 @@
use wasm_bindgen::prelude::*;
#[cfg(target_arch = "wasm32")]
pub mod binary_message_helper;
#[cfg(target_arch = "wasm32")]
mod client;
#[cfg(target_arch = "wasm32")]
pub mod encoded_payload_helper;
#[cfg(target_arch = "wasm32")]
pub mod gateway_selector;
#[cfg(target_arch = "wasm32")]
pub mod validation;
#[wasm_bindgen]
pub fn set_panic_hook() {
+35
View File
@@ -0,0 +1,35 @@
use nymsphinx::addressing::clients::Recipient;
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn validate_recipient(recipient: String) -> Result<(), JsError> {
match Recipient::try_from_base58_string(recipient) {
Ok(_) => Ok(()),
Err(e) => Err(JsError::new(format!("{}", e).as_str())),
}
}
#[cfg(test)]
mod tests {
use super::validate_recipient;
use wasm_bindgen_test::*;
#[wasm_bindgen_test]
fn test_recipient_validation_ok() {
let res = validate_recipient("DyQmXnst5NGGjzUZxRC5Bjs5bd7CBF3xMpsSmbRiizr2.GH6YTBP2NXU3AVqd8WjiTMVyeMjunXMEsp7gVCMEJqpD@336yuXAeGEgedRfqTJZsG2YV7P13QH1bHv1SjCZYarc9".to_string());
assert!(res.is_ok())
}
#[wasm_bindgen_test]
fn test_recipient_validation_fails() {
assert!(validate_recipient(" DyQmXnst5NGGjzUZxRC5Bjs5bd7CBF3xMpsSmbRiizr2.GH6YTBP2NXU3AVqd8WjiTMVyeMjunXMEsp7gVCMEJqpD@336yuXAeGEgedRfqTJZsG2YV7P13QH1bHv1SjCZYarc9".to_string()).is_err());
assert!(validate_recipient(
"DyQmXnst5NGGjzUZxRC5BjbRiizr2.GH6YTBP2NXU3AVqd8WD@336yuXAeGEgedRfqTJZQH1bHv1SjCZYarc9"
.to_string()
)
.is_err());
assert!(validate_recipient("🙀🙀🙀🙀".to_string()).is_err());
assert!(validate_recipient("".to_string()).is_err());
assert!(validate_recipient(" ".to_string()).is_err());
}
}
+1 -1
View File
@@ -7,4 +7,4 @@ edition = "2021"
[dependencies]
futures = "0.3"
log = "0.4.17"
log = { workspace = true }
+8 -7
View File
@@ -10,24 +10,25 @@ edition = "2021"
# TODO: (for this and other crates), similarly to 'tokio', import only required "futures" modules rather than
# the entire crate
futures = "0.3"
log = "0.4"
log = { workspace = true }
thiserror = "1.0"
url = "2.2"
rand = { version = "0.7.3", features = ["wasm-bindgen"] }
async-trait = { version = "0.1.51" }
tokio = { version = "1.21.2", features = ["macros"] }
tokio = { version = "1.24.1", features = ["macros"] }
# internal
coconut-interface = { path = "../../coconut-interface", optional = true }
coconut-interface = { path = "../../coconut-interface" }
credentials = { path = "../../credentials" }
crypto = { path = "../../crypto" }
gateway-requests = { path = "../../../gateway/gateway-requests" }
network-defaults = { path = "../../network-defaults" }
nymsphinx = { path = "../../nymsphinx" }
pemstore = { path = "../../pemstore" }
validator-client = { path = "../validator-client", optional = true }
validator-client = { path = "../validator-client" }
task = { path = "../../task" }
serde = { version = "1.0", features = ["derive"]}
mobile-storage = { path = "../../mobile-storage" }
[dependencies.tungstenite]
@@ -36,11 +37,11 @@ default-features = false
# non-wasm-only dependencies
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.tokio]
version = "1.21.2"
version = "1.24.1"
features = ["macros", "rt", "net", "sync", "time"]
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.tokio-stream]
version = "0.1.9"
version = "0.1.11"
features = ["net", "sync", "time"]
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.tokio-tungstenite]
@@ -79,5 +80,5 @@ features = ["js"]
#url = "2.1"
[features]
coconut = ["gateway-requests/coconut", "coconut-interface", "validator-client", "credentials/coconut"]
wasm = []
mobile = []
@@ -4,21 +4,31 @@
use crate::error::GatewayClientError;
#[cfg(target_arch = "wasm32")]
use crate::wasm_storage::Storage;
use crate::wasm_mockups::Storage;
#[cfg(not(target_arch = "wasm32"))]
#[cfg(not(feature = "mobile"))]
use credential_storage::storage::Storage;
#[cfg(all(target_arch = "wasm32", feature = "coconut"))]
use crate::wasm_storage::StorageError;
#[cfg(not(target_arch = "wasm32"))]
#[cfg(feature = "mobile")]
use mobile_storage::Storage;
#[cfg(all(not(target_arch = "wasm32"), feature = "coconut"))]
#[cfg(not(target_arch = "wasm32"))]
#[cfg(feature = "mobile")]
use mobile_storage::StorageError;
#[cfg(target_arch = "wasm32")]
use crate::wasm_mockups::StorageError;
#[cfg(not(target_arch = "wasm32"))]
#[cfg(not(feature = "mobile"))]
use credential_storage::error::StorageError;
#[cfg(feature = "coconut")]
#[cfg(target_arch = "wasm32")]
use crate::wasm_mockups::{Client, CosmWasmClient};
use std::str::FromStr;
#[cfg(feature = "coconut")]
use validator_client::client::CoconutApiClient;
#[cfg(feature = "coconut")]
#[cfg(not(target_arch = "wasm32"))]
use validator_client::{nyxd::CosmWasmClient, Client};
use {
coconut_interface::Base58,
credentials::coconut::{
@@ -28,41 +38,38 @@ use {
// TODO: make it nicer for wasm (I don't want to touch it for this experiment)
#[cfg(target_arch = "wasm32")]
use crate::wasm_storage::PersistentStorage;
use crate::wasm_mockups::PersistentStorage;
#[cfg(not(target_arch = "wasm32"))]
#[cfg(not(feature = "mobile"))]
use credential_storage::PersistentStorage;
#[cfg(not(target_arch = "wasm32"))]
#[cfg(feature = "mobile")]
use mobile_storage::PersistentStorage;
#[derive(Clone)]
pub struct BandwidthController<St: Storage = PersistentStorage> {
#[allow(dead_code)]
#[allow(dead_code)]
pub struct BandwidthController<C: Clone, St: Storage = PersistentStorage> {
storage: St,
#[cfg(feature = "coconut")]
coconut_api_clients: Vec<CoconutApiClient>,
nyxd_client: Client<C>,
}
impl<St> BandwidthController<St>
impl<C, St> BandwidthController<C, St>
where
C: CosmWasmClient + Sync + Send + Clone,
St: Storage + Clone + 'static,
{
#[cfg(feature = "coconut")]
pub fn new(storage: St, coconut_api_clients: Vec<CoconutApiClient>) -> Self {
pub fn new(storage: St, nyxd_client: Client<C>) -> Self {
BandwidthController {
storage,
coconut_api_clients,
nyxd_client,
}
}
#[cfg(not(feature = "coconut"))]
pub fn new(storage: St) -> Result<Self, GatewayClientError> {
Ok(BandwidthController { storage })
}
#[cfg(feature = "coconut")]
pub async fn prepare_coconut_credential(
&self,
) -> Result<(coconut_interface::Credential, i64), GatewayClientError> {
let verification_key = obtain_aggregate_verification_key(&self.coconut_api_clients).await?;
let bandwidth_credential = self.storage.get_next_coconut_credential().await?;
let voucher_value = u64::from_str(&bandwidth_credential.voucher_value)
.map_err(|_| StorageError::InconsistentData)?;
@@ -73,6 +80,19 @@ where
coconut_interface::Attribute::try_from_bs58(bandwidth_credential.binding_number)?;
let signature =
coconut_interface::Signature::try_from_bs58(bandwidth_credential.signature)?;
let epoch_id = u64::from_str(&bandwidth_credential.epoch_id)
.map_err(|_| StorageError::InconsistentData)?;
#[cfg(not(target_arch = "wasm32"))]
let coconut_api_clients = validator_client::CoconutApiClient::all_coconut_api_clients(
&self.nyxd_client,
epoch_id,
)
.await
.expect("Could not query api clients");
#[cfg(target_arch = "wasm32")]
let coconut_api_clients = vec![];
let verification_key = obtain_aggregate_verification_key(&coconut_api_clients).await?;
// the below would only be executed once we know where we want to spend it (i.e. which gateway and stuff)
Ok((
@@ -81,6 +101,7 @@ where
voucher_info,
serial_number,
binding_number,
epoch_id,
&signature,
&verification_key,
)?,
@@ -88,7 +109,6 @@ where
))
}
#[cfg(feature = "coconut")]
pub async fn consume_credential(&self, id: i64) -> Result<(), GatewayClientError> {
Ok(self.storage.consume_coconut_credential(id).await?)
}
+30 -32
View File
@@ -9,6 +9,7 @@ pub use crate::packet_router::{
};
use crate::socket_state::{PartiallyDelegated, SocketState};
use crate::{cleanup_socket_message, try_decrypt_binary_message};
use coconut_interface::Credential;
use crypto::asymmetric::identity;
use futures::{SinkExt, StreamExt};
use gateway_requests::authentication::encrypted_address::EncryptedAddressBytes;
@@ -25,16 +26,23 @@ use std::time::Duration;
use task::TaskClient;
use tungstenite::protocol::Message;
#[cfg(feature = "coconut")]
use coconut_interface::Credential;
#[cfg(not(target_arch = "wasm32"))]
use credential_storage::PersistentStorage;
#[cfg(not(target_arch = "wasm32"))]
use tokio_tungstenite::connect_async;
#[cfg(not(target_arch = "wasm32"))]
use validator_client::nyxd::CosmWasmClient;
#[cfg(not(target_arch = "wasm32"))]
#[cfg(not(feature = "mobile"))]
use credential_storage::PersistentStorage;
#[cfg(not(target_arch = "wasm32"))]
#[cfg(feature = "mobile")]
use mobile_storage::PersistentStorage;
#[cfg(target_arch = "wasm32")]
use crate::wasm_storage::PersistentStorage;
use crate::wasm_mockups::CosmWasmClient;
#[cfg(target_arch = "wasm32")]
use crate::wasm_mockups::PersistentStorage;
#[cfg(target_arch = "wasm32")]
use wasm_timer;
#[cfg(target_arch = "wasm32")]
@@ -43,19 +51,18 @@ use wasm_utils::websocket::JSWebsocket;
const DEFAULT_RECONNECTION_ATTEMPTS: usize = 10;
const DEFAULT_RECONNECTION_BACKOFF: Duration = Duration::from_secs(5);
pub struct GatewayClient {
pub struct GatewayClient<C: Clone> {
authenticated: bool,
disabled_credentials_mode: bool,
bandwidth_remaining: i64,
gateway_address: String,
gateway_identity: identity::PublicKey,
gateway_owner: String,
local_identity: Arc<identity::KeyPair>,
shared_key: Option<Arc<SharedKeys>>,
connection: SocketState,
packet_router: PacketRouter,
response_timeout_duration: Duration,
bandwidth_controller: Option<BandwidthController<PersistentStorage>>,
bandwidth_controller: Option<BandwidthController<C, PersistentStorage>>,
// reconnection related variables
/// Specifies whether client should try to reconnect to gateway on connection failure.
@@ -70,19 +77,21 @@ pub struct GatewayClient {
shutdown: TaskClient,
}
impl GatewayClient {
impl<C> GatewayClient<C>
where
C: CosmWasmClient + Sync + Send + Clone,
{
// TODO: put it all in a Config struct
#[allow(clippy::too_many_arguments)]
pub fn new(
gateway_address: String,
local_identity: Arc<identity::KeyPair>,
gateway_identity: identity::PublicKey,
gateway_owner: String,
shared_key: Option<Arc<SharedKeys>>,
mixnet_message_sender: MixnetMessageSender,
ack_sender: AcknowledgementSender,
response_timeout_duration: Duration,
bandwidth_controller: Option<BandwidthController<PersistentStorage>>,
bandwidth_controller: Option<BandwidthController<C, PersistentStorage>>,
shutdown: TaskClient,
) -> Self {
GatewayClient {
@@ -91,7 +100,6 @@ impl GatewayClient {
bandwidth_remaining: 0,
gateway_address,
gateway_identity,
gateway_owner,
local_identity,
shared_key,
connection: SocketState::NotConnected,
@@ -125,7 +133,6 @@ impl GatewayClient {
pub fn new_init(
gateway_address: String,
gateway_identity: identity::PublicKey,
gateway_owner: String,
local_identity: Arc<identity::KeyPair>,
response_timeout_duration: Duration,
) -> Self {
@@ -138,13 +145,12 @@ impl GatewayClient {
let shutdown = TaskClient::dummy();
let packet_router = PacketRouter::new(ack_tx, mix_tx, shutdown.clone());
GatewayClient {
GatewayClient::<C> {
authenticated: false,
disabled_credentials_mode: true,
bandwidth_remaining: 0,
gateway_address,
gateway_identity,
gateway_owner,
local_identity,
shared_key: None,
connection: SocketState::NotConnected,
@@ -534,7 +540,6 @@ impl GatewayClient {
}
}
#[cfg(feature = "coconut")]
async fn claim_coconut_bandwidth(
&mut self,
credential: Credential,
@@ -584,28 +589,21 @@ impl GatewayClient {
return self.try_claim_testnet_bandwidth().await;
}
let _gateway_owner = self.gateway_owner.clone();
#[cfg(feature = "coconut")]
let (credential, credential_id) = self
.bandwidth_controller
.as_ref()
.unwrap()
.prepare_coconut_credential()
.await?;
#[cfg(not(feature = "coconut"))]
return self.try_claim_testnet_bandwidth().await;
#[cfg(feature = "coconut")]
{
self.claim_coconut_bandwidth(credential).await?;
self.bandwidth_controller
.as_ref()
.unwrap()
.consume_credential(credential_id)
.await?;
Ok(())
}
self.claim_coconut_bandwidth(credential).await?;
self.bandwidth_controller
.as_ref()
.unwrap()
.consume_credential(credential_id)
.await?;
Ok(())
}
fn estimate_required_bandwidth(&self, packets: &[MixPacket]) -> i64 {
@@ -2,10 +2,14 @@
// SPDX-License-Identifier: Apache-2.0
#[cfg(target_arch = "wasm32")]
use crate::wasm_storage::StorageError;
use crate::wasm_mockups::StorageError;
#[cfg(not(feature = "mobile"))]
#[cfg(not(target_arch = "wasm32"))]
use credential_storage::error::StorageError;
use gateway_requests::registration::handshake::error::HandshakeError;
#[cfg(feature = "mobile")]
#[cfg(not(target_arch = "wasm32"))]
use mobile_storage::StorageError;
use std::io;
use thiserror::Error;
use tungstenite::Error as WsError;
@@ -26,7 +30,6 @@ pub enum GatewayClientError {
#[error("There was a credential storage error - {0}")]
CredentialStorageError(#[from] StorageError),
#[cfg(feature = "coconut")]
#[error("Coconut error - {0}")]
CoconutError(#[from] coconut_interface::CoconutError),
+1 -1
View File
@@ -17,7 +17,7 @@ pub mod error;
pub mod packet_router;
pub mod socket_state;
#[cfg(target_arch = "wasm32")]
mod wasm_storage;
pub mod wasm_mockups;
/// Helper method for reading from websocket stream. Helps to flatten the structure.
pub(crate) fn cleanup_socket_message(
@@ -2,6 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
use async_trait::async_trait;
use std::marker::PhantomData;
use thiserror::Error;
#[derive(Error, Debug)]
@@ -14,6 +15,18 @@ pub enum StorageError {
InconsistentData,
}
pub trait CosmWasmClient {}
#[derive(Clone)]
pub struct SigningNyxdClient {}
impl CosmWasmClient for SigningNyxdClient {}
#[derive(Clone)]
pub struct Client<C> {
_phantom: PhantomData<C>,
}
#[derive(Clone)]
pub struct PersistentStorage {}
@@ -24,6 +37,7 @@ pub struct CoconutCredential {
pub serial_number: String,
pub binding_number: String,
pub signature: String,
pub epoch_id: String,
}
#[async_trait]
+5 -4
View File
@@ -8,9 +8,10 @@ edition = "2021"
[dependencies]
futures = "0.3"
log = "0.4.8"
tokio = { version = "1.21.2", features = ["time", "net", "rt"] }
tokio-util = { version = "0.7.3", features = ["codec"] }
log = { workspace = true }
tokio = { version = "1.24.1", features = ["time", "net", "rt"] }
tokio-util = { version = "0.7.4", features = ["codec"] }
# internal
nymsphinx = {path = "../../nymsphinx" }
nymsphinx = { path = "../../nymsphinx" }
task = { path = "../../task" }
@@ -16,6 +16,7 @@ type MixForwardingReceiver = mpsc::UnboundedReceiver<MixPacket>;
pub struct PacketForwarder {
mixnet_client: Client,
packet_receiver: MixForwardingReceiver,
shutdown: task::TaskClient,
}
impl PacketForwarder {
@@ -25,6 +26,7 @@ impl PacketForwarder {
initial_connection_timeout: Duration,
maximum_connection_buffer_size: usize,
use_legacy_version: bool,
shutdown: task::TaskClient,
) -> (PacketForwarder, MixForwardingSender) {
let client_config = Config::new(
initial_reconnection_backoff,
@@ -40,26 +42,35 @@ impl PacketForwarder {
PacketForwarder {
mixnet_client: Client::new(client_config),
packet_receiver,
shutdown,
},
packet_sender,
)
}
pub async fn run(&mut self) {
while let Some(mix_packet) = self.packet_receiver.next().await {
trace!("Going to forward packet to {:?}", mix_packet.next_hop());
while !self.shutdown.is_shutdown() {
tokio::select! {
biased;
_ = self.shutdown.recv() => {
log::trace!("PacketForwarder: Received shutdown");
}
Some(mix_packet) = self.packet_receiver.next() => {
trace!("Going to forward packet to {:?}", mix_packet.next_hop());
let next_hop = mix_packet.next_hop();
let packet_mode = mix_packet.packet_mode();
let sphinx_packet = mix_packet.into_sphinx_packet();
// we don't care about responses, we just want to fire packets
// as quickly as possible
let next_hop = mix_packet.next_hop();
let packet_mode = mix_packet.packet_mode();
let sphinx_packet = mix_packet.into_sphinx_packet();
// we don't care about responses, we just want to fire packets
// as quickly as possible
if let Err(err) =
self.mixnet_client
.send_without_response(next_hop, sphinx_packet, packet_mode)
{
debug!("failed to forward the packet - {err}")
if let Err(err) =
self.mixnet_client
.send_without_response(next_hop, sphinx_packet, packet_mode)
{
debug!("failed to forward the packet - {err}")
}
}
}
}
}
@@ -17,19 +17,20 @@ mixnet-contract-common = { path= "../../cosmwasm-smart-contracts/mixnet-contract
vesting-contract-common = { path= "../../cosmwasm-smart-contracts/vesting-contract" }
coconut-bandwidth-contract-common = { path= "../../cosmwasm-smart-contracts/coconut-bandwidth-contract" }
multisig-contract-common = { path = "../../cosmwasm-smart-contracts/multisig-contract" }
group-contract-common = { path = "../../cosmwasm-smart-contracts/group-contract" }
vesting-contract = { path = "../../../contracts/vesting" }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
reqwest = { version = "0.11", features = ["json"] }
thiserror = "1"
log = "0.4"
log = { workspace = true }
url = { version = "2.2", features = ["serde"] }
tokio = { version = "1.21.2", features = ["sync", "time"] }
tokio = { version = "1.24.1", features = ["sync", "time"] }
futures = "0.3"
coconut-interface = { path = "../../coconut-interface" }
network-defaults = { path = "../../network-defaults" }
nym-api-requests = { path = "../../../nym-api/nym-api-requests", features = ["coconut"] }
nym-api-requests = { path = "../../../nym-api/nym-api-requests" }
# required for nyxd-client
# at some point it might be possible to make it wasm-compatible
@@ -39,6 +40,7 @@ bip39 = { version = "1", features = ["rand"], optional = true }
config = { path = "../../config", optional = true }
cosmrs = { git = "https://github.com/neacsu/cosmos-rust", branch = "neacsu/feegrant_support", features = ["rpc", "bip32", "cosmwasm"], optional = true}
cw3 = { version = "0.13.4", optional = true }
cw4 = { version = "0.13.4", optional = true }
prost = { version = "0.10", default-features = false, optional = true }
flate2 = { version = "1.0.20", optional = true }
sha2 = { version = "0.9.5", optional = true }
@@ -56,6 +58,7 @@ nyxd-client = [
"config",
"cosmrs",
"cw3",
"cw4",
"prost",
"flate2",
"sha2",
@@ -21,7 +21,9 @@ use crate::nyxd::traits::{DkgQueryClient, MixnetQueryClient, MultisigQueryClient
use crate::nyxd::{self, CosmWasmClient, NyxdClient, QueryNyxdClient, SigningNyxdClient};
#[cfg(feature = "nyxd-client")]
use coconut_dkg_common::{
dealer::ContractDealing, types::DealerDetails, verification_key::ContractVKShare,
dealer::ContractDealing,
types::{DealerDetails, EpochId},
verification_key::ContractVKShare,
};
#[cfg(feature = "nyxd-client")]
use coconut_interface::Base58;
@@ -128,7 +130,8 @@ impl Config {
}
#[cfg(feature = "nyxd-client")]
pub struct Client<C> {
#[derive(Clone)]
pub struct Client<C: Clone> {
// TODO: we really shouldn't be storing a mnemonic here, but removing it would be
// non-trivial amount of work and it's out of scope of the current branch
mnemonic: Option<bip39::Mnemonic>,
@@ -218,7 +221,10 @@ impl Client<QueryNyxdClient> {
// nyxd wrappers
#[cfg(feature = "nyxd-client")]
impl<C> Client<C> {
impl<C> Client<C>
where
C: Clone,
{
// use case: somebody initialised client without a contract in order to upload and initialise one
// and now they want to actually use it without making new client
@@ -676,6 +682,7 @@ impl<C> Client<C> {
pub async fn get_all_nyxd_verification_key_shares(
&self,
epoch_id: EpochId,
) -> Result<Vec<ContractVKShare>, ValidatorClientError>
where
C: CosmWasmClient + Sync + Send,
@@ -685,7 +692,11 @@ impl<C> Client<C> {
loop {
let mut paged_response = self
.nyxd
.get_vk_shares_paged(start_after.take(), self.verification_key_page_limit)
.get_vk_shares_paged(
epoch_id,
start_after.take(),
self.verification_key_page_limit,
)
.await?;
shares.append(&mut paged_response.shares);
@@ -730,7 +741,10 @@ impl<C> Client<C> {
// validator-api wrappers
#[cfg(feature = "nyxd-client")]
impl<C> Client<C> {
impl<C> Client<C>
where
C: Clone,
{
pub fn change_nym_api(&mut self, new_endpoint: Url) {
self.nym_api.change_url(new_endpoint)
}
@@ -792,14 +806,15 @@ pub struct CoconutApiClient {
#[cfg(feature = "nyxd-client")]
impl CoconutApiClient {
pub async fn all_coconut_api_clients<C>(
pub async fn all_coconut_api_clients<C: Clone>(
nyxd_client: &Client<C>,
epoch_id: EpochId,
) -> Result<Vec<Self>, ValidatorClientError>
where
C: CosmWasmClient + Sync + Send,
{
Ok(nyxd_client
.get_all_nyxd_verification_key_shares()
.get_all_nyxd_verification_key_shares(epoch_id)
.await?
.into_iter()
.filter_map(Self::try_from)
@@ -6,7 +6,7 @@ use thiserror::Error;
#[derive(Error, Debug)]
pub enum ValidatorClientError {
#[error("There was an issue with the validator api request - {source}")]
#[error("nym api request failed - {source}")]
NymAPIError {
#[from]
source: nym_api::error::NymAPIError,
@@ -16,7 +16,7 @@ pub enum ValidatorClientError {
MalformedUrlProvided(#[from] url::ParseError),
#[cfg(feature = "nyxd-client")]
#[error("There was an issue with the Nyxd client - {0}")]
#[error("nyxd request failed - {0}")]
NyxdError(#[from] crate::nyxd::error::NyxdError),
#[error("No validator API url has been provided")]
@@ -9,10 +9,8 @@ pub mod nym_api;
#[cfg(feature = "nyxd-client")]
pub mod nyxd;
#[cfg(feature = "nyxd-client")]
pub use crate::client::{CoconutApiClient, NymApiClient};
pub use crate::error::ValidatorClientError;
pub use nym_api_requests::*;
#[cfg(feature = "nyxd-client")]
pub use client::{Client, Config};
pub use client::{Client, CoconutApiClient, Config, NymApiClient};

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