Compare commits

...

103 Commits

Author SHA1 Message Date
Tommy Verrall 7644a48c23 Update ci-build-upload-binaries.yml 2024-07-04 09:54:12 +02:00
Jon Häggblad 6078787daa Remove constructor since it's weakly typed (#4689) 2024-07-03 12:26:47 +02:00
Jon Häggblad 6d93f36c82 Fix NR config compatibility (#4690)
* Make NR able to read config with old keys in

We removed stuff related to the old statistics service, so we ignore
unknown fields to be nice to our users

* Remove deleted config keys from NR template
2024-07-03 12:10:41 +02:00
import this e65e611859 remove roles selection on blacklisting node - PR done (#4687) 2024-07-02 13:37:23 +01:00
import this 4a25725a11 README.md update (#4685)
* start README update

* test alpha on github preview

* test alpha on github preview

* comment out rewards

* finish README update
2024-07-01 16:27:59 +02:00
Jon Häggblad d34c829174 Create UserAgent that can be passed from the binary to the nym api client (#4677)
* Create UserAgent that can be passed from the binary to the nym api client

* TryFrom for UserAgent to HeaderValue

* Add user agent for getting the list of gateways

* Fix wasm client

* Move clap behind feature flag in bin-common

* Implement conversion to UserAgent

* Set user_agent on base client in native and socks5 clients

* Set user agent in socks5-listener lib

* wip

* wip

* Deserialize cargo_triple to unknown by default

* Abbreviate git hash

* Remove unused import

* Add missing dep, and remove dbg statements

* Reorder string representation

* Remove commented out code

* Revert temporary log level change
2024-07-01 13:29:10 +02:00
Jędrzej Stuczyński 6963ead65a minor cleanup 2024-07-01 08:25:31 +01:00
Jon Häggblad 0425cdeaf0 Merge pull request #4680 from nymtech/jon/deps-to-workspace
Move and whole bump of crates to workspace and upgrade some
2024-06-27 13:25:21 +02:00
import this 789914b096 [DOCs/operators]: Updates v2024.6-chomp and T&Cs (#4674)
* initialise updates and ToC

* add toc flag

* changelog and node black-xit improvement

* add node-api-check option

* syntax fix

* syntax fix

* change CI/CD with git reset

* fix typo

* add T&C AMA explanation link - ready for review

* fix typo

* resolve review comments

* add ToC standalone page

* minor edit - ready to go
2024-06-27 09:59:57 +00:00
Jon Häggblad 8acd3a0975 Move a few more deps partially to workspace 2024-06-27 10:52:15 +02:00
Jon Häggblad fa1519ec6a Move itertools to workspace deps 2024-06-27 10:52:15 +02:00
Jon Häggblad da94b7e8df Sort list 2024-06-27 10:52:15 +02:00
Jon Häggblad 4aa8cb4647 Move dalek and rand_chacha crates to workspace 2024-06-27 10:52:15 +02:00
Jon Häggblad 5d13538508 Use workspace base64 dep 2024-06-27 10:52:15 +02:00
Jon Häggblad 4bbbcf629d Fix warning for default_features 2024-06-27 10:52:15 +02:00
Jon Häggblad 34ef970fd8 Move dirs 4.0 to workspace deps 2024-06-27 10:52:14 +02:00
Jon Häggblad fec570613c Remove code that refers to removed nym-network-statistics (#4679)
* Remove nym-network-statistics from workspace

* Remove nym-network-statistics

* Cargo.lock

* Update ci workflow

* Remove code that refers to removed nym-network-statistics

* Remove more

* Remove nym-statistics-common

* Delete commented out modules

* Remove commented out code

* Remove more commented out code

* Remove more commented out stuff

* Remove unused function
2024-06-27 10:32:32 +02:00
Jon Häggblad 14a904eff0 Remove nym-network-statistics (#4678)
* Remove nym-network-statistics from workspace

* Remove nym-network-statistics

* Cargo.lock

* Update ci workflow
2024-06-27 10:32:09 +02:00
benedetta davico 24ffb8fe8c Merge pull request #4675 from nymtech/release/2024.6-chomp
Release/2024.6-chomp to develop
2024-06-26 12:15:52 +02:00
import this d1bf1f2005 [DOCs/operators]: Guides to improve operator tooling and debugging (#4673)
* initialise node api check guide

* syntax edits

* spell check
2024-06-26 09:55:19 +00:00
import this c42b3f7617 Python CLI to self diagnose Nym nodes (#4606)
* initialised node_api_check CLI

* add swagger data

* print all stats as dicts - first one needs a tweak

* gateways and mixnodes return all dictionaries

* finish basic functionality of returning all data as dicts - need moe functions

* add --no_routing_history and --markdown options

* add error message

* initialise version count command

* version count work - missing error checks

* separate swagger query - need tweak for old mixnodes

* implement output function

* finished - ready for review

* simplify swagger request

* simplify error log

* address review - ping swagger/error solved

* finished version for review

* finished and cleaned - ready for review
2024-06-26 09:54:43 +00:00
benedetta davico 606144dd87 Update CHANGELOG.md 2024-06-25 09:51:20 +02:00
Tommy Verrall a5bcbcc1f5 Update publish-nym-binaries.yml
remove unused binaries for publishing
2024-06-25 09:28:11 +02:00
Tommy Verrall 31cd62b676 Merge pull request #4672 from nymtech/dependabot/npm_and_yarn/wasm/mix-fetch/internal-dev/braces-3.0.3
Bump braces from 3.0.2 to 3.0.3 in /wasm/mix-fetch/internal-dev
2024-06-24 14:06:40 +02:00
dependabot[bot] 53366c4151 Bump braces from 3.0.2 to 3.0.3 in /wasm/mix-fetch/internal-dev
Bumps [braces](https://github.com/micromatch/braces) from 3.0.2 to 3.0.3.
- [Changelog](https://github.com/micromatch/braces/blob/master/CHANGELOG.md)
- [Commits](https://github.com/micromatch/braces/compare/3.0.2...3.0.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-21 12:40:59 +00:00
Jędrzej Stuczyński 2ca63a6fd5 Merge pull request #4671 from nymtech/feature/embedded-ignore-score
make embedded NR/IPR ignore performance of the gateway
2024-06-21 10:50:15 +01:00
Jędrzej Stuczyński d33baec79b clippy 2024-06-21 10:41:33 +01:00
Jędrzej Stuczyński 0626e54b6a make embedded NR/IPR ignore performance of the gateway 2024-06-21 10:03:24 +01:00
Drazen Urch 2a260d46f8 New clippy lints (#4660)
* New clippy lints

* I guess this got removed
2024-06-21 10:02:29 +01:00
Tommy Verrall 7cb5afdeab Merge pull request #4661 from edcalderon/patch-3
Update setup.md
2024-06-21 09:29:35 +02:00
Tommy Verrall d18f4c0380 Merge pull request #4665 from nymtech/dependabot/npm_and_yarn/wasm/client/internal-dev-node/ws-8.17.1
Bump ws from 8.13.0 to 8.17.1 in /wasm/client/internal-dev-node
2024-06-21 09:28:58 +02:00
Yana Matrosova c9c4059c90 Update Gateway and NR in mixFetch docs (#4669)
* Update Gateway and NR in mixFetch docs

---------

Co-authored-by: Yana <yanok87@users.noreply.github.com>
2024-06-20 20:40:56 +02:00
Zane Schepke 3fe33dec8b Merge pull request #4670 from nymtech/zane/expiry-on-import
add expiry returned on import
2024-06-20 09:21:24 -04:00
Zane Schepke 589074360d change to OffsetDateTime 2024-06-20 09:16:05 -04:00
Zane Schepke 2e5406692c add expiry returned on import 2024-06-20 07:00:48 -04:00
Jędrzej Stuczyński 1920177b2f Merge pull request #4666 from nymtech/jstuczyn-patch-1
[bugfix] missing rustls feature
2024-06-19 09:03:45 +01:00
Jędrzej Stuczyński f562433519 [bugfix] missing rustls feature
it just happens to work due to feature-unification. it should probably have this feature by itself.
2024-06-18 16:29:07 +01:00
dependabot[bot] 2affa76304 Bump ws from 8.13.0 to 8.17.1 in /wasm/client/internal-dev-node
Bumps [ws](https://github.com/websockets/ws) from 8.13.0 to 8.17.1.
- [Release notes](https://github.com/websockets/ws/releases)
- [Commits](https://github.com/websockets/ws/compare/8.13.0...8.17.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-18 14:28:26 +00:00
Tommy Verrall d6aeb9142f Merge pull request #4662 from nymtech/dependabot/npm_and_yarn/sdk/typescript/packages/nodejs-client/ws-8.17.1
Bump ws from 8.14.2 to 8.17.1 in /sdk/typescript/packages/nodejs-client
2024-06-18 10:41:50 +02:00
Tommy Verrall 70af84b6b1 Merge pull request #4663 from nymtech/dependabot/npm_and_yarn/clients/native/examples/js-examples/websocket/braces-3.0.3
Bump braces from 3.0.2 to 3.0.3 in /clients/native/examples/js-examples/websocket
2024-06-18 10:14:52 +02:00
dependabot[bot] fc397053c8 Bump braces in /clients/native/examples/js-examples/websocket
Bumps [braces](https://github.com/micromatch/braces) from 3.0.2 to 3.0.3.
- [Changelog](https://github.com/micromatch/braces/blob/master/CHANGELOG.md)
- [Commits](https://github.com/micromatch/braces/compare/3.0.2...3.0.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-18 07:03:57 +00:00
dependabot[bot] 3092c8e68e Bump ws from 8.14.2 to 8.17.1 in /sdk/typescript/packages/nodejs-client
Bumps [ws](https://github.com/websockets/ws) from 8.14.2 to 8.17.1.
- [Release notes](https://github.com/websockets/ws/releases)
- [Commits](https://github.com/websockets/ws/compare/8.14.2...8.17.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-18 00:56:03 +00:00
Edward Calderon 4a1efab5c8 Update setup.md
unexpected argument 'true' found
2024-06-17 14:43:15 -05:00
Drazen Urch a2d57f269d New clippy lints (#4660)
* New clippy lints

* I guess this got removed
2024-06-17 15:29:19 +02:00
import this 38c4cc3345 minor syntax edits - the PR is finished for review (#4657) 2024-06-17 12:18:21 +00:00
Jędrzej Stuczyński 06ebe56914 Merge pull request #4654 from nymtech/chore/rename-accept-toc-flag
renamed 'accept-toc' flag and fields into explicit 'accept-operator-terms-and-conditions'
2024-06-17 11:31:41 +01:00
Jędrzej Stuczyński 1c3140898f fixed warning message 2024-06-17 10:09:05 +01:00
Tommy Verrall 6005bf6101 Merge pull request #4659 from nymtech/dependabot/npm_and_yarn/nym-api/tests/braces-3.0.3
Bump braces from 3.0.2 to 3.0.3 in /nym-api/tests
2024-06-17 09:44:34 +02:00
dependabot[bot] 78b9ebb463 Bump braces from 3.0.2 to 3.0.3 in /nym-api/tests
Bumps [braces](https://github.com/micromatch/braces) from 3.0.2 to 3.0.3.
- [Changelog](https://github.com/micromatch/braces/blob/master/CHANGELOG.md)
- [Commits](https://github.com/micromatch/braces/compare/3.0.2...3.0.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-17 07:39:12 +00:00
Tommy Verrall ad7f993f0f Merge pull request #4658 from nymtech/dependabot/npm_and_yarn/docker/typescript_client/upload_contract/braces-3.0.3
Bump braces from 3.0.2 to 3.0.3 in /docker/typescript_client/upload_contract
2024-06-17 09:38:25 +02:00
Tommy Verrall 9be8a53ea2 Merge pull request #4656 from edcalderon/patch-2
Update vps-setup.md
2024-06-17 09:37:56 +02:00
Tommy Verrall a89f8cf2ab Merge pull request #4655 from edcalderon/patch-1
Update configuration.md
2024-06-17 09:37:10 +02:00
dependabot[bot] a2dab0e64d Bump braces in /docker/typescript_client/upload_contract
Bumps [braces](https://github.com/micromatch/braces) from 3.0.2 to 3.0.3.
- [Changelog](https://github.com/micromatch/braces/blob/master/CHANGELOG.md)
- [Commits](https://github.com/micromatch/braces/compare/3.0.2...3.0.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-17 01:25:23 +00:00
Edward Calderon 52459f6545 Update vps-setup.md
miss parameter
2024-06-14 17:56:50 -05:00
Edward Calderon a82bc3356e Update configuration.md
typo
2024-06-14 15:17:38 -05:00
Jędrzej Stuczyński 9ebe8310a1 renamed 'accept-toc' flag and fields into explicit 'accept-operator-terms-and-conditions' 2024-06-14 17:22:42 +01:00
benedettadavico cf5c5f1df4 update changelog and bump binaries 2024-06-14 16:21:26 +02:00
import this 8585a68d7f syntax fix (#4653) 2024-06-14 18:36:15 +05:30
import this e8540c13a5 [DOCs/operators]: Introduction of the new RELEASE CYCLE & SANDBOX FAUCET (#4652)
* initialise release cycle page

* syntax fix - missing sandbox and faucet guide

* add to summary

* add faucet notes as a draft

* add faucet points and bn feedback as a comment

* create sandbox testnet guide page

* syntax edit

* syntax edit

* change config flag syntax
2024-06-14 12:14:59 +00:00
Jon Häggblad 5a24a8fafc Merge pull request #4643 from nymtech/jon/remove-nc 2024-06-14 12:03:42 +02:00
import this 1195b120ff update nymvpn cli page (#4649) 2024-06-13 09:09:53 +00:00
Tommy Verrall f30cfc0be7 Merge pull request #4650 from nymtech/bugfix/remove-ephemera_migrations
Remove additional code as part of Ephemera Purge and SP and contracts
2024-06-12 17:05:09 +02:00
Tommy Verrall 9460a9941c remove additional code :) 2024-06-12 16:40:11 +02:00
Tommy Verrall eeffc0db51 fmt 2024-06-12 16:29:00 +02:00
Tommy Verrall b7d6e0e1e3 remove left over bbc code 2024-06-12 16:27:00 +02:00
Tommy Verrall 45e0b406ac remove additional ephemera code and related service provider info 2024-06-12 16:15:52 +02:00
import this 405d4653df [DOCs]: NC purge (#4645)
* update wallet desktop url

* purge nym connect docs

* update socks 5 client quickstart

* add api link - ready to merge

* remove allowlist from the integration faq

* syntax fix
2024-06-12 09:16:49 +00:00
Jędrzej Stuczyński 579527b480 Merge pull request #4648 from nymtech/bugfix/contracts-compat
bugfix: make sure nym-api can handle non-cw2 (or without detailed build info) compliant contracts
2024-06-11 19:04:32 +02:00
Jędrzej Stuczyński 70360196f0 bugfix: make sure nym-api can handle non-cw2 (or without detailed build info) compliant contracts 2024-06-11 17:38:24 +01:00
Tommy Verrall b777adeda6 Merge pull request #4639 from nymtech/jon/remove-pr-template
Remove old PR template
2024-06-11 16:25:23 +02:00
Jędrzej Stuczyński 6a6505c9d7 Merge pull request #4647 from nymtech/feature/toc-flag
introduced a flag to accept toc and exposed it via self-described API
2024-06-11 15:20:42 +02:00
Jędrzej Stuczyński b10119d339 Merge pull request #4646 from nymtech/jstuczyn-patch-1
bugfix: make sure to return an error on invalid public ip
2024-06-11 15:09:25 +02:00
Jędrzej Stuczyński 3a4bd4ffd6 introduced a flag to accept toc and exposed it via self-described API 2024-06-11 14:08:09 +01:00
Jędrzej Stuczyński 9769387730 bugfix: make sure to return an error on invalid public ip 2024-06-11 13:58:25 +01:00
Jędrzej Stuczyński 71747e3c82 Merge pull request #4630 from nymtech/feature/forbid-empty-ips
validate nym-node public ips on startup
2024-06-11 14:43:42 +02:00
Jędrzej Stuczyński 5cbbeee0d5 Merge pull request #4631 from nymtech/feature/standarise-contract-info
standarised ContractBuildInformation and added it to all contracts
2024-06-11 14:43:25 +02:00
Jon Häggblad 57187be113 Remove nym-connect CI files 2024-06-11 14:05:05 +02:00
Jon Häggblad fbd634a866 Remove references to nym-connect in toolchain files 2024-06-11 14:05:05 +02:00
Jon Häggblad 8d4eba858e Delete nym-connect directory 2024-06-11 14:05:04 +02:00
Jędrzej Stuczyński f1486fb989 updated schema files 2024-06-11 12:22:38 +01:00
Jędrzej Stuczyński c50c30ae76 standarised ContractBuildInformation and added it to all contracts 2024-06-11 12:22:15 +01:00
Jędrzej Stuczyński 5745cb4d7a Merge pull request #4642 from nymtech/chore/purge-ephemera
Removed ephemera code
2024-06-11 13:15:04 +02:00
Jon Häggblad 00c978c864 Add ci check for PR having an assigned milestone (#4644)
* Add ci check for PR having an assigned milestone

* fix trigger
2024-06-11 12:58:25 +02:00
Tommy Verrall 9e4c58efdf Merge pull request #4640 from nymtech/feature/periodic_remove
Remove stale peers
2024-06-11 12:26:55 +02:00
Tommy Verrall 13e6fcaa85 Merge pull request #4635 from nymtech/feature/new-node-endpoints
Feature/new node endpoints
2024-06-11 12:26:30 +02:00
Tommy Verrall 9bd095ec18 Merge pull request #4638 from nymtech/dependabot/npm_and_yarn/testnet-faucet/braces-3.0.3
Bump braces from 3.0.2 to 3.0.3 in /testnet-faucet
2024-06-11 12:25:13 +02:00
Jędrzej Stuczyński 60d50ff17a fixed visibility of '--local' flag 2024-06-11 11:22:31 +01:00
Tommy Verrall 03f3f0285a Merge pull request #4624 from nymtech/jon/fix-cargo-warnings
Fix cargo warnings
2024-06-11 12:22:12 +02:00
Jędrzej Stuczyński 3e87063ab4 Removed ephemera code 2024-06-11 11:17:26 +01:00
Bogdan-Ștefan Neacşu a32cbd44b0 Remove stale peers 2024-06-11 10:05:38 +00:00
Jon Häggblad 962070a33c Remove old PR template 2024-06-11 12:04:24 +02:00
Jon Häggblad 55f11a5433 Disable profile settings for crate not included
Cargo is warning about

warning: profile package spec `nym-wasm-sdk` in profile `release` did not match any packages

Fix this by commenting out the profile settings for that crate as it's
currently not included  in the main workspace
2024-06-11 11:52:04 +02:00
Jon Häggblad 48332a1069 Fix cargo warnings about default-features for the main workspace
On every cargo command we have the set warnings:

warning: /home/jon/src/nym/nym/common/dkg/Cargo.toml: `default-features` is ignored for bls12_381, since `default-features` was not specified for `workspace.dependencies.bls12_381`, this could become a hard error in the future
warning: /home/jon/src/nym/nym/common/dkg/Cargo.toml: `default-features` is ignored for ff, since `default-features` was not specified for `workspace.dependencies.ff`, this could become a hard error in the future
warning: /home/jon/src/nym/nym/common/dkg/Cargo.toml: `default-features` is ignored for group, since `default-features` was not specified for `workspace.dependencies.group`, this could become a hard error in the future
warning: /home/jon/src/nym/nym/common/client-libs/validator-client/Cargo.toml: `default-features` is ignored for bip32, since `default-features` was not specified for `workspace.dependencies.bip32`, this could become a hard error in the future
warning: /home/jon/src/nym/nym/common/client-libs/validator-client/Cargo.toml: `default-features` is ignored for prost, since `default-features` was not specified for `workspace.dependencies.prost`, this could become a hard error in the future
warning: /home/jon/src/nym/nym/common/credentials-interface/Cargo.toml: `default-features` is ignored for bls12_381, since `default-features` was not specified for `workspace.dependencies.bls12_381`, this could become a hard error in the future
warning: /home/jon/src/nym/nym/common/credentials/Cargo.toml: `default-features` is ignored for bls12_381, since `default-features` was not specified for `workspace.dependencies.bls12_381`, this could become a hard error in the future
warning: /home/jon/src/nym/nym/common/nymcoconut/Cargo.toml: `default-features` is ignored for bls12_381, since `default-features` was not specified for `workspace.dependencies.bls12_381`, this could become a hard error in the future
warning: /home/jon/src/nym/nym/common/nymcoconut/Cargo.toml: `default-features` is ignored for ff, since `default-features` was not specified for `workspace.dependencies.ff`, this could become a hard error in the future
warning: /home/jon/src/nym/nym/common/nymcoconut/Cargo.toml: `default-features` is ignored for group, since `default-features` was not specified for `workspace.dependencies.group`, this could become a hard error in the future

This commit adds default-features = false to the workspace dependencies
to fix these. An alternative way would be to remove
`default-features = false`
in the crates, but I assume these were put there for a good reason. Also
we might have other crates outside of the main workspace that depends on
these crates having default features disabled.
2024-06-11 11:52:01 +02:00
dependabot[bot] 205c887686 Bump braces from 3.0.2 to 3.0.3 in /testnet-faucet
Bumps [braces](https://github.com/micromatch/braces) from 3.0.2 to 3.0.3.
- [Changelog](https://github.com/micromatch/braces/blob/master/CHANGELOG.md)
- [Commits](https://github.com/micromatch/braces/compare/3.0.2...3.0.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-11 09:48:46 +00:00
Jędrzej Stuczyński 464041f9e1 ibid for nym-connect 2024-06-10 14:48:35 +01:00
Jędrzej Stuczyński 433748521c wasm fixes 2024-06-10 13:00:24 +01:00
Jędrzej Stuczyński 3cbcd001f4 clippy + test build issues 2024-06-10 11:36:57 +01:00
Jędrzej Stuczyński 282b27646f review comments 2024-06-10 11:19:27 +01:00
Jędrzej Stuczyński 5cc3ee32e9 fix test 2024-06-10 11:17:44 +01:00
Jędrzej Stuczyński f412f45b50 proper type conversions and client compat 2024-06-10 11:03:26 +01:00
Jędrzej Stuczyński 9c19452758 scaffolding of using new endpoints in the client 2024-06-10 10:11:07 +01:00
Jędrzej Stuczyński bf34d00478 new endpoints on nym-api side 2024-06-07 17:02:53 +01:00
Jędrzej Stuczyński 7d714a22f0 validate nym-node public ips on startup 2024-06-06 11:23:16 +01:00
661 changed files with 3425 additions and 39426 deletions
-9
View File
@@ -1,9 +0,0 @@
# Description
Closes: #XXXX
<!-- If appropriate, insert relevant description here -->
# Checklist:
- [ ] added a changelog entry to `CHANGELOG.md`
+2 -2
View File
@@ -41,8 +41,8 @@ jobs:
# This is a workaround replacement which builds on the last working commit b332a6b55668f60988e36961f3f62a794ba82ddb and then on current branch
- name: Save current branch to ~/current_branch
run: git rev-parse --abbrev-ref HEAD > ~/current_branch
- name: Git pull & switch to b332a6b55668f60988e36961f3f62a794ba82ddb
run: git pull && git checkout b332a6b55668f60988e36961f3f62a794ba82ddb
- name: Git pull, reset & switch to b332a6b55668f60988e36961f3f62a794ba82ddb
run: git pull && git reset --hard && git checkout b332a6b55668f60988e36961f3f62a794ba82ddb
- name: Build all projects in documentation/ & move to ~/dist/docs/ from b332a6b55668f60988e36961f3f62a794ba82ddb
run: cd documentation && ./build_all_to_dist.sh
@@ -104,12 +104,9 @@ jobs:
name: nym-binaries-artifacts
path: |
target/release/nym-client
target/release/nym-gateway
target/release/nym-mixnode
target/release/nym-socks5-client
target/release/nym-api
target/release/nym-network-requester
target/release/nym-network-statistics
target/release/nym-cli
target/release/nymvisor
target/release/nym-node
@@ -124,12 +121,9 @@ jobs:
OUTPUT_DIR: ci-builds/${{ github.ref_name }}
run: |
cp target/release/nym-client $OUTPUT_DIR
cp target/release/nym-gateway $OUTPUT_DIR
cp target/release/nym-mixnode $OUTPUT_DIR
cp target/release/nym-socks5-client $OUTPUT_DIR
cp target/release/nym-api $OUTPUT_DIR
cp target/release/nym-network-requester $OUTPUT_DIR
cp target/release/nym-network-statistics $OUTPUT_DIR
cp target/release/nymvisor $OUTPUT_DIR
cp target/release/nym-node $OUTPUT_DIR
cp target/release/nym-cli $OUTPUT_DIR
-2
View File
@@ -6,7 +6,6 @@ on:
- 'clients/**'
- 'common/**'
- 'explorer-api/**'
- 'ephemera/**'
- 'gateway/**'
- 'integrations/**'
- 'mixnode/**'
@@ -24,7 +23,6 @@ on:
- 'clients/**'
- 'common/**'
- 'explorer-api/**'
- 'ephemera/**'
- 'gateway/**'
- 'integrations/**'
- 'mixnode/**'
+2 -2
View File
@@ -46,8 +46,8 @@ jobs:
# This is a workaround replacement which builds on the last working commit b332a6b55668f60988e36961f3f62a794ba82ddb and then on current branch
- name: Save current branch to ~/current_branch
run: git rev-parse --abbrev-ref HEAD > ~/current_branch
- name: Git pull & switch to b332a6b55668f60988e36961f3f62a794ba82ddb
run: git pull && git checkout b332a6b55668f60988e36961f3f62a794ba82ddb
- name: Git pull, reset & switch to b332a6b55668f60988e36961f3f62a794ba82ddb
run: git pull && git reset --hard && git checkout b332a6b55668f60988e36961f3f62a794ba82ddb
- name: Build all projects in documentation/ & move to ~/dist/docs/ from b332a6b55668f60988e36961f3f62a794ba82ddb
run: cd documentation && ./build_all_to_dist.sh
@@ -1,65 +0,0 @@
name: ci-nym-connect-desktop-rust
on:
pull_request:
paths:
- "nym-connect/desktop/src-tauri/**"
- "nym-connect/desktop/src-tauri/Cargo.toml"
- "clients/client-core/**"
- "clients/socks5/**"
- "common/**"
- "gateway/gateway-requests/**"
- "contracts/vesting/**"
- "nym-api/nym-api-requests/**"
jobs:
build:
runs-on: [self-hosted, custom-linux]
env:
CARGO_TERM_COLOR: always
steps:
- name: Install Dependencies (Linux)
run: sudo apt-get update && sudo apt-get -y install libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev squashfs-tools libayatana-appindicator3-dev
continue-on-error: true
- name: Check out repository code
uses: actions/checkout@v2
- name: Install rust toolchain
uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
override: true
components: rustfmt, clippy
- name: Check formatting
uses: actions-rs/cargo@v1
with:
command: fmt
args: --manifest-path nym-connect/desktop/Cargo.toml --all -- --check
- name: Build all binaries
uses: actions-rs/cargo@v1
with:
command: build
args: --manifest-path nym-connect/desktop/Cargo.toml --workspace
- name: Run all tests
uses: actions-rs/cargo@v1
with:
command: test
args: --manifest-path nym-connect/desktop/Cargo.toml --workspace
- uses: actions-rs/clippy-check@v1
name: Clippy checks
continue-on-error: true
with:
token: ${{ secrets.GITHUB_TOKEN }}
args: --manifest-path nym-connect/desktop/Cargo.toml --workspace --all-features
- name: Run clippy
uses: actions-rs/cargo@v1
with:
command: clippy
args: --manifest-path nym-connect/desktop/Cargo.toml --workspace --all-features -- -D warnings
@@ -1,72 +0,0 @@
name: ci-nym-connect-desktop
on:
pull_request:
paths:
- 'nym-connect/desktop/**'
defaults:
run:
working-directory: nym-connect/desktop
jobs:
build:
runs-on: custom-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 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
- name: Install app dependencies
run: yarn
continue-on-error: true
- name: Set environment from the example
run: cp .env.sample .env
- run: yarn storybook: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: "nym-connect/desktop/storybook-static/"
REMOTE_HOST: ${{ secrets.CI_WWW_REMOTE_HOST }}
REMOTE_USER: ${{ secrets.CI_WWW_REMOTE_USER }}
TARGET: ${{ secrets.CI_WWW_REMOTE_TARGET }}/nym-connect-${{ 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: nym-connect
NYM_PROJECT_NAME: "nym-connect"
NYM_CI_WWW_BASE: "${{ secrets.NYM_CI_WWW_BASE }}"
NYM_CI_WWW_LOCATION: "nym-connect-${{ 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
@@ -1,92 +0,0 @@
name: nightly-nym-connect-desktop-build
on:
workflow_dispatch:
schedule:
- cron: '14 1 * * *'
jobs:
build:
strategy:
fail-fast: false
matrix:
os: [ubuntu-20.04, macos-latest, windows-latest]
runs-on: ${{ matrix.os }}
env:
CARGO_TERM_COLOR: always
MANIFEST_PATH: --manifest-path nym-connect/desktop/Cargo.toml
continue-on-error: true
steps:
- name: Check out repository code
uses: actions/checkout@v3
- name: Install Dependencies (Linux)
run: sudo apt-get update && sudo apt-get install -y libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev squashfs-tools
if: matrix.os == 'ubuntu-20.04'
- name: Install rust toolchain
uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
override: true
components: rustfmt, clippy
- name: Check formatting
uses: actions-rs/cargo@v1
with:
command: fmt
args: ${{ env.MANIFEST_PATH }} --all -- --check
- name: Build
uses: actions-rs/cargo@v1
with:
command: build
args: ${{ env.MANIFEST_PATH }} --release --workspace
- name: Unit tests
uses: actions-rs/cargo@v1
with:
command: test
args: ${{ env.MANIFEST_PATH }} --workspace
- name: Clippy
uses: actions-rs/cargo@v1
with:
command: clippy
args: ${{ env.MANIFEST_PATH }} --workspace --all-targets -- -D warnings
notification:
needs: build
runs-on: custom-linux
steps:
- name: Collect jobs status
uses: technote-space/workflow-conclusion-action@v2
- name: Check out repository code
uses: actions/checkout@v3
- name: install npm
uses: actions/setup-node@v3
if: env.WORKFLOW_CONCLUSION == 'failure'
with:
node-version: 18
- name: Matrix - Node Install
if: env.WORKFLOW_CONCLUSION == 'failure'
run: npm install
working-directory: .github/workflows/support-files
- name: Matrix - Send Notification
if: env.WORKFLOW_CONCLUSION == 'failure'
env:
NYM_NOTIFICATION_KIND: nightly
NYM_PROJECT_NAME: "nym-connect-desktop-nightly-build"
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
GIT_COMMIT_MESSAGE: "${{ github.event.head_commit.message }}"
GIT_BRANCH: "${GITHUB_REF##*/}"
IS_SUCCESS: "${{ env.WORKFLOW_CONCLUSION == 'success' }}"
MATRIX_SERVER: "${{ secrets.MATRIX_SERVER }}"
MATRIX_ROOM: "${{ secrets.MATRIX_ROOM_NIGHTLY }}"
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
+27
View File
@@ -0,0 +1,27 @@
name: pr-validation
on:
pull_request:
branches:
- develop
- 'release/**'
types:
- labeled
- unlabeled
- opened
- reopened
- synchronize
- edited
- milestoned
- demilestoned
env:
LABELS: ${{ join( github.event.pull_request.labels.*.name, ' ' ) }}
jobs:
check-milestone:
name: Check Milestone
runs-on: ubuntu-latest
steps:
- if: github.event.pull_request.milestone == null && contains( env.LABELS, 'no-milestone' ) == false
run: exit 1
@@ -27,23 +27,17 @@ jobs:
release_id: ${{ steps.create-release.outputs.id }}
release_date: ${{ fromJSON(steps.create-release.outputs.assets)[0].published_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 }}
nymvisor_hash: ${{ steps.binary-hashes.outputs.nymvisor_hash }}
nymnode_hash: ${{ steps.binary-hashes.outputs.nymnode_hash }}
socks5_hash: ${{ steps.binary-hashes.outputs.socks5_hash }}
netreq_hash: ${{ steps.binary-hashes.outputs.netreq_hash }}
cli_hash: ${{ steps.binary-hashes.outputs.cli_hash }}
netstat_hash: ${{ steps.binary-hashes.outputs.netstat_hash }}
client_version: ${{ steps.binary-versions.outputs.client_version }}
mixnode_version: ${{ steps.binary-versions.outputs.mixnode_version }}
gateway_version: ${{ steps.binary-versions.outputs.gateway_version }}
nymvisor_version: ${{ steps.binary-versions.outputs.nymvisor_version }}
nymnode_version: ${{ steps.binary-versions.outputs.nymnode_version }}
socks5_version: ${{ steps.binary-versions.outputs.socks5_version }}
netreq_version: ${{ steps.binary-versions.outputs.netreq_version }}
cli_version: ${{ steps.binary-versions.outputs.cli_version }}
netstat_version: ${{ steps.binary-versions.outputs.netstat_version }}
steps:
- uses: actions/checkout@v3
@@ -75,12 +69,9 @@ jobs:
path: |
target/release/explorer-api
target/release/nym-client
target/release/nym-gateway
target/release/nym-mixnode
target/release/nym-socks5-client
target/release/nym-api
target/release/nym-network-requester
target/release/nym-network-statistics
target/release/nym-cli
target/release/nymvisor
target/release/nym-node
@@ -94,12 +85,9 @@ jobs:
files: |
target/release/explorer-api
target/release/nym-client
target/release/nym-gateway
target/release/nym-mixnode
target/release/nym-socks5-client
target/release/nym-api
target/release/nym-network-requester
target/release/nym-network-statistics
target/release/nym-cli
target/release/nymvisor
target/release/nym-node
@@ -1,122 +0,0 @@
name: publish-nym-connect-macos
on:
workflow_dispatch:
release:
types: [created]
defaults:
run:
working-directory: nym-connect/desktop
jobs:
publish-tauri:
if: ${{ (startsWith(github.ref, 'refs/tags/nym-connect-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }}
strategy:
fail-fast: false
matrix:
platform: [macos-12-large]
runs-on: ${{ matrix.platform }}
outputs:
release_id: ${{ steps.create-release.outputs.id }}
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 }}
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
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 }}
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: Install project dependencies
shell: bash
run: cd .. && yarn --network-timeout 100000
- 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 }}
SENTRY_DSN_RUST: ${{ secrets.SENTRY_DSN_RUST }}
SENTRY_DSN_JS: ${{ secrets.SENTRY_DSN_JS }}
run: yarn && yarn build
- name: Upload Artifact
uses: actions/upload-artifact@v3
with:
name: nym-connect_1.0.0_x64.dmg
path: nym-connect/desktop/target/release/bundle/dmg/nym-connect_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*
push-release-data:
if: ${{ (startsWith(github.ref, 'refs/tags/nym-connect-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }}
uses: ./.github/workflows/release-calculate-hash.yml
needs: publish-tauri
with:
release_tag: ${{ github.ref_name }}
secrets: inherit
@@ -1,89 +0,0 @@
name: publish-nym-connect-ubuntu
on:
workflow_dispatch:
release:
types: [created]
defaults:
run:
working-directory: nym-connect/desktop
jobs:
publish-tauri:
if: ${{ (startsWith(github.ref, 'refs/tags/nym-connect-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }}
strategy:
fail-fast: false
matrix:
platform: [custom-ubuntu-20.04]
runs-on: ${{ matrix.platform }}
outputs:
release_id: ${{ steps.create-release.outputs.id }}
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 }}
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: Build app
run: yarn build
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
with:
name: nym-connect.AppImage.tar.gz
path: nym-connect/desktop/target/release/bundle/appimage/nym-connect_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*
push-release-data:
if: ${{ (startsWith(github.ref, 'refs/tags/nym-connect-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }}
uses: ./.github/workflows/release-calculate-hash.yml
needs: publish-tauri
with:
release_tag: ${{ github.ref_name }}
secrets: inherit
@@ -1,108 +0,0 @@
name: publish-nym-connect-win10
on:
workflow_dispatch:
release:
types: [created]
defaults:
run:
working-directory: nym-connect/desktop
jobs:
publish-tauri:
if: ${{ (startsWith(github.ref, 'refs/tags/nym-connect-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }}
strategy:
fail-fast: false
matrix:
platform: [windows10]
runs-on: ${{ matrix.platform }}
outputs:
release_id: ${{ steps.create-release.outputs.id }}
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 }}
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: 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 }}
SENTRY_DSN_RUST: ${{ secrets.SENTRY_DSN_RUST }}
SENTRY_DSN_JS: ${{ secrets.SENTRY_DSN_JS }}
run: yarn build
- name: Upload Artifact
uses: actions/upload-artifact@v3
with:
name: nym-connect_1.0.0_x64_en-US.msi
path: nym-connect/desktop/target/release/bundle/msi/nym-connect_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*
push-release-data:
if: ${{ (startsWith(github.ref, 'refs/tags/nym-connect-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }}
uses: ./.github/workflows/release-calculate-hash.yml
needs: publish-tauri
with:
release_tag: ${{ github.ref_name }}
secrets: inherit
@@ -1,29 +0,0 @@
const Handlebars = require('handlebars');
const fs = require('fs');
const path = require('path');
async function addToContextAndValidate(context) {
if (!context.env.NYM_CI_WWW_LOCATION) {
throw new Error('Please ensure the env var NYM_CI_WWW_LOCATION is set');
}
if (!context.env.NYM_CI_WWW_BASE) {
throw new Error('Please ensure the env var NYM_CI_WWW_BASE is set');
}
}
async function getMessageBody(context) {
const source = fs
.readFileSync(
context.env.IS_SUCCESS === 'true'
? path.resolve(__dirname, 'templates', 'success')
: path.resolve(__dirname, 'templates', 'failure'),
)
.toString();
const template = Handlebars.compile(source);
return template(context);
}
module.exports = {
addToContextAndValidate,
getMessageBody,
};
@@ -1,16 +0,0 @@
🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥
> :rocket: {{ env.NYM_PROJECT_NAME }}
>
> 🔴 **FAILURE** :cry:
>
> `branch` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/tree/{{ env.GIT_BRANCH_NAME }}
>
> `commit` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/commit/{{ env.GITHUB_SHA }}
>
> `build ` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/actions/runs/{{ env.GITHUB_RUN_ID }}
>
Commit message:
```
{{ env.GIT_COMMIT_MESSAGE }}
```
@@ -1,16 +0,0 @@
🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩
> :rocket: {{ env.NYM_PROJECT_NAME }} ➡️➡️➡️➡️➡️ **View storybook:** https://{{ env.NYM_CI_WWW_LOCATION }}.{{ env.NYM_CI_WWW_BASE }}/
>
> ✅ **SUCCESS**
>
> `branch` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/tree/{{ env.GIT_BRANCH_NAME }}
>
> `commit` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/commit/{{ env.GITHUB_SHA }}
>
> `build ` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/actions/runs/{{ env.GITHUB_RUN_ID }}
>
Commit message by `{{ env.GITHUB_ACTOR }}` at {{ timestamp }}:
```
{{ env.GIT_COMMIT_MESSAGE }}
```
+40
View File
@@ -4,6 +4,46 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
## [Unreleased]
## [2024.6-chomp] (2024-06-25)
- Remove additional code as part of Ephemera Purge and SP and contracts ([#4650])
- bugfix: make sure nym-api can handle non-cw2 (or without detailed build info) compliant contracts ([#4648])
- introduced a flag to accept toc and exposed it via self-described API ([#4647])
- bugfix: make sure to return an error on invalid public ip ([#4646])
- Add ci check for PR having an assigned milestone ([#4644])
- Removed ephemera code ([#4642])
- Remove stale peers ([#4640])
- Add generic wg private network routing ([#4636])
- Feature/new node endpoints ([#4635])
- standarised ContractBuildInformation and added it to all contracts ([#4631])
- validate nym-node public ips on startup ([#4630])
- Bump defguard wg ([#4625])
- Fix cargo warnings ([#4624])
- Update kernel peers on peer modification ([#4622])
- Handle v6 and v7 requests in the IPR, but reply with v6 ([#4620])
- fix typo ([#4619])
- Update crypto and rand crates ([#4607])
- Purge name service and service provider directory contracts ([#4603])
[#4650]: https://github.com/nymtech/nym/pull/4650
[#4648]: https://github.com/nymtech/nym/pull/4648
[#4647]: https://github.com/nymtech/nym/pull/4647
[#4646]: https://github.com/nymtech/nym/pull/4646
[#4644]: https://github.com/nymtech/nym/pull/4644
[#4642]: https://github.com/nymtech/nym/pull/4642
[#4640]: https://github.com/nymtech/nym/pull/4640
[#4636]: https://github.com/nymtech/nym/pull/4636
[#4635]: https://github.com/nymtech/nym/pull/4635
[#4631]: https://github.com/nymtech/nym/pull/4631
[#4630]: https://github.com/nymtech/nym/pull/4630
[#4625]: https://github.com/nymtech/nym/pull/4625
[#4624]: https://github.com/nymtech/nym/pull/4624
[#4622]: https://github.com/nymtech/nym/pull/4622
[#4620]: https://github.com/nymtech/nym/pull/4620
[#4619]: https://github.com/nymtech/nym/pull/4619
[#4607]: https://github.com/nymtech/nym/pull/4607
[#4603]: https://github.com/nymtech/nym/pull/4603
## [2024.5-ragusa] (2024-05-22)
- Feature/nym node api location ([#4605])
Generated
+35 -92
View File
@@ -526,8 +526,6 @@ dependencies = [
"bs58 0.5.1",
"hmac",
"k256",
"once_cell",
"pbkdf2",
"rand_core 0.6.4",
"ripemd",
"sha2 0.10.8",
@@ -2095,14 +2093,14 @@ checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0"
[[package]]
name = "explorer-api"
version = "1.1.34"
version = "1.1.35"
dependencies = [
"chrono",
"clap 4.5.4",
"dotenvy",
"humantime-serde",
"isocountry",
"itertools 0.10.5",
"itertools 0.12.1",
"log",
"maxminddb",
"nym-bin-common",
@@ -2204,7 +2202,6 @@ version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449"
dependencies = [
"bitvec",
"rand_core 0.6.4",
"subtle 2.5.0",
]
@@ -2224,7 +2221,7 @@ dependencies = [
"atomic 0.6.0",
"pear",
"serde",
"toml 0.8.12",
"toml 0.8.14",
"uncased",
"version_check",
]
@@ -3275,15 +3272,6 @@ dependencies = [
"either",
]
[[package]]
name = "itertools"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57"
dependencies = [
"either",
]
[[package]]
name = "itertools"
version = "0.12.1"
@@ -3861,7 +3849,7 @@ dependencies = [
[[package]]
name = "nym-api"
version = "1.1.38"
version = "1.1.39"
dependencies = [
"anyhow",
"async-trait",
@@ -3943,6 +3931,7 @@ dependencies = [
"nym-crypto",
"nym-mixnet-contract-common",
"nym-node-requests",
"rocket",
"schemars",
"serde",
"serde_json",
@@ -4020,7 +4009,7 @@ dependencies = [
[[package]]
name = "nym-cli"
version = "1.1.36"
version = "1.1.37"
dependencies = [
"anyhow",
"base64 0.13.1",
@@ -4099,7 +4088,7 @@ dependencies = [
[[package]]
name = "nym-client"
version = "1.1.35"
version = "1.1.36"
dependencies = [
"bs58 0.5.1",
"clap 4.5.4",
@@ -4284,7 +4273,7 @@ dependencies = [
"ff",
"getrandom 0.2.15",
"group",
"itertools 0.10.5",
"itertools 0.12.1",
"nym-dkg",
"nym-pemstore",
"rand 0.8.5",
@@ -4339,10 +4328,12 @@ dependencies = [
"bs58 0.5.1",
"cosmwasm-schema",
"cosmwasm-std",
"cw-storage-plus",
"schemars",
"serde",
"serde_json",
"thiserror",
"vergen",
]
[[package]]
@@ -4459,16 +4450,6 @@ dependencies = [
"zeroize",
]
[[package]]
name = "nym-ephemera-common"
version = "0.1.0"
dependencies = [
"cosmwasm-schema",
"cosmwasm-std",
"cw-utils",
"nym-contracts-common",
]
[[package]]
name = "nym-execute"
version = "0.1.0"
@@ -4547,7 +4528,6 @@ dependencies = [
"nym-node-http-api",
"nym-pemstore",
"nym-sphinx",
"nym-statistics-common",
"nym-task",
"nym-types",
"nym-validator-client",
@@ -4643,6 +4623,7 @@ version = "0.1.0"
dependencies = [
"async-trait",
"http 1.1.0",
"nym-bin-common",
"reqwest 0.12.4",
"serde",
"serde_json",
@@ -4920,7 +4901,7 @@ dependencies = [
[[package]]
name = "nym-network-requester"
version = "1.1.36"
version = "1.1.37"
dependencies = [
"addr",
"anyhow",
@@ -4949,7 +4930,6 @@ dependencies = [
"nym-socks5-proxy-helpers",
"nym-socks5-requests",
"nym-sphinx",
"nym-statistics-common",
"nym-task",
"nym-types",
"pretty_env_logger",
@@ -4970,26 +4950,9 @@ dependencies = [
"zeroize",
]
[[package]]
name = "nym-network-statistics"
version = "1.1.34"
dependencies = [
"dirs 4.0.0",
"log",
"nym-bin-common",
"nym-statistics-common",
"nym-task",
"pretty_env_logger",
"rocket",
"serde",
"sqlx",
"thiserror",
"tokio",
]
[[package]]
name = "nym-node"
version = "1.1.2"
version = "1.1.3"
dependencies = [
"anyhow",
"bip39",
@@ -5024,7 +4987,7 @@ dependencies = [
"sysinfo 0.30.12",
"thiserror",
"tokio",
"toml 0.8.12",
"toml 0.8.14",
"tracing",
"url",
"zeroize",
@@ -5170,7 +5133,7 @@ dependencies = [
"chacha20poly1305",
"criterion",
"curve25519-dalek 4.1.2",
"fastrand 1.9.0",
"fastrand 2.1.0",
"getrandom 0.2.15",
"log",
"rand 0.8.5",
@@ -5251,7 +5214,7 @@ dependencies = [
[[package]]
name = "nym-socks5-client"
version = "1.1.35"
version = "1.1.36"
dependencies = [
"bs58 0.5.1",
"clap 4.5.4",
@@ -5270,6 +5233,7 @@ dependencies = [
"nym-socks5-client-core",
"nym-sphinx",
"nym-topology",
"nym-validator-client",
"rand 0.8.5",
"serde",
"serde_json",
@@ -5515,20 +5479,6 @@ dependencies = [
"thiserror",
]
[[package]]
name = "nym-statistics-common"
version = "1.0.1"
dependencies = [
"async-trait",
"log",
"reqwest 0.12.4",
"serde",
"serde_json",
"sqlx",
"thiserror",
"tokio",
]
[[package]]
name = "nym-store-cipher"
version = "0.1.0"
@@ -5603,7 +5553,7 @@ dependencies = [
"cosmwasm-std",
"eyre",
"hmac",
"itertools 0.11.0",
"itertools 0.12.1",
"log",
"nym-config",
"nym-crypto",
@@ -5642,7 +5592,7 @@ dependencies = [
"eyre",
"flate2",
"futures",
"itertools 0.10.5",
"itertools 0.12.1",
"log",
"nym-api-requests",
"nym-coconut",
@@ -5650,7 +5600,6 @@ dependencies = [
"nym-coconut-dkg-common",
"nym-config",
"nym-contracts-common",
"nym-ephemera-common",
"nym-group-contract-common",
"nym-http-api-client",
"nym-mixnet-contract-common",
@@ -5752,6 +5701,7 @@ dependencies = [
"nym-task",
"nym-wireguard-types",
"tokio",
"tokio-stream",
"x25519-dalek",
]
@@ -5777,7 +5727,7 @@ dependencies = [
[[package]]
name = "nymvisor"
version = "0.1.1"
version = "0.1.2"
dependencies = [
"anyhow",
"bytes",
@@ -6089,16 +6039,6 @@ version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
[[package]]
name = "pbkdf2"
version = "0.12.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2"
dependencies = [
"digest 0.10.7",
"hmac",
]
[[package]]
name = "pear"
version = "0.2.9"
@@ -7614,9 +7554,9 @@ dependencies = [
[[package]]
name = "serde_spanned"
version = "0.6.5"
version = "0.6.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1"
checksum = "79e674e01f999af37c49f70a6ede167a8a60b2503e56c5599532a65baa5969a0"
dependencies = [
"serde",
]
@@ -8636,21 +8576,21 @@ dependencies = [
[[package]]
name = "toml"
version = "0.8.12"
version = "0.8.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e9dd1545e8208b4a5af1aa9bbd0b4cf7e9ea08fabc5d0a5c67fcaafa17433aa3"
checksum = "6f49eb2ab21d2f26bd6db7bf383edc527a7ebaee412d17af4d40fdccd442f335"
dependencies = [
"serde",
"serde_spanned",
"toml_datetime",
"toml_edit 0.22.12",
"toml_edit 0.22.14",
]
[[package]]
name = "toml_datetime"
version = "0.6.5"
version = "0.6.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1"
checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf"
dependencies = [
"serde",
]
@@ -8670,9 +8610,9 @@ dependencies = [
[[package]]
name = "toml_edit"
version = "0.22.12"
version = "0.22.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3328d4f68a705b2a4498da1d580585d39a6510f98318a2cec3018a7ec61ddef"
checksum = "f21c7aaf97f1bd9ca9d4f9e73b0a6c74bd5afef56f2bc931943a6e1c37e04e38"
dependencies = [
"indexmap 2.2.6",
"serde",
@@ -9235,11 +9175,14 @@ checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
[[package]]
name = "vergen"
version = "8.2.6"
version = "8.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1290fd64cc4e7d3c9b07d7f333ce0ce0007253e32870e632624835cc80b83939"
checksum = "e27d6bdd219887a9eadd19e1c34f32e47fa332301184935c6d9bca26f3cca525"
dependencies = [
"anyhow",
"cargo_metadata",
"cfg-if",
"regex",
"rustc_version 0.4.0",
"rustversion",
"time",
+25 -18
View File
@@ -35,7 +35,6 @@ members = [
"common/cosmwasm-smart-contracts/coconut-bandwidth-contract",
"common/cosmwasm-smart-contracts/coconut-dkg",
"common/cosmwasm-smart-contracts/contracts-common",
# "common/cosmwasm-smart-contracts/ephemera",
"common/cosmwasm-smart-contracts/group-contract",
"common/cosmwasm-smart-contracts/mixnet-contract",
"common/cosmwasm-smart-contracts/multisig-contract",
@@ -77,7 +76,6 @@ members = [
"common/socks5-client-core",
"common/socks5/proxy-helpers",
"common/socks5/requests",
"common/statistics",
"common/store-cipher",
"common/task",
"common/topology",
@@ -100,7 +98,6 @@ members = [
"service-providers/common",
"service-providers/ip-packet-router",
"service-providers/network-requester",
"service-providers/network-statistics",
"nym-api",
"nym-browser-extension/storage",
"nym-api/nym-api-requests",
@@ -117,7 +114,7 @@ members = [
"tools/nymvisor",
"tools/ts-rs-cli",
"wasm/client",
# "wasm/full-nym-wasm",
# "wasm/full-nym-wasm", # If we uncomment this again, remember to also uncomment the profile settings below
"wasm/mix-fetch",
"wasm/node-tester",
"wasm/zknym-lib",
@@ -128,7 +125,6 @@ default-members = [
"clients/socks5",
"gateway",
"service-providers/network-requester",
"service-providers/network-statistics",
"mixnode",
"nym-api",
"tools/nymvisor",
@@ -141,9 +137,6 @@ exclude = [
"explorer",
"contracts",
"nym-wallet",
"nym-connect/mobile/src-tauri",
"nym-connect/desktop",
"nym-vpn/ui/src-tauri",
"cpu-cycles",
"sdk/ffi/cpp",
]
@@ -196,12 +189,15 @@ cupid = "0.6.1"
curve25519-dalek = "4.1"
dashmap = "5.5.3"
defguard_wireguard_rs = "0.4.2"
digest = "0.10.7"
dirs = "4.0"
doc-comment = "0.3"
dotenvy = "0.15.6"
ecdsa = "0.16"
ed25519-dalek = "2.1"
etherparse = "0.13.0"
eyre = "0.6.9"
fastrand = "2.1.0"
flate2 = "1.0.28"
futures = "0.3.28"
generic-array = "0.14.7"
@@ -213,14 +209,15 @@ hex = "0.4.3"
hex-literal = "0.3.3"
hkdf = "0.12.3"
hmac = "0.12.1"
http = "1"
httpcodec = "0.2.3"
humantime = "2.1.0"
humantime-serde = "1.1.1"
http = "1"
hyper = "1.3.1"
indexed_db_futures = "0.3.0"
inquire = "0.6.2"
ip_network = "0.4.1"
ipnetwork = "0.16"
isocountry = "0.3.2"
k256 = "0.13"
lazy_static = "1.4.0"
@@ -243,6 +240,7 @@ publicsuffix = "2.2.3"
quote = "1"
rand = "0.8.5"
rand-07 = "0.7.3"
rand_chacha = "0.3"
rand_chacha_02 = "0.2"
rand_core = "0.6.3"
rand_distr = "0.4"
@@ -256,6 +254,7 @@ rocket_cors = "0.6.0"
rocket_okapi = "0.8.0"
safer-ffi = "0.1.4"
schemars = "0.8.1"
semver = "1.0.23"
serde = "1.0.152"
serde_bytes = "0.11.6"
serde_derive = "1.0"
@@ -263,12 +262,14 @@ serde_json = "1.0.91"
serde_repr = "0.1"
serde_with = "3.4.0"
serde_yaml = "0.9.25"
sha2 = "0.10.8"
si-scale = "0.2.2"
sphinx-packet = "0.1.1"
sqlx = "0.6.3"
strum = "0.25"
subtle-encoding = "0.5"
syn = "1"
sysinfo = "0.30.12"
tap = "1.0.1"
tar = "0.4.40"
tempfile = "3.5.0"
@@ -279,6 +280,7 @@ tokio-stream = "0.1.14"
tokio-test = "0.4.2"
tokio-tungstenite = { version = "0.20.1" }
tokio-util = "0.7.10"
toml = "0.8.14"
tower = "0.4.13"
tower-http = "0.5.2"
tracing = "0.1.37"
@@ -290,9 +292,10 @@ tungstenite = { version = "0.20.1", default-features = false }
url = "2.4"
utoipa = "4.2.0"
utoipa-swagger-ui = "6.0.0"
vergen = { version = "=8.2.6", default-features = false }
vergen = { version = "=8.3.1", default-features = false }
walkdir = "2"
wasm-bindgen-test = "0.3.36"
x25519-dalek = "2.0.0"
zeroize = "1.6.0"
prometheus = { version = "0.13.0" }
@@ -300,9 +303,9 @@ prometheus = { version = "0.13.0" }
# coconut/DKG related
# unfortunately until https://github.com/zkcrypto/bls12_381/issues/10 is resolved, we have to rely on the fork
# as we need to be able to serialize Gt so that we could create the lookup table for baby-step-giant-step algorithm
bls12_381 = { git = "https://github.com/jstuczyn/bls12_381", branch = "feature/gt-serialization-0.8.0" }
group = "0.13.0"
ff = "0.13.0"
bls12_381 = { git = "https://github.com/jstuczyn/bls12_381", default-features = false, branch = "feature/gt-serialization-0.8.0" }
group = { version = "0.13.0", default-features = false }
ff = { version = "0.13.0", default-features = false }
# cosmwasm-related
cosmwasm-derive = "=1.4.3"
@@ -321,14 +324,14 @@ cw4 = { version = "=1.1.2" }
cw-controllers = { version = "=1.1.0" }
# cosmrs-related
bip32 = "0.5.1"
bip32 = { version = "0.5.1", default-features = false }
# temporarily using a fork again (yay.) because we need staking and slashing support
cosmrs = { git = "https://github.com/jstuczyn/cosmos-rust", branch = "nym-temp/all-validator-features" }
#cosmrs = { git = "https://github.com/jstuczyn/cosmos-rust", branch = "nym-temp/all-validator-features" } # unfortuntely we need a fork by yours truly to get the staking support
tendermint = "0.34" # same version as used by cosmrs
tendermint-rpc = "0.34" # same version as used by cosmrs
prost = "0.12"
prost = { version = "0.12", default-features = false }
# wasm-related dependencies
gloo-utils = "0.2.0"
@@ -340,6 +343,7 @@ wasm-bindgen = "0.2.92"
wasm-bindgen-futures = "0.4.39"
wasmtimer = "0.2.0"
web-sys = "0.3.69"
itertools = "0.12.0"
# Profile settings for individual crates
@@ -356,9 +360,12 @@ opt-level = 'z'
# lto = true
opt-level = 'z'
[profile.release.package.nym-wasm-sdk]
# lto = true
opt-level = 'z'
# Commented out since the crate is also commented out from the inclusion in the
# workspace above. We should uncomment this if we re-include it in the
# workspace
#[profile.release.package.nym-wasm-sdk]
## lto = true
#opt-level = 'z'
[profile.release.package.mix-fetch-wasm]
# lto = true
-1
View File
@@ -92,7 +92,6 @@ endef
$(eval $(call add_cargo_workspace,main,.))
$(eval $(call add_cargo_workspace,contracts,contracts,--lib --target wasm32-unknown-unknown,RUSTFLAGS='-C link-arg=-s'))
$(eval $(call add_cargo_workspace,wallet,nym-wallet))
$(eval $(call add_cargo_workspace,connect,nym-connect/desktop))
# -----------------------------------------------------------------------------
# SDK
+36 -56
View File
@@ -7,86 +7,66 @@ SPDX-License-Identifier: Apache-2.0
The platform is composed of multiple Rust crates. Top-level executable binary crates include:
* nym-mixnode - shuffles [Sphinx](https://github.com/nymtech/sphinx) packets together to provide privacy against network-level attackers.
* nym-client - an executable which you can build into your own applications. Use it for interacting with Nym nodes.
* nym-socks5-client - a Socks5 proxy you can run on your machine and use with existing applications.
* nym-gateway - acts sort of like a mailbox for mixnet messages, which removes the need for direct delivery to potentially offline or firewalled devices.
* nym-network-monitor - sends packets through the full system to check that they are working as expected, and stores node uptime histories as the basis of a rewards system ("mixmining" or "proof-of-mixing").
* nym-explorer - a (projected) block explorer and (existing) mixnet viewer.
* nym-wallet - a desktop wallet implemented using the [Tauri](https://tauri.studio/en/docs/about/intro) framework.
* `nym-node` - a tool for running a node within the Nym network. Nym Nodes containing functionality such as `mixnode`, `entry-gateway` and `exit-gateway` are fundamental components of Nym Mixnet architecture. Nym Nodes are ran by decentralised node operators. Read more about `nym-node` in [Operators Guide documentation](https://nymtech.net/operators/nodes/nym-node.html). Network functionality of `nym-node` (labeled with `--mode` flag) can be:
- `mixnode` - shuffles [Sphinx](https://github.com/nymtech/sphinx) packets together to provide privacy against network-level attackers.
- `gateway` - acts sort of like a mailbox for mixnet messages, which removes the need for direct delivery to potentially offline or firewalled devices. Gateways can be further categorized as `entry-gateway` and `exit-gateway`. The latter has an extra embedded IP packet router and Network requester to route data to the internet.
* `nym-client` - an executable which you can build into your own applications. Use it for interacting with Nym nodes.
* `nym-socks5-client` - a Socks5 proxy you can run on your machine and use with existing applications.
* `nym-explorer` - a (projected) block explorer and (existing) mixnet viewer.
* `nym-wallet` - a desktop wallet implemented using the [Tauri](https://tauri.studio/en/docs/about/intro) framework.
<!-- coming soon
* `nym-network-monitor` - sends packets through the full system to check that they are working as expected, and stores node uptime histories as the basis of a rewards system ("mixmining" or "proof-of-mixing").
-->
```ascii
┌─►mix──┐ mix mix
│ │
Entry │ │ Exit
client ───► Gateway ──┘ mix │ mix ┌─►mix ───► Gateway ───► internet
│ │
│ │
mix └─►mix──┘ mix
```
[![Build Status](https://img.shields.io/github/actions/workflow/status/nymtech/nym/build.yml?branch=develop&style=for-the-badge&logo=github-actions)](https://github.com/nymtech/nym/actions?query=branch%3Adevelop)
### Building
Platform build instructions are available on [our docs site](https://nymtech.net/docs/binaries/pre-built-binaries.html).
Wallet build instructions are also available on [our docs site](https://nymtech.net/docs/wallet/desktop-wallet.html).
* Platform build instructions are available on Nym [Operators Guide documentation](https://nymtech.net/operators/binaries/building-nym.html).
* Wallet build instructions are available on Nym [Technical docs](https://nymtech.net/docs/wallet/desktop-wallet.html).
### Developing
There's a `.env.sample-dev` file provided which you can rename to `.env` if you want convenient logging, backtrace, or other environment variables pre-set. The `.env` file is ignored so you don't need to worry about checking it in.
There's a [`sandbox.env`](https://github.com/nymtech/nym/envs/sandbox.env) file provided which you can rename to `.env` if you want convenient testing environment. Read more about sandbox environment in our [Operators Guide page](https://nymtech.net/operators/sandbox.html).
For Typescript components, please see [ts-packages](./ts-packages).
References for developers:
* [Developers Portal](https://nymtech.net/developers)
* [Typescript SDKs](https://sdk.nymtech.net/)
* [Technical Documentation - Nym network overview](https://nymtech.net/docs/)
* [Release Cycle - git flow](https://nymtech.net/operators/release-cycle.html)
### Developer chat
> We used to use Keybase for developer chats, but we have since migrated to Matrix and Discord. We no longer check the old **nymtech.friends** Keybase team.
You can chat to us in two places:
* The #dev channel on [Matrix](https://matrix.to/#/#dev:nymtech.chat)
* The various developer channels on [Discord](https://discord.gg/nym)
* The various developer channels on [Discord](discord.gg/nymproject)
### Rewards
### Tokenomics & Rewards
Node, node operator and delegator rewards are determined according to the principles laid out in the section 6 of [Nym Whitepaper](https://nymtech.net/nym-whitepaper.pdf). Below is a TLDR of the variables and formulas involved in calculating the epoch rewards. Initial reward pool is set to 250 million Nym, making the circulating supply 750 million Nym.
|Symbol|Definition|
|---|---|
|<img src="https://render.githubusercontent.com/render/math?math=R#gh-light-mode-only"><img src="https://render.githubusercontent.com/render/math?math=\color{white}R#gh-dark-mode-only">|global share of rewards available, starts at 2% of the reward pool.
|<img src="https://render.githubusercontent.com/render/math?math=R_{i}#gh-light-mode-only"><img src="https://render.githubusercontent.com/render/math?math=\color{white}R_{i}#gh-dark-mode-only">|node reward for mixnode `i`.
|<img src="https://render.githubusercontent.com/render/math?math=\sigma_{i}#gh-light-mode-only"><img src="https://render.githubusercontent.com/render/math?math=\color{white}\sigma_{i}#gh-dark-mode-only">|ratio of total node stake (node bond + all delegations) to the token circulating supply.
|<img src="https://render.githubusercontent.com/render/math?math=\lambda_{i}#gh-light-mode-only"><img src="https://render.githubusercontent.com/render/math?math=\color{white}\lambda_{i}#gh-dark-mode-only">|ratio of stake operator has pledged to their node to the token circulating supply.
|<img src="https://render.githubusercontent.com/render/math?math=\omega_{i}#gh-light-mode-only"><img src="https://render.githubusercontent.com/render/math?math=\color{white}\omega_{i}#gh-dark-mode-only">|fraction of total effort undertaken by node `i`, set to `1/k`.
|<img src="https://render.githubusercontent.com/render/math?math=k#gh-light-mode-only"><img src="https://render.githubusercontent.com/render/math?math=\color{white}k#gh-dark-mode-only">|number of nodes stakeholders are incentivised to create, set by the validators, a matter of governance. Currently determined by the `reward set` size, and set to 720 in testnet Sandbox.
|<img src="https://render.githubusercontent.com/render/math?math=\alpha#gh-light-mode-only"><img src="https://render.githubusercontent.com/render/math?math=\color{white}\alpha#gh-dark-mode-only">|A Sybil attack resistance parameter - the higher this parameter is set, the stronger the reduction in competitiveness for a Sybil attacker.
|<img src="https://render.githubusercontent.com/render/math?math=PM_{i}#gh-light-mode-only"><img src="https://render.githubusercontent.com/render/math?math=\color{white}PM_{i}#gh-dark-mode-only">|declared profit margin of operator `i`, defaults to 10%.
|<img src="https://render.githubusercontent.com/render/math?math=PF_{i}#gh-light-mode-only"><img src="https://render.githubusercontent.com/render/math?math=\color{white}PF_{i}#gh-dark-mode-only">|uptime of node `i`, scaled to 0 - 1, for the rewarding epoch
|<img src="https://render.githubusercontent.com/render/math?math=PP_{i}#gh-light-mode-only"><img src="https://render.githubusercontent.com/render/math?math=\color{white}PP_{i}#gh-dark-mode-only">|cost of operating node `i` for the duration of the rewarding epoch, set to 40 NYMs.
Node reward for node `i` is determined as:
<img src="https://render.githubusercontent.com/render/math?math=R_{i}=PF_{i} \cdot R \cdot (\sigma^'_{i} \cdot \omega_{i} \cdot k %2b \alpha \cdot \lambda^'_{i} \cdot \sigma^'_{i} \cdot k)/(1 %2b \alpha)#gh-light-mode-only">
<img src="https://render.githubusercontent.com/render/math?math=\color{white}R_{i}=PF_{i} \cdot R \cdot (\sigma^'_{i} \cdot \omega_{i} \cdot k %2b \alpha \cdot \lambda^'_{i} \cdot \sigma^'_{i} \cdot k)/(1 %2b \alpha)#gh-dark-mode-only">
where:
<img src="https://render.githubusercontent.com/render/math?math=\sigma^'_{i} = min\{\sigma_{i}, 1/k\}#gh-light-mode-only">
<img src="https://render.githubusercontent.com/render/math?math=\color{white}\sigma^'_{i} = min\{\sigma_{i}, 1/k\}#gh-dark-mode-only">
and
<img src="https://render.githubusercontent.com/render/math?math=\lambda^'_{i} = min\{\lambda_{i}, 1/k\}#gh-light-mode-only">
<img src="https://render.githubusercontent.com/render/math?math=\color{white}\lambda^'_{i} = min\{\lambda_{i}, 1/k\}#gh-dark-mode-only">
Operator of node `i` is credited with the following amount:
<img src="https://render.githubusercontent.com/render/math?math=min\{PP_{i},R_{i})\} %2b max\{0, (PM_{i} %2b (1 - PM_{i}) \cdot \lambda_{i}/\delta_{i}) \cdot (R_{i} - PP_{i})\}#gh-light-mode-only">
<img src="https://render.githubusercontent.com/render/math?math=\color{white}min\{PP_{i},R_{i})\} %2b max\{0, (PM_{i} %2b (1 - PM_{i}) \cdot \lambda_{i}/\delta_{i}) \cdot (R_{i} - PP_{i})\}#gh-dark-mode-only">
Delegate with stake `s` receives:
<img src="https://render.githubusercontent.com/render/math?math=max\{0, (1-PM_{i}) \cdot (s^'/\sigma_{i}) \cdot (R_{i} - PP_{i})\}#gh-light-mode-only">
<img src="https://render.githubusercontent.com/render/math?math=\color{white}max\{0, (1-PM_{i}) \cdot (s^'/\sigma_{i}) \cdot (R_{i} - PP_{i})\}#gh-dark-mode-only">
where `s'` is stake `s` scaled over total token circulating supply.
Nym network economic incentives, operator and validator rewards, and scalability of the network are determined according to the principles laid out in the section 6 of [Nym Whitepaper](https://nymtech.net/nym-whitepaper.pdf).
Initial reward pool is set to 250 million Nym, making the circulating supply 750 million Nym.
### Licensing and copyright information
This is a monorepo and components that make up Nym as a system are licensed individually, so for accurate information, please check individual files.
As a general approach, licensing is as follows this pattern:
- applications and binaries are GPLv3
- libraries and components are Apache 2.0 or MIT
- documentation is Apache 2.0 or CC0-1.0
Again, for accurate information, please check individual files.
Nym Node Operators and Validators Temrs and Conditions can be found [here](https://nymtech.net/terms-and-conditions/operators/v1.0.0).
+3 -3
View File
@@ -1,6 +1,6 @@
[package]
name = "nym-client"
version = "1.1.35"
version = "1.1.36"
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jędrzej Stuczyński <andrew@nymtech.net>"]
description = "Implementation of the Nym Client"
edition = "2021"
@@ -23,7 +23,7 @@ url = { workspace = true }
bs58 = { workspace = true }
clap = { workspace = true, features = ["cargo", "derive"] }
dirs = "4.0"
dirs = { workspace = true }
log = { workspace = true } # self explanatory
rand = { workspace = true }
serde = { workspace = true, features = ["derive"] } # for config serialization/deserialization
@@ -37,7 +37,7 @@ zeroize = { workspace = true }
## internal
nym-bandwidth-controller = { path = "../../common/bandwidth-controller" }
nym-bin-common = { path = "../../common/bin-common", features = ["output_format"] }
nym-bin-common = { path = "../../common/bin-common", features = ["output_format", "clap"] }
nym-client-core = { path = "../../common/client-core", features = ["fs-surb-storage", "fs-gateways-storage", "cli"] }
nym-config = { path = "../../common/config" }
nym-credential-storage = { path = "../../common/credential-storage" }
+78 -236
View File
@@ -744,6 +744,18 @@
"concat-map": "0.0.1"
}
},
"node_modules/braces": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
"integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
"dev": true,
"dependencies": {
"fill-range": "^7.1.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/browserslist": {
"version": "4.20.2",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.20.2.tgz",
@@ -862,51 +874,6 @@
"fsevents": "~2.3.2"
}
},
"node_modules/chokidar/node_modules/braces": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
"dev": true,
"dependencies": {
"fill-range": "^7.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/chokidar/node_modules/fill-range": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
"dev": true,
"dependencies": {
"to-regex-range": "^5.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/chokidar/node_modules/is-number": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
"dev": true,
"engines": {
"node": ">=0.12.0"
}
},
"node_modules/chokidar/node_modules/to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
"dev": true,
"dependencies": {
"is-number": "^7.0.0"
},
"engines": {
"node": ">=8.0"
}
},
"node_modules/chrome-trace-event": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz",
@@ -1593,39 +1560,6 @@
"node": ">=8.6.0"
}
},
"node_modules/fast-glob/node_modules/braces": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
"dev": true,
"dependencies": {
"fill-range": "^7.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/fast-glob/node_modules/fill-range": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
"dev": true,
"dependencies": {
"to-regex-range": "^5.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/fast-glob/node_modules/is-number": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
"dev": true,
"engines": {
"node": ">=0.12.0"
}
},
"node_modules/fast-glob/node_modules/micromatch": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz",
@@ -1639,18 +1573,6 @@
"node": ">=8.6"
}
},
"node_modules/fast-glob/node_modules/to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
"dev": true,
"dependencies": {
"is-number": "^7.0.0"
},
"engines": {
"node": ">=8.0"
}
},
"node_modules/fast-json-stable-stringify": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
@@ -1683,6 +1605,18 @@
"node": ">=0.8.0"
}
},
"node_modules/fill-range": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
"integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
"dev": true,
"dependencies": {
"to-regex-range": "^5.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/finalhandler": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz",
@@ -2137,39 +2071,6 @@
}
}
},
"node_modules/http-proxy-middleware/node_modules/braces": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
"dev": true,
"dependencies": {
"fill-range": "^7.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/http-proxy-middleware/node_modules/fill-range": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
"dev": true,
"dependencies": {
"to-regex-range": "^5.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/http-proxy-middleware/node_modules/is-number": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
"dev": true,
"engines": {
"node": ">=0.12.0"
}
},
"node_modules/http-proxy-middleware/node_modules/micromatch": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz",
@@ -2183,18 +2084,6 @@
"node": ">=8.6"
}
},
"node_modules/http-proxy-middleware/node_modules/to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
"dev": true,
"dependencies": {
"is-number": "^7.0.0"
},
"engines": {
"node": ">=8.0"
}
},
"node_modules/human-signals": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz",
@@ -2361,6 +2250,15 @@
"node": ">=0.10.0"
}
},
"node_modules/is-number": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
"dev": true,
"engines": {
"node": ">=0.12.0"
}
},
"node_modules/is-path-cwd": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz",
@@ -3853,6 +3751,18 @@
"integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==",
"dev": true
},
"node_modules/to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
"dev": true,
"dependencies": {
"is-number": "^7.0.0"
},
"engines": {
"node": ">=8.0"
}
},
"node_modules/toidentifier": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
@@ -5213,6 +5123,15 @@
"concat-map": "0.0.1"
}
},
"braces": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
"integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
"dev": true,
"requires": {
"fill-range": "^7.1.1"
}
},
"browserslist": {
"version": "4.20.2",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.20.2.tgz",
@@ -5283,41 +5202,6 @@
"is-glob": "~4.0.1",
"normalize-path": "~3.0.0",
"readdirp": "~3.6.0"
},
"dependencies": {
"braces": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
"dev": true,
"requires": {
"fill-range": "^7.0.1"
}
},
"fill-range": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
"dev": true,
"requires": {
"to-regex-range": "^5.0.1"
}
},
"is-number": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
"dev": true
},
"to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
"dev": true,
"requires": {
"is-number": "^7.0.0"
}
}
}
},
"chrome-trace-event": {
@@ -5852,30 +5736,6 @@
"micromatch": "^4.0.4"
},
"dependencies": {
"braces": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
"dev": true,
"requires": {
"fill-range": "^7.0.1"
}
},
"fill-range": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
"dev": true,
"requires": {
"to-regex-range": "^5.0.1"
}
},
"is-number": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
"dev": true
},
"micromatch": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz",
@@ -5885,15 +5745,6 @@
"braces": "^3.0.1",
"picomatch": "^2.2.3"
}
},
"to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
"dev": true,
"requires": {
"is-number": "^7.0.0"
}
}
}
},
@@ -5926,6 +5777,15 @@
"websocket-driver": ">=0.5.1"
}
},
"fill-range": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
"integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
"dev": true,
"requires": {
"to-regex-range": "^5.0.1"
}
},
"finalhandler": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz",
@@ -6247,30 +6107,6 @@
"micromatch": "^4.0.2"
},
"dependencies": {
"braces": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
"dev": true,
"requires": {
"fill-range": "^7.0.1"
}
},
"fill-range": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
"dev": true,
"requires": {
"to-regex-range": "^5.0.1"
}
},
"is-number": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
"dev": true
},
"micromatch": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz",
@@ -6280,15 +6116,6 @@
"braces": "^3.0.1",
"picomatch": "^2.2.3"
}
},
"to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
"dev": true,
"requires": {
"is-number": "^7.0.0"
}
}
}
},
@@ -6407,6 +6234,12 @@
"is-extglob": "^2.1.1"
}
},
"is-number": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
"dev": true
},
"is-path-cwd": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz",
@@ -7524,6 +7357,15 @@
"integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==",
"dev": true
},
"to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
"dev": true,
"requires": {
"is-number": "^7.0.0"
}
},
"toidentifier": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
+3 -1
View File
@@ -106,8 +106,10 @@ impl SocketClient {
};
let storage = self.initialise_storage().await?;
let user_agent = nym_bin_common::bin_info!().into();
let mut base_client = BaseClientBuilder::new(&self.config.base, storage, dkg_query_client);
let mut base_client = BaseClientBuilder::new(&self.config.base, storage, dkg_query_client)
.with_user_agent(user_agent);
if let Some(custom_mixnet) = &self.custom_mixnet {
base_client = base_client.with_stored_topology(custom_mixnet)?;
+2 -1
View File
@@ -22,8 +22,9 @@ impl AsRef<CommonClientAddGatewayArgs> for Args {
}
pub(crate) async fn execute(args: Args) -> Result<(), ClientError> {
let user_agent = nym_bin_common::bin_info!().into();
let output = args.output;
let res = add_gateway::<CliNativeClient, _>(args).await?;
let res = add_gateway::<CliNativeClient, _>(args, Some(user_agent)).await?;
println!("{}", output.format(&res));
Ok(())
+2 -1
View File
@@ -114,8 +114,9 @@ impl Display for InitResults {
pub(crate) async fn execute(args: Init) -> Result<(), ClientError> {
eprintln!("Initialising client...");
let user_agent = nym_bin_common::bin_info!().into();
let output = args.output;
let res = initialise_client::<CliNativeClient>(args).await?;
let res = initialise_client::<CliNativeClient>(args, Some(user_agent)).await?;
let init_results = InitResults::new(res);
println!("{}", output.format(&init_results));
+6 -5
View File
@@ -1,6 +1,6 @@
[package]
name = "nym-socks5-client"
version = "1.1.35"
version = "1.1.36"
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"
@@ -25,17 +25,18 @@ zeroize = { workspace = true }
nym-bin-common = { path = "../../common/bin-common", features = ["output_format"] }
nym-client-core = { path = "../../common/client-core", features = ["fs-surb-storage", "fs-gateways-storage", "cli"] }
nym-config = { path = "../../common/config" }
nym-credential-storage = { path = "../../common/credential-storage" }
nym-credentials = { path = "../../common/credentials" }
nym-crypto = { path = "../../common/crypto" }
nym-gateway-requests = { path = "../../gateway/gateway-requests" }
nym-credential-storage = { path = "../../common/credential-storage" }
nym-id = { path = "../../common/nym-id" }
nym-network-defaults = { path = "../../common/network-defaults" }
nym-sphinx = { path = "../../common/nymsphinx" }
nym-ordered-buffer = { path = "../../common/socks5/ordered-buffer" }
nym-pemstore = { path = "../../common/pemstore" }
nym-topology = { path = "../../common/topology" }
nym-socks5-client-core = { path = "../../common/socks5-client-core" }
nym-id = { path = "../../common/nym-id" }
nym-sphinx = { path = "../../common/nymsphinx" }
nym-topology = { path = "../../common/topology" }
nym-validator-client = { path = "../../common/client-libs/validator-client", features = ["http-client"] }
[features]
default = []
+2 -1
View File
@@ -22,8 +22,9 @@ impl AsRef<CommonClientAddGatewayArgs> for Args {
}
pub(crate) async fn execute(args: Args) -> Result<(), Socks5ClientError> {
let user_agent = nym_bin_common::bin_info!().into();
let output = args.output;
let res = add_gateway::<CliSocks5Client, _>(args).await?;
let res = add_gateway::<CliSocks5Client, _>(args, Some(user_agent)).await?;
println!("{}", output.format(&res));
Ok(())
+2 -1
View File
@@ -129,8 +129,9 @@ impl Display for InitResults {
pub(crate) async fn execute(args: Init) -> Result<(), Socks5ClientError> {
eprintln!("Initialising client...");
let user_agent = nym_bin_common::bin_info!().into();
let output = args.output;
let res = initialise_client::<CliSocks5Client>(args).await?;
let res = initialise_client::<CliSocks5Client>(args, Some(user_agent)).await?;
let init_results = InitResults::new(res);
println!("{}", output.format(&init_results));
+9 -3
View File
@@ -116,7 +116,13 @@ pub(crate) async fn execute(args: Run) -> Result<(), Box<dyn std::error::Error +
let storage =
OnDiskPersistent::from_paths(config.storage_paths.common_paths, &config.core.base.debug)
.await?;
NymClient::new(config.core, storage, args.common_args.custom_mixnet)
.run_forever()
.await
let user_agent = nym_bin_common::bin_info!().into();
NymClient::new(
config.core,
storage,
user_agent,
args.common_args.custom_mixnet,
)
.run_forever()
.await
}
+5 -4
View File
@@ -9,9 +9,9 @@ repository = { workspace = true }
[dependencies]
const-str = { workspace = true }
clap = { workspace = true, features = ["derive"] }
clap_complete = { workspace = true }
clap_complete_fig = { workspace = true }
clap = { workspace = true, features = ["derive"], optional = true }
clap_complete = { workspace = true, optional = true }
clap_complete_fig = { workspace = true, optional = true }
log = { workspace = true }
pretty_env_logger = { workspace = true }
semver = "0.11"
@@ -34,7 +34,7 @@ vergen = { workspace = true, features = ["build", "git", "gitcl", "rustc", "carg
[features]
default = []
openapi = ["utoipa"]
output_format = ["serde_json"]
output_format = ["serde_json", "dep:clap"]
bin_info_schema = ["schemars"]
basic_tracing = ["tracing-subscriber"]
tracing = [
@@ -44,3 +44,4 @@ tracing = [
"tracing-opentelemetry",
"opentelemetry",
]
clap = [ "dep:clap", "dep:clap_complete", "dep:clap_complete_fig" ]
@@ -44,6 +44,10 @@ pub struct BinaryBuildInformation {
/// Provides the cargo debug mode that was used for the build.
// NOTE: keep the old name cargo_profile instead of cargo_debug for backwards compatibility
pub cargo_profile: &'static str,
// VERGEN_CARGO_TARGET_TRIPLE
/// Provides the cargo target triple that was used for the build.
pub cargo_triple: &'static str,
}
impl BinaryBuildInformation {
@@ -66,6 +70,7 @@ impl BinaryBuildInformation {
rustc_version: env!("VERGEN_RUSTC_SEMVER"),
rustc_channel: env!("VERGEN_RUSTC_CHANNEL"),
cargo_profile,
cargo_triple: env!("VERGEN_CARGO_TARGET_TRIPLE"),
}
}
@@ -95,6 +100,7 @@ impl BinaryBuildInformation {
rustc_version: env!("VERGEN_RUSTC_SEMVER"),
rustc_channel: env!("VERGEN_RUSTC_CHANNEL"),
cargo_profile,
cargo_triple: env!("VERGEN_CARGO_TARGET_TRIPLE"),
}
}
@@ -109,6 +115,7 @@ impl BinaryBuildInformation {
rustc_version: self.rustc_version.to_owned(),
rustc_channel: self.rustc_channel.to_owned(),
cargo_profile: self.cargo_profile.to_owned(),
cargo_triple: self.cargo_triple.to_owned(),
}
}
@@ -156,6 +163,15 @@ pub struct BinaryBuildInformationOwned {
/// Provides the cargo debug mode that was used for the build.
// NOTE: keep the old name cargo_profile instead of cargo_debug for backwards compatibility
pub cargo_profile: String,
// VERGEN_CARGO_TARGET_TRIPLE
/// Provides the cargo target triple that was used for the build.
#[serde(default = "unknown")]
pub cargo_triple: String,
}
fn unknown() -> String {
"unknown".to_string()
}
impl Display for BinaryBuildInformationOwned {
+3 -1
View File
@@ -2,9 +2,11 @@
// SPDX-License-Identifier: Apache-2.0
pub mod build_information;
pub mod completions;
pub mod logging;
pub mod version_checker;
#[cfg(feature = "clap")]
pub mod completions;
#[cfg(feature = "output_format")]
pub mod output_format;
+2 -2
View File
@@ -10,7 +10,7 @@ license.workspace = true
[dependencies]
async-trait = { workspace = true }
base64 = "0.21.2"
base64 = { workspace = true }
bs58 = { workspace = true }
cfg-if = { workspace = true }
clap = { workspace = true, optional = true }
@@ -20,7 +20,7 @@ log = { workspace = true }
rand = { workspace = true }
serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true }
sha2 = "0.10.6"
sha2 = { workspace = true }
si-scale = { workspace = true }
tap = { workspace = true }
thiserror = { workspace = true }
@@ -24,6 +24,11 @@ const DEFAULT_MESSAGE_STREAM_AVERAGE_DELAY: Duration = Duration::from_millis(20)
const DEFAULT_AVERAGE_PACKET_DELAY: Duration = Duration::from_millis(50);
const DEFAULT_TOPOLOGY_REFRESH_RATE: Duration = Duration::from_secs(5 * 60); // every 5min
const DEFAULT_TOPOLOGY_RESOLUTION_TIMEOUT: Duration = Duration::from_millis(5_000);
// the same values as our current (10.06.24) blacklist
const DEFAULT_MIN_MIXNODE_PERFORMANCE: u8 = 50;
const DEFAULT_MIN_GATEWAY_PERFORMANCE: u8 = 50;
const DEFAULT_MAX_STARTUP_GATEWAY_WAITING_PERIOD: Duration = Duration::from_secs(70 * 60); // 70min -> full epoch (1h) + a bit of overhead
// Set this to a high value for now, so that we don't risk sporadic timeouts that might cause
@@ -516,6 +521,14 @@ pub struct Topology {
/// Specifies the mixnode topology to be used for sending packets.
pub topology_structure: TopologyStructure,
/// Specifies a minimum performance of a mixnode that is used on route construction.
/// This setting is only applicable when `NymApi` topology is used.
pub minimum_mixnode_performance: u8,
/// Specifies a minimum performance of a gateway that is used on route construction.
/// This setting is only applicable when `NymApi` topology is used.
pub minimum_gateway_performance: u8,
}
#[allow(clippy::large_enum_variant)]
@@ -550,6 +563,8 @@ impl Default for Topology {
disable_refreshing: false,
max_startup_gateway_waiting_period: DEFAULT_MAX_STARTUP_GATEWAY_WAITING_PERIOD,
topology_structure: TopologyStructure::default(),
minimum_mixnode_performance: DEFAULT_MIN_MIXNODE_PERFORMANCE,
minimum_gateway_performance: DEFAULT_MIN_GATEWAY_PERFORMANCE,
}
}
}
@@ -146,6 +146,7 @@ impl From<ConfigV5> for Config {
.topology
.max_startup_gateway_waiting_period,
topology_structure: value.debug.topology.topology_structure.into(),
..Default::default()
},
reply_surbs: ReplySurbs {
minimum_reply_surb_storage_threshold: value
@@ -0,0 +1,18 @@
/*
* Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
* SPDX-License-Identifier: Apache-2.0
*/
CREATE TABLE remote_gateway_details_temp
(
gateway_id_bs58 TEXT NOT NULL UNIQUE PRIMARY KEY REFERENCES registered_gateway (gateway_id_bs58),
derived_aes128_ctr_blake3_hmac_keys_bs58 TEXT NOT NULL,
gateway_owner_address TEXT,
gateway_listener TEXT NOT NULL,
wg_tun_address TEXT
);
INSERT INTO remote_gateway_details_temp SELECT * FROM remote_gateway_details;
DROP TABLE remote_gateway_details;
ALTER TABLE remote_gateway_details_temp RENAME TO remote_gateway_details;
@@ -65,7 +65,7 @@ impl GatewayDetails {
pub fn new_remote(
gateway_id: identity::PublicKey,
derived_aes128_ctr_blake3_hmac_keys: Arc<SharedKeys>,
gateway_owner_address: AccountId,
gateway_owner_address: Option<AccountId>,
gateway_listener: Url,
wg_tun_address: Option<Url>,
) -> Self {
@@ -170,7 +170,7 @@ pub struct RegisteredGateway {
pub struct RawRemoteGatewayDetails {
pub gateway_id_bs58: String,
pub derived_aes128_ctr_blake3_hmac_keys_bs58: String,
pub gateway_owner_address: String,
pub gateway_owner_address: Option<String>,
pub gateway_listener: String,
pub wg_tun_address: Option<String>,
}
@@ -195,14 +195,19 @@ impl TryFrom<RawRemoteGatewayDetails> for RemoteGatewayDetails {
})?,
);
let gateway_owner_address =
AccountId::from_str(&value.gateway_owner_address).map_err(|source| {
BadGateway::MalformedGatewayOwnerAccountAddress {
gateway_id: value.gateway_id_bs58.clone(),
raw_owner: value.gateway_owner_address.clone(),
source,
}
})?;
let gateway_owner_address = value
.gateway_owner_address
.as_ref()
.map(|raw_owner| {
AccountId::from_str(raw_owner).map_err(|source| {
BadGateway::MalformedGatewayOwnerAccountAddress {
gateway_id: value.gateway_id_bs58.clone(),
raw_owner: raw_owner.clone(),
source,
}
})
})
.transpose()?;
let gateway_listener = Url::parse(&value.gateway_listener).map_err(|source| {
BadGateway::MalformedListener {
@@ -241,7 +246,7 @@ impl<'a> From<&'a RemoteGatewayDetails> for RawRemoteGatewayDetails {
derived_aes128_ctr_blake3_hmac_keys_bs58: value
.derived_aes128_ctr_blake3_hmac_keys
.to_base58_string(),
gateway_owner_address: value.gateway_owner_address.to_string(),
gateway_owner_address: value.gateway_owner_address.as_ref().map(|o| o.to_string()),
gateway_listener: value.gateway_listener.to_string(),
wg_tun_address: value.wg_tun_address.as_ref().map(|addr| addr.to_string()),
}
@@ -256,7 +261,7 @@ pub struct RemoteGatewayDetails {
// the keys will be zeroized
pub derived_aes128_ctr_blake3_hmac_keys: Arc<SharedKeys>,
pub gateway_owner_address: AccountId,
pub gateway_owner_address: Option<AccountId>,
pub gateway_listener: Url,
@@ -16,6 +16,7 @@ use log::info;
use nym_client_core_gateways_storage::GatewayDetails;
use nym_crypto::asymmetric::identity;
use nym_topology::NymTopology;
use nym_validator_client::UserAgent;
use std::path::PathBuf;
#[cfg_attr(feature = "cli", derive(clap::Args))]
@@ -60,7 +61,10 @@ pub struct CommonClientAddGatewayArgs {
pub custom_mixnet: Option<PathBuf>,
}
pub async fn add_gateway<C, A>(args: A) -> Result<GatewayInfo, C::Error>
pub async fn add_gateway<C, A>(
args: A,
user_agent: Option<UserAgent>,
) -> Result<GatewayInfo, C::Error>
where
A: AsRef<CommonClientAddGatewayArgs>,
C: CliClient,
@@ -111,7 +115,8 @@ where
hardcoded_topology.get_gateways()
} else {
let mut rng = rand::thread_rng();
crate::init::helpers::current_gateways(&mut rng, &core.client.nym_api_urls).await?
crate::init::helpers::current_gateways(&mut rng, &core.client.nym_api_urls, user_agent)
.await?
};
// since we're registering with a brand new gateway,
@@ -16,6 +16,7 @@ use log::info;
use nym_client_core_gateways_storage::GatewayDetails;
use nym_crypto::asymmetric::identity;
use nym_topology::NymTopology;
use nym_validator_client::UserAgent;
use rand::rngs::OsRng;
use std::path::PathBuf;
@@ -96,6 +97,7 @@ pub struct InitResultsWithConfig<T> {
pub async fn initialise_client<C>(
init_args: C::InitArgs,
user_agent: Option<UserAgent>,
) -> Result<InitResultsWithConfig<C::Config>, C::Error>
where
C: InitialisableClient,
@@ -163,7 +165,8 @@ where
hardcoded_topology.get_gateways()
} else {
let mut rng = rand::thread_rng();
crate::init::helpers::current_gateways(&mut rng, &core.client.nym_api_urls).await?
crate::init::helpers::current_gateways(&mut rng, &core.client.nym_api_urls, user_agent)
.await?
};
let gateway_setup = GatewaySetup::New {
@@ -25,7 +25,7 @@ use crate::client::replies::reply_storage::{
};
use crate::client::topology_control::nym_api_provider::NymApiTopologyProvider;
use crate::client::topology_control::{
TopologyAccessor, TopologyRefresher, TopologyRefresherConfig,
nym_api_provider, TopologyAccessor, TopologyRefresher, TopologyRefresherConfig,
};
use crate::config::{Config, DebugConfig};
use crate::error::ClientCoreError;
@@ -53,7 +53,7 @@ use nym_task::connections::{ConnectionCommandReceiver, ConnectionCommandSender,
use nym_task::{TaskClient, TaskHandle};
use nym_topology::provider_trait::TopologyProvider;
use nym_topology::HardcodedTopologyProvider;
use nym_validator_client::nyxd::contract_traits::DkgQueryClient;
use nym_validator_client::{nyxd::contract_traits::DkgQueryClient, UserAgent};
use rand::rngs::OsRng;
use std::fmt::Debug;
use std::os::raw::c_int as RawFd;
@@ -184,6 +184,7 @@ pub struct BaseClientBuilder<'a, C, S: MixnetClientStorage> {
custom_topology_provider: Option<Box<dyn TopologyProvider + Send + Sync>>,
custom_gateway_transceiver: Option<Box<dyn GatewayTransceiver + Send>>,
shutdown: Option<TaskClient>,
user_agent: Option<UserAgent>,
setup_method: GatewaySetup,
}
@@ -207,6 +208,7 @@ where
custom_topology_provider: None,
custom_gateway_transceiver: None,
shutdown: None,
user_agent: None,
setup_method: GatewaySetup::MustLoad { gateway_id: None },
}
}
@@ -250,6 +252,12 @@ where
self
}
#[must_use]
pub fn with_user_agent(mut self, user_agent: UserAgent) -> Self {
self.user_agent = Some(user_agent);
self
}
pub fn with_stored_topology<P: AsRef<Path>>(
mut self,
file: P,
@@ -388,7 +396,10 @@ where
let cfg = GatewayConfig::new(
details.gateway_id,
Some(details.gateway_owner_address.to_string()),
details
.gateway_owner_address
.as_ref()
.map(|o| o.to_string()),
gateway_listener,
);
GatewayClient::new(
@@ -462,14 +473,20 @@ where
fn setup_topology_provider(
custom_provider: Option<Box<dyn TopologyProvider + Send + Sync>>,
provider_from_config: config::TopologyStructure,
config_topology: config::Topology,
nym_api_urls: Vec<Url>,
user_agent: Option<UserAgent>,
) -> Box<dyn TopologyProvider + Send + Sync> {
// if no custom provider was ... provided ..., create one using nym-api
custom_provider.unwrap_or_else(|| match provider_from_config {
custom_provider.unwrap_or_else(|| match config_topology.topology_structure {
config::TopologyStructure::NymApi => Box::new(NymApiTopologyProvider::new(
nym_api_provider::Config {
min_mixnode_performance: config_topology.minimum_mixnode_performance,
min_gateway_performance: config_topology.minimum_gateway_performance,
},
nym_api_urls,
env!("CARGO_PKG_VERSION").to_string(),
user_agent,
)),
config::TopologyStructure::GeoAware(group_by) => {
Box::new(GeoAwareTopologyProvider::new(
@@ -680,8 +697,9 @@ where
let topology_provider = Self::setup_topology_provider(
self.custom_topology_provider.take(),
self.config.debug.topology.topology_structure,
self.config.debug.topology,
self.config.get_nym_api_endpoints(),
self.user_agent.clone(),
);
// needs to be started as the first thing to block if required waiting for the gateway
@@ -92,11 +92,11 @@ pub mod v1_1_33 {
message: format!("the stored gateway id was malformed: {err}"),
})?,
derived_aes128_ctr_blake3_hmac_keys: Arc::new(gateway_shared_key),
gateway_owner_address: gateway_owner.parse().map_err(|err| {
gateway_owner_address: Some(gateway_owner.parse().map_err(|err| {
ClientCoreError::UpgradeFailure {
message: format!("the stored gateway owner address was malformed: {err}"),
}
})?,
})?),
gateway_listener: gateway_listener.parse().map_err(|err| {
ClientCoreError::UpgradeFailure {
message: format!("the stored gateway listener address was malformed: {err}"),
@@ -2,14 +2,36 @@
// SPDX-License-Identifier: Apache-2.0
use async_trait::async_trait;
use log::{error, warn};
use log::{debug, error, warn};
use nym_topology::provider_trait::TopologyProvider;
use nym_topology::{nym_topology_from_detailed, NymTopology, NymTopologyError};
use nym_topology::{NymTopology, NymTopologyError};
use nym_validator_client::UserAgent;
use rand::prelude::SliceRandom;
use rand::thread_rng;
use url::Url;
// the same values as our current (10.06.24) blacklist
pub const DEFAULT_MIN_MIXNODE_PERFORMANCE: u8 = 50;
pub const DEFAULT_MIN_GATEWAY_PERFORMANCE: u8 = 50;
pub(crate) struct Config {
pub(crate) min_mixnode_performance: u8,
pub(crate) min_gateway_performance: u8,
}
impl Default for Config {
fn default() -> Self {
// old values that decided on blacklist membership
Config {
min_mixnode_performance: DEFAULT_MIN_MIXNODE_PERFORMANCE,
min_gateway_performance: DEFAULT_MIN_GATEWAY_PERFORMANCE,
}
}
}
pub(crate) struct NymApiTopologyProvider {
config: Config,
validator_client: nym_validator_client::client::NymApiClient,
nym_api_urls: Vec<Url>,
@@ -18,13 +40,26 @@ pub(crate) struct NymApiTopologyProvider {
}
impl NymApiTopologyProvider {
pub(crate) fn new(mut nym_api_urls: Vec<Url>, client_version: String) -> Self {
pub(crate) fn new(
config: Config,
mut nym_api_urls: Vec<Url>,
client_version: String,
user_agent: Option<UserAgent>,
) -> Self {
nym_api_urls.shuffle(&mut thread_rng());
NymApiTopologyProvider {
validator_client: nym_validator_client::client::NymApiClient::new(
let validator_client = if let Some(user_agent) = user_agent {
nym_validator_client::client::NymApiClient::new_with_user_agent(
nym_api_urls[0].clone(),
),
user_agent,
)
} else {
nym_validator_client::client::NymApiClient::new(nym_api_urls[0].clone())
};
NymApiTopologyProvider {
config,
validator_client,
nym_api_urls,
client_version,
currently_used_api: 0,
@@ -61,7 +96,11 @@ impl NymApiTopologyProvider {
}
async fn get_current_compatible_topology(&mut self) -> Option<NymTopology> {
let mixnodes = match self.validator_client.get_cached_active_mixnodes().await {
let mixnodes = match self
.validator_client
.get_basic_mixnodes(Some(self.client_version.clone()))
.await
{
Err(err) => {
error!("failed to get network mixnodes - {err}");
return None;
@@ -69,7 +108,11 @@ impl NymApiTopologyProvider {
Ok(mixes) => mixes,
};
let gateways = match self.validator_client.get_cached_described_gateways().await {
let gateways = match self
.validator_client
.get_basic_gateways(Some(self.client_version.clone()))
.await
{
Err(err) => {
error!("failed to get network gateways - {err}");
return None;
@@ -77,8 +120,20 @@ impl NymApiTopologyProvider {
Ok(gateways) => gateways,
};
let topology = nym_topology_from_detailed(mixnodes, gateways)
.filter_system_version(&self.client_version);
debug!(
"there are {} mixnodes and {} gateways in total (before performance filtering)",
mixnodes.len(),
gateways.len()
);
let topology = NymTopology::from_unordered(
mixnodes.iter().filter(|m| {
m.performance.round_to_integer() >= self.config.min_mixnode_performance
}),
gateways.iter().filter(|g| {
g.performance.round_to_integer() >= self.config.min_gateway_performance
}),
);
if let Err(err) = self.check_layer_distribution(&topology) {
warn!("The current filtered active topology has extremely skewed layer distribution. It cannot be used: {err}");
+7 -1
View File
@@ -9,6 +9,7 @@ use nym_crypto::asymmetric::identity;
use nym_gateway_client::GatewayClient;
use nym_topology::{filter::VersionFilterable, gateway, mix};
use nym_validator_client::client::IdentityKeyRef;
use nym_validator_client::UserAgent;
use rand::{seq::SliceRandom, Rng};
use std::{sync::Arc, time::Duration};
use tungstenite::Message;
@@ -59,11 +60,16 @@ impl<'a> GatewayWithLatency<'a> {
pub async fn current_gateways<R: Rng>(
rng: &mut R,
nym_apis: &[Url],
user_agent: Option<UserAgent>,
) -> Result<Vec<gateway::Node>, ClientCoreError> {
let nym_api = nym_apis
.choose(rng)
.ok_or(ClientCoreError::ListOfNymApisIsEmpty)?;
let client = nym_validator_client::client::NymApiClient::new(nym_api.clone());
let client = if let Some(user_agent) = user_agent {
nym_validator_client::client::NymApiClient::new_with_user_agent(nym_api.clone(), user_agent)
} else {
nym_validator_client::client::NymApiClient::new(nym_api.clone())
};
log::debug!("Fetching list of gateways from: {nym_api}");
+14 -8
View File
@@ -29,7 +29,7 @@ pub enum SelectedGateway {
Remote {
gateway_id: identity::PublicKey,
gateway_owner_address: AccountId,
gateway_owner_address: Option<AccountId>,
gateway_listener: Url,
@@ -84,13 +84,19 @@ impl SelectedGateway {
let wg_tun_address = wg_tun_address(wg_tun_ip_address, &node)?;
let gateway_owner_address = AccountId::from_str(&node.owner).map_err(|source| {
ClientCoreError::MalformedGatewayOwnerAccountAddress {
gateway_id: node.identity_key.to_base58_string(),
raw_owner: node.owner,
err: source.to_string(),
}
})?;
let gateway_owner_address = node
.owner
.as_ref()
.map(|raw_owner| {
AccountId::from_str(raw_owner).map_err(|source| {
ClientCoreError::MalformedGatewayOwnerAccountAddress {
gateway_id: node.identity_key.to_base58_string(),
raw_owner: raw_owner.clone(),
err: source.to_string(),
}
})
})
.transpose()?;
let gateway_listener =
Url::parse(&gateway_listener).map_err(|source| ClientCoreError::MalformedListener {
@@ -14,7 +14,6 @@ colored = { workspace = true }
nym-coconut-dkg-common = { path = "../../cosmwasm-smart-contracts/coconut-dkg" }
nym-contracts-common = { path = "../../cosmwasm-smart-contracts/contracts-common" }
nym-ephemera-common = { path = "../../cosmwasm-smart-contracts/ephemera" }
nym-mixnet-contract-common = { path = "../../cosmwasm-smart-contracts/mixnet-contract" }
nym-vesting-contract-common = { path = "../../cosmwasm-smart-contracts/vesting-contract" }
nym-coconut-bandwidth-contract-common = { path = "../../cosmwasm-smart-contracts/coconut-bandwidth-contract" }
@@ -22,7 +21,7 @@ nym-multisig-contract-common = { path = "../../cosmwasm-smart-contracts/multisig
nym-group-contract-common = { path = "../../cosmwasm-smart-contracts/group-contract" }
serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true }
nym-http-api-client = { path = "../../../common/http-api-client"}
nym-http-api-client = { path = "../../../common/http-api-client" }
thiserror = { workspace = true }
log = { workspace = true }
url = { workspace = true, features = ["serde"] }
@@ -55,7 +54,7 @@ cw-controllers = { workspace = true }
prost = { workspace = true, default-features = false }
flate2 = { workspace = true }
sha2 = { version = "0.9.5" }
itertools = { version = "0.10" }
itertools = { workspace = true }
zeroize = { workspace = true, features = ["zeroize_derive"] }
cosmwasm-std = { workspace = true }
@@ -18,6 +18,8 @@ use nym_api_requests::models::{
GatewayCoreStatusResponse, MixnodeCoreStatusResponse, MixnodeStatusResponse,
RewardEstimationResponse, StakeSaturationResponse,
};
use nym_api_requests::nym_nodes::SkimmedNode;
use nym_http_api_client::UserAgent;
use nym_network_defaults::NymNetworkDetails;
use url::Url;
@@ -257,6 +259,16 @@ impl NymApiClient {
NymApiClient { nym_api }
}
pub fn new_with_user_agent(api_url: Url, user_agent: UserAgent) -> Self {
let nym_api = nym_api::Client::builder::<_, ValidatorClientError>(api_url)
.expect("invalid api url")
.with_user_agent(user_agent)
.build::<ValidatorClientError>()
.expect("failed to build nym api client");
NymApiClient { nym_api }
}
pub fn api_url(&self) -> &Url {
self.nym_api.current_url()
}
@@ -265,6 +277,28 @@ impl NymApiClient {
self.nym_api.change_base_url(new_endpoint);
}
pub async fn get_basic_mixnodes(
&self,
semver_compatibility: Option<String>,
) -> Result<Vec<SkimmedNode>, ValidatorClientError> {
Ok(self
.nym_api
.get_basic_mixnodes(semver_compatibility)
.await?
.nodes)
}
pub async fn get_basic_gateways(
&self,
semver_compatibility: Option<String>,
) -> Result<Vec<SkimmedNode>, ValidatorClientError> {
Ok(self
.nym_api
.get_basic_gateways(semver_compatibility)
.await?
.nodes)
}
pub async fn get_cached_active_mixnodes(
&self,
) -> Result<Vec<MixNodeDetails>, ValidatorClientError> {
@@ -17,6 +17,7 @@ pub use crate::signing::direct_wallet::DirectSecp256k1HdWallet;
pub use client::NymApiClient;
pub use client::{Client, CoconutApiClient, Config};
pub use nym_api_requests::*;
pub use nym_http_api_client::UserAgent;
#[cfg(feature = "http-client")]
pub use cosmrs::rpc::HttpClient as HttpRpcClient;
@@ -31,6 +31,7 @@ pub mod routes;
use nym_api_requests::coconut::models::FreePassNonceResponse;
use nym_api_requests::coconut::FreePassRequest;
use nym_api_requests::nym_nodes::{CachedNodesResponse, SkimmedNode};
pub use nym_http_api_client::Client;
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
@@ -95,6 +96,52 @@ pub trait NymApiClientExt: ApiClient {
.await
}
async fn get_basic_mixnodes(
&self,
semver_compatibility: Option<String>,
) -> Result<CachedNodesResponse<SkimmedNode>, NymAPIError> {
let params = if let Some(semver_compatibility) = &semver_compatibility {
vec![("semver_compatibility", semver_compatibility.as_str())]
} else {
vec![]
};
self.get_json(
&[
routes::API_VERSION,
"unstable",
"nym-nodes",
"mixnodes",
"skimmed",
],
&params,
)
.await
}
async fn get_basic_gateways(
&self,
semver_compatibility: Option<String>,
) -> Result<CachedNodesResponse<SkimmedNode>, NymAPIError> {
let params = if let Some(semver_compatibility) = &semver_compatibility {
vec![("semver_compatibility", semver_compatibility.as_str())]
} else {
vec![]
};
self.get_json(
&[
routes::API_VERSION,
"unstable",
"nym-nodes",
"gateways",
"skimmed",
],
&params,
)
.await
}
async fn get_active_mixnodes(&self) -> Result<Vec<MixNodeDetails>, NymAPIError> {
self.get_json(
&[routes::API_VERSION, routes::MIXNODES, routes::ACTIVE],
@@ -1,79 +0,0 @@
// 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 nym_ephemera_common::msg::QueryMsg as EphemeraQueryMsg;
use nym_ephemera_common::peers::PagedPeerResponse;
use nym_ephemera_common::types::JsonPeerInfo;
use serde::Deserialize;
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
pub trait EphemeraQueryClient {
async fn query_ephemera_contract<T>(&self, query: EphemeraQueryMsg) -> Result<T, NyxdError>
where
for<'a> T: Deserialize<'a>;
async fn get_peers_paged(
&self,
start_after: Option<String>,
limit: Option<u32>,
) -> Result<PagedPeerResponse, NyxdError> {
let request = EphemeraQueryMsg::GetPeers { start_after, limit };
self.query_ephemera_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 PagedEphemeraQueryClient: EphemeraQueryClient {
async fn get_all_ephemera_peers(&self) -> Result<Vec<JsonPeerInfo>, NyxdError> {
collect_paged!(self, get_peers_paged, peers)
}
}
#[async_trait]
impl<T> PagedEphemeraQueryClient for T where T: EphemeraQueryClient {}
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
impl<C> EphemeraQueryClient for C
where
C: CosmWasmClient + NymContractsProvider + Send + Sync,
{
async fn query_ephemera_contract<T>(&self, query: EphemeraQueryMsg) -> Result<T, NyxdError>
where
for<'a> T: Deserialize<'a>,
{
let ephemera_contract_address = &self
.ephemera_contract_address()
.ok_or_else(|| NyxdError::unavailable_contract_address("ephemera contract"))?;
self.query_contract_smart(ephemera_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: EphemeraQueryClient + Send + Sync>(
client: C,
msg: EphemeraQueryMsg,
) {
match msg {
EphemeraQueryMsg::GetPeers { limit, start_after } => {
client.get_peers_paged(start_after, limit).ignore()
}
};
}
}
@@ -1,86 +0,0 @@
// 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_ephemera_common::msg::ExecuteMsg as EphemeraExecuteMsg;
use nym_ephemera_common::types::JsonPeerInfo;
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
pub trait EphemeraSigningClient {
async fn execute_ephemera_contract(
&self,
fee: Option<Fee>,
msg: EphemeraExecuteMsg,
memo: String,
funds: Vec<Coin>,
) -> Result<ExecuteResult, NyxdError>;
async fn register_as_peer(
&self,
peer_info: JsonPeerInfo,
fee: Option<Fee>,
) -> Result<ExecuteResult, NyxdError> {
let req = EphemeraExecuteMsg::RegisterPeer { peer_info };
self.execute_ephemera_contract(fee, req, "registering as peer".to_string(), vec![])
.await
}
}
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
impl<C> EphemeraSigningClient for C
where
C: SigningCosmWasmClient + NymContractsProvider + Sync,
NyxdError: From<<Self as OfflineSigner>::Error>,
{
async fn execute_ephemera_contract(
&self,
fee: Option<Fee>,
msg: EphemeraExecuteMsg,
memo: String,
funds: Vec<Coin>,
) -> Result<ExecuteResult, NyxdError> {
let ephemera_contract_address = self
.ephemera_contract_address()
.ok_or_else(|| NyxdError::unavailable_contract_address("ephemera contract"))?;
let fee = fee.unwrap_or(Fee::Auto(Some(self.simulated_gas_multiplier())));
let signer_address = &self.signer_addresses()?[0];
self.execute(
signer_address,
ephemera_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: EphemeraSigningClient + Send + Sync>(
client: C,
msg: EphemeraExecuteMsg,
) {
match msg {
EphemeraExecuteMsg::RegisterPeer { peer_info } => {
client.register_as_peer(peer_info, None).ignore()
}
};
}
}
@@ -10,7 +10,6 @@ use std::str::FromStr;
// query clients
pub mod coconut_bandwidth_query_client;
pub mod dkg_query_client;
pub mod ephemera_query_client;
pub mod group_query_client;
pub mod mixnet_query_client;
pub mod multisig_query_client;
@@ -19,7 +18,6 @@ pub mod vesting_query_client;
// signing clients
pub mod coconut_bandwidth_signing_client;
pub mod dkg_signing_client;
pub mod ephemera_signing_client;
pub mod group_signing_client;
pub mod mixnet_signing_client;
pub mod multisig_signing_client;
@@ -30,7 +28,6 @@ pub use coconut_bandwidth_query_client::{
CoconutBandwidthQueryClient, PagedCoconutBandwidthQueryClient,
};
pub use dkg_query_client::{DkgQueryClient, PagedDkgQueryClient};
pub use ephemera_query_client::{EphemeraQueryClient, PagedEphemeraQueryClient};
pub use group_query_client::{GroupQueryClient, PagedGroupQueryClient};
pub use mixnet_query_client::{MixnetQueryClient, PagedMixnetQueryClient};
pub use multisig_query_client::{MultisigQueryClient, PagedMultisigQueryClient};
@@ -39,7 +36,6 @@ pub use vesting_query_client::{PagedVestingQueryClient, VestingQueryClient};
// re-export signing traits
pub use coconut_bandwidth_signing_client::CoconutBandwidthSigningClient;
pub use dkg_signing_client::DkgSigningClient;
pub use ephemera_signing_client::EphemeraSigningClient;
pub use group_signing_client::GroupSigningClient;
pub use mixnet_signing_client::MixnetSigningClient;
pub use multisig_signing_client::MultisigSigningClient;
@@ -56,9 +52,6 @@ pub trait NymContractsProvider {
fn dkg_contract_address(&self) -> Option<&AccountId>;
fn group_contract_address(&self) -> Option<&AccountId>;
fn multisig_contract_address(&self) -> Option<&AccountId>;
// ephemera-related
fn ephemera_contract_address(&self) -> Option<&AccountId>;
}
#[derive(Debug, Clone)]
@@ -70,8 +63,6 @@ pub struct TypedNymContracts {
pub group_contract_address: Option<AccountId>,
pub multisig_contract_address: Option<AccountId>,
pub coconut_dkg_contract_address: Option<AccountId>,
pub ephemera_contract_address: Option<AccountId>,
}
impl TryFrom<NymContracts> for TypedNymContracts {
@@ -103,10 +94,6 @@ impl TryFrom<NymContracts> for TypedNymContracts {
.coconut_dkg_contract_address
.map(|addr| addr.parse())
.transpose()?,
ephemera_contract_address: value
.ephemera_contract_address
.map(|addr| addr.parse())
.transpose()?,
})
}
}
@@ -140,6 +140,6 @@ mod tests {
let fee = &gas_price * gas_limit;
// the failing behaviour was result value of 3937
assert_eq!(fee.amount, 3938u64.into());
assert_eq!(fee.amount, 3938u128);
}
}
@@ -70,6 +70,8 @@ use crate::http_client;
use crate::{DirectSigningHttpRpcNyxdClient, QueryHttpRpcNyxdClient};
#[cfg(feature = "http-client")]
use cosmrs::rpc::{HttpClient, HttpClientUrl};
use nym_contracts_common::build_information::CONTRACT_BUILD_INFO_STORAGE_KEY;
use nym_contracts_common::ContractBuildInformation;
pub mod coin;
pub mod contract_traits;
@@ -278,10 +280,6 @@ impl<C, S> NymContractsProvider for NyxdClient<C, S> {
fn multisig_contract_address(&self) -> Option<&AccountId> {
self.config.contracts.multisig_contract_address.as_ref()
}
fn ephemera_contract_address(&self) -> Option<&AccountId> {
self.config.contracts.ephemera_contract_address.as_ref()
}
}
// queries
@@ -332,6 +330,33 @@ where
.await
.map(|block| block.block_id.hash)
}
pub async fn try_get_cw2_contract_version(
&self,
contract_address: &AccountId,
) -> Option<cw2::ContractVersion> {
let raw_info = self
.query_contract_raw(contract_address, b"contract_info".to_vec())
.await
.ok()?;
serde_json::from_slice(&raw_info).ok()
}
pub async fn try_get_contract_build_information(
&self,
contract_address: &AccountId,
) -> Option<ContractBuildInformation> {
let raw_info = self
.query_contract_raw(
contract_address,
CONTRACT_BUILD_INFO_STORAGE_KEY.as_bytes().to_vec(),
)
.await
.ok()?;
serde_json::from_slice(&raw_info).ok()
}
}
// signing
@@ -11,9 +11,13 @@ repository = { workspace = true }
bs58 = { workspace = true }
cosmwasm-std = { workspace = true }
cosmwasm-schema = { workspace = true }
cw-storage-plus = { workspace = true }
schemars = { workspace = true }
serde = { workspace = true, features = ["derive"] }
thiserror = { workspace = true }
[dev-dependencies]
serde_json = { workspace = true }
[build-dependencies]
vergen = { version = "=8.3.1", features = ["build", "git", "gitcl", "rustc", "cargo"] }
@@ -0,0 +1,17 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use vergen::EmitBuilder;
fn main() {
EmitBuilder::builder()
.all_build()
.rustc_semver()
.git_branch()
.git_commit_timestamp()
.git_sha(false)
.cargo_debug()
.cargo_opt_level()
.emit()
.expect("failed to extract build metadata");
}
@@ -0,0 +1,85 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::ContractBuildInformation;
use cosmwasm_std::{StdResult, Storage};
use cw_storage_plus::Item;
pub const CONTRACT_BUILD_INFO_STORAGE_KEY: &str = "contract_build_info";
pub const CONTRACT_BUILD_INFO: Item<ContractBuildInformation> =
Item::new(CONTRACT_BUILD_INFO_STORAGE_KEY);
// important note. this MUST BE called inside the contract code itself and not any intermediate crate
// otherwise macro expansions will resolve to incorrect data
#[macro_export]
macro_rules! get_build_information {
() => {
$crate::types::ContractBuildInformation::new(
env!("CARGO_PKG_NAME"),
env!("CARGO_PKG_VERSION"),
)
};
}
pub fn set_state_build_information(
store: &mut dyn Storage,
build_info: ContractBuildInformation,
) -> StdResult<()> {
CONTRACT_BUILD_INFO.save(store, &build_info)
}
pub fn get_contract_build_information(store: &dyn Storage) -> StdResult<ContractBuildInformation> {
CONTRACT_BUILD_INFO.load(store)
}
#[macro_export]
macro_rules! set_build_information {
( $store:expr ) => {
$crate::build_information::set_state_build_information(
$store,
$crate::get_build_information!(),
)
};
}
#[cfg(test)]
mod tests {
use super::*;
use cosmwasm_std::testing::MockStorage;
#[test]
fn get_and_set_work() {
let mut store = MockStorage::new();
// error if not set
assert!(get_contract_build_information(&store).is_err());
// set and get
let contract_name = "nym-mixnet-contract";
let contract_version = "1.2.3";
let build_info = ContractBuildInformation::new(contract_name, contract_version);
set_state_build_information(&mut store, build_info).unwrap();
let loaded = get_contract_build_information(&store).unwrap();
let expected = ContractBuildInformation {
contract_name: contract_name.into(),
build_version: contract_version.into(),
build_timestamp: env!("VERGEN_BUILD_TIMESTAMP").to_string(),
commit_sha: option_env!("VERGEN_GIT_SHA")
.unwrap_or("UNKNOWN")
.to_string(),
commit_timestamp: option_env!("VERGEN_GIT_COMMIT_TIMESTAMP")
.unwrap_or("UNKNOWN")
.to_string(),
commit_branch: option_env!("VERGEN_GIT_BRANCH")
.unwrap_or("UNKNOWN")
.to_string(),
rustc_version: env!("VERGEN_RUSTC_SEMVER").to_string(),
cargo_debug: env!("VERGEN_CARGO_DEBUG").to_string(),
cargo_opt_level: env!("VERGEN_CARGO_OPT_LEVEL").to_string(),
};
assert_eq!(expected, loaded);
}
}
@@ -4,6 +4,7 @@
#![warn(clippy::expect_used)]
#![warn(clippy::unwrap_used)]
pub mod build_information;
pub mod dealings;
pub mod events;
pub mod signing;
@@ -132,10 +132,18 @@ where
}
}
fn default_unknown() -> String {
"unknown".to_string()
}
// TODO: there's no reason this couldn't be used for proper binaries, but in that case
// perhaps the struct should get renamed and moved to a "more" common crate
#[cw_serde]
pub struct ContractBuildInformation {
/// Provides the name of the binary, i.e. the content of `CARGO_PKG_NAME` environmental variable.
#[serde(default = "default_unknown")]
pub contract_name: String,
// VERGEN_BUILD_TIMESTAMP
/// Provides the build timestamp, for example `2021-02-23T20:14:46.558472672+00:00`.
pub build_timestamp: String,
@@ -159,6 +167,38 @@ pub struct ContractBuildInformation {
// VERGEN_RUSTC_SEMVER
/// Provides the rustc version that was used for the build, for example `1.52.0-nightly`.
pub rustc_version: String,
// VERGEN_CARGO_DEBUG
/// Provides the cargo debug mode that was used for the build.
#[serde(default = "default_unknown")]
pub cargo_debug: String,
// VERGEN_CARGO_OPT_LEVEL
/// Provides the opt value set by cargo during the build
#[serde(default = "default_unknown")]
pub cargo_opt_level: String,
}
impl ContractBuildInformation {
pub fn new(name: impl Into<String>, version: impl Into<String>) -> Self {
ContractBuildInformation {
contract_name: name.into(),
build_version: version.into(),
build_timestamp: env!("VERGEN_BUILD_TIMESTAMP").to_string(),
commit_sha: option_env!("VERGEN_GIT_SHA")
.unwrap_or("UNKNOWN")
.to_string(),
commit_timestamp: option_env!("VERGEN_GIT_COMMIT_TIMESTAMP")
.unwrap_or("UNKNOWN")
.to_string(),
commit_branch: option_env!("VERGEN_GIT_BRANCH")
.unwrap_or("UNKNOWN")
.to_string(),
rustc_version: env!("VERGEN_RUSTC_SEMVER").to_string(),
cargo_debug: env!("VERGEN_CARGO_DEBUG").to_string(),
cargo_opt_level: env!("VERGEN_CARGO_OPT_LEVEL").to_string(),
}
}
}
#[cfg(test)]
@@ -1,17 +0,0 @@
[package]
name = "nym-ephemera-common"
version = "0.1.0"
edition = "2021"
license.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
cosmwasm-schema = { workspace = true }
cosmwasm-std = { workspace = true }
cw-utils = { workspace = true }
contracts-common = { path = "../contracts-common", package = "nym-contracts-common" }
[features]
schema = []
@@ -1,3 +0,0 @@
pub mod msg;
pub mod peers;
pub mod types;
@@ -1,33 +0,0 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
#[cfg(feature = "schema")]
use crate::peers::PagedPeerResponse;
use crate::types::JsonPeerInfo;
use cosmwasm_schema::cw_serde;
#[cfg(feature = "schema")]
use cosmwasm_schema::QueryResponses;
#[cw_serde]
pub struct InstantiateMsg {
pub group_addr: String,
pub mix_denom: String,
}
#[cw_serde]
pub enum ExecuteMsg {
RegisterPeer { peer_info: JsonPeerInfo },
}
#[cw_serde]
#[cfg_attr(feature = "schema", derive(QueryResponses))]
pub enum QueryMsg {
#[cfg_attr(feature = "schema", returns(PagedPeerResponse))]
GetPeers {
limit: Option<u32>,
start_after: Option<String>,
},
}
#[cw_serde]
pub struct MigrateMsg {}
@@ -1,25 +0,0 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::types::JsonPeerInfo;
use cosmwasm_schema::cw_serde;
use cosmwasm_std::Addr;
#[cw_serde]
pub struct PagedPeerResponse {
pub peers: Vec<JsonPeerInfo>,
pub per_page: usize,
/// Field indicating paging information for the following queries if the caller wishes to get further entries.
pub start_next_after: Option<Addr>,
}
impl PagedPeerResponse {
pub fn new(peers: Vec<JsonPeerInfo>, per_page: usize, start_next_after: Option<Addr>) -> Self {
PagedPeerResponse {
peers,
per_page,
start_next_after,
}
}
}
@@ -1,29 +0,0 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use cosmwasm_schema::cw_serde;
use cosmwasm_std::Addr;
#[cw_serde]
pub struct JsonPeerInfo {
/// The cosmos address of the peer, used in interacting with the chain.
pub cosmos_address: Addr,
/// The TCP/IP address of the peer.
/// Expected formats:
/// 1. `<IP>:<PORT>`
/// 2. `/ip4/<IP>/tcp/<PORT>` - this is the format used by libp2p multiaddr
pub ip_address: String,
///Serialized public key.
pub public_key: String,
}
impl JsonPeerInfo {
#[must_use]
pub fn new(cosmos_address: Addr, ip_address: String, public_key: String) -> Self {
Self {
cosmos_address,
ip_address,
public_key,
}
}
}
@@ -29,7 +29,7 @@ time = { workspace = true, features = ["parsing", "formatting"] }
ts-rs = { workspace = true, optional = true }
[dev-dependencies]
rand_chacha = "0.3"
rand_chacha = { workspace = true }
time = { workspace = true, features = ["serde", "macros"] }
[features]
@@ -234,12 +234,6 @@ pub enum MixnetContractError {
#[error("the epoch is currently not in the 'epoch advancement' state. (the state is {current_state})")]
EpochNotInAdvancementState { current_state: EpochState },
#[error("failed to parse {value} into a valid SemVer version: {error_message}")]
SemVerFailure {
value: String,
error_message: String,
},
#[error("failed to verify message signature: {source}")]
SignatureVerificationFailure {
#[from]
+5 -5
View File
@@ -12,16 +12,16 @@ aes = { workspace = true, optional = true }
bs58 = { workspace = true }
blake3 = { workspace = true, features = ["traits-preview"], optional = true }
ctr = { workspace = true, optional = true }
digest = { version = "0.10.3", optional = true }
digest = { workspace = true, optional = true }
generic-array = { workspace = true, optional = true }
hkdf = { workspace = true, optional = true }
hmac = { workspace = true, optional = true }
cipher = { workspace = true, optional = true }
x25519-dalek = { version = "2.0", optional = true, features = ["static_secrets"]}
ed25519-dalek = { version = "2.1", features = ["rand_core"], optional = true }
x25519-dalek = { workspace = true, features = ["static_secrets"], optional = true }
ed25519-dalek = { workspace = true, features = ["rand_core"], optional = true }
rand = { workspace = true, optional = true }
serde_bytes = { version = "0.11.6", optional = true }
serde_crate = { version = "1.0", optional = true, default_features = false, features = ["derive"], package = "serde" }
serde_crate = { version = "1.0", optional = true, default-features = false, features = ["derive"], package = "serde" }
subtle-encoding = { workspace = true, features = ["bech32-preview"] }
thiserror = { workspace = true }
zeroize = { workspace = true, optional = true, features = ["zeroize_derive"] }
@@ -31,7 +31,7 @@ nym-sphinx-types = { path = "../nymsphinx/types", version = "0.2.0", default-fea
nym-pemstore = { path = "../../common/pemstore", version = "0.3.0" }
[dev-dependencies]
rand_chacha = "0.3"
rand_chacha = { workspace = true }
[features]
default = ["sphinx"]
+1 -1
View File
@@ -19,7 +19,7 @@ bs58 = { workspace = true }
lazy_static = { workspace = true }
rand = { version = "0.8.5", default-features = false}
rand_chacha = "0.3"
rand_chacha = { workspace = true }
rand_core = { workspace = true }
sha2 = "0.9"
serde = { workspace = true }
+2
View File
@@ -20,6 +20,8 @@ serde_json = { workspace = true }
thiserror = { workspace = true }
tracing = { workspace = true }
nym-bin-common = { path = "../bin-common" }
# for request timeout until https://github.com/seanmonstar/reqwest/issues/1135 is fixed
[target."cfg(target_arch = \"wasm32\")".dependencies.wasmtimer]
workspace = true
+4
View File
@@ -14,6 +14,10 @@ use url::Url;
pub use reqwest::IntoUrl;
pub use user_agent::UserAgent;
mod user_agent;
pub const DEFAULT_TIMEOUT: Duration = Duration::from_secs(10);
pub type PathSegments<'a> = &'a [&'a str];
+56
View File
@@ -0,0 +1,56 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use std::fmt;
use http::HeaderValue;
use nym_bin_common::build_information::{BinaryBuildInformation, BinaryBuildInformationOwned};
#[derive(Clone, Debug)]
pub struct UserAgent {
pub application: String,
pub version: String,
pub platform: String,
pub git_commit: String,
}
impl fmt::Display for UserAgent {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let abbreviated_commit = self.git_commit.chars().take(7).collect::<String>();
write!(
f,
"{}/{}/{}/{}",
self.application, self.version, self.platform, abbreviated_commit
)
}
}
impl TryFrom<UserAgent> for HeaderValue {
type Error = http::header::InvalidHeaderValue;
fn try_from(user_agent: UserAgent) -> Result<Self, Self::Error> {
HeaderValue::from_str(&user_agent.to_string())
}
}
impl From<BinaryBuildInformation> for UserAgent {
fn from(build_info: BinaryBuildInformation) -> Self {
UserAgent {
application: build_info.binary_name.to_string(),
version: build_info.build_version.to_string(),
platform: build_info.cargo_triple.to_string(),
git_commit: build_info.commit_sha.to_string(),
}
}
}
impl From<BinaryBuildInformationOwned> for UserAgent {
fn from(build_info: BinaryBuildInformationOwned) -> Self {
UserAgent {
application: build_info.binary_name,
version: build_info.build_version,
platform: build_info.cargo_triple,
git_commit: build_info.commit_sha,
}
}
}
+1 -42
View File
@@ -31,9 +31,6 @@ pub struct NymContracts {
pub group_contract_address: Option<String>,
pub multisig_contract_address: Option<String>,
pub coconut_dkg_contract_address: Option<String>,
pub ephemera_contract_address: Option<String>,
pub service_provider_directory_contract_address: Option<String>,
pub name_service_contract_address: Option<String>,
}
// I wanted to use the simpler `NetworkDetails` name, but there's a clash
@@ -128,11 +125,6 @@ impl NymNetworkDetails {
.with_group_contract(get_optional_env(var_names::GROUP_CONTRACT_ADDRESS))
.with_multisig_contract(get_optional_env(var_names::MULTISIG_CONTRACT_ADDRESS))
.with_coconut_dkg_contract(get_optional_env(var_names::COCONUT_DKG_CONTRACT_ADDRESS))
.with_ephemera_contract(get_optional_env(var_names::EPHEMERA_CONTRACT_ADDRESS))
.with_service_provider_directory_contract(get_optional_env(
var_names::SERVICE_PROVIDER_DIRECTORY_CONTRACT_ADDRESS,
))
.with_name_service_contract(get_optional_env(var_names::NAME_SERVICE_CONTRACT_ADDRESS))
.with_explorer_api(get_optional_env(var_names::EXPLORER_API))
}
@@ -161,9 +153,6 @@ impl NymNetworkDetails {
coconut_dkg_contract_address: parse_optional_str(
mainnet::COCONUT_DKG_CONTRACT_ADDRESS,
),
ephemera_contract_address: parse_optional_str(mainnet::EPHEMERA_CONTRACT_ADDRESS),
service_provider_directory_contract_address: None,
name_service_contract_address: None,
},
explorer_api: parse_optional_str(mainnet::EXPLORER_API),
}
@@ -269,27 +258,6 @@ impl NymNetworkDetails {
self
}
#[must_use]
pub fn with_ephemera_contract<S: Into<String>>(mut self, contract: Option<S>) -> Self {
self.contracts.ephemera_contract_address = contract.map(Into::into);
self
}
#[must_use]
pub fn with_service_provider_directory_contract<S: Into<String>>(
mut self,
contract: Option<S>,
) -> Self {
self.contracts.service_provider_directory_contract_address = contract.map(Into::into);
self
}
#[must_use]
pub fn with_name_service_contract<S: Into<String>>(mut self, contract: Option<S>) -> Self {
self.contracts.name_service_contract_address = contract.map(Into::into);
self
}
#[must_use]
pub fn with_explorer_api<S: Into<String>>(mut self, endpoint: Option<S>) -> Self {
self.explorer_api = endpoint.map(Into::into);
@@ -453,22 +421,13 @@ pub fn setup_env<P: AsRef<Path>>(config_env_file: Option<P>) {
}
}
// Name of the event triggered by the eth contract. If the event name is changed,
// this would also need to be changed; It is currently tested against the json abi
pub const ETH_EVENT_NAME: &str = "BBCredentialPurchased";
pub const ETH_BURN_FUNCTION_NAME: &str = "generateBasicBandwidthCredential";
pub const ETH_ERC20_APPROVE_FUNCTION_NAME: &str = "approve";
// Ethereum constants used for token bridge
/// How much bandwidth (in bytes) one token can buy
pub const BYTES_PER_UTOKEN: u64 = 1024;
/// How much bandwidth (in bytes) one freepass provides
pub const BYTES_PER_FREEPASS: u64 = 1024 * 1024 * 1024; // 1GB
/// Threshold for claiming more bandwidth: 1 MB
pub const REMAINING_BANDWIDTH_THRESHOLD: i64 = 1024 * 1024;
/// How many ERC20 tokens should be burned to buy bandwidth
/// How many tokens should be burned to buy bandwidth
pub const TOKENS_TO_BURN: u64 = 1;
/// How many ERC20 utokens should be burned to buy bandwidth
pub const UTOKENS_TO_BURN: u64 = TOKENS_TO_BURN * 1000000;
-18
View File
@@ -24,11 +24,9 @@ pub const MULTISIG_CONTRACT_ADDRESS: &str =
"n1txayqfz5g9qww3rlflpg025xd26m9payz96u54x4fe3s2ktz39xqk67gzx";
pub const COCONUT_DKG_CONTRACT_ADDRESS: &str =
"n19604yflqggs9mk2z26mqygq43q2kr3n932egxx630svywd5mpxjsztfpvx";
pub const EPHEMERA_CONTRACT_ADDRESS: &str = "";
pub const REWARDING_VALIDATOR_ADDRESS: &str = "n10yyd98e2tuwu0f7ypz9dy3hhjw7v772q6287gy";
pub const STATISTICS_SERVICE_DOMAIN_ADDRESS: &str = "https://mainnet-stats.nymte.ch:8090/";
pub const NYXD_URL: &str = "https://rpc.nymtech.net";
pub const NYM_API: &str = "https://validator.nymtech.net/api/";
pub const NYXD_WS: &str = "wss://rpc.nymtech.net/websocket";
@@ -107,18 +105,10 @@ pub fn export_to_env() {
var_names::COCONUT_DKG_CONTRACT_ADDRESS,
COCONUT_DKG_CONTRACT_ADDRESS,
);
set_var_to_default(
var_names::EPHEMERA_CONTRACT_ADDRESS,
EPHEMERA_CONTRACT_ADDRESS,
);
set_var_to_default(
var_names::REWARDING_VALIDATOR_ADDRESS,
REWARDING_VALIDATOR_ADDRESS,
);
set_var_to_default(
var_names::STATISTICS_SERVICE_DOMAIN_ADDRESS,
STATISTICS_SERVICE_DOMAIN_ADDRESS,
);
set_var_to_default(var_names::NYXD, NYXD_URL);
set_var_to_default(var_names::NYM_API, NYM_API);
set_var_to_default(var_names::NYXD_WEBSOCKET, NYXD_WS);
@@ -156,18 +146,10 @@ pub fn export_to_env_if_not_set() {
var_names::COCONUT_DKG_CONTRACT_ADDRESS,
COCONUT_DKG_CONTRACT_ADDRESS,
);
set_var_conditionally_to_default(
var_names::EPHEMERA_CONTRACT_ADDRESS,
EPHEMERA_CONTRACT_ADDRESS,
);
set_var_conditionally_to_default(
var_names::REWARDING_VALIDATOR_ADDRESS,
REWARDING_VALIDATOR_ADDRESS,
);
set_var_conditionally_to_default(
var_names::STATISTICS_SERVICE_DOMAIN_ADDRESS,
STATISTICS_SERVICE_DOMAIN_ADDRESS,
);
set_var_conditionally_to_default(var_names::NYXD, NYXD_URL);
set_var_conditionally_to_default(var_names::NYM_API, NYM_API);
set_var_conditionally_to_default(var_names::NYXD_WEBSOCKET, NYXD_WS);
-5
View File
@@ -18,12 +18,7 @@ pub const COCONUT_BANDWIDTH_CONTRACT_ADDRESS: &str = "COCONUT_BANDWIDTH_CONTRACT
pub const GROUP_CONTRACT_ADDRESS: &str = "GROUP_CONTRACT_ADDRESS";
pub const MULTISIG_CONTRACT_ADDRESS: &str = "MULTISIG_CONTRACT_ADDRESS";
pub const COCONUT_DKG_CONTRACT_ADDRESS: &str = "COCONUT_DKG_CONTRACT_ADDRESS";
pub const EPHEMERA_CONTRACT_ADDRESS: &str = "EPHEMERA_CONTRACT_ADDRESS";
pub const REWARDING_VALIDATOR_ADDRESS: &str = "REWARDING_VALIDATOR_ADDRESS";
pub const STATISTICS_SERVICE_DOMAIN_ADDRESS: &str = "STATISTICS_SERVICE_DOMAIN_ADDRESS";
pub const SERVICE_PROVIDER_DIRECTORY_CONTRACT_ADDRESS: &str =
"SERVICE_PROVIDER_DIRECTORY_CONTRACT_ADDRESS";
pub const NAME_SERVICE_CONTRACT_ADDRESS: &str = "NAME_SERVICE_CONTRACT_ADDRESS";
pub const NYXD: &str = "NYXD";
pub const NYM_API: &str = "NYM_API";
pub const NYXD_WEBSOCKET: &str = "NYXD_WS";
+2 -2
View File
@@ -41,7 +41,7 @@ impl<'a> From<&'a mix::Node> for TestableNode {
fn from(value: &'a mix::Node) -> Self {
TestableNode {
encoded_identity: value.identity_key.to_base58_string(),
owner: value.owner.clone(),
owner: value.owner.as_ref().cloned().unwrap_or_default(),
typ: NodeType::Mixnode {
mix_id: value.mix_id,
},
@@ -53,7 +53,7 @@ impl<'a> From<&'a gateway::Node> for TestableNode {
fn from(value: &'a gateway::Node) -> Self {
TestableNode {
encoded_identity: value.identity_key.to_base58_string(),
owner: value.owner.clone(),
owner: value.owner.as_ref().cloned().unwrap_or_default(),
typ: NodeType::Gateway,
}
}
+9 -5
View File
@@ -6,6 +6,7 @@ use nym_credential_storage::models::StorableIssuedCredential;
use nym_credential_storage::storage::Storage;
use nym_credentials::coconut::bandwidth::issued::BandwidthCredentialIssuedDataVariant;
use nym_credentials::IssuedBandwidthCredential;
use time::OffsetDateTime;
use tracing::{debug, warn};
use zeroize::Zeroizing;
@@ -13,7 +14,7 @@ pub async fn import_credential<S>(
credentials_store: S,
raw_credential: Vec<u8>,
credential_version: impl Into<Option<u8>>,
) -> Result<(), NymIdError>
) -> Result<Option<OffsetDateTime>, NymIdError>
where
S: Storage,
<S as Storage>::StorageError: Send + Sync + 'static,
@@ -29,9 +30,10 @@ where
credential.typ()
);
match credential.variant_data() {
let expiry_date = match credential.variant_data() {
BandwidthCredentialIssuedDataVariant::Voucher(voucher_info) => {
debug!("with value of {}", voucher_info.value())
debug!("with value of {}", voucher_info.value());
None
}
BandwidthCredentialIssuedDataVariant::FreePass(freepass_info) => {
debug!("with expiry at {}", freepass_info.expiry_date());
@@ -42,9 +44,11 @@ where
return Err(NymIdError::ExpiredCredentialImport {
expiration: freepass_info.expiry_date(),
});
} else {
Some(freepass_info.expiry_date())
}
}
}
};
// SAFETY:
// for the epoch to run over u32::MAX, we'd have to advance it for few centuries every block...
@@ -67,5 +71,5 @@ where
.map_err(|source| NymIdError::StorageError {
source: Box::new(source),
})?;
Ok(())
Ok(expiry_date)
}
+2 -2
View File
@@ -9,7 +9,7 @@ license.workspace = true
[dependencies]
bls12_381 = { workspace = true, default-features = false, features = ["pairings", "alloc", "experimental"] }
itertools = "0.10"
itertools = { workspace = true }
digest = "0.9"
rand = "0.8"
thiserror = { workspace = true }
@@ -33,7 +33,7 @@ default-features = false
[dev-dependencies]
criterion = { workspace = true, features = ["html_reports"] }
doc-comment = { workspace = true }
rand_chacha = "0.3"
rand_chacha = { workspace = true }
[[bench]]
name = "benchmarks"
+1 -1
View File
@@ -9,7 +9,7 @@ repository = { workspace = true }
[dependencies]
rand = { workspace = true }
serde_crate = { version = "1.0", optional = true, default_features = false, features = ["derive"], package = "serde" }
serde_crate = { version = "1.0", optional = true, default-features = false, features = ["derive"], package = "serde" }
generic-array = { workspace = true, optional = true, features = ["serde"] }
thiserror = { workspace = true }
zeroize = { workspace = true }
@@ -24,4 +24,4 @@ nym-topology = { path = "../../topology" }
version = "0.2.83"
[dev-dependencies]
rand_chacha = "0.3"
rand_chacha = { workspace = true }
+18 -48
View File
@@ -300,8 +300,8 @@ impl Fragment {
#[derive(PartialEq, Clone, Debug)]
pub(crate) struct FragmentHeader {
/// ID associated with `FragmentSet` to which this particular `Fragment` belongs.
/// Its value is restricted to (0, i32::max_value()].
/// Note that it *excludes* 0, but *includes* i32::max_value().
/// Its value is restricted to (0, i32::MAX].
/// Note that it *excludes* 0, but *includes* i32::MAX.
/// This allows the field to be represented using 31 bits.
id: i32,
@@ -319,7 +319,7 @@ pub(crate) struct FragmentHeader {
previous_fragments_set_id: Option<i32>,
/// Optional ID of next `FragmentSet` into which the original message was split.
/// Note, this option is only valid of `current_fragment == total_fragments == u8::max_value()`
/// Note, this option is only valid of `current_fragment == total_fragments == u8::MAX`
next_fragments_set_id: Option<i32>,
}
@@ -414,7 +414,7 @@ impl FragmentHeader {
if current_fragment == 1 {
previous_fragments_set_id = Some(linked_id);
} else if total_fragments == current_fragment && current_fragment == u8::max_value() {
} else if total_fragments == current_fragment && current_fragment == u8::MAX {
next_fragments_set_id = Some(linked_id);
} else {
return Err(ChunkingError::MalformedHeaderError);
@@ -585,14 +585,7 @@ mod fragment_tests {
rng.fill_bytes(&mut msg);
let fragment = Fragment {
header: FragmentHeader::try_new(
12345,
u8::max_value(),
u8::max_value(),
None,
Some(1234),
)
.unwrap(),
header: FragmentHeader::try_new(12345, u8::MAX, u8::MAX, None, Some(1234)).unwrap(),
payload: msg,
};
let packet_bytes = fragment.clone().into_bytes();
@@ -602,14 +595,7 @@ mod fragment_tests {
rng.fill_bytes(&mut msg);
let fragment = Fragment {
header: FragmentHeader::try_new(
12345,
u8::max_value(),
u8::max_value(),
None,
Some(1234),
)
.unwrap(),
header: FragmentHeader::try_new(12345, u8::MAX, u8::MAX, None, Some(1234)).unwrap(),
payload: msg,
};
let packet_bytes = fragment.clone().into_bytes();
@@ -822,8 +808,8 @@ mod fragment_tests {
assert!(Fragment::try_new(
&full_payload,
id,
u8::max_value(),
u8::max_value(),
u8::MAX,
u8::MAX,
None,
Some(link_id),
max_plaintext_size(),
@@ -884,8 +870,8 @@ mod fragment_tests {
assert!(Fragment::try_new(
&non_full_payload,
id,
u8::max_value(),
u8::max_value(),
u8::MAX,
u8::MAX,
None,
Some(link_id),
max_plaintext_size(),
@@ -894,8 +880,8 @@ mod fragment_tests {
assert!(Fragment::try_new(
&non_full_payload2,
id,
u8::max_value(),
u8::max_value(),
u8::MAX,
u8::MAX,
None,
Some(link_id),
max_plaintext_size(),
@@ -905,8 +891,8 @@ mod fragment_tests {
assert!(Fragment::try_new(
&too_much_payload,
id,
u8::max_value(),
u8::max_value(),
u8::MAX,
u8::MAX,
None,
Some(link_id),
max_plaintext_size(),
@@ -1008,14 +994,7 @@ mod fragment_header {
fn fragmented_header_cannot_be_created_with_zero_id() {
assert!(FragmentHeader::try_new(0, 10, 5, None, None).is_err());
assert!(FragmentHeader::try_new(12345, 10, 5, Some(0), None).is_err());
assert!(FragmentHeader::try_new(
12345,
u8::max_value(),
u8::max_value(),
None,
Some(0),
)
.is_err());
assert!(FragmentHeader::try_new(12345, u8::MAX, u8::MAX, None, Some(0),).is_err());
}
#[test]
@@ -1066,14 +1045,7 @@ mod fragment_header {
#[test]
fn can_only_be_post_linked_for_last_fragment() {
assert!(FragmentHeader::try_new(12345, 10, 10, None, Some(1234)).is_ok());
assert!(FragmentHeader::try_new(
12345,
u8::max_value(),
u8::max_value(),
None,
Some(1234),
)
.is_ok());
assert!(FragmentHeader::try_new(12345, u8::MAX, u8::MAX, None, Some(1234),).is_ok());
assert!(FragmentHeader::try_new(12345, 10, 2, Some(1234), None).is_err());
}
@@ -1117,8 +1089,7 @@ mod fragment_header {
#[test]
fn post_linked_can_be_converted_to_and_from_bytes_for_exact_number_of_bytes_provided() {
let fragmented_header =
FragmentHeader::try_new(12345, u8::max_value(), u8::max_value(), None, Some(1234))
.unwrap();
FragmentHeader::try_new(12345, u8::MAX, u8::MAX, None, Some(1234)).unwrap();
let header_bytes = fragmented_header.to_bytes();
let (recovered_header, bytes_used) =
@@ -1130,8 +1101,7 @@ mod fragment_header {
#[test]
fn post_linked_can_be_converted_to_and_from_bytes_for_more_than_required_number_of_bytes() {
let fragmented_header =
FragmentHeader::try_new(12345, u8::max_value(), u8::max_value(), None, Some(1234))
.unwrap();
FragmentHeader::try_new(12345, u8::MAX, u8::MAX, None, Some(1234)).unwrap();
let mut header_bytes = fragmented_header.to_bytes();
header_bytes.append(vec![1, 2, 3, 4, 5].as_mut());
+2 -2
View File
@@ -41,7 +41,7 @@ pub mod set;
/// (or implicitly the only one), it has no lower bound on the number of `Fragment`s.
/// (Apart from the restriction of containing at least a single one). If the set is located
/// somewhere in the middle, *it must be* full. Finally, regardless of its position, it must also be
/// true that it contains no more than `u8::max_value()`, i.e. 255 `Fragment`s.
/// true that it contains no more than `u8::MAX`, i.e. 255 `Fragment`s.
/// Again, the reasoning for this is further explained in `set.rs` file. However, you might
/// also want to look at `fragment.rs` to understand the full context behind that design choice.
///
@@ -151,7 +151,7 @@ mod tests {
- MAX_NODE_ADDRESS_UNPADDED_LEN;
let plaintext_lens = vec![17, used_plaintext_len, 20, 42, 10000];
const SET_LEN: usize = u8::max_value() as usize;
const SET_LEN: usize = u8::MAX as usize;
for plaintext_len in plaintext_lens {
let unlinked_len = unlinked_fragment_payload_max_len(plaintext_len);
+30 -34
View File
@@ -24,7 +24,7 @@ struct ReconstructionBuffer {
previous_fragments_set_id: Option<i32>,
/// Once all fragments are received, the value of `next_fragments_set_id` is copied
/// from the last `Fragment` in the set (assuming the set is full, i.e. it contains
/// `u8::max_value()` elements).
/// `u8::MAX` elements).
next_fragments_set_id: Option<i32>,
/// The actual `Fragment` data held by the `ReconstructionBuffer`. When created it is already
@@ -40,7 +40,7 @@ pub type ReconstructedMessage = (Vec<u8>, Vec<i32>);
impl ReconstructionBuffer {
/// Initialises new instance of a `ReconstructionBuffer` with given size, i.e.
/// number of expected `Fragment`s in the set.
/// The `u8` input type of `size` argument ensures it has the `u8::max_value()` upper bound.
/// The `u8` input type of `size` argument ensures it has the `u8::MAX` upper bound.
fn new(size: u8) -> Self {
// Note: `new` should have never been called with size 0 in the first place
// as `size` value is based on the first recovered `Fragment` in the set.
@@ -122,8 +122,8 @@ impl ReconstructionBuffer {
.as_ref()
.unwrap()
.previous_fragments_set_id();
self.next_fragments_set_id = if self.fragments.len() == u8::max_value() as usize {
self.fragments[u8::max_value() as usize - 1]
self.next_fragments_set_id = if self.fragments.len() == u8::MAX as usize {
self.fragments[u8::MAX as usize - 1]
.as_ref()
.unwrap()
.next_fragments_set_id()
@@ -313,8 +313,8 @@ mod reconstruction_buffer {
assert_eq!(None, frag);
}
let buf = ReconstructionBuffer::new(u8::max_value());
assert_eq!(u8::max_value() as usize, buf.fragments.len());
let buf = ReconstructionBuffer::new(u8::MAX);
assert_eq!(u8::MAX as usize, buf.fragments.len());
for frag in buf.fragments {
assert_eq!(None, frag);
}
@@ -358,11 +358,11 @@ mod reconstruction_buffer {
buf.insert_fragment(Fragment::try_from_bytes(&raw_fragments[2]).unwrap());
assert_eq!(message.to_vec(), buf.reconstruct_set_data());
let mut buf = ReconstructionBuffer::new(u8::max_value());
let mut buf = ReconstructionBuffer::new(u8::MAX);
let message = vec![
42u8;
unlinked_fragment_payload_max_len(AVAILABLE_PLAINTEXT_SIZE)
* u8::max_value() as usize
* u8::MAX as usize
];
let raw_fragments: Vec<_> =
crate::split_into_sets(&mut rand::rngs::OsRng, &message, AVAILABLE_PLAINTEXT_SIZE)
@@ -445,7 +445,7 @@ mod reconstruction_buffer {
.map(|x| x.into_bytes())
.collect();
for raw_fragment in raw_fragments.iter().take(u8::max_value() as usize - 1) {
for raw_fragment in raw_fragments.iter().take(u8::MAX as usize - 1) {
buf.insert_fragment(Fragment::try_from_bytes(raw_fragment).unwrap());
}
@@ -563,7 +563,7 @@ mod message_reconstructor {
.map(|x| x.into_bytes())
.collect();
for raw_fragment in raw_fragments.iter().take(u8::max_value() as usize) {
for raw_fragment in raw_fragments.iter().take(u8::MAX as usize) {
assert!(reconstructor
.insert_new_fragment(
reconstructor
@@ -611,7 +611,7 @@ mod message_reconstructor {
.collect();
// note that first set is not fully inserted
for raw_fragment in raw_fragments.iter().take(u8::max_value() as usize - 1) {
for raw_fragment in raw_fragments.iter().take(u8::MAX as usize - 1) {
assert!(reconstructor
.insert_new_fragment(
reconstructor
@@ -657,7 +657,7 @@ mod message_reconstructor {
.map(|x| x.into_bytes())
.collect();
for raw_fragment in raw_fragments.iter().take(u8::max_value() as usize) {
for raw_fragment in raw_fragments.iter().take(u8::MAX as usize) {
assert!(reconstructor
.insert_new_fragment(
reconstructor
@@ -699,7 +699,7 @@ mod message_reconstructor {
.map(|x| x.into_bytes())
.collect();
for raw_fragment in raw_fragments.iter().take(u8::max_value() as usize) {
for raw_fragment in raw_fragments.iter().take(u8::MAX as usize) {
assert!(reconstructor
.insert_new_fragment(
reconstructor
@@ -738,7 +738,7 @@ mod message_reconstructor {
.collect();
// note that first set is not fully inserted
for raw_fragment in raw_fragments.iter().take(u8::max_value() as usize - 1) {
for raw_fragment in raw_fragments.iter().take(u8::MAX as usize - 1) {
assert!(reconstructor
.insert_new_fragment(
reconstructor
@@ -779,7 +779,7 @@ mod message_reconstructor {
.map(|x| x.into_bytes())
.collect();
for raw_fragment in raw_fragments.iter().take(u8::max_value() as usize * 2) {
for raw_fragment in raw_fragments.iter().take(u8::MAX as usize * 2) {
assert!(reconstructor
.insert_new_fragment(
reconstructor
@@ -793,7 +793,7 @@ mod message_reconstructor {
assert!(reconstructor
.insert_new_fragment(
reconstructor
.recover_fragment(raw_fragments[(u8::max_value() as usize) * 2].clone())
.recover_fragment(raw_fragments[(u8::MAX as usize) * 2].clone())
.unwrap()
)
.is_none());
@@ -822,11 +822,7 @@ mod message_reconstructor {
.collect();
// note that first set is not fully inserted
for raw_fragment in raw_fragments
.iter()
.skip(1)
.take(u8::max_value() as usize * 2 - 1)
{
for raw_fragment in raw_fragments.iter().skip(1).take(u8::MAX as usize * 2 - 1) {
assert!(reconstructor
.insert_new_fragment(
reconstructor
@@ -839,7 +835,7 @@ mod message_reconstructor {
assert!(reconstructor
.insert_new_fragment(
reconstructor
.recover_fragment(raw_fragments[(u8::max_value() as usize) * 2].clone())
.recover_fragment(raw_fragments[(u8::MAX as usize) * 2].clone())
.unwrap()
)
.is_none());
@@ -896,7 +892,7 @@ mod message_reconstructor {
.collect();
// note that first set is not fully inserted
for raw_fragment in raw_fragments1.iter().take(u8::max_value() as usize - 1) {
for raw_fragment in raw_fragments1.iter().take(u8::MAX as usize - 1) {
assert!(reconstructor
.insert_new_fragment(
reconstructor
@@ -930,7 +926,7 @@ mod message_reconstructor {
.map(|x| x.into_bytes())
.collect();
for raw_fragment in raw_fragments2.iter().take(u8::max_value() as usize) {
for raw_fragment in raw_fragments2.iter().take(u8::MAX as usize) {
assert!(reconstructor
.insert_new_fragment(
reconstructor
@@ -970,7 +966,7 @@ mod message_reconstructor {
.map(|x| x.into_bytes())
.collect();
for raw_fragment in raw_fragments.iter().take(u8::max_value() as usize) {
for raw_fragment in raw_fragments.iter().take(u8::MAX as usize) {
assert!(reconstructor
.insert_new_fragment(
reconstructor
@@ -1252,7 +1248,7 @@ mod message_reconstructor {
//
// we're inserting this via the buffer approach as not to trigger immediate re-assembly
let mut reconstructor = MessageReconstructor::default();
let mut set_buf1 = ReconstructionBuffer::new(u8::max_value());
let mut set_buf1 = ReconstructionBuffer::new(u8::MAX);
let mut set_buf2 = ReconstructionBuffer::new(1);
let mut rng = thread_rng();
@@ -1267,7 +1263,7 @@ mod message_reconstructor {
.map(|x| x.into_bytes())
.collect();
for raw_fragment in raw_fragments.iter().take(u8::max_value() as usize) {
for raw_fragment in raw_fragments.iter().take(u8::MAX as usize) {
set_buf1.insert_fragment(Fragment::try_from_bytes(raw_fragment).unwrap());
}
@@ -1630,19 +1626,19 @@ mod message_reconstruction {
.into_iter()
.flat_map(|fragment_set| fragment_set.into_iter())
.collect();
assert_eq!(fragments1.len(), u8::max_value() as usize);
assert_eq!(fragments1.len(), u8::MAX as usize);
let mut fragments2: Vec<_> =
crate::split_into_sets(&mut rand::rngs::OsRng, &message2, AVAILABLE_PLAINTEXT_SIZE)
.into_iter()
.flat_map(|fragment_set| fragment_set.into_iter())
.collect();
assert_eq!(fragments2.len(), u8::max_value() as usize);
assert_eq!(fragments2.len(), u8::MAX as usize);
// combine and shuffle fragments
fragments1.append(fragments2.as_mut());
fragments1.shuffle(&mut rng);
let fragments = fragments1;
assert_eq!(fragments.len(), (u8::max_value() as usize) * 2);
assert_eq!(fragments.len(), (u8::MAX as usize) * 2);
let mut message_reconstructor = MessageReconstructor::default();
for fragment in fragments.into_iter() {
@@ -1762,7 +1758,7 @@ mod message_reconstruction {
.flat_map(|fragment_set| fragment_set.into_iter())
.map(|x| x.into_bytes())
.collect();
assert_eq!(fragments.len(), 4 * (u8::max_value() as usize));
assert_eq!(fragments.len(), 4 * (u8::MAX as usize));
// shuffle the fragments
fragments.shuffle(&mut rng);
@@ -1811,19 +1807,19 @@ mod message_reconstruction {
.into_iter()
.flat_map(|fragment_set| fragment_set.into_iter())
.collect();
assert_eq!(fragments1.len(), 4 * (u8::max_value() as usize));
assert_eq!(fragments1.len(), 4 * (u8::MAX as usize));
let mut fragments2: Vec<_> =
crate::split_into_sets(&mut rand::rngs::OsRng, &message2, AVAILABLE_PLAINTEXT_SIZE)
.into_iter()
.flat_map(|fragment_set| fragment_set.into_iter())
.collect();
assert_eq!(fragments2.len(), 4 * (u8::max_value() as usize));
assert_eq!(fragments2.len(), 4 * (u8::MAX as usize));
// combine and shuffle fragments
fragments1.append(fragments2.as_mut());
fragments1.shuffle(&mut rng);
let fragments = fragments1;
assert_eq!(fragments.len(), (u8::max_value() as usize) * 8);
assert_eq!(fragments.len(), (u8::MAX as usize) * 8);
let mut message_reconstructor = MessageReconstructor::default();
for fragment in fragments.into_iter() {
+25 -25
View File
@@ -11,7 +11,7 @@ use rand::Rng;
/// on its payload length of the maximum number of `Fragment`s multiplied by their maximum,
/// fragmented, length.
pub const fn max_unlinked_set_payload_length(max_plaintext_size: usize) -> usize {
u8::max_value() as usize * unlinked_fragment_payload_max_len(max_plaintext_size)
u8::MAX as usize * unlinked_fragment_payload_max_len(max_plaintext_size)
}
/// If the set is being linked to another one, by either being the very first set, or the very last,
@@ -52,8 +52,8 @@ pub const fn two_way_linked_set_payload_length(max_plaintext_size: usize) -> usi
pub(crate) type FragmentSet = Vec<Fragment>;
/// Generate a pseudo-random id for a `FragmentSet`.
/// Its value is restricted to (0, i32::max_value()].
/// Note that it *excludes* 0, but *includes* i32::max_value().
/// Its value is restricted to (0, i32::MAX].
/// Note that it *excludes* 0, but *includes* i32::MAX.
/// This particular range allows for the id to be represented using 31bits, rather than
/// the full length of 32 while still providing more than enough variability to
/// distinguish different `FragmentSet`s.
@@ -89,13 +89,13 @@ fn prepare_unlinked_fragmented_set(
/ unlinked_fragment_payload_max_len(max_plaintext_size) as f64)
.ceil() as usize;
debug_assert!(pre_casted_frags <= u8::max_value() as usize);
debug_assert!(pre_casted_frags <= u8::MAX as usize);
let num_fragments = pre_casted_frags as u8;
let mut fragments = Vec::with_capacity(num_fragments as usize);
for i in 1..(pre_casted_frags + 1) {
// we can't use u8 directly here as upper (NON-INCLUSIVE, so it would always fit) bound could be u8::max_value() + 1
// we can't use u8 directly here as upper (NON-INCLUSIVE, so it would always fit) bound could be u8::MAX + 1
let lb = (i - 1) * unlinked_fragment_payload_max_len(max_plaintext_size);
let ub = usize::min(
message.len(),
@@ -131,7 +131,7 @@ fn prepare_linked_fragment_set(
) -> FragmentSet {
// determine number of fragments in the set:
let num_frags_usize = if next_link_id.is_some() {
u8::max_value() as usize
u8::MAX as usize
} else {
// we know this set is linked, if it's not post-linked then it MUST BE pre-linked
let tail_len = if message.len() >= linked_fragment_payload_max_len(max_plaintext_size) {
@@ -142,7 +142,7 @@ fn prepare_linked_fragment_set(
let pre_casted_frags = 1
+ (tail_len as f64 / unlinked_fragment_payload_max_len(max_plaintext_size) as f64)
.ceil() as usize;
if pre_casted_frags > u8::max_value() as usize {
if pre_casted_frags > u8::MAX as usize {
panic!("message would produce too many fragments!")
};
pre_casted_frags
@@ -162,7 +162,7 @@ fn prepare_linked_fragment_set(
let mut fragments = Vec::with_capacity(num_frags_usize);
for i in 1..(num_frags_usize + 1) {
// we can't use u8 directly here as upper (NON-INCLUSIVE, so i would always fit) bound could be u8::max_value() + 1
// we can't use u8 directly here as upper (NON-INCLUSIVE, so i would always fit) bound could be u8::MAX + 1
let fragment = Fragment::try_new(
&message[lb..ub],
id,
@@ -343,7 +343,7 @@ mod tests {
fn verify_post_linked_set_payload(mut set: FragmentSet, payload: &[u8]) {
for i in (0..set.len()).rev() {
let lb = i * unlinked_fragment_payload_max_len(max_plaintext_size());
let ub = if i == (u8::max_value() as usize - 1) {
let ub = if i == (u8::MAX as usize - 1) {
i * unlinked_fragment_payload_max_len(max_plaintext_size())
+ linked_fragment_payload_max_len(max_plaintext_size())
} else {
@@ -365,7 +365,7 @@ mod tests {
(i - 1) * unlinked_fragment_payload_max_len(max_plaintext_size())
+ linked_fragment_payload_max_len(max_plaintext_size())
};
let ub = if i == (u8::max_value() as usize - 1) {
let ub = if i == (u8::MAX as usize - 1) {
(i - 1) * unlinked_fragment_payload_max_len(max_plaintext_size())
+ 2 * linked_fragment_payload_max_len(max_plaintext_size())
} else {
@@ -434,7 +434,7 @@ mod tests {
id,
max_plaintext_size(),
);
assert_eq!(u8::max_value() as usize, max_fragment_set.len());
assert_eq!(u8::MAX as usize, max_fragment_set.len());
verify_unlinked_set_payload(max_fragment_set, &max_fragments_set_payload);
let mut full_set_payload =
@@ -442,7 +442,7 @@ mod tests {
rng.fill_bytes(&mut full_set_payload);
let full_fragment_set =
prepare_unlinked_fragmented_set(&full_set_payload, id, max_plaintext_size());
assert_eq!(u8::max_value() as usize, full_fragment_set.len());
assert_eq!(u8::MAX as usize, full_fragment_set.len());
verify_unlinked_set_payload(full_fragment_set, &full_set_payload);
}
@@ -515,7 +515,7 @@ mod tests {
None,
max_plaintext_size(),
);
assert_eq!(u8::max_value() as usize, max_fragment_set.len());
assert_eq!(u8::MAX as usize, max_fragment_set.len());
verify_pre_linked_set_payload(max_fragment_set, &max_fragments_set_payload);
let mut full_set_payload =
@@ -528,7 +528,7 @@ mod tests {
None,
max_plaintext_size(),
);
assert_eq!(u8::max_value() as usize, full_fragment_set.len());
assert_eq!(u8::MAX as usize, full_fragment_set.len());
verify_pre_linked_set_payload(full_fragment_set, &full_set_payload);
}
@@ -561,7 +561,7 @@ mod tests {
Some(link_id),
max_plaintext_size(),
);
assert_eq!(u8::max_value() as usize, full_fragment_set.len());
assert_eq!(u8::MAX as usize, full_fragment_set.len());
verify_post_linked_set_payload(full_fragment_set, &full_set_payload);
}
@@ -608,7 +608,7 @@ mod tests {
Some(post_link_id),
max_plaintext_size(),
);
assert_eq!(u8::max_value() as usize, full_fragment_set.len());
assert_eq!(u8::MAX as usize, full_fragment_set.len());
verify_two_way_linked_set_payload(full_fragment_set, &full_set_payload);
}
@@ -700,8 +700,8 @@ mod tests {
let mut sets = split_into_sets(&mut rng, &message, max_plaintext_size());
assert_eq!(2, sets.len());
assert_eq!(sets[0].len(), u8::max_value() as usize);
assert_eq!(sets[1].len(), u8::max_value() as usize);
assert_eq!(sets[0].len(), u8::MAX as usize);
assert_eq!(sets[1].len(), u8::MAX as usize);
verify_correct_link(&sets[0], &sets[1]);
verify_pre_linked_set_payload(
sets.pop().unwrap(),
@@ -726,9 +726,9 @@ mod tests {
rng.fill_bytes(&mut message);
let mut sets = split_into_sets(&mut rng, &message, max_plaintext_size());
assert_eq!(4, sets.len());
assert_eq!(sets[0].len(), u8::max_value() as usize);
assert_eq!(sets[1].len(), u8::max_value() as usize);
assert_eq!(sets[2].len(), u8::max_value() as usize);
assert_eq!(sets[0].len(), u8::MAX as usize);
assert_eq!(sets[1].len(), u8::MAX as usize);
assert_eq!(sets[2].len(), u8::MAX as usize);
verify_correct_link(&sets[0], &sets[1]);
verify_correct_link(&sets[1], &sets[2]);
@@ -766,10 +766,10 @@ mod tests {
let mut sets = split_into_sets(&mut rng, &message, max_plaintext_size());
assert_eq!(4, sets.len());
assert_eq!(sets[0].len(), u8::max_value() as usize);
assert_eq!(sets[1].len(), u8::max_value() as usize);
assert_eq!(sets[2].len(), u8::max_value() as usize);
assert_eq!(sets[3].len(), u8::max_value() as usize);
assert_eq!(sets[0].len(), u8::MAX as usize);
assert_eq!(sets[1].len(), u8::MAX as usize);
assert_eq!(sets[2].len(), u8::MAX as usize);
assert_eq!(sets[3].len(), u8::MAX as usize);
verify_correct_link(&sets[0], &sets[1]);
verify_correct_link(&sets[1], &sets[2]);
+4 -4
View File
@@ -235,7 +235,7 @@ mod message_receiver {
1,
vec![mix::Node {
mix_id: 123,
owner: "foomp1".to_string(),
owner: None,
host: "10.20.30.40".parse().unwrap(),
mix_host: "10.20.30.40:1789".parse().unwrap(),
identity_key: identity::PublicKey::from_base58_string(
@@ -255,7 +255,7 @@ mod message_receiver {
2,
vec![mix::Node {
mix_id: 234,
owner: "foomp2".to_string(),
owner: None,
host: "11.21.31.41".parse().unwrap(),
mix_host: "11.21.31.41:1789".parse().unwrap(),
identity_key: identity::PublicKey::from_base58_string(
@@ -275,7 +275,7 @@ mod message_receiver {
3,
vec![mix::Node {
mix_id: 456,
owner: "foomp3".to_string(),
owner: None,
host: "12.22.32.42".parse().unwrap(),
mix_host: "12.22.32.42:1789".parse().unwrap(),
identity_key: identity::PublicKey::from_base58_string(
@@ -295,7 +295,7 @@ mod message_receiver {
// currently coco_nodes don't really exist so this is still to be determined
mixes,
vec![gateway::Node {
owner: "foomp4".to_string(),
owner: None,
host: "1.2.3.4".parse().unwrap(),
mix_host: "1.2.3.4:1789".parse().unwrap(),
clients_ws_port: 9000,
+1 -1
View File
@@ -17,7 +17,7 @@ cosmrs.workspace = true
eyre = { workspace = true }
futures.workspace = true
humantime = { workspace = true }
sha2 = "0.10.8"
sha2 = { workspace = true }
serde = { workspace = true, features = ["derive"] }
sqlx = { workspace = true, features = ["runtime-tokio-rustls", "sqlite", "macros", "migrate", "time"] }
tendermint.workspace = true
+1 -1
View File
@@ -8,7 +8,7 @@ license.workspace = true
[dependencies]
anyhow = { workspace = true }
dirs = "4.0"
dirs = { workspace = true }
futures = { workspace = true }
log = { workspace = true }
pin-project = { workspace = true }
+12 -2
View File
@@ -27,6 +27,7 @@ use nym_task::manager::TaskStatus;
use nym_task::{TaskClient, TaskHandle};
use anyhow::anyhow;
use nym_validator_client::UserAgent;
use std::error::Error;
use std::path::PathBuf;
@@ -61,6 +62,8 @@ pub struct NymClient<S> {
setup_method: GatewaySetup,
user_agent: UserAgent,
/// Optional path to a .json file containing standalone network details.
custom_mixnet: Option<PathBuf>,
}
@@ -74,11 +77,17 @@ where
<S::GatewaysDetailsStore as GatewaysDetailsStore>::StorageError: Sync + Send,
<S::KeyStore as KeyStore>::StorageError: Send + Sync,
{
pub fn new(config: Config, storage: S, custom_mixnet: Option<PathBuf>) -> Self {
pub fn new(
config: Config,
storage: S,
user_agent: UserAgent,
custom_mixnet: Option<PathBuf>,
) -> Self {
NymClient {
config,
storage,
setup_method: GatewaySetup::MustLoad { gateway_id: None },
user_agent,
custom_mixnet,
}
}
@@ -226,7 +235,8 @@ where
let mut base_builder =
BaseClientBuilder::new(&self.config.base, self.storage, dkg_query_client)
.with_gateway_setup(self.setup_method);
.with_gateway_setup(self.setup_method)
.with_user_agent(self.user_agent);
if let Some(custom_mixnet) = &self.custom_mixnet {
base_builder = base_builder.with_stored_topology(custom_mixnet)?;
-20
View File
@@ -1,20 +0,0 @@
# Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
# SPDX-License-Identifier: Apache-2.0
[package]
name = "nym-statistics-common"
version = "1.0.1"
edition = "2021"
license.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
async-trait = { workspace = true }
log = { workspace = true }
reqwest = { workspace = true, features = ["json"] }
serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true }
sqlx = { workspace = true, features = ["runtime-tokio-rustls", "chrono"]}
thiserror = { workspace = true }
tokio = { workspace = true, features = ["time"] }
-51
View File
@@ -1,51 +0,0 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::error::StatsError;
use crate::StatsMessage;
pub const DEFAULT_STATISTICS_SERVICE_ADDRESS: &str = "127.0.0.1";
pub const DEFAULT_STATISTICS_SERVICE_PORT: u16 = 8091;
pub const STATISTICS_SERVICE_VERSION: &str = "/v1";
pub const STATISTICS_SERVICE_API_STATISTICS: &str = "statistic";
pub async fn build_and_send_statistics_request(
msg: StatsMessage,
url: String,
) -> Result<(), StatsError> {
reqwest::Client::new()
.post(format!(
"{url}{STATISTICS_SERVICE_VERSION}/{STATISTICS_SERVICE_API_STATISTICS}"
))
.json(&msg)
.send()
.await?;
Ok(())
}
pub fn build_statistics_request_bytes(msg: StatsMessage) -> Result<Vec<u8>, StatsError> {
let json_msg = msg.to_json()?;
let req = reqwest::Request::new(
reqwest::Method::POST,
reqwest::Url::parse(&format!(
"http://{DEFAULT_STATISTICS_SERVICE_ADDRESS}:{DEFAULT_STATISTICS_SERVICE_PORT}{STATISTICS_SERVICE_VERSION}/{STATISTICS_SERVICE_API_STATISTICS}"
))
.unwrap(),
);
let data = format!(
"{} {} {:?}\n\
Content-Type: application/json\n\
Content-Length: {}\n\n\
{}\n",
req.method().as_str(),
req.url().as_str(),
req.version(),
json_msg.len(),
json_msg
);
Ok(data.into_bytes())
}
-57
View File
@@ -1,57 +0,0 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use async_trait::async_trait;
use log::error;
use sqlx::types::chrono::{DateTime, Utc};
use std::time::Duration;
use tokio::time;
use crate::error::StatsError;
use crate::StatsMessage;
const STATISTICS_TIMER_INTERVAL: Duration = Duration::from_secs(60);
#[async_trait]
pub trait StatisticsCollector {
async fn create_stats_message(
&self,
interval: Duration,
timestamp: DateTime<Utc>,
) -> StatsMessage;
async fn send_stats_message(&self, stats_message: StatsMessage) -> Result<(), StatsError>;
async fn reset_stats(&mut self);
}
pub struct StatisticsSender<T: StatisticsCollector> {
collector: T,
interval: Duration,
timestamp: DateTime<Utc>,
}
impl<T: StatisticsCollector> StatisticsSender<T> {
pub fn new(collector: T) -> Self {
StatisticsSender {
collector,
interval: STATISTICS_TIMER_INTERVAL,
timestamp: Utc::now(),
}
}
pub async fn run(&mut self) {
let mut interval = time::interval(self.interval);
loop {
interval.tick().await;
let stats_message = self
.collector
.create_stats_message(self.interval, self.timestamp)
.await;
if let Err(e) = self.collector.send_stats_message(stats_message).await {
error!("Statistics not sent: {}", e);
}
self.collector.reset_stats().await;
self.timestamp = Utc::now();
}
}
}
-13
View File
@@ -1,13 +0,0 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use thiserror::Error;
#[derive(Debug, Error)]
pub enum StatsError {
#[error("Serde JSON error: {0}")]
SerdeJsonError(#[from] serde_json::Error),
#[error("Reqwest error: {0}")]
ReqwestError(#[from] reqwest::Error),
}
-65
View File
@@ -1,65 +0,0 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use serde::{Deserialize, Serialize};
use error::StatsError;
pub mod api;
pub mod collector;
pub mod error;
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct StatsMessage {
pub stats_data: Vec<StatsData>,
pub interval_seconds: u32,
pub timestamp: String,
}
impl StatsMessage {
pub fn to_json(&self) -> Result<String, StatsError> {
Ok(serde_json::to_string(self)?)
}
pub fn from_json(s: &str) -> Result<Self, StatsError> {
Ok(serde_json::from_str(s)?)
}
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub enum StatsData {
Service(StatsServiceData),
Gateway(StatsGatewayData),
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct StatsGatewayData {
pub gateway_id: String,
pub inbox_count: u32,
}
impl StatsGatewayData {
pub fn new(gateway_id: String, inbox_count: u32) -> Self {
StatsGatewayData {
gateway_id,
inbox_count,
}
}
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct StatsServiceData {
pub requested_service: String,
pub request_bytes: u32,
pub response_bytes: u32,
}
impl StatsServiceData {
pub fn new(requested_service: String, request_bytes: u32, response_bytes: u32) -> Self {
StatsServiceData {
requested_service,
request_bytes,
response_bytes,
}
}
}
+52 -9
View File
@@ -8,6 +8,9 @@ use nym_mixnet_contract_common::GatewayBond;
use nym_sphinx_addressing::nodes::{NodeIdentity, NymNodeRoutingAddress};
use nym_sphinx_types::Node as SphinxNode;
use nym_api_requests::nym_nodes::SkimmedNode;
use rand::seq::SliceRandom;
use rand::thread_rng;
use std::fmt;
use std::fmt::Formatter;
use std::io;
@@ -40,11 +43,13 @@ pub enum GatewayConversionError {
#[source]
err: AddrParseError,
},
#[error("provided node is not an entry gateway in this epoch!")]
NotGateway,
}
#[derive(Clone)]
pub struct Node {
pub owner: String,
pub host: NetworkAddress,
// we're keeping this as separate resolved field since we do not want to be resolving the potential
// hostname every time we want to construct a path via this node
@@ -58,6 +63,9 @@ pub struct Node {
pub identity_key: identity::PublicKey,
pub sphinx_key: encryption::PublicKey, // TODO: or nymsphinx::PublicKey? both are x25519
// to be removed:
pub owner: Option<String>,
pub version: NodeVersion,
}
@@ -78,11 +86,9 @@ impl std::fmt::Debug for Node {
impl Node {
pub fn parse_host(raw: &str) -> Result<NetworkAddress, GatewayConversionError> {
raw.parse()
.map_err(|err| GatewayConversionError::InvalidAddress {
value: raw.to_owned(),
source: err,
})
// safety: this conversion is infallible
// (but we retain result return type for legacy reasons)
Ok(raw.parse().unwrap())
}
pub fn extract_mix_host(
@@ -120,7 +126,7 @@ impl fmt::Display for Node {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"Node(id: {}, owner: {}, host: {})",
"Node(id: {}, owner: {:?}, host: {})",
self.identity_key, self.owner, self.host,
)
}
@@ -154,7 +160,7 @@ impl<'a> TryFrom<&'a GatewayBond> for Node {
let mix_host = Self::extract_mix_host(&host, bond.gateway.mix_port)?;
Ok(Node {
owner: bond.owner.as_str().to_owned(),
owner: Some(bond.owner.as_str().to_owned()),
host,
mix_host,
clients_ws_port: bond.gateway.clients_port,
@@ -199,7 +205,7 @@ impl<'a> TryFrom<&'a DescribedGateway> for Node {
let mix_host = SocketAddr::new(ips[0], value.bond.gateway.mix_port);
Ok(Node {
owner: value.bond.owner.as_str().to_owned(),
owner: Some(value.bond.owner.as_str().to_owned()),
host,
mix_host,
clients_ws_port: self_described.mixnet_websockets.ws_port,
@@ -219,6 +225,43 @@ impl<'a> TryFrom<&'a DescribedGateway> for Node {
}
}
impl<'a> TryFrom<&'a SkimmedNode> for Node {
type Error = GatewayConversionError;
fn try_from(value: &'a SkimmedNode) -> Result<Self, Self::Error> {
let Some(entry_details) = &value.entry else {
return Err(GatewayConversionError::NotGateway);
};
if value.ip_addresses.is_empty() {
return Err(GatewayConversionError::NoIpAddressesProvided {
gateway: value.ed25519_identity_pubkey.clone(),
});
}
// safety: we just checked the slice is not empty
#[allow(clippy::unwrap_used)]
let ip = value.ip_addresses.choose(&mut thread_rng()).unwrap();
let host = if let Some(hostname) = &entry_details.hostname {
NetworkAddress::Hostname(hostname.to_string())
} else {
NetworkAddress::IpAddr(*ip)
};
Ok(Node {
host,
mix_host: SocketAddr::new(*ip, value.mix_port),
clients_ws_port: entry_details.ws_port,
clients_wss_port: entry_details.wss_port,
identity_key: value.ed25519_identity_pubkey.parse()?,
sphinx_key: value.x25519_sphinx_pubkey.parse()?,
owner: None,
version: NodeVersion::Unknown,
})
}
}
impl TryFrom<DescribedGateway> for Node {
type Error = GatewayConversionError;
+41 -6
View File
@@ -6,7 +6,7 @@
use crate::filter::VersionFilterable;
pub use error::NymTopologyError;
use log::warn;
use log::{debug, warn};
use nym_mixnet_contract_common::mixnode::MixNodeDetails;
use nym_mixnet_contract_common::{GatewayBond, IdentityKeyRef, MixId};
use nym_sphinx_addressing::nodes::NodeIdentity;
@@ -14,6 +14,7 @@ use nym_sphinx_types::Node as SphinxNode;
use rand::prelude::SliceRandom;
use rand::{CryptoRng, Rng};
use std::collections::BTreeMap;
use std::convert::Infallible;
use std::fmt::{self, Display, Formatter};
use std::io;
@@ -93,7 +94,7 @@ impl NetworkAddress {
}
impl FromStr for NetworkAddress {
type Err = std::io::Error;
type Err = Infallible;
fn from_str(s: &str) -> Result<Self, Self::Err> {
if let Ok(ip_addr) = s.parse() {
@@ -137,6 +138,38 @@ impl NymTopology {
NymTopology { mixes, gateways }
}
pub fn from_unordered<MI, GI, M, G>(unordered_mixes: MI, unordered_gateways: GI) -> Self
where
MI: Iterator<Item = M>,
GI: Iterator<Item = G>,
G: TryInto<gateway::Node>,
M: TryInto<mix::Node>,
<G as TryInto<gateway::Node>>::Error: Display,
<M as TryInto<mix::Node>>::Error: Display,
{
let mut mixes = BTreeMap::new();
let mut gateways = Vec::new();
for node in unordered_mixes.into_iter() {
match node.try_into() {
Ok(mixnode) => mixes
.entry(mixnode.layer as MixLayer)
.or_insert_with(Vec::new)
.push(mixnode),
Err(err) => debug!("malformed mixnode: {err}"),
}
}
for node in unordered_gateways.into_iter() {
match node.try_into() {
Ok(gateway) => gateways.push(gateway),
Err(err) => debug!("malformed gateway: {err}"),
}
}
NymTopology::new(mixes, gateways)
}
#[cfg(feature = "serializable")]
pub fn new_from_file<P: AsRef<std::path::Path>>(path: P) -> std::io::Result<Self> {
let file = std::fs::File::open(path)?;
@@ -491,7 +524,7 @@ mod converting_mixes_to_vec {
fn returns_a_vec_with_hashmap_values() {
let node1 = mix::Node {
mix_id: 42,
owner: "N/A".to_string(),
owner: Some("N/A".to_string()),
host: "3.3.3.3".parse().unwrap(),
mix_host: "3.3.3.3:1789".parse().unwrap(),
identity_key: identity::PublicKey::from_base58_string(
@@ -507,12 +540,12 @@ mod converting_mixes_to_vec {
};
let node2 = mix::Node {
owner: "Alice".to_string(),
owner: Some("Alice".to_string()),
..node1.clone()
};
let node3 = mix::Node {
owner: "Bob".to_string(),
owner: Some("Bob".to_string()),
..node1.clone()
};
@@ -522,7 +555,9 @@ mod converting_mixes_to_vec {
let topology = NymTopology::new(mixes, vec![]);
let mixvec = topology.mixes_as_vec();
assert!(mixvec.iter().any(|node| node.owner == "N/A"));
assert!(mixvec
.iter()
.any(|node| node.owner.as_ref() == Some(&"N/A".to_string())));
}
}
+55 -7
View File
@@ -8,6 +8,9 @@ use nym_mixnet_contract_common::{MixId, MixNodeBond};
use nym_sphinx_addressing::nodes::NymNodeRoutingAddress;
use nym_sphinx_types::Node as SphinxNode;
use nym_api_requests::nym_nodes::{NodeRole, SkimmedNode};
use rand::seq::SliceRandom;
use rand::thread_rng;
use std::fmt::Formatter;
use std::io;
use std::net::SocketAddr;
@@ -27,12 +30,20 @@ pub enum MixnodeConversionError {
#[source]
source: io::Error,
},
#[error("invalid mix layer")]
InvalidLayer,
#[error("'{mixnode}' has not provided any valid ip addresses")]
NoIpAddressesProvided { mixnode: String },
#[error("provided node is not a mixnode in this epoch!")]
NotMixnode,
}
#[derive(Clone)]
pub struct Node {
pub mix_id: MixId,
pub owner: String,
pub host: NetworkAddress,
// we're keeping this as separate resolved field since we do not want to be resolving the potential
// hostname every time we want to construct a path via this node
@@ -40,7 +51,10 @@ pub struct Node {
pub identity_key: identity::PublicKey,
pub sphinx_key: encryption::PublicKey, // TODO: or nymsphinx::PublicKey? both are x25519
pub layer: Layer,
// to be removed:
pub version: NodeVersion,
pub owner: Option<String>,
}
impl std::fmt::Debug for Node {
@@ -60,11 +74,9 @@ impl std::fmt::Debug for Node {
impl Node {
pub fn parse_host(raw: &str) -> Result<NetworkAddress, MixnodeConversionError> {
raw.parse()
.map_err(|err| MixnodeConversionError::InvalidAddress {
value: raw.to_owned(),
source: err,
})
// safety: this conversion is infallible
// (but we retain result return type for legacy reasons)
Ok(raw.parse().unwrap())
}
pub fn extract_mix_host(
@@ -109,7 +121,7 @@ impl<'a> TryFrom<&'a MixNodeBond> for Node {
Ok(Node {
mix_id: bond.mix_id,
owner: bond.owner.as_str().to_owned(),
owner: Some(bond.owner.as_str().to_owned()),
host,
mix_host,
identity_key: identity::PublicKey::from_base58_string(&bond.mix_node.identity_key)?,
@@ -120,6 +132,42 @@ impl<'a> TryFrom<&'a MixNodeBond> for Node {
}
}
impl<'a> TryFrom<&'a SkimmedNode> for Node {
type Error = MixnodeConversionError;
fn try_from(value: &'a SkimmedNode) -> Result<Self, Self::Error> {
if value.ip_addresses.is_empty() {
return Err(MixnodeConversionError::NoIpAddressesProvided {
mixnode: value.ed25519_identity_pubkey.clone(),
});
}
let layer = match value.role {
NodeRole::Mixnode { layer } => layer
.try_into()
.map_err(|_| MixnodeConversionError::InvalidLayer)?,
_ => return Err(MixnodeConversionError::NotMixnode),
};
// safety: we just checked the slice is not empty
#[allow(clippy::unwrap_used)]
let ip = value.ip_addresses.choose(&mut thread_rng()).unwrap();
let host = NetworkAddress::IpAddr(*ip);
Ok(Node {
mix_id: value.node_id,
host,
mix_host: SocketAddr::new(*ip, value.mix_port),
identity_key: value.ed25519_identity_pubkey.parse()?,
sphinx_key: value.x25519_sphinx_pubkey.parse()?,
layer,
owner: None,
version: NodeVersion::Unknown,
})
}
}
impl TryFrom<MixNodeBond> for Node {
type Error = MixnodeConversionError;
+4 -2
View File
@@ -109,7 +109,8 @@ pub struct SerializableMixNode {
#[serde(alias = "mix_id")]
pub mix_id: u32,
pub owner: String,
#[cfg_attr(feature = "wasm-serde-types", tsify(optional))]
pub owner: Option<String>,
pub host: String,
@@ -180,7 +181,8 @@ impl<'a> From<&'a mix::Node> for SerializableMixNode {
#[serde(rename_all = "camelCase")]
#[serde(deny_unknown_fields)]
pub struct SerializableGateway {
pub owner: String,
#[cfg_attr(feature = "wasm-serde-types", tsify(optional))]
pub owner: Option<String>,
pub host: String,
+4 -4
View File
@@ -8,21 +8,21 @@ rust-version = "1.58"
license.workspace = true
[dependencies]
base64 = "0.21.4"
base64 = { workspace = true }
eyre = { workspace = true }
hmac = { workspace = true }
itertools = "0.11"
itertools = { workspace = true }
log = { workspace = true }
reqwest = { workspace = true }
schemars = { workspace = true }
serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true }
sha2 = "0.10.8"
sha2 = { workspace = true }
strum = { workspace = true, features = ["derive"] }
thiserror = { workspace = true }
ts-rs = { workspace = true }
url = { workspace = true }
x25519-dalek = { version = "2.0.0", features = ["static_secrets"] }
x25519-dalek = { workspace = true, features = ["static_secrets"] }
cosmwasm-std = { workspace = true }
cosmrs = { workspace = true }
+1 -3
View File
@@ -124,7 +124,6 @@ pub struct GatewayNetworkRequesterDetails {
pub encryption_key: String,
pub open_proxy: bool,
pub enabled_statistics: bool,
// just a convenience wrapper around all the keys
pub address: String,
@@ -142,8 +141,7 @@ impl fmt::Display for GatewayNetworkRequesterDetails {
writeln!(f, "\tencryption key: {}", self.encryption_key)?;
writeln!(f, "\taddress: {}", self.address)?;
writeln!(f, "\tuses open proxy: {}", self.open_proxy)?;
writeln!(f, "\tsends statistics: {}", self.enabled_statistics)
writeln!(f, "\tuses open proxy: {}", self.open_proxy)
}
}
+12
View File
@@ -362,6 +362,14 @@ pub struct TopologyWasm {
/// the first valid instance.
/// Supersedes `topology_refresh_rate_ms`.
pub disable_refreshing: bool,
/// Specifies a minimum performance of a mixnode that is used on route construction.
/// This setting is only applicable when `NymApi` topology is used.
pub minimum_mixnode_performance: u8,
/// Specifies a minimum performance of a gateway that is used on route construction.
/// This setting is only applicable when `NymApi` topology is used.
pub minimum_gateway_performance: u8,
}
impl Default for TopologyWasm {
@@ -382,6 +390,8 @@ impl From<TopologyWasm> for ConfigTopology {
topology.max_startup_gateway_waiting_period_ms as u64,
),
topology_structure: Default::default(),
minimum_mixnode_performance: topology.minimum_mixnode_performance,
minimum_gateway_performance: topology.minimum_gateway_performance,
}
}
}
@@ -395,6 +405,8 @@ impl From<ConfigTopology> for TopologyWasm {
.max_startup_gateway_waiting_period
.as_millis() as u32,
disable_refreshing: topology.disable_refreshing,
minimum_mixnode_performance: topology.minimum_mixnode_performance,
minimum_gateway_performance: topology.minimum_gateway_performance,
}
}
}
@@ -244,6 +244,16 @@ pub struct TopologyWasmOverride {
/// Supersedes `topology_refresh_rate_ms`.
#[tsify(optional)]
pub disable_refreshing: Option<bool>,
/// Specifies a minimum performance of a mixnode that is used on route construction.
/// This setting is only applicable when `NymApi` topology is used.
#[tsify(optional)]
pub minimum_mixnode_performance: Option<u8>,
/// Specifies a minimum performance of a gateway that is used on route construction.
/// This setting is only applicable when `NymApi` topology is used.
#[tsify(optional)]
pub minimum_gateway_performance: Option<u8>,
}
impl From<TopologyWasmOverride> for TopologyWasm {
@@ -261,6 +271,12 @@ impl From<TopologyWasmOverride> for TopologyWasm {
.max_startup_gateway_waiting_period_ms
.unwrap_or(def.max_startup_gateway_waiting_period_ms),
disable_refreshing: value.disable_refreshing.unwrap_or(def.disable_refreshing),
minimum_mixnode_performance: value
.minimum_mixnode_performance
.unwrap_or(def.minimum_mixnode_performance),
minimum_gateway_performance: value
.minimum_gateway_performance
.unwrap_or(def.minimum_gateway_performance),
}
}
}

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