Compare commits

..

423 Commits

Author SHA1 Message Date
Tommy Verrall e20ed854df check outputs 2023-08-29 11:46:14 +02:00
Tommy Verrall c6509c3a95 fix string 2023-08-29 11:35:31 +02:00
Tommy Verrall 8a9d242d03 check to see if this fixes strapi 2023-08-29 11:32:10 +02:00
Jon Häggblad 769a26fdeb Merge pull request #3815 from nymtech/jon/revert-clippy-change
Revert clippy fix for arc_with_non_send_sync in wasm client
2023-08-28 09:53:16 +02:00
Jon Häggblad 2e7ddcb195 Allow arc_with_non_send_sync in wasm client 2023-08-26 21:51:16 +02:00
Jon Häggblad 84d893198b Revert "Replace Arc with Rc on clippy's suggestion"
This reverts commit b050ae72de.
2023-08-26 21:09:33 +02:00
Fran Arbanas 2f6617daac Feature/issue credentials (#3691)
* Move the functionality to issue credentials from the credential binary and connect it with nym-cli

* finished CLI part, trying to fit SDK part

* finished Rust SDK

* fix: cleanup

* linting

* linting

* linting

* remove one layer of coconut in nym-cli

* linting

* Fixes based on PR comments

* formatting

* fixes based on PR comments

* formatting

* fixing clippy errors

* fixed post-rebasing issues and converted the lib into shared dep for other binaries

* removed credentials client in favour of moving the functionality to nym-cli

* removed redundant 'issue_credential' example (it did the same thing as 'bandwdith')

* removed credentials client from build server

* made the coconut cli also accept nym-api configs

* fixed support for socks5 and NR

---------

Co-authored-by: Jędrzej Stuczyński <jedrzej.stuczynski@gmail.com>
2023-08-25 17:13:52 +02:00
Tommy Verrall 9e483da802 Merge pull request #3814 from nymtech/jon/include-gateways-in-georouting
In geoaware routing, choose mixnodes close to exit gateway
2023-08-25 16:56:07 +02:00
Jon Häggblad d530e492ec Fix compilation 2023-08-25 16:13:41 +02:00
Jon Häggblad 6c67cff235 Allow clippy for now 2023-08-25 16:02:13 +02:00
Jon Häggblad 66f04d17b7 Select country group by the exit gateway 2023-08-25 15:52:43 +02:00
Jon Häggblad 492155d04a Also filter gateways on location 2023-08-25 15:52:43 +02:00
Jon Häggblad 069226125b Separate cfg wasm function 2023-08-25 15:42:40 +02:00
Jędrzej Stuczyński 1ce536c2fa [Manually reapplied] Merge pull request #3804 from nymtech/feature/explorer-gateway-iplocation
This was originally a commit 'b0a45c03b16c74697d8b46428fd83a25a5168add'.
However, we had to manually reapply it due to accidentally messing up the branch history.
2023-08-25 13:59:38 +01:00
Lorexia 2fbb901deb Update mixnode setup to return IPv4 2023-08-25 13:56:31 +01:00
Tommy Verrall 3c3ec9c831 Merge pull request #3812 from nymtech/jon/nym-connect-filter-gateway-version
nym-connect: filter gateways on compatible version
2023-08-25 11:58:35 +02:00
Jon Häggblad 6a34a99fee Merge pull request #3811 from nymtech/jon/clippy
Fix clippy for latest rustc
2023-08-25 11:44:57 +02:00
Jon Häggblad ec75a06c9d nym-connect: filter gateways on compatible version 2023-08-25 11:27:47 +02:00
Tommy Verrall 2fbe7bb350 Merge pull request #3810 from nymtech/jon/make-explorer-api-url-configurable-in-geo-aware
Add EXPLORER_API configurable url
2023-08-25 10:17:36 +02:00
Jon Häggblad ee67f3d0f0 rustfmt 2023-08-25 09:10:10 +02:00
Jon Häggblad 188650ea05 Stay on 1.71.0 for nym-wallet until the clippy crash is resolved 2023-08-25 09:09:05 +02:00
Jon Häggblad decae2b54d Clippy pub use shadowing warning 2023-08-25 09:01:27 +02:00
Jon Häggblad 8104761914 Update nym-connect Cargo.lock 2023-08-25 07:37:45 +02:00
Jon Häggblad 8503def37f Remove nym-connect mobile from Makefile 2023-08-25 07:37:29 +02:00
Jon Häggblad 48023eab41 Remove shadowing import 2023-08-25 07:33:49 +02:00
Jon Häggblad b050ae72de Replace Arc with Rc on clippy's suggestion 2023-08-25 07:33:32 +02:00
Jon Häggblad 377c9be790 clippy --fix 2023-08-24 17:58:51 +02:00
Jon Häggblad 5d7fd66cfc rustfmt 2023-08-24 17:55:19 +02:00
Jon Häggblad 5128aef193 Upgrade ts-rs to 7.0.0 2023-08-24 17:55:19 +02:00
Jon Häggblad 6a327b0bd6 No timeout for wasm 2023-08-24 16:01:47 +02:00
Jon Häggblad 8a38c61065 Fix wallet build 2023-08-24 15:43:48 +02:00
Jon Häggblad f0a888d59c Add EXPLORER_API configurable url 2023-08-24 15:34:49 +02:00
mfahampshire f1b9cf4d68 update minibolt pp 2023-08-23 20:56:43 +02:00
Tommy Verrall 392e7b5268 Merge pull request #3806 from nymtech/fix/wallet-gateway-form
fix(wallet): gateway bond form wrong helper text
2023-08-23 18:01:40 +02:00
pierre 776a9d508a fix wrong helper text 2023-08-23 17:44:53 +02:00
pierre 2f624d4f10 doc(nc-android): add notes for AAB build 2023-08-23 17:20:51 +02:00
Jędrzej Stuczyński 3c9faff4ec [hotfix]: don't assign invalid fields when crossing the JS boundary (#3805)
* [hotfix]: don't assign invalid fields when crossing the JS boundary

* eslint
2023-08-23 16:12:01 +01:00
pierre 026d52a218 print location in uppercase 2023-08-23 16:46:07 +02:00
pierre f8b70097d3 use geoip location for gateways 2023-08-23 16:17:07 +02:00
Tommy Verrall 0d3df4b58d Merge pull request #3802 from nymtech/bugfix/use-correct-tendermint-dialect
Bugfix/use correct tendermint dialect
2023-08-23 12:46:41 +02:00
Jędrzej Stuczyński 5241047f45 implemented compatibility mode for reqwest client 2023-08-23 11:05:31 +01:00
Jędrzej Stuczyński 2651784e8b fully delegating 'TendermintRpcClient' trait 2023-08-23 10:42:09 +01:00
Jędrzej Stuczyński 2cd2b1ccd4 always using http client in v034 compat mode 2023-08-23 10:08:33 +01:00
Jon Häggblad af4e8241e7 Fix rocksdb compilation (#3801)
* Fix rocksdb compilation

* Add ephemera to CI build

* Add nym-nr-query to CI build

* Fix clippy in ephemera rocksdb
2023-08-23 10:07:45 +02:00
Jon Häggblad 92350daca8 network-requester: disable poisson process by default (#3783)
* network-requester: disable poisson process by default

* network-requester: instead add new top-level config field

* Remove quoation marks in template
2023-08-22 14:17:03 +02:00
Jędrzej Stuczyński b429c64168 [demo] libp2p example with nym-sdk (#3763)
* imported libp2p to monorepo

* fixed vanilla ping example

* added libp2p client to workspace

* naively replaced dockerised client with the sdk

* moved libp2p code to sdk examples

* reduced number of dependencies required for libp2p example

* updated readmes

* added protobuf compiler to build dependencies

* added protoc dependency to readme for chat and ping examples

---------

Co-authored-by: mfahampshire <maxhampshire@pm.me>
2023-08-22 13:12:13 +02:00
Tommy Verrall f88622ac08 Delete upload-nyxd-ci.yml
not needed anymore removing
2023-08-22 12:21:44 +02:00
Jędrzej Stuczyński 0a5a2c6747 removed needless_pass_by_ref_mut in mixnet contract tests (#3798) 2023-08-22 11:56:23 +02:00
Tommy Verrall 824bd636f9 Merge pull request #3795 from nymtech/release/v1.1.28
Release/v1.1.28
2023-08-22 11:17:29 +02:00
Tommy Verrall cf6411ac08 Merge pull request #3794 from nymtech/qa/fix-windows-builder
Update nym-connect-publish-windows10.yml
2023-08-22 10:59:23 +02:00
Tommy Verrall 6428133122 Merge pull request #3793 from nymtech/qa/fix-api-tests
change ci to run against sandbox for tests
2023-08-22 10:55:24 +02:00
Tommy Verrall 3c69f9c2f9 Update nym-connect-publish-windows10.yml 2023-08-22 10:35:46 +02:00
Tommy Verrall c1e4b87744 change ci to run against sandbox for tests 2023-08-22 10:31:37 +02:00
benedettadavico 22246d0d5d bumping versions and updating changelog 2023-08-22 09:54:51 +02:00
Tommy Verrall 29593ef3c9 removing placeholders for the timebeing to enable windows build 2023-08-22 09:27:49 +02:00
Tommy Verrall 12f21185e3 Merge pull request #3791 from nymtech/feature/ephemera_upgrade
Feature/ephemera upgrade
2023-08-21 16:46:40 +02:00
Bogdan-Ștefan Neacșu 85ab3d5c80 Include 1.1.28 upgrade for ephemera config template 2023-08-21 16:51:32 +03:00
Pierre Dommerc dffe171b7f feat(explorer-api): add gateway geoip location (#3785)
* feat(explorer-api): add gateway geoip location

* fix lint
2023-08-21 15:50:18 +02:00
mfahampshire 6d3b198f00 change minibolt description 2023-08-21 14:04:21 +02:00
mfahampshire d4920b82f0 include 2faktor's PR material 2023-08-21 14:04:08 +02:00
mfahampshire 24099d159b change minibolt description 2023-08-21 14:02:29 +02:00
mfahampshire 463033aa64 version bump in toml files fr docs projects 2023-08-21 13:59:57 +02:00
mfahampshire c1ba56ab1c include 2faktor's PR material 2023-08-21 13:59:20 +02:00
mfahampshire 8dfe8f4678 version bump in toml files fr docs projects 2023-08-21 09:54:09 +02:00
Tommy Verrall c2a38c9b53 Merge branch 'develop' into release/v1.1.28 2023-08-21 09:35:39 +02:00
Tommy Verrall 33e7ce53fb Merge pull request #3723 from nymtech/feature/nc-desktop-userdata
refactor(nc-desktop): use userdata storage to save user gateway&sp
2023-08-21 09:34:46 +02:00
mx bdf18e30fb Merge pull request #3674 from nymtech/feature/operators-guide
feature/operators-guide
2023-08-18 16:03:18 +00:00
mfahampshire e0b32e1cc9 updated css font 2023-08-18 17:47:48 +02:00
Mark Sinclair 4ff69b77a9 Update general.css 2023-08-18 16:44:38 +01:00
Mark Sinclair 5f095d703d Update custom.css 2023-08-18 16:44:01 +01:00
Mark Sinclair ff4dbd09d0 Update general.css 2023-08-18 16:42:18 +01:00
Mark Sinclair 404d2d9857 Update build_all_to_dist.sh 2023-08-18 16:28:42 +01:00
Mark Sinclair b5f2ecd79e Update build_all_to_dist.sh 2023-08-18 16:24:57 +01:00
Mark Sinclair 38b9e14851 Update cd-docs.yml 2023-08-18 15:43:50 +01:00
mfahampshire 6ead19bd97 added conditional push for master branch 2023-08-18 15:55:59 +02:00
mfahampshire c169971287 fixed mdbook versions 2023-08-18 15:45:44 +02:00
mfahampshire 7b3cbdcd44 cont. work on cicd 2023-08-18 15:36:11 +02:00
mfahampshire 43dfb31eb2 modified ci script 2023-08-18 14:37:14 +02:00
mfahampshire ff4350ec90 changed name of script for staging to dist/ 2023-08-18 14:36:46 +02:00
mfahampshire c8516071fc removed developer portal specific files 2023-08-18 14:36:22 +02:00
Bogdan-Ștefan Neacşu ee5b55fab6 Feature/ephemera (#3731)
* Feature/ephemera compile (#3437)

* Include ephemera node code in repo

* Upgrade deps

* Bump minor version of cosmwasm-std

* Include ephemera in nym-api dep and downgrade rusqlite

* Fix clippy and ephemera docs code

* More clippy on ephemera

---------

Co-authored-by: Andrus Salumets <andrus@nymtech.net>

* Start ephemera components in nym-api (#3475)

* Start ephemera components in nym-api

* Pass nyxd client and use common metric structures

* Swap url endpoint with contract for sending rewarding messages

* Fix build after rebase

* Perform ephemera rewards computation before normal nym-api ones

* Remove contract mock from ephemera

* Take raw rewards from network monitor

* Remove ephemera old reward version

* Use nym shutdown procedure in ephemera

* Temporary fix for some warnings

* Umock contract membership of ephemera (#3574)

* Pass nyxd client to members provider

* Basic ephemera contract

* Add register peer tx

* Add query all peers

* Nyxd ephemera client

* Add registration of ephemera peer

* Replace epoch http api with actual contract

* Merge ephemera config into nym-api config

* Load cluster from contract

* Guard nym-outfox out of cosmwasm builds (#3650)

* Feature/fixes while testing (#3668)

* Commit local peer before querying contract

* Default to anyonline

* Remove string from template

* Fix avg computing

* Use updated qa env

* Fix clippy

* Add unit tests for ephemera contract

* Upload ephemera contract in CI

* Add group check for peer signup

* Peer registration unit test

* Start ephemera only on monitoring

* Remove old MixnodeToReward struct

* Move all ephemera config to its file

* Skip with serde ephemera config

* Fix default value in args

* Feature/add ephemera flag (#3727)

* Replace unwrap with error handling

* Add ephemera enable flag

* Fix template

* Add json schema to ephemera contract (#3735)

* Update lock files

* Update changelog

---------

Co-authored-by: Andrus Salumets <andrus@nymtech.net>
2023-08-18 14:14:13 +03:00
mfahampshire 11f3ce9224 Merge branch 'feature/operators-guide' of github.com:nymtech/nym into feature/operators-guide 2023-08-18 11:40:26 +02:00
mfahampshire 0f43521497 tweak 2023-08-18 11:22:58 +02:00
mfahampshire a1a1970dc1 updated readme with soon to be operator doc URL 2023-08-18 11:22:58 +02:00
mfahampshire 89ea3039d5 removed unnecessary linkcheck rendering output from dist/ 2023-08-18 11:22:58 +02:00
mfahampshire efa1e0353e rough staging sh script 2023-08-18 11:22:58 +02:00
mfahampshire 96e2712039 reintroduced linkchecker + fixed broken links 2023-08-18 11:22:58 +02:00
mfahampshire 84ad777c42 added workflow_dispatch to ci for dev-portal and docs 2023-08-18 11:22:58 +02:00
mfahampshire f569ba1c17 pull fix from ci-dev.yml to ci-docs.yml 2023-08-18 11:22:58 +02:00
serinko 54ff3ee987 applied theme changes:dev-portal -> docs 2023-08-18 11:22:58 +02:00
serinko 1f2a2c37ab picked theme changes:dev-portal -> operators; theme finished 2023-08-18 11:22:58 +02:00
serinko b0d5bacafd picked theme changes:dev-portal -> operators; theme finished 2023-08-18 11:22:58 +02:00
Jędrzej Stuczyński 8b65e44767 using stricter version requirements for mdbook and mdbook-variables 2023-08-18 11:22:58 +02:00
Gala a2445183bf theme change 2023-08-18 11:22:58 +02:00
mfahampshire 230d8aa170 changed out of date var 'mix_node_release_version' to 'platform_release_version 2023-08-18 11:22:58 +02:00
mfahampshire 035535058e fixed incorrect import path for chat app 2023-08-18 11:22:58 +02:00
mfahampshire df9aec1554 updated grantee info update link 2023-08-18 11:22:58 +02:00
mfahampshire 740846befc fixed links 2023-08-18 11:22:58 +02:00
mfahampshire 074e27291b updated links in operator binaries compilation list 2023-08-18 11:22:58 +02:00
mfahampshire b1c3264f69 removed doubled header 2023-08-18 11:22:58 +02:00
mfahampshire 905318ad27 final tweaks 2023-08-18 11:22:58 +02:00
mfahampshire 7065f870eb removed glossary file: needs rework 2023-08-18 11:22:58 +02:00
mfahampshire ee14dfc75e added coc and license 2023-08-18 11:22:58 +02:00
mfahampshire a93de8b4c5 updated vars in all books for next release version 2023-08-18 11:22:54 +02:00
mfahampshire 534c8f49d1 added notes to ws and socks client subsections re: rust sdk 2023-08-18 11:21:12 +02:00
mfahampshire 3da3f66ea3 * tweaked mixnode doc
* removed token diagram from nyx validator doc
2023-08-18 11:21:12 +02:00
mfahampshire 32bfceacb5 added custom 404 page for all books 2023-08-18 11:21:12 +02:00
mfahampshire 7a606e11f4 NR page 2023-08-18 11:21:12 +02:00
mfahampshire d3d5346cfe typo fix 2023-08-18 11:21:12 +02:00
mfahampshire 8fe549daa5 more links, fleshed out intro 2023-08-18 11:21:12 +02:00
mfahampshire f15be9456a added links 2023-08-18 11:21:12 +02:00
serinko 567d3c8173 socks5: new commands from #3699 2023-08-18 11:21:12 +02:00
serinko ce81f0c841 operators-guides final review of links and typos 2023-08-18 11:21:12 +02:00
serinko 9652060c57 correction of typos 2023-08-18 11:21:12 +02:00
serinko 9c0317ab28 correcting links, typos - doc finished 2023-08-18 11:21:12 +02:00
serinko d13116bda0 old typos edits 2023-08-18 11:21:12 +02:00
serinko 77f8eadd0e scp automation tested - doc finished 2023-08-18 11:21:12 +02:00
serinko 1e2de5067a correct go installation - guide finished 2023-08-18 11:21:12 +02:00
serinko c43344d489 remove reduntant nym/docs/ 2023-08-18 11:21:12 +02:00
serinko 2711e6f679 filled/docs/validators.md 2023-08-18 11:21:12 +02:00
mfahampshire c85f7d2565 skeleton of NR page 2023-08-18 11:21:12 +02:00
mfahampshire e8506f6d53 cont. 2023-08-18 11:21:12 +02:00
mfahampshire 6d5ff1146b * deleted old setup guides
* added new info on operator guides
* adding stubs for in-depth node pages
2023-08-18 11:21:08 +02:00
mfahampshire 1f226682f4 added custom 404 + updated platform version 2023-08-18 11:20:03 +02:00
mfahampshire f17d2cec0d typo fix 2023-08-18 11:18:00 +02:00
mfahampshire 089d5e6dbb * removed old wallet-address flag
* 'mixnode' -> 'mix node' for consistency in non-code / non-binary references
2023-08-18 11:18:00 +02:00
mfahampshire fca384fba2 tweaked intro page 2023-08-18 11:18:00 +02:00
serinko 3ae803a343 #3674 feedback implemented 2023-08-18 11:18:00 +02:00
serinko 99224310e9 operators: plugins work, ready for final review 2023-08-18 11:18:00 +02:00
serinko d2e59f12f6 operators: book built, no {comments} left, cmdrun and admonish not working 2023-08-18 11:18:00 +02:00
serinko 99a321c54d reinit the book, delete *.html in /src 2023-08-18 11:18:00 +02:00
serinko 8fd832e217 reinitialized the book - simplified book.toml 2023-08-18 11:17:59 +02:00
serinko 09c4df8448 operators guide: book built 2023-08-18 11:17:59 +02:00
serinko 09b15ae020 operators guide: add src/binaries/ files, fix links 2023-08-18 11:17:59 +02:00
serinko 585cf55026 operators: typo edit 2023-08-18 11:17:59 +02:00
serinko a0418daaea operators: comment missing info 2023-08-18 11:17:59 +02:00
serinko f0c0ddb1c2 operators: book build - minor issues remain 2023-08-18 11:17:59 +02:00
serinko b006e1820f faq.md: initial questions and answers - in progress 2023-08-18 11:17:59 +02:00
serinko 50b755cfde corrected scp -3 option 2023-08-18 11:17:59 +02:00
serinko a002ddda8d operators-guide:troubleshooting.md done - content ready to go out 2023-08-18 11:17:59 +02:00
serinko 49d909815d operators-guide: incorporated PR #3656 2023-08-18 11:17:59 +02:00
serinko 990f7d64dd operators-guide: create validator tutorial & add maintenance points 2023-08-18 11:17:59 +02:00
serinko d422741be4 operators-guide: create NR page & edit maintenance page 2023-08-18 11:17:59 +02:00
serinko 389ccffb63 operators-guide: moved repeating to maintenance.md, shortened and cleaned the existing guides 2023-08-18 11:17:59 +02:00
serinko 9a76db479b operator-guides: made todo notes 2023-08-18 11:17:59 +02:00
serinko 55cd1a8b91 operators-guide: created generic docs maintenance.md and preliminary-steps.md to avoid redundancy 2023-08-18 11:17:59 +02:00
serinko cbee6153bd mixnode-seup: minor edits 2023-08-18 11:17:59 +02:00
serinko 232032baf4 feature/operators-guide: coppied all configs from ../docs/ 2023-08-18 11:17:59 +02:00
serinko 17e1c5f970 initilizing operators guides mdbook 2023-08-18 11:17:59 +02:00
mfahampshire 85ab634d9c tweak 2023-08-18 10:10:36 +02:00
Tommy Verrall 3d245f745f Merge pull request #3756 from nymtech/feature/rust-sdk-concurrent-send-receive
[rust-sdk] feat: make it more convenient to send and receive messages in different tasks
2023-08-17 15:05:27 +02:00
Tommy Verrall c8cee9b56e Merge remote-tracking branch 'origin/develop' into feature/rust-sdk-concurrent-send-receive 2023-08-17 15:01:34 +02:00
Tommy Verrall aa64256ecd Merge pull request #3726 from nymtech/feature/validator-client-housekeeping
feat: validator client refactoring + wasm compatible nyxd client
2023-08-17 14:22:50 +02:00
mfahampshire 853d537e51 * added message types explainer
* added split task example
2023-08-17 13:45:36 +02:00
Jędrzej Stuczyński 2993e85c7a removed redundant notify and instead awaiting the task futures 2023-08-17 12:21:15 +01:00
Tommy Verrall a8041eec7b Merge pull request #3697 from nymtech/dependabot/npm_and_yarn/nym-api/tests/word-wrap-1.2.5
Bump word-wrap from 1.2.3 to 1.2.5 in /nym-api/tests
2023-08-17 12:02:28 +02:00
Jędrzej Stuczyński e849dc13fd post-rebase fixes 2023-08-17 10:59:09 +01:00
Jędrzej Stuczyński d13c8bde57 Feature/wasm tendermint rpc client (#3744)
* wasm-compatible reqwest-based rpc client

* better constructors for the reqwest based client

* fixed usages of the client

* introduced /network/details endpoint to nym-api to return used network information (#3758)

* introduced /network/details endpoint to nym-api to return used network information

* introduced endpoints for nym contract information
2023-08-17 10:56:10 +01:00
Jędrzej Stuczyński aae4725005 fixed wasm build for explorer-api-requests 2023-08-17 10:54:15 +01:00
Jędrzej Stuczyński 42d08195f7 fixed 'OfflineSigner' implementation for 'NyxdClient' and 'MaybeSigningClient' 2023-08-17 10:54:15 +01:00
Jędrzej Stuczyński 3409e86a63 removed unused import post rebasing 2023-08-17 10:54:15 +01:00
Jędrzej Stuczyński a255c6733b clippy 2023-08-17 10:54:15 +01:00
Jędrzej Stuczyński c3a09a0860 missing handler for 'MixnetQueryMsg::GetStateParams' 2023-08-17 10:54:15 +01:00
Jędrzej Stuczyński 4652ac882f missing implementations of signing methods 2023-08-17 10:54:15 +01:00
Jędrzej Stuczyński 1740cead37 fixed usage of paged query client traits 2023-08-17 10:54:14 +01:00
Jędrzej Stuczyński cc6fdfa110 signing clients for coconut bandwidth and dkg 2023-08-17 10:54:14 +01:00
Jędrzej Stuczyński 9e40763f7f using type alias in the credential client 2023-08-17 10:54:14 +01:00
Jędrzej Stuczyński 6bcc781a67 dealing with all query clients 2023-08-17 10:54:13 +01:00
Jędrzej Stuczyński 15bc4ae272 clippy 2023-08-17 10:52:37 +01:00
Jędrzej Stuczyński 3c8dd7a72b all crates building 2023-08-17 10:52:37 +01:00
Jędrzej Stuczyński 8ef9560843 all binaries compiling 2023-08-17 10:52:37 +01:00
Jędrzej Stuczyński c41e377c69 wip in making the rest of the codebase compile again 2023-08-17 10:52:37 +01:00
Jędrzej Stuczyński dbe2790ba0 restored signing contract traits 2023-08-17 10:52:37 +01:00
Jędrzej Stuczyński 93214cabbb deprecating wasm mockups to remember to revisit them 2023-08-17 10:52:37 +01:00
Jędrzej Stuczyński ce47e91186 first round of cleanup 2023-08-17 10:52:36 +01:00
Jędrzej Stuczyński a4f415cb45 extended the paged query client 2023-08-17 10:52:36 +01:00
Jędrzej Stuczyński e911e9e7ee wip 2023-08-17 10:52:36 +01:00
Jędrzej Stuczyński dd887bd89b start of the paged trait 2023-08-17 10:52:36 +01:00
Jędrzej Stuczyński e2bf9daf52 wip 2023-08-17 10:52:36 +01:00
Jędrzej Stuczyński aa7a6114be renamed 'traits' module to 'contract_traits' 2023-08-17 10:52:34 +01:00
pierre a2a887627d remove dev log 2023-08-17 11:50:00 +02:00
pierre 2b283090fa update log 2023-08-17 11:50:00 +02:00
pierre c097567f78 wip 2023-08-17 11:50:00 +02:00
pierre 93ec0f1984 add clear method to app data 2023-08-17 11:50:00 +02:00
pierre edf5050ba6 remove dead code 2023-08-17 11:50:00 +02:00
pierre 3317804a80 feat(nc-desktop): use userdata storage to save user gateway&sp 2023-08-17 11:50:00 +02:00
Tommy Verrall 0951c83ace Merge pull request #3781 from nymtech/release/v1.1.27
merge changes of wallet release into develop
2023-08-17 11:47:48 +02:00
Tommy Verrall 9754cd8a06 revert package.json 2023-08-17 11:30:10 +02:00
Jon Häggblad 6d3570913b Verify address with identity key in name-service contract (#3640)
* Validate nym address

* wip: check client_id match

* wip: now compiles

* Fix first set of tests

* Another set of fixed tests

* Fix rebase issues

* rustfmt

* register tests updated

* integration tests now working

* Remove commented out code and unused imports

* Tidy up

* Fix error

* Update schema

* Fix example

* Add assertion in test

* update nym-cli to be able to register names

* Remove left-over dbg
2023-08-17 11:22:11 +02:00
Tommy Verrall 8ef84df168 fix package.json file 2023-08-17 10:41:18 +02:00
Tommy Verrall 28f4ddb698 correct workflow 2023-08-17 10:37:12 +02:00
Tommy Verrall c52cb4f963 prepare wallet release
due to contract changes
2023-08-17 10:33:08 +02:00
Tommy Verrall 59a7034121 Merge pull request #3767 from nymtech/feature/init-retain-socket
feat: retain connection between client `init` and `run`
2023-08-17 07:51:37 +02:00
Tommy Verrall 9ec1d2dc36 Merge pull request #3779 from nymtech/fix/ci_nc_publish
ci: fix gh actions for nc release
2023-08-16 16:30:00 +02:00
pierre 022951ed0c fix gh actions 2023-08-16 16:27:54 +02:00
Tommy Verrall 1538eb0f6f Merge pull request #3777 from nymtech/release/v1.1.27
Release/v1.1.27
2023-08-16 15:55:52 +02:00
Tommy Verrall 82ea3add6a Merge remote-tracking branch 'origin/release/v1.1.27' into release/v1.1.27 2023-08-16 15:45:56 +02:00
Tommy Verrall 53b653d9cf revert package json change 2023-08-16 15:45:19 +02:00
Tommy Verrall a97004b6e0 update contracts-build.yml
needs to use 1.69.0 to build contracts
2023-08-16 11:42:00 +02:00
Tommy Verrall 61aacd16cd Merge remote-tracking branch 'origin/release/v1.1.27' into release/v1.1.27 2023-08-16 11:37:06 +02:00
Tommy Verrall 55bf5ce5b0 change version to minor in the update files 2023-08-16 11:36:41 +02:00
Tommy Verrall e9789681cc update package.json 2023-08-16 11:20:04 +02:00
Tommy Verrall d33d9d4409 update package.json for windows build 2023-08-16 11:15:15 +02:00
Tommy Verrall 852e1ace7e stage vesting schema change 2023-08-16 10:58:33 +02:00
Tommy Verrall cc3cfbfdc1 updating the change logs and relevant versions 2023-08-16 10:31:42 +02:00
Jędrzej Stuczyński 55f3fc278f new GatewaySetup variant to reuse the connection 2023-08-15 14:43:52 +01:00
Tommy Verrall 9478472070 Merge pull request #3761 from nymtech/feature/nc_use_env
Feature/nc use env
2023-08-15 10:28:36 +02:00
Jędrzej Stuczyński 950919b36c fixed usages of init 2023-08-14 15:33:05 +01:00
Bogdan-Ștefan Neacșu 5ee9c24b92 Merge remote-tracking branch 'origin/develop' into feature/nc_use_env 2023-08-14 17:28:13 +03:00
Jędrzej Stuczyński de67055e4f reusing existing gateway connection 2023-08-14 14:51:01 +01:00
Jędrzej Stuczyński 52e27152f6 retaining gateway client after init 2023-08-14 14:30:45 +01:00
Pierre Dommerc 0c24f39300 chore: remove nym-connect/mobile (#3766) 2023-08-14 14:00:07 +02:00
Jędrzej Stuczyński 204dba1a66 revert the update of tauri dependencies (#3765) 2023-08-14 13:56:46 +02:00
Bogdan-Ștefan Neacșu 461a7a2df9 Merge remote-tracking branch 'origin/develop' into feature/nc_use_env 2023-08-14 14:38:03 +03:00
Jędrzej Stuczyński f12f6b29cd Chore/rustsec (#3764)
* RUSTSEC-2023-0044

* RUSTSEC-2023-0034
2023-08-14 12:17:54 +01:00
Bogdan-Ștefan Neacșu 5385685b3f Copy sandbox.env values to wallet hard-coded ones 2023-08-14 13:39:46 +03:00
Bogdan-Ștefan Neacșu 691ac6d5ea NC to use network dependent endpoints 2023-08-14 13:39:46 +03:00
Bogdan-Ștefan Neacșu ed3535d510 Add network name to .envs 2023-08-14 13:39:46 +03:00
Bogdan-Ștefan Neacșu c6519ffdff Add NC .env configuration 2023-08-14 13:39:43 +03:00
Jon Häggblad 69e4b1ae1c Update Cargo.lock files 2023-08-14 12:18:53 +02:00
Jędrzej Stuczyński d0ba4056d6 Bugfix/contract types serde (#3753)
* additional logs in abci queries

* added serde aliases for deserialization of contract types using their old format

* installing rust toolchain during the schema CI

* making the workflow be executed on our custom runner

* checking for diff only in the schema directory
2023-08-14 10:05:16 +01:00
Fouad c81a5ac002 Reset gateway performance on disconnect (#3620)
* rest gateway performance on disconnect

* update mobile context
2023-08-14 10:42:27 +02:00
Tommy Verrall 93a8e2a9bf Merge pull request #3662 from nymtech/dependabot/npm_and_yarn/nym-api/tests/semver-6.3.1
Bump semver from 6.3.0 to 6.3.1 in /nym-api/tests
2023-08-14 10:29:18 +02:00
mfahampshire 6c83b88247 updated readme with soon to be operator doc URL 2023-08-11 13:08:19 +02:00
Tommy Verrall 83d5cc9bf4 Merge pull request #3757 from nymtech/feature/nc_user_feedback
feat(nc-desktop): add user feedback page
2023-08-11 12:42:47 +02:00
mfahampshire 6a54a6653c removed unnecessary linkcheck rendering output from dist/ 2023-08-11 12:30:41 +02:00
mfahampshire d11cf4c9a3 rough staging sh script 2023-08-11 12:29:30 +02:00
mfahampshire f9108ea400 reintroduced linkchecker + fixed broken links 2023-08-11 12:29:20 +02:00
pierre 9a5ce73dfd close send feedback modal on click 2023-08-11 12:23:44 +02:00
pierre af51ab3f71 add max chars limit to feedback text 2023-08-11 11:55:01 +02:00
mfahampshire 3714ee76ff added workflow_dispatch to ci for dev-portal and docs 2023-08-11 10:53:34 +02:00
mx 0e37c572f0 Update ci-dev.yml
added workflow_dispatch
2023-08-11 08:53:12 +00:00
mfahampshire b1b276e8ba pull fix from ci-dev.yml to ci-docs.yml 2023-08-11 10:16:37 +02:00
serinko 9966d0fa5f applied theme changes:dev-portal -> docs 2023-08-10 18:39:04 +02:00
serinko c5c6d3cc27 picked theme changes:dev-portal -> operators; theme finished 2023-08-10 18:32:13 +02:00
serinko 0f777204b8 picked theme changes:dev-portal -> operators; theme finished 2023-08-10 18:31:56 +02:00
Gala cbda950259 Merge pull request #3759 from nymtech/theme
Theme
2023-08-10 17:58:26 +02:00
pierre d57e8efff2 revert upstream changes 2023-08-10 16:10:46 +02:00
pierre c4c4355a54 add feedback note 2023-08-10 16:05:44 +02:00
pierre aaef36a5d7 display a notice to enable error reporting first 2023-08-10 16:05:44 +02:00
pierre 062f4911e1 add user feedback page 2023-08-10 16:05:44 +02:00
twofaktor 59e4567342 Update minibolt_pp.png 2023-08-10 16:05:44 +02:00
⚡️2FakTor⚡️ de2b106568 Update community-applications-and-guides.md 2023-08-10 16:05:44 +02:00
Jędrzej Stuczyński ae79dc4ec6 using stricter version requirements for mdbook and mdbook-variables 2023-08-10 14:40:15 +01:00
Gala d49ba6e025 theme change 2023-08-09 17:56:36 +02:00
Bogdan-Ștefan Neacşu 60ab58998d Print warning when coconut verif endpoint doesn't work (#3755) 2023-08-09 18:12:59 +03:00
Jędrzej Stuczyński 75bb9140b0 fixed doc tests 2023-08-09 14:49:16 +01:00
Jędrzej Stuczyński b63f5409db cargo fmt 2023-08-09 14:43:43 +01:00
Jędrzej Stuczyński de6c1ba1f0 made the Stream return a single message at each call 2023-08-09 14:39:57 +01:00
Jędrzej Stuczyński e705b76b36 unified sending interface + example of split sending 2023-08-09 14:27:17 +01:00
mfahampshire 05259410b2 changed out of date var 'mix_node_release_version' to 'platform_release_version 2023-08-09 14:25:29 +02:00
mfahampshire 6be7c094be fixed incorrect import path for chat app 2023-08-09 14:24:57 +02:00
mfahampshire 2db3297d1e updated grantee info update link 2023-08-09 14:11:06 +02:00
Jędrzej Stuczyński a1295a316b utility 'Stream' implementation for MixnetClient 2023-08-09 12:50:34 +01:00
mfahampshire fc7e4be175 fixed links 2023-08-09 13:25:37 +02:00
mfahampshire 3dd3692e8d updated links in operator binaries compilation list 2023-08-09 12:51:34 +02:00
mfahampshire 4bb6f21faa Merge branch 'release/v1.1.27' into feature/operators-guide 2023-08-09 12:50:06 +02:00
mfahampshire 62c03b3136 removed doubled header 2023-08-09 11:47:11 +02:00
mfahampshire e9d10caaf8 final tweaks 2023-08-09 11:30:12 +02:00
mfahampshire 432f6a006f removed glossary file: needs rework 2023-08-09 11:29:57 +02:00
mfahampshire 4f05169361 added coc and license 2023-08-09 11:29:34 +02:00
Bogdan-Ștefan Neacşu be88a9b277 Remove stale BBC env var (#3720) 2023-08-08 16:33:50 +01:00
Tommy Verrall fce2c704af Merge pull request #3750 from nymtech/release/v1.1.26
Release/v1.1.26
2023-08-08 16:04:32 +02:00
benedetta davico d8a95d3810 Update Cargo.toml 2023-08-08 15:42:05 +02:00
benedetta davico 191aa149df Update Cargo.toml 2023-08-08 15:37:16 +02:00
benedettadavico f4df1a9168 Merge branch 'release/v1.1.26' of https://github.com/nymtech/nym into release/v1.1.26 2023-08-08 15:22:49 +02:00
benedettadavico 62316244d9 Revert package.json changes needed temporary build 2023-08-08 15:16:22 +02:00
benedettadavico a26c6d7a29 Temporary update to fix windows build 2023-08-08 15:16:22 +02:00
benedettadavico 8fda246a3c Update changelog and versions for release v1.1.26 2023-08-08 15:16:22 +02:00
Bogdan-Ștefan Neacșu 5620fd7009 Set sphinx as default packet type 2023-08-08 15:16:22 +02:00
Bogdan-Ștefan Neacşu 122612fa03 Apply fix from feature/ephemera to develop too (#3698) (#3742) 2023-08-08 15:16:22 +02:00
mfahampshire 53db18df2c rephrased intro 2023-08-08 15:14:20 +02:00
Jon Häggblad e00910bcb8 Add geo-aware mixnet topology provider (#3713)
* WIP: initial work

* wupwup

* WIP: experiments

* Move topology provider and requests to own crate

* Make sure we use the new crate everywhere

* Sort Cargo.toml

* Extract out some functions in geo_aware_provider

* rustfmt

* Add CountryGroup type

* Assign unknown as well

* wipwip

* Add command line flag to socks5-client

* Use geo-aware mixnode selection in nym-connect when in medium mode

* rustfmt

* clippy

* Fix nym-connect build

* wasm fix

* Spelling
2023-08-08 15:14:13 +02:00
mfahampshire 23a669c4de updated vars in all books for next release version 2023-08-08 14:19:29 +02:00
benedettadavico 0af9b3c6c8 Revert package.json changes needed temporary build 2023-08-08 14:17:55 +02:00
mfahampshire 88d2592a4e added notes to ws and socks client subsections re: rust sdk 2023-08-08 14:16:48 +02:00
mfahampshire 85c22525cf * tweaked mixnode doc
* removed token diagram from nyx validator doc
2023-08-08 14:10:44 +02:00
mfahampshire 7e27413a12 added custom 404 page for all books 2023-08-08 13:59:53 +02:00
benedettadavico 2d60a9da3f Temporary update to fix windows build 2023-08-08 11:24:08 +02:00
benedettadavico 795efb9f0b Update changelog and versions for release v1.1.26 2023-08-08 11:15:30 +02:00
mfahampshire 2eeb8bb590 NR page 2023-08-07 16:38:13 +02:00
mfahampshire 2565716816 typo fix 2023-08-07 16:38:02 +02:00
mfahampshire f954ce5c97 more links, fleshed out intro 2023-08-07 16:06:39 +02:00
mfahampshire baebbe4e4d added links 2023-08-07 15:52:48 +02:00
Tommy Verrall 695d34735c Merge pull request #3748 from nymtech/feature/fix_default_packet_type 2023-08-07 15:36:31 +02:00
Bogdan-Ștefan Neacșu 314d7a7526 Set sphinx as default packet type 2023-08-07 15:52:03 +03:00
serinko 2dd3e031bd socks5: new commands from #3699 2023-08-07 13:13:11 +02:00
serinko 860ec74b59 operators-guides final review of links and typos 2023-08-07 12:47:29 +02:00
serinko bff806e5f5 correction of typos 2023-08-07 12:40:28 +02:00
serinko f8b9bb7e78 correcting links, typos - doc finished 2023-08-07 12:38:10 +02:00
serinko 913095ee60 old typos edits 2023-08-07 12:36:19 +02:00
serinko d44b88842e scp automation tested - doc finished 2023-08-07 12:19:34 +02:00
serinko a67092ad17 correct go installation - guide finished 2023-08-07 12:08:18 +02:00
Tommy Verrall a86c1a6a60 Merge pull request #3745 from nymtech/feature/explorer-api-build-info
added --version command to explorer-api
2023-08-07 11:40:04 +02:00
Bogdan-Ștefan Neacşu 7ad2865250 Add empty migration to group contract (#3740) 2023-08-07 12:32:20 +03:00
Bogdan-Ștefan Neacşu 49440bf60e Apply fix from feature/ephemera to develop too (#3698) (#3742) 2023-08-07 12:27:31 +03:00
Jędrzej Stuczyński b3b43b56be added --version command to explorer-api 2023-08-07 10:15:15 +01:00
Mark Sinclair 4a23729a6a Add GitHub Action to build Typescript SDK docs 2023-08-04 16:31:21 +01:00
pierre 5711bbd0c1 feat(nc-android): add runtime permission request 2023-08-04 17:15:01 +02:00
pierre 1b1f0293ec fix(nc-android): text colors 2023-08-04 15:36:06 +02:00
serinko 0b29e28e3f remove reduntant nym/docs/ 2023-08-04 13:19:29 +02:00
serinko f26f159bb0 filled/docs/validators.md 2023-08-04 13:18:12 +02:00
mfahampshire a8ddaddaf4 skeleton of NR page 2023-08-03 21:15:58 +02:00
mfahampshire 84741f2020 cont. 2023-08-03 19:51:03 +02:00
mfahampshire cc65236085 * deleted old setup guides
* added new info on operator guides
* adding stubs for in-depth node pages
2023-08-03 19:28:37 +02:00
mfahampshire e18c541400 added custom 404 + updated platform version 2023-08-03 19:28:13 +02:00
mfahampshire c1e8ebd46a typo fix 2023-08-03 16:46:05 +02:00
mfahampshire 0b6eb17793 * removed old wallet-address flag
* 'mixnode' -> 'mix node' for consistency in non-code / non-binary references
2023-08-03 16:43:58 +02:00
mfahampshire 10696ae4dc tweaked intro page 2023-08-03 16:31:45 +02:00
Jędrzej Stuczyński 9285aaf487 Generate json schema for all used contracts (#3693)
* removed sealed impl of serde for tx::Fee

* further upgraded cosmwasm to 1.3.0

* wip

* created schema for mixnet contract

* updated return type of 'GetBondedMixnodeDetailsByIdentity' query

* fixed imported version of serde_json_wasm

* updated return type of 'GetFamilyByHead' query

* updated return type of 'GetFamilyByLabel' query

* updated return type of 'GetFamilyMembersByHead' and 'GetFamilyMembersByLabel' queries

* fixed broken tests due to type changes

* added support for GetFamilyMembersByLabel and GetFamilyMembersByHead queries in 'mixnet_query_client'

* moved 'Account' and 'VestingContractError' to common crate

* created schema for vesting contract

* Added documentation for all query messages in the vesting contract

* improved mixnet contract schema by adding documentation to all query types

* feature-locking cw2 import

* created schema for the name service contract

* created schema for the service provider directory contract

* created schema for the coconut bandwidth contract

* created schema for the coconut dkg contract

* created schema for the coconut cw4 group contract

* created schema for the coconut cw3 multisig contract

* fixed missing import and adjusted makefile

* cargo fmt

* clippy

* adjusted contract CI to build with --lib flag

* missing --lib flag in the makefile

* updated lock files

* makefile for generating the schemas

* added github action to check for schema difference

* adding missing step to checkout the repo
2023-08-03 15:09:07 +01:00
Bogdan-Ștefan Neacşu 55bd7f8a61 Fix doubling the data dir in nym-api (#3739) 2023-08-03 17:07:59 +03:00
Jędrzej Stuczyński b66c4cf0bb removed dependency on wasm-timer fork (#3733) 2023-08-03 11:01:03 +01:00
mfahampshire 4696470b19 rephrased intro 2023-08-02 16:26:41 +02:00
Tommy Verrall 5dacf0c8f8 Merge pull request #3730 from nymtech/qa/fix-api-tests
fix config for prod runs on api tests
2023-08-02 15:05:27 +02:00
Tommy Verrall cbafd37102 fix config 2023-08-02 13:22:02 +02:00
Tommy Verrall e537359c73 Merge pull request #3728 from nymtech/qa/fix-api-tests
fix api tests for no blacklisted nodes
2023-08-02 13:21:00 +02:00
Tommy Verrall 2ed3e646be linting and removing unused imports 2023-08-02 13:02:29 +02:00
Tommy Verrall c725ae4e2b remove console 2023-08-02 12:55:46 +02:00
Tommy Verrall 5ab2c738df fix api tests for no blacklisted nodes 2023-08-02 12:54:09 +02:00
pierre cd70b0de75 build(nc-android): disable sentry upload proguard mapping files 2023-08-02 11:18:30 +02:00
serinko 6395303466 #3674 feedback implemented 2023-08-02 10:40:26 +02:00
dependabot[bot] 60264486fd Bump semver from 6.3.0 to 6.3.1 in /nym-api/tests
Bumps [semver](https://github.com/npm/node-semver) from 6.3.0 to 6.3.1.
- [Release notes](https://github.com/npm/node-semver/releases)
- [Changelog](https://github.com/npm/node-semver/blob/v6.3.1/CHANGELOG.md)
- [Commits](https://github.com/npm/node-semver/compare/v6.3.0...v6.3.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-02 08:37:23 +00:00
Tommy Verrall 6359b38a5d Merge pull request #3660 from nymtech/dependabot/npm_and_yarn/nym-wallet/webdriver/semver-5.7.2
Bump semver from 5.7.1 to 5.7.2 in /nym-wallet/webdriver
2023-08-02 10:36:36 +02:00
serinko 502a2d6a23 operators: plugins work, ready for final review 2023-08-02 08:04:57 +02:00
serinko 974cee1f22 operators: book built, no {comments} left, cmdrun and admonish not working 2023-08-01 17:37:12 +02:00
dependabot[bot] 00b5a46cbc Bump semver from 5.7.1 to 5.7.2 in /nym-wallet/webdriver
Bumps [semver](https://github.com/npm/node-semver) from 5.7.1 to 5.7.2.
- [Release notes](https://github.com/npm/node-semver/releases)
- [Changelog](https://github.com/npm/node-semver/blob/v5.7.2/CHANGELOG.md)
- [Commits](https://github.com/npm/node-semver/compare/v5.7.1...v5.7.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-01 15:22:00 +00:00
Fouad e97a068bf0 Type documentation for NymSDK (#3701)
* set up development process for docs

* set up development process for docs

* Add local installs for Typedoc on gitignore

* Add Typedoc comments on types.ts file

* add typedoc config file

* update types and add annotations

* Add updates on types file

* add examples + manage sort order for doc items

* update client methods with examples

* add description of NymMixnetClientOptions

* add description of NymMixnetClientOptions

* fix linting

---------

Co-authored-by: Lorexia <alexia.lorenza.martinel@protonmail.com>
2023-08-01 16:21:12 +01:00
serinko 7ac3bb10cb reinit the book, delete *.html in /src 2023-08-01 16:43:57 +02:00
serinko 20d51437b5 reinitialized the book - simplified book.toml 2023-08-01 16:30:07 +02:00
serinko 1965df05e7 operators guide: book built 2023-08-01 11:04:11 +02:00
serinko 615c65cb22 operators guide: add src/binaries/ files, fix links 2023-08-01 10:58:29 +02:00
Lorexia c7147ebfb2 Add updates to community list projects 2023-08-01 10:50:49 +02:00
mfahampshire a344cda916 removed old wallet address flag again 2023-08-01 10:50:46 +02:00
Lorexia 15a6af49f0 Add updates to community list projects 2023-08-01 10:49:02 +02:00
mfahampshire 97956afdf6 removed old wallet address flag again 2023-08-01 10:48:52 +02:00
serinko 432af5a204 operators: typo edit 2023-07-31 13:53:21 +02:00
serinko ce87df3026 operators: comment missing info 2023-07-31 13:47:57 +02:00
serinko db407847e3 operators: book build - minor issues remain 2023-07-31 13:25:11 +02:00
Jon Häggblad 7b71775e08 Add geo-aware mixnet topology provider (#3713)
* WIP: initial work

* wupwup

* WIP: experiments

* Move topology provider and requests to own crate

* Make sure we use the new crate everywhere

* Sort Cargo.toml

* Extract out some functions in geo_aware_provider

* rustfmt

* Add CountryGroup type

* Assign unknown as well

* wipwip

* Add command line flag to socks5-client

* Use geo-aware mixnode selection in nym-connect when in medium mode

* rustfmt

* clippy

* Fix nym-connect build

* wasm fix

* Spelling
2023-07-28 14:48:33 +02:00
serinko 02f5fa6816 faq.md: initial questions and answers - in progress 2023-07-28 13:22:40 +02:00
pierre 5fbccc3406 build(nc-android): moving build config to kotlin 2023-07-27 19:11:33 +02:00
pierre 5964f104c5 fix(nc-desktop): typo 2023-07-27 15:54:45 +02:00
pierre ac8afe133f fix(nc-desktop): typo 2023-07-27 15:53:55 +02:00
serinko 3aa9ad0197 corrected scp -3 option 2023-07-27 13:01:09 +02:00
serinko 7ccadffdba operators-guide:troubleshooting.md done - content ready to go out 2023-07-27 12:41:22 +02:00
Bogdan-Ștefan Neacşu 19736b1204 Fix develop after bad automerge (#3712) 2023-07-27 13:25:34 +03:00
pierre 6e5f6bf0df ci: fix release strapi actions 2023-07-27 11:42:42 +02:00
pierre 0bfc1be1d5 ci: fix release strapi actions 2023-07-27 11:42:02 +02:00
Jędrzej Stuczyński 67435e9cdf Feature/simplify cli parsing (#3699)
* added a global flag to disable the printed out banner inside tty

* added a 'build-info' command to our binaries

* added binary name to BinaryBuildInformation

* clippy
2023-07-27 10:20:07 +01:00
Bogdan-Ștefan Neacşu a47899aa77 Apply fix from feature/ephemera to develop too (#3698) 2023-07-27 12:18:08 +03:00
pierre aedacf6c65 ci: fix release strapi actions 2023-07-27 11:12:42 +02:00
pierre 44fa52a7a7 ci: fix release strapi actions 2023-07-27 11:08:24 +02:00
Tommy Verrall f6e20c8201 Merge branch 'release/v1.1.25' into develop 2023-07-26 17:39:34 +02:00
pierre 1da6ee2058 fix workflows (try) 2023-07-26 17:37:54 +02:00
pierre 109fb96fca fix workflows 2023-07-26 17:37:54 +02:00
benedetta davico 557bfa7b34 Update CHANGELOG.md 2023-07-26 17:37:25 +02:00
Tommy Verrall 4c9727b1ef Update nym-connect-publish-ubuntu.yml (#3706)
* Update nym-connect-publish-ubuntu.yml

* Update nym-connect-publish-ubuntu.yml

* Update nym-connect-publish-macos.yml

* Update nym-connect-publish-windows10.yml
2023-07-26 17:37:25 +02:00
Tommy Verrall a0408b74dc Update nym-connect-publish-macos.yml (#3705)
* Update nym-connect-publish-macos.yml

install wasm and build

* Update nym-connect-publish-macos.yml

use the correct download
2023-07-26 17:37:25 +02:00
Tommy Verrall 8a1ed12f58 bump versions for NC 2023-07-26 17:37:25 +02:00
mfahampshire c38c5c2f0d fixed clippy warning 2023-07-26 17:37:25 +02:00
pierre 03300a859e build(nc-desktop): sentry dsn as env var 2023-07-26 17:37:22 +02:00
mfahampshire 2fe5401a38 ran fmt 2023-07-26 17:37:22 +02:00
mfahampshire d8a44cd9c1 added reply with surbs example to rust sdk examples dir 2023-07-26 17:37:22 +02:00
mfahampshire a0b41db22d added rust sdk surb example 2023-07-26 17:37:22 +02:00
Pierre Dommerc 7d6d8669b0 feat(nc-desktop): add sentry to backend (#3652) 2023-07-26 17:37:18 +02:00
mfahampshire a1a2f37fce included url 2023-07-26 17:23:20 +02:00
mfahampshire 91341733c1 updated NR guide with list explainer + info on comments in local allow list 2023-07-26 17:23:20 +02:00
mfahampshire 93cd8821c3 version update 2023-07-26 17:23:20 +02:00
mfahampshire b79ec60381 * added serinko + alexia to book authors
* version bumps for next release
2023-07-26 17:23:20 +02:00
mfahampshire 2c2dd54028 updated sdk documentation with surb example 2023-07-26 17:23:20 +02:00
mfahampshire 4306cec49c version bumps 2023-07-26 17:23:14 +02:00
mfahampshire 5781d3043f removed command information from mix node + gateway guide 2023-07-26 17:23:14 +02:00
⚡️2FakTor⚡️ d843407ba7 Update network-requester-setup.md 2023-07-26 17:23:14 +02:00
⚡️2FakTor⚡️ 053e047cca Update network-requester-setup.md 2023-07-26 17:23:14 +02:00
Jędrzej Stuczyński 516561dcf9 Feature/wasm nyxd client (#3708)
* separated signing and nyxd-client features

* updated cosmrs to the most recent version

* using tendermint_rpc directly for the Client trait

* fixed rest of the codebase

* removed nyxd-client feature

* export more types

* clippy that seems to have been skipped in makefile
2023-07-26 15:49:45 +01:00
Jon Häggblad 290dbc1a03 client-core: make latency based gateway selection concurrent (#3709) 2023-07-26 13:08:06 +02:00
serinko c120196be0 operators-guide: incorporated PR #3656 2023-07-26 12:55:05 +02:00
serinko f2a395fe42 operators-guide: create validator tutorial & add maintenance points 2023-07-26 11:46:36 +02:00
Jon Häggblad 524863aae7 Uncouple gateways and network-requester in nym-connect (#3639)
* Split fetching network-requesters from gateways

* Tidy names

* Select gateway independenty in frontend

* Fix threshold value

* Fix gateway type

* Fix naming for setGateway and setServiceProvider

* Unshadow variable

* Naming conventions

* Missing semicolon

* Explicit types in invoke calls

* Dedup random function

* Inline some functions

* Silence handlebars in log

* Emojis in healthcheck log statements

* Remove gateway from service provider type

* Remove unneeded type cast

* fix linting

* Remove gateway field from harbour master response type

---------

Co-authored-by: fmtabbara <fmtabbara@hotmail.co.uk>
2023-07-25 13:51:27 +02:00
Tommy Verrall 61ad336b18 Merge pull request #3598 from nymtech/bug-fix/balanceVSfeeWarning
TX warning when fee > balance
2023-07-25 09:55:34 +02:00
pierre 867b745a38 fix(nc-android): http requests 2023-07-25 08:53:34 +02:00
fmtabbara 78e54287da include tx amount when checking balance 2023-07-24 16:57:28 +01:00
fmtabbara 96c29b974b add warning for more txs 2023-07-24 16:57:28 +01:00
fmtabbara eadd116ae4 add warning modal for more txs 2023-07-24 16:57:28 +01:00
fmtabbara f1175280cf add warning to tx modals when fee exceeds balance 2023-07-24 16:57:28 +01:00
serinko cf79bdc098 operators-guide: create NR page & edit maintenance page 2023-07-24 12:53:32 +02:00
dependabot[bot] 34e2affef8 Bump word-wrap from 1.2.3 to 1.2.5 in /nym-api/tests
Bumps [word-wrap](https://github.com/jonschlinkert/word-wrap) from 1.2.3 to 1.2.5.
- [Release notes](https://github.com/jonschlinkert/word-wrap/releases)
- [Commits](https://github.com/jonschlinkert/word-wrap/compare/1.2.3...1.2.5)

---
updated-dependencies:
- dependency-name: word-wrap
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-23 02:08:02 +00:00
pierre 34a47a9449 build(nc-desktop): sentry dsn as env var 2023-07-21 15:56:08 +02:00
Bogdan-Ștefan Neacşu dff11df2bd Add DKG resharing benchmark (#3692)
* Add DKG resharing benchmark

* Fix clippy
2023-07-21 11:25:14 +01:00
benedettadavico feb888a154 updating sandbox .env 2023-07-20 17:20:00 +02:00
Pierre Dommerc 415fe4605c feat(nc-desktop): add sentry to backend (#3652) 2023-07-20 13:17:49 +02:00
Pierre Dommerc 70e6539298 refactor(nc-desktop): add privacy level user settings (#3664) 2023-07-19 15:56:00 +02:00
pierre fe76ba68a0 ci: fix connect-desktop-ci workflow 2023-07-19 15:41:00 +02:00
pierre 863580a6f2 ci: fix workflow for strapi data publish 2023-07-18 19:23:31 +02:00
pierre 4c558db08e add alephium to supported wallets 2023-07-18 17:08:20 +02:00
Mark Sinclair 9d5b582908 SDK - fix unsubscribe function for events (#3659)
Co-authored-by: Mark Sinclair <mmsinclair@users.noreply.github.com>
2023-07-18 14:12:00 +01:00
Fouad c12b20f1d6 Feature/sdk browser extension examples (#3673)
* New TypeScript SDK example: Google Chrome

Example of a simple manifest v3 extension to load a Nym client within  a
popup view.

* Firefox Extension example for Nym TypeScript SDK

* Fix typo

* Add basic install script

* fix up html files

* remove unnecessary background page

* bundle extensions with webpack

* use icons from shared assets

* ignore sdk index file

* import sdk lib

* create new build script for non-inline workers

* import workers and build as separate files using webpack

* update html titles

* create react app node tester example

* add readme file

* update readme for FF extension

* code formatting

---------

Co-authored-by: Nadim Kobeissi <nadim@symbolic.software>
Co-authored-by: Mark Sinclair <mmsinclair@users.noreply.github.com>
2023-07-18 14:09:40 +01:00
farbanas edeb8369df Merge branch 'master' into develop 2023-07-18 14:22:46 +02:00
farbanas 22b2405aa2 Merge branch 'release/v1.1.24' 2023-07-18 13:43:47 +02:00
farbanas 63254ecffe update versions and changelogs for the release 2023-07-18 13:43:30 +02:00
farbanas 407d280019 fixes to GH action 2023-07-18 11:23:15 +02:00
farbanas 1fafc126fb debugging 2023-07-18 11:06:45 +02:00
farbanas 9a51135d22 debugging 2023-07-18 10:43:27 +02:00
Tommy Verrall 1b2790da80 Merge pull request #3676 from nymtech/bugfix/#3630
[wallet] bugfix: don't send funds for pledge decrease simulation
2023-07-17 12:08:32 +02:00
Jędrzej Stuczyński f8943eebce preemptively resolving future clippy issue 2023-07-17 11:01:45 +01:00
Jędrzej Stuczyński d7b53cba40 don't send funds for pledge decrease simulation 2023-07-17 11:01:45 +01:00
mx 89d2f0ac12 Merge pull request #3665 from nymtech/dev-portal/communityupdates
Dev portal/communityupdates
2023-07-17 09:49:52 +00:00
wigy 110b4d384e fix: typo in Rust SDK docs (#3655) 2023-07-17 10:29:28 +01:00
serinko cf71d655e2 operators-guide: moved repeating to maintenance.md, shortened and cleaned the existing guides 2023-07-14 19:21:25 +02:00
serinko 141b9d396c operator-guides: made todo notes 2023-07-14 17:17:07 +02:00
serinko ff65d052b8 operators-guide: created generic docs maintenance.md and preliminary-steps.md to avoid redundancy 2023-07-14 13:25:12 +02:00
serinko 153e899e0e mixnode-seup: minor edits 2023-07-14 11:20:51 +02:00
serinko 7e5c79848f feature/operators-guide: coppied all configs from ../docs/ 2023-07-13 16:59:25 +02:00
serinko 92b4dbb250 initilizing operators guides mdbook 2023-07-13 16:51:04 +02:00
Lorexia 4631c72c6b Update quickstart overview, delete project comments in community-applications-and-guides 2023-07-13 10:36:27 +02:00
Lorexia 12aa5f1f4f Add Minibolt to community projects list 2023-07-12 18:37:06 +02:00
Lorexia 825f25800a Add Nymster email info, update Nostr-Nym link, update deployed apps text 2023-07-12 14:44:51 +02:00
Lorexia d9b4d8fde6 Add preprocessors for build, update NIsNymUp issue, update DarkFi picture 2023-07-12 11:05:42 +02:00
Lorexia a98613d83c Update community application list, merge community and guides pages, update SUMMARY file, update overview file 2023-07-11 19:57:21 +02:00
mfahampshire 34de42fe7a updated validator docs: upgrade to 0.32.0 instructions 2023-07-11 15:51:02 +02:00
serinko 6e2eaf29e7 edited NC-Matrix user manual
- changed setup for Mac
- fixed typo
2023-07-10 15:32:23 +02:00
mx c6b193eb4f Merge pull request #3657 from nymtech/serinko-dev-portal-patch
update NC-Matrix user manual
2023-07-10 08:17:17 +00:00
serinko 92b9edf0da edited NC-Matrix user manual
- changed setup for Mac
- fixed typo
2023-07-04 14:52:05 +00:00
1159 changed files with 74688 additions and 37781 deletions
@@ -57,7 +57,7 @@ jobs:
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
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 protobuf-compiler
continue-on-error: true
- name: Install Rust stable
@@ -98,7 +98,6 @@ jobs:
cp target/release/nym-network-requester $OUTPUT_DIR
cp target/release/nym-network-statistics $OUTPUT_DIR
cp target/release/nym-cli $OUTPUT_DIR
cp target/release/nym-credential-client $OUTPUT_DIR
cp target/release/explorer-api $OUTPUT_DIR
cp contracts/target/wasm32-unknown-unknown/release/mixnet_contract.wasm $OUTPUT_DIR
+5 -1
View File
@@ -6,6 +6,7 @@ on:
- 'clients/**'
- 'common/**'
- 'explorer-api/**'
- 'ephemera/**'
- 'gateway/**'
- 'integrations/**'
- 'mixnode/**'
@@ -15,6 +16,7 @@ on:
- 'nym-api/**'
- 'nym-outfox/**'
- 'tools/nym-cli/**'
- 'tools/nym-nr-query/**'
- 'tools/ts-rs-cli/**'
- 'Cargo.toml'
pull_request:
@@ -22,6 +24,7 @@ on:
- 'clients/**'
- 'common/**'
- 'explorer-api/**'
- 'ephemera/**'
- 'gateway/**'
- 'integrations/**'
- 'mixnode/**'
@@ -31,6 +34,7 @@ on:
- 'nym-api/**'
- 'nym-outfox/**'
- 'tools/nym-cli/**'
- 'tools/nym-nr-query/**'
- 'tools/ts-rs-cli/**'
- 'Cargo.toml'
@@ -42,7 +46,7 @@ jobs:
RUSTC_WRAPPER: /home/ubuntu/.cargo/bin/sccache
steps:
- name: Install Dependencies (Linux)
run: sudo apt-get update && sudo apt-get -y install libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev libudev-dev squashfs-tools
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 protobuf-compiler
continue-on-error: true
- name: Check out repository code
-76
View File
@@ -1,76 +0,0 @@
name: CD dev-portal
on:
push:
branches: master
paths:
- 'documentation/dev-portal/**'
jobs:
build:
runs-on: custom-runner-linux
steps:
- uses: actions/checkout@v3
- name: Install rsync
run: sudo apt-get install rsync
- uses: rlespinasse/github-slug-action@v3.x
- uses: actions/setup-node@v3
with:
node-version: 18
- name: Install Rust stable
uses: actions-rs/toolchain@v1
with:
toolchain: stable
- name: Install mdbook
run: (test -x $HOME/.cargo/bin/mdbook || cargo install --vers "^0.4" mdbook)
- name: Install mdbook plugins
run: |
cargo install --vers "^0.2.0" mdbook-variables && cargo install \
--vers "^1.8.0" mdbook-admonish && cargo install --vers \
"^0.1.2" mdbook-last-changed && cargo install --vers "^0.1.2" \
mdbook-theme && cargo install --vers "^0.7.7" mdbook-linkcheck
- name: Clean website
run: cd documentation/dev-portal && mdbook clean
- name: Build website
run: cd documentation/dev-portal && mdbook build
- name: Deploy branch master to dev
continue-on-error: true
uses: easingthemes/ssh-deploy@main
env:
SSH_PRIVATE_KEY: ${{ secrets.CD_WWW_SSH_PRIVATE_KEY }}
ARGS: "-rltgoDzvO --delete"
SOURCE: "documentation/dev-portal/book/html/"
REMOTE_HOST: ${{ secrets.CD_WWW_REMOTE_HOST_DEV }}
REMOTE_USER: ${{ secrets.CD_WWW_REMOTE_USER }}
TARGET: ${{ secrets.CD_WWW_REMOTE_TARGET_DEVP }}/
EXCLUDE: "/dist/, /node_modules/"
- name: Deploy branch master to prod
uses: easingthemes/ssh-deploy@main
env:
SSH_PRIVATE_KEY: ${{ secrets.CD_WWW_SSH_PRIVATE_KEY }}
ARGS: "-rltgoDzvO --delete"
SOURCE: "documentation/dev-portal/book/html/"
REMOTE_HOST: ${{ secrets.CD_WWW_REMOTE_HOST_PROD }}
REMOTE_USER: ${{ secrets.CD_WWW_REMOTE_USER }}
TARGET: ${{ secrets.CD_WWW_REMOTE_TARGET_DEVP }}/
EXCLUDE: "/dist/, /node_modules/"
- name: Matrix - Node Install
run: npm install
working-directory: .github/workflows/support-files
- name: Matrix - Send Notification
env:
NYM_NOTIFICATION_KIND: cd-dev
NYM_PROJECT_NAME: "Dev portal CD"
NYM_CI_WWW_BASE: "${{ secrets.NYM_CD_WWW_BASE }}"
NYM_CI_WWW_LOCATION: "${{ env.GITHUB_REF_SLUG }}"
GIT_COMMIT_MESSAGE: "${{ github.event.head_commit.message }}"
GIT_BRANCH: "${GITHUB_REF##*/}"
MATRIX_SERVER: "${{ secrets.MATRIX_SERVER }}"
MATRIX_ROOM: "${{ secrets.MATRIX_ROOM_DEVP }}"
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:
args: .github/workflows/support-files/notifications/entry_point.sh
+13 -13
View File
@@ -1,6 +1,7 @@
name: CD docs
on:
workflow_dispatch:
push:
branches: master
paths:
@@ -27,39 +28,38 @@ jobs:
command: build
args: --workspace --release --all
- name: Install mdbook
run: (test -x $HOME/.cargo/bin/mdbook || cargo install --vers "^0.4" mdbook)
run: (test -x $HOME/.cargo/bin/mdbook || cargo install --vers "^0.4.33" mdbook)
- name: Install mdbook plugins
run: |
cargo install --vers "^0.2.0" mdbook-variables && cargo install \
cargo install --vers "=0.2.2" mdbook-variables && cargo install \
--vers "^1.8.0" mdbook-admonish && cargo install --vers \
"^0.1.2" mdbook-last-changed && cargo install --vers "^0.1.2" \
mdbook-theme && cargo install --vers "^0.7.7" mdbook-linkcheck && \
cargo install --vers "^0.5.0" mdbook-cmdrun
- name: Clean website
run: cd documentation/docs && mdbook clean
- name: Build website
run: cd documentation/docs && mdbook build
"^0.1.2" mdbook-last-changed && cargo install --vers "^0.1.2" mdbook-theme \
&& cargo install --vers "^0.7.7" mdbook-linkcheck
- name: Build all projects in documentation/ & move to ~/dist/docs/
run: cd documentation && ./build_all_to_dist.sh
continue-on-error: false
- name: Deploy branch master to dev
continue-on-error: true
uses: easingthemes/ssh-deploy@main
env:
SSH_PRIVATE_KEY: ${{ secrets.CD_WWW_SSH_PRIVATE_KEY }}
ARGS: "-rltgoDzvO --delete"
SOURCE: "documentation/docs/book/"
SOURCE: "dist/docs/"
REMOTE_HOST: ${{ secrets.CD_WWW_REMOTE_HOST_DEV }}
REMOTE_USER: ${{ secrets.CD_WWW_REMOTE_USER }}
TARGET: ${{ secrets.CD_WWW_REMOTE_TARGET }}/
EXCLUDE: "/dist/, /node_modules/"
EXCLUDE: "/node_modules/"
- name: Deploy branch master to prod
if: github.ref == 'refs/heads/master'
uses: easingthemes/ssh-deploy@main
env:
SSH_PRIVATE_KEY: ${{ secrets.CD_WWW_SSH_PRIVATE_KEY }}
ARGS: "-rltgoDzvO --delete"
SOURCE: "documentation/docs/book/"
SOURCE: "dist/docs/"
REMOTE_HOST: ${{ secrets.CD_WWW_REMOTE_HOST_PROD }}
REMOTE_USER: ${{ secrets.CD_WWW_REMOTE_USER }}
TARGET: ${{ secrets.CD_WWW_REMOTE_TARGET }}/
EXCLUDE: "/dist/, /node_modules/"
EXCLUDE: "/node_modules/"
- name: Matrix - Node Install
run: npm install
working-directory: .github/workflows/support-files
@@ -0,0 +1,31 @@
name: Check Contract Schema
on:
push:
paths:
- 'contracts/**'
- 'common/**'
pull_request:
paths:
- 'contracts/**'
- 'common/**'
jobs:
check-schema:
name: Generate and check schema
runs-on: custom-runner-linux
steps:
- name: Check out repository code
uses: actions/checkout@v2
- name: Install Rust toolchain
uses: actions-rs/toolchain@v1
with:
toolchain: stable
- name: Generate the schema
run: make contract-schema
- name: Check for diff
run: git diff --exit-code -- contracts/*/schema
-66
View File
@@ -1,66 +0,0 @@
name: CI dev-portal
on:
push:
branches-ignore: master
paths:
- 'documentation/dev-portal/**'
jobs:
build:
runs-on: custom-runner-linux
steps:
- uses: actions/checkout@v3
- name: Install rsync
run: sudo apt-get install rsync
- uses: rlespinasse/github-slug-action@v3.x
- uses: actions/setup-node@v3
with:
node-version: 18
- name: Install Rust stable
uses: actions-rs/toolchain@v1
with:
toolchain: stable
- name: Install mdbook
run: (test -x $HOME/.cargo/bin/mdbook || cargo install --vers "^0.4" mdbook)
- name: Install mdbook plugins
run: |
cargo install --vers "^0.2.0" mdbook-variables && cargo install \
--vers "^1.8.0" mdbook-admonish && cargo install --vers \
"^0.1.2" mdbook-last-changed && cargo install --vers "^0.1.2" mdbook-theme \
&& cargo install --vers "^0.7.7" mdbook-linkcheck
- name: Clean website
run: cd documentation/dev-portal && mdbook clean
- name: Build website
run: cd documentation/dev-portal && mdbook build
- 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: "-rltgoDzvO --delete"
SOURCE: "documentation/dev-portal/book/html/"
REMOTE_HOST: ${{ secrets.CI_WWW_REMOTE_HOST }}
REMOTE_USER: ${{ secrets.CI_WWW_REMOTE_USER }}
TARGET: ${{ secrets.CI_WWW_REMOTE_TARGET }}/dev-portal-${{ env.GITHUB_REF_SLUG }}
EXCLUDE: "/dist/, /node_modules/"
- name: Matrix - Node Install
run: npm install
working-directory: .github/workflows/support-files
- name: Matrix - Send Notification
env:
NYM_NOTIFICATION_KIND: ci-dev
NYM_PROJECT_NAME: "Dev portal CI"
NYM_CI_WWW_BASE: "${{ secrets.NYM_CI_WWW_BASE }}"
NYM_CI_WWW_LOCATION: "dev-portal-${{ env.GITHUB_REF_SLUG }}"
GIT_COMMIT_MESSAGE: "${{ github.event.head_commit.message }}"
GIT_BRANCH: "${GITHUB_REF##*/}"
MATRIX_SERVER: "${{ secrets.MATRIX_SERVER }}"
MATRIX_ROOM: "${{ secrets.MATRIX_ROOM_DEVP }}"
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:
args: .github/workflows/support-files/notifications/entry_point.sh
+10 -11
View File
@@ -1,6 +1,7 @@
name: CI docs
on:
workflow_dispatch:
push:
branches-ignore: master
paths:
@@ -27,29 +28,27 @@ jobs:
command: build
args: --workspace --release --all
- name: Install mdbook
run: (test -x $HOME/.cargo/bin/mdbook || cargo install --vers "^0.4" mdbook)
run: (test -x $HOME/.cargo/bin/mdbook || cargo install --vers "^0.4.33" mdbook)
- name: Install mdbook plugins
run: |
cargo install --vers "^0.2.0" mdbook-variables && cargo install \
cargo install --vers "=0.2.2" mdbook-variables && cargo install \
--vers "^1.8.0" mdbook-admonish && cargo install --vers \
"^0.1.2" mdbook-last-changed && cargo install --vers "^0.1.2" \
mdbook-theme && cargo install --vers "^0.7.7" mdbook-linkcheck && \
cargo install --vers "^0.5.0" mdbook-cmdrun
- name: Clean website
run: cd documentation/docs && mdbook clean
- name: Build website
run: cd documentation/docs && mdbook build
"^0.1.2" mdbook-last-changed && cargo install --vers "^0.1.2" mdbook-theme \
&& cargo install --vers "^0.7.7" mdbook-linkcheck
- name: Build all projects in documentation/ & move to ~/dist/docs/
run: cd documentation && ./build_all_to_dist.sh
continue-on-error: false
- 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: "-rltgoDzvO --delete"
SOURCE: "documentation/docs/book/"
SOURCE: "dist/docs/"
REMOTE_HOST: ${{ secrets.CI_WWW_REMOTE_HOST }}
REMOTE_USER: ${{ secrets.CI_WWW_REMOTE_USER }}
TARGET: ${{ secrets.CI_WWW_REMOTE_TARGET }}/docs-${{ env.GITHUB_REF_SLUG }}
EXCLUDE: "/dist/, /node_modules/"
EXCLUDE: "/node_modules/"
- name: Matrix - Node Install
run: npm install
working-directory: .github/workflows/support-files
+6 -1
View File
@@ -23,7 +23,12 @@ jobs:
node-version: 18
- name: Install Yarn
run: npm install -g yarn
- name: Install Rust stable
uses: actions-rs/toolchain@v1
with:
toolchain: stable
- name: Install wasm-pack
run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
- name: Install project dependencies
run: cd ../.. && yarn --network-timeout 100000
-72
View File
@@ -1,72 +0,0 @@
name: Nym Connect - mobile (Rust)
on:
push:
paths:
- "nym-connect/mobile/src-tauri/**"
- "nym-connect/mobile/src-tauri/Cargo.toml"
- "!nym-connect/mobile/src-tauri/gen/**"
- "clients/client-core/**"
- "clients/socks5/**"
- "common/**"
- "gateway/gateway-requests/**"
- "contracts/vesting/**"
- "nym-api/nym-api-requests/**"
pull_request:
paths:
- "nym-connect/mobile/src-tauri/**"
- "nym-connect/mobile/src-tauri/Cargo.toml"
- "!nym-connect/mobile/src-tauri/gen/**"
- "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/mobile/src-tauri/
steps:
- name: Install Dependencies (Linux)
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
- 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/mobile/src-tauri/Cargo.toml -- --check
- name: Build all binaries
run: cargo build --manifest-path nym-connect/mobile/src-tauri/Cargo.toml
- name: Run all tests
run: cargo test --manifest-path nym-connect/mobile/src-tauri/Cargo.toml
- name: Clippy
run: cargo clippy --manifest-path nym-connect/mobile/src-tauri/Cargo.toml --all-targets -- -D warnings
+1 -1
View File
@@ -14,7 +14,7 @@ jobs:
- name: Install Rust stable
uses: actions-rs/toolchain@v1
with:
toolchain: stable
toolchain: 1.69.0
target: wasm32-unknown-unknown
override: true
components: rustfmt, clippy
+3 -3
View File
@@ -48,12 +48,12 @@ jobs:
RUSTFLAGS: '-C link-arg=-s'
with:
command: build
args: --manifest-path contracts/Cargo.toml --workspace --target wasm32-unknown-unknown
args: --manifest-path contracts/Cargo.toml --workspace --lib --target wasm32-unknown-unknown
- uses: actions-rs/cargo@v1
with:
command: test
args: --manifest-path contracts/Cargo.toml
args: --lib --manifest-path contracts/Cargo.toml
- uses: actions-rs/cargo@v1
with:
@@ -64,4 +64,4 @@ jobs:
if: ${{ matrix.rust != 'nightly' }}
with:
command: clippy
args: --manifest-path contracts/Cargo.toml --workspace --all-targets -- -D warnings
args: --lib --manifest-path contracts/Cargo.toml --workspace --all-targets -- -D warnings
+1 -1
View File
@@ -24,7 +24,7 @@ jobs:
continue-on-error: ${{ matrix.rust == 'nightly' || matrix.rust == 'beta' || matrix.rust == 'stable' }}
steps:
- name: Install Dependencies (Linux)
run: sudo apt-get update && sudo apt-get install libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev libudev-dev squashfs-tools
run: sudo apt-get update && sudo apt-get install libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev libudev-dev squashfs-tools protobuf-compiler
continue-on-error: true
if: matrix.os == 'ubuntu-20.04'
+1 -1
View File
@@ -37,7 +37,7 @@ jobs:
continue-on-error: ${{ matrix.rust == 'nightly' || matrix.rust == 'beta' || matrix.rust == 'stable' }}
steps:
- name: Install Dependencies (Linux)
run: sudo apt-get update && sudo apt-get install libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev libudev-dev squashfs-tools
run: sudo apt-get update && sudo apt-get install libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev libudev-dev squashfs-tools protobuf-compiler
continue-on-error: true
if: matrix.os == 'ubuntu-20.04'
@@ -19,7 +19,7 @@ jobs:
outputs:
release_id: ${{ steps.create-release.outputs.id }}
release_date: ${{ fromJSON(steps.create-release.outputs.assets)[0].published_at }}
release_date: ${{ fromJSON(steps.create-release.outputs.assets)[0].created_at }}
version: ${{ steps.release-info.outputs.version }}
filename: ${{ steps.release-info.outputs.filename }}
file_hash: ${{ steps.release-info.outputs.file_hash }}
@@ -31,10 +31,20 @@ jobs:
uses: actions/setup-node@v3
with:
node-version: 18
- name: Install Rust stable
uses: actions-rs/toolchain@v1
with:
toolchain: stable
target: wasm32-unknown-unknown
- name: Install wasm-pack
run: |
export WASM_PACK_VERSION="v0.12.1"
curl -LO https://github.com/rustwasm/wasm-pack/releases/download/${WASM_PACK_VERSION}/wasm-pack-${WASM_PACK_VERSION}-x86_64-apple-darwin.tar.gz
tar xvzf wasm-pack-${WASM_PACK_VERSION}-x86_64-apple-darwin.tar.gz -C $HOME/.cargo/bin --strip-components=1
rm wasm-pack-${WASM_PACK_VERSION}-x86_64-apple-darwin.tar.gz
- name: Install the Apple developer certificate for code signing
env:
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
@@ -78,6 +88,8 @@ jobs:
APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
SENTRY_DSN_RUST: ${{ secrets.SENTRY_DSN_RUST }}
SENTRY_DSN_JS: ${{ secrets.SENTRY_DSN_JS }}
run: yarn && yarn build
- name: Upload Artifact
@@ -103,9 +115,10 @@ jobs:
- id: release-info
name: Prepare release info
run: |
semver="${${{ github.ref_name }}##nym-connect-}" && semver="${semver##v}"
echo "version=$semver" >> "$GITHUB_OUTPUT"
echo "filename=nym-connect_$version_x64.dmg" >> "$GITHUB_OUTPUT"
ref=${{ github.ref_name }}
semver="${ref##nym-connect-}" && semver="${semver##v}"
echo "version=${semver}" >> "$GITHUB_OUTPUT"
echo "filename=nym-connect_${semver}_x64.dmg " >> "$GITHUB_OUTPUT"
echo "file_hash=${{ hashFiles('nym-connect/desktop/target/release/bundle/dmg/nym-connect_*_x64.dmg') }}" >> "$GITHUB_OUTPUT"
push-release-data:
@@ -19,7 +19,7 @@ jobs:
outputs:
release_id: ${{ steps.create-release.outputs.id }}
release_date: ${{ fromJSON(steps.create-release.outputs.assets)[0].published_at }}
release_date: ${{ fromJSON(steps.create-release.outputs.assets)[0].created_at }}
version: ${{ steps.release-info.outputs.version }}
filename: ${{ steps.release-info.outputs.filename }}
file_hash: ${{ steps.release-info.outputs.file_hash }}
@@ -61,6 +61,8 @@ jobs:
env:
TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
SENTRY_DSN_RUST: ${{ secrets.SENTRY_DSN_RUST }}
SENTRY_DSN_JS: ${{ secrets.SENTRY_DSN_JS }}
- name: Upload Artifact
uses: actions/upload-artifact@v3
@@ -80,9 +82,10 @@ jobs:
- id: release-info
name: Prepare release info
run: |
semver="${${{ github.ref_name }}##nym-connect-}" && semver="${semver##v}"
echo "version=$semver" >> "$GITHUB_OUTPUT"
echo "filename=nym-connect_$version_amd64.AppImage" >> "$GITHUB_OUTPUT"
ref=${{ github.ref_name }}
semver="${ref##nym-connect-}" && semver="${semver##v}"
echo "version=${semver}" >> "$GITHUB_OUTPUT"
echo "filename=nym-connect_${semver}_amd64.AppImage" >> "$GITHUB_OUTPUT"
echo "file_hash=${{ hashFiles('nym-connect/desktop/target/release/bundle/appimage/nym-connect_*_amd64.AppImage') }}" >> "$GITHUB_OUTPUT"
push-release-data:
@@ -19,7 +19,7 @@ jobs:
outputs:
release_id: ${{ steps.create-release.outputs.id }}
release_date: ${{ fromJSON(steps.create-release.outputs.assets)[0].published_at }}
release_date: ${{ fromJSON(steps.create-release.outputs.assets)[0].created_at }}
version: ${{ steps.release-info.outputs.version }}
filename: ${{ steps.release-info.outputs.filename }}
file_hash: ${{ steps.release-info.outputs.file_hash }}
@@ -79,6 +79,8 @@ jobs:
WINDOWS_CERTIFICATE_PASSWORD: ${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }}
TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
SENTRY_DSN_RUST: ${{ secrets.SENTRY_DSN_RUST }}
SENTRY_DSN_JS: ${{ secrets.SENTRY_DSN_JS }}
run: yarn build
- name: Upload Artifact
@@ -98,10 +100,12 @@ jobs:
nym-connect/desktop/target/release/bundle/msi/*.msi.zip*
- id: release-info
name: Prepare release info
shell: bash
run: |
semver="${${{ github.ref_name }}##nym-connect-}" && semver="${semver##v}"
echo "version=$semver" >> "$GITHUB_OUTPUT"
echo "filename=nym-connect_$version_x64_en-US.msi" >> "$GITHUB_OUTPUT"
ref=${{ github.ref_name }}
semver="${ref##nym-connect-}" && semver="${semver##v}"
echo "version=${semver}" >> "$GITHUB_OUTPUT"
echo "filename=nym-connect_${semver}_x64_en-US.msi" >> "$GITHUB_OUTPUT"
echo "file_hash=${{ hashFiles('nym-connect/desktop/target/release/bundle/msi/nym-connect_*_x64_en-US.msi') }}" >> "$GITHUB_OUTPUT"
push-release-data:
@@ -1,104 +0,0 @@
name: Publish Nym Connect - desktop (MacOS)
on:
workflow_dispatch:
inputs:
release_tag:
required: true
description: Release tag (nym-connect-s-v*)
type: string
default: 'nym-connect-s-v1.0.0'
push:
tags:
- nym-connect-s-v*
defaults:
run:
working-directory: nym-connect/desktop
jobs:
publish-tauri:
if: ${{ (startsWith(github.ref, 'refs/tags/nym-connect-s-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }}
strategy:
fail-fast: false
matrix:
platform: [macos-latest]
runs-on: ${{ matrix.platform }}
steps:
- uses: actions/checkout@v2
- name: Node
uses: actions/setup-node@v3
with:
node-version: 18
- name: Install Rust stable
uses: actions-rs/toolchain@v1
with:
toolchain: stable
- name: Install the Apple developer certificate for code signing
env:
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
run: |
# create variables
CERTIFICATE_PATH=$RUNNER_TEMP/build_certificate.p12
KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db
# import certificate and provisioning profile from secrets
echo -n "$APPLE_CERTIFICATE" | base64 --decode --output $CERTIFICATE_PATH
# create temporary keychain
security create-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
security set-keychain-settings -lut 21600 $KEYCHAIN_PATH
security unlock-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
# import certificate to keychain
security import $CERTIFICATE_PATH -P "$APPLE_CERTIFICATE_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH
security list-keychain -d user -s $KEYCHAIN_PATH
- name: Create env file
uses: timheuer/base64-to-file@v1.2
with:
fileName: '.env'
encodedString: ${{ secrets.WALLET_ADMIN_ADDRESS }}
- name: Prepare for build
env:
RELEASE_TAG: ${{ github.ref_name || inputs.release_tag }}
run: ./scripts/pre_medium_build.sh
- name: Install app dependencies and build it
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
ENABLE_CODE_SIGNING: ${{ secrets.APPLE_CERTIFICATE }}
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_IDENTITY_ID }}
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
NYM_CONNECT_ENABLE_MEDIUM: 1
run: yarn && yarn build
- name: Upload Artifact
uses: actions/upload-artifact@v3
with:
name: nym-connect-s_1.0.0_x64.dmg
path: nym-connect/desktop/target/release/bundle/dmg/nym-connect-s_1*_x64.dmg
retention-days: 30
- name: Clean up keychain
if: ${{ always() }}
run: |
security delete-keychain $RUNNER_TEMP/app-signing.keychain-db
- id: create-release
name: Upload to release based on tag name
uses: softprops/action-gh-release@v1
if: github.event_name == 'release'
with:
files: |
nym-connect/desktop/target/release/bundle/dmg/*.dmg
nym-connect/desktop/target/release/bundle/macos/*.app.tar.gz*
@@ -1,85 +0,0 @@
name: Publish NymConnect S - desktop (Ubuntu)
on:
workflow_dispatch:
inputs:
release_tag:
required: true
description: Release tag (nym-connect-s-v*)
type: string
default: 'nym-connect-s-v1.0.0'
push:
tags:
- nym-connect-s-v*
defaults:
run:
working-directory: nym-connect/desktop
jobs:
publish-tauri:
if: ${{ (startsWith(github.ref, 'refs/tags/nym-connect-s-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }}
strategy:
fail-fast: false
matrix:
platform: [custom-runner-linux]
runs-on: ${{ matrix.platform }}
steps:
- uses: actions/checkout@v2
- name: Tauri dependencies
run: >
sudo apt-get update &&
sudo apt-get install -y webkit2gtk-4.0 libayatana-appindicator3-dev
continue-on-error: true
- name: Node
uses: actions/setup-node@v3
with:
node-version: 18
- name: Install Rust stable
uses: actions-rs/toolchain@v1
with:
toolchain: stable
- name: Install project dependencies
shell: bash
run: cd .. && yarn --network-timeout 100000
- name: Install app dependencies
run: yarn
- name: Create env file
uses: timheuer/base64-to-file@v1.2
with:
fileName: '.env'
encodedString: ${{ secrets.WALLET_ADMIN_ADDRESS }}
- name: Prepare for build
env:
RELEASE_TAG: ${{ github.ref_name || inputs.release_tag }}
run: ./scripts/pre_medium_build.sh
- name: Build app
run: yarn build
env:
TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
NYM_CONNECT_ENABLE_MEDIUM: 1
- name: Upload Artifact
uses: actions/upload-artifact@v3
with:
name: nym-connect-s.AppImage.tar.gz
path: nym-connect/desktop/target/release/bundle/appimage/nym-connect-s_1*_amd64.AppImage
retention-days: 30
- id: create-release
name: Upload to release based on tag name
uses: softprops/action-gh-release@v1
if: github.event_name == 'release'
with:
files: |
nym-connect/desktop/target/release/bundle/appimage/*.AppImage
nym-connect/desktop/target/release/bundle/appimage/*.AppImage.tar.gz*
@@ -1,104 +0,0 @@
name: Publish Nym Connect - desktop (Windows 10)
on:
workflow_dispatch:
inputs:
release_tag:
required: true
description: Release tag (nym-connect-s-v*)
type: string
default: 'nym-connect-s-v1.0.0'
push:
tags:
- nym-connect-s-v*
defaults:
run:
working-directory: nym-connect/desktop
jobs:
publish-tauri:
if: ${{ (startsWith(github.ref, 'refs/tags/nym-connect-s-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }}
strategy:
fail-fast: false
matrix:
platform: [windows10]
runs-on: ${{ matrix.platform }}
steps:
- name: Clean up first
continue-on-error: true
working-directory: .
run: |
cd ..
del /s /q /A:H nym
rmdir /s /q nym
- uses: actions/checkout@v3
- name: Import signing certificate
env:
WINDOWS_CERTIFICATE: ${{ secrets.WINDOWS_CERTIFICATE }}
WINDOWS_CERTIFICATE_PASSWORD: ${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }}
run: |
New-Item -ItemType directory -Path certificate
Set-Content -Path certificate/tempCert.txt -Value $env:WINDOWS_CERTIFICATE
certutil -decode certificate/tempCert.txt certificate/certificate.pfx
Remove-Item -path certificate -include tempCert.txt
Import-PfxCertificate -FilePath certificate/certificate.pfx -CertStoreLocation Cert:\CurrentUser\My -Password (ConvertTo-SecureString -String $env:WINDOWS_CERTIFICATE_PASSWORD -Force -AsPlainText)
- name: Node
uses: actions/setup-node@v3
with:
node-version: 18
- name: Install Rust stable
uses: actions-rs/toolchain@v1
with:
toolchain: stable
- name: Create env file
uses: timheuer/base64-to-file@v1.2
with:
fileName: '.env'
encodedString: ${{ secrets.WALLET_ADMIN_ADDRESS }}
- name: Install project dependencies
shell: bash
run: cd .. && yarn --network-timeout 100000
- name: Install app dependencies
shell: bash
run: yarn --network-timeout 100000
- name: Prepare for build
env:
RELEASE_TAG: ${{ github.ref_name || inputs.release_tag }}
run: ./scripts/pre_medium_build.sh
- name: Build and sign it
shell: bash
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
ENABLE_CODE_SIGNING: ${{ secrets.WINDOWS_CERTIFICATE }}
WINDOWS_CERTIFICATE: ${{ secrets.WINDOWS_CERTIFICATE }}
WINDOWS_CERTIFICATE_PASSWORD: ${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }}
TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
NYM_CONNECT_ENABLE_MEDIUM: 1
run: yarn build
- name: Upload Artifact
uses: actions/upload-artifact@v3
with:
name: nym-connect-s_1.0.0_x64_en-US.msi
path: nym-connect/desktop/target/release/bundle/msi/nym-connect-s_1*_x64_en-US.msi
retention-days: 30
- id: create-release
name: Upload to release based on tag name
uses: softprops/action-gh-release@v1
if: github.event_name == 'release'
with:
files: |
nym-connect/desktop/target/release/bundle/msi/*.msi
nym-connect/desktop/target/release/bundle/msi/*.msi.zip*
+20 -1
View File
@@ -25,7 +25,7 @@ jobs:
outputs:
release_id: ${{ steps.create-release.outputs.id }}
release_date: ${{ fromJSON(steps.create-release.outputs.assets)[0].published_at }}
release_date: ${{ fromJSON(steps.create-release.outputs.assets)[0].created_at }}
client_hash: ${{ steps.binary-hashes.outputs.client_hash }}
mixnode_hash: ${{ steps.binary-hashes.outputs.mixnode_hash }}
gateway_hash: ${{ steps.binary-hashes.outputs.gateway_hash }}
@@ -40,6 +40,7 @@ jobs:
netreq_version: ${{ steps.binary-versions.outputs.netreq_version }}
cli_version: ${{ steps.binary-versions.outputs.cli_version }}
netstat_version: ${{ steps.binary-versions.outputs.netstat_version }}
platform: ${{ steps.get-platform-version.outputs.platform }}"
steps:
- uses: actions/checkout@v3
@@ -96,6 +97,11 @@ jobs:
target/release/nym-network-statistics
target/release/nym-cli
- id: echo-outputs
name: echo output for assets
run: |
echo "data from release: $ ${{ steps.create-release.outputs }}"
- id: release-info
name: Prepare release info
run: |
@@ -124,6 +130,12 @@ jobs:
v=$(rg '^version = "(.*)"' -or '$1' tools/nym-cli/Cargo.toml) && echo "cli_version=$v" >> "$GITHUB_OUTPUT"
v=$(rg '^version = "(.*)"' -or '$1' service-providers/network-statistics/Cargo.toml) && echo "netstat_version=$v" >> "$GITHUB_OUTPUT"
- id: get-platform-version
name: get platform version
run: |
echo "::set-output name=platform::$(uname -r)"
push-release-data-client:
if: ${{ (startsWith(github.ref, 'refs/tags/nym-binaries-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }}
uses: ./.github/workflows/push-release-data.yml
@@ -139,6 +151,7 @@ jobs:
file_hash: ${{ needs.publish-nym.outputs.client_hash }}
name: Client
category: binaries
platform: "${{ needs.publish-nym.outputs.platform }}"
secrets: inherit
push-release-data-mixnode:
@@ -156,6 +169,7 @@ jobs:
file_hash: ${{ needs.publish-nym.outputs.mixnode_hash }}
name: Mixnode
category: binaries
platform: "${{ needs.publish-nym.outputs.platform }}"
secrets: inherit
push-release-data-gateway:
@@ -173,6 +187,7 @@ jobs:
file_hash: ${{ needs.publish-nym.outputs.gateway_hash }}
name: Gateway
category: binaries
platform: "${{ needs.publish-nym.outputs.platform }}"
secrets: inherit
push-release-data-socks5:
@@ -190,6 +205,7 @@ jobs:
file_hash: ${{ needs.publish-nym.outputs.socks5_hash }}
name: Socks5 Client
category: binaries
platform: "${{ needs.publish-nym.outputs.platform }}"
secrets: inherit
push-release-data-network-requester:
@@ -207,6 +223,7 @@ jobs:
file_hash: ${{ needs.publish-nym.outputs.netreq_hash }}
name: Network Requester
category: binaries
platform: "${{ needs.publish-nym.outputs.platform }}"
secrets: inherit
push-release-data-cli:
@@ -224,6 +241,7 @@ jobs:
file_hash: ${{ needs.publish-nym.outputs.cli_hash }}
name: Cli
category: binaries
platform: "${{ needs.publish-nym.outputs.platform }}"
secrets: inherit
push-release-data-network-stat:
@@ -241,4 +259,5 @@ jobs:
file_hash: ${{ needs.publish-nym.outputs.netstat_hash }}
name: Network Statistics
category: binaries
platform: "${{ needs.publish-nym.outputs.platform }}"
secrets: inherit
@@ -19,7 +19,7 @@ jobs:
outputs:
release_id: ${{ steps.create-release.outputs.id }}
release_date: ${{ fromJSON(steps.create-release.outputs.assets)[0].published_at }}
release_date: ${{ fromJSON(steps.create-release.outputs.assets)[0].created_at }}
version: ${{ steps.release-info.outputs.version }}
filename: ${{ steps.release-info.outputs.filename }}
file_hash: ${{ steps.release-info.outputs.file_hash }}
@@ -99,12 +99,14 @@ jobs:
files: |
nym-wallet/target/release/bundle/dmg/*.dmg
nym-wallet/target/release/bundle/macos/*.app.tar.gz*
- id: release-info
name: Prepare release info
run: |
semver="${${{ github.ref_name }}##nym-wallet-}" && semver="${semver##v}"
echo "version=$semver" >> "$GITHUB_OUTPUT"
echo "filename=nym-wallet_$version_x64.dmg" >> "$GITHUB_OUTPUT"
ref=${{ github.ref_name }}
semver="${ref##nym-wallet-}" && semver="${semver##v}"
echo "version=${semver}" >> "$GITHUB_OUTPUT"
echo "filename=nym-wallet_${semver}_x64.dmg" >> "$GITHUB_OUTPUT"
echo "file_hash=${{ hashFiles('nym-wallet/target/release/bundle/dmg/nym-wallet_*_x64.dmg') }}" >> "$GITHUB_OUTPUT"
push-release-data:
@@ -19,7 +19,7 @@ jobs:
outputs:
release_id: ${{ steps.create-release.outputs.id }}
release_date: ${{ fromJSON(steps.create-release.outputs.assets)[0].published_at }}
release_date: ${{ fromJSON(steps.create-release.outputs.assets)[0].created_at }}
version: ${{ steps.release-info.outputs.version }}
filename: ${{ steps.release-info.outputs.filename }}
file_hash: ${{ steps.release-info.outputs.file_hash }}
@@ -61,6 +61,13 @@ jobs:
TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
- name: Upload Artifact
uses: actions/upload-artifact@v3
with:
name: nym-wallet_1.0.0_amd64.AppImage.tar.gz
path: nym-wallet/target/release/bundle/appimage/nym-wallet*.AppImage.tar.gz
retention-days: 30
- id: create-release
name: Upload to release based on tag name
uses: softprops/action-gh-release@v1
@@ -73,9 +80,10 @@ jobs:
- id: release-info
name: Prepare release info
run: |
semver="${${{ github.ref_name }}##nym-wallet-}" && semver="${semver##v}"
echo "version=$semver" >> "$GITHUB_OUTPUT"
echo "filename=nym-wallet_$version_amd64.AppImage" >> "$GITHUB_OUTPUT"
ref=${{ github.ref_name }}
semver="${ref##nym-wallet-}" && semver="${semver##v}"
echo "version=${semver}" >> "$GITHUB_OUTPUT"
echo "filename=nym-wallet_${semver}_amd64.AppImage" >> "$GITHUB_OUTPUT"
echo "file_hash=${{ hashFiles('nym-wallet/target/release/bundle/appimage/nym-wallet_*_amd64.AppImage') }}" >> "$GITHUB_OUTPUT"
push-release-data:
@@ -19,7 +19,7 @@ jobs:
outputs:
release_id: ${{ steps.create-release.outputs.id }}
release_date: ${{ fromJSON(steps.create-release.outputs.assets)[0].published_at }}
release_date: ${{ fromJSON(steps.create-release.outputs.assets)[0].created_at }}
version: ${{ steps.release-info.outputs.version }}
filename: ${{ steps.release-info.outputs.filename }}
file_hash: ${{ steps.release-info.outputs.file_hash }}
@@ -96,12 +96,14 @@ jobs:
files: |
nym-wallet/target/release/bundle/msi/*.msi
nym-wallet/target/release/bundle/msi/*.msi.zip*
- id: release-info
name: Prepare release info
run: |
semver="${${{ github.ref_name }}##nym-wallet-}" && semver="${semver##v}"
echo "version=$semver" >> "$GITHUB_OUTPUT"
echo "filename=nym-wallet_$version_x64_en-US.msi" >> "$GITHUB_OUTPUT"
ref=${{ github.ref_name }}
semver="${ref##nym-wallet-}" && semver="${semver##v}"
echo "version=${semver}" >> "$GITHUB_OUTPUT"
echo "filename=nym-wallet_${semver}_x64_en-US.msi" >> "$GITHUB_OUTPUT"
echo "file_hash=${{ hashFiles('nym-wallet/target/release/bundle/msi/nym-wallet_*_x64_en-US.msi') }}" >> "$GITHUB_OUTPUT"
push-release-data:
+1 -1
View File
@@ -32,5 +32,5 @@ jobs:
run: yarn
- name: Run tests
run: yarn test:qa
run: yarn test:sandbox
working-directory: nym-api/tests
+50
View File
@@ -0,0 +1,50 @@
name: Typescript SDK docs
on:
push:
paths:
- "sdk/typescript/**"
pull_request:
paths:
- "sdk/typescript/**"
jobs:
build:
runs-on: custom-runner-linux
steps:
- uses: actions/checkout@v2
- name: Install rsync
run: sudo apt-get install rsync
continue-on-error: true
- uses: rlespinasse/github-slug-action@v3.x
- uses: actions/setup-node@v3
with:
node-version: 18
- name: Install Rust stable
uses: actions-rs/toolchain@v1
with:
toolchain: stable
- name: Setup yarn
run: npm install -g yarn
- name: Install
run: yarn
- name: Matrix - Node Install
run: npm install
working-directory: .github/workflows/support-files
- name: Matrix - Send Notification
env:
NYM_NOTIFICATION_KIND: ts-packages
NYM_PROJECT_NAME: "ts-packages"
NYM_CI_WWW_BASE: "${{ secrets.NYM_CI_WWW_BASE }}"
NYM_CI_WWW_LOCATION: "ts-${{ env.GITHUB_REF_SLUG }}"
GIT_COMMIT_MESSAGE: "${{ github.event.head_commit.message }}"
GIT_BRANCH: "${GITHUB_REF##*/}"
IS_SUCCESS: "${{ job.status == 'success' }}"
MATRIX_SERVER: "${{ secrets.MATRIX_SERVER }}"
MATRIX_ROOM: "${{ secrets.MATRIX_ROOM }}"
MATRIX_USER_ID: "${{ secrets.MATRIX_USER_ID }}"
MATRIX_TOKEN: "${{ secrets.MATRIX_TOKEN }}"
MATRIX_DEVICE_ID: "${{ secrets.MATRIX_DEVICE_ID }}"
uses: docker://keybaseio/client:stable-node
with:
args: .github/workflows/support-files/notifications/entry_point.sh
-4
View File
@@ -7,8 +7,6 @@ on:
- "sdk/typescript/**"
- "nym-connect/desktop/src/**"
- "nym-connect/desktop/package.json"
- "nym-connect/mobile/src/**"
- "nym-connect/mobile/package.json"
- "nym-wallet/src/**"
- "nym-wallet/package.json"
- "explorer/**"
@@ -18,8 +16,6 @@ on:
- "sdk/typescript/**"
- "nym-connect/desktop/src/**"
- "nym-connect/desktop/package.json"
- "nym-connect/mobile/src/**"
- "nym-connect/mobile/package.json"
- "nym-wallet/src/**"
- "nym-wallet/package.json"
- "explorer/**"
-79
View File
@@ -1,79 +0,0 @@
name: Upload nyxd to CI
on:
workflow_dispatch:
jobs:
publish-nyxd:
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/nyxd
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 build-essential curl wget libssl-dev libgtk-3-dev libudev-dev squashfs-tools git
continue-on-error: true
- name: Update env variables to include go
run: |
sudo rm -rf /usr/local/go
curl https://dl.google.com/go/go1.19.2.linux-amd64.tar.gz | sudo tar -C/usr/local -zxvf -
cat <<'EOF' >>$HOME/.profile
export GOROOT=/usr/local/go
export GOPATH=$HOME/go
export GO111MODULE=on
export PATH=$PATH:/usr/local/go/bin:$HOME/go/bin
EOF
source $HOME/.profile
- name: Verify Go is installed
run: go version
- name: Clone nyxd repo
run: |
git clone https://github.com/tommyv1987/nyxd
cd nyxd
git checkout release/v0.30.2
- name: Run nyxd
run: |
pwd
cd nyxd && make build
sleep 10
ls /home/runner/work/nym/nym/nyxd/build
- name: Prepare build output
shell: bash
env:
OUTPUT_DIR: ci-builds/nyxd
run: |
cp /home/runner/work/nym/nym/nyxd/build/nyxd $OUTPUT_DIR
WASMVM_SO=$(ldd /home/runner/work/nym/nym/nyxd/build/nyxd | grep "libwasm*" | awk '{ print $3 }')
ls $WASMVM_SO
sleep 3
cp $(echo $WASMVM_SO) $OUTPUT_DIR
- name: Deploy nyxd 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/"
+1 -1
View File
@@ -31,7 +31,7 @@ jobs:
uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
toolchain: 1.71.0
override: true
components: rustfmt, clippy
+49
View File
@@ -4,6 +4,55 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
## [Unreleased]
## [1.1.28] (2023-08-22)
- [final step3]: add [rust] support to nyxd client in wasm ([#3743])
- Feature/ephemera upgrade ([#3791])
- [rust-sdk] feat: make it more convenient to send and receive messages in different tasks ([#3756])
- feat: validator client refactoring + wasm compatible nyxd client ([#3726])
- feat: retain connection between client init and run ([#3767])
[#3743]: https://github.com/nymtech/nym/issues/3743
[#3791]: https://github.com/nymtech/nym/pull/3791
[#3756]: https://github.com/nymtech/nym/pull/3756
[#3726]: https://github.com/nymtech/nym/pull/3726
[#3767]: https://github.com/nymtech/nym/pull/3767
## [1.1.27] (2023-08-16)
- fix serialisation of contract types ([#3752])
- Investigate spending credentials from the main API (coconut enabled to a gateway) from feature/ephemera branch ([#3741])
- NymConnect UI stuck in showing "Gateway has issues" ([#3594])
- [UPDATE] Update MiniBolt community-applications-and-guides dev docs ([#3754])
[#3752]: https://github.com/nymtech/nym/issues/3752
[#3741]: https://github.com/nymtech/nym/issues/3741
[#3594]: https://github.com/nymtech/nym/issues/3594
[#3754]: https://github.com/nymtech/nym/pull/3754
## [v1.1.24] (2023-08-08)
- Latency based gateway selection is serial and slow ([#3710])
- Network-requester: strip comments from allow lists ([#3625])
- Remove (or start maintaining) `upgrade` commands from all binaries ([#3600])
- Set sphinx as default packet type ([#3748])
- Apply fix from feature/ephemera to develop too (#3698) ([#3742])
- Feature/coco demos ([#3732])
- Add updates to community list projects ([#3722])
- Add geo-aware mixnet topology provider ([#3713])
- Add updates to community list projects ([#3711])
[#3710]: https://github.com/nymtech/nym/issues/3710
[#3625]: https://github.com/nymtech/nym/issues/3625
[#3600]: https://github.com/nymtech/nym/issues/3600
[#3748]: https://github.com/nymtech/nym/pull/3748
[#3742]: https://github.com/nymtech/nym/pull/3742
[#3732]: https://github.com/nymtech/nym/pull/3732
[#3722]: https://github.com/nymtech/nym/pull/3722
[#3713]: https://github.com/nymtech/nym/pull/3713
[#3711]: https://github.com/nymtech/nym/pull/3711
## [v1.1.23] (2023-07-04)
- nym-cli: add client identity key signing support ([#3576])
Generated
+1653 -926
View File
File diff suppressed because it is too large Load Diff
+25 -14
View File
@@ -17,7 +17,6 @@ opt-level = 3
resolver = "2"
members = [
"clients/credential",
"clients/native",
"clients/native/websocket-requests",
"clients/socks5",
@@ -43,6 +42,7 @@ members = [
"common/cosmwasm-smart-contracts/vesting-contract",
"common/credential-storage",
"common/credentials",
"common/credential-utils",
"common/crypto",
"common/dkg",
"common/execute",
@@ -75,6 +75,7 @@ members = [
"common/types",
"common/wasm-utils",
"explorer-api",
"explorer-api/explorer-api-requests",
"gateway",
"gateway/gateway-requests",
"integrations/bity",
@@ -118,30 +119,40 @@ anyhow = "1.0.71"
async-trait = "0.1.64"
bip39 = { version = "2.0.0", features = ["zeroize"] }
cfg-if = "1.0.0"
cosmwasm-derive = "=1.2.5"
cosmwasm-schema = "=1.2.5"
cosmwasm-std = "=1.2.5"
cosmwasm-storage = "=1.2.5"
cosmrs = "=0.8.0"
cosmwasm-derive = "=1.3.0"
cosmwasm-schema = "=1.3.0"
cosmwasm-std = "=1.3.0"
# use 0.5.0 as that's the version used by cosmwasm-std 1.3.0
# (and ideally we don't want to pull the same dependency twice)
serde-json-wasm = "=0.5.0"
cosmwasm-storage = "=1.3.0"
cosmrs = "=0.14.0"
# same version as used by cosmrs
cw-utils = "=1.0.1"
cw-storage-plus = "=1.0.1"
cw2 = { version = "=1.0.1" }
cw3 = { version = "=1.0.1" }
cw3-fixed-multisig = { version = "=1.0.1" }
cw4 = { version = "=1.0.1" }
cw-controllers = { version = "=1.0.1" }
cw-storage-plus = "=1.1.0"
cw2 = { version = "=1.1.0" }
cw3 = { version = "=1.1.0" }
cw4 = { version = "=1.1.0" }
cw-controllers = { version = "=1.1.0" }
dotenvy = "0.15.6"
futures = "0.3.28"
generic-array = "0.14.7"
k256 = "0.11"
getrandom = "0.2.10"
k256 = "0.13"
lazy_static = "1.4.0"
log = "0.4"
once_cell = "1.7.2"
rand = "0.8.5"
reqwest = "0.11.18"
serde = "1.0.152"
serde_json = "1.0.91"
tap = "1.0.1"
tendermint-rpc = "0.32" # same version as used by cosmrs
thiserror = "1.0.38"
tokio = "1.24.1"
url = "2.2"
ts-rs = "7.0.0"
url = "2.4"
zeroize = "1.6.0"
# wasm-related dependencies
wasmtimer = "0.2.0"
+5 -5
View File
@@ -73,13 +73,10 @@ endef
# Generate targets for the various cargo workspaces
$(eval $(call add_cargo_workspace,main,.))
$(eval $(call add_cargo_workspace,contracts,contracts,--target wasm32-unknown-unknown))
$(eval $(call add_cargo_workspace,contracts,contracts,--lib --target wasm32-unknown-unknown))
$(eval $(call add_cargo_workspace,wasm-client,clients/webassembly,--target wasm32-unknown-unknown))
$(eval $(call add_cargo_workspace,wallet,nym-wallet,))
$(eval $(call add_cargo_workspace,connect,nym-connect/desktop))
ifdef NYM_MOBILE
$(eval $(call add_cargo_workspace,connect-mobile,nym-connect/mobile/src-tauri))
endif
# -----------------------------------------------------------------------------
# Convenience targets for crates that are already part of the main workspace
@@ -104,7 +101,7 @@ NAME_SERVICE_CONTRACT=$(CONTRACTS_OUT_DIR)/nym_name_service.wasm
wasm: wasm-build wasm-opt
wasm-build:
RUSTFLAGS='-C link-arg=-s' cargo build --manifest-path contracts/Cargo.toml --release --target wasm32-unknown-unknown
RUSTFLAGS='-C link-arg=-s' cargo build --lib --manifest-path contracts/Cargo.toml --release --target wasm32-unknown-unknown
wasm-opt:
wasm-opt --disable-sign-ext -Os $(VESTING_CONTRACT) -o $(VESTING_CONTRACT)
@@ -112,6 +109,9 @@ wasm-opt:
wasm-opt --disable-sign-ext -Os $(SERVICE_PROVIDER_DIRECTORY_CONTRACT) -o $(SERVICE_PROVIDER_DIRECTORY_CONTRACT)
wasm-opt --disable-sign-ext -Os $(NAME_SERVICE_CONTRACT) -o $(NAME_SERVICE_CONTRACT)
contract-schema:
$(MAKE) -C contracts schema
# -----------------------------------------------------------------------------
# Misc
# -----------------------------------------------------------------------------
-32
View File
@@ -1,32 +0,0 @@
<!--
Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
SPDX-License-Identifier: Apache-2.0
-->
## Credential binary
The credential binary is used to acquire coconut bandwidth credentials in exchange for nym tokens. Those credentials are stored in the client's `data` directory, so that they can be used as the client sees fit.
### Warning
The credential binary is still experimental software. The infrastructure for using it is not yet deployed to mainnet and it's still in the process of being deployed to sandbox.
### Building
From the project's root directory, run:
```
cargo build -p nym-credential-client
```
which generates the `nym-credential-client` binary in `target/debug/nym-credential-client`.
### Running
For example, you can get a credential worth 3 nym (3000000 unym) in a socks5 client that was already initialized like so:
```
./target/debug/nym-credential-client --config-env-file envs/sandbox.env --client-home-directory ~/.nym/socks5-clients/cred_client --nyxd-url https://sandbox-validator1.nymtech.net --mnemonic $MNEMONIC --recovery-dir /tmp/recovery --amount 3000000
```
More information regarding how to run the binary can be found by running it with the `--help` argument.
-55
View File
@@ -1,55 +0,0 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::error::Result;
use bip39::Mnemonic;
use nym_network_defaults::{NymNetworkDetails, VOUCHER_INFO};
use nym_validator_client::nyxd;
use nym_validator_client::nyxd::traits::CoconutBandwidthSigningClient;
use nym_validator_client::nyxd::{Coin, DirectSigningNyxdClient, Fee, NyxdClient};
use std::str::FromStr;
use url::Url;
pub(crate) struct Client {
nyxd_client: NyxdClient<DirectSigningNyxdClient>,
mix_denom_base: String,
}
impl Client {
pub fn new(nyxd_url: &str, mnemonic: &str) -> Self {
let nyxd_url = Url::from_str(nyxd_url).unwrap();
let mnemonic = Mnemonic::from_str(mnemonic).unwrap();
let network_details = NymNetworkDetails::new_from_env();
let config = nyxd::Config::try_from_nym_network_details(&network_details)
.expect("failed to construct valid validator client config with the provided network");
let nyxd_client =
NyxdClient::connect_with_mnemonic(config, nyxd_url.as_ref(), mnemonic, None).unwrap();
Client {
nyxd_client,
mix_denom_base: network_details.chain_details.mix_denom.base,
}
}
pub async fn deposit(
&self,
amount: u64,
verification_key: String,
encryption_key: String,
fee: Option<Fee>,
) -> Result<String> {
let amount = Coin::new(amount as u128, self.mix_denom_base.clone());
Ok(self
.nyxd_client
.deposit(
amount,
String::from(VOUCHER_INFO),
verification_key,
encryption_key,
fee,
)
.await?
.transaction_hash
.to_string())
}
}
-82
View File
@@ -1,82 +0,0 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use clap::{ArgGroup, Args, Subcommand};
use log::*;
use nym_bandwidth_controller::acquire::state::State;
use nym_bin_common::completions::ArgShell;
use nym_credential_storage::persistent_storage::PersistentStorage;
use nym_validator_client::nyxd::traits::DkgQueryClient;
use crate::error::Result;
use crate::recovery_storage::RecoveryStorage;
#[derive(Subcommand)]
pub(crate) enum Command {
/// Run the binary to obtain a credential
Run(Run),
/// Generate shell completions
Completions(ArgShell),
/// Generate Fig specification
GenerateFigSpec,
}
#[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)]
pub(crate) client_home_directory: std::path::PathBuf,
/// A mnemonic for the account that buys the credential
#[clap(long)]
pub(crate) mnemonic: String,
/// 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 recover_credentials<C: DkgQueryClient + Send + Sync>(
client: &C,
recovery_storage: &RecoveryStorage,
shared_storage: &PersistentStorage,
) -> Result<()> {
for voucher in recovery_storage.unconsumed_vouchers()? {
let state = State::new(voucher);
if let Err(e) =
nym_bandwidth_controller::acquire::get_credential(&state, client, shared_storage).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(())
}
-36
View File
@@ -1,36 +0,0 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use std::time::SystemTimeError;
use thiserror::Error;
use nym_credential_storage::error::StorageError;
use nym_credentials::error::Error as CredentialError;
use nym_validator_client::nyxd::error::NyxdError;
use nym_validator_client::ValidatorClientError;
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("Bandwidth controller error: {0}")]
BandwidthControllerError(#[from] nym_bandwidth_controller::error::BandwidthControllerError),
#[error("Nyxd error: {0}")]
Nyxd(#[from] NyxdError),
#[error("Validator client error: {0}")]
ValidatorClientError(#[from] ValidatorClientError),
#[error("Credential error: {0}")]
Credential(#[from] CredentialError),
#[error("Could not use shared storage")]
SharedStorageError(#[from] StorageError),
#[error("Could not get system time")]
SysTimeError(#[from] SystemTimeError),
}
-128
View File
@@ -1,128 +0,0 @@
// Copyright 2022-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
mod commands;
mod error;
mod recovery_storage;
use commands::*;
use error::Result;
use log::*;
use nym_bin_common::completions::fig_generate;
use nym_config::DEFAULT_DATA_DIR;
use nym_network_defaults::{setup_env, NymNetworkDetails};
use std::process::exit;
use std::time::{Duration, SystemTime};
use clap::{CommandFactory, Parser};
use nym_bin_common::logging::setup_logging;
use nym_client_core::config::disk_persistence::CommonClientPaths;
use nym_validator_client::nyxd::traits::DkgQueryClient;
use nym_validator_client::nyxd::{Coin, CosmWasmClient};
use nym_validator_client::Config;
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>,
#[clap(subcommand)]
pub(crate) command: Command,
}
async fn block_until_coconut_is_available<C: CosmWasmClient + Send + Sync>(
client: &nym_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);
}
break;
} else {
// Use 1 additional second to not start the next iteration immediately and spam get_current_epoch queries
let secs_until_final = epoch
.final_timestamp_secs()
.saturating_sub(current_timestamp_secs)
+ 1;
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) => {
// we assume the structure of <home-dir>/data
let data_dir = r.client_home_directory.join(DEFAULT_DATA_DIR);
let paths = CommonClientPaths::new_default(data_dir);
let db_path = paths.credentials_database;
let shared_storage =
nym_credential_storage::initialise_persistent_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).expect(
"failed to construct valid validator client config with the provided network",
);
let amount = Coin::new(
r.amount as u128,
network_details.chain_details.mix_denom.base,
);
let client =
nym_validator_client::Client::new_signing(config, r.mnemonic.parse().unwrap())?;
block_until_coconut_is_available(&client).await?;
info!("Starting depositing funds, don't kill the process");
if !r.recovery_mode {
let state =
nym_bandwidth_controller::acquire::deposit(&client.nyxd, amount).await?;
if nym_bandwidth_controller::acquire::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.nyxd, &recovery_storage, &shared_storage).await?;
}
}
Command::Completions(c) => c.generate(&mut Cli::command(), bin_name),
Command::GenerateFigSpec => fig_generate(&mut Cli::command(), bin_name),
}
Ok(())
}
@@ -1,56 +0,0 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use nym_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 -5
View File
@@ -1,6 +1,6 @@
[package]
name = "nym-client"
version = "1.1.23"
version = "1.1.26"
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jędrzej Stuczyński <andrew@nymtech.net>"]
description = "Implementation of the Nym Client"
edition = "2021"
@@ -14,11 +14,11 @@ path = "src/lib.rs"
[dependencies]
# dependencies to review:
futures = "0.3" # bunch of futures stuff, however, now that I think about it, it could perhaps be completely removed
futures = { workspace = true } # bunch of futures stuff, however, now that I think about it, it could perhaps be completely removed
# the AsyncRead, AsyncWrite, Stream, Sink, etc. traits could be used from tokio
# channels should really be replaced with crossbeam due to that implementation being more efficient
# and the single instance of abortable we have should really be refactored anyway
url = "2.2"
url = { workspace = true }
clap = { version = "4.0", features = ["cargo", "derive"] }
dirs = "4.0"
@@ -28,7 +28,7 @@ pretty_env_logger = "0.4" # for formatting log messages
rand = { version = "0.7.3", features = ["wasm-bindgen"] } # rng-related traits + some rng implementation to use
serde = { workspace = true, features = ["derive"] } # for config serialization/deserialization
serde_json = { workspace = true }
thiserror = "1.0.34"
thiserror = { workspace = true }
tap = "1.0.1"
tokio = { version = "1.24.1", features = ["rt-multi-thread", "net", "signal"] } # async runtime
tokio-tungstenite = "0.14" # websocket
@@ -48,7 +48,7 @@ nym-sphinx = { path = "../../common/nymsphinx" }
nym-pemstore = { path = "../../common/pemstore" }
nym-task = { path = "../../common/task" }
nym-topology = { path = "../../common/topology" }
nym-validator-client = { path = "../../common/client-libs/validator-client", features = ["nyxd-client"] }
nym-validator-client = { path = "../../common/client-libs/validator-client", features = ["http-client"] }
nym-client-websocket-requests = { path = "websocket-requests" }
[dev-dependencies]
+2 -3
View File
@@ -19,8 +19,7 @@ use nym_sphinx::anonymous_replies::requests::AnonymousSenderTag;
use nym_sphinx::params::PacketType;
use nym_task::connections::TransmissionLane;
use nym_task::TaskManager;
use nym_validator_client::nyxd::QueryNyxdClient;
use nym_validator_client::Client;
use nym_validator_client::QueryHttpRpcNyxdClient;
use std::error::Error;
use tokio::sync::watch::error::SendError;
@@ -29,7 +28,7 @@ pub use nym_sphinx::receiver::ReconstructedMessage;
pub mod config;
type NativeClientBuilder<'a> = BaseClientBuilder<'a, Client<QueryNyxdClient>, OnDiskPersistent>;
type NativeClientBuilder<'a> = BaseClientBuilder<'a, QueryHttpRpcNyxdClient, OnDiskPersistent>;
pub struct SocketClient {
/// Client configuration options, including, among other things, packet sending rates,
+16
View File
@@ -0,0 +1,16 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use clap::Args;
use nym_bin_common::bin_info_owned;
use nym_bin_common::output_format::OutputFormat;
#[derive(Args)]
pub(crate) struct BuildInfo {
#[clap(short, long, default_value_t = OutputFormat::default())]
output: OutputFormat,
}
pub(crate) fn execute(args: BuildInfo) {
println!("{}", args.output.format(&bin_info_owned!()))
}
+3 -2
View File
@@ -174,14 +174,15 @@ pub(crate) async fn execute(args: &Init) -> Result<(), ClientError> {
let details_store =
OnDiskGatewayDetails::new(&config.storage_paths.common_paths.gateway_details);
let init_details = nym_client_core::init::setup_gateway(
&gateway_setup,
gateway_setup,
&key_store,
&details_store,
register_gateway,
Some(&config.base.client.nym_api_urls),
)
.await
.tap_err(|err| eprintln!("Failed to setup gateway\nError: {err}"))?;
.tap_err(|err| eprintln!("Failed to setup gateway\nError: {err}"))?
.details;
let config_save_location = config.default_location();
config.save_to_default_location().tap_err(|_| {
+15 -7
View File
@@ -10,7 +10,7 @@ use clap::CommandFactory;
use clap::{Parser, Subcommand};
use lazy_static::lazy_static;
use log::{error, info};
use nym_bin_common::build_information::BinaryBuildInformation;
use nym_bin_common::bin_info;
use nym_bin_common::completions::{fig_generate, ArgShell};
use nym_client_core::client::base_client::storage::gateway_details::{
OnDiskGatewayDetails, PersistedGatewayDetails,
@@ -22,12 +22,12 @@ use nym_config::OptionalSet;
use std::error::Error;
use std::net::IpAddr;
pub(crate) mod build_info;
pub(crate) mod init;
pub(crate) mod run;
lazy_static! {
pub static ref PRETTY_BUILD_INFORMATION: String =
BinaryBuildInformation::new(env!("CARGO_PKG_VERSION")).pretty_print();
pub static ref PRETTY_BUILD_INFORMATION: String = bin_info!().pretty_print();
}
// Helper for passing LONG_VERSION to clap
@@ -42,6 +42,10 @@ pub(crate) struct Cli {
#[clap(short, long)]
pub(crate) config_env_file: Option<std::path::PathBuf>,
/// Flag used for disabling the printed banner in tty.
#[clap(long)]
pub(crate) no_banner: bool,
#[clap(subcommand)]
command: Commands,
}
@@ -54,6 +58,9 @@ pub(crate) enum Commands {
/// Run the Nym client with provided configuration client optionally overriding set parameters
Run(run::Run),
/// Show build information of this binary
BuildInfo(build_info::BuildInfo),
/// Generate shell completions
Completions(ArgShell),
@@ -73,12 +80,13 @@ pub(crate) struct OverrideConfig {
enabled_credentials_mode: Option<bool>,
}
pub(crate) async fn execute(args: &Cli) -> Result<(), Box<dyn Error + Send + Sync>> {
pub(crate) async fn execute(args: Cli) -> Result<(), Box<dyn Error + Send + Sync>> {
let bin_name = "nym-native-client";
match &args.command {
Commands::Init(m) => init::execute(m).await?,
Commands::Run(m) => run::execute(m).await?,
match args.command {
Commands::Init(m) => init::execute(&m).await?,
Commands::Run(m) => run::execute(&m).await?,
Commands::BuildInfo(m) => build_info::execute(m),
Commands::Completions(s) => s.generate(&mut Cli::command(), bin_name),
Commands::GenerateFigSpec => fig_generate(&mut Cli::command(), bin_name),
}
+7 -4
View File
@@ -14,10 +14,13 @@ pub mod websocket;
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
setup_logging();
maybe_print_banner(crate_name!(), crate_version!());
let args = commands::Cli::parse();
setup_env(args.config_env_file.as_ref());
commands::execute(&args).await
if !args.no_banner {
maybe_print_banner(crate_name!(), crate_version!());
}
setup_logging();
commands::execute(args).await
}
@@ -105,10 +105,10 @@ impl ClientRequest {
let conn_id_bytes = connection_id.unwrap_or(0).to_be_bytes();
std::iter::once(ClientRequestTag::Send as u8)
.chain(recipient.to_bytes().into_iter()) // will not be length prefixed because the length is constant
.chain(conn_id_bytes.into_iter())
.chain(data_len_bytes.into_iter())
.chain(data.into_iter())
.chain(recipient.to_bytes()) // will not be length prefixed because the length is constant
.chain(conn_id_bytes)
.chain(data_len_bytes)
.chain(data)
.collect()
}
@@ -180,11 +180,11 @@ impl ClientRequest {
let conn_id_bytes = connection_id.unwrap_or(0).to_be_bytes();
std::iter::once(ClientRequestTag::SendAnonymous as u8)
.chain(reply_surbs.to_be_bytes().into_iter())
.chain(recipient.to_bytes().into_iter()) // will not be length prefixed because the length is constant
.chain(conn_id_bytes.into_iter())
.chain(data_len_bytes.into_iter())
.chain(data.into_iter())
.chain(reply_surbs.to_be_bytes())
.chain(recipient.to_bytes()) // will not be length prefixed because the length is constant
.chain(conn_id_bytes)
.chain(data_len_bytes)
.chain(data)
.collect()
}
@@ -258,10 +258,10 @@ impl ClientRequest {
let conn_id_bytes = connection_id.unwrap_or(0).to_be_bytes();
std::iter::once(ClientRequestTag::Reply as u8)
.chain(sender_tag.to_bytes().into_iter())
.chain(conn_id_bytes.into_iter())
.chain(message_len_bytes.into_iter())
.chain(message.into_iter())
.chain(sender_tag.to_bytes())
.chain(conn_id_bytes)
.chain(message_len_bytes)
.chain(message)
.collect()
}
@@ -332,7 +332,7 @@ impl ClientRequest {
fn serialize_closed_connection(connection_id: u64) -> Vec<u8> {
let conn_id_bytes = connection_id.to_be_bytes();
std::iter::once(ClientRequestTag::ClosedConnection as u8)
.chain(conn_id_bytes.into_iter())
.chain(conn_id_bytes)
.collect()
}
@@ -359,7 +359,7 @@ impl ClientRequest {
fn serialize_get_lane_queue_lengths(connection_id: u64) -> Vec<u8> {
let conn_id_bytes = connection_id.to_be_bytes();
std::iter::once(ClientRequestTag::GetLaneQueueLength as u8)
.chain(conn_id_bytes.into_iter())
.chain(conn_id_bytes)
.collect()
}
@@ -67,15 +67,15 @@ impl ServerResponse {
if let Some(sender_tag) = reconstructed_message.sender_tag {
std::iter::once(ServerResponseTag::Received as u8)
.chain(std::iter::once(true as u8))
.chain(sender_tag.to_bytes().into_iter())
.chain(sender_tag.to_bytes())
.chain(message_len_bytes.iter().cloned())
.chain(reconstructed_message.message.into_iter())
.chain(reconstructed_message.message)
.collect()
} else {
std::iter::once(ServerResponseTag::Received as u8)
.chain(std::iter::once(false as u8))
.chain(message_len_bytes.iter().cloned())
.chain(reconstructed_message.message.into_iter())
.chain(reconstructed_message.message)
.collect()
}
}
@@ -149,7 +149,7 @@ impl ServerResponse {
// SELF_ADDRESS_RESPONSE_TAG || self_address
fn serialize_self_address(address: Recipient) -> Vec<u8> {
std::iter::once(ServerResponseTag::SelfAddress as u8)
.chain(address.to_bytes().into_iter())
.chain(address.to_bytes())
.collect()
}
@@ -211,8 +211,8 @@ impl ServerResponse {
let message_len_bytes = (error.message.len() as u64).to_be_bytes();
std::iter::once(ServerResponseTag::Error as u8)
.chain(std::iter::once(error.kind as u8))
.chain(message_len_bytes.into_iter())
.chain(error.message.into_bytes().into_iter())
.chain(message_len_bytes)
.chain(error.message.into_bytes())
.collect()
}
+3 -3
View File
@@ -1,6 +1,6 @@
[package]
name = "nym-socks5-client"
version = "1.1.23"
version = "1.1.26"
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"
@@ -14,9 +14,9 @@ pretty_env_logger = "0.4"
serde = { workspace = true, features = ["derive"] } # for config serialization/deserialization
serde_json = { workspace = true }
tap = "1.0.1"
thiserror = "1.0.34"
thiserror = { workspace = true }
tokio = { version = "1.24.1", features = ["rt-multi-thread", "net", "signal"] }
url = "2.2"
url = { workspace = true }
# internal
nym-bin-common = { path = "../../common/bin-common", features = ["output_format"] }
+16
View File
@@ -0,0 +1,16 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use clap::Args;
use nym_bin_common::bin_info_owned;
use nym_bin_common::output_format::OutputFormat;
#[derive(Args)]
pub(crate) struct BuildInfo {
#[clap(short, long, default_value_t = OutputFormat::default())]
output: OutputFormat,
}
pub(crate) fn execute(args: BuildInfo) {
println!("{}", args.output.format(&bin_info_owned!()))
}
+4 -2
View File
@@ -94,6 +94,7 @@ impl From<Init> for OverrideConfig {
use_anonymous_replies: init_config.use_reply_surbs,
fastmode: init_config.fastmode,
no_cover: init_config.no_cover,
geo_routing: None,
medium_toggle: false,
nyxd_urls: init_config.nyxd_urls,
enabled_credentials_mode: init_config.enabled_credentials_mode,
@@ -185,14 +186,15 @@ pub(crate) async fn execute(args: &Init) -> Result<(), Socks5ClientError> {
let details_store =
OnDiskGatewayDetails::new(&config.storage_paths.common_paths.gateway_details);
let init_details = nym_client_core::init::setup_gateway(
&gateway_setup,
gateway_setup,
&key_store,
&details_store,
register_gateway,
Some(&config.core.base.client.nym_api_urls),
)
.await
.tap_err(|err| eprintln!("Failed to setup gateway\nError: {err}"))?;
.tap_err(|err| eprintln!("Failed to setup gateway\nError: {err}"))?
.details;
// TODO: ask the service provider we specified for its interface version and set it in the config
+37 -8
View File
@@ -10,24 +10,25 @@ use clap::CommandFactory;
use clap::{Parser, Subcommand};
use lazy_static::lazy_static;
use log::{error, info};
use nym_bin_common::build_information::BinaryBuildInformation;
use nym_bin_common::bin_info;
use nym_bin_common::completions::{fig_generate, ArgShell};
use nym_client_core::client::base_client::storage::gateway_details::{
OnDiskGatewayDetails, PersistedGatewayDetails,
};
use nym_client_core::client::key_manager::persistence::OnDiskKeys;
use nym_client_core::config::GatewayEndpointConfig;
use nym_client_core::client::topology_control::geo_aware_provider::CountryGroup;
use nym_client_core::config::{GatewayEndpointConfig, GroupBy, TopologyStructure};
use nym_client_core::error::ClientCoreError;
use nym_config::OptionalSet;
use nym_sphinx::params::{PacketSize, PacketType};
use std::error::Error;
pub(crate) mod build_info;
pub mod init;
pub(crate) mod run;
lazy_static! {
pub static ref PRETTY_BUILD_INFORMATION: String =
BinaryBuildInformation::new(env!("CARGO_PKG_VERSION")).pretty_print();
pub static ref PRETTY_BUILD_INFORMATION: String = bin_info!().pretty_print();
}
// Helper for passing LONG_VERSION to clap
@@ -42,6 +43,10 @@ pub(crate) struct Cli {
#[clap(short, long)]
pub(crate) config_env_file: Option<std::path::PathBuf>,
/// Flag used for disabling the printed banner in tty.
#[clap(long)]
pub(crate) no_banner: bool,
#[clap(subcommand)]
command: Commands,
}
@@ -54,6 +59,9 @@ pub(crate) enum Commands {
/// Run the Nym client with provided configuration client optionally overriding set parameters
Run(run::Run),
/// Show build information of this binary
BuildInfo(build_info::BuildInfo),
/// Generate shell completions
Completions(ArgShell),
@@ -68,18 +76,20 @@ pub(crate) struct OverrideConfig {
use_anonymous_replies: Option<bool>,
fastmode: bool,
no_cover: bool,
geo_routing: Option<CountryGroup>,
medium_toggle: bool,
nyxd_urls: Option<Vec<url::Url>>,
enabled_credentials_mode: Option<bool>,
outfox: bool,
}
pub(crate) async fn execute(args: &Cli) -> Result<(), Box<dyn Error + Send + Sync>> {
pub(crate) async fn execute(args: Cli) -> Result<(), Box<dyn Error + Send + Sync>> {
let bin_name = "nym-socks5-client";
match &args.command {
Commands::Init(m) => init::execute(m).await?,
Commands::Run(m) => run::execute(m).await?,
match args.command {
Commands::Init(m) => init::execute(&m).await?,
Commands::Run(m) => run::execute(&m).await?,
Commands::BuildInfo(m) => build_info::execute(m),
Commands::Completions(s) => s.generate(&mut Cli::command(), bin_name),
Commands::GenerateFigSpec => fig_generate(&mut Cli::command(), bin_name),
}
@@ -91,6 +101,21 @@ pub(crate) fn override_config(config: Config, args: OverrideConfig) -> Config {
let secondary_packet_size = args.medium_toggle.then_some(PacketSize::ExtendedPacket16);
let no_per_hop_delays = args.medium_toggle;
let topology_structure = if args.medium_toggle {
// Use the location of the network-requester
let address = config
.core
.socks5
.provider_mix_address
.parse()
.expect("failed to parse provider mix address");
TopologyStructure::GeoAware(GroupBy::NymAddress(address))
} else if let Some(code) = args.geo_routing {
TopologyStructure::GeoAware(GroupBy::CountryGroup(code))
} else {
TopologyStructure::default()
};
let packet_type = if args.outfox {
PacketType::Outfox
} else {
@@ -114,6 +139,10 @@ pub(crate) fn override_config(config: Config, args: OverrideConfig) -> Config {
// NOTE: see comment above about the order of the other disble cover traffic config
.with_base(BaseClientConfig::with_disabled_cover_traffic, args.no_cover)
.with_base(BaseClientConfig::with_packet_type, packet_type)
.with_base(
BaseClientConfig::with_topology_structure,
topology_structure,
)
.with_optional(Config::with_anonymous_replies, args.use_anonymous_replies)
.with_optional(Config::with_port, args.port)
.with_optional_base_custom_env(
+13
View File
@@ -11,6 +11,7 @@ use clap::Args;
use log::*;
use nym_bin_common::version_checker::is_minor_version_compatible;
use nym_client_core::client::base_client::storage::OnDiskPersistent;
use nym_client_core::client::topology_control::geo_aware_provider::CountryGroup;
use nym_crypto::asymmetric::identity;
use nym_socks5_client_core::NymClient;
use nym_sphinx::addressing::clients::Recipient;
@@ -60,6 +61,10 @@ pub(crate) struct Run {
#[clap(long, hide = true)]
no_cover: bool,
/// Set geo-aware mixnode selection when sending mixnet traffic, for experiments only.
#[clap(long, hide = true, value_parser = validate_country_group)]
geo_routing: Option<CountryGroup>,
/// Enable medium mixnet traffic, for experiments only.
/// This includes things like disabling cover traffic, no per hop delays, etc.
#[clap(long, hide = true)]
@@ -82,6 +87,7 @@ impl From<Run> for OverrideConfig {
use_anonymous_replies: run_config.use_anonymous_replies,
fastmode: run_config.fastmode,
no_cover: run_config.no_cover,
geo_routing: run_config.geo_routing,
medium_toggle: run_config.medium_toggle,
nyxd_urls: run_config.nyxd_urls,
enabled_credentials_mode: run_config.enabled_credentials_mode,
@@ -90,6 +96,13 @@ impl From<Run> for OverrideConfig {
}
}
fn validate_country_group(s: &str) -> Result<CountryGroup, String> {
match s.parse() {
Ok(cg) => Ok(cg),
Err(_) => Err(format!("failed to parse country group: {}", s)),
}
}
// this only checks compatibility between config the binary. It does not take into consideration
// network version. It might do so in the future.
fn version_check(cfg: &Config) -> bool {
+7 -4
View File
@@ -13,10 +13,13 @@ pub mod error;
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
setup_logging();
maybe_print_banner(crate_name!(), crate_version!());
let args = commands::Cli::parse();
setup_env(args.config_env_file.as_ref());
commands::execute(&args).await
if !args.no_banner {
maybe_print_banner(crate_name!(), crate_version!());
}
setup_logging();
commands::execute(args).await
}
+756 -612
View File
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -3,7 +3,7 @@ name = "nym-client-wasm"
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jedrzej Stuczynski <andrew@nymtech.net>"]
version = "1.1.1"
edition = "2021"
keywords = ["nym", "sphinx", "wasm", "webassembly", "privacy", "client"]
keywords = ["nym", "sphinx", "wasm", "webassembly", "privacy"]
license = "Apache-2.0"
repository = "https://github.com/nymtech/nym"
description = "A webassembly client which can be used to interact with the the Nym privacy platform. Wasm is used for Sphinx packet generation."
@@ -33,7 +33,7 @@ wasm-bindgen-futures = "0.4"
thiserror = "1.0.40"
zeroize = "1.6.0"
wasm-timer = { git = "https://github.com/mmsinclair/wasm-timer", rev = "b9d1a54ad514c2f230a026afe0dde341e98cd7b6"}
wasmtimer = { version = "0.2.0", features = ["tokio"] }
# internal
nym-node-tester-utils = { path = "../../common/node-tester-utils" }
+1
View File
@@ -246,6 +246,7 @@ impl From<TopologyWasm> for ConfigTopology {
topology.topology_resolution_timeout_ms,
),
disable_refreshing: topology.disable_refreshing,
topology_structure: Default::default(),
}
}
}
+2 -2
View File
@@ -114,7 +114,7 @@ impl WasmTopologyExt for Arc<ClientState> {
let this = Arc::clone(self);
future_to_promise(async move {
let Some(current_topology) = this.topology_accessor.current_topology().await else {
return Err(WasmClientError::UnavailableNetworkTopology.into())
return Err(WasmClientError::UnavailableNetworkTopology.into());
};
match current_topology.find_mix_by_identity(&mixnode_identity) {
@@ -135,7 +135,7 @@ impl WasmTopologyExt for Arc<ClientState> {
let this = Arc::clone(self);
future_to_promise(async move {
let Some(current_topology) = this.topology_accessor.current_topology().await else {
return Err(WasmClientError::UnavailableNetworkTopology.into())
return Err(WasmClientError::UnavailableNetworkTopology.into());
};
let Some(mix) = current_topology.find_mix_by_identity(&mixnode_identity) else {
+2 -2
View File
@@ -14,7 +14,6 @@ use crate::storage::traits::FullWasmClientStorage;
use crate::storage::ClientStorage;
use crate::topology::WasmNymTopology;
use js_sys::Promise;
use nym_bandwidth_controller::wasm_mockups::{Client as FakeClient, DirectSigningNyxdClient};
use nym_client_core::client::base_client::{
BaseClientBuilder, ClientInput, ClientOutput, ClientState,
};
@@ -26,6 +25,7 @@ use nym_task::TaskManager;
use nym_topology::provider_trait::{HardcodedTopologyProvider, TopologyProvider};
use nym_topology::NymTopology;
use nym_validator_client::client::IdentityKey;
use nym_validator_client::QueryReqwestRpcNyxdClient;
use rand::rngs::OsRng;
use rand::RngCore;
use std::sync::Arc;
@@ -152,7 +152,7 @@ impl NymClientBuilder {
let maybe_topology_provider = self.topology_provider();
let mut base_builder: BaseClientBuilder<_, FullWasmClientStorage> =
BaseClientBuilder::<FakeClient<DirectSigningNyxdClient>, _>::new(
BaseClientBuilder::<QueryReqwestRpcNyxdClient, _>::new(
&self.config.base,
storage,
None,
@@ -52,7 +52,7 @@ pub fn encode_payload_with_headers(
Ok(metadata) => {
let metadata = metadata.as_bytes().to_vec();
let size = (metadata.len() as u64).to_be_bytes().to_vec();
Ok(vec![size, metadata, payload].concat())
Ok([size, metadata, payload].concat())
}
Err(e) => Err(JsValue::from(JsError::new(
format!("Could not encode message: {}", e).as_str(),
+5 -5
View File
@@ -8,7 +8,7 @@ use js_sys::Promise;
use nym_client_core::client::replies::reply_storage::browser_backend;
use nym_client_core::config;
use nym_client_core::init::helpers::current_gateways;
use nym_client_core::init::{setup_gateway_from, GatewaySetup, InitialisationDetails};
use nym_client_core::init::{setup_gateway_from, GatewaySetup, InitialisationResult};
use nym_sphinx::addressing::clients::Recipient;
use nym_sphinx::anonymous_replies::requests::AnonymousSenderTag;
use nym_topology::{gateway, NymTopology};
@@ -82,14 +82,14 @@ async fn setup_gateway(
client_store: &ClientStorage,
chosen_gateway: Option<IdentityKey>,
gateways: &[gateway::Node],
) -> Result<InitialisationDetails, WasmClientError> {
) -> Result<InitialisationResult, WasmClientError> {
let setup = if client_store.has_full_gateway_info().await? {
GatewaySetup::MustLoad
} else {
GatewaySetup::new_fresh(chosen_gateway.clone(), None)
};
setup_gateway_from(&setup, client_store, client_store, false, Some(gateways))
setup_gateway_from(setup, client_store, client_store, false, Some(gateways))
.await
.map_err(Into::into)
}
@@ -98,7 +98,7 @@ pub(crate) async fn setup_gateway_from_api(
client_store: &ClientStorage,
chosen_gateway: Option<IdentityKey>,
nym_apis: &[Url],
) -> Result<InitialisationDetails, WasmClientError> {
) -> Result<InitialisationResult, WasmClientError> {
let mut rng = thread_rng();
let gateways = current_gateways(&mut rng, nym_apis).await?;
setup_gateway(client_store, chosen_gateway, &gateways).await
@@ -108,7 +108,7 @@ pub(crate) async fn setup_from_topology(
explicit_gateway: Option<IdentityKey>,
topology: &NymTopology,
client_store: &ClientStorage,
) -> Result<InitialisationDetails, WasmClientError> {
) -> Result<InitialisationResult, WasmClientError> {
let gateways = topology.gateways();
setup_gateway(client_store, explicit_gateway, gateways).await
}
+4
View File
@@ -1,6 +1,10 @@
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
// After reading https://github.com/rust-lang/rust-clippy/issues/11382
// I suspect we *maybe* have hit a false positive, but I'm not sure.
#![allow(clippy::arc_with_non_send_sync)]
use wasm_bindgen::prelude::*;
#[cfg(target_arch = "wasm32")]
@@ -10,6 +10,7 @@ use std::collections::HashSet;
use std::time::Duration;
use tokio::sync::MutexGuard as AsyncMutexGuard;
use wasm_utils::{console_error, console_log, console_warn};
use wasmtimer::tokio::sleep;
pub(crate) struct EphemeralTestReceiver<'a> {
sent_packets: u32,
@@ -57,7 +58,7 @@ impl<'a> EphemeralTestReceiver<'a> {
let Some(received_packet) = packet else {
// can't do anything more...
console_error!("packet receiver has stopped processing results!");
return true
return true;
};
match received_packet {
Received::Message(msg) => {
@@ -90,7 +91,7 @@ impl<'a> EphemeralTestReceiver<'a> {
}
pub(crate) async fn perform_test(mut self) -> NodeTestResult {
let mut timeout_fut = wasm_timer::Delay::new(self.timeout_duration);
let mut timeout_fut = sleep(self.timeout_duration);
loop {
tokio::select! {
+31 -21
View File
@@ -12,10 +12,9 @@ use crate::tester::helpers::{
use crate::topology::WasmNymTopology;
use futures::channel::mpsc;
use js_sys::Promise;
use nym_bandwidth_controller::wasm_mockups::{Client as FakeClient, DirectSigningNyxdClient};
use nym_bandwidth_controller::BandwidthController;
use nym_client_core::client::key_manager::ManagedKeys;
use nym_client_core::init::InitialisationDetails;
use nym_client_core::init::{InitialisationDetails, InitialisationResult};
use nym_credential_storage::ephemeral_storage::EphemeralStorage;
use nym_gateway_client::GatewayClient;
use nym_node_tester_utils::receiver::SimpleMessageReceiver;
@@ -27,6 +26,7 @@ use nym_sphinx::preparer::PreparedFragment;
use nym_task::TaskManager;
use nym_topology::NymTopology;
use nym_validator_client::client::IdentityKey;
use nym_validator_client::QueryReqwestRpcNyxdClient;
use rand::rngs::OsRng;
use std::collections::HashSet;
use std::sync::atomic::{AtomicBool, AtomicU32, Ordering};
@@ -42,7 +42,7 @@ pub(crate) mod helpers;
pub type NodeTestMessage = TestMessage<WasmTestMessageExt>;
type LockedGatewayClient =
Arc<AsyncMutex<GatewayClient<FakeClient<DirectSigningNyxdClient>, EphemeralStorage>>>;
Arc<AsyncMutex<GatewayClient<QueryReqwestRpcNyxdClient, EphemeralStorage>>>;
pub(crate) const DEFAULT_TEST_TIMEOUT: Duration = Duration::from_secs(10);
pub(crate) const DEFAULT_TEST_PACKETS: u32 = 20;
@@ -78,8 +78,7 @@ pub struct NymNodeTesterBuilder {
base_topology: NymTopology,
// unimplemented
bandwidth_controller:
Option<BandwidthController<FakeClient<DirectSigningNyxdClient>, EphemeralStorage>>,
bandwidth_controller: Option<BandwidthController<QueryReqwestRpcNyxdClient, EphemeralStorage>>,
}
fn address(keys: &ManagedKeys, gateway_identity: NodeIdentity) -> Recipient {
@@ -130,9 +129,9 @@ impl NymNodeTesterBuilder {
async fn gateway_info(
&self,
client_store: &ClientStorage,
) -> Result<InitialisationDetails, WasmClientError> {
) -> Result<InitialisationResult, WasmClientError> {
if let Ok(loaded) = InitialisationDetails::try_load(client_store, client_store).await {
Ok(loaded)
Ok(loaded.into())
} else {
setup_from_topology(self.gateway.clone(), &self.base_topology, client_store).await
}
@@ -148,26 +147,37 @@ impl NymNodeTesterBuilder {
};
let client_store = ClientStorage::new_async(&storage_id, None).await?;
let init_details = self.gateway_info(&client_store).await?;
let initialisation_result = self.gateway_info(&client_store).await?;
let init_details = initialisation_result.details;
let managed_keys = init_details.managed_keys;
let gateway_endpoint = init_details.gateway_details;
let gateway_identity = gateway_endpoint.try_get_gateway_identity_key()?;
let managed_keys = init_details.managed_keys;
let (mixnet_message_sender, mixnet_message_receiver) = mpsc::unbounded();
let (ack_sender, ack_receiver) = mpsc::unbounded();
let mut gateway_client = GatewayClient::new(
gateway_endpoint.gateway_listener,
managed_keys.identity_keypair(),
gateway_identity,
Some(managed_keys.must_get_gateway_shared_key()),
mixnet_message_sender,
ack_sender,
Duration::from_secs(10),
self.bandwidth_controller.take(),
task_manager.subscribe(),
);
let mut gateway_client =
if let Some(existing_client) = initialisation_result.authenticated_ephemeral_client {
existing_client.upgrade(
mixnet_message_sender,
ack_sender,
Duration::from_secs(10),
self.bandwidth_controller.take(),
task_manager.subscribe(),
)
} else {
GatewayClient::new(
gateway_endpoint.gateway_listener,
managed_keys.identity_keypair(),
gateway_identity,
Some(managed_keys.must_get_gateway_shared_key()),
mixnet_message_sender,
ack_sender,
Duration::from_secs(10),
self.bandwidth_controller.take(),
task_manager.subscribe(),
)
};
gateway_client.set_disabled_credentials_mode(true);
gateway_client.authenticate_and_start().await?;
+1 -1
View File
@@ -8,5 +8,5 @@ edition = "2021"
[dependencies]
log = "0.4"
tokio = { workspace = true, features = ["time"] }
futures = "0.3"
futures = { workspace = true }
notify = "5.1.0"
+2 -3
View File
@@ -9,7 +9,7 @@ edition = "2021"
bip39 = { workspace = true }
rand = "0.7.3"
thiserror = "1.0"
url = "2.2"
url = { workspace = true }
nym-coconut-interface = { path = "../coconut-interface" }
nym-credential-storage = { path = "../credential-storage" }
@@ -18,7 +18,6 @@ nym-crypto = { path = "../crypto", features = ["rand", "asymmetric", "symmetric"
nym-network-defaults = { path = "../network-defaults" }
nym-validator-client = { path = "../client-libs/validator-client", default-features = false }
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.nym-validator-client]
path = "../client-libs/validator-client"
features = ["nyxd-client"]
features = ["http-client"]
@@ -8,11 +8,11 @@ use nym_credentials::coconut::bandwidth::{BandwidthVoucher, TOTAL_ATTRIBUTES};
use nym_credentials::coconut::utils::obtain_aggregate_signature;
use nym_crypto::asymmetric::{encryption, identity};
use nym_network_defaults::VOUCHER_INFO;
use nym_validator_client::nyxd::traits::CoconutBandwidthSigningClient;
use nym_validator_client::nyxd::traits::DkgQueryClient;
use nym_validator_client::nyxd::tx::Hash;
use nym_validator_client::coconut::all_coconut_api_clients;
use nym_validator_client::nyxd::contract_traits::CoconutBandwidthSigningClient;
use nym_validator_client::nyxd::contract_traits::DkgQueryClient;
use nym_validator_client::nyxd::Coin;
use nym_validator_client::CoconutApiClient;
use nym_validator_client::nyxd::Hash;
use rand::rngs::OsRng;
use state::{KeyPair, State};
use std::str::FromStr;
@@ -21,7 +21,7 @@ pub mod state;
pub async fn deposit<C>(client: &C, amount: Coin) -> Result<State, BandwidthControllerError>
where
C: CoconutBandwidthSigningClient,
C: CoconutBandwidthSigningClient + Sync,
{
let mut rng = OsRng;
let signing_keypair = KeyPair::from(identity::KeyPair::new(&mut rng));
@@ -70,7 +70,8 @@ where
.get_current_epoch_threshold()
.await?
.ok_or(BandwidthControllerError::NoThreshold)?;
let coconut_api_clients = CoconutApiClient::all_coconut_api_clients(client, epoch_id).await?;
let coconut_api_clients = all_coconut_api_clients(client, epoch_id).await?;
let signature = obtain_aggregate_signature(
&state.params,
+4 -1
View File
@@ -6,15 +6,18 @@ use nym_credential_storage::error::StorageError;
use nym_credentials::error::Error as CredentialsError;
use nym_crypto::asymmetric::encryption::KeyRecoveryError;
use nym_crypto::asymmetric::identity::Ed25519RecoveryError;
use nym_validator_client::coconut::CoconutApiError;
use nym_validator_client::error::ValidatorClientError;
use thiserror::Error;
#[derive(Debug, Error)]
pub enum BandwidthControllerError {
#[cfg(not(target_arch = "wasm32"))]
#[error("Nyxd error: {0}")]
Nyxd(#[from] nym_validator_client::nyxd::error::NyxdError),
#[error("coconut api query failure: {0}")]
CoconutApiError(#[from] CoconutApiError),
#[error("There was a credential storage error - {0}")]
CredentialStorageError(Box<dyn std::error::Error + Send + Sync>),
+4 -17
View File
@@ -2,10 +2,10 @@
// SPDX-License-Identifier: Apache-2.0
use crate::error::BandwidthControllerError;
use nym_credential_storage::error::StorageError;
use nym_credential_storage::storage::Storage;
use nym_validator_client::coconut::all_coconut_api_clients;
use nym_validator_client::nyxd::contract_traits::DkgQueryClient;
use std::str::FromStr;
use {
nym_coconut_interface::Base58,
@@ -14,17 +14,8 @@ use {
},
};
#[cfg(not(target_arch = "wasm32"))]
use nym_validator_client::nyxd::traits::DkgQueryClient;
#[cfg(target_arch = "wasm32")]
use crate::wasm_mockups::DkgQueryClient;
#[cfg(not(target_arch = "wasm32"))]
pub mod acquire;
pub mod error;
#[cfg(target_arch = "wasm32")]
pub mod wasm_mockups;
pub struct BandwidthController<C, St> {
storage: St,
@@ -64,12 +55,8 @@ impl<C, St: Storage> BandwidthController<C, St> {
let epoch_id = u64::from_str(&bandwidth_credential.epoch_id)
.map_err(|_| StorageError::InconsistentData)?;
#[cfg(not(target_arch = "wasm32"))]
let coconut_api_clients =
nym_validator_client::CoconutApiClient::all_coconut_api_clients(&self.client, epoch_id)
.await?;
#[cfg(target_arch = "wasm32")]
let coconut_api_clients = vec![];
let coconut_api_clients = all_coconut_api_clients(&self.client, epoch_id).await?;
let verification_key = obtain_aggregate_verification_key(&coconut_api_clients).await?;
// the below would only be executed once we know where we want to spend it (i.e. which gateway and stuff)
@@ -1,17 +0,0 @@
// Copyright 2022-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use std::marker::PhantomData;
pub struct DirectSigningNyxdClient {}
pub trait DkgQueryClient {}
// impl CosmWasmClient for DirectSigningNyxdClient {}
#[derive(Clone)]
pub struct Client<C> {
_phantom: PhantomData<C>,
}
impl<C> DkgQueryClient for Client<C> {}
+70 -29
View File
@@ -5,9 +5,13 @@
// and be used by our smart contracts
use serde::{Deserialize, Serialize};
use std::fmt::{Display, Formatter};
#[derive(Debug)]
pub struct BinaryBuildInformation {
/// Provides the name of the binary, i.e. the content of `CARGO_PKG_NAME` environmental variable.
pub binary_name: &'static str,
// VERGEN_BUILD_TIMESTAMP
/// Provides the build timestamp, for example `2021-02-23T20:14:46.558472672+00:00`.
pub build_timestamp: &'static str,
@@ -43,8 +47,9 @@ pub struct BinaryBuildInformation {
impl BinaryBuildInformation {
// explicitly require the build_version to be passed as it's binary specific
pub const fn new(build_version: &'static str) -> Self {
pub const fn new(binary_name: &'static str, build_version: &'static str) -> Self {
BinaryBuildInformation {
binary_name,
build_timestamp: env!("VERGEN_BUILD_TIMESTAMP"),
build_version,
commit_sha: env!("VERGEN_GIT_SHA"),
@@ -58,6 +63,7 @@ impl BinaryBuildInformation {
pub fn to_owned(&self) -> BinaryBuildInformationOwned {
BinaryBuildInformationOwned {
binary_name: self.binary_name.to_owned(),
build_timestamp: self.build_timestamp.to_owned(),
build_version: self.build_version.to_owned(),
commit_sha: self.commit_sha.to_owned(),
@@ -70,39 +76,15 @@ impl BinaryBuildInformation {
}
pub fn pretty_print(&self) -> String {
format!(
r#"
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
"#,
"Build Timestamp:",
self.build_timestamp,
"Build Version:",
self.build_version,
"Commit SHA:",
self.commit_sha,
"Commit Date:",
self.commit_timestamp,
"Commit Branch:",
self.commit_branch,
"rustc Version:",
self.rustc_version,
"rustc Channel:",
self.rustc_channel,
"cargo Profile:",
self.cargo_profile,
)
self.to_owned().to_string()
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct BinaryBuildInformationOwned {
/// Provides the name of the binary, i.e. the content of `CARGO_PKG_NAME` environmental variable.
pub binary_name: String,
// VERGEN_BUILD_TIMESTAMP
/// Provides the build timestamp, for example `2021-02-23T20:14:46.558472672+00:00`.
pub build_timestamp: String,
@@ -135,3 +117,62 @@ pub struct BinaryBuildInformationOwned {
/// Provides the cargo profile that was used for the build, for example `debug`.
pub cargo_profile: String,
}
impl Display for BinaryBuildInformationOwned {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(
f,
r#"
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
"#,
"Binary Name:",
self.binary_name,
"Build Timestamp:",
self.build_timestamp,
"Build Version:",
self.build_version,
"Commit SHA:",
self.commit_sha,
"Commit Date:",
self.commit_timestamp,
"Commit Branch:",
self.commit_branch,
"rustc Version:",
self.rustc_version,
"rustc Channel:",
self.rustc_channel,
"cargo Profile:",
self.cargo_profile,
)
}
}
// since this macro will get expanded at the callsite, it will pull in correct binary version
#[macro_export]
macro_rules! bin_info {
() => {
$crate::build_information::BinaryBuildInformation::new(
env!("CARGO_PKG_NAME"),
env!("CARGO_PKG_VERSION"),
)
};
}
#[macro_export]
macro_rules! bin_info_owned {
() => {
$crate::build_information::BinaryBuildInformation::new(
env!("CARGO_PKG_NAME"),
env!("CARGO_PKG_VERSION"),
)
.to_owned()
};
}
+11 -12
View File
@@ -10,27 +10,30 @@ rust-version = "1.66"
[dependencies]
async-trait = { workspace = true }
base64 = "0.21.2"
dirs = "4.0"
cfg-if = "1.0.0"
dashmap = "5.4.0"
futures = "0.3"
dirs = "4.0"
futures = { workspace = true }
humantime-serde = "1.0"
log = { workspace = true }
rand = { version = "0.7.3", features = ["wasm-bindgen"] }
reqwest = { workspace = true }
serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true }
sha2 = "0.10.6"
tap = "1.0.1"
thiserror = "1.0.34"
url = { version ="2.2", features = ["serde"] }
tungstenite = { version = "0.13.0", default-features = false }
tokio = { version = "1.24.1", features = ["macros"]}
time = "0.3.17"
tokio = { version = "1.24.1", features = ["macros"]}
tungstenite = { version = "0.13.0", default-features = false }
url = { workspace = true, features = ["serde"] }
zeroize = { workspace = true }
# internal
nym-bandwidth-controller = { path = "../bandwidth-controller" }
nym-config = { path = "../config" }
nym-crypto = { path = "../crypto" }
nym-explorer-api-requests = { path = "../../explorer-api/explorer-api-requests" }
nym-gateway-client = { path = "../client-libs/gateway-client" }
#gateway-client = { path = "../../common/client-libs/gateway-client", default-features = false, features = ["wasm", "coconut"] }
nym-gateway-requests = { path = "../../gateway/gateway-requests" }
@@ -43,10 +46,6 @@ nym-task = { path = "../task" }
nym-credential-storage = { path = "../credential-storage" }
nym-network-defaults = { path = "../network-defaults" }
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.nym-validator-client]
path = "../client-libs/validator-client"
features = ["nyxd-client"]
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.tokio-stream]
version = "0.1.11"
features = ["time"]
@@ -69,9 +68,9 @@ version = "0.4"
[target."cfg(target_arch = \"wasm32\")".dependencies.wasm-bindgen]
version = "0.2.83"
[target."cfg(target_arch = \"wasm32\")".dependencies.wasm-timer]
git = "https://github.com/mmsinclair/wasm-timer"
rev = "b9d1a54ad514c2f230a026afe0dde341e98cd7b6"
[target."cfg(target_arch = \"wasm32\")".dependencies.wasmtimer]
workspace = true
features = ["tokio"]
[target."cfg(target_arch = \"wasm32\")".dependencies.gloo-timers]
version = "0.2.4"
@@ -2,11 +2,12 @@
// SPDX-License-Identifier: Apache-2.0
use super::received_buffer::ReceivedBufferMessage;
use super::topology_control::geo_aware_provider::GeoAwareTopologyProvider;
use crate::client::base_client::storage::gateway_details::GatewayDetailsStore;
use crate::client::base_client::storage::MixnetClientStorage;
use crate::client::cover_traffic_stream::LoopCoverTrafficStream;
use crate::client::inbound_messages::{InputMessage, InputMessageReceiver, InputMessageSender};
use crate::client::key_manager::persistence::KeyStore;
use crate::client::key_manager::ManagedKeys;
use crate::client::mix_traffic::{BatchMixMessageSender, MixTrafficController};
use crate::client::real_messages_control;
use crate::client::real_messages_control::RealMessagesController;
@@ -22,8 +23,9 @@ use crate::client::topology_control::nym_api_provider::NymApiTopologyProvider;
use crate::client::topology_control::{
TopologyAccessor, TopologyRefresher, TopologyRefresherConfig,
};
use crate::config::{Config, DebugConfig, GatewayEndpointConfig};
use crate::config::{Config, DebugConfig};
use crate::error::ClientCoreError;
use crate::init::{setup_gateway, GatewaySetup, InitialisationDetails, InitialisationResult};
use crate::{config, spawn_future};
use futures::channel::mpsc;
use log::{debug, info};
@@ -42,18 +44,11 @@ use nym_sphinx::receiver::{ReconstructedMessage, SphinxMessageReceiver};
use nym_task::connections::{ConnectionCommandReceiver, ConnectionCommandSender, LaneQueueLengths};
use nym_task::{TaskClient, TaskManager};
use nym_topology::provider_trait::TopologyProvider;
use nym_validator_client::nyxd::contract_traits::DkgQueryClient;
use std::sync::Arc;
use tap::TapFallible;
use url::Url;
#[cfg(target_arch = "wasm32")]
use nym_bandwidth_controller::wasm_mockups::DkgQueryClient;
use crate::client::base_client::storage::gateway_details::GatewayDetailsStore;
use crate::init::{setup_gateway, GatewaySetup, InitialisationDetails};
#[cfg(not(target_arch = "wasm32"))]
use nym_validator_client::nyxd::traits::DkgQueryClient;
#[cfg(all(not(target_arch = "wasm32"), feature = "fs-surb-storage"))]
pub mod non_wasm_helpers;
@@ -199,16 +194,13 @@ where
// note: do **NOT** make this method public as its only valid usage is from within `start_base`
// because it relies on the crypto keys being already loaded
fn mix_address(
managed_keys: &ManagedKeys,
gateway_config: &GatewayEndpointConfig,
) -> Recipient {
fn mix_address(details: &InitialisationDetails) -> Recipient {
Recipient::new(
*managed_keys.identity_public_key(),
*managed_keys.encryption_public_key(),
*details.managed_keys.identity_public_key(),
*details.managed_keys.encryption_public_key(),
// TODO: below only works under assumption that gateway address == gateway id
// (which currently is true)
NodeIdentity::from_base58_string(&gateway_config.gateway_id).unwrap(),
NodeIdentity::from_base58_string(&details.gateway_details.gateway_id).unwrap(),
)
}
@@ -293,8 +285,7 @@ where
async fn start_gateway_client(
config: &Config,
gateway_config: GatewayEndpointConfig,
managed_keys: &ManagedKeys,
initialisation_result: InitialisationResult,
bandwidth_controller: Option<BandwidthController<C, S::CredentialStore>>,
mixnet_message_sender: MixnetMessageSender,
ack_sender: AcknowledgementSender,
@@ -304,24 +295,39 @@ where
<S::KeyStore as KeyStore>::StorageError: Send + Sync + 'static,
<S::CredentialStore as CredentialStorage>::StorageError: Send + Sync + 'static,
{
let gateway_address = gateway_config.gateway_listener.clone();
let gateway_id = gateway_config.gateway_id;
let managed_keys = initialisation_result.details.managed_keys;
// TODO: in theory, at this point, this should be infallible
let gateway_identity = identity::PublicKey::from_base58_string(gateway_id)
.map_err(ClientCoreError::UnableToCreatePublicKeyFromGatewayId)?;
let mut gateway_client =
if let Some(existing_client) = initialisation_result.authenticated_ephemeral_client {
existing_client.upgrade(
mixnet_message_sender,
ack_sender,
config.debug.gateway_connection.gateway_response_timeout,
bandwidth_controller,
shutdown,
)
} else {
let gateway_config = initialisation_result.details.gateway_details;
let mut gateway_client = GatewayClient::new(
gateway_address,
managed_keys.identity_keypair(),
gateway_identity,
Some(managed_keys.must_get_gateway_shared_key()),
mixnet_message_sender,
ack_sender,
config.debug.gateway_connection.gateway_response_timeout,
bandwidth_controller,
shutdown,
);
let gateway_address = gateway_config.gateway_listener.clone();
let gateway_id = gateway_config.gateway_id;
// TODO: in theory, at this point, this should be infallible
let gateway_identity = identity::PublicKey::from_base58_string(gateway_id)
.map_err(ClientCoreError::UnableToCreatePublicKeyFromGatewayId)?;
GatewayClient::new(
gateway_address,
managed_keys.identity_keypair(),
gateway_identity,
Some(managed_keys.must_get_gateway_shared_key()),
mixnet_message_sender,
ack_sender,
config.debug.gateway_connection.gateway_response_timeout,
bandwidth_controller,
shutdown,
)
};
gateway_client.set_disabled_credentials_mode(config.client.disabled_credentials_mode);
@@ -339,14 +345,22 @@ where
fn setup_topology_provider(
custom_provider: Option<Box<dyn TopologyProvider + Send + Sync>>,
provider_from_config: config::TopologyStructure,
nym_api_urls: Vec<Url>,
) -> Box<dyn TopologyProvider + Send + Sync> {
// if no custom provider was ... provided ..., create one using nym-api
custom_provider.unwrap_or_else(|| {
Box::new(NymApiTopologyProvider::new(
custom_provider.unwrap_or_else(|| match provider_from_config {
config::TopologyStructure::NymApi => Box::new(NymApiTopologyProvider::new(
nym_api_urls,
env!("CARGO_PKG_VERSION").to_string(),
))
)),
config::TopologyStructure::GeoAware(group_by) => {
Box::new(GeoAwareTopologyProvider::new(
nym_api_urls,
env!("CARGO_PKG_VERSION").to_string(),
group_by,
))
}
})
}
@@ -438,17 +452,23 @@ where
Ok(mem_store)
}
async fn initialise_keys_and_gateway(&self) -> Result<InitialisationDetails, ClientCoreError>
async fn initialise_keys_and_gateway(
setup_method: GatewaySetup,
key_store: &S::KeyStore,
details_store: &S::GatewayDetailsStore,
overwrite_data: bool,
validator_servers: Option<&[Url]>,
) -> Result<InitialisationResult, ClientCoreError>
where
<S::KeyStore as KeyStore>::StorageError: Sync + Send,
<S::GatewayDetailsStore as GatewayDetailsStore>::StorageError: Sync + Send,
{
setup_gateway(
&self.setup_method,
self.client_store.key_store(),
self.client_store.gateway_details_store(),
false,
Some(&self.config.client.nym_api_urls),
setup_method,
key_store,
details_store,
overwrite_data,
validator_servers,
)
.await
}
@@ -464,9 +484,14 @@ where
info!("Starting nym client");
// derive (or load) client keys and gateway configuration
let details = self.initialise_keys_and_gateway().await?;
let gateway_config = details.gateway_details;
let managed_keys = details.managed_keys;
let init_res = Self::initialise_keys_and_gateway(
self.setup_method,
self.client_store.key_store(),
self.client_store.gateway_details_store(),
false,
Some(&self.config.client.nym_api_urls),
)
.await?;
let (reply_storage_backend, credential_store) = self.client_store.into_runtime_stores();
@@ -500,14 +525,15 @@ where
let (reply_controller_sender, reply_controller_receiver) =
reply_controller::requests::new_control_channels();
let self_address = Self::mix_address(&managed_keys, &gateway_config);
let self_address = Self::mix_address(&init_res.details);
let ack_key = init_res.details.managed_keys.ack_key();
let encryption_keys = init_res.details.managed_keys.encryption_keypair();
// the components are started in very specific order. Unless you know what you are doing,
// do not change that.
let gateway_client = Self::start_gateway_client(
self.config,
gateway_config,
&managed_keys,
init_res,
bandwidth_controller,
mixnet_messages_sender,
ack_sender,
@@ -521,8 +547,10 @@ where
let topology_provider = Self::setup_topology_provider(
self.custom_topology_provider.take(),
self.config.debug.topology.topology_structure,
self.config.get_nym_api_endpoints(),
);
Self::start_topology_refresher(
topology_provider,
self.config.debug.topology,
@@ -532,7 +560,7 @@ where
.await?;
Self::start_received_messages_buffer_controller(
managed_keys.encryption_keypair(),
encryption_keys,
received_buffer_request_receiver,
mixnet_messages_receiver,
reply_storage.key_storage(),
@@ -557,7 +585,7 @@ where
let controller_config = real_messages_control::Config::new(
&self.config.debug,
managed_keys.ack_key(),
Arc::clone(&ack_key),
self_address,
);
@@ -584,7 +612,7 @@ where
{
Self::start_cover_traffic_stream(
&self.config.debug,
managed_keys.ack_key(),
ack_key,
self_address,
shared_topology_accessor.clone(),
message_sender,
@@ -10,8 +10,8 @@ use crate::error::ClientCoreError;
use log::{error, info};
use nym_bandwidth_controller::BandwidthController;
use nym_credential_storage::storage::Storage as CredentialStorage;
use nym_validator_client::nyxd::QueryNyxdClient;
use nym_validator_client::Client;
use nym_validator_client::nyxd;
use nym_validator_client::QueryHttpRpcNyxdClient;
use std::path::Path;
use std::{fs, io};
use time::OffsetDateTime;
@@ -104,48 +104,38 @@ pub async fn setup_fs_reply_surb_backend<P: AsRef<Path>>(
pub fn create_bandwidth_controller<St: CredentialStorage>(
config: &Config,
storage: St,
) -> BandwidthController<Client<QueryNyxdClient>, St> {
) -> BandwidthController<QueryHttpRpcNyxdClient, St> {
let nyxd_url = config
.get_validator_endpoints()
.pop()
.expect("No nyxd validator endpoint provided");
let api_url = config
.get_nym_api_endpoints()
.pop()
.expect("No validator api endpoint provided");
create_bandwidth_controller_with_urls(nyxd_url, api_url, storage)
create_bandwidth_controller_with_urls(nyxd_url, storage)
}
pub fn create_bandwidth_controller_with_urls<St: CredentialStorage>(
nyxd_url: Url,
nym_api_url: Url,
storage: St,
) -> BandwidthController<Client<QueryNyxdClient>, St> {
let client = default_query_dkg_client(nyxd_url, nym_api_url);
) -> BandwidthController<QueryHttpRpcNyxdClient, St> {
let client = default_query_dkg_client(nyxd_url);
BandwidthController::new(storage, client)
}
pub fn default_query_dkg_client_from_config(config: &Config) -> Client<QueryNyxdClient> {
pub fn default_query_dkg_client_from_config(config: &Config) -> QueryHttpRpcNyxdClient {
let nyxd_url = config
.get_validator_endpoints()
.pop()
.expect("No nyxd validator endpoint provided");
let api_url = config
.get_nym_api_endpoints()
.pop()
.expect("No validator api endpoint provided");
default_query_dkg_client(nyxd_url, api_url)
default_query_dkg_client(nyxd_url)
}
pub fn default_query_dkg_client(nyxd_url: Url, nym_api_url: Url) -> Client<QueryNyxdClient> {
pub fn default_query_dkg_client(nyxd_url: Url) -> QueryHttpRpcNyxdClient {
let details = nym_network_defaults::NymNetworkDetails::new_from_env();
let mut client_config = nym_validator_client::Config::try_from_nym_network_details(&details)
let client_config = nyxd::Config::try_from_nym_network_details(&details)
.expect("failed to construct validator client config");
// overwrite env configuration with config URLs
client_config = client_config.with_urls(nyxd_url, nym_api_url);
nym_validator_client::Client::new_query(client_config)
QueryHttpRpcNyxdClient::connect(client_config, nyxd_url.as_str())
.expect("Could not construct query client")
}
@@ -19,10 +19,10 @@ use std::time::Duration;
use tokio::sync::mpsc::error::TrySendError;
#[cfg(not(target_arch = "wasm32"))]
use tokio::time;
use tokio::time::{sleep, Sleep};
#[cfg(target_arch = "wasm32")]
use wasm_timer;
use wasmtimer::tokio::{sleep, Sleep};
pub struct LoopCoverTrafficStream<R>
where
@@ -39,11 +39,7 @@ where
/// Internal state, determined by `average_message_sending_delay`,
/// used to keep track of when a next packet should be sent out.
#[cfg(not(target_arch = "wasm32"))]
next_delay: Pin<Box<time::Sleep>>,
#[cfg(target_arch = "wasm32")]
next_delay: Pin<Box<wasm_timer::Delay>>,
next_delay: Pin<Box<Sleep>>,
/// Channel used for sending prepared nym packets to `MixTrafficController` that sends them
/// out to the network without any further delays.
@@ -90,17 +86,9 @@ where
// The next interval value is `next_poisson_delay` after the one that just
// yielded.
#[cfg(not(target_arch = "wasm32"))]
{
let now = self.next_delay.deadline();
let next = now + next_poisson_delay;
self.next_delay.as_mut().reset(next);
}
#[cfg(target_arch = "wasm32")]
{
self.next_delay.as_mut().reset(next_poisson_delay);
}
let now = self.next_delay.deadline();
let next = now + next_poisson_delay;
self.next_delay.as_mut().reset(next);
Poll::Ready(Some(()))
}
@@ -120,11 +108,7 @@ impl LoopCoverTrafficStream<OsRng> {
) -> Self {
let rng = OsRng;
#[cfg(not(target_arch = "wasm32"))]
let next_delay = Box::pin(time::sleep(Default::default()));
#[cfg(target_arch = "wasm32")]
let next_delay = Box::pin(wasm_timer::Delay::new(Default::default()));
let next_delay = Box::pin(sleep(Default::default()));
LoopCoverTrafficStream {
ack_key,
@@ -142,12 +126,7 @@ impl LoopCoverTrafficStream<OsRng> {
}
fn set_next_delay(&mut self, amount: Duration) {
#[cfg(not(target_arch = "wasm32"))]
let next_delay = Box::pin(time::sleep(amount));
#[cfg(target_arch = "wasm32")]
let next_delay = Box::pin(wasm_timer::Delay::new(amount));
let next_delay = Box::pin(sleep(amount));
self.next_delay = next_delay;
}
@@ -2,13 +2,12 @@
// SPDX-License-Identifier: Apache-2.0
use std::time::Duration;
use wasm_timer;
pub use wasm_timer::*;
pub use wasmtimer::{std::Instant, tokio::*};
pub type IntervalStream = gloo_timers::future::IntervalStream;
pub(crate) fn get_time_now() -> Instant {
wasm_timer::Instant::now()
Instant::now()
}
pub(crate) fn new_interval_stream(polling_rate: Duration) -> IntervalStream {
+2 -7
View File
@@ -3,15 +3,10 @@
use crate::spawn_future;
use log::*;
use nym_credential_storage::storage::Storage;
use nym_gateway_client::GatewayClient;
use nym_sphinx::forwarding::packet::MixPacket;
use nym_credential_storage::storage::Storage;
#[cfg(not(target_arch = "wasm32"))]
use nym_validator_client::nyxd::traits::DkgQueryClient;
#[cfg(target_arch = "wasm32")]
use nym_bandwidth_controller::wasm_mockups::DkgQueryClient;
use nym_validator_client::nyxd::contract_traits::DkgQueryClient;
pub type BatchMixMessageSender = tokio::sync::mpsc::Sender<Vec<MixPacket>>;
pub type BatchMixMessageReceiver = tokio::sync::mpsc::Receiver<Vec<MixPacket>>;
@@ -27,9 +27,10 @@ use std::sync::Arc;
use std::time::Duration;
#[cfg(not(target_arch = "wasm32"))]
use tokio::time;
use tokio::time::{sleep, Sleep};
#[cfg(target_arch = "wasm32")]
use wasm_timer;
use wasmtimer::tokio::{sleep, Sleep};
mod sending_delay_controller;
@@ -82,11 +83,7 @@ where
/// Internal state, determined by `average_message_sending_delay`,
/// used to keep track of when a next packet should be sent out.
#[cfg(not(target_arch = "wasm32"))]
next_delay: Option<Pin<Box<time::Sleep>>>,
#[cfg(target_arch = "wasm32")]
next_delay: Option<Pin<Box<wasm_timer::Delay>>>,
next_delay: Option<Pin<Box<Sleep>>>,
// To make sure we don't overload the mix_tx channel, we limit the rate we are pushing
// messages.
@@ -373,17 +370,9 @@ where
// The next interval value is `next_poisson_delay` after the one that just
// yielded.
#[cfg(not(target_arch = "wasm32"))]
{
let now = next_delay.deadline();
let next = now + next_poisson_delay;
next_delay.as_mut().reset(next);
}
#[cfg(target_arch = "wasm32")]
{
next_delay.as_mut().reset(next_poisson_delay);
}
let now = next_delay.deadline();
let next = now + next_poisson_delay;
next_delay.as_mut().reset(next);
// On every iteration we get new messages from upstream. Given that these come bunched
// in `Vec`, this ensures that on average we will fetch messages faster than we can
@@ -421,12 +410,7 @@ where
self.config.traffic.message_sending_average_delay,
);
#[cfg(not(target_arch = "wasm32"))]
let next_delay = Box::pin(time::sleep(sampled));
#[cfg(target_arch = "wasm32")]
let next_delay = Box::pin(wasm_timer::Delay::new(sampled));
let next_delay = Box::pin(sleep(sampled));
self.next_delay = Some(next_delay);
Poll::Pending
@@ -0,0 +1,434 @@
use std::{collections::HashMap, fmt};
use log::{debug, error, info};
use nym_explorer_api_requests::{PrettyDetailedGatewayBond, PrettyDetailedMixNodeBond};
use nym_network_defaults::var_names::EXPLORER_API;
use nym_topology::{
nym_topology_from_detailed,
provider_trait::{async_trait, TopologyProvider},
NymTopology,
};
use nym_validator_client::client::{IdentityKey, MixId};
use rand::{prelude::SliceRandom, thread_rng};
use serde::{Deserialize, Serialize};
use tap::TapOptional;
use url::Url;
use crate::config::GroupBy;
const MIN_NODES_PER_LAYER: usize = 1;
#[cfg(target_arch = "wasm32")]
fn reqwest_client() -> Option<reqwest::Client> {
reqwest::Client::builder().build().ok()
}
#[cfg(not(target_arch = "wasm32"))]
fn reqwest_client() -> Option<reqwest::Client> {
reqwest::Client::builder()
.timeout(std::time::Duration::from_secs(5))
.build()
.ok()
}
// TODO: create a explorer-api-client
async fn fetch_mixnodes_from_explorer_api() -> Option<Vec<PrettyDetailedMixNodeBond>> {
let explorer_api_url = std::env::var(EXPLORER_API).ok()?;
let explorer_api_url = Url::parse(&explorer_api_url)
.ok()?
.join("v1/mix-nodes")
.ok()?;
debug!("Fetching: {}", explorer_api_url);
reqwest_client()?
.get(explorer_api_url)
.send()
.await
.ok()?
.json::<Vec<PrettyDetailedMixNodeBond>>()
.await
.ok()
}
// TODO: create a explorer-api-client
async fn fetch_gateways_from_explorer_api() -> Option<Vec<PrettyDetailedGatewayBond>> {
let explorer_api_url = std::env::var(EXPLORER_API).ok()?;
let explorer_api_url = Url::parse(&explorer_api_url)
.ok()?
.join("v1/gateways")
.ok()?;
debug!("Fetching: {}", explorer_api_url);
reqwest_client()?
.get(explorer_api_url)
.send()
.await
.ok()?
.json::<Vec<PrettyDetailedGatewayBond>>()
.await
.ok()
}
#[derive(Copy, Clone, Hash, PartialEq, Eq, Serialize, Deserialize, Debug)]
pub enum CountryGroup {
Europe,
NorthAmerica,
SouthAmerica,
Oceania,
Asia,
Africa,
Unknown,
}
impl CountryGroup {
// We map contry codes into group, which initially are continent codes to a first approximation,
// but we do it manually to reserve the right to tweak this distribution for our purposes.
fn new(country_code: &str) -> Self {
let country_code = country_code.to_uppercase();
use CountryGroup::*;
match country_code.as_ref() {
// Europe
"AT" => Europe,
"BG" => Europe,
"CH" => Europe,
"CY" => Europe,
"CZ" => Europe,
"DE" => Europe,
"DK" => Europe,
"ES" => Europe,
"FI" => Europe,
"FR" => Europe,
"GB" => Europe,
"GR" => Europe,
"IE" => Europe,
"IT" => Europe,
"LT" => Europe,
"LU" => Europe,
"LV" => Europe,
"MD" => Europe,
"MT" => Europe,
"NL" => Europe,
"NO" => Europe,
"PL" => Europe,
"RO" => Europe,
"SE" => Europe,
"SK" => Europe,
"TR" => Europe,
"UA" => Europe,
// North America
"CA" => NorthAmerica,
"MX" => NorthAmerica,
"US" => NorthAmerica,
// South America
"AR" => SouthAmerica,
"BR" => SouthAmerica,
"CL" => SouthAmerica,
"CO" => SouthAmerica,
"CR" => SouthAmerica,
"GT" => SouthAmerica,
// Oceania
"AU" => Oceania,
// Asia
"AM" => Asia,
"BH" => Asia,
"CN" => Asia,
"GE" => Asia,
"HK" => Asia,
"ID" => Asia,
"IL" => Asia,
"IN" => Asia,
"JP" => Asia,
"KH" => Asia,
"KR" => Asia,
"KZ" => Asia,
"MY" => Asia,
"RU" => Asia,
"SG" => Asia,
"TH" => Asia,
"VN" => Asia,
// Africa
"SC" => Africa,
"UG" => Africa,
"ZA" => Africa,
// And group level codes work too
"EU" => Europe,
"NA" => NorthAmerica,
"SA" => SouthAmerica,
"OC" => Oceania,
"AS" => Asia,
"AF" => Africa,
// And some aliases
"EUROPE" => Europe,
"NORTHAMERICA" => NorthAmerica,
"SOUTHAMERICA" => SouthAmerica,
"OCEANIA" => Oceania,
"ASIA" => Asia,
"AFRICA" => Africa,
_ => {
info!("Unknown country code: {}", country_code);
Unknown
}
}
}
}
impl fmt::Display for CountryGroup {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use CountryGroup::*;
match self {
Europe => write!(f, "EU"),
NorthAmerica => write!(f, "NA"),
SouthAmerica => write!(f, "SA"),
Oceania => write!(f, "OC"),
Asia => write!(f, "AS"),
Africa => write!(f, "AF"),
Unknown => write!(f, "Unknown"),
}
}
}
impl std::str::FromStr for CountryGroup {
type Err = ();
fn from_str(s: &str) -> Result<Self, Self::Err> {
let group = CountryGroup::new(s);
if group == CountryGroup::Unknown {
Err(())
} else {
Ok(group)
}
}
}
impl CountryGroup {
#[allow(unused)]
fn known(self) -> Option<CountryGroup> {
use CountryGroup::*;
match self {
Europe | NorthAmerica | SouthAmerica | Oceania | Asia | Africa => Some(self),
Unknown => None,
}
}
}
fn group_mixnodes_by_country_code(
mixnodes: Vec<PrettyDetailedMixNodeBond>,
) -> HashMap<CountryGroup, Vec<MixId>> {
mixnodes
.into_iter()
.fold(HashMap::<CountryGroup, Vec<MixId>>::new(), |mut acc, m| {
if let Some(ref location) = m.location {
let country_code = location.two_letter_iso_country_code.clone();
let group_code = CountryGroup::new(country_code.as_str());
let mixnodes = acc.entry(group_code).or_insert_with(Vec::new);
mixnodes.push(m.mix_id);
}
acc
})
}
fn group_gateways_by_country_code(
gateways: Vec<PrettyDetailedGatewayBond>,
) -> HashMap<CountryGroup, Vec<IdentityKey>> {
gateways.into_iter().fold(
HashMap::<CountryGroup, Vec<IdentityKey>>::new(),
|mut acc, g| {
if let Some(ref location) = g.location {
let country_code = location.two_letter_iso_country_code.clone();
let group_code = CountryGroup::new(country_code.as_str());
let gateways = acc.entry(group_code).or_insert_with(Vec::new);
gateways.push(g.gateway.identity_key)
}
acc
},
)
}
fn log_mixnode_distribution(mixnodes: &HashMap<CountryGroup, Vec<MixId>>) {
let mixnode_distribution = mixnodes
.iter()
.map(|(k, v)| format!("{}: {}", k, v.len()))
.collect::<Vec<_>>()
.join(", ");
debug!("Mixnode distribution - {}", mixnode_distribution);
}
fn log_gateway_distribution(gateways: &HashMap<CountryGroup, Vec<IdentityKey>>) {
let gateway_distribution = gateways
.iter()
.map(|(k, v)| format!("{}: {}", k, v.len()))
.collect::<Vec<_>>()
.join(", ");
debug!("Gateway distribution - {}", gateway_distribution);
}
fn check_layer_integrity(topology: NymTopology) -> Result<(), ()> {
let mixes = topology.mixes();
if mixes.keys().len() < 3 {
error!("Layer is missing in topology!");
return Err(());
}
for (layer, mixnodes) in mixes {
debug!("Layer {:?} has {} mixnodes", layer, mixnodes.len());
if mixnodes.len() < MIN_NODES_PER_LAYER {
error!(
"There are only {} mixnodes in layer {:?}",
mixnodes.len(),
layer
);
return Err(());
}
}
Ok(())
}
pub struct GeoAwareTopologyProvider {
validator_client: nym_validator_client::client::NymApiClient,
filter_on: GroupBy,
client_version: String,
}
impl GeoAwareTopologyProvider {
pub fn new(
mut nym_api_urls: Vec<Url>,
client_version: String,
filter_on: GroupBy,
) -> GeoAwareTopologyProvider {
log::info!(
"Creating geo-aware topology provider with filter on {:?}",
filter_on
);
nym_api_urls.shuffle(&mut thread_rng());
GeoAwareTopologyProvider {
validator_client: nym_validator_client::client::NymApiClient::new(
nym_api_urls[0].clone(),
),
filter_on,
client_version,
}
}
async fn get_topology(&self) -> Option<NymTopology> {
let mixnodes = match self.validator_client.get_cached_active_mixnodes().await {
Err(err) => {
error!("failed to get network mixnodes - {err}");
return None;
}
Ok(mixes) => mixes,
};
let gateways = match self.validator_client.get_cached_gateways().await {
Err(err) => {
error!("failed to get network gateways - {err}");
return None;
}
Ok(gateways) => gateways,
};
// Also fetch mixnodes cached by explorer-api, with the purpose of getting their
// geolocation.
debug!("Fetching mixnodes from explorer-api...");
let Some(mixnodes_from_explorer_api) = fetch_mixnodes_from_explorer_api().await else {
error!("failed to get mixnodes from explorer-api");
return None;
};
debug!("Fetching gateways from explorer-api...");
let Some(gateways_from_explorer_api) = fetch_gateways_from_explorer_api().await else {
error!("failed to get mixnodes from explorer-api");
return None;
};
// Determine what we should filter around
let filter_on = match self.filter_on {
GroupBy::CountryGroup(group) => group,
GroupBy::NymAddress(recipient) => {
// Convert recipient into a country group by extracting out the gateway part and
// using that as the country code.
let gateway = recipient.gateway().to_base58_string();
// Lookup the location of this gateway by using the location data from the
// explorer-api
let gateway_location = gateways_from_explorer_api
.iter()
.find(|g| g.gateway.identity_key == gateway)
.and_then(|g| g.location.clone())
.map(|location| location.two_letter_iso_country_code)
.tap_none(|| error!("No location found for the gateway: {}", gateway))?;
debug!(
"Filtering on nym-address: {}, with location: {}",
recipient, gateway_location
);
CountryGroup::new(&gateway_location)
}
};
debug!("Filter group: {}", filter_on);
// Partition mixnodes_from_explorer_api according to the value of
// two_letter_iso_country_code.
// NOTE: we construct the full distribution here, but only use the one we're interested in.
// The reason we this instead of a straight filter is that this opens up the possibility to
// complement a small grouping with mixnodes from adjecent countries.
let mixnode_distribution = group_mixnodes_by_country_code(mixnodes_from_explorer_api);
log_mixnode_distribution(&mixnode_distribution);
let gateway_distribution = group_gateways_by_country_code(gateways_from_explorer_api);
log_gateway_distribution(&gateway_distribution);
let Some(filtered_mixnode_ids) = mixnode_distribution.get(&filter_on) else {
error!("no mixnodes found for: {}", filter_on);
return None;
};
let Some(filtered_gateway_ids) = gateway_distribution.get(&filter_on) else {
error!("no gateways found for: {}", filter_on);
return None;
};
let mixnodes = mixnodes
.into_iter()
.filter(|m| filtered_mixnode_ids.contains(&m.mix_id()))
.collect::<Vec<_>>();
let gateways = gateways
.into_iter()
.filter(|g| filtered_gateway_ids.contains(g.identity()))
.collect::<Vec<_>>();
let topology = nym_topology_from_detailed(mixnodes, gateways)
.filter_system_version(&self.client_version);
// TODO: return real error type
check_layer_integrity(topology.clone()).ok()?;
Some(topology)
}
}
#[cfg(not(target_arch = "wasm32"))]
#[async_trait]
impl TopologyProvider for GeoAwareTopologyProvider {
// this will be manually refreshed on a timer specified inside mixnet client config
async fn get_new_topology(&mut self) -> Option<NymTopology> {
self.get_topology().await
}
}
#[cfg(target_arch = "wasm32")]
#[async_trait(?Send)]
impl TopologyProvider for GeoAwareTopologyProvider {
// this will be manually refreshed on a timer specified inside mixnet client config
async fn get_new_topology(&mut self) -> Option<NymTopology> {
self.get_topology().await
}
}
@@ -10,6 +10,7 @@ use nym_topology::NymTopologyError;
use std::time::Duration;
mod accessor;
pub mod geo_aware_provider;
pub(crate) mod nym_api_provider;
// TODO: move it to config later
+33 -2
View File
@@ -3,12 +3,15 @@
use nym_config::defaults::NymNetworkDetails;
use nym_crypto::asymmetric::identity;
use nym_sphinx::params::{PacketSize, PacketType};
use nym_sphinx::{
addressing::clients::Recipient,
params::{PacketSize, PacketType},
};
use serde::{Deserialize, Serialize};
use std::time::Duration;
use url::Url;
use crate::error::ClientCoreError;
use crate::{client::topology_control::geo_aware_provider::CountryGroup, error::ClientCoreError};
#[cfg(target_arch = "wasm32")]
use wasm_bindgen::prelude::*;
@@ -158,6 +161,15 @@ impl Config {
self
}
pub fn with_topology_structure(mut self, topology_structure: TopologyStructure) -> Self {
self.set_topology_structure(topology_structure);
self
}
pub fn set_topology_structure(&mut self, topology_structure: TopologyStructure) {
self.debug.topology.topology_structure = topology_structure;
}
pub fn with_no_per_hop_delays(mut self, no_per_hop_delays: bool) -> Self {
if no_per_hop_delays {
self.set_no_per_hop_delays()
@@ -466,6 +478,24 @@ pub struct Topology {
/// the first valid instance.
/// Supersedes `topology_refresh_rate_ms`.
pub disable_refreshing: bool,
/// Specifies the mixnode topology to be used for sending packets.
pub topology_structure: TopologyStructure,
}
#[allow(clippy::large_enum_variant)]
#[derive(Default, Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
pub enum TopologyStructure {
#[default]
NymApi,
GeoAware(GroupBy),
}
#[allow(clippy::large_enum_variant)]
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
pub enum GroupBy {
CountryGroup(CountryGroup),
NymAddress(Recipient),
}
impl Default for Topology {
@@ -474,6 +504,7 @@ impl Default for Topology {
topology_refresh_rate: DEFAULT_TOPOLOGY_REFRESH_RATE,
topology_resolution_timeout: DEFAULT_TOPOLOGY_RESOLUTION_TIMEOUT,
disable_refreshing: false,
topology_structure: TopologyStructure::default(),
}
}
}
@@ -267,6 +267,7 @@ impl From<TopologyV1_1_20_2> for Topology {
topology_refresh_rate: value.topology_refresh_rate,
topology_resolution_timeout: value.topology_resolution_timeout,
disable_refreshing: value.disable_refreshing,
topology_structure: Default::default(),
}
}
}
+36 -32
View File
@@ -3,11 +3,11 @@
use crate::config::GatewayEndpointConfig;
use crate::error::ClientCoreError;
use crate::init::RegistrationResult;
use futures::{SinkExt, StreamExt};
use log::{debug, info, trace, warn};
use nym_crypto::asymmetric::identity;
use nym_gateway_client::GatewayClient;
use nym_gateway_requests::registration::handshake::SharedKeys;
use nym_topology::{filter::VersionFilterable, gateway};
use rand::{seq::SliceRandom, Rng};
use std::{sync::Arc, time::Duration};
@@ -15,8 +15,6 @@ use tap::TapFallible;
use tungstenite::Message;
use url::Url;
#[cfg(not(target_arch = "wasm32"))]
use nym_validator_client::nyxd::DirectSigningNyxdClient;
#[cfg(not(target_arch = "wasm32"))]
use tokio::net::TcpStream;
#[cfg(not(target_arch = "wasm32"))]
@@ -27,17 +25,20 @@ use tokio_tungstenite::connect_async;
use tokio_tungstenite::{MaybeTlsStream, WebSocketStream};
#[cfg(not(target_arch = "wasm32"))]
type WsConn = WebSocketStream<MaybeTlsStream<TcpStream>>;
#[cfg(not(target_arch = "wasm32"))]
use tokio::time::sleep;
#[cfg(target_arch = "wasm32")]
use nym_bandwidth_controller::wasm_mockups::DirectSigningNyxdClient;
#[cfg(target_arch = "wasm32")]
use wasm_timer::Instant;
#[cfg(target_arch = "wasm32")]
use wasm_utils::websocket::JSWebsocket;
#[cfg(target_arch = "wasm32")]
use wasmtimer::std::Instant;
#[cfg(target_arch = "wasm32")]
use wasmtimer::tokio::sleep;
#[cfg(target_arch = "wasm32")]
type WsConn = JSWebsocket;
const CONCURRENT_GATEWAYS_MEASURED: usize = 20;
const MEASUREMENTS: usize = 3;
#[cfg(not(target_arch = "wasm32"))]
@@ -124,15 +125,9 @@ async fn measure_latency(gateway: &gateway::Node) -> Result<GatewayWithLatency,
Ok::<(), ClientCoreError>(())
};
// thanks to wasm we can't use tokio::time::timeout : (
#[cfg(not(target_arch = "wasm32"))]
let timeout = tokio::time::sleep(PING_TIMEOUT);
#[cfg(not(target_arch = "wasm32"))]
let timeout = sleep(PING_TIMEOUT);
tokio::pin!(timeout);
#[cfg(target_arch = "wasm32")]
let mut timeout = wasm_timer::Delay::new(PING_TIMEOUT);
tokio::select! {
_ = &mut timeout => {
warn!("timed out while trying to perform measurement...")
@@ -158,23 +153,29 @@ pub(super) async fn choose_gateway_by_latency<R: Rng>(
rng: &mut R,
gateways: &[gateway::Node],
) -> Result<gateway::Node, ClientCoreError> {
info!("choosing gateway by latency...");
info!(
"choosing gateway by latency, pinging {} gateways ...",
gateways.len()
);
let mut gateways_with_latency = Vec::new();
for gateway in gateways {
let id = *gateway.identity();
trace!("measuring latency to {id}...");
let with_latency = match measure_latency(gateway).await {
Ok(res) => res,
Err(err) => {
warn!("failed to measure {id}: {err}");
continue;
}
};
debug!("{id}: {:?}", with_latency.latency);
gateways_with_latency.push(with_latency)
}
let gateways_with_latency = Arc::new(tokio::sync::Mutex::new(Vec::new()));
futures::stream::iter(gateways)
.for_each_concurrent(CONCURRENT_GATEWAYS_MEASURED, |gateway| async {
let id = *gateway.identity();
trace!("measuring latency to {id}...");
match measure_latency(gateway).await {
Ok(with_latency) => {
debug!("{id}: {:?}", with_latency.latency);
gateways_with_latency.lock().await.push(with_latency);
}
Err(err) => {
warn!("failed to measure {id}: {err}");
}
};
})
.await;
let gateways_with_latency = gateways_with_latency.lock().await;
let chosen = gateways_with_latency
.choose_weighted(rng, |item| 1. / item.latency.as_secs_f32())
.expect("invalid selection weight!");
@@ -200,9 +201,9 @@ pub(super) fn uniformly_random_gateway<R: Rng>(
pub(super) async fn register_with_gateway(
gateway: &GatewayEndpointConfig,
our_identity: Arc<identity::KeyPair>,
) -> Result<Arc<SharedKeys>, ClientCoreError> {
) -> Result<RegistrationResult, ClientCoreError> {
let timeout = Duration::from_millis(1500);
let mut gateway_client: GatewayClient<DirectSigningNyxdClient, _> = GatewayClient::new_init(
let mut gateway_client = GatewayClient::new_init(
gateway.gateway_listener.clone(),
gateway.try_get_gateway_identity_key()?,
our_identity.clone(),
@@ -216,5 +217,8 @@ pub(super) async fn register_with_gateway(
.perform_initial_authentication()
.await
.tap_err(|_| log::warn!("Failed to register with the gateway!"))?;
Ok(shared_keys)
Ok(RegistrationResult {
shared_keys,
authenticated_ephemeral_client: Some(gateway_client),
})
}
+67 -18
View File
@@ -14,16 +14,39 @@ use crate::{
error::ClientCoreError,
};
use nym_crypto::asymmetric::identity;
use nym_gateway_client::client::InitOnly;
use nym_gateway_client::GatewayClient;
use nym_gateway_requests::registration::handshake::SharedKeys;
use nym_sphinx::addressing::{clients::Recipient, nodes::NodeIdentity};
use nym_topology::gateway;
use nym_validator_client::client::IdentityKey;
use rand::rngs::OsRng;
use serde::Serialize;
use std::fmt::{Debug, Display};
use std::sync::Arc;
use url::Url;
pub mod helpers;
pub struct RegistrationResult {
pub shared_keys: Arc<SharedKeys>,
pub authenticated_ephemeral_client: Option<GatewayClient<InitOnly>>,
}
pub struct InitialisationResult {
pub details: InitialisationDetails,
pub authenticated_ephemeral_client: Option<GatewayClient<InitOnly>>,
}
impl From<InitialisationDetails> for InitialisationResult {
fn from(details: InitialisationDetails) -> Self {
InitialisationResult {
details,
authenticated_ephemeral_client: None,
}
}
}
// TODO: rename to something better...
#[derive(Debug)]
pub struct InitialisationDetails {
@@ -74,7 +97,6 @@ impl InitialisationDetails {
}
}
#[derive(Debug, Clone)]
pub enum GatewaySetup {
/// The gateway specification MUST BE loaded from the underlying storage.
MustLoad,
@@ -92,6 +114,13 @@ pub enum GatewaySetup {
/// Full gateway configuration
details: PersistedGatewayDetails,
},
ReuseConnection {
/// The authenticated ephemeral client that was created during `init`
authenticated_ephemeral_client: GatewayClient<InitOnly>,
/// Details of this pre-initialised client
details: InitialisationDetails,
},
}
impl From<PersistedGatewayDetails> for GatewaySetup {
@@ -266,18 +295,32 @@ fn ensure_valid_details(
}
pub async fn setup_gateway_from<K, D>(
setup: &GatewaySetup,
setup: GatewaySetup,
key_store: &K,
details_store: &D,
overwrite_data: bool,
gateways: Option<&[gateway::Node]>,
) -> Result<InitialisationDetails, ClientCoreError>
) -> Result<InitialisationResult, ClientCoreError>
where
K: KeyStore,
D: GatewayDetailsStore,
K::StorageError: Send + Sync + 'static,
D::StorageError: Send + Sync + 'static,
{
// I don't like how we can't deal with this variant in the match below, but we need to take ownership of internal values.
if let GatewaySetup::ReuseConnection {
authenticated_ephemeral_client,
details,
} = setup
{
// if we have already performed the full setup, forward the details.
// it's up to the caller to ensure persistence
return Ok(InitialisationResult {
details,
authenticated_ephemeral_client: Some(authenticated_ephemeral_client),
});
}
let mut rng = OsRng;
// try load gateway details
@@ -286,14 +329,14 @@ where
// try load keys and decide what to do based on the GatewaySetup
let mut managed_keys = match ManagedKeys::try_load(key_store).await {
Ok(loaded_keys) => {
match setup {
match &setup {
GatewaySetup::MustLoad => {
// get EVERYTHING from the storage
let details = loaded_details?;
ensure_valid_details(&details, &loaded_keys)?;
// no need to persist anything as we got everything from the storage
return Ok(InitialisationDetails::new(details.into(), loaded_keys));
return Ok(InitialisationDetails::new(details.into(), loaded_keys).into());
}
GatewaySetup::Predefined { details } => {
// we already have defined gateway details AND a shared key
@@ -304,10 +347,9 @@ where
_store_gateway_details(details_store, details).await?;
}
return Ok(InitialisationDetails::new(
details.clone().into(),
loaded_keys,
));
return Ok(
InitialisationDetails::new(details.clone().into(), loaded_keys).into(),
);
}
GatewaySetup::Specified { gateway_identity } => {
// if that data was already stored...
@@ -323,7 +365,8 @@ where
return Ok(InitialisationDetails::new(
existing_gateway.into(),
loaded_keys,
));
)
.into());
}
}
@@ -341,7 +384,8 @@ where
return Ok(InitialisationDetails::new(
existing_gateway.into(),
loaded_keys,
));
)
.into());
}
// we didn't get full details from the store and we have loaded some keys
@@ -352,6 +396,9 @@ where
return Err(ClientCoreError::ForbiddenKeyOverwrite);
}
}
GatewaySetup::ReuseConnection { .. } => {
unreachable!("the reuse connection variant was already manually covered")
}
}
}
Err(_) => {
@@ -371,7 +418,9 @@ where
let our_identity = managed_keys.identity_keypair();
// Establish connection, authenticate and generate keys for talking with the gateway
let shared_keys = helpers::register_with_gateway(&gateway_details, our_identity).await?;
let registration_result =
helpers::register_with_gateway(&gateway_details, our_identity).await?;
let shared_keys = registration_result.shared_keys;
let persisted_details = PersistedGatewayDetails::new(gateway_details, &shared_keys);
@@ -386,19 +435,19 @@ where
// persist gateway config
_store_gateway_details(details_store, &persisted_details).await?;
Ok(InitialisationDetails::new(
persisted_details.into(),
managed_keys,
))
Ok(InitialisationResult {
details: InitialisationDetails::new(persisted_details.into(), managed_keys),
authenticated_ephemeral_client: registration_result.authenticated_ephemeral_client,
})
}
pub async fn setup_gateway<K, D>(
setup: &GatewaySetup,
setup: GatewaySetup,
key_store: &K,
details_store: &D,
overwrite_data: bool,
validator_servers: Option<&[Url]>,
) -> Result<InitialisationDetails, ClientCoreError>
) -> Result<InitialisationResult, ClientCoreError>
where
K: KeyStore,
D: GatewayDetailsStore,
+7 -7
View File
@@ -9,10 +9,10 @@ edition = "2021"
[dependencies]
# TODO: (for this and other crates), similarly to 'tokio', import only required "futures" modules rather than
# the entire crate
futures = "0.3"
futures = { workspace = true }
log = { workspace = true }
thiserror = "1.0"
url = "2.2"
thiserror = { workspace = true }
url = { workspace = true }
rand = { version = "0.7.3", features = ["wasm-bindgen"] }
tokio = { version = "1.24.1", features = ["macros"] }
@@ -25,7 +25,7 @@ nym-gateway-requests = { path = "../../../gateway/gateway-requests" }
nym-network-defaults = { path = "../../network-defaults" }
nym-sphinx = { path = "../../nymsphinx" }
nym-pemstore = { path = "../../pemstore" }
nym-validator-client = { path = "../validator-client" }
nym-validator-client = { path = "../validator-client", default-features = false }
nym-task = { path = "../../task" }
serde = { workspace = true, features = ["derive"] }
@@ -58,9 +58,9 @@ path = "../../wasm-utils"
features = ["websocket"]
# only import it in wasm. Prefer proper tokio timer in non-wasm
[target."cfg(target_arch = \"wasm32\")".dependencies.wasm-timer]
git = "https://github.com/mmsinclair/wasm-timer"
rev = "b9d1a54ad514c2f230a026afe0dde341e98cd7b6"
[target."cfg(target_arch = \"wasm32\")".dependencies.wasmtimer]
workspace = true
features = ["tokio"]
# this is due to tungstenite using `rand` 0.8 and associated changes in `getrandom` crate
# which now does not support wasm32-unknown-unknown target by default.
+53 -27
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::error::GatewayClientError;
@@ -22,6 +22,7 @@ use nym_gateway_requests::{BinaryRequest, ClientControlRequest, ServerResponse,
use nym_network_defaults::{REMAINING_BANDWIDTH_THRESHOLD, TOKENS_TO_BURN};
use nym_sphinx::forwarding::packet::MixPacket;
use nym_task::TaskClient;
use nym_validator_client::nyxd::contract_traits::DkgQueryClient;
use rand::rngs::OsRng;
use std::convert::TryFrom;
use std::sync::Arc;
@@ -29,21 +30,19 @@ use std::time::Duration;
use tungstenite::protocol::Message;
#[cfg(not(target_arch = "wasm32"))]
use nym_validator_client::nyxd::traits::DkgQueryClient;
use tokio::time::sleep;
#[cfg(not(target_arch = "wasm32"))]
use tokio_tungstenite::connect_async;
#[cfg(target_arch = "wasm32")]
use nym_bandwidth_controller::wasm_mockups::DkgQueryClient;
#[cfg(target_arch = "wasm32")]
use wasm_timer;
#[cfg(target_arch = "wasm32")]
use wasm_utils::websocket::JSWebsocket;
#[cfg(target_arch = "wasm32")]
use wasmtimer::tokio::sleep;
const DEFAULT_RECONNECTION_ATTEMPTS: usize = 10;
const DEFAULT_RECONNECTION_BACKOFF: Duration = Duration::from_secs(5);
pub struct GatewayClient<C, St> {
pub struct GatewayClient<C, St = EphemeralCredentialStorage> {
authenticated: bool,
disabled_credentials_mode: bool,
bandwidth_remaining: i64,
@@ -197,16 +196,7 @@ impl<C, St> GatewayClient<C, St> {
return Ok(());
}
#[cfg(not(target_arch = "wasm32"))]
tokio::time::sleep(self.reconnection_backoff).await;
#[cfg(target_arch = "wasm32")]
if let Err(err) = wasm_timer::Delay::new(self.reconnection_backoff).await {
error!(
"the timer has gone away while in reconnection backoff! - {}",
err
);
}
sleep(self.reconnection_backoff).await;
}
// final attempt (done separately to be able to return a proper error)
@@ -235,16 +225,9 @@ impl<C, St> GatewayClient<C, St> {
_ => return Err(GatewayClientError::ConnectionInInvalidState),
};
#[cfg(not(target_arch = "wasm32"))]
let timeout = tokio::time::sleep(self.response_timeout_duration);
#[cfg(not(target_arch = "wasm32"))]
let timeout = sleep(self.response_timeout_duration);
tokio::pin!(timeout);
// technically the `wasm_timer` also works outside wasm, but unless required,
// I really prefer to just stick to tokio
#[cfg(target_arch = "wasm32")]
let mut timeout = wasm_timer::Delay::new(self.response_timeout_duration);
loop {
tokio::select! {
_ = self.shutdown.recv() => {
@@ -484,6 +467,14 @@ impl<C, St> GatewayClient<C, St> {
pub async fn perform_initial_authentication(
&mut self,
) -> Result<Arc<SharedKeys>, GatewayClientError> {
if self.authenticated {
return if let Some(shared_key) = &self.shared_key {
Ok(Arc::clone(shared_key))
} else {
Err(GatewayClientError::AuthenticationFailure)
};
}
if self.shared_key.is_some() {
self.authenticate(None).await?;
} else {
@@ -768,7 +759,9 @@ impl<C, St> GatewayClient<C, St> {
}
}
impl<C> GatewayClient<C, EphemeralCredentialStorage> {
pub struct InitOnly;
impl GatewayClient<InitOnly, EphemeralCredentialStorage> {
// for initialisation we do not need credential storage. Though it's still a bit weird we have to set the generic...
pub fn new_init(
gateway_address: String,
@@ -785,7 +778,7 @@ impl<C> GatewayClient<C, EphemeralCredentialStorage> {
let shutdown = TaskClient::dummy();
let packet_router = PacketRouter::new(ack_tx, mix_tx, shutdown.clone());
GatewayClient::<C, EphemeralCredentialStorage> {
GatewayClient {
authenticated: false,
disabled_credentials_mode: true,
bandwidth_remaining: 0,
@@ -803,4 +796,37 @@ impl<C> GatewayClient<C, EphemeralCredentialStorage> {
shutdown,
}
}
pub fn upgrade<C, St>(
self,
mixnet_message_sender: MixnetMessageSender,
ack_sender: AcknowledgementSender,
response_timeout_duration: Duration,
bandwidth_controller: Option<BandwidthController<C, St>>,
shutdown: TaskClient,
) -> GatewayClient<C, St> {
// invariants that can't be broken
// (unless somebody decided to expose some field that wasn't meant to be exposed)
assert!(self.authenticated);
assert!(self.connection.is_available());
assert!(self.shared_key.is_some());
GatewayClient {
authenticated: self.authenticated,
disabled_credentials_mode: self.disabled_credentials_mode,
bandwidth_remaining: self.bandwidth_remaining,
gateway_address: self.gateway_address,
gateway_identity: self.gateway_identity,
local_identity: self.local_identity,
shared_key: self.shared_key,
connection: self.connection,
packet_router: PacketRouter::new(ack_sender, mixnet_message_sender, shutdown.clone()),
response_timeout_duration,
bandwidth_controller,
should_reconnect_on_failure: self.should_reconnect_on_failure,
reconnection_attempts: self.reconnection_attempts,
reconnection_backoff: self.reconnection_backoff,
shutdown,
}
}
}
+1 -1
View File
@@ -7,7 +7,7 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
futures = "0.3"
futures = { workspace = true }
log = { workspace = true }
tokio = { version = "1.24.1", features = ["time", "net", "rt"] }
tokio-util = { version = "0.7.4", features = ["codec"] }
+38 -49
View File
@@ -21,80 +21,69 @@ nym-multisig-contract-common = { path = "../../cosmwasm-smart-contracts/multisig
nym-name-service-common = { path = "../../cosmwasm-smart-contracts/name-service" }
nym-group-contract-common = { path = "../../cosmwasm-smart-contracts/group-contract" }
nym-service-provider-directory-common = { path = "../../cosmwasm-smart-contracts/service-provider-directory" }
nym-vesting-contract = { path = "../../../contracts/vesting" }
serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true }
reqwest = { version = "0.11", features = ["json"] }
thiserror = "1"
reqwest = { workspace = true, features = ["json"] }
thiserror = { workspace = true }
log = { workspace = true }
url = { version = "2.2", features = ["serde"] }
tokio = { version = "1.24.1", features = ["sync", "time"] }
futures = "0.3"
openssl = { version = "0.10", features = ["vendored"], optional = true }
url = { workspace = true, features = ["serde"] }
tokio = { workspace = true, features = ["sync", "time"] }
futures = { workspace = true }
openssl = { version = "^0.10.55", features = ["vendored"], optional = true }
nym-coconut-interface = { path = "../../coconut-interface" }
nym-network-defaults = { path = "../../network-defaults" }
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
# perhaps after https://github.com/cosmos/cosmos-rust/pull/97 is resolved (and tendermint-rs is updated)
async-trait = { workspace = true, optional = true }
bip39 = { workspace = true, features = ["rand"], optional = true }
nym-config = { path = "../../config", optional = true }
cosmrs = { workspace = true, features = ["rpc", "bip32", "cosmwasm"], optional = true }
async-trait = { workspace = true }
bip39 = { workspace = true, features = ["rand"] }
nym-config = { path = "../../config" }
cosmrs = { workspace = true, features = ["bip32", "cosmwasm"] }
# note that this has the same version as used by cosmrs
eyre = { version = "0.6", optional = true }
cw3 = { workspace = true, optional = true }
cw4 = { workspace = true, optional = true }
prost = { version = "0.10", default-features = false, optional = true }
flate2 = { version = "1.0.20", optional = true }
sha2 = { version = "0.9.5", optional = true }
itertools = { version = "0.10", optional = true }
zeroize = { version = "1.5.7", optional = true, features = ["zeroize_derive"] }
cosmwasm-std = { workspace = true, optional = true }
# import it just for the `Client` trait
tendermint-rpc = { workspace = true }
eyre = { version = "0.6" }
cw-utils = { workspace = true }
cw2 = { workspace = true }
cw3 = { workspace = true }
cw4 = { workspace = true }
cw-controllers = { workspace = true }
prost = { version = "0.11", default-features = false }
flate2 = { version = "1.0.20" }
sha2 = { version = "0.9.5" }
itertools = { version = "0.10" }
zeroize = { workspace = true, features = ["zeroize_derive"] }
cosmwasm-std = { workspace = true }
# required for polling for broadcast result
[target."cfg(target_arch = \"wasm32\")".dependencies.wasmtimer]
workspace = true
features = ["tokio"]
[dev-dependencies]
bip39 = { workspace = true }
cosmrs = { workspace = true, features = ["rpc", "bip32"] }
tokio = { version = "1.24.1", features = ["rt-multi-thread", "macros"] }
ts-rs = "6.1.2"
cosmrs = { workspace = true, features = ["bip32"] }
ts-rs = { workspace = true }
[[example]]
name = "offline_signing"
# it should only really require the "signing" feature,
# but that would require another round of refactoring to make it possible
# (traits would need to be moved around and refactored themselves)
required-features = ["nyxd-client"]
required-features = ["http-client"]
[[example]]
name = "query_service_provider_directory"
required-features = ["nyxd-client"]
required-features = ["http-client"]
[[example]]
name = "query_name_service"
required-features = ["nyxd-client"]
required-features = ["http-client"]
[features]
nyxd-client = [
"async-trait",
"cosmrs",
"cosmwasm-std",
"cw3",
"cw4",
"flate2",
"itertools",
"openssl",
"prost",
"sha2",
"signing"
]
signing = [
"bip39",
"cosmrs",
"eyre",
"nym-config",
"zeroize"
]
default = ["http-client"]
http-client = ["cosmrs/rpc", "openssl"]
generate-ts = []
@@ -2,9 +2,9 @@
// SPDX-License-Identifier: Apache-2.0
use cosmrs::bank::MsgSend;
use cosmrs::rpc::{self, HttpClient};
use cosmrs::tx::Msg;
use cosmrs::{tx, AccountId, Coin, Denom};
use nym_validator_client::http_client;
use nym_validator_client::nyxd::CosmWasmClient;
use nym_validator_client::signing::direct_wallet::DirectSecp256k1HdWallet;
use nym_validator_client::signing::tx_signer::TxSigner;
@@ -23,11 +23,11 @@ async fn main() {
let signer_address = signer.try_derive_accounts().unwrap()[0].address().clone();
// local 'client' ONLY signing messages
let tx_signer = TxSigner::new(signer);
let tx_signer = signer;
// possibly remote client that doesn't do ANY signing
// (only broadcasts + queries for sequence numbers)
let broadcaster = HttpClient::new(validator).unwrap();
let broadcaster = http_client(validator).unwrap();
// get signer information
let sequence_response = broadcaster.get_sequence(&signer_address).await.unwrap();
@@ -54,7 +54,7 @@ async fn main() {
denom,
amount: 2500u32.into(),
},
100000,
100000u32,
);
let tx_raw = tx_signer
@@ -70,7 +70,7 @@ async fn main() {
.unwrap();
// broadcast the tx
let res = rpc::Client::broadcast_tx_commit(&broadcaster, tx_bytes.into())
let res = tendermint_rpc::client::Client::broadcast_tx_commit(&broadcaster, tx_bytes)
.await
.unwrap();
@@ -3,11 +3,13 @@ use std::str::FromStr;
use cosmrs::AccountId;
use nym_name_service_common::Address;
use nym_network_defaults::{setup_env, NymNetworkDetails};
use nym_validator_client::nyxd::traits::NameServiceQueryClient;
use nym_validator_client::nyxd::contract_traits::{
NameServiceQueryClient, PagedNameServiceQueryClient,
};
#[tokio::main]
async fn main() {
setup_env(Some(&"../../../envs/qa-qwerty.env".parse().unwrap()));
setup_env(Some("../../../envs/qa-qwerty.env"));
let network_details = NymNetworkDetails::new_from_env();
let config =
nym_validator_client::Config::try_from_nym_network_details(&network_details).unwrap();
@@ -26,7 +28,7 @@ async fn main() {
let names_by_owner = client.nyxd.get_names_by_owner(owner).await.unwrap();
println!("names (by owner): {names_by_owner:#?}");
let nym_address = Address::new("client_id.client_key@gateway_id");
let nym_address = Address::new("client_id.client_key@gateway_id").unwrap();
let names_by_address = client.nyxd.get_names_by_address(nym_address).await.unwrap();
println!("names (by address): {names_by_address:#?}");
@@ -3,11 +3,13 @@ use std::str::FromStr;
use cosmrs::AccountId;
use nym_network_defaults::{setup_env, NymNetworkDetails};
use nym_service_provider_directory_common::NymAddress;
use nym_validator_client::nyxd::traits::SpDirectoryQueryClient;
use nym_validator_client::nyxd::contract_traits::{
PagedSpDirectoryQueryClient, SpDirectoryQueryClient,
};
#[tokio::main]
async fn main() {
setup_env(Some(&"../../../envs/qa-qwerty.env".parse().unwrap()));
setup_env(Some("../../../envs/qa-qwerty.env"));
let network_details = NymNetworkDetails::new_from_env();
let config =
nym_validator_client::Config::try_from_nym_network_details(&network_details).unwrap();
+92 -559
View File
@@ -1,63 +1,46 @@
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::{nym_api, ValidatorClientError};
use crate::nyxd::{self, NyxdClient};
use crate::signing::direct_wallet::DirectSecp256k1HdWallet;
use crate::signing::signer::{NoSigner, OfflineSigner};
use crate::{
nym_api, DirectSigningReqwestRpcValidatorClient, QueryReqwestRpcValidatorClient,
ReqwestRpcClient, ValidatorClientError,
};
use nym_api_requests::coconut::{
BlindSignRequestBody, BlindedSignatureResponse, VerifyCredentialBody, VerifyCredentialResponse,
};
use nym_api_requests::models::MixNodeBondAnnotated;
use nym_api_requests::models::{
GatewayCoreStatusResponse, MixnodeCoreStatusResponse, MixnodeStatusResponse,
RewardEstimationResponse, StakeSaturationResponse,
};
use nym_coconut_dkg_common::types::NodeIndex;
use nym_coconut_interface::VerificationKey;
use nym_network_defaults::NymNetworkDetails;
use url::Url;
pub use nym_mixnet_contract_common::{
mixnode::MixNodeDetails, GatewayBond, IdentityKey, IdentityKeyRef, MixId,
};
use url::Url;
#[cfg(feature = "nyxd-client")]
use crate::nyxd::traits::{DkgQueryClient, EphemeraQueryClient, MixnetQueryClient};
#[cfg(feature = "nyxd-client")]
use crate::nyxd::{self, CosmWasmClient, NyxdClient, QueryNyxdClient, SigningNyxdClient};
#[cfg(feature = "nyxd-client")]
use crate::signing::direct_wallet::DirectSecp256k1HdWallet;
#[cfg(feature = "nyxd-client")]
use nym_api_requests::models::MixNodeBondAnnotated;
#[cfg(feature = "nyxd-client")]
use nym_coconut_dkg_common::{types::EpochId, verification_key::ContractVKShare};
#[cfg(feature = "nyxd-client")]
use nym_coconut_interface::Base58;
#[cfg(feature = "nyxd-client")]
use nym_ephemera_common::types::JsonPeerInfo;
#[cfg(feature = "nyxd-client")]
use nym_mixnet_contract_common::{
families::{Family, FamilyHead},
mixnode::MixNodeBond,
pending_events::{PendingEpochEvent, PendingIntervalEvent},
Delegation, RewardedSetNodeStatus, UnbondedMixnode,
};
#[cfg(feature = "nyxd-client")]
use nym_network_defaults::NymNetworkDetails;
#[cfg(feature = "nyxd-client")]
use std::str::FromStr;
// re-export the type to not break existing imports
pub use crate::coconut::CoconutApiClient;
#[cfg(feature = "http-client")]
use crate::rpc::http_client;
#[cfg(feature = "http-client")]
use crate::{DirectSigningHttpRpcValidatorClient, HttpRpcClient, QueryHttpRpcValidatorClient};
#[cfg(feature = "nyxd-client")]
#[must_use]
#[derive(Debug, Clone)]
pub struct Config {
api_url: Url,
nyxd_url: Url,
// TODO: until refactored, this is a dead field under some features
nyxd_config: nyxd::Config,
mixnode_page_limit: Option<u32>,
gateway_page_limit: Option<u32>,
mixnode_delegations_page_limit: Option<u32>,
rewarded_set_page_limit: Option<u32>,
}
#[cfg(feature = "nyxd-client")]
impl Config {
pub fn try_from_nym_network_details(
details: &NymNetworkDetails,
@@ -80,10 +63,6 @@ impl Config {
.parse()
.map_err(ValidatorClientError::MalformedUrlProvided)?,
nyxd_config: nyxd::Config::try_from_nym_network_details(details)?,
mixnode_page_limit: None,
gateway_page_limit: None,
mixnode_delegations_page_limit: None,
rewarded_set_page_limit: None,
})
}
@@ -100,88 +79,57 @@ impl Config {
self
}
pub fn with_mixnode_page_limit(mut self, limit: Option<u32>) -> Config {
self.mixnode_page_limit = limit;
self
}
pub fn with_gateway_page_limit(mut self, limit: Option<u32>) -> Config {
self.gateway_page_limit = limit;
self
}
pub fn with_mixnode_delegations_page_limit(mut self, limit: Option<u32>) -> Config {
self.mixnode_delegations_page_limit = limit;
self
}
pub fn with_rewarded_set_page_limit(mut self, limit: Option<u32>) -> Config {
self.rewarded_set_page_limit = limit;
pub fn with_simulated_gas_multiplier(mut self, gas_multiplier: f32) -> Self {
self.nyxd_config.simulated_gas_multiplier = gas_multiplier;
self
}
}
#[cfg(feature = "nyxd-client")]
pub struct Client<C> {
mixnode_page_limit: Option<u32>,
gateway_page_limit: Option<u32>,
mixnode_delegations_page_limit: Option<u32>,
rewarded_set_page_limit: Option<u32>,
pub struct Client<C, S = NoSigner> {
// ideally they would have been read-only, but unfortunately rust doesn't have such features
pub nym_api: nym_api::Client,
pub nyxd: NyxdClient<C>,
pub nyxd: NyxdClient<C, S>,
}
#[cfg(feature = "nyxd-client")]
impl Client<SigningNyxdClient<DirectSecp256k1HdWallet>> {
#[cfg(feature = "http-client")]
impl Client<HttpRpcClient, DirectSecp256k1HdWallet> {
pub fn new_signing(
config: Config,
mnemonic: bip39::Mnemonic,
) -> Result<Client<SigningNyxdClient<DirectSecp256k1HdWallet>>, ValidatorClientError> {
let nym_api_client = nym_api::Client::new(config.api_url.clone());
let nyxd_client = NyxdClient::connect_with_mnemonic(
config.nyxd_config.clone(),
config.nyxd_url.as_str(),
mnemonic,
None,
)?;
) -> Result<DirectSigningHttpRpcValidatorClient, ValidatorClientError> {
let rpc_client = http_client(config.nyxd_url.as_str())?;
let prefix = &config.nyxd_config.chain_details.bech32_account_prefix;
let wallet = DirectSecp256k1HdWallet::from_mnemonic(prefix, mnemonic);
Ok(Client {
mixnode_page_limit: config.mixnode_page_limit,
gateway_page_limit: config.gateway_page_limit,
mixnode_delegations_page_limit: config.mixnode_delegations_page_limit,
rewarded_set_page_limit: config.rewarded_set_page_limit,
nym_api: nym_api_client,
nyxd: nyxd_client,
})
Ok(Self::new_signing_with_rpc_client(
config, rpc_client, wallet,
))
}
pub fn change_nyxd(&mut self, new_endpoint: Url) -> Result<(), ValidatorClientError> {
self.nyxd.change_endpoint(new_endpoint.as_ref())?;
Ok(())
}
}
pub fn set_nyxd_simulated_gas_multiplier(&mut self, multiplier: f32) {
self.nyxd.set_simulated_gas_multiplier(multiplier)
impl Client<ReqwestRpcClient, DirectSecp256k1HdWallet> {
pub fn new_reqwest_signing(
config: Config,
mnemonic: bip39::Mnemonic,
) -> DirectSigningReqwestRpcValidatorClient {
let rpc_client = ReqwestRpcClient::new(config.nyxd_url.clone());
let prefix = &config.nyxd_config.chain_details.bech32_account_prefix;
let wallet = DirectSecp256k1HdWallet::from_mnemonic(prefix, mnemonic);
Self::new_signing_with_rpc_client(config, rpc_client, wallet)
}
}
#[cfg(feature = "nyxd-client")]
impl Client<QueryNyxdClient> {
pub fn new_query(config: Config) -> Result<Client<QueryNyxdClient>, ValidatorClientError> {
let nym_api_client = nym_api::Client::new(config.api_url.clone());
let nyxd_client =
NyxdClient::connect(config.nyxd_config.clone(), config.nyxd_url.as_str())?;
Ok(Client {
mixnode_page_limit: config.mixnode_page_limit,
gateway_page_limit: config.gateway_page_limit,
mixnode_delegations_page_limit: config.mixnode_delegations_page_limit,
rewarded_set_page_limit: config.rewarded_set_page_limit,
nym_api: nym_api_client,
nyxd: nyxd_client,
})
#[cfg(feature = "http-client")]
impl Client<HttpRpcClient> {
pub fn new_query(config: Config) -> Result<QueryHttpRpcValidatorClient, ValidatorClientError> {
let rpc_client = http_client(config.nyxd_url.as_str())?;
Ok(Self::new_with_rpc_client(config, rpc_client))
}
pub fn change_nyxd(&mut self, new_endpoint: Url) -> Result<(), ValidatorClientError> {
@@ -190,412 +138,44 @@ impl Client<QueryNyxdClient> {
}
}
// nyxd wrappers
#[cfg(feature = "nyxd-client")]
impl Client<ReqwestRpcClient> {
pub fn new_reqwest_query(config: Config) -> QueryReqwestRpcValidatorClient {
let rpc_client = ReqwestRpcClient::new(config.nyxd_url.clone());
Self::new_with_rpc_client(config, rpc_client)
}
}
impl<C> Client<C> {
// use case: somebody initialised client without a contract in order to upload and initialise one
// and now they want to actually use it without making new client
pub fn new_with_rpc_client(config: Config, rpc_client: C) -> Self {
let nym_api_client = nym_api::Client::new(config.api_url.clone());
pub fn set_mixnet_contract_address(&mut self, mixnet_contract_address: cosmrs::AccountId) {
self.nyxd
.set_mixnet_contract_address(mixnet_contract_address)
}
pub fn get_mixnet_contract_address(&self) -> cosmrs::AccountId {
self.nyxd.mixnet_contract_address().clone()
}
pub async fn get_all_node_families(&self) -> Result<Vec<Family>, ValidatorClientError>
where
C: CosmWasmClient + Sync + Send,
{
let mut families = Vec::new();
let mut start_after = None;
loop {
let paged_response = self
.nyxd
.get_all_node_families_paged(start_after.take(), None)
.await?;
families.extend(paged_response.families);
if let Some(start_after_res) = paged_response.start_next_after {
start_after = Some(start_after_res)
} else {
break;
}
Client {
nym_api: nym_api_client,
nyxd: NyxdClient::new(config.nyxd_config, rpc_client),
}
Ok(families)
}
}
pub async fn get_all_family_members(
&self,
) -> Result<Vec<(IdentityKey, FamilyHead)>, ValidatorClientError>
impl<C, S> Client<C, S> {
pub fn new_signing_with_rpc_client(config: Config, rpc_client: C, signer: S) -> Self
where
C: CosmWasmClient + Sync + Send,
S: OfflineSigner,
{
let mut members = Vec::new();
let mut start_after = None;
let nym_api_client = nym_api::Client::new(config.api_url.clone());
loop {
let paged_response = self
.nyxd
.get_all_family_members_paged(start_after.take(), None)
.await?;
members.extend(paged_response.members);
if let Some(start_after_res) = paged_response.start_next_after {
start_after = Some(start_after_res)
} else {
break;
}
Client {
nym_api: nym_api_client,
nyxd: NyxdClient::new_signing(config.nyxd_config, rpc_client, signer),
}
Ok(members)
}
// basically handles paging for us
pub async fn get_all_nyxd_rewarded_set_mixnodes(
&self,
) -> Result<Vec<(MixId, RewardedSetNodeStatus)>, ValidatorClientError>
where
C: CosmWasmClient + Sync + Send,
{
let mut identities = Vec::new();
let mut start_after = None;
loop {
let mut paged_response = self
.nyxd
.get_rewarded_set_paged(start_after.take(), self.rewarded_set_page_limit)
.await?;
identities.append(&mut paged_response.nodes);
if let Some(start_after_res) = paged_response.start_next_after {
start_after = Some(start_after_res)
} else {
break;
}
}
Ok(identities)
}
pub async fn get_all_nyxd_mixnode_bonds(&self) -> Result<Vec<MixNodeBond>, ValidatorClientError>
where
C: CosmWasmClient + Sync + Send,
{
let mut mixnodes = Vec::new();
let mut start_after = None;
loop {
let mut paged_response = self
.nyxd
.get_mixnode_bonds_paged(self.mixnode_page_limit, start_after.take())
.await?;
mixnodes.append(&mut paged_response.nodes);
if let Some(start_after_res) = paged_response.start_next_after {
start_after = Some(start_after_res)
} else {
break;
}
}
Ok(mixnodes)
}
pub async fn get_all_nyxd_mixnodes_detailed(
&self,
) -> Result<Vec<MixNodeDetails>, ValidatorClientError>
where
C: CosmWasmClient + Sync + Send,
{
let mut mixnodes = Vec::new();
let mut start_after = None;
loop {
let mut paged_response = self
.nyxd
.get_mixnodes_detailed_paged(self.mixnode_page_limit, start_after.take())
.await?;
mixnodes.append(&mut paged_response.nodes);
if let Some(start_after_res) = paged_response.start_next_after {
start_after = Some(start_after_res)
} else {
break;
}
}
Ok(mixnodes)
}
pub async fn get_all_nyxd_unbonded_mixnodes(
&self,
) -> Result<Vec<(MixId, UnbondedMixnode)>, ValidatorClientError>
where
C: CosmWasmClient + Sync + Send,
{
let mut mixnodes = Vec::new();
let mut start_after = None;
loop {
let mut paged_response = self
.nyxd
.get_unbonded_paged(self.mixnode_page_limit, start_after.take())
.await?;
mixnodes.append(&mut paged_response.nodes);
if let Some(start_after_res) = paged_response.start_next_after {
start_after = Some(start_after_res)
} else {
break;
}
}
Ok(mixnodes)
}
pub async fn get_all_nyxd_unbonded_mixnodes_by_owner(
&self,
owner: &cosmrs::AccountId,
) -> Result<Vec<(MixId, UnbondedMixnode)>, ValidatorClientError>
where
C: CosmWasmClient + Sync + Send,
{
let mut mixnodes = Vec::new();
let mut start_after = None;
loop {
let mut paged_response = self
.nyxd
.get_unbonded_by_owner_paged(owner, self.mixnode_page_limit, start_after.take())
.await?;
mixnodes.append(&mut paged_response.nodes);
if let Some(start_after_res) = paged_response.start_next_after {
start_after = Some(start_after_res)
} else {
break;
}
}
Ok(mixnodes)
}
pub async fn get_all_nyxd_unbonded_mixnodes_by_identity(
&self,
identity_key: String,
) -> Result<Vec<(MixId, UnbondedMixnode)>, ValidatorClientError>
where
C: CosmWasmClient + Sync + Send,
{
let mut mixnodes = Vec::new();
let mut start_after = None;
loop {
let mut paged_response = self
.nyxd
.get_unbonded_by_identity_paged(
identity_key.clone(),
self.mixnode_page_limit,
start_after.take(),
)
.await?;
mixnodes.append(&mut paged_response.nodes);
if let Some(start_after_res) = paged_response.start_next_after {
start_after = Some(start_after_res)
} else {
break;
}
}
Ok(mixnodes)
}
pub async fn get_all_nyxd_gateways(&self) -> Result<Vec<GatewayBond>, ValidatorClientError>
where
C: CosmWasmClient + Sync + Send,
{
let mut gateways = Vec::new();
let mut start_after = None;
loop {
let mut paged_response = self
.nyxd
.get_gateways_paged(start_after.take(), self.gateway_page_limit)
.await?;
gateways.append(&mut paged_response.nodes);
if let Some(start_after_res) = paged_response.start_next_after {
start_after = Some(start_after_res)
} else {
break;
}
}
Ok(gateways)
}
pub async fn get_all_nyxd_single_mixnode_delegations(
&self,
mix_id: MixId,
) -> Result<Vec<Delegation>, ValidatorClientError>
where
C: CosmWasmClient + Sync + Send,
{
let mut delegations = Vec::new();
let mut start_after = None;
loop {
let mut paged_response = self
.nyxd
.get_mixnode_delegations_paged(
mix_id,
start_after.take(),
self.mixnode_delegations_page_limit,
)
.await?;
delegations.append(&mut paged_response.delegations);
if let Some(start_after_res) = paged_response.start_next_after {
start_after = Some(start_after_res)
} else {
break;
}
}
Ok(delegations)
}
pub async fn get_all_delegator_delegations(
&self,
delegation_owner: &cosmrs::AccountId,
) -> Result<Vec<Delegation>, ValidatorClientError>
where
C: CosmWasmClient + Sync + Send,
{
let mut delegations = Vec::new();
let mut start_after = None;
loop {
let mut paged_response = self
.nyxd
.get_delegator_delegations_paged(
delegation_owner.to_string(),
start_after.take(),
self.mixnode_delegations_page_limit,
)
.await?;
delegations.append(&mut paged_response.delegations);
if let Some(start_after_res) = paged_response.start_next_after {
start_after = Some(start_after_res)
} else {
break;
}
}
Ok(delegations)
}
pub async fn get_all_network_delegations(&self) -> Result<Vec<Delegation>, ValidatorClientError>
where
C: CosmWasmClient + Sync + Send,
{
let mut delegations = Vec::new();
let mut start_after = None;
loop {
let mut paged_response = self
.nyxd
.get_all_network_delegations_paged(
start_after.take(),
self.mixnode_delegations_page_limit,
)
.await?;
delegations.append(&mut paged_response.delegations);
if let Some(start_after_res) = paged_response.start_next_after {
start_after = Some(start_after_res)
} else {
break;
}
}
Ok(delegations)
}
pub async fn get_all_nyxd_pending_epoch_events(
&self,
) -> Result<Vec<PendingEpochEvent>, ValidatorClientError>
where
C: CosmWasmClient + Sync + Send,
{
let mut events = Vec::new();
let mut start_after = None;
loop {
let mut paged_response = self
.nyxd
.get_pending_epoch_events_paged(start_after.take(), self.rewarded_set_page_limit)
.await?;
events.append(&mut paged_response.events);
if let Some(start_after_res) = paged_response.start_next_after {
start_after = Some(start_after_res)
} else {
break;
}
}
Ok(events)
}
pub async fn get_all_nyxd_pending_interval_events(
&self,
) -> Result<Vec<PendingIntervalEvent>, ValidatorClientError>
where
C: CosmWasmClient + Sync + Send,
{
let mut events = Vec::new();
let mut start_after = None;
loop {
let mut paged_response = self
.nyxd
.get_pending_interval_events_paged(start_after.take(), self.rewarded_set_page_limit)
.await?;
events.append(&mut paged_response.events);
if let Some(start_after_res) = paged_response.start_next_after {
start_after = Some(start_after_res)
} else {
break;
}
}
Ok(events)
}
pub async fn get_all_ephemera_peers(&self) -> Result<Vec<JsonPeerInfo>, ValidatorClientError>
where
C: CosmWasmClient + Sync + Send,
{
let mut peers = Vec::new();
let mut start_after = None;
loop {
let mut paged_response = self.get_peers_paged(start_after.take(), None).await?;
peers.append(&mut paged_response.peers);
if let Some(start_after_res) = paged_response.start_next_after {
start_after = Some(start_after_res.to_string())
} else {
break;
}
}
Ok(peers)
}
}
// validator-api wrappers
#[cfg(feature = "nyxd-client")]
impl<C> Client<C> {
impl<C, S> Client<C, S> {
pub fn api_url(&self) -> &Url {
self.nym_api.current_url()
}
pub fn change_nym_api(&mut self, new_endpoint: Url) {
self.nym_api.change_url(new_endpoint)
}
@@ -652,87 +232,46 @@ impl<C> Client<C> {
}
}
#[derive(Clone)]
pub struct CoconutApiClient {
pub api_client: NymApiClient,
pub verification_key: VerificationKey,
pub node_id: NodeIndex,
#[cfg(feature = "nyxd-client")]
pub cosmos_address: cosmrs::AccountId,
}
#[cfg(feature = "nyxd-client")]
impl CoconutApiClient {
pub async fn all_coconut_api_clients<C>(
client: &C,
epoch_id: EpochId,
) -> Result<Vec<Self>, ValidatorClientError>
where
C: DkgQueryClient + Sync + Send,
{
Ok(client
.get_all_verification_key_shares(epoch_id)
.await?
.into_iter()
.filter_map(Self::try_from)
.collect())
}
fn try_from(share: ContractVKShare) -> Option<Self> {
if share.verified {
if let Ok(url_address) = Url::parse(&share.announce_address) {
if let Ok(verification_key) = VerificationKey::try_from_bs58(&share.share) {
if let Ok(cosmos_address) = cosmrs::AccountId::from_str(share.owner.as_str()) {
return Some(CoconutApiClient {
api_client: NymApiClient::new(url_address),
verification_key,
node_id: share.node_index,
cosmos_address,
});
}
}
}
}
None
}
}
#[derive(Clone)]
pub struct NymApiClient {
pub nym_api_client: nym_api::Client,
pub nym_api: nym_api::Client,
// TODO: perhaps if we really need it at some (currently I don't see any reasons for it)
// we could re-implement the communication with the REST API on port 1317
}
impl NymApiClient {
pub fn new(api_url: Url) -> Self {
let nym_api_client = nym_api::Client::new(api_url);
let nym_api = nym_api::Client::new(api_url);
NymApiClient { nym_api_client }
NymApiClient { nym_api }
}
pub fn api_url(&self) -> &Url {
self.nym_api.current_url()
}
pub fn change_nym_api(&mut self, new_endpoint: Url) {
self.nym_api_client.change_url(new_endpoint);
self.nym_api.change_url(new_endpoint);
}
pub async fn get_cached_active_mixnodes(
&self,
) -> Result<Vec<MixNodeDetails>, ValidatorClientError> {
Ok(self.nym_api_client.get_active_mixnodes().await?)
Ok(self.nym_api.get_active_mixnodes().await?)
}
pub async fn get_cached_rewarded_mixnodes(
&self,
) -> Result<Vec<MixNodeDetails>, ValidatorClientError> {
Ok(self.nym_api_client.get_rewarded_mixnodes().await?)
Ok(self.nym_api.get_rewarded_mixnodes().await?)
}
pub async fn get_cached_mixnodes(&self) -> Result<Vec<MixNodeDetails>, ValidatorClientError> {
Ok(self.nym_api_client.get_mixnodes().await?)
Ok(self.nym_api.get_mixnodes().await?)
}
pub async fn get_cached_gateways(&self) -> Result<Vec<GatewayBond>, ValidatorClientError> {
Ok(self.nym_api_client.get_gateways().await?)
Ok(self.nym_api.get_gateways().await?)
}
pub async fn get_gateway_core_status_count(
@@ -741,7 +280,7 @@ impl NymApiClient {
since: Option<i64>,
) -> Result<GatewayCoreStatusResponse, ValidatorClientError> {
Ok(self
.nym_api_client
.nym_api
.get_gateway_core_status_count(identity, since)
.await?)
}
@@ -752,7 +291,7 @@ impl NymApiClient {
since: Option<i64>,
) -> Result<MixnodeCoreStatusResponse, ValidatorClientError> {
Ok(self
.nym_api_client
.nym_api
.get_mixnode_core_status_count(mix_id, since)
.await?)
}
@@ -761,34 +300,28 @@ impl NymApiClient {
&self,
mix_id: MixId,
) -> Result<MixnodeStatusResponse, ValidatorClientError> {
Ok(self.nym_api_client.get_mixnode_status(mix_id).await?)
Ok(self.nym_api.get_mixnode_status(mix_id).await?)
}
pub async fn get_mixnode_reward_estimation(
&self,
mix_id: MixId,
) -> Result<RewardEstimationResponse, ValidatorClientError> {
Ok(self
.nym_api_client
.get_mixnode_reward_estimation(mix_id)
.await?)
Ok(self.nym_api.get_mixnode_reward_estimation(mix_id).await?)
}
pub async fn get_mixnode_stake_saturation(
&self,
mix_id: MixId,
) -> Result<StakeSaturationResponse, ValidatorClientError> {
Ok(self
.nym_api_client
.get_mixnode_stake_saturation(mix_id)
.await?)
Ok(self.nym_api.get_mixnode_stake_saturation(mix_id).await?)
}
pub async fn blind_sign(
&self,
request_body: &BlindSignRequestBody,
) -> Result<BlindedSignatureResponse, ValidatorClientError> {
Ok(self.nym_api_client.blind_sign(request_body).await?)
Ok(self.nym_api.blind_sign(request_body).await?)
}
pub async fn verify_bandwidth_credential(
@@ -796,7 +329,7 @@ impl NymApiClient {
request_body: &VerifyCredentialBody,
) -> Result<VerifyCredentialResponse, ValidatorClientError> {
Ok(self
.nym_api_client
.nym_api
.verify_bandwidth_credential(request_body)
.await?)
}
@@ -0,0 +1,97 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::nyxd::contract_traits::{DkgQueryClient, PagedDkgQueryClient};
use crate::nyxd::error::NyxdError;
use crate::NymApiClient;
use nym_coconut_dkg_common::types::{EpochId, NodeIndex};
use nym_coconut_dkg_common::verification_key::ContractVKShare;
use nym_coconut_interface::{Base58, CoconutError, VerificationKey};
use thiserror::Error;
use url::Url;
// TODO: it really doesn't feel like this should live in this crate.
#[derive(Clone)]
pub struct CoconutApiClient {
pub api_client: NymApiClient,
pub verification_key: VerificationKey,
pub node_id: NodeIndex,
pub cosmos_address: cosmrs::AccountId,
}
// TODO: this should be using the coconut error
// (which is in different crate; perhaps this client should be moved there?)
#[derive(Debug, Error)]
pub enum CoconutApiError {
// TODO: ask @BN whether this is a correct error message
#[error("the provided key share hasn't been verified")]
UnverifiedShare,
#[error("failed to query the contract: {source}")]
ContractQueryFailure {
#[from]
source: NyxdError,
},
#[error("the provided announce address is malformed: {source}")]
MalformedAnnounceAddress {
#[from]
source: url::ParseError,
},
#[error("the provided verification key is malformed: {source}")]
MalformedVerificationKey {
#[from]
source: CoconutError,
},
#[error("the provided account address is malformed: {source}")]
MalformedAccountAddress {
#[from]
source: cosmrs::ErrorReport,
},
}
impl TryFrom<ContractVKShare> for CoconutApiClient {
type Error = CoconutApiError;
fn try_from(share: ContractVKShare) -> Result<Self, Self::Error> {
if !share.verified {
return Err(CoconutApiError::UnverifiedShare);
}
let url_address = Url::parse(&share.announce_address)?;
Ok(CoconutApiClient {
api_client: NymApiClient::new(url_address),
verification_key: VerificationKey::try_from_bs58(&share.share)?,
node_id: share.node_index,
cosmos_address: share.owner.as_str().parse()?,
})
}
}
pub async fn all_coconut_api_clients<C>(
client: &C,
epoch_id: EpochId,
) -> Result<Vec<CoconutApiClient>, CoconutApiError>
where
C: DkgQueryClient + Sync + Send,
{
// TODO: this will error out if there's an invalid share out there. is that what we want?
client
.get_all_verification_key_shares(epoch_id)
.await?
.into_iter()
.map(TryInto::try_into)
.collect::<Result<Vec<_>, _>>()
// ... if not, let's switch to the below:
// client
// .get_all_verification_key_shares(epoch_id)
// .await?
// .into_iter()
// .filter_map(TryInto::try_into)
// .collect::<Result<Vec<_>, _>>()
}
@@ -1,8 +1,7 @@
use crate::nyxd::contract_traits::MixnetQueryClient;
use crate::nyxd::error::NyxdError;
use crate::nyxd::{Config as ClientConfig, NyxdClient, QueryNyxdClient};
use crate::{NymApiClient, ValidatorClientError};
use crate::nyxd::traits::MixnetQueryClient;
use crate::nyxd::Config as ClientConfig;
use crate::{NymApiClient, QueryHttpRpcNyxdClient, ValidatorClientError};
use colored::Colorize;
use core::fmt;
use itertools::Itertools;
@@ -53,7 +52,7 @@ pub async fn test_nyxd_url_connection(
let config = ClientConfig::try_from_nym_network_details(&network)
.expect("failed to create valid nyxd client config");
let mut nyxd_client = NyxdClient::<QueryNyxdClient>::connect(config, nyxd_url.as_str())?;
let mut nyxd_client = QueryHttpRpcNyxdClient::connect(config, nyxd_url.as_str())?;
// possibly redundant, but lets just leave it here
nyxd_client.set_mixnet_contract_address(address);
match test_nyxd_connection(network, &nyxd_url, &nyxd_client).await {
@@ -75,7 +74,7 @@ fn setup_connection_tests<H: BuildHasher + 'static>(
let config = ClientConfig::try_from_nym_network_details(&network)
.expect("failed to create valid nyxd client config");
if let Ok(mut client) = NyxdClient::<QueryNyxdClient>::connect(config, url.as_str()) {
if let Ok(mut client) = QueryHttpRpcNyxdClient::connect(config, url.as_str()) {
// possibly redundant, but lets just leave it here
client.set_mixnet_contract_address(address);
Some(ClientForConnectionTest::Nyxd(
@@ -112,7 +111,7 @@ fn extract_and_collect_results_into_map(
async fn test_nyxd_connection(
network: NymNetworkDetails,
url: &Url,
client: &NyxdClient<QueryNyxdClient>,
client: &QueryHttpRpcNyxdClient,
) -> ConnectionResult {
let result = match timeout(
Duration::from_secs(CONNECTION_TEST_TIMEOUT_SEC),
@@ -120,7 +119,7 @@ async fn test_nyxd_connection(
)
.await
{
Ok(Err(NyxdError::TendermintError(e))) => {
Ok(Err(NyxdError::TendermintErrorRpc(e))) => {
// If we get a tendermint-rpc error, we classify the node as not contactable
log::warn!("Checking: nyxd url: {url}: {}: {}", "failed".red(), e);
false
@@ -186,7 +185,7 @@ async fn test_nym_api_connection(
}
enum ClientForConnectionTest {
Nyxd(NymNetworkDetails, Url, Box<NyxdClient<QueryNyxdClient>>),
Nyxd(NymNetworkDetails, Url, Box<QueryHttpRpcNyxdClient>),
Api(NymNetworkDetails, Url, NymApiClient),
}
@@ -2,6 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
use crate::nym_api;
pub use tendermint_rpc::error::Error as TendermintRpcError;
use thiserror::Error;
#[derive(Error, Debug)]
@@ -12,10 +13,12 @@ pub enum ValidatorClientError {
source: nym_api::error::NymAPIError,
},
#[error("Tendermint RPC request failure: {0}")]
TendermintErrorRpc(#[from] TendermintRpcError),
#[error("One of the provided URLs was malformed - {0}")]
MalformedUrlProvided(#[from] url::ParseError),
#[cfg(feature = "nyxd-client")]
#[error("nyxd request failed - {0}")]
NyxdError(#[from] crate::nyxd::error::NyxdError),
+33 -7
View File
@@ -1,20 +1,46 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
pub mod client;
#[cfg(feature = "nyxd-client")]
pub mod coconut;
#[cfg(feature = "http-client")]
pub mod connection_tester;
pub mod error;
pub mod nym_api;
#[cfg(feature = "nyxd-client")]
pub mod nyxd;
#[cfg(feature = "signing")]
pub mod rpc;
pub mod signing;
pub use crate::error::ValidatorClientError;
pub use crate::rpc::reqwest::ReqwestRpcClient;
pub use crate::signing::direct_wallet::DirectSecp256k1HdWallet;
pub use client::NymApiClient;
pub use client::{Client, CoconutApiClient, Config};
pub use nym_api_requests::*;
#[cfg(feature = "nyxd-client")]
pub use client::{Client, CoconutApiClient, Config};
#[cfg(feature = "http-client")]
pub use cosmrs::rpc::HttpClient as HttpRpcClient;
#[cfg(feature = "http-client")]
pub use rpc::http_client;
// some type aliasing
pub type ValidatorClient<C> = Client<C>;
pub type SigningValidatorClient<C, S> = Client<C, S>;
#[cfg(feature = "http-client")]
pub type QueryHttpRpcValidatorClient = Client<HttpRpcClient>;
#[cfg(feature = "http-client")]
pub type QueryHttpRpcNyxdClient = nyxd::NyxdClient<HttpRpcClient>;
#[cfg(feature = "http-client")]
pub type DirectSigningHttpRpcValidatorClient = Client<HttpRpcClient, DirectSecp256k1HdWallet>;
#[cfg(feature = "http-client")]
pub type DirectSigningHttpRpcNyxdClient = nyxd::NyxdClient<HttpRpcClient, DirectSecp256k1HdWallet>;
pub type QueryReqwestRpcValidatorClient = Client<ReqwestRpcClient>;
pub type QueryReqwestRpcNyxdClient = nyxd::NyxdClient<ReqwestRpcClient>;
pub type DirectSigningReqwestRpcValidatorClient = Client<ReqwestRpcClient, DirectSecp256k1HdWallet>;
pub type DirectSigningReqwestRpcNyxdClient =
nyxd::NyxdClient<ReqwestRpcClient, DirectSecp256k1HdWallet>;
@@ -7,11 +7,11 @@ use nym_api_requests::coconut::{
BlindSignRequestBody, BlindedSignatureResponse, VerifyCredentialBody, VerifyCredentialResponse,
};
use nym_api_requests::models::{
ComputeRewardEstParam, GatewayCoreStatusResponse, GatewayStatusReportResponse,
GatewayUptimeHistoryResponse, InclusionProbabilityResponse, MixNodeBondAnnotated,
MixnodeCoreStatusResponse, MixnodeStatusReportResponse, MixnodeStatusResponse,
MixnodeUptimeHistoryResponse, RequestError, RewardEstimationResponse, StakeSaturationResponse,
UptimeResponse,
ComputeRewardEstParam, GatewayBondAnnotated, GatewayCoreStatusResponse,
GatewayStatusReportResponse, GatewayUptimeHistoryResponse, InclusionProbabilityResponse,
MixNodeBondAnnotated, MixnodeCoreStatusResponse, MixnodeStatusReportResponse,
MixnodeStatusResponse, MixnodeUptimeHistoryResponse, RequestError, RewardEstimationResponse,
StakeSaturationResponse, UptimeResponse,
};
use nym_mixnet_contract_common::mixnode::MixNodeDetails;
use nym_mixnet_contract_common::{GatewayBond, IdentityKeyRef, MixId};
@@ -148,6 +148,19 @@ impl Client {
.await
}
pub async fn get_gateways_detailed(&self) -> Result<Vec<GatewayBondAnnotated>, NymAPIError> {
self.query_nym_api(
&[
routes::API_VERSION,
routes::STATUS,
routes::GATEWAYS,
routes::DETAILED,
],
NO_PARAMS,
)
.await
}
pub async fn get_mixnodes_detailed_unfiltered(
&self,
) -> Result<Vec<MixNodeBondAnnotated>, NymAPIError> {
@@ -52,7 +52,6 @@ impl<'a> Div<GasPrice> for &'a Coin {
} else {
implicit_gas_limit.u128() as u64
}
.into()
}
}
@@ -191,32 +190,32 @@ mod tests {
let amount = Coin::new(3938, "unym");
let gas_price = "0.025unym".parse().unwrap();
let res = amount / gas_price;
assert_eq!(157520, res.value());
assert_eq!(157520, res);
let amount = Coin::new(1234567890, "unym");
let gas_price = "0.025unym".parse().unwrap();
let res = amount / gas_price;
assert_eq!(49382715600, res.value());
assert_eq!(49382715600, res);
let amount = Coin::new(1, "unym");
let gas_price = "0.025unym".parse().unwrap();
let res = amount / gas_price;
assert_eq!(40, res.value());
assert_eq!(40, res);
let amount = Coin::new(150_000_000, "unym");
let gas_price = "0.001234unym".parse().unwrap();
let res = amount / gas_price;
assert_eq!(121555915721, res.value());
assert_eq!(121555915721, res);
let amount = Coin::new(150_000_000, "unym");
let gas_price = "1unym".parse().unwrap();
let res = amount / gas_price;
assert_eq!(150_000_000, res.value());
assert_eq!(150_000_000, res);
let amount = Coin::new(150_000_000, "unym");
let gas_price = "1234.56unym".parse().unwrap();
let res = amount / gas_price;
assert_eq!(121500, res.value());
assert_eq!(121500, res);
}
#[test]
@@ -0,0 +1,100 @@
// Copyright 2022-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::collect_paged;
use crate::nyxd::contract_traits::NymContractsProvider;
use crate::nyxd::error::NyxdError;
use crate::nyxd::CosmWasmClient;
use async_trait::async_trait;
use nym_coconut_bandwidth_contract_common::msg::QueryMsg as CoconutBandwidthQueryMsg;
use nym_coconut_bandwidth_contract_common::spend_credential::{
PagedSpendCredentialResponse, SpendCredential, SpendCredentialResponse,
};
use serde::Deserialize;
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
pub trait CoconutBandwidthQueryClient {
async fn query_coconut_bandwidth_contract<T>(
&self,
query: CoconutBandwidthQueryMsg,
) -> Result<T, NyxdError>
where
for<'a> T: Deserialize<'a>;
async fn get_spent_credential(
&self,
blinded_serial_number: String,
) -> Result<SpendCredentialResponse, NyxdError> {
self.query_coconut_bandwidth_contract(CoconutBandwidthQueryMsg::GetSpentCredential {
blinded_serial_number,
})
.await
}
async fn get_all_spent_credential_paged(
&self,
start_after: Option<String>,
limit: Option<u32>,
) -> Result<PagedSpendCredentialResponse, NyxdError> {
self.query_coconut_bandwidth_contract(CoconutBandwidthQueryMsg::GetAllSpentCredentials {
limit,
start_after,
})
.await
}
}
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
pub trait PagedCoconutBandwidthQueryClient: CoconutBandwidthQueryClient {
async fn get_all_spent_credentials(&self) -> Result<Vec<SpendCredential>, NyxdError> {
collect_paged!(self, get_all_spent_credential_paged, spend_credentials)
}
}
#[async_trait]
impl<T> PagedCoconutBandwidthQueryClient for T where T: CoconutBandwidthQueryClient {}
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
impl<C> CoconutBandwidthQueryClient for C
where
C: CosmWasmClient + NymContractsProvider + Send + Sync,
{
async fn query_coconut_bandwidth_contract<T>(
&self,
query: CoconutBandwidthQueryMsg,
) -> Result<T, NyxdError>
where
for<'a> T: Deserialize<'a>,
{
let coconut_bandwidth_contract_address = self
.coconut_bandwidth_contract_address()
.ok_or_else(|| NyxdError::unavailable_contract_address("coconut bandwidth contract"))?;
self.query_contract_smart(coconut_bandwidth_contract_address, &query)
.await
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::nyxd::contract_traits::tests::IgnoreValue;
// it's enough that this compiles and clippy is happy about it
#[allow(dead_code)]
fn all_query_variants_are_covered<C: CoconutBandwidthQueryClient + Send + Sync>(
client: C,
msg: CoconutBandwidthQueryMsg,
) {
match msg {
CoconutBandwidthQueryMsg::GetSpentCredential {
blinded_serial_number,
} => client.get_spent_credential(blinded_serial_number).ignore(),
CoconutBandwidthQueryMsg::GetAllSpentCredentials { limit, start_after } => client
.get_all_spent_credential_paged(start_after, limit)
.ignore(),
};
}
}
@@ -0,0 +1,153 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::nyxd::contract_traits::NymContractsProvider;
use crate::nyxd::cosmwasm_client::types::ExecuteResult;
use crate::nyxd::error::NyxdError;
use crate::nyxd::{Coin, Fee, SigningCosmWasmClient};
use crate::signing::signer::OfflineSigner;
use async_trait::async_trait;
use nym_coconut_bandwidth_contract_common::spend_credential::SpendCredentialData;
use nym_coconut_bandwidth_contract_common::{
deposit::DepositData, msg::ExecuteMsg as CoconutBandwidthExecuteMsg,
};
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
pub trait CoconutBandwidthSigningClient {
async fn execute_coconut_bandwidth_contract(
&self,
fee: Option<Fee>,
msg: CoconutBandwidthExecuteMsg,
memo: String,
funds: Vec<Coin>,
) -> Result<ExecuteResult, NyxdError>;
async fn deposit(
&self,
amount: Coin,
info: String,
verification_key: String,
encryption_key: String,
fee: Option<Fee>,
) -> Result<ExecuteResult, NyxdError> {
let req = CoconutBandwidthExecuteMsg::DepositFunds {
data: DepositData::new(info.to_string(), verification_key, encryption_key),
};
self.execute_coconut_bandwidth_contract(
fee,
req,
"CoconutBandwidth::Deposit".to_string(),
vec![amount],
)
.await
}
async fn spend_credential(
&self,
funds: Coin,
blinded_serial_number: String,
gateway_cosmos_address: String,
fee: Option<Fee>,
) -> Result<ExecuteResult, NyxdError> {
let req = CoconutBandwidthExecuteMsg::SpendCredential {
data: SpendCredentialData::new(
funds.into(),
blinded_serial_number,
gateway_cosmos_address,
),
};
self.execute_coconut_bandwidth_contract(
fee,
req,
"CoconutBandwidth::SpendCredential".to_string(),
vec![],
)
.await
}
async fn release_funds(
&self,
amount: Coin,
fee: Option<Fee>,
) -> Result<ExecuteResult, NyxdError> {
self.execute_coconut_bandwidth_contract(
fee,
CoconutBandwidthExecuteMsg::ReleaseFunds {
funds: amount.into(),
},
"CoconutBandwidth::ReleaseFunds".to_string(),
vec![],
)
.await
}
}
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
impl<C> CoconutBandwidthSigningClient for C
where
C: SigningCosmWasmClient + NymContractsProvider + Sync,
NyxdError: From<<Self as OfflineSigner>::Error>,
{
async fn execute_coconut_bandwidth_contract(
&self,
fee: Option<Fee>,
msg: CoconutBandwidthExecuteMsg,
memo: String,
funds: Vec<Coin>,
) -> Result<ExecuteResult, NyxdError> {
let coconut_bandwidth_contract_address = self
.coconut_bandwidth_contract_address()
.ok_or_else(|| NyxdError::unavailable_contract_address("coconut bandwidth contract"))?;
let fee = fee.unwrap_or(Fee::Auto(Some(self.simulated_gas_multiplier())));
let signer_address = &self.signer_addresses()?[0];
self.execute(
signer_address,
coconut_bandwidth_contract_address,
&msg,
fee,
memo,
funds,
)
.await
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::nyxd::contract_traits::tests::{mock_coin, IgnoreValue};
// it's enough that this compiles and clippy is happy about it
#[allow(dead_code)]
fn all_execute_variants_are_covered<C: CoconutBandwidthSigningClient + Send + Sync>(
client: C,
msg: CoconutBandwidthExecuteMsg,
) {
match msg {
CoconutBandwidthExecuteMsg::DepositFunds { data } => client
.deposit(
mock_coin(),
data.deposit_info().to_string(),
data.identity_key().to_string(),
data.encryption_key().to_string(),
None,
)
.ignore(),
CoconutBandwidthExecuteMsg::SpendCredential { data } => client
.spend_credential(
mock_coin(),
data.blinded_serial_number().to_string(),
data.gateway_cosmos_address().to_string(),
None,
)
.ignore(),
CoconutBandwidthExecuteMsg::ReleaseFunds { funds } => {
client.release_funds(funds.into(), None).ignore()
}
};
}
}
@@ -0,0 +1,182 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::collect_paged;
use crate::nyxd::contract_traits::NymContractsProvider;
use crate::nyxd::error::NyxdError;
use crate::nyxd::CosmWasmClient;
use async_trait::async_trait;
use cosmrs::AccountId;
use nym_coconut_dkg_common::dealer::{
ContractDealing, DealerDetailsResponse, PagedDealerResponse, PagedDealingsResponse,
};
use nym_coconut_dkg_common::msg::QueryMsg as DkgQueryMsg;
use nym_coconut_dkg_common::types::{DealerDetails, Epoch, EpochId, InitialReplacementData};
use nym_coconut_dkg_common::verification_key::{ContractVKShare, PagedVKSharesResponse};
use serde::Deserialize;
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
pub trait DkgQueryClient {
async fn query_dkg_contract<T>(&self, query: DkgQueryMsg) -> Result<T, NyxdError>
where
for<'a> T: Deserialize<'a>;
async fn get_current_epoch(&self) -> Result<Epoch, NyxdError> {
let request = DkgQueryMsg::GetCurrentEpochState {};
self.query_dkg_contract(request).await
}
async fn get_current_epoch_threshold(&self) -> Result<Option<u64>, NyxdError> {
let request = DkgQueryMsg::GetCurrentEpochThreshold {};
self.query_dkg_contract(request).await
}
async fn get_initial_dealers(&self) -> Result<Option<InitialReplacementData>, NyxdError> {
let request = DkgQueryMsg::GetInitialDealers {};
self.query_dkg_contract(request).await
}
async fn get_dealer_details(
&self,
address: &AccountId,
) -> Result<DealerDetailsResponse, NyxdError> {
let request = DkgQueryMsg::GetDealerDetails {
dealer_address: address.to_string(),
};
self.query_dkg_contract(request).await
}
async fn get_current_dealers_paged(
&self,
start_after: Option<String>,
limit: Option<u32>,
) -> Result<PagedDealerResponse, NyxdError> {
let request = DkgQueryMsg::GetCurrentDealers { start_after, limit };
self.query_dkg_contract(request).await
}
async fn get_past_dealers_paged(
&self,
start_after: Option<String>,
limit: Option<u32>,
) -> Result<PagedDealerResponse, NyxdError> {
let request = DkgQueryMsg::GetPastDealers { start_after, limit };
self.query_dkg_contract(request).await
}
async fn get_dealings_paged(
&self,
idx: u64,
start_after: Option<String>,
limit: Option<u32>,
) -> Result<PagedDealingsResponse, NyxdError> {
let request = DkgQueryMsg::GetDealing {
idx,
limit,
start_after,
};
self.query_dkg_contract(request).await
}
async fn get_vk_shares_paged(
&self,
epoch_id: EpochId,
start_after: Option<String>,
limit: Option<u32>,
) -> Result<PagedVKSharesResponse, NyxdError> {
let request = DkgQueryMsg::GetVerificationKeys {
epoch_id,
limit,
start_after,
};
self.query_dkg_contract(request).await
}
}
// extension trait to the query client to deal with the paged queries
// (it didn't feel appropriate to combine it with the existing trait
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
pub trait PagedDkgQueryClient: DkgQueryClient {
async fn get_all_current_dealers(&self) -> Result<Vec<DealerDetails>, NyxdError> {
collect_paged!(self, get_current_dealers_paged, dealers)
}
async fn get_all_past_dealers(&self) -> Result<Vec<DealerDetails>, NyxdError> {
collect_paged!(self, get_past_dealers_paged, dealers)
}
async fn get_all_epoch_dealings(&self, idx: u64) -> Result<Vec<ContractDealing>, NyxdError> {
collect_paged!(self, get_dealings_paged, dealings, idx)
}
async fn get_all_verification_key_shares(
&self,
epoch_id: EpochId,
) -> Result<Vec<ContractVKShare>, NyxdError> {
collect_paged!(self, get_vk_shares_paged, shares, epoch_id)
}
}
#[async_trait]
impl<T> PagedDkgQueryClient for T where T: DkgQueryClient {}
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
impl<C> DkgQueryClient for C
where
C: CosmWasmClient + NymContractsProvider + Send + Sync,
{
async fn query_dkg_contract<T>(&self, query: DkgQueryMsg) -> Result<T, NyxdError>
where
for<'a> T: Deserialize<'a>,
{
let dkg_contract_address = &self
.dkg_contract_address()
.ok_or_else(|| NyxdError::unavailable_contract_address("dkg contract"))?;
self.query_contract_smart(dkg_contract_address, &query)
.await
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::nyxd::contract_traits::tests::IgnoreValue;
// it's enough that this compiles and clippy is happy about it
#[allow(dead_code)]
fn all_query_variants_are_covered<C: DkgQueryClient + Send + Sync>(
client: C,
msg: DkgQueryMsg,
) {
match msg {
DkgQueryMsg::GetCurrentEpochState {} => client.get_current_epoch().ignore(),
DkgQueryMsg::GetCurrentEpochThreshold {} => {
client.get_current_epoch_threshold().ignore()
}
DkgQueryMsg::GetInitialDealers {} => client.get_initial_dealers().ignore(),
DkgQueryMsg::GetDealerDetails { dealer_address } => client
.get_dealer_details(&dealer_address.parse().unwrap())
.ignore(),
DkgQueryMsg::GetCurrentDealers { limit, start_after } => client
.get_current_dealers_paged(start_after, limit)
.ignore(),
DkgQueryMsg::GetPastDealers { limit, start_after } => {
client.get_past_dealers_paged(start_after, limit).ignore()
}
DkgQueryMsg::GetDealing {
idx,
limit,
start_after,
} => client.get_dealings_paged(idx, start_after, limit).ignore(),
DkgQueryMsg::GetVerificationKeys {
epoch_id,
limit,
start_after,
} => client
.get_vk_shares_paged(epoch_id, start_after, limit)
.ignore(),
};
}
}
@@ -0,0 +1,176 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::nyxd::contract_traits::NymContractsProvider;
use crate::nyxd::cosmwasm_client::types::ExecuteResult;
use crate::nyxd::error::NyxdError;
use crate::nyxd::{Coin, Fee, SigningCosmWasmClient};
use crate::signing::signer::OfflineSigner;
use async_trait::async_trait;
use cosmrs::AccountId;
use cosmwasm_std::Addr;
use nym_coconut_dkg_common::msg::ExecuteMsg as DkgExecuteMsg;
use nym_coconut_dkg_common::types::EncodedBTEPublicKeyWithProof;
use nym_coconut_dkg_common::verification_key::VerificationKeyShare;
use nym_contracts_common::dealings::ContractSafeBytes;
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
pub trait DkgSigningClient {
async fn execute_dkg_contract(
&self,
fee: Option<Fee>,
msg: DkgExecuteMsg,
memo: String,
funds: Vec<Coin>,
) -> Result<ExecuteResult, NyxdError>;
async fn advance_dkg_epoch_state(&self, fee: Option<Fee>) -> Result<ExecuteResult, NyxdError> {
let req = DkgExecuteMsg::AdvanceEpochState {};
self.execute_dkg_contract(fee, req, "advancing DKG state".to_string(), vec![])
.await
}
async fn surpass_threshold(&self, fee: Option<Fee>) -> Result<ExecuteResult, NyxdError> {
let req = DkgExecuteMsg::SurpassedThreshold {};
self.execute_dkg_contract(fee, req, "surpass DKG threshold".to_string(), vec![])
.await
}
async fn register_dealer(
&self,
bte_key: EncodedBTEPublicKeyWithProof,
announce_address: String,
resharing: bool,
fee: Option<Fee>,
) -> Result<ExecuteResult, NyxdError> {
let req = DkgExecuteMsg::RegisterDealer {
bte_key_with_proof: bte_key,
announce_address,
resharing,
};
self.execute_dkg_contract(fee, req, "registering as a dealer".to_string(), vec![])
.await
}
async fn submit_dealing_bytes(
&self,
dealing_bytes: ContractSafeBytes,
resharing: bool,
fee: Option<Fee>,
) -> Result<ExecuteResult, NyxdError> {
let req = DkgExecuteMsg::CommitDealing {
dealing_bytes,
resharing,
};
self.execute_dkg_contract(fee, req, "dealing commitment".to_string(), vec![])
.await
}
async fn submit_verification_key_share(
&self,
share: VerificationKeyShare,
resharing: bool,
fee: Option<Fee>,
) -> Result<ExecuteResult, NyxdError> {
let req = DkgExecuteMsg::CommitVerificationKeyShare { share, resharing };
self.execute_dkg_contract(
fee,
req,
"verification key share commitment".to_string(),
vec![],
)
.await
}
async fn verify_verification_key_share(
&self,
owner: &AccountId,
resharing: bool,
fee: Option<Fee>,
) -> Result<ExecuteResult, NyxdError> {
// the call to unchecked is fine as we're converting from pre-validated `AccountId`
let owner = Addr::unchecked(owner.to_string());
let req = DkgExecuteMsg::VerifyVerificationKeyShare { owner, resharing };
self.execute_dkg_contract(
fee,
req,
"verification key VerifyVerificationKeyShare".to_string(),
vec![],
)
.await
}
}
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
impl<C> DkgSigningClient for C
where
C: SigningCosmWasmClient + NymContractsProvider + Sync,
NyxdError: From<<Self as OfflineSigner>::Error>,
{
async fn execute_dkg_contract(
&self,
fee: Option<Fee>,
msg: DkgExecuteMsg,
memo: String,
funds: Vec<Coin>,
) -> Result<ExecuteResult, NyxdError> {
let dkg_contract_address = self
.dkg_contract_address()
.ok_or_else(|| NyxdError::unavailable_contract_address("dkg contract"))?;
let fee = fee.unwrap_or(Fee::Auto(Some(self.simulated_gas_multiplier())));
let signer_address = &self.signer_addresses()?[0];
self.execute(signer_address, dkg_contract_address, &msg, fee, memo, funds)
.await
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::nyxd::contract_traits::tests::IgnoreValue;
// it's enough that this compiles and clippy is happy about it
#[allow(dead_code)]
fn all_execute_variants_are_covered<C: DkgSigningClient + Send + Sync>(
client: C,
msg: DkgExecuteMsg,
) {
match msg {
DkgExecuteMsg::RegisterDealer {
bte_key_with_proof,
announce_address,
resharing,
} => client
.register_dealer(bte_key_with_proof, announce_address, resharing, None)
.ignore(),
DkgExecuteMsg::CommitDealing {
dealing_bytes,
resharing,
} => client
.submit_dealing_bytes(dealing_bytes, resharing, None)
.ignore(),
DkgExecuteMsg::CommitVerificationKeyShare { share, resharing } => client
.submit_verification_key_share(share, resharing, None)
.ignore(),
DkgExecuteMsg::VerifyVerificationKeyShare { owner, resharing } => client
.verify_verification_key_share(
&owner.into_string().parse().unwrap(),
resharing,
None,
)
.ignore(),
DkgExecuteMsg::SurpassedThreshold {} => client.surpass_threshold(None).ignore(),
DkgExecuteMsg::AdvanceEpochState {} => client.advance_dkg_epoch_state(None).ignore(),
};
}
}

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