Compare commits

...

159 Commits

Author SHA1 Message Date
Jon Häggblad ddd9498c0b gateway: stray println that should be eprintln 2023-02-21 15:21:14 +01:00
farbanas bda32cfef3 docs: update changelog 2023-02-21 09:07:41 -05:00
farbanas b3425a6a6e chore: bump vesting contract 2023-02-21 09:03:56 -05:00
farbanas 9e7c77ca6a docs: update CHANGELOG.md 2023-02-21 08:59:40 -05:00
Jędrzej Stuczyński 39e75850ff Problem142 (#3025)
* revamped calculation of spendable coins and behaviour of stakes

* added new queries to the VestingQueryClient

* fixed return types for the query client

* updated wallet commands

* updated common commands

* 🔥 removed dead and commented out code

* comment regarding the 'state_dump_decoder'

* query for withdrawn coins
2023-02-21 13:55:14 +00:00
farbanas 9912e445a4 docs: updated changelogs in preparation for release 2023-02-21 07:53:08 -05:00
farbanas 02397832f4 chore: updated versions as part of preparation for release v1.1.10 2023-02-21 07:44:03 -05:00
farbanas 03fa8c17d7 docs: minor cleanup changes to changelog 2023-02-21 07:32:39 -05:00
Jon Häggblad bbb3287029 Add client functionality into nym-network-requester (#2972)
* network-requester: replace websocket with mixnet client

* network-requester: mini tidy

* network-requester: add info line about own address

* network-requester: update to nym-crypto rename
2023-02-20 13:00:34 +01:00
Tommy Verrall 494f1d5199 Merge pull request #3046 from nymtech/feature/ne-filter-by-minor-version
NE - Filter by version
2023-02-20 08:49:46 +01:00
fmtabbara 723b4b4754 small performance optimizations
fix lint error
2023-02-16 19:43:25 +00:00
Fouad dafb69d2d6 Feature/nym connect logs in app (#3045)
* remove menu bar

* create log view toggle function

* update routes

* update changelog

* fix clippy error
2023-02-16 16:15:53 +01:00
fmtabbara e225c1ee1b use minor version as latest comparator 2023-02-16 15:10:07 +00:00
Jon Häggblad 1feb53cc87 Merge pull request #3043 from nymtech/jon/chore/fix-auto-updated-files
nym-wallet: fix auto-updated files
2023-02-16 13:04:36 +01:00
Jon Häggblad bb64d8c03e wallet: minor updates to autogenerated files 2023-02-16 12:20:39 +01:00
Jon Häggblad 580cc58f42 Merge pull request #2855 from nymtech/jon/chore/add-nym-prefix-to-mixnet-and-vesting-contract-packages
contracts: add nym prefix to mixnet and vesting contract packages
2023-02-16 12:14:03 +01:00
fmtabbara 40af0f94b0 correct explorer changelog 2023-02-16 11:08:08 +00:00
Fouad c9c68ab2cb Fix send address bug (#3031)
* remove non-zero and trailing spaces

* update wallet changelog
2023-02-16 11:06:49 +00:00
Fouad 26c5fa7262 NE - Gateway version filter (#3037)
* add version filter

* allow copy gateway identity key

* use dynamic latest version value

* update explorer changelog
2023-02-16 11:03:55 +00:00
Jon Häggblad 2d59236ee8 verloc: don't shutdown listener on corrupted connection (#3036) 2023-02-15 18:14:24 +01:00
Jon Häggblad 17322ccda2 ci: update typescript-lint.yml (#3035) 2023-02-15 17:52:33 +01:00
Jon Häggblad 3d2e7d32d9 nym-connect-android fixes 2023-02-15 16:13:53 +01:00
Jon Häggblad 0b93215941 rustfmt 2023-02-15 16:13:53 +01:00
Jon Häggblad 8f4fd62957 rename pemstore to nym-pemstore 2023-02-15 16:13:53 +01:00
Jon Häggblad 4844ac953a rename crypto to nym-crypto 2023-02-15 16:13:53 +01:00
Jon Häggblad aab094984e contracts: add nym- prefix to mixnet and vesting package names 2023-02-15 16:13:53 +01:00
Jon Häggblad c8bd6b99fa nym-wallet: update Cargo.lock 2023-02-15 10:32:20 +01:00
Raphaël Walther 081d6097b6 Github Actions: Remove keybase notifications 2023-02-15 10:02:19 +01:00
farbanas 4820258270 fix: nym-cli-publish GH action resolve 2023-02-14 08:15:26 -05:00
farbanas e41a59fddc merge resolve 2023-02-14 07:50:47 -05:00
Jon Häggblad 130491e80f ci: fix get_release regex for nightly 2023-02-14 13:30:40 +01:00
farbanas 165e7d8b27 Merge branch 'release/v1.1.9' of github.com:nymtech/nym into release/v1.1.9 2023-02-14 07:30:25 -05:00
farbanas 3c97d0d16b Updated changelogs 2023-02-14 07:28:59 -05:00
Jon Häggblad 16ae72fbd9 ci: run check-merge-conflicts nightly 2023-02-14 13:25:06 +01:00
farbanas bc55c10e19 bumped versions for release/v1.1.9 2023-02-14 07:18:03 -05:00
Fouad a925c39642 Wallet - Fix operator cost in playground (#3021)
* remove upper limit restriction

* update validation
2023-02-14 12:13:19 +00:00
Jon Häggblad 4fa018540c ci: get_release name 2023-02-14 12:43:07 +01:00
Jon Häggblad e2b69b79e7 ci: update and rename check-merge-conflicts.yml 2023-02-14 12:38:57 +01:00
Fouad d23fb366e4 update changelog and fix lint errors (#3023)
add unreleased tag into NC changelog
2023-02-14 10:46:10 +00:00
Jon Häggblad be369c2023 ci: another fix to check-git-branches.yml 2023-02-14 11:17:59 +01:00
Bogdan-Ștefan Neacșu 7e90ff8b85 Fix nyxd typo 2023-02-14 12:17:11 +02:00
Jon Häggblad f5c5b342bb ci: fix check-git-branches.yml 2023-02-14 11:15:19 +01:00
Jon Häggblad af9cf52b1e ci: add workflow for checking if branches merge 2023-02-14 11:01:28 +01:00
Bogdan-Ștefan Neacşu 3d500c25c5 Hide coconut runtime flags (#2990) 2023-02-14 11:58:04 +02:00
Jon Häggblad 3b9fb9088d ci: tweak git-merge-check.sh 2023-02-14 10:23:08 +01:00
Jon Häggblad c95b5f0982 ci: add script for checking if branches merge successfully 2023-02-14 10:19:28 +01:00
Jon Häggblad 7cca3c716a mixnode: upgrade sysinfo dependency (#3022)
Fixes build on windows with nightly rustc due to

    https://github.com/MSxDOS/ntapi/issues/11
2023-02-14 06:51:12 +01:00
Fouad 9348722b84 Feature/nym connect pick a gateway (#3008)
* Add new route and initial UI

* allow IdentityKeyFormField to have a small size option

* add disabled prop to the shared IdentityKeyFormField component

* defined custom gateway type

* use custom gateway in state

* set and validate custom gateway in settings page

* validate user gateway when moving away from page

* use storage

* hide gateway input when inactive

* add explorer link to settings page
2023-02-13 22:47:48 +00:00
Jon Häggblad fd1fb7ca7b rust-sdk: fix clippy in example (#3020) 2023-02-13 15:22:39 +01:00
Jon Häggblad 6252b66724 ci: keep the 3 nightly builds in sync (#3018) 2023-02-13 15:00:24 +01:00
Jon Häggblad b770cab3f0 nym-wallet: update Cargo.lock to fix security advisories (#3015) 2023-02-13 13:36:39 +01:00
Fouad 726a406797 update add account instructions (#2981)
* update add account instructions
2023-02-13 10:55:53 +00:00
Fouad 4652d65874 Update password strength checking (#2994)
* use zxcvbn password strength checker

* prevent user from proceeding with a weak password + add tips

* create storybook for password strength component

* update storybook

* update password-strength
2023-02-13 10:27:04 +00:00
Fouad a4ca94ccef dont force user to copy mnemonic (#2992)
* dont force user to copy mnemonic

* add title to mnemonic page
2023-02-13 10:26:37 +00:00
Pierre Dommerc e69552b19d fix(nc-android): disable landscape mode (#3012)
* fix(nc-android): disable landscape mode

* feat(nc-android): UI sizing
2023-02-10 17:43:51 +01:00
pierre e3cc43487a fix(nc-andoird): apk build 2023-02-10 16:13:17 +01:00
pierre 41be555aa6 ci(nc-android): fix build 2023-02-10 13:44:51 +01:00
pierre bdc0bcbd56 ci(nc-android): fix gradle build 2023-02-10 12:29:35 +01:00
Jon Häggblad 0baa8b2c92 rust-sdk: improve send api (#3011)
* nym-sdk: remove unneeded function

* rust-sdk: rework send api a bit

* rust-sdk: add send_wait without impl

* fix doc test failures

* more doctest fixes
2023-02-10 11:07:48 +01:00
pierre 2ab969b2c6 ci(nc-android): debug workflow, use precompiled tauri cli 2023-02-09 22:47:28 +01:00
pierre 9f2e7e16e5 ci(nc-android): fix workflow apk build 2023-02-09 18:53:50 +01:00
pierre 1c99446bcc ci(nc-android): fix workflow for nc android apk upload 2023-02-09 18:21:55 +01:00
Pierre Dommerc 90d9c9ec41 feat(nc-android): add nym icon launchers (#3007) 2023-02-09 17:17:00 +01:00
Jon Häggblad 2e38c5e38e nym-sdk: remove a few unwraps related to creating reply surb storage (#3006) 2023-02-09 16:55:01 +01:00
Bogdan-Ștefan Neacşu dbb7a27441 Feature/stabilize credential deposit (#3002) 2023-02-09 16:55:18 +02:00
Jon Häggblad 89c05387f8 rust-sdk: add two more examples (#3003) 2023-02-09 15:43:12 +01:00
Jon Häggblad 7952277c4b rust-sdk: restructure API to builder pattern (#3000) 2023-02-09 14:58:42 +01:00
Pierre Dommerc c5866db137 feat(nc-android): sync with nc desktop (new design) (#2971)
* feat(nc-android): fit the design to mobile

* refactor(nc-android): resync with nc desktop

* fix(nc-android): tauri version

* refactor(nc-android): resync with nc desktop (rust)

* chore(nc-android): format code

* chore(nc-android): bump version
2023-02-09 14:26:19 +01:00
Dave Hrycyszyn 37187c79cc Merge branch 'master' into develop 2023-02-08 16:54:27 +00:00
Dave Hrycyszyn 24839770ff Fixing Cargo.lock to include updated version of nym-api 2023-02-08 16:54:09 +00:00
Dave Hrycyszyn 0238499e33 Changelog bump to trigger nym-connect build 2023-02-08 16:48:17 +00:00
Dave Hrycyszyn 3363230c4c Building the SDK package and only selected examples 2023-02-08 16:48:17 +00:00
pierre 1f8b373780 fix(nym-connect): lint errors 2023-02-08 16:48:17 +00:00
Dave Hrycyszyn 7ac3ec3598 Merge branch 'release/v1.1.9' 2023-02-08 16:21:57 +00:00
Dave Hrycyszyn 77ae71eba4 Changelog bump to trigger nym-connect build 2023-02-08 16:15:33 +00:00
Dave Hrycyszyn d4b836277e Merge branch 'release/v1.1.9' 2023-02-08 16:04:49 +00:00
Dave Hrycyszyn b92ee84874 Building the SDK package and only selected examples 2023-02-08 15:56:30 +00:00
pierre 2eb0ce381a fix(nym-connect): lint errors 2023-02-08 16:36:00 +01:00
Jon Häggblad 037cd54573 Merge branch 'release/v1.1.9' into develop 2023-02-08 13:45:37 +01:00
Jon Häggblad 9f42f0152b Merge branch 'release/v1.1.9' 2023-02-08 13:27:32 +01:00
Dave Hrycyszyn 5217edcca3 Changelog tweaks 2023-02-08 13:14:12 +01:00
joeiacono2021 e306effdac Merge branch 'release/v1.1.9' of https://github.com/nymtech/nym into release/v1.1.9 2023-02-08 13:14:12 +01:00
joeiacono2021 dc2b1c6d2a changelog changes for release 1.1.9 2023-02-08 13:14:12 +01:00
Jon Häggblad 4232801e80 changelog: add note about fix for unexpected shutdown 2023-02-08 13:14:12 +01:00
Fouad 96df3ad4ce Feature/nym connect health status frontend (#2969)
* filter services on rust side by gateway performance

* format rust code

* create events hook

* use events hook

* remove unused component

remove unused component

update prop names in svg

* display errors in connected screen when needed

update failed health check message
2023-02-08 13:14:12 +01:00
Fouad d614a2b81b link owner field to ng explorer (#2970)
* link owner field to ng explorer
2023-02-08 13:14:12 +01:00
Fouad d27245e184 filter services on rust side by gateway performance (#2966)
* filter services on rust side by gateway performance

* update changelog for NC
2023-02-08 13:14:12 +01:00
Mark Sinclair 5dbfcadfdb GitHub Actions: fix up build-and-upload-binaries-ci.yml 2023-02-08 13:14:12 +01:00
Jędrzej Stuczyński 035dada0e0 introduced '/circulating-supply/total-supply-value' and '/circulating-supply/circulating-supply-value' endpoints (#2965) 2023-02-08 13:14:12 +01:00
Mark Sinclair 1d867156e3 Update build-and-upload-binaries-ci.yml 2023-02-08 13:14:12 +01:00
Mark Sinclair ed9be47ec4 Update build-and-upload-binaries-ci.yml 2023-02-08 13:14:12 +01:00
Mark Sinclair 3aa2e6c54d Update build-and-upload-binaries-ci.yml 2023-02-08 13:14:12 +01:00
Mark Sinclair eb96fc72b9 GitHub Actions: add action to build and upload binaries to CI server 2023-02-08 13:14:12 +01:00
Jon Häggblad 59cec6f03c Don't drop in mixnet connection handlers (#2963) 2023-02-08 13:14:12 +01:00
Fouad c0a0d89a90 NymConnect - Add button animations (#2950)
* add button animations

* pulse and disable button on connecting/disconnecting status

* update button component story

* disabled hover on connecting/disconnecting

* add transition delay

fix up overflow
2023-02-08 13:14:12 +01:00
Bogdan-Ștefan Neacşu 3099f2ead3 Hide coconut runtime flags (#2990) 2023-02-08 13:00:17 +01:00
Bogdan-Ștefan Neacşu baf88ce10a Skip errors on blind sign within threshold (#2976) 2023-02-08 11:45:39 +01:00
Jędrzej Stuczyński 362e7f2fea 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-08 08:59:48 +01:00
Bogdan-Ștefan Neacşu d89081d8a1 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-08 08:59:48 +01:00
Pierre Dommerc eeba17a01f 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-08 08:59:48 +01:00
Jon Häggblad 25762900fa Remove all the .DS_Store files and add to gitignore (#2974) 2023-02-08 08:59:48 +01:00
Bogdan-Ștefan Neacşu 3bc7f281b4 Fix typo during merge back to develop (#2956) 2023-02-08 08:59:48 +01:00
Jędrzej Stuczyński 3e23bdf3c0 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-08 08:59:48 +01:00
cgi-bin/ 5a89e894a9 typo: electrum (#2954) 2023-02-08 08:59:48 +01:00
Pierre Dommerc 795977a75d 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-08 08:59:48 +01:00
farbanas 8dbddb7b7e fix: formatting 2023-02-08 08:59:48 +01:00
Mark Sinclair 4e057cd250 Update build-and-upload-binaries-ci.yml 2023-02-08 08:59:48 +01:00
farbanas b62c969a7c fix: wrong parameter type for addresses in generator commands (should be AccountId instead of String) 2023-02-08 08:59:48 +01:00
Mark Sinclair be1ec79b01 Update build-and-upload-binaries-ci.yml 2023-02-08 08:59:48 +01:00
Fran Arbanas 5d10e62450 Update CHANGELOG.md 2023-02-08 08:59:48 +01:00
Mark Sinclair 64acddead6 Update build-and-upload-binaries-ci.yml 2023-02-08 08:59:48 +01:00
Mark Sinclair 8bbf766eeb Update build-and-upload-binaries-ci.yml 2023-02-08 08:59:48 +01:00
Mark Sinclair d7cd942dec Update build-and-upload-binaries-ci.yml 2023-02-08 08:59:48 +01:00
Mark Sinclair a9124a63f9 Update build-and-upload-binaries-ci.yml 2023-02-08 08:59:48 +01:00
Mark Sinclair b0d7169b39 Update build-and-upload-binaries-ci.yml 2023-02-08 08:59:48 +01:00
Mark Sinclair d57b486bf4 GitHub Actions: add action to build and upload binaries to CI server 2023-02-08 08:59:48 +01:00
Bogdan-Ștefan Neacșu ef8ecd42a3 Fix flaky dkg test 2023-02-08 08:59:48 +01:00
dependabot[bot] 02e1dc01af 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-08 08:59:48 +01:00
dependabot[bot] b29bd8bcc3 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-08 08:59:48 +01:00
dependabot[bot] 9ad9fd36e2 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-08 08:59:48 +01:00
Tommy Verrall bd61679c58 Binary checker, introduction 2023-02-08 08:59:48 +01:00
Jon Häggblad 21e636616d Merge tag 'nym-binaries-v1.1.8' into develop 2023-02-08 08:25:24 +01:00
farbanas 9881a94757 bumped nym-api version 2023-02-03 15:12:18 +01:00
Jędrzej Stuczyński 76b07d487b introduced '/circulating-supply/total-supply-value' and '/circulating-supply/circulating-supply-value' endpoints (#2965) 2023-02-03 13:37:55 +00: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 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
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
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
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
farbanas 538bcf1d0a merge resolve 2023-01-24 13:25:25 +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
farbanas 58d15429de feat: change Github hosted ubuntu-20.04 runners for our own custom-runner-linux 2023-01-17 13:05:35 +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
729 changed files with 38134 additions and 8430 deletions
Vendored
BIN
View File
Binary file not shown.
+2 -6
View File
@@ -39,18 +39,14 @@ jobs:
uses: actions/setup-node@v3
with:
node-version: 16
- name: Keybase - Node Install
- name: Matrix - Node Install
run: npm install
working-directory: .github/workflows/support-files
- name: Keybase - Send Notification
- name: Matrix - Send Notification
env:
NYM_NOTIFICATION_KIND: security
NYM_PROJECT_NAME: "Daily security report"
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
KEYBASE_NYMBOT_USERNAME: "${{ secrets.KEYBASE_NYMBOT_USERNAME }}"
KEYBASE_NYMBOT_PAPERKEY: "${{ secrets.KEYBASE_NYMBOT_PAPERKEY }}"
KEYBASE_NYMBOT_TEAM: "${{ secrets.KEYBASE_NYMBOT_TEAM }}"
KEYBASE_NYM_CHANNEL: "security"
MATRIX_SERVER: "${{ secrets.MATRIX_SERVER }}"
MATRIX_ROOM: "${{ secrets.MATRIX_ROOM }}"
MATRIX_USER_ID: "${{ secrets.MATRIX_USER_ID }}"
@@ -0,0 +1,112 @@
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/"
+2 -6
View File
@@ -43,10 +43,10 @@ jobs:
REMOTE_USER: ${{ secrets.CI_WWW_REMOTE_USER }}
TARGET: ${{ secrets.CI_WWW_REMOTE_TARGET }}/ts-${{ env.GITHUB_REF_SLUG }}-example
EXCLUDE: "/dist/, /node_modules/"
- name: Keybase - Node Install
- name: Matrix - Node Install
run: npm install
working-directory: .github/workflows/support-files
- name: Keybase - Send Notification
- name: Matrix - Send Notification
env:
NYM_NOTIFICATION_KIND: ts-packages
NYM_PROJECT_NAME: "ts-packages"
@@ -54,10 +54,6 @@ jobs:
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 }}"
+30 -28
View File
@@ -2,11 +2,33 @@ name: Continuous integration
on:
push:
paths-ignore:
- 'explorer/**'
paths:
- 'clients/**'
- 'common/**'
- 'explorer-api/**'
- 'gateway/**'
- 'integrations/**'
- 'mixnode/**'
- 'sdk/rust/nym-sdk/**'
- 'service-providers/**'
- 'nym-api/**'
- 'nym-outfox/**'
- 'tools/nym-cli/**'
- 'tools/ts-rs-cli/**'
pull_request:
paths-ignore:
- 'explorer/**'
paths:
- 'clients/**'
- 'common/**'
- 'explorer-api/**'
- 'gateway/**'
- 'integrations/**'
- 'mixnode/**'
- 'sdk/rust/nym-sdk/**'
- 'service-providers/**'
- 'nym-api/**'
- 'nym-outfox/**'
- 'tools/nym-cli/**'
- 'tools/ts-rs-cli/**'
jobs:
build:
@@ -52,44 +74,24 @@ jobs:
uses: actions-rs/cargo@v1
with:
command: test
args: --workspace --all-features
args: --workspace
- name: Run expensive tests
if: github.ref == 'refs/heads/develop' || github.event.pull_request.base.ref == 'develop' || github.event.pull_request.base.ref == 'master'
uses: actions-rs/cargo@v1
with:
command: test
args: --workspace --all-features -- --ignored
args: --workspace -- --ignored
- uses: actions-rs/clippy-check@v1
name: Clippy checks
continue-on-error: true
with:
token: ${{ secrets.GITHUB_TOKEN }}
args: --workspace --all-features
args: --workspace
- name: Run clippy
uses: actions-rs/cargo@v1
with:
command: clippy
args: --workspace --all-targets --all-features -- -D warnings
# COCONUT stuff
- name: Build all binaries with coconut enabled
uses: actions-rs/cargo@v1
with:
command: build
args: --workspace --features=coconut
- name: Run all tests with coconut enabled
uses: actions-rs/cargo@v1
with:
command: test
args: --workspace --features=coconut
- name: Run clippy with coconut enabled
uses: actions-rs/cargo@v1
with:
command: clippy
args: --all-targets --features=coconut -- -D warnings
args: --workspace --all-targets -- -D warnings
@@ -0,0 +1,61 @@
name: check-merge-conflicts
# Check that the latest release branch merges into master and develop without
# any conflicts that git is not able to resolve
on:
workflow_dispatch:
schedule:
- cron: '5 6 * * *'
jobs:
get_release:
runs-on: ubuntu-latest
outputs:
output1: ${{ steps.step2.outputs.latest_release }}
steps:
- name: Check out repository code
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Set output variable to latest release branch
id: step2
run: echo "latest_release=$(git branch -r | grep -E 'release/v[0-9]+\.[0-9]+\.[0-9]+$' | sort -V | tail -n 1)" >> $GITHUB_OUTPUT
check-merge-release-into-master:
name: Check that the release branch merges into master
needs: get_release
runs-on: ubuntu-latest
steps:
- name: Checkout repo
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Setup git user
run: |
git config --global user.name "ci"
git config --global user.email "ci@localhost"
- name: Check merge release branch into master
run: |
./.github/workflows/support-files/git-merge-check.sh origin/master $branch1
env:
branch1: ${{needs.get_release.outputs.output1}}
check-merge-release-into-develop:
name: Check that the release branch merges into develop
needs: get_release
runs-on: ubuntu-latest
steps:
- name: Checkout repo
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Setup git user
run: |
git config --global user.name "ci"
git config --global user.email "ci@localhost"
- name: Check merge release branch into develop
run: |
./.github/workflows/support-files/git-merge-check.sh origin/develop $branch1
env:
branch1: ${{needs.get_release.outputs.output1}}
+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
+17 -2
View File
@@ -2,8 +2,23 @@ name: Nym Connect (rust)
on:
push:
paths-ignore:
- 'explorer/**'
paths:
- 'nym-connect/**'
- 'clients/client-core/**'
- 'clients/socks5/**'
- 'common/**'
- 'gateway/gateway-requests/**'
- 'contracts/vesting/**'
- 'nym-api/nym-api-requests/**'
pull_request:
paths:
- 'nym-connect/**'
- 'clients/client-core/**'
- 'clients/socks5/**'
- 'common/**'
- 'gateway/gateway-requests/**'
- 'contracts/vesting/**'
- 'nym-api/nym-api-requests/**'
jobs:
build:
+2 -8
View File
@@ -6,17 +6,11 @@ on:
jobs:
build:
runs-on: ubuntu-20.04
if: ${{ startsWith(github.ref, 'refs/tags/nym-contracts-') && github.event_name == 'release' }}
runs-on: [self-hosted, custom-runner-linux]
steps:
- uses: actions/checkout@v2
- name: Check the release tag starts with `nym-contracts-`
if: startsWith(github.ref, 'refs/tags/nym-contracts-') == false && github.event_name != 'workflow_dispatch'
uses: actions/github-script@v3
with:
script: |
core.setFailed('Release tag did not start with nym-contracts-...')
- name: Install Rust stable
uses: actions-rs/toolchain@v1
with:
+5 -3
View File
@@ -2,11 +2,13 @@ name: Contracts
on:
push:
paths-ignore:
- 'explorer/**'
paths:
- 'contracts/**'
- 'common/**'
pull_request:
paths-ignore:
- 'explorer/**'
- 'contracts/**'
- 'common/**'
jobs:
matrix_prep:
+134
View File
@@ -0,0 +1,134 @@
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: custom-runner-linux
env:
ANDROID_HOME: ${{ github.workspace }}/android-sdk
NDK_VERSION: 25.1.8937393
NDK_HOME: ${{ github.workspace }}/android-sdk/ndk/25.1.8937393
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 \
unzip \
curl \
wget \
libssl-dev \
libgtk-3-dev \
squashfs-tools \
libayatana-appindicator3-dev \
librsvg2-dev
- name: Checkout
uses: actions/checkout@v3
- 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: 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:
ANDROID_SDK_ROOT: ${{ env.ANDROID_HOME }}
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 --split-per-abi -t aarch64
# TODO add the version number to APK name
- name: Rename APK artifact
run: |
mkdir apk/
mv nym-connect-android/src-tauri/gen/android/nym_connect_android/app/build/outputs/apk/arm64/debug/app-arm64-debug.apk \
apk/nym-connect-arm64-debug.apk
mv nym-connect-android/src-tauri/gen/android/nym_connect_android/app/build/outputs/apk/x86_64/debug/app-x86_64-debug.apk \
apk/nym-connect-x86_64-debug.apk
- name: Upload APK artifact
uses: actions/upload-artifact@v3
with:
name: nc-apk-debug
path: |
apk/nym-connect-arm64-debug.apk
apk/nym-connect-x86_64-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: ???
+1 -1
View File
@@ -10,6 +10,7 @@ env:
jobs:
publish-nym:
if: ${{ startsWith(github.ref, 'refs/tags/nym-explorer-api-') && (github.event_name == 'release' || github.event_name == 'workflow_dispatch') }}
strategy:
fail-fast: false
matrix:
@@ -24,7 +25,6 @@ jobs:
continue-on-error: true
- name: Check the release tag starts with `nym-explorer-api-`
if: startsWith(github.ref, 'refs/tags/nym-explorer-api-') == false && github.event_name != 'workflow_dispatch'
uses: actions/github-script@v3
with:
script: |
+2 -6
View File
@@ -57,10 +57,10 @@ jobs:
REMOTE_USER: ${{ secrets.CI_WWW_REMOTE_USER }}
TARGET: ${{ secrets.CI_WWW_REMOTE_TARGET }}/ne-sb-${{ env.GITHUB_REF_SLUG }}
EXCLUDE: "/dist/, /node_modules/"
- name: Keybase - Node Install
- name: Matrix - Node Install
run: npm install
working-directory: .github/workflows/support-files
- name: Keybase - Send Notification
- name: Matrix - Send Notification
env:
NYM_NOTIFICATION_KIND: network-explorer
NYM_PROJECT_NAME: "Network Explorer"
@@ -69,10 +69,6 @@ jobs:
NYM_CI_WWW_LOCATION_STORYBOOK: "ne-sb-${{ 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-network-explorer"
IS_SUCCESS: "${{ job.status == 'success' }}"
MATRIX_SERVER: "${{ secrets.MATRIX_SERVER }}"
MATRIX_ROOM: "${{ secrets.MATRIX_ROOM }}"
+9 -45
View File
@@ -10,7 +10,7 @@ jobs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
steps:
# creates the matrix strategy from nightly_build_matrix_includes.json
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- id: set-matrix
uses: JoshuaTheMiller/conditional-build-matrix@main
with:
@@ -29,7 +29,7 @@ jobs:
if: matrix.os == 'ubuntu-20.04'
- name: Check out repository code
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: Install rust toolchain
uses: actions-rs/toolchain@v1
@@ -77,7 +77,7 @@ jobs:
- name: Reclaim some disk space (because Windows is being annoying)
uses: actions-rs/cargo@v1
if: ${{ matrix.os == 'windows-latest' }}
if: ${{ matrix.os == 'windows-latest' || matrix.os == 'ubuntu-20.04' }}
with:
command: clean
@@ -86,7 +86,7 @@ jobs:
uses: actions-rs/cargo@v1
with:
command: test
args: --workspace --all-features -- --ignored
args: --workspace -- --ignored
- name: Reclaim some disk space (because Windows is being annoying)
uses: actions-rs/cargo@v1
@@ -99,14 +99,14 @@ jobs:
continue-on-error: true
with:
token: ${{ secrets.GITHUB_TOKEN }}
args: --all-features
args: --workspace
- name: Run clippy
uses: actions-rs/cargo@v1
if: ${{ matrix.rust != 'nightly' }}
with:
command: clippy
args: --workspace --all-targets --all-features -- -D warnings
args: --workspace --all-targets -- -D warnings
- name: Reclaim some disk space
uses: actions-rs/cargo@v1
@@ -114,38 +114,6 @@ jobs:
with:
command: clean
# COCONUT stuff
- name: Build all binaries with coconut enabled
uses: actions-rs/cargo@v1
with:
command: build
args: --workspace --features=coconut
- name: Reclaim some disk space (because Windows is being annoying)
uses: actions-rs/cargo@v1
if: ${{ matrix.os == 'windows-latest' }}
with:
command: clean
- name: Run all tests with coconut enabled
uses: actions-rs/cargo@v1
with:
command: test
args: --workspace --features=coconut
- name: Reclaim some disk space (because Windows is being annoying)
uses: actions-rs/cargo@v1
if: ${{ matrix.os == 'windows-latest' }}
with:
command: clean
- name: Run clippy with coconut enabled
uses: actions-rs/cargo@v1
if: ${{ matrix.rust != 'nightly' }}
with:
command: clippy
args: --workspace --all-targets --features=coconut -- -D warnings
# nym-wallet (the rust part)
- name: Build nym-wallet rust code
uses: actions-rs/cargo@v1
@@ -179,17 +147,17 @@ jobs:
- name: Collect jobs status
uses: technote-space/workflow-conclusion-action@v2
- name: Check out repository code
uses: actions/checkout@v2
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: Matrix - Node Install
if: env.WORKFLOW_CONCLUSION == 'failure'
run: npm install
working-directory: .github/workflows/support-files
- name: Keybase - Send Notification
- name: Matrix - Send Notification
if: env.WORKFLOW_CONCLUSION == 'failure'
env:
NYM_NOTIFICATION_KIND: nightly
@@ -197,10 +165,6 @@ jobs:
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
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-nightly"
IS_SUCCESS: "${{ env.WORKFLOW_CONCLUSION == 'success' }}"
MATRIX_SERVER: "${{ secrets.MATRIX_SERVER }}"
MATRIX_ROOM: "${{ secrets.MATRIX_ROOM }}"
+24 -48
View File
@@ -28,7 +28,7 @@ jobs:
run: git fetch --all
- name: Set output variable to latest release branch
id: step2
run: echo "latest_release=$(git branch -r | grep -E 'release/v[0-9]+\.[0-9]+\.[0-9]+' | tail -n 1 | sed 's/ origin\///')" >> $GITHUB_OUTPUT
run: echo "latest_release=$(git branch -r | grep -E 'release/v[0-9]+\.[0-9]+\.[0-9]+$' | sort -V | tail -n 1 | sed 's/ origin\///')" >> $GITHUB_OUTPUT
build:
needs: [get_release,matrix_prep]
strategy:
@@ -54,6 +54,12 @@ jobs:
override: true
components: rustfmt, clippy
- name: Check formatting
uses: actions-rs/cargo@v1
with:
command: fmt
args: --all -- --check
- name: Build all binaries
uses: actions-rs/cargo@v1
with:
@@ -66,6 +72,18 @@ jobs:
with:
command: clean
- name: Build all examples
uses: actions-rs/cargo@v1
with:
command: build
args: --workspace --examples
- name: Reclaim some disk space (because Windows is being annoying)
uses: actions-rs/cargo@v1
if: ${{ matrix.os == 'windows-latest' }}
with:
command: clean
- name: Run all tests
uses: actions-rs/cargo@v1
with:
@@ -74,7 +92,7 @@ jobs:
- name: Reclaim some disk space (because Windows is being annoying)
uses: actions-rs/cargo@v1
if: ${{ matrix.os == 'windows-latest' }}
if: ${{ matrix.os == 'windows-latest' || matrix.os == 'ubuntu-20.04' }}
with:
command: clean
@@ -83,13 +101,7 @@ jobs:
uses: actions-rs/cargo@v1
with:
command: test
args: --workspace --all-features -- --ignored
- name: Check formatting
uses: actions-rs/cargo@v1
with:
command: fmt
args: --all -- --check
args: --workspace -- --ignored
- name: Reclaim some disk space (because Windows is being annoying)
uses: actions-rs/cargo@v1
@@ -102,7 +114,7 @@ jobs:
continue-on-error: true
with:
token: ${{ secrets.GITHUB_TOKEN }}
args: --all-features
args: --workspace
- name: Run clippy
uses: actions-rs/cargo@v1
@@ -117,38 +129,6 @@ jobs:
with:
command: clean
# COCONUT stuff
- name: Build all binaries with coconut enabled
uses: actions-rs/cargo@v1
with:
command: build
args: --workspace --features=coconut
- name: Reclaim some disk space (because Windows is being annoying)
uses: actions-rs/cargo@v1
if: ${{ matrix.os == 'windows-latest' }}
with:
command: clean
- name: Run all tests with coconut enabled
uses: actions-rs/cargo@v1
with:
command: test
args: --workspace --features=coconut
- name: Reclaim some disk space (because Windows is being annoying)
uses: actions-rs/cargo@v1
if: ${{ matrix.os == 'windows-latest' }}
with:
command: clean
- name: Run clippy with coconut enabled
uses: actions-rs/cargo@v1
if: ${{ matrix.rust != 'nightly' }}
with:
command: clippy
args: --workspace --all-targets --features=coconut -- -D warnings
# nym-wallet (the rust part)
- name: Build nym-wallet rust code
uses: actions-rs/cargo@v1
@@ -188,11 +168,11 @@ jobs:
if: env.WORKFLOW_CONCLUSION == 'failure'
with:
node-version: 16
- name: Keybase - Node Install
- name: Matrix - Node Install
if: env.WORKFLOW_CONCLUSION == 'failure'
run: npm install
working-directory: .github/workflows/support-files
- name: Keybase - Send Notification
- name: Matrix - Send Notification
if: env.WORKFLOW_CONCLUSION == 'failure'
env:
NYM_NOTIFICATION_KIND: nightly
@@ -200,10 +180,6 @@ jobs:
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
GIT_COMMIT_MESSAGE: "${{ github.event.head_commit.message }}"
GIT_BRANCH_NAME: "${{needs.get_release.outputs.output1}}"
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-nightly-release"
IS_SUCCESS: "${{ env.WORKFLOW_CONCLUSION == 'success' }}"
MATRIX_SERVER: "${{ secrets.MATRIX_SERVER }}"
MATRIX_ROOM: "${{ secrets.MATRIX_ROOM }}"
+24 -48
View File
@@ -28,7 +28,7 @@ jobs:
run: git fetch --all
- name: Set output variable to latest release branch
id: step2
run: echo "latest_release=$(git branch -r | grep -E 'release/v[0-9]+\.[0-9]+\.[0-9]+' | tail -n 2 | head -n 1 | sed 's/ origin\///')" >> $GITHUB_OUTPUT
run: echo "latest_release=$(git branch -r | grep -E 'release/v[0-9]+\.[0-9]+\.[0-9]+$' | sort -V | tail -n 2 | head -n 1 | sed 's/ origin\///')" >> $GITHUB_OUTPUT
build:
needs: [get_release,matrix_prep]
strategy:
@@ -54,6 +54,12 @@ jobs:
override: true
components: rustfmt, clippy
- name: Check formatting
uses: actions-rs/cargo@v1
with:
command: fmt
args: --all -- --check
- name: Build all binaries
uses: actions-rs/cargo@v1
with:
@@ -66,6 +72,18 @@ jobs:
with:
command: clean
- name: Build all examples
uses: actions-rs/cargo@v1
with:
command: build
args: --workspace --examples
- name: Reclaim some disk space (because Windows is being annoying)
uses: actions-rs/cargo@v1
if: ${{ matrix.os == 'windows-latest' }}
with:
command: clean
- name: Run all tests
uses: actions-rs/cargo@v1
with:
@@ -74,7 +92,7 @@ jobs:
- name: Reclaim some disk space (because Windows is being annoying)
uses: actions-rs/cargo@v1
if: ${{ matrix.os == 'windows-latest' }}
if: ${{ matrix.os == 'windows-latest' || matrix.os == 'ubuntu-20.04' }}
with:
command: clean
@@ -83,13 +101,7 @@ jobs:
uses: actions-rs/cargo@v1
with:
command: test
args: --workspace --all-features -- --ignored
- name: Check formatting
uses: actions-rs/cargo@v1
with:
command: fmt
args: --all -- --check
args: --workspace -- --ignored
- name: Reclaim some disk space (because Windows is being annoying)
uses: actions-rs/cargo@v1
@@ -102,7 +114,7 @@ jobs:
continue-on-error: true
with:
token: ${{ secrets.GITHUB_TOKEN }}
args: --all-features
args: --workspace
- name: Run clippy
uses: actions-rs/cargo@v1
@@ -117,38 +129,6 @@ jobs:
with:
command: clean
# COCONUT stuff
- name: Build all binaries with coconut enabled
uses: actions-rs/cargo@v1
with:
command: build
args: --workspace --features=coconut
- name: Reclaim some disk space (because Windows is being annoying)
uses: actions-rs/cargo@v1
if: ${{ matrix.os == 'windows-latest' }}
with:
command: clean
- name: Run all tests with coconut enabled
uses: actions-rs/cargo@v1
with:
command: test
args: --workspace --features=coconut
- name: Reclaim some disk space (because Windows is being annoying)
uses: actions-rs/cargo@v1
if: ${{ matrix.os == 'windows-latest' }}
with:
command: clean
- name: Run clippy with coconut enabled
uses: actions-rs/cargo@v1
if: ${{ matrix.rust != 'nightly' }}
with:
command: clippy
args: --workspace --all-targets --features=coconut -- -D warnings
# nym-wallet (the rust part)
- name: Build nym-wallet rust code
uses: actions-rs/cargo@v1
@@ -188,11 +168,11 @@ jobs:
if: env.WORKFLOW_CONCLUSION == 'failure'
with:
node-version: 16
- name: Keybase - Node Install
- name: Matrix - Node Install
if: env.WORKFLOW_CONCLUSION == 'failure'
run: npm install
working-directory: .github/workflows/support-files
- name: Keybase - Send Notification
- name: Matrix - Send Notification
if: env.WORKFLOW_CONCLUSION == 'failure'
env:
NYM_NOTIFICATION_KIND: nightly
@@ -200,10 +180,6 @@ jobs:
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
GIT_COMMIT_MESSAGE: "${{ github.event.head_commit.message }}"
GIT_BRANCH_NAME: "${{needs.get_release.outputs.output1}}"
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-nightly-release"
IS_SUCCESS: "${{ env.WORKFLOW_CONCLUSION == 'success' }}"
MATRIX_SERVER: "${{ secrets.MATRIX_SERVER }}"
MATRIX_ROOM: "${{ secrets.MATRIX_ROOM }}"
+1 -1
View File
@@ -10,6 +10,7 @@ env:
jobs:
publish-nym-cli:
if: ${{ startsWith(github.ref, 'refs/tags/nym-cli-') && (github.event_name == 'release' || github.event_name == 'workflow_dispatch') }}
strategy:
fail-fast: false
matrix:
@@ -20,7 +21,6 @@ jobs:
- uses: actions/checkout@v3
- name: Check the release tag starts with `nym-cli-`
if: startsWith(github.ref, 'refs/tags/nym-cli-') == false && github.event_name != 'workflow_dispatch'
uses: actions/github-script@v3
with:
script: |
@@ -10,6 +10,7 @@ defaults:
jobs:
publish-tauri:
if: ${{ startsWith(github.ref, 'refs/tags/nym-connect-') && github.event_name == 'release' }}
strategy:
fail-fast: false
matrix:
@@ -19,13 +20,6 @@ jobs:
steps:
- uses: actions/checkout@v2
- name: Check the release tag starts with `nym-connect-`
if: startsWith(github.ref, 'refs/tags/nym-connect-') == false && github.event_name != 'workflow_dispatch'
uses: actions/github-script@v3
with:
script: |
core.setFailed('Release tag did not start with nym-connect-...')
- name: Node v16
uses: actions/setup-node@v3
with:
@@ -10,10 +10,11 @@ defaults:
jobs:
publish-tauri:
if: ${{ startsWith(github.ref, 'refs/tags/nym-connect-') && github.event_name == 'release' }}
strategy:
fail-fast: false
matrix:
platform: [ubuntu-20.04]
platform: [custom-runner-linux]
runs-on: ${{ matrix.platform }}
steps:
@@ -24,17 +25,12 @@ jobs:
sudo apt-get update &&
sudo apt-get install -y webkit2gtk-4.0 libayatana-appindicator3-dev
continue-on-error: true
- name: Check the release tag starts with `nym-connect-`
if: startsWith(github.ref, 'refs/tags/nym-connect-') == false && github.event_name != 'workflow_dispatch'
uses: actions/github-script@v3
with:
script: |
core.setFailed('Release tag did not start with nym-connect-...')
- name: Node v16
uses: actions/setup-node@v3
with:
node-version: 16
- name: Install Rust stable
uses: actions-rs/toolchain@v1
with:
@@ -10,6 +10,7 @@ defaults:
jobs:
publish-tauri:
if: ${{ startsWith(github.ref, 'refs/tags/nym-connect-') && github.event_name == 'release' }}
strategy:
fail-fast: false
matrix:
@@ -27,13 +28,6 @@ jobs:
- uses: actions/checkout@v3
- name: Check the release tag starts with `nym-connect-`
if: startsWith(github.ref, 'refs/tags/nym-connect-') == false && github.event_name != 'workflow_dispatch'
uses: actions/github-script@v3
with:
script: |
core.setFailed('Release tag did not start with nym-connect-...')
- name: Import signing certificate
env:
WINDOWS_CERTIFICATE: ${{ secrets.WINDOWS_CERTIFICATE }}
+2 -6
View File
@@ -39,10 +39,10 @@ jobs:
REMOTE_USER: ${{ secrets.CI_WWW_REMOTE_USER }}
TARGET: ${{ secrets.CI_WWW_REMOTE_TARGET }}/nym-connect-${{ env.GITHUB_REF_SLUG }}
EXCLUDE: "/dist/, /node_modules/"
- name: Keybase - Node Install
- name: Matrix - Node Install
run: npm install
working-directory: .github/workflows/support-files
- name: Keybase - Send Notification
- name: Matrix - Send Notification
env:
NYM_NOTIFICATION_KIND: nym-connect
NYM_PROJECT_NAME: "nym-connect"
@@ -50,10 +50,6 @@ jobs:
NYM_CI_WWW_LOCATION: "nym-connect-${{ 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-nym-connect"
IS_SUCCESS: "${{ job.status == 'success' }}"
MATRIX_SERVER: "${{ secrets.MATRIX_SERVER }}"
MATRIX_ROOM: "${{ secrets.MATRIX_ROOM }}"
+4 -8
View File
@@ -16,10 +16,11 @@ env:
jobs:
publish-nym:
if: ${{ startsWith(github.ref, 'refs/tags/nym-binaries-') && github.event_name == 'release' }}
strategy:
fail-fast: false
matrix:
platform: [ubuntu-20.04]
platform: [custom-runner-linux]
runs-on: ${{ matrix.platform }}
steps:
@@ -28,13 +29,6 @@ jobs:
- name: Install Dependencies (Linux)
run: sudo apt-get update && sudo apt-get -y install libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev libudev-dev squashfs-tools
continue-on-error: true
- name: Check the release tag starts with `nym-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
run: |
@@ -57,6 +51,7 @@ jobs:
with:
name: my-artifact
path: |
target/release/explorer-api
target/release/nym-client
target/release/nym-gateway
target/release/nym-mixnode
@@ -72,6 +67,7 @@ jobs:
if: github.event_name == 'release'
with:
files: |
target/release/explorer-api
target/release/nym-client
target/release/nym-gateway
target/release/nym-mixnode
@@ -10,6 +10,7 @@ defaults:
jobs:
publish-tauri:
if: ${{ startsWith(github.ref, 'refs/tags/nym-wallet-') && github.event_name == 'release' }}
strategy:
fail-fast: false
matrix:
@@ -19,13 +20,6 @@ jobs:
steps:
- uses: actions/checkout@v2
- name: Check the release tag starts with `nym-wallet-`
if: startsWith(github.ref, 'refs/tags/nym-wallet-') == false && github.event_name != 'workflow_dispatch'
uses: actions/github-script@v3
with:
script: |
core.setFailed('Release tag did not start with nym-wallet-...')
- name: Node v16
uses: actions/setup-node@v3
with:
@@ -9,10 +9,11 @@ defaults:
jobs:
publish-tauri:
if: ${{ startsWith(github.ref, 'refs/tags/nym-wallet-') && github.event_name == 'release' }}
strategy:
fail-fast: false
matrix:
platform: [ubuntu-20.04]
platform: [custom-runner-linux]
runs-on: ${{ matrix.platform }}
steps:
@@ -23,17 +24,12 @@ jobs:
sudo apt-get update &&
sudo apt-get install -y webkit2gtk-4.0
continue-on-error: true
- 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: Node v16
uses: actions/setup-node@v3
with:
node-version: 16
- name: Install Rust stable
uses: actions-rs/toolchain@v1
with:
@@ -9,6 +9,7 @@ defaults:
jobs:
publish-tauri:
if: ${{ startsWith(github.ref, 'refs/tags/nym-wallet-') && github.event_name == 'release' }}
strategy:
fail-fast: false
matrix:
@@ -26,13 +27,6 @@ jobs:
- uses: actions/checkout@v3
- name: Check the release tag starts with `nym-wallet-`
if: startsWith(github.ref, 'refs/tags/nym-wallet-') == false
uses: actions/github-script@v3
with:
script: |
core.setFailed('Release tag did not start with nym-wallet-...')
- name: Import signing certificate
env:
WINDOWS_CERTIFICATE: ${{ secrets.WINDOWS_CERTIFICATE }}
+2 -6
View File
@@ -35,10 +35,10 @@ jobs:
REMOTE_USER: ${{ secrets.CI_WWW_REMOTE_USER }}
TARGET: ${{ secrets.CI_WWW_REMOTE_TARGET }}/wallet-${{ env.GITHUB_REF_SLUG }}
EXCLUDE: "/dist/, /node_modules/"
- name: Keybase - Node Install
- name: Matrix - Node Install
run: npm install
working-directory: .github/workflows/support-files
- name: Keybase - Send Notification
- name: Matrix - Send Notification
env:
NYM_NOTIFICATION_KIND: nym-wallet
NYM_PROJECT_NAME: "nym-wallet"
@@ -46,10 +46,6 @@ jobs:
NYM_CI_WWW_LOCATION: "wallet-${{ 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-nym-wallet"
IS_SUCCESS: "${{ job.status == 'success' }}"
MATRIX_SERVER: "${{ secrets.MATRIX_SERVER }}"
MATRIX_ROOM: "${{ secrets.MATRIX_ROOM }}"
+1 -5
View File
@@ -1,7 +1,3 @@
KEYBASE_NYM_CHANNEL=
KEYBASE_NYMBOT_USERNAME=
KEYBASE_NYMBOT_PAPERKEY=
MATRIX_SERVER=
MATRIX_ROOM=
MATRIX_ROOM_OF_SHAME=
@@ -39,4 +35,4 @@ NYM_CI_WWW_BASE=example.com
# Nightly builds
WORKFLOW_CONCLUSION=success
SHOW_DEBUG=true
SHOW_DEBUG=true
+10 -9
View File
@@ -4,7 +4,7 @@ This is a collection of scripts and files to support GitHub Actions.
## Sending Notifications
These scripts send CI notifications to Keybase by creating messages from templates and env vars passed from GitHub Actions.
These scripts send CI notifications to Matrix by creating messages from templates and env vars passed from GitHub Actions.
### Adding notifications to a GitHub Action
@@ -19,10 +19,11 @@ jobs:
env:
NYM_NOTIFICATION_KIND: "my-component"
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-network-explorer"
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 }}"
IS_SUCCESS: "${{ job.status == 'success' }}"
uses: docker://keybaseio/client:stable-node
with:
@@ -34,8 +35,8 @@ Notifications are run by adding the snippet above to a GitHub Action, and:
1. Installing node packages needed at run time
2. Set the env vars as required:
- `NYM_NOTIFICATION_KIND` matches the directory in `.github/workflows/support-files/${NYM_NOTIFICATION_KIND}` to provide the templates and extra scripting in `index.js`
- Keybase credentials, channel and other env vars for the status of the build and repo
3. Replacing the default entry point shell script on the `keybaseio/client:stable-node` docker image to run `.github/workflows/support-files/notifications/entry_point.sh`
- Matrix credentials, room and other env vars for the status of the build and repo
3. Replacing the default entry point shell script on the `keybaseio/client:stable-node` docker image to run `.github/workflows/support-files/notifications/entry_point.sh`
### Running locally
@@ -43,7 +44,7 @@ You will need:
- Node 16 LTS
- npm
Copy `.github/workflows/support-files/.env.example` to `.github/workflows/support-files/.env` and valid Keybase credentials.
Copy `.github/workflows/support-files/.env.example` to `.github/workflows/support-files/.env` and valid Matrix credentials.
Then run `npm install` to get dependencies.
@@ -55,4 +56,4 @@ npm install
cp .env.example .env
vi .env
npm run dev
```
```
+62
View File
@@ -0,0 +1,62 @@
#!/usr/bin/env bash
#
# Basic usage:
# ./git-merge-check origin/develop origin/release/v1.1.9
#
set -x
set -o nounset
set -o pipefail
# Start from branch ...
branch1=$1
# ... and try to merge in
branch2=$2
echo "Checking if $branch2 merges without conflicts into $branch1..."
git checkout -q $branch1 || exit 1
# There are two options here as far as I see on what we should check for. Either
#
# (A) check for CONFLICT in any file except whitelist (such as .lock files)
# (B) check for "Automatic merge failed"
#
# Both of these options have drawbacks.
#
# The first (A) has the problem in that maybe we don't want to fail if the
# changes can be automatically merged (duh), but at least we are not pestered
# about constant lock file changes.
# The second (B) has the problem that it's difficult to filter out automatic
# merge fails for files we don't care about (.lock files).
#
# The ideal solution would be to check for automatic merge fails for files
# except those on a whitelist (e.g. lock files).
# For now I choose to use (B) here, because I hope it might be less noisy
# Alternative A
#output=$(git merge --no-commit --no-ff $branch2 | grep -v .lock)
#merge_failed=$(echo $output | grep -v "CONFLICT")
#return_code=$?
# Alternative B
output=$(git merge --no-commit --no-ff $branch2)
merge_failed=$(echo $output | grep -v "Automatic merge failed")
return_code=$?
# Restore
git merge --abort
git checkout -q -
if [ $return_code -eq 0 ]; then
echo "Merge check success"
else
echo "Merge check failed"
fi
exit $return_code
@@ -1,6 +1,5 @@
require('dotenv').config();
const Bot = require('keybase-bot');
const { sendMatrixMessage } = require('./send_message_to_matrix');
let context = {
@@ -24,21 +23,6 @@ function validateContext() {
'Please set env var NYM_PROJECT_NAME with the project name for displaying in notification messages',
);
}
if (!context.env.KEYBASE_NYM_CHANNEL) {
throw new Error(
'Please set env var KEYBASE_NYM_CHANNEL with the channel name for the notification message',
);
}
if (!context.env.KEYBASE_NYMBOT_USERNAME) {
throw new Error(
'Username is not defined. Please set env var KEYBASE_NYMBOT_USERNAME',
);
}
if (!context.env.KEYBASE_NYMBOT_PAPERKEY) {
throw new Error(
'Paperkey is not defined. Please set env var KEYBASE_NYMBOT_PAPERKEY',
);
}
if (context.env.MATRIX_ROOM) {
if (!context.env.MATRIX_SERVER) {
throw new Error(
@@ -84,12 +68,6 @@ function createTemplateContext() {
context.kind = context.env.NYM_NOTIFICATION_KIND;
context.keybase = {
channel: context.env.KEYBASE_NYM_CHANNEL,
username: context.env.KEYBASE_NYMBOT_USERNAME,
paperkey: context.env.KEYBASE_NYMBOT_PAPERKEY,
};
if (!context.env.GIT_BRANCH_NAME) {
context.env.GIT_BRANCH_NAME = context.env.GITHUB_REF.split('/')
.slice(2)
@@ -99,40 +77,6 @@ function createTemplateContext() {
context.status = process.env.IS_SUCCESS === 'true' ? 'success' : 'failure';
}
async function sendKeybaseMessage(messageBody) {
const bot = new Bot();
try {
console.log(
`Initialising keybase with user "${
context.keybase.username
}" and key: "${'*'.repeat(context.keybase.paperkey.length)}"...`,
);
await bot.init(context.keybase.username, context.keybase.paperkey, {
verbose: false,
});
const channel = {
name: context.env.KEYBASE_NYMBOT_TEAM || 'nymtech_bot',
membersType: 'team',
topicName: context.keybase.channel,
topic_type: 'CHAT',
};
const message = {
body: messageBody,
};
console.log(`Sending to ${channel.name}#${channel.topicName}...`);
await bot.chat.send(channel, message);
console.log('Message sent!');
} catch (error) {
console.error(error);
process.exitCode = -1;
} finally {
await bot.deinit();
}
}
/**
* Uses the `kind` set in the context to process the context and generate a notification message
* @returns {Promise<string>} A string notification message body
@@ -169,7 +113,6 @@ async function main() {
console.log(messageBody);
console.log('-----------------------------------------');
}
await sendKeybaseMessage(messageBody);
if(context.env.MATRIX_ROOM) {
await sendMatrixMessage(context, messageBody, context.env.MATRIX_ROOM)
}
+2 -3
View File
@@ -1,6 +1,6 @@
{
"name": "send-keybase-message",
"description": "Sends a notification message with the keybase package that fails when piped into the keybase CLI",
"name": "send-matrix-message",
"description": "Sends a notification message with the matrix sdk",
"version": "1.0.0",
"private": true,
"scripts": {
@@ -10,7 +10,6 @@
"dependencies": {
"dotenv": "^16.0.0",
"handlebars": "^4.7.7",
"keybase-bot": "^3.6.1",
"matrix-js-sdk": "^9.3.0",
"node-localstorage": "^2.1.6",
"octokit": "^1.7.1",
+4 -7
View File
@@ -6,6 +6,7 @@ on:
- 'ts-packages/**'
- 'sdk/typescript/**'
- nym-connect
- nym-connect-android
- nym-wallet
jobs:
@@ -23,11 +24,11 @@ jobs:
- name: Setup yarn
run: npm install -g yarn
- name: Lint
run: yarn && yarn lint && yarn tsc
- name: Keybase - Node Install
run: yarn && yarn build && yarn lint && yarn tsc
- name: Matrix - Node Install
run: npm install
working-directory: .github/workflows/support-files
- name: Keybase - Send Notification
- name: Matrix - Send Notification
env:
NYM_NOTIFICATION_KIND: ts-packages
NYM_PROJECT_NAME: "ts-packages"
@@ -35,10 +36,6 @@ jobs:
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 }}"
+11 -4
View File
@@ -2,11 +2,17 @@ name: Nym Wallet (rust)
on:
push:
paths-ignore:
- 'explorer/**'
paths:
- 'nym-wallet/**'
- 'common/**'
- 'contracts/vesting/**'
- 'nym-api/nym-api-requests/**'
pull_request:
paths-ignore:
- 'explorer/**'
paths:
- 'nym-wallet/**'
- 'common/**'
- 'contracts/vesting/**'
- 'nym-api/nym-api-requests/**'
jobs:
build:
@@ -16,6 +22,7 @@ jobs:
steps:
- name: Install Dependencies (Linux)
run: sudo apt-get update && sudo apt-get -y install libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev squashfs-tools
continue-on-error: true
- name: Check out repository code
uses: actions/checkout@v2
+7 -7
View File
@@ -2,8 +2,13 @@ name: Wasm Client
on:
pull_request:
paths-ignore:
- 'explorer/**'
paths:
- 'clients/webassembly/**'
- 'clients/client-core/**'
- 'common/**'
- 'contracts/**'
- 'gateway/gateway-requests/**'
- 'nym-api/nym-api-requests/**'
jobs:
wasm:
@@ -24,11 +29,6 @@ jobs:
command: build
args: --manifest-path clients/webassembly/Cargo.toml --target wasm32-unknown-unknown
- uses: actions-rs/cargo@v1
with:
command: build
args: --manifest-path clients/webassembly/Cargo.toml --target wasm32-unknown-unknown --features=coconut
- uses: actions-rs/cargo@v1
with:
command: fmt
+1
View File
@@ -42,3 +42,4 @@ envs/qwerty.env
Cargo.lock
nym-connect/Cargo.lock
.parcel-cache
**/.DS_Store
+47 -10
View File
@@ -2,9 +2,52 @@
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]
# [v1.1.8] (2023-01-31)
## [v1.1.10] (2023-02-21)
- Verloc listener causing mixnode unexpected shutdown ([#3038])
- rust-sdk - update API following implementation experience with the network-requester ([#3001])
- Prevent coconut deposits in incompatible states ([#2991])
- Support unavailable signer within threshold ([#2987])
- Implement DKG re-sharing ([#2935])
- contracts: add nym prefix to mixnet and vesting contract packages ([#2855])
- Introduce common interface for all service providers to allow obtaining information such as whether they're online, what binary version they're running, etc. ([#2758])
- Add client functionality to nym-network-requester ([#1900])
- nym-api: uptime rework ([#3053])
- ci: update typescript-lint.yml ([#3035])
- contracts: add nym prefix to mixnet and vesting contract packages ([#2855])
[#3038]: https://github.com/nymtech/nym/issues/3038
[#3001]: https://github.com/nymtech/nym/issues/3001
[#2991]: https://github.com/nymtech/nym/issues/2991
[#2987]: https://github.com/nymtech/nym/issues/2987
[#2935]: https://github.com/nymtech/nym/issues/2935
[#2855]: https://github.com/nymtech/nym/pull/2855
[#2758]: https://github.com/nymtech/nym/issues/2758
[#1900]: https://github.com/nymtech/nym/issues/1900
[#3053]: https://github.com/nymtech/nym/pull/3053
[#3035]: https://github.com/nymtech/nym/pull/3035
[#2855]: https://github.com/nymtech/nym/pull/2855
## [v1.1.9] (2023-02-07)
### Added
- Remove Coconut feature flag ([#2793])
- Separate `nym-api` endpoints with values of "total-supply" and "circulating-supply" in `nym` ([#2964])
### Changed
- native-client: is now capable of listening for requests on sockets different than `127.0.0.1` ([#2912]). 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.
- mixnode, gateway: fix unexpected shutdown on corrupted connection ([#2963])
[#2793]: https://github.com/nymtech/nym/issues/2793
[#2912]: https://github.com/nymtech/nym/issues/2912
[#2964]: https://github.com/nymtech/nym/issues/2964
[#2963]: https://github.com/nymtech/nym/issues/3017
## [v1.1.8] (2023-01-31)
### Added
@@ -18,13 +61,13 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
- nym-api: an `--id` flag is now always explicitly required ([#2873])
[#2754]: https://github.com/nymtech/nym/issues/2754
[#2839]: https://github.com/nymtech/nym/issues/2810
[#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)
## [v1.1.7] (2023-01-24)
### Added
@@ -80,12 +123,6 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
### 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
Generated
+390 -347
View File
File diff suppressed because it is too large Load Diff
+11 -1
View File
@@ -38,6 +38,7 @@ members = [
"common/cosmwasm-smart-contracts/mixnet-contract",
"common/cosmwasm-smart-contracts/multisig-contract",
"common/cosmwasm-smart-contracts/vesting-contract",
"common/mobile-storage",
"common/credential-storage",
"common/credentials",
"common/crypto",
@@ -75,6 +76,7 @@ members = [
"integrations/bity",
"mixnode",
"sdk/rust/nym-sdk",
"service-providers/common",
"service-providers/network-requester",
"service-providers/network-statistics",
"nym-api",
@@ -95,7 +97,7 @@ default-members = [
"explorer-api",
]
exclude = ["explorer", "contracts", "clients/webassembly", "nym-wallet", "nym-connect"]
exclude = ["explorer", "contracts", "clients/webassembly", "nym-wallet", "nym-connect", "nym-connect-android"]
[workspace.package]
authors = ["Nym Technologies SA"]
@@ -104,4 +106,12 @@ homepage = "https://nymtech.net"
edition = "2021"
[workspace.dependencies]
async-trait = "0.1.63"
lazy_static = "1.4.0"
log = "0.4"
serde = "1.0.152"
serde_json = "1.0.91"
tap = "1.0.1"
thiserror = "1.0.38"
tokio = "1.24.1"
url = "2.2"
+6 -13
View File
@@ -2,10 +2,10 @@ test: clippy-all cargo-test wasm fmt
test-all: test cargo-test-expensive
no-clippy: build cargo-test wasm fmt
happy: fmt clippy-happy test
clippy-all: clippy-main clippy-coconut clippy-all-contracts clippy-all-wallet clippy-all-connect clippy-all-wasm-client
clippy-all: clippy-main clippy-all-contracts clippy-all-wallet clippy-all-connect clippy-all-wasm-client
clippy-happy: clippy-happy-main clippy-happy-contracts clippy-happy-wallet clippy-happy-connect
cargo-test: test-main test-contracts test-wallet test-connect test-coconut
cargo-test-expensive: test-main-expensive test-contracts-expensive test-wallet-expensive test-connect-expensive test-coconut-expensive
cargo-test: test-main test-contracts test-wallet test-connect
cargo-test-expensive: test-main-expensive test-contracts-expensive test-wallet-expensive test-connect-expensive
build: build-contracts build-wallet build-main build-connect build-wasm-client
fmt: fmt-main fmt-contracts fmt-wallet fmt-connect fmt-wasm-client
@@ -24,9 +24,6 @@ clippy-happy-connect:
clippy-main:
cargo clippy --workspace -- -D warnings
clippy-coconut:
cargo clippy --workspace --features coconut -- -D warnings
clippy-wasm:
cargo clippy --manifest-path clients/webassembly/Cargo.toml --target wasm32-unknown-unknown --workspace -- -D warnings
@@ -46,16 +43,9 @@ clippy-all-wasm-client:
test-main:
cargo test --workspace
test-coconut:
cargo test --workspace --features coconut
test-main-expensive:
cargo test --workspace -- --ignored
test-coconut-expensive:
cargo test --workspace --features coconut -- --ignored
test-contracts:
cargo test --manifest-path contracts/Cargo.toml --all-features
@@ -119,3 +109,6 @@ mixnet-opt: wasm
generate-typescript:
cd tools/ts-rs-cli && cargo run && cd ../..
yarn types:lint:fix
run-validator-tests:
cd nym-api/tests/functional_test && yarn test:qa
BIN
View File
Binary file not shown.
+3 -4
View File
@@ -1,6 +1,6 @@
[package]
name = "client-core"
version = "1.1.8"
version = "1.1.10"
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"]
edition = "2021"
rust-version = "1.66"
@@ -26,13 +26,13 @@ time = "0.3.17"
# internal
config = { path = "../../common/config" }
client-connections = { path = "../../common/client-connections" }
crypto = { path = "../../common/crypto" }
nym-crypto = { path = "../../common/crypto" }
gateway-client = { path = "../../common/client-libs/gateway-client" }
#gateway-client = { path = "../../common/client-libs/gateway-client", default-features = false, features = ["wasm", "coconut"] }
gateway-requests = { path = "../../gateway/gateway-requests" }
nonexhaustive-delayqueue = { path = "../../common/nonexhaustive-delayqueue" }
nymsphinx = { path = "../../common/nymsphinx" }
pemstore = { path = "../../common/pemstore" }
nym-pemstore = { path = "../../common/pemstore" }
topology = { path = "../../common/topology" }
validator-client = { path = "../../common/client-libs/validator-client", default-features = false }
task = { path = "../../common/task" }
@@ -82,5 +82,4 @@ sqlx = { version = "0.6.2", features = ["runtime-tokio-rustls", "sqlite", "macro
default = []
fs-surb-storage = ["sqlx"]
wasm = ["gateway-client/wasm"]
coconut = ["gateway-client/coconut", "gateway-requests/coconut"]
@@ -0,0 +1,11 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
//
use crate::{client::replies::reply_storage, config::DebugConfig};
pub fn setup_empty_reply_surb_backend(debug_config: &DebugConfig) -> reply_storage::Empty {
reply_storage::Empty {
min_surb_threshold: debug_config.minimum_reply_surb_storage_threshold,
max_surb_threshold: debug_config.maximum_reply_surb_storage_threshold,
}
}
@@ -22,7 +22,6 @@ use crate::config::{Config, DebugConfig, GatewayEndpointConfig};
use crate::error::ClientCoreError;
use crate::spawn_future;
use client_connections::{ConnectionCommandReceiver, ConnectionCommandSender, LaneQueueLengths};
use crypto::asymmetric::{encryption, identity};
use futures::channel::mpsc;
use gateway_client::bandwidth::BandwidthController;
#[cfg(target_arch = "wasm32")]
@@ -32,6 +31,7 @@ use gateway_client::{
MixnetMessageSender,
};
use log::{debug, info};
use nym_crypto::asymmetric::{encryption, identity};
use nymsphinx::acknowledgements::AckKey;
use nymsphinx::addressing::clients::Recipient;
use nymsphinx::addressing::nodes::NodeIdentity;
@@ -49,11 +49,24 @@ use super::received_buffer::ReceivedBufferMessage;
#[cfg(all(not(target_arch = "wasm32"), feature = "fs-surb-storage"))]
pub mod non_wasm_helpers;
pub mod helpers;
#[derive(Clone)]
pub struct ClientInput {
pub connection_command_sender: ConnectionCommandSender,
pub input_sender: InputMessageSender,
}
impl ClientInput {
pub async fn send(
&self,
message: InputMessage,
) -> Result<(), tokio::sync::mpsc::error::SendError<InputMessage>> {
self.input_sender.send(message).await
}
}
#[derive(Clone)]
pub struct ClientOutput {
pub received_buffer_request_sender: ReceivedBufferRequestSender,
}
@@ -289,10 +302,6 @@ where
if gateway_id.is_empty() {
return Err(ClientCoreError::GatewayIdUnknown);
}
let gateway_owner = self.gateway_config.gateway_owner.clone();
if gateway_owner.is_empty() {
return Err(ClientCoreError::GatewayOwnerUnknown);
}
let gateway_address = self.gateway_config.gateway_listener.clone();
if gateway_address.is_empty() {
return Err(ClientCoreError::GatwayAddressUnknown);
@@ -305,6 +314,7 @@ where
let shared_key = if self.key_manager.is_gateway_key_set() {
Some(self.key_manager.gateway_shared_key())
} else {
log::info!("Gateway key not set! Will proceed anyway.");
None
};
@@ -312,7 +322,6 @@ where
gateway_address,
self.key_manager.identity_keypair(),
gateway_identity,
gateway_owner,
shared_key,
mixnet_message_sender,
ack_sender,
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
use crate::client::replies::reply_storage::{
self, fs_backend, CombinedReplyStorage, ReplyStorageBackend,
fs_backend, CombinedReplyStorage, ReplyStorageBackend,
};
use crate::config::DebugConfig;
use crate::error::ClientCoreError;
@@ -98,10 +98,3 @@ pub async fn setup_fs_reply_surb_backend<P: AsRef<Path>>(
Ok(setup_inactive_backend(debug_config))
}
}
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,
}
}
@@ -77,4 +77,12 @@ impl InputMessage {
lane,
}
}
pub fn lane(&self) -> &TransmissionLane {
match self {
InputMessage::Regular { lane, .. }
| InputMessage::Anonymous { lane, .. }
| InputMessage::Reply { lane, .. } => lane,
}
}
}
+13 -13
View File
@@ -2,9 +2,9 @@
// SPDX-License-Identifier: Apache-2.0
use crate::config::persistence::key_pathfinder::ClientKeyPathfinder;
use crypto::asymmetric::{encryption, identity};
use gateway_requests::registration::handshake::SharedKeys;
use log::*;
use nym_crypto::asymmetric::{encryption, identity};
use nymsphinx::acknowledgements::AckKey;
use rand::{CryptoRng, RngCore};
use std::io;
@@ -72,17 +72,17 @@ impl KeyManager {
/// Loads previously stored client keys from the disk.
fn load_client_keys(client_pathfinder: &ClientKeyPathfinder) -> io::Result<Self> {
let identity_keypair: identity::KeyPair =
pemstore::load_keypair(&pemstore::KeyPairPath::new(
nym_pemstore::load_keypair(&nym_pemstore::KeyPairPath::new(
client_pathfinder.private_identity_key().to_owned(),
client_pathfinder.public_identity_key().to_owned(),
))?;
let encryption_keypair: encryption::KeyPair =
pemstore::load_keypair(&pemstore::KeyPairPath::new(
nym_pemstore::load_keypair(&nym_pemstore::KeyPairPath::new(
client_pathfinder.private_encryption_key().to_owned(),
client_pathfinder.public_encryption_key().to_owned(),
))?;
let ack_key: AckKey = pemstore::load_key(client_pathfinder.ack_key())?;
let ack_key: AckKey = nym_pemstore::load_key(client_pathfinder.ack_key())?;
Ok(KeyManager {
identity_keypair: Arc::new(identity_keypair),
@@ -98,7 +98,7 @@ impl KeyManager {
let mut key_manager = Self::load_client_keys(client_pathfinder)?;
let gateway_shared_key: SharedKeys =
pemstore::load_key(client_pathfinder.gateway_shared_key())?;
nym_pemstore::load_key(client_pathfinder.gateway_shared_key())?;
key_manager.gateway_shared_key = Some(Arc::new(gateway_shared_key));
@@ -113,7 +113,7 @@ impl KeyManager {
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());
nym_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 {
@@ -132,27 +132,27 @@ impl KeyManager {
// it is done so for the consistency sake so that you wouldn't require an rng instance
// during `load_keys` to generate the said key.
pub fn store_keys(&self, client_pathfinder: &ClientKeyPathfinder) -> io::Result<()> {
pemstore::store_keypair(
nym_pemstore::store_keypair(
self.identity_keypair.as_ref(),
&pemstore::KeyPairPath::new(
&nym_pemstore::KeyPairPath::new(
client_pathfinder.private_identity_key().to_owned(),
client_pathfinder.public_identity_key().to_owned(),
),
)?;
pemstore::store_keypair(
nym_pemstore::store_keypair(
self.encryption_keypair.as_ref(),
&pemstore::KeyPairPath::new(
&nym_pemstore::KeyPairPath::new(
client_pathfinder.private_encryption_key().to_owned(),
client_pathfinder.public_encryption_key().to_owned(),
),
)?;
pemstore::store_key(self.ack_key.as_ref(), client_pathfinder.ack_key())?;
nym_pemstore::store_key(self.ack_key.as_ref(), client_pathfinder.ack_key())?;
match self.gateway_shared_key.as_ref() {
None => debug!("No gateway shared key available to store!"),
Some(gate_key) => {
pemstore::store_key(gate_key.as_ref(), client_pathfinder.gateway_shared_key())?
nym_pemstore::store_key(gate_key.as_ref(), client_pathfinder.gateway_shared_key())?
}
}
@@ -168,7 +168,7 @@ impl KeyManager {
))
}
Some(gate_key) => {
pemstore::store_key(gate_key.as_ref(), client_pathfinder.gateway_shared_key())?
nym_pemstore::store_key(gate_key.as_ref(), client_pathfinder.gateway_shared_key())?
}
}
@@ -81,7 +81,11 @@ pub struct Config {
/// Defines maximum amount of time the client is going to wait for reply surbs before explicitly asking
/// for more even though in theory they wouldn't need to.
maximum_reply_surb_waiting_period: Duration,
maximum_reply_surb_rerequest_waiting_period: Duration,
/// Defines maximum amount of time the client is going to wait for reply surbs before
/// deciding it's never going to get them and would drop all pending messages
maximum_reply_surb_drop_waiting_period: Duration,
/// Defines maximum amount of time given reply surb is going to be valid for.
/// This is going to be superseded by key rotation once implemented.
@@ -119,7 +123,8 @@ impl<'a> From<&'a Config> for reply_controller::Config {
cfg.minimum_reply_surb_request_size,
cfg.maximum_reply_surb_request_size,
cfg.maximum_allowed_reply_surb_request_size,
cfg.maximum_reply_surb_waiting_period,
cfg.maximum_reply_surb_rerequest_waiting_period,
cfg.maximum_reply_surb_drop_waiting_period,
cfg.maximum_reply_surb_age,
cfg.maximum_reply_key_age,
)
@@ -161,8 +166,10 @@ impl Config {
.maximum_reply_surb_request_size,
maximum_allowed_reply_surb_request_size: base_client_debug_config
.maximum_allowed_reply_surb_request_size,
maximum_reply_surb_waiting_period: base_client_debug_config
.maximum_reply_surb_waiting_period,
maximum_reply_surb_rerequest_waiting_period: base_client_debug_config
.maximum_reply_surb_rerequest_waiting_period,
maximum_reply_surb_drop_waiting_period: base_client_debug_config
.maximum_reply_surb_drop_waiting_period,
maximum_reply_surb_age: base_client_debug_config.maximum_reply_surb_age,
maximum_reply_key_age: base_client_debug_config.maximum_reply_key_age,
}
@@ -342,7 +342,6 @@ where
if let Poll::Ready(Some(id)) = Pin::new(&mut self.client_connection_rx).poll_next(cx) {
match id {
ConnectionCommand::Close(id) => self.on_close_connection(id),
ConnectionCommand::ActiveConnections(_) => panic!(),
}
}
@@ -421,7 +420,6 @@ where
if let Poll::Ready(Some(id)) = Pin::new(&mut self.client_connection_rx).poll_next(cx) {
match id {
ConnectionCommand::Close(id) => self.on_close_connection(id),
ConnectionCommand::ActiveConnections(_) => panic!(),
}
}
@@ -4,13 +4,13 @@
use crate::client::replies::reply_controller::ReplyControllerSender;
use crate::client::replies::reply_storage::SentReplyKeys;
use crate::spawn_future;
use crypto::asymmetric::encryption;
use crypto::Digest;
use futures::channel::mpsc;
use futures::lock::Mutex;
use futures::StreamExt;
use gateway_client::MixnetMessageReceiver;
use log::*;
use nym_crypto::asymmetric::encryption;
use nym_crypto::Digest;
use nymsphinx::anonymous_replies::requests::{
RepliableMessage, RepliableMessageContent, ReplyMessage, ReplyMessageContent,
};
@@ -30,7 +30,8 @@ pub struct Config {
min_surb_request_size: u32,
max_surb_request_size: u32,
maximum_allowed_reply_surb_request_size: u32,
max_surb_waiting_period: Duration,
max_surb_rerequest_waiting_period: Duration,
max_surb_drop_waiting_period: Duration,
max_reply_surb_age: Duration,
max_reply_key_age: Duration,
}
@@ -40,7 +41,8 @@ impl Config {
min_surb_request_size: u32,
max_surb_request_size: u32,
maximum_allowed_reply_surb_request_size: u32,
max_surb_waiting_period: Duration,
max_surb_rerequest_waiting_period: Duration,
max_surb_drop_waiting_period: Duration,
max_reply_surb_age: Duration,
max_reply_key_age: Duration,
) -> Self {
@@ -48,7 +50,8 @@ impl Config {
min_surb_request_size,
max_surb_request_size,
maximum_allowed_reply_surb_request_size,
max_surb_waiting_period,
max_surb_rerequest_waiting_period,
max_surb_drop_waiting_period,
max_reply_surb_age,
max_reply_key_age,
}
@@ -742,9 +745,13 @@ where
let diff = now - last_received_time;
if diff > self.config.max_surb_waiting_period {
warn!("We haven't received any surbs in {:?} from {pending_reply_target}. Going to explicitly ask for more", diff);
to_request.push(*pending_reply_target);
if diff > self.config.max_surb_rerequest_waiting_period {
if diff > self.config.max_surb_drop_waiting_period {
to_remove.push(*pending_reply_target)
} else {
debug!("We haven't received any surbs in {:?} from {pending_reply_target}. Going to explicitly ask for more", diff);
to_request.push(*pending_reply_target);
}
}
}
@@ -5,6 +5,8 @@ use crate::client::replies::reply_storage::backend::Empty;
use crate::client::replies::reply_storage::{CombinedReplyStorage, ReplyStorageBackend};
use async_trait::async_trait;
use std::path::PathBuf;
// well, right now we don't have the browser storage : (
// so we keep everything in memory
#[derive(Debug)]
@@ -27,6 +29,18 @@ impl Backend {
impl ReplyStorageBackend for Backend {
type StorageError = <Empty as ReplyStorageBackend>::StorageError;
async fn new(
debug_config: &crate::config::DebugConfig,
_db_path: Option<PathBuf>,
) -> Result<Self, Self::StorageError> {
Ok(Backend {
empty: Empty {
min_surb_threshold: debug_config.minimum_reply_surb_storage_threshold,
max_surb_threshold: debug_config.maximum_reply_surb_storage_threshold,
},
})
}
async fn flush_surb_storage(
&mut self,
storage: &CombinedReplyStorage,
@@ -56,4 +56,9 @@ pub enum StorageError {
details: String,
// err: Option<Box<dyn std::error::Error>>
},
#[error("failed to create storage")]
FailedToCreateStorage {
source: Box<dyn std::error::Error + Send + Sync>,
},
}
@@ -1,6 +1,7 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::client::base_client::non_wasm_helpers;
use crate::client::replies::reply_storage::backend::fs_backend::manager::StorageManager;
use crate::client::replies::reply_storage::backend::fs_backend::models::{
ReplySurbStorageMetadata, StoredReplyKey, StoredReplySurb, StoredSenderTag, StoredSurbSender,
@@ -367,6 +368,20 @@ impl Backend {
impl ReplyStorageBackend for Backend {
type StorageError = error::StorageError;
async fn new(
debug_config: &crate::config::DebugConfig,
db_path: Option<PathBuf>,
) -> Result<Self, Self::StorageError> {
non_wasm_helpers::setup_fs_reply_surb_backend(db_path, debug_config)
.await
.map_err(|err| {
log::error!("Failed to create storage: {err}");
Self::StorageError::FailedToCreateStorage {
source: Box::new(err),
}
})
}
fn is_active(&self) -> bool {
self.manager.is_active()
}
@@ -3,8 +3,8 @@
use crate::client::replies::reply_storage::backend::fs_backend::error::StorageError;
use crate::client::replies::reply_storage::key_storage::UsedReplyKey;
use crypto::generic_array::typenum::Unsigned;
use crypto::Digest;
use nym_crypto::generic_array::typenum::Unsigned;
use nym_crypto::Digest;
use nymsphinx::addressing::clients::{Recipient, RecipientBytes};
use nymsphinx::anonymous_replies::encryption_key::EncryptionKeyDigest;
use nymsphinx::anonymous_replies::requests::{AnonymousSenderTag, SENDER_TAG_SIZE};
@@ -3,7 +3,7 @@
use crate::client::replies::reply_storage::CombinedReplyStorage;
use async_trait::async_trait;
use std::error::Error;
use std::{error::Error, path::PathBuf};
use thiserror::Error;
#[cfg(target_arch = "wasm32")]
@@ -30,6 +30,16 @@ pub struct Empty {
impl ReplyStorageBackend for Empty {
type StorageError = UndefinedError;
async fn new(
debug_config: &crate::config::DebugConfig,
_db_path: Option<PathBuf>,
) -> Result<Self, Self::StorageError> {
Ok(Self {
min_surb_threshold: debug_config.minimum_reply_surb_storage_threshold,
max_surb_threshold: debug_config.maximum_reply_surb_storage_threshold,
})
}
async fn flush_surb_storage(
&mut self,
_storage: &CombinedReplyStorage,
@@ -63,6 +73,11 @@ impl ReplyStorageBackend for Empty {
pub trait ReplyStorageBackend: Sized {
type StorageError: Error + 'static;
async fn new(
debug_config: &crate::config::DebugConfig,
db_path: Option<PathBuf>,
) -> Result<Self, Self::StorageError>;
fn is_active(&self) -> bool {
true
}
+23 -6
View File
@@ -45,7 +45,8 @@ const DEFAULT_MAXIMUM_REPLY_SURB_REQUEST_SIZE: u32 = 100;
const DEFAULT_MAXIMUM_ALLOWED_SURB_REQUEST_SIZE: u32 = 500;
const DEFAULT_MAXIMUM_REPLY_SURB_WAITING_PERIOD: Duration = Duration::from_secs(10);
const DEFAULT_MAXIMUM_REPLY_SURB_REREQUEST_WAITING_PERIOD: Duration = Duration::from_secs(10);
const DEFAULT_MAXIMUM_REPLY_SURB_DROP_WAITING_PERIOD: Duration = Duration::from_secs(5 * 60);
// 12 hours
const DEFAULT_MAXIMUM_REPLY_SURB_AGE: Duration = Duration::from_secs(12 * 60 * 60);
@@ -170,10 +171,15 @@ impl<T> Config<T> {
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;
}
pub fn with_gateway_endpoint(mut self, gateway_endpoint: GatewayEndpointConfig) -> Self {
self.client.gateway_endpoint = gateway_endpoint;
self
}
pub fn with_gateway_id<S: Into<String>>(&mut self, id: S) {
self.client.gateway_endpoint.gateway_id = id.into();
}
@@ -372,8 +378,12 @@ impl<T> Config<T> {
self.debug.maximum_allowed_reply_surb_request_size
}
pub fn get_maximum_reply_surb_waiting_period(&self) -> Duration {
self.debug.maximum_reply_surb_waiting_period
pub fn get_maximum_reply_surb_rerequest_waiting_period(&self) -> Duration {
self.debug.maximum_reply_surb_rerequest_waiting_period
}
pub fn get_maximum_reply_surb_drop_waiting_period(&self) -> Duration {
self.debug.maximum_reply_surb_drop_waiting_period
}
pub fn get_maximum_reply_surb_age(&self) -> Duration {
@@ -663,7 +673,12 @@ pub struct DebugConfig {
/// Defines maximum amount of time the client is going to wait for reply surbs before explicitly asking
/// for more even though in theory they wouldn't need to.
#[serde(with = "humantime_serde")]
pub maximum_reply_surb_waiting_period: Duration,
pub maximum_reply_surb_rerequest_waiting_period: Duration,
/// Defines maximum amount of time the client is going to wait for reply surbs before
/// deciding it's never going to get them and would drop all pending messages
#[serde(with = "humantime_serde")]
pub maximum_reply_surb_drop_waiting_period: Duration,
/// Defines maximum amount of time given reply surb is going to be valid for.
/// This is going to be superseded by key rotation once implemented.
@@ -704,7 +719,9 @@ impl Default for DebugConfig {
minimum_reply_surb_request_size: DEFAULT_MINIMUM_REPLY_SURB_REQUEST_SIZE,
maximum_reply_surb_request_size: DEFAULT_MAXIMUM_REPLY_SURB_REQUEST_SIZE,
maximum_allowed_reply_surb_request_size: DEFAULT_MAXIMUM_ALLOWED_SURB_REQUEST_SIZE,
maximum_reply_surb_waiting_period: DEFAULT_MAXIMUM_REPLY_SURB_WAITING_PERIOD,
maximum_reply_surb_rerequest_waiting_period:
DEFAULT_MAXIMUM_REPLY_SURB_REREQUEST_WAITING_PERIOD,
maximum_reply_surb_drop_waiting_period: DEFAULT_MAXIMUM_REPLY_SURB_DROP_WAITING_PERIOD,
maximum_reply_surb_age: DEFAULT_MAXIMUM_REPLY_SURB_AGE,
maximum_reply_key_age: DEFAULT_MAXIMUM_REPLY_KEY_AGE,
}
+1 -1
View File
@@ -1,8 +1,8 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crypto::asymmetric::identity::Ed25519RecoveryError;
use gateway_client::error::GatewayClientError;
use nym_crypto::asymmetric::identity::Ed25519RecoveryError;
use topology::NymTopologyError;
use validator_client::ValidatorClientError;
+1 -2
View File
@@ -7,11 +7,11 @@ use crate::{
error::ClientCoreError,
};
use config::NymConfig;
use crypto::asymmetric::identity;
#[cfg(target_arch = "wasm32")]
use gateway_client::wasm_mockups::SigningNyxdClient;
use gateway_client::GatewayClient;
use gateway_requests::registration::handshake::SharedKeys;
use nym_crypto::asymmetric::identity;
use rand::{seq::SliceRandom, thread_rng};
use std::{sync::Arc, time::Duration};
use tap::TapFallible;
@@ -63,7 +63,6 @@ pub(super) async fn register_with_gateway(
let mut gateway_client: GatewayClient<SigningNyxdClient> = GatewayClient::new_init(
gateway.clients_address(),
gateway.identity_key,
gateway.owner.clone(),
our_identity.clone(),
timeout,
);
+3 -3
View File
@@ -11,7 +11,7 @@ use serde::Serialize;
use tap::TapFallible;
use config::NymConfig;
use crypto::asymmetric::{encryption, identity};
use nym_crypto::asymmetric::{encryption, identity};
use url::Url;
use crate::client::key_manager::KeyManager;
@@ -188,7 +188,7 @@ where
pathfinder: &ClientKeyPathfinder,
) -> Result<identity::KeyPair, ClientCoreError> {
let identity_keypair: identity::KeyPair =
pemstore::load_keypair(&pemstore::KeyPairPath::new(
nym_pemstore::load_keypair(&nym_pemstore::KeyPairPath::new(
pathfinder.private_identity_key().to_owned(),
pathfinder.public_identity_key().to_owned(),
))
@@ -200,7 +200,7 @@ where
pathfinder: &ClientKeyPathfinder,
) -> Result<encryption::KeyPair, ClientCoreError> {
let sphinx_keypair: encryption::KeyPair =
pemstore::load_keypair(&pemstore::KeyPairPath::new(
nym_pemstore::load_keypair(&nym_pemstore::KeyPairPath::new(
pathfinder.private_encryption_key().to_owned(),
pathfinder.public_encryption_key().to_owned(),
))
+4 -5
View File
@@ -7,8 +7,8 @@ edition = "2021"
[dependencies]
bip39 = "1.0.1"
cfg-if = "0.1"
clap = { version = "4.0", features = ["cargo", "derive"] }
log = "0.4"
rand = "0.7.3"
serde = { version = "1.0", features = ["derive"] }
thiserror = "1.0"
@@ -20,10 +20,9 @@ config = { path = "../../common/config" }
completions = { path = "../../common/completions" }
credentials = { path = "../../common/credentials" }
credential-storage = { path = "../../common/credential-storage" }
crypto = { path = "../../common/crypto", features = ["rand", "asymmetric", "symmetric", "aes", "hashing"] }
nym-crypto = { path = "../../common/crypto", features = ["rand", "asymmetric", "symmetric", "aes", "hashing"] }
logging = { path = "../../common/logging"}
network-defaults = { path = "../../common/network-defaults" }
pemstore = { path = "../../common/pemstore" }
nym-pemstore = { path = "../../common/pemstore" }
validator-client = { path = "../../common/client-libs/validator-client", features = ["nyxd-client"] }
[features]
coconut = ["credentials/coconut"]
+82 -33
View File
@@ -1,8 +1,9 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use clap::{Args, Subcommand};
use clap::{ArgGroup, Args, Subcommand};
use completions::ArgShell;
use log::*;
use rand::rngs::OsRng;
use std::str::FromStr;
@@ -11,19 +12,21 @@ use credential_storage::storage::Storage;
use credential_storage::PersistentStorage;
use credentials::coconut::bandwidth::{BandwidthVoucher, TOTAL_ATTRIBUTES};
use credentials::coconut::utils::obtain_aggregate_signature;
use crypto::asymmetric::{encryption, identity};
use network_defaults::{NymNetworkDetails, VOUCHER_INFO};
use network_defaults::VOUCHER_INFO;
use nym_crypto::asymmetric::{encryption, identity};
use validator_client::nyxd::traits::DkgQueryClient;
use validator_client::nyxd::tx::Hash;
use validator_client::{CoconutApiClient, Config};
use validator_client::nyxd::CosmWasmClient;
use validator_client::CoconutApiClient;
use crate::client::Client;
use crate::error::{CredentialClientError, Result};
use crate::recovery_storage::RecoveryStorage;
use crate::state::{KeyPair, State};
#[derive(Subcommand)]
pub(crate) enum Command {
/// Run the binary
/// Run the binary to obtain a credential
Run(Run),
/// Generate shell completions
@@ -34,6 +37,11 @@ pub(crate) enum Command {
}
#[derive(Args)]
#[clap(group(
ArgGroup::new("recov")
.required(true)
.args(&["amount", "recovery_mode"]),
))]
pub(crate) struct Run {
/// Home directory of the client that is supposed to use the credential.
#[clap(long)]
@@ -47,15 +55,25 @@ pub(crate) struct Run {
#[clap(long)]
pub(crate) mnemonic: String,
/// The amount of utokens the credential will hold
#[clap(long)]
/// The amount of utokens the credential will hold. If recovery mode is enabled, this value
/// is not needed
#[clap(long, default_value = "0")]
pub(crate) amount: u64,
/// Path to a directory used to store recovery files for unconsumed deposits
#[clap(long)]
pub(crate) recovery_dir: std::path::PathBuf,
/// Recovery mode, when enabled, tries to recover any deposit data dumped in recovery_dir
#[clap(long)]
pub(crate) recovery_mode: bool,
}
pub(crate) async fn deposit(nyxd_url: &str, mnemonic: &str, amount: u64) -> Result<State> {
let mut rng = OsRng;
let signing_keypair = KeyPair::from(identity::KeyPair::new(&mut rng));
let encryption_keypair = KeyPair::from(encryption::KeyPair::new(&mut rng));
let params = Parameters::new(TOTAL_ATTRIBUTES).unwrap();
let client = Client::new(nyxd_url, mnemonic);
let tx_hash = client
@@ -67,46 +85,47 @@ pub(crate) async fn deposit(nyxd_url: &str, mnemonic: &str, amount: u64) -> Resu
)
.await?;
let state = State {
amount,
tx_hash,
signing_keypair,
encryption_keypair,
};
let voucher = BandwidthVoucher::new(
&params,
amount.to_string(),
VOUCHER_INFO.to_string(),
Hash::from_str(&tx_hash).map_err(|_| CredentialClientError::InvalidTxHash)?,
identity::PrivateKey::from_base58_string(&signing_keypair.private_key)?,
encryption::PrivateKey::from_base58_string(&encryption_keypair.private_key)?,
);
let state = State { voucher, params };
Ok(state)
}
pub(crate) async fn get_credential(state: &State, shared_storage: PersistentStorage) -> Result<()> {
let network_details = NymNetworkDetails::new_from_env();
let config = Config::try_from_nym_network_details(&network_details)?;
let client = validator_client::Client::new_query(config)?;
pub(crate) async fn get_credential<C: Clone + CosmWasmClient + Send + Sync>(
state: &State,
client: validator_client::Client<C>,
shared_storage: PersistentStorage,
) -> Result<()> {
let epoch_id = client.nyxd.get_current_epoch().await?.epoch_id;
let threshold = client
.nyxd
.get_current_epoch_threshold()
.await?
.ok_or(CredentialClientError::NoThreshold)?;
let coconut_api_clients = CoconutApiClient::all_coconut_api_clients(&client, epoch_id).await?;
let params = Parameters::new(TOTAL_ATTRIBUTES).unwrap();
let bandwidth_credential_attributes = BandwidthVoucher::new(
&params,
state.amount.to_string(),
VOUCHER_INFO.to_string(),
Hash::from_str(&state.tx_hash).map_err(|_| CredentialClientError::InvalidTxHash)?,
identity::PrivateKey::from_base58_string(&state.signing_keypair.private_key)?,
encryption::PrivateKey::from_base58_string(&state.encryption_keypair.private_key)?,
);
let signature = obtain_aggregate_signature(
&params,
&bandwidth_credential_attributes,
&state.params,
&state.voucher,
&coconut_api_clients,
threshold,
)
.await?;
println!("Signature: {:?}", signature.to_bs58());
info!("Signature: {:?}", signature.to_bs58());
shared_storage
.insert_coconut_credential(
state.amount.to_string(),
state.voucher.get_voucher_value(),
VOUCHER_INFO.to_string(),
bandwidth_credential_attributes.get_private_attributes()[0].to_bs58(),
bandwidth_credential_attributes.get_private_attributes()[1].to_bs58(),
state.voucher.get_private_attributes()[0].to_bs58(),
state.voucher.get_private_attributes()[1].to_bs58(),
signature.to_bs58(),
epoch_id.to_string(),
)
@@ -114,3 +133,33 @@ pub(crate) async fn get_credential(state: &State, shared_storage: PersistentStor
Ok(())
}
pub(crate) async fn recover_credentials<C: Clone + CosmWasmClient + Send + Sync>(
client: validator_client::Client<C>,
recovery_storage: &RecoveryStorage,
shared_storage: PersistentStorage,
) -> Result<()> {
for voucher in recovery_storage.unconsumed_vouchers()? {
let state = State {
voucher,
params: Parameters::new(TOTAL_ATTRIBUTES).unwrap(),
};
if let Err(e) = get_credential(&state, client.clone(), shared_storage.clone()).await {
error!(
"Could not recover deposit {} due to {:?}, try again later",
state.voucher.tx_hash(),
e
)
} else {
info!(
"Converted deposit {} to a credential, removing recovery data for it",
state.voucher.tx_hash()
);
if let Err(e) = recovery_storage.remove_voucher(state.voucher.tx_hash().to_string()) {
warn!("Could not remove recovery data - {:?}", e);
}
}
}
Ok(())
}
+12 -2
View File
@@ -1,12 +1,13 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use std::time::SystemTimeError;
use thiserror::Error;
use credential_storage::error::StorageError;
use credentials::error::Error as CredentialError;
use crypto::asymmetric::encryption::KeyRecoveryError;
use crypto::asymmetric::identity::Ed25519RecoveryError;
use nym_crypto::asymmetric::encryption::KeyRecoveryError;
use nym_crypto::asymmetric::identity::Ed25519RecoveryError;
use validator_client::nyxd::error::NyxdError;
use validator_client::ValidatorClientError;
@@ -14,6 +15,9 @@ pub type Result<T> = std::result::Result<T, CredentialClientError>;
#[derive(Error, Debug)]
pub enum CredentialClientError {
#[error("IO error: {0}")]
IOError(#[from] std::io::Error),
#[error("Nyxd error: {0}")]
Nyxd(#[from] NyxdError),
@@ -34,4 +38,10 @@ pub enum CredentialClientError {
#[error("Could not use shared storage")]
SharedStorageError(#[from] StorageError),
#[error("Could not get system time")]
SysTimeError(#[from] SystemTimeError),
#[error("Threshold not set yet")]
NoThreshold,
}
+95 -42
View File
@@ -1,56 +1,109 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
cfg_if::cfg_if! {
if #[cfg(feature = "coconut")] {
mod client;
mod commands;
mod error;
mod recovery_storage;
mod state;
mod client;
mod commands;
mod error;
mod state;
use commands::*;
use completions::fig_generate;
use config::{DATA_DIR, DB_FILE_NAME};
use error::Result;
use log::*;
use network_defaults::{setup_env, NymNetworkDetails};
use std::process::exit;
use std::time::{Duration, SystemTime};
use error::Result;
use network_defaults::setup_env;
use completions::fig_generate;
use commands::*;
use config::{DATA_DIR, DB_FILE_NAME};
use clap::{CommandFactory, Parser};
use logging::setup_logging;
use validator_client::nyxd::traits::DkgQueryClient;
use validator_client::nyxd::CosmWasmClient;
use validator_client::Config;
use clap::{CommandFactory, Parser};
const SAFETY_BUFFER_SECS: u64 = 60; // 1 minute
#[derive(Parser)]
#[clap(author = "Nymtech", version, about)]
struct Cli {
/// Path pointing to an env file that configures the client.
#[clap(short, long)]
pub(crate) config_env_file: Option<std::path::PathBuf>,
#[derive(Parser)]
#[clap(author = "Nymtech", version, about)]
struct Cli {
/// Path pointing to an env file that configures the client.
#[clap(short, long)]
pub(crate) config_env_file: Option<std::path::PathBuf>,
#[clap(subcommand)]
pub(crate) command: Command,
}
#[clap(subcommand)]
pub(crate) command: Command,
}
#[tokio::main]
async fn main() -> Result<()> {
let args = Cli::parse();
setup_env(args.config_env_file.as_ref());
let bin_name = "nym-credential-client";
match args.command {
Command::Run(r) => {
let db_path = r.client_home_directory.join(DATA_DIR).join(DB_FILE_NAME);
let shared_storage = credential_storage::initialise_storage(db_path).await;
let state = deposit(&r.nyxd_url, &r.mnemonic, r.amount).await?;
get_credential(&state, shared_storage).await?;
}
Command::Completions(c) => c.generate(&mut crate::Cli::command(), bin_name),
Command::GenerateFigSpec => fig_generate(&mut crate::Cli::command(), bin_name)
async fn block_until_coconut_is_available<C: Clone + CosmWasmClient + Send + Sync>(
client: &validator_client::Client<C>,
) -> Result<()> {
loop {
let epoch = client.nyxd.get_current_epoch().await?;
let current_timestamp_secs = SystemTime::now()
.duration_since(SystemTime::UNIX_EPOCH)?
.as_secs();
if epoch.state.is_final() {
if current_timestamp_secs + SAFETY_BUFFER_SECS >= epoch.finish_timestamp.seconds() {
info!("In the next {} minute(s), a transition will take place in the coconut system. Deposits should be halted in this time for safety reasons.", SAFETY_BUFFER_SECS / 60);
exit(0);
}
Ok(())
}
} else {
fn main() {
println!("Crate only designed for coconut feature");
break;
} else {
// Use 20 additional seconds to avoid the exact moment of going into the final epoch state
let secs_until_final = epoch.final_timestamp_secs() + 20 - current_timestamp_secs;
info!("Approximately {} seconds until coconut is available. Sleeping until then. You can safely kill the process at any moment.", secs_until_final);
std::thread::sleep(Duration::from_secs(secs_until_final));
}
}
Ok(())
}
#[tokio::main]
async fn main() -> Result<()> {
let args = Cli::parse();
setup_logging();
setup_env(args.config_env_file.as_ref());
let bin_name = "nym-credential-client";
match args.command {
Command::Run(r) => {
let db_path = r.client_home_directory.join(DATA_DIR).join(DB_FILE_NAME);
let shared_storage = credential_storage::initialise_storage(db_path).await;
let recovery_storage = recovery_storage::RecoveryStorage::new(r.recovery_dir)?;
let network_details = NymNetworkDetails::new_from_env();
let config = Config::try_from_nym_network_details(&network_details)?;
let client = validator_client::Client::new_query(config)?;
block_until_coconut_is_available(&client).await?;
info!("Starting depositing funds, don't kill the process");
if !r.recovery_mode {
let state = deposit(&r.nyxd_url, &r.mnemonic, r.amount).await?;
if get_credential(&state, client, shared_storage)
.await
.is_err()
{
warn!("Failed to obtain credential. Dumping recovery data.",);
match recovery_storage.insert_voucher(&state.voucher) {
Ok(file_path) => {
warn!("Dumped recovery data to {:?}. Try using recovery mode to convert it to a credential", file_path);
}
Err(e) => {
error!("Could not dump recovery data to file system due to {:?}, the deposit will be lost!", e)
}
}
}
} else {
recover_credentials(client, &recovery_storage, shared_storage).await?;
}
}
Command::Completions(c) => c.generate(&mut crate::Cli::command(), bin_name),
Command::GenerateFigSpec => fig_generate(&mut crate::Cli::command(), bin_name),
}
Ok(())
}
@@ -0,0 +1,56 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use credentials::coconut::bandwidth::BandwidthVoucher;
use std::fs::{create_dir_all, read_dir, File};
use std::io::{Read, Write};
use std::path::PathBuf;
pub struct RecoveryStorage {
recovery_dir: PathBuf,
}
impl RecoveryStorage {
pub fn new(recovery_dir: PathBuf) -> std::io::Result<Self> {
create_dir_all(&recovery_dir)?;
Ok(Self { recovery_dir })
}
pub fn unconsumed_vouchers(&self) -> std::io::Result<impl Iterator<Item = BandwidthVoucher>> {
Ok(read_dir(&self.recovery_dir)?
.filter_map(|entry| entry.ok())
.filter_map(|entry| {
let path = entry.path();
if path.is_file() {
Some(path)
} else {
None
}
})
.filter_map(|path| File::open(path).ok())
.filter_map(|mut f| {
let mut buff = Vec::new();
if f.read_to_end(&mut buff).is_ok() {
Some(buff)
} else {
None
}
})
.filter_map(|buff| BandwidthVoucher::try_from_bytes(&buff).ok()))
}
pub fn insert_voucher(&self, voucher: &BandwidthVoucher) -> std::io::Result<PathBuf> {
let file_name = voucher.tx_hash().to_string();
let file_path = self.recovery_dir.join(file_name);
let mut file = File::create(&file_path)?;
let buff = voucher.to_bytes();
file.write_all(&buff)?;
Ok(file_path)
}
pub fn remove_voucher(&self, file_name: String) -> std::io::Result<()> {
let file_path = self.recovery_dir.join(file_name);
std::fs::remove_file(file_path)
}
}
+5 -8
View File
@@ -1,11 +1,11 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use serde::{Deserialize, Serialize};
use coconut_interface::Parameters;
use credentials::coconut::bandwidth::BandwidthVoucher;
use crypto::asymmetric::{encryption, identity};
use nym_crypto::asymmetric::{encryption, identity};
#[derive(Clone, Debug, Deserialize, Serialize)]
pub(crate) struct KeyPair {
pub public_key: String,
pub private_key: String,
@@ -29,10 +29,7 @@ impl From<encryption::KeyPair> for KeyPair {
}
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub(crate) struct State {
pub amount: u64,
pub tx_hash: String,
pub signing_keypair: KeyPair,
pub encryption_keypair: KeyPair,
pub voucher: BandwidthVoucher,
pub params: Parameters,
}
+5 -8
View File
@@ -1,6 +1,6 @@
[package]
name = "nym-client"
version = "1.1.8"
version = "1.1.10"
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jędrzej Stuczyński <andrew@nymtech.net>"]
description = "Implementation of the Nym Client"
edition = "2021"
@@ -37,26 +37,23 @@ tokio-tungstenite = "0.14" # websocket
build-information = { path = "../../common/build-information" }
client-core = { path = "../client-core", features = ["fs-surb-storage"] }
client-connections = { path = "../../common/client-connections" }
coconut-interface = { path = "../../common/coconut-interface", optional = true }
coconut-interface = { path = "../../common/coconut-interface" }
config = { path = "../../common/config" }
completions = { path = "../../common/completions" }
credential-storage = { path = "../../common/credential-storage" }
credentials = { path = "../../common/credentials", optional = true }
crypto = { path = "../../common/crypto" }
credentials = { path = "../../common/credentials" }
nym-crypto = { path = "../../common/crypto" }
logging = { path = "../../common/logging"}
gateway-client = { path = "../../common/client-libs/gateway-client" }
gateway-requests = { path = "../../gateway/gateway-requests" }
network-defaults = { path = "../../common/network-defaults" }
nymsphinx = { path = "../../common/nymsphinx" }
pemstore = { path = "../../common/pemstore" }
nym-pemstore = { path = "../../common/pemstore" }
task = { path = "../../common/task" }
topology = { path = "../../common/topology" }
validator-client = { path = "../../common/client-libs/validator-client", features = ["nyxd-client"] }
version-checker = { path = "../../common/version-checker" }
websocket-requests = { path = "websocket-requests" }
[features]
coconut = ["coconut-interface", "credentials", "credentials/coconut", "gateway-requests/coconut", "gateway-client/coconut", "client-core/coconut"]
[dev-dependencies]
serde_json = "1.0" # for the "textsend" example
+18 -4
View File
@@ -2,16 +2,19 @@
// SPDX-License-Identifier: Apache-2.0
use crate::client::config::template::config_template;
pub use client_core::config::Config as BaseConfig;
pub use client_core::config::MISSING_VALUE;
use client_core::config::{ClientCoreConfigTrait, DebugConfig};
use client_core::config::ClientCoreConfigTrait;
use config::defaults::DEFAULT_WEBSOCKET_LISTENING_PORT;
use config::{NymConfig, OptionalSet};
use serde::{Deserialize, Serialize};
use std::fmt::Debug;
use std::net::{IpAddr, Ipv4Addr};
use std::path::PathBuf;
use std::str::FromStr;
pub use client_core::config::Config as BaseConfig;
pub use client_core::config::MISSING_VALUE;
pub use client_core::config::{DebugConfig, GatewayEndpointConfig};
mod template;
#[derive(Debug, Deserialize, PartialEq, Eq, Serialize, Clone, Copy)]
@@ -104,6 +107,11 @@ impl Config {
self
}
pub fn with_host(mut self, host: IpAddr) -> Self {
self.socket.host = host;
self
}
pub fn with_port(mut self, port: u16) -> Self {
self.socket.listening_port = port;
self
@@ -130,6 +138,10 @@ impl Config {
self.socket.socket_type
}
pub fn get_listening_ip(&self) -> IpAddr {
self.socket.host
}
pub fn get_listening_port(&self) -> u16 {
self.socket.listening_port
}
@@ -180,9 +192,10 @@ impl Config {
}
#[derive(Debug, Deserialize, PartialEq, Eq, Serialize)]
#[serde(deny_unknown_fields)]
#[serde(default, deny_unknown_fields)]
pub struct Socket {
socket_type: SocketType,
host: IpAddr,
listening_port: u16,
}
@@ -190,6 +203,7 @@ impl Default for Socket {
fn default() -> Self {
Socket {
socket_type: SocketType::WebSocket,
host: IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)),
listening_port: DEFAULT_WEBSOCKET_LISTENING_PORT,
}
}
@@ -93,6 +93,9 @@ socket_type = '{{ socket.socket_type }}'
# will be listening for incoming requests
listening_port = {{ socket.listening_port }}
# if applicable (for the case of 'WebSocket'), the ip address on which the client
# will be listening for incoming requests
host = '{{ socket.host }}'
##### logging configuration options #####
+54 -10
View File
@@ -11,19 +11,22 @@ use client_core::client::base_client::{
non_wasm_helpers, BaseClientBuilder, ClientInput, ClientOutput, ClientState,
};
use client_core::client::inbound_messages::InputMessage;
use client_core::client::key_manager::KeyManager;
use client_core::client::received_buffer::{ReceivedBufferMessage, ReconstructedMessagesReceiver};
use client_core::client::received_buffer::{
ReceivedBufferMessage, ReceivedBufferRequestSender, ReconstructedMessagesReceiver,
};
use client_core::config::persistence::key_pathfinder::ClientKeyPathfinder;
use futures::channel::mpsc;
use gateway_client::bandwidth::BandwidthController;
use log::*;
use nymsphinx::addressing::clients::Recipient;
use nymsphinx::anonymous_replies::requests::AnonymousSenderTag;
use nymsphinx::receiver::ReconstructedMessage;
use task::TaskManager;
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 {
/// Client configuration options, including, among other things, packet sending rates,
@@ -45,6 +48,13 @@ impl SocketClient {
}
}
pub fn new_with_keys(config: Config, key_manager: KeyManager) -> Self {
SocketClient {
config,
key_manager,
}
}
async fn create_bandwidth_controller(config: &Config) -> BandwidthController<QueryNyxdClient> {
let details = network_defaults::NymNetworkDetails::new_from_env();
let mut client_config = validator_client::Config::try_from_nym_network_details(&details)
@@ -102,7 +112,8 @@ impl SocketClient {
reply_controller_sender,
);
websocket::Listener::new(config.get_listening_port()).start(websocket_handler, shutdown);
websocket::Listener::new(config.get_listening_ip(), config.get_listening_port())
.start(websocket_handler, shutdown);
}
/// blocking version of `start_socket` method. Will run forever (or until SIGINT is sent)
@@ -119,10 +130,17 @@ impl SocketClient {
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(
self.config.get_base(),
self.key_manager,
Some(Self::create_bandwidth_controller(&self.config).await),
bandwidth_controller,
non_wasm_helpers::setup_fs_reply_surb_backend(
Some(self.config.get_base().get_reply_surb_database_path()),
self.config.get_debug_settings(),
@@ -156,10 +174,17 @@ impl SocketClient {
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(
self.config.get_base(),
self.key_manager,
Some(Self::create_bandwidth_controller(&self.config).await),
bandwidth_controller,
non_wasm_helpers::setup_fs_reply_surb_backend(
Some(self.config.get_base().get_reply_surb_database_path()),
self.config.get_debug_settings(),
@@ -167,6 +192,8 @@ impl SocketClient {
.await?,
);
let address = base_client.as_mix_recipient();
let mut started_client = base_client.start_base().await?;
let client_input = started_client.client_input.register_producer();
let client_output = started_client.client_output.register_consumer();
@@ -184,21 +211,38 @@ impl SocketClient {
Ok(DirectClient {
client_input,
_received_buffer_request_sender: client_output.received_buffer_request_sender,
reconstructed_receiver,
_shutdown_notifier: started_client.task_manager,
address,
shutdown_notifier: started_client.task_manager,
})
}
}
pub struct DirectClient {
client_input: ClientInput,
// make sure to not drop the channel
_received_buffer_request_sender: ReceivedBufferRequestSender,
reconstructed_receiver: ReconstructedMessagesReceiver,
address: Recipient,
// we need to keep reference to this guy otherwise things will start dropping
_shutdown_notifier: TaskManager,
shutdown_notifier: TaskManager,
}
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
/// It's untested and there are absolutely no guarantees about it (but seems to have worked
/// well enough in local tests)
+10 -8
View File
@@ -8,10 +8,11 @@ use crate::{
};
use clap::Args;
use config::NymConfig;
use crypto::asymmetric::identity;
use nym_crypto::asymmetric::identity;
use nymsphinx::addressing::clients::Recipient;
use serde::Serialize;
use std::fmt::Display;
use std::net::IpAddr;
use tap::TapFallible;
#[derive(Args, Clone)]
@@ -30,8 +31,7 @@ pub(crate) struct Init {
force_register_gateway: bool,
/// Comma separated list of rest endpoints of the nyxd validators
#[cfg(feature = "coconut")]
#[clap(long, alias = "nymd_validators", value_delimiter = ',')]
#[clap(long, alias = "nyxd_validators", value_delimiter = ',', hide = true)]
nyxd_urls: Option<Vec<url::Url>>,
/// Comma separated list of rest endpoints of the API validators
@@ -47,6 +47,10 @@ pub(crate) struct Init {
#[clap(short, long)]
port: Option<u16>,
/// Ip for the socket (if applicable) to listen for requests.
#[clap(long)]
host: Option<IpAddr>,
/// Mostly debug-related option to increase default traffic rate so that you would not need to
/// modify config post init
#[clap(long, hide = true)]
@@ -58,8 +62,7 @@ pub(crate) struct Init {
/// Set this client to work in a enabled credentials mode that would attempt to use gateway
/// with bandwidth credential requirement.
#[cfg(feature = "coconut")]
#[clap(long)]
#[clap(long, hide = true)]
enabled_credentials_mode: Option<bool>,
/// Save a summary of the initialization to a json file
@@ -73,12 +76,11 @@ impl From<Init> for OverrideConfig {
nym_apis: init_config.nym_apis,
disable_socket: init_config.disable_socket,
port: init_config.port,
host: init_config.host,
fastmode: init_config.fastmode,
no_cover: init_config.no_cover,
#[cfg(feature = "coconut")]
nyxd_urls: init_config.nyxd_urls,
#[cfg(feature = "coconut")]
enabled_credentials_mode: init_config.enabled_credentials_mode,
}
}
@@ -145,7 +147,7 @@ pub(crate) async fn execute(args: &Init) -> Result<(), ClientError> {
.await
.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(|_| {
log::error!("Failed to save the config file");
+16 -23
View File
@@ -9,6 +9,7 @@ use completions::{fig_generate, ArgShell};
use config::OptionalSet;
use lazy_static::lazy_static;
use std::error::Error;
use std::net::IpAddr;
pub(crate) mod init;
pub(crate) mod run;
@@ -56,12 +57,10 @@ pub(crate) struct OverrideConfig {
nym_apis: Option<Vec<url::Url>>,
disable_socket: Option<bool>,
port: Option<u16>,
host: Option<IpAddr>,
fastmode: bool,
no_cover: bool,
#[cfg(feature = "coconut")]
nyxd_urls: Option<Vec<url::Url>>,
#[cfg(feature = "coconut")]
enabled_credentials_mode: Option<bool>,
}
@@ -78,35 +77,29 @@ pub(crate) async fn execute(args: &Cli) -> Result<(), Box<dyn Error + Send + Syn
Ok(())
}
pub(crate) fn override_config(mut config: Config, args: OverrideConfig) -> Config {
config = config
pub(crate) fn override_config(config: Config, args: OverrideConfig) -> Config {
config
.with_optional(Config::with_disabled_socket, args.disable_socket)
.with_base(BaseConfig::with_high_default_traffic_volume, args.fastmode)
.with_base(BaseConfig::with_disabled_cover_traffic, args.no_cover)
.with_optional(Config::with_port, args.port)
.with_optional(Config::with_host, args.host)
.with_optional_custom_env_ext(
BaseConfig::with_custom_nym_apis,
args.nym_apis,
network_defaults::var_names::NYM_API,
config::parse_urls,
);
#[cfg(feature = "coconut")]
{
config = config
.with_optional_custom_env_ext(
BaseConfig::with_custom_nyxd,
args.nyxd_urls,
network_defaults::var_names::NYXD,
config::parse_urls,
)
.with_optional_ext(
BaseConfig::with_disabled_credentials,
args.enabled_credentials_mode.map(|b| !b),
);
}
config
)
.with_optional_custom_env_ext(
BaseConfig::with_custom_nyxd,
args.nyxd_urls,
network_defaults::var_names::NYXD,
config::parse_urls,
)
.with_optional_ext(
BaseConfig::with_disabled_credentials,
args.enabled_credentials_mode.map(|b| !b),
)
}
#[cfg(test)]
+9 -8
View File
@@ -2,6 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
use std::error::Error;
use std::net::IpAddr;
use crate::{
client::{config::Config, SocketClient},
@@ -11,8 +12,8 @@ use crate::{
use clap::Args;
use config::NymConfig;
use crypto::asymmetric::identity;
use log::*;
use nym_crypto::asymmetric::identity;
use version_checker::is_minor_version_compatible;
#[derive(Args, Clone)]
@@ -22,8 +23,7 @@ pub(crate) struct Run {
id: String,
/// Comma separated list of rest endpoints of the nyxd validators
#[cfg(feature = "coconut")]
#[clap(long, alias = "nymd_validators", value_delimiter = ',')]
#[clap(long, alias = "nyxd_validators", value_delimiter = ',', hide = true)]
nyxd_urls: Option<Vec<url::Url>>,
/// Comma separated list of rest endpoints of the API validators
@@ -44,6 +44,10 @@ pub(crate) struct Run {
#[clap(short, long)]
port: Option<u16>,
/// Ip for the socket (if applicable) to listen for requests.
#[clap(long)]
host: Option<IpAddr>,
/// Mostly debug-related option to increase default traffic rate so that you would not need to
/// modify config post init
#[clap(long, hide = true)]
@@ -55,8 +59,7 @@ pub(crate) struct Run {
/// Set this client to work in a enabled credentials mode that would attempt to use gateway
/// with bandwidth credential requirement.
#[cfg(feature = "coconut")]
#[clap(long)]
#[clap(long, hide = true)]
enabled_credentials_mode: Option<bool>,
}
@@ -66,12 +69,10 @@ impl From<Run> for OverrideConfig {
nym_apis: run_config.nym_apis,
disable_socket: run_config.disable_socket,
port: run_config.port,
host: run_config.host,
fastmode: run_config.fastmode,
no_cover: run_config.no_cover,
#[cfg(feature = "coconut")]
nyxd_urls: run_config.nyxd_urls,
#[cfg(feature = "coconut")]
enabled_credentials_mode: run_config.enabled_credentials_mode,
}
}
+3 -3
View File
@@ -3,6 +3,7 @@
use super::handler::HandlerBuilder;
use log::*;
use std::net::IpAddr;
use std::{net::SocketAddr, process, sync::Arc};
use tokio::io::AsyncWriteExt;
use tokio::{sync::Notify, task::JoinHandle};
@@ -24,10 +25,9 @@ pub(crate) struct Listener {
}
impl Listener {
pub(crate) fn new(port: u16) -> Self {
pub(crate) fn new(host: IpAddr, port: u16) -> Self {
Listener {
// unless we find compelling reason not to, just listen on local only
address: SocketAddr::new("127.0.0.1".parse().unwrap(), port),
address: SocketAddr::new(host, port),
state: State::AwaitingConnection,
}
}
+12 -9
View File
@@ -1,6 +1,6 @@
[package]
name = "nym-socks5-client"
version = "1.1.8"
version = "1.1.10"
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"]
description = "A SOCKS5 localhost proxy that converts incoming messages to Sphinx and sends them to a Nym address"
edition = "2021"
@@ -19,8 +19,8 @@ log = { workspace = true }
pin-project = "1.0"
pretty_env_logger = "0.4"
rand = { version = "0.7.3", features = ["wasm-bindgen"] }
serde = { version = "1.0", features = ["derive"] } # for config serialization/deserialization
serde_json = "1.0.89"
serde = { workspace = true, features = ["derive"] } # for config serialization/deserialization
serde_json = { workspace = true }
tap = "1.0.1"
thiserror = "1.0.34"
tokio = { version = "1.24.1", features = ["rt-multi-thread", "net", "signal"] }
@@ -30,20 +30,22 @@ url = "2.2"
build-information = { path = "../../common/build-information" }
client-core = { path = "../client-core", features = ["fs-surb-storage"] }
client-connections = { path = "../../common/client-connections" }
coconut-interface = { path = "../../common/coconut-interface", optional = true }
coconut-interface = { path = "../../common/coconut-interface" }
config = { path = "../../common/config" }
completions = { path = "../../common/completions" }
credential-storage = { path = "../../common/credential-storage" }
credentials = { path = "../../common/credentials", optional = true }
crypto = { path = "../../common/crypto" }
credential-storage = { path = "../../common/credential-storage", optional = true }
mobile-storage = { path = "../../common/mobile-storage", optional = true }
credentials = { path = "../../common/credentials" }
nym-crypto = { path = "../../common/crypto" }
logging = { path = "../../common/logging"}
gateway-client = { path = "../../common/client-libs/gateway-client" }
gateway-requests = { path = "../../gateway/gateway-requests" }
network-defaults = { path = "../../common/network-defaults" }
nymsphinx = { path = "../../common/nymsphinx" }
ordered-buffer = { path = "../../common/socks5/ordered-buffer" }
pemstore = { path = "../../common/pemstore" }
nym-pemstore = { path = "../../common/pemstore" }
proxy-helpers = { path = "../../common/socks5/proxy-helpers" }
service-providers-common = { path = "../../service-providers/common" }
socks5-requests = { path = "../../common/socks5/requests" }
task = { path = "../../common/task" }
topology = { path = "../../common/topology" }
@@ -51,5 +53,6 @@ validator-client = { path = "../../common/client-libs/validator-client", feature
version-checker = { path = "../../common/version-checker" }
[features]
coconut = ["coconut-interface", "credentials", "gateway-requests/coconut", "gateway-client/coconut", "credentials/coconut", "client-core/coconut"]
default = ["credential-storage"]
eth = []
mobile = ["mobile-storage", "gateway-client/mobile"]
+43 -8
View File
@@ -1,4 +1,4 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::client::config::template::config_template;
@@ -9,6 +9,8 @@ use config::defaults::DEFAULT_SOCKS5_LISTENING_PORT;
use config::{NymConfig, OptionalSet};
use nymsphinx::addressing::clients::Recipient;
use serde::{Deserialize, Serialize};
use service_providers_common::interface::ProviderInterfaceVersion;
use socks5_requests::Socks5ProtocolVersion;
use std::fmt::Debug;
use std::path::PathBuf;
use std::str::FromStr;
@@ -18,7 +20,7 @@ mod template;
const DEFAULT_CONNECTION_START_SURBS: u32 = 20;
const DEFAULT_PER_REQUEST_SURBS: u32 = 3;
#[derive(Debug, Default, Deserialize, PartialEq, Serialize)]
#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct Config {
#[serde(flatten)]
@@ -36,10 +38,12 @@ impl NymConfig for Config {
}
fn default_root_directory() -> PathBuf {
dirs::home_dir()
.expect("Failed to evaluate $HOME value")
.join(".nym")
.join("socks5-clients")
#[cfg(not(feature = "mobile"))]
let base_dir = dirs::home_dir().expect("Failed to evaluate $HOME value");
#[cfg(feature = "mobile")]
let base_dir = PathBuf::from("/tmp");
base_dir.join(".nym").join("socks5-clients")
}
fn try_default_root_directory() -> Option<PathBuf> {
@@ -88,6 +92,16 @@ impl Config {
self
}
pub fn with_provider_interface_version(mut self, version: ProviderInterfaceVersion) -> Self {
self.socks5.provider_interface_version = version;
self
}
pub fn with_socks5_protocol_version(mut self, version: Socks5ProtocolVersion) -> Self {
self.socks5.socks5_protocol_version = version;
self
}
pub fn with_anonymous_replies(mut self, anonymous_replies: bool) -> Self {
self.socks5.send_anonymously = anonymous_replies;
self
@@ -115,6 +129,14 @@ impl Config {
.expect("malformed provider address")
}
pub fn get_provider_interface_version(&self) -> ProviderInterfaceVersion {
self.socks5.provider_interface_version
}
pub fn get_socks5_protocol_version(&self) -> Socks5ProtocolVersion {
self.socks5.socks5_protocol_version
}
pub fn get_send_anonymously(&self) -> bool {
self.socks5.send_anonymously
}
@@ -176,7 +198,7 @@ impl Config {
}
}
#[derive(Debug, Deserialize, PartialEq, Eq, Serialize)]
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct Socks5 {
/// The port on which the client will be listening for incoming requests
@@ -185,6 +207,15 @@ pub struct Socks5 {
/// The mix address of the provider to which all requests are going to be sent.
provider_mix_address: String,
/// The version of the 'service provider' this client is going to use in its communication with the
/// specified socks5 provider.
// if in doubt, use the legacy version as initially nobody will be using the updated binaries
#[serde(default = "ProviderInterfaceVersion::new_legacy")]
provider_interface_version: ProviderInterfaceVersion,
#[serde(default = "Socks5ProtocolVersion::new_legacy")]
socks5_protocol_version: Socks5ProtocolVersion,
/// Specifies whether this client is going to use an anonymous sender tag for communication with the service provider.
/// While this is going to hide its actual address information, it will make the actual communication
/// slower and consume nearly double the bandwidth as it will require sending reply SURBs.
@@ -199,6 +230,8 @@ impl Socks5 {
Socks5 {
listening_port: DEFAULT_SOCKS5_LISTENING_PORT,
provider_mix_address: provider_mix_address.into(),
provider_interface_version: ProviderInterfaceVersion::Legacy,
socks5_protocol_version: Socks5ProtocolVersion::Legacy,
send_anonymously: false,
}
}
@@ -209,12 +242,14 @@ impl Default for Socks5 {
Socks5 {
listening_port: DEFAULT_SOCKS5_LISTENING_PORT,
provider_mix_address: "".into(),
provider_interface_version: ProviderInterfaceVersion::Legacy,
socks5_protocol_version: Socks5ProtocolVersion::Legacy,
send_anonymously: false,
}
}
}
#[derive(Debug, Deserialize, PartialEq, Eq, Serialize)]
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct Socks5Debug {
/// Number of reply SURBs attached to each `Request::Connect` message.
+40 -7
View File
@@ -8,13 +8,17 @@ use crate::socks::{
authentication::{AuthenticationMethods, Authenticator, User},
server::SphinxSocksServer,
};
use client_core::client::base_client::{
non_wasm_helpers, BaseClientBuilder, ClientInput, ClientOutput, ClientState,
};
#[cfg(feature = "mobile")]
use client_core::client::base_client::helpers::setup_empty_reply_surb_backend;
#[cfg(not(feature = "mobile"))]
use client_core::client::base_client::non_wasm_helpers;
use client_core::client::base_client::{BaseClientBuilder, ClientInput, ClientOutput, ClientState};
use client_core::client::key_manager::KeyManager;
use client_core::config::persistence::key_pathfinder::ClientKeyPathfinder;
use futures::channel::mpsc;
use futures::StreamExt;
#[cfg(not(feature = "mobile"))]
use gateway_client::bandwidth::BandwidthController;
use log::*;
use nymsphinx::addressing::clients::Recipient;
@@ -54,6 +58,19 @@ impl NymClient {
}
}
pub fn new_with_keys(config: Config, key_manager: Option<KeyManager>) -> Self {
let key_manager = key_manager.unwrap_or_else(|| {
let pathfinder = ClientKeyPathfinder::new_from_config(config.get_base());
KeyManager::load_keys(&pathfinder).expect("failed to load stored keys")
});
NymClient {
config,
key_manager,
}
}
#[cfg(not(feature = "mobile"))]
async fn create_bandwidth_controller(config: &Config) -> BandwidthController<QueryNyxdClient> {
let details = network_defaults::NymNetworkDetails::new_from_env();
let mut client_config = validator_client::Config::try_from_nym_network_details(&details)
@@ -72,10 +89,15 @@ impl NymClient {
client_config = client_config.with_urls(nyxd_url, api_url);
let client = validator_client::Client::new_query(client_config)
.expect("Could not construct query client");
BandwidthController::new(
credential_storage::initialise_storage(config.get_base().get_database_path()).await,
client,
)
#[cfg(not(feature = "mobile"))]
let storage =
credential_storage::initialise_storage(config.get_base().get_database_path()).await;
#[cfg(feature = "mobile")]
let storage = mobile_storage::PersistentStorage {};
BandwidthController::new(storage, client)
}
fn start_socks5_listener(
@@ -112,6 +134,8 @@ impl NymClient {
self_address,
shared_lane_queue_lengths,
socks::client::Config::new(
config.get_provider_interface_version(),
config.get_socks5_protocol_version(),
config.get_send_anonymously(),
config.get_connection_start_surbs(),
config.get_per_request_surbs(),
@@ -188,6 +212,7 @@ impl NymClient {
}
pub async fn start(self) -> Result<TaskManager, Socks5ClientError> {
#[cfg(not(feature = "mobile"))]
let base_builder = BaseClientBuilder::new_from_base_config(
self.config.get_base(),
self.key_manager,
@@ -199,6 +224,14 @@ impl NymClient {
.await?,
);
#[cfg(feature = "mobile")]
let base_builder = BaseClientBuilder::<_, QueryNyxdClient>::new_from_base_config(
self.config.get_base(),
self.key_manager,
None,
setup_empty_reply_surb_backend(self.config.get_debug_settings()),
);
let self_address = base_builder.as_mix_recipient();
let mut started_client = base_builder.start_base().await?;
let client_input = started_client.client_input.register_producer();
+6 -9
View File
@@ -8,7 +8,7 @@ use crate::{
};
use clap::Args;
use config::NymConfig;
use crypto::asymmetric::identity;
use nym_crypto::asymmetric::identity;
use nymsphinx::addressing::clients::Recipient;
use serde::Serialize;
use std::fmt::Display;
@@ -43,8 +43,7 @@ pub(crate) struct Init {
force_register_gateway: bool,
/// Comma separated list of rest endpoints of the nyxd validators
#[cfg(feature = "coconut")]
#[clap(long, alias = "nymd_validators", value_delimiter = ',')]
#[clap(long, alias = "nyxd_validators", value_delimiter = ',', hide = true)]
nyxd_urls: Option<Vec<url::Url>>,
/// Comma separated list of rest endpoints of the API validators
@@ -67,8 +66,7 @@ pub(crate) struct Init {
/// Set this client to work in a enabled credentials mode that would attempt to use gateway
/// with bandwidth credential requirement.
#[cfg(feature = "coconut")]
#[clap(long)]
#[clap(long, hide = true)]
enabled_credentials_mode: Option<bool>,
/// Save a summary of the initialization to a json file
@@ -84,10 +82,7 @@ impl From<Init> for OverrideConfig {
use_anonymous_replies: init_config.use_reply_surbs,
fastmode: init_config.fastmode,
no_cover: init_config.no_cover,
#[cfg(feature = "coconut")]
nyxd_urls: init_config.nyxd_urls,
#[cfg(feature = "coconut")]
enabled_credentials_mode: init_config.enabled_credentials_mode,
}
}
@@ -158,7 +153,9 @@ pub(crate) async fn execute(args: &Init) -> Result<(), Socks5ClientError> {
.await
.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);
// TODO: ask the service provider we specified for its interface version and set it in the config
config.save_to_file(None).tap_err(|_| {
log::error!("Failed to save the config file");
+13 -23
View File
@@ -60,10 +60,7 @@ pub(crate) struct OverrideConfig {
use_anonymous_replies: Option<bool>,
fastmode: bool,
no_cover: bool,
#[cfg(feature = "coconut")]
nyxd_urls: Option<Vec<url::Url>>,
#[cfg(feature = "coconut")]
enabled_credentials_mode: Option<bool>,
}
@@ -80,8 +77,8 @@ pub(crate) async fn execute(args: &Cli) -> Result<(), Box<dyn Error + Send + Syn
Ok(())
}
pub(crate) fn override_config(mut config: Config, args: OverrideConfig) -> Config {
config = config
pub(crate) fn override_config(config: Config, args: OverrideConfig) -> Config {
config
.with_base(BaseConfig::with_high_default_traffic_volume, args.fastmode)
.with_base(BaseConfig::with_disabled_cover_traffic, args.no_cover)
.with_optional(Config::with_anonymous_replies, args.use_anonymous_replies)
@@ -91,24 +88,17 @@ pub(crate) fn override_config(mut config: Config, args: OverrideConfig) -> Confi
args.nym_apis,
network_defaults::var_names::NYM_API,
config::parse_urls,
);
#[cfg(feature = "coconut")]
{
config = config
.with_optional_custom_env_ext(
BaseConfig::with_custom_nyxd,
args.nyxd_urls,
network_defaults::var_names::NYXD,
config::parse_urls,
)
.with_optional_ext(
BaseConfig::with_disabled_credentials,
args.enabled_credentials_mode.map(|b| !b),
);
}
config
)
.with_optional_custom_env_ext(
BaseConfig::with_custom_nyxd,
args.nyxd_urls,
network_defaults::var_names::NYXD,
config::parse_urls,
)
.with_optional_ext(
BaseConfig::with_disabled_credentials,
args.enabled_credentials_mode.map(|b| !b),
)
}
#[cfg(test)]
+3 -8
View File
@@ -9,8 +9,8 @@ use crate::{
use clap::Args;
use config::NymConfig;
use crypto::asymmetric::identity;
use log::*;
use nym_crypto::asymmetric::identity;
use nymsphinx::addressing::clients::Recipient;
use version_checker::is_minor_version_compatible;
@@ -43,8 +43,7 @@ pub(crate) struct Run {
gateway: Option<identity::PublicKey>,
/// Comma separated list of rest endpoints of the nyxd validators
#[cfg(feature = "coconut")]
#[clap(long, alias = "nymd_validators", value_delimiter = ',')]
#[clap(long, alias = "nyxd_validators", value_delimiter = ',', hide = true)]
nyxd_urls: Option<Vec<url::Url>>,
/// Comma separated list of rest endpoints of the Nym APIs
@@ -66,8 +65,7 @@ pub(crate) struct Run {
/// Set this client to work in a enabled credentials mode that would attempt to use gateway
/// with bandwidth credential requirement.
#[cfg(feature = "coconut")]
#[clap(long)]
#[clap(long, hide = true)]
enabled_credentials_mode: Option<bool>,
}
@@ -79,10 +77,7 @@ impl From<Run> for OverrideConfig {
use_anonymous_replies: run_config.use_anonymous_replies,
fastmode: run_config.fastmode,
no_cover: run_config.no_cover,
#[cfg(feature = "coconut")]
nyxd_urls: run_config.nyxd_urls,
#[cfg(feature = "coconut")]
enabled_credentials_mode: run_config.enabled_credentials_mode,
}
}
+10 -1
View File
@@ -1,6 +1,6 @@
use crate::socks::types::SocksProxyError;
use client_core::error::ClientCoreError;
use socks5_requests::ConnectionId;
use socks5_requests::{ConnectionError, ConnectionId};
#[derive(thiserror::Error, Debug)]
pub enum Socks5ClientError {
@@ -28,3 +28,12 @@ pub enum Socks5ClientError {
error: String,
},
}
impl From<ConnectionError> for Socks5ClientError {
fn from(value: ConnectionError) -> Self {
Socks5ClientError::NetworkRequesterError {
connection_id: value.connection_id,
error: value.network_requester_error,
}
}
}
+132 -30
View File
@@ -16,7 +16,10 @@ use proxy_helpers::connection_controller::{
};
use proxy_helpers::proxy_runner::ProxyRunner;
use rand::RngCore;
use socks5_requests::{ConnectionId, Message, RemoteAddress, Request};
use service_providers_common::interface::{ProviderInterfaceVersion, RequestVersion};
use socks5_requests::{
ConnectionId, RemoteAddress, Socks5ProtocolVersion, Socks5ProviderRequest, Socks5Request,
};
use std::io;
use std::net::SocketAddr;
use std::pin::Pin;
@@ -128,6 +131,8 @@ impl AsyncWrite for StreamState {
#[derive(Debug, Copy, Clone)]
pub(crate) struct Config {
provider_interface_version: ProviderInterfaceVersion,
socks5_protocol_version: Socks5ProtocolVersion,
use_surbs_for_responses: bool,
connection_start_surbs: u32,
per_request_surbs: u32,
@@ -135,16 +140,27 @@ pub(crate) struct Config {
impl Config {
pub(crate) fn new(
provider_interface_version: ProviderInterfaceVersion,
socks5_protocol_version: Socks5ProtocolVersion,
use_surbs_for_responses: bool,
connection_start_surbs: u32,
per_request_surbs: u32,
) -> Self {
Self {
provider_interface_version,
socks5_protocol_version,
use_surbs_for_responses,
connection_start_surbs,
per_request_surbs,
}
}
fn request_version(&self) -> RequestVersion<Socks5Request> {
RequestVersion {
provider_interface: self.provider_interface_version,
provider_protocol: self.socks5_protocol_version,
}
}
}
/// A client connecting to the Socks proxy server, because
@@ -173,7 +189,9 @@ impl Drop for SocksClient {
// if we never managed to start a proxy, the entry will not exist in the controller
if self.started_proxy {
self.controller_sender
.unbounded_send(ControllerCommand::Remove(self.connection_id))
.unbounded_send(ControllerCommand::Remove {
connection_id: self.connection_id,
})
.unwrap();
}
}
@@ -248,19 +266,26 @@ impl SocksClient {
// Send an error back to the client
pub async fn send_error_v4(&mut self, r: ResponseCodeV4) -> Result<(), SocksProxyError> {
self.stream.write_all(&[SOCKS4_VERSION, r as u8]).await?;
Ok(())
self.stream
.write_all(&[SOCKS4_VERSION, r as u8])
.await
.map_err(|source| SocksProxyError::SocketWriteError { source })
}
pub async fn send_error_v5(&mut self, r: ResponseCodeV5) -> Result<(), SocksProxyError> {
self.stream.write_all(&[SOCKS5_VERSION, r as u8]).await?;
Ok(())
self.stream
.write_all(&[SOCKS5_VERSION, r as u8])
.await
.map_err(|source| SocksProxyError::SocketWriteError { source })
}
/// Shutdown the `TcpStream` to the client and end the session
pub async fn shutdown(&mut self) -> Result<(), SocksProxyError> {
info!("client is shutting down its TCP stream");
self.stream.shutdown().await?;
self.stream
.shutdown()
.await
.map_err(|source| SocksProxyError::SocketShutdownFailure { source })?;
self.shutdown_listener.mark_as_success();
Ok(())
}
@@ -268,11 +293,20 @@ impl SocksClient {
/// Initializes the new client, checking that the correct Socks version (5)
/// is in use and that the client is authenticated, then runs the request.
pub async fn run(&mut self) -> Result<(), SocksProxyError> {
debug!("New connection from: {}", self.stream.peer_addr()?.ip());
debug!(
"New connection from: {}",
self.stream
.peer_addr()
.map_err(|source| SocksProxyError::PeerAddrExtractionFailure { source })?
.ip()
);
// Read a byte from the stream and determine the version being requested
let mut header = [0u8];
self.stream.read_exact(&mut header).await?;
self.stream
.read_exact(&mut header)
.await
.map_err(|source| SocksProxyError::SocketReadError { source })?;
self.socks_version = match SocksVersion::try_from(header[0]) {
Ok(version) => Some(version),
@@ -284,7 +318,10 @@ impl SocksClient {
if self.socks_version == Some(SocksVersion::V5) {
let mut auth = [0u8];
self.stream.read_exact(&mut auth).await?;
self.stream
.read_exact(&mut auth)
.await
.map_err(|source| SocksProxyError::SocketReadError { source })?;
self.auth_nmethods = auth[0];
self.authenticate_socks5().await?;
}
@@ -293,8 +330,15 @@ impl SocksClient {
}
async fn send_anonymous_connect_to_mixnet(&mut self, remote_address: RemoteAddress) {
let req = Request::new_connect(self.connection_id, remote_address, None);
let msg = Message::Request(req);
// TODO: simplify by using `request_version`
let req = Socks5Request::new_connect(
self.config.socks5_protocol_version,
self.connection_id,
remote_address,
None,
);
let msg =
Socks5ProviderRequest::new_provider_data(self.config.provider_interface_version, req);
let input_message = InputMessage::new_anonymous(
self.service_provider,
@@ -309,8 +353,15 @@ impl SocksClient {
}
async fn send_connect_to_mixnet_with_return_address(&mut self, remote_address: RemoteAddress) {
let req = Request::new_connect(self.connection_id, remote_address, Some(self.self_address));
let msg = Message::Request(req);
// TODO: simplify by using `request_version`
let req = Socks5Request::new_connect(
self.config.socks5_protocol_version,
self.connection_id,
remote_address,
Some(self.self_address),
);
let msg =
Socks5ProviderRequest::new_provider_data(self.config.provider_interface_version, req);
let input_message = InputMessage::new_regular(
self.service_provider,
@@ -350,6 +401,7 @@ impl SocksClient {
let input_sender = self.input_sender.clone();
let anonymous = self.config.use_surbs_for_responses;
let per_request_surbs = self.config.per_request_surbs;
let request_version = self.config.request_version();
let recipient = self.service_provider;
let (stream, _) = ProxyRunner::new(
@@ -363,8 +415,16 @@ impl SocksClient {
self.shutdown_listener.clone(),
)
.run(move |conn_id, read_data, socket_closed| {
let provider_request = Request::new_send(conn_id, read_data, socket_closed);
let provider_message = Message::Request(provider_request);
let provider_request = Socks5Request::new_send(
request_version.provider_protocol,
conn_id,
read_data,
socket_closed,
);
let provider_message = Socks5ProviderRequest::new_provider_data(
request_version.provider_interface,
provider_request,
);
let lane = TransmissionLane::ConnectionId(conn_id);
if anonymous {
InputMessage::new_anonymous(
@@ -413,7 +473,10 @@ impl SocksClient {
self.started_proxy = true;
self.controller_sender
.unbounded_send(ControllerCommand::Insert(self.connection_id, mix_sender))
.unbounded_send(ControllerCommand::Insert {
connection_id: self.connection_id,
connection_sender: mix_sender,
})
.unwrap();
info!(
@@ -491,7 +554,13 @@ impl SocksClient {
/// into the Authenticator (where it'll be more easily testable)
/// would be a good next step.
async fn authenticate_socks5(&mut self) -> Result<(), SocksProxyError> {
debug!("Authenticating w/ {}", self.stream.peer_addr()?.ip());
debug!(
"Authenticating w/ {}",
self.stream
.peer_addr()
.map_err(|source| SocksProxyError::PeerAddrExtractionFailure { source })?
.ip()
);
// Get valid auth methods
let methods = self.get_available_methods().await?;
trace!("methods: {:?}", methods);
@@ -505,27 +574,45 @@ impl SocksClient {
response[1] = AuthenticationMethods::UserPass as u8;
debug!("Sending USER/PASS packet");
self.stream.write_all(&response).await?;
self.stream
.write_all(&response)
.await
.map_err(|source| SocksProxyError::SocketWriteError { source })?;
let mut header = [0u8; 2];
// Read a byte from the stream and determine the version being requested
self.stream.read_exact(&mut header).await?;
self.stream
.read_exact(&mut header)
.await
.map_err(|source| SocksProxyError::SocketReadError { source })?;
// debug!("Auth Header: [{}, {}]", header[0], header[1]);
// Username parsing
let ulen = header[1];
let mut username = vec![0; ulen as usize];
self.stream.read_exact(&mut username).await?;
self.stream
.read_exact(&mut username)
.await
.map_err(|source| SocksProxyError::SocketReadError { source })?;
// Password Parsing
let plen = self.stream.read_u8().await?;
let plen = self
.stream
.read_u8()
.await
.map_err(|source| SocksProxyError::SocketReadError { source })?;
let mut password = vec![0; plen as usize];
self.stream.read_exact(&mut password).await?;
self.stream
.read_exact(&mut password)
.await
.map_err(|source| SocksProxyError::SocketReadError { source })?;
let username_str = String::from_utf8(username)?;
let password_str = String::from_utf8(password)?;
let username_str = String::from_utf8(username)
.map_err(|source| SocksProxyError::MalformedAuthUsername { source })?;
let password_str = String::from_utf8(password)
.map_err(|source| SocksProxyError::MalformedAuthPassword { source })?;
let user = User {
username: username_str,
@@ -536,11 +623,17 @@ impl SocksClient {
if self.authenticator.is_allowed(&user) {
debug!("Access Granted. User: {}", user.username);
let response = [1, ResponseCodeV5::Success as u8];
self.stream.write_all(&response).await?;
self.stream
.write_all(&response)
.await
.map_err(|source| SocksProxyError::SocketWriteError { source })?;
} else {
debug!("Access Denied. User: {}", user.username);
let response = [1, ResponseCodeV5::Failure as u8];
self.stream.write_all(&response).await?;
self.stream
.write_all(&response)
.await
.map_err(|source| SocksProxyError::SocketWriteError { source })?;
// Shutdown
self.shutdown().await?;
@@ -551,12 +644,18 @@ impl SocksClient {
// set the default auth method (no auth)
response[1] = AuthenticationMethods::NoAuth as u8;
debug!("Sending NOAUTH packet");
self.stream.write_all(&response).await?;
self.stream
.write_all(&response)
.await
.map_err(|source| SocksProxyError::SocketWriteError { source })?;
Ok(())
} else {
warn!("Client has no suitable authentication methods!");
response[1] = AuthenticationMethods::NoMethods as u8;
self.stream.write_all(&response).await?;
self.stream
.write_all(&response)
.await
.map_err(|source| SocksProxyError::SocketWriteError { source })?;
self.shutdown().await?;
Err(ResponseCodeV5::Failure.into())
}
@@ -567,7 +666,10 @@ impl SocksClient {
let mut methods: Vec<u8> = Vec::with_capacity(self.auth_nmethods as usize);
for _ in 0..self.auth_nmethods {
let mut method = [0u8; 1];
self.stream.read_exact(&mut method).await?;
self.stream
.read_exact(&mut method)
.await
.map_err(|source| SocksProxyError::SocketReadError { source })?;
if self.authenticator.auth_methods.contains(&method[0]) {
methods.append(&mut method.to_vec());
}
+54 -30
View File
@@ -5,8 +5,9 @@ use log::*;
use client_core::client::received_buffer::ReconstructedMessagesReceiver;
use client_core::client::received_buffer::{ReceivedBufferMessage, ReceivedBufferRequestSender};
use nymsphinx::receiver::ReconstructedMessage;
use proxy_helpers::connection_controller::{ControllerCommand, ControllerSender};
use socks5_requests::Message;
use proxy_helpers::connection_controller::ControllerSender;
use service_providers_common::interface::{ControlResponse, ResponseContent};
use socks5_requests::{Socks5ProviderResponse, Socks5Response, Socks5ResponseContent};
use task::TaskClient;
use crate::error::Socks5ClientError;
@@ -52,6 +53,39 @@ impl MixnetResponseListener {
}
}
fn on_control_response(
&self,
control_response: ControlResponse,
) -> Result<(), Socks5ClientError> {
error!("received a control response which we don't know how to handle yet!");
error!("got: {:?}", control_response);
// I guess we'd need another channel here to forward those to where they need to go
Ok(())
}
fn on_provider_data_response(
&self,
provider_response: Socks5Response,
) -> Result<(), Socks5ClientError> {
match provider_response.content {
Socks5ResponseContent::ConnectionError(err_response) => {
error!(
"Network requester failed on connection id {} with error: {}",
err_response.connection_id, err_response.network_requester_error
);
Err(err_response.into())
}
Socks5ResponseContent::NetworkData(response) => {
self.controller_sender
.unbounded_send(response.into())
.unwrap();
Ok(())
}
}
}
fn on_message(
&self,
reconstructed_message: ReconstructedMessage,
@@ -60,38 +94,28 @@ impl MixnetResponseListener {
if reconstructed_message.sender_tag.is_some() {
warn!("this message was sent anonymously - it couldn't have come from the service provider");
}
let response = match Message::try_from_bytes(&raw_message) {
match Socks5ProviderResponse::try_from_bytes(&raw_message) {
Err(err) => {
warn!("failed to parse received response - {err}");
return Ok(());
warn!("failed to parse received response: {err}");
Ok(())
}
Ok(Message::Request(_)) => {
warn!("unexpected request");
return Ok(());
}
Ok(Message::Response(data)) => data,
Ok(Message::NetworkRequesterResponse(r)) => {
error!(
"Network requester failed on connection id {} with error: {}",
r.connection_id, r.network_requester_error
Ok(response) => {
// as long as the client used the same (or older) interface than the service provider,
// the response should have used exactly the same version
trace!(
"the received response was sent with {:?} interface version",
response.interface_version
);
return Err(Socks5ClientError::NetworkRequesterError {
connection_id: r.connection_id,
error: r.network_requester_error,
});
match response.content {
ResponseContent::Control(control_response) => {
self.on_control_response(control_response)
}
ResponseContent::ProviderData(provider_response) => {
self.on_provider_data_response(provider_response)
}
}
}
};
self.controller_sender
.unbounded_send(ControllerCommand::Send(
response.connection_id,
response.data,
response.is_closed,
))
.unwrap();
Ok(())
}
}
pub(crate) async fn run(&mut self) {
+1 -1
View File
@@ -33,7 +33,7 @@ impl TryFrom<u8> for SocksVersion {
match version {
SOCKS4_VERSION => Ok(Self::V4),
SOCKS5_VERSION => Ok(Self::V5),
_ => Err(SocksProxyError::UnsupportedProxyVersion(version)),
_ => Err(SocksProxyError::UnsupportedProxyVersion { version }),
}
}
}
+39 -10
View File
@@ -28,7 +28,10 @@ impl SocksRequest {
log::trace!("read from stream socks4");
let mut packet = [0u8; 3];
stream.read_exact(&mut packet).await?;
stream
.read_exact(&mut packet)
.await
.map_err(|source| SocksProxyError::SocketReadError { source })?;
// CD (command)
let Some(command) = SocksCommand::from(packet[0] as usize) else {
@@ -43,7 +46,10 @@ impl SocksRequest {
// DSTIP
let mut ip = [0u8; 4];
stream.read_exact(&mut ip).await?;
stream
.read_exact(&mut ip)
.await
.map_err(|source| SocksProxyError::SocketReadError { source })?;
// USERID
let _userid = read_until_zero(stream).await;
@@ -76,12 +82,17 @@ impl SocksRequest {
let mut packet = [0u8; 4];
// Read a byte from the stream and determine the version being requested
stream.read_exact(&mut packet).await?;
stream
.read_exact(&mut packet)
.await
.map_err(|source| SocksProxyError::SocketReadError { source })?;
// VER
if packet[0] != SOCKS5_VERSION {
warn!("Unsupported version: SOCKS{}", packet[0]);
return Err(SocksProxyError::UnsupportedProxyVersion(packet[0]));
return Err(SocksProxyError::UnsupportedProxyVersion {
version: (packet[0]),
});
}
// CMD
@@ -103,26 +114,41 @@ impl SocksRequest {
let addr = match addr_type {
AddrType::Domain => {
let mut domain_length = [0u8];
stream.read_exact(&mut domain_length).await?;
stream
.read_exact(&mut domain_length)
.await
.map_err(|source| SocksProxyError::SocketReadError { source })?;
let mut domain = vec![0u8; domain_length[0] as usize];
stream.read_exact(&mut domain).await?;
stream
.read_exact(&mut domain)
.await
.map_err(|source| SocksProxyError::SocketReadError { source })?;
domain
}
AddrType::V4 => {
let mut addr = [0u8; 4];
stream.read_exact(&mut addr).await?;
stream
.read_exact(&mut addr)
.await
.map_err(|source| SocksProxyError::SocketReadError { source })?;
addr.to_vec()
}
AddrType::V6 => {
let mut addr = [0u8; 16];
stream.read_exact(&mut addr).await?;
stream
.read_exact(&mut addr)
.await
.map_err(|source| SocksProxyError::SocketReadError { source })?;
addr.to_vec()
}
};
// DST.PORT
let mut port = [0u8; 2];
stream.read_exact(&mut port).await?;
stream
.read_exact(&mut port)
.await
.map_err(|source| SocksProxyError::SocketReadError { source })?;
let port = merge_u8_into_u16(port[0], port[1]);
Ok(SocksRequest {
@@ -179,7 +205,10 @@ where
let mut result = Vec::new();
let mut char = [0u8];
loop {
stream.read_exact(&mut char).await?;
stream
.read_exact(&mut char)
.await
.map_err(|source| SocksProxyError::SocketReadError { source })?;
if char[0] == 0 {
break;
}
+7 -2
View File
@@ -10,7 +10,7 @@ use client_core::client::{
};
use log::*;
use nymsphinx::addressing::clients::Recipient;
use proxy_helpers::connection_controller::{BroadcastActiveConnections, Controller};
use proxy_helpers::connection_controller::Controller;
use std::net::SocketAddr;
use tap::TapFallible;
use task::TaskClient;
@@ -69,7 +69,7 @@ impl SphinxSocksServer {
// controller for managing all active connections
let (mut active_streams_controller, controller_sender) = Controller::new(
client_connection_tx,
BroadcastActiveConnections::Off,
//BroadcastActiveConnections::Off,
self.shutdown.clone(),
);
tokio::spawn(async move {
@@ -86,6 +86,11 @@ impl SphinxSocksServer {
mixnet_response_listener.run().await;
});
// TODO:, if required, there should be another task here responsible for control requests.
// it should get `input_sender` to send actual requests into the mixnet
// and some channel that connects it from `MixnetResponseListener` to receive
// any control responses
loop {
tokio::select! {
Ok((stream, _remote)) = listener.accept() => {
+52 -24
View File
@@ -1,3 +1,7 @@
use socks5_requests::Socks5RequestError;
use std::string::FromUtf8Error;
use thiserror::Error;
/// SOCKS4 Response codes
#[allow(dead_code)]
pub(crate) enum ResponseCodeV4 {
@@ -8,9 +12,8 @@ pub(crate) enum ResponseCodeV4 {
}
/// Possible SOCKS5 Response Codes
#[allow(dead_code)]
#[derive(Debug, thiserror::Error)]
pub(crate) enum ResponseCodeV5 {
#[derive(Debug, Error)]
pub enum ResponseCodeV5 {
#[error("SOCKS5 Server Success")]
Success = 0x00,
#[error("SOCKS5 Server Failure")]
@@ -31,30 +34,55 @@ pub(crate) enum ResponseCodeV5 {
AddrTypeNotSupported = 0x08,
}
#[derive(Debug)]
#[derive(Error, Debug)]
pub enum SocksProxyError {
GenericError(Box<dyn std::error::Error + Send + Sync>),
UnsupportedProxyVersion(u8),
}
#[error("{version} of the socks protocol is not supported by this client")]
UnsupportedProxyVersion { version: u8 },
impl std::fmt::Display for SocksProxyError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
SocksProxyError::GenericError(err) => write!(f, "GenericError - {err}"),
SocksProxyError::UnsupportedProxyVersion(version) => {
write!(f, "Unsupported proxy version {}", version)
}
}
}
}
#[error("failed to write to the socket: {source}")]
SocketWriteError {
#[source]
source: std::io::Error,
},
impl<E> From<E> for SocksProxyError
where
E: std::error::Error + Send + Sync + 'static,
{
fn from(err: E) -> Self {
SocksProxyError::GenericError(Box::new(err))
}
#[error("failed to read from the socket: {source}")]
SocketReadError {
#[source]
source: std::io::Error,
},
#[error("failed to shutdown underlying socket stream: {source}")]
SocketShutdownFailure {
#[source]
source: std::io::Error,
},
#[error("failed to extract ip address of the connected peer: {source}")]
PeerAddrExtractionFailure {
#[source]
source: std::io::Error,
},
#[error("failed to authenticate user due to malformed username: {source}")]
MalformedAuthUsername {
#[source]
source: FromUtf8Error,
},
#[error("failed to authenticate user due to malformed password: {source}")]
MalformedAuthPassword {
#[source]
source: FromUtf8Error,
},
#[error(transparent)]
Socks5ResponseFailure(#[from] ResponseCodeV5),
#[error("could not complete the provider request: {source}")]
ProviderRequestFailure {
#[from]
source: Socks5RequestError,
},
}
/// DST.addr variant types
+4 -5
View File
@@ -15,7 +15,6 @@ crate-type = ["cdylib", "rlib"]
[features]
default = ["console_error_panic_hook"]
offline-test = []
coconut = ["coconut-interface", "credentials", "gateway-client/coconut"]
[dependencies]
futures = "0.3"
@@ -33,12 +32,12 @@ wasm-bindgen-futures = "0.4"
# internal
client-core = { path = "../client-core", default-features = false, features = ["wasm"] }
client-connections = { path = "../../common/client-connections" }
coconut-interface = { path = "../../common/coconut-interface", optional = true }
credentials = { path = "../../common/credentials", optional = true }
crypto = { path = "../../common/crypto" }
coconut-interface = { path = "../../common/coconut-interface" }
credentials = { path = "../../common/credentials" }
nym-crypto = { path = "../../common/crypto" }
nymsphinx = { path = "../../common/nymsphinx" }
topology = { path = "../../common/topology" }
gateway-client = { path = "../../common/client-libs/gateway-client", default-features = false, features = ["wasm", "coconut"] }
gateway-client = { path = "../../common/client-libs/gateway-client", default-features = false, features = ["wasm"] }
validator-client = { path = "../../common/client-libs/validator-client", default-features = false }
wasm-utils = { path = "../../common/wasm-utils" }
task = { path = "../../common/task" }
+15 -5
View File
@@ -125,7 +125,11 @@ pub struct Debug {
/// Defines maximum amount of time the client is going to wait for reply surbs before explicitly asking
/// for more even though in theory they wouldn't need to.
pub maximum_reply_surb_waiting_period_ms: u64,
pub maximum_reply_surb_rerequest_waiting_period_ms: u64,
/// Defines maximum amount of time the client is going to wait for reply surbs before
/// deciding it's never going to get them and would drop all pending messages
pub maximum_reply_surb_drop_waiting_period_ms: u64,
/// Defines maximum amount of time given reply surb is going to be valid for.
/// This is going to be superseded by key rotation once implemented.
@@ -168,8 +172,11 @@ impl From<Debug> for ConfigDebug {
minimum_reply_surb_request_size: debug.minimum_reply_surb_request_size,
maximum_reply_surb_request_size: debug.maximum_reply_surb_request_size,
maximum_allowed_reply_surb_request_size: debug.maximum_allowed_reply_surb_request_size,
maximum_reply_surb_waiting_period: Duration::from_millis(
debug.maximum_reply_surb_waiting_period_ms,
maximum_reply_surb_rerequest_waiting_period: Duration::from_millis(
debug.maximum_reply_surb_rerequest_waiting_period_ms,
),
maximum_reply_surb_drop_waiting_period: Duration::from_millis(
debug.maximum_reply_surb_drop_waiting_period_ms,
),
maximum_reply_surb_age: Duration::from_millis(debug.maximum_reply_surb_age_ms),
maximum_reply_key_age: Duration::from_millis(debug.maximum_reply_key_age_ms),
@@ -200,8 +207,11 @@ impl From<ConfigDebug> for Debug {
minimum_reply_surb_request_size: debug.minimum_reply_surb_request_size,
maximum_reply_surb_request_size: debug.maximum_reply_surb_request_size,
maximum_allowed_reply_surb_request_size: debug.maximum_allowed_reply_surb_request_size,
maximum_reply_surb_waiting_period_ms: debug
.maximum_reply_surb_waiting_period
maximum_reply_surb_rerequest_waiting_period_ms: debug
.maximum_reply_surb_rerequest_waiting_period
.as_millis() as u64,
maximum_reply_surb_drop_waiting_period_ms: debug
.maximum_reply_surb_drop_waiting_period
.as_millis() as u64,
maximum_reply_surb_age_ms: debug.maximum_reply_surb_age.as_millis() as u64,
maximum_reply_key_age_ms: debug.maximum_reply_key_age.as_millis() as u64,
+4
View File
@@ -6,6 +6,10 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
serde = { workspace = true, features = ["derive"], optional = true }
[build-dependencies]
vergen = { version = "7", default-features = false, features = ["build", "git", "rustc", "cargo"] }
[features]
default = []
+50
View File
@@ -4,6 +4,7 @@
// TODO: at a later date this crate should probably also expose `ContractBuildInformation`
// and be used by our smart contracts
#[derive(Debug)]
pub struct BinaryBuildInformation {
// VERGEN_BUILD_TIMESTAMP
/// Provides the build timestamp, for example `2021-02-23T20:14:46.558472672+00:00`.
@@ -53,6 +54,19 @@ impl BinaryBuildInformation {
}
}
pub fn to_owned(&self) -> BinaryBuildInformationOwned {
BinaryBuildInformationOwned {
build_timestamp: self.build_timestamp.to_owned(),
build_version: self.build_version.to_owned(),
commit_sha: self.commit_sha.to_owned(),
commit_timestamp: self.commit_timestamp.to_owned(),
commit_branch: self.commit_branch.to_owned(),
rustc_version: self.rustc_version.to_owned(),
rustc_channel: self.rustc_channel.to_owned(),
cargo_profile: self.cargo_profile.to_owned(),
}
}
pub fn pretty_print(&self) -> String {
format!(
r#"
@@ -84,3 +98,39 @@ impl BinaryBuildInformation {
)
}
}
#[derive(Debug)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct BinaryBuildInformationOwned {
// VERGEN_BUILD_TIMESTAMP
/// Provides the build timestamp, for example `2021-02-23T20:14:46.558472672+00:00`.
pub build_timestamp: String,
// VERGEN_BUILD_SEMVER
/// Provides the build version, for example `0.1.0-9-g46f83e1`.
pub build_version: String,
// VERGEN_GIT_SHA
/// Provides the hash of the commit that was used for the build, for example `46f83e112520533338245862d366f6a02cef07d4`.
pub commit_sha: String,
// VERGEN_GIT_COMMIT_TIMESTAMP
/// Provides the timestamp of the commit that was used for the build, for example `2021-02-23T08:08:02-05:00`.
pub commit_timestamp: String,
// VERGEN_GIT_BRANCH
/// Provides the name of the git branch that was used for the build, for example `master`.
pub commit_branch: String,
// VERGEN_RUSTC_SEMVER
/// Provides the rustc version that was used for the build, for example `1.52.0-nightly`.
pub rustc_version: String,
// VERGEN_RUSTC_CHANNEL
/// Provides the rustc channel that was used for the build, for example `nightly`.
pub rustc_channel: String,
// VERGEN_CARGO_PROFILE
/// Provides the cargo profile that was used for the build, for example `debug`.
pub cargo_profile: String,
}
-6
View File
@@ -25,12 +25,6 @@ pub enum ConnectionCommand {
// Announce that at a connection was closed. E.g the `OutQueueControl` uses this to discard
// transmission lanes.
Close(ConnectionId),
// In the network requester for example, we usually want to broadcast active connections
// regularly, so we know what connections we need to request lane queue lengths for from the
// client.
// In the socks5-client, this is not needed since have direct access to the lane queue lengths.
ActiveConnections(Vec<ConnectionId>),
}
// The `OutQueueControl` publishes the backlog per lane, primarily so that upstream can slow down
+5 -4
View File
@@ -18,16 +18,17 @@ async-trait = { version = "0.1.51" }
tokio = { version = "1.24.1", features = ["macros"] }
# internal
coconut-interface = { path = "../../coconut-interface", optional = true }
coconut-interface = { path = "../../coconut-interface" }
credentials = { path = "../../credentials" }
crypto = { path = "../../crypto" }
nym-crypto = { path = "../../crypto" }
gateway-requests = { path = "../../../gateway/gateway-requests" }
network-defaults = { path = "../../network-defaults" }
nymsphinx = { path = "../../nymsphinx" }
pemstore = { path = "../../pemstore" }
nym-pemstore = { path = "../../pemstore" }
validator-client = { path = "../validator-client" }
task = { path = "../../task" }
serde = { version = "1.0", features = ["derive"]}
mobile-storage = { path = "../../mobile-storage" }
[dependencies.tungstenite]
@@ -79,5 +80,5 @@ features = ["js"]
#url = "2.1"
[features]
coconut = ["gateway-requests/coconut", "coconut-interface", "credentials/coconut"]
wasm = []
mobile = []
@@ -1,27 +1,34 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
#[cfg(feature = "coconut")]
use crate::error::GatewayClientError;
#[cfg(target_arch = "wasm32")]
use crate::wasm_mockups::Storage;
#[cfg(not(target_arch = "wasm32"))]
#[cfg(not(feature = "mobile"))]
use credential_storage::storage::Storage;
#[cfg(all(target_arch = "wasm32", feature = "coconut"))]
#[cfg(not(target_arch = "wasm32"))]
#[cfg(feature = "mobile")]
use mobile_storage::Storage;
#[cfg(not(target_arch = "wasm32"))]
#[cfg(feature = "mobile")]
use mobile_storage::StorageError;
#[cfg(target_arch = "wasm32")]
use crate::wasm_mockups::StorageError;
#[cfg(all(not(target_arch = "wasm32"), feature = "coconut"))]
#[cfg(not(target_arch = "wasm32"))]
#[cfg(not(feature = "mobile"))]
use credential_storage::error::StorageError;
#[cfg(target_arch = "wasm32")]
use crate::wasm_mockups::{Client, CosmWasmClient};
#[cfg(feature = "coconut")]
use std::str::FromStr;
#[cfg(not(target_arch = "wasm32"))]
use validator_client::{nyxd::CosmWasmClient, Client};
#[cfg(feature = "coconut")]
use {
coconut_interface::Base58,
credentials::coconut::{
@@ -34,8 +41,13 @@ use {
use crate::wasm_mockups::PersistentStorage;
#[cfg(not(target_arch = "wasm32"))]
#[cfg(not(feature = "mobile"))]
use credential_storage::PersistentStorage;
#[cfg(not(target_arch = "wasm32"))]
#[cfg(feature = "mobile")]
use mobile_storage::PersistentStorage;
#[derive(Clone)]
#[allow(dead_code)]
pub struct BandwidthController<C: Clone, St: Storage = PersistentStorage> {
@@ -55,7 +67,6 @@ where
}
}
#[cfg(feature = "coconut")]
pub async fn prepare_coconut_credential(
&self,
) -> Result<(coconut_interface::Credential, i64), GatewayClientError> {
@@ -98,7 +109,6 @@ where
))
}
#[cfg(feature = "coconut")]
pub async fn consume_credential(&self, id: i64) -> Result<(), GatewayClientError> {
Ok(self.storage.consume_coconut_credential(id).await?)
}
+19 -27
View File
@@ -9,7 +9,7 @@ pub use crate::packet_router::{
};
use crate::socket_state::{PartiallyDelegated, SocketState};
use crate::{cleanup_socket_message, try_decrypt_binary_message};
use crypto::asymmetric::identity;
use coconut_interface::Credential;
use futures::{SinkExt, StreamExt};
use gateway_requests::authentication::encrypted_address::EncryptedAddressBytes;
use gateway_requests::iv::IV;
@@ -17,6 +17,7 @@ use gateway_requests::registration::handshake::{client_handshake, SharedKeys};
use gateway_requests::{BinaryRequest, ClientControlRequest, ServerResponse, PROTOCOL_VERSION};
use log::*;
use network_defaults::{REMAINING_BANDWIDTH_THRESHOLD, TOKENS_TO_BURN};
use nym_crypto::asymmetric::identity;
use nymsphinx::forwarding::packet::MixPacket;
use rand::rngs::OsRng;
use std::convert::TryFrom;
@@ -25,16 +26,19 @@ use std::time::Duration;
use task::TaskClient;
use tungstenite::protocol::Message;
#[cfg(feature = "coconut")]
use coconut_interface::Credential;
#[cfg(not(target_arch = "wasm32"))]
use credential_storage::PersistentStorage;
#[cfg(not(target_arch = "wasm32"))]
use tokio_tungstenite::connect_async;
#[cfg(not(target_arch = "wasm32"))]
use validator_client::nyxd::CosmWasmClient;
#[cfg(not(target_arch = "wasm32"))]
#[cfg(not(feature = "mobile"))]
use credential_storage::PersistentStorage;
#[cfg(not(target_arch = "wasm32"))]
#[cfg(feature = "mobile")]
use mobile_storage::PersistentStorage;
#[cfg(target_arch = "wasm32")]
use crate::wasm_mockups::CosmWasmClient;
#[cfg(target_arch = "wasm32")]
@@ -53,7 +57,6 @@ pub struct GatewayClient<C: Clone> {
bandwidth_remaining: i64,
gateway_address: String,
gateway_identity: identity::PublicKey,
gateway_owner: String,
local_identity: Arc<identity::KeyPair>,
shared_key: Option<Arc<SharedKeys>>,
connection: SocketState,
@@ -84,7 +87,6 @@ where
gateway_address: String,
local_identity: Arc<identity::KeyPair>,
gateway_identity: identity::PublicKey,
gateway_owner: String,
shared_key: Option<Arc<SharedKeys>>,
mixnet_message_sender: MixnetMessageSender,
ack_sender: AcknowledgementSender,
@@ -98,7 +100,6 @@ where
bandwidth_remaining: 0,
gateway_address,
gateway_identity,
gateway_owner,
local_identity,
shared_key,
connection: SocketState::NotConnected,
@@ -132,7 +133,6 @@ where
pub fn new_init(
gateway_address: String,
gateway_identity: identity::PublicKey,
gateway_owner: String,
local_identity: Arc<identity::KeyPair>,
response_timeout_duration: Duration,
) -> Self {
@@ -151,7 +151,6 @@ where
bandwidth_remaining: 0,
gateway_address,
gateway_identity,
gateway_owner,
local_identity,
shared_key: None,
connection: SocketState::NotConnected,
@@ -442,6 +441,7 @@ where
}
debug_assert!(self.connection.is_available());
log::trace!("Registering gateway");
// it's fine to instantiate it here as it's only used once (during authentication or registration)
// and putting it into the GatewayClient struct would be a hassle
@@ -541,7 +541,6 @@ where
}
}
#[cfg(feature = "coconut")]
async fn claim_coconut_bandwidth(
&mut self,
credential: Credential,
@@ -591,28 +590,21 @@ where
return self.try_claim_testnet_bandwidth().await;
}
let _gateway_owner = self.gateway_owner.clone();
#[cfg(feature = "coconut")]
let (credential, credential_id) = self
.bandwidth_controller
.as_ref()
.unwrap()
.prepare_coconut_credential()
.await?;
#[cfg(not(feature = "coconut"))]
return self.try_claim_testnet_bandwidth().await;
#[cfg(feature = "coconut")]
{
self.claim_coconut_bandwidth(credential).await?;
self.bandwidth_controller
.as_ref()
.unwrap()
.consume_credential(credential_id)
.await?;
Ok(())
}
self.claim_coconut_bandwidth(credential).await?;
self.bandwidth_controller
.as_ref()
.unwrap()
.consume_credential(credential_id)
.await?;
Ok(())
}
fn estimate_required_bandwidth(&self, packets: &[MixPacket]) -> i64 {
@@ -3,9 +3,13 @@
#[cfg(target_arch = "wasm32")]
use crate::wasm_mockups::StorageError;
#[cfg(not(feature = "mobile"))]
#[cfg(not(target_arch = "wasm32"))]
use credential_storage::error::StorageError;
use gateway_requests::registration::handshake::error::HandshakeError;
#[cfg(feature = "mobile")]
#[cfg(not(target_arch = "wasm32"))]
use mobile_storage::StorageError;
use std::io;
use thiserror::Error;
use tungstenite::Error as WsError;
@@ -26,7 +30,6 @@ pub enum GatewayClientError {
#[error("There was a credential storage error - {0}")]
CredentialStorageError(#[from] StorageError),
#[cfg(feature = "coconut")]
#[error("Coconut error - {0}")]
CoconutError(#[from] coconut_interface::CoconutError),
@@ -12,13 +12,13 @@ base64 = "0.13"
colored = "2.0"
coconut-dkg-common = { path = "../../cosmwasm-smart-contracts/coconut-dkg" }
contracts-common = { path = "../../cosmwasm-smart-contracts/contracts-common" }
mixnet-contract-common = { path= "../../cosmwasm-smart-contracts/mixnet-contract" }
vesting-contract-common = { path= "../../cosmwasm-smart-contracts/vesting-contract" }
nym-contracts-common = { path = "../../cosmwasm-smart-contracts/contracts-common" }
nym-mixnet-contract-common = { path= "../../cosmwasm-smart-contracts/mixnet-contract" }
nym-vesting-contract-common = { path= "../../cosmwasm-smart-contracts/vesting-contract" }
coconut-bandwidth-contract-common = { path= "../../cosmwasm-smart-contracts/coconut-bandwidth-contract" }
multisig-contract-common = { path = "../../cosmwasm-smart-contracts/multisig-contract" }
group-contract-common = { path = "../../cosmwasm-smart-contracts/group-contract" }
vesting-contract = { path = "../../../contracts/vesting" }
nym-vesting-contract = { path = "../../../contracts/vesting" }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
reqwest = { version = "0.11", features = ["json"] }
@@ -30,7 +30,7 @@ futures = "0.3"
coconut-interface = { path = "../../coconut-interface" }
network-defaults = { path = "../../network-defaults" }
nym-api-requests = { path = "../../../nym-api/nym-api-requests", features = ["coconut"] }
nym-api-requests = { path = "../../../nym-api/nym-api-requests" }
# required for nyxd-client
# at some point it might be possible to make it wasm-compatible
@@ -4,9 +4,6 @@
use crate::{nym_api, ValidatorClientError};
use coconut_dkg_common::types::NodeIndex;
use coconut_interface::VerificationKey;
use mixnet_contract_common::mixnode::MixNodeDetails;
use mixnet_contract_common::MixId;
use mixnet_contract_common::{GatewayBond, IdentityKeyRef};
use nym_api_requests::coconut::{
BlindSignRequestBody, BlindedSignatureResponse, VerifyCredentialBody, VerifyCredentialResponse,
};
@@ -14,6 +11,9 @@ use nym_api_requests::models::{
GatewayCoreStatusResponse, MixnodeCoreStatusResponse, MixnodeStatusResponse,
RewardEstimationResponse, StakeSaturationResponse,
};
use nym_mixnet_contract_common::mixnode::MixNodeDetails;
use nym_mixnet_contract_common::MixId;
use nym_mixnet_contract_common::{GatewayBond, IdentityKeyRef};
#[cfg(feature = "nyxd-client")]
use crate::nyxd::traits::{DkgQueryClient, MixnetQueryClient, MultisigQueryClient};
@@ -30,17 +30,17 @@ use coconut_interface::Base58;
#[cfg(feature = "nyxd-client")]
use cw3::ProposalResponse;
#[cfg(feature = "nyxd-client")]
use mixnet_contract_common::{
use network_defaults::NymNetworkDetails;
#[cfg(feature = "nyxd-client")]
use nym_api_requests::models::MixNodeBondAnnotated;
#[cfg(feature = "nyxd-client")]
use nym_mixnet_contract_common::{
families::{Family, FamilyHead},
mixnode::MixNodeBond,
pending_events::{PendingEpochEvent, PendingIntervalEvent},
Delegation, IdentityKey, RewardedSetNodeStatus, UnbondedMixnode,
};
#[cfg(feature = "nyxd-client")]
use network_defaults::NymNetworkDetails;
#[cfg(feature = "nyxd-client")]
use nym_api_requests::models::MixNodeBondAnnotated;
#[cfg(feature = "nyxd-client")]
use std::str::FromStr;
use url::Url;
@@ -934,16 +934,6 @@ impl NymApiClient {
Ok(self.nym_api_client.blind_sign(request_body).await?)
}
pub async fn partial_bandwidth_credential(
&self,
request_body: &str,
) -> Result<BlindedSignatureResponse, ValidatorClientError> {
Ok(self
.nym_api_client
.partial_bandwidth_credential(request_body)
.await?)
}
pub async fn verify_bandwidth_credential(
&self,
request_body: &VerifyCredentialBody,
@@ -3,8 +3,6 @@
use crate::nym_api::error::NymAPIError;
use crate::nym_api::routes::{CORE_STATUS_COUNT, SINCE_ARG};
use mixnet_contract_common::mixnode::MixNodeDetails;
use mixnet_contract_common::{GatewayBond, IdentityKeyRef, MixId};
use nym_api_requests::coconut::{
BlindSignRequestBody, BlindedSignatureResponse, VerifyCredentialBody, VerifyCredentialResponse,
};
@@ -15,6 +13,8 @@ use nym_api_requests::models::{
MixnodeUptimeHistoryResponse, RequestError, RewardEstimationResponse, StakeSaturationResponse,
UptimeResponse,
};
use nym_mixnet_contract_common::mixnode::MixNodeDetails;
use nym_mixnet_contract_common::{GatewayBond, IdentityKeyRef, MixId};
use reqwest::Response;
use serde::{Deserialize, Serialize};
use url::Url;
@@ -449,23 +449,6 @@ impl Client {
.await
}
pub async fn partial_bandwidth_credential(
&self,
request_body: &str,
) -> Result<BlindedSignatureResponse, NymAPIError> {
self.post_nym_api(
&[
routes::API_VERSION,
routes::COCONUT_ROUTES,
routes::BANDWIDTH,
routes::COCONUT_PARTIAL_BANDWIDTH_CREDENTIAL,
],
NO_PARAMS,
request_body,
)
.await
}
pub async fn verify_bandwidth_credential(
&self,
request_body: &VerifyCredentialBody,
@@ -14,7 +14,6 @@ pub const COCONUT_ROUTES: &str = "coconut";
pub const BANDWIDTH: &str = "bandwidth";
pub const COCONUT_BLIND_SIGN: &str = "blind-sign";
pub const COCONUT_PARTIAL_BANDWIDTH_CREDENTIAL: &str = "partial-bandwidth-credential";
pub const COCONUT_VERIFY_BANDWIDTH_CREDENTIAL: &str = "verify-bandwidth-credential";
pub const STATUS_ROUTES: &str = "status";
@@ -17,13 +17,13 @@ use cosmrs::rpc::HttpClientUrl;
use cosmrs::tx::Msg;
use execute::execute;
use log::debug;
use mixnet_contract_common::MixId;
use network_defaults::{ChainDetails, NymNetworkDetails};
use nym_mixnet_contract_common::MixId;
use nym_vesting_contract_common::ExecuteMsg as VestingExecuteMsg;
use nym_vesting_contract_common::PledgeCap;
use serde::{Deserialize, Serialize};
use std::convert::TryInto;
use std::time::SystemTime;
use vesting_contract_common::ExecuteMsg as VestingExecuteMsg;
use vesting_contract_common::PledgeCap;
pub use crate::nyxd::cosmwasm_client::client::CosmWasmClient;
pub use crate::nyxd::cosmwasm_client::signing_client::SigningCosmWasmClient;

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