Compare commits

...

138 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
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
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
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
farbanas ac10e03aec chore: added --all-targets --all-features to clippy 2023-01-13 10:31:19 +01:00
Fouad 4854e929ed link to the ng mixnet explorer for account info (#2823) 2023-01-12 12:33:28 +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
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
690 changed files with 30791 additions and 11135 deletions
+4
View File
@@ -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
-55
View File
@@ -1,55 +0,0 @@
name: Daily security audit
on: workflow_dispatch
jobs:
cargo-deny:
runs-on: ubuntu-20.04
steps:
- name: Checkout repository code
uses: actions/checkout@v2
- name: Install rust toolchain
uses: actions-rs/toolchain@v1
with:
toolchain: stable
- name: Install cargo deny
run: cargo install --locked cargo-deny
- name: Run cargo deny
run: |
find . -name Cargo.toml -exec cargo deny --manifest-path {} check \
advisories -A advisory-not-detected --hide-inclusion-graph \; &> \
>(uniq &> .github/workflows/support-files/notifications/deny.message )
- uses: actions/upload-artifact@v3
with:
name: report
path: .github/workflows/support-files/notifications/deny.message
notification:
needs: cargo-deny
runs-on: custom-runner-linux
steps:
- name: Check out repository code
uses: actions/checkout@v2
- name: Download report from previous job
uses: actions/download-artifact@v3
with:
name: report
path: .github/workflows/support-files/notifications
- name: Keybase - Node Install
run: npm install
working-directory: .github/workflows/support-files
- name: Keybase - Send Notification
env:
NYM_NOTIFICATION_KIND: security
NYM_PROJECT_NAME: "Daily security report"
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
KEYBASE_NYMBOT_USERNAME: "${{ secrets.KEYBASE_NYMBOT_USERNAME }}"
KEYBASE_NYMBOT_PAPERKEY: "${{ secrets.KEYBASE_NYMBOT_PAPERKEY }}"
KEYBASE_NYMBOT_TEAM: "${{ secrets.KEYBASE_NYMBOT_TEAM }}"
KEYBASE_NYM_CHANNEL: "security"
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
@@ -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:
+37 -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,48 +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
+18 -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
+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:
@@ -0,0 +1,57 @@
name: CI for Network Explorer API
on:
workflow_dispatch:
release:
types: [created]
env:
NETWORK: mainnet
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:
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: Check the release tag starts with `nym-explorer-api-`
uses: actions/github-script@v3
with:
script: |
core.setFailed('Release tag did not start with nym-explorer-api-...')
- name: Install Rust stable
uses: actions-rs/toolchain@v1
with:
toolchain: stable
- name: Build all explorer-api
uses: actions-rs/cargo@v1
with:
command: build
args: --manifest-path explorer-api/Cargo.toml --workspace --release
- name: Upload Artifact
uses: actions/upload-artifact@v3
with:
name: my-artifact
path: |
target/release/explorer-api
retention-days: 30
- name: Upload to release based on tag name
uses: softprops/action-gh-release@v1
if: github.event_name == 'release'
with:
files: |
target/release/explorer-api
+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:
+27 -41
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
@@ -86,7 +99,7 @@ jobs:
continue-on-error: true
with:
token: ${{ secrets.GITHUB_TOKEN }}
args: --all-features
args: --workspace
- name: Run clippy
uses: actions-rs/cargo@v1
@@ -101,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
@@ -167,6 +148,11 @@ jobs:
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
+6 -32
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
@@ -116,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
@@ -182,6 +151,11 @@ jobs:
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
+6 -32
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
@@ -116,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
@@ -182,6 +151,11 @@ jobs:
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
+50
View File
@@ -0,0 +1,50 @@
name: Publish Nym CLI binaries
on:
workflow_dispatch:
release:
types: [created]
env:
NETWORK: mainnet
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:
platform: [ubuntu-20.04, windows-latest, macos-latest]
runs-on: ${{ matrix.platform }}
steps:
- uses: actions/checkout@v3
- name: Check the release tag starts with `nym-cli-`
uses: actions/github-script@v3
with:
script: |
core.setFailed('Release tag did not start with nym-cli-...')
- name: Install Rust stable
uses: actions-rs/toolchain@v1
with:
toolchain: stable
- name: Build binary
run: make build-nym-cli
- name: Upload Artifact
uses: actions/upload-artifact@v3
with:
name: nym-cli-${{ matrix.platform }}
path: |
target/release/nym-cli*
retention-days: 30
- name: Upload to release based on tag name
uses: softprops/action-gh-release@v1
if: github.event_name == 'release'
with:
files: |
target/release/nym-cli
@@ -24,6 +24,7 @@ jobs:
run: >
sudo apt-get update &&
sudo apt-get install -y webkit2gtk-4.0 libayatana-appindicator3-dev
continue-on-error: true
- name: Node v16
uses: actions/setup-node@v3
+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:
+3 -2
View File
@@ -28,6 +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
continue-on-error: true
- name: Sets env vars for tokio if set in manual dispatch inputs
run: |
@@ -55,7 +56,7 @@ jobs:
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,7 +72,7 @@ jobs:
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
@@ -23,6 +23,7 @@ jobs:
run: >
sudo apt-get update &&
sudo apt-get install -y webkit2gtk-4.0
continue-on-error: true
- name: Node v16
uses: actions/setup-node@v3
@@ -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
+11 -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
+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
+70 -3
View File
@@ -2,28 +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
+1043 -851
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.
+2 -3
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,7 +13,7 @@ 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"
@@ -82,5 +82,4 @@ sqlx = { version = "0.6.2", features = ["runtime-tokio-rustls", "sqlite", "macro
default = []
fs-surb-storage = ["sqlx"]
wasm = ["gateway-client/wasm"]
coconut = ["gateway-client/coconut", "gateway-requests/coconut"]
@@ -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());
@@ -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))
}
}
+13 -4
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);
(
@@ -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,
}
@@ -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
}
@@ -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(())
}
+25 -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);
@@ -372,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 {
@@ -541,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)
}
}
@@ -663,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.
@@ -704,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,
}
+5 -2
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,6 +17,8 @@ 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>,
@@ -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,
);
+1 -1
View File
@@ -149,7 +149,7 @@ pub fn load_existing_gateway_config<T>(id: &str) -> Result<GatewayEndpointConfig
where
T: NymConfig + ClientCoreConfigTrait,
{
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!(
-3
View File
@@ -7,7 +7,6 @@ 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"] }
@@ -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(())
}
+4 -7
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,7 +23,7 @@ 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
@@ -37,11 +37,11 @@ tokio-tungstenite = "0.14" # websocket
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
+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 #####
+25 -37
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,7 +102,8 @@ 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)
@@ -137,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?,
@@ -174,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?,
+7 -5
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,7 +114,7 @@ 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 \"{id}\" was already initialised before");
}
+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);
+1 -1
View File
@@ -131,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)
});
+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,
}
}
+8 -6
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"] }
@@ -30,11 +30,12 @@ url = "2.2"
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.
+56 -40
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;
@@ -20,6 +23,7 @@ use log::*;
use nymsphinx::addressing::clients::Recipient;
use std::error::Error;
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(
@@ -201,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();
+1 -6
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,7 +117,7 @@ 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 \"{id}\" was already initialised before");
}
+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)
});
+5 -4
View File
@@ -15,13 +15,14 @@ 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.24.1", features = ["sync"] }
url = "2.2"
@@ -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 }
+5 -4
View File
@@ -10,7 +10,7 @@ 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"] }
@@ -18,16 +18,17 @@ async-trait = { version = "0.1.51" }
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]
@@ -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]
+1 -1
View File
@@ -8,7 +8,7 @@ edition = "2021"
[dependencies]
futures = "0.3"
log = "0.4.8"
log = { workspace = true }
tokio = { version = "1.24.1", features = ["time", "net", "rt"] }
tokio-util = { version = "0.7.4", features = ["codec"] }
@@ -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.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)
@@ -65,6 +65,7 @@ pub struct Config {
pub(crate) vesting_contract_address: Option<AccountId>,
pub(crate) bandwidth_claim_contract_address: Option<AccountId>,
pub(crate) coconut_bandwidth_contract_address: Option<AccountId>,
pub(crate) group_contract_address: Option<AccountId>,
pub(crate) multisig_contract_address: Option<AccountId>,
pub(crate) coconut_dkg_contract_address: Option<AccountId>,
// TODO: add this in later commits
@@ -119,6 +120,10 @@ impl Config {
.as_ref(),
prefix,
)?,
group_contract_address: Self::parse_optional_account(
details.contracts.group_contract_address.as_ref(),
prefix,
)?,
multisig_contract_address: Self::parse_optional_account(
details.contracts.multisig_contract_address.as_ref(),
prefix,
@@ -131,8 +136,8 @@ impl Config {
}
}
#[derive(Debug)]
pub struct NyxdClient<C> {
#[derive(Clone, Debug)]
pub struct NyxdClient<C: Clone> {
client: C,
config: Config,
client_address: Option<Vec<AccountId>>,
@@ -209,7 +214,10 @@ impl NyxdClient<SigningNyxdClient> {
}
}
impl<C> NyxdClient<C> {
impl<C> NyxdClient<C>
where
C: Clone,
{
pub fn current_config(&self) -> &Config {
&self.config
}
@@ -276,6 +284,10 @@ impl<C> NyxdClient<C> {
.unwrap()
}
pub fn group_contract_address(&self) -> &AccountId {
self.config.group_contract_address.as_ref().unwrap()
}
// TODO: this should get changed into Result<&AccountId, NyxdError> (or Option<&AccountId> in future commits
// note: what unwrap is doing here is just moving a failure that would have normally
// occurred in `connect` when attempting to parse an empty address,
@@ -18,7 +18,7 @@ pub trait CoconutBandwidthQueryClient {
}
#[async_trait]
impl<C: CosmWasmClient + Sync + Send> CoconutBandwidthQueryClient for NyxdClient<C> {
impl<C: CosmWasmClient + Sync + Send + Clone> CoconutBandwidthQueryClient for NyxdClient<C> {
async fn get_spent_credential(
&self,
blinded_serial_number: String,
@@ -30,7 +30,9 @@ pub trait CoconutBandwidthSigningClient {
}
#[async_trait]
impl<C: SigningCosmWasmClient + Sync + Send> CoconutBandwidthSigningClient for NyxdClient<C> {
impl<C: SigningCosmWasmClient + Sync + Send + Clone> CoconutBandwidthSigningClient
for NyxdClient<C>
{
async fn deposit(
&self,
amount: Coin,
@@ -8,7 +8,7 @@ use coconut_dkg_common::dealer::{
DealerDetailsResponse, PagedDealerResponse, PagedDealingsResponse,
};
use coconut_dkg_common::msg::QueryMsg as DkgQueryMsg;
use coconut_dkg_common::types::Epoch;
use coconut_dkg_common::types::{Epoch, EpochId};
use coconut_dkg_common::verification_key::PagedVKSharesResponse;
use cosmrs::AccountId;
@@ -39,6 +39,7 @@ pub trait DkgQueryClient {
) -> Result<PagedDealingsResponse, NyxdError>;
async fn get_vk_shares_paged(
&self,
epoch_id: EpochId,
start_after: Option<String>,
page_limit: Option<u32>,
) -> Result<PagedVKSharesResponse, NyxdError>;
@@ -47,7 +48,7 @@ pub trait DkgQueryClient {
#[async_trait]
impl<C> DkgQueryClient for NyxdClient<C>
where
C: CosmWasmClient + Send + Sync,
C: CosmWasmClient + Send + Sync + Clone,
{
async fn get_current_epoch(&self) -> Result<Epoch, NyxdError> {
let request = DkgQueryMsg::GetCurrentEpochState {};
@@ -119,10 +120,12 @@ where
async fn get_vk_shares_paged(
&self,
epoch_id: EpochId,
start_after: Option<String>,
page_limit: Option<u32>,
) -> Result<PagedVKSharesResponse, NyxdError> {
let request = DkgQueryMsg::GetVerificationKeys {
epoch_id,
limit: page_limit,
start_after,
};
@@ -36,7 +36,7 @@ pub trait DkgSigningClient {
#[async_trait]
impl<C> DkgSigningClient for NyxdClient<C>
where
C: SigningCosmWasmClient + Send + Sync,
C: SigningCosmWasmClient + Send + Sync + Clone,
{
async fn advance_dkg_epoch_state(&self, fee: Option<Fee>) -> Result<ExecuteResult, NyxdError> {
let req = DkgExecuteMsg::AdvanceEpochState {};
@@ -0,0 +1,28 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::nyxd::error::NyxdError;
use crate::nyxd::{CosmWasmClient, NyxdClient};
use group_contract_common::msg::QueryMsg;
use async_trait::async_trait;
use cw4::MemberResponse;
#[async_trait]
pub trait GroupQueryClient {
async fn member(&self, addr: String) -> Result<MemberResponse, NyxdError>;
}
#[async_trait]
impl<C: CosmWasmClient + Sync + Send + Clone> GroupQueryClient for NyxdClient<C> {
async fn member(&self, addr: String) -> Result<MemberResponse, NyxdError> {
let request = QueryMsg::Member {
addr,
at_height: None,
};
self.client
.query_contract_smart(self.group_contract_address(), &request)
.await
}
}
@@ -395,7 +395,7 @@ pub trait MixnetQueryClient {
#[async_trait]
impl<C> MixnetQueryClient for NyxdClient<C>
where
C: CosmWasmClient + Sync + Send,
C: CosmWasmClient + Sync + Send + Clone,
{
async fn query_mixnet_contract<T>(&self, query: MixnetQueryMsg) -> Result<T, NyxdError>
where
@@ -410,7 +410,7 @@ where
#[async_trait]
impl<C> MixnetQueryClient for crate::Client<C>
where
C: CosmWasmClient + Sync + Send,
C: CosmWasmClient + Sync + Send + Clone,
{
async fn query_mixnet_contract<T>(&self, query: MixnetQueryMsg) -> Result<T, NyxdError>
where
@@ -627,7 +627,7 @@ pub trait MixnetSigningClient {
#[async_trait]
impl<C> MixnetSigningClient for NyxdClient<C>
where
C: SigningCosmWasmClient + Sync + Send,
C: SigningCosmWasmClient + Sync + Send + Clone,
{
async fn execute_mixnet_contract(
&self,
@@ -653,7 +653,7 @@ where
#[async_trait]
impl<C> MixnetSigningClient for crate::Client<C>
where
C: SigningCosmWasmClient + Sync + Send,
C: SigningCosmWasmClient + Sync + Send + Clone,
{
async fn execute_mixnet_contract(
&self,
@@ -5,6 +5,7 @@ mod coconut_bandwidth_query_client;
mod coconut_bandwidth_signing_client;
mod dkg_query_client;
mod dkg_signing_client;
mod group_query_client;
mod mixnet_query_client;
mod mixnet_signing_client;
mod multisig_query_client;
@@ -16,6 +17,7 @@ pub use coconut_bandwidth_query_client::CoconutBandwidthQueryClient;
pub use coconut_bandwidth_signing_client::CoconutBandwidthSigningClient;
pub use dkg_query_client::DkgQueryClient;
pub use dkg_signing_client::DkgSigningClient;
pub use group_query_client::GroupQueryClient;
pub use mixnet_query_client::MixnetQueryClient;
pub use mixnet_signing_client::MixnetSigningClient;
pub use multisig_query_client::MultisigQueryClient;
@@ -20,7 +20,7 @@ pub trait MultisigQueryClient {
}
#[async_trait]
impl<C: CosmWasmClient + Sync + Send> MultisigQueryClient for NyxdClient<C> {
impl<C: CosmWasmClient + Sync + Send + Clone> MultisigQueryClient for NyxdClient<C> {
async fn get_proposal(&self, proposal_id: u64) -> Result<ProposalResponse, NyxdError> {
let request = QueryMsg::Proposal { proposal_id };
self.client
@@ -38,7 +38,7 @@ pub trait MultisigSigningClient {
}
#[async_trait]
impl<C: SigningCosmWasmClient + Sync + Send> MultisigSigningClient for NyxdClient<C> {
impl<C: SigningCosmWasmClient + Sync + Send + Clone> MultisigSigningClient for NyxdClient<C> {
async fn propose_release_funds(
&self,
title: String,
@@ -269,7 +269,7 @@ pub trait VestingQueryClient {
}
#[async_trait]
impl<C: CosmWasmClient + Sync + Send> VestingQueryClient for NyxdClient<C> {
impl<C: CosmWasmClient + Sync + Send + Clone> VestingQueryClient for NyxdClient<C> {
async fn query_vesting_contract<T>(&self, query: VestingQueryMsg) -> Result<T, NyxdError>
where
for<'a> T: Deserialize<'a>,
@@ -129,7 +129,7 @@ pub trait VestingSigningClient {
}
#[async_trait]
impl<C: SigningCosmWasmClient + Sync + Send> VestingSigningClient for NyxdClient<C> {
impl<C: SigningCosmWasmClient + Sync + Send + Clone> VestingSigningClient for NyxdClient<C> {
async fn execute_vesting_contract(
&self,
fee: Option<Fee>,
+11 -2
View File
@@ -18,6 +18,8 @@ pub struct Credential {
theta: Theta,
voucher_value: u64,
voucher_info: String,
#[getset(get = "pub")]
epoch_id: u64,
}
impl Credential {
pub fn new(
@@ -25,12 +27,14 @@ impl Credential {
theta: Theta,
voucher_value: u64,
voucher_info: String,
epoch_id: u64,
) -> Credential {
Credential {
n_params,
theta,
voucher_value,
voucher_info,
epoch_id,
}
}
@@ -68,6 +72,7 @@ impl Credential {
let theta_bytes = self.theta.to_bytes();
let theta_bytes_len = theta_bytes.len();
let voucher_value_bytes = self.voucher_value.to_be_bytes();
let epoch_id_bytes = self.epoch_id.to_be_bytes();
let voucher_info_bytes = self.voucher_info.as_bytes();
let voucher_info_len = voucher_info_bytes.len();
@@ -76,6 +81,7 @@ impl Credential {
bytes.extend_from_slice(&(theta_bytes_len as u64).to_be_bytes());
bytes.extend_from_slice(&theta_bytes);
bytes.extend_from_slice(&voucher_value_bytes);
bytes.extend_from_slice(&epoch_id_bytes);
bytes.extend_from_slice(voucher_info_bytes);
bytes
@@ -103,7 +109,9 @@ impl Credential {
.map_err(|e| CoconutError::Deserialization(e.to_string()))?;
eight_byte.copy_from_slice(&bytes[12 + theta_len as usize..20 + theta_len as usize]);
let voucher_value = u64::from_be_bytes(eight_byte);
let voucher_info = String::from_utf8(bytes[20 + theta_len as usize..].to_vec())
eight_byte.copy_from_slice(&bytes[20 + theta_len as usize..28 + theta_len as usize]);
let epoch_id = u64::from_be_bytes(eight_byte);
let voucher_info = String::from_utf8(bytes[28 + theta_len as usize..].to_vec())
.map_err(|e| CoconutError::Deserialization(e.to_string()))?;
Ok(Credential {
@@ -111,6 +119,7 @@ impl Credential {
theta,
voucher_value,
voucher_info,
epoch_id,
})
}
}
@@ -166,7 +175,7 @@ mod tests {
binding_number,
)
.unwrap();
let credential = Credential::new(4, theta, voucher_value, voucher_info);
let credential = Credential::new(4, theta, voucher_value, voucher_info, 42);
let serialized_credential = credential.as_bytes();
let deserialized_credential = Credential::from_bytes(&serialized_credential).unwrap();
+2 -2
View File
@@ -1,7 +1,7 @@
[package]
name = "nym-cli-commands"
version = "1.0.0"
authors = ["Nym Technologies SA"]
authors.workspace = true
edition = "2021"
[dependencies]
@@ -15,7 +15,7 @@ cw-utils = { version = "0.13.4" }
handlebars = "3.0.1"
humantime-serde = "1.0"
k256 = { version = "0.10", features = ["ecdsa", "sha256"] }
log = "0.4"
log = { workspace = true }
rand = {version = "0.6", features = ["std"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1"
@@ -1,10 +1,13 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use std::str::FromStr;
use clap::Parser;
use log::{debug, info};
use coconut_bandwidth_contract_common::msg::InstantiateMsg;
use validator_client::nyxd::AccountId;
#[derive(Debug, Parser)]
pub struct Args {
@@ -12,7 +15,7 @@ pub struct Args {
pub pool_addr: String,
#[clap(long)]
pub multisig_addr: Option<String>,
pub multisig_addr: Option<AccountId>,
#[clap(long)]
pub mix_denom: Option<String>,
@@ -24,8 +27,10 @@ pub async fn generate(args: Args) {
debug!("Received arguments: {:?}", args);
let multisig_addr = args.multisig_addr.unwrap_or_else(|| {
std::env::var(network_defaults::var_names::REWARDING_VALIDATOR_ADDRESS)
.expect("Multisig address has to be set")
let address = std::env::var(network_defaults::var_names::REWARDING_VALIDATOR_ADDRESS)
.expect("Multisig address has to be set");
AccountId::from_str(address.as_str())
.expect("Failed converting multisig address to AccountId")
});
let mix_denom = args.mix_denom.unwrap_or_else(|| {
@@ -34,7 +39,7 @@ pub async fn generate(args: Args) {
let instantiate_msg = InstantiateMsg {
pool_addr: args.pool_addr,
multisig_addr,
multisig_addr: multisig_addr.to_string(),
mix_denom,
};
@@ -7,6 +7,7 @@ use std::str::FromStr;
use coconut_dkg_common::msg::InstantiateMsg;
use coconut_dkg_common::types::TimeConfiguration;
use validator_client::nyxd::AccountId;
#[derive(Debug, Parser)]
pub struct Args {
@@ -14,7 +15,7 @@ pub struct Args {
pub group_addr: String,
#[clap(long)]
pub multisig_addr: Option<String>,
pub multisig_addr: Option<AccountId>,
#[clap(long)]
pub public_key_submission_time_secs: Option<u64>,
@@ -44,8 +45,10 @@ pub async fn generate(args: Args) {
debug!("Received arguments: {:?}", args);
let multisig_addr = args.multisig_addr.unwrap_or_else(|| {
std::env::var(network_defaults::var_names::REWARDING_VALIDATOR_ADDRESS)
.expect("Multisig address has to be set")
let address = std::env::var(network_defaults::var_names::REWARDING_VALIDATOR_ADDRESS)
.expect("Multisig address has to be set");
AccountId::from_str(address.as_str())
.expect("Failed converting multisig address to AccountId")
});
let mix_denom = args.mix_denom.unwrap_or_else(|| {
@@ -86,7 +89,7 @@ pub async fn generate(args: Args) {
let instantiate_msg = InstantiateMsg {
group_addr: args.group_addr,
multisig_addr,
multisig_addr: multisig_addr.to_string(),
time_configuration: Some(time_configuration),
mix_denom,
};
@@ -6,15 +6,17 @@ use log::{debug, info};
use cosmwasm_std::Decimal;
use mixnet_contract_common::{InitialRewardingParams, InstantiateMsg, Percent};
use std::str::FromStr;
use std::time::Duration;
use validator_client::nyxd::AccountId;
#[derive(Debug, Parser)]
pub struct Args {
#[clap(long)]
pub rewarding_validator_address: Option<String>,
pub rewarding_validator_address: Option<AccountId>,
#[clap(long)]
pub vesting_contract_address: Option<String>,
pub vesting_contract_address: Option<AccountId>,
#[clap(long)]
pub rewarding_denom: Option<String>,
@@ -77,13 +79,17 @@ pub async fn generate(args: Args) {
debug!("initial_rewarding_params: {:?}", initial_rewarding_params);
let rewarding_validator_address = args.rewarding_validator_address.unwrap_or_else(|| {
std::env::var(network_defaults::var_names::REWARDING_VALIDATOR_ADDRESS)
.expect("Rewarding validator address has to be set")
let address = std::env::var(network_defaults::var_names::REWARDING_VALIDATOR_ADDRESS)
.expect("Rewarding validator address has to be set");
AccountId::from_str(address.as_str())
.expect("Failed converting rewarding validator address to AccountId")
});
let vesting_contract_address = args.vesting_contract_address.unwrap_or_else(|| {
std::env::var(network_defaults::var_names::VESTING_CONTRACT_ADDRESS)
.expect("Vesting contract address has to be set")
let address = std::env::var(network_defaults::var_names::VESTING_CONTRACT_ADDRESS)
.expect("Vesting contract address has to be set");
AccountId::from_str(address.as_str())
.expect("Failed converting vesting contract address to AccountId")
});
let rewarding_denom = args.rewarding_denom.unwrap_or_else(|| {
@@ -92,8 +98,8 @@ pub async fn generate(args: Args) {
});
let instantiate_msg = InstantiateMsg {
rewarding_validator_address,
vesting_contract_address,
rewarding_validator_address: rewarding_validator_address.to_string(),
vesting_contract_address: vesting_contract_address.to_string(),
rewarding_denom,
epochs_in_interval: args.epochs_in_interval,
epoch_duration: Duration::from_secs(args.epoch_duration),

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