Compare commits

...

334 Commits

Author SHA1 Message Date
Bogdan-Ștefan Neacşu b5213f3908 Hide coconut runtime flags (#2990) 2023-02-08 13:00:58 +02:00
Bogdan-Ștefan Neacşu 590a4644e2 Skip errors on blind sign within threshold (#2976) 2023-02-08 11:54:12 +02:00
Bogdan-Ștefan Neacşu f8345e03c6 Feature/dkg reshare (#2936)
* Add resharing parameter

* Fix equality of dealers and members

* Contract resharing handling

* Dealer verification unit test

* Dealing commit unit test

* Epoch state unit tests

* Fix clippy

* Fmt

* Query initial dealer data

* Resharing nym-api changes

* Implement the mockups for nym-api dkg tests

* Dealing test

* Vk unit test

* Fix skipping vk submission

* Fix clippy

* Missing dealing for noninitial resharing dealer

* Check master vk holds after resharing on nym-apis

* Update changelog

* Fix clippy
2023-02-07 12:56:08 +02:00
Jon Häggblad 6675ea0249 Remove all the .DS_Store files and add to gitignore (#2974) 2023-02-07 11:45:40 +01:00
Jędrzej Stuczyński 56f48e6e41 Feature/service provider interface (#2934)
* added additional workspace-wide dependencies

* Added conditional serialization on 'BinaryBuildInformationOwned'

* initial framework for service provider messages

* updated request/response tags to account for existing variants of Socks5Message

* handling legacy deserialization

* another serialization revamp to account for legacy version

* legacy client working with versioned network requester

* socks5 client deserializing responses into updated structures

* using new structures for sending in socks5 client

* SendRequest wrapper for Request::Send variant

* created named fields for all variants of 'ControllerCommand'

* Versioning socks5 requests + moving to proper Socks5Request struct

* Updated backwards compatible Socks5Response

* unused imports

* poc ServiceProvider trait

* wip

* implemented 'ServiceProvider' trait on the Network Requester

* Socks5RequestError

* added properly serialized ErrorResponse to ControlResponse

* fixed version serialization + feature selection

* handling of version control requests

* improved SocksProxyError by providing more concrete variants and removing generic case

* got rid of ServiceProviderClient trait and wrote simple example showing control requests

* tests for serialisation backwards compatibility

* post-merge fixes due to method renaming

* enum boxing to make clippy happier

* making sure to not drop buffer channel when starting `DirectClient`

* Using nym-sdk in the example

* Replaced printing version to stdout with proper log call
2023-02-07 09:49:19 +00:00
Pierre Dommerc 1733aaa4cc NC Android - setup APK publish (#2967)
* ci(nc-android): init workflow apk build & release

* ci(nc-android): setup nc android project for APK publish

* docs(nc-android): update readme

* ci(nc-android): add note in the workflow
2023-02-06 10:56:39 +01:00
Mark Sinclair 78aa07360c Update build-and-upload-binaries-ci.yml 2023-02-03 17:10:13 +00:00
Mark Sinclair 4e52478c7a Update build-and-upload-binaries-ci.yml 2023-02-03 16:54:49 +00:00
Mark Sinclair 7c77665a37 Update build-and-upload-binaries-ci.yml 2023-02-03 16:36:44 +00:00
Mark Sinclair 72880b9764 Update build-and-upload-binaries-ci.yml 2023-02-03 16:14:29 +00:00
Mark Sinclair fd1c0ae62b Update build-and-upload-binaries-ci.yml 2023-02-03 12:03:13 +00:00
Mark Sinclair bd7399091b Update build-and-upload-binaries-ci.yml 2023-02-03 11:57:32 +00:00
Mark Sinclair 00fad44e2e Update build-and-upload-binaries-ci.yml 2023-02-03 11:46:07 +00:00
Mark Sinclair ea33c332ee GitHub Actions: add action to build and upload binaries to CI server 2023-02-03 11:35:03 +00:00
Bogdan-Ștefan Neacșu b39f8af8d0 Fix flaky dkg test 2023-02-03 12:29:21 +02:00
dependabot[bot] a400463b7e build(deps): bump ua-parser-js in /nym-wallet/webdriver (#2909)
Bumps [ua-parser-js](https://github.com/faisalman/ua-parser-js) from 0.7.28 to 0.7.33.
- [Release notes](https://github.com/faisalman/ua-parser-js/releases)
- [Changelog](https://github.com/faisalman/ua-parser-js/blob/master/changelog.md)
- [Commits](https://github.com/faisalman/ua-parser-js/compare/0.7.28...0.7.33)

---
updated-dependencies:
- dependency-name: ua-parser-js
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-03 10:00:09 +00:00
dependabot[bot] 82928af64c build(deps): bump http-cache-semantics in /nym-wallet/webdriver (#2960)
Bumps [http-cache-semantics](https://github.com/kornelski/http-cache-semantics) from 4.1.0 to 4.1.1.
- [Release notes](https://github.com/kornelski/http-cache-semantics/releases)
- [Commits](https://github.com/kornelski/http-cache-semantics/commits)

---
updated-dependencies:
- dependency-name: http-cache-semantics
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-03 09:59:08 +00:00
dependabot[bot] c5891f546c build(deps): bump http-cache-semantics from 4.1.0 to 4.1.1 (#2961)
Bumps [http-cache-semantics](https://github.com/kornelski/http-cache-semantics) from 4.1.0 to 4.1.1.
- [Release notes](https://github.com/kornelski/http-cache-semantics/releases)
- [Commits](https://github.com/kornelski/http-cache-semantics/commits)

---
updated-dependencies:
- dependency-name: http-cache-semantics
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-03 09:58:34 +00:00
Tommy Verrall 580b677489 Binary checker, introduction 2023-02-03 08:46:40 -01:00
Jędrzej Stuczyński 2093789c5c Added an option to set custom 'host' for the native client (#2939)
* Added an option to set custom 'host' for the native client

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

* refactor(nc-android): remove dead code

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

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

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

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

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

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

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

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

* Remove examples from monorepo

---------

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

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

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

get rid of sqlite refs as temporary workaround

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

* feat(nc-android): wip

* hack in config removal of read/write

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

* wip

* chore: remove debug comments

* Register gateway

* client-core: remove unneeded changes

* build: revert crate name change

* refactor(socks5-client): add feature mobile

* refactor(gateway-client): rename mobile feature

* socks5: restore default_root_directory

* client-core: further simplifications

* get_config_file_location just return error

* fix(nc-mobile): fix ui mobile

* socks5: minor tweak to default_root_directory

* remove unneeded changes

* nym-connect build fixes

* Use default feature for normal credential storage

* rustfmt

* rustfmt: nym-connect

* restore Cargo.toml

* Remove --all-features from workflow

* Remove some unused use

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

* Allow unused

* Add continue-on-error

* another clippy --all-features remove

* remove --all-features from clippy nightly

* fix(nc-mobile): frontend code errors

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

* fix(nc-android): build

* fix(nc-android): lint errors

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

* ci: add cargo clean step for ubuntu

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

* nym-connect: query connection state

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

* rustfmt

* nym-connect: extract out into function

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

* Remove github workflow remainings

* Only run dkg if coconut enabled

* Fix typo

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

* Adapt tests to new locked

* Typo

* More tests

* Fix withdraw test

* Rollback changes

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

* nym-connect: redo connection test

* nym-connect: strongly typed response

* Fix clippy

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

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

fix sx prop breakage

yarn lock update

* return dist folder

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

* rust-sdk: whole bunch of rustdoc

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

* allow sorting on profit margin and operator cost

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

* GitHub Actions: add Typescript project linting

* Fix dependency

* Revert changes and exclude rule

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

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

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

* Suppress errors in build script

* Add Parcel 2.0 example

* WASM client: fix tests

* Update SDK docs and images

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

* Revert "Removing unused prestart"

This reverts commit cbeac10383.

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

This reverts commit 0e0a62938d.

* Add typing for React 18

* Improve README files

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

* Hook for group queries

* Test epoch advancement

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

* changelog: update

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

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

* Add comment

* changelog: add note

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

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

* Reset nym-api for rerun

* Gateway updates signer APIs at runtime

* Fix clippy

* Add epoch id

* Use IndexedMap for shares

* Query with epoch id

* Add Clone to client traits

* Pass nyxd client instead of api data

* Get the specific epoch vk

* Make wasm work

* Remove wasm test runs

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

* Put epoch_id in storage pk

* Gateway uses old keys but current verifiers

* Add group contract to env

* Move group msg in common

* Only run DKG if part of group

* Clippy test

* Rename wasm_storage to wasm_mockups

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

* cargo: add authors to top-level workspace

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

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

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

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

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

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

* Using full module path for logs

* Some minor renames and extractions

* Fixing a few clippy warnings about double references

* Ripped the allowed_hosts module out into separate module files

* Removing old comment

* Removing unused import

* Knocking down visibility on function

* Docs on OutboundRequestFilter

* Removing a function that doesn't justify its existence

* Keeping struct with its impl

* Renamed a few modules

* Smoothing and rearranging code, no big changes

* It's now possible to inject a standard allowed_list

* Logging all standard allowed domains at network requester startup

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

* ibid for 'tokio-stream'

* ibid for 'tokio-util'

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

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

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

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

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

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

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

* unifying some startup code and passing TaskClient around

* graceful shutdown handling for mix socket listener

* graceful shutdown handling for clients listener

* graceful shutdown handling for packet forwarding

* unified waiting for interrupt across binaries

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

* printing formatted message on main error

* fixed failing test

* removed duplicate code that should have been gone ages ago

* ibid

* removed biased selection for authenticated handler

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

* new react and reactdom packages in root

* new react and reactdom packages in nym connect

* new react and reactdom packages in root

* update react and reactdom for explorer

* react and react-dom upgrade for ts-packages

remove unused import

fix linting error

* use custom FC typing

move typings folder

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

* ibid

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

* Finishing merge of conflicted files

* Minor smoothing

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

* Refactored nyxd client usages to make things bit more clear

* Moved caching support stuff into the support folder

* Moved storage code into support module

* Removed dead code

* Tweaks

* Handling cases a little more nicely in circulating supply api

* Renamed nymd_client to nyxd_client

* Pulled CacheNotification into the caching support module

* Pulled some domain-specific helpers out of cache refresher

* Moving some more helper methods out of the cache refresher

* Deleting unused code

* Extracted a few more functions out of the cache refresher

* A few comments as breadcrumbs

* Renaming the anemic "helpers" to "node_sets"

* Renaming the validator_cache module to nym_contract_cache

* Renaming nym contract cache stuff to make things clearer

* Renamging a few things in comments

* Renaming validator_cache to nym_contract_cache

* foomp

* Started refactoring http and cli

* Extracted cli arg parsing into its own module

* Cleanup

* Extracted start methods into various modules to clean main up

* WIP commit

* Build working, swagger not

* Fixed swagger docs metadata

* Removed log statement

* Circulating supply cache now working with simple logic

* Fixed up circulating supply method names

* Starting to work in some (wrong) constants

* Documented the cache

* Renaming circulating-supply route

* nym-api compiling after the rebasing

but most likely not fully working yet

* removed unused imports

* only starting RewardedSetUpdater if the config flag is set

* nym-api compiling with coconut feature

* removed redundant process_runner

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

* signle entry point for starting nym_contract_cache

* do not eagerly grab instances of managed state

* inlining openapi route spec

* CirculatingSupplyResponse type

* fixed compilation of coconut tests

* calculating circulating supply based on mixmining reserve and vesting tokens

* separated different variants of caching intervals

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

* fixed types export

* renamed the query on the vesting contract

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

* cleaned up startup procedure for nym-api

* startup checks for rewarding permisssions

* updated changelog

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

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

* client-core: tidy docs and clippy

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

remove duplicated imports

* set and reset (when necessary) gateway performance

* remove unneeded useEffect

* remove log
2023-01-12 10:47:58 +01:00
farbanas dddc6eae57 fix: added continue-on-error for clippy-check since they fail on forked repositories due to permission errors which we won't solve 2023-01-12 10:45:27 +01:00
Jędrzej Stuczyński 8beb33fe92 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-11 14:37:05 +00: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
Jędrzej Stuczyński bf5b8fab85 made most of cli boolean arguments optional (#2819)
so that if not provided, they would not overwrite config values
2023-01-11 12:14:16 +00:00
Gala 70ae45b6c9 Changing the explorers guru link 2023-01-11 12:59:16 +01:00
Jon Häggblad b0960091c1 Merge pull request #2764 from nymtech/feature/rust-sdk-initial-version
Initial Rust client SDK
2023-01-11 10:06:15 +01:00
Jon Häggblad b97a12186f rust-fmt: append path in error 2023-01-11 00:32:21 +01:00
Jon Häggblad 36496a519a rust-sdk: add additinal example 2023-01-11 00:13:45 +01:00
Jon Häggblad 87fad25ac3 rust-sdk: implement manualy set/get keys 2023-01-11 00:13:28 +01:00
Jon Häggblad df3d478caa rust-sdk: make new_from_dir return result 2023-01-10 23:28:26 +01:00
Jon Häggblad 751e3ccd27 Merge remote-tracking branch 'origin/develop' into feature/rust-sdk-initial-version 2023-01-10 23:14:24 +01:00
Mark Sinclair 74a4546d72 GitHub Actions: post messages to another channel on job failures 2023-01-10 18:25:42 +00:00
Jędrzej Stuczyński 2587d00b9e feature: reduce staking address capabilities + refactor vesting storage (#2796)
* checks for existing staking account

* removed code for v2 migration

* using stronger types for storage keys

* Added type alias for the storage key and documented each `Map`

* remove the hacky way of storing staker information

* allow the staking address account to perform delegations with the additional msg argument

* new unit tests

* updated client code

* modified migrate msg to explicitly require confirming having performed manual checks

* re-ordered arguments
2023-01-10 17:36:27 +00:00
Fouad cf25c331c0 Upgrade webpack (#2800)
* upgrade webpack and remove unused client lib

* upgrade webpack loaders
2023-01-10 17:08:09 +00:00
Mark Sinclair a24c7e4783 Merge pull request #2813 from nymtech/feature/matrix-messages
Send matrix notification messages
2023-01-10 16:40:38 +00:00
Mark Sinclair 9ea725bf83 GitHub Actions: add matrix env vars to all jobs with notifications 2023-01-10 16:36:50 +00:00
Mark Sinclair fe78d4faf0 GitHub Actions: support sending notification messages to matrix 2023-01-10 16:24:23 +00:00
Jędrzej Stuczyński 0df063f9f6 feature: query for obtaining amount of vesting coins for all accounts (#2791)
* wip

* Introduced paged queries for getting list of all vesting accounts and for amount of vesting coins

* Added the queries to VestingQueryClient trait

* Added default implementations to all trait queries

* Fixed naming for the vesting coins query

* Helper functions for dealing with paging

* Updated changelog
2023-01-10 14:58:40 +00:00
Bogdan-Ștefan Neacşu ad8fdbdddf Feature/configurable dkg signup (#2809)
* Refactored consts to config structure

* Nym-cli generate init for dkg contract
2023-01-10 16:33:16 +02:00
Bogdan-Ștefan Neacşu 8d3aea969e Handle case when changed value is 42 (#2808) 2023-01-10 15:01:57 +02:00
farbanas 96444509d0 fix: updated changelog for binaries with the version of the release 2023-01-10 13:53:02 +01:00
farbanas 078ca0b0d1 Merge resolve 2023-01-10 13:52:00 +01:00
farbanas aab91e424e Merge resolve 2023-01-10 13:48:04 +01:00
farbanas 273dc41559 feat: update changelogs 2023-01-10 13:43:09 +01:00
farbanas 61bc74148f Update versions 2023-01-10 13:10:24 +01:00
Jędrzej Stuczyński 5b14eecf82 bugfix: for Default config impl generate fresh mnemonic over using a hardcoded one (#2806) 2023-01-10 10:39:58 +00:00
Jon Häggblad 2746cabecc rust-sdk: reorder in client file 2023-01-10 01:43:50 +01:00
Jon Häggblad 666cbcf2cc rust-sdk: extract out builder 2023-01-10 01:36:27 +01:00
Fran Arbanas 30110aff65 Merge pull request #1827 from nymtech/feat/nym-cli-cosmwasm-generate-init-message
nym-cli generate instantiate message for mixnet and vesting contracts
2023-01-09 19:54:28 +01:00
farbanas 1954c49ac2 merge resolve 2023-01-09 19:38:16 +01:00
farbanas 70328ba114 merge resolve 2023-01-09 19:30:25 +01:00
farbanas c43b2dc117 merge resolve 2023-01-09 16:03:42 +01:00
Drazen Urch 4a8a9096dd Save to JSON in addition to printing (#1864)
* Save to JSON in addition to printing

* Save node details to json for mixnode

* Remove Cargo.locks

* Cli ergonomics

* Json output for gateway
2023-01-09 12:51:21 +01:00
Jon Häggblad 96ab4325e3 rust-sdk: tidy 2023-01-09 12:39:23 +01:00
Jon Häggblad 11e2ba33e7 fix compilation after merge in latest develop 2023-01-09 10:44:02 +01:00
Jon Häggblad 95db26c35b changelog: add note 2023-01-09 10:43:42 +01:00
Jon Häggblad aed96b2d44 Merge remote-tracking branch 'origin/develop' into feature/rust-sdk-initial-version 2023-01-09 10:41:10 +01:00
Jon Häggblad 326d5fcec8 rustfmt 2023-01-09 10:02:46 +01:00
Jędrzej Stuczyński 88d813b9c1 Feature/optional set trait (#2773)
* Defined OptionalSet trait

* extended the trait to handle environment

* sample implementation for the gateway

* implementation for mixnode

* Added the same feature to nym-api config + made some config types stricter

* fixed compilation and linter issues

* keeping track of parsing error

* attempt at using the trait for the client configs

* Streamlined more arguments

* Removed deprecation on setters

* fixed incorrect test constructor

* missed rebase fixes
2023-01-06 18:13:25 +00:00
Pierre Dommerc e181a1cfb1 feat(wallet-buy): pass wallet address as url param (#2780) 2023-01-06 09:38:30 +01:00
Jon Häggblad afae6fc9a5 rust-sdk: move Keys to its own file 2023-01-05 17:44:03 +01:00
Jon Häggblad 23c13a409a rust-sdk: rename key_paths to paths 2023-01-05 17:06:21 +01:00
Dave Hrycyszyn 29091aab8e Feature/rename nymd to nyxd (#2696)
* Renaming all instances of nymd to nyxd

* Might as well get the changelogs too

* Making it clearer that an ApiClient is a NymApiClient

* Lining up config templates with struct keys on gateway

* Changed the last references to validator_urls to nyxd_urls

* Fixed up a few type errors after refactoring

* Changed the changelog

* Fixed typo in changelog

* Further instances of renaming 'nymd' + introducing additional clap aliases

* updated environmental variables and allowed usage of deprecated variants

* missing occurences of coconut-locked environmental variables

Co-authored-by: Jędrzej Stuczyński <jedrzej.stuczynski@gmail.com>
2023-01-05 15:35:47 +00:00
Jon Häggblad 1d522143a2 rust-sdk: remove more unwraps 2023-01-05 16:18:39 +01:00
Jon Häggblad 775ce0f95d rust-sdk: fix some issues identified during draft review 2023-01-05 16:18:39 +01:00
Jon Häggblad b019786c5a rust-sdk: replace a bunch of unwrap with error return 2023-01-05 16:18:39 +01:00
Jon Häggblad 9b9c01fb8f rust-sdk: initial version 2023-01-05 16:18:39 +01:00
Dave Hrycyszyn 6c857b5daf wip 2023-01-05 16:18:39 +01:00
Dave Hrycyszyn 5ea084d286 Starting with Rust sdk 2023-01-05 16:18:39 +01:00
Pierre Dommerc fdbe3a1f6a fix(explorer,explorer-api): mixnode location (#2763)
* chore(explorer-api): remove useless route (/terms)

* feat(explorer-api-geoip): add coordinates lat&lon

* fix(explorer): mixnode location

* fix: typo

* fix: clippy
2023-01-05 15:53:15 +01:00
Jędrzej Stuczyński 5f4926dd49 feature: use clap derive for nym-api + use stricter validation for other binaries (#2772)
* fixed all uses of deprecated clap methods

* updated all uses of clap to 4.0

* unified obtaining build information

* moved around the imports

* Moved all nym-api arguments to ApiArgs and simplified parsing

* Using common shutdown signal code

* Using clap for parsing Vec<Url>

* stricter validation of socks5-client arguments

* ibid for the native client

* ibid for the gateway

* ibid for the mixnode

* clippy
2023-01-05 10:32:57 +00:00
dependabot[bot] 1f132a4eaa build(deps): bump got and nodemon (#1624)
Bumps [got](https://github.com/sindresorhus/got) and [nodemon](https://github.com/remy/nodemon). These dependencies needed to be updated together.

Removes `got`

Updates `nodemon` from 2.0.12 to 2.0.19
- [Release notes](https://github.com/remy/nodemon/releases)
- [Commits](https://github.com/remy/nodemon/compare/v2.0.12...v2.0.19)

---
updated-dependencies:
- dependency-name: got
  dependency-type: indirect
- dependency-name: nodemon
  dependency-type: direct:production
...

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-05 10:21:05 +00:00
dependabot[bot] 097d2d51cc build(deps): bump undici, hardhat and @nomiclabs/hardhat-etherscan (#1634)
Bumps [undici](https://github.com/nodejs/undici), [hardhat](https://github.com/nomiclabs/hardhat) and [@nomiclabs/hardhat-etherscan](https://github.com/nomiclabs/hardhat). These dependencies needed to be updated together.

Updates `undici` from 4.16.0 to 5.10.0
- [Release notes](https://github.com/nodejs/undici/releases)
- [Commits](https://github.com/nodejs/undici/compare/v4.16.0...v5.10.0)

Updates `hardhat` from 2.9.2 to 2.11.2
- [Release notes](https://github.com/nomiclabs/hardhat/releases)
- [Commits](https://github.com/nomiclabs/hardhat/compare/hardhat@2.9.2...hardhat@2.11.2)

Updates `@nomiclabs/hardhat-etherscan` from 3.0.3 to 3.1.0
- [Release notes](https://github.com/nomiclabs/hardhat/releases)
- [Commits](https://github.com/nomiclabs/hardhat/compare/@nomiclabs/hardhat-etherscan@3.0.3...@nomiclabs/hardhat-etherscan@3.1.0)

---
updated-dependencies:
- dependency-name: undici
  dependency-type: indirect
- dependency-name: hardhat
  dependency-type: direct:development
- dependency-name: "@nomiclabs/hardhat-etherscan"
  dependency-type: direct:development
...

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-05 10:20:56 +00:00
dependabot[bot] a2078d997b Bump loader-utils from 1.4.0 to 1.4.2 (#1763)
Bumps [loader-utils](https://github.com/webpack/loader-utils) from 1.4.0 to 1.4.2.
- [Release notes](https://github.com/webpack/loader-utils/releases)
- [Changelog](https://github.com/webpack/loader-utils/blob/v1.4.2/CHANGELOG.md)
- [Commits](https://github.com/webpack/loader-utils/compare/v1.4.0...v1.4.2)

---
updated-dependencies:
- dependency-name: loader-utils
  dependency-type: indirect
...

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-05 10:20:37 +00:00
dependabot[bot] 558d4b899d Bump deep-object-diff from 1.1.7 to 1.1.9 (#1765)
Bumps [deep-object-diff](https://github.com/mattphillips/deep-object-diff) from 1.1.7 to 1.1.9.
- [Release notes](https://github.com/mattphillips/deep-object-diff/releases)
- [Commits](https://github.com/mattphillips/deep-object-diff/commits)

---
updated-dependencies:
- dependency-name: deep-object-diff
  dependency-type: indirect
...

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-05 10:20:24 +00:00
dependabot[bot] 4fcb98e839 Bump decode-uri-component in /contracts/basic-bandwidth-generation (#1838)
Bumps [decode-uri-component](https://github.com/SamVerschueren/decode-uri-component) from 0.2.0 to 0.2.2.
- [Release notes](https://github.com/SamVerschueren/decode-uri-component/releases)
- [Commits](https://github.com/SamVerschueren/decode-uri-component/compare/v0.2.0...v0.2.2)

---
updated-dependencies:
- dependency-name: decode-uri-component
  dependency-type: indirect
...

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-05 10:20:11 +00:00
dependabot[bot] 702bb202a3 Bump decode-uri-component from 0.2.0 to 0.2.2 (#1840)
Bumps [decode-uri-component](https://github.com/SamVerschueren/decode-uri-component) from 0.2.0 to 0.2.2.
- [Release notes](https://github.com/SamVerschueren/decode-uri-component/releases)
- [Commits](https://github.com/SamVerschueren/decode-uri-component/compare/v0.2.0...v0.2.2)

---
updated-dependencies:
- dependency-name: decode-uri-component
  dependency-type: indirect
...

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-05 10:19:59 +00:00
dependabot[bot] 71ff2c04a0 Bump express in /clients/native/examples/js-examples/websocket (#1849)
Bumps [express](https://github.com/expressjs/express) from 4.17.1 to 4.18.2.
- [Release notes](https://github.com/expressjs/express/releases)
- [Changelog](https://github.com/expressjs/express/blob/master/History.md)
- [Commits](https://github.com/expressjs/express/compare/4.17.1...4.18.2)

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

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-05 10:19:46 +00:00
dependabot[bot] cb30384eaf Bump qs and express in /clients/native/examples/js-examples/websocket (#1850)
Bumps [qs](https://github.com/ljharb/qs) and [express](https://github.com/expressjs/express). These dependencies needed to be updated together.

Updates `qs` from 6.7.0 to 6.11.0
- [Release notes](https://github.com/ljharb/qs/releases)
- [Changelog](https://github.com/ljharb/qs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ljharb/qs/compare/v6.7.0...v6.11.0)

Updates `express` from 4.17.1 to 4.18.2
- [Release notes](https://github.com/expressjs/express/releases)
- [Changelog](https://github.com/expressjs/express/blob/master/History.md)
- [Commits](https://github.com/expressjs/express/compare/4.17.1...4.18.2)

---
updated-dependencies:
- dependency-name: qs
  dependency-type: indirect
- dependency-name: express
  dependency-type: indirect
...

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-05 10:19:38 +00:00
dependabot[bot] e911c2fbc0 Bump qs and express in /clients/webassembly/js-example (#1851)
Bumps [qs](https://github.com/ljharb/qs) and [express](https://github.com/expressjs/express). These dependencies needed to be updated together.

Updates `qs` from 6.7.0 to 6.11.0
- [Release notes](https://github.com/ljharb/qs/releases)
- [Changelog](https://github.com/ljharb/qs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ljharb/qs/compare/v6.7.0...v6.11.0)

Updates `express` from 4.17.1 to 4.18.2
- [Release notes](https://github.com/expressjs/express/releases)
- [Changelog](https://github.com/expressjs/express/blob/master/History.md)
- [Commits](https://github.com/expressjs/express/compare/4.17.1...4.18.2)

---
updated-dependencies:
- dependency-name: qs
  dependency-type: indirect
- dependency-name: express
  dependency-type: indirect
...

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-05 10:19:27 +00:00
dependabot[bot] bb005a39f5 Bump qs, body-parser and express (#1852)
Bumps [qs](https://github.com/ljharb/qs), [qs](https://github.com/ljharb/qs), [body-parser](https://github.com/expressjs/body-parser) and [express](https://github.com/expressjs/express). These dependencies needed to be updated together.

Updates `qs` from 6.10.1 to 6.11.0
- [Release notes](https://github.com/ljharb/qs/releases)
- [Changelog](https://github.com/ljharb/qs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ljharb/qs/compare/v6.10.1...v6.11.0)

Updates `qs` from 6.5.2 to 6.11.0
- [Release notes](https://github.com/ljharb/qs/releases)
- [Changelog](https://github.com/ljharb/qs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ljharb/qs/compare/v6.10.1...v6.11.0)

Updates `body-parser` from 1.19.0 to 1.20.1
- [Release notes](https://github.com/expressjs/body-parser/releases)
- [Changelog](https://github.com/expressjs/body-parser/blob/master/HISTORY.md)
- [Commits](https://github.com/expressjs/body-parser/compare/1.19.0...1.20.1)

Updates `express` from 4.17.1 to 4.18.2
- [Release notes](https://github.com/expressjs/express/releases)
- [Changelog](https://github.com/expressjs/express/blob/master/History.md)
- [Commits](https://github.com/expressjs/express/compare/4.17.1...4.18.2)

---
updated-dependencies:
- dependency-name: qs
  dependency-type: indirect
- dependency-name: qs
  dependency-type: indirect
- dependency-name: body-parser
  dependency-type: indirect
- dependency-name: express
  dependency-type: indirect
...

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-05 10:19:19 +00:00
dependabot[bot] ea72c37083 Bump express in /contracts/basic-bandwidth-generation (#1853)
Bumps [express](https://github.com/expressjs/express) from 4.17.1 to 4.18.2.
- [Release notes](https://github.com/expressjs/express/releases)
- [Changelog](https://github.com/expressjs/express/blob/master/History.md)
- [Commits](https://github.com/expressjs/express/compare/4.17.1...4.18.2)

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

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-05 10:19:10 +00:00
dependabot[bot] a24dd8b9bc build(deps): bump json5 from 2.2.1 to 2.2.3 in /nym-api/tests (#2768)
Bumps [json5](https://github.com/json5/json5) from 2.2.1 to 2.2.3.
- [Release notes](https://github.com/json5/json5/releases)
- [Changelog](https://github.com/json5/json5/blob/main/CHANGELOG.md)
- [Commits](https://github.com/json5/json5/compare/v2.2.1...v2.2.3)

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

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-05 10:11:01 +00:00
dependabot[bot] b006c01397 build(deps): bump json5 from 2.2.1 to 2.2.3 in /testnet-faucet (#2769)
Bumps [json5](https://github.com/json5/json5) from 2.2.1 to 2.2.3.
- [Release notes](https://github.com/json5/json5/releases)
- [Changelog](https://github.com/json5/json5/blob/main/CHANGELOG.md)
- [Commits](https://github.com/json5/json5/compare/v2.2.1...v2.2.3)

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

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-05 10:10:38 +00:00
dependabot[bot] f7f2a51458 build(deps): bump json5 from 1.0.1 to 1.0.2 (#2770)
Bumps [json5](https://github.com/json5/json5) from 1.0.1 to 1.0.2.
- [Release notes](https://github.com/json5/json5/releases)
- [Changelog](https://github.com/json5/json5/blob/main/CHANGELOG.md)
- [Commits](https://github.com/json5/json5/compare/v1.0.1...v1.0.2)

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

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-05 10:10:04 +00:00
Jon Häggblad 408396c900 client-core: remove generic parameter for ClientCoreError (#2765)
* client-core: remove generic parameter for ClientCoreError

* fix compilation
2023-01-04 15:41:11 +01:00
Jędrzej Stuczyński a97c913bb1 Fixed missing feature lock for coconut-exlusive fields (#2767) 2023-01-04 14:00:55 +00:00
Jędrzej Stuczyński dba5a9caef Renamed 'nym-validator-api' package name to 'nym-api' (#2766) 2023-01-04 13:00:37 +00:00
Pierre Dommerc 3e39573feb feat(wallet-buy): pass wallet address as url param (#2752) 2023-01-04 13:26:09 +01:00
Jędrzej Stuczyński ac312e9109 feature: standarise arguments (#2762)
* Renamed "address" argument in "sign" command to "wallet-address"

* Ability to optionally describe mixnode with command line arguments

* renamed 'validators' arguments to 'nym-apis' in mixnode binary

* cleaned up gateway validator-related url arguments

* fixup! Renamed "address" argument in "sign" command to "wallet-address"

* renamed 'use_anonymous_sender_tag' to 'use_anonymous_replies'

* 'nymd_endpoints => 'nymd_validators'

* more consistency for nymd_validators and nym_apis urls arguments

* updated changelog
2023-01-04 09:59:08 +00:00
Jędrzej Stuczyński 8a2a7dc0ce bugfix: don't start rewarding unless rewarding.enabled is explicitly set to true (#2753)
* start rewarded set updater based on config flag

* removed dead code annotation

* updated changelog
2023-01-04 09:44:32 +00:00
Fouad 5b15ed6f15 merge resolve 2022-12-22 15:48:40 +01:00
Fouad 9684b7ffbd merge resolve 2022-12-22 15:45:02 +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
Gala 57703af642 Merge pull request #2746 from nymtech/revert-1519-339-net-switch-bttn
Revert "NE: Switch button to change the explorer network"
2022-12-22 14:21:24 +01:00
Gala 9dd4c5d871 Revert "NE: Switch button to change the explorer network" 2022-12-22 14:20:21 +01:00
farbanas 4813cf6c18 feat: release v1.1.5 of nym-wallet 2022-12-22 12:14:01 +01:00
farbanas 29f48efe49 feat: release v1.1.5 of nym-wallet 2022-12-22 12:13:44 +01:00
farbanas 280ac34115 feat: release v1.1.5 of nym-wallet 2022-12-22 12:12:46 +01:00
benedetta davico 83b76c6b37 Merge pull request #1519 from nymtech/339-net-switch-bttn
NE: Switch button to change the explorer network
2022-12-22 11:23:00 +01:00
Gala 4120234155 fix build problem 2022-12-22 11:09:55 +01:00
Gala 42b444ddf8 Merge branch '339-net-switch-bttn' of github.com:nymtech/nym into 339-net-switch-bttn 2022-12-22 10:55:03 +01:00
Gala acd832d8e5 cleaning 2022-12-22 10:54:26 +01:00
Gala 75a726ebbe some styles 2022-12-22 10:54:12 +01:00
Gala b9fbab6024 adding button on mov nav and make it smaller 2022-12-22 10:54:12 +01:00
Gala 06ed8716a1 adding a switch between networks 2022-12-22 10:54:12 +01:00
benedetta davico beddd3dcee Merge pull request #2742 from nymtech/feat/2130-tables-update-rebase
Feat/2130 tables update rebase
2022-12-22 10:37:53 +01:00
Drazen Urch bdc285dbbb Add numeric family ids to explorer-api (#2707) 2022-12-21 23:37:32 +01:00
benedetta davico 4d02dfb899 Merge pull request #2741 from nymtech/fix/explorer-gateway-bond-decimals
fix(explorer): set gateway bond 6 decimals
2022-12-21 18:10:47 +01:00
Gala 80d6cb5c12 last small touch 2022-12-21 17:34:26 +01:00
Gala 7422ab69ba Merge branch 'feat/2130-tables-update-rebase' of github.com:nymtech/nym into feat/2130-tables-update-rebase 2022-12-21 17:30:26 +01:00
Gala 60c8185bea cleaning 2022-12-21 17:26:34 +01:00
Gala 9d3c7c0be8 refactor from PR request 2022-12-21 17:26:34 +01:00
Gala d6048fae52 refactor 2022-12-21 17:26:22 +01:00
Gala ddb7b0e872 delegations layout and tooltip when delegate with vesting 2022-12-21 17:26:22 +01:00
Gala 4995dde705 bond table changes 2022-12-21 17:25:09 +01:00
Gala 63bfe4246f fix parameters settings layout 2022-12-21 17:24:23 +01:00
Gala 4654b360e0 cleaning 2022-12-21 17:23:52 +01:00
Gala 7c5c19986a refactor from PR request 2022-12-21 17:23:52 +01:00
Gala 46edca0bd4 refactor 2022-12-21 17:23:52 +01:00
Gala b03a1f922d refactor 2022-12-21 17:23:52 +01:00
Gala 9616c90433 delegations layout and tooltip when delegate with vesting 2022-12-21 17:23:52 +01:00
Gala ea49f0a265 delegations table changes wip 2022-12-21 17:23:52 +01:00
Gala 2470c8b9b5 tidying up 2022-12-21 17:23:52 +01:00
Gala 7d001965ec change date order to dd/mm/yy 2022-12-21 17:22:26 +01:00
Gala 11b1089d83 removing epoch on settings and fixing divider position 2022-12-21 17:22:26 +01:00
Gala 52699d7598 bond table changes 2022-12-21 17:21:51 +01:00
benedetta davico 87443dd624 Merge pull request #2743 from nymtech/feat/2161-ne-gate-version
Feat/2161 ne gate version
2022-12-21 15:25:07 +01:00
benedetta davico a02a1b0385 Merge pull request #2728 from nymtech/feat/2722-ne-ui
make fields match button height
2022-12-21 15:09:32 +01:00
Gala e0f2fa6705 fix indentation 2022-12-21 14:45:14 +01:00
Gala 7949b07213 Merge branch 'feat/2161-ne-gate-version' of github.com:nymtech/nym into feat/2161-ne-gate-version 2022-12-21 14:07:16 +01:00
Gala bd20fd0b1f remove console log 2022-12-21 14:06:32 +01:00
Gala 57d3d6fd0f sdding version number on the gateways list and details 2022-12-21 14:06:32 +01:00
Gala 06eff652dd wip adding gt version 2022-12-21 14:06:32 +01:00
Gala 246decac4a remove console log 2022-12-21 14:01:53 +01:00
Gala a14ae298ae sdding version number on the gateways list and details 2022-12-21 13:59:23 +01:00
Gala 43188051d3 Merge branch 'feat/2130-tables-update-rebase' of github.com:nymtech/nym into feat/2130-tables-update-rebase 2022-12-21 12:48:46 +01:00
Gala 8aa15fa467 fix parameters settings layout 2022-12-21 12:41:12 +01:00
benedetta davico f77b037ef7 Merge pull request #2704 from nymtech/feature/nym-connect-display-info
NymConnect - Display service info in tooltip **1.1.5 Release**
2022-12-21 12:39:44 +01:00
Gala 75dbc5d790 Merge branch 'release/v1.1.5' into feat/2130-tables-update-rebase 2022-12-21 12:20:42 +01:00
Gala e6bcd706ff cleaning 2022-12-21 12:03:46 +01:00
Gala 9a077a0928 refactor from PR request 2022-12-21 12:03:46 +01:00
Gala 11fd42e187 refactor 2022-12-21 12:03:46 +01:00
Gala 6e499e5996 refactor 2022-12-21 12:03:46 +01:00
Gala f98cc73a1f delegations layout and tooltip when delegate with vesting 2022-12-21 12:03:46 +01:00
Gala db9bf4d3fa delegations table changes wip 2022-12-21 12:03:46 +01:00
Gala b30628529d tidying up 2022-12-21 12:03:46 +01:00
Gala 3be615f74f change date order to dd/mm/yy 2022-12-21 12:03:46 +01:00
Gala a8ccd2ec17 removing epoch on settings and fixing divider position 2022-12-21 12:03:46 +01:00
Gala 2d71caf50a bond table changes 2022-12-21 12:03:46 +01:00
Gala 4d08d62fc2 wip adding gt version 2022-12-21 11:54:41 +01:00
pierre 40e5595d65 fix(explorer): set gateway bond 6 decimals 2022-12-21 11:46:12 +01:00
Gala 6780d58a98 cleaning 2022-12-21 11:19:50 +01:00
Gala ccbf06f179 refactor from PR request 2022-12-21 11:19:50 +01:00
Gala e6ecf71cc3 refactor 2022-12-21 11:19:50 +01:00
Gala c66312ee96 refactor 2022-12-21 11:19:50 +01:00
Gala 808802aeb4 delegations layout and tooltip when delegate with vesting 2022-12-21 11:19:50 +01:00
Gala fb38f24e5c delegations table changes wip 2022-12-21 11:19:50 +01:00
Gala 65f148a5ad tidying up 2022-12-21 11:19:50 +01:00
Gala 2bcdc5d11e change date order to dd/mm/yy 2022-12-21 11:19:50 +01:00
Gala 5ecb03ffe9 removing epoch on settings and fixing divider position 2022-12-21 11:19:50 +01:00
Gala 8505989dad bond table changes 2022-12-21 11:19:50 +01:00
benedetta davico ed5e865db7 Merge pull request #2718 from nymtech/feature/wallet-epoch-time-in-unbond-modal
Add epoch info to unbond modal **1.1.5 Release**
2022-12-21 10:37:38 +01:00
benedetta davico ea3194e0c3 Merge pull request #2720 from nymtech/feature/wallet-fix-parameter-input-layout
Fix param input layout **1.1.5 Release**
2022-12-21 10:24:05 +01:00
Gala 190bff4ffe Merge branch 'release/v1.1.5' of github.com:nymtech/nym into release/v1.1.5 2022-12-21 10:21:23 +01:00
fmtabbara c509555d15 fix param input layout 2022-12-21 09:22:01 +01:00
fmtabbara f0d66fdd88 add epoch info to unbond modal 2022-12-21 09:19:39 +01:00
fmtabbara 14847d01b7 remove console.log 2022-12-21 09:17:38 +01:00
fmtabbara f4711902bd display service info in tooltip
trim provider address
2022-12-21 09:17:38 +01:00
Jędrzej Stuczyński 32ad93c57e Feature/multi surb transmission lanes (#2723)
* Preserve information about original transmission lanes when buffering reply packets

* Attempting to send partial data in 'handle_send_reply' if we don't have enough surbs immediately

* Display logging of reply surb request target

* promoted reply_controller to a directory

* moved channels and messages to separate file

* simplifications due to rust 1.66

* Using a shoarthand for obtaining connection_id

* made TransmissionBuffer generic

* Moved transmissaion buffer to a higher level directory + defined wasm helpers

* Using transmission buffer in reply controller

* Using the pending replies size in lane lenghts queries

* fixed an out of bounds use of fragments

* Fixed dropped channel in getting lane queue length

* Fixed an edge case failure for reply retransmissions

* measuring (and logging) time it takes to obtain lane lenghts

* decreased logging level

* Removed non-wasm lock on total_size
2022-12-20 19:38:49 +00:00
farbanas c4a68dbbe6 chore: formatting 2022-12-20 15:28:51 +01:00
fmtabbara 1140503eba merge 1.1.4 to develop 2022-12-20 13:49:10 +00:00
farbanas d92d6877a4 Merge branch 'release/v1.1.4' 2022-12-20 12:33:46 +01:00
Drazen Urch b4f2233d2b Outfox and Lion (#2730) 2022-12-20 11:29:28 +01:00
Gala a746738d48 make fields match button height 2022-12-19 13:40:26 +01:00
Jon Häggblad c67f0fb7f8 Merge remote-tracking branch 'origin/release/v1.1.4' into develop 2022-12-19 12:39:11 +01:00
Fouad 7c12a3422c Feature/node settings apy playground (#1677)
* 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>
2022-12-19 11:22:51 +00:00
Jon Häggblad 6c4f0bc2f4 validator-client: fix typo in error message 2022-12-19 09:12:33 +01:00
Jon Häggblad 052a9a71c2 client: tweak shutdown order (#2724)
* clients: slightly tweak shutdown

* tweak log
2022-12-16 17:03:39 +01:00
Jon Häggblad da094f0208 wallet: rewrite some abci errors on the fly (#2716)
* wallet: rewrite some abci errors on the fly

* changelog: update

* Tidy
2022-12-16 12:02:23 +01:00
Bogdan-Ștefan Neacşu 254302ec38 Feature/auto dkg advance (#2714)
* Add dkg epoch

* Make epoch state advancement dependent only on time

* Nym api tries advancing the dkg epoch state

* Update the time table a bit

It still needs to be changed before production, as the sign-up timeframe
needs to be something like a few days.

* Update changelog

* Fix tests

* Fix clippy after rustc update
2022-12-16 12:21:39 +02:00
Jon Häggblad b7be48a1b3 Merge remote-tracking branch 'origin/release/v1.1.4' into develop 2022-12-16 11:09:31 +01:00
Jon Häggblad 870c4f73a8 socks5: send additional status messages available for the frontend (#2715)
* socks5: send network-requester error in status channel

* Minor tidy

* task-manager: send status msg to indicate ready

* changelog: add note

* coconut/tests: fix clippy for rustc 1.66
2022-12-16 00:24:45 +01:00
Jon Häggblad c2c883e840 client: create websocket handler builder (#2700)
* client: create websocket handler builder

* rustfmt
2022-12-16 00:23:58 +01:00
Bogdan-Ștefan Neacşu 5e600de932 Modify wasm specific make targets (#2693) 2022-12-15 12:22:43 +02:00
farbanas 70fcb8c046 feat: added the rest of the generators, updated some fields based on PR comments 2022-12-15 10:07:19 +01:00
Jon Häggblad eb07ec8580 client: sort out shutdown procedure and harmonize with socks5-client (#2695)
* common/task: rename ShutdownNotifier to TaskManager

* nym-client: return boxed error

* nym-client: enable graceful shutdown

* nym-client: task wait on shutdown to instead exit on closed channel

* Fix build

* Fix unused

* changelog: update
2022-12-14 17:13:00 +01:00
Dave Hrycyszyn f6a79ce7c3 Renaming validator-api to nym-api (#1863)
* Renaming validator-api to nym-api

* nym-api: simplified crate name

* Added nym-api rename to changelog

* Changed some output messages

* Renamed validator-api-requests to nym-api requests

* Removing more references to validator-api-requests

* Additional lockfile name changes after full build

* Removing mistakenly added merge files

* ibid

* ibid

* Getting rid of ref to validator_api deep inside validator-client

* Fixing file storage paths

* Renaming struct function names referring to validator_api

* Simplifying struct init

* Fixed up all other instances of nym_api.

* Renaming validatorApi to nymApi in TypeScript client for consistency

v

* Found a few more Rust instances

* Changed examples in TypeScript SDK

* Found one more instance of the use of validator instead of nym apis

* Aliasing config key name for deserialization to preserve compatibility with old configs
2022-12-14 15:05:01 +00:00
Fouad 4ece8b7e8f Feature/nym connect experimental software text (#2692)
* use experimental text
2022-12-14 13:04:54 +00:00
Bogdan-Ștefan Neacşu bb557985c0 DKG resharing unit test (#2668) 2022-12-14 14:47:59 +02:00
Fouad 3ebb24b2c8 get version number from tauri and display (#2684)
* get version number from tauri and display

* update internal version numbers
2022-12-14 12:12:34 +00:00
Jędrzej Stuczyński 97b01db23e Chore/more error macros (#2686)
* cleaned up MixProcessingError

* Added Error impl to (hopefully) all error enums in the codebase

* Replaced all occurences of error("{0}") with error(transparent)

* Changelog entry
2022-12-13 17:42:11 +00:00
farbanas ce676c2bb5 Merge branch 'release/v1.1.3' 2022-12-13 15:18:49 +01:00
farbanas a096f9d54e Merge branch 'release/v1.1.3' 2022-12-13 13:24:01 +01:00
farbanas d9b6823106 Merge branch 'release/v1.1.2' 2022-12-07 12:37:14 +01:00
farbanas 89bcb5649b changed ubuntu-latest on GH actions to ubuntu-20.04 2022-12-06 17:23:08 +01:00
farbanas 53444cf55a fix: rewarding denom was unyxt by default, it should be unymt 2022-12-05 13:22:21 +01:00
farbanas f2e460a96b chore: import cleanup 2022-12-01 12:17:46 +01:00
farbanas b5b7b7255b feat: add vesting contract instatiate message generation 2022-12-01 11:41:03 +01:00
farbanas 894a46688a chore: formatting 2022-12-01 10:21:00 +01:00
farbanas 5d3550a569 fix: remove the debug output for instantiate message as it incorrectly escapes strings 2022-12-01 10:16:36 +01:00
farbanas b43dab4f83 chore: added a couple of debug messages to parseOptionalAccount 2022-11-30 17:24:25 +01:00
farbanas 1bdb58571d feat: refactor cosmwasm nym-cli command a bit to support multiple tiers. Add a generator for mixnet contract instantiate messages 2022-11-30 16:01:35 +01:00
Gala a74a99d81d cleaning 2022-08-10 16:38:56 +02:00
Gala c09d3af92f Merge branch 'develop' into 340-ne-content 2022-08-10 16:35:38 +02:00
Gala 76773c58d7 some styles 2022-08-10 16:34:30 +02:00
Gala fd90175e87 adding button on mov nav and make it smaller 2022-08-10 15:43:42 +02:00
Gala 0eb859467e adding a switch between networks 2022-08-10 15:09:44 +02:00
1281 changed files with 50006 additions and 44103 deletions
+1 -1
View File
@@ -14,7 +14,7 @@ GEOIPUPDATE_LICENSE_KEY=xxx
# List of space-separated database edition IDs. Edition IDs may # List of space-separated database edition IDs. Edition IDs may
# consist of letters, digits, and dashes. For example, GeoIP2-City # consist of letters, digits, and dashes. For example, GeoIP2-City
# would download the GeoIP2 City database (GeoIP2-City). # would download the GeoIP2 City database (GeoIP2-City).
GEOIPUPDATE_EDITION_IDS=GeoLite2-Country GEOIPUPDATE_EDITION_IDS=GeoLite2-City
# The number of hours between geoipupdate runs. If this is not set # The number of hours between geoipupdate runs. If this is not set
# or is set to 0, geoipupdate will run once and exit. # or is set to 0, geoipupdate will run once and exit.
GEOIPUPDATE_FREQUENCY=72 GEOIPUPDATE_FREQUENCY=72
+10 -1
View File
@@ -26,7 +26,7 @@ jobs:
path: .github/workflows/support-files/notifications/deny.message path: .github/workflows/support-files/notifications/deny.message
notification: notification:
needs: cargo-deny needs: cargo-deny
runs-on: ubuntu-20.04 runs-on: custom-runner-linux
steps: steps:
- name: Check out repository code - name: Check out repository code
uses: actions/checkout@v2 uses: actions/checkout@v2
@@ -35,6 +35,10 @@ jobs:
with: with:
name: report name: report
path: .github/workflows/support-files/notifications path: .github/workflows/support-files/notifications
- name: install npm
uses: actions/setup-node@v3
with:
node-version: 16
- name: Keybase - Node Install - name: Keybase - Node Install
run: npm install run: npm install
working-directory: .github/workflows/support-files working-directory: .github/workflows/support-files
@@ -47,6 +51,11 @@ jobs:
KEYBASE_NYMBOT_PAPERKEY: "${{ secrets.KEYBASE_NYMBOT_PAPERKEY }}" KEYBASE_NYMBOT_PAPERKEY: "${{ secrets.KEYBASE_NYMBOT_PAPERKEY }}"
KEYBASE_NYMBOT_TEAM: "${{ secrets.KEYBASE_NYMBOT_TEAM }}" KEYBASE_NYMBOT_TEAM: "${{ secrets.KEYBASE_NYMBOT_TEAM }}"
KEYBASE_NYM_CHANNEL: "security" 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 uses: docker://keybaseio/client:stable-node
with: with:
args: .github/workflows/support-files/notifications/entry_point.sh args: .github/workflows/support-files/notifications/entry_point.sh
@@ -0,0 +1,113 @@
name: Build and upload binaries to CI
on:
workflow_dispatch:
push:
paths:
- 'clients/**'
- 'common/**'
- 'contracts/**'
- '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:
- 'clients/**'
- 'common/**'
- 'contracts/**'
- 'explorer-api/**'
- 'gateway/**'
- 'integrations/**'
- 'mixnode/**'
- 'sdk/rust/nym-sdk/**'
- 'service-providers/**'
- 'nym-api/**'
- 'nym-outfox/**'
- 'tools/nym-cli/**'
- 'tools/ts-rs-cli/**'
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: Prepare build output directory
shell: bash
env:
OUTPUT_DIR: ci-builds/${{ github.ref_name }}
run: |
rm -rf ci-builds || true
mkdir -p $OUTPUT_DIR
echo $OUTPUT_DIR
- 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: 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: Install Rust stable
uses: actions-rs/toolchain@v1
with:
toolchain: stable
target: wasm32-unknown-unknown
override: true
components: rustfmt, clippy
- name: Build release contracts
run: make wasm
- name: Prepare build output
shell: bash
env:
OUTPUT_DIR: ci-builds/${{ github.ref_name }}
run: |
cp target/release/nym-client $OUTPUT_DIR
cp target/release/nym-gateway $OUTPUT_DIR
cp target/release/nym-mixnode $OUTPUT_DIR
cp target/release/nym-socks5-client $OUTPUT_DIR
cp target/release/nym-api $OUTPUT_DIR
cp target/release/nym-network-requester $OUTPUT_DIR
cp target/release/nym-network-statistics $OUTPUT_DIR
cp target/release/nym-cli $OUTPUT_DIR
cp contracts/target/wasm32-unknown-unknown/release/mixnet_contract.wasm $OUTPUT_DIR
cp contracts/target/wasm32-unknown-unknown/release/vesting_contract.wasm $OUTPUT_DIR
- name: Deploy branch to CI www
continue-on-error: true
uses: easingthemes/ssh-deploy@main
env:
SSH_PRIVATE_KEY: ${{ secrets.CI_WWW_SSH_PRIVATE_KEY }}
ARGS: "-avzr"
SOURCE: "ci-builds/"
REMOTE_HOST: ${{ secrets.CI_WWW_REMOTE_HOST }}
REMOTE_USER: ${{ secrets.CI_WWW_REMOTE_USER }}
TARGET: ${{ secrets.CI_WWW_REMOTE_TARGET }}/builds/
EXCLUDE: "/dist/, /node_modules/"
@@ -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
+6
View File
@@ -12,6 +12,7 @@ jobs:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- name: Install rsync - name: Install rsync
run: sudo apt-get install rsync run: sudo apt-get install rsync
continue-on-error: true
- uses: rlespinasse/github-slug-action@v3.x - uses: rlespinasse/github-slug-action@v3.x
- uses: actions/setup-node@v3 - uses: actions/setup-node@v3
with: with:
@@ -58,6 +59,11 @@ jobs:
KEYBASE_NYMBOT_TEAM: "${{ secrets.KEYBASE_NYMBOT_TEAM }}" KEYBASE_NYMBOT_TEAM: "${{ secrets.KEYBASE_NYMBOT_TEAM }}"
KEYBASE_NYM_CHANNEL: "ci-ts-packages" KEYBASE_NYM_CHANNEL: "ci-ts-packages"
IS_SUCCESS: "${{ job.status == 'success' }}" 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 uses: docker://keybaseio/client:stable-node
with: with:
args: .github/workflows/support-files/notifications/entry_point.sh args: .github/workflows/support-files/notifications/entry_point.sh
+39 -29
View File
@@ -2,21 +2,44 @@ name: Continuous integration
on: on:
push: push:
paths-ignore: paths:
- 'explorer/**' - '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: pull_request:
paths-ignore: paths:
- 'explorer/**' - '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: jobs:
build: build:
runs-on: [ self-hosted, custom-linux ] runs-on: [ self-hosted, custom-linux ]
# Enable sccache via environment variable # Enable sccache via environment variable
env: env:
RUSTC_WRAPPER: /home/ubuntu/.cargo/bin/sccache RUSTC_WRAPPER: /home/ubuntu/.cargo/bin/sccache
steps: steps:
- name: Install Dependencies (Linux) - 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 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 - name: Check out repository code
uses: actions/checkout@v2 uses: actions/checkout@v2
@@ -41,47 +64,34 @@ jobs:
command: build command: build
args: --workspace args: --workspace
- name: Build all examples
uses: actions-rs/cargo@v1
with:
command: build
args: --workspace --examples
- name: Run all tests - name: Run all tests
uses: actions-rs/cargo@v1 uses: actions-rs/cargo@v1
with: with:
command: test command: test
args: --workspace --all-features args: --workspace
- name: Run expensive tests - name: Run expensive tests
if: github.ref == 'refs/heads/develop' || github.event.pull_request.base.ref == 'develop' || github.event.pull_request.base.ref == 'master' 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 uses: actions-rs/cargo@v1
with: with:
command: test command: test
args: --workspace --all-features -- --ignored args: --workspace -- --ignored
- uses: actions-rs/clippy-check@v1 - uses: actions-rs/clippy-check@v1
name: Clippy checks name: Clippy checks
continue-on-error: true
with: with:
token: ${{ secrets.GITHUB_TOKEN }} token: ${{ secrets.GITHUB_TOKEN }}
args: --workspace --all-features args: --workspace
- name: Run clippy - name: Run clippy
uses: actions-rs/cargo@v1 uses: actions-rs/cargo@v1
with: with:
command: clippy command: clippy
args: --workspace -- -D warnings args: --workspace --all-targets -- -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
+70
View File
@@ -0,0 +1,70 @@
name: Nym Connect for Android (rust)
on:
push:
paths:
- "nym-connect-android/src-tauri/**"
- "clients/client-core/**"
- "clients/socks5/**"
- "common/**"
- "gateway/gateway-requests/**"
- "contracts/vesting/**"
- "nym-api/nym-api-requests/**"
pull_request:
paths:
- "nym-connect-android/src-tauri/**"
- "clients/client-core/**"
- "clients/socks5/**"
- "common/**"
- "gateway/gateway-requests/**"
- "contracts/vesting/**"
- "nym-api/nym-api-requests/**"
jobs:
build:
#runs-on: [self-hosted, custom-linux]
runs-on: ubuntu-22.04
#env:
#RUSTC_WRAPPER: /home/ubuntu/.cargo/bin/sccache
#defaults:
#run:
#working-directory: nym-connect-android/src-tauri/
steps:
- name: Install Dependencies (Linux)
if: ${{ !env.ACT }}
run: |
sudo apt-get update
sudo apt-get -y install \
libwebkit2gtk-4.1-dev \
build-essential \
curl \
wget \
libssl-dev \
libgtk-3-dev \
squashfs-tools \
libayatana-appindicator3-dev \
librsvg2-dev \
libsoup-3.0-dev \
libjavascriptcoregtk-4.1-dev
#continue-on-error: true
- name: Checkout
uses: actions/checkout@v3
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@master
with:
toolchain: stable
components: clippy, rustfmt
- name: Check formatting
run: cargo fmt --manifest-path nym-connect-android/src-tauri/Cargo.toml -- --check
- name: Build all binaries
run: cargo build --manifest-path nym-connect-android/src-tauri/Cargo.toml
- name: Run all tests
run: cargo test --manifest-path nym-connect-android/src-tauri/Cargo.toml
- name: Clippy
run: cargo clippy --manifest-path nym-connect-android/src-tauri/Cargo.toml --all-targets -- -D warnings
+19 -2
View File
@@ -2,8 +2,23 @@ name: Nym Connect (rust)
on: on:
push: push:
paths-ignore: paths:
- 'explorer/**' - '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: jobs:
build: build:
@@ -13,6 +28,7 @@ jobs:
steps: steps:
- name: Install Dependencies (Linux) - 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 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 - name: Check out repository code
uses: actions/checkout@v2 uses: actions/checkout@v2
@@ -45,6 +61,7 @@ jobs:
- uses: actions-rs/clippy-check@v1 - uses: actions-rs/clippy-check@v1
name: Clippy checks name: Clippy checks
continue-on-error: true
with: with:
token: ${{ secrets.GITHUB_TOKEN }} token: ${{ secrets.GITHUB_TOKEN }}
args: --manifest-path nym-connect/Cargo.toml --workspace --all-features args: --manifest-path nym-connect/Cargo.toml --workspace --all-features
+2 -8
View File
@@ -6,17 +6,11 @@ on:
jobs: jobs:
build: 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: steps:
- uses: actions/checkout@v2 - 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 - name: Install Rust stable
uses: actions-rs/toolchain@v1 uses: actions-rs/toolchain@v1
with: with:
+5 -3
View File
@@ -2,11 +2,13 @@ name: Contracts
on: on:
push: push:
paths-ignore: paths:
- 'explorer/**' - 'contracts/**'
- 'common/**'
pull_request: pull_request:
paths-ignore: paths-ignore:
- 'explorer/**' - 'contracts/**'
- 'common/**'
jobs: jobs:
matrix_prep: matrix_prep:
+127
View File
@@ -0,0 +1,127 @@
name: NC Android APK Release
on:
workflow_dispatch:
push:
branches:
- "release/nc-android-v[0-9].[0-9].[0-9]*"
jobs:
build:
name: Build APK
runs-on: ubuntu-latest
env:
ANDROID_HOME: ${{ github.workspace }}/android-sdk
NDK_VERSION: 25.1.8937393
NDK_HOME: ${{ env.ANDROID_HOME }}/ndk/${{ env.NDK_VERSION }}
SDK_PLATFORM_VERSION: android-33
SDK_BUILDTOOLS_VERSION: 33.0.1
steps:
- name: Install Dependencies (Linux)
# https://next--tauri.netlify.app/next/guides/getting-started/prerequisites/linux/#1-system-dependencies
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 \
librsvg2-dev
- name: Install Java
uses: actions/setup-java@v3
with:
distribution: "temurin"
java-version: "17"
- name: Install Android SDK manager
# https://developer.android.com/studio/command-line/sdkmanager
run: |
curl -sS https://dl.google.com/android/repository/commandlinetools-linux-9477386_latest.zip -o cmdline-tools.zip
unzip cmdline-tools.zip
mkdir -p $ANDROID_HOME/cmdline-tools/latest
mv cmdline-tools/* $ANDROID_HOME/cmdline-tools/latest
rm -rf cmdline-tools
- name: Install Android S/NDK
run: |
echo y | $ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager --licenses
echo y | $ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager \
"platforms;$SDK_PLATFORM_VERSION" \
"platform-tools" \
"ndk;$NDK_VERSION" \
"build-tools;$SDK_BUILDTOOLS_VERSION"
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
- name: Install tauri cli
run: cargo install tauri-cli --version "^2.0.0-alpha.2"
- name: Install rust android targets
run: |
rustup target add aarch64-linux-android \
armv7-linux-androideabi \
i686-linux-android \
x86_64-linux-android
- name: Setup Nodejs
uses: actions/setup-node@v3
with:
node-version: 18
- name: Install yarn
run: |
npm i -g yarn
yarn --version
- name: Checkout
uses: actions/checkout@v3
- name: Build frontend code
run: |
yarn install --frozen-lockfile
yarn build
yarn workspace @nym/nym-connect-android webpack:prod
- name: Build APK
working-directory: nym-connect-android
env:
WRY_ANDROID_PACKAGE: net.nymtech.nym_connect_android
WRY_ANDROID_LIBRARY: nym_connect_android
# TODO build with release profile (--release), it will requires
# to sign the APK. For now build with debug profile to avoid that
run: cargo tauri android build --debug --apk
# TODO add the version number to APK name
- name: Rename APK artifact
run: |
mv nym-connect-android/src-tauri/gen/android/nym_connect_android/app/build/outputs/apk/universal/debug/app-universal-debug.apk \
nym-connect-debug.apk
- name: Upload APK artifact
uses: actions/upload-artifact@v3
with:
name: nc-apk-debug
path: nym-connect-debug.apk
publish:
name: Publish APK
needs: build
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Download binary artifact
uses: actions/download-artifact@v3
with:
name: nc-apk-debug
path: apk
# TODO add a step to upload the APK somewhere
# - name: Publish
# uses: ???
+2 -1
View File
@@ -10,6 +10,7 @@ env:
jobs: jobs:
publish-nym: publish-nym:
if: ${{ startsWith(github.ref, 'refs/tags/nym-explorer-api-') && (github.event_name == 'release' || github.event_name == 'workflow_dispatch') }}
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
@@ -21,9 +22,9 @@ jobs:
- name: Install Dependencies (Linux) - 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 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-` - name: Check the release tag starts with `nym-explorer-api-`
if: startsWith(github.ref, 'refs/tags/nym-explorer-api-') == false && github.event_name != 'workflow_dispatch'
uses: actions/github-script@v3 uses: actions/github-script@v3
with: with:
script: | script: |
+6
View File
@@ -17,6 +17,7 @@ jobs:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- name: Install rsync - name: Install rsync
run: sudo apt-get install rsync run: sudo apt-get install rsync
continue-on-error: true
- uses: rlespinasse/github-slug-action@v3.x - uses: rlespinasse/github-slug-action@v3.x
- uses: actions/setup-node@v3 - uses: actions/setup-node@v3
with: with:
@@ -73,6 +74,11 @@ jobs:
KEYBASE_NYMBOT_TEAM: "${{ secrets.KEYBASE_NYMBOT_TEAM }}" KEYBASE_NYMBOT_TEAM: "${{ secrets.KEYBASE_NYMBOT_TEAM }}"
KEYBASE_NYM_CHANNEL: "ci-network-explorer" KEYBASE_NYM_CHANNEL: "ci-network-explorer"
IS_SUCCESS: "${{ job.status == 'success' }}" 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 uses: docker://keybaseio/client:stable-node
with: with:
args: .github/workflows/support-files/notifications/entry_point.sh args: .github/workflows/support-files/notifications/entry_point.sh
+34 -42
View File
@@ -25,6 +25,7 @@ jobs:
steps: steps:
- name: Install Dependencies (Linux) - 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 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' if: matrix.os == 'ubuntu-20.04'
- name: Check out repository code - name: Check out repository code
@@ -38,6 +39,12 @@ jobs:
override: true override: true
components: rustfmt, clippy components: rustfmt, clippy
- name: Check formatting
uses: actions-rs/cargo@v1
with:
command: fmt
args: --all -- --check
- name: Build all binaries - name: Build all binaries
uses: actions-rs/cargo@v1 uses: actions-rs/cargo@v1
with: with:
@@ -50,6 +57,18 @@ jobs:
with: with:
command: clean 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 - name: Run all tests
uses: actions-rs/cargo@v1 uses: actions-rs/cargo@v1
with: with:
@@ -58,7 +77,7 @@ jobs:
- name: Reclaim some disk space (because Windows is being annoying) - name: Reclaim some disk space (because Windows is being annoying)
uses: actions-rs/cargo@v1 uses: actions-rs/cargo@v1
if: ${{ matrix.os == 'windows-latest' }} if: ${{ matrix.os == 'windows-latest' || matrix.os == 'ubuntu-20.04' }}
with: with:
command: clean command: clean
@@ -67,13 +86,7 @@ jobs:
uses: actions-rs/cargo@v1 uses: actions-rs/cargo@v1
with: with:
command: test command: test
args: --workspace --all-features -- --ignored args: --workspace -- --ignored
- name: Check formatting
uses: actions-rs/cargo@v1
with:
command: fmt
args: --all -- --check
- name: Reclaim some disk space (because Windows is being annoying) - name: Reclaim some disk space (because Windows is being annoying)
uses: actions-rs/cargo@v1 uses: actions-rs/cargo@v1
@@ -83,9 +96,10 @@ jobs:
- uses: actions-rs/clippy-check@v1 - uses: actions-rs/clippy-check@v1
name: Clippy checks name: Clippy checks
continue-on-error: true
with: with:
token: ${{ secrets.GITHUB_TOKEN }} token: ${{ secrets.GITHUB_TOKEN }}
args: --all-features args: --workspace
- name: Run clippy - name: Run clippy
uses: actions-rs/cargo@v1 uses: actions-rs/cargo@v1
@@ -100,38 +114,6 @@ jobs:
with: with:
command: clean 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) # nym-wallet (the rust part)
- name: Build nym-wallet rust code - name: Build nym-wallet rust code
uses: actions-rs/cargo@v1 uses: actions-rs/cargo@v1
@@ -160,12 +142,17 @@ jobs:
notification: notification:
needs: build needs: build
runs-on: ubuntu-20.04 runs-on: custom-runner-linux
steps: steps:
- name: Collect jobs status - name: Collect jobs status
uses: technote-space/workflow-conclusion-action@v2 uses: technote-space/workflow-conclusion-action@v2
- name: Check out repository code - name: Check out repository code
uses: actions/checkout@v2 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 - name: Keybase - Node Install
if: env.WORKFLOW_CONCLUSION == 'failure' if: env.WORKFLOW_CONCLUSION == 'failure'
run: npm install run: npm install
@@ -183,6 +170,11 @@ jobs:
KEYBASE_NYMBOT_TEAM: "${{ secrets.KEYBASE_NYMBOT_TEAM }}" KEYBASE_NYMBOT_TEAM: "${{ secrets.KEYBASE_NYMBOT_TEAM }}"
KEYBASE_NYM_CHANNEL: "ci-nightly" KEYBASE_NYM_CHANNEL: "ci-nightly"
IS_SUCCESS: "${{ env.WORKFLOW_CONCLUSION == 'success' }}" IS_SUCCESS: "${{ env.WORKFLOW_CONCLUSION == '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 uses: docker://keybaseio/client:stable-node
with: with:
args: .github/workflows/support-files/notifications/entry_point.sh args: .github/workflows/support-files/notifications/entry_point.sh
+13 -33
View File
@@ -38,6 +38,7 @@ jobs:
steps: steps:
- name: Install Dependencies (Linux) - 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 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' if: matrix.os == 'ubuntu-20.04'
- name: Check out latest release branch - name: Check out latest release branch
@@ -98,6 +99,7 @@ jobs:
- uses: actions-rs/clippy-check@v1 - uses: actions-rs/clippy-check@v1
name: Clippy checks name: Clippy checks
continue-on-error: true
with: with:
token: ${{ secrets.GITHUB_TOKEN }} token: ${{ secrets.GITHUB_TOKEN }}
args: --all-features args: --all-features
@@ -115,38 +117,6 @@ jobs:
with: with:
command: clean 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) # nym-wallet (the rust part)
- name: Build nym-wallet rust code - name: Build nym-wallet rust code
uses: actions-rs/cargo@v1 uses: actions-rs/cargo@v1
@@ -175,12 +145,17 @@ jobs:
notification: notification:
needs: [build,get_release] needs: [build,get_release]
runs-on: ubuntu-20.04 runs-on: custom-runner-linux
steps: steps:
- name: Collect jobs status - name: Collect jobs status
uses: technote-space/workflow-conclusion-action@v2 uses: technote-space/workflow-conclusion-action@v2
- name: Check out repository code - name: Check out repository code
uses: actions/checkout@v3 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 - name: Keybase - Node Install
if: env.WORKFLOW_CONCLUSION == 'failure' if: env.WORKFLOW_CONCLUSION == 'failure'
run: npm install run: npm install
@@ -198,6 +173,11 @@ jobs:
KEYBASE_NYMBOT_TEAM: "${{ secrets.KEYBASE_NYMBOT_TEAM }}" KEYBASE_NYMBOT_TEAM: "${{ secrets.KEYBASE_NYMBOT_TEAM }}"
KEYBASE_NYM_CHANNEL: "ci-nightly-release" KEYBASE_NYM_CHANNEL: "ci-nightly-release"
IS_SUCCESS: "${{ env.WORKFLOW_CONCLUSION == 'success' }}" IS_SUCCESS: "${{ env.WORKFLOW_CONCLUSION == '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 uses: docker://keybaseio/client:stable-node
with: with:
args: .github/workflows/support-files/notifications/entry_point.sh args: .github/workflows/support-files/notifications/entry_point.sh
+13 -33
View File
@@ -38,6 +38,7 @@ jobs:
steps: steps:
- name: Install Dependencies (Linux) - 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 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' if: matrix.os == 'ubuntu-20.04'
- name: Check out latest release branch - name: Check out latest release branch
@@ -98,6 +99,7 @@ jobs:
- uses: actions-rs/clippy-check@v1 - uses: actions-rs/clippy-check@v1
name: Clippy checks name: Clippy checks
continue-on-error: true
with: with:
token: ${{ secrets.GITHUB_TOKEN }} token: ${{ secrets.GITHUB_TOKEN }}
args: --all-features args: --all-features
@@ -115,38 +117,6 @@ jobs:
with: with:
command: clean 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) # nym-wallet (the rust part)
- name: Build nym-wallet rust code - name: Build nym-wallet rust code
uses: actions-rs/cargo@v1 uses: actions-rs/cargo@v1
@@ -175,12 +145,17 @@ jobs:
notification: notification:
needs: [build,get_release] needs: [build,get_release]
runs-on: ubuntu-20.04 runs-on: custom-runner-linux
steps: steps:
- name: Collect jobs status - name: Collect jobs status
uses: technote-space/workflow-conclusion-action@v2 uses: technote-space/workflow-conclusion-action@v2
- name: Check out repository code - name: Check out repository code
uses: actions/checkout@v3 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 - name: Keybase - Node Install
if: env.WORKFLOW_CONCLUSION == 'failure' if: env.WORKFLOW_CONCLUSION == 'failure'
run: npm install run: npm install
@@ -198,6 +173,11 @@ jobs:
KEYBASE_NYMBOT_TEAM: "${{ secrets.KEYBASE_NYMBOT_TEAM }}" KEYBASE_NYMBOT_TEAM: "${{ secrets.KEYBASE_NYMBOT_TEAM }}"
KEYBASE_NYM_CHANNEL: "ci-nightly-release" KEYBASE_NYM_CHANNEL: "ci-nightly-release"
IS_SUCCESS: "${{ env.WORKFLOW_CONCLUSION == 'success' }}" IS_SUCCESS: "${{ env.WORKFLOW_CONCLUSION == '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 uses: docker://keybaseio/client:stable-node
with: with:
args: .github/workflows/support-files/notifications/entry_point.sh args: .github/workflows/support-files/notifications/entry_point.sh
+1 -1
View File
@@ -10,6 +10,7 @@ env:
jobs: jobs:
publish-nym-cli: publish-nym-cli:
if: ${{ startsWith(github.ref, 'refs/tags/nym-cli-') && (github.event_name == 'release' || github.event_name = 'workflow_dispatch') }}
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
@@ -20,7 +21,6 @@ jobs:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: Check the release tag starts with `nym-cli-` - name: Check the release tag starts with `nym-cli-`
if: startsWith(github.ref, 'refs/tags/nym-cli-') == false && github.event_name != 'workflow_dispatch'
uses: actions/github-script@v3 uses: actions/github-script@v3
with: with:
script: | script: |
@@ -10,6 +10,7 @@ defaults:
jobs: jobs:
publish-tauri: publish-tauri:
if: ${{ startsWith(github.ref, 'refs/tags/nym-connect-') && github.event_name == 'release' }}
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
@@ -19,13 +20,6 @@ jobs:
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- name: Check the release tag starts with `nym-connect-`
if: startsWith(github.ref, 'refs/tags/nym-connect-') == false && github.event_name != 'workflow_dispatch'
uses: actions/github-script@v3
with:
script: |
core.setFailed('Release tag did not start with nym-connect-...')
- name: Node v16 - name: Node v16
uses: actions/setup-node@v3 uses: actions/setup-node@v3
with: with:
@@ -10,10 +10,11 @@ defaults:
jobs: jobs:
publish-tauri: publish-tauri:
if: ${{ startsWith(github.ref, 'refs/tags/nym-connect-') && github.event_name == 'release' }}
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
platform: [ubuntu-20.04] platform: [custom-runner-linux]
runs-on: ${{ matrix.platform }} runs-on: ${{ matrix.platform }}
steps: steps:
@@ -23,17 +24,13 @@ jobs:
run: > run: >
sudo apt-get update && sudo apt-get update &&
sudo apt-get install -y webkit2gtk-4.0 libayatana-appindicator3-dev sudo apt-get install -y webkit2gtk-4.0 libayatana-appindicator3-dev
- name: Check the release tag starts with `nym-connect-` continue-on-error: true
if: startsWith(github.ref, 'refs/tags/nym-connect-') == false && github.event_name != 'workflow_dispatch'
uses: actions/github-script@v3
with:
script: |
core.setFailed('Release tag did not start with nym-connect-...')
- name: Node v16 - name: Node v16
uses: actions/setup-node@v3 uses: actions/setup-node@v3
with: with:
node-version: 16 node-version: 16
- name: Install Rust stable - name: Install Rust stable
uses: actions-rs/toolchain@v1 uses: actions-rs/toolchain@v1
with: with:
@@ -10,6 +10,7 @@ defaults:
jobs: jobs:
publish-tauri: publish-tauri:
if: ${{ startsWith(github.ref, 'refs/tags/nym-connect-') && github.event_name == 'release' }}
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
@@ -27,13 +28,6 @@ jobs:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: Check the release tag starts with `nym-connect-`
if: startsWith(github.ref, 'refs/tags/nym-connect-') == false && github.event_name != 'workflow_dispatch'
uses: actions/github-script@v3
with:
script: |
core.setFailed('Release tag did not start with nym-connect-...')
- name: Import signing certificate - name: Import signing certificate
env: env:
WINDOWS_CERTIFICATE: ${{ secrets.WINDOWS_CERTIFICATE }} WINDOWS_CERTIFICATE: ${{ secrets.WINDOWS_CERTIFICATE }}
+6
View File
@@ -16,6 +16,7 @@ jobs:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- name: Install rsync - name: Install rsync
run: sudo apt-get install rsync run: sudo apt-get install rsync
continue-on-error: true
- uses: rlespinasse/github-slug-action@v3.x - uses: rlespinasse/github-slug-action@v3.x
- uses: actions/setup-node@v3 - uses: actions/setup-node@v3
with: with:
@@ -54,6 +55,11 @@ jobs:
KEYBASE_NYMBOT_TEAM: "${{ secrets.KEYBASE_NYMBOT_TEAM }}" KEYBASE_NYMBOT_TEAM: "${{ secrets.KEYBASE_NYMBOT_TEAM }}"
KEYBASE_NYM_CHANNEL: "ci-nym-connect" KEYBASE_NYM_CHANNEL: "ci-nym-connect"
IS_SUCCESS: "${{ job.status == 'success' }}" 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 uses: docker://keybaseio/client:stable-node
with: with:
args: .github/workflows/support-files/notifications/entry_point.sh args: .github/workflows/support-files/notifications/entry_point.sh
+7 -10
View File
@@ -16,10 +16,11 @@ env:
jobs: jobs:
publish-nym: publish-nym:
if: ${{ startsWith(github.ref, 'refs/tags/nym-binaries-') && github.event_name == 'release' }}
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
platform: [ubuntu-20.04] platform: [custom-runner-linux]
runs-on: ${{ matrix.platform }} runs-on: ${{ matrix.platform }}
steps: steps:
@@ -27,13 +28,7 @@ jobs:
- name: Install Dependencies (Linux) - 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 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-binaries-`
if: startsWith(github.ref, 'refs/tags/nym-binaries-') == false && github.event_name != 'workflow_dispatch'
uses: actions/github-script@v3
with:
script: |
core.setFailed('Release tag did not start with nym-binaries-...')
- name: Sets env vars for tokio if set in manual dispatch inputs - name: Sets env vars for tokio if set in manual dispatch inputs
run: | run: |
@@ -56,11 +51,12 @@ jobs:
with: with:
name: my-artifact name: my-artifact
path: | path: |
target/release/explorer-api
target/release/nym-client target/release/nym-client
target/release/nym-gateway target/release/nym-gateway
target/release/nym-mixnode target/release/nym-mixnode
target/release/nym-socks5-client target/release/nym-socks5-client
target/release/nym-validator-api target/release/nym-api
target/release/nym-network-requester target/release/nym-network-requester
target/release/nym-network-statistics target/release/nym-network-statistics
target/release/nym-cli target/release/nym-cli
@@ -71,11 +67,12 @@ jobs:
if: github.event_name == 'release' if: github.event_name == 'release'
with: with:
files: | files: |
target/release/explorer-api
target/release/nym-client target/release/nym-client
target/release/nym-gateway target/release/nym-gateway
target/release/nym-mixnode target/release/nym-mixnode
target/release/nym-socks5-client target/release/nym-socks5-client
target/release/nym-validator-api target/release/nym-api
target/release/nym-network-requester target/release/nym-network-requester
target/release/nym-network-statistics target/release/nym-network-statistics
target/release/nym-cli target/release/nym-cli
@@ -10,6 +10,7 @@ defaults:
jobs: jobs:
publish-tauri: publish-tauri:
if: ${{ startsWith(github.ref, 'refs/tags/nym-wallet-') && github.event_name == 'release' }}
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
@@ -19,13 +20,6 @@ jobs:
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- name: Check the release tag starts with `nym-wallet-`
if: startsWith(github.ref, 'refs/tags/nym-wallet-') == false && github.event_name != 'workflow_dispatch'
uses: actions/github-script@v3
with:
script: |
core.setFailed('Release tag did not start with nym-wallet-...')
- name: Node v16 - name: Node v16
uses: actions/setup-node@v3 uses: actions/setup-node@v3
with: with:
@@ -9,10 +9,11 @@ defaults:
jobs: jobs:
publish-tauri: publish-tauri:
if: ${{ startsWith(github.ref, 'refs/tags/nym-wallet-') && github.event_name == 'release' }}
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
platform: [ubuntu-20.04] platform: [custom-runner-linux]
runs-on: ${{ matrix.platform }} runs-on: ${{ matrix.platform }}
steps: steps:
@@ -22,17 +23,13 @@ jobs:
run: > run: >
sudo apt-get update && sudo apt-get update &&
sudo apt-get install -y webkit2gtk-4.0 sudo apt-get install -y webkit2gtk-4.0
- name: Check the release tag starts with `nym-wallet-` continue-on-error: true
if: startsWith(github.ref, 'refs/tags/nym-wallet-') == false
uses: actions/github-script@v3
with:
script: |
core.setFailed('Release tag did not start with nym-wallet-...')
- name: Node v16 - name: Node v16
uses: actions/setup-node@v3 uses: actions/setup-node@v3
with: with:
node-version: 16 node-version: 16
- name: Install Rust stable - name: Install Rust stable
uses: actions-rs/toolchain@v1 uses: actions-rs/toolchain@v1
with: with:
@@ -9,6 +9,7 @@ defaults:
jobs: jobs:
publish-tauri: publish-tauri:
if: ${{ startsWith(github.ref, 'refs/tags/nym-wallet-') && github.event_name == 'release' }}
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
@@ -26,13 +27,6 @@ jobs:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: Check the release tag starts with `nym-wallet-`
if: startsWith(github.ref, 'refs/tags/nym-wallet-') == false
uses: actions/github-script@v3
with:
script: |
core.setFailed('Release tag did not start with nym-wallet-...')
- name: Import signing certificate - name: Import signing certificate
env: env:
WINDOWS_CERTIFICATE: ${{ secrets.WINDOWS_CERTIFICATE }} WINDOWS_CERTIFICATE: ${{ secrets.WINDOWS_CERTIFICATE }}
@@ -12,6 +12,7 @@ jobs:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- name: Install rsync - name: Install rsync
run: sudo apt-get install rsync run: sudo apt-get install rsync
continue-on-error: true
- uses: rlespinasse/github-slug-action@v3.x - uses: rlespinasse/github-slug-action@v3.x
- uses: actions/setup-node@v3 - uses: actions/setup-node@v3
with: with:
@@ -50,6 +51,11 @@ jobs:
KEYBASE_NYMBOT_TEAM: "${{ secrets.KEYBASE_NYMBOT_TEAM }}" KEYBASE_NYMBOT_TEAM: "${{ secrets.KEYBASE_NYMBOT_TEAM }}"
KEYBASE_NYM_CHANNEL: "ci-nym-wallet" KEYBASE_NYM_CHANNEL: "ci-nym-wallet"
IS_SUCCESS: "${{ job.status == 'success' }}" 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 uses: docker://keybaseio/client:stable-node
with: with:
args: .github/workflows/support-files/notifications/entry_point.sh args: .github/workflows/support-files/notifications/entry_point.sh
+1
View File
@@ -26,6 +26,7 @@ jobs:
libappindicator3-dev libappindicator3-dev
webkit2gtk-driver webkit2gtk-driver
xvfb xvfb
continue-on-error: true
- name: Install minimal stable - name: Install minimal stable
uses: actions-rs/toolchain@v1 uses: actions-rs/toolchain@v1
@@ -2,6 +2,13 @@ KEYBASE_NYM_CHANNEL=
KEYBASE_NYMBOT_USERNAME= KEYBASE_NYMBOT_USERNAME=
KEYBASE_NYMBOT_PAPERKEY= KEYBASE_NYMBOT_PAPERKEY=
MATRIX_SERVER=
MATRIX_ROOM=
MATRIX_ROOM_OF_SHAME=
MATRIX_USER_ID=
MATRIX_TOKEN=
MATRIX_DEVICE_ID=
NYM_NOTIFICATION_KIND=nightly NYM_NOTIFICATION_KIND=nightly
NYM_PROJECT_NAME=Nightly Build NYM_PROJECT_NAME=Nightly Build
+3 -1
View File
@@ -2,4 +2,6 @@ node_modules
.idea .idea
# don't commit the lock file to avoid cross-platform issues # don't commit the lock file to avoid cross-platform issues
package-lock.json package-lock.json
scratch
@@ -1,6 +1,7 @@
require('dotenv').config(); require('dotenv').config();
const Bot = require('keybase-bot'); const Bot = require('keybase-bot');
const { sendMatrixMessage } = require('./send_message_to_matrix');
let context = { let context = {
kinds: ['nym-wallet', 'ts-packages', 'network-explorer', 'nightly', 'nym-connect','security'], kinds: ['nym-wallet', 'ts-packages', 'network-explorer', 'nightly', 'nym-connect','security'],
@@ -38,6 +39,28 @@ function validateContext() {
'Paperkey is not defined. Please set env var KEYBASE_NYMBOT_PAPERKEY', 'Paperkey is not defined. Please set env var KEYBASE_NYMBOT_PAPERKEY',
); );
} }
if (context.env.MATRIX_ROOM) {
if (!context.env.MATRIX_SERVER) {
throw new Error(
'Matrix server is not defined. Please set env var MATRIX_SERVER',
);
}
if (!context.env.MATRIX_USER_ID) {
throw new Error(
'Matrix user id is not defined. Please set env var MATRIX_USER_ID',
);
}
if (!context.env.MATRIX_TOKEN) {
throw new Error(
'Matrix token is not defined. Please set env var MATRIX_TOKEN',
);
}
if (!context.env.MATRIX_DEVICE_ID) {
throw new Error(
'Matrix device id is not defined. Please set env var MATRIX_DEVICE_ID',
);
}
}
} }
/** /**
@@ -147,6 +170,13 @@ async function main() {
console.log('-----------------------------------------'); console.log('-----------------------------------------');
} }
await sendKeybaseMessage(messageBody); await sendKeybaseMessage(messageBody);
if(context.env.MATRIX_ROOM) {
await sendMatrixMessage(context, messageBody, context.env.MATRIX_ROOM)
}
if(context.env.MATRIX_ROOM_OF_SHAME && context.env.IS_SUCCESS !== 'true') {
// when a job fails
await sendMatrixMessage(context, messageBody, context.env.MATRIX_ROOM_OF_SHAME)
}
} }
// call main function and let NodeJS handle the promise // call main function and let NodeJS handle the promise
@@ -0,0 +1,80 @@
const sdk = require('matrix-js-sdk');
global.Olm = require('olm');
const { LocalStorage } = require('node-localstorage');
const localStorage = new LocalStorage('./scratch');
const {
LocalStorageCryptoStore,
} = require('matrix-js-sdk/lib/crypto/store/localStorage-crypto-store');
const vfile = require('to-vfile');
const unified = require('unified');
const remarkParse = require('remark-parse');
const remarkHtml = require('remark-html');
const emoji = require('remark-emoji');
// hide all matrix client output
console.error = (error) => console.log('❌ error: ', error);
process.stderr.write = () => {};
process.stdout.write = () => {};
function createClient(context, room, message) {
const server = context.env.MATRIX_SERVER;
const token = context.env.MATRIX_TOKEN;
const deviceId = context.env.MATRIX_DEVICE_ID;
const userId = context.env.MATRIX_USER_ID;
const client = sdk.createClient({
baseUrl: server,
accessToken: token,
userId,
deviceId,
sessionStore: new sdk.WebStorageSessionStore(localStorage),
cryptoStore: new LocalStorageCryptoStore(localStorage),
});
client.on('sync', async function(state, prevState, res) {
if (state !== 'PREPARED') return;
client.setGlobalErrorOnUnknownDevices(false);
try {
await client.joinRoom(room);
await client.sendEvent(
room,
'm.room.message',
{
msgtype: 'm.text',
format: 'org.matrix.custom.html',
body: message,
formatted_body: message,
},
'',
);
} catch (error) {
console.error('Job failed: ' + error.message);
}
client.stopClient();
process.exit(0);
});
return client;
}
async function markdownToHtml(messageAsMarkdown) {
const file = await unified()
.use(emoji)
.use(remarkParse)
.use(remarkHtml)
.process(await vfile({ path: 'test.md', contents: messageAsMarkdown}));
return String(file);
}
async function sendMatrixMessage(contextArg, messageAsMarkdown, roomId) {
const messageAsHtml = await markdownToHtml(messageAsMarkdown);
const client = createClient(contextArg, roomId, messageAsHtml);
await client.initCrypto();
await client.startClient({ initialSyncLimit: 1 });
}
module.exports = {
sendMatrixMessage,
};
+9 -1
View File
@@ -11,7 +11,15 @@
"dotenv": "^16.0.0", "dotenv": "^16.0.0",
"handlebars": "^4.7.7", "handlebars": "^4.7.7",
"keybase-bot": "^3.6.1", "keybase-bot": "^3.6.1",
"octokit": "^1.7.1" "matrix-js-sdk": "^9.3.0",
"node-localstorage": "^2.1.6",
"octokit": "^1.7.1",
"olm": "https://packages.matrix.org/npm/olm/olm-3.2.1.tgz",
"remark-emoji": "^2.2.0",
"remark-html": "^13.0.2",
"remark-parse": "^9.0.0",
"to-vfile": "^6.1.0",
"unified": "^9.2.2"
}, },
"devDependencies": { "devDependencies": {
"prettier": "2.3.2" "prettier": "2.3.2"
+51
View File
@@ -0,0 +1,51 @@
name: CI for linting Typescript
on:
push:
paths:
- 'ts-packages/**'
- 'sdk/typescript/**'
- nym-connect
- nym-connect-android
- nym-wallet
jobs:
build:
runs-on: custom-runner-linux
steps:
- uses: actions/checkout@v2
- name: Install rsync
run: sudo apt-get install rsync
continue-on-error: true
- uses: rlespinasse/github-slug-action@v3.x
- uses: actions/setup-node@v3
with:
node-version: 16
- name: Setup yarn
run: npm install -g yarn
- name: Lint
run: yarn && yarn lint && yarn tsc
- name: Keybase - Node Install
run: npm install
working-directory: .github/workflows/support-files
- name: Keybase - Send Notification
env:
NYM_NOTIFICATION_KIND: ts-packages
NYM_PROJECT_NAME: "ts-packages"
NYM_CI_WWW_BASE: "${{ secrets.NYM_CI_WWW_BASE }}"
NYM_CI_WWW_LOCATION: "ts-${{ env.GITHUB_REF_SLUG }}"
GIT_COMMIT_MESSAGE: "${{ github.event.head_commit.message }}"
GIT_BRANCH: "${GITHUB_REF##*/}"
KEYBASE_NYMBOT_USERNAME: "${{ secrets.KEYBASE_NYMBOT_USERNAME }}"
KEYBASE_NYMBOT_PAPERKEY: "${{ secrets.KEYBASE_NYMBOT_PAPERKEY }}"
KEYBASE_NYMBOT_TEAM: "${{ secrets.KEYBASE_NYMBOT_TEAM }}"
KEYBASE_NYM_CHANNEL: "ci-ts-packages"
IS_SUCCESS: "${{ job.status == 'success' }}"
MATRIX_SERVER: "${{ secrets.MATRIX_SERVER }}"
MATRIX_ROOM: "${{ secrets.MATRIX_ROOM }}"
MATRIX_USER_ID: "${{ secrets.MATRIX_USER_ID }}"
MATRIX_TOKEN: "${{ secrets.MATRIX_TOKEN }}"
MATRIX_DEVICE_ID: "${{ secrets.MATRIX_DEVICE_ID }}"
uses: docker://keybaseio/client:stable-node
with:
args: .github/workflows/support-files/notifications/entry_point.sh
+12 -4
View File
@@ -2,11 +2,17 @@ name: Nym Wallet (rust)
on: on:
push: push:
paths-ignore: paths:
- 'explorer/**' - 'nym-wallet/**'
- 'common/**'
- 'contracts/vesting/**'
- 'nym-api/nym-api-requests/**'
pull_request: pull_request:
paths-ignore: paths:
- 'explorer/**' - 'nym-wallet/**'
- 'common/**'
- 'contracts/vesting/**'
- 'nym-api/nym-api-requests/**'
jobs: jobs:
build: build:
@@ -16,6 +22,7 @@ jobs:
steps: steps:
- name: Install Dependencies (Linux) - 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 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 - name: Check out repository code
uses: actions/checkout@v2 uses: actions/checkout@v2
@@ -48,6 +55,7 @@ jobs:
- uses: actions-rs/clippy-check@v1 - uses: actions-rs/clippy-check@v1
name: Clippy checks name: Clippy checks
continue-on-error: true
with: with:
token: ${{ secrets.GITHUB_TOKEN }} token: ${{ secrets.GITHUB_TOKEN }}
args: --manifest-path nym-wallet/Cargo.toml --workspace --all-features args: --manifest-path nym-wallet/Cargo.toml --workspace --all-features
+7 -12
View File
@@ -2,8 +2,13 @@ name: Wasm Client
on: on:
pull_request: pull_request:
paths-ignore: paths:
- 'explorer/**' - 'clients/webassembly/**'
- 'clients/client-core/**'
- 'common/**'
- 'contracts/**'
- 'gateway/gateway-requests/**'
- 'nym-api/nym-api-requests/**'
jobs: jobs:
wasm: wasm:
@@ -24,16 +29,6 @@ jobs:
command: build command: build
args: --manifest-path clients/webassembly/Cargo.toml --target wasm32-unknown-unknown 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 - uses: actions-rs/cargo@v1
with: with:
command: fmt command: fmt
+5 -1
View File
@@ -38,4 +38,8 @@ validator-config
validator-api-config.toml validator-api-config.toml
dist dist
storybook-static storybook-static
envs/qwerty.env envs/qwerty.env
Cargo.lock
nym-connect/Cargo.lock
.parcel-cache
**/.DS_Store
+7 -5
View File
@@ -1,6 +1,8 @@
{ {
"mainnet":[{ "mainnet": [
"nymd_url":"https://rpc.nyx.nodes.guru/", {
"api_url":"https://api.nyx.nodes.guru/" "nyxd_url": "https://rpc.nyx.nodes.guru/",
}] "api_url": "https://api.nyx.nodes.guru/"
} }
]
}
+141 -41
View File
@@ -2,15 +2,121 @@
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). 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.
- dkg resharing mode ([#2936])
[#2890]: https://github.com/nymtech/nym/pull/2890
[#2939]: https://github.com/nymtech/nym/pull/2939
[#2936]: https://github.com/nymtech/nym/pull/2936
# [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 ([#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] (2023-01-10)
### Added
### Changed
## [v1.1.5] (2023-01-10)
### Added
- socks5: send status message for service ready, and network-requester error response in https://github.com/nymtech/nym/pull/2715
### Changed
- all-binaries: improved error logging in https://github.com/nymtech/nym/pull/2686
- native client: bring shutdown logic up to the same level as socks5-client in https://github.com/nymtech/nym/pull/2695
- nym-api, coconut-dkg contract: automatic, time-based dkg epoch state advancement in https://github.com/nymtech/nym/pull/2670
- DKG resharing unit test by @neacsu in https://github.com/nymtech/nym/pull/2668
- Renaming validator-api to nym-api by @futurechimp in https://github.com/nymtech/nym/pull/1863
- Modify wasm specific make targets by @neacsu in https://github.com/nymtech/nym/pull/2693
- client: create websocket handler builder by @octol in https://github.com/nymtech/nym/pull/2700
- Outfox and Lion by @durch in https://github.com/nymtech/nym/pull/2730
- Feature/multi surb transmission lanes by @jstuczyn in https://github.com/nymtech/nym/pull/2723
## [v1.1.4] (2022-12-20) ## [v1.1.4] (2022-12-20)
This release adds multiple Single Use Reply Blocks (SURBs) to allow arbitrarily-sized anonymized replies. This release adds multiple Single Use Reply Blocks (SURBs) to allow arbitrarily-sized anonymized replies.
At the moment this is turned off by default, but available for use by application developers. At the moment this is turned off by default, but available for use by application developers.
We will need to wait for network-requesters to upgrade to this new release, after which multi-SURB anonymization will become the default setting for the SOCKS proxy clients. We will need to wait for network-requesters to upgrade to this new release, after which multi-SURB anonymization will become the default setting for the SOCKS proxy clients.
The release also include some additional work for distributed key generation in the Coconut signing authority nodes. The release also include some additional work for distributed key generation in the Coconut signing authority nodes.
### Changed ### Changed
@@ -25,7 +131,7 @@ The release also include some additional work for distributed key generation in
### Changed ### Changed
- validator-api: can recover from shutdown during DKG process ([#1872]) - validator-api: can recover from shutdown during DKG process ([#1872])
- clients: deduplicate gateway inititialization, part of work towards a rust-sdk - clients: deduplicate gateway initialization, part of work towards a rust-sdk
- clients: keep all transmission lanes going at all times by making priority probabilistic - clients: keep all transmission lanes going at all times by making priority probabilistic
- clients: ability to use multi-reply SURBs to send arbitrarily long messages fully anonymously whilst requesting additional reply blocks whenever they're about to run out ([#1796], [#1801], [#1804], [#1835], [#1858], [#1883])) - clients: ability to use multi-reply SURBs to send arbitrarily long messages fully anonymously whilst requesting additional reply blocks whenever they're about to run out ([#1796], [#1801], [#1804], [#1835], [#1858], [#1883]))
@@ -33,7 +139,7 @@ The release also include some additional work for distributed key generation in
- network-requester: fix bug where websocket connection disconnect resulted in success error code - network-requester: fix bug where websocket connection disconnect resulted in success error code
- clients: fix a few panics handling the gateway-client - clients: fix a few panics handling the gateway-client
- mixnode, gateway, validator-api: Use mainnet values as defaults for URLs and mixnet contract ([#1884]) - mixnode, gateway, validator-api: Use mainnet values as defaults for URLs and mixnet contract ([#1884])
- socks5: fixed bug where connections sometimes where closed too early - socks5: fixed bug where connections sometimes where closed too early
- clients: improve message logging when received message fails to get reconstructed ([#1803]) - clients: improve message logging when received message fails to get reconstructed ([#1803])
@@ -53,7 +159,7 @@ The release also include some additional work for distributed key generation in
- gateway: Renamed flag from `enabled/disabled_credentials_mode` to `only-coconut-credentials` - gateway: Renamed flag from `enabled/disabled_credentials_mode` to `only-coconut-credentials`
- "Family" feature for node families + layers - "Family" feature for node families + layers
- Initial coconut functionality including credentials and distributed key generation - Initial coconut functionality including credentials and distributed key generation
## [v1.1.1](https://github.com/nymtech/nym/tree/v1.1.1) (2022-11-29) ## [v1.1.1](https://github.com/nymtech/nym/tree/v1.1.1) (2022-11-29)
@@ -89,7 +195,6 @@ The release also include some additional work for distributed key generation in
[#1786]: https://github.com/nymtech/nym/pull/1786 [#1786]: https://github.com/nymtech/nym/pull/1786
[#1805]: https://github.com/nymtech/nym/pull/1805 [#1805]: https://github.com/nymtech/nym/pull/1805
## [v1.1.0](https://github.com/nymtech/nym/tree/v1.1.0) (2022-11-09) ## [v1.1.0](https://github.com/nymtech/nym/tree/v1.1.0) (2022-11-09)
### Added ### Added
@@ -101,7 +206,7 @@ The release also include some additional work for distributed key generation in
- native-client/socks5-client/wasm-client: `use_extended_packet_size` Debug config option to make the client use 'ExtendedPacketSize' for its traffic (32kB as opposed to 2kB in 1.0.2) ([#1671]) - native-client/socks5-client/wasm-client: `use_extended_packet_size` Debug config option to make the client use 'ExtendedPacketSize' for its traffic (32kB as opposed to 2kB in 1.0.2) ([#1671])
- network-requester: added additional Blockstream Green wallet endpoint to `example.allowed.list` ([#1611]) - network-requester: added additional Blockstream Green wallet endpoint to `example.allowed.list` ([#1611])
- validator-api: add `interval_operating_cost` and `profit_margin_percent` to compute reward estimation endpoint - validator-api: add `interval_operating_cost` and `profit_margin_percent` to compute reward estimation endpoint
- validator-client: added `query_contract_smart` and `query_contract_raw` on `NymdClient` ([#1558]) - validator-client: added `query_contract_smart` and `query_contract_raw` on `NyxdClient` ([#1558])
- wasm-client: uses updated wasm-compatible `client-core` so that it's now capable of packet retransmission, cover traffic and poisson delay (among other things!) ([#1673]) - wasm-client: uses updated wasm-compatible `client-core` so that it's now capable of packet retransmission, cover traffic and poisson delay (among other things!) ([#1673])
### Fixed ### Fixed
@@ -116,7 +221,7 @@ The release also include some additional work for distributed key generation in
- gateway-client: will attempt to read now as many as 8 websocket messages at once, assuming they're already available on the socket ([#1669]) - gateway-client: will attempt to read now as many as 8 websocket messages at once, assuming they're already available on the socket ([#1669])
- moved `Percent` struct to `contracts-common`, change affects explorer-api - moved `Percent` struct to `contracts-common`, change affects explorer-api
- socks5 client: graceful shutdown should fix error on disconnect in nym-connect ([#1591]) - socks5 client: graceful shutdown should fix error on disconnect in nym-connect ([#1591])
- validator-api: changed error serialization on `inclusion_probability`, `stake-saturation` and `reward-estimation` endpoints to provide more accurate information ([#1681]) - validator-api: changed error serialization on `inclusion_probability`, `stake-saturation` and `reward-estimation` endpoints to provide more accurate information ([#1681])
- validator-client: made `fee` argument optional for `execute` and `execute_multiple` ([#1541]) - validator-client: made `fee` argument optional for `execute` and `execute_multiple` ([#1541])
- wasm-client: fixed build errors on MacOS and changed example JS code to use mainnet ([#1585]) - wasm-client: fixed build errors on MacOS and changed example JS code to use mainnet ([#1585])
- validator-api: changes to internal SQL schema due to the mixnet contract revamp ([#1472]) - validator-api: changes to internal SQL schema due to the mixnet contract revamp ([#1472])
@@ -144,7 +249,6 @@ The release also include some additional work for distributed key generation in
[#1724]: https://github.com/nymtech/nym/pull/1724 [#1724]: https://github.com/nymtech/nym/pull/1724
[#1725]: https://github.com/nymtech/nym/pull/1725 [#1725]: https://github.com/nymtech/nym/pull/1725
## [nym-binaries-1.0.2](https://github.com/nymtech/nym/tree/nym-binaries-1.0.2) ## [nym-binaries-1.0.2](https://github.com/nymtech/nym/tree/nym-binaries-1.0.2)
### Added ### Added
@@ -197,9 +301,8 @@ The release also include some additional work for distributed key generation in
- All binaries and cosmwasm blobs are configured at runtime now; binaries are configured using environment variables or .env files and contracts keep the configuration parameters in storage ([#1463]) - All binaries and cosmwasm blobs are configured at runtime now; binaries are configured using environment variables or .env files and contracts keep the configuration parameters in storage ([#1463])
- gateway, network-statistics: include gateway id in the sent statistical data ([#1478]) - gateway, network-statistics: include gateway id in the sent statistical data ([#1478])
- network explorer: tweak how active set probability is shown ([#1503]) - network explorer: tweak how active set probability is shown ([#1503])
- validator-api: rewarder set update fails without panicking on possible nymd queries ([#1520]) - validator-api: rewarder set update fails without panicking on possible nyxd queries ([#1520])
- network-requester, socks5 client (nym-connect): send and receive respectively a message error to be displayed about filter check failure ([#1576]) - network-requester, socks5 client (nym-connect): send and receive respectively a message error to be displayed about filter check failure ([#1576])
[#1249]: https://github.com/nymtech/nym/pull/1249 [#1249]: https://github.com/nymtech/nym/pull/1249
[#1256]: https://github.com/nymtech/nym/pull/1256 [#1256]: https://github.com/nymtech/nym/pull/1256
@@ -293,9 +396,9 @@ The release also include some additional work for distributed key generation in
- Bump minimist from 1.2.5 to 1.2.6 in /clients/tauri-client [\#1163](https://github.com/nymtech/nym/pull/1163) ([dependabot[bot]](https://github.com/apps/dependabot)) - Bump minimist from 1.2.5 to 1.2.6 in /clients/tauri-client [\#1163](https://github.com/nymtech/nym/pull/1163) ([dependabot[bot]](https://github.com/apps/dependabot))
- Bump minimist from 1.2.5 to 1.2.6 in /clients/webassembly/js-example [\#1162](https://github.com/nymtech/nym/pull/1162) ([dependabot[bot]](https://github.com/apps/dependabot)) - Bump minimist from 1.2.5 to 1.2.6 in /clients/webassembly/js-example [\#1162](https://github.com/nymtech/nym/pull/1162) ([dependabot[bot]](https://github.com/apps/dependabot))
- Bump minimist from 1.2.5 to 1.2.6 in /clients/native/examples/js-examples/websocket [\#1160](https://github.com/nymtech/nym/pull/1160) ([dependabot[bot]](https://github.com/apps/dependabot)) - Bump minimist from 1.2.5 to 1.2.6 in /clients/native/examples/js-examples/websocket [\#1160](https://github.com/nymtech/nym/pull/1160) ([dependabot[bot]](https://github.com/apps/dependabot))
- Bump minimist from 1.2.5 to 1.2.6 in /docker/typescript\_client/upload\_contract [\#1159](https://github.com/nymtech/nym/pull/1159) ([dependabot[bot]](https://github.com/apps/dependabot)) - Bump minimist from 1.2.5 to 1.2.6 in /docker/typescript_client/upload_contract [\#1159](https://github.com/nymtech/nym/pull/1159) ([dependabot[bot]](https://github.com/apps/dependabot))
- Feature/vesting full [\#1158](https://github.com/nymtech/nym/pull/1158) ([fmtabbara](https://github.com/fmtabbara)) - Feature/vesting full [\#1158](https://github.com/nymtech/nym/pull/1158) ([fmtabbara](https://github.com/fmtabbara))
- get\_current\_epoch tauri [\#1156](https://github.com/nymtech/nym/pull/1156) ([durch](https://github.com/durch)) - get_current_epoch tauri [\#1156](https://github.com/nymtech/nym/pull/1156) ([durch](https://github.com/durch))
- Cleanup [\#1155](https://github.com/nymtech/nym/pull/1155) ([durch](https://github.com/durch)) - Cleanup [\#1155](https://github.com/nymtech/nym/pull/1155) ([durch](https://github.com/durch))
- Feature flag reward payments [\#1154](https://github.com/nymtech/nym/pull/1154) ([durch](https://github.com/durch)) - Feature flag reward payments [\#1154](https://github.com/nymtech/nym/pull/1154) ([durch](https://github.com/durch))
- Add Query endpoints for calculating rewards [\#1152](https://github.com/nymtech/nym/pull/1152) ([durch](https://github.com/durch)) - Add Query endpoints for calculating rewards [\#1152](https://github.com/nymtech/nym/pull/1152) ([durch](https://github.com/durch))
@@ -304,7 +407,7 @@ The release also include some additional work for distributed key generation in
- wallet: use Urls rather than Strings for validator urls [\#1148](https://github.com/nymtech/nym/pull/1148) ([octol](https://github.com/octol)) - wallet: use Urls rather than Strings for validator urls [\#1148](https://github.com/nymtech/nym/pull/1148) ([octol](https://github.com/octol))
- Change accumulated reward to Option, migrate delegations [\#1147](https://github.com/nymtech/nym/pull/1147) ([durch](https://github.com/durch)) - Change accumulated reward to Option, migrate delegations [\#1147](https://github.com/nymtech/nym/pull/1147) ([durch](https://github.com/durch))
- wallet: fetch validators url remotely if available [\#1146](https://github.com/nymtech/nym/pull/1146) ([octol](https://github.com/octol)) - wallet: fetch validators url remotely if available [\#1146](https://github.com/nymtech/nym/pull/1146) ([octol](https://github.com/octol))
- Fix delegated\_free calculation [\#1145](https://github.com/nymtech/nym/pull/1145) ([durch](https://github.com/durch)) - Fix delegated_free calculation [\#1145](https://github.com/nymtech/nym/pull/1145) ([durch](https://github.com/durch))
- Update Nym wallet dependencies to use `ts-packages` [\#1144](https://github.com/nymtech/nym/pull/1144) ([mmsinclair](https://github.com/mmsinclair)) - Update Nym wallet dependencies to use `ts-packages` [\#1144](https://github.com/nymtech/nym/pull/1144) ([mmsinclair](https://github.com/mmsinclair))
- wallet: try validators one by one if available [\#1143](https://github.com/nymtech/nym/pull/1143) ([octol](https://github.com/octol)) - wallet: try validators one by one if available [\#1143](https://github.com/nymtech/nym/pull/1143) ([octol](https://github.com/octol))
- Update Network Explorer Packages and add mix node identity key copy [\#1142](https://github.com/nymtech/nym/pull/1142) ([mmsinclair](https://github.com/mmsinclair)) - Update Network Explorer Packages and add mix node identity key copy [\#1142](https://github.com/nymtech/nym/pull/1142) ([mmsinclair](https://github.com/mmsinclair))
@@ -344,14 +447,13 @@ The release also include some additional work for distributed key generation in
- feature/pedersen-commitments [\#1048](https://github.com/nymtech/nym/pull/1048) ([danielementary](https://github.com/danielementary)) - feature/pedersen-commitments [\#1048](https://github.com/nymtech/nym/pull/1048) ([danielementary](https://github.com/danielementary))
- Feature/reuse init owner [\#970](https://github.com/nymtech/nym/pull/970) ([neacsu](https://github.com/neacsu)) - Feature/reuse init owner [\#970](https://github.com/nymtech/nym/pull/970) ([neacsu](https://github.com/neacsu))
## [v0.12.1](https://github.com/nymtech/nym/tree/v0.12.1) (2021-12-23) ## [v0.12.1](https://github.com/nymtech/nym/tree/v0.12.1) (2021-12-23)
[Full Changelog](https://github.com/nymtech/nym/compare/v0.12.0...v0.12.1) [Full Changelog](https://github.com/nymtech/nym/compare/v0.12.0...v0.12.1)
**Implemented enhancements:** **Implemented enhancements:**
- Add version check to binaries [\#967](https://github.com/nymtech/nym/issues/967) - Add version check to binaries [\#967](https://github.com/nymtech/nym/issues/967)
**Fixed bugs:** **Fixed bugs:**
@@ -381,7 +483,7 @@ The release also include some additional work for distributed key generation in
- Bugfix/remove mixnode bonding overwrite [\#917](https://github.com/nymtech/nym/pull/917) ([jstuczyn](https://github.com/jstuczyn)) - Bugfix/remove mixnode bonding overwrite [\#917](https://github.com/nymtech/nym/pull/917) ([jstuczyn](https://github.com/jstuczyn))
- Fixes crash condition in validator API when calculating last day uptime [\#909](https://github.com/nymtech/nym/pull/909) ([jstuczyn](https://github.com/jstuczyn)) - Fixes crash condition in validator API when calculating last day uptime [\#909](https://github.com/nymtech/nym/pull/909) ([jstuczyn](https://github.com/jstuczyn))
- Bugfix/monitor initial values wait [\#907](https://github.com/nymtech/nym/pull/907) ([jstuczyn](https://github.com/jstuczyn)) - Bugfix/monitor initial values wait [\#907](https://github.com/nymtech/nym/pull/907) ([jstuczyn](https://github.com/jstuczyn))
- Bug fix: Network Explorer: Add freegeoip API key and split out tasks for country distributions [\#806](https://github.com/nymtech/nym/pull/806) ([mmsinclair](https://github.com/mmsinclair)) - Bug fix: Network Explorer: Add freegeoip API key and split out tasks for country distributions [\#806](https://github.com/nymtech/nym/pull/806) ([mmsinclair](https://github.com/mmsinclair))
- Explorer API: port test now split out address resolution and add units tests [\#755](https://github.com/nymtech/nym/pull/755) ([mmsinclair](https://github.com/mmsinclair)) - Explorer API: port test now split out address resolution and add units tests [\#755](https://github.com/nymtech/nym/pull/755) ([mmsinclair](https://github.com/mmsinclair))
**Closed issues:** **Closed issues:**
@@ -396,7 +498,7 @@ The release also include some additional work for distributed key generation in
- help!!! [\#712](https://github.com/nymtech/nym/issues/712) - help!!! [\#712](https://github.com/nymtech/nym/issues/712)
- UX feature request: show all delegated nodes in wallet [\#711](https://github.com/nymtech/nym/issues/711) - UX feature request: show all delegated nodes in wallet [\#711](https://github.com/nymtech/nym/issues/711)
- UX feature request: add current balance on wallet pages [\#710](https://github.com/nymtech/nym/issues/710) - UX feature request: add current balance on wallet pages [\#710](https://github.com/nymtech/nym/issues/710)
- got sign issue from bot [\#709](https://github.com/nymtech/nym/issues/709) - got sign issue from bot [\#709](https://github.com/nymtech/nym/issues/709)
- As a wallet user, I would like to be able to log out of the wallet [\#706](https://github.com/nymtech/nym/issues/706) - As a wallet user, I would like to be able to log out of the wallet [\#706](https://github.com/nymtech/nym/issues/706)
- As a wallet user, I would like to have a "receive" page where I can see my own wallet address [\#705](https://github.com/nymtech/nym/issues/705) - As a wallet user, I would like to have a "receive" page where I can see my own wallet address [\#705](https://github.com/nymtech/nym/issues/705)
- Update native client/socks client/mixnode/gateway `upgrade` command [\#689](https://github.com/nymtech/nym/issues/689) - Update native client/socks client/mixnode/gateway `upgrade` command [\#689](https://github.com/nymtech/nym/issues/689)
@@ -406,7 +508,7 @@ The release also include some additional work for distributed key generation in
- nym-socks5-client crash after opening Keybase team "Browse all channels" [\#494](https://github.com/nymtech/nym/issues/494) - nym-socks5-client crash after opening Keybase team "Browse all channels" [\#494](https://github.com/nymtech/nym/issues/494)
- Mixed Content problem [\#400](https://github.com/nymtech/nym/issues/400) - Mixed Content problem [\#400](https://github.com/nymtech/nym/issues/400)
- Gateway disk quota [\#137](https://github.com/nymtech/nym/issues/137) - Gateway disk quota [\#137](https://github.com/nymtech/nym/issues/137)
- Simplify message encapsulation with regards to topology [\#127](https://github.com/nymtech/nym/issues/127) - Simplify message encapsulation with regards to topology [\#127](https://github.com/nymtech/nym/issues/127)
- Create constants for cli argument names [\#115](https://github.com/nymtech/nym/issues/115) - Create constants for cli argument names [\#115](https://github.com/nymtech/nym/issues/115)
- Using Blake3 as a hash function [\#103](https://github.com/nymtech/nym/issues/103) - Using Blake3 as a hash function [\#103](https://github.com/nymtech/nym/issues/103)
- Validator should decide which layer a node is in [\#86](https://github.com/nymtech/nym/issues/86) - Validator should decide which layer a node is in [\#86](https://github.com/nymtech/nym/issues/86)
@@ -462,10 +564,10 @@ The release also include some additional work for distributed key generation in
- Feature/pre cosmrs updates [\#935](https://github.com/nymtech/nym/pull/935) ([jstuczyn](https://github.com/jstuczyn)) - Feature/pre cosmrs updates [\#935](https://github.com/nymtech/nym/pull/935) ([jstuczyn](https://github.com/jstuczyn))
- Feature/client on behalf [\#934](https://github.com/nymtech/nym/pull/934) ([neacsu](https://github.com/neacsu)) - Feature/client on behalf [\#934](https://github.com/nymtech/nym/pull/934) ([neacsu](https://github.com/neacsu))
- Webpack wallet prod configuration [\#933](https://github.com/nymtech/nym/pull/933) ([tommyv1987](https://github.com/tommyv1987)) - Webpack wallet prod configuration [\#933](https://github.com/nymtech/nym/pull/933) ([tommyv1987](https://github.com/tommyv1987))
- Adding tx\_hash to wallet response [\#932](https://github.com/nymtech/nym/pull/932) ([futurechimp](https://github.com/futurechimp)) - Adding tx_hash to wallet response [\#932](https://github.com/nymtech/nym/pull/932) ([futurechimp](https://github.com/futurechimp))
- Release/1.0.0 pre1 [\#931](https://github.com/nymtech/nym/pull/931) ([durch](https://github.com/durch)) - Release/1.0.0 pre1 [\#931](https://github.com/nymtech/nym/pull/931) ([durch](https://github.com/durch))
- Feature/identity verification [\#930](https://github.com/nymtech/nym/pull/930) ([jstuczyn](https://github.com/jstuczyn)) - Feature/identity verification [\#930](https://github.com/nymtech/nym/pull/930) ([jstuczyn](https://github.com/jstuczyn))
- Move cleaned up smart contracts to main code repo [\#929](https://github.com/nymtech/nym/pull/929) ([mfahampshire](https://github.com/mfahampshire)) - Move cleaned up smart contracts to main code repo [\#929](https://github.com/nymtech/nym/pull/929) ([mfahampshire](https://github.com/mfahampshire))
- Feature/mixnet contract further adjustments [\#928](https://github.com/nymtech/nym/pull/928) ([jstuczyn](https://github.com/jstuczyn)) - Feature/mixnet contract further adjustments [\#928](https://github.com/nymtech/nym/pull/928) ([jstuczyn](https://github.com/jstuczyn))
- typo copy change for nodemap [\#926](https://github.com/nymtech/nym/pull/926) ([Aid19801](https://github.com/Aid19801)) - typo copy change for nodemap [\#926](https://github.com/nymtech/nym/pull/926) ([Aid19801](https://github.com/Aid19801))
- Feature/UI enhancements for Desktop Wallet [\#925](https://github.com/nymtech/nym/pull/925) ([fmtabbara](https://github.com/fmtabbara)) - Feature/UI enhancements for Desktop Wallet [\#925](https://github.com/nymtech/nym/pull/925) ([fmtabbara](https://github.com/fmtabbara))
@@ -478,7 +580,7 @@ The release also include some additional work for distributed key generation in
- Feature/faucet page react [\#911](https://github.com/nymtech/nym/pull/911) ([fmtabbara](https://github.com/fmtabbara)) - Feature/faucet page react [\#911](https://github.com/nymtech/nym/pull/911) ([fmtabbara](https://github.com/fmtabbara))
- Feature/mixnet contract refactor [\#910](https://github.com/nymtech/nym/pull/910) ([futurechimp](https://github.com/futurechimp)) - Feature/mixnet contract refactor [\#910](https://github.com/nymtech/nym/pull/910) ([futurechimp](https://github.com/futurechimp))
- Update README.md [\#905](https://github.com/nymtech/nym/pull/905) ([tommyv1987](https://github.com/tommyv1987)) - Update README.md [\#905](https://github.com/nymtech/nym/pull/905) ([tommyv1987](https://github.com/tommyv1987))
- BUG: Bond cell denom [\#904](https://github.com/nymtech/nym/pull/904) ([Aid19801](https://github.com/Aid19801)) - BUG: Bond cell denom [\#904](https://github.com/nymtech/nym/pull/904) ([Aid19801](https://github.com/Aid19801))
- Explorer UI tests missing data-testid [\#903](https://github.com/nymtech/nym/pull/903) ([tommyv1987](https://github.com/tommyv1987)) - Explorer UI tests missing data-testid [\#903](https://github.com/nymtech/nym/pull/903) ([tommyv1987](https://github.com/tommyv1987))
- Fix up Nym-Wallet README.md [\#899](https://github.com/nymtech/nym/pull/899) ([tommyv1987](https://github.com/tommyv1987)) - Fix up Nym-Wallet README.md [\#899](https://github.com/nymtech/nym/pull/899) ([tommyv1987](https://github.com/tommyv1987))
- Feature/batch delegator rewarding [\#898](https://github.com/nymtech/nym/pull/898) ([jstuczyn](https://github.com/jstuczyn)) - Feature/batch delegator rewarding [\#898](https://github.com/nymtech/nym/pull/898) ([jstuczyn](https://github.com/jstuczyn))
@@ -496,7 +598,7 @@ The release also include some additional work for distributed key generation in
- Reverted gateway registration handshake to its 0.11.0 version [\#882](https://github.com/nymtech/nym/pull/882) ([jstuczyn](https://github.com/jstuczyn)) - Reverted gateway registration handshake to its 0.11.0 version [\#882](https://github.com/nymtech/nym/pull/882) ([jstuczyn](https://github.com/jstuczyn))
- Network Explorer [\#881](https://github.com/nymtech/nym/pull/881) ([mmsinclair](https://github.com/mmsinclair)) - Network Explorer [\#881](https://github.com/nymtech/nym/pull/881) ([mmsinclair](https://github.com/mmsinclair))
- Feature/rewarding interval updates [\#880](https://github.com/nymtech/nym/pull/880) ([jstuczyn](https://github.com/jstuczyn)) - Feature/rewarding interval updates [\#880](https://github.com/nymtech/nym/pull/880) ([jstuczyn](https://github.com/jstuczyn))
- Put client\_address and id in the correct order [\#875](https://github.com/nymtech/nym/pull/875) ([neacsu](https://github.com/neacsu)) - Put client_address and id in the correct order [\#875](https://github.com/nymtech/nym/pull/875) ([neacsu](https://github.com/neacsu))
- remove gateway selection on delegation and undelegation pages [\#873](https://github.com/nymtech/nym/pull/873) ([fmtabbara](https://github.com/fmtabbara)) - remove gateway selection on delegation and undelegation pages [\#873](https://github.com/nymtech/nym/pull/873) ([fmtabbara](https://github.com/fmtabbara))
- Set MSRV on all binaries to 1.56 [\#872](https://github.com/nymtech/nym/pull/872) ([jstuczyn](https://github.com/jstuczyn)) - Set MSRV on all binaries to 1.56 [\#872](https://github.com/nymtech/nym/pull/872) ([jstuczyn](https://github.com/jstuczyn))
- add native window items \(copy/paste\) via tauri [\#871](https://github.com/nymtech/nym/pull/871) ([fmtabbara](https://github.com/fmtabbara)) - add native window items \(copy/paste\) via tauri [\#871](https://github.com/nymtech/nym/pull/871) ([fmtabbara](https://github.com/fmtabbara))
@@ -512,7 +614,7 @@ The release also include some additional work for distributed key generation in
- Overflow checks in release [\#846](https://github.com/nymtech/nym/pull/846) ([jstuczyn](https://github.com/jstuczyn)) - Overflow checks in release [\#846](https://github.com/nymtech/nym/pull/846) ([jstuczyn](https://github.com/jstuczyn))
- fix delegate success overflow [\#842](https://github.com/nymtech/nym/pull/842) ([fmtabbara](https://github.com/fmtabbara)) - fix delegate success overflow [\#842](https://github.com/nymtech/nym/pull/842) ([fmtabbara](https://github.com/fmtabbara))
- Feature NYM wallet webdriverio test [\#841](https://github.com/nymtech/nym/pull/841) ([tommyv1987](https://github.com/tommyv1987)) - Feature NYM wallet webdriverio test [\#841](https://github.com/nymtech/nym/pull/841) ([tommyv1987](https://github.com/tommyv1987))
- Update nym\_wallet.yml [\#840](https://github.com/nymtech/nym/pull/840) ([tommyv1987](https://github.com/tommyv1987)) - Update nym_wallet.yml [\#840](https://github.com/nymtech/nym/pull/840) ([tommyv1987](https://github.com/tommyv1987))
- Feature/vouchers [\#837](https://github.com/nymtech/nym/pull/837) ([aniampio](https://github.com/aniampio)) - Feature/vouchers [\#837](https://github.com/nymtech/nym/pull/837) ([aniampio](https://github.com/aniampio))
- Apply readable ids to elements on Nym Wallet [\#836](https://github.com/nymtech/nym/pull/836) ([tommyv1987](https://github.com/tommyv1987)) - Apply readable ids to elements on Nym Wallet [\#836](https://github.com/nymtech/nym/pull/836) ([tommyv1987](https://github.com/tommyv1987))
- Feature/removal of monitor good nodes [\#833](https://github.com/nymtech/nym/pull/833) ([jstuczyn](https://github.com/jstuczyn)) - Feature/removal of monitor good nodes [\#833](https://github.com/nymtech/nym/pull/833) ([jstuczyn](https://github.com/jstuczyn))
@@ -536,8 +638,8 @@ The release also include some additional work for distributed key generation in
- Created getters for AccountData [\#787](https://github.com/nymtech/nym/pull/787) ([jstuczyn](https://github.com/jstuczyn)) - Created getters for AccountData [\#787](https://github.com/nymtech/nym/pull/787) ([jstuczyn](https://github.com/jstuczyn))
- Feature/migrate hidden delegations [\#786](https://github.com/nymtech/nym/pull/786) ([neacsu](https://github.com/neacsu)) - Feature/migrate hidden delegations [\#786](https://github.com/nymtech/nym/pull/786) ([neacsu](https://github.com/neacsu))
- Feature/persistent gateway storage [\#784](https://github.com/nymtech/nym/pull/784) ([jstuczyn](https://github.com/jstuczyn)) - Feature/persistent gateway storage [\#784](https://github.com/nymtech/nym/pull/784) ([jstuczyn](https://github.com/jstuczyn))
- Replaced unwrap\_or\_else with unwrap\_or\_default [\#780](https://github.com/nymtech/nym/pull/780) ([jstuczyn](https://github.com/jstuczyn)) - Replaced unwrap_or_else with unwrap_or_default [\#780](https://github.com/nymtech/nym/pull/780) ([jstuczyn](https://github.com/jstuczyn))
- Add block\_height method to Delegation [\#778](https://github.com/nymtech/nym/pull/778) ([durch](https://github.com/durch)) - Add block_height method to Delegation [\#778](https://github.com/nymtech/nym/pull/778) ([durch](https://github.com/durch))
- Make fee helpers public [\#777](https://github.com/nymtech/nym/pull/777) ([durch](https://github.com/durch)) - Make fee helpers public [\#777](https://github.com/nymtech/nym/pull/777) ([durch](https://github.com/durch))
- re-enable bonding [\#776](https://github.com/nymtech/nym/pull/776) ([fmtabbara](https://github.com/fmtabbara)) - re-enable bonding [\#776](https://github.com/nymtech/nym/pull/776) ([fmtabbara](https://github.com/fmtabbara))
- Explorer-api: add API resource to show the delegations for each mix node [\#774](https://github.com/nymtech/nym/pull/774) ([mmsinclair](https://github.com/mmsinclair)) - Explorer-api: add API resource to show the delegations for each mix node [\#774](https://github.com/nymtech/nym/pull/774) ([mmsinclair](https://github.com/mmsinclair))
@@ -546,14 +648,14 @@ The release also include some additional work for distributed key generation in
- Adding deps for building the Tauri wallet under Ubuntu [\#770](https://github.com/nymtech/nym/pull/770) ([futurechimp](https://github.com/futurechimp)) - Adding deps for building the Tauri wallet under Ubuntu [\#770](https://github.com/nymtech/nym/pull/770) ([futurechimp](https://github.com/futurechimp))
- remove alert [\#767](https://github.com/nymtech/nym/pull/767) ([fmtabbara](https://github.com/fmtabbara)) - remove alert [\#767](https://github.com/nymtech/nym/pull/767) ([fmtabbara](https://github.com/fmtabbara))
- Feature/consumable bandwidth [\#766](https://github.com/nymtech/nym/pull/766) ([neacsu](https://github.com/neacsu)) - Feature/consumable bandwidth [\#766](https://github.com/nymtech/nym/pull/766) ([neacsu](https://github.com/neacsu))
- Update coconut-rs and use hash\_to\_scalar from there [\#765](https://github.com/nymtech/nym/pull/765) ([neacsu](https://github.com/neacsu)) - Update coconut-rs and use hash_to_scalar from there [\#765](https://github.com/nymtech/nym/pull/765) ([neacsu](https://github.com/neacsu))
- Feature/active sets [\#764](https://github.com/nymtech/nym/pull/764) ([jstuczyn](https://github.com/jstuczyn)) - Feature/active sets [\#764](https://github.com/nymtech/nym/pull/764) ([jstuczyn](https://github.com/jstuczyn))
- add app alert banner [\#762](https://github.com/nymtech/nym/pull/762) ([fmtabbara](https://github.com/fmtabbara)) - add app alert banner [\#762](https://github.com/nymtech/nym/pull/762) ([fmtabbara](https://github.com/fmtabbara))
- Updated cosmos-sdk [\#761](https://github.com/nymtech/nym/pull/761) ([jstuczyn](https://github.com/jstuczyn)) - Updated cosmos-sdk [\#761](https://github.com/nymtech/nym/pull/761) ([jstuczyn](https://github.com/jstuczyn))
- Feature/bond blockstamp [\#760](https://github.com/nymtech/nym/pull/760) ([neacsu](https://github.com/neacsu)) - Feature/bond blockstamp [\#760](https://github.com/nymtech/nym/pull/760) ([neacsu](https://github.com/neacsu))
- Feature/revert migration code [\#759](https://github.com/nymtech/nym/pull/759) ([neacsu](https://github.com/neacsu)) - Feature/revert migration code [\#759](https://github.com/nymtech/nym/pull/759) ([neacsu](https://github.com/neacsu))
- Bump next from 11.1.0 to 11.1.1 in /wallet-web [\#758](https://github.com/nymtech/nym/pull/758) ([dependabot[bot]](https://github.com/apps/dependabot)) - Bump next from 11.1.0 to 11.1.1 in /wallet-web [\#758](https://github.com/nymtech/nym/pull/758) ([dependabot[bot]](https://github.com/apps/dependabot))
- Add block\_height in the Delegation structure as well [\#757](https://github.com/nymtech/nym/pull/757) ([neacsu](https://github.com/neacsu)) - Add block_height in the Delegation structure as well [\#757](https://github.com/nymtech/nym/pull/757) ([neacsu](https://github.com/neacsu))
- Feature/add blockstamp [\#756](https://github.com/nymtech/nym/pull/756) ([neacsu](https://github.com/neacsu)) - Feature/add blockstamp [\#756](https://github.com/nymtech/nym/pull/756) ([neacsu](https://github.com/neacsu))
- NetworkMonitorBuilder - starting the monitor after rocket has launched [\#754](https://github.com/nymtech/nym/pull/754) ([jstuczyn](https://github.com/jstuczyn)) - NetworkMonitorBuilder - starting the monitor after rocket has launched [\#754](https://github.com/nymtech/nym/pull/754) ([jstuczyn](https://github.com/jstuczyn))
- Enabled validators api argument [\#753](https://github.com/nymtech/nym/pull/753) ([jstuczyn](https://github.com/jstuczyn)) - Enabled validators api argument [\#753](https://github.com/nymtech/nym/pull/753) ([jstuczyn](https://github.com/jstuczyn))
@@ -565,21 +667,21 @@ The release also include some additional work for distributed key generation in
- Feature/more reliable uptime calculation [\#747](https://github.com/nymtech/nym/pull/747) ([jstuczyn](https://github.com/jstuczyn)) - Feature/more reliable uptime calculation [\#747](https://github.com/nymtech/nym/pull/747) ([jstuczyn](https://github.com/jstuczyn))
- Update template toml key [\#746](https://github.com/nymtech/nym/pull/746) ([neacsu](https://github.com/neacsu)) - Update template toml key [\#746](https://github.com/nymtech/nym/pull/746) ([neacsu](https://github.com/neacsu))
- Feature/cred after handshake [\#745](https://github.com/nymtech/nym/pull/745) ([neacsu](https://github.com/neacsu)) - Feature/cred after handshake [\#745](https://github.com/nymtech/nym/pull/745) ([neacsu](https://github.com/neacsu))
- Reinstate the POST method blind\_sign [\#744](https://github.com/nymtech/nym/pull/744) ([neacsu](https://github.com/neacsu)) - Reinstate the POST method blind_sign [\#744](https://github.com/nymtech/nym/pull/744) ([neacsu](https://github.com/neacsu))
- explorer-api: add pending field to port check response [\#742](https://github.com/nymtech/nym/pull/742) ([mmsinclair](https://github.com/mmsinclair)) - explorer-api: add pending field to port check response [\#742](https://github.com/nymtech/nym/pull/742) ([mmsinclair](https://github.com/mmsinclair))
- Feature/use delegation rates [\#741](https://github.com/nymtech/nym/pull/741) ([neacsu](https://github.com/neacsu)) - Feature/use delegation rates [\#741](https://github.com/nymtech/nym/pull/741) ([neacsu](https://github.com/neacsu))
- Feature/copy to clipboard [\#740](https://github.com/nymtech/nym/pull/740) ([fmtabbara](https://github.com/fmtabbara)) - Feature/copy to clipboard [\#740](https://github.com/nymtech/nym/pull/740) ([fmtabbara](https://github.com/fmtabbara))
- Feature/update wallet with stake rates [\#739](https://github.com/nymtech/nym/pull/739) ([neacsu](https://github.com/neacsu)) - Feature/update wallet with stake rates [\#739](https://github.com/nymtech/nym/pull/739) ([neacsu](https://github.com/neacsu))
- Add stake reward rates and bump version of client [\#738](https://github.com/nymtech/nym/pull/738) ([neacsu](https://github.com/neacsu)) - Add stake reward rates and bump version of client [\#738](https://github.com/nymtech/nym/pull/738) ([neacsu](https://github.com/neacsu))
- Bump next from 10.1.3 to 11.1.0 in /wallet-web [\#737](https://github.com/nymtech/nym/pull/737) ([dependabot[bot]](https://github.com/apps/dependabot)) - Bump next from 10.1.3 to 11.1.0 in /wallet-web [\#737](https://github.com/nymtech/nym/pull/737) ([dependabot[bot]](https://github.com/apps/dependabot))
- Feature/nymd client integration [\#736](https://github.com/nymtech/nym/pull/736) ([jstuczyn](https://github.com/jstuczyn)) - Feature/nyxd client integration [\#736](https://github.com/nymtech/nym/pull/736) ([jstuczyn](https://github.com/jstuczyn))
- Bug/fix parking lot on wasm [\#735](https://github.com/nymtech/nym/pull/735) ([neacsu](https://github.com/neacsu)) - Bug/fix parking lot on wasm [\#735](https://github.com/nymtech/nym/pull/735) ([neacsu](https://github.com/neacsu))
- Explorer API: add new HTTP resource to decorate mix nodes with geoip locations [\#734](https://github.com/nymtech/nym/pull/734) ([mmsinclair](https://github.com/mmsinclair)) - Explorer API: add new HTTP resource to decorate mix nodes with geoip locations [\#734](https://github.com/nymtech/nym/pull/734) ([mmsinclair](https://github.com/mmsinclair))
- Feature/completing nymd client api [\#732](https://github.com/nymtech/nym/pull/732) ([jstuczyn](https://github.com/jstuczyn)) - Feature/completing nyxd client api [\#732](https://github.com/nymtech/nym/pull/732) ([jstuczyn](https://github.com/jstuczyn))
- Explorer API - add port check and node description/stats proxy [\#731](https://github.com/nymtech/nym/pull/731) ([mmsinclair](https://github.com/mmsinclair)) - Explorer API - add port check and node description/stats proxy [\#731](https://github.com/nymtech/nym/pull/731) ([mmsinclair](https://github.com/mmsinclair))
- Feature/nymd client fee handling [\#730](https://github.com/nymtech/nym/pull/730) ([jstuczyn](https://github.com/jstuczyn)) - Feature/nyxd client fee handling [\#730](https://github.com/nymtech/nym/pull/730) ([jstuczyn](https://github.com/jstuczyn))
- Update DelegationCheck.tsx [\#725](https://github.com/nymtech/nym/pull/725) ([jessgess](https://github.com/jessgess)) - Update DelegationCheck.tsx [\#725](https://github.com/nymtech/nym/pull/725) ([jessgess](https://github.com/jessgess))
- Rust nymd/cosmwasm client [\#724](https://github.com/nymtech/nym/pull/724) ([jstuczyn](https://github.com/jstuczyn)) - Rust nyxd/cosmwasm client [\#724](https://github.com/nymtech/nym/pull/724) ([jstuczyn](https://github.com/jstuczyn))
- Removed wasm feature bypassing cyclic dependencies [\#723](https://github.com/nymtech/nym/pull/723) ([jstuczyn](https://github.com/jstuczyn)) - Removed wasm feature bypassing cyclic dependencies [\#723](https://github.com/nymtech/nym/pull/723) ([jstuczyn](https://github.com/jstuczyn))
- Updated used sphinx dependency to the most recent revision [\#722](https://github.com/nymtech/nym/pull/722) ([jstuczyn](https://github.com/jstuczyn)) - Updated used sphinx dependency to the most recent revision [\#722](https://github.com/nymtech/nym/pull/722) ([jstuczyn](https://github.com/jstuczyn))
- update state management and validation [\#721](https://github.com/nymtech/nym/pull/721) ([fmtabbara](https://github.com/fmtabbara)) - update state management and validation [\#721](https://github.com/nymtech/nym/pull/721) ([fmtabbara](https://github.com/fmtabbara))
@@ -598,10 +700,8 @@ The release also include some additional work for distributed key generation in
- Bond and delegation alerts [\#698](https://github.com/nymtech/nym/pull/698) ([fmtabbara](https://github.com/fmtabbara)) - Bond and delegation alerts [\#698](https://github.com/nymtech/nym/pull/698) ([fmtabbara](https://github.com/fmtabbara))
- Bugfix/network monitor version check [\#697](https://github.com/nymtech/nym/pull/697) ([jstuczyn](https://github.com/jstuczyn)) - Bugfix/network monitor version check [\#697](https://github.com/nymtech/nym/pull/697) ([jstuczyn](https://github.com/jstuczyn))
- Feature/other containers [\#692](https://github.com/nymtech/nym/pull/692) ([neacsu](https://github.com/neacsu)) - Feature/other containers [\#692](https://github.com/nymtech/nym/pull/692) ([neacsu](https://github.com/neacsu))
- Using validator API instead of nymd [\#690](https://github.com/nymtech/nym/pull/690) ([futurechimp](https://github.com/futurechimp)) - Using validator API instead of nyxd [\#690](https://github.com/nymtech/nym/pull/690) ([futurechimp](https://github.com/futurechimp))
- Hang coconut issuance off the validator-api [\#679](https://github.com/nymtech/nym/pull/679) ([durch](https://github.com/durch)) - Hang coconut issuance off the validator-api [\#679](https://github.com/nymtech/nym/pull/679) ([durch](https://github.com/durch))
- Update hmac and blake3 [\#673](https://github.com/nymtech/nym/pull/673) ([durch](https://github.com/durch)) - Update hmac and blake3 [\#673](https://github.com/nymtech/nym/pull/673) ([durch](https://github.com/durch))
\* _This Changelog was automatically generated by [github_changelog_generator](https://github.com/github-changelog-generator/github-changelog-generator)_
\* *This Changelog was automatically generated by [github_changelog_generator](https://github.com/github-changelog-generator/github-changelog-generator)*
Generated
+1388 -928
View File
File diff suppressed because it is too large Load Diff
+24 -4
View File
@@ -30,12 +30,15 @@ members = [
"common/coconut-interface", "common/coconut-interface",
"common/commands", "common/commands",
"common/config", "common/config",
"common/build-information",
"common/cosmwasm-smart-contracts/coconut-bandwidth-contract", "common/cosmwasm-smart-contracts/coconut-bandwidth-contract",
"common/cosmwasm-smart-contracts/coconut-dkg", "common/cosmwasm-smart-contracts/coconut-dkg",
"common/cosmwasm-smart-contracts/contracts-common", "common/cosmwasm-smart-contracts/contracts-common",
"common/cosmwasm-smart-contracts/group-contract",
"common/cosmwasm-smart-contracts/mixnet-contract", "common/cosmwasm-smart-contracts/mixnet-contract",
"common/cosmwasm-smart-contracts/multisig-contract", "common/cosmwasm-smart-contracts/multisig-contract",
"common/cosmwasm-smart-contracts/vesting-contract", "common/cosmwasm-smart-contracts/vesting-contract",
"common/mobile-storage",
"common/credential-storage", "common/credential-storage",
"common/credentials", "common/credentials",
"common/crypto", "common/crypto",
@@ -72,10 +75,13 @@ members = [
"gateway/gateway-requests", "gateway/gateway-requests",
"integrations/bity", "integrations/bity",
"mixnode", "mixnode",
"sdk/rust/nym-sdk",
"service-providers/common",
"service-providers/network-requester", "service-providers/network-requester",
"service-providers/network-statistics", "service-providers/network-statistics",
"validator-api", "nym-api",
"validator-api/validator-api-requests", "nym-api/nym-api-requests",
"nym-outfox",
"tools/nym-cli", "tools/nym-cli",
"tools/ts-rs-cli" "tools/ts-rs-cli"
] ]
@@ -87,8 +93,22 @@ default-members = [
"service-providers/network-requester", "service-providers/network-requester",
"service-providers/network-statistics", "service-providers/network-statistics",
"mixnode", "mixnode",
"validator-api", "nym-api",
"explorer-api", "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]
async-trait = "0.1.63"
log = "0.4"
thiserror = "1.0.38"
serde = "1.0.152"
serde_json = "1.0.91"
tokio = "1.24.1"
+7 -20
View File
@@ -2,10 +2,10 @@ test: clippy-all cargo-test wasm fmt
test-all: test cargo-test-expensive test-all: test cargo-test-expensive
no-clippy: build cargo-test wasm fmt no-clippy: build cargo-test wasm fmt
happy: fmt clippy-happy test 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 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: test-main test-contracts test-wallet test-connect
cargo-test-expensive: test-main-expensive test-contracts-expensive test-wallet-expensive test-connect-expensive test-coconut-expensive 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 build: build-contracts build-wallet build-main build-connect build-wasm-client
fmt: fmt-main fmt-contracts fmt-wallet fmt-connect fmt-wasm-client fmt: fmt-main fmt-contracts fmt-wallet fmt-connect fmt-wasm-client
@@ -24,11 +24,8 @@ clippy-happy-connect:
clippy-main: clippy-main:
cargo clippy --workspace -- -D warnings cargo clippy --workspace -- -D warnings
clippy-coconut:
cargo clippy --workspace --features coconut -- -D warnings
clippy-wasm: clippy-wasm:
cargo clippy --workspace --features wasm -- -D warnings cargo clippy --manifest-path clients/webassembly/Cargo.toml --target wasm32-unknown-unknown --workspace -- -D warnings
clippy-all-contracts: clippy-all-contracts:
@@ -46,19 +43,9 @@ clippy-all-wasm-client:
test-main: test-main:
cargo test --workspace cargo test --workspace
test-coconut:
cargo test --workspace --features coconut
test-wasm:
cargo test --workspace --features wasm
test-main-expensive: test-main-expensive:
cargo test --workspace -- --ignored cargo test --workspace -- --ignored
test-coconut-expensive:
cargo test --workspace --features coconut -- --ignored
test-contracts: test-contracts:
cargo test --manifest-path contracts/Cargo.toml --all-features cargo test --manifest-path contracts/Cargo.toml --all-features
@@ -71,9 +58,6 @@ test-wallet:
test-wallet-expensive: test-wallet-expensive:
cargo test --manifest-path nym-wallet/Cargo.toml --all-features -- --ignored 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: test-connect:
cargo test --manifest-path nym-connect/Cargo.toml --all-features cargo test --manifest-path nym-connect/Cargo.toml --all-features
@@ -125,3 +109,6 @@ mixnet-opt: wasm
generate-typescript: generate-typescript:
cd tools/ts-rs-cli && cargo run && cd ../.. cd tools/ts-rs-cli && cargo run && cd ../..
yarn types:lint:fix yarn types:lint:fix
run-validator-tests:
cd nym-api/tests/functional_test && yarn test:qa
+7 -7
View File
@@ -1,8 +1,9 @@
[package] [package]
name = "client-core" name = "client-core"
version = "1.1.4" version = "1.1.8"
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"] authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"]
edition = "2021" edition = "2021"
rust-version = "1.66"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@@ -12,14 +13,14 @@ dirs = "4.0"
dashmap = "5.4.0" dashmap = "5.4.0"
futures = "0.3" futures = "0.3"
humantime-serde = "1.0" humantime-serde = "1.0"
log = "0.4" log = { workspace = true }
rand = { version = "0.7.3", features = ["wasm-bindgen"] } rand = { version = "0.7.3", features = ["wasm-bindgen"] }
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0.89" serde_json = "1.0.89"
tap = "1.0.1" tap = "1.0.1"
thiserror = "1.0.34" thiserror = "1.0.34"
url = { version ="2.2", features = ["serde"] } url = { version ="2.2", features = ["serde"] }
tokio = { version = "1.21.2", features = ["macros"]} tokio = { version = "1.24.1", features = ["macros"]}
time = "0.3.17" time = "0.3.17"
# internal # internal
@@ -37,11 +38,11 @@ validator-client = { path = "../../common/client-libs/validator-client", default
task = { path = "../../common/task" } task = { path = "../../common/task" }
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.tokio-stream] [target."cfg(not(target_arch = \"wasm32\"))".dependencies.tokio-stream]
version = "0.1.9" version = "0.1.11"
features = ["time"] features = ["time"]
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.tokio] [target."cfg(not(target_arch = \"wasm32\"))".dependencies.tokio]
version = "1.21.2" version = "1.24.1"
features = ["time"] features = ["time"]
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.sqlx] [target."cfg(not(target_arch = \"wasm32\"))".dependencies.sqlx]
@@ -74,12 +75,11 @@ features = ["wasm-bindgen"]
tempfile = "3.1.0" tempfile = "3.1.0"
[build-dependencies] [build-dependencies]
tokio = { version = "1.21.2", features = ["rt-multi-thread", "macros"] } tokio = { version = "1.24.1", features = ["rt-multi-thread", "macros"] }
sqlx = { version = "0.6.2", features = ["runtime-tokio-rustls", "sqlite", "macros", "migrate"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-rustls", "sqlite", "macros", "migrate"] }
[features] [features]
default = [] default = []
fs-surb-storage = ["sqlx"] fs-surb-storage = ["sqlx"]
wasm = ["gateway-client/wasm"] wasm = ["gateway-client/wasm"]
coconut = ["gateway-client/coconut", "gateway-requests/coconut"]
+2 -2
View File
@@ -9,9 +9,9 @@ async fn main() {
use std::env; use std::env;
let out_dir = env::var("OUT_DIR").unwrap(); let out_dir = env::var("OUT_DIR").unwrap();
let database_path = format!("{}/fs-surbs-example.sqlite", out_dir); let database_path = format!("{out_dir}/fs-surbs-example.sqlite");
let mut conn = SqliteConnection::connect(&format!("sqlite://{}?mode=rwc", database_path)) let mut conn = SqliteConnection::connect(&format!("sqlite://{database_path}?mode=rwc"))
.await .await
.expect("Failed to create SQLx database connection"); .expect("Failed to create SQLx database connection");
@@ -0,0 +1,11 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
//
use crate::{client::replies::reply_storage, config::DebugConfig};
pub fn setup_empty_reply_surb_backend(debug_config: &DebugConfig) -> reply_storage::Empty {
reply_storage::Empty {
min_surb_threshold: debug_config.minimum_reply_surb_storage_threshold,
max_surb_threshold: debug_config.maximum_reply_surb_storage_threshold,
}
}
+139 -64
View File
@@ -25,6 +25,8 @@ use client_connections::{ConnectionCommandReceiver, ConnectionCommandSender, Lan
use crypto::asymmetric::{encryption, identity}; use crypto::asymmetric::{encryption, identity};
use futures::channel::mpsc; use futures::channel::mpsc;
use gateway_client::bandwidth::BandwidthController; use gateway_client::bandwidth::BandwidthController;
#[cfg(target_arch = "wasm32")]
use gateway_client::wasm_mockups::CosmWasmClient;
use gateway_client::{ use gateway_client::{
AcknowledgementReceiver, AcknowledgementSender, GatewayClient, MixnetMessageReceiver, AcknowledgementReceiver, AcknowledgementSender, GatewayClient, MixnetMessageReceiver,
MixnetMessageSender, MixnetMessageSender,
@@ -33,17 +35,23 @@ use log::{debug, info};
use nymsphinx::acknowledgements::AckKey; use nymsphinx::acknowledgements::AckKey;
use nymsphinx::addressing::clients::Recipient; use nymsphinx::addressing::clients::Recipient;
use nymsphinx::addressing::nodes::NodeIdentity; use nymsphinx::addressing::nodes::NodeIdentity;
use nymsphinx::receiver::ReconstructedMessage;
use std::sync::Arc; use std::sync::Arc;
use std::time::Duration; use std::time::Duration;
use tap::TapFallible; use tap::TapFallible;
use task::{ShutdownListener, ShutdownNotifier}; use task::{TaskClient, TaskManager};
use url::Url; 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"))] #[cfg(all(not(target_arch = "wasm32"), feature = "fs-surb-storage"))]
pub mod non_wasm_helpers; pub mod non_wasm_helpers;
pub mod helpers;
pub struct ClientInput { pub struct ClientInput {
pub shared_lane_queue_lengths: LaneQueueLengths,
pub connection_command_sender: ConnectionCommandSender, pub connection_command_sender: ConnectionCommandSender,
pub input_sender: InputMessageSender, pub input_sender: InputMessageSender,
} }
@@ -52,6 +60,27 @@ pub struct ClientOutput {
pub received_buffer_request_sender: ReceivedBufferRequestSender, pub received_buffer_request_sender: ReceivedBufferRequestSender,
} }
impl ClientOutput {
pub fn register_receiver(
&mut self,
) -> Result<mpsc::UnboundedReceiver<Vec<ReconstructedMessage>>, ClientCoreError> {
let (reconstructed_sender, reconstructed_receiver) = mpsc::unbounded();
self.received_buffer_request_sender
.unbounded_send(ReceivedBufferMessage::ReceiverAnnounce(
reconstructed_sender,
))
.map_err(|_| ClientCoreError::FailedToRegisterReceiver)?;
Ok(reconstructed_receiver)
}
}
pub struct ClientState {
pub shared_lane_queue_lengths: LaneQueueLengths,
pub reply_controller_sender: ReplyControllerSender,
}
pub enum ClientInputStatus { pub enum ClientInputStatus {
AwaitingProducer { client_input: ClientInput }, AwaitingProducer { client_input: ClientInput },
Connected, Connected,
@@ -80,33 +109,60 @@ impl ClientOutputStatus {
} }
} }
pub struct BaseClientBuilder<'a, B> { #[derive(Copy, Clone, PartialEq, Eq)]
pub enum CredentialsToggle {
Enabled,
Disabled,
}
impl CredentialsToggle {
pub fn is_enabled(&self) -> bool {
self == &CredentialsToggle::Enabled
}
pub fn is_disabled(&self) -> bool {
self == &CredentialsToggle::Disabled
}
}
impl From<bool> for CredentialsToggle {
fn from(value: bool) -> Self {
if value {
CredentialsToggle::Enabled
} else {
CredentialsToggle::Disabled
}
}
}
pub struct BaseClientBuilder<'a, B, C: Clone> {
// due to wasm limitations I had to split it like this : ( // due to wasm limitations I had to split it like this : (
gateway_config: &'a GatewayEndpointConfig, gateway_config: &'a GatewayEndpointConfig,
debug_config: &'a DebugConfig, debug_config: &'a DebugConfig,
disabled_credentials: bool, disabled_credentials: bool,
validator_api_endpoints: Vec<Url>, nym_api_endpoints: Vec<Url>,
reply_storage_backend: B, reply_storage_backend: B,
bandwidth_controller: Option<BandwidthController>, bandwidth_controller: Option<BandwidthController<C>>,
key_manager: KeyManager, key_manager: KeyManager,
} }
impl<'a, B> BaseClientBuilder<'a, B> impl<'a, B, C> BaseClientBuilder<'a, B, C>
where where
B: ReplyStorageBackend + Send + Sync + 'static, B: ReplyStorageBackend + Send + Sync + 'static,
C: CosmWasmClient + Sync + Send + Clone + 'static,
{ {
pub fn new_from_base_config<T>( pub fn new_from_base_config<T>(
base_config: &'a Config<T>, base_config: &'a Config<T>,
key_manager: KeyManager, key_manager: KeyManager,
bandwidth_controller: Option<BandwidthController>, bandwidth_controller: Option<BandwidthController<C>>,
reply_storage_backend: B, reply_storage_backend: B,
) -> BaseClientBuilder<'a, B> { ) -> BaseClientBuilder<'a, B, C> {
BaseClientBuilder { BaseClientBuilder {
gateway_config: base_config.get_gateway_endpoint_config(), gateway_config: base_config.get_gateway_endpoint_config(),
debug_config: base_config.get_debug_config(), debug_config: base_config.get_debug_config(),
disabled_credentials: base_config.get_disabled_credentials_mode(), disabled_credentials: base_config.get_disabled_credentials_mode(),
validator_api_endpoints: base_config.get_validator_api_endpoints(), nym_api_endpoints: base_config.get_nym_api_endpoints(),
bandwidth_controller, bandwidth_controller,
reply_storage_backend, reply_storage_backend,
key_manager, key_manager,
@@ -117,18 +173,18 @@ where
gateway_config: &'a GatewayEndpointConfig, gateway_config: &'a GatewayEndpointConfig,
debug_config: &'a DebugConfig, debug_config: &'a DebugConfig,
key_manager: KeyManager, key_manager: KeyManager,
bandwidth_controller: Option<BandwidthController>, bandwidth_controller: Option<BandwidthController<C>>,
reply_storage_backend: B, reply_storage_backend: B,
disabled_credentials: bool, credentials_toggle: CredentialsToggle,
validator_api_endpoints: Vec<Url>, nym_api_endpoints: Vec<Url>,
) -> BaseClientBuilder<'a, B> { ) -> BaseClientBuilder<'a, B, C> {
BaseClientBuilder { BaseClientBuilder {
gateway_config, gateway_config,
debug_config, debug_config,
disabled_credentials, disabled_credentials: credentials_toggle.is_disabled(),
validator_api_endpoints, nym_api_endpoints,
bandwidth_controller,
reply_storage_backend, reply_storage_backend,
bandwidth_controller,
key_manager, key_manager,
} }
} }
@@ -151,7 +207,7 @@ where
self_address: Recipient, self_address: Recipient,
topology_accessor: TopologyAccessor, topology_accessor: TopologyAccessor,
mix_tx: BatchMixMessageSender, mix_tx: BatchMixMessageSender,
shutdown: ShutdownListener, shutdown: TaskClient,
) { ) {
info!("Starting loop cover traffic stream..."); info!("Starting loop cover traffic stream...");
@@ -185,7 +241,7 @@ where
reply_controller_receiver: ReplyControllerReceiver, reply_controller_receiver: ReplyControllerReceiver,
lane_queue_lengths: LaneQueueLengths, lane_queue_lengths: LaneQueueLengths,
client_connection_rx: ConnectionCommandReceiver, client_connection_rx: ConnectionCommandReceiver,
shutdown: ShutdownListener, shutdown: TaskClient,
) { ) {
info!("Starting real traffic stream..."); info!("Starting real traffic stream...");
@@ -212,7 +268,7 @@ where
mixnet_receiver: MixnetMessageReceiver, mixnet_receiver: MixnetMessageReceiver,
reply_key_storage: SentReplyKeys, reply_key_storage: SentReplyKeys,
reply_controller_sender: ReplyControllerSender, reply_controller_sender: ReplyControllerSender,
shutdown: ShutdownListener, shutdown: TaskClient,
) { ) {
info!("Starting received messages buffer controller..."); info!("Starting received messages buffer controller...");
ReceivedMessagesBufferController::new( ReceivedMessagesBufferController::new(
@@ -229,16 +285,12 @@ where
&mut self, &mut self,
mixnet_message_sender: MixnetMessageSender, mixnet_message_sender: MixnetMessageSender,
ack_sender: AcknowledgementSender, ack_sender: AcknowledgementSender,
shutdown: ShutdownListener, shutdown: TaskClient,
) -> Result<GatewayClient, ClientCoreError<B>> { ) -> Result<GatewayClient<C>, ClientCoreError> {
let gateway_id = self.gateway_config.gateway_id.clone(); let gateway_id = self.gateway_config.gateway_id.clone();
if gateway_id.is_empty() { if gateway_id.is_empty() {
return Err(ClientCoreError::GatewayIdUnknown); return Err(ClientCoreError::GatewayIdUnknown);
} }
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(); let gateway_address = self.gateway_config.gateway_listener.clone();
if gateway_address.is_empty() { if gateway_address.is_empty() {
return Err(ClientCoreError::GatwayAddressUnknown); return Err(ClientCoreError::GatwayAddressUnknown);
@@ -248,7 +300,7 @@ where
.map_err(ClientCoreError::UnableToCreatePublicKeyFromGatewayId)?; .map_err(ClientCoreError::UnableToCreatePublicKeyFromGatewayId)?;
// disgusting wasm workaround since there's no key persistence there (nor `client init`) // disgusting wasm workaround since there's no key persistence there (nor `client init`)
let shared_key = if self.key_manager.gateway_key_set() { let shared_key = if self.key_manager.is_gateway_key_set() {
Some(self.key_manager.gateway_shared_key()) Some(self.key_manager.gateway_shared_key())
} else { } else {
None None
@@ -258,7 +310,6 @@ where
gateway_address, gateway_address,
self.key_manager.identity_keypair(), self.key_manager.identity_keypair(),
gateway_identity, gateway_identity,
gateway_owner,
shared_key, shared_key,
mixnet_message_sender, mixnet_message_sender,
ack_sender, ack_sender,
@@ -281,13 +332,13 @@ where
// future responsible for periodically polling directory server and updating // future responsible for periodically polling directory server and updating
// the current global view of topology // the current global view of topology
async fn start_topology_refresher( async fn start_topology_refresher(
validator_api_urls: Vec<Url>, nym_api_urls: Vec<Url>,
refresh_rate: Duration, refresh_rate: Duration,
topology_accessor: TopologyAccessor, topology_accessor: TopologyAccessor,
shutdown: ShutdownListener, shutdown: TaskClient,
) -> Result<(), ClientCoreError<B>> { ) -> Result<(), ClientCoreError> {
let topology_refresher_config = TopologyRefresherConfig::new( let topology_refresher_config = TopologyRefresherConfig::new(
validator_api_urls, nym_api_urls,
refresh_rate, refresh_rate,
env!("CARGO_PKG_VERSION").to_string(), env!("CARGO_PKG_VERSION").to_string(),
); );
@@ -316,8 +367,8 @@ where
// over it. Perhaps GatewayClient needs to be thread-shareable or have some channel for // over it. Perhaps GatewayClient needs to be thread-shareable or have some channel for
// requests? // requests?
fn start_mix_traffic_controller( fn start_mix_traffic_controller(
gateway_client: GatewayClient, gateway_client: GatewayClient<C>,
shutdown: ShutdownListener, shutdown: TaskClient,
) -> BatchMixMessageSender { ) -> BatchMixMessageSender {
info!("Starting mix traffic controller..."); info!("Starting mix traffic controller...");
let (mix_traffic_controller, mix_tx) = MixTrafficController::new(gateway_client); let (mix_traffic_controller, mix_tx) = MixTrafficController::new(gateway_client);
@@ -327,25 +378,43 @@ where
async fn setup_persistent_reply_storage( async fn setup_persistent_reply_storage(
backend: B, backend: B,
shutdown: ShutdownListener, shutdown: TaskClient,
) -> Result<CombinedReplyStorage, ClientCoreError<B>> { ) -> Result<CombinedReplyStorage, ClientCoreError>
let persistent_storage = PersistentReplyStorage::new(backend); where
let mem_store = persistent_storage <B as ReplyStorageBackend>::StorageError: Sync + Send,
.load_state_from_backend() {
.await if backend.is_active() {
.map_err(|err| ClientCoreError::SurbStorageError { source: err })?; log::trace!("Setup persistent reply storage");
let persistent_storage = PersistentReplyStorage::new(backend);
let store_clone = mem_store.clone(); let mem_store = persistent_storage
spawn_future(async move { .load_state_from_backend()
persistent_storage
.flush_on_shutdown(store_clone, shutdown)
.await .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<B>> { pub async fn start_base(mut self) -> Result<BaseClient, ClientCoreError>
where
<B as ReplyStorageBackend>::StorageError: Sync + Send,
{
info!("Starting nym client"); info!("Starting nym client");
// channels for inter-component communication // channels for inter-component communication
// TODO: make the channels be internally created by the relevant components // TODO: make the channels be internally created by the relevant components
@@ -367,29 +436,31 @@ where
let shared_topology_accessor = TopologyAccessor::new(); let shared_topology_accessor = TopologyAccessor::new();
// Shutdown notifier for signalling tasks to stop // Shutdown notifier for signalling tasks to stop
let shutdown = ShutdownNotifier::default(); let task_manager = TaskManager::default();
// channels responsible for dealing with reply-related fun // channels responsible for dealing with reply-related fun
let (reply_controller_sender, reply_controller_receiver) = let (reply_controller_sender, reply_controller_receiver) =
reply_controller::new_control_channels(); reply_controller::requests::new_control_channels();
let self_address = self.as_mix_recipient(); let self_address = self.as_mix_recipient();
// the components are started in very specific order. Unless you know what you are doing, // the components are started in very specific order. Unless you know what you are doing,
// do not change that. // do not change that.
let gateway_client = self let gateway_client = self
.start_gateway_client(mixnet_messages_sender, ack_sender, shutdown.subscribe()) .start_gateway_client(mixnet_messages_sender, ack_sender, task_manager.subscribe())
.await?; .await?;
let reply_storage = let reply_storage = Self::setup_persistent_reply_storage(
Self::setup_persistent_reply_storage(self.reply_storage_backend, shutdown.subscribe()) self.reply_storage_backend,
.await?; task_manager.subscribe(),
)
.await?;
Self::start_topology_refresher( Self::start_topology_refresher(
self.validator_api_endpoints.clone(), self.nym_api_endpoints.clone(),
self.debug_config.topology_refresh_rate, self.debug_config.topology_refresh_rate,
shared_topology_accessor.clone(), shared_topology_accessor.clone(),
shutdown.subscribe(), task_manager.subscribe(),
) )
.await?; .await?;
@@ -399,7 +470,7 @@ where
mixnet_messages_receiver, mixnet_messages_receiver,
reply_storage.key_storage(), reply_storage.key_storage(),
reply_controller_sender.clone(), reply_controller_sender.clone(),
shutdown.subscribe(), task_manager.subscribe(),
); );
// The sphinx_message_sender is the transmitter for any component generating sphinx packets // The sphinx_message_sender is the transmitter for any component generating sphinx packets
@@ -407,7 +478,7 @@ where
// traffic stream. // traffic stream.
// The MixTrafficController then sends the actual traffic // The MixTrafficController then sends the actual traffic
let sphinx_message_sender = let sphinx_message_sender =
Self::start_mix_traffic_controller(gateway_client, shutdown.subscribe()); Self::start_mix_traffic_controller(gateway_client, task_manager.subscribe());
// Channels that the websocket listener can use to signal downstream to the real traffic // Channels that the websocket listener can use to signal downstream to the real traffic
// controller that connections are closed. // controller that connections are closed.
@@ -435,11 +506,11 @@ where
input_receiver, input_receiver,
sphinx_message_sender.clone(), sphinx_message_sender.clone(),
reply_storage, reply_storage,
reply_controller_sender, reply_controller_sender.clone(),
reply_controller_receiver, reply_controller_receiver,
shared_lane_queue_lengths.clone(), shared_lane_queue_lengths.clone(),
client_connection_rx, client_connection_rx,
shutdown.subscribe(), task_manager.subscribe(),
); );
if !self.debug_config.disable_loop_cover_traffic_stream { if !self.debug_config.disable_loop_cover_traffic_stream {
@@ -449,7 +520,7 @@ where
self_address, self_address,
shared_topology_accessor, shared_topology_accessor,
sphinx_message_sender, sphinx_message_sender,
shutdown.subscribe(), task_manager.subscribe(),
); );
} }
@@ -459,7 +530,6 @@ where
Ok(BaseClient { Ok(BaseClient {
client_input: ClientInputStatus::AwaitingProducer { client_input: ClientInputStatus::AwaitingProducer {
client_input: ClientInput { client_input: ClientInput {
shared_lane_queue_lengths,
connection_command_sender: client_connection_tx, connection_command_sender: client_connection_tx,
input_sender, input_sender,
}, },
@@ -469,7 +539,11 @@ where
received_buffer_request_sender, received_buffer_request_sender,
}, },
}, },
shutdown_notifier: shutdown, client_state: ClientState {
shared_lane_queue_lengths,
reply_controller_sender,
},
task_manager,
}) })
} }
} }
@@ -477,6 +551,7 @@ where
pub struct BaseClient { pub struct BaseClient {
pub client_input: ClientInputStatus, pub client_input: ClientInputStatus,
pub client_output: ClientOutputStatus, pub client_output: ClientOutputStatus,
pub client_state: ClientState,
pub shutdown_notifier: ShutdownNotifier, pub task_manager: TaskManager,
} }
@@ -14,13 +14,15 @@ use time::OffsetDateTime;
async fn setup_fresh_backend<P: AsRef<Path>>( async fn setup_fresh_backend<P: AsRef<Path>>(
db_path: P, db_path: P,
debug_config: &DebugConfig, debug_config: &DebugConfig,
) -> Result<fs_backend::Backend, ClientCoreError<fs_backend::Backend>> { ) -> Result<fs_backend::Backend, ClientCoreError> {
info!("creating fresh surb database"); info!("creating fresh surb database");
let mut storage_backend = match fs_backend::Backend::init(db_path).await { let mut storage_backend = match fs_backend::Backend::init(db_path).await {
Ok(backend) => backend, Ok(backend) => backend,
Err(err) => { Err(err) => {
error!("failed to setup persistent storage backend for our reply needs: {err}"); error!("failed to setup persistent storage backend for our reply needs: {err}");
return Err(ClientCoreError::SurbStorageError { source: err }); return Err(ClientCoreError::SurbStorageError {
source: Box::new(err),
});
} }
}; };
@@ -34,11 +36,21 @@ async fn setup_fresh_backend<P: AsRef<Path>>(
storage_backend storage_backend
.init_fresh(&mem_store) .init_fresh(&mem_store)
.await .await
.map_err(|err| ClientCoreError::SurbStorageError { source: err })?; .map_err(|err| ClientCoreError::SurbStorageError {
source: Box::new(err),
})?;
Ok(storage_backend) 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<()> { fn archive_corrupted_database<P: AsRef<Path>>(db_path: P) -> io::Result<()> {
let db_path = db_path.as_ref(); let db_path = db_path.as_ref();
debug_assert!(db_path.exists()); debug_assert!(db_path.exists());
@@ -49,7 +61,7 @@ fn archive_corrupted_database<P: AsRef<Path>>(db_path: P) -> io::Result<()> {
let new_extension = let new_extension =
if let Some(existing_extension) = db_path.extension().and_then(|ext| ext.to_str()) { if let Some(existing_extension) = db_path.extension().and_then(|ext| ext.to_str()) {
format!("{existing_extension}.{}", suffix) format!("{existing_extension}.{suffix}")
} else { } else {
suffix suffix
}; };
@@ -61,23 +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>>( pub async fn setup_fs_reply_surb_backend<P: AsRef<Path>>(
db_path: P, db_path: Option<P>,
debug_config: &DebugConfig, debug_config: &DebugConfig,
) -> Result<fs_backend::Backend, ClientCoreError<fs_backend::Backend>> { ) -> Result<fs_backend::Backend, ClientCoreError> {
// if the database file doesnt exist, initialise fresh storage, otherwise attempt to load the existing one if let Some(db_path) = db_path {
let db_path = db_path.as_ref(); // if the database file doesnt exist, initialise fresh storage, otherwise attempt to load
if db_path.exists() { // the existing one
info!("loading existing surb database"); let db_path = db_path.as_ref();
match fs_backend::Backend::try_load(db_path).await { if db_path.exists() {
Ok(backend) => Ok(backend), info!("loading existing surb database");
Err(err) => { match fs_backend::Backend::try_load(db_path).await {
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"); 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)?; archive_corrupted_database(db_path)?;
setup_fresh_backend(db_path, debug_config).await setup_fresh_backend(db_path, debug_config).await
}
} }
} else {
setup_fresh_backend(db_path, debug_config).await
} }
} else { } else {
setup_fresh_backend(db_path, debug_config).await Ok(setup_inactive_backend(debug_config))
} }
} }
@@ -213,7 +213,7 @@ impl LoopCoverTrafficStream<OsRng> {
tokio::task::yield_now().await; tokio::task::yield_now().await;
} }
pub fn start_with_shutdown(mut self, mut shutdown: task::ShutdownListener) { pub fn start_with_shutdown(mut self, mut shutdown: task::TaskClient) {
// we should set initial delay only when we actually start the stream // we should set initial delay only when we actually start the stream
let sampled = let sampled =
sample_poisson_duration(&mut self.rng, self.average_cover_message_sending_delay); sample_poisson_duration(&mut self.rng, self.average_cover_message_sending_delay);
@@ -0,0 +1,14 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
#[cfg(not(target_arch = "wasm32"))]
mod non_wasm;
#[cfg(target_arch = "wasm32")]
mod wasm;
#[cfg(not(target_arch = "wasm32"))]
pub use non_wasm::*;
#[cfg(target_arch = "wasm32")]
pub use wasm::*;
@@ -0,0 +1,13 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
pub use tokio::time::*;
pub type IntervalStream = tokio_stream::wrappers::IntervalStream;
pub(crate) fn get_time_now() -> Instant {
Instant::now()
}
pub(crate) fn new_interval_stream(polling_rate: Duration) -> IntervalStream {
tokio_stream::wrappers::IntervalStream::new(tokio::time::interval(polling_rate))
}
@@ -0,0 +1,16 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use std::time::Duration;
use wasm_timer;
pub use wasm_timer::*;
pub type IntervalStream = gloo_timers::future::IntervalStream;
pub(crate) fn get_time_now() -> Instant {
wasm_timer::Instant::now()
}
pub(crate) fn new_interval_stream(polling_rate: Duration) -> IntervalStream {
gloo_timers::future::IntervalStream::new(polling_rate.as_millis() as u32)
}
+94 -27
View File
@@ -17,6 +17,7 @@ use std::sync::Arc;
// use the old key after new one was issued. // use the old key after new one was issued.
// Remember that Arc<T> has Deref implementation for T // Remember that Arc<T> has Deref implementation for T
#[derive(Clone)]
pub struct KeyManager { pub struct KeyManager {
/// identity key associated with the client instance. /// identity key associated with the client instance.
identity_keypair: Arc<identity::KeyPair>, identity_keypair: Arc<identity::KeyPair>,
@@ -41,9 +42,6 @@ pub struct KeyManager {
*/ */
impl KeyManager { impl KeyManager {
// this is actually **NOT** dead code
// I have absolutely no idea why the compiler insists it's unused. The call happens during client::init::execute
#[allow(dead_code)]
/// Creates new instance of a [`KeyManager`] /// Creates new instance of a [`KeyManager`]
pub fn new<R>(rng: &mut R) -> Self pub fn new<R>(rng: &mut R) -> Self
where where
@@ -57,16 +55,22 @@ impl KeyManager {
} }
} }
// this is actually **NOT** dead code pub fn from_keys(
// I have absolutely no idea why the compiler insists it's unused. The call happens during client::init::execute id_keypair: identity::KeyPair,
#[allow(dead_code)] enc_keypair: encryption::KeyPair,
/// After shared key with the gateway is derived, puts its ownership to this instance of a [`KeyManager`]. gateway_shared_key: SharedKeys,
pub fn insert_gateway_shared_key(&mut self, gateway_shared_key: Arc<SharedKeys>) { ack_key: AckKey,
self.gateway_shared_key = Some(gateway_shared_key) ) -> Self {
Self {
identity_keypair: Arc::new(id_keypair),
encryption_keypair: Arc::new(enc_keypair),
gateway_shared_key: Some(Arc::new(gateway_shared_key)),
ack_key: Arc::new(ack_key),
}
} }
/// Loads previously stored keys from the disk. /// Loads previously stored client keys from the disk.
pub fn load_keys(client_pathfinder: &ClientKeyPathfinder) -> io::Result<Self> { fn load_client_keys(client_pathfinder: &ClientKeyPathfinder) -> io::Result<Self> {
let identity_keypair: identity::KeyPair = let identity_keypair: identity::KeyPair =
pemstore::load_keypair(&pemstore::KeyPairPath::new( pemstore::load_keypair(&pemstore::KeyPairPath::new(
client_pathfinder.private_identity_key().to_owned(), client_pathfinder.private_identity_key().to_owned(),
@@ -78,24 +82,51 @@ impl KeyManager {
client_pathfinder.public_encryption_key().to_owned(), client_pathfinder.public_encryption_key().to_owned(),
))?; ))?;
let gateway_shared_key: SharedKeys =
pemstore::load_key(client_pathfinder.gateway_shared_key())?;
let ack_key: AckKey = pemstore::load_key(client_pathfinder.ack_key())?; let ack_key: AckKey = pemstore::load_key(client_pathfinder.ack_key())?;
// TODO: ack key is never stored so it is generated now. But perhaps it should be stored
// after all for consistency sake?
Ok(KeyManager { Ok(KeyManager {
identity_keypair: Arc::new(identity_keypair), identity_keypair: Arc::new(identity_keypair),
encryption_keypair: Arc::new(encryption_keypair), encryption_keypair: Arc::new(encryption_keypair),
gateway_shared_key: Some(Arc::new(gateway_shared_key)), gateway_shared_key: None,
ack_key: Arc::new(ack_key), ack_key: Arc::new(ack_key),
}) })
} }
// this is actually **NOT** dead code /// Loads previously stored keys from the disk. Fails if not all, including the shared gateway
// I have absolutely no idea why the compiler insists it's unused. The call happens during client::init::execute /// key, is available.
#[allow(dead_code)] pub fn load_keys(client_pathfinder: &ClientKeyPathfinder) -> io::Result<Self> {
let mut key_manager = Self::load_client_keys(client_pathfinder)?;
let gateway_shared_key: SharedKeys =
pemstore::load_key(client_pathfinder.gateway_shared_key())?;
key_manager.gateway_shared_key = Some(Arc::new(gateway_shared_key));
Ok(key_manager)
}
/// Loads previously stored keys from the disk. Fails if client keys are not availabe, but the
/// shared gateway key is optional.
pub fn load_keys_but_gateway_is_optional(
client_pathfinder: &ClientKeyPathfinder,
) -> io::Result<Self> {
let mut key_manager = Self::load_client_keys(client_pathfinder)?;
let gateway_shared_key: Result<SharedKeys, io::Error> =
pemstore::load_key(client_pathfinder.gateway_shared_key());
// It's ok if the gateway key was not found
let gateway_shared_key = match gateway_shared_key {
Err(err) if err.kind() == io::ErrorKind::NotFound => Ok(None),
Err(err) => Err(err),
Ok(key) => Ok(Some(key)),
}?;
key_manager.gateway_shared_key = gateway_shared_key.map(Arc::new);
Ok(key_manager)
}
/// Stores all available keys on the disk. /// Stores all available keys on the disk.
// While perhaps there is no much point in storing the `AckKey` on the disk, // While perhaps there is no much point in storing the `AckKey` on the disk,
// it is done so for the consistency sake so that you wouldn't require an rng instance // it is done so for the consistency sake so that you wouldn't require an rng instance
@@ -119,7 +150,7 @@ impl KeyManager {
pemstore::store_key(self.ack_key.as_ref(), client_pathfinder.ack_key())?; pemstore::store_key(self.ack_key.as_ref(), client_pathfinder.ack_key())?;
match self.gateway_shared_key.as_ref() { match self.gateway_shared_key.as_ref() {
None => warn!("No gateway shared key available to store!"), None => debug!("No gateway shared key available to store!"),
Some(gate_key) => { Some(gate_key) => {
pemstore::store_key(gate_key.as_ref(), client_pathfinder.gateway_shared_key())? pemstore::store_key(gate_key.as_ref(), client_pathfinder.gateway_shared_key())?
} }
@@ -128,16 +159,57 @@ impl KeyManager {
Ok(()) Ok(())
} }
pub fn store_gateway_key(&self, client_pathfinder: &ClientKeyPathfinder) -> io::Result<()> {
match self.gateway_shared_key.as_ref() {
None => {
return Err(io::Error::new(
io::ErrorKind::Other,
"trying to store a non-existing key",
))
}
Some(gate_key) => {
pemstore::store_key(gate_key.as_ref(), client_pathfinder.gateway_shared_key())?
}
}
Ok(())
}
/// Overwrite the existing identity keypair
pub fn set_identity_keypair(&mut self, id_keypair: identity::KeyPair) {
self.identity_keypair = Arc::new(id_keypair);
}
/// Gets an atomically reference counted pointer to [`identity::KeyPair`]. /// Gets an atomically reference counted pointer to [`identity::KeyPair`].
pub fn identity_keypair(&self) -> Arc<identity::KeyPair> { pub fn identity_keypair(&self) -> Arc<identity::KeyPair> {
Arc::clone(&self.identity_keypair) Arc::clone(&self.identity_keypair)
} }
/// Overwrite the existing encryption keypair
pub fn set_encryption_keypair(&mut self, enc_keypair: encryption::KeyPair) {
self.encryption_keypair = Arc::new(enc_keypair);
}
/// Gets an atomically reference counted pointer to [`encryption::KeyPair`]. /// Gets an atomically reference counted pointer to [`encryption::KeyPair`].
pub fn encryption_keypair(&self) -> Arc<encryption::KeyPair> { pub fn encryption_keypair(&self) -> Arc<encryption::KeyPair> {
Arc::clone(&self.encryption_keypair) Arc::clone(&self.encryption_keypair)
} }
/// Overwrite the existing ack key
pub fn set_ack_key(&mut self, ack_key: AckKey) {
self.ack_key = Arc::new(ack_key);
}
/// Gets an atomically reference counted pointer to [`AckKey`].
pub fn ack_key(&self) -> Arc<AckKey> {
Arc::clone(&self.ack_key)
}
/// After shared key with the gateway is derived, puts its ownership to this instance of a [`KeyManager`].
pub fn insert_gateway_shared_key(&mut self, gateway_shared_key: Arc<SharedKeys>) {
self.gateway_shared_key = Some(gateway_shared_key)
}
/// Gets an atomically reference counted pointer to [`SharedKey`]. /// Gets an atomically reference counted pointer to [`SharedKey`].
// since this function is not fully public, it is not expected to be used externally and // since this function is not fully public, it is not expected to be used externally and
// hence it's up to us to ensure it's called in correct context // hence it's up to us to ensure it's called in correct context
@@ -149,12 +221,7 @@ impl KeyManager {
) )
} }
pub fn gateway_key_set(&self) -> bool { pub fn is_gateway_key_set(&self) -> bool {
self.gateway_shared_key.is_some() self.gateway_shared_key.is_some()
} }
/// Gets an atomically reference counted pointer to [`AckKey`].
pub fn ack_key(&self) -> Arc<AckKey> {
Arc::clone(&self.ack_key)
}
} }
+20 -10
View File
@@ -2,9 +2,13 @@
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use crate::spawn_future; use crate::spawn_future;
#[cfg(target_arch = "wasm32")]
use gateway_client::wasm_mockups::CosmWasmClient;
use gateway_client::GatewayClient; use gateway_client::GatewayClient;
use log::*; use log::*;
use nymsphinx::forwarding::packet::MixPacket; 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 BatchMixMessageSender = tokio::sync::mpsc::Sender<Vec<MixPacket>>;
pub type BatchMixMessageReceiver = tokio::sync::mpsc::Receiver<Vec<MixPacket>>; pub type BatchMixMessageReceiver = tokio::sync::mpsc::Receiver<Vec<MixPacket>>;
@@ -13,10 +17,10 @@ pub type BatchMixMessageReceiver = tokio::sync::mpsc::Receiver<Vec<MixPacket>>;
pub const MIX_MESSAGE_RECEIVER_BUFFER_SIZE: usize = 32; pub const MIX_MESSAGE_RECEIVER_BUFFER_SIZE: usize = 32;
const MAX_FAILURE_COUNT: usize = 100; const MAX_FAILURE_COUNT: usize = 100;
pub struct MixTrafficController { pub struct MixTrafficController<C: Clone> {
// TODO: most likely to be replaced by some higher level construct as // TODO: most likely to be replaced by some higher level construct as
// later on gateway_client will need to be accessible by other entities // later on gateway_client will need to be accessible by other entities
gateway_client: GatewayClient, gateway_client: GatewayClient<C>,
mix_rx: BatchMixMessageReceiver, mix_rx: BatchMixMessageReceiver,
// TODO: this is temporary work-around. // TODO: this is temporary work-around.
@@ -24,8 +28,13 @@ pub struct MixTrafficController {
consecutive_gateway_failure_count: usize, consecutive_gateway_failure_count: usize,
} }
impl MixTrafficController { impl<C> MixTrafficController<C>
pub fn new(gateway_client: GatewayClient) -> (MixTrafficController, BatchMixMessageSender) { where
C: CosmWasmClient + Sync + Send + Clone + 'static,
{
pub fn new(
gateway_client: GatewayClient<C>,
) -> (MixTrafficController<C>, BatchMixMessageSender) {
let (sphinx_message_sender, sphinx_message_receiver) = let (sphinx_message_sender, sphinx_message_receiver) =
tokio::sync::mpsc::channel(MIX_MESSAGE_RECEIVER_BUFFER_SIZE); tokio::sync::mpsc::channel(MIX_MESSAGE_RECEIVER_BUFFER_SIZE);
( (
@@ -51,13 +60,13 @@ impl MixTrafficController {
}; };
match result { match result {
Err(e) => { Err(err) => {
error!("Failed to send sphinx packet(s) to the gateway! - {:?}", e); error!("Failed to send sphinx packet(s) to the gateway! - {err}");
self.consecutive_gateway_failure_count += 1; self.consecutive_gateway_failure_count += 1;
if self.consecutive_gateway_failure_count == MAX_FAILURE_COUNT { if self.consecutive_gateway_failure_count == MAX_FAILURE_COUNT {
// todo: in the future this should initiate a 'graceful' shutdown or try // todo: in the future this should initiate a 'graceful' shutdown or try
// to reconnect? // to reconnect?
panic!("failed to send sphinx packet to the gateway {} times in a row - assuming the gateway is dead. Can't do anything about it yet :(", MAX_FAILURE_COUNT) panic!("failed to send sphinx packet to the gateway {MAX_FAILURE_COUNT} times in a row - assuming the gateway is dead. Can't do anything about it yet :(")
} }
} }
Ok(_) => { Ok(_) => {
@@ -67,11 +76,11 @@ impl MixTrafficController {
} }
} }
pub fn start_with_shutdown(mut self, mut shutdown: task::ShutdownListener) { pub fn start_with_shutdown(mut self, mut shutdown: task::TaskClient) {
spawn_future(async move { spawn_future(async move {
debug!("Started MixTrafficController with graceful shutdown support"); debug!("Started MixTrafficController with graceful shutdown support");
while !shutdown.is_shutdown() { loop {
tokio::select! { tokio::select! {
mix_packets = self.mix_rx.recv() => match mix_packets { mix_packets = self.mix_rx.recv() => match mix_packets {
Some(mix_packets) => { Some(mix_packets) => {
@@ -82,8 +91,9 @@ impl MixTrafficController {
break; break;
} }
}, },
_ = shutdown.recv() => { _ = shutdown.recv_with_delay() => {
log::trace!("MixTrafficController: Received shutdown"); log::trace!("MixTrafficController: Received shutdown");
break;
} }
} }
} }
+2
View File
@@ -3,6 +3,7 @@
pub mod base_client; pub mod base_client;
pub mod cover_traffic_stream; pub mod cover_traffic_stream;
pub(crate) mod helpers;
pub mod inbound_messages; pub mod inbound_messages;
pub mod key_manager; pub mod key_manager;
pub mod mix_traffic; pub mod mix_traffic;
@@ -10,3 +11,4 @@ pub mod real_messages_control;
pub mod received_buffer; pub mod received_buffer;
pub mod replies; pub mod replies;
pub mod topology_control; pub mod topology_control;
pub(crate) mod transmission_buffer;
@@ -65,7 +65,7 @@ impl AcknowledgementListener {
} }
} }
pub(super) async fn run_with_shutdown(&mut self, mut shutdown: task::ShutdownListener) { pub(super) async fn run_with_shutdown(&mut self, mut shutdown: task::TaskClient) {
debug!("Started AcknowledgementListener with graceful shutdown support"); debug!("Started AcknowledgementListener with graceful shutdown support");
while !shutdown.is_shutdown() { while !shutdown.is_shutdown() {
@@ -77,7 +77,7 @@ impl AcknowledgementListener {
break; break;
} }
}, },
_ = shutdown.recv() => { _ = shutdown.recv_with_delay() => {
log::trace!("AcknowledgementListener: Received shutdown"); log::trace!("AcknowledgementListener: Received shutdown");
} }
} }
@@ -213,7 +213,11 @@ impl ActionController {
} }
// note: when the entry expires it's automatically removed from pending_acks_timers // note: when the entry expires it's automatically removed from pending_acks_timers
fn handle_expired_ack_timer(&mut self, expired_ack: Expired<FragmentIdentifier>) { fn handle_expired_ack_timer(
&mut self,
expired_ack: Expired<FragmentIdentifier>,
task_client: &mut task::TaskClient,
) {
// I'm honestly not sure how to handle it, because getting it means other things in our // I'm honestly not sure how to handle it, because getting it means other things in our
// system are already misbehaving. If we ever see this panic, then I guess we should worry // system are already misbehaving. If we ever see this panic, then I guess we should worry
// about it. Perhaps just reschedule it at later point? // about it. Perhaps just reschedule it at later point?
@@ -231,9 +235,16 @@ impl ActionController {
// downgrading an arc and then upgrading vs cloning is difference of 30ns vs 15ns // downgrading an arc and then upgrading vs cloning is difference of 30ns vs 15ns
// so it's literally a NO difference while it might prevent us from unnecessarily // so it's literally a NO difference while it might prevent us from unnecessarily
// resending data (in maybe 1 in 1 million cases, but it's something) // resending data (in maybe 1 in 1 million cases, but it's something)
self.retransmission_sender if self
.retransmission_sender
.unbounded_send(Arc::downgrade(pending_ack_data)) .unbounded_send(Arc::downgrade(pending_ack_data))
.unwrap() .is_err()
{
assert!(
task_client.is_shutdown_poll(),
"Failed to send pending ack for retransmission"
);
}
} else { } else {
// this shouldn't cause any issues but shouldn't have happened to begin with! // this shouldn't cause any issues but shouldn't have happened to begin with!
error!("An already removed pending ack has expired") error!("An already removed pending ack has expired")
@@ -249,7 +260,7 @@ impl ActionController {
} }
} }
pub(super) async fn run_with_shutdown(&mut self, mut shutdown: task::ShutdownListener) { pub(super) async fn run_with_shutdown(&mut self, mut shutdown: task::TaskClient) {
debug!("Started ActionController with graceful shutdown support"); debug!("Started ActionController with graceful shutdown support");
while !shutdown.is_shutdown() { while !shutdown.is_shutdown() {
@@ -264,21 +275,18 @@ impl ActionController {
} }
}, },
expired_ack = self.pending_acks_timers.next() => match expired_ack { expired_ack = self.pending_acks_timers.next() => match expired_ack {
Some(expired_ack) => self.handle_expired_ack_timer(expired_ack), Some(expired_ack) => self.handle_expired_ack_timer(expired_ack, &mut shutdown),
None => { None => {
log::trace!("ActionController: Stopping since ack channel closed"); log::trace!("ActionController: Stopping since ack channel closed");
break; break;
} }
}, },
_ = shutdown.recv() => { _ = shutdown.recv_with_delay() => {
log::trace!("ActionController: Received shutdown"); log::trace!("ActionController: Received shutdown");
} }
} }
} }
#[cfg(not(target_arch = "wasm32"))] shutdown.recv_timeout().await;
tokio::time::timeout(Duration::from_secs(5), shutdown.recv())
.await
.expect("Task stopped without shutdown called");
log::debug!("ActionController: Exiting"); log::debug!("ActionController: Exiting");
} }
} }
@@ -109,7 +109,7 @@ where
}; };
} }
pub(super) async fn run_with_shutdown(&mut self, mut shutdown: task::ShutdownListener) { pub(super) async fn run_with_shutdown(&mut self, mut shutdown: task::TaskClient) {
debug!("Started InputMessageListener with graceful shutdown support"); debug!("Started InputMessageListener with graceful shutdown support");
while !shutdown.is_shutdown() { while !shutdown.is_shutdown() {
@@ -123,7 +123,7 @@ where
break; break;
} }
}, },
_ = shutdown.recv() => { _ = shutdown.recv_with_delay() => {
log::trace!("InputMessageListener: Received shutdown"); log::trace!("InputMessageListener: Received shutdown");
} }
} }
@@ -249,7 +249,7 @@ where
} }
} }
pub(super) fn start_with_shutdown(self, shutdown: task::ShutdownListener) { pub(super) fn start_with_shutdown(self, shutdown: task::TaskClient) {
let mut acknowledgement_listener = self.acknowledgement_listener; let mut acknowledgement_listener = self.acknowledgement_listener;
let mut input_message_listener = self.input_message_listener; let mut input_message_listener = self.input_message_listener;
let mut retransmission_request_listener = self.retransmission_request_listener; let mut retransmission_request_listener = self.retransmission_request_listener;
@@ -137,7 +137,7 @@ where
.await .await
} }
pub(super) async fn run_with_shutdown(&mut self, mut shutdown: task::ShutdownListener) { pub(super) async fn run_with_shutdown(&mut self, mut shutdown: task::TaskClient) {
debug!("Started RetransmissionRequestListener with graceful shutdown support"); debug!("Started RetransmissionRequestListener with graceful shutdown support");
while !shutdown.is_shutdown() { while !shutdown.is_shutdown() {
@@ -37,7 +37,7 @@ impl SentNotificationListener {
.unwrap(); .unwrap();
} }
pub(super) async fn run_with_shutdown(&mut self, mut shutdown: task::ShutdownListener) { pub(super) async fn run_with_shutdown(&mut self, mut shutdown: task::TaskClient) {
debug!("Started SentNotificationListener with graceful shutdown support"); debug!("Started SentNotificationListener with graceful shutdown support");
while !shutdown.is_shutdown() { while !shutdown.is_shutdown() {
@@ -51,7 +51,7 @@ impl SentNotificationListener {
break; break;
} }
}, },
_ = shutdown.recv() => { _ = shutdown.recv_with_delay() => {
log::trace!("SentNotificationListener: Received shutdown"); log::trace!("SentNotificationListener: Received shutdown");
} }
} }
@@ -20,6 +20,7 @@ use nymsphinx::params::{PacketSize, DEFAULT_NUM_MIX_HOPS};
use nymsphinx::preparer::{MessagePreparer, PreparedFragment}; use nymsphinx::preparer::{MessagePreparer, PreparedFragment};
use nymsphinx::Delay; use nymsphinx::Delay;
use rand::{CryptoRng, Rng}; use rand::{CryptoRng, Rng};
use std::collections::HashMap;
use std::sync::Arc; use std::sync::Arc;
use std::time::Duration; use std::time::Duration;
use thiserror::Error; use thiserror::Error;
@@ -278,7 +279,7 @@ where
reply_surb: ReplySurb, reply_surb: ReplySurb,
amount: u32, amount: u32,
) -> Result<(), SurbWrappedPreparationError> { ) -> Result<(), SurbWrappedPreparationError> {
debug!("requesting {amount} reply SURBs from {from:?}"); debug!("requesting {amount} reply SURBs from {from}");
let surbs_request = let surbs_request =
ReplyMessage::new_surb_request_message(self.config.sender_address, amount); ReplyMessage::new_surb_request_message(self.config.sender_address, amount);
@@ -294,19 +295,11 @@ where
))) )))
} }
// the only difference between this method and `try_send_reply_chunks` is that pub(crate) async fn send_retransmission_reply_chunks(
// here we are not creating acks as acks are already in memory waiting to get cleared.
// we are only updating their existing delays
pub(crate) async fn try_send_retransmission_reply_chunks(
&mut self, &mut self,
fragments: Vec<Fragment>, prepared_fragments: Vec<PreparedFragment>,
reply_surbs: Vec<ReplySurb>,
lane: TransmissionLane, lane: TransmissionLane,
) -> Result<(), SurbWrappedPreparationError> { ) {
let prepared_fragments = self
.prepare_reply_chunks_for_sending(fragments.clone(), reply_surbs)
.await?;
let mut real_messages = Vec::with_capacity(prepared_fragments.len()); let mut real_messages = Vec::with_capacity(prepared_fragments.len());
for prepared in prepared_fragments { for prepared in prepared_fragments {
@@ -315,33 +308,58 @@ where
} }
self.forward_messages(real_messages, lane).await; self.forward_messages(real_messages, lane).await;
Ok(())
} }
pub(crate) async fn try_send_reply_chunks( pub(crate) async fn try_send_reply_chunks_on_lane(
&mut self, &mut self,
target: AnonymousSenderTag, target: AnonymousSenderTag,
fragments: Vec<Fragment>, fragments: Vec<Fragment>,
reply_surbs: Vec<ReplySurb>, reply_surbs: Vec<ReplySurb>,
lane: TransmissionLane, lane: TransmissionLane,
) -> Result<(), SurbWrappedPreparationError> {
// TODO: technically this is performing an unnecessary cloning, but in the grand scheme of things
// is it really that bad?
self.try_send_reply_chunks(
target,
fragments.into_iter().map(|f| (lane, f)).collect(),
reply_surbs,
)
.await
}
pub(crate) async fn try_send_reply_chunks(
&mut self,
target: AnonymousSenderTag,
fragments: Vec<(TransmissionLane, Fragment)>,
reply_surbs: Vec<ReplySurb>,
) -> Result<(), SurbWrappedPreparationError> { ) -> Result<(), SurbWrappedPreparationError> {
let prepared_fragments = self let prepared_fragments = self
.prepare_reply_chunks_for_sending(fragments.clone(), reply_surbs) .prepare_reply_chunks_for_sending(
fragments.iter().map(|(_, f)| f.clone()).collect(),
reply_surbs,
)
.await?; .await?;
let mut pending_acks = Vec::with_capacity(fragments.len()); let mut pending_acks = Vec::with_capacity(fragments.len());
let mut real_messages = Vec::with_capacity(fragments.len()); let mut to_forward: HashMap<_, Vec<_>> = HashMap::new();
for (raw, prepared) in fragments.into_iter().zip(prepared_fragments.into_iter()) { for (raw, prepared) in fragments.into_iter().zip(prepared_fragments.into_iter()) {
let lane = raw.0;
let fragment = raw.1;
let real_message = RealMessage::new(prepared.mix_packet, prepared.fragment_identifier); let real_message = RealMessage::new(prepared.mix_packet, prepared.fragment_identifier);
let delay = prepared.total_delay; let delay = prepared.total_delay;
let pending_ack = PendingAcknowledgement::new_anonymous(raw, delay, target, false); let pending_ack = PendingAcknowledgement::new_anonymous(fragment, delay, target, false);
real_messages.push(real_message); let entry = to_forward.entry(lane).or_default();
entry.push(real_message);
pending_acks.push(pending_ack); pending_acks.push(pending_ack);
} }
self.forward_messages(real_messages, lane).await; for (lane, real_messages) in to_forward {
self.forward_messages(real_messages, lane).await;
}
self.insert_pending_acks(pending_acks); self.insert_pending_acks(pending_acks);
Ok(()) Ok(())
} }
@@ -467,7 +485,7 @@ where
Ok(prepared_fragment) Ok(prepared_fragment)
} }
async fn prepare_reply_chunks_for_sending( pub(crate) async fn prepare_reply_chunks_for_sending(
&mut self, &mut self,
fragments: Vec<Fragment>, fragments: Vec<Fragment>,
reply_surbs: Vec<ReplySurb>, reply_surbs: Vec<ReplySurb>,
@@ -81,7 +81,11 @@ pub struct Config {
/// Defines maximum amount of time the client is going to wait for reply surbs before explicitly asking /// 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. /// 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. /// 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. /// 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.minimum_reply_surb_request_size,
cfg.maximum_reply_surb_request_size, cfg.maximum_reply_surb_request_size,
cfg.maximum_allowed_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_surb_age,
cfg.maximum_reply_key_age, cfg.maximum_reply_key_age,
) )
@@ -161,8 +166,10 @@ impl Config {
.maximum_reply_surb_request_size, .maximum_reply_surb_request_size,
maximum_allowed_reply_surb_request_size: base_client_debug_config maximum_allowed_reply_surb_request_size: base_client_debug_config
.maximum_allowed_reply_surb_request_size, .maximum_allowed_reply_surb_request_size,
maximum_reply_surb_waiting_period: base_client_debug_config maximum_reply_surb_rerequest_waiting_period: base_client_debug_config
.maximum_reply_surb_waiting_period, .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_surb_age: base_client_debug_config.maximum_reply_surb_age,
maximum_reply_key_age: base_client_debug_config.maximum_reply_key_age, maximum_reply_key_age: base_client_debug_config.maximum_reply_key_age,
} }
@@ -263,7 +270,7 @@ impl RealMessagesController<OsRng> {
} }
} }
pub fn start_with_shutdown(self, shutdown: task::ShutdownListener) { pub fn start_with_shutdown(self, shutdown: task::TaskClient) {
let mut out_queue_control = self.out_queue_control; let mut out_queue_control = self.out_queue_control;
let ack_control = self.ack_control; let ack_control = self.ack_control;
let mut reply_control = self.reply_control; let mut reply_control = self.reply_control;
@@ -1,9 +1,11 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net> // Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use self::sending_delay_controller::SendingDelayController;
use crate::client::mix_traffic::BatchMixMessageSender; use crate::client::mix_traffic::BatchMixMessageSender;
use crate::client::real_messages_control::acknowledgement_control::SentPacketNotificationSender; use crate::client::real_messages_control::acknowledgement_control::SentPacketNotificationSender;
use crate::client::topology_control::TopologyAccessor; use crate::client::topology_control::TopologyAccessor;
use crate::client::transmission_buffer::TransmissionBuffer;
use client_connections::{ use client_connections::{
ConnectionCommand, ConnectionCommandReceiver, ConnectionId, LaneQueueLengths, TransmissionLane, ConnectionCommand, ConnectionCommandReceiver, ConnectionId, LaneQueueLengths, TransmissionLane,
}; };
@@ -29,22 +31,7 @@ use tokio::time;
#[cfg(target_arch = "wasm32")] #[cfg(target_arch = "wasm32")]
use wasm_timer; use wasm_timer;
use self::{
sending_delay_controller::SendingDelayController, transmission_buffer::TransmissionBuffer,
};
mod sending_delay_controller; mod sending_delay_controller;
mod transmission_buffer;
#[cfg(not(target_arch = "wasm32"))]
fn get_time_now() -> time::Instant {
time::Instant::now()
}
#[cfg(target_arch = "wasm32")]
fn get_time_now() -> wasm_timer::Instant {
wasm_timer::Instant::now()
}
/// Configurable parameters of the `OutQueueControl` /// Configurable parameters of the `OutQueueControl`
pub(crate) struct Config { pub(crate) struct Config {
@@ -135,7 +122,7 @@ where
/// Buffer containing all incoming real messages keyed by transmission lane, that we will send /// Buffer containing all incoming real messages keyed by transmission lane, that we will send
/// out to the mixnet. /// out to the mixnet.
transmission_buffer: TransmissionBuffer, transmission_buffer: TransmissionBuffer<RealMessage>,
/// Incoming channel for being notified of closed connections, so that we can close lanes /// Incoming channel for being notified of closed connections, so that we can close lanes
/// corresponding to connections. To avoid sending traffic unnecessary /// corresponding to connections. To avoid sending traffic unnecessary
@@ -162,6 +149,10 @@ impl From<PreparedFragment> for RealMessage {
} }
impl RealMessage { impl RealMessage {
pub(crate) fn packet_size(&self) -> usize {
self.mix_packet.sphinx_packet().len()
}
pub(crate) fn new(mix_packet: MixPacket, fragment_id: FragmentIdentifier) -> Self { pub(crate) fn new(mix_packet: MixPacket, fragment_id: FragmentIdentifier) -> Self {
RealMessage { RealMessage {
mix_packet, mix_packet,
@@ -207,7 +198,7 @@ where
real_receiver, real_receiver,
rng, rng,
topology_access, topology_access,
transmission_buffer: Default::default(), transmission_buffer: TransmissionBuffer::new(),
client_connection_rx, client_connection_rx,
lane_queue_lengths, lane_queue_lengths,
} }
@@ -264,7 +255,7 @@ where
}; };
if let Err(err) = self.mix_tx.send(vec![next_message]).await { if let Err(err) = self.mix_tx.send(vec![next_message]).await {
log::error!("Failed to send: {}", err); log::error!("Failed to send: {err}");
} }
// notify ack controller about sending our message only after we actually managed to push it // notify ack controller about sending our message only after we actually managed to push it
@@ -328,7 +319,9 @@ where
fn pop_next_message(&mut self) -> Option<RealMessage> { fn pop_next_message(&mut self) -> Option<RealMessage> {
// Pop the next message from the transmission buffer // Pop the next message from the transmission buffer
let (lane, real_next) = self.transmission_buffer.pop_next_message_at_random()?; let (lane, real_next) = self
.transmission_buffer
.pop_next_message_at_random(&mut self.rng)?;
// Update the published queue length // Update the published queue length
let lane_length = self.transmission_buffer.lane_length(&lane); let lane_length = self.transmission_buffer.lane_length(&lane);
@@ -469,7 +462,7 @@ where
} }
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
fn log_status(&self, shutdown: &mut task::ShutdownListener) { fn log_status(&self, shutdown: &mut task::TaskClient) {
use crate::error::ClientCoreStatusMessage; use crate::error::ClientCoreStatusMessage;
let packets = self.transmission_buffer.total_size(); let packets = self.transmission_buffer.total_size();
@@ -478,14 +471,10 @@ where
let mult = self.sending_delay_controller.current_multiplier(); let mult = self.sending_delay_controller.current_multiplier();
let delay = self.current_average_message_sending_delay().as_millis(); let delay = self.current_average_message_sending_delay().as_millis();
let status_str = if self.config.disable_poisson_packet_distribution { let status_str = if self.config.disable_poisson_packet_distribution {
format!( format!("Status: {lanes} lanes, backlog: {backlog:.2} kiB ({packets}), no delay")
"Status: {lanes} lanes, backlog: {:.2} kiB ({packets}), no delay",
backlog
)
} else { } else {
format!( format!(
"Status: {lanes} lanes, backlog: {:.2} kiB ({packets}), avg delay: {}ms ({mult})", "Status: {lanes} lanes, backlog: {backlog:.2} kiB ({packets}), avg delay: {delay}ms ({mult})"
backlog, delay
) )
}; };
if packets > 1000 { if packets > 1000 {
@@ -514,7 +503,7 @@ where
} }
} }
pub(super) async fn run_with_shutdown(&mut self, mut shutdown: task::ShutdownListener) { pub(super) async fn run_with_shutdown(&mut self, mut shutdown: task::TaskClient) {
debug!("Started OutQueueControl with graceful shutdown support"); debug!("Started OutQueueControl with graceful shutdown support");
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
@@ -525,7 +514,7 @@ where
while !shutdown.is_shutdown() { while !shutdown.is_shutdown() {
tokio::select! { tokio::select! {
biased; biased;
_ = shutdown.recv() => { _ = shutdown.recv_with_delay() => {
log::trace!("OutQueueControl: Received shutdown"); log::trace!("OutQueueControl: Received shutdown");
} }
_ = status_timer.tick() => { _ = status_timer.tick() => {
@@ -542,9 +531,7 @@ where
} }
} }
} }
tokio::time::timeout(Duration::from_secs(5), shutdown.recv()) shutdown.recv_timeout().await;
.await
.expect("Task stopped without shutdown called");
} }
#[cfg(target_arch = "wasm32")] #[cfg(target_arch = "wasm32")]
@@ -1,14 +1,9 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net> // Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use super::get_time_now; use crate::client::helpers::{get_time_now, Instant};
use std::time::Duration; use std::time::Duration;
#[cfg(not(target_arch = "wasm32"))]
use tokio::time;
#[cfg(target_arch = "wasm32")]
use wasm_timer;
// The minimum time between increasing the average delay between packets. If we hit the ceiling in // The minimum time between increasing the average delay between packets. If we hit the ceiling in
// the available buffer space we want to take somewhat swift action, but we still need to give a // the available buffer space we want to take somewhat swift action, but we still need to give a
// short time to give the channel a chance reduce pressure. // short time to give the channel a chance reduce pressure.
@@ -39,19 +34,11 @@ pub(crate) struct SendingDelayController {
lower_bound: u32, lower_bound: u32,
/// To make sure we don't change the multiplier to fast, we limit a change to some duration /// To make sure we don't change the multiplier to fast, we limit a change to some duration
#[cfg(not(target_arch = "wasm32"))] time_when_changed: Instant,
time_when_changed: time::Instant,
#[cfg(target_arch = "wasm32")]
time_when_changed: wasm_timer::Instant,
/// If we have a long enough time without any backpressure detected we try reducing the sending /// If we have a long enough time without any backpressure detected we try reducing the sending
/// delay multiplier /// delay multiplier
#[cfg(not(target_arch = "wasm32"))] time_when_backpressure_detected: Instant,
time_when_backpressure_detected: time::Instant,
#[cfg(target_arch = "wasm32")]
time_when_backpressure_detected: wasm_timer::Instant,
} }
impl Default for SendingDelayController { impl Default for SendingDelayController {
@@ -77,10 +64,12 @@ impl SendingDelayController {
self.current_multiplier self.current_multiplier
} }
#[cfg(not(target_arch = "wasm32"))]
pub(crate) fn min_multiplier(&self) -> u32 { pub(crate) fn min_multiplier(&self) -> u32 {
self.lower_bound self.lower_bound
} }
#[cfg(not(target_arch = "wasm32"))]
pub(crate) fn max_multiplier(&self) -> u32 { pub(crate) fn max_multiplier(&self) -> u32 {
self.upper_bound self.upper_bound
} }
@@ -399,21 +399,20 @@ impl RequestReceiver {
} }
} }
async fn run_with_shutdown(&mut self, mut shutdown: task::ShutdownListener) { async fn run_with_shutdown(&mut self, mut shutdown: task::TaskClient) {
debug!("Started RequestReceiver with graceful shutdown support"); debug!("Started RequestReceiver with graceful shutdown support");
while !shutdown.is_shutdown() { while !shutdown.is_shutdown() {
tokio::select! { tokio::select! {
biased; biased;
_ = shutdown.recv() => { _ = shutdown.recv_with_delay() => {
log::trace!("RequestReceiver: Received shutdown"); log::trace!("RequestReceiver: Received shutdown");
} }
request = self.query_receiver.next() => { request = self.query_receiver.next() => {
match request { if let Some(message) = request {
Some(message) => self.handle_message(message).await, self.handle_message(message).await
None => { } else {
log::trace!("RequestReceiver: Stopping since channel closed"); log::trace!("RequestReceiver: Stopping since channel closed");
break; break;
},
} }
}, },
} }
@@ -439,20 +438,19 @@ impl FragmentedMessageReceiver {
} }
} }
async fn run_with_shutdown(&mut self, mut shutdown: task::ShutdownListener) { async fn run_with_shutdown(&mut self, mut shutdown: task::TaskClient) {
debug!("Started FragmentedMessageReceiver with graceful shutdown support"); debug!("Started FragmentedMessageReceiver with graceful shutdown support");
while !shutdown.is_shutdown() { while !shutdown.is_shutdown() {
tokio::select! { tokio::select! {
new_messages = self.mixnet_packet_receiver.next() => match new_messages { new_messages = self.mixnet_packet_receiver.next() => {
Some(new_messages) => { if let Some(new_messages) = new_messages {
self.received_buffer.handle_new_received(new_messages).await; self.received_buffer.handle_new_received(new_messages).await;
} } else {
None => {
log::trace!("FragmentedMessageReceiver: Stopping since channel closed"); log::trace!("FragmentedMessageReceiver: Stopping since channel closed");
break; break;
} }
}, },
_ = shutdown.recv() => { _ = shutdown.recv_with_delay() => {
log::trace!("FragmentedMessageReceiver: Received shutdown"); log::trace!("FragmentedMessageReceiver: Received shutdown");
} }
} }
@@ -490,7 +488,7 @@ impl ReceivedMessagesBufferController {
} }
} }
pub fn start_with_shutdown(self, shutdown: task::ShutdownListener) { pub fn start_with_shutdown(self, shutdown: task::TaskClient) {
let mut fragmented_message_receiver = self.fragmented_message_receiver; let mut fragmented_message_receiver = self.fragmented_message_receiver;
let mut request_receiver = self.request_receiver; let mut request_receiver = self.request_receiver;
@@ -4,8 +4,8 @@
use crate::client::real_messages_control::acknowledgement_control::PendingAcknowledgement; use crate::client::real_messages_control::acknowledgement_control::PendingAcknowledgement;
use crate::client::real_messages_control::message_handler::{MessageHandler, PreparationError}; use crate::client::real_messages_control::message_handler::{MessageHandler, PreparationError};
use crate::client::replies::reply_storage::CombinedReplyStorage; use crate::client::replies::reply_storage::CombinedReplyStorage;
use client_connections::TransmissionLane; use client_connections::{ConnectionId, TransmissionLane};
use futures::channel::mpsc; use futures::channel::oneshot;
use futures::StreamExt; use futures::StreamExt;
use log::{debug, error, info, trace, warn}; use log::{debug, error, info, trace, warn};
use nymsphinx::addressing::clients::Recipient; use nymsphinx::addressing::clients::Recipient;
@@ -15,122 +15,23 @@ use nymsphinx::chunking::fragment::{Fragment, FragmentIdentifier};
use rand::{CryptoRng, Rng}; use rand::{CryptoRng, Rng};
use std::cmp::{max, min}; use std::cmp::{max, min};
use std::collections::btree_map::Entry; use std::collections::btree_map::Entry;
use std::collections::{BTreeMap, HashMap, VecDeque}; use std::collections::{BTreeMap, HashMap};
use std::sync::{Arc, Weak}; use std::sync::{Arc, Weak};
use std::time::Duration; use std::time::Duration;
use time::OffsetDateTime; use time::OffsetDateTime;
#[cfg(not(target_arch = "wasm32"))] use crate::client::helpers::new_interval_stream;
type IntervalStream = tokio_stream::wrappers::IntervalStream; use crate::client::transmission_buffer::TransmissionBuffer;
pub(crate) use requests::{ReplyControllerMessage, ReplyControllerReceiver, ReplyControllerSender};
#[cfg(target_arch = "wasm32")] pub mod requests;
type IntervalStream = gloo_timers::future::IntervalStream;
pub(crate) fn new_control_channels() -> (ReplyControllerSender, ReplyControllerReceiver) {
let (tx, rx) = mpsc::unbounded();
(tx.into(), rx)
}
#[derive(Debug, Clone)]
pub(crate) struct ReplyControllerSender(mpsc::UnboundedSender<ReplyControllerMessage>);
impl From<mpsc::UnboundedSender<ReplyControllerMessage>> for ReplyControllerSender {
fn from(inner: mpsc::UnboundedSender<ReplyControllerMessage>) -> Self {
ReplyControllerSender(inner)
}
}
impl ReplyControllerSender {
pub(crate) fn send_retransmission_data(
&self,
recipient: AnonymousSenderTag,
timed_out_ack: Weak<PendingAcknowledgement>,
extra_surb_request: bool,
) {
self.0
.unbounded_send(ReplyControllerMessage::RetransmitReply {
recipient,
timed_out_ack,
extra_surb_request,
})
.expect("ReplyControllerReceiver has died!")
}
pub(crate) fn send_reply(
&self,
recipient: AnonymousSenderTag,
message: Vec<u8>,
lane: TransmissionLane,
) {
self.0
.unbounded_send(ReplyControllerMessage::SendReply {
recipient,
message,
lane,
})
.expect("ReplyControllerReceiver has died!")
}
pub(crate) fn send_additional_surbs(
&self,
sender_tag: AnonymousSenderTag,
reply_surbs: Vec<ReplySurb>,
from_surb_request: bool,
) {
self.0
.unbounded_send(ReplyControllerMessage::AdditionalSurbs {
sender_tag,
reply_surbs,
from_surb_request,
})
.expect("ReplyControllerReceiver has died!")
}
pub(crate) fn send_additional_surbs_request(&self, recipient: Recipient, amount: u32) {
self.0
.unbounded_send(ReplyControllerMessage::AdditionalSurbsRequest {
recipient: Box::new(recipient),
amount,
})
.expect("ReplyControllerReceiver has died!")
}
}
pub(crate) type ReplyControllerReceiver = mpsc::UnboundedReceiver<ReplyControllerMessage>;
#[derive(Debug)]
pub(crate) enum ReplyControllerMessage {
RetransmitReply {
recipient: AnonymousSenderTag,
timed_out_ack: Weak<PendingAcknowledgement>,
extra_surb_request: bool,
},
SendReply {
recipient: AnonymousSenderTag,
message: Vec<u8>,
lane: TransmissionLane,
},
AdditionalSurbs {
sender_tag: AnonymousSenderTag,
reply_surbs: Vec<ReplySurb>,
from_surb_request: bool,
},
// Should this also be handled in here? it's technically a completely different side of the pipe
// let's see how it works when combined, might split it before creating PR
AdditionalSurbsRequest {
recipient: Box<Recipient>,
amount: u32,
},
}
pub struct Config { pub struct Config {
min_surb_request_size: u32, min_surb_request_size: u32,
max_surb_request_size: u32, max_surb_request_size: u32,
maximum_allowed_reply_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_surb_age: Duration,
max_reply_key_age: Duration, max_reply_key_age: Duration,
} }
@@ -140,7 +41,8 @@ impl Config {
min_surb_request_size: u32, min_surb_request_size: u32,
max_surb_request_size: u32, max_surb_request_size: u32,
maximum_allowed_reply_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_surb_age: Duration,
max_reply_key_age: Duration, max_reply_key_age: Duration,
) -> Self { ) -> Self {
@@ -148,7 +50,8 @@ impl Config {
min_surb_request_size, min_surb_request_size,
max_surb_request_size, max_surb_request_size,
maximum_allowed_reply_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_surb_age,
max_reply_key_age, max_reply_key_age,
} }
@@ -172,7 +75,7 @@ pub struct ReplyController<R> {
// of surbs required to send the message through // of surbs required to send the message through
// expected_reliability: f32, // expected_reliability: f32,
request_receiver: ReplyControllerReceiver, request_receiver: ReplyControllerReceiver,
pending_replies: HashMap<AnonymousSenderTag, VecDeque<Fragment>>, pending_replies: HashMap<AnonymousSenderTag, TransmissionBuffer<Fragment>>,
/// Retransmission packets that have already timed out and are waiting for additional reply SURBs /// Retransmission packets that have already timed out and are waiting for additional reply SURBs
/// so that they could be sent back to the network. Once we receive more SURBs, we should send them ASAP. /// so that they could be sent back to the network. Once we receive more SURBs, we should send them ASAP.
@@ -204,17 +107,28 @@ where
} }
} }
/// Inserts the pending replies into the BACK of the queue fn insert_pending_replies<V: Into<VecDeque<Fragment>>>( fn insert_pending_replies<I: IntoIterator<Item = Fragment>>(
fn insert_pending_replies<V: Into<VecDeque<Fragment>>>(
&mut self, &mut self,
recipient: &AnonymousSenderTag, recipient: &AnonymousSenderTag,
fragments: V, fragments: I,
lane: TransmissionLane,
) { ) {
if let Some(existing) = self.pending_replies.get_mut(recipient) { self.pending_replies
existing.append(&mut fragments.into()) .entry(*recipient)
} else { .or_insert_with(TransmissionBuffer::new)
self.pending_replies.insert(*recipient, fragments.into()); .store(&lane, fragments)
} }
fn re_insert_pending_replies(
&mut self,
recipient: &AnonymousSenderTag,
fragments: Vec<(TransmissionLane, Fragment)>,
) {
// the buffer should ALWAYS exist at this point, if it doesn't, it's a bug...
self.pending_replies
.entry(*recipient)
.or_insert_with(TransmissionBuffer::new)
.store_multiple(fragments)
} }
fn re_insert_pending_retransmission( fn re_insert_pending_retransmission(
@@ -244,7 +158,7 @@ where
let pending_queue_size = self let pending_queue_size = self
.pending_replies .pending_replies
.get(target) .get(target)
.map(|pending_queue| pending_queue.len()) .map(|pending_queue| pending_queue.total_size())
.unwrap_or_default(); .unwrap_or_default();
let retransmission_queue = self let retransmission_queue = self
@@ -299,43 +213,62 @@ where
} }
trace!("handling reply to {:?}", recipient_tag); trace!("handling reply to {:?}", recipient_tag);
let fragments = self.message_handler.split_reply_message(data); let mut fragments = self.message_handler.split_reply_message(data);
let total_size = fragments.len();
trace!("This reply requires {:?} SURBs", total_size);
let required_surbs = fragments.len(); let available_surbs = self
trace!("This reply requires {:?} SURBs", required_surbs);
// TODO: edge case:
// we're making a lot of requests and have to request a lot of surbs
// (but at some point we run out of surbs for surb requests)
let (surbs, _surbs_left) = self
.full_reply_storage .full_reply_storage
.surbs_storage_ref() .surbs_storage_ref()
.get_reply_surbs(&recipient_tag, required_surbs); .available_surbs(&recipient_tag);
let min_surbs_threshold = self
.full_reply_storage
.surbs_storage_ref()
.min_surb_threshold();
if let Some(reply_surbs) = surbs { let max_to_send = if available_surbs > min_surbs_threshold {
if let Err(err) = self min(fragments.len(), available_surbs - min_surbs_threshold)
.message_handler
.try_send_reply_chunks(recipient_tag, fragments, reply_surbs, lane)
.await
{
let err = err.return_unused_surbs(
self.full_reply_storage.surbs_storage_ref(),
&recipient_tag,
);
warn!("failed to send reply to {:?} - {err}", recipient_tag);
// TODO: should we buffer that data to try again?
}
} else { } else {
// we don't have enough surbs for this reply 0
self.insert_pending_replies(&recipient_tag, fragments); };
if self.should_request_more_surbs(&recipient_tag) { if max_to_send > 0 {
self.request_reply_surbs_for_queue_clearing(recipient_tag) let (surbs, _surbs_left) = self
.await; .full_reply_storage
.surbs_storage_ref()
.get_reply_surbs(&recipient_tag, max_to_send);
if let Some(reply_surbs) = surbs {
let to_send = fragments.drain(..max_to_send).collect::<Vec<_>>();
if let Err(err) = self
.message_handler
.try_send_reply_chunks_on_lane(
recipient_tag,
to_send.clone(),
reply_surbs,
lane,
)
.await
{
let err = err.return_unused_surbs(
self.full_reply_storage.surbs_storage_ref(),
&recipient_tag,
);
warn!("failed to send reply to {recipient_tag}: {err}");
self.insert_pending_replies(&recipient_tag, to_send, lane);
}
} }
} }
// if there's leftover data we didn't send because we didn't have enough (or any) surbs - buffer it
if !fragments.is_empty() {
self.insert_pending_replies(&recipient_tag, fragments, lane);
}
if self.should_request_more_surbs(&recipient_tag) {
self.request_reply_surbs_for_queue_clearing(recipient_tag)
.await;
}
} }
async fn request_additional_reply_surbs( async fn request_additional_reply_surbs(
@@ -398,35 +331,18 @@ where
}; };
let mut to_take = Vec::new(); let mut to_take = Vec::new();
let mut to_remove = Vec::new();
// TODO: once rust 1.66.0 is stabilised on 15.12.22, just change it to while to_take.len() < max_to_clear {
// `.pop_front()` to directly take ownership if let Some((_, data)) = pending.pop_first() {
for (k, data) in pending.iter() { // no need to do anything if we failed to upgrade the reference,
let upgraded = match data.upgrade() { // it means we got the ack while the data was waiting in the queue
Some(upgraded) => upgraded, if let Some(upgraded) = data.upgrade() {
None => { to_take.push(upgraded)
// we got the ack while the data was waiting in the queue
to_remove.push(*k);
continue;
} }
}; } else {
// our map is empty!
to_take.push(upgraded);
// we have taken as many entries as we could have
if to_take.len() >= max_to_clear {
break; break;
} }
// TODO: use if upgraded.is_extra_surb_request() to bypass the limit
}
for ack in &to_take {
pending.remove(&ack.inner_fragment_identifier());
}
for id in to_remove {
pending.remove(&id);
} }
if to_take.is_empty() { if to_take.is_empty() {
@@ -447,46 +363,47 @@ where
let to_send_vec = to_take.iter().map(|ack| ack.fragment_data()).collect(); let to_send_vec = to_take.iter().map(|ack| ack.fragment_data()).collect();
if let Err(err) = self let prepared_fragments = match self
.message_handler .message_handler
.try_send_retransmission_reply_chunks( .prepare_reply_chunks_for_sending(to_send_vec, surbs_for_reply)
to_send_vec,
surbs_for_reply,
TransmissionLane::Retransmission,
)
.await .await
{ {
let err = err.return_unused_surbs(self.full_reply_storage.surbs_storage_ref(), &target); Ok(prepared) => prepared,
self.re_insert_pending_retransmission(&target, to_take); Err(err) => {
let err =
err.return_unused_surbs(self.full_reply_storage.surbs_storage_ref(), &target);
self.re_insert_pending_retransmission(&target, to_take);
warn!( warn!(
"failed to clear pending retransmission queue for {:?} - {err}", "failed to clear pending retransmission queue for {:?} - {err}",
target target
); );
} return;
}
};
// we can't fail at this point, so drop all references to acks so that timer updates wouldn't blow up
drop(to_take);
self.message_handler
.send_retransmission_reply_chunks(prepared_fragments, TransmissionLane::Retransmission)
.await;
} }
fn pop_at_most_pending_replies( fn pop_at_most_pending_replies(
&mut self, &mut self,
from: &AnonymousSenderTag, from: &AnonymousSenderTag,
amount: usize, amount: usize,
) -> Option<VecDeque<Fragment>> { ) -> Option<Vec<(TransmissionLane, Fragment)>> {
// if possible, pop all pending replies, if not, pop only entries for which we'd have a reply surb // if possible, pop all pending replies, if not, pop only entries for which we'd have a reply surb
let total = self.pending_replies.get(from)?.len(); let total = self.pending_replies.get(from)?.total_size();
trace!("pending queue has {total} elements"); trace!("pending queue has {total} elements");
if total == 0 { if total == 0 {
return None; return None;
} }
if total < amount { self.pending_replies
self.pending_replies.remove(from) .get_mut(from)?
} else { .pop_at_most_n_next_messages_at_random(amount)
Some(
self.pending_replies
.get_mut(from)?
.drain(..amount)
.collect(),
)
}
} }
async fn try_clear_pending_queue(&mut self, target: AnonymousSenderTag) { async fn try_clear_pending_queue(&mut self, target: AnonymousSenderTag) {
@@ -510,9 +427,9 @@ where
// we're guaranteed to not get more entries than we have reply surbs for // we're guaranteed to not get more entries than we have reply surbs for
if let Some(to_send) = self.pop_at_most_pending_replies(&target, max_to_clear) { if let Some(to_send) = self.pop_at_most_pending_replies(&target, max_to_clear) {
let to_send_vec = to_send.iter().cloned().collect::<Vec<_>>(); let to_send_clone = to_send.clone();
if to_send_vec.is_empty() { if to_send_clone.is_empty() {
panic!( panic!(
"please let the devs know if you ever see this message (reply_controller.rs)" "please let the devs know if you ever see this message (reply_controller.rs)"
); );
@@ -521,27 +438,22 @@ where
let (surbs_for_reply, _) = self let (surbs_for_reply, _) = self
.full_reply_storage .full_reply_storage
.surbs_storage_ref() .surbs_storage_ref()
.get_reply_surbs(&target, to_send_vec.len()); .get_reply_surbs(&target, to_send_clone.len());
let Some(surbs_for_reply) = surbs_for_reply else { let Some(surbs_for_reply) = surbs_for_reply else {
error!("somehow different task has stolen our reply surbs! - this should have been impossible"); error!("somehow different task has stolen our reply surbs! - this should have been impossible");
self.insert_pending_replies(&target, to_send); self.re_insert_pending_replies(&target, to_send);
return; return;
}; };
if let Err(err) = self if let Err(err) = self
.message_handler .message_handler
.try_send_reply_chunks( .try_send_reply_chunks(target, to_send_clone, surbs_for_reply)
target,
to_send_vec,
surbs_for_reply,
TransmissionLane::General,
)
.await .await
{ {
let err = let err =
err.return_unused_surbs(self.full_reply_storage.surbs_storage_ref(), &target); err.return_unused_surbs(self.full_reply_storage.surbs_storage_ref(), &target);
self.insert_pending_replies(&target, to_send); self.re_insert_pending_replies(&target, to_send);
warn!("failed to clear pending queue for {:?} - {err}", target); warn!("failed to clear pending queue for {:?} - {err}", target);
} }
} else { } else {
@@ -712,6 +624,30 @@ where
} }
} }
// to be honest this doesn't make a lot of sense in the context of `connection_id`,
// it should really be asked per tag
fn handle_lane_queue_length(
&self,
connection_id: ConnectionId,
response_channel: oneshot::Sender<usize>,
) {
// TODO: if we ever have duplicate ids for different senders, it means our rng is super weak
// thus I don't think we have to worry about it?
let lane = TransmissionLane::ConnectionId(connection_id);
for buf in self.pending_replies.values() {
if let Some(length) = buf.lane_length(&lane) {
if response_channel.send(length).is_err() {
error!("the requester for lane queue length has dropped the response channel!")
}
return;
}
}
// make sure that if we didn't find that lane, we reply with 0
if response_channel.send(0).is_err() {
error!("the requester for lane queue length has dropped the response channel!")
}
}
async fn handle_request(&mut self, request: ReplyControllerMessage) { async fn handle_request(&mut self, request: ReplyControllerMessage) {
match request { match request {
ReplyControllerMessage::RetransmitReply { ReplyControllerMessage::RetransmitReply {
@@ -735,19 +671,26 @@ where
self.handle_received_surbs(sender_tag, reply_surbs, from_surb_request) self.handle_received_surbs(sender_tag, reply_surbs, from_surb_request)
.await .await
} }
ReplyControllerMessage::LaneQueueLength {
connection_id,
response_channel,
} => self.handle_lane_queue_length(connection_id, response_channel),
ReplyControllerMessage::AdditionalSurbsRequest { recipient, amount } => { ReplyControllerMessage::AdditionalSurbsRequest { recipient, amount } => {
self.handle_surb_request(*recipient, amount).await self.handle_surb_request(*recipient, amount).await
} }
} }
} }
// TODO: modify this method to more accurately determine the amount of surbs it needs to request
// it should take into consideration the average latency, sending rate and queue size.
// it should request as many surbs as it takes to saturate its sending rate before next batch arrives
async fn request_reply_surbs_for_queue_clearing(&mut self, target: AnonymousSenderTag) { async fn request_reply_surbs_for_queue_clearing(&mut self, target: AnonymousSenderTag) {
trace!("requesting surbs for queues clearing"); trace!("requesting surbs for queues clearing");
let pending_queue_size = self let pending_queue_size = self
.pending_replies .pending_replies
.get(&target) .get(&target)
.map(|pending_queue| pending_queue.len()) .map(|pending_queue| pending_queue.total_size())
.unwrap_or_default(); .unwrap_or_default();
let retransmission_queue = self let retransmission_queue = self
@@ -787,7 +730,7 @@ where
} }
let Some(last_received) = self.full_reply_storage.surbs_storage_ref().surbs_last_received_at(pending_reply_target) else { let Some(last_received) = self.full_reply_storage.surbs_storage_ref().surbs_last_received_at(pending_reply_target) else {
error!("we have {} pending replies for {pending_reply_target}, but we somehow never received any reply surbs from them!", vals.len()); error!("we have {} pending replies for {pending_reply_target}, but we somehow never received any reply surbs from them!", vals.total_size());
to_remove.push(*pending_reply_target); to_remove.push(*pending_reply_target);
continue; continue;
}; };
@@ -802,9 +745,13 @@ where
let diff = now - last_received_time; let diff = now - last_received_time;
if diff > self.config.max_surb_waiting_period { if diff > self.config.max_surb_rerequest_waiting_period {
warn!("We haven't received any surbs in {:?} from {pending_reply_target}. Going to explicitly ask for more", diff); if diff > self.config.max_surb_drop_waiting_period {
to_request.push(*pending_reply_target); 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);
}
} }
} }
@@ -883,28 +830,25 @@ where
} }
} }
fn create_interval_stream(polling_rate: Duration) -> IntervalStream { // #[cfg(not(target_arch = "wasm32"))]
#[cfg(not(target_arch = "wasm32"))] // async fn log_status(&self) {
return tokio_stream::wrappers::IntervalStream::new(tokio::time::interval(polling_rate)); // todo!()
// }
#[cfg(target_arch = "wasm32")] pub(crate) async fn run_with_shutdown(&mut self, mut shutdown: task::TaskClient) {
return gloo_timers::future::IntervalStream::new(polling_rate.as_millis() as u32);
}
pub(crate) async fn run_with_shutdown(&mut self, mut shutdown: task::ShutdownListener) {
debug!("Started ReplyController with graceful shutdown support"); debug!("Started ReplyController with graceful shutdown support");
let polling_rate = Duration::from_secs(5); let polling_rate = Duration::from_secs(5);
let mut stale_inspection = Self::create_interval_stream(polling_rate); let mut stale_inspection = new_interval_stream(polling_rate);
// this is in the order of hours/days so we don't have to poll it that often // this is in the order of hours/days so we don't have to poll it that often
let polling_rate = Duration::from_secs(self.config.max_reply_surb_age.as_secs() / 10); let polling_rate = Duration::from_secs(self.config.max_reply_surb_age.as_secs() / 10);
let mut invalidation_inspection = Self::create_interval_stream(polling_rate); let mut invalidation_inspection = new_interval_stream(polling_rate);
while !shutdown.is_shutdown() { while !shutdown.is_shutdown() {
tokio::select! { tokio::select! {
biased; biased;
_ = shutdown.recv() => { _ = shutdown.recv_with_delay() => {
log::trace!("ReplyController: Received shutdown"); log::trace!("ReplyController: Received shutdown");
}, },
req = self.request_receiver.next() => match req { req = self.request_receiver.next() => match req {
@@ -0,0 +1,154 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::client::real_messages_control::acknowledgement_control::PendingAcknowledgement;
use client_connections::{ConnectionId, TransmissionLane};
use futures::channel::{mpsc, oneshot};
use log::error;
use nymsphinx::addressing::clients::Recipient;
use nymsphinx::anonymous_replies::requests::AnonymousSenderTag;
use nymsphinx::anonymous_replies::ReplySurb;
use std::sync::Weak;
pub(crate) fn new_control_channels() -> (ReplyControllerSender, ReplyControllerReceiver) {
let (tx, rx) = mpsc::unbounded();
(tx.into(), rx)
}
#[derive(Debug, Clone)]
pub struct ReplyControllerSender(mpsc::UnboundedSender<ReplyControllerMessage>);
impl From<mpsc::UnboundedSender<ReplyControllerMessage>> for ReplyControllerSender {
fn from(inner: mpsc::UnboundedSender<ReplyControllerMessage>) -> Self {
ReplyControllerSender(inner)
}
}
impl ReplyControllerSender {
pub(crate) fn send_retransmission_data(
&self,
recipient: AnonymousSenderTag,
timed_out_ack: Weak<PendingAcknowledgement>,
extra_surb_request: bool,
) {
self.0
.unbounded_send(ReplyControllerMessage::RetransmitReply {
recipient,
timed_out_ack,
extra_surb_request,
})
.expect("ReplyControllerReceiver has died!")
}
pub(crate) fn send_reply(
&self,
recipient: AnonymousSenderTag,
message: Vec<u8>,
lane: TransmissionLane,
) {
self.0
.unbounded_send(ReplyControllerMessage::SendReply {
recipient,
message,
lane,
})
.expect("ReplyControllerReceiver has died!")
}
pub(crate) fn send_additional_surbs(
&self,
sender_tag: AnonymousSenderTag,
reply_surbs: Vec<ReplySurb>,
from_surb_request: bool,
) {
self.0
.unbounded_send(ReplyControllerMessage::AdditionalSurbs {
sender_tag,
reply_surbs,
from_surb_request,
})
.expect("ReplyControllerReceiver has died!")
}
pub(crate) fn send_additional_surbs_request(&self, recipient: Recipient, amount: u32) {
self.0
.unbounded_send(ReplyControllerMessage::AdditionalSurbsRequest {
recipient: Box::new(recipient),
amount,
})
.expect("ReplyControllerReceiver has died!")
}
pub async fn get_lane_queue_length(&self, connection_id: ConnectionId) -> usize {
let (response_tx, response_rx) = oneshot::channel();
self.0
.unbounded_send(ReplyControllerMessage::LaneQueueLength {
connection_id,
response_channel: response_tx,
})
.expect("ReplyControllerReceiver has died!");
match response_rx.await {
Ok(length) => length,
Err(_) => {
error!("The reply controller has dropped our response channel!");
// TODO: should we panic here instead? this message implies something weird and unrecoverable has happened
0
}
}
}
}
pub struct ReplyQueueLengths {
reply_controller_sender: ReplyControllerSender,
}
impl ReplyQueueLengths {
pub fn new(reply_controller_sender: ReplyControllerSender) -> Self {
Self {
reply_controller_sender,
}
}
pub async fn get_lane_queue_length(&self, connection_id: ConnectionId) -> usize {
self.reply_controller_sender
.get_lane_queue_length(connection_id)
.await
}
}
pub(crate) type ReplyControllerReceiver = mpsc::UnboundedReceiver<ReplyControllerMessage>;
#[derive(Debug)]
pub(crate) enum ReplyControllerMessage {
RetransmitReply {
recipient: AnonymousSenderTag,
timed_out_ack: Weak<PendingAcknowledgement>,
extra_surb_request: bool,
},
SendReply {
recipient: AnonymousSenderTag,
message: Vec<u8>,
lane: TransmissionLane,
},
AdditionalSurbs {
sender_tag: AnonymousSenderTag,
reply_surbs: Vec<ReplySurb>,
from_surb_request: bool,
},
// this one doesn't belong here either...
LaneQueueLength {
connection_id: ConnectionId,
response_channel: oneshot::Sender<usize>,
},
// Should this also be handled in here? it's technically a completely different side of the pipe
// let's see how it works when combined, might split it before creating PR
AdditionalSurbsRequest {
recipient: Box<Recipient>,
amount: u32,
},
}
@@ -7,6 +7,7 @@ use async_trait::async_trait;
// well, right now we don't have the browser storage : ( // well, right now we don't have the browser storage : (
// so we keep everything in memory // so we keep everything in memory
#[derive(Debug)]
pub struct Backend { pub struct Backend {
empty: Empty, empty: Empty,
} }
@@ -40,4 +41,8 @@ impl ReplyStorageBackend for Backend {
async fn load_surb_storage(&self) -> Result<CombinedReplyStorage, Self::StorageError> { async fn load_surb_storage(&self) -> Result<CombinedReplyStorage, Self::StorageError> {
self.empty.load_surb_storage().await 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")] #[error("the provided database path doesn't have a filename defined")]
DatabasePathWithoutFilename { provided_path: PathBuf }, 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}")] #[error("failed to rename our databse file - {source}")]
DatabaseRenameError { DatabaseRenameError {
#[source] #[source]
@@ -20,6 +20,16 @@ impl StorageManager {
database_path: P, database_path: P,
fresh: bool, fresh: bool,
) -> Result<Self, StorageError> { ) -> 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() let mut opts = sqlx::sqlite::SqliteConnectOptions::new()
.filename(database_path) .filename(database_path)
.create_if_missing(fresh); .create_if_missing(fresh);
@@ -22,11 +22,49 @@ mod error;
mod manager; mod manager;
mod models; 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)] #[derive(Debug)]
pub struct Backend { pub struct Backend {
temporary_old_path: Option<PathBuf>, temporary_old_path: Option<PathBuf>,
database_path: PathBuf, database_path: PathBuf,
manager: StorageManager, manager: StorageManagerState,
} }
impl Backend { impl Backend {
@@ -40,17 +78,32 @@ impl Backend {
}); });
} }
let manager = StorageManager::init(database_path, true).await?;
manager.create_status_table().await?;
let backend = Backend { let backend = Backend {
temporary_old_path: None, temporary_old_path: None,
database_path: owned_path, database_path: owned_path,
manager: StorageManager::init(database_path, true).await?, manager: StorageManagerState::Storage(manager),
}; };
backend.manager.create_status_table().await?;
Ok(backend) 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> { pub async fn try_load<P: AsRef<Path>>(database_path: P) -> Result<Self, StorageError> {
let owned_path: PathBuf = database_path.as_ref().into(); let owned_path: PathBuf = database_path.as_ref().into();
if owned_path.file_name().is_none() { if owned_path.file_name().is_none() {
@@ -119,12 +172,12 @@ impl Backend {
Ok(Backend { Ok(Backend {
temporary_old_path: None, temporary_old_path: None,
database_path: owned_path, database_path: owned_path,
manager, manager: StorageManagerState::Storage(manager),
}) })
} }
async fn close_pool(&mut self) { 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> { async fn rotate(&mut self) -> Result<(), StorageError> {
@@ -143,8 +196,9 @@ impl Backend {
fs::rename(&self.database_path, &temp_old) fs::rename(&self.database_path, &temp_old)
.map_err(|err| StorageError::DatabaseRenameError { source: err })?; .map_err(|err| StorageError::DatabaseRenameError { source: err })?;
self.manager = StorageManager::init(&self.database_path, true).await?; self.manager =
self.manager.create_status_table().await?; StorageManagerState::Storage(StorageManager::init(&self.database_path, true).await?);
self.manager.get_mut().create_status_table().await?;
self.temporary_old_path = Some(temp_old); self.temporary_old_path = Some(temp_old);
Ok(()) Ok(())
@@ -161,26 +215,27 @@ impl Backend {
} }
async fn start_storage_flush(&self) -> Result<(), StorageError> { 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> { async fn end_storage_flush(&self) -> Result<(), StorageError> {
self.manager self.manager
.get()
.set_previous_flush_timestamp(OffsetDateTime::now_utc().unix_timestamp()) .set_previous_flush_timestamp(OffsetDateTime::now_utc().unix_timestamp())
.await?; .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> { 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> { 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> { 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, // 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 // 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() { for map_ref in tags.as_raw_iter() {
let (recipient, tag) = map_ref.pair(); let (recipient, tag) = map_ref.pair();
self.manager self.manager
.get()
.insert_tag(StoredSenderTag::new(*recipient, *tag)) .insert_tag(StoredSenderTag::new(*recipient, *tag))
.await?; .await?;
} }
@@ -203,7 +259,7 @@ impl Backend {
} }
async fn get_stored_reply_keys(&self) -> Result<SentReplyKeys, StorageError> { 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, // 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 // 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() { for map_ref in reply_keys.as_raw_iter() {
let (digest, key) = map_ref.pair(); let (digest, key) = map_ref.pair();
self.manager self.manager
.get()
.insert_reply_key(StoredReplyKey::new(*digest, *key)) .insert_reply_key(StoredReplyKey::new(*digest, *key))
.await?; .await?;
} }
@@ -226,7 +283,7 @@ impl Backend {
} }
async fn get_stored_reply_surbs(&self) -> Result<ReceivedReplySurbsMap, StorageError> { 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 metadata = self.get_reply_surb_storage_metadata().await?;
let mut received_surbs = Vec::with_capacity(surb_senders.len()); let mut received_surbs = Vec::with_capacity(surb_senders.len());
@@ -236,6 +293,7 @@ impl Backend {
sender.try_into()?; sender.try_into()?;
let stored_surbs = self let stored_surbs = self
.manager .manager
.get()
.get_reply_surbs(sender_id) .get_reply_surbs(sender_id)
.await? .await?
.into_iter() .into_iter()
@@ -263,6 +321,7 @@ impl Backend {
let (tag, received_surbs) = map_ref.pair(); let (tag, received_surbs) = map_ref.pair();
let sender_id = self let sender_id = self
.manager .manager
.get()
.insert_surb_sender(StoredSurbSender::new( .insert_surb_sender(StoredSurbSender::new(
*tag, *tag,
received_surbs.surbs_last_received_at(), received_surbs.surbs_last_received_at(),
@@ -271,6 +330,7 @@ impl Backend {
for reply_surb in received_surbs.surbs_ref() { for reply_surb in received_surbs.surbs_ref() {
self.manager self.manager
.get()
.insert_reply_surb(StoredReplySurb::new(sender_id, reply_surb)) .insert_reply_surb(StoredReplySurb::new(sender_id, reply_surb))
.await? .await?
} }
@@ -282,6 +342,7 @@ impl Backend {
&self, &self,
) -> Result<ReplySurbStorageMetadata, StorageError> { ) -> Result<ReplySurbStorageMetadata, StorageError> {
self.manager self.manager
.get()
.get_reply_surb_storage_metadata() .get_reply_surb_storage_metadata()
.await .await
.map_err(Into::into) .map_err(Into::into)
@@ -292,6 +353,7 @@ impl Backend {
reply_surbs: &ReceivedReplySurbsMap, reply_surbs: &ReceivedReplySurbsMap,
) -> Result<(), StorageError> { ) -> Result<(), StorageError> {
self.manager self.manager
.get()
.insert_reply_surb_storage_metadata(ReplySurbStorageMetadata::new( .insert_reply_surb_storage_metadata(ReplySurbStorageMetadata::new(
reply_surbs.min_surb_threshold(), reply_surbs.min_surb_threshold(),
reply_surbs.max_surb_threshold(), reply_surbs.max_surb_threshold(),
@@ -305,6 +367,10 @@ impl Backend {
impl ReplyStorageBackend for Backend { impl ReplyStorageBackend for Backend {
type StorageError = error::StorageError; type StorageError = error::StorageError;
fn is_active(&self) -> bool {
self.manager.is_active()
}
async fn start_storage_session(&self) -> Result<(), Self::StorageError> { async fn start_storage_session(&self) -> Result<(), Self::StorageError> {
self.start_client_use().await self.start_client_use().await
} }
@@ -342,6 +408,18 @@ impl ReplyStorageBackend for Backend {
Ok(CombinedReplyStorage::load(reply_keys, reply_surbs, tags)) 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> { async fn stop_storage_session(self) -> Result<(), Self::StorageError> {
self.stop_client_use().await self.stop_client_use().await
} }
@@ -44,8 +44,7 @@ impl TryFrom<StoredSenderTag> for (RecipientBytes, AnonymousSenderTag) {
let Ok(sender_tag_bytes) = value.tag.try_into() else { let Ok(sender_tag_bytes) = value.tag.try_into() else {
return Err(StorageError::CorruptedData { return Err(StorageError::CorruptedData {
details: format!( details: format!(
"the retrieved sender tag has length of {tag_len} while {} was expected", "the retrieved sender tag has length of {tag_len} while {SENDER_TAG_SIZE} was expected",
SENDER_TAG_SIZE
), ),
}); });
}; };
@@ -132,8 +131,7 @@ impl TryFrom<StoredSurbSender> for (AnonymousSenderTag, i64) {
let Ok(sender_tag_bytes) = value.tag.try_into() else { let Ok(sender_tag_bytes) = value.tag.try_into() else {
return Err(StorageError::CorruptedData { return Err(StorageError::CorruptedData {
details: format!( details: format!(
"the retrieved sender tag has length of {tag_len} while {} was expected", "the retrieved sender tag has length of {tag_len} while {SENDER_TAG_SIZE} was expected",
SENDER_TAG_SIZE
), ),
}); });
}; };
@@ -19,10 +19,11 @@ pub mod fs_backend;
#[error("no information provided")] #[error("no information provided")]
pub struct UndefinedError; pub struct UndefinedError;
#[derive(Debug)]
pub struct Empty { pub struct Empty {
// we need to keep 'basic' metadata here to "load" the CombinedReplyStorage // we need to keep 'basic' metadata here to "load" the CombinedReplyStorage
min_surb_threshold: usize, pub min_surb_threshold: usize,
max_surb_threshold: usize, pub max_surb_threshold: usize,
} }
#[async_trait] #[async_trait]
@@ -49,12 +50,23 @@ impl ReplyStorageBackend for Empty {
self.max_surb_threshold, 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] #[async_trait]
pub trait ReplyStorageBackend: Sized { pub trait ReplyStorageBackend: Sized {
type StorageError: Error + 'static; type StorageError: Error + 'static;
fn is_active(&self) -> bool {
true
}
async fn start_storage_session(&self) -> Result<(), Self::StorageError> { async fn start_storage_session(&self) -> Result<(), Self::StorageError> {
Ok(()) Ok(())
} }
@@ -72,6 +84,11 @@ pub trait ReplyStorageBackend: Sized {
async fn load_surb_storage(&self) -> Result<CombinedReplyStorage, Self::StorageError>; 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> { async fn stop_storage_session(self) -> Result<(), Self::StorageError> {
Ok(()) Ok(())
} }
@@ -37,7 +37,7 @@ where
pub async fn flush_on_shutdown( pub async fn flush_on_shutdown(
mut self, mut self,
mem_state: CombinedReplyStorage, mem_state: CombinedReplyStorage,
mut shutdown: task::ShutdownListener, mut shutdown: task::TaskClient,
) { ) {
use log::{debug, error, info, warn}; use log::{debug, error, info, warn};
@@ -136,19 +136,15 @@ impl Default for TopologyAccessor {
} }
pub struct TopologyRefresherConfig { pub struct TopologyRefresherConfig {
validator_api_urls: Vec<Url>, nym_api_urls: Vec<Url>,
refresh_rate: Duration, refresh_rate: Duration,
client_version: String, client_version: String,
} }
impl TopologyRefresherConfig { impl TopologyRefresherConfig {
pub fn new( pub fn new(nym_api_urls: Vec<Url>, refresh_rate: Duration, client_version: String) -> Self {
validator_api_urls: Vec<Url>,
refresh_rate: Duration,
client_version: String,
) -> Self {
TopologyRefresherConfig { TopologyRefresherConfig {
validator_api_urls, nym_api_urls,
refresh_rate, refresh_rate,
client_version, client_version,
} }
@@ -156,10 +152,10 @@ impl TopologyRefresherConfig {
} }
pub struct TopologyRefresher { pub struct TopologyRefresher {
validator_client: validator_client::client::ApiClient, validator_client: validator_client::client::NymApiClient,
client_version: String, client_version: String,
validator_api_urls: Vec<Url>, nym_api_urls: Vec<Url>,
topology_accessor: TopologyAccessor, topology_accessor: TopologyAccessor,
refresh_rate: Duration, refresh_rate: Duration,
@@ -169,14 +165,14 @@ pub struct TopologyRefresher {
impl TopologyRefresher { impl TopologyRefresher {
pub fn new(mut cfg: TopologyRefresherConfig, topology_accessor: TopologyAccessor) -> Self { pub fn new(mut cfg: TopologyRefresherConfig, topology_accessor: TopologyAccessor) -> Self {
cfg.validator_api_urls.shuffle(&mut thread_rng()); cfg.nym_api_urls.shuffle(&mut thread_rng());
TopologyRefresher { TopologyRefresher {
validator_client: validator_client::client::ApiClient::new( validator_client: validator_client::client::NymApiClient::new(
cfg.validator_api_urls[0].clone(), cfg.nym_api_urls[0].clone(),
), ),
client_version: cfg.client_version, client_version: cfg.client_version,
validator_api_urls: cfg.validator_api_urls, nym_api_urls: cfg.nym_api_urls,
topology_accessor, topology_accessor,
refresh_rate: cfg.refresh_rate, refresh_rate: cfg.refresh_rate,
currently_used_api: 0, currently_used_api: 0,
@@ -184,15 +180,15 @@ impl TopologyRefresher {
} }
} }
fn use_next_validator_api(&mut self) { fn use_next_nym_api(&mut self) {
if self.validator_api_urls.len() == 1 { if self.nym_api_urls.len() == 1 {
warn!("There's only a single validator API available - it won't be possible to use a different one"); warn!("There's only a single nym API available - it won't be possible to use a different one");
return; return;
} }
self.currently_used_api = (self.currently_used_api + 1) % self.validator_api_urls.len(); self.currently_used_api = (self.currently_used_api + 1) % self.nym_api_urls.len();
self.validator_client self.validator_client
.change_validator_api(self.validator_api_urls[self.currently_used_api].clone()) .change_nym_api(self.nym_api_urls[self.currently_used_api].clone())
} }
/// Verifies whether nodes a reasonably distributed among all mix layers. /// Verifies whether nodes a reasonably distributed among all mix layers.
@@ -288,7 +284,7 @@ impl TopologyRefresher {
let new_topology = self.get_current_compatible_topology().await; let new_topology = self.get_current_compatible_topology().await;
if new_topology.is_none() { if new_topology.is_none() {
self.use_next_validator_api(); self.use_next_nym_api();
} }
if new_topology.is_none() && self.was_latest_valid { if new_topology.is_none() && self.was_latest_valid {
@@ -310,7 +306,7 @@ impl TopologyRefresher {
self.topology_accessor.ensure_is_routable().await self.topology_accessor.ensure_is_routable().await
} }
pub fn start_with_shutdown(mut self, mut shutdown: task::ShutdownListener) { pub fn start_with_shutdown(mut self, mut shutdown: task::TaskClient) {
spawn_future(async move { spawn_future(async move {
debug!("Started TopologyRefresher with graceful shutdown support"); debug!("Started TopologyRefresher with graceful shutdown support");
@@ -1,38 +1,57 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net> // Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use crate::client::helpers::{get_time_now, Instant};
use crate::client::real_messages_control::real_traffic_stream::RealMessage;
use client_connections::TransmissionLane; use client_connections::TransmissionLane;
use nymsphinx::chunking::fragment::Fragment;
use rand::{seq::SliceRandom, Rng}; use rand::{seq::SliceRandom, Rng};
use std::{ use std::{
collections::{HashMap, HashSet, VecDeque}, collections::{HashMap, HashSet, VecDeque},
time::Duration, time::Duration,
}; };
#[cfg(not(target_arch = "wasm32"))]
use tokio::time;
#[cfg(target_arch = "wasm32")]
use wasm_timer;
use super::{get_time_now, RealMessage};
// The number of lanes included in the oldest set. Used when we need to prioritize traffic. // The number of lanes included in the oldest set. Used when we need to prioritize traffic.
const OLDEST_LANE_SET_SIZE: usize = 4; const OLDEST_LANE_SET_SIZE: usize = 4;
// As a way of prune connections we also check for timeouts. // As a way of prune connections we also check for timeouts.
const MSG_CONSIDERED_STALE_AFTER_SECS: u64 = 10 * 60; const MSG_CONSIDERED_STALE_AFTER_SECS: u64 = 10 * 60;
#[derive(Default)] pub(crate) trait SizedData {
pub(crate) struct TransmissionBuffer { fn data_size(&self) -> usize;
buffer: HashMap<TransmissionLane, LaneBufferEntry>,
} }
impl TransmissionBuffer { impl SizedData for RealMessage {
fn data_size(&self) -> usize {
self.packet_size()
}
}
impl SizedData for Fragment {
fn data_size(&self) -> usize {
// note that raw `Fragment` is smaller than sphinx packet payload
// as it doesn't include surb-ack or the [shared] key materials
self.payload_size()
}
}
#[derive(Default)]
pub(crate) struct TransmissionBuffer<T> {
buffer: HashMap<TransmissionLane, LaneBufferEntry<T>>,
}
impl<T> TransmissionBuffer<T> {
pub(crate) fn new() -> Self {
TransmissionBuffer {
buffer: HashMap::new(),
}
}
#[allow(unused)] #[allow(unused)]
pub(crate) fn is_empty(&self) -> bool { pub(crate) fn is_empty(&self) -> bool {
self.buffer.is_empty() self.buffer.is_empty()
} }
pub(crate) fn remove(&mut self, lane: &TransmissionLane) -> Option<LaneBufferEntry> { pub(crate) fn remove(&mut self, lane: &TransmissionLane) -> Option<LaneBufferEntry<T>> {
self.buffer.remove(lane) self.buffer.remove(lane)
} }
@@ -57,20 +76,22 @@ impl TransmissionBuffer {
.collect() .collect()
} }
#[cfg(not(target_arch = "wasm32"))]
pub(crate) fn total_size(&self) -> usize { pub(crate) fn total_size(&self) -> usize {
self.buffer.values().map(LaneBufferEntry::len).sum() self.buffer.values().map(LaneBufferEntry::len).sum()
} }
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
pub(crate) fn total_size_in_bytes(&self) -> usize { pub(crate) fn total_size_in_bytes(&self) -> usize
where
T: SizedData,
{
self.buffer self.buffer
.values() .values()
.map(|lane_buffer_entry| { .map(|lane_buffer_entry| {
lane_buffer_entry lane_buffer_entry
.real_messages .items
.iter() .iter()
.map(|real_message| real_message.mix_packet.sphinx_packet().len()) .map(|item| item.data_size())
.sum::<usize>() .sum::<usize>()
}) })
.sum() .sum()
@@ -92,42 +113,51 @@ impl TransmissionBuffer {
.collect() .collect()
} }
pub(crate) fn store(&mut self, lane: &TransmissionLane, real_messages: Vec<RealMessage>) { pub(crate) fn store<I: IntoIterator<Item = T>>(&mut self, lane: &TransmissionLane, items: I) {
if let Some(lane_buffer_entry) = self.buffer.get_mut(lane) { if let Some(lane_buffer_entry) = self.buffer.get_mut(lane) {
lane_buffer_entry.append(real_messages); lane_buffer_entry.extend(items);
} else { } else {
self.buffer self.buffer
.insert(*lane, LaneBufferEntry::new(real_messages)); .insert(*lane, LaneBufferEntry::new(items.into_iter().collect()));
} }
} }
fn pick_random_lane(&self) -> Option<&TransmissionLane> { pub(crate) fn store_multiple(&mut self, items: Vec<(TransmissionLane, T)>) {
let lanes: Vec<&TransmissionLane> = self.buffer.keys().collect(); for (lane, item) in items {
lanes.choose(&mut rand::thread_rng()).copied() self.buffer
.entry(lane)
.or_insert_with(LaneBufferEntry::new_empty)
.push_item(item)
}
} }
fn pick_random_small_lane(&self) -> Option<&TransmissionLane> { fn pick_random_lane<R: Rng + ?Sized>(&self, rng: &mut R) -> Option<&TransmissionLane> {
let lanes: Vec<&TransmissionLane> = self.buffer.keys().collect();
lanes.choose(rng).copied()
}
fn pick_random_small_lane<R: Rng + ?Sized>(&self, rng: &mut R) -> Option<&TransmissionLane> {
let lanes: Vec<&TransmissionLane> = self let lanes: Vec<&TransmissionLane> = self
.buffer .buffer
.iter() .iter()
.filter(|(_, v)| v.is_small()) .filter(|(_, v)| v.is_small())
.map(|(k, _)| k) .map(|(k, _)| k)
.collect(); .collect();
lanes.choose(&mut rand::thread_rng()).copied() lanes.choose(rng).copied()
} }
// 2/3 chance to pick from the old lanes // 2/3 chance to pick from the old lanes
fn pick_random_old_lane(&self) -> Option<TransmissionLane> { fn pick_random_old_lane<R: Rng + ?Sized>(&self, rng: &mut R) -> Option<TransmissionLane> {
let rand = &mut rand::thread_rng(); let rand = &mut rand::thread_rng();
if rand.gen_ratio(2, 3) { if rand.gen_ratio(2, 3) {
let lanes = self.get_oldest_set(); let lanes = self.get_oldest_set();
lanes.choose(rand).copied() lanes.choose(rand).copied()
} else { } else {
self.pick_random_lane().copied() self.pick_random_lane(rng).copied()
} }
} }
fn pop_front_from_lane(&mut self, lane: &TransmissionLane) -> Option<RealMessage> { fn pop_front_from_lane(&mut self, lane: &TransmissionLane) -> Option<T> {
let real_msgs_queued = self.buffer.get_mut(lane)?; let real_msgs_queued = self.buffer.get_mut(lane)?;
let real_next = real_msgs_queued.pop_front()?; let real_next = real_msgs_queued.pop_front()?;
real_msgs_queued.messages_transmitted += 1; real_msgs_queued.messages_transmitted += 1;
@@ -137,19 +167,48 @@ impl TransmissionBuffer {
Some(real_next) Some(real_next)
} }
pub(crate) fn pop_next_message_at_random(&mut self) -> Option<(TransmissionLane, RealMessage)> { pub(crate) fn pop_at_most_n_next_messages_at_random(
&mut self,
n: usize,
) -> Option<Vec<(TransmissionLane, T)>> {
// let start = Instant::now();
if self.buffer.is_empty() {
return None;
}
let rng = &mut rand::thread_rng();
let mut items = Vec::with_capacity(n);
while items.len() < n {
let Some(next) = self.pop_next_message_at_random(rng) else {
break
};
items.push(next)
}
// todo!("time time taken");
Some(items)
}
pub(crate) fn pop_next_message_at_random<R: Rng + ?Sized>(
&mut self,
// turns out the caller always have access to some rng, so no point in instantiating new one
rng: &mut R,
) -> Option<(TransmissionLane, T)> {
if self.buffer.is_empty() { if self.buffer.is_empty() {
return None; return None;
} }
// Very basic heuristic where we prioritize according to small lanes first, the older lanes // Very basic heuristic where we prioritize according to small lanes first, the older lanes
// to try to finish lanes when possible, then the rest. // to try to finish lanes when possible, then the rest.
let lane = if let Some(small_lane) = self.pick_random_small_lane() { let lane = if let Some(small_lane) = self.pick_random_small_lane(rng) {
*small_lane *small_lane
} else if let Some(old_lane) = self.pick_random_old_lane() { } else if let Some(old_lane) = self.pick_random_old_lane(rng) {
old_lane old_lane
} else { } else {
*self.pick_random_lane()? *self.pick_random_lane(rng)?
}; };
let msg = self.pop_front_from_lane(&lane)?; let msg = self.pop_front_from_lane(&lane)?;
@@ -171,35 +230,46 @@ impl TransmissionBuffer {
} }
} }
pub(crate) struct LaneBufferEntry { pub(crate) struct LaneBufferEntry<T> {
pub real_messages: VecDeque<RealMessage>, pub items: VecDeque<T>,
pub messages_transmitted: usize, pub messages_transmitted: usize,
#[cfg(not(target_arch = "wasm32"))] pub time_for_last_activity: Instant,
pub time_for_last_activity: time::Instant,
#[cfg(target_arch = "wasm32")]
pub time_for_last_activity: wasm_timer::Instant,
} }
impl LaneBufferEntry { impl<T> LaneBufferEntry<T> {
fn new(real_messages: Vec<RealMessage>) -> Self { fn new_empty() -> Self {
LaneBufferEntry { LaneBufferEntry {
real_messages: real_messages.into(), items: VecDeque::new(),
messages_transmitted: 0, messages_transmitted: 0,
time_for_last_activity: get_time_now(), time_for_last_activity: get_time_now(),
} }
} }
fn append(&mut self, real_messages: Vec<RealMessage>) { fn new(items: VecDeque<T>) -> Self {
self.real_messages.append(&mut real_messages.into()); LaneBufferEntry {
items,
messages_transmitted: 0,
time_for_last_activity: get_time_now(),
}
}
fn push_item(&mut self, item: T) {
self.items.push_back(item);
// I'm not updating time here on purpose. This method is called just after `new_empty`,
// where the time is already set. Furthermore, this method is called there multiple times at once
}
fn extend<I: IntoIterator<Item = T>>(&mut self, items: I) {
self.items.extend(items);
self.time_for_last_activity = get_time_now(); self.time_for_last_activity = get_time_now();
} }
fn pop_front(&mut self) -> Option<RealMessage> { fn pop_front(&mut self) -> Option<T> {
self.real_messages.pop_front() self.items.pop_front()
} }
fn is_small(&self) -> bool { fn is_small(&self) -> bool {
self.real_messages.len() < 100 self.items.len() < 100
} }
fn is_stale(&self) -> bool { fn is_stale(&self) -> bool {
@@ -208,10 +278,10 @@ impl LaneBufferEntry {
} }
fn len(&self) -> usize { fn len(&self) -> usize {
self.real_messages.len() self.items.len()
} }
fn is_empty(&self) -> bool { fn is_empty(&self) -> bool {
self.real_messages.is_empty() self.items.is_empty()
} }
} }
+93 -29
View File
@@ -1,7 +1,8 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net> // Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use config::{NymConfig, DB_FILE_NAME}; use config::defaults::NymNetworkDetails;
use config::{NymConfig, OptionalSet, DB_FILE_NAME};
use nymsphinx::params::PacketSize; use nymsphinx::params::PacketSize;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::marker::PhantomData; use std::marker::PhantomData;
@@ -44,7 +45,8 @@ const DEFAULT_MAXIMUM_REPLY_SURB_REQUEST_SIZE: u32 = 100;
const DEFAULT_MAXIMUM_ALLOWED_SURB_REQUEST_SIZE: u32 = 500; 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 // 12 hours
const DEFAULT_MAXIMUM_REPLY_SURB_AGE: Duration = Duration::from_secs(12 * 60 * 60); const DEFAULT_MAXIMUM_REPLY_SURB_AGE: Duration = Duration::from_secs(12 * 60 * 60);
@@ -70,12 +72,15 @@ pub struct Config<T> {
#[serde(default)] #[serde(default)]
debug: DebugConfig, debug: DebugConfig,
} }
impl<T> ClientCoreConfigTrait for Config<T> { impl<T> ClientCoreConfigTrait for Config<T> {
fn get_gateway_endpoint(&self) -> &GatewayEndpointConfig { fn get_gateway_endpoint(&self) -> &GatewayEndpointConfig {
&self.client.gateway_endpoint &self.client.gateway_endpoint
} }
} }
impl<T> OptionalSet for Config<T> where T: NymConfig {}
impl<T> Config<T> { impl<T> Config<T> {
pub fn new<S: Into<String>>(id: S) -> Self pub fn new<S: Into<String>>(id: S) -> Self
where where
@@ -84,6 +89,7 @@ impl<T> Config<T> {
Config::default().with_id(id) Config::default().with_id(id)
} }
#[must_use]
pub fn with_id<S: Into<String>>(mut self, id: S) -> Self pub fn with_id<S: Into<String>>(mut self, id: S) -> Self
where where
T: NymConfig, T: NymConfig,
@@ -160,24 +166,47 @@ impl<T> Config<T> {
changes_made changes_made
} }
pub fn with_disabled_credentials(&mut self, disabled_credentials_mode: bool) { pub fn with_disabled_credentials(mut self, disabled_credentials_mode: bool) -> Self {
self.client.disabled_credentials_mode = disabled_credentials_mode; self.client.disabled_credentials_mode = disabled_credentials_mode;
self
} }
pub fn with_gateway_endpoint(&mut self, gateway_endpoint: GatewayEndpointConfig) { pub fn set_gateway_endpoint(&mut self, gateway_endpoint: GatewayEndpointConfig) {
self.client.gateway_endpoint = gateway_endpoint; self.client.gateway_endpoint = gateway_endpoint;
} }
pub fn with_gateway_endpoint(mut self, gateway_endpoint: GatewayEndpointConfig) -> Self {
self.client.gateway_endpoint = gateway_endpoint;
self
}
pub fn with_gateway_id<S: Into<String>>(&mut self, id: S) { pub fn with_gateway_id<S: Into<String>>(&mut self, id: S) {
self.client.gateway_endpoint.gateway_id = id.into(); self.client.gateway_endpoint.gateway_id = id.into();
} }
pub fn set_custom_validators(&mut self, validator_urls: Vec<Url>) { pub fn with_custom_nyxd(mut self, urls: Vec<Url>) -> Self {
self.client.validator_urls = validator_urls; self.client.nyxd_urls = urls;
self
} }
pub fn set_custom_validator_apis(&mut self, validator_api_urls: Vec<Url>) { pub fn set_custom_nyxd(&mut self, nyxd_urls: Vec<Url>) {
self.client.validator_api_urls = validator_api_urls; self.client.nyxd_urls = nyxd_urls;
}
pub fn with_custom_nym_apis(mut self, nym_api_urls: Vec<Url>) -> Self {
self.client.nym_api_urls = nym_api_urls;
self
}
pub fn set_custom_nym_apis(&mut self, nym_api_urls: Vec<Url>) {
self.client.nym_api_urls = nym_api_urls;
}
pub fn with_high_default_traffic_volume(mut self, enabled: bool) -> Self {
if enabled {
self.set_high_default_traffic_volume();
}
self
} }
pub fn set_high_default_traffic_volume(&mut self) { pub fn set_high_default_traffic_volume(&mut self) {
@@ -188,6 +217,13 @@ impl<T> Config<T> {
self.debug.message_sending_average_delay = Duration::from_millis(4); self.debug.message_sending_average_delay = Duration::from_millis(4);
} }
pub fn with_disabled_cover_traffic(mut self, disabled: bool) -> Self {
if disabled {
self.set_no_cover_traffic()
}
self
}
pub fn set_no_cover_traffic(&mut self) { pub fn set_no_cover_traffic(&mut self) {
self.debug.disable_loop_cover_traffic_stream = true; self.debug.disable_loop_cover_traffic_stream = true;
self.debug.disable_main_poisson_packet_distribution = true; self.debug.disable_main_poisson_packet_distribution = true;
@@ -234,11 +270,11 @@ impl<T> Config<T> {
} }
pub fn get_validator_endpoints(&self) -> Vec<Url> { pub fn get_validator_endpoints(&self) -> Vec<Url> {
self.client.validator_urls.clone() self.client.nyxd_urls.clone()
} }
pub fn get_validator_api_endpoints(&self) -> Vec<Url> { pub fn get_nym_api_endpoints(&self) -> Vec<Url> {
self.client.validator_api_urls.clone() self.client.nym_api_urls.clone()
} }
pub fn get_gateway_id(&self) -> String { pub fn get_gateway_id(&self) -> String {
@@ -342,8 +378,12 @@ impl<T> Config<T> {
self.debug.maximum_allowed_reply_surb_request_size self.debug.maximum_allowed_reply_surb_request_size
} }
pub fn get_maximum_reply_surb_waiting_period(&self) -> Duration { pub fn get_maximum_reply_surb_rerequest_waiting_period(&self) -> Duration {
self.debug.maximum_reply_surb_waiting_period 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 { pub fn get_maximum_reply_surb_age(&self) -> Duration {
@@ -420,12 +460,13 @@ pub struct Client<T> {
#[serde(default)] #[serde(default)]
disabled_credentials_mode: bool, disabled_credentials_mode: bool,
/// Addresses to nymd validators via which the client can communicate with the chain. /// Addresses to nyxd validators via which the client can communicate with the chain.
#[serde(default)] #[serde(alias = "validator_urls")]
validator_urls: Vec<Url>, nyxd_urls: Vec<Url>,
/// Addresses to APIs running on validator from which the client gets the view of the network. /// Addresses to APIs running on validator from which the client gets the view of the network.
validator_api_urls: Vec<Url>, #[serde(alias = "validator_api_urls")]
nym_api_urls: Vec<Url>,
/// Path to file containing private identity key. /// Path to file containing private identity key.
private_identity_key_file: PathBuf, private_identity_key_file: PathBuf,
@@ -470,13 +511,29 @@ pub struct Client<T> {
impl<T: NymConfig> Default for Client<T> { impl<T: NymConfig> Default for Client<T> {
fn default() -> Self { fn default() -> Self {
let network = NymNetworkDetails::new_mainnet();
let nyxd_urls = network
.endpoints
.iter()
.map(|validator| validator.nyxd_url())
.collect();
let nym_api_urls = network
.endpoints
.iter()
.filter_map(|validator| validator.api_url())
.collect::<Vec<_>>();
if nym_api_urls.is_empty() {
panic!("we do not have any default nym-api urls available!")
}
// there must be explicit checks for whether id is not empty later // there must be explicit checks for whether id is not empty later
Client { Client {
version: env!("CARGO_PKG_VERSION").to_string(), version: env!("CARGO_PKG_VERSION").to_string(),
id: "".to_string(), id: "".to_string(),
disabled_credentials_mode: true, disabled_credentials_mode: true,
validator_urls: vec![], nyxd_urls,
validator_api_urls: vec![], nym_api_urls,
private_identity_key_file: Default::default(), private_identity_key_file: Default::default(),
public_identity_key_file: Default::default(), public_identity_key_file: Default::default(),
private_encryption_key_file: Default::default(), private_encryption_key_file: Default::default(),
@@ -494,35 +551,35 @@ impl<T: NymConfig> Default for Client<T> {
impl<T: NymConfig> Client<T> { impl<T: NymConfig> Client<T> {
fn default_private_identity_key_file(id: &str) -> PathBuf { 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 { 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 { 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 { 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 { 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 { 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 { 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 { 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)
} }
} }
@@ -616,7 +673,12 @@ pub struct DebugConfig {
/// Defines maximum amount of time the client is going to wait for reply surbs before explicitly asking /// 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. /// for more even though in theory they wouldn't need to.
#[serde(with = "humantime_serde")] #[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. /// 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. /// This is going to be superseded by key rotation once implemented.
@@ -657,7 +719,9 @@ impl Default for DebugConfig {
minimum_reply_surb_request_size: DEFAULT_MINIMUM_REPLY_SURB_REQUEST_SIZE, minimum_reply_surb_request_size: DEFAULT_MINIMUM_REPLY_SURB_REQUEST_SIZE,
maximum_reply_surb_request_size: DEFAULT_MAXIMUM_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_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_surb_age: DEFAULT_MAXIMUM_REPLY_SURB_AGE,
maximum_reply_key_age: DEFAULT_MAXIMUM_REPLY_KEY_AGE, maximum_reply_key_age: DEFAULT_MAXIMUM_REPLY_KEY_AGE,
} }
@@ -7,12 +7,12 @@ use std::path::{Path, PathBuf};
#[derive(Debug)] #[derive(Debug)]
pub struct ClientKeyPathfinder { pub struct ClientKeyPathfinder {
identity_private_key: PathBuf, pub identity_private_key: PathBuf,
identity_public_key: PathBuf, pub identity_public_key: PathBuf,
encryption_private_key: PathBuf, pub encryption_private_key: PathBuf,
encryption_public_key: PathBuf, pub encryption_public_key: PathBuf,
gateway_shared_key: PathBuf, pub gateway_shared_key: PathBuf,
ack_key: PathBuf, pub ack_key: PathBuf,
} }
impl ClientKeyPathfinder { impl ClientKeyPathfinder {
@@ -22,8 +22,8 @@ impl ClientKeyPathfinder {
ClientKeyPathfinder { ClientKeyPathfinder {
identity_private_key: config_dir.join("private_identity.pem"), identity_private_key: config_dir.join("private_identity.pem"),
identity_public_key: config_dir.join("public_identity.pem"), identity_public_key: config_dir.join("public_identity.pem"),
encryption_private_key: config_dir.join("public_encryption.pem"), encryption_private_key: config_dir.join("private_encryption.pem"),
encryption_public_key: config_dir.join("private_encryption.pem"), encryption_public_key: config_dir.join("public_encryption.pem"),
gateway_shared_key: config_dir.join("gateway_shared.pem"), gateway_shared_key: config_dir.join("gateway_shared.pem"),
ack_key: config_dir.join("ack_key.pem"), ack_key: config_dir.join("ack_key.pem"),
} }
@@ -40,6 +40,28 @@ impl ClientKeyPathfinder {
} }
} }
pub fn any_file_exists(&self) -> bool {
matches!(self.identity_public_key.try_exists(), Ok(true))
|| matches!(self.identity_private_key.try_exists(), Ok(true))
|| matches!(self.encryption_public_key.try_exists(), Ok(true))
|| matches!(self.encryption_private_key.try_exists(), Ok(true))
|| matches!(self.gateway_shared_key.try_exists(), Ok(true))
|| matches!(self.ack_key.try_exists(), Ok(true))
}
pub fn any_file_exists_and_return(&self) -> Option<PathBuf> {
file_exists(&self.identity_public_key)
.or_else(|| file_exists(&self.identity_private_key))
.or_else(|| file_exists(&self.encryption_public_key))
.or_else(|| file_exists(&self.encryption_private_key))
.or_else(|| file_exists(&self.gateway_shared_key))
.or_else(|| file_exists(&self.ack_key))
}
pub fn gateway_key_file_exists(&self) -> bool {
matches!(self.gateway_shared_key.try_exists(), Ok(true))
}
pub fn private_identity_key(&self) -> &Path { pub fn private_identity_key(&self) -> &Path {
&self.identity_private_key &self.identity_private_key
} }
@@ -64,3 +86,10 @@ impl ClientKeyPathfinder {
&self.ack_key &self.ack_key
} }
} }
fn file_exists(path: &Path) -> Option<PathBuf> {
if matches!(path.try_exists(), Ok(true)) {
return Some(path.to_path_buf());
}
None
}
+11 -5
View File
@@ -1,14 +1,13 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net> // Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use crate::client::replies::reply_storage::ReplyStorageBackend;
use crypto::asymmetric::identity::Ed25519RecoveryError; use crypto::asymmetric::identity::Ed25519RecoveryError;
use gateway_client::error::GatewayClientError; use gateway_client::error::GatewayClientError;
use topology::NymTopologyError; use topology::NymTopologyError;
use validator_client::ValidatorClientError; use validator_client::ValidatorClientError;
#[derive(thiserror::Error, Debug)] #[derive(thiserror::Error, Debug)]
pub enum ClientCoreError<B: ReplyStorageBackend> { pub enum ClientCoreError {
#[error("I/O error: {0}")] #[error("I/O error: {0}")]
IoError(#[from] std::io::Error), IoError(#[from] std::io::Error),
@@ -30,8 +29,8 @@ pub enum ClientCoreError<B: ReplyStorageBackend> {
#[error("Failed to setup gateway")] #[error("Failed to setup gateway")]
FailedToSetupGateway, FailedToSetupGateway,
#[error("List of validator apis is empty")] #[error("List of nym apis is empty")]
ListOfValidatorApisIsEmpty, ListOfNymApisIsEmpty,
#[error("Could not load existing gateway configuration: {0}")] #[error("Could not load existing gateway configuration: {0}")]
CouldNotLoadExistingGatewayConfiguration(std::io::Error), CouldNotLoadExistingGatewayConfiguration(std::io::Error),
@@ -40,7 +39,9 @@ pub enum ClientCoreError<B: ReplyStorageBackend> {
InsufficientNetworkTopology(#[from] NymTopologyError), InsufficientNetworkTopology(#[from] NymTopologyError),
#[error("experienced a failure with our reply surb persistent storage: {source}")] #[error("experienced a failure with our reply surb persistent storage: {source}")]
SurbStorageError { source: B::StorageError }, SurbStorageError {
source: Box<dyn std::error::Error + Send + Sync>,
},
#[error("The gateway id is invalid - {0}")] #[error("The gateway id is invalid - {0}")]
UnableToCreatePublicKeyFromGatewayId(Ed25519RecoveryError), UnableToCreatePublicKeyFromGatewayId(Ed25519RecoveryError),
@@ -54,6 +55,9 @@ pub enum ClientCoreError<B: ReplyStorageBackend> {
#[error("The address of the gateway is unknown - did you run init?")] #[error("The address of the gateway is unknown - did you run init?")]
GatwayAddressUnknown, GatwayAddressUnknown,
#[error("failed to register receiver for reconstructed mixnet messages")]
FailedToRegisterReceiver,
#[error("Unexpected exit")] #[error("Unexpected exit")]
UnexpectedExit, UnexpectedExit,
} }
@@ -61,8 +65,10 @@ pub enum ClientCoreError<B: ReplyStorageBackend> {
/// Set of messages that the client can send to listeners via the task manager /// Set of messages that the client can send to listeners via the task manager
#[derive(thiserror::Error, Debug)] #[derive(thiserror::Error, Debug)]
pub enum ClientCoreStatusMessage { pub enum ClientCoreStatusMessage {
// NOTE: The nym-connect frontend listens for these strings, so don't change them until we have a more robust mechanism in place
#[error("The connected gateway is slow, or the connection to it is slow")] #[error("The connected gateway is slow, or the connection to it is slow")]
GatewayIsSlow, GatewayIsSlow,
// NOTE: The nym-connect frontend listens for these strings, so don't change them until we have a more robust mechanism in place
#[error("The connected gateway is very slow, or the connection to it is very slow")] #[error("The connected gateway is very slow, or the connection to it is very slow")]
GatewayIsVerySlow, GatewayIsVerySlow,
} }
+19 -31
View File
@@ -1,7 +1,6 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net> // Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use crate::client::replies::reply_storage::ReplyStorageBackend;
use crate::{ use crate::{
client::key_manager::KeyManager, client::key_manager::KeyManager,
config::{persistence::key_pathfinder::ClientKeyPathfinder, Config}, config::{persistence::key_pathfinder::ClientKeyPathfinder, Config},
@@ -9,27 +8,28 @@ use crate::{
}; };
use config::NymConfig; use config::NymConfig;
use crypto::asymmetric::identity; use crypto::asymmetric::identity;
#[cfg(target_arch = "wasm32")]
use gateway_client::wasm_mockups::SigningNyxdClient;
use gateway_client::GatewayClient; use gateway_client::GatewayClient;
use gateway_requests::registration::handshake::SharedKeys; use gateway_requests::registration::handshake::SharedKeys;
use rand::{rngs::OsRng, seq::SliceRandom, thread_rng}; use rand::{seq::SliceRandom, thread_rng};
use std::{sync::Arc, time::Duration}; use std::{sync::Arc, time::Duration};
use tap::TapFallible; use tap::TapFallible;
use topology::{filter::VersionFilterable, gateway}; use topology::{filter::VersionFilterable, gateway};
use url::Url; use url::Url;
#[cfg(not(target_arch = "wasm32"))]
use validator_client::nyxd::SigningNyxdClient;
pub(super) async fn query_gateway_details<B>( pub(super) async fn query_gateway_details(
validator_servers: Vec<Url>, validator_servers: Vec<Url>,
chosen_gateway_id: Option<String>, chosen_gateway_id: Option<identity::PublicKey>,
) -> Result<gateway::Node, ClientCoreError<B>> ) -> Result<gateway::Node, ClientCoreError> {
where let nym_api = validator_servers
B: ReplyStorageBackend,
{
let validator_api = validator_servers
.choose(&mut thread_rng()) .choose(&mut thread_rng())
.ok_or(ClientCoreError::ListOfValidatorApisIsEmpty)?; .ok_or(ClientCoreError::ListOfNymApisIsEmpty)?;
let validator_client = validator_client::client::ApiClient::new(validator_api.clone()); let validator_client = validator_client::client::NymApiClient::new(nym_api.clone());
log::trace!("Fetching list of gateways from: {}", validator_api); log::trace!("Fetching list of gateways from: {}", nym_api);
let gateways = validator_client.get_cached_gateways().await?; let gateways = validator_client.get_cached_gateways().await?;
let valid_gateways = gateways let valid_gateways = gateways
.into_iter() .into_iter()
@@ -44,7 +44,7 @@ where
if let Some(gateway_id) = chosen_gateway_id { if let Some(gateway_id) = chosen_gateway_id {
filtered_gateways filtered_gateways
.iter() .iter()
.find(|gateway| gateway.identity_key.to_base58_string() == gateway_id) .find(|gateway| gateway.identity_key == gateway_id)
.ok_or_else(|| ClientCoreError::NoGatewayWithId(gateway_id.to_string())) .ok_or_else(|| ClientCoreError::NoGatewayWithId(gateway_id.to_string()))
.cloned() .cloned()
} else { } else {
@@ -55,18 +55,14 @@ where
} }
} }
async fn register_with_gateway<B>( pub(super) async fn register_with_gateway(
gateway: &gateway::Node, gateway: &gateway::Node,
our_identity: Arc<identity::KeyPair>, our_identity: Arc<identity::KeyPair>,
) -> Result<Arc<SharedKeys>, ClientCoreError<B>> ) -> Result<Arc<SharedKeys>, ClientCoreError> {
where
B: ReplyStorageBackend,
{
let timeout = Duration::from_millis(1500); 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.clients_address(),
gateway.identity_key, gateway.identity_key,
gateway.owner.clone(),
our_identity.clone(), our_identity.clone(),
timeout, timeout,
); );
@@ -81,21 +77,13 @@ where
Ok(shared_keys) Ok(shared_keys)
} }
pub(super) async fn register_with_gateway_and_store_keys<T, B>( pub(super) fn store_keys<T>(
gateway_details: gateway::Node, key_manager: &KeyManager,
config: &Config<T>, config: &Config<T>,
) -> Result<(), ClientCoreError<B>> ) -> Result<(), ClientCoreError>
where where
T: NymConfig, T: NymConfig,
B: ReplyStorageBackend,
{ {
let mut rng = OsRng;
let mut key_manager = KeyManager::new(&mut rng);
let shared_keys =
register_with_gateway(&gateway_details, key_manager.identity_keypair()).await?;
key_manager.insert_gateway_shared_key(shared_keys);
let pathfinder = ClientKeyPathfinder::new_from_config(config); let pathfinder = ClientKeyPathfinder::new_from_config(config);
Ok(key_manager Ok(key_manager
.store_keys(&pathfinder) .store_keys(&pathfinder)
+93 -75
View File
@@ -6,24 +6,26 @@
use std::fmt::Display; use std::fmt::Display;
use nymsphinx::addressing::{clients::Recipient, nodes::NodeIdentity}; use nymsphinx::addressing::{clients::Recipient, nodes::NodeIdentity};
use rand::rngs::OsRng;
use serde::Serialize; use serde::Serialize;
use tap::TapFallible; use tap::TapFallible;
use config::NymConfig; use config::NymConfig;
use crypto::asymmetric::{encryption, identity}; use crypto::asymmetric::{encryption, identity};
use url::Url;
use crate::client::replies::reply_storage::ReplyStorageBackend; use crate::client::key_manager::KeyManager;
use crate::{ use crate::{
config::{ config::{
persistence::key_pathfinder::ClientKeyPathfinder, ClientCoreConfigTrait, Config, persistence::key_pathfinder::ClientKeyPathfinder, ClientCoreConfigTrait, Config,
GatewayEndpointConfig, GatewayEndpointConfig,
}, },
error::ClientCoreError, error::ClientCoreError,
init::helpers::{query_gateway_details, register_with_gateway_and_store_keys},
}; };
mod helpers; mod helpers;
/// Struct describing the results of the client initialization procedure.
#[derive(Debug, Serialize)] #[derive(Debug, Serialize)]
pub struct InitResults { pub struct InitResults {
version: String, version: String,
@@ -61,84 +63,93 @@ impl Display for InitResults {
} }
} }
/// Convenience function for setting up the gateway for a client. Depending on the arguments given /// Create a new set of client keys.
/// it will do the sensible thing. pub fn new_client_keys() -> KeyManager {
pub async fn setup_gateway<B, C, T>( let mut rng = OsRng;
KeyManager::new(&mut rng)
}
/// Authenticate and register with a gateway.
/// Either pick one at random by querying the available gateways from the nym-api, or use the
/// chosen one if it's among the available ones.
/// The shared key is added to the supplied `KeyManager` and the endpoint details are returned.
pub async fn register_with_gateway(
key_manager: &mut KeyManager,
nym_api_endpoints: Vec<Url>,
chosen_gateway_id: Option<identity::PublicKey>,
) -> Result<GatewayEndpointConfig, ClientCoreError> {
// Get the gateway details of the gateway we will use
let gateway = helpers::query_gateway_details(nym_api_endpoints, chosen_gateway_id).await?;
log::debug!("Querying gateway gives: {}", gateway);
let our_identity = key_manager.identity_keypair();
// Establish connection, authenticate and generate keys for talking with the gateway
let shared_keys = helpers::register_with_gateway(&gateway, our_identity).await?;
key_manager.insert_gateway_shared_key(shared_keys);
Ok(gateway.into())
}
/// Convenience function for setting up the gateway for a client given a `Config`. Depending on the
/// arguments given it will do the sensible thing. Either it will
///
/// a. Reuse existing gateway configuration from storage.
/// b. Create a new gateway configuration but keep existing keys. This assumes that the caller
/// knows what they are doing and that the keys match the requested gateway.
/// c. Create a new gateway configuration with a newly registered gateway and keys.
pub async fn setup_gateway_from_config<C, T>(
register_gateway: bool, register_gateway: bool,
user_chosen_gateway_id: Option<String>, user_chosen_gateway_id: Option<identity::PublicKey>,
config: &Config<T>, config: &Config<T>,
) -> Result<GatewayEndpointConfig, ClientCoreError<B>> ) -> Result<GatewayEndpointConfig, ClientCoreError>
where where
B: ReplyStorageBackend,
C: NymConfig + ClientCoreConfigTrait, C: NymConfig + ClientCoreConfigTrait,
T: NymConfig, T: NymConfig,
{ {
let id = config.get_id(); let id = config.get_id();
if register_gateway {
register_with_gateway(user_chosen_gateway_id, config).await // If we are not going to register gateway, and an explicitly chosed gateway is not passed in,
} else if let Some(user_chosen_gateway_id) = user_chosen_gateway_id { // load the existing configuration file
config_gateway_with_existing_keys(user_chosen_gateway_id, config).await if !register_gateway && user_chosen_gateway_id.is_none() {
} else { println!("Not registering gateway, will reuse existing config and keys");
reuse_existing_gateway_config::<B, C>(&id) return load_existing_gateway_config::<C>(&id);
} }
}
/// Get the gateway details by querying the validator-api. Either pick one at random or use // Else, we preceed by querying the nym-api
/// the chosen one if it's among the available ones.
/// Saves keys to disk, specified by the paths in `config`.
pub async fn register_with_gateway<B, T>(
user_chosen_gateway_id: Option<String>,
config: &Config<T>,
) -> Result<GatewayEndpointConfig, ClientCoreError<B>>
where
B: ReplyStorageBackend,
T: NymConfig,
{
println!("Configuring gateway");
let gateway = let gateway =
query_gateway_details(config.get_validator_api_endpoints(), user_chosen_gateway_id).await?; helpers::query_gateway_details(config.get_nym_api_endpoints(), user_chosen_gateway_id)
.await?;
log::debug!("Querying gateway gives: {}", gateway); log::debug!("Querying gateway gives: {}", gateway);
// Registering with gateway by setting up and writing shared keys to disk // If we are not registering, just return this and assume the caller has the keys already and
log::trace!("Registering gateway"); // wants to keep the,
register_with_gateway_and_store_keys(gateway.clone(), config).await?; if !register_gateway && user_chosen_gateway_id.is_some() {
println!("Saved all generated keys"); println!("Using gateway provided by user, keeping existing keys");
return Ok(gateway.into());
}
Ok(gateway.into()) // Create new keys and derive our identity
} let mut key_manager = new_client_keys();
let our_identity = key_manager.identity_keypair();
/// Set the gateway using the usual procedue of querying the validator-api, but don't register or // Establish connection, authenticate and generate keys for talking with the gateway
/// create any keys. println!("Registering with new gateway");
/// This assumes that the user knows what they are doing, and that the existing keys are valid for let shared_keys = helpers::register_with_gateway(&gateway, our_identity).await?;
/// the gateway being used key_manager.insert_gateway_shared_key(shared_keys);
pub async fn config_gateway_with_existing_keys<B, T>(
user_chosen_gateway_id: String, // Write all keys to storage and just return the gateway endpoint config. It is assumed that we
config: &Config<T>, // will load keys from storage when actually connecting.
) -> Result<GatewayEndpointConfig, ClientCoreError<B>> helpers::store_keys(&key_manager, config)?;
where
B: ReplyStorageBackend,
T: NymConfig,
{
println!("Using gateway provided by user, keeping existing keys");
let gateway = query_gateway_details(
config.get_validator_api_endpoints(),
Some(user_chosen_gateway_id),
)
.await?;
log::debug!("Querying gateway gives: {}", gateway);
Ok(gateway.into()) Ok(gateway.into())
} }
/// Read and reuse the existing gateway configuration from a file that was generate earlier. /// Read and reuse the existing gateway configuration from a file that was generate earlier.
pub fn reuse_existing_gateway_config<B, T>( pub fn load_existing_gateway_config<T>(id: &str) -> Result<GatewayEndpointConfig, ClientCoreError>
id: &str,
) -> Result<GatewayEndpointConfig, ClientCoreError<B>>
where where
B: ReplyStorageBackend,
T: NymConfig + ClientCoreConfigTrait, T: NymConfig + ClientCoreConfigTrait,
{ {
println!("Not registering gateway, will reuse existing config and keys"); T::load_from_file(id)
T::load_from_file(Some(id))
.map(|existing_config| existing_config.get_gateway_endpoint().clone()) .map(|existing_config| existing_config.get_gateway_endpoint().clone())
.map_err(|err| { .map_err(|err| {
log::error!( log::error!(
@@ -152,20 +163,30 @@ where
}) })
} }
/// Get the full client address from the client keys and the gateway identity
pub fn get_client_address(
key_manager: &KeyManager,
gateway_config: &GatewayEndpointConfig,
) -> Recipient {
Recipient::new(
*key_manager.identity_keypair().public_key(),
*key_manager.encryption_keypair().public_key(),
// TODO: below only works under assumption that gateway address == gateway id
// (which currently is true)
NodeIdentity::from_base58_string(&gateway_config.gateway_id).unwrap(),
)
}
/// Get the client address by loading the keys from stored files. /// Get the client address by loading the keys from stored files.
pub fn get_client_address_from_stored_keys<B, T>( pub fn get_client_address_from_stored_keys<T>(
config: &Config<T>, config: &Config<T>,
) -> Result<Recipient, ClientCoreError<B>> ) -> Result<Recipient, ClientCoreError>
where where
T: config::NymConfig, T: config::NymConfig,
B: ReplyStorageBackend,
{ {
fn load_identity_keys<B>( fn load_identity_keys(
pathfinder: &ClientKeyPathfinder, pathfinder: &ClientKeyPathfinder,
) -> Result<identity::KeyPair, ClientCoreError<B>> ) -> Result<identity::KeyPair, ClientCoreError> {
where
B: ReplyStorageBackend,
{
let identity_keypair: identity::KeyPair = let identity_keypair: identity::KeyPair =
pemstore::load_keypair(&pemstore::KeyPairPath::new( pemstore::load_keypair(&pemstore::KeyPairPath::new(
pathfinder.private_identity_key().to_owned(), pathfinder.private_identity_key().to_owned(),
@@ -175,12 +196,9 @@ where
Ok(identity_keypair) Ok(identity_keypair)
} }
fn load_sphinx_keys<B>( fn load_sphinx_keys(
pathfinder: &ClientKeyPathfinder, pathfinder: &ClientKeyPathfinder,
) -> Result<encryption::KeyPair, ClientCoreError<B>> ) -> Result<encryption::KeyPair, ClientCoreError> {
where
B: ReplyStorageBackend,
{
let sphinx_keypair: encryption::KeyPair = let sphinx_keypair: encryption::KeyPair =
pemstore::load_keypair(&pemstore::KeyPairPath::new( pemstore::load_keypair(&pemstore::KeyPairPath::new(
pathfinder.private_encryption_key().to_owned(), pathfinder.private_encryption_key().to_owned(),
@@ -208,9 +226,9 @@ where
pub fn output_to_json<T: Serialize>(init_results: &T, output_file: &str) { pub fn output_to_json<T: Serialize>(init_results: &T, output_file: &str) {
match std::fs::File::create(output_file) { match std::fs::File::create(output_file) {
Ok(file) => match serde_json::to_writer_pretty(file, init_results) { Ok(file) => match serde_json::to_writer_pretty(file, init_results) {
Ok(_) => println!("Saved: {}", output_file), Ok(_) => println!("Saved: {output_file}"),
Err(err) => eprintln!("Could not save {}: {}", output_file, err), Err(err) => eprintln!("Could not save {output_file}: {err}"),
}, },
Err(err) => eprintln!("Could not save {}: {}", output_file, err), Err(err) => eprintln!("Could not save {output_file}: {err}"),
} }
} }
+3 -6
View File
@@ -7,13 +7,12 @@ edition = "2021"
[dependencies] [dependencies]
bip39 = "1.0.1" bip39 = "1.0.1"
cfg-if = "0.1" clap = { version = "4.0", features = ["cargo", "derive"] }
clap = { version = "3.2", features = ["cargo", "derive"] }
rand = "0.7.3" rand = "0.7.3"
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
thiserror = "1.0" thiserror = "1.0"
url = "2.2" url = "2.2"
tokio = { version = "1.21.2", features = ["rt-multi-thread", "net", "signal", "macros"] } # async runtime tokio = { version = "1.24.1", features = ["rt-multi-thread", "net", "signal", "macros"] } # async runtime
coconut-interface = { path = "../../common/coconut-interface" } coconut-interface = { path = "../../common/coconut-interface" }
config = { path = "../../common/config" } config = { path = "../../common/config" }
@@ -23,7 +22,5 @@ credential-storage = { path = "../../common/credential-storage" }
crypto = { path = "../../common/crypto", features = ["rand", "asymmetric", "symmetric", "aes", "hashing"] } crypto = { path = "../../common/crypto", features = ["rand", "asymmetric", "symmetric", "aes", "hashing"] }
network-defaults = { path = "../../common/network-defaults" } network-defaults = { path = "../../common/network-defaults" }
pemstore = { path = "../../common/pemstore" } pemstore = { path = "../../common/pemstore" }
validator-client = { path = "../../common/client-libs/validator-client", features = ["nymd-client"] } validator-client = { path = "../../common/client-libs/validator-client", features = ["nyxd-client"] }
[features]
coconut = ["credentials/coconut"]
+11 -11
View File
@@ -6,27 +6,27 @@ use bip39::Mnemonic;
use network_defaults::{NymNetworkDetails, VOUCHER_INFO}; use network_defaults::{NymNetworkDetails, VOUCHER_INFO};
use std::str::FromStr; use std::str::FromStr;
use url::Url; use url::Url;
use validator_client::nymd; use validator_client::nyxd;
use validator_client::nymd::traits::CoconutBandwidthSigningClient; use validator_client::nyxd::traits::CoconutBandwidthSigningClient;
use validator_client::nymd::{Coin, Fee, NymdClient, SigningNymdClient}; use validator_client::nyxd::{Coin, Fee, NyxdClient, SigningNyxdClient};
pub(crate) struct Client { pub(crate) struct Client {
nymd_client: NymdClient<SigningNymdClient>, nyxd_client: NyxdClient<SigningNyxdClient>,
mix_denom_base: String, mix_denom_base: String,
} }
impl Client { impl Client {
pub fn new(nymd_url: &str, mnemonic: &str) -> Self { pub fn new(nyxd_url: &str, mnemonic: &str) -> Self {
let nymd_url = Url::from_str(nymd_url).unwrap(); let nyxd_url = Url::from_str(nyxd_url).unwrap();
let mnemonic = Mnemonic::from_str(mnemonic).unwrap(); let mnemonic = Mnemonic::from_str(mnemonic).unwrap();
let network_details = NymNetworkDetails::new_from_env(); let network_details = NymNetworkDetails::new_from_env();
let config = nymd::Config::try_from_nym_network_details(&network_details) let config = nyxd::Config::try_from_nym_network_details(&network_details)
.expect("failed to construct valid validator client config with the provided network"); .expect("failed to construct valid validator client config with the provided network");
let nymd_client = let nyxd_client =
NymdClient::connect_with_mnemonic(config, nymd_url.as_ref(), mnemonic, None).unwrap(); NyxdClient::connect_with_mnemonic(config, nyxd_url.as_ref(), mnemonic, None).unwrap();
Client { Client {
nymd_client, nyxd_client,
mix_denom_base: network_details.chain_details.mix_denom.base, mix_denom_base: network_details.chain_details.mix_denom.base,
} }
} }
@@ -40,7 +40,7 @@ impl Client {
) -> Result<String> { ) -> Result<String> {
let amount = Coin::new(amount as u128, self.mix_denom_base.clone()); let amount = Coin::new(amount as u128, self.mix_denom_base.clone());
Ok(self Ok(self
.nymd_client .nyxd_client
.deposit( .deposit(
amount, amount,
String::from(VOUCHER_INFO), String::from(VOUCHER_INFO),
+15 -6
View File
@@ -13,7 +13,8 @@ use credentials::coconut::bandwidth::{BandwidthVoucher, TOTAL_ATTRIBUTES};
use credentials::coconut::utils::obtain_aggregate_signature; use credentials::coconut::utils::obtain_aggregate_signature;
use crypto::asymmetric::{encryption, identity}; use crypto::asymmetric::{encryption, identity};
use network_defaults::{NymNetworkDetails, VOUCHER_INFO}; use network_defaults::{NymNetworkDetails, VOUCHER_INFO};
use validator_client::nymd::tx::Hash; use validator_client::nyxd::traits::DkgQueryClient;
use validator_client::nyxd::tx::Hash;
use validator_client::{CoconutApiClient, Config}; use validator_client::{CoconutApiClient, Config};
use crate::client::Client; use crate::client::Client;
@@ -38,9 +39,9 @@ pub(crate) struct Run {
#[clap(long)] #[clap(long)]
pub(crate) client_home_directory: std::path::PathBuf, pub(crate) client_home_directory: std::path::PathBuf,
/// The nymd URL that should be used /// The nyxd URL that should be used
#[clap(long)] #[clap(long)]
pub(crate) nymd_url: String, pub(crate) nyxd_url: String,
/// A mnemonic for the account that buys the credential /// A mnemonic for the account that buys the credential
#[clap(long)] #[clap(long)]
@@ -51,12 +52,12 @@ pub(crate) struct Run {
pub(crate) amount: u64, pub(crate) amount: u64,
} }
pub(crate) async fn deposit(nymd_url: &str, mnemonic: &str, amount: u64) -> Result<State> { pub(crate) async fn deposit(nyxd_url: &str, mnemonic: &str, amount: u64) -> Result<State> {
let mut rng = OsRng; let mut rng = OsRng;
let signing_keypair = KeyPair::from(identity::KeyPair::new(&mut rng)); let signing_keypair = KeyPair::from(identity::KeyPair::new(&mut rng));
let encryption_keypair = KeyPair::from(encryption::KeyPair::new(&mut rng)); let encryption_keypair = KeyPair::from(encryption::KeyPair::new(&mut rng));
let client = Client::new(nymd_url, mnemonic); let client = Client::new(nyxd_url, mnemonic);
let tx_hash = client let tx_hash = client
.deposit( .deposit(
amount, amount,
@@ -80,7 +81,13 @@ pub(crate) async fn get_credential(state: &State, shared_storage: PersistentStor
let network_details = NymNetworkDetails::new_from_env(); let network_details = NymNetworkDetails::new_from_env();
let config = Config::try_from_nym_network_details(&network_details)?; let config = Config::try_from_nym_network_details(&network_details)?;
let client = validator_client::Client::new_query(config)?; 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 threshold = client
.nyxd
.get_current_epoch_threshold()
.await?
.ok_or(CredentialClientError::NoThreshold)?;
let coconut_api_clients = CoconutApiClient::all_coconut_api_clients(&client, epoch_id).await?;
let params = Parameters::new(TOTAL_ATTRIBUTES).unwrap(); let params = Parameters::new(TOTAL_ATTRIBUTES).unwrap();
let bandwidth_credential_attributes = BandwidthVoucher::new( let bandwidth_credential_attributes = BandwidthVoucher::new(
@@ -96,6 +103,7 @@ pub(crate) async fn get_credential(state: &State, shared_storage: PersistentStor
&params, &params,
&bandwidth_credential_attributes, &bandwidth_credential_attributes,
&coconut_api_clients, &coconut_api_clients,
threshold,
) )
.await?; .await?;
println!("Signature: {:?}", signature.to_bs58()); println!("Signature: {:?}", signature.to_bs58());
@@ -106,6 +114,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()[0].to_bs58(),
bandwidth_credential_attributes.get_private_attributes()[1].to_bs58(), bandwidth_credential_attributes.get_private_attributes()[1].to_bs58(),
signature.to_bs58(), signature.to_bs58(),
epoch_id.to_string(),
) )
.await?; .await?;
+6 -3
View File
@@ -7,15 +7,15 @@ use credential_storage::error::StorageError;
use credentials::error::Error as CredentialError; use credentials::error::Error as CredentialError;
use crypto::asymmetric::encryption::KeyRecoveryError; use crypto::asymmetric::encryption::KeyRecoveryError;
use crypto::asymmetric::identity::Ed25519RecoveryError; use crypto::asymmetric::identity::Ed25519RecoveryError;
use validator_client::nymd::error::NymdError; use validator_client::nyxd::error::NyxdError;
use validator_client::ValidatorClientError; use validator_client::ValidatorClientError;
pub type Result<T> = std::result::Result<T, CredentialClientError>; pub type Result<T> = std::result::Result<T, CredentialClientError>;
#[derive(Error, Debug)] #[derive(Error, Debug)]
pub enum CredentialClientError { pub enum CredentialClientError {
#[error("Nymd error: {0}")] #[error("Nyxd error: {0}")]
Nymd(#[from] NymdError), Nyxd(#[from] NyxdError),
#[error("Validator client error: {0}")] #[error("Validator client error: {0}")]
ValidatorClientError(#[from] ValidatorClientError), ValidatorClientError(#[from] ValidatorClientError),
@@ -34,4 +34,7 @@ pub enum CredentialClientError {
#[error("Could not use shared storage")] #[error("Could not use shared storage")]
SharedStorageError(#[from] StorageError), SharedStorageError(#[from] StorageError),
#[error("Threshold not set yet")]
NoThreshold,
} }
+39 -48
View File
@@ -1,56 +1,47 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net> // Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
cfg_if::cfg_if! { mod client;
if #[cfg(feature = "coconut")] { mod commands;
mod error;
mod state;
mod client; use commands::*;
mod commands; use completions::fig_generate;
mod error; use config::{DATA_DIR, DB_FILE_NAME};
mod state; use error::Result;
use network_defaults::setup_env;
use error::Result; use clap::{CommandFactory, Parser};
use network_defaults::setup_env;
use completions::fig_generate;
use commands::*;
use config::{DATA_DIR, DB_FILE_NAME};
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(subcommand)]
#[clap(author = "Nymtech", version, about)] pub(crate) command: Command,
struct Cli { }
/// Path pointing to an env file that configures the client.
#[clap(short, long)] #[tokio::main]
pub(crate) config_env_file: Option<std::path::PathBuf>, async fn main() -> Result<()> {
let args = Cli::parse();
#[clap(subcommand)] setup_env(args.config_env_file.as_ref());
pub(crate) command: Command, let bin_name = "nym-credential-client";
}
match args.command {
#[tokio::main] Command::Run(r) => {
async fn main() -> Result<()> { let db_path = r.client_home_directory.join(DATA_DIR).join(DB_FILE_NAME);
let args = Cli::parse(); let shared_storage = credential_storage::initialise_storage(db_path).await;
setup_env(args.config_env_file.clone());
let bin_name = "nym-credential-client"; let state = deposit(&r.nyxd_url, &r.mnemonic, r.amount).await?;
get_credential(&state, shared_storage).await?;
match args.command { }
Command::Run(r) => { Command::Completions(c) => c.generate(&mut crate::Cli::command(), bin_name),
let db_path = r.client_home_directory.join(DATA_DIR).join(DB_FILE_NAME); Command::GenerateFigSpec => fig_generate(&mut crate::Cli::command(), bin_name),
let shared_storage = credential_storage::initialise_storage(db_path).await; }
let state = deposit(&r.nymd_url, &r.mnemonic, r.amount).await?; Ok(())
get_credential(&state, shared_storage).await?;
}
Command::Completions(c) => c.generate(&mut crate::Cli::into_app(), bin_name),
Command::GenerateFigSpec => fig_generate(&mut crate::Cli::into_app(), bin_name)
}
Ok(())
}
} else {
fn main() {
println!("Crate only designed for coconut feature");
}
}
} }
+9 -13
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "nym-client" name = "nym-client"
version = "1.1.4" version = "1.1.8"
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jędrzej Stuczyński <andrew@nymtech.net>"] authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jędrzej Stuczyński <andrew@nymtech.net>"]
description = "Implementation of the Nym Client" description = "Implementation of the Nym Client"
edition = "2021" edition = "2021"
@@ -20,26 +20,28 @@ futures = "0.3" # bunch of futures stuff, however, now that I think about it, it
# and the single instance of abortable we have should really be refactored anyway # and the single instance of abortable we have should really be refactored anyway
url = "2.2" url = "2.2"
clap = { version = "3.2", features = ["cargo", "derive"] } clap = { version = "4.0", features = ["cargo", "derive"] }
dirs = "4.0" dirs = "4.0"
log = "0.4" # self explanatory lazy_static = "1.4.0"
log = { workspace = true } # self explanatory
pretty_env_logger = "0.4" # for formatting log messages pretty_env_logger = "0.4" # for formatting log messages
rand = { version = "0.7.3", features = ["wasm-bindgen"] } # rng-related traits + some rng implementation to use rand = { version = "0.7.3", features = ["wasm-bindgen"] } # rng-related traits + some rng implementation to use
serde = { version = "1.0.104", features = ["derive"] } # for config serialization/deserialization serde = { version = "1.0.104", features = ["derive"] } # for config serialization/deserialization
serde_json = "1.0" serde_json = "1.0"
thiserror = "1.0.34" thiserror = "1.0.34"
tap = "1.0.1" tap = "1.0.1"
tokio = { version = "1.21.2", features = ["rt-multi-thread", "net", "signal"] } # async runtime tokio = { version = "1.24.1", features = ["rt-multi-thread", "net", "signal"] } # async runtime
tokio-tungstenite = "0.14" # websocket tokio-tungstenite = "0.14" # websocket
## internal ## internal
build-information = { path = "../../common/build-information" }
client-core = { path = "../client-core", features = ["fs-surb-storage"] } client-core = { path = "../client-core", features = ["fs-surb-storage"] }
client-connections = { path = "../../common/client-connections" } client-connections = { path = "../../common/client-connections" }
coconut-interface = { path = "../../common/coconut-interface", optional = true } coconut-interface = { path = "../../common/coconut-interface" }
config = { path = "../../common/config" } config = { path = "../../common/config" }
completions = { path = "../../common/completions" } completions = { path = "../../common/completions" }
credential-storage = { path = "../../common/credential-storage" } credential-storage = { path = "../../common/credential-storage" }
credentials = { path = "../../common/credentials", optional = true } credentials = { path = "../../common/credentials" }
crypto = { path = "../../common/crypto" } crypto = { path = "../../common/crypto" }
logging = { path = "../../common/logging"} logging = { path = "../../common/logging"}
gateway-client = { path = "../../common/client-libs/gateway-client" } gateway-client = { path = "../../common/client-libs/gateway-client" }
@@ -49,15 +51,9 @@ nymsphinx = { path = "../../common/nymsphinx" }
pemstore = { path = "../../common/pemstore" } pemstore = { path = "../../common/pemstore" }
task = { path = "../../common/task" } task = { path = "../../common/task" }
topology = { path = "../../common/topology" } topology = { path = "../../common/topology" }
validator-client = { path = "../../common/client-libs/validator-client", features = ["nymd-client"] } validator-client = { path = "../../common/client-libs/validator-client", features = ["nyxd-client"] }
version-checker = { path = "../../common/version-checker" } version-checker = { path = "../../common/version-checker" }
websocket-requests = { path = "websocket-requests" } websocket-requests = { path = "websocket-requests" }
[features]
coconut = ["coconut-interface", "credentials", "credentials/coconut", "gateway-requests/coconut", "gateway-client/coconut", "client-core/coconut"]
[dev-dependencies] [dev-dependencies]
serde_json = "1.0" # for the "textsend" example serde_json = "1.0" # for the "textsend" example
[build-dependencies]
vergen = { version = "5", default-features = false, features = ["build", "git", "rustc", "cargo"] }
-8
View File
@@ -1,8 +0,0 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use vergen::{vergen, Config};
fn main() {
vergen(Config::default()).expect("failed to extract build metadata")
}
File diff suppressed because it is too large Load Diff
@@ -85,7 +85,7 @@ async fn send_file_without_reply() {
let (mut ws_stream, _) = connect_async(uri).await.unwrap(); let (mut ws_stream, _) = connect_async(uri).await.unwrap();
let recipient = get_self_address(&mut ws_stream).await; let recipient = get_self_address(&mut ws_stream).await;
println!("our full address is: {}", recipient); println!("our full address is: {recipient}");
let read_data = std::fs::read("examples/dummy_file").unwrap(); let read_data = std::fs::read("examples/dummy_file").unwrap();
+5 -14
View File
@@ -36,7 +36,7 @@ async fn send_text_with_reply() {
let (mut ws_stream, _) = connect_async(uri).await.unwrap(); let (mut ws_stream, _) = connect_async(uri).await.unwrap();
let recipient = get_self_address(&mut ws_stream).await; let recipient = get_self_address(&mut ws_stream).await;
println!("our full address is: {}", recipient); println!("our full address is: {recipient}");
let send_request = json!({ let send_request = json!({
"type" : "send", "type" : "send",
@@ -45,10 +45,7 @@ async fn send_text_with_reply() {
"withReplySurb": true, "withReplySurb": true,
}); });
println!( println!("sending {message:?} (*with* reply SURB) over the mix network...");
"sending {:?} (*with* reply SURB) over the mix network...",
message
);
let response = let response =
send_message_and_get_json_response(&mut ws_stream, send_request.to_string()).await; send_message_and_get_json_response(&mut ws_stream, send_request.to_string()).await;
@@ -59,10 +56,7 @@ async fn send_text_with_reply() {
"replySurb": response["replySurb"] "replySurb": response["replySurb"]
}); });
println!( println!("sending {reply_message:?} (using reply SURB!) over the mix network...");
"sending {:?} (using reply SURB!) over the mix network...",
reply_message
);
let response = let response =
send_message_and_get_json_response(&mut ws_stream, reply_request.to_string()).await; send_message_and_get_json_response(&mut ws_stream, reply_request.to_string()).await;
@@ -76,7 +70,7 @@ async fn send_text_without_reply() {
let (mut ws_stream, _) = connect_async(uri).await.unwrap(); let (mut ws_stream, _) = connect_async(uri).await.unwrap();
let recipient = get_self_address(&mut ws_stream).await; let recipient = get_self_address(&mut ws_stream).await;
println!("our full address is: {}", recipient); println!("our full address is: {recipient}");
let send_request = json!({ let send_request = json!({
"type" : "send", "type" : "send",
@@ -85,10 +79,7 @@ async fn send_text_without_reply() {
"withReplySurb": false, "withReplySurb": false,
}); });
println!( println!("sending {message:?} (*without* reply SURB) over the mix network...");
"sending {:?} (*without* reply SURB) over the mix network...",
message
);
let response = let response =
send_message_and_get_json_response(&mut ws_stream, send_request.to_string()).await; send_message_and_get_json_response(&mut ws_stream, send_request.to_string()).await;
+74 -4
View File
@@ -2,12 +2,18 @@
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use crate::client::config::template::config_template; use crate::client::config::template::config_template;
pub use client_core::config::MISSING_VALUE; use client_core::config::ClientCoreConfigTrait;
use client_core::config::{ClientCoreConfigTrait, Config as BaseConfig, DebugConfig};
use config::defaults::DEFAULT_WEBSOCKET_LISTENING_PORT; use config::defaults::DEFAULT_WEBSOCKET_LISTENING_PORT;
use config::NymConfig; use config::{NymConfig, OptionalSet};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::fmt::Debug;
use std::net::{IpAddr, Ipv4Addr};
use std::path::PathBuf; use std::path::PathBuf;
use std::str::FromStr;
pub use client_core::config::Config as BaseConfig;
pub use client_core::config::MISSING_VALUE;
pub use client_core::config::{DebugConfig, GatewayEndpointConfig};
mod template; mod template;
@@ -92,6 +98,20 @@ impl Config {
self self
} }
pub fn with_disabled_socket(mut self, disabled: bool) -> Self {
if disabled {
self.socket.socket_type = SocketType::None;
} else {
self.socket.socket_type = SocketType::WebSocket;
}
self
}
pub fn with_host(mut self, host: IpAddr) -> Self {
self.socket.host = host;
self
}
pub fn with_port(mut self, port: u16) -> Self { pub fn with_port(mut self, port: u16) -> Self {
self.socket.listening_port = port; self.socket.listening_port = port;
self self
@@ -118,15 +138,64 @@ impl Config {
self.socket.socket_type self.socket.socket_type
} }
pub fn get_listening_ip(&self) -> IpAddr {
self.socket.host
}
pub fn get_listening_port(&self) -> u16 { pub fn get_listening_port(&self) -> u16 {
self.socket.listening_port self.socket.listening_port
} }
// poor man's 'builder' method
pub fn with_base<F, T>(mut self, f: F, val: T) -> Self
where
F: Fn(BaseConfig<Self>, T) -> BaseConfig<Self>,
{
self.base = f(self.base, val);
self
}
// helper methods to use `OptionalSet` trait. Those are defined due to very... ehm. 'specific' structure of this config
// (plz, lets refactor it)
pub fn with_optional_ext<F, T>(mut self, f: F, val: Option<T>) -> Self
where
F: Fn(BaseConfig<Self>, T) -> BaseConfig<Self>,
{
self.base = self.base.with_optional(f, val);
self
}
pub fn with_optional_env_ext<F, T>(mut self, f: F, val: Option<T>, env_var: &str) -> Self
where
F: Fn(BaseConfig<Self>, T) -> BaseConfig<Self>,
T: FromStr,
<T as FromStr>::Err: Debug,
{
self.base = self.base.with_optional_env(f, val, env_var);
self
}
pub fn with_optional_custom_env_ext<F, T, G>(
mut self,
f: F,
val: Option<T>,
env_var: &str,
parser: G,
) -> Self
where
F: Fn(BaseConfig<Self>, T) -> BaseConfig<Self>,
G: Fn(&str) -> T,
{
self.base = self.base.with_optional_custom_env(f, val, env_var, parser);
self
}
} }
#[derive(Debug, Deserialize, PartialEq, Eq, Serialize)] #[derive(Debug, Deserialize, PartialEq, Eq, Serialize)]
#[serde(deny_unknown_fields)] #[serde(default, deny_unknown_fields)]
pub struct Socket { pub struct Socket {
socket_type: SocketType, socket_type: SocketType,
host: IpAddr,
listening_port: u16, listening_port: u16,
} }
@@ -134,6 +203,7 @@ impl Default for Socket {
fn default() -> Self { fn default() -> Self {
Socket { Socket {
socket_type: SocketType::WebSocket, socket_type: SocketType::WebSocket,
host: IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)),
listening_port: DEFAULT_WEBSOCKET_LISTENING_PORT, listening_port: DEFAULT_WEBSOCKET_LISTENING_PORT,
} }
} }
+8 -5
View File
@@ -23,16 +23,16 @@ id = '{{ client.id }}'
# to claim bandwidth without presenting bandwidth credentials. # to claim bandwidth without presenting bandwidth credentials.
disabled_credentials_mode = {{ client.disabled_credentials_mode }} disabled_credentials_mode = {{ client.disabled_credentials_mode }}
# Addresses to nymd validators via which the client can communicate with the chain. # Addresses to nyxd validators via which the client can communicate with the chain.
validator_urls = [ nyxd_urls = [
{{#each client.validator_urls }} {{#each client.nyxd_urls }}
'{{this}}', '{{this}}',
{{/each}} {{/each}}
] ]
# Addresses to APIs running on validator from which the client gets the view of the network. # Addresses to APIs running on validator from which the client gets the view of the network.
validator_api_urls = [ nym_api_urls = [
{{#each client.validator_api_urls }} {{#each client.nym_api_urls }}
'{{this}}', '{{this}}',
{{/each}} {{/each}}
] ]
@@ -93,6 +93,9 @@ socket_type = '{{ socket.socket_type }}'
# will be listening for incoming requests # will be listening for incoming requests
listening_port = {{ socket.listening_port }} 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 ##### ##### logging configuration options #####
+109 -72
View File
@@ -1,26 +1,32 @@
// Copyright 2021-2022 - Nym Technologies SA <contact@nymtech.net> // Copyright 2021-2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use std::error::Error;
use crate::client::config::Config; use crate::client::config::Config;
use crate::error::ClientError; use crate::error::ClientError;
use crate::websocket; use crate::websocket;
use client_connections::TransmissionLane; use client_connections::TransmissionLane;
use client_core::client::base_client::{ use client_core::client::base_client::{
non_wasm_helpers, BaseClientBuilder, ClientInput, ClientOutput, non_wasm_helpers, BaseClientBuilder, ClientInput, ClientOutput, ClientState,
}; };
use client_core::client::inbound_messages::InputMessage; use client_core::client::inbound_messages::InputMessage;
use client_core::client::key_manager::KeyManager; use client_core::client::received_buffer::{
use client_core::client::received_buffer::{ReceivedBufferMessage, ReconstructedMessagesReceiver}; ReceivedBufferMessage, ReceivedBufferRequestSender, ReconstructedMessagesReceiver,
};
use client_core::config::persistence::key_pathfinder::ClientKeyPathfinder; use client_core::config::persistence::key_pathfinder::ClientKeyPathfinder;
use futures::channel::mpsc; use futures::channel::mpsc;
use gateway_client::bandwidth::BandwidthController; use gateway_client::bandwidth::BandwidthController;
use log::*; use log::*;
use nymsphinx::addressing::clients::Recipient;
use nymsphinx::anonymous_replies::requests::AnonymousSenderTag; use nymsphinx::anonymous_replies::requests::AnonymousSenderTag;
use nymsphinx::receiver::ReconstructedMessage; use task::TaskManager;
use task::{wait_for_signal, ShutdownNotifier}; use tokio::sync::watch::error::SendError;
use validator_client::nyxd::QueryNyxdClient;
pub(crate) mod config; pub use client_core::client::key_manager::KeyManager;
pub use nymsphinx::addressing::clients::Recipient;
pub use nymsphinx::receiver::ReconstructedMessage;
pub mod config;
pub struct SocketClient { pub struct SocketClient {
/// Client configuration options, including, among other things, packet sending rates, /// Client configuration options, including, among other things, packet sending rates,
@@ -42,104 +48,101 @@ impl SocketClient {
} }
} }
async fn create_bandwidth_controller(config: &Config) -> BandwidthController { pub fn new_with_keys(config: Config, key_manager: KeyManager) -> Self {
#[cfg(feature = "coconut")] SocketClient {
let bandwidth_controller = { config,
let details = network_defaults::NymNetworkDetails::new_from_env(); key_manager,
let mut client_config = }
validator_client::Config::try_from_nym_network_details(&details) }
.expect("failed to construct validator client config");
let nymd_url = config async fn create_bandwidth_controller(config: &Config) -> BandwidthController<QueryNyxdClient> {
.get_base() let details = network_defaults::NymNetworkDetails::new_from_env();
.get_validator_endpoints() let mut client_config = validator_client::Config::try_from_nym_network_details(&details)
.pop() .expect("failed to construct validator client config");
.expect("No nymd validator endpoint provided"); let nyxd_url = config
let api_url = config .get_base()
.get_base() .get_validator_endpoints()
.get_validator_api_endpoints() .pop()
.pop() .expect("No nyxd validator endpoint provided");
.expect("No validator api endpoint provided"); let api_url = config
// overwrite env configuration with config URLs .get_base()
client_config = client_config.with_urls(nymd_url, api_url); .get_nym_api_endpoints()
let client = validator_client::Client::new_query(client_config) .pop()
.expect("Could not construct query client"); .expect("No validator api endpoint provided");
let coconut_api_clients = // overwrite env configuration with config URLs
validator_client::CoconutApiClient::all_coconut_api_clients(&client) client_config = client_config.with_urls(nyxd_url, api_url);
.await let client = validator_client::Client::new_query(client_config)
.expect("Could not query api clients"); .expect("Could not construct query client");
BandwidthController::new( 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, credential_storage::initialise_storage(config.get_base().get_database_path()).await,
client,
) )
.expect("Could not create bandwidth controller");
bandwidth_controller
} }
fn start_websocket_listener( fn start_websocket_listener(
config: &Config, config: &Config,
client_input: ClientInput, client_input: ClientInput,
client_output: ClientOutput, client_output: ClientOutput,
self_address: Recipient, client_state: ClientState,
self_address: &Recipient,
shutdown: task::TaskClient,
) { ) {
info!("Starting websocket listener..."); info!("Starting websocket listener...");
let ClientInput { let ClientInput {
shared_lane_queue_lengths,
connection_command_sender, connection_command_sender,
input_sender, input_sender,
} = client_input; } = client_input;
let received_buffer_request_sender = client_output.received_buffer_request_sender; let ClientOutput {
received_buffer_request_sender,
} = client_output;
let websocket_handler = websocket::Handler::new( let ClientState {
shared_lane_queue_lengths,
reply_controller_sender,
} = client_state;
let websocket_handler = websocket::HandlerBuilder::new(
input_sender, input_sender,
connection_command_sender, connection_command_sender,
received_buffer_request_sender, received_buffer_request_sender,
self_address, self_address,
shared_lane_queue_lengths, shared_lane_queue_lengths,
reply_controller_sender,
); );
websocket::Listener::new(config.get_listening_port()).start(websocket_handler); 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) /// blocking version of `start_socket` method. Will run forever (or until SIGINT is sent)
pub async fn run_socket_forever(self) -> Result<(), ClientError> { pub async fn run_socket_forever(self) -> Result<(), Box<dyn Error + Send + Sync>> {
let mut shutdown = self.start_socket().await?; let shutdown = self.start_socket().await?;
wait_for_signal().await;
println!(
"Received signal - the client will terminate now (threads are not yet nicely stopped, if you see stack traces that's alright)."
);
log::info!("Sending shutdown");
shutdown.signal_shutdown().ok();
// Some of these components have shutdown signalling implemented as part of socks5 work,
// but since it's not fully implemented (yet) for all the components of the native client,
// we don't try to wait and instead just stop immediately.
log::info!("Waiting for tasks to finish... (Press ctrl-c to force)");
shutdown.wait_for_shutdown().await;
let res = shutdown.catch_interrupt().await;
log::info!("Stopping nym-client"); log::info!("Stopping nym-client");
Ok(()) res
} }
pub async fn start_socket(self) -> Result<ShutdownNotifier, ClientError> { pub async fn start_socket(self) -> Result<TaskManager, ClientError> {
if !self.config.get_socket_type().is_websocket() { if !self.config.get_socket_type().is_websocket() {
return Err(ClientError::InvalidSocketMode); return Err(ClientError::InvalidSocketMode);
} }
// don't create bandwidth controller if credentials are disabled
let bandwidth_controller = if self.config.get_base().get_disabled_credentials_mode() {
None
} else {
Some(Self::create_bandwidth_controller(&self.config).await)
};
let base_builder = BaseClientBuilder::new_from_base_config( let base_builder = BaseClientBuilder::new_from_base_config(
self.config.get_base(), self.config.get_base(),
self.key_manager, self.key_manager,
Some(Self::create_bandwidth_controller(&self.config).await), bandwidth_controller,
non_wasm_helpers::setup_fs_reply_surb_backend( 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(), self.config.get_debug_settings(),
) )
.await?, .await?,
@@ -149,13 +152,21 @@ impl SocketClient {
let mut started_client = base_builder.start_base().await?; let mut started_client = base_builder.start_base().await?;
let client_input = started_client.client_input.register_producer(); let client_input = started_client.client_input.register_producer();
let client_output = started_client.client_output.register_consumer(); let client_output = started_client.client_output.register_consumer();
let client_state = started_client.client_state;
Self::start_websocket_listener(&self.config, client_input, client_output, self_address); Self::start_websocket_listener(
&self.config,
client_input,
client_output,
client_state,
&self_address,
started_client.task_manager.subscribe(),
);
info!("Client startup finished!"); info!("Client startup finished!");
info!("The address of this client is: {}", self_address); info!("The address of this client is: {}", self_address);
Ok(started_client.shutdown_notifier) Ok(started_client.task_manager)
} }
pub async fn start_direct(self) -> Result<DirectClient, ClientError> { pub async fn start_direct(self) -> Result<DirectClient, ClientError> {
@@ -163,17 +174,26 @@ impl SocketClient {
return Err(ClientError::InvalidSocketMode); return Err(ClientError::InvalidSocketMode);
} }
// don't create bandwidth controller if credentials are disabled
let bandwidth_controller = if self.config.get_base().get_disabled_credentials_mode() {
None
} else {
Some(Self::create_bandwidth_controller(&self.config).await)
};
let base_client = BaseClientBuilder::new_from_base_config( let base_client = BaseClientBuilder::new_from_base_config(
self.config.get_base(), self.config.get_base(),
self.key_manager, self.key_manager,
Some(Self::create_bandwidth_controller(&self.config).await), bandwidth_controller,
non_wasm_helpers::setup_fs_reply_surb_backend( 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(), self.config.get_debug_settings(),
) )
.await?, .await?,
); );
let address = base_client.as_mix_recipient();
let mut started_client = base_client.start_base().await?; let mut started_client = base_client.start_base().await?;
let client_input = started_client.client_input.register_producer(); let client_input = started_client.client_input.register_producer();
let client_output = started_client.client_output.register_consumer(); let client_output = started_client.client_output.register_consumer();
@@ -191,21 +211,38 @@ impl SocketClient {
Ok(DirectClient { Ok(DirectClient {
client_input, client_input,
_received_buffer_request_sender: client_output.received_buffer_request_sender,
reconstructed_receiver, reconstructed_receiver,
_shutdown_notifier: started_client.shutdown_notifier, address,
shutdown_notifier: started_client.task_manager,
}) })
} }
} }
pub struct DirectClient { pub struct DirectClient {
client_input: ClientInput, client_input: ClientInput,
// make sure to not drop the channel
_received_buffer_request_sender: ReceivedBufferRequestSender,
reconstructed_receiver: ReconstructedMessagesReceiver, reconstructed_receiver: ReconstructedMessagesReceiver,
address: Recipient,
// we need to keep reference to this guy otherwise things will start dropping // we need to keep reference to this guy otherwise things will start dropping
_shutdown_notifier: ShutdownNotifier, shutdown_notifier: TaskManager,
} }
impl DirectClient { impl DirectClient {
pub fn address(&self) -> &Recipient {
&self.address
}
pub fn signal_shutdown(&self) -> Result<(), SendError<()>> {
self.shutdown_notifier.signal_shutdown()
}
pub async fn wait_for_shutdown(&mut self) {
self.shutdown_notifier.wait_for_shutdown().await
}
/// EXPERIMENTAL DIRECT RUST API /// EXPERIMENTAL DIRECT RUST API
/// It's untested and there are absolutely no guarantees about it (but seems to have worked /// It's untested and there are absolutely no guarantees about it (but seems to have worked
/// well enough in local tests) /// well enough in local tests)
+32 -27
View File
@@ -8,9 +8,11 @@ use crate::{
}; };
use clap::Args; use clap::Args;
use config::NymConfig; use config::NymConfig;
use crypto::asymmetric::identity;
use nymsphinx::addressing::clients::Recipient; use nymsphinx::addressing::clients::Recipient;
use serde::Serialize; use serde::Serialize;
use std::fmt::Display; use std::fmt::Display;
use std::net::IpAddr;
use tap::TapFallible; use tap::TapFallible;
#[derive(Args, Clone)] #[derive(Args, Clone)]
@@ -21,43 +23,47 @@ pub(crate) struct Init {
/// Id of the gateway we are going to connect to. /// Id of the gateway we are going to connect to.
#[clap(long)] #[clap(long)]
gateway: Option<String>, gateway: Option<identity::PublicKey>,
/// Force register gateway. WARNING: this will overwrite any existing keys for the given id, /// Force register gateway. WARNING: this will overwrite any existing keys for the given id,
/// potentially causing loss of access. /// potentially causing loss of access.
#[clap(long)] #[clap(long)]
force_register_gateway: bool, force_register_gateway: bool,
/// Comma separated list of rest endpoints of the nymd validators /// Comma separated list of rest endpoints of the nyxd validators
#[clap(long)] #[clap(long, alias = "nymd_validators", value_delimiter = ',', hide = true)]
nymd_validators: Option<String>, nyxd_urls: Option<Vec<url::Url>>,
/// Comma separated list of rest endpoints of the API validators /// Comma separated list of rest endpoints of the API validators
#[clap(long)] #[clap(long, alias = "api_validators", value_delimiter = ',')]
api_validators: Option<String>, // the alias here is included for backwards compatibility (1.1.4 and before)
nym_apis: Option<Vec<url::Url>>,
/// Whether to not start the websocket /// Whether to not start the websocket
#[clap(long)] #[clap(long)]
disable_socket: bool, disable_socket: Option<bool>,
/// Port for the socket (if applicable) to listen on in all subsequent runs /// Port for the socket (if applicable) to listen on in all subsequent runs
#[clap(short, long)] #[clap(short, long)]
port: Option<u16>, 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 /// Mostly debug-related option to increase default traffic rate so that you would not need to
/// modify config post init /// modify config post init
#[clap(long, hidden = true)] #[clap(long, hide = true)]
fastmode: bool, fastmode: bool,
/// Disable loop cover traffic and the Poisson rate limiter (for debugging only) /// Disable loop cover traffic and the Poisson rate limiter (for debugging only)
#[clap(long, hidden = true)] #[clap(long, hide = true)]
no_cover: bool, no_cover: bool,
/// Set this client to work in a enabled credentials mode that would attempt to use gateway /// Set this client to work in a enabled credentials mode that would attempt to use gateway
/// with bandwidth credential requirement. /// with bandwidth credential requirement.
#[cfg(feature = "coconut")] #[clap(long, hide = true)]
#[clap(long)] enabled_credentials_mode: Option<bool>,
enabled_credentials_mode: bool,
/// Save a summary of the initialization to a json file /// Save a summary of the initialization to a json file
#[clap(long)] #[clap(long)]
@@ -67,14 +73,14 @@ pub(crate) struct Init {
impl From<Init> for OverrideConfig { impl From<Init> for OverrideConfig {
fn from(init_config: Init) -> Self { fn from(init_config: Init) -> Self {
OverrideConfig { OverrideConfig {
nymd_validators: init_config.nymd_validators, nym_apis: init_config.nym_apis,
api_validators: init_config.api_validators,
disable_socket: init_config.disable_socket, disable_socket: init_config.disable_socket,
port: init_config.port, port: init_config.port,
host: init_config.host,
fastmode: init_config.fastmode, fastmode: init_config.fastmode,
no_cover: init_config.no_cover, no_cover: init_config.no_cover,
#[cfg(feature = "coconut")] nyxd_urls: init_config.nyxd_urls,
enabled_credentials_mode: init_config.enabled_credentials_mode, enabled_credentials_mode: init_config.enabled_credentials_mode,
} }
} }
@@ -108,18 +114,17 @@ pub(crate) async fn execute(args: &Init) -> Result<(), ClientError> {
let id = &args.id; 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 { if already_init {
println!( println!("Client \"{id}\" was already initialised before");
"Client \"{}\" was already initialised before! \
Config information will be overwritten (but keys will be kept)!",
id
);
} }
// Usually you only register with the gateway on the first init, however you can force // Usually you only register with the gateway on the first init, however you can force
// re-registering if wanted. // re-registering if wanted.
let user_wants_force_register = args.force_register_gateway; let user_wants_force_register = args.force_register_gateway;
if user_wants_force_register {
println!("Instructed to force registering gateway. This might overwrite keys!");
}
// If the client was already initialized, don't generate new keys and don't re-register with // If the client was already initialized, don't generate new keys and don't re-register with
// the gateway (because this would create a new shared key). // the gateway (because this would create a new shared key).
@@ -127,14 +132,14 @@ pub(crate) async fn execute(args: &Init) -> Result<(), ClientError> {
let register_gateway = !already_init || user_wants_force_register; let register_gateway = !already_init || user_wants_force_register;
// Attempt to use a user-provided gateway, if possible // Attempt to use a user-provided gateway, if possible
let user_chosen_gateway_id = args.gateway.clone(); let user_chosen_gateway_id = args.gateway;
// Load and potentially override config // Load and potentially override config
let mut config = override_config(Config::new(id), OverrideConfig::from(args.clone())); let mut config = override_config(Config::new(id), OverrideConfig::from(args.clone()));
// Setup gateway by either registering a new one, or creating a new config from the selected // Setup gateway by either registering a new one, or creating a new config from the selected
// one but with keys kept, or reusing the gateway configuration. // one but with keys kept, or reusing the gateway configuration.
let gateway = client_core::init::setup_gateway::<_, Config, _>( let gateway = client_core::init::setup_gateway_from_config::<Config, _>(
register_gateway, register_gateway,
user_chosen_gateway_id, user_chosen_gateway_id,
config.get_base(), config.get_base(),
@@ -142,7 +147,7 @@ pub(crate) async fn execute(args: &Init) -> Result<(), ClientError> {
.await .await
.tap_err(|err| eprintln!("Failed to setup gateway\nError: {err}"))?; .tap_err(|err| eprintln!("Failed to setup gateway\nError: {err}"))?;
config.get_base_mut().with_gateway_endpoint(gateway); config.get_base_mut().set_gateway_endpoint(gateway);
config.save_to_file(None).tap_err(|_| { config.save_to_file(None).tap_err(|_| {
log::error!("Failed to save the config file"); log::error!("Failed to save the config file");
@@ -152,20 +157,20 @@ pub(crate) async fn execute(args: &Init) -> Result<(), ClientError> {
let address = client_core::init::get_client_address_from_stored_keys(config.get_base())?; let address = client_core::init::get_client_address_from_stored_keys(config.get_base())?;
let init_results = InitResults::new(&config, &address); let init_results = InitResults::new(&config, &address);
println!("{}", init_results); println!("{init_results}");
// Output summary to a json file, if specified // Output summary to a json file, if specified
if args.output_json { if args.output_json {
client_core::init::output_to_json(&init_results, "client_init_results.json"); client_core::init::output_to_json(&init_results, "client_init_results.json");
} }
println!("\nThe address of this client is: {}\n", address); println!("\nThe address of this client is: {address}\n");
Ok(()) Ok(())
} }
fn print_saved_config(config: &Config) { fn print_saved_config(config: &Config) {
let config_save_location = config.get_config_file_save_location(); let config_save_location = config.get_config_file_save_location();
println!("Saved configuration file to {:?}", config_save_location); println!("Saved configuration file to {config_save_location:?}");
println!("Using gateway: {}", config.get_base().get_gateway_id()); println!("Using gateway: {}", config.get_base().get_gateway_id());
log::debug!("Gateway id: {}", config.get_base().get_gateway_id()); log::debug!("Gateway id: {}", config.get_base().get_gateway_id());
log::debug!("Gateway owner: {}", config.get_base().get_gateway_owner()); log::debug!("Gateway owner: {}", config.get_base().get_gateway_owner());
+44 -91
View File
@@ -1,53 +1,32 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net> // Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use crate::client::config::{Config, SocketType}; use crate::client::config::{BaseConfig, Config};
use crate::error::ClientError; use build_information::BinaryBuildInformation;
use clap::CommandFactory; use clap::CommandFactory;
use clap::{Parser, Subcommand}; use clap::{Parser, Subcommand};
use completions::{fig_generate, ArgShell}; 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 init;
pub(crate) mod run; pub(crate) mod run;
pub(crate) mod upgrade; pub(crate) mod upgrade;
fn long_version() -> String { lazy_static! {
format!( pub static ref PRETTY_BUILD_INFORMATION: String =
r#" BinaryBuildInformation::new(env!("CARGO_PKG_VERSION")).pretty_print();
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
"#,
"Build Timestamp:",
env!("VERGEN_BUILD_TIMESTAMP"),
"Build Version:",
env!("VERGEN_BUILD_SEMVER"),
"Commit SHA:",
env!("VERGEN_GIT_SHA"),
"Commit Date:",
env!("VERGEN_GIT_COMMIT_TIMESTAMP"),
"Commit Branch:",
env!("VERGEN_GIT_BRANCH"),
"rustc Version:",
env!("VERGEN_RUSTC_SEMVER"),
"rustc Channel:",
env!("VERGEN_RUSTC_CHANNEL"),
"cargo Profile:",
env!("VERGEN_CARGO_PROFILE"),
)
} }
fn long_version_static() -> &'static str { // Helper for passing LONG_VERSION to clap
Box::leak(long_version().into_boxed_str()) fn pretty_build_info_static() -> &'static str {
&PRETTY_BUILD_INFORMATION
} }
#[derive(Parser)] #[derive(Parser)]
#[clap(author = "Nymtech", version, long_version = long_version_static(), about)] #[clap(author = "Nymtech", version, long_version = pretty_build_info_static(), about)]
pub(crate) struct Cli { pub(crate) struct Cli {
/// Path pointing to an env file that configures the client. /// Path pointing to an env file that configures the client.
#[clap(short, long)] #[clap(short, long)]
@@ -75,78 +54,52 @@ pub(crate) enum Commands {
// Configuration that can be overridden. // Configuration that can be overridden.
pub(crate) struct OverrideConfig { pub(crate) struct OverrideConfig {
nymd_validators: Option<String>, nym_apis: Option<Vec<url::Url>>,
api_validators: Option<String>, disable_socket: Option<bool>,
disable_socket: bool,
port: Option<u16>, port: Option<u16>,
host: Option<IpAddr>,
fastmode: bool, fastmode: bool,
no_cover: bool, no_cover: bool,
nyxd_urls: Option<Vec<url::Url>>,
#[cfg(feature = "coconut")] enabled_credentials_mode: Option<bool>,
enabled_credentials_mode: bool,
} }
pub(crate) async fn execute(args: &Cli) -> Result<(), ClientError> { pub(crate) async fn execute(args: &Cli) -> Result<(), Box<dyn Error + Send + Sync>> {
let bin_name = "nym-native-client"; let bin_name = "nym-native-client";
match &args.command { match &args.command {
Commands::Init(m) => init::execute(m).await?, Commands::Init(m) => init::execute(m).await?,
Commands::Run(m) => run::execute(m).await?, Commands::Run(m) => run::execute(m).await?,
Commands::Upgrade(m) => upgrade::execute(m), Commands::Upgrade(m) => upgrade::execute(m),
Commands::Completions(s) => s.generate(&mut Cli::into_app(), bin_name), Commands::Completions(s) => s.generate(&mut Cli::command(), bin_name),
Commands::GenerateFigSpec => fig_generate(&mut Cli::into_app(), bin_name), Commands::GenerateFigSpec => fig_generate(&mut Cli::command(), bin_name),
} }
Ok(()) Ok(())
} }
pub(crate) fn override_config(mut config: Config, args: OverrideConfig) -> Config { pub(crate) fn override_config(config: Config, args: OverrideConfig) -> Config {
if let Some(raw_validators) = args.nymd_validators {
config
.get_base_mut()
.set_custom_validators(config::parse_validators(&raw_validators));
} else if std::env::var(network_defaults::var_names::CONFIGURED).is_ok() {
let raw_validators = std::env::var(network_defaults::var_names::NYMD_VALIDATOR)
.expect("nymd validator not set");
config
.get_base_mut()
.set_custom_validators(config::parse_validators(&raw_validators));
}
if let Some(raw_validators) = args.api_validators {
config
.get_base_mut()
.set_custom_validator_apis(config::parse_validators(&raw_validators));
} else if std::env::var(network_defaults::var_names::CONFIGURED).is_ok() {
let raw_validators = std::env::var(network_defaults::var_names::API_VALIDATOR)
.expect("api validator not set");
config
.get_base_mut()
.set_custom_validator_apis(config::parse_validators(&raw_validators));
}
if args.disable_socket {
config = config.with_socket(SocketType::None);
}
if let Some(port) = args.port {
config = config.with_port(port);
}
#[cfg(feature = "coconut")]
{
if args.enabled_credentials_mode {
config.get_base_mut().with_disabled_credentials(false)
}
}
if args.fastmode {
config.get_base_mut().set_high_default_traffic_volume();
}
if args.no_cover {
config.get_base_mut().set_no_cover_traffic();
}
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,
)
.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)] #[cfg(test)]
+29 -21
View File
@@ -1,6 +1,9 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net> // Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use std::error::Error;
use std::net::IpAddr;
use crate::{ use crate::{
client::{config::Config, SocketClient}, client::{config::Config, SocketClient},
commands::{override_config, OverrideConfig}, commands::{override_config, OverrideConfig},
@@ -9,6 +12,7 @@ use crate::{
use clap::Args; use clap::Args;
use config::NymConfig; use config::NymConfig;
use crypto::asymmetric::identity;
use log::*; use log::*;
use version_checker::is_minor_version_compatible; use version_checker::is_minor_version_compatible;
@@ -18,53 +22,57 @@ pub(crate) struct Run {
#[clap(long)] #[clap(long)]
id: String, id: String,
/// Comma separated list of rest endpoints of the nymd validators /// Comma separated list of rest endpoints of the nyxd validators
#[clap(long)] #[clap(long, alias = "nymd_validators", value_delimiter = ',', hide = true)]
nymd_validators: Option<String>, nyxd_urls: Option<Vec<url::Url>>,
/// Comma separated list of rest endpoints of the API validators /// Comma separated list of rest endpoints of the API validators
#[clap(long)] #[clap(long, alias = "api_validators", value_delimiter = ',')]
api_validators: Option<String>, // the alias here is included for backwards compatibility (1.1.4 and before)
nym_apis: Option<Vec<url::Url>>,
/// Id of the gateway we want to connect to. If overridden, it is user's responsibility to /// Id of the gateway we want to connect to. If overridden, it is user's responsibility to
/// ensure prior registration happened /// ensure prior registration happened
#[clap(long)] #[clap(long)]
gateway: Option<String>, gateway: Option<identity::PublicKey>,
/// Whether to not start the websocket /// Whether to not start the websocket
#[clap(long)] #[clap(long)]
disable_socket: bool, disable_socket: Option<bool>,
/// Port for the socket to listen on /// Port for the socket to listen on
#[clap(short, long)] #[clap(short, long)]
port: Option<u16>, 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 /// Mostly debug-related option to increase default traffic rate so that you would not need to
/// modify config post init /// modify config post init
#[clap(long, hidden = true)] #[clap(long, hide = true)]
fastmode: bool, fastmode: bool,
/// Disable loop cover traffic and the Poisson rate limiter (for debugging only) /// Disable loop cover traffic and the Poisson rate limiter (for debugging only)
#[clap(long, hidden = true)] #[clap(long, hide = true)]
no_cover: bool, no_cover: bool,
/// Set this client to work in a enabled credentials mode that would attempt to use gateway /// Set this client to work in a enabled credentials mode that would attempt to use gateway
/// with bandwidth credential requirement. /// with bandwidth credential requirement.
#[cfg(feature = "coconut")] #[clap(long, hide = true)]
#[clap(long)] enabled_credentials_mode: Option<bool>,
enabled_credentials_mode: bool,
} }
impl From<Run> for OverrideConfig { impl From<Run> for OverrideConfig {
fn from(run_config: Run) -> Self { fn from(run_config: Run) -> Self {
OverrideConfig { OverrideConfig {
nymd_validators: run_config.nymd_validators, nym_apis: run_config.nym_apis,
api_validators: run_config.api_validators,
disable_socket: run_config.disable_socket, disable_socket: run_config.disable_socket,
port: run_config.port, port: run_config.port,
host: run_config.host,
fastmode: run_config.fastmode, fastmode: run_config.fastmode,
no_cover: run_config.no_cover, no_cover: run_config.no_cover,
#[cfg(feature = "coconut")] nyxd_urls: run_config.nyxd_urls,
enabled_credentials_mode: run_config.enabled_credentials_mode, enabled_credentials_mode: run_config.enabled_credentials_mode,
} }
} }
@@ -89,14 +97,14 @@ fn version_check(cfg: &Config) -> bool {
} }
} }
pub(crate) async fn execute(args: &Run) -> Result<(), ClientError> { pub(crate) async fn execute(args: &Run) -> Result<(), Box<dyn Error + Send + Sync>> {
let id = &args.id; 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, Ok(cfg) => cfg,
Err(err) => { Err(err) => {
error!("Failed to load config for {}. Are you sure you have run `init` before? (Error was: {})", id, err); error!("Failed to load config for {}. Are you sure you have run `init` before? (Error was: {err})", id);
return Err(ClientError::FailedToLoadConfig(id.to_string())); return Err(Box::new(ClientError::FailedToLoadConfig(id.to_string())));
} }
}; };
@@ -109,7 +117,7 @@ pub(crate) async fn execute(args: &Run) -> Result<(), ClientError> {
if !version_check(&config) { if !version_check(&config) {
error!("failed the local version check"); error!("failed the local version check");
return Err(ClientError::FailedLocalVersionCheck); return Err(Box::new(ClientError::FailedLocalVersionCheck));
} }
SocketClient::new(config).run_socket_forever().await SocketClient::new(config).run_socket_forever().await
+11 -25
View File
@@ -17,36 +17,26 @@ fn fail_upgrade<D1: Display, D2: Display>(from_version: D1, to_version: D2) -> !
} }
fn print_start_upgrade<D1: Display, D2: Display>(from: D1, to: D2) { fn print_start_upgrade<D1: Display, D2: Display>(from: D1, to: D2) {
println!( println!("\n==================\nTrying to upgrade client from {from} to {to} ...");
"\n==================\nTrying to upgrade client from {} to {} ...",
from, to
);
} }
fn print_failed_upgrade<D1: Display, D2: Display>(from: D1, to: D2) { fn print_failed_upgrade<D1: Display, D2: Display>(from: D1, to: D2) {
eprintln!( eprintln!("Upgrade from {from} to {to} failed!\n==================\n");
"Upgrade from {} to {} failed!\n==================\n",
from, to
);
} }
fn print_successful_upgrade<D1: Display, D2: Display>(from: D1, to: D2) { fn print_successful_upgrade<D1: Display, D2: Display>(from: D1, to: D2) {
println!( println!("Upgrade from {from} to {to} was successful!\n==================\n");
"Upgrade from {} to {} was successful!\n==================\n",
from, to
);
} }
fn outdated_upgrade(config_version: &Version, package_version: &Version) -> ! { fn outdated_upgrade(config_version: &Version, package_version: &Version) -> ! {
eprintln!( eprintln!(
"Cannot perform upgrade from {} to {}. Your version is too old to perform the upgrade.!", "Cannot perform upgrade from {config_version} to {package_version}. Your version is too old to perform the upgrade.!"
config_version, package_version
); );
process::exit(1) process::exit(1)
} }
fn unsupported_upgrade(current_version: &Version, config_version: &Version) -> ! { fn unsupported_upgrade(current_version: &Version, config_version: &Version) -> ! {
eprintln!("Cannot perform upgrade from {} to {}. Please let the developers know about this issue if you expected it to work!", config_version, current_version); eprintln!("Cannot perform upgrade from {config_version} to {current_version}. Please let the developers know about this issue if you expected it to work!");
process::exit(1) process::exit(1)
} }
@@ -59,14 +49,13 @@ pub(crate) struct Upgrade {
fn parse_config_version(config: &Config) -> Version { fn parse_config_version(config: &Config) -> Version {
let version = Version::parse(config.get_base().get_version()).unwrap_or_else(|err| { let version = Version::parse(config.get_base().get_version()).unwrap_or_else(|err| {
eprintln!("failed to parse client version! - {:?}", err); eprintln!("failed to parse client version! - {err}");
process::exit(1) process::exit(1)
}); });
if version.is_prerelease() || !version.build.is_empty() { if version.is_prerelease() || !version.build.is_empty() {
eprintln!( eprintln!(
"Trying to upgrade from a non-released version {}. This is not supported!", "Trying to upgrade from a non-released version {version}. This is not supported!"
version
); );
process::exit(1) process::exit(1)
} }
@@ -81,10 +70,7 @@ fn parse_package_version() -> Version {
// however, we are not using them ourselves at the moment and hence it should be fine. // however, we are not using them ourselves at the moment and hence it should be fine.
// if we change our mind, we could easily tweak this code // if we change our mind, we could easily tweak this code
if version.is_prerelease() || !version.build.is_empty() { if version.is_prerelease() || !version.build.is_empty() {
eprintln!( eprintln!("Trying to upgrade to a non-released version {version}. This is not supported!");
"Trying to upgrade to a non-released version {}. This is not supported!",
version
);
process::exit(1) process::exit(1)
} }
@@ -110,7 +96,7 @@ fn minor_0_12_upgrade(
.set_custom_version(to_version.to_string().as_ref()); .set_custom_version(to_version.to_string().as_ref());
config.save_to_file(None).unwrap_or_else(|err| { config.save_to_file(None).unwrap_or_else(|err| {
eprintln!("failed to overwrite config file! - {:?}", err); eprintln!("failed to overwrite config file! - {err}");
print_failed_upgrade(config_version, &to_version); print_failed_upgrade(config_version, &to_version);
process::exit(1); process::exit(1);
}); });
@@ -145,8 +131,8 @@ pub(crate) fn execute(args: &Upgrade) {
let id = &args.id; 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); eprintln!("failed to load existing config file! - {err}");
process::exit(1) process::exit(1)
}); });
+1 -2
View File
@@ -1,4 +1,3 @@
use client_core::client::replies::reply_storage::fs_backend;
use client_core::error::ClientCoreError; use client_core::error::ClientCoreError;
#[derive(thiserror::Error, Debug)] #[derive(thiserror::Error, Debug)]
@@ -7,7 +6,7 @@ pub enum ClientError {
IoError(#[from] std::io::Error), IoError(#[from] std::io::Error),
#[error("client-core error: {0}")] #[error("client-core error: {0}")]
ClientCoreError(#[from] ClientCoreError<fs_backend::Backend>), ClientCoreError(#[from] ClientCoreError),
#[error("Failed to load config for: {0}")] #[error("Failed to load config for: {0}")]
FailedToLoadConfig(String), FailedToLoadConfig(String),
+6 -22
View File
@@ -1,8 +1,9 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net> // Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use clap::{crate_version, Parser}; use std::error::Error;
use error::ClientError;
use clap::{crate_name, crate_version, Parser};
use logging::setup_logging; use logging::setup_logging;
use network_defaults::setup_env; use network_defaults::setup_env;
@@ -12,28 +13,11 @@ pub mod error;
pub mod websocket; pub mod websocket;
#[tokio::main] #[tokio::main]
async fn main() -> Result<(), ClientError> { async fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
setup_logging(); setup_logging();
println!("{}", banner()); println!("{}", logging::banner(crate_name!(), crate_version!()));
let args = commands::Cli::parse(); let args = commands::Cli::parse();
setup_env(args.config_env_file.clone()); setup_env(args.config_env_file.as_ref());
commands::execute(&args).await commands::execute(&args).await
} }
fn banner() -> String {
format!(
r#"
_ __ _ _ _ __ ___
| '_ \| | | | '_ \ _ \
| | | | |_| | | | | | |
|_| |_|\__, |_| |_| |_|
|___/
(client - version {:})
"#,
crate_version!()
)
}

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