Compare commits

..

1 Commits

Author SHA1 Message Date
Mark Sinclair 1955e03a35 Test and earn
- add logging and clear local storage menu items
- bump nym-connect version
- add app version number
- add reset trigger when clearing SP storage
- bump tauri version (nym-connect and nym-wallet)
- fix webpack config for prod builds
- new selector for services, with an advanced section for service providers
2022-12-17 05:33:23 +00:00
190 changed files with 8674 additions and 5955 deletions
+28 -44
View File
@@ -13,32 +13,10 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
- all-binaries: improved error logging ([#2686])
- native client: bring shutdown logic up to the same level as socks5-client
- nym-api, coconut-dkg contract: automatic, time-based dkg epoch state advancement ([#2670])
- all-binaries: standarised argument names (note: old names should still be accepted) ([#2762]
### Fixed
- nym-api: should now correctly use `rewarding.enabled` config flag ([#2753])
[#2686]: https://github.com/nymtech/nym/pull/2686
[#2670]: https://github.com/nymtech/nym/pull/2670
[#2753]: https://github.com/nymtech/nym/pull/2753
[#2762]: https://github.com/nymtech/nym/pull/2762
## [v1.1.4] (2022-12-20)
This release adds multiple Single Use Reply Blocks (SURBs) to allow arbitrarily-sized anonymized replies.
At the moment this is turned off by default, but available for use by application developers.
We will need to wait for network-requesters to upgrade to this new release, after which multi-SURB anonymization will become the default setting for the SOCKS proxy clients.
The release also include some additional work for distributed key generation in the Coconut signing authority nodes.
### Changed
- Feature/dkg contract threshold by @neacsu in https://github.com/nymtech/nym/pull/1885
- Multi-surbs by @jstuczyn in https://github.com/nymtech/nym/pull/2667
- Fix multi-surb backwards compatibility in pre 1.1.4 client config files by @jstuczyn in https://github.com/nymtech/nym/pull/2703
- fix: ignore corrupted surb storage and instead create fresh one by @jstuczyn in https://github.com/nymtech/nym/pull/2711
- socks5: rework waiting in inbound.rs by @octol in https://github.com/nymtech/nym/pull/1880
## [v1.1.3] (2022-12-13)
@@ -53,7 +31,7 @@ The release also include some additional work for distributed key generation in
- network-requester: fix bug where websocket connection disconnect resulted in success error code
- clients: fix a few panics handling the gateway-client
- mixnode, gateway, validator-api: Use mainnet values as defaults for URLs and mixnet contract ([#1884])
- mixnode, gateway, validator-api: Use mainnet values as defaults for URLs and mixnet contract ([#1884])
- socks5: fixed bug where connections sometimes where closed too early
- clients: improve message logging when received message fails to get reconstructed ([#1803])
@@ -73,7 +51,7 @@ The release also include some additional work for distributed key generation in
- gateway: Renamed flag from `enabled/disabled_credentials_mode` to `only-coconut-credentials`
- "Family" feature for node families + layers
- Initial coconut functionality including credentials and distributed key generation
- Initial coconut functionality including credentials and distributed key generation
## [v1.1.1](https://github.com/nymtech/nym/tree/v1.1.1) (2022-11-29)
@@ -109,6 +87,7 @@ The release also include some additional work for distributed key generation in
[#1786]: https://github.com/nymtech/nym/pull/1786
[#1805]: https://github.com/nymtech/nym/pull/1805
## [v1.1.0](https://github.com/nymtech/nym/tree/v1.1.0) (2022-11-09)
### Added
@@ -135,7 +114,7 @@ The release also include some additional work for distributed key generation in
- gateway-client: will attempt to read now as many as 8 websocket messages at once, assuming they're already available on the socket ([#1669])
- moved `Percent` struct to `contracts-common`, change affects explorer-api
- socks5 client: graceful shutdown should fix error on disconnect in nym-connect ([#1591])
- validator-api: changed error serialization on `inclusion_probability`, `stake-saturation` and `reward-estimation` endpoints to provide more accurate information ([#1681])
- validator-api: changed error serialization on `inclusion_probability`, `stake-saturation` and `reward-estimation` endpoints to provide more accurate information ([#1681])
- validator-client: made `fee` argument optional for `execute` and `execute_multiple` ([#1541])
- wasm-client: fixed build errors on MacOS and changed example JS code to use mainnet ([#1585])
- validator-api: changes to internal SQL schema due to the mixnet contract revamp ([#1472])
@@ -163,6 +142,7 @@ The release also include some additional work for distributed key generation in
[#1724]: https://github.com/nymtech/nym/pull/1724
[#1725]: https://github.com/nymtech/nym/pull/1725
## [nym-binaries-1.0.2](https://github.com/nymtech/nym/tree/nym-binaries-1.0.2)
### Added
@@ -216,7 +196,8 @@ The release also include some additional work for distributed key generation in
- gateway, network-statistics: include gateway id in the sent statistical data ([#1478])
- network explorer: tweak how active set probability is shown ([#1503])
- validator-api: rewarder set update fails without panicking on possible nymd queries ([#1520])
- network-requester, socks5 client (nym-connect): send and receive respectively a message error to be displayed about filter check failure ([#1576])
- network-requester, socks5 client (nym-connect): send and receive respectively a message error to be displayed about filter check failure ([#1576])
[#1249]: https://github.com/nymtech/nym/pull/1249
[#1256]: https://github.com/nymtech/nym/pull/1256
@@ -310,9 +291,9 @@ The release also include some additional work for distributed key generation in
- Bump minimist from 1.2.5 to 1.2.6 in /clients/tauri-client [\#1163](https://github.com/nymtech/nym/pull/1163) ([dependabot[bot]](https://github.com/apps/dependabot))
- Bump minimist from 1.2.5 to 1.2.6 in /clients/webassembly/js-example [\#1162](https://github.com/nymtech/nym/pull/1162) ([dependabot[bot]](https://github.com/apps/dependabot))
- Bump minimist from 1.2.5 to 1.2.6 in /clients/native/examples/js-examples/websocket [\#1160](https://github.com/nymtech/nym/pull/1160) ([dependabot[bot]](https://github.com/apps/dependabot))
- Bump minimist from 1.2.5 to 1.2.6 in /docker/typescript_client/upload_contract [\#1159](https://github.com/nymtech/nym/pull/1159) ([dependabot[bot]](https://github.com/apps/dependabot))
- Bump minimist from 1.2.5 to 1.2.6 in /docker/typescript\_client/upload\_contract [\#1159](https://github.com/nymtech/nym/pull/1159) ([dependabot[bot]](https://github.com/apps/dependabot))
- Feature/vesting full [\#1158](https://github.com/nymtech/nym/pull/1158) ([fmtabbara](https://github.com/fmtabbara))
- get_current_epoch tauri [\#1156](https://github.com/nymtech/nym/pull/1156) ([durch](https://github.com/durch))
- get\_current\_epoch tauri [\#1156](https://github.com/nymtech/nym/pull/1156) ([durch](https://github.com/durch))
- Cleanup [\#1155](https://github.com/nymtech/nym/pull/1155) ([durch](https://github.com/durch))
- Feature flag reward payments [\#1154](https://github.com/nymtech/nym/pull/1154) ([durch](https://github.com/durch))
- Add Query endpoints for calculating rewards [\#1152](https://github.com/nymtech/nym/pull/1152) ([durch](https://github.com/durch))
@@ -321,7 +302,7 @@ The release also include some additional work for distributed key generation in
- wallet: use Urls rather than Strings for validator urls [\#1148](https://github.com/nymtech/nym/pull/1148) ([octol](https://github.com/octol))
- Change accumulated reward to Option, migrate delegations [\#1147](https://github.com/nymtech/nym/pull/1147) ([durch](https://github.com/durch))
- wallet: fetch validators url remotely if available [\#1146](https://github.com/nymtech/nym/pull/1146) ([octol](https://github.com/octol))
- Fix delegated_free calculation [\#1145](https://github.com/nymtech/nym/pull/1145) ([durch](https://github.com/durch))
- Fix delegated\_free calculation [\#1145](https://github.com/nymtech/nym/pull/1145) ([durch](https://github.com/durch))
- Update Nym wallet dependencies to use `ts-packages` [\#1144](https://github.com/nymtech/nym/pull/1144) ([mmsinclair](https://github.com/mmsinclair))
- wallet: try validators one by one if available [\#1143](https://github.com/nymtech/nym/pull/1143) ([octol](https://github.com/octol))
- Update Network Explorer Packages and add mix node identity key copy [\#1142](https://github.com/nymtech/nym/pull/1142) ([mmsinclair](https://github.com/mmsinclair))
@@ -361,13 +342,14 @@ The release also include some additional work for distributed key generation in
- feature/pedersen-commitments [\#1048](https://github.com/nymtech/nym/pull/1048) ([danielementary](https://github.com/danielementary))
- Feature/reuse init owner [\#970](https://github.com/nymtech/nym/pull/970) ([neacsu](https://github.com/neacsu))
## [v0.12.1](https://github.com/nymtech/nym/tree/v0.12.1) (2021-12-23)
[Full Changelog](https://github.com/nymtech/nym/compare/v0.12.0...v0.12.1)
**Implemented enhancements:**
- Add version check to binaries [\#967](https://github.com/nymtech/nym/issues/967)
- Add version check to binaries [\#967](https://github.com/nymtech/nym/issues/967)
**Fixed bugs:**
@@ -397,7 +379,7 @@ The release also include some additional work for distributed key generation in
- Bugfix/remove mixnode bonding overwrite [\#917](https://github.com/nymtech/nym/pull/917) ([jstuczyn](https://github.com/jstuczyn))
- Fixes crash condition in validator API when calculating last day uptime [\#909](https://github.com/nymtech/nym/pull/909) ([jstuczyn](https://github.com/jstuczyn))
- Bugfix/monitor initial values wait [\#907](https://github.com/nymtech/nym/pull/907) ([jstuczyn](https://github.com/jstuczyn))
- Bug fix: Network Explorer: Add freegeoip API key and split out tasks for country distributions [\#806](https://github.com/nymtech/nym/pull/806) ([mmsinclair](https://github.com/mmsinclair))
- Bug fix: Network Explorer: Add freegeoip API key and split out tasks for country distributions [\#806](https://github.com/nymtech/nym/pull/806) ([mmsinclair](https://github.com/mmsinclair))
- Explorer API: port test now split out address resolution and add units tests [\#755](https://github.com/nymtech/nym/pull/755) ([mmsinclair](https://github.com/mmsinclair))
**Closed issues:**
@@ -412,7 +394,7 @@ The release also include some additional work for distributed key generation in
- help!!! [\#712](https://github.com/nymtech/nym/issues/712)
- UX feature request: show all delegated nodes in wallet [\#711](https://github.com/nymtech/nym/issues/711)
- UX feature request: add current balance on wallet pages [\#710](https://github.com/nymtech/nym/issues/710)
- got sign issue from bot [\#709](https://github.com/nymtech/nym/issues/709)
- got sign issue from bot [\#709](https://github.com/nymtech/nym/issues/709)
- As a wallet user, I would like to be able to log out of the wallet [\#706](https://github.com/nymtech/nym/issues/706)
- As a wallet user, I would like to have a "receive" page where I can see my own wallet address [\#705](https://github.com/nymtech/nym/issues/705)
- Update native client/socks client/mixnode/gateway `upgrade` command [\#689](https://github.com/nymtech/nym/issues/689)
@@ -422,7 +404,7 @@ The release also include some additional work for distributed key generation in
- nym-socks5-client crash after opening Keybase team "Browse all channels" [\#494](https://github.com/nymtech/nym/issues/494)
- Mixed Content problem [\#400](https://github.com/nymtech/nym/issues/400)
- Gateway disk quota [\#137](https://github.com/nymtech/nym/issues/137)
- Simplify message encapsulation with regards to topology [\#127](https://github.com/nymtech/nym/issues/127)
- Simplify message encapsulation with regards to topology [\#127](https://github.com/nymtech/nym/issues/127)
- Create constants for cli argument names [\#115](https://github.com/nymtech/nym/issues/115)
- Using Blake3 as a hash function [\#103](https://github.com/nymtech/nym/issues/103)
- Validator should decide which layer a node is in [\#86](https://github.com/nymtech/nym/issues/86)
@@ -478,10 +460,10 @@ The release also include some additional work for distributed key generation in
- Feature/pre cosmrs updates [\#935](https://github.com/nymtech/nym/pull/935) ([jstuczyn](https://github.com/jstuczyn))
- Feature/client on behalf [\#934](https://github.com/nymtech/nym/pull/934) ([neacsu](https://github.com/neacsu))
- Webpack wallet prod configuration [\#933](https://github.com/nymtech/nym/pull/933) ([tommyv1987](https://github.com/tommyv1987))
- Adding tx_hash to wallet response [\#932](https://github.com/nymtech/nym/pull/932) ([futurechimp](https://github.com/futurechimp))
- Adding tx\_hash to wallet response [\#932](https://github.com/nymtech/nym/pull/932) ([futurechimp](https://github.com/futurechimp))
- Release/1.0.0 pre1 [\#931](https://github.com/nymtech/nym/pull/931) ([durch](https://github.com/durch))
- Feature/identity verification [\#930](https://github.com/nymtech/nym/pull/930) ([jstuczyn](https://github.com/jstuczyn))
- Move cleaned up smart contracts to main code repo [\#929](https://github.com/nymtech/nym/pull/929) ([mfahampshire](https://github.com/mfahampshire))
- Move cleaned up smart contracts to main code repo [\#929](https://github.com/nymtech/nym/pull/929) ([mfahampshire](https://github.com/mfahampshire))
- Feature/mixnet contract further adjustments [\#928](https://github.com/nymtech/nym/pull/928) ([jstuczyn](https://github.com/jstuczyn))
- typo copy change for nodemap [\#926](https://github.com/nymtech/nym/pull/926) ([Aid19801](https://github.com/Aid19801))
- Feature/UI enhancements for Desktop Wallet [\#925](https://github.com/nymtech/nym/pull/925) ([fmtabbara](https://github.com/fmtabbara))
@@ -494,7 +476,7 @@ The release also include some additional work for distributed key generation in
- Feature/faucet page react [\#911](https://github.com/nymtech/nym/pull/911) ([fmtabbara](https://github.com/fmtabbara))
- Feature/mixnet contract refactor [\#910](https://github.com/nymtech/nym/pull/910) ([futurechimp](https://github.com/futurechimp))
- Update README.md [\#905](https://github.com/nymtech/nym/pull/905) ([tommyv1987](https://github.com/tommyv1987))
- BUG: Bond cell denom [\#904](https://github.com/nymtech/nym/pull/904) ([Aid19801](https://github.com/Aid19801))
- BUG: Bond cell denom [\#904](https://github.com/nymtech/nym/pull/904) ([Aid19801](https://github.com/Aid19801))
- Explorer UI tests missing data-testid [\#903](https://github.com/nymtech/nym/pull/903) ([tommyv1987](https://github.com/tommyv1987))
- Fix up Nym-Wallet README.md [\#899](https://github.com/nymtech/nym/pull/899) ([tommyv1987](https://github.com/tommyv1987))
- Feature/batch delegator rewarding [\#898](https://github.com/nymtech/nym/pull/898) ([jstuczyn](https://github.com/jstuczyn))
@@ -512,7 +494,7 @@ The release also include some additional work for distributed key generation in
- Reverted gateway registration handshake to its 0.11.0 version [\#882](https://github.com/nymtech/nym/pull/882) ([jstuczyn](https://github.com/jstuczyn))
- Network Explorer [\#881](https://github.com/nymtech/nym/pull/881) ([mmsinclair](https://github.com/mmsinclair))
- Feature/rewarding interval updates [\#880](https://github.com/nymtech/nym/pull/880) ([jstuczyn](https://github.com/jstuczyn))
- Put client_address and id in the correct order [\#875](https://github.com/nymtech/nym/pull/875) ([neacsu](https://github.com/neacsu))
- Put client\_address and id in the correct order [\#875](https://github.com/nymtech/nym/pull/875) ([neacsu](https://github.com/neacsu))
- remove gateway selection on delegation and undelegation pages [\#873](https://github.com/nymtech/nym/pull/873) ([fmtabbara](https://github.com/fmtabbara))
- Set MSRV on all binaries to 1.56 [\#872](https://github.com/nymtech/nym/pull/872) ([jstuczyn](https://github.com/jstuczyn))
- add native window items \(copy/paste\) via tauri [\#871](https://github.com/nymtech/nym/pull/871) ([fmtabbara](https://github.com/fmtabbara))
@@ -528,7 +510,7 @@ The release also include some additional work for distributed key generation in
- Overflow checks in release [\#846](https://github.com/nymtech/nym/pull/846) ([jstuczyn](https://github.com/jstuczyn))
- fix delegate success overflow [\#842](https://github.com/nymtech/nym/pull/842) ([fmtabbara](https://github.com/fmtabbara))
- Feature NYM wallet webdriverio test [\#841](https://github.com/nymtech/nym/pull/841) ([tommyv1987](https://github.com/tommyv1987))
- Update nym_wallet.yml [\#840](https://github.com/nymtech/nym/pull/840) ([tommyv1987](https://github.com/tommyv1987))
- Update nym\_wallet.yml [\#840](https://github.com/nymtech/nym/pull/840) ([tommyv1987](https://github.com/tommyv1987))
- Feature/vouchers [\#837](https://github.com/nymtech/nym/pull/837) ([aniampio](https://github.com/aniampio))
- Apply readable ids to elements on Nym Wallet [\#836](https://github.com/nymtech/nym/pull/836) ([tommyv1987](https://github.com/tommyv1987))
- Feature/removal of monitor good nodes [\#833](https://github.com/nymtech/nym/pull/833) ([jstuczyn](https://github.com/jstuczyn))
@@ -552,8 +534,8 @@ The release also include some additional work for distributed key generation in
- Created getters for AccountData [\#787](https://github.com/nymtech/nym/pull/787) ([jstuczyn](https://github.com/jstuczyn))
- Feature/migrate hidden delegations [\#786](https://github.com/nymtech/nym/pull/786) ([neacsu](https://github.com/neacsu))
- Feature/persistent gateway storage [\#784](https://github.com/nymtech/nym/pull/784) ([jstuczyn](https://github.com/jstuczyn))
- Replaced unwrap_or_else with unwrap_or_default [\#780](https://github.com/nymtech/nym/pull/780) ([jstuczyn](https://github.com/jstuczyn))
- Add block_height method to Delegation [\#778](https://github.com/nymtech/nym/pull/778) ([durch](https://github.com/durch))
- Replaced unwrap\_or\_else with unwrap\_or\_default [\#780](https://github.com/nymtech/nym/pull/780) ([jstuczyn](https://github.com/jstuczyn))
- Add block\_height method to Delegation [\#778](https://github.com/nymtech/nym/pull/778) ([durch](https://github.com/durch))
- Make fee helpers public [\#777](https://github.com/nymtech/nym/pull/777) ([durch](https://github.com/durch))
- re-enable bonding [\#776](https://github.com/nymtech/nym/pull/776) ([fmtabbara](https://github.com/fmtabbara))
- Explorer-api: add API resource to show the delegations for each mix node [\#774](https://github.com/nymtech/nym/pull/774) ([mmsinclair](https://github.com/mmsinclair))
@@ -562,14 +544,14 @@ The release also include some additional work for distributed key generation in
- Adding deps for building the Tauri wallet under Ubuntu [\#770](https://github.com/nymtech/nym/pull/770) ([futurechimp](https://github.com/futurechimp))
- remove alert [\#767](https://github.com/nymtech/nym/pull/767) ([fmtabbara](https://github.com/fmtabbara))
- Feature/consumable bandwidth [\#766](https://github.com/nymtech/nym/pull/766) ([neacsu](https://github.com/neacsu))
- Update coconut-rs and use hash_to_scalar from there [\#765](https://github.com/nymtech/nym/pull/765) ([neacsu](https://github.com/neacsu))
- Update coconut-rs and use hash\_to\_scalar from there [\#765](https://github.com/nymtech/nym/pull/765) ([neacsu](https://github.com/neacsu))
- Feature/active sets [\#764](https://github.com/nymtech/nym/pull/764) ([jstuczyn](https://github.com/jstuczyn))
- add app alert banner [\#762](https://github.com/nymtech/nym/pull/762) ([fmtabbara](https://github.com/fmtabbara))
- Updated cosmos-sdk [\#761](https://github.com/nymtech/nym/pull/761) ([jstuczyn](https://github.com/jstuczyn))
- Feature/bond blockstamp [\#760](https://github.com/nymtech/nym/pull/760) ([neacsu](https://github.com/neacsu))
- Feature/revert migration code [\#759](https://github.com/nymtech/nym/pull/759) ([neacsu](https://github.com/neacsu))
- Bump next from 11.1.0 to 11.1.1 in /wallet-web [\#758](https://github.com/nymtech/nym/pull/758) ([dependabot[bot]](https://github.com/apps/dependabot))
- Add block_height in the Delegation structure as well [\#757](https://github.com/nymtech/nym/pull/757) ([neacsu](https://github.com/neacsu))
- Add block\_height in the Delegation structure as well [\#757](https://github.com/nymtech/nym/pull/757) ([neacsu](https://github.com/neacsu))
- Feature/add blockstamp [\#756](https://github.com/nymtech/nym/pull/756) ([neacsu](https://github.com/neacsu))
- NetworkMonitorBuilder - starting the monitor after rocket has launched [\#754](https://github.com/nymtech/nym/pull/754) ([jstuczyn](https://github.com/jstuczyn))
- Enabled validators api argument [\#753](https://github.com/nymtech/nym/pull/753) ([jstuczyn](https://github.com/jstuczyn))
@@ -581,7 +563,7 @@ The release also include some additional work for distributed key generation in
- Feature/more reliable uptime calculation [\#747](https://github.com/nymtech/nym/pull/747) ([jstuczyn](https://github.com/jstuczyn))
- Update template toml key [\#746](https://github.com/nymtech/nym/pull/746) ([neacsu](https://github.com/neacsu))
- Feature/cred after handshake [\#745](https://github.com/nymtech/nym/pull/745) ([neacsu](https://github.com/neacsu))
- Reinstate the POST method blind_sign [\#744](https://github.com/nymtech/nym/pull/744) ([neacsu](https://github.com/neacsu))
- Reinstate the POST method blind\_sign [\#744](https://github.com/nymtech/nym/pull/744) ([neacsu](https://github.com/neacsu))
- explorer-api: add pending field to port check response [\#742](https://github.com/nymtech/nym/pull/742) ([mmsinclair](https://github.com/mmsinclair))
- Feature/use delegation rates [\#741](https://github.com/nymtech/nym/pull/741) ([neacsu](https://github.com/neacsu))
- Feature/copy to clipboard [\#740](https://github.com/nymtech/nym/pull/740) ([fmtabbara](https://github.com/fmtabbara))
@@ -618,4 +600,6 @@ The release also include some additional work for distributed key generation in
- Hang coconut issuance off the validator-api [\#679](https://github.com/nymtech/nym/pull/679) ([durch](https://github.com/durch))
- Update hmac and blake3 [\#673](https://github.com/nymtech/nym/pull/673) ([durch](https://github.com/durch))
\* _This Changelog was automatically generated by [github_changelog_generator](https://github.com/github-changelog-generator/github-changelog-generator)_
\* *This Changelog was automatically generated by [github_changelog_generator](https://github.com/github-changelog-generator/github-changelog-generator)*
Generated
+114 -314
View File
@@ -23,16 +23,6 @@ dependencies = [
"generic-array 0.14.5",
]
[[package]]
name = "aead"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c192eb8f11fc081b0fe4259ba5af04217d4e0faddd02417310a927911abd7c8"
dependencies = [
"crypto-common",
"generic-array 0.14.5",
]
[[package]]
name = "aes"
version = "0.7.5"
@@ -63,7 +53,7 @@ version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df5f85a83a7d8b0442b6aa7b504b8212c1733da07b98aae43d4bc21b2cb3cdf6"
dependencies = [
"aead 0.4.3",
"aead",
"aes 0.7.5",
"cipher 0.3.0",
"ctr 0.8.0",
@@ -91,12 +81,6 @@ dependencies = [
"memchr",
]
[[package]]
name = "anes"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299"
[[package]]
name = "ansi_term"
version = "0.12.1"
@@ -426,13 +410,6 @@ dependencies = [
"serde",
]
[[package]]
name = "build-information"
version = "0.1.0"
dependencies = [
"vergen 7.2.1",
]
[[package]]
name = "bumpalo"
version = "3.9.1"
@@ -466,12 +443,6 @@ dependencies = [
"rustc_version 0.4.0",
]
[[package]]
name = "cast"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
[[package]]
name = "cc"
version = "1.0.73"
@@ -503,30 +474,6 @@ dependencies = [
"keystream",
]
[[package]]
name = "chacha20"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7fc89c7c5b9e7a02dfe45cd2367bae382f9ed31c61ca8debe5f827c420a2f08"
dependencies = [
"cfg-if 1.0.0",
"cipher 0.4.3",
"cpufeatures",
]
[[package]]
name = "chacha20poly1305"
version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35"
dependencies = [
"aead 0.5.1",
"chacha20",
"cipher 0.4.3",
"poly1305",
"zeroize",
]
[[package]]
name = "chrono"
version = "0.4.19"
@@ -541,33 +488,6 @@ dependencies = [
"winapi",
]
[[package]]
name = "ciborium"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0c137568cc60b904a7724001b35ce2630fd00d5d84805fbb608ab89509d788f"
dependencies = [
"ciborium-io",
"ciborium-ll",
"serde",
]
[[package]]
name = "ciborium-io"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "346de753af073cc87b52b2083a506b38ac176a44cfb05497b622e27be899b369"
[[package]]
name = "ciborium-ll"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "213030a2b5a4e0c0892b6652260cf6ccac84827b83a85a534e178e3906c4cf1b"
dependencies = [
"ciborium-io",
"half",
]
[[package]]
name = "cipher"
version = "0.3.0"
@@ -585,7 +505,6 @@ checksum = "d1873270f8f7942c191139cb8a40fd228da6c3fd2fc376d7e92d47aa14aeb59e"
dependencies = [
"crypto-common",
"inout",
"zeroize",
]
[[package]]
@@ -605,51 +524,41 @@ version = "3.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "190814073e85d238f31ff738fcb0bf6910cedeb73376c87cd69291028966fd83"
dependencies = [
"atty",
"bitflags",
"clap_lex 0.2.4",
"clap_derive",
"clap_lex",
"indexmap",
"once_cell",
"strsim",
"termcolor",
"textwrap 0.15.0",
]
[[package]]
name = "clap"
version = "4.0.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2148adefda54e14492fb9bddcc600b4344c5d1a3123bd666dcb939c6f0e0e57e"
dependencies = [
"atty",
"bitflags",
"clap_derive",
"clap_lex 0.3.0",
"once_cell",
"strsim",
"termcolor",
]
[[package]]
name = "clap_complete"
version = "4.0.7"
version = "3.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10861370d2ba66b0f5989f83ebf35db6421713fd92351790e7fdd6c36774c56b"
checksum = "e4179da71abd56c26b54dd0c248cc081c1f43b0a1a7e8448e28e57a29baa993d"
dependencies = [
"clap 4.0.26",
"clap 3.2.8",
]
[[package]]
name = "clap_complete_fig"
version = "4.0.2"
version = "3.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46b30e010e669cd021e5004f3be26cff6b7c08d2a8a0d65b48d43a8cc0efd6c3"
checksum = "ed37b4c0c1214673eba6ad8ea31666626bf72be98ffb323067d973c48b4964b9"
dependencies = [
"clap 4.0.26",
"clap 3.2.8",
"clap_complete",
]
[[package]]
name = "clap_derive"
version = "4.0.21"
version = "3.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0177313f9f02afc995627906bbd8967e2be069f5261954222dac78290c2b9014"
checksum = "759bf187376e1afa7b85b959e6a664a3e7a95203415dba952ad19139e798f902"
dependencies = [
"heck 0.4.0",
"proc-macro-error",
@@ -667,15 +576,6 @@ dependencies = [
"os_str_bytes",
]
[[package]]
name = "clap_lex"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d4198f73e42b4936b35b5bb248d81d2b595ecb170da0bac7655c54eedfa8da8"
dependencies = [
"os_str_bytes",
]
[[package]]
name = "client-connections"
version = "0.1.0"
@@ -686,7 +586,7 @@ dependencies = [
[[package]]
name = "client-core"
version = "1.1.4"
version = "1.1.3"
dependencies = [
"async-trait",
"client-connections",
@@ -792,7 +692,7 @@ dependencies = [
name = "completions"
version = "0.1.0"
dependencies = [
"clap 4.0.26",
"clap 3.2.8",
"clap_complete",
"clap_complete_fig",
]
@@ -1031,7 +931,7 @@ version = "0.1.0"
dependencies = [
"bip39",
"cfg-if 0.1.10",
"clap 4.0.26",
"clap 3.2.8",
"coconut-interface",
"completions",
"config",
@@ -1080,9 +980,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1604dafd25fba2fe2d5895a9da139f8dc9b319a5fe5354ca137cbbce4e178d10"
dependencies = [
"atty",
"cast 0.2.7",
"cast",
"clap 2.34.0",
"criterion-plot 0.4.4",
"criterion-plot",
"csv",
"itertools",
"lazy_static",
@@ -1099,49 +999,13 @@ dependencies = [
"walkdir",
]
[[package]]
name = "criterion"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7c76e09c1aae2bc52b3d2f29e13c6572553b30c4aa1b8a49fd70de6412654cb"
dependencies = [
"anes",
"atty",
"cast 0.3.0",
"ciborium",
"clap 3.2.8",
"criterion-plot 0.5.0",
"itertools",
"lazy_static",
"num-traits",
"oorandom",
"plotters",
"rayon",
"regex",
"serde",
"serde_derive",
"serde_json",
"tinytemplate",
"walkdir",
]
[[package]]
name = "criterion-plot"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d00996de9f2f7559f7f4dc286073197f83e92256a59ed395f9aac01fe717da57"
dependencies = [
"cast 0.2.7",
"itertools",
]
[[package]]
name = "criterion-plot"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1"
dependencies = [
"cast 0.3.0",
"cast",
"itertools",
]
@@ -1270,12 +1134,11 @@ dependencies = [
[[package]]
name = "crypto-common"
version = "0.1.6"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
checksum = "57952ca27b5e3606ff4dd79b0020231aaf9d6aa76dc05fd30137538c50bd3ce8"
dependencies = [
"generic-array 0.14.5",
"rand_core 0.6.3",
"typenum",
]
@@ -1603,7 +1466,7 @@ dependencies = [
"bitvec",
"bls12_381 0.6.0",
"bs58",
"criterion 0.3.5",
"criterion",
"ff 0.11.0",
"group 0.11.0",
"lazy_static",
@@ -1791,7 +1654,7 @@ name = "explorer-api"
version = "1.1.1"
dependencies = [
"chrono",
"clap 4.0.26",
"clap 3.2.8",
"contracts-common",
"dotenv",
"humantime-serde",
@@ -1804,9 +1667,6 @@ dependencies = [
"network-defaults",
"okapi",
"pretty_env_logger",
"rand 0.8.5",
"rand_pcg 0.3.1",
"rand_seeder",
"reqwest",
"rocket",
"rocket_cors",
@@ -1838,9 +1698,9 @@ checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
[[package]]
name = "fastrand"
version = "1.8.0"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499"
checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf"
dependencies = [
"instant",
]
@@ -3231,72 +3091,6 @@ dependencies = [
"libc",
]
[[package]]
name = "nym-api"
version = "1.1.4"
dependencies = [
"anyhow",
"async-trait",
"bip39",
"bs58",
"build-information",
"cfg-if 1.0.0",
"clap 4.0.26",
"coconut-bandwidth-contract-common",
"coconut-dkg-common",
"coconut-interface",
"config",
"console-subscriber",
"contracts-common",
"cosmwasm-std",
"credential-storage",
"credentials",
"crypto",
"cw-utils",
"cw3",
"dirs",
"dkg",
"dotenv",
"futures",
"gateway-client",
"getset",
"humantime-serde",
"inclusion-probability",
"lazy_static",
"log",
"logging",
"mixnet-contract-common",
"multisig-contract-common",
"nym-api-requests",
"nymcoconut",
"nymsphinx",
"okapi",
"pemstore",
"pin-project",
"pretty_env_logger",
"rand 0.7.3",
"rand 0.8.5",
"reqwest",
"rocket",
"rocket_cors",
"rocket_okapi",
"schemars",
"serde",
"serde_json",
"sqlx 0.6.2",
"tap",
"task",
"thiserror",
"time 0.3.17",
"tokio",
"tokio-stream",
"topology",
"ts-rs",
"url",
"validator-client",
"version-checker",
]
[[package]]
name = "nym-api-requests"
version = "0.1.0"
@@ -3329,13 +3123,13 @@ dependencies = [
[[package]]
name = "nym-cli"
version = "1.1.4"
version = "1.1.3"
dependencies = [
"anyhow",
"base64",
"bip39",
"bs58",
"clap 4.0.26",
"clap 3.2.8",
"clap_complete",
"clap_complete_fig",
"dotenv",
@@ -3359,7 +3153,7 @@ dependencies = [
"bip39",
"bs58",
"cfg-if 1.0.0",
"clap 4.0.26",
"clap 3.2.8",
"comfy-table",
"cosmrs",
"cosmwasm-std",
@@ -3383,10 +3177,9 @@ dependencies = [
[[package]]
name = "nym-client"
version = "1.1.4"
version = "1.1.3"
dependencies = [
"build-information",
"clap 4.0.26",
"clap 3.2.8",
"client-connections",
"client-core",
"coconut-interface",
@@ -3399,7 +3192,6 @@ dependencies = [
"futures",
"gateway-client",
"gateway-requests",
"lazy_static",
"log",
"logging",
"network-defaults",
@@ -3417,20 +3209,20 @@ dependencies = [
"topology",
"url",
"validator-client",
"vergen 5.1.17",
"version-checker",
"websocket-requests",
]
[[package]]
name = "nym-gateway"
version = "1.1.4"
version = "1.1.3"
dependencies = [
"anyhow",
"async-trait",
"bip39",
"bs58",
"build-information",
"clap 4.0.26",
"clap 3.2.8",
"coconut-interface",
"colored",
"completions",
@@ -3443,7 +3235,6 @@ dependencies = [
"futures",
"gateway-requests",
"humantime-serde",
"lazy_static",
"log",
"logging",
"mixnet-client",
@@ -3466,17 +3257,17 @@ dependencies = [
"tokio-util 0.7.3",
"url",
"validator-client",
"vergen 5.1.17",
"version-checker",
]
[[package]]
name = "nym-mixnode"
version = "1.1.4"
version = "1.1.3"
dependencies = [
"anyhow",
"bs58",
"build-information",
"clap 4.0.26",
"clap 3.2.8",
"colored",
"completions",
"config",
@@ -3508,15 +3299,16 @@ dependencies = [
"topology",
"url",
"validator-client",
"vergen 5.1.17",
"version-checker",
]
[[package]]
name = "nym-network-requester"
version = "1.1.4"
version = "1.1.3"
dependencies = [
"async-trait",
"clap 4.0.26",
"clap 3.2.8",
"client-connections",
"completions",
"dirs",
@@ -3545,7 +3337,7 @@ dependencies = [
[[package]]
name = "nym-network-statistics"
version = "1.1.4"
version = "1.1.3"
dependencies = [
"dirs",
"log",
@@ -3559,28 +3351,11 @@ dependencies = [
"tokio",
]
[[package]]
name = "nym-outfox"
version = "0.1.0"
dependencies = [
"blake3",
"chacha20",
"chacha20poly1305",
"criterion 0.4.0",
"curve25519-dalek",
"fastrand",
"getrandom 0.2.6",
"rayon",
"thiserror",
"zeroize",
]
[[package]]
name = "nym-socks5-client"
version = "1.1.4"
version = "1.1.3"
dependencies = [
"build-information",
"clap 4.0.26",
"clap 3.2.8",
"client-connections",
"client-core",
"coconut-interface",
@@ -3593,7 +3368,6 @@ dependencies = [
"futures",
"gateway-client",
"gateway-requests",
"lazy_static",
"log",
"logging",
"network-defaults",
@@ -3614,6 +3388,7 @@ dependencies = [
"topology",
"url",
"validator-client",
"vergen 5.1.17",
"version-checker",
]
@@ -3643,6 +3418,70 @@ dependencies = [
"vesting-contract-common",
]
[[package]]
name = "nym-validator-api"
version = "1.1.3"
dependencies = [
"anyhow",
"async-trait",
"bs58",
"cfg-if 1.0.0",
"clap 3.2.8",
"coconut-bandwidth-contract-common",
"coconut-dkg-common",
"coconut-interface",
"config",
"console-subscriber",
"contracts-common",
"cosmwasm-std",
"credential-storage",
"credentials",
"crypto",
"cw-utils",
"cw3",
"dirs",
"dkg",
"dotenv",
"futures",
"gateway-client",
"getset",
"humantime-serde",
"inclusion-probability",
"log",
"logging",
"mixnet-contract-common",
"multisig-contract-common",
"nym-api-requests",
"nymcoconut",
"nymsphinx",
"okapi",
"pemstore",
"pin-project",
"pretty_env_logger",
"rand 0.7.3",
"rand 0.8.5",
"reqwest",
"rocket",
"rocket_cors",
"rocket_okapi",
"schemars",
"serde",
"serde_json",
"sqlx 0.6.2",
"tap",
"task",
"thiserror",
"time 0.3.17",
"tokio",
"tokio-stream",
"topology",
"ts-rs",
"url",
"validator-client",
"vergen 7.2.1",
"version-checker",
]
[[package]]
name = "nym-wallet-types"
version = "1.0.0"
@@ -3670,7 +3509,7 @@ dependencies = [
"bincode",
"bls12_381 0.6.0",
"bs58",
"criterion 0.3.5",
"criterion",
"digest 0.9.0",
"dkg",
"doc-comment",
@@ -4182,17 +4021,6 @@ dependencies = [
"plotters-backend",
]
[[package]]
name = "poly1305"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf"
dependencies = [
"cpufeatures",
"opaque-debug 0.3.0",
"universal-hash 0.5.0",
]
[[package]]
name = "polyval"
version = "0.5.3"
@@ -4202,7 +4030,7 @@ dependencies = [
"cfg-if 1.0.0",
"cpufeatures",
"opaque-debug 0.3.0",
"universal-hash 0.4.1",
"universal-hash",
]
[[package]]
@@ -4424,7 +4252,7 @@ dependencies = [
"rand_isaac",
"rand_jitter",
"rand_os",
"rand_pcg 0.1.2",
"rand_pcg",
"rand_xorshift",
"winapi",
]
@@ -4588,24 +4416,6 @@ dependencies = [
"rand_core 0.4.2",
]
[[package]]
name = "rand_pcg"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59cad018caf63deb318e5a4586d99a24424a364f40f1e5778c29aca23f4fc73e"
dependencies = [
"rand_core 0.6.3",
]
[[package]]
name = "rand_seeder"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf2890aaef0aa82719a50e808de264f9484b74b442e1a3a0e5ee38243ac40bdb"
dependencies = [
"rand_core 0.6.3",
]
[[package]]
name = "rand_xorshift"
version = "0.1.1"
@@ -6578,16 +6388,6 @@ dependencies = [
"subtle 2.4.1",
]
[[package]]
name = "universal-hash"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d3160b73c9a19f7e2939a2fdad446c57c1bbbbf4d919d3213ff1267a580d8b5"
dependencies = [
"crypto-common",
"subtle 2.4.1",
]
[[package]]
name = "untrusted"
version = "0.7.1"
@@ -7111,9 +6911,9 @@ checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec"
[[package]]
name = "zeroize"
version = "1.5.7"
version = "1.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c394b5bd0c6f669e7275d9c20aa90ae064cb22e75a1cad54e1b34088034b149f"
checksum = "d68d9dcec5f9b43a30d38c49f91dfedfaac384cb8f085faca366c26207dd1619"
dependencies = [
"zeroize_derive",
]
-2
View File
@@ -30,7 +30,6 @@ members = [
"common/coconut-interface",
"common/commands",
"common/config",
"common/build-information",
"common/cosmwasm-smart-contracts/coconut-bandwidth-contract",
"common/cosmwasm-smart-contracts/coconut-dkg",
"common/cosmwasm-smart-contracts/contracts-common",
@@ -77,7 +76,6 @@ members = [
"service-providers/network-statistics",
"nym-api",
"nym-api/nym-api-requests",
"nym-outfox",
"tools/nym-cli",
"tools/ts-rs-cli"
]
+1 -2
View File
@@ -1,9 +1,8 @@
[package]
name = "client-core"
version = "1.1.4"
version = "1.1.3"
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"]
edition = "2021"
rust-version = "1.66"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@@ -230,7 +230,7 @@ where
mixnet_message_sender: MixnetMessageSender,
ack_sender: AcknowledgementSender,
shutdown: TaskClient,
) -> Result<GatewayClient, ClientCoreError> {
) -> Result<GatewayClient, ClientCoreError<B>> {
let gateway_id = self.gateway_config.gateway_id.clone();
if gateway_id.is_empty() {
return Err(ClientCoreError::GatewayIdUnknown);
@@ -285,7 +285,7 @@ where
refresh_rate: Duration,
topology_accessor: TopologyAccessor,
shutdown: TaskClient,
) -> Result<(), ClientCoreError> {
) -> Result<(), ClientCoreError<B>> {
let topology_refresher_config = TopologyRefresherConfig::new(
nym_api_urls,
refresh_rate,
@@ -328,17 +328,12 @@ where
async fn setup_persistent_reply_storage(
backend: B,
shutdown: TaskClient,
) -> Result<CombinedReplyStorage, ClientCoreError>
where
<B as ReplyStorageBackend>::StorageError: Sync + Send,
{
) -> Result<CombinedReplyStorage, ClientCoreError<B>> {
let persistent_storage = PersistentReplyStorage::new(backend);
let mem_store = persistent_storage
.load_state_from_backend()
.await
.map_err(|err| ClientCoreError::SurbStorageError {
source: Box::new(err),
})?;
.map_err(|err| ClientCoreError::SurbStorageError { source: err })?;
let store_clone = mem_store.clone();
spawn_future(async move {
@@ -350,10 +345,7 @@ where
Ok(mem_store)
}
pub async fn start_base(mut self) -> Result<BaseClient, ClientCoreError>
where
<B as ReplyStorageBackend>::StorageError: Sync + Send,
{
pub async fn start_base(mut self) -> Result<BaseClient, ClientCoreError<B>> {
info!("Starting nym client");
// channels for inter-component communication
// TODO: make the channels be internally created by the relevant components
@@ -379,7 +371,7 @@ where
// channels responsible for dealing with reply-related fun
let (reply_controller_sender, reply_controller_receiver) =
reply_controller::requests::new_control_channels();
reply_controller::new_control_channels();
let self_address = self.as_mix_recipient();
@@ -445,7 +437,7 @@ where
input_receiver,
sphinx_message_sender.clone(),
reply_storage,
reply_controller_sender.clone(),
reply_controller_sender,
reply_controller_receiver,
shared_lane_queue_lengths.clone(),
client_connection_rx,
@@ -479,7 +471,6 @@ where
received_buffer_request_sender,
},
},
reply_controller_sender,
task_manager,
})
}
@@ -489,8 +480,5 @@ pub struct BaseClient {
pub client_input: ClientInputStatus,
pub client_output: ClientOutputStatus,
// it feels very wrong to put this channel here, but I can't think of any other way of passing it to the native client
pub reply_controller_sender: ReplyControllerSender,
pub task_manager: TaskManager,
}
@@ -14,15 +14,13 @@ use time::OffsetDateTime;
async fn setup_fresh_backend<P: AsRef<Path>>(
db_path: P,
debug_config: &DebugConfig,
) -> Result<fs_backend::Backend, ClientCoreError> {
) -> Result<fs_backend::Backend, ClientCoreError<fs_backend::Backend>> {
info!("creating fresh surb database");
let mut storage_backend = match fs_backend::Backend::init(db_path).await {
Ok(backend) => backend,
Err(err) => {
error!("failed to setup persistent storage backend for our reply needs: {err}");
return Err(ClientCoreError::SurbStorageError {
source: Box::new(err),
});
return Err(ClientCoreError::SurbStorageError { source: err });
}
};
@@ -36,9 +34,7 @@ async fn setup_fresh_backend<P: AsRef<Path>>(
storage_backend
.init_fresh(&mem_store)
.await
.map_err(|err| ClientCoreError::SurbStorageError {
source: Box::new(err),
})?;
.map_err(|err| ClientCoreError::SurbStorageError { source: err })?;
Ok(storage_backend)
}
@@ -67,7 +63,7 @@ fn archive_corrupted_database<P: AsRef<Path>>(db_path: P) -> io::Result<()> {
pub async fn setup_fs_reply_surb_backend<P: AsRef<Path>>(
db_path: P,
debug_config: &DebugConfig,
) -> Result<fs_backend::Backend, ClientCoreError> {
) -> Result<fs_backend::Backend, ClientCoreError<fs_backend::Backend>> {
// if the database file doesnt exist, initialise fresh storage, otherwise attempt to load the existing one
let db_path = db_path.as_ref();
if db_path.exists() {
@@ -1,14 +0,0 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
#[cfg(not(target_arch = "wasm32"))]
mod non_wasm;
#[cfg(target_arch = "wasm32")]
mod wasm;
#[cfg(not(target_arch = "wasm32"))]
pub use non_wasm::*;
#[cfg(target_arch = "wasm32")]
pub use wasm::*;
@@ -1,13 +0,0 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
pub use tokio::time::*;
pub type IntervalStream = tokio_stream::wrappers::IntervalStream;
pub(crate) fn get_time_now() -> Instant {
Instant::now()
}
pub(crate) fn new_interval_stream(polling_rate: Duration) -> IntervalStream {
tokio_stream::wrappers::IntervalStream::new(tokio::time::interval(polling_rate))
}
@@ -1,16 +0,0 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use std::time::Duration;
use wasm_timer;
pub use wasm_timer::*;
pub type IntervalStream = gloo_timers::future::IntervalStream;
pub(crate) fn get_time_now() -> Instant {
wasm_timer::Instant::now()
}
pub(crate) fn new_interval_stream(polling_rate: Duration) -> IntervalStream {
gloo_timers::future::IntervalStream::new(polling_rate.as_millis() as u32)
}
-2
View File
@@ -3,7 +3,6 @@
pub mod base_client;
pub mod cover_traffic_stream;
pub(crate) mod helpers;
pub mod inbound_messages;
pub mod key_manager;
pub mod mix_traffic;
@@ -11,4 +10,3 @@ pub mod real_messages_control;
pub mod received_buffer;
pub mod replies;
pub mod topology_control;
pub(crate) mod transmission_buffer;
@@ -20,7 +20,6 @@ use nymsphinx::params::{PacketSize, DEFAULT_NUM_MIX_HOPS};
use nymsphinx::preparer::{MessagePreparer, PreparedFragment};
use nymsphinx::Delay;
use rand::{CryptoRng, Rng};
use std::collections::HashMap;
use std::sync::Arc;
use std::time::Duration;
use thiserror::Error;
@@ -279,7 +278,7 @@ where
reply_surb: ReplySurb,
amount: u32,
) -> Result<(), SurbWrappedPreparationError> {
debug!("requesting {amount} reply SURBs from {from}");
debug!("requesting {amount} reply SURBs from {from:?}");
let surbs_request =
ReplyMessage::new_surb_request_message(self.config.sender_address, amount);
@@ -295,11 +294,19 @@ where
)))
}
pub(crate) async fn send_retransmission_reply_chunks(
// the only difference between this method and `try_send_reply_chunks` is that
// here we are not creating acks as acks are already in memory waiting to get cleared.
// we are only updating their existing delays
pub(crate) async fn try_send_retransmission_reply_chunks(
&mut self,
prepared_fragments: Vec<PreparedFragment>,
fragments: Vec<Fragment>,
reply_surbs: Vec<ReplySurb>,
lane: TransmissionLane,
) {
) -> Result<(), SurbWrappedPreparationError> {
let prepared_fragments = self
.prepare_reply_chunks_for_sending(fragments.clone(), reply_surbs)
.await?;
let mut real_messages = Vec::with_capacity(prepared_fragments.len());
for prepared in prepared_fragments {
@@ -308,58 +315,33 @@ where
}
self.forward_messages(real_messages, lane).await;
Ok(())
}
pub(crate) async fn try_send_reply_chunks_on_lane(
pub(crate) async fn try_send_reply_chunks(
&mut self,
target: AnonymousSenderTag,
fragments: Vec<Fragment>,
reply_surbs: Vec<ReplySurb>,
lane: TransmissionLane,
) -> Result<(), SurbWrappedPreparationError> {
// TODO: technically this is performing an unnecessary cloning, but in the grand scheme of things
// is it really that bad?
self.try_send_reply_chunks(
target,
fragments.into_iter().map(|f| (lane, f)).collect(),
reply_surbs,
)
.await
}
pub(crate) async fn try_send_reply_chunks(
&mut self,
target: AnonymousSenderTag,
fragments: Vec<(TransmissionLane, Fragment)>,
reply_surbs: Vec<ReplySurb>,
) -> Result<(), SurbWrappedPreparationError> {
let prepared_fragments = self
.prepare_reply_chunks_for_sending(
fragments.iter().map(|(_, f)| f.clone()).collect(),
reply_surbs,
)
.prepare_reply_chunks_for_sending(fragments.clone(), reply_surbs)
.await?;
let mut pending_acks = Vec::with_capacity(fragments.len());
let mut to_forward: HashMap<_, Vec<_>> = HashMap::new();
let mut real_messages = Vec::with_capacity(fragments.len());
for (raw, prepared) in fragments.into_iter().zip(prepared_fragments.into_iter()) {
let lane = raw.0;
let fragment = raw.1;
let real_message = RealMessage::new(prepared.mix_packet, prepared.fragment_identifier);
let delay = prepared.total_delay;
let pending_ack = PendingAcknowledgement::new_anonymous(fragment, delay, target, false);
let pending_ack = PendingAcknowledgement::new_anonymous(raw, delay, target, false);
let entry = to_forward.entry(lane).or_default();
entry.push(real_message);
real_messages.push(real_message);
pending_acks.push(pending_ack);
}
for (lane, real_messages) in to_forward {
self.forward_messages(real_messages, lane).await;
}
self.forward_messages(real_messages, lane).await;
self.insert_pending_acks(pending_acks);
Ok(())
}
@@ -485,7 +467,7 @@ where
Ok(prepared_fragment)
}
pub(crate) async fn prepare_reply_chunks_for_sending(
async fn prepare_reply_chunks_for_sending(
&mut self,
fragments: Vec<Fragment>,
reply_surbs: Vec<ReplySurb>,
@@ -1,11 +1,9 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use self::sending_delay_controller::SendingDelayController;
use crate::client::mix_traffic::BatchMixMessageSender;
use crate::client::real_messages_control::acknowledgement_control::SentPacketNotificationSender;
use crate::client::topology_control::TopologyAccessor;
use crate::client::transmission_buffer::TransmissionBuffer;
use client_connections::{
ConnectionCommand, ConnectionCommandReceiver, ConnectionId, LaneQueueLengths, TransmissionLane,
};
@@ -31,7 +29,22 @@ use tokio::time;
#[cfg(target_arch = "wasm32")]
use wasm_timer;
use self::{
sending_delay_controller::SendingDelayController, transmission_buffer::TransmissionBuffer,
};
mod sending_delay_controller;
mod transmission_buffer;
#[cfg(not(target_arch = "wasm32"))]
fn get_time_now() -> time::Instant {
time::Instant::now()
}
#[cfg(target_arch = "wasm32")]
fn get_time_now() -> wasm_timer::Instant {
wasm_timer::Instant::now()
}
/// Configurable parameters of the `OutQueueControl`
pub(crate) struct Config {
@@ -122,7 +135,7 @@ where
/// Buffer containing all incoming real messages keyed by transmission lane, that we will send
/// out to the mixnet.
transmission_buffer: TransmissionBuffer<RealMessage>,
transmission_buffer: TransmissionBuffer,
/// Incoming channel for being notified of closed connections, so that we can close lanes
/// corresponding to connections. To avoid sending traffic unnecessary
@@ -149,10 +162,6 @@ impl From<PreparedFragment> for RealMessage {
}
impl RealMessage {
pub(crate) fn packet_size(&self) -> usize {
self.mix_packet.sphinx_packet().len()
}
pub(crate) fn new(mix_packet: MixPacket, fragment_id: FragmentIdentifier) -> Self {
RealMessage {
mix_packet,
@@ -198,7 +207,7 @@ where
real_receiver,
rng,
topology_access,
transmission_buffer: TransmissionBuffer::new(),
transmission_buffer: Default::default(),
client_connection_rx,
lane_queue_lengths,
}
@@ -319,9 +328,7 @@ where
fn pop_next_message(&mut self) -> Option<RealMessage> {
// Pop the next message from the transmission buffer
let (lane, real_next) = self
.transmission_buffer
.pop_next_message_at_random(&mut self.rng)?;
let (lane, real_next) = self.transmission_buffer.pop_next_message_at_random()?;
// Update the published queue length
let lane_length = self.transmission_buffer.lane_length(&lane);
@@ -1,9 +1,14 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::client::helpers::{get_time_now, Instant};
use super::get_time_now;
use std::time::Duration;
#[cfg(not(target_arch = "wasm32"))]
use tokio::time;
#[cfg(target_arch = "wasm32")]
use wasm_timer;
// The minimum time between increasing the average delay between packets. If we hit the ceiling in
// the available buffer space we want to take somewhat swift action, but we still need to give a
// short time to give the channel a chance reduce pressure.
@@ -34,11 +39,19 @@ pub(crate) struct SendingDelayController {
lower_bound: u32,
/// To make sure we don't change the multiplier to fast, we limit a change to some duration
time_when_changed: Instant,
#[cfg(not(target_arch = "wasm32"))]
time_when_changed: time::Instant,
#[cfg(target_arch = "wasm32")]
time_when_changed: wasm_timer::Instant,
/// If we have a long enough time without any backpressure detected we try reducing the sending
/// delay multiplier
time_when_backpressure_detected: Instant,
#[cfg(not(target_arch = "wasm32"))]
time_when_backpressure_detected: time::Instant,
#[cfg(target_arch = "wasm32")]
time_when_backpressure_detected: wasm_timer::Instant,
}
impl Default for SendingDelayController {
@@ -1,57 +1,38 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::client::helpers::{get_time_now, Instant};
use crate::client::real_messages_control::real_traffic_stream::RealMessage;
use client_connections::TransmissionLane;
use nymsphinx::chunking::fragment::Fragment;
use rand::{seq::SliceRandom, Rng};
use std::{
collections::{HashMap, HashSet, VecDeque},
time::Duration,
};
#[cfg(not(target_arch = "wasm32"))]
use tokio::time;
#[cfg(target_arch = "wasm32")]
use wasm_timer;
use super::{get_time_now, RealMessage};
// The number of lanes included in the oldest set. Used when we need to prioritize traffic.
const OLDEST_LANE_SET_SIZE: usize = 4;
// As a way of prune connections we also check for timeouts.
const MSG_CONSIDERED_STALE_AFTER_SECS: u64 = 10 * 60;
pub(crate) trait SizedData {
fn data_size(&self) -> usize;
}
impl SizedData for RealMessage {
fn data_size(&self) -> usize {
self.packet_size()
}
}
impl SizedData for Fragment {
fn data_size(&self) -> usize {
// note that raw `Fragment` is smaller than sphinx packet payload
// as it doesn't include surb-ack or the [shared] key materials
self.payload_size()
}
}
#[derive(Default)]
pub(crate) struct TransmissionBuffer<T> {
buffer: HashMap<TransmissionLane, LaneBufferEntry<T>>,
pub(crate) struct TransmissionBuffer {
buffer: HashMap<TransmissionLane, LaneBufferEntry>,
}
impl<T> TransmissionBuffer<T> {
pub(crate) fn new() -> Self {
TransmissionBuffer {
buffer: HashMap::new(),
}
}
impl TransmissionBuffer {
#[allow(unused)]
pub(crate) fn is_empty(&self) -> bool {
self.buffer.is_empty()
}
pub(crate) fn remove(&mut self, lane: &TransmissionLane) -> Option<LaneBufferEntry<T>> {
pub(crate) fn remove(&mut self, lane: &TransmissionLane) -> Option<LaneBufferEntry> {
self.buffer.remove(lane)
}
@@ -76,22 +57,20 @@ impl<T> TransmissionBuffer<T> {
.collect()
}
#[cfg(not(target_arch = "wasm32"))]
pub(crate) fn total_size(&self) -> usize {
self.buffer.values().map(LaneBufferEntry::len).sum()
}
#[cfg(not(target_arch = "wasm32"))]
pub(crate) fn total_size_in_bytes(&self) -> usize
where
T: SizedData,
{
pub(crate) fn total_size_in_bytes(&self) -> usize {
self.buffer
.values()
.map(|lane_buffer_entry| {
lane_buffer_entry
.items
.real_messages
.iter()
.map(|item| item.data_size())
.map(|real_message| real_message.mix_packet.sphinx_packet().len())
.sum::<usize>()
})
.sum()
@@ -113,51 +92,42 @@ impl<T> TransmissionBuffer<T> {
.collect()
}
pub(crate) fn store<I: IntoIterator<Item = T>>(&mut self, lane: &TransmissionLane, items: I) {
pub(crate) fn store(&mut self, lane: &TransmissionLane, real_messages: Vec<RealMessage>) {
if let Some(lane_buffer_entry) = self.buffer.get_mut(lane) {
lane_buffer_entry.extend(items);
lane_buffer_entry.append(real_messages);
} else {
self.buffer
.insert(*lane, LaneBufferEntry::new(items.into_iter().collect()));
.insert(*lane, LaneBufferEntry::new(real_messages));
}
}
pub(crate) fn store_multiple(&mut self, items: Vec<(TransmissionLane, T)>) {
for (lane, item) in items {
self.buffer
.entry(lane)
.or_insert_with(LaneBufferEntry::new_empty)
.push_item(item)
}
}
fn pick_random_lane<R: Rng + ?Sized>(&self, rng: &mut R) -> Option<&TransmissionLane> {
fn pick_random_lane(&self) -> Option<&TransmissionLane> {
let lanes: Vec<&TransmissionLane> = self.buffer.keys().collect();
lanes.choose(rng).copied()
lanes.choose(&mut rand::thread_rng()).copied()
}
fn pick_random_small_lane<R: Rng + ?Sized>(&self, rng: &mut R) -> Option<&TransmissionLane> {
fn pick_random_small_lane(&self) -> Option<&TransmissionLane> {
let lanes: Vec<&TransmissionLane> = self
.buffer
.iter()
.filter(|(_, v)| v.is_small())
.map(|(k, _)| k)
.collect();
lanes.choose(rng).copied()
lanes.choose(&mut rand::thread_rng()).copied()
}
// 2/3 chance to pick from the old lanes
fn pick_random_old_lane<R: Rng + ?Sized>(&self, rng: &mut R) -> Option<TransmissionLane> {
fn pick_random_old_lane(&self) -> Option<TransmissionLane> {
let rand = &mut rand::thread_rng();
if rand.gen_ratio(2, 3) {
let lanes = self.get_oldest_set();
lanes.choose(rand).copied()
} else {
self.pick_random_lane(rng).copied()
self.pick_random_lane().copied()
}
}
fn pop_front_from_lane(&mut self, lane: &TransmissionLane) -> Option<T> {
fn pop_front_from_lane(&mut self, lane: &TransmissionLane) -> Option<RealMessage> {
let real_msgs_queued = self.buffer.get_mut(lane)?;
let real_next = real_msgs_queued.pop_front()?;
real_msgs_queued.messages_transmitted += 1;
@@ -167,48 +137,19 @@ impl<T> TransmissionBuffer<T> {
Some(real_next)
}
pub(crate) fn pop_at_most_n_next_messages_at_random(
&mut self,
n: usize,
) -> Option<Vec<(TransmissionLane, T)>> {
// let start = Instant::now();
if self.buffer.is_empty() {
return None;
}
let rng = &mut rand::thread_rng();
let mut items = Vec::with_capacity(n);
while items.len() < n {
let Some(next) = self.pop_next_message_at_random(rng) else {
break
};
items.push(next)
}
// todo!("time time taken");
Some(items)
}
pub(crate) fn pop_next_message_at_random<R: Rng + ?Sized>(
&mut self,
// turns out the caller always have access to some rng, so no point in instantiating new one
rng: &mut R,
) -> Option<(TransmissionLane, T)> {
pub(crate) fn pop_next_message_at_random(&mut self) -> Option<(TransmissionLane, RealMessage)> {
if self.buffer.is_empty() {
return None;
}
// Very basic heuristic where we prioritize according to small lanes first, the older lanes
// to try to finish lanes when possible, then the rest.
let lane = if let Some(small_lane) = self.pick_random_small_lane(rng) {
let lane = if let Some(small_lane) = self.pick_random_small_lane() {
*small_lane
} else if let Some(old_lane) = self.pick_random_old_lane(rng) {
} else if let Some(old_lane) = self.pick_random_old_lane() {
old_lane
} else {
*self.pick_random_lane(rng)?
*self.pick_random_lane()?
};
let msg = self.pop_front_from_lane(&lane)?;
@@ -230,46 +171,35 @@ impl<T> TransmissionBuffer<T> {
}
}
pub(crate) struct LaneBufferEntry<T> {
pub items: VecDeque<T>,
pub(crate) struct LaneBufferEntry {
pub real_messages: VecDeque<RealMessage>,
pub messages_transmitted: usize,
pub time_for_last_activity: Instant,
#[cfg(not(target_arch = "wasm32"))]
pub time_for_last_activity: time::Instant,
#[cfg(target_arch = "wasm32")]
pub time_for_last_activity: wasm_timer::Instant,
}
impl<T> LaneBufferEntry<T> {
fn new_empty() -> Self {
impl LaneBufferEntry {
fn new(real_messages: Vec<RealMessage>) -> Self {
LaneBufferEntry {
items: VecDeque::new(),
real_messages: real_messages.into(),
messages_transmitted: 0,
time_for_last_activity: get_time_now(),
}
}
fn new(items: VecDeque<T>) -> Self {
LaneBufferEntry {
items,
messages_transmitted: 0,
time_for_last_activity: get_time_now(),
}
}
fn push_item(&mut self, item: T) {
self.items.push_back(item);
// I'm not updating time here on purpose. This method is called just after `new_empty`,
// where the time is already set. Furthermore, this method is called there multiple times at once
}
fn extend<I: IntoIterator<Item = T>>(&mut self, items: I) {
self.items.extend(items);
fn append(&mut self, real_messages: Vec<RealMessage>) {
self.real_messages.append(&mut real_messages.into());
self.time_for_last_activity = get_time_now();
}
fn pop_front(&mut self) -> Option<T> {
self.items.pop_front()
fn pop_front(&mut self) -> Option<RealMessage> {
self.real_messages.pop_front()
}
fn is_small(&self) -> bool {
self.items.len() < 100
self.real_messages.len() < 100
}
fn is_stale(&self) -> bool {
@@ -278,10 +208,10 @@ impl<T> LaneBufferEntry<T> {
}
fn len(&self) -> usize {
self.items.len()
self.real_messages.len()
}
fn is_empty(&self) -> bool {
self.items.is_empty()
self.real_messages.is_empty()
}
}
@@ -4,8 +4,8 @@
use crate::client::real_messages_control::acknowledgement_control::PendingAcknowledgement;
use crate::client::real_messages_control::message_handler::{MessageHandler, PreparationError};
use crate::client::replies::reply_storage::CombinedReplyStorage;
use client_connections::{ConnectionId, TransmissionLane};
use futures::channel::oneshot;
use client_connections::TransmissionLane;
use futures::channel::mpsc;
use futures::StreamExt;
use log::{debug, error, info, trace, warn};
use nymsphinx::addressing::clients::Recipient;
@@ -15,16 +15,116 @@ use nymsphinx::chunking::fragment::{Fragment, FragmentIdentifier};
use rand::{CryptoRng, Rng};
use std::cmp::{max, min};
use std::collections::btree_map::Entry;
use std::collections::{BTreeMap, HashMap};
use std::collections::{BTreeMap, HashMap, VecDeque};
use std::sync::{Arc, Weak};
use std::time::Duration;
use time::OffsetDateTime;
use crate::client::helpers::new_interval_stream;
use crate::client::transmission_buffer::TransmissionBuffer;
pub(crate) use requests::{ReplyControllerMessage, ReplyControllerReceiver, ReplyControllerSender};
#[cfg(not(target_arch = "wasm32"))]
type IntervalStream = tokio_stream::wrappers::IntervalStream;
pub mod requests;
#[cfg(target_arch = "wasm32")]
type IntervalStream = gloo_timers::future::IntervalStream;
pub(crate) fn new_control_channels() -> (ReplyControllerSender, ReplyControllerReceiver) {
let (tx, rx) = mpsc::unbounded();
(tx.into(), rx)
}
#[derive(Debug, Clone)]
pub(crate) struct ReplyControllerSender(mpsc::UnboundedSender<ReplyControllerMessage>);
impl From<mpsc::UnboundedSender<ReplyControllerMessage>> for ReplyControllerSender {
fn from(inner: mpsc::UnboundedSender<ReplyControllerMessage>) -> Self {
ReplyControllerSender(inner)
}
}
impl ReplyControllerSender {
pub(crate) fn send_retransmission_data(
&self,
recipient: AnonymousSenderTag,
timed_out_ack: Weak<PendingAcknowledgement>,
extra_surb_request: bool,
) {
self.0
.unbounded_send(ReplyControllerMessage::RetransmitReply {
recipient,
timed_out_ack,
extra_surb_request,
})
.expect("ReplyControllerReceiver has died!")
}
pub(crate) fn send_reply(
&self,
recipient: AnonymousSenderTag,
message: Vec<u8>,
lane: TransmissionLane,
) {
self.0
.unbounded_send(ReplyControllerMessage::SendReply {
recipient,
message,
lane,
})
.expect("ReplyControllerReceiver has died!")
}
pub(crate) fn send_additional_surbs(
&self,
sender_tag: AnonymousSenderTag,
reply_surbs: Vec<ReplySurb>,
from_surb_request: bool,
) {
self.0
.unbounded_send(ReplyControllerMessage::AdditionalSurbs {
sender_tag,
reply_surbs,
from_surb_request,
})
.expect("ReplyControllerReceiver has died!")
}
pub(crate) fn send_additional_surbs_request(&self, recipient: Recipient, amount: u32) {
self.0
.unbounded_send(ReplyControllerMessage::AdditionalSurbsRequest {
recipient: Box::new(recipient),
amount,
})
.expect("ReplyControllerReceiver has died!")
}
}
pub(crate) type ReplyControllerReceiver = mpsc::UnboundedReceiver<ReplyControllerMessage>;
#[derive(Debug)]
pub(crate) enum ReplyControllerMessage {
RetransmitReply {
recipient: AnonymousSenderTag,
timed_out_ack: Weak<PendingAcknowledgement>,
extra_surb_request: bool,
},
SendReply {
recipient: AnonymousSenderTag,
message: Vec<u8>,
lane: TransmissionLane,
},
AdditionalSurbs {
sender_tag: AnonymousSenderTag,
reply_surbs: Vec<ReplySurb>,
from_surb_request: bool,
},
// Should this also be handled in here? it's technically a completely different side of the pipe
// let's see how it works when combined, might split it before creating PR
AdditionalSurbsRequest {
recipient: Box<Recipient>,
amount: u32,
},
}
pub struct Config {
min_surb_request_size: u32,
@@ -72,7 +172,7 @@ pub struct ReplyController<R> {
// of surbs required to send the message through
// expected_reliability: f32,
request_receiver: ReplyControllerReceiver,
pending_replies: HashMap<AnonymousSenderTag, TransmissionBuffer<Fragment>>,
pending_replies: HashMap<AnonymousSenderTag, VecDeque<Fragment>>,
/// Retransmission packets that have already timed out and are waiting for additional reply SURBs
/// so that they could be sent back to the network. Once we receive more SURBs, we should send them ASAP.
@@ -104,28 +204,17 @@ where
}
}
fn insert_pending_replies<I: IntoIterator<Item = Fragment>>(
/// Inserts the pending replies into the BACK of the queue fn insert_pending_replies<V: Into<VecDeque<Fragment>>>(
fn insert_pending_replies<V: Into<VecDeque<Fragment>>>(
&mut self,
recipient: &AnonymousSenderTag,
fragments: I,
lane: TransmissionLane,
fragments: V,
) {
self.pending_replies
.entry(*recipient)
.or_insert_with(TransmissionBuffer::new)
.store(&lane, fragments)
}
fn re_insert_pending_replies(
&mut self,
recipient: &AnonymousSenderTag,
fragments: Vec<(TransmissionLane, Fragment)>,
) {
// the buffer should ALWAYS exist at this point, if it doesn't, it's a bug...
self.pending_replies
.entry(*recipient)
.or_insert_with(TransmissionBuffer::new)
.store_multiple(fragments)
if let Some(existing) = self.pending_replies.get_mut(recipient) {
existing.append(&mut fragments.into())
} else {
self.pending_replies.insert(*recipient, fragments.into());
}
}
fn re_insert_pending_retransmission(
@@ -155,7 +244,7 @@ where
let pending_queue_size = self
.pending_replies
.get(target)
.map(|pending_queue| pending_queue.total_size())
.map(|pending_queue| pending_queue.len())
.unwrap_or_default();
let retransmission_queue = self
@@ -210,61 +299,42 @@ where
}
trace!("handling reply to {:?}", recipient_tag);
let mut fragments = self.message_handler.split_reply_message(data);
let total_size = fragments.len();
trace!("This reply requires {:?} SURBs", total_size);
let fragments = self.message_handler.split_reply_message(data);
let available_surbs = self
let required_surbs = fragments.len();
trace!("This reply requires {:?} SURBs", required_surbs);
// TODO: edge case:
// we're making a lot of requests and have to request a lot of surbs
// (but at some point we run out of surbs for surb requests)
let (surbs, _surbs_left) = self
.full_reply_storage
.surbs_storage_ref()
.available_surbs(&recipient_tag);
let min_surbs_threshold = self
.full_reply_storage
.surbs_storage_ref()
.min_surb_threshold();
.get_reply_surbs(&recipient_tag, required_surbs);
let max_to_send = if available_surbs > min_surbs_threshold {
min(fragments.len(), available_surbs - min_surbs_threshold)
} else {
0
};
if let Some(reply_surbs) = surbs {
if let Err(err) = self
.message_handler
.try_send_reply_chunks(recipient_tag, fragments, reply_surbs, lane)
.await
{
let err = err.return_unused_surbs(
self.full_reply_storage.surbs_storage_ref(),
&recipient_tag,
);
warn!("failed to send reply to {:?} - {err}", recipient_tag);
if max_to_send > 0 {
let (surbs, _surbs_left) = self
.full_reply_storage
.surbs_storage_ref()
.get_reply_surbs(&recipient_tag, max_to_send);
if let Some(reply_surbs) = surbs {
let to_send = fragments.drain(..max_to_send).collect::<Vec<_>>();
if let Err(err) = self
.message_handler
.try_send_reply_chunks_on_lane(
recipient_tag,
to_send.clone(),
reply_surbs,
lane,
)
.await
{
let err = err.return_unused_surbs(
self.full_reply_storage.surbs_storage_ref(),
&recipient_tag,
);
warn!("failed to send reply to {recipient_tag}: {err}");
self.insert_pending_replies(&recipient_tag, to_send, lane);
}
// TODO: should we buffer that data to try again?
}
}
} else {
// we don't have enough surbs for this reply
self.insert_pending_replies(&recipient_tag, fragments);
// if there's leftover data we didn't send because we didn't have enough (or any) surbs - buffer it
if !fragments.is_empty() {
self.insert_pending_replies(&recipient_tag, fragments, lane);
}
if self.should_request_more_surbs(&recipient_tag) {
self.request_reply_surbs_for_queue_clearing(recipient_tag)
.await;
if self.should_request_more_surbs(&recipient_tag) {
self.request_reply_surbs_for_queue_clearing(recipient_tag)
.await;
}
}
}
@@ -328,18 +398,35 @@ where
};
let mut to_take = Vec::new();
let mut to_remove = Vec::new();
while to_take.len() < max_to_clear {
if let Some((_, data)) = pending.pop_first() {
// no need to do anything if we failed to upgrade the reference,
// it means we got the ack while the data was waiting in the queue
if let Some(upgraded) = data.upgrade() {
to_take.push(upgraded)
// TODO: once rust 1.66.0 is stabilised on 15.12.22, just change it to
// `.pop_front()` to directly take ownership
for (k, data) in pending.iter() {
let upgraded = match data.upgrade() {
Some(upgraded) => upgraded,
None => {
// we got the ack while the data was waiting in the queue
to_remove.push(*k);
continue;
}
} else {
// our map is empty!
};
to_take.push(upgraded);
// we have taken as many entries as we could have
if to_take.len() >= max_to_clear {
break;
}
// TODO: use if upgraded.is_extra_surb_request() to bypass the limit
}
for ack in &to_take {
pending.remove(&ack.inner_fragment_identifier());
}
for id in to_remove {
pending.remove(&id);
}
if to_take.is_empty() {
@@ -360,47 +447,46 @@ where
let to_send_vec = to_take.iter().map(|ack| ack.fragment_data()).collect();
let prepared_fragments = match self
if let Err(err) = self
.message_handler
.prepare_reply_chunks_for_sending(to_send_vec, surbs_for_reply)
.try_send_retransmission_reply_chunks(
to_send_vec,
surbs_for_reply,
TransmissionLane::Retransmission,
)
.await
{
Ok(prepared) => prepared,
Err(err) => {
let err =
err.return_unused_surbs(self.full_reply_storage.surbs_storage_ref(), &target);
self.re_insert_pending_retransmission(&target, to_take);
let err = err.return_unused_surbs(self.full_reply_storage.surbs_storage_ref(), &target);
self.re_insert_pending_retransmission(&target, to_take);
warn!(
"failed to clear pending retransmission queue for {:?} - {err}",
target
);
return;
}
};
// we can't fail at this point, so drop all references to acks so that timer updates wouldn't blow up
drop(to_take);
self.message_handler
.send_retransmission_reply_chunks(prepared_fragments, TransmissionLane::Retransmission)
.await;
warn!(
"failed to clear pending retransmission queue for {:?} - {err}",
target
);
}
}
fn pop_at_most_pending_replies(
&mut self,
from: &AnonymousSenderTag,
amount: usize,
) -> Option<Vec<(TransmissionLane, Fragment)>> {
) -> Option<VecDeque<Fragment>> {
// if possible, pop all pending replies, if not, pop only entries for which we'd have a reply surb
let total = self.pending_replies.get(from)?.total_size();
let total = self.pending_replies.get(from)?.len();
trace!("pending queue has {total} elements");
if total == 0 {
return None;
}
self.pending_replies
.get_mut(from)?
.pop_at_most_n_next_messages_at_random(amount)
if total < amount {
self.pending_replies.remove(from)
} else {
Some(
self.pending_replies
.get_mut(from)?
.drain(..amount)
.collect(),
)
}
}
async fn try_clear_pending_queue(&mut self, target: AnonymousSenderTag) {
@@ -424,9 +510,9 @@ where
// we're guaranteed to not get more entries than we have reply surbs for
if let Some(to_send) = self.pop_at_most_pending_replies(&target, max_to_clear) {
let to_send_clone = to_send.clone();
let to_send_vec = to_send.iter().cloned().collect::<Vec<_>>();
if to_send_clone.is_empty() {
if to_send_vec.is_empty() {
panic!(
"please let the devs know if you ever see this message (reply_controller.rs)"
);
@@ -435,22 +521,27 @@ where
let (surbs_for_reply, _) = self
.full_reply_storage
.surbs_storage_ref()
.get_reply_surbs(&target, to_send_clone.len());
.get_reply_surbs(&target, to_send_vec.len());
let Some(surbs_for_reply) = surbs_for_reply else {
error!("somehow different task has stolen our reply surbs! - this should have been impossible");
self.re_insert_pending_replies(&target, to_send);
self.insert_pending_replies(&target, to_send);
return;
};
if let Err(err) = self
.message_handler
.try_send_reply_chunks(target, to_send_clone, surbs_for_reply)
.try_send_reply_chunks(
target,
to_send_vec,
surbs_for_reply,
TransmissionLane::General,
)
.await
{
let err =
err.return_unused_surbs(self.full_reply_storage.surbs_storage_ref(), &target);
self.re_insert_pending_replies(&target, to_send);
self.insert_pending_replies(&target, to_send);
warn!("failed to clear pending queue for {:?} - {err}", target);
}
} else {
@@ -621,30 +712,6 @@ where
}
}
// to be honest this doesn't make a lot of sense in the context of `connection_id`,
// it should really be asked per tag
fn handle_lane_queue_length(
&self,
connection_id: ConnectionId,
response_channel: oneshot::Sender<usize>,
) {
// TODO: if we ever have duplicate ids for different senders, it means our rng is super weak
// thus I don't think we have to worry about it?
let lane = TransmissionLane::ConnectionId(connection_id);
for buf in self.pending_replies.values() {
if let Some(length) = buf.lane_length(&lane) {
if response_channel.send(length).is_err() {
error!("the requester for lane queue length has dropped the response channel!")
}
return;
}
}
// make sure that if we didn't find that lane, we reply with 0
if response_channel.send(0).is_err() {
error!("the requester for lane queue length has dropped the response channel!")
}
}
async fn handle_request(&mut self, request: ReplyControllerMessage) {
match request {
ReplyControllerMessage::RetransmitReply {
@@ -668,26 +735,19 @@ where
self.handle_received_surbs(sender_tag, reply_surbs, from_surb_request)
.await
}
ReplyControllerMessage::LaneQueueLength {
connection_id,
response_channel,
} => self.handle_lane_queue_length(connection_id, response_channel),
ReplyControllerMessage::AdditionalSurbsRequest { recipient, amount } => {
self.handle_surb_request(*recipient, amount).await
}
}
}
// TODO: modify this method to more accurately determine the amount of surbs it needs to request
// it should take into consideration the average latency, sending rate and queue size.
// it should request as many surbs as it takes to saturate its sending rate before next batch arrives
async fn request_reply_surbs_for_queue_clearing(&mut self, target: AnonymousSenderTag) {
trace!("requesting surbs for queues clearing");
let pending_queue_size = self
.pending_replies
.get(&target)
.map(|pending_queue| pending_queue.total_size())
.map(|pending_queue| pending_queue.len())
.unwrap_or_default();
let retransmission_queue = self
@@ -727,7 +787,7 @@ where
}
let Some(last_received) = self.full_reply_storage.surbs_storage_ref().surbs_last_received_at(pending_reply_target) else {
error!("we have {} pending replies for {pending_reply_target}, but we somehow never received any reply surbs from them!", vals.total_size());
error!("we have {} pending replies for {pending_reply_target}, but we somehow never received any reply surbs from them!", vals.len());
to_remove.push(*pending_reply_target);
continue;
};
@@ -823,20 +883,23 @@ where
}
}
// #[cfg(not(target_arch = "wasm32"))]
// async fn log_status(&self) {
// todo!()
// }
fn create_interval_stream(polling_rate: Duration) -> IntervalStream {
#[cfg(not(target_arch = "wasm32"))]
return tokio_stream::wrappers::IntervalStream::new(tokio::time::interval(polling_rate));
#[cfg(target_arch = "wasm32")]
return gloo_timers::future::IntervalStream::new(polling_rate.as_millis() as u32);
}
pub(crate) async fn run_with_shutdown(&mut self, mut shutdown: task::TaskClient) {
debug!("Started ReplyController with graceful shutdown support");
let polling_rate = Duration::from_secs(5);
let mut stale_inspection = new_interval_stream(polling_rate);
let mut stale_inspection = Self::create_interval_stream(polling_rate);
// this is in the order of hours/days so we don't have to poll it that often
let polling_rate = Duration::from_secs(self.config.max_reply_surb_age.as_secs() / 10);
let mut invalidation_inspection = new_interval_stream(polling_rate);
let mut invalidation_inspection = Self::create_interval_stream(polling_rate);
while !shutdown.is_shutdown() {
tokio::select! {
@@ -1,136 +0,0 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::client::real_messages_control::acknowledgement_control::PendingAcknowledgement;
use client_connections::{ConnectionId, TransmissionLane};
use futures::channel::{mpsc, oneshot};
use log::error;
use nymsphinx::addressing::clients::Recipient;
use nymsphinx::anonymous_replies::requests::AnonymousSenderTag;
use nymsphinx::anonymous_replies::ReplySurb;
use std::sync::Weak;
pub(crate) fn new_control_channels() -> (ReplyControllerSender, ReplyControllerReceiver) {
let (tx, rx) = mpsc::unbounded();
(tx.into(), rx)
}
#[derive(Debug, Clone)]
pub struct ReplyControllerSender(mpsc::UnboundedSender<ReplyControllerMessage>);
impl From<mpsc::UnboundedSender<ReplyControllerMessage>> for ReplyControllerSender {
fn from(inner: mpsc::UnboundedSender<ReplyControllerMessage>) -> Self {
ReplyControllerSender(inner)
}
}
impl ReplyControllerSender {
pub(crate) fn send_retransmission_data(
&self,
recipient: AnonymousSenderTag,
timed_out_ack: Weak<PendingAcknowledgement>,
extra_surb_request: bool,
) {
self.0
.unbounded_send(ReplyControllerMessage::RetransmitReply {
recipient,
timed_out_ack,
extra_surb_request,
})
.expect("ReplyControllerReceiver has died!")
}
pub(crate) fn send_reply(
&self,
recipient: AnonymousSenderTag,
message: Vec<u8>,
lane: TransmissionLane,
) {
self.0
.unbounded_send(ReplyControllerMessage::SendReply {
recipient,
message,
lane,
})
.expect("ReplyControllerReceiver has died!")
}
pub(crate) fn send_additional_surbs(
&self,
sender_tag: AnonymousSenderTag,
reply_surbs: Vec<ReplySurb>,
from_surb_request: bool,
) {
self.0
.unbounded_send(ReplyControllerMessage::AdditionalSurbs {
sender_tag,
reply_surbs,
from_surb_request,
})
.expect("ReplyControllerReceiver has died!")
}
pub(crate) fn send_additional_surbs_request(&self, recipient: Recipient, amount: u32) {
self.0
.unbounded_send(ReplyControllerMessage::AdditionalSurbsRequest {
recipient: Box::new(recipient),
amount,
})
.expect("ReplyControllerReceiver has died!")
}
pub async fn get_lane_queue_length(&self, connection_id: ConnectionId) -> usize {
let (response_tx, response_rx) = oneshot::channel();
self.0
.unbounded_send(ReplyControllerMessage::LaneQueueLength {
connection_id,
response_channel: response_tx,
})
.expect("ReplyControllerReceiver has died!");
match response_rx.await {
Ok(length) => length,
Err(_) => {
error!("The reply controller has dropped our response channel!");
// TODO: should we panic here instead? this message implies something weird and unrecoverable has happened
0
}
}
}
}
pub(crate) type ReplyControllerReceiver = mpsc::UnboundedReceiver<ReplyControllerMessage>;
#[derive(Debug)]
pub(crate) enum ReplyControllerMessage {
RetransmitReply {
recipient: AnonymousSenderTag,
timed_out_ack: Weak<PendingAcknowledgement>,
extra_surb_request: bool,
},
SendReply {
recipient: AnonymousSenderTag,
message: Vec<u8>,
lane: TransmissionLane,
},
AdditionalSurbs {
sender_tag: AnonymousSenderTag,
reply_surbs: Vec<ReplySurb>,
from_surb_request: bool,
},
// this one doesn't belong here either...
LaneQueueLength {
connection_id: ConnectionId,
response_channel: oneshot::Sender<usize>,
},
// Should this also be handled in here? it's technically a completely different side of the pipe
// let's see how it works when combined, might split it before creating PR
AdditionalSurbsRequest {
recipient: Box<Recipient>,
amount: u32,
},
}
+3 -4
View File
@@ -1,13 +1,14 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::client::replies::reply_storage::ReplyStorageBackend;
use crypto::asymmetric::identity::Ed25519RecoveryError;
use gateway_client::error::GatewayClientError;
use topology::NymTopologyError;
use validator_client::ValidatorClientError;
#[derive(thiserror::Error, Debug)]
pub enum ClientCoreError {
pub enum ClientCoreError<B: ReplyStorageBackend> {
#[error("I/O error: {0}")]
IoError(#[from] std::io::Error),
@@ -39,9 +40,7 @@ pub enum ClientCoreError {
InsufficientNetworkTopology(#[from] NymTopologyError),
#[error("experienced a failure with our reply surb persistent storage: {source}")]
SurbStorageError {
source: Box<dyn std::error::Error + Send + Sync>,
},
SurbStorageError { source: B::StorageError },
#[error("The gateway id is invalid - {0}")]
UnableToCreatePublicKeyFromGatewayId(Ed25519RecoveryError),
+14 -6
View File
@@ -1,6 +1,7 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::client::replies::reply_storage::ReplyStorageBackend;
use crate::{
client::key_manager::KeyManager,
config::{persistence::key_pathfinder::ClientKeyPathfinder, Config},
@@ -16,10 +17,13 @@ use tap::TapFallible;
use topology::{filter::VersionFilterable, gateway};
use url::Url;
pub(super) async fn query_gateway_details(
pub(super) async fn query_gateway_details<B>(
validator_servers: Vec<Url>,
chosen_gateway_id: Option<String>,
) -> Result<gateway::Node, ClientCoreError> {
) -> Result<gateway::Node, ClientCoreError<B>>
where
B: ReplyStorageBackend,
{
let nym_api = validator_servers
.choose(&mut thread_rng())
.ok_or(ClientCoreError::ListOfNymApisIsEmpty)?;
@@ -51,10 +55,13 @@ pub(super) async fn query_gateway_details(
}
}
async fn register_with_gateway(
async fn register_with_gateway<B>(
gateway: &gateway::Node,
our_identity: Arc<identity::KeyPair>,
) -> Result<Arc<SharedKeys>, ClientCoreError> {
) -> Result<Arc<SharedKeys>, ClientCoreError<B>>
where
B: ReplyStorageBackend,
{
let timeout = Duration::from_millis(1500);
let mut gateway_client = GatewayClient::new_init(
gateway.clients_address(),
@@ -74,12 +81,13 @@ async fn register_with_gateway(
Ok(shared_keys)
}
pub(super) async fn register_with_gateway_and_store_keys<T>(
pub(super) async fn register_with_gateway_and_store_keys<T, B>(
gateway_details: gateway::Node,
config: &Config<T>,
) -> Result<(), ClientCoreError>
) -> Result<(), ClientCoreError<B>>
where
T: NymConfig,
B: ReplyStorageBackend,
{
let mut rng = OsRng;
let mut key_manager = KeyManager::new(&mut rng);
+28 -15
View File
@@ -12,6 +12,7 @@ use tap::TapFallible;
use config::NymConfig;
use crypto::asymmetric::{encryption, identity};
use crate::client::replies::reply_storage::ReplyStorageBackend;
use crate::{
config::{
persistence::key_pathfinder::ClientKeyPathfinder, ClientCoreConfigTrait, Config,
@@ -62,13 +63,13 @@ impl Display for InitResults {
/// Convenience function for setting up the gateway for a client. Depending on the arguments given
/// it will do the sensible thing.
pub async fn setup_gateway<C, T>(
pub async fn setup_gateway<B, C, T>(
register_gateway: bool,
// TODO: this should get refactored to instead take Option<identity::PublicKey>
user_chosen_gateway_id: Option<String>,
config: &Config<T>,
) -> Result<GatewayEndpointConfig, ClientCoreError>
) -> Result<GatewayEndpointConfig, ClientCoreError<B>>
where
B: ReplyStorageBackend,
C: NymConfig + ClientCoreConfigTrait,
T: NymConfig,
{
@@ -78,18 +79,19 @@ where
} else if let Some(user_chosen_gateway_id) = user_chosen_gateway_id {
config_gateway_with_existing_keys(user_chosen_gateway_id, config).await
} else {
reuse_existing_gateway_config::<C>(&id)
reuse_existing_gateway_config::<B, C>(&id)
}
}
/// Get the gateway details by querying the validator-api. Either pick one at random or use
/// the chosen one if it's among the available ones.
/// Saves keys to disk, specified by the paths in `config`.
pub async fn register_with_gateway<T>(
pub async fn register_with_gateway<B, T>(
user_chosen_gateway_id: Option<String>,
config: &Config<T>,
) -> Result<GatewayEndpointConfig, ClientCoreError>
) -> Result<GatewayEndpointConfig, ClientCoreError<B>>
where
B: ReplyStorageBackend,
T: NymConfig,
{
println!("Configuring gateway");
@@ -109,11 +111,12 @@ where
/// create any keys.
/// This assumes that the user knows what they are doing, and that the existing keys are valid for
/// the gateway being used
pub async fn config_gateway_with_existing_keys<T>(
pub async fn config_gateway_with_existing_keys<B, T>(
user_chosen_gateway_id: String,
config: &Config<T>,
) -> Result<GatewayEndpointConfig, ClientCoreError>
) -> Result<GatewayEndpointConfig, ClientCoreError<B>>
where
B: ReplyStorageBackend,
T: NymConfig,
{
println!("Using gateway provided by user, keeping existing keys");
@@ -124,8 +127,11 @@ where
}
/// Read and reuse the existing gateway configuration from a file that was generate earlier.
pub fn reuse_existing_gateway_config<T>(id: &str) -> Result<GatewayEndpointConfig, ClientCoreError>
pub fn reuse_existing_gateway_config<B, T>(
id: &str,
) -> Result<GatewayEndpointConfig, ClientCoreError<B>>
where
B: ReplyStorageBackend,
T: NymConfig + ClientCoreConfigTrait,
{
println!("Not registering gateway, will reuse existing config and keys");
@@ -144,15 +150,19 @@ where
}
/// Get the client address by loading the keys from stored files.
pub fn get_client_address_from_stored_keys<T>(
pub fn get_client_address_from_stored_keys<B, T>(
config: &Config<T>,
) -> Result<Recipient, ClientCoreError>
) -> Result<Recipient, ClientCoreError<B>>
where
T: config::NymConfig,
B: ReplyStorageBackend,
{
fn load_identity_keys(
fn load_identity_keys<B>(
pathfinder: &ClientKeyPathfinder,
) -> Result<identity::KeyPair, ClientCoreError> {
) -> Result<identity::KeyPair, ClientCoreError<B>>
where
B: ReplyStorageBackend,
{
let identity_keypair: identity::KeyPair =
pemstore::load_keypair(&pemstore::KeyPairPath::new(
pathfinder.private_identity_key().to_owned(),
@@ -162,9 +172,12 @@ where
Ok(identity_keypair)
}
fn load_sphinx_keys(
fn load_sphinx_keys<B>(
pathfinder: &ClientKeyPathfinder,
) -> Result<encryption::KeyPair, ClientCoreError> {
) -> Result<encryption::KeyPair, ClientCoreError<B>>
where
B: ReplyStorageBackend,
{
let sphinx_keypair: encryption::KeyPair =
pemstore::load_keypair(&pemstore::KeyPairPath::new(
pathfinder.private_encryption_key().to_owned(),
+1 -1
View File
@@ -8,7 +8,7 @@ edition = "2021"
[dependencies]
bip39 = "1.0.1"
cfg-if = "0.1"
clap = { version = "4.0", features = ["cargo", "derive"] }
clap = { version = "3.2", features = ["cargo", "derive"] }
rand = "0.7.3"
serde = { version = "1.0", features = ["derive"] }
thiserror = "1.0"
+3 -3
View File
@@ -31,7 +31,7 @@ cfg_if::cfg_if! {
#[tokio::main]
async fn main() -> Result<()> {
let args = Cli::parse();
setup_env(args.config_env_file.as_ref());
setup_env(args.config_env_file.clone());
let bin_name = "nym-credential-client";
match args.command {
@@ -42,8 +42,8 @@ cfg_if::cfg_if! {
let state = deposit(&r.nymd_url, &r.mnemonic, r.amount).await?;
get_credential(&state, shared_storage).await?;
}
Command::Completions(c) => c.generate(&mut crate::Cli::command(), bin_name),
Command::GenerateFigSpec => fig_generate(&mut crate::Cli::command(), bin_name)
Command::Completions(c) => c.generate(&mut crate::Cli::into_app(), bin_name),
Command::GenerateFigSpec => fig_generate(&mut crate::Cli::into_app(), bin_name)
}
Ok(())
+5 -4
View File
@@ -1,6 +1,6 @@
[package]
name = "nym-client"
version = "1.1.4"
version = "1.1.3"
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jędrzej Stuczyński <andrew@nymtech.net>"]
description = "Implementation of the Nym Client"
edition = "2021"
@@ -20,9 +20,8 @@ futures = "0.3" # bunch of futures stuff, however, now that I think about it, it
# and the single instance of abortable we have should really be refactored anyway
url = "2.2"
clap = { version = "4.0", features = ["cargo", "derive"] }
clap = { version = "3.2", features = ["cargo", "derive"] }
dirs = "4.0"
lazy_static = "1.4.0"
log = "0.4" # self explanatory
pretty_env_logger = "0.4" # for formatting log messages
rand = { version = "0.7.3", features = ["wasm-bindgen"] } # rng-related traits + some rng implementation to use
@@ -34,7 +33,6 @@ tokio = { version = "1.21.2", features = ["rt-multi-thread", "net", "signal"] }
tokio-tungstenite = "0.14" # websocket
## internal
build-information = { path = "../../common/build-information" }
client-core = { path = "../client-core", features = ["fs-surb-storage"] }
client-connections = { path = "../../common/client-connections" }
coconut-interface = { path = "../../common/coconut-interface", optional = true }
@@ -60,3 +58,6 @@ coconut = ["coconut-interface", "credentials", "credentials/coconut", "gateway-r
[dev-dependencies]
serde_json = "1.0" # for the "textsend" example
[build-dependencies]
vergen = { version = "5", default-features = false, features = ["build", "git", "rustc", "cargo"] }
@@ -1,4 +1,4 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use vergen::{vergen, Config};
File diff suppressed because it is too large Load Diff
-4
View File
@@ -13,7 +13,6 @@ use client_core::client::base_client::{
use client_core::client::inbound_messages::InputMessage;
use client_core::client::key_manager::KeyManager;
use client_core::client::received_buffer::{ReceivedBufferMessage, ReconstructedMessagesReceiver};
use client_core::client::replies::reply_controller::requests::ReplyControllerSender;
use client_core::config::persistence::key_pathfinder::ClientKeyPathfinder;
use futures::channel::mpsc;
use gateway_client::bandwidth::BandwidthController;
@@ -88,7 +87,6 @@ impl SocketClient {
client_input: ClientInput,
client_output: ClientOutput,
self_address: &Recipient,
reply_controller_sender: ReplyControllerSender,
shutdown: task::TaskClient,
) {
info!("Starting websocket listener...");
@@ -109,7 +107,6 @@ impl SocketClient {
received_buffer_request_sender,
self_address,
shared_lane_queue_lengths,
reply_controller_sender,
);
websocket::Listener::new(config.get_listening_port()).start(websocket_handler, shutdown);
@@ -157,7 +154,6 @@ impl SocketClient {
client_input,
client_output,
&self_address,
started_client.reply_controller_sender,
started_client.task_manager.subscribe(),
);
+14 -18
View File
@@ -8,7 +8,6 @@ use crate::{
};
use clap::Args;
use config::NymConfig;
use crypto::asymmetric::identity;
use nymsphinx::addressing::clients::Recipient;
use serde::Serialize;
use std::fmt::Display;
@@ -22,7 +21,7 @@ pub(crate) struct Init {
/// Id of the gateway we are going to connect to.
#[clap(long)]
gateway: Option<identity::PublicKey>,
gateway: Option<String>,
/// Force register gateway. WARNING: this will overwrite any existing keys for the given id,
/// potentially causing loss of access.
@@ -30,14 +29,12 @@ pub(crate) struct Init {
force_register_gateway: bool,
/// Comma separated list of rest endpoints of the nymd validators
#[cfg(feature = "coconut")]
#[clap(long, value_delimiter = ',')]
nymd_validators: Option<Vec<url::Url>>,
#[clap(long)]
nymd_validators: Option<String>,
/// Comma separated list of rest endpoints of the API validators
#[clap(long, alias = "api_validators", value_delimiter = ',')]
// the alias here is included for backwards compatibility (1.1.4 and before)
nym_apis: Option<Vec<url::Url>>,
#[clap(long)]
api_validators: Option<String>,
/// Whether to not start the websocket
#[clap(long)]
@@ -49,11 +46,11 @@ pub(crate) struct Init {
/// Mostly debug-related option to increase default traffic rate so that you would not need to
/// modify config post init
#[clap(long, hide = true)]
#[clap(long, hidden = true)]
fastmode: bool,
/// Disable loop cover traffic and the Poisson rate limiter (for debugging only)
#[clap(long, hide = true)]
#[clap(long, hidden = true)]
no_cover: bool,
/// Set this client to work in a enabled credentials mode that would attempt to use gateway
@@ -70,14 +67,13 @@ pub(crate) struct Init {
impl From<Init> for OverrideConfig {
fn from(init_config: Init) -> Self {
OverrideConfig {
nym_apis: init_config.nym_apis,
nymd_validators: init_config.nymd_validators,
api_validators: init_config.api_validators,
disable_socket: init_config.disable_socket,
port: init_config.port,
fastmode: init_config.fastmode,
no_cover: init_config.no_cover,
#[cfg(feature = "coconut")]
nymd_validators: init_config.nymd_validators,
#[cfg(feature = "coconut")]
enabled_credentials_mode: init_config.enabled_credentials_mode,
}
@@ -131,16 +127,16 @@ pub(crate) async fn execute(args: &Init) -> Result<(), ClientError> {
let register_gateway = !already_init || user_wants_force_register;
// Attempt to use a user-provided gateway, if possible
let user_chosen_gateway_id = args.gateway;
let user_chosen_gateway_id = args.gateway.clone();
// Load and potentially override config
let mut config = override_config(Config::new(id), OverrideConfig::from(args.clone()));
// Setup gateway by either registering a new one, or creating a new config from the selected
// one but with keys kept, or reusing the gateway configuration.
let gateway = client_core::init::setup_gateway::<Config, _>(
let gateway = client_core::init::setup_gateway::<_, Config, _>(
register_gateway,
user_chosen_gateway_id.map(|id| id.to_base58_string()),
user_chosen_gateway_id,
config.get_base(),
)
.await
@@ -156,14 +152,14 @@ pub(crate) async fn execute(args: &Init) -> Result<(), ClientError> {
let address = client_core::init::get_client_address_from_stored_keys(config.get_base())?;
let init_results = InitResults::new(&config, &address);
println!("{init_results}");
println!("{}", init_results);
// Output summary to a json file, if specified
if args.output_json {
client_core::init::output_to_json(&init_results, "client_init_results.json");
}
println!("\nThe address of this client is: {address}\n");
println!("\nThe address of this client is: {}\n", address);
Ok(())
}
+54 -27
View File
@@ -1,30 +1,54 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use std::error::Error;
use crate::client::config::{Config, SocketType};
use build_information::BinaryBuildInformation;
use clap::CommandFactory;
use clap::{Parser, Subcommand};
use completions::{fig_generate, ArgShell};
use lazy_static::lazy_static;
use std::error::Error;
pub(crate) mod init;
pub(crate) mod run;
pub(crate) mod upgrade;
lazy_static! {
pub static ref PRETTY_BUILD_INFORMATION: String =
BinaryBuildInformation::new(env!("CARGO_PKG_VERSION")).pretty_print();
fn long_version() -> String {
format!(
r#"
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
"#,
"Build Timestamp:",
env!("VERGEN_BUILD_TIMESTAMP"),
"Build Version:",
env!("VERGEN_BUILD_SEMVER"),
"Commit SHA:",
env!("VERGEN_GIT_SHA"),
"Commit Date:",
env!("VERGEN_GIT_COMMIT_TIMESTAMP"),
"Commit Branch:",
env!("VERGEN_GIT_BRANCH"),
"rustc Version:",
env!("VERGEN_RUSTC_SEMVER"),
"rustc Channel:",
env!("VERGEN_RUSTC_CHANNEL"),
"cargo Profile:",
env!("VERGEN_CARGO_PROFILE"),
)
}
// Helper for passing LONG_VERSION to clap
fn pretty_build_info_static() -> &'static str {
&PRETTY_BUILD_INFORMATION
fn long_version_static() -> &'static str {
Box::leak(long_version().into_boxed_str())
}
#[derive(Parser)]
#[clap(author = "Nymtech", version, long_version = pretty_build_info_static(), about)]
#[clap(author = "Nymtech", version, long_version = long_version_static(), about)]
pub(crate) struct Cli {
/// Path pointing to an env file that configures the client.
#[clap(short, long)]
@@ -52,14 +76,13 @@ pub(crate) enum Commands {
// Configuration that can be overridden.
pub(crate) struct OverrideConfig {
nym_apis: Option<Vec<url::Url>>,
nymd_validators: Option<String>,
api_validators: Option<String>,
disable_socket: bool,
port: Option<u16>,
fastmode: bool,
no_cover: bool,
#[cfg(feature = "coconut")]
nymd_validators: Option<Vec<url::Url>>,
#[cfg(feature = "coconut")]
enabled_credentials_mode: bool,
}
@@ -71,21 +94,34 @@ pub(crate) async fn execute(args: &Cli) -> Result<(), Box<dyn Error + Send + Syn
Commands::Init(m) => init::execute(m).await?,
Commands::Run(m) => run::execute(m).await?,
Commands::Upgrade(m) => upgrade::execute(m),
Commands::Completions(s) => s.generate(&mut Cli::command(), bin_name),
Commands::GenerateFigSpec => fig_generate(&mut Cli::command(), bin_name),
Commands::Completions(s) => s.generate(&mut Cli::into_app(), bin_name),
Commands::GenerateFigSpec => fig_generate(&mut Cli::into_app(), bin_name),
}
Ok(())
}
pub(crate) fn override_config(mut config: Config, args: OverrideConfig) -> Config {
if let Some(nym_apis) = args.nym_apis {
config.get_base_mut().set_custom_nym_apis(nym_apis);
if let Some(raw_validators) = args.nymd_validators {
config
.get_base_mut()
.set_custom_validators(config::parse_validators(&raw_validators));
} else if std::env::var(network_defaults::var_names::CONFIGURED).is_ok() {
let raw_validators = std::env::var(network_defaults::var_names::NYMD_VALIDATOR)
.expect("nymd validator not set");
config
.get_base_mut()
.set_custom_validators(config::parse_validators(&raw_validators));
}
if let Some(raw_validators) = args.api_validators {
config
.get_base_mut()
.set_custom_nym_apis(config::parse_validators(&raw_validators));
} else if std::env::var(network_defaults::var_names::CONFIGURED).is_ok() {
let raw_validators = std::env::var(network_defaults::var_names::API_VALIDATOR)
.expect("api validator not set");
config
.get_base_mut()
.set_custom_nym_apis(config::parse_urls(&raw_validators));
.set_custom_nym_apis(config::parse_validators(&raw_validators));
}
if args.disable_socket {
@@ -98,15 +134,6 @@ pub(crate) fn override_config(mut config: Config, args: OverrideConfig) -> Confi
#[cfg(feature = "coconut")]
{
if let Some(nymd_validators) = args.nymd_validators {
config.get_base_mut().set_custom_validators(nymd_validators);
} else if std::env::var(network_defaults::var_names::CONFIGURED).is_ok() {
let raw_validators = std::env::var(network_defaults::var_names::NYMD_VALIDATOR)
.expect("nymd validator not set");
config
.get_base_mut()
.set_custom_validators(config::parse_urls(&raw_validators));
}
if args.enabled_credentials_mode {
config.get_base_mut().with_disabled_credentials(false)
}
+10 -15
View File
@@ -1,4 +1,4 @@
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use std::error::Error;
@@ -11,7 +11,6 @@ use crate::{
use clap::Args;
use config::NymConfig;
use crypto::asymmetric::identity;
use log::*;
use version_checker::is_minor_version_compatible;
@@ -22,19 +21,17 @@ pub(crate) struct Run {
id: String,
/// Comma separated list of rest endpoints of the nymd validators
#[cfg(feature = "coconut")]
#[clap(long, value_delimiter = ',')]
nymd_validators: Option<Vec<url::Url>>,
#[clap(long)]
nymd_validators: Option<String>,
/// Comma separated list of rest endpoints of the API validators
#[clap(long, alias = "api_validators", value_delimiter = ',')]
// the alias here is included for backwards compatibility (1.1.4 and before)
nym_apis: Option<Vec<url::Url>>,
#[clap(long)]
api_validators: Option<String>,
/// Id of the gateway we want to connect to. If overridden, it is user's responsibility to
/// ensure prior registration happened
#[clap(long)]
gateway: Option<identity::PublicKey>,
gateway: Option<String>,
/// Whether to not start the websocket
#[clap(long)]
@@ -46,11 +43,11 @@ pub(crate) struct Run {
/// Mostly debug-related option to increase default traffic rate so that you would not need to
/// modify config post init
#[clap(long, hide = true)]
#[clap(long, hidden = true)]
fastmode: bool,
/// Disable loop cover traffic and the Poisson rate limiter (for debugging only)
#[clap(long, hide = true)]
#[clap(long, hidden = true)]
no_cover: bool,
/// Set this client to work in a enabled credentials mode that would attempt to use gateway
@@ -63,14 +60,12 @@ pub(crate) struct Run {
impl From<Run> for OverrideConfig {
fn from(run_config: Run) -> Self {
OverrideConfig {
nym_apis: run_config.nym_apis,
nymd_validators: run_config.nymd_validators,
api_validators: run_config.api_validators,
disable_socket: run_config.disable_socket,
port: run_config.port,
fastmode: run_config.fastmode,
no_cover: run_config.no_cover,
#[cfg(feature = "coconut")]
nymd_validators: run_config.nymd_validators,
#[cfg(feature = "coconut")]
enabled_credentials_mode: run_config.enabled_credentials_mode,
}
+2 -1
View File
@@ -1,3 +1,4 @@
use client_core::client::replies::reply_storage::fs_backend;
use client_core::error::ClientCoreError;
#[derive(thiserror::Error, Debug)]
@@ -6,7 +7,7 @@ pub enum ClientError {
IoError(#[from] std::io::Error),
#[error("client-core error: {0}")]
ClientCoreError(#[from] ClientCoreError),
ClientCoreError(#[from] ClientCoreError<fs_backend::Backend>),
#[error("Failed to load config for: {0}")]
FailedToLoadConfig(String),
+1 -1
View File
@@ -18,7 +18,7 @@ async fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
println!("{}", banner());
let args = commands::Cli::parse();
setup_env(args.config_env_file.as_ref());
setup_env(args.config_env_file.clone());
commands::execute(&args).await
}
+73 -63
View File
@@ -2,9 +2,8 @@
// SPDX-License-Identifier: Apache-2.0
use client_connections::{
ConnectionCommand, ConnectionCommandSender, ConnectionId, LaneQueueLengths, TransmissionLane,
ConnectionCommand, ConnectionCommandSender, LaneQueueLengths, TransmissionLane,
};
use client_core::client::replies::reply_controller::requests::ReplyControllerSender;
use client_core::client::{
inbound_messages::{InputMessage, InputMessageSender},
received_buffer::{
@@ -17,9 +16,7 @@ use log::*;
use nymsphinx::addressing::clients::Recipient;
use nymsphinx::anonymous_replies::requests::AnonymousSenderTag;
use nymsphinx::receiver::ReconstructedMessage;
use std::time::Duration;
use tokio::net::TcpStream;
use tokio::time::Instant;
use tokio_tungstenite::{
accept_async,
tungstenite::{protocol::Message as WsMessage, Error as WsError},
@@ -44,7 +41,6 @@ pub(crate) struct HandlerBuilder {
buffer_requester: ReceivedBufferRequestSender,
self_full_address: Recipient,
lane_queue_lengths: LaneQueueLengths,
reply_controller_sender: ReplyControllerSender,
}
impl HandlerBuilder {
@@ -54,7 +50,6 @@ impl HandlerBuilder {
buffer_requester: ReceivedBufferRequestSender,
self_full_address: &Recipient,
lane_queue_lengths: LaneQueueLengths,
reply_controller_sender: ReplyControllerSender,
) -> Self {
Self {
msg_input,
@@ -62,7 +57,6 @@ impl HandlerBuilder {
buffer_requester,
self_full_address: *self_full_address,
lane_queue_lengths,
reply_controller_sender,
}
}
@@ -76,7 +70,6 @@ impl HandlerBuilder {
socket: None,
received_response_type: Default::default(),
lane_queue_lengths: self.lane_queue_lengths.clone(),
reply_controller_sender: self.reply_controller_sender.clone(),
}
}
}
@@ -89,7 +82,6 @@ pub(crate) struct Handler {
socket: Option<WebSocketStream<TcpStream>>,
received_response_type: ReceivedResponseType,
lane_queue_lengths: LaneQueueLengths,
reply_controller_sender: ReplyControllerSender,
}
impl Drop for Handler {
@@ -105,48 +97,6 @@ impl Drop for Handler {
}
impl Handler {
async fn get_lane_queue_length(&self, connection_id: ConnectionId) -> Option<ServerResponse> {
let req_start = Instant::now();
// get the base queue length
// Note that this does _NOT_ take into account the packets that have been received but not
// yet reach `OutQueueControl`, so it might be a tad low.
let conn_lane = TransmissionLane::ConnectionId(connection_id);
let Ok(base_length) = self
.lane_queue_lengths
.lock()
.map(|guard| guard.get(&conn_lane).unwrap_or_default()) else {
// I'd argue we should panic here as this error it not recoverable
error!("The lane queue length lock is poisoned!!");
return None
};
// get the number of pending replies waiting for reply surbs
let reply_queue_length = self
.reply_controller_sender
.get_lane_queue_length(connection_id)
.await;
let queue_length = base_length + reply_queue_length;
let time_taken = req_start.elapsed();
let msg =
format!("it took {time_taken:?} to get lane length for connection {connection_id}. The length is: {queue_length} = {base_length} (already queued up) + {reply_queue_length} (waiting for reply SURBs)");
if time_taken > Duration::from_millis(1) {
info!("{msg}");
} else if time_taken > Duration::from_millis(10) {
warn!("{msg}");
} else if time_taken > Duration::from_millis(50) {
error!("{msg}");
}
Some(ServerResponse::LaneQueueLength {
lane: connection_id,
queue_length,
})
}
async fn handle_send(
&mut self,
recipient: Recipient,
@@ -171,11 +121,27 @@ impl Handler {
.expect("InputMessageReceiver has stopped receiving!");
// Only reply back with a `LaneQueueLength` if the sender providided a connection id
let TransmissionLane::ConnectionId(connection_id) = lane else {
return None
let connection_id = match lane {
TransmissionLane::General
| TransmissionLane::ReplySurbRequest
| TransmissionLane::Retransmission
| TransmissionLane::AdditionalReplySurbs => return None,
TransmissionLane::ConnectionId(id) => id,
};
self.get_lane_queue_length(connection_id).await
// on receiving a send, we reply back the current lane queue length for that connection id.
// Note that this does _NOT_ take into account the packets that have been received but not
// yet reach `OutQueueControl`, so it might be a tad low.
if let Ok(lane_queue_lengths) = self.lane_queue_lengths.lock() {
let queue_length = lane_queue_lengths.get(&lane).unwrap_or(0);
return Some(ServerResponse::LaneQueueLength {
lane: connection_id,
queue_length,
});
}
log::warn!("Failed to get the lane queue length lock, not responding back with the current queue length");
None
}
async fn handle_send_anonymous(
@@ -202,11 +168,27 @@ impl Handler {
.expect("InputMessageReceiver has stopped receiving!");
// Only reply back with a `LaneQueueLength` if the sender providided a connection id
let TransmissionLane::ConnectionId(connection_id) = lane else {
return None
let connection_id = match lane {
TransmissionLane::General
| TransmissionLane::ReplySurbRequest
| TransmissionLane::Retransmission
| TransmissionLane::AdditionalReplySurbs => return None,
TransmissionLane::ConnectionId(id) => id,
};
self.get_lane_queue_length(connection_id).await
// on receiving a send, we reply back the current lane queue length for that connection id.
// Note that this does _NOT_ take into account the packets that have been received but not
// yet reach `OutQueueControl`, so it might be a tad low.
if let Ok(lane_queue_lengths) = self.lane_queue_lengths.lock() {
let queue_length = lane_queue_lengths.get(&lane).unwrap_or(0);
return Some(ServerResponse::LaneQueueLength {
lane: connection_id,
queue_length,
});
}
log::warn!("Failed to get the lane queue length lock, not responding back with the current queue length");
None
}
async fn handle_reply(
@@ -229,11 +211,27 @@ impl Handler {
.expect("InputMessageReceiver has stopped receiving!");
// Only reply back with a `LaneQueueLength` if the sender providided a connection id
let TransmissionLane::ConnectionId(connection_id) = lane else {
return None
let connection_id = match lane {
TransmissionLane::General
| TransmissionLane::ReplySurbRequest
| TransmissionLane::Retransmission
| TransmissionLane::AdditionalReplySurbs => return None,
TransmissionLane::ConnectionId(id) => id,
};
self.get_lane_queue_length(connection_id).await
// on receiving a send, we reply back the current lane queue length for that connection id.
// Note that this does _NOT_ take into account the packets that have been received but not
// yet reach `OutQueueControl`, so it might be a tad low.
if let Ok(lane_queue_lengths) = self.lane_queue_lengths.lock() {
let queue_length = lane_queue_lengths.get(&lane).unwrap_or(0);
return Some(ServerResponse::LaneQueueLength {
lane: connection_id,
queue_length,
});
}
log::warn!("Failed to get the lane queue length lock, not responding back with the current queue length");
None
}
fn handle_self_address(&self) -> ServerResponse {
@@ -247,8 +245,20 @@ impl Handler {
None
}
async fn handle_get_lane_queue_length(&self, connection_id: u64) -> Option<ServerResponse> {
self.get_lane_queue_length(connection_id).await
fn handle_get_lane_queue_length(&self, connection_id: u64) -> Option<ServerResponse> {
let Ok(lane_queue_lengths) = self.lane_queue_lengths.lock() else {
log::warn!(
"Failed to get the lane queue length lock, not responding back with the current queue length"
);
return None;
};
let lane = TransmissionLane::ConnectionId(connection_id);
let queue_length = lane_queue_lengths.get(&lane).unwrap_or(0);
Some(ServerResponse::LaneQueueLength {
lane: connection_id,
queue_length,
})
}
async fn handle_request(&mut self, request: ClientRequest) -> Option<ServerResponse> {
@@ -277,7 +287,7 @@ impl Handler {
ClientRequest::SelfAddress => Some(self.handle_self_address()),
ClientRequest::ClosedConnection(id) => self.handle_closed_connection(id),
ClientRequest::GetLaneQueueLength(id) => self.handle_get_lane_queue_length(id).await,
ClientRequest::GetLaneQueueLength(id) => self.handle_get_lane_queue_length(id),
}
}
+5 -4
View File
@@ -1,6 +1,6 @@
[package]
name = "nym-socks5-client"
version = "1.1.4"
version = "1.1.3"
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"
@@ -11,10 +11,9 @@ name = "nym_socks5"
path = "src/lib.rs"
[dependencies]
clap = { version = "4.0", features = ["cargo", "derive"] }
clap = { version = "3.2", features = ["cargo", "derive"] }
dirs = "4.0"
futures = "0.3"
lazy_static = "1.4.0"
log = "0.4"
pin-project = "1.0"
pretty_env_logger = "0.4"
@@ -27,7 +26,6 @@ tokio = { version = "1.21.2", features = ["rt-multi-thread", "net", "signal"] }
url = "2.2"
# internal
build-information = { path = "../../common/build-information" }
client-core = { path = "../client-core", features = ["fs-surb-storage"] }
client-connections = { path = "../../common/client-connections" }
coconut-interface = { path = "../../common/coconut-interface", optional = true }
@@ -53,3 +51,6 @@ version-checker = { path = "../../common/version-checker" }
[features]
coconut = ["coconut-interface", "credentials", "gateway-requests/coconut", "gateway-client/coconut", "credentials/coconut", "client-core/coconut"]
eth = []
[build-dependencies]
vergen = { version = "5", default-features = false, features = ["build", "git", "rustc", "cargo"] }
+8
View File
@@ -0,0 +1,8 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use vergen::{vergen, Config};
fn main() {
vergen(Config::default()).expect("failed to extract build metadata")
}
+17 -23
View File
@@ -8,7 +8,6 @@ use crate::{
};
use clap::Args;
use config::NymConfig;
use crypto::asymmetric::identity;
use nymsphinx::addressing::clients::Recipient;
use serde::Serialize;
use std::fmt::Display;
@@ -22,20 +21,19 @@ pub(crate) struct Init {
/// Address of the socks5 provider to send messages to.
#[clap(long)]
provider: Recipient,
provider: String,
/// Specifies whether this client is going to use an anonymous sender tag for communication with the service provider.
/// While this is going to hide its actual address information, it will make the actual communication
/// slower and consume nearly double the bandwidth as it will require sending reply SURBs.
///
/// Note that some service providers might not support this.
// the alias here is included for backwards compatibility (1.1.4 and before)
#[clap(long, alias = "use_anonymous_sender_tag")]
use_reply_surbs: bool,
#[clap(long)]
use_anonymous_sender_tag: bool,
/// Id of the gateway we are going to connect to.
#[clap(long)]
gateway: Option<identity::PublicKey>,
gateway: Option<String>,
/// Force register gateway. WARNING: this will overwrite any existing keys for the given id,
/// potentially causing loss of access.
@@ -43,14 +41,12 @@ pub(crate) struct Init {
force_register_gateway: bool,
/// Comma separated list of rest endpoints of the nymd validators
#[cfg(feature = "coconut")]
#[clap(long, value_delimiter = ',')]
nymd_validators: Option<Vec<url::Url>>,
#[clap(long)]
nymd_validators: Option<String>,
/// Comma separated list of rest endpoints of the API validators
#[clap(long, alias = "api_validators", value_delimiter = ',')]
// the alias here is included for backwards compatibility (1.1.4 and before)
nym_apis: Option<Vec<url::Url>>,
#[clap(long)]
api_validators: Option<String>,
/// Port for the socket to listen on in all subsequent runs
#[clap(short, long)]
@@ -58,11 +54,11 @@ pub(crate) struct Init {
/// Mostly debug-related option to increase default traffic rate so that you would not need to
/// modify config post init
#[clap(long, hide = true)]
#[clap(long, hidden = true)]
fastmode: bool,
/// Disable loop cover traffic and the Poisson rate limiter (for debugging only)
#[clap(long, hide = true)]
#[clap(long, hidden = true)]
no_cover: bool,
/// Set this client to work in a enabled credentials mode that would attempt to use gateway
@@ -79,14 +75,12 @@ pub(crate) struct Init {
impl From<Init> for OverrideConfig {
fn from(init_config: Init) -> Self {
OverrideConfig {
nym_apis: init_config.nym_apis,
nymd_validators: init_config.nymd_validators,
api_validators: init_config.api_validators,
port: init_config.port,
use_anonymous_replies: init_config.use_reply_surbs,
use_anonymous_sender_tag: init_config.use_anonymous_sender_tag,
fastmode: init_config.fastmode,
no_cover: init_config.no_cover,
#[cfg(feature = "coconut")]
nymd_validators: init_config.nymd_validators,
#[cfg(feature = "coconut")]
enabled_credentials_mode: init_config.enabled_credentials_mode,
}
@@ -141,19 +135,19 @@ pub(crate) async fn execute(args: &Init) -> Result<(), Socks5ClientError> {
let register_gateway = !already_init || user_wants_force_register;
// Attempt to use a user-provided gateway, if possible
let user_chosen_gateway_id = args.gateway;
let user_chosen_gateway_id = args.gateway.clone();
// Load and potentially override config
let mut config = override_config(
Config::new(id, &provider_address.to_string()),
Config::new(id, provider_address),
OverrideConfig::from(args.clone()),
);
// Setup gateway by either registering a new one, or creating a new config from the selected
// one but with keys kept, or reusing the gateway configuration.
let gateway = client_core::init::setup_gateway::<Config, _>(
let gateway = client_core::init::setup_gateway::<_, Config, _>(
register_gateway,
user_chosen_gateway_id.map(|id| id.to_base58_string()),
user_chosen_gateway_id,
config.get_base(),
)
.await
+56 -31
View File
@@ -1,31 +1,55 @@
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use std::error::Error;
use crate::client::config::Config;
use build_information::BinaryBuildInformation;
use clap::CommandFactory;
use clap::{Parser, Subcommand};
use completions::{fig_generate, ArgShell};
use config::parse_urls;
use lazy_static::lazy_static;
use std::error::Error;
use config::parse_validators;
pub mod init;
pub(crate) mod run;
pub(crate) mod upgrade;
lazy_static! {
pub static ref PRETTY_BUILD_INFORMATION: String =
BinaryBuildInformation::new(env!("CARGO_PKG_VERSION")).pretty_print();
fn long_version() -> String {
format!(
r#"
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
"#,
"Build Timestamp:",
env!("VERGEN_BUILD_TIMESTAMP"),
"Build Version:",
env!("VERGEN_BUILD_SEMVER"),
"Commit SHA:",
env!("VERGEN_GIT_SHA"),
"Commit Date:",
env!("VERGEN_GIT_COMMIT_TIMESTAMP"),
"Commit Branch:",
env!("VERGEN_GIT_BRANCH"),
"rustc Version:",
env!("VERGEN_RUSTC_SEMVER"),
"rustc Channel:",
env!("VERGEN_RUSTC_CHANNEL"),
"cargo Profile:",
env!("VERGEN_CARGO_PROFILE"),
)
}
// Helper for passing LONG_VERSION to clap
fn pretty_build_info_static() -> &'static str {
&PRETTY_BUILD_INFORMATION
fn long_version_static() -> &'static str {
Box::leak(long_version().into_boxed_str())
}
#[derive(Parser)]
#[clap(author = "Nymtech", version, long_version = pretty_build_info_static(), about)]
#[clap(author = "Nymtech", version, long_version = long_version_static(), about)]
pub(crate) struct Cli {
/// Path pointing to an env file that configures the client.
#[clap(short, long)]
@@ -55,14 +79,13 @@ pub(crate) enum Commands {
// Configuration that can be overridden.
pub(crate) struct OverrideConfig {
nym_apis: Option<Vec<url::Url>>,
nymd_validators: Option<String>,
api_validators: Option<String>,
port: Option<u16>,
use_anonymous_replies: bool,
use_anonymous_sender_tag: bool,
fastmode: bool,
no_cover: bool,
#[cfg(feature = "coconut")]
nymd_validators: Option<Vec<url::Url>>,
#[cfg(feature = "coconut")]
enabled_credentials_mode: bool,
}
@@ -74,22 +97,33 @@ pub(crate) async fn execute(args: &Cli) -> Result<(), Box<dyn Error + Send + Syn
Commands::Init(m) => init::execute(m).await?,
Commands::Run(m) => run::execute(m).await?,
Commands::Upgrade(m) => upgrade::execute(m),
Commands::Completions(s) => s.generate(&mut Cli::command(), bin_name),
Commands::GenerateFigSpec => fig_generate(&mut Cli::command(), bin_name),
Commands::Completions(s) => s.generate(&mut Cli::into_app(), bin_name),
Commands::GenerateFigSpec => fig_generate(&mut Cli::into_app(), bin_name),
}
Ok(())
}
pub(crate) fn override_config(mut config: Config, args: OverrideConfig) -> Config {
if let Some(nym_apis) = args.nym_apis {
config.get_base_mut().set_custom_nym_apis(nym_apis);
if let Some(raw_validators) = args.nymd_validators {
config
.get_base_mut()
.set_custom_validators(parse_validators(&raw_validators));
} else if let Ok(raw_validators) = std::env::var(network_defaults::var_names::NYMD_VALIDATOR) {
config
.get_base_mut()
.set_custom_validators(parse_validators(&raw_validators));
}
if let Some(raw_validators) = args.api_validators {
config
.get_base_mut()
.set_custom_nym_apis(parse_validators(&raw_validators));
} else if let Ok(raw_validators) = std::env::var(network_defaults::var_names::API_VALIDATOR) {
config
.get_base_mut()
.set_custom_nym_apis(parse_urls(&raw_validators));
.set_custom_nym_apis(parse_validators(&raw_validators));
}
if args.use_anonymous_replies {
if args.use_anonymous_sender_tag {
config = config.with_anonymous_replies(true)
}
@@ -99,15 +133,6 @@ pub(crate) fn override_config(mut config: Config, args: OverrideConfig) -> Confi
#[cfg(feature = "coconut")]
{
if let Some(nymd_validators) = args.nymd_validators {
config.get_base_mut().set_custom_validators(nymd_validators);
} else if let Ok(raw_validators) =
std::env::var(network_defaults::var_names::NYMD_VALIDATOR)
{
config
.get_base_mut()
.set_custom_validators(parse_urls(&raw_validators));
}
if args.enabled_credentials_mode {
config.get_base_mut().with_disabled_credentials(false)
}
+13 -19
View File
@@ -9,9 +9,7 @@ use crate::{
use clap::Args;
use config::NymConfig;
use crypto::asymmetric::identity;
use log::*;
use nymsphinx::addressing::clients::Recipient;
use version_checker::is_minor_version_compatible;
#[derive(Args, Clone)]
@@ -29,27 +27,25 @@ pub(crate) struct Run {
/// slower and consume nearly double the bandwidth as it will require sending reply SURBs.
///
/// Note that some service providers might not support this.
// the alias here is included for backwards compatibility (1.1.4 and before)
#[clap(long, alias = "use_anonymous_sender_tag")]
use_anonymous_replies: bool,
#[clap(long)]
use_anonymous_sender_tag: bool,
/// Address of the socks5 provider to send messages to.
#[clap(long)]
provider: Option<Recipient>,
provider: Option<String>,
/// Id of the gateway we want to connect to. If overridden, it is user's responsibility to
/// ensure prior registration happened
#[clap(long)]
gateway: Option<identity::PublicKey>,
gateway: Option<String>,
/// Comma separated list of rest endpoints of the nymd validators
#[cfg(feature = "coconut")]
#[clap(long, value_delimiter = ',')]
nymd_validators: Option<Vec<url::Url>>,
#[clap(long)]
nymd_validators: Option<String>,
/// Comma separated list of rest endpoints of the Nym APIs
#[clap(long, value_delimiter = ',')]
nym_apis: Option<Vec<url::Url>>,
#[clap(long)]
nym_apis: Option<String>,
/// Port for the socket to listen on
#[clap(short, long)]
@@ -57,11 +53,11 @@ pub(crate) struct Run {
/// Mostly debug-related option to increase default traffic rate so that you would not need to
/// modify config post init
#[clap(long, hide = true)]
#[clap(long, hidden = true)]
fastmode: bool,
/// Disable loop cover traffic and the Poisson rate limiter (for debugging only)
#[clap(long, hide = true)]
#[clap(long, hidden = true)]
no_cover: bool,
/// Set this client to work in a enabled credentials mode that would attempt to use gateway
@@ -74,14 +70,12 @@ pub(crate) struct Run {
impl From<Run> for OverrideConfig {
fn from(run_config: Run) -> Self {
OverrideConfig {
nym_apis: run_config.nym_apis,
nymd_validators: run_config.nymd_validators,
api_validators: run_config.nym_apis,
port: run_config.port,
use_anonymous_replies: run_config.use_anonymous_replies,
use_anonymous_sender_tag: run_config.use_anonymous_sender_tag,
fastmode: run_config.fastmode,
no_cover: run_config.no_cover,
#[cfg(feature = "coconut")]
nymd_validators: run_config.nymd_validators,
#[cfg(feature = "coconut")]
enabled_credentials_mode: run_config.enabled_credentials_mode,
}
+2 -1
View File
@@ -1,4 +1,5 @@
use crate::socks::types::SocksProxyError;
use client_core::client::replies::reply_storage::fs_backend;
use client_core::error::ClientCoreError;
use socks5_requests::ConnectionId;
@@ -8,7 +9,7 @@ pub enum Socks5ClientError {
IoError(#[from] std::io::Error),
#[error("client-core error: {0}")]
ClientCoreError(#[from] ClientCoreError),
ClientCoreError(#[from] ClientCoreError<fs_backend::Backend>),
#[error("SOCKS proxy error")]
SocksProxyError(SocksProxyError),
+1 -1
View File
@@ -18,7 +18,7 @@ async fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
println!("{}", banner());
let args = commands::Cli::parse();
setup_env(args.config_env_file.as_ref());
setup_env(args.config_env_file.clone());
commands::execute(&args).await
}
File diff suppressed because it is too large Load Diff
-11
View File
@@ -1,11 +0,0 @@
[package]
name = "build-information"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
[build-dependencies]
vergen = { version = "7", default-features = false, features = ["build", "git", "rustc", "cargo"] }
-86
View File
@@ -1,86 +0,0 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
// TODO: at a later date this crate should probably also expose `ContractBuildInformation`
// and be used by our smart contracts
pub struct BinaryBuildInformation {
// VERGEN_BUILD_TIMESTAMP
/// Provides the build timestamp, for example `2021-02-23T20:14:46.558472672+00:00`.
pub build_timestamp: &'static str,
// VERGEN_BUILD_SEMVER
/// Provides the build version, for example `0.1.0-9-g46f83e1`.
pub build_version: &'static str,
// VERGEN_GIT_SHA
/// Provides the hash of the commit that was used for the build, for example `46f83e112520533338245862d366f6a02cef07d4`.
pub commit_sha: &'static str,
// VERGEN_GIT_COMMIT_TIMESTAMP
/// Provides the timestamp of the commit that was used for the build, for example `2021-02-23T08:08:02-05:00`.
pub commit_timestamp: &'static str,
// VERGEN_GIT_BRANCH
/// Provides the name of the git branch that was used for the build, for example `master`.
pub commit_branch: &'static str,
// VERGEN_RUSTC_SEMVER
/// Provides the rustc version that was used for the build, for example `1.52.0-nightly`.
pub rustc_version: &'static str,
// VERGEN_RUSTC_CHANNEL
/// Provides the rustc channel that was used for the build, for example `nightly`.
pub rustc_channel: &'static str,
// VERGEN_CARGO_PROFILE
/// Provides the cargo profile that was used for the build, for example `debug`.
pub cargo_profile: &'static str,
}
impl BinaryBuildInformation {
// explicitly require the build_version to be passed as it's binary specific
pub const fn new(build_version: &'static str) -> Self {
BinaryBuildInformation {
build_timestamp: env!("VERGEN_BUILD_TIMESTAMP"),
build_version,
commit_sha: env!("VERGEN_GIT_SHA"),
commit_timestamp: env!("VERGEN_GIT_COMMIT_TIMESTAMP"),
commit_branch: env!("VERGEN_GIT_BRANCH"),
rustc_version: env!("VERGEN_RUSTC_SEMVER"),
rustc_channel: env!("VERGEN_RUSTC_CHANNEL"),
cargo_profile: env!("VERGEN_CARGO_PROFILE"),
}
}
pub fn pretty_print(&self) -> String {
format!(
r#"
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
"#,
"Build Timestamp:",
self.build_timestamp,
"Build Version:",
self.build_version,
"Commit SHA:",
self.commit_sha,
"Commit Date:",
self.commit_timestamp,
"Commit Branch:",
self.commit_branch,
"rustc Version:",
self.rustc_version,
"rustc Channel:",
self.rustc_channel,
"cargo Profile:",
self.cargo_profile,
)
}
}
+2 -1
View File
@@ -1,9 +1,10 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use futures::channel::mpsc;
use std::collections::HashMap;
use futures::channel::mpsc;
pub type ConnectionId = u64;
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
@@ -9,11 +9,10 @@ use nym_api_requests::coconut::{
BlindSignRequestBody, BlindedSignatureResponse, VerifyCredentialBody, VerifyCredentialResponse,
};
use nym_api_requests::models::{
ComputeRewardEstParam, GatewayCoreStatusResponse, GatewayStatusReportResponse,
GatewayUptimeHistoryResponse, InclusionProbabilityResponse, MixNodeBondAnnotated,
MixnodeCoreStatusResponse, MixnodeStatusReportResponse, MixnodeStatusResponse,
MixnodeUptimeHistoryResponse, RequestError, RewardEstimationResponse, StakeSaturationResponse,
UptimeResponse,
GatewayCoreStatusResponse, GatewayStatusReportResponse, GatewayUptimeHistoryResponse,
InclusionProbabilityResponse, MixNodeBondAnnotated, MixnodeCoreStatusResponse,
MixnodeStatusReportResponse, MixnodeStatusResponse, MixnodeUptimeHistoryResponse, RequestError,
RewardEstimationResponse, StakeSaturationResponse, UptimeResponse,
};
use reqwest::Response;
use serde::{Deserialize, Serialize};
@@ -362,25 +361,6 @@ impl Client {
.await
}
pub async fn compute_mixnode_reward_estimation(
&self,
mix_id: MixId,
request_body: &ComputeRewardEstParam,
) -> Result<RewardEstimationResponse, NymAPIError> {
self.post_nym_api(
&[
routes::API_VERSION,
routes::STATUS_ROUTES,
routes::MIXNODE,
&mix_id.to_string(),
routes::COMPUTE_REWARD_ESTIMATION,
],
NO_PARAMS,
request_body,
)
.await
}
pub async fn get_mixnode_stake_saturation(
&self,
mix_id: MixId,
@@ -28,7 +28,6 @@ pub const STATUS: &str = "status";
pub const REPORT: &str = "report";
pub const HISTORY: &str = "history";
pub const REWARD_ESTIMATION: &str = "reward-estimation";
pub const COMPUTE_REWARD_ESTIMATION: &str = "compute-reward-estimation";
pub const AVG_UPTIME: &str = "avg_uptime";
pub const STAKE_SATURATION: &str = "stake-saturation";
pub const INCLUSION_CHANCE: &str = "inclusion-probability";
@@ -166,7 +166,7 @@ fn try_parse_abci_log(log: &abci::Log) -> Option<String> {
.value()
.contains("Maximum amount of locked coins has already been pledged")
{
Some("Maximum amount of locked tokens has alredy been used. You can only use up to 10% of your locked tokens for bonding and delegating.".to_string())
Some("Maximum amount of locked tokens has alredy been used. You can only use up tp 10% of your locked tokens for bonding and delegating.".to_string())
} else {
None
}
+1 -1
View File
@@ -10,7 +10,7 @@ bip39 = "1.0.1"
bs58 = "0.4"
comfy-table = "6.0.0"
cfg-if = "1.0.0"
clap = { version = "4.0", features = ["derive"] }
clap = { version = "3.2", features = ["derive"] }
handlebars = "3.0.1"
humantime-serde = "1.0"
k256 = { version = "0.10", features = ["ecdsa", "sha256"] }
+1 -1
View File
@@ -32,7 +32,7 @@ pub struct ClientArgs {
pub fn get_network_details(args: &ClientArgs) -> Result<NymNetworkDetails, ContextError> {
// let the network defaults crate handle setting up the env vars if the file arg is set, otherwise
// it will default to what is already in env vars, falling back to mainnet
setup_env(args.config_env_file.as_ref());
setup_env(args.config_env_file.clone());
// override the env vars with user supplied arguments, if set
if let Some(nymd_url) = args.nymd_url.as_ref() {
+3 -3
View File
@@ -6,6 +6,6 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
clap = { version = "4.0", features = ["derive"] }
clap_complete = "4.0"
clap_complete_fig = "4.0"
clap = { version = "3.2", features = ["derive"] }
clap_complete = "3.2"
clap_complete_fig = "3.2"
+3 -3
View File
@@ -1,5 +1,5 @@
use clap::builder::Command;
use clap::clap_derive::ValueEnum;
use clap::clap_derive::ArgEnum;
use clap::Args;
use clap_complete::generator::generate;
use clap_complete::Shell as ClapShell;
@@ -14,7 +14,7 @@ pub fn fig_generate(command: &mut Command, name: &str) {
)
}
#[derive(ValueEnum, Copy, Clone)]
#[derive(ArgEnum, Copy, Clone)]
pub enum Shell {
Bash,
Elvish,
@@ -25,7 +25,7 @@ pub enum Shell {
#[derive(Args, Copy, Clone)]
pub struct ArgShell {
#[clap(value_enum, value_name = "SHELL")]
#[clap(arg_enum, value_name = "SHELL")]
shell: Shell,
}
+4 -5
View File
@@ -118,14 +118,13 @@ pub trait NymConfig: Default + Serialize + DeserializeOwned {
}
}
// this function is only used for parsing values from the network defaults and thus the "expect" there are fine
pub fn parse_urls(raw: &str) -> Vec<url::Url> {
pub fn parse_validators(raw: &str) -> Vec<url::Url> {
raw.split(',')
.map(|raw_url| {
raw_url
.map(|raw_validator| {
raw_validator
.trim()
.parse()
.expect("one of the provided nym api urls is invalid")
.expect("one of the provided validator api urls is invalid")
})
.collect()
}
@@ -56,6 +56,7 @@ impl Family {
self.proxy.as_ref()
}
#[allow(dead_code)]
pub fn label(&self) -> &str {
&self.label
}
@@ -7,7 +7,6 @@ pub use ed25519_dalek::{Verifier, PUBLIC_KEY_LENGTH, SECRET_KEY_LENGTH, SIGNATUR
use nymsphinx_types::{DestinationAddressBytes, DESTINATION_ADDRESS_LENGTH};
use pemstore::traits::{PemStorableKey, PemStorableKeyPair};
use std::fmt::{self, Display, Formatter};
use std::str::FromStr;
use thiserror::Error;
#[cfg(feature = "rand")]
@@ -142,14 +141,6 @@ impl PublicKey {
}
}
impl FromStr for PublicKey {
type Err = Ed25519RecoveryError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
PublicKey::from_base58_string(s)
}
}
#[cfg(feature = "serde")]
impl Serialize for PublicKey {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+1 -1
View File
@@ -289,7 +289,7 @@ impl ValidatorDetails {
}
}
pub fn setup_env(config_env_file: Option<&PathBuf>) {
pub fn setup_env(config_env_file: Option<PathBuf>) {
match std::env::var(var_names::CONFIGURED) {
// if the configuration is not already set in the env vars
Err(std::env::VarError::NotPresent) => {
@@ -10,7 +10,6 @@ use nymsphinx_types::Destination;
use serde::de::{Error as SerdeError, Unexpected, Visitor};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::fmt::{self, Formatter};
use std::str::FromStr;
use thiserror::Error;
// Not entirely sure whether this is the correct place for those, but let's see how it's going
@@ -226,14 +225,6 @@ impl std::fmt::Display for Recipient {
}
}
impl FromStr for Recipient {
type Err = RecipientFormattingError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Recipient::try_from_base58_string(s)
}
}
#[cfg(test)]
mod tests {
use super::*;
@@ -208,11 +208,6 @@ impl Fragment {
}
}
/// Gets the size of payload contained in this `Fragment`.
pub fn payload_size(&self) -> usize {
self.payload.len()
}
/// Extracts id of this `Fragment`.
pub fn id(&self) -> i32 {
self.header.id
File diff suppressed because it is too large Load Diff
@@ -1,12 +1,12 @@
{
"devDependencies": {
"@nomiclabs/hardhat-ethers": "^2.0.5",
"@nomiclabs/hardhat-etherscan": "^3.1.0",
"@nomiclabs/hardhat-etherscan": "^3.0.3",
"@nomiclabs/hardhat-waffle": "^2.0.3",
"chai": "^4.3.6",
"ethereum-waffle": "^3.4.4",
"ethers": "^5.6.1",
"hardhat": "^2.11.2",
"hardhat": "^2.9.2",
"solidity-coverage": "^0.7.20"
},
"dependencies": {
-5
View File
@@ -313,11 +313,6 @@ fn try_update_staking_address(
info: MessageInfo,
deps: DepsMut<'_>,
) -> Result<Response, ContractError> {
if let Some(ref to_address) = to_address {
if let Ok(_account) = account_from_address(&to_address, deps.storage, deps.api) {
return Err(ContractError::StakingAccountExists(to_address.to_string()));
}
}
let address = info.sender.clone();
let to_address = to_address.and_then(|x| deps.api.addr_validate(&x).ok());
let mut account = account_from_address(info.sender.as_str(), deps.storage, deps.api)?;
-2
View File
@@ -52,6 +52,4 @@ pub enum ContractError {
LockedPledgeCapReached { current: Uint128, cap: Uint128 },
#[error("VESTING: ({}: Account owned by {owner} has unpopulated vesting periods!", line!())]
UnpopulatedVestingPeriods { owner: Addr },
#[error("VESTING: Vesting account associated with {0} already exists, only addresses with not existing vesting accounts can be added as staking addresses")]
StakingAccountExists(String),
}
File diff suppressed because it is too large Load Diff
@@ -16,7 +16,7 @@
},
"dependencies": {
"@types/node": "^14.14.22",
"nodemon": "^2.0.20",
"nodemon": "^2.0.7",
"@nymproject/nym-validator-client" : "0.18.0",
"save-dev": "0.0.1-security",
"tasktimer": "^3.0.0",
+1 -4
View File
@@ -7,7 +7,7 @@ edition = "2021"
[dependencies]
chrono = { version = "0.4.19", features = ["serde"] }
clap = { version = "4.0", features = ["cargo", "derive"] }
clap = { version = "3.2", features = ["cargo", "derive"] }
humantime-serde = "1.0"
isocountry = "0.3.2"
itertools = "0.10.3"
@@ -25,9 +25,6 @@ thiserror = "1.0.29"
tokio = {version = "1.21.2", features = ["full"] }
maxminddb = "0.23.0"
dotenv = "0.15.0"
rand = "0.8.5"
rand_seeder = "0.2.3"
rand_pcg = "0.3.1"
mixnet-contract-common = { path = "../common/cosmwasm-smart-contracts/mixnet-contract" }
contracts-common = { path = "../common/cosmwasm-smart-contracts/contracts-common" }
+30 -2
View File
@@ -8,7 +8,7 @@ use dotenv::dotenv;
use log::info;
use logging::setup_logging;
use network_defaults::setup_env;
use task::{wait_for_signal, TaskManager};
use task::TaskManager;
mod buy_terms;
pub(crate) mod cache;
@@ -35,7 +35,7 @@ async fn main() {
dotenv().ok();
setup_logging();
let args = commands::Cli::parse();
setup_env(args.config_env_file.as_ref());
setup_env(args.config_env_file);
let mut explorer_api = ExplorerApi::new();
explorer_api.run().await;
}
@@ -88,3 +88,31 @@ impl ExplorerApi {
log::info!("Stopping explorer API");
}
}
#[cfg(unix)]
async fn wait_for_signal() {
use tokio::signal::unix::{signal, SignalKind};
let mut sigterm = signal(SignalKind::terminate()).expect("Failed to setup SIGTERM channel");
let mut sigquit = signal(SignalKind::quit()).expect("Failed to setup SIGQUIT channel");
tokio::select! {
_ = tokio::signal::ctrl_c() => {
log::info!("Received SIGINT");
},
_ = sigterm.recv() => {
log::info!("Received SIGTERM");
}
_ = sigquit.recv() => {
log::info!("Received SIGQUIT");
}
}
}
#[cfg(not(unix))]
async fn wait_for_signal() {
tokio::select! {
_ = tokio::signal::ctrl_c() => {
log::info!("Received SIGINT");
},
}
}
-1
View File
@@ -40,7 +40,6 @@ pub(crate) struct PrettyDetailedMixNodeBond {
pub estimated_delegators_apy: f64,
pub operating_cost: Coin,
pub profit_margin_percent: Percent,
pub family_id: Option<u16>,
}
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, JsonSchema)]
-1
View File
@@ -6,7 +6,6 @@ use std::time::Duration;
pub(crate) mod http;
pub(crate) mod location;
pub(crate) mod models;
pub(crate) mod utils;
pub(crate) const CACHE_REFRESH_RATE: Duration = Duration::from_secs(30);
pub(crate) const CACHE_ENTRY_TTL: Duration = Duration::from_secs(60);
-4
View File
@@ -13,7 +13,6 @@ use tokio::sync::{RwLock, RwLockReadGuard};
use crate::helpers::best_effort_small_dec_to_f64;
use validator_client::models::MixNodeBondAnnotated;
use super::utils::family_numerical_id;
use crate::mix_node::models::{MixnodeStatus, PrettyDetailedMixNodeBond};
use crate::mix_nodes::location::{Location, LocationCache, LocationCacheItem};
use crate::mix_nodes::CACHE_ENTRY_TTL;
@@ -141,8 +140,6 @@ impl ThreadsafeMixNodesCache {
let denom = &node.mixnode_details.original_pledge().denom;
let rewarding_info = &node.mixnode_details.rewarding_details;
let family_id = node.family.as_ref().map(family_numerical_id);
PrettyDetailedMixNodeBond {
mix_id,
location: location.and_then(|l| l.location.clone()),
@@ -160,7 +157,6 @@ impl ThreadsafeMixNodesCache {
estimated_delegators_apy: best_effort_small_dec_to_f64(node.estimated_delegators_apy),
operating_cost: rewarding_info.cost_params.interval_operating_cost.clone(),
profit_margin_percent: rewarding_info.cost_params.profit_margin_percent,
family_id,
}
}
-13
View File
@@ -1,15 +1,9 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use mixnet_contract_common::families::FamilyHead;
use rand::Rng;
use rand_pcg::Pcg64;
use rand_seeder::Seeder;
use crate::mix_nodes::location::GeoLocation;
use isocountry::CountryCode;
#[allow(dead_code)]
pub(crate) fn map_2_letter_to_3_letter_country_code(geo: &GeoLocation) -> String {
match CountryCode::for_alpha2(&geo.country_code) {
Ok(three_letter_country_code) => three_letter_country_code.alpha3().to_string(),
@@ -22,10 +16,3 @@ pub(crate) fn map_2_letter_to_3_letter_country_code(geo: &GeoLocation) -> String
}
}
}
// We don't need numerical IDs anywhere, so to avoid modifying the contract storage again and
// since this is for explorer ergonomics, it will generate a deterministic random u16 based on the family Identity.
pub(crate) fn family_numerical_id(fh: &FamilyHead) -> u16 {
let mut rng: Pcg64 = Seeder::from(fh.identity()).make_rng();
rng.gen()
}
+1 -6
View File
@@ -4,8 +4,6 @@ import Select, { SelectChangeEvent } from '@mui/material/Select';
import { Filters } from './Filters/Filters';
import { useIsMobile } from '../hooks/useIsMobile';
const fieldsHeight = '42.25px';
type TableToolBarProps = {
onChangeSearch: (arg: string) => void;
onChangePageSize: (event: SelectChangeEvent<string>) => void;
@@ -37,7 +35,7 @@ export const TableToolbar: React.FC<TableToolBarProps> = ({
}}
>
<Box sx={{ display: 'flex', flexDirection: isMobile ? 'column-reverse' : 'row', alignItems: 'middle' }}>
<Box sx={{ display: 'flex', justifyContent: 'space-between', height: fieldsHeight }}>
<Box sx={{ display: 'flex', justifyContent: 'space-between' }}>
{childrenBefore}
<Select
labelId="simple-select-label"
@@ -67,9 +65,6 @@ export const TableToolbar: React.FC<TableToolBarProps> = ({
sx={{
width: isMobile ? '100%' : 200,
marginBottom: isMobile ? 2 : 0,
'& > :not(style)': {
height: fieldsHeight,
},
}}
value={searchTerm}
data-testid="search-box"
+9 -5
View File
@@ -3,7 +3,7 @@
[package]
name = "nym-gateway"
version = "1.1.4"
version = "1.1.3"
authors = [
"Dave Hrycyszyn <futurechimp@users.noreply.github.com>",
"Jędrzej Stuczyński <andrew@nymtech.net>",
@@ -19,14 +19,13 @@ anyhow = "1.0.53"
async-trait = { version = "0.1.51" }
bip39 = "1.0.1"
bs58 = "0.4.0"
clap = { version = "4.0", features = ["cargo", "derive"] }
clap = { version = "3.2", features = ["cargo", "derive"] }
colored = "2.0"
dashmap = "4.0"
dirs = "4.0"
dotenv = "0.15.0"
futures = "0.3"
humantime-serde = "1.0.1"
lazy_static = "1.4.0"
log = "0.4"
once_cell = "1.7.2"
pretty_env_logger = "0.4"
@@ -52,7 +51,6 @@ tokio-util = { version = "0.7.3", features = ["codec"] }
url = { version = "2.2", features = ["serde"] }
# internal
build-information = { path = "../common/build-information" }
coconut-interface = { path = "../common/coconut-interface", optional = true }
credentials = { path = "../common/credentials" }
config = { path = "../common/config" }
@@ -87,4 +85,10 @@ sqlx = { version = "0.5", features = [
"sqlite",
"macros",
"migrate",
] }
] }
vergen = { version = "5", default-features = false, features = [
"build",
"git",
"rustc",
"cargo",
] }
+3
View File
@@ -1,5 +1,6 @@
use sqlx::{Connection, SqliteConnection};
use std::env;
use vergen::{vergen, Config};
#[tokio::main]
async fn main() {
@@ -22,4 +23,6 @@ async fn main() {
// for some strange reason we need to add a leading `/` to the windows path even though it's
// not a valid windows path... but hey, it works...
println!("cargo:rustc-env=DATABASE_URL=sqlite:///{}", &database_path);
vergen(Config::default()).expect("failed to extract build metadata")
}
+18 -27
View File
@@ -1,4 +1,4 @@
// Copyright 2020-2023 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2020 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::{
@@ -8,9 +8,6 @@ use crate::{
use clap::Args;
use config::NymConfig;
use crypto::asymmetric::{encryption, identity};
use std::net::IpAddr;
use std::path::PathBuf;
use validator_client::nymd;
#[derive(Args, Clone)]
pub struct Init {
@@ -20,11 +17,11 @@ pub struct Init {
/// The custom host on which the gateway will be running for receiving sphinx packets
#[clap(long)]
host: IpAddr,
host: String,
/// The wallet address you will use to bond this gateway, e.g. nymt1z9egw0knv47nmur0p8vk4rcx59h9gg4zuxrrr9
#[clap(long)]
wallet_address: nymd::AccountId,
wallet_address: String,
/// The port on which the gateway will be listening for sphinx packets
#[clap(long)]
@@ -36,27 +33,23 @@ pub struct Init {
/// The host that will be reported to the directory server
#[clap(long)]
// TODO: could this be changed to `Option<url::Url>`?
announce_host: Option<String>,
/// Path to sqlite database containing all gateway persistent data
#[clap(long)]
datastore: Option<PathBuf>,
datastore: Option<String>,
/// Comma separated list of endpoints of nym APIs
#[clap(long, alias = "validator_apis", value_delimiter = ',')]
// the alias here is included for backwards compatibility (1.1.4 and before)
nym_apis: Option<Vec<url::Url>>,
#[clap(long)]
nym_apis: Option<String>,
/// Comma separated list of endpoints of the validator
#[cfg(feature = "coconut")]
#[clap(long, alias = "validators", value_delimiter = ',')]
// the alias here is included for backwards compatibility (1.1.4 and before)
nymd_validators: Option<Vec<url::Url>>,
#[clap(long)]
validators: Option<String>,
/// Cosmos wallet mnemonic needed for double spending protection
#[clap(long)]
mnemonic: Option<bip39::Mnemonic>,
mnemonic: Option<String>,
/// Set this gateway to work only with coconut credentials; that would disallow clients to
/// bypass bandwidth credential requirement
@@ -70,7 +63,7 @@ pub struct Init {
/// URL where a statistics aggregator is running. The default value is a Nym aggregator server
#[clap(long)]
statistics_service_url: Option<url::Url>,
statistics_service_url: Option<String>,
}
impl From<Init> for OverrideConfig {
@@ -83,15 +76,14 @@ impl From<Init> for OverrideConfig {
datastore: init_config.datastore,
announce_host: init_config.announce_host,
nym_apis: init_config.nym_apis,
validators: init_config.validators,
mnemonic: init_config.mnemonic,
#[cfg(feature = "coconut")]
only_coconut_credentials: init_config.only_coconut_credentials,
enabled_statistics: init_config.enabled_statistics,
statistics_service_url: init_config.statistics_service_url,
#[cfg(feature = "coconut")]
nymd_validators: init_config.nymd_validators,
#[cfg(feature = "coconut")]
only_coconut_credentials: init_config.only_coconut_credentials,
}
}
}
@@ -167,19 +159,18 @@ mod tests {
async fn create_gateway_with_in_mem_storage() {
let args = Init {
id: "foo-id".to_string(),
host: "1.1.1.1".parse().unwrap(),
wallet_address: "n1z9egw0knv47nmur0p8vk4rcx59h9gg4zjx9ede".parse().unwrap(),
host: "foo-host".to_string(),
wallet_address: "n1z9egw0knv47nmur0p8vk4rcx59h9gg4zjx9ede".to_string(),
mix_port: Some(42),
clients_port: Some(43),
announce_host: Some("foo-announce-host".to_string()),
datastore: Some("/foo-datastore".parse().unwrap()),
datastore: Some("foo-datastore".to_string()),
nym_apis: None,
validators: None,
mnemonic: None,
statistics_service_url: None,
enabled_statistics: None,
#[cfg(feature = "coconut")]
nymd_validators: None,
#[cfg(feature = "coconut")]
only_coconut_credentials: false,
};
std::env::set_var(BECH32_PREFIX, "n");
+37 -34
View File
@@ -1,20 +1,19 @@
// Copyright 2020-2023 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2020 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use std::{process, str::FromStr};
use crate::{config::Config, Cli};
use clap::CommandFactory;
use clap::Subcommand;
use colored::Colorize;
use completions::{fig_generate, ArgShell};
use config::parse_validators;
use crypto::bech32_address_validation;
use network_defaults::mainnet::read_var_if_not_default;
use network_defaults::var_names::{
API_VALIDATOR, BECH32_PREFIX, CONFIGURED, STATISTICS_SERVICE_DOMAIN_ADDRESS,
API_VALIDATOR, BECH32_PREFIX, CONFIGURED, NYMD_VALIDATOR, STATISTICS_SERVICE_DOMAIN_ADDRESS,
};
use std::net::IpAddr;
use std::path::PathBuf;
use std::process;
use validator_client::nymd::{self};
pub(crate) mod init;
pub(crate) mod node_details;
@@ -48,19 +47,18 @@ pub(crate) enum Commands {
// Configuration that can be overridden.
pub(crate) struct OverrideConfig {
host: Option<IpAddr>,
wallet_address: Option<nymd::AccountId>,
host: Option<String>,
wallet_address: Option<String>,
mix_port: Option<u16>,
clients_port: Option<u16>,
datastore: Option<PathBuf>,
datastore: Option<String>,
announce_host: Option<String>,
enabled_statistics: Option<bool>,
statistics_service_url: Option<url::Url>,
nym_apis: Option<Vec<url::Url>>,
mnemonic: Option<bip39::Mnemonic>,
statistics_service_url: Option<String>,
nym_apis: Option<String>,
validators: Option<String>,
mnemonic: Option<String>,
#[cfg(feature = "coconut")]
nymd_validators: Option<Vec<url::Url>>,
#[cfg(feature = "coconut")]
only_coconut_credentials: bool,
}
@@ -74,8 +72,8 @@ pub(crate) async fn execute(args: Cli) {
Commands::Run(m) => run::execute(m).await,
Commands::Sign(m) => sign::execute(m),
Commands::Upgrade(m) => upgrade::execute(m).await,
Commands::Completions(s) => s.generate(&mut crate::Cli::command(), bin_name),
Commands::GenerateFigSpec => fig_generate(&mut crate::Cli::command(), bin_name),
Commands::Completions(s) => s.generate(&mut crate::Cli::into_app(), bin_name),
Commands::GenerateFigSpec => fig_generate(&mut crate::Cli::into_app(), bin_name),
}
}
@@ -105,8 +103,12 @@ pub(crate) fn override_config(mut config: Config, args: OverrideConfig) -> Confi
config = config.with_enabled_statistics(enabled_statistics);
}
if let Some(url) = args.statistics_service_url {
config = config.with_custom_statistics_service_url(url);
if let Some(raw_url) = args.statistics_service_url {
config = config.with_custom_statistics_service_url(
raw_url
.parse()
.expect("the provided statistics service url is invalid!"),
);
} else if std::env::var(CONFIGURED).is_ok() {
if let Some(raw_url) = read_var_if_not_default(STATISTICS_SERVICE_DOMAIN_ADDRESS) {
config = config.with_custom_statistics_service_url(
@@ -117,18 +119,26 @@ pub(crate) fn override_config(mut config: Config, args: OverrideConfig) -> Confi
}
}
if let Some(nym_apis) = args.nym_apis {
config = config.with_custom_nym_apis(nym_apis);
if let Some(raw_validators) = args.nym_apis {
config = config.with_custom_nym_apis(parse_validators(&raw_validators));
} else if std::env::var(CONFIGURED).is_ok() {
if let Some(raw_validators) = read_var_if_not_default(API_VALIDATOR) {
config = config.with_custom_nym_apis(::config::parse_urls(&raw_validators))
config = config.with_custom_nym_apis(::config::parse_validators(&raw_validators))
}
}
if let Some(ref raw_validators) = args.validators {
config = config.with_custom_validator_nymd(parse_validators(raw_validators));
} else if std::env::var(CONFIGURED).is_ok() {
if let Some(raw_validators) = read_var_if_not_default(NYMD_VALIDATOR) {
config = config.with_custom_validator_nymd(::config::parse_validators(&raw_validators))
}
}
if let Some(wallet_address) = args.wallet_address {
// perform extra validation to ensure we have correct prefix
validate_bech32_address_or_exit(wallet_address.as_ref());
config = config.with_wallet_address(wallet_address);
let trimmed = wallet_address.trim();
validate_bech32_address_or_exit(trimmed);
config = config.with_wallet_address(trimmed);
}
if let Some(datastore_path) = args.datastore {
@@ -136,20 +146,13 @@ pub(crate) fn override_config(mut config: Config, args: OverrideConfig) -> Confi
}
if let Some(cosmos_mnemonic) = args.mnemonic {
config = config.with_cosmos_mnemonic(cosmos_mnemonic);
config = config.with_cosmos_mnemonic(
bip39::Mnemonic::from_str(&cosmos_mnemonic).expect("Provided mnemonic is invalid"),
);
}
#[cfg(feature = "coconut")]
{
use network_defaults::var_names::NYMD_VALIDATOR;
if let Some(nymd_validators) = args.nymd_validators {
config = config.with_custom_validator_nymd(nymd_validators);
} else if std::env::var(CONFIGURED).is_ok() {
if let Some(raw_validators) = read_var_if_not_default(NYMD_VALIDATOR) {
config = config.with_custom_validator_nymd(::config::parse_urls(&raw_validators))
}
}
config = config.with_only_coconut_credentials(args.only_coconut_credentials);
}
+15 -23
View File
@@ -1,4 +1,4 @@
// Copyright 2020-2023 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2020 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::{
@@ -8,9 +8,6 @@ use crate::{
use clap::Args;
use config::NymConfig;
use log::*;
use std::net::IpAddr;
use std::path::PathBuf;
use validator_client::nymd;
#[derive(Args, Clone)]
pub struct Run {
@@ -20,11 +17,11 @@ pub struct Run {
/// The custom host on which the gateway will be running for receiving sphinx packets
#[clap(long)]
host: Option<IpAddr>,
host: Option<String>,
/// The wallet address you will use to bond this gateway, e.g. nymt1z9egw0knv47nmur0p8vk4rcx59h9gg4zuxrrr9
#[clap(long)]
wallet_address: Option<nymd::AccountId>,
wallet_address: Option<String>,
/// The port on which the gateway will be listening for sphinx packets
#[clap(long)]
@@ -36,27 +33,23 @@ pub struct Run {
/// The host that will be reported to the directory server
#[clap(long)]
// TODO: could this be changed to `Option<url::Url>`?
announce_host: Option<String>,
/// Path to sqlite database containing all gateway persistent data
#[clap(long)]
datastore: Option<PathBuf>,
datastore: Option<String>,
/// Comma separated list of endpoints of nym APIs
#[clap(long, alias = "validator_apis", value_delimiter = ',')]
// the alias here is included for backwards compatibility (1.1.4 and before)
nym_apis: Option<Vec<url::Url>>,
/// Comma separated list of endpoints of the nym APIs
#[clap(long)]
nym_apis: Option<String>,
/// Comma separated list of endpoints of the validator
#[cfg(feature = "coconut")]
#[clap(long, alias = "validators", value_delimiter = ',')]
// the alias here is included for backwards compatibility (1.1.4 and before)
nymd_validators: Option<Vec<url::Url>>,
#[clap(long)]
validators: Option<String>,
/// Cosmos wallet mnemonic
#[clap(long)]
mnemonic: Option<bip39::Mnemonic>,
mnemonic: Option<String>,
/// Set this gateway to work only with coconut credentials; that would disallow clients to
/// bypass bandwidth credential requirement
@@ -70,7 +63,7 @@ pub struct Run {
/// URL where a statistics aggregator is running. The default value is a Nym aggregator server
#[clap(long)]
statistics_service_url: Option<url::Url>,
statistics_service_url: Option<String>,
}
impl From<Run> for OverrideConfig {
@@ -83,15 +76,14 @@ impl From<Run> for OverrideConfig {
datastore: run_config.datastore,
announce_host: run_config.announce_host,
nym_apis: run_config.nym_apis,
validators: run_config.validators,
mnemonic: run_config.mnemonic,
#[cfg(feature = "coconut")]
only_coconut_credentials: run_config.only_coconut_credentials,
enabled_statistics: run_config.enabled_statistics,
statistics_service_url: run_config.statistics_service_url,
#[cfg(feature = "coconut")]
nymd_validators: run_config.nymd_validators,
#[cfg(feature = "coconut")]
only_coconut_credentials: run_config.only_coconut_credentials,
}
}
}
+15 -14
View File
@@ -1,9 +1,8 @@
// Copyright 2020-2023 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2020 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::commands::validate_bech32_address_or_exit;
use crate::{
commands::version_check,
commands::{validate_bech32_address_or_exit, version_check},
config::{persistence::pathfinder::GatewayPathfinder, Config},
};
use anyhow::{anyhow, Result};
@@ -11,10 +10,9 @@ use clap::{ArgGroup, Args};
use config::NymConfig;
use crypto::asymmetric::identity;
use log::error;
use validator_client::nymd;
#[derive(Args, Clone)]
#[clap(group(ArgGroup::new("sign").required(true).args(&["wallet_address", "text"])))]
#[clap(group(ArgGroup::new("sign").required(true).args(&["address", "text"])))]
pub struct Sign {
/// The id of the mixnode you want to sign with
#[clap(long)]
@@ -22,7 +20,7 @@ pub struct Sign {
/// Signs your blockchain address with your identity key
#[clap(long)]
wallet_address: Option<nymd::AccountId>,
address: Option<String>,
/// Signs an arbitrary piece of text with your identity key
#[clap(long)]
@@ -31,7 +29,7 @@ pub struct Sign {
enum SignedTarget {
Text(String),
Address(nymd::AccountId),
Address(String),
}
impl TryFrom<Sign> for SignedTarget {
@@ -40,7 +38,7 @@ impl TryFrom<Sign> for SignedTarget {
fn try_from(args: Sign) -> Result<Self, Self::Error> {
if let Some(text) = args.text {
Ok(SignedTarget::Text(text))
} else if let Some(address) = args.wallet_address {
} else if let Some(address) = args.address {
Ok(SignedTarget::Address(address))
} else {
// This is unreachable, and hopefully clap will support it explicitly by outputting an
@@ -60,12 +58,15 @@ pub fn load_identity_keys(pathfinder: &GatewayPathfinder) -> identity::KeyPair {
identity_keypair
}
fn print_signed_address(private_key: &identity::PrivateKey, wallet_address: nymd::AccountId) {
// perform extra validation to ensure we have correct prefix
validate_bech32_address_or_exit(wallet_address.as_ref());
fn print_signed_address(private_key: &identity::PrivateKey, raw_address: &str) {
let trimmed = raw_address.trim();
validate_bech32_address_or_exit(trimmed);
let signature = private_key.sign_text(trimmed);
let signature = private_key.sign_text(wallet_address.as_ref());
println!("The base58-encoded signature on '{wallet_address}' is: {signature}",);
println!(
"The base58-encoded signature on '{}' is: {}",
trimmed, signature
);
}
fn print_signed_text(private_key: &identity::PrivateKey, text: &str) {
@@ -112,6 +113,6 @@ pub fn execute(args: &Sign) {
match signed_target {
SignedTarget::Text(text) => print_signed_text(identity_keypair.private_key(), &text),
SignedTarget::Address(addr) => print_signed_address(identity_keypair.private_key(), addr),
SignedTarget::Address(addr) => print_signed_address(identity_keypair.private_key(), &addr),
}
}
+1 -1
View File
@@ -103,7 +103,7 @@ fn minor_0_12_upgrade(
print_start_upgrade(config_version, &to_version);
let upgraded_config = config.with_custom_version(to_version.to_string());
let upgraded_config = config.with_custom_version(to_version.to_string().as_ref());
upgraded_config.save_to_file(None).unwrap_or_else(|err| {
eprintln!("failed to overwrite config file! - {err}");
+21 -15
View File
@@ -4,6 +4,7 @@
use crate::config::template::config_template;
use config::defaults::{DEFAULT_CLIENT_LISTENING_PORT, DEFAULT_MIX_LISTENING_PORT};
use config::NymConfig;
use log::error;
use network_defaults::mainnet::{API_VALIDATOR, NYMD_VALIDATOR, STATISTICS_SERVICE_DOMAIN_ADDRESS};
use serde::{Deserialize, Serialize};
use std::net::IpAddr;
@@ -11,7 +12,6 @@ use std::path::PathBuf;
use std::str::FromStr;
use std::time::Duration;
use url::Url;
use validator_client::nymd;
pub mod persistence;
mod template;
@@ -149,7 +149,6 @@ impl Config {
self
}
#[cfg(feature = "coconut")]
pub fn with_custom_validator_nymd(mut self, validator_nymd_urls: Vec<Url>) -> Self {
self.gateway.validator_nymd_urls = validator_nymd_urls;
self
@@ -160,8 +159,16 @@ impl Config {
self
}
pub fn with_listening_address(mut self, listening_address: IpAddr) -> Self {
self.gateway.listening_address = listening_address;
pub fn with_listening_address<S: Into<String>>(mut self, listening_address: S) -> Self {
let listening_address_string = listening_address.into();
if let Ok(ip_addr) = listening_address_string.parse() {
self.gateway.listening_address = ip_addr;
} else {
error!(
"failed to change listening address. the provided value ({}) was invalid",
listening_address_string
);
}
self
}
@@ -185,18 +192,18 @@ impl Config {
self
}
pub fn with_custom_persistent_store(mut self, store_dir: PathBuf) -> Self {
self.gateway.persistent_storage = store_dir;
pub fn with_custom_persistent_store<S: Into<String>>(mut self, store_dir: S) -> Self {
self.gateway.persistent_storage = PathBuf::from(store_dir.into());
self
}
pub fn with_custom_version<S: Into<String>>(mut self, version: S) -> Self {
self.gateway.version = version.into();
pub fn with_custom_version(mut self, version: &str) -> Self {
self.gateway.version = version.to_string();
self
}
pub fn with_wallet_address(mut self, wallet_address: nymd::AccountId) -> Self {
self.gateway.wallet_address = Some(wallet_address);
pub fn with_wallet_address(mut self, wallet_address: &str) -> Self {
self.gateway.wallet_address = wallet_address.to_string();
self
}
@@ -295,8 +302,8 @@ impl Config {
&self.gateway.version
}
pub fn get_wallet_address(&self) -> Option<nymd::AccountId> {
self.gateway.wallet_address.clone()
pub fn get_wallet_address(&self) -> &str {
&self.gateway.wallet_address
}
}
@@ -370,8 +377,7 @@ pub struct Gateway {
persistent_storage: PathBuf,
/// The Cosmos wallet address that will control this gateway
// the only reason this is an Option is because of the lack of existence of a sane default value
wallet_address: Option<nymd::AccountId>,
wallet_address: String,
}
impl Gateway {
@@ -417,7 +423,7 @@ impl Default for Gateway {
cosmos_mnemonic: bip39::Mnemonic::from_str("exact antique hybrid width raise anchor puzzle degree fee quit long crack net vague hip despair write put useless civil mechanic broom music day").unwrap(),
nym_root_directory: Config::default_root_directory(),
persistent_storage: Default::default(),
wallet_address: None,
wallet_address: "nymXXXXXXXX".to_string(),
}
}
}
+44 -11
View File
@@ -1,28 +1,24 @@
// Copyright 2020 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use build_information::BinaryBuildInformation;
use clap::{crate_version, Parser};
use lazy_static::lazy_static;
use logging::setup_logging;
use network_defaults::setup_env;
use once_cell::sync::OnceCell;
mod commands;
mod config;
mod node;
lazy_static! {
pub static ref PRETTY_BUILD_INFORMATION: String =
BinaryBuildInformation::new(env!("CARGO_PKG_VERSION")).pretty_print();
}
static LONG_VERSION: OnceCell<String> = OnceCell::new();
// Helper for passing LONG_VERSION to clap
fn pretty_build_info_static() -> &'static str {
&PRETTY_BUILD_INFORMATION
// Helper for passing LONG_ABOUT to clap
fn long_version_static() -> &'static str {
LONG_VERSION.get().expect("Failed to get long about text")
}
#[derive(Parser)]
#[clap(author = "Nymtech", version, about, long_version = pretty_build_info_static())]
#[clap(author = "Nymtech", version, about, long_version = long_version_static())]
struct Cli {
/// Path pointing to an env file that configures the gateway.
#[clap(short, long)]
@@ -36,9 +32,12 @@ struct Cli {
async fn main() {
setup_logging();
println!("{}", banner());
LONG_VERSION
.set(long_version())
.expect("Failed to set long about text");
let args = Cli::parse();
setup_env(args.config_env_file.as_ref());
setup_env(args.config_env_file.clone());
commands::execute(args).await;
}
@@ -59,6 +58,37 @@ fn banner() -> String {
)
}
fn long_version() -> String {
format!(
r#"
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
"#,
"Build Timestamp:",
env!("VERGEN_BUILD_TIMESTAMP"),
"Build Version:",
env!("VERGEN_BUILD_SEMVER"),
"Commit SHA:",
env!("VERGEN_GIT_SHA"),
"Commit Date:",
env!("VERGEN_GIT_COMMIT_TIMESTAMP"),
"Commit Branch:",
env!("VERGEN_GIT_BRANCH"),
"rustc Version:",
env!("VERGEN_RUSTC_SEMVER"),
"rustc Channel:",
env!("VERGEN_RUSTC_CHANNEL"),
"cargo Profile:",
env!("VERGEN_CARGO_PROFILE")
)
}
#[cfg(test)]
mod tests {
use super::*;
@@ -66,6 +96,9 @@ mod tests {
#[test]
fn verify_cli() {
LONG_VERSION
.set(long_version())
.expect("Failed to set long about text");
Cli::command().debug_assert();
}
}
+9 -15
View File
@@ -1,20 +1,19 @@
// Copyright 2020-2023 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2020 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use self::storage::PersistentStorage;
use crate::commands::sign::load_identity_keys;
use crate::commands::validate_bech32_address_or_exit;
use crate::config::persistence::pathfinder::GatewayPathfinder;
use crate::config::Config;
use crate::node::client_handling::active_clients::ActiveClientsStore;
use crate::node::client_handling::websocket;
use crate::node::mixnet_handling::receiver::connection_handler::ConnectionHandler;
use crate::node::statistics::collector::GatewayStatisticsCollector;
use crate::node::storage::Storage;
use colored::Colorize;
use crypto::asymmetric::{encryption, identity};
use log::*;
use mixnet_client::forwarder::{MixForwardingSender, PacketForwarder};
#[cfg(feature = "coconut")]
use network_defaults::NymNetworkDetails;
use rand::seq::SliceRandom;
use rand::thread_rng;
use statistics_common::collector::StatisticsSender;
@@ -22,15 +21,16 @@ use std::net::SocketAddr;
use std::process;
use std::sync::Arc;
use crate::config::persistence::pathfinder::GatewayPathfinder;
#[cfg(feature = "coconut")]
use crate::node::client_handling::websocket::connection_handler::coconut::CoconutVerifier;
#[cfg(feature = "coconut")]
use credentials::coconut::utils::obtain_aggregate_verification_key;
#[cfg(feature = "coconut")]
use network_defaults::NymNetworkDetails;
#[cfg(feature = "coconut")]
use validator_client::{Client, CoconutApiClient};
use self::storage::PersistentStorage;
pub(crate) mod client_handling;
pub(crate) mod mixnet_handling;
pub(crate) mod statistics;
@@ -117,15 +117,9 @@ where
fn generate_owner_signature(&self) -> String {
let pathfinder = GatewayPathfinder::new_from_config(&self.config);
let identity_keypair = load_identity_keys(&pathfinder);
let Some(address) = self.config.get_wallet_address() else {
let error_message = "Error: gateway hasn't set its wallet address".red();
println!("{error_message}");
println!("Exiting...");
process::exit(1);
};
// perform extra validation to ensure we have correct prefix
validate_bech32_address_or_exit(address.as_ref());
let verification_code = identity_keypair.private_key().sign_text(address.as_ref());
let address = self.config.get_wallet_address();
validate_bech32_address_or_exit(address);
let verification_code = identity_keypair.private_key().sign_text(address);
verification_code
}
+5 -3
View File
@@ -3,7 +3,7 @@
[package]
name = "nym-mixnode"
version = "1.1.4"
version = "1.1.3"
authors = [
"Dave Hrycyszyn <futurechimp@users.noreply.github.com>",
"Jędrzej Stuczyński <andrew@nymtech.net>",
@@ -18,7 +18,7 @@ rust-version = "1.58.1"
[dependencies]
anyhow = "1.0.40"
bs58 = "0.4.0"
clap = { version = "4.0", features = ["cargo", "derive"] }
clap = { version = "3.2", features = ["cargo", "derive"] }
colored = "2.0"
cupid = "0.6.1"
dirs = "4.0"
@@ -38,7 +38,6 @@ toml = "0.5.8"
url = { version = "2.2", features = ["serde"] }
## internal
build-information = { path = "../common/build-information" }
config = { path="../common/config" }
crypto = { path="../common/crypto" }
completions = { path="../common/completions" }
@@ -58,3 +57,6 @@ tokio = { version="1.21.2", features = ["rt-multi-thread", "net", "signal", "tes
nymsphinx-types = { path = "../common/nymsphinx/types" }
nymsphinx-params = { path = "../common/nymsphinx/params" }
[build-dependencies]
vergen = { version = "5", default-features = false, features = ["build", "git", "rustc", "cargo"] }
+8
View File
@@ -0,0 +1,8 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use vergen::{vergen, Config};
fn main() {
vergen(Config::default()).expect("failed to extract build metadata")
}
+24 -46
View File
@@ -1,6 +1,3 @@
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::config::Config;
use crate::node::node_description::NodeDescription;
use clap::Args;
@@ -14,32 +11,9 @@ pub(crate) struct Describe {
/// The id of the mixnode you want to describe
#[clap(long)]
id: String,
/// Human readable name of this node
#[clap(long)]
name: Option<String>,
/// Description of this node
#[clap(long)]
description: Option<String>,
/// Link associated with this node, for example `https://mixnode.yourdomain.com`
#[clap(long)]
link: Option<String>,
/// Physical location of this node, for example `City: London, Country: UK`
#[clap(long)]
location: Option<String>,
}
fn read_user_input() -> String {
io::stdout().flush().unwrap();
let mut buf = String::new();
io::stdin().read_line(&mut buf).unwrap();
buf.trim().to_string()
}
pub(crate) fn execute(args: Describe) {
pub(crate) fn execute(args: &Describe) {
// ensure that the mixnode has in fact been initialized
match Config::load_from_file(Some(&args.id)) {
Ok(cfg) => cfg,
@@ -49,29 +23,33 @@ pub(crate) fn execute(args: Describe) {
}
};
// get input from the user
print!("name: ");
io::stdout().flush().unwrap();
let mut name_buf = String::new();
io::stdin().read_line(&mut name_buf).unwrap();
let name = name_buf.trim().to_string();
print!("description: ");
io::stdout().flush().unwrap();
let mut desc_buf = String::new();
io::stdin().read_line(&mut desc_buf).unwrap();
let description = desc_buf.trim().to_string();
let example_url = "https://mixnode.yourdomain.com".bright_cyan();
let example_location = "City: London, Country: UK";
// get input from the user if not provided via the arguments
let name = args.name.unwrap_or_else(|| {
print!("name: ");
read_user_input()
});
print!("link, e.g. {}: ", example_url);
io::stdout().flush().unwrap();
let mut link_buf = String::new();
io::stdin().read_line(&mut link_buf).unwrap();
let link = link_buf.trim().to_string();
let description = args.description.unwrap_or_else(|| {
print!("description: ");
read_user_input()
});
let link = args.link.unwrap_or_else(|| {
print!("link, e.g. {example_url}: ");
read_user_input()
});
let location = args.location.unwrap_or_else(|| {
print!("location, e.g. {example_location}: ");
read_user_input()
});
print!("location, e.g. {}: ", example_location);
io::stdout().flush().unwrap();
let mut location_buf = String::new();
io::stdin().read_line(&mut location_buf).unwrap();
let location = location_buf.trim().to_string();
let node_description = NodeDescription {
name,
+9 -11
View File
@@ -1,15 +1,14 @@
// Copyright 2020-2023 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2020 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use super::OverrideConfig;
use crate::config::Config;
use crate::node::MixNode;
use crate::{commands::override_config, config::persistence::pathfinder::MixNodePathfinder};
use clap::Args;
use config::NymConfig;
use crypto::asymmetric::{encryption, identity};
use std::net::IpAddr;
use validator_client::nymd;
use super::OverrideConfig;
#[derive(Args, Clone)]
pub(crate) struct Init {
@@ -19,11 +18,11 @@ pub(crate) struct Init {
/// The host on which the mixnode will be running
#[clap(long)]
host: IpAddr,
host: String,
/// The wallet address you will use to bond this mixnode, e.g. nymt1z9egw0knv47nmur0p8vk4rcx59h9gg4zuxrrr9
#[clap(long)]
wallet_address: nymd::AccountId,
wallet_address: String,
/// The port on which the mixnode will be listening for mix packets
#[clap(long)]
@@ -41,10 +40,9 @@ pub(crate) struct Init {
#[clap(long)]
announce_host: Option<String>,
/// Comma separated list of nym-api endpoints of the validators
// the alias here is included for backwards compatibility (1.1.4 and before)
#[clap(long, alias = "validators", value_delimiter = ',')]
nym_apis: Option<Vec<url::Url>>,
/// Comma separated list of rest endpoints of the validators
#[clap(long)]
validators: Option<String>,
}
impl From<Init> for OverrideConfig {
@@ -57,7 +55,7 @@ impl From<Init> for OverrideConfig {
verloc_port: init_config.verloc_port,
http_api_port: init_config.http_api_port,
announce_host: init_config.announce_host,
nym_apis: init_config.nym_apis,
validators: init_config.validators,
}
}
}
+24 -22
View File
@@ -1,17 +1,19 @@
// Copyright 2020 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use std::process;
use crate::{config::Config, Cli};
use clap::CommandFactory;
use clap::Subcommand;
use colored::Colorize;
use completions::{fig_generate, ArgShell};
use config::defaults::mainnet::read_var_if_not_default;
use config::defaults::var_names::{API_VALIDATOR, BECH32_PREFIX, CONFIGURED};
use config::{
defaults::var_names::{API_VALIDATOR, BECH32_PREFIX, CONFIGURED},
parse_validators,
};
use crypto::bech32_address_validation;
use std::net::IpAddr;
use std::process;
use validator_client::nymd;
mod describe;
mod init;
@@ -50,27 +52,27 @@ pub(crate) enum Commands {
// Configuration that can be overridden.
struct OverrideConfig {
id: String,
host: Option<IpAddr>,
wallet_address: Option<nymd::AccountId>,
host: Option<String>,
wallet_address: Option<String>,
mix_port: Option<u16>,
verloc_port: Option<u16>,
http_api_port: Option<u16>,
announce_host: Option<String>,
nym_apis: Option<Vec<url::Url>>,
validators: Option<String>,
}
pub(crate) async fn execute(args: Cli) {
let bin_name = "nym-mixnode";
match args.command {
match &args.command {
Commands::Describe(m) => describe::execute(m),
Commands::Init(m) => init::execute(&m),
Commands::Run(m) => run::execute(&m).await,
Commands::Sign(m) => sign::execute(&m),
Commands::Upgrade(m) => upgrade::execute(&m),
Commands::NodeDetails(m) => node_details::execute(&m),
Commands::Completions(s) => s.generate(&mut crate::Cli::command(), bin_name),
Commands::GenerateFigSpec => fig_generate(&mut crate::Cli::command(), bin_name),
Commands::Init(m) => init::execute(m),
Commands::Run(m) => run::execute(m).await,
Commands::Sign(m) => sign::execute(m),
Commands::Upgrade(m) => upgrade::execute(m),
Commands::NodeDetails(m) => node_details::execute(m),
Commands::Completions(s) => s.generate(&mut crate::Cli::into_app(), bin_name),
Commands::GenerateFigSpec => fig_generate(&mut crate::Cli::into_app(), bin_name),
}
}
@@ -93,11 +95,11 @@ fn override_config(mut config: Config, args: OverrideConfig) -> Config {
config = config.with_http_api_port(port);
}
if let Some(nym_apis) = args.nym_apis {
config = config.with_custom_nym_apis(nym_apis);
if let Some(ref raw_validators) = args.validators {
config = config.with_custom_nym_apis(parse_validators(raw_validators));
} else if std::env::var(CONFIGURED).is_ok() {
if let Some(raw_validators) = read_var_if_not_default(API_VALIDATOR) {
config = config.with_custom_nym_apis(::config::parse_urls(&raw_validators))
config = config.with_custom_nym_apis(::config::parse_validators(&raw_validators))
}
}
@@ -108,10 +110,10 @@ fn override_config(mut config: Config, args: OverrideConfig) -> Config {
config = config.announce_address_from_listening_address()
}
if let Some(wallet_address) = args.wallet_address {
// perform extra validation to ensure we have correct prefix
validate_bech32_address_or_exit(wallet_address.as_ref());
config = config.with_wallet_address(wallet_address);
if let Some(ref wallet_address) = args.wallet_address {
let trimmed = wallet_address.trim();
validate_bech32_address_or_exit(trimmed);
config = config.with_wallet_address(trimmed);
}
config
+8 -10
View File
@@ -1,14 +1,13 @@
// Copyright 2020 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use super::OverrideConfig;
use crate::commands::{override_config, version_check};
use crate::config::Config;
use crate::node::MixNode;
use clap::Args;
use config::NymConfig;
use std::net::IpAddr;
use validator_client::nymd;
use super::OverrideConfig;
#[derive(Args, Clone)]
pub(crate) struct Run {
@@ -18,11 +17,11 @@ pub(crate) struct Run {
/// The custom host on which the mixnode will be running
#[clap(long)]
host: Option<IpAddr>,
host: Option<String>,
/// The wallet address you will use to bond this mixnode, e.g. nymt1z9egw0knv47nmur0p8vk4rcx59h9gg4zuxrrr9
#[clap(long)]
wallet_address: Option<nymd::AccountId>,
wallet_address: Option<String>,
/// The port on which the mixnode will be listening for mix packets
#[clap(long)]
@@ -40,10 +39,9 @@ pub(crate) struct Run {
#[clap(long)]
announce_host: Option<String>,
/// Comma separated list of nym-api endpoints of the validators
// the alias here is included for backwards compatibility (1.1.4 and before)
#[clap(long, alias = "validators", value_delimiter = ',')]
nym_apis: Option<Vec<url::Url>>,
/// Comma separated list of rest endpoints of the validators
#[clap(long)]
validators: Option<String>,
}
impl From<Run> for OverrideConfig {
@@ -56,7 +54,7 @@ impl From<Run> for OverrideConfig {
verloc_port: run_config.verloc_port,
http_api_port: run_config.http_api_port,
announce_host: run_config.announce_host,
nym_apis: run_config.nym_apis,
validators: run_config.validators,
}
}
}
+15 -14
View File
@@ -1,4 +1,4 @@
// Copyright 2020-2023 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2020 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use std::convert::TryFrom;
@@ -11,21 +11,19 @@ use clap::{ArgGroup, Args};
use config::NymConfig;
use crypto::asymmetric::identity;
use log::error;
use validator_client::nymd;
use super::version_check;
#[derive(Args, Clone)]
#[clap(group(ArgGroup::new("sign").required(true).args(&["wallet_address", "text"])))]
#[clap(group(ArgGroup::new("sign").required(true).args(&["address", "text"])))]
pub(crate) struct Sign {
/// The id of the mixnode you want to sign with
#[clap(long)]
id: String,
/// Signs your blockchain address with your identity key
// the alias here is included for backwards compatibility (1.1.4 and before)
#[clap(long, alias = "address")]
wallet_address: Option<nymd::AccountId>,
#[clap(long)]
address: Option<String>,
/// Signs an arbitrary piece of text with your identity key
#[clap(long)]
@@ -34,7 +32,7 @@ pub(crate) struct Sign {
enum SignedTarget {
Text(String),
Address(nymd::AccountId),
Address(String),
}
impl TryFrom<Sign> for SignedTarget {
@@ -43,7 +41,7 @@ impl TryFrom<Sign> for SignedTarget {
fn try_from(args: Sign) -> Result<Self, Self::Error> {
if let Some(text) = args.text {
Ok(SignedTarget::Text(text))
} else if let Some(address) = args.wallet_address {
} else if let Some(address) = args.address {
Ok(SignedTarget::Address(address))
} else {
// This is unreachable, and hopefully clap will support it explicitly by outputting an
@@ -54,12 +52,15 @@ impl TryFrom<Sign> for SignedTarget {
}
}
fn print_signed_address(private_key: &identity::PrivateKey, wallet_address: nymd::AccountId) {
// perform extra validation to ensure we have correct prefix
validate_bech32_address_or_exit(wallet_address.as_ref());
fn print_signed_address(private_key: &identity::PrivateKey, raw_address: &str) {
let trimmed = raw_address.trim();
validate_bech32_address_or_exit(trimmed);
let signature = private_key.sign_text(trimmed);
let signature = private_key.sign_text(wallet_address.as_ref());
println!("The base58-encoded signature on '{wallet_address}' is: {signature}",);
println!(
"The base58-encoded signature on '{}' is: {}",
trimmed, signature
);
}
fn print_signed_text(private_key: &identity::PrivateKey, text: &str) {
@@ -106,6 +107,6 @@ pub(crate) fn execute(args: &Sign) {
match signed_target {
SignedTarget::Text(text) => print_signed_text(identity_keypair.private_key(), &text),
SignedTarget::Address(addr) => print_signed_address(identity_keypair.private_key(), addr),
SignedTarget::Address(addr) => print_signed_address(identity_keypair.private_key(), &addr),
}
}
+16 -10
View File
@@ -13,7 +13,6 @@ use std::path::PathBuf;
use std::str::FromStr;
use std::time::Duration;
use url::Url;
use validator_client::nymd;
pub mod persistence;
mod template;
@@ -161,8 +160,16 @@ impl Config {
self
}
pub fn with_listening_address(mut self, listening_address: IpAddr) -> Self {
self.mixnode.listening_address = listening_address;
pub fn with_listening_address<S: Into<String>>(mut self, listening_address: S) -> Self {
let listening_address_string = listening_address.into();
if let Ok(ip_addr) = listening_address_string.parse() {
self.mixnode.listening_address = ip_addr
} else {
error!(
"failed to change listening address. the provided value ({}) was invalid",
listening_address_string
)
}
self
}
@@ -196,8 +203,8 @@ impl Config {
self
}
pub fn with_wallet_address(mut self, wallet_address: nymd::AccountId) -> Self {
self.mixnode.wallet_address = Some(wallet_address);
pub fn with_wallet_address(mut self, wallet_address: &str) -> Self {
self.mixnode.wallet_address = wallet_address.to_string();
self
}
@@ -310,8 +317,8 @@ impl Config {
self.verloc.retry_timeout
}
pub fn get_wallet_address(&self) -> Option<nymd::AccountId> {
self.mixnode.wallet_address.clone()
pub fn get_wallet_address(&self) -> &str {
&self.mixnode.wallet_address
}
}
@@ -370,8 +377,7 @@ struct MixNode {
nym_root_directory: PathBuf,
/// The Cosmos wallet address that will control this mixnode
// the only reason this is an Option is because of the lack of existence of a sane default value
wallet_address: Option<nymd::AccountId>,
wallet_address: String,
}
impl MixNode {
@@ -408,7 +414,7 @@ impl Default for MixNode {
public_sphinx_key_file: Default::default(),
nym_api_urls: vec![Url::from_str(API_VALIDATOR).expect("Invalid default API URL")],
nym_root_directory: Config::default_root_directory(),
wallet_address: None,
wallet_address: "nymXXXXXXXX".to_string(),
}
}
}
+39 -10
View File
@@ -1,11 +1,10 @@
// Copyright 2020-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
#[macro_use]
extern crate rocket;
// Copyright 2020 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use ::config::defaults::setup_env;
use build_information::BinaryBuildInformation;
use clap::{crate_version, Parser};
use lazy_static::lazy_static;
use logging::setup_logging;
@@ -15,17 +14,16 @@ mod config;
mod node;
lazy_static! {
pub static ref PRETTY_BUILD_INFORMATION: String =
BinaryBuildInformation::new(env!("CARGO_PKG_VERSION")).pretty_print();
pub static ref LONG_VERSION: String = long_version();
}
// Helper for passing LONG_VERSION to clap
fn pretty_build_info_static() -> &'static str {
&PRETTY_BUILD_INFORMATION
fn long_version_static() -> &'static str {
&LONG_VERSION
}
#[derive(Parser)]
#[clap(author = "Nymtech", version, about, long_version = pretty_build_info_static())]
#[clap(author = "Nymtech", version, about, long_version = long_version_static())]
struct Cli {
/// Path pointing to an env file that configures the mixnode.
#[clap(short, long)]
@@ -41,7 +39,7 @@ async fn main() {
println!("{}", banner());
let args = Cli::parse();
setup_env(args.config_env_file.as_ref());
setup_env(args.config_env_file.clone());
commands::execute(args).await;
}
@@ -62,6 +60,37 @@ fn banner() -> String {
)
}
fn long_version() -> String {
format!(
r#"
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
"#,
"Build Timestamp:",
env!("VERGEN_BUILD_TIMESTAMP"),
"Build Version:",
env!("VERGEN_BUILD_SEMVER"),
"Commit SHA:",
env!("VERGEN_GIT_SHA"),
"Commit Date:",
env!("VERGEN_GIT_COMMIT_TIMESTAMP"),
"Commit Branch:",
env!("VERGEN_GIT_BRANCH"),
"rustc Version:",
env!("VERGEN_RUSTC_SEMVER"),
"rustc Channel:",
env!("VERGEN_RUSTC_CHANNEL"),
"cargo Profile:",
env!("VERGEN_CARGO_PROFILE")
)
}
#[cfg(test)]
mod tests {
use super::*;
+4 -14
View File
@@ -18,7 +18,6 @@ use crate::node::node_description::NodeDescription;
use crate::node::node_statistics::SharedNodeStats;
use crate::node::packet_delayforwarder::{DelayForwarder, PacketDelayForwardSender};
use ::crypto::asymmetric::{encryption, identity};
use colored::Colorize;
use config::NymConfig;
use log::{error, info, warn};
use mixnode_common::verloc::{self, AtomicVerlocResult, VerlocMeasurer};
@@ -88,15 +87,9 @@ impl MixNode {
fn generate_owner_signature(&self) -> String {
let pathfinder = MixNodePathfinder::new_from_config(&self.config);
let identity_keypair = Self::load_identity_keys(&pathfinder);
let Some(address) = self.config.get_wallet_address() else {
let error_message = "Error: mixnode hasn't set its wallet address".red();
println!("{error_message}");
println!("Exiting...");
process::exit(1);
};
// perform extra validation to ensure we have correct prefix
validate_bech32_address_or_exit(address.as_ref());
let verification_code = identity_keypair.private_key().sign_text(address.as_ref());
let address = self.config.get_wallet_address();
validate_bech32_address_or_exit(address);
let verification_code = identity_keypair.private_key().sign_text(address);
verification_code
}
@@ -125,10 +118,7 @@ impl MixNode {
);
println!(
"You are bonding to wallet address: {}\n\n",
self.config
.get_wallet_address()
.map(|addr| addr.to_string())
.unwrap_or_else(|| "UNSPECIFIED".to_string())
self.config.get_wallet_address()
);
}
+9 -6
View File
@@ -2,8 +2,8 @@
# SPDX-License-Identifier: Apache-2.0
[package]
name = "nym-api"
version = "1.1.4"
name = "nym-validator-api"
version = "1.1.3"
authors = [
"Dave Hrycyszyn <futurechimp@users.noreply.github.com>",
"Jędrzej Stuczyński <andrew@nymtech.net>",
@@ -17,15 +17,13 @@ rust-version = "1.56"
[dependencies]
async-trait = "0.1.52"
bs58 = {version = "0.4.0", optional = true }
bip39 = "1"
cfg-if = "1.0"
clap = { version = "4.0", features = ["cargo", "derive"] }
clap = { version = "3.2", features = ["cargo"] }
console-subscriber = { version = "0.1.1", optional = true } # validator-api needs to be built with RUSTFLAGS="--cfg tokio_unstable"
dirs = "4.0"
dotenv = "0.15.0"
futures = "0.3.24"
humantime-serde = "1.0"
lazy_static = "1.4.0"
log = "0.4.17"
pin-project = "1.0"
pretty_env_logger = "0.4.0"
@@ -65,7 +63,6 @@ rocket_okapi = { version = "0.8.0-rc.2", features = ["swagger"] }
schemars = { version = "0.8", features = ["preserve_order"] }
## internal
build-information = { path = "../common/build-information" }
coconut-bandwidth-contract-common = { path = "../common/cosmwasm-smart-contracts/coconut-bandwidth-contract" }
coconut-dkg-common = { path = "../common/cosmwasm-smart-contracts/coconut-dkg", optional = true }
coconut-interface = { path = "../common/coconut-interface", optional = true }
@@ -118,6 +115,12 @@ sqlx = { version = "0.6.2", features = [
"macros",
"migrate",
] }
vergen = { version = "7", default-features = false, features = [
"build",
"git",
"rustc",
"cargo",
] }
[dev-dependencies]
cw3 = "0.13.4"
+3
View File
@@ -1,5 +1,6 @@
use sqlx::{Connection, SqliteConnection};
use std::env;
use vergen::{vergen, Config};
#[tokio::main]
async fn main() {
@@ -22,4 +23,6 @@ async fn main() {
// for some strange reason we need to add a leading `/` to the windows path even though it's
// not a valid windows path... but hey, it works...
println!("cargo:rustc-env=DATABASE_URL=sqlite:///{}", &database_path);
vergen(Config::default()).expect("failed to extract build metadata")
}
+1 -1
View File
@@ -114,7 +114,7 @@ impl MixNodeBondAnnotated {
}
}
#[derive(Debug, Serialize, Deserialize, JsonSchema)]
#[derive(Deserialize, JsonSchema)]
pub struct ComputeRewardEstParam {
pub performance: Option<Performance>,
pub active_in_rewarded_set: Option<bool>,
+2
View File
@@ -446,6 +446,8 @@ impl Config {
self.network_monitor.credentials_database_path.clone()
}
// TODO: Remove if still unused
#[allow(dead_code)]
pub fn get_rewarding_enabled(&self) -> bool {
self.rewarding.enabled
}
+262 -141
View File
@@ -1,4 +1,4 @@
// Copyright 2020-2023 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2020 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
#[macro_use]
@@ -6,7 +6,6 @@ extern crate rocket;
use crate::config::Config;
use crate::contract_cache::ValidatorCacheRefresher;
use crate::epoch_operations::RewardedSetUpdater;
use crate::network_monitor::NetworkMonitorBuilder;
use crate::node_status_api::uptime_updater::HistoricalUptimeUpdater;
use crate::nymd_client::Client;
@@ -16,12 +15,9 @@ use ::config::defaults::setup_env;
use ::config::defaults::var_names::{CONFIGURED, MIXNET_CONTRACT_ADDRESS, MIX_DENOM};
use ::config::NymConfig;
use anyhow::Result;
use build_information::BinaryBuildInformation;
use clap::Parser;
use clap::{crate_version, App, Arg, ArgMatches};
use contract_cache::ValidatorCache;
use lazy_static::lazy_static;
use log::{info, warn};
use logging::setup_logging;
use node_status_api::NodeStatusCache;
use okapi::openapi3::OpenApi;
use rocket::fairing::AdHoc;
@@ -30,21 +26,27 @@ use rocket::{Ignite, Rocket};
use rocket_cors::{AllowedHeaders, AllowedOrigins, Cors};
use rocket_okapi::mount_endpoints_and_merged_docs;
use rocket_okapi::swagger_ui::make_swagger_ui;
use std::path::PathBuf;
use std::str::FromStr;
use std::sync::Arc;
use std::time::Duration;
use std::{fs, process};
use task::{wait_for_signal, TaskManager};
use task::TaskManager;
use tokio::sync::Notify;
use validator_client::nymd::{self, SigningNymdClient};
#[cfg(feature = "coconut")]
use url::Url;
use validator_client::nymd::SigningNymdClient;
use crate::epoch_operations::RewardedSetUpdater;
#[cfg(feature = "coconut")]
use coconut::{
comm::QueryCommunicationChannel,
dkg::controller::{init_keypair, DkgController},
InternalSignRequest,
};
use logging::setup_logging;
#[cfg(feature = "coconut")]
use rand::rngs::OsRng;
use validator_client::nymd::bip32::secp256k1::elliptic_curve::rand_core::OsRng;
pub(crate) mod config;
pub(crate) mod contract_cache;
@@ -58,92 +60,150 @@ mod swagger;
#[cfg(feature = "coconut")]
mod coconut;
lazy_static! {
pub static ref PRETTY_BUILD_INFORMATION: String =
BinaryBuildInformation::new(env!("CARGO_PKG_VERSION")).pretty_print();
const ID: &str = "id";
const CONFIG_ENV_FILE: &str = "config-env-file";
const MONITORING_ENABLED: &str = "enable-monitor";
const REWARDING_ENABLED: &str = "enable-rewarding";
const MIXNET_CONTRACT_ARG: &str = "mixnet-contract";
const MNEMONIC_ARG: &str = "mnemonic";
const WRITE_CONFIG_ARG: &str = "save-config";
const NYMD_VALIDATOR_ARG: &str = "nymd-validator";
const ENABLED_CREDENTIALS_MODE_ARG_NAME: &str = "enabled-credentials-mode";
#[cfg(feature = "coconut")]
const ANNOUNCE_ADDRESS: &str = "announce-address";
#[cfg(feature = "coconut")]
const COCONUT_ENABLED: &str = "enable-coconut";
const REWARDING_MONITOR_THRESHOLD_ARG: &str = "monitor-threshold";
const MIN_MIXNODE_RELIABILITY_ARG: &str = "min_mixnode_reliability";
const MIN_GATEWAY_RELIABILITY_ARG: &str = "min_gateway_reliability";
fn long_version() -> String {
format!(
r#"
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
"#,
"Build Timestamp:",
env!("VERGEN_BUILD_TIMESTAMP"),
"Build Version:",
env!("VERGEN_BUILD_SEMVER"),
"Commit SHA:",
env!("VERGEN_GIT_SHA"),
"Commit Date:",
env!("VERGEN_GIT_COMMIT_TIMESTAMP"),
"Commit Branch:",
env!("VERGEN_GIT_BRANCH"),
"rustc Version:",
env!("VERGEN_RUSTC_SEMVER"),
"rustc Channel:",
env!("VERGEN_RUSTC_CHANNEL"),
"cargo Profile:",
env!("VERGEN_CARGO_PROFILE")
)
}
// Helper for passing LONG_VERSION to clap
fn pretty_build_info_static() -> &'static str {
&PRETTY_BUILD_INFORMATION
}
fn parse_args() -> ArgMatches {
let build_details = long_version();
let base_app = App::new("Nym API")
.version(crate_version!())
.long_version(&*build_details)
.author("Nymtech")
.arg(
Arg::with_name(CONFIG_ENV_FILE)
.help("Path pointing to an env file that configures the Nym API")
.long(CONFIG_ENV_FILE)
.short('c')
.takes_value(true)
)
.arg(
Arg::with_name(ID)
.help("Id of the nym-api we want to run")
.long(ID)
.takes_value(true)
)
.arg(
Arg::with_name(MONITORING_ENABLED)
.help("specifies whether a network monitoring is enabled on this API")
.long(MONITORING_ENABLED)
.short('m')
)
.arg(
Arg::with_name(REWARDING_ENABLED)
.help("specifies whether a network rewarding is enabled on this API")
.long(REWARDING_ENABLED)
.short('r')
.requires_all(&[MONITORING_ENABLED, MNEMONIC_ARG])
)
.arg(
Arg::with_name(NYMD_VALIDATOR_ARG)
.help("Endpoint to nymd instance from which the monitor will grab nodes to test")
.long(NYMD_VALIDATOR_ARG)
.takes_value(true)
)
.arg(Arg::with_name(MIXNET_CONTRACT_ARG)
.long(MIXNET_CONTRACT_ARG)
.help("Address of the mixnet contract managing the network")
.takes_value(true),
)
.arg(Arg::with_name(MNEMONIC_ARG)
.long(MNEMONIC_ARG)
.help("Mnemonic of the network monitor used for rewarding operators")
.takes_value(true)
)
.arg(
Arg::with_name(WRITE_CONFIG_ARG)
.help("specifies whether a config file based on provided arguments should be saved to a file")
.long(WRITE_CONFIG_ARG)
.short('w')
)
.arg(
Arg::with_name(REWARDING_MONITOR_THRESHOLD_ARG)
.help("Specifies the minimum percentage of monitor test run data present in order to distribute rewards for given interval.")
.takes_value(true)
.long(REWARDING_MONITOR_THRESHOLD_ARG)
)
.arg(
Arg::with_name(MIN_MIXNODE_RELIABILITY_ARG)
.long(MIN_MIXNODE_RELIABILITY_ARG)
.help("Mixnodes with reliability lower the this get blacklisted by network monitor, get no traffic and cannot be selected into a rewarded set.")
.takes_value(true)
)
.arg(
Arg::with_name(MIN_GATEWAY_RELIABILITY_ARG)
.long(MIN_GATEWAY_RELIABILITY_ARG)
.help("Gateways with reliability lower the this get blacklisted by network monitor, get no traffic and cannot be selected into a rewarded set.")
.takes_value(true)
)
.arg(
Arg::with_name(ENABLED_CREDENTIALS_MODE_ARG_NAME)
.long(ENABLED_CREDENTIALS_MODE_ARG_NAME)
.help("Set this nym api to work in a enabled credentials that would attempt to use gateway with the bandwidth credential requirement")
);
// explicitly defined custom parser (as opposed to just using
// #[arg(value_parser = clap::value_parser!(u8).range(0..100))]
// for better error message
fn threshold_in_range(s: &str) -> Result<u8, String> {
let threshold: usize = s
.parse()
.map_err(|_| format!("`{s}` isn't a valid threshold number"))?;
if threshold > 100 {
Err(format!("{threshold} is not within the range 0-100"))
} else {
Ok(threshold as u8)
}
}
#[derive(Parser)]
#[clap(author = "Nymtech", version, long_version = pretty_build_info_static(), about)]
struct ApiArgs {
/// Path pointing to an env file that configures the Nym API.
#[clap(short, long)]
config_env_file: Option<std::path::PathBuf>,
/// Id of the nym-api we want to run
#[clap(long)]
id: Option<String>,
/// Specifies whether network monitoring is enabled on this API
#[clap(short = 'm', long)]
enable_monitor: bool,
/// Specifies whether network rewarding is enabled on this API
#[clap(short = 'r', long, requires = "enable_monitor", requires = "mnemonic")]
enable_rewarding: bool,
/// Endpoint to nymd instance from which the monitor will grab nodes to test
#[clap(long)]
nymd_validator: Option<url::Url>,
/// Address of the mixnet contract managing the network
#[clap(long)]
mixnet_contract: Option<nymd::AccountId>,
/// Mnemonic of the network monitor used for rewarding operators
// even though we're currently converting the mnemonic to string (and then back to the concrete type)
// at least we're getting immediate validation when passing the arguments
#[clap(long)]
mnemonic: Option<bip39::Mnemonic>,
/// Specifies whether a config file based on provided arguments should be saved to a file
#[clap(short = 'w', long)]
save_config: bool,
/// Specifies the minimum percentage of monitor test run data present in order to distribute rewards for given interval.
#[clap(long, value_parser = threshold_in_range)]
monitor_threshold: Option<u8>,
/// Mixnodes with reliability lower the this get blacklisted by network monitor, get no traffic and cannot be selected into a rewarded set.
#[clap(long, value_parser = threshold_in_range)]
min_mixnode_reliability: Option<u8>,
/// Gateways with reliability lower the this get blacklisted by network monitor, get no traffic and cannot be selected into a rewarded set.
#[clap(long, value_parser = threshold_in_range)]
min_gateway_reliability: Option<u8>,
/// Set this nym api to work in a enabled credentials that would attempt to use gateway with the bandwidth credential requirement
#[clap(long)]
enabled_credentials_mode: bool,
/// Announced address where coconut clients will connect.
#[cfg(feature = "coconut")]
#[clap(long)]
announce_address: Option<url::Url>,
/// Flag to indicate whether coconut signer authority is enabled on this API
#[cfg(feature = "coconut")]
#[clap(long, requires = "mnemonic", requires = "announce-address")]
enable_coconut: bool,
let base_app = base_app
.arg(
Arg::with_name(ANNOUNCE_ADDRESS)
.help("Announced address where coconut clients will connect.")
.long(ANNOUNCE_ADDRESS)
.takes_value(true),
)
.arg(
Arg::with_name(COCONUT_ENABLED)
.help("Flag to indicate whether coconut signer authority is enabled on this API")
.requires_all(&[MNEMONIC_ARG, ANNOUNCE_ADDRESS])
.long(COCONUT_ENABLED),
);
base_app.get_matches()
}
async fn wait_for_interrupt(mut shutdown: TaskManager) {
@@ -158,55 +218,122 @@ async fn wait_for_interrupt(mut shutdown: TaskManager) {
log::info!("Stopping nym API");
}
fn override_config(mut config: Config, args: ApiArgs) -> Config {
if let Some(id) = args.id {
fs::create_dir_all(Config::default_config_directory(Some(&id)))
#[cfg(unix)]
async fn wait_for_signal() {
use tokio::signal::unix::{signal, SignalKind};
let mut sigterm = signal(SignalKind::terminate()).expect("Failed to setup SIGTERM channel");
let mut sigquit = signal(SignalKind::quit()).expect("Failed to setup SIGQUIT channel");
tokio::select! {
_ = tokio::signal::ctrl_c() => {
log::info!("Received SIGINT");
},
_ = sigterm.recv() => {
log::info!("Received SIGTERM");
}
_ = sigquit.recv() => {
log::info!("Received SIGQUIT");
}
}
}
#[cfg(not(unix))]
async fn wait_for_signal() {
tokio::select! {
_ = tokio::signal::ctrl_c() => {
log::info!("Received SIGINT");
},
}
}
fn override_config(mut config: Config, matches: &ArgMatches) -> Config {
if let Some(id) = matches.value_of(ID) {
fs::create_dir_all(Config::default_config_directory(Some(id)))
.expect("Could not create config directory");
fs::create_dir_all(Config::default_data_directory(Some(&id)))
fs::create_dir_all(Config::default_data_directory(Some(id)))
.expect("Could not create data directory");
config = config.with_id(&id);
config = config.with_id(id);
}
config = config
.with_network_monitor_enabled(args.enable_monitor)
.with_rewarding_enabled(args.enable_rewarding)
.with_disabled_credentials_mode(!args.enabled_credentials_mode);
if let Some(nymd_validator) = args.nymd_validator {
config = config.with_custom_nymd_validator(nymd_validator);
if matches.is_present(MONITORING_ENABLED) {
config = config.with_network_monitor_enabled(true)
}
if let Some(mixnet_contract) = args.mixnet_contract {
config = config.with_custom_mixnet_contract(mixnet_contract.to_string())
if matches.is_present(REWARDING_ENABLED) {
config = config.with_rewarding_enabled(true)
}
#[cfg(feature = "coconut")]
if matches.is_present(COCONUT_ENABLED) {
config = config.with_coconut_signer_enabled(true)
}
#[cfg(feature = "coconut")]
if let Some(announce_address) = matches.value_of(ANNOUNCE_ADDRESS) {
config = config.with_announce_address(
Url::parse(announce_address).expect("Could not parse announce address"),
);
}
if let Some(raw_validator) = matches.value_of(NYMD_VALIDATOR_ARG) {
let parsed = match raw_validator.parse() {
Err(err) => {
error!("Passed validator argument is invalid - {err}");
process::exit(1)
}
Ok(url) => url,
};
config = config.with_custom_nymd_validator(parsed);
}
if let Some(mixnet_contract) = matches.value_of(MIXNET_CONTRACT_ARG) {
config = config.with_custom_mixnet_contract(mixnet_contract)
} else if std::env::var(CONFIGURED).is_ok() {
if let Some(mixnet_contract) = read_var_if_not_default(MIXNET_CONTRACT_ADDRESS) {
config = config.with_custom_mixnet_contract(mixnet_contract)
}
}
if let Some(mnemonic) = args.mnemonic {
config = config.with_mnemonic(mnemonic.to_string())
if let Some(mnemonic) = matches.value_of(MNEMONIC_ARG) {
config = config.with_mnemonic(mnemonic)
}
if let Some(monitor_threshold) = args.monitor_threshold {
if let Some(monitor_threshold) = matches
.value_of(REWARDING_MONITOR_THRESHOLD_ARG)
.map(|t| t.parse::<u8>())
{
let monitor_threshold =
monitor_threshold.expect("Provided monitor threshold is not a number!");
assert!(
monitor_threshold <= 100,
"Provided monitor threshold is greater than 100!"
);
config = config.with_minimum_interval_monitor_threshold(monitor_threshold)
}
if let Some(reliability) = args.min_mixnode_reliability {
config = config.with_min_mixnode_reliability(reliability)
if let Some(reliability) = matches
.value_of(MIN_MIXNODE_RELIABILITY_ARG)
.map(|t| t.parse::<u8>())
{
config = config.with_min_mixnode_reliability(
reliability.expect("Provided reliability is not a u8 number!"),
)
}
if let Some(reliability) = args.min_gateway_reliability {
config = config.with_min_gateway_reliability(reliability)
if let Some(reliability) = matches
.value_of(MIN_GATEWAY_RELIABILITY_ARG)
.map(|t| t.parse::<u8>())
{
config = config.with_min_gateway_reliability(
reliability.expect("Provided reliability is not a u8 number!"),
)
}
#[cfg(feature = "coconut")]
if let Some(announce_address) = args.announce_address {
config = config
.with_announce_address(announce_address)
.with_coconut_signer_enabled(args.enable_coconut);
if matches.is_present(ENABLED_CREDENTIALS_MODE_ARG_NAME) {
config = config.with_disabled_credentials_mode(false)
}
if args.save_config {
if matches.is_present(WRITE_CONFIG_ARG) {
info!("Saving the configuration to a file");
if let Err(err) = config.save_to_file(None) {
error!("Failed to write config to a file - {err}");
@@ -363,11 +490,11 @@ fn get_servers() -> Vec<rocket_okapi::okapi::openapi3::Server> {
}]
}
async fn run_nym_api(args: ApiArgs) -> Result<()> {
async fn run_nym_api(matches: ArgMatches) -> Result<()> {
let system_version = env!("CARGO_PKG_VERSION");
// try to load config from the file, if it doesn't exist, use default values
let id = args.id.as_deref();
let id = matches.value_of(ID);
let (config, _already_inited) = match Config::load_from_file(id) {
Ok(cfg) => (cfg, true),
Err(_) => {
@@ -376,14 +503,14 @@ async fn run_nym_api(args: ApiArgs) -> Result<()> {
.into_string()
.unwrap();
warn!(
"Could not load the configuration file from {config_path}. Either the file did not exist or was malformed. Using the default values instead",
"Could not load the configuration file from {}. Either the file did not exist or was malformed. Using the default values instead",
config_path
);
(Config::new(), false)
}
};
let save_to_file = args.save_config;
let config = override_config(config, args);
let config = override_config(config, &matches);
#[cfg(feature = "coconut")]
if !_already_inited {
@@ -391,16 +518,9 @@ async fn run_nym_api(args: ApiArgs) -> Result<()> {
}
// if we just wanted to write data to the config, exit
if save_to_file {
info!("Saving the configuration to a file");
if let Err(err) = config.save_to_file(None) {
error!("Failed to write config to a file - {err}");
process::exit(1)
} else {
return Ok(());
}
if matches.is_present(WRITE_CONFIG_ARG) {
return Ok(());
}
let mix_denom = std::env::var(MIX_DENOM).expect("mix denom not set");
let signing_nymd_client = Client::new_signing(&config);
@@ -464,13 +584,11 @@ async fn run_nym_api(args: ApiArgs) -> Result<()> {
tokio::spawn(async move { validator_cache_refresher.run(shutdown_listener).await });
// spawn rewarded set updater
if config.get_rewarding_enabled() {
let mut rewarded_set_updater =
RewardedSetUpdater::new(signing_nymd_client, validator_cache.clone(), storage)
.await?;
let shutdown_listener = shutdown.subscribe();
tokio::spawn(async move { rewarded_set_updater.run(shutdown_listener).await.unwrap() });
}
let mut rewarded_set_updater =
RewardedSetUpdater::new(signing_nymd_client, validator_cache.clone(), storage).await?;
let shutdown_listener = shutdown.subscribe();
tokio::spawn(async move { rewarded_set_updater.run(shutdown_listener).await.unwrap() });
validator_cache_listener
} else {
// Spawn the validator cache refresher.
@@ -540,7 +658,10 @@ async fn main() -> Result<()> {
}}
setup_logging();
let args = ApiArgs::parse();
setup_env(args.config_env_file.as_ref());
let args = parse_args();
let config_env_file = args
.value_of(CONFIG_ENV_FILE)
.map(|s| PathBuf::from_str(s).expect("invalid env config file"));
setup_env(config_env_file);
run_nym_api(args).await
}
+3 -3
View File
@@ -2161,9 +2161,9 @@ json-stringify-safe@5.0.1:
integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==
json5@^2.2.1:
version "2.2.3"
resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283"
integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==
version "2.2.1"
resolved "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz"
integrity sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==
kleur@^3.0.3:
version "3.0.3"
+1 -9
View File
@@ -1,18 +1,10 @@
## UNRELEASED
## [nym-connect-v1.1.4](https://github.com/nymtech/nym/tree/nym-connect-v1.1.4) (2022-12-20)
This release contains the new opt-in Test & Earn program, and it uses a stress-tested directory of network requesters to improve reliability. It also has some bugfixes, performance improvements, and better error handling.
- nym-connect: send status messages from socks5 task to tauri backend by @octol in https://github.com/nymtech/nym/pull/1882
- socks5: rework waiting in inbound.rs by @octol in https://github.com/nymtech/nym/pull/1880
- Test&Earn by @mmsinclair in https://github.com/nymtech/nym/pull/2729
## [nym-connect-v1.1.3](https://github.com/nymtech/nym/tree/nym-connect-v1.1.3) (2022-12-13)
- socks5-client: added support for socks4a.
## [nym-connect-v1.1.2](https://github.com/nymtech/nym/tree/nym-connect-v1.1.2) (2022-12-06)
## [nym-connect-v1.1.2](https://github.com/nymtech/nym/tree/nym-connect-v1.1.2) (2022-11-29)
- socks5-client: fix error with client failing and disconnecting unnecessarily.
+24 -61
View File
@@ -407,13 +407,6 @@ dependencies = [
"memchr",
]
[[package]]
name = "build-information"
version = "0.1.0"
dependencies = [
"vergen 7.4.4",
]
[[package]]
name = "bumpalo"
version = "3.11.0"
@@ -573,33 +566,35 @@ dependencies = [
[[package]]
name = "clap"
version = "4.0.26"
version = "3.2.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2148adefda54e14492fb9bddcc600b4344c5d1a3123bd666dcb939c6f0e0e57e"
checksum = "86447ad904c7fb335a790c9d7fe3d0d971dc523b8ccd1561a520de9a85302750"
dependencies = [
"atty",
"bitflags",
"clap_derive",
"clap_lex",
"indexmap",
"once_cell",
"strsim",
"termcolor",
"textwrap",
]
[[package]]
name = "clap_complete"
version = "4.0.7"
version = "3.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10861370d2ba66b0f5989f83ebf35db6421713fd92351790e7fdd6c36774c56b"
checksum = "3f7a2e0a962c45ce25afce14220bc24f9dade0a1787f185cecf96bfba7847cd8"
dependencies = [
"clap",
]
[[package]]
name = "clap_complete_fig"
version = "4.0.2"
version = "3.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46b30e010e669cd021e5004f3be26cff6b7c08d2a8a0d65b48d43a8cc0efd6c3"
checksum = "ed37b4c0c1214673eba6ad8ea31666626bf72be98ffb323067d973c48b4964b9"
dependencies = [
"clap",
"clap_complete",
@@ -607,9 +602,9 @@ dependencies = [
[[package]]
name = "clap_derive"
version = "4.0.21"
version = "3.2.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0177313f9f02afc995627906bbd8967e2be069f5261954222dac78290c2b9014"
checksum = "ea0c8bce528c4be4da13ea6fead8965e95b6073585a2f05204bd8f4119f82a65"
dependencies = [
"heck 0.4.0",
"proc-macro-error",
@@ -620,9 +615,9 @@ dependencies = [
[[package]]
name = "clap_lex"
version = "0.3.0"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d4198f73e42b4936b35b5bb248d81d2b595ecb170da0bac7655c54eedfa8da8"
checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5"
dependencies = [
"os_str_bytes",
]
@@ -637,7 +632,7 @@ dependencies = [
[[package]]
name = "client-core"
version = "1.1.4"
version = "1.1.3"
dependencies = [
"async-trait",
"client-connections",
@@ -1588,16 +1583,7 @@ version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2953d1df47ac0eb70086ccabf0275aa8da8591a28bd358ee2b52bd9f9e3ff9e9"
dependencies = [
"enum-iterator-derive 0.8.1",
]
[[package]]
name = "enum-iterator"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "45a0ac4aeb3a18f92eaf09c6bb9b3ac30ff61ca95514fc58cbead1c9a6bf5401"
dependencies = [
"enum-iterator-derive 1.1.0",
"enum-iterator-derive",
]
[[package]]
@@ -1611,17 +1597,6 @@ dependencies = [
"syn",
]
[[package]]
name = "enum-iterator-derive"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "828de45d0ca18782232dfb8f3ea9cc428e8ced380eb26a520baaacfc70de39ce"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "env_logger"
version = "0.7.1"
@@ -3463,9 +3438,8 @@ dependencies = [
[[package]]
name = "nym-socks5-client"
version = "1.1.4"
version = "1.1.3"
dependencies = [
"build-information",
"clap",
"client-connections",
"client-core",
@@ -3477,7 +3451,6 @@ dependencies = [
"futures",
"gateway-client",
"gateway-requests",
"lazy_static",
"log",
"logging",
"network-defaults",
@@ -3498,6 +3471,7 @@ dependencies = [
"topology",
"url",
"validator-client",
"vergen",
"version-checker",
]
@@ -6054,6 +6028,12 @@ dependencies = [
"winapi-util",
]
[[package]]
name = "textwrap"
version = "0.15.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7b3e525a49ec206798b40326a44121291b530c963cfb01018f63e135bac543d"
[[package]]
name = "thin-slice"
version = "0.1.1"
@@ -6558,7 +6538,7 @@ dependencies = [
"anyhow",
"cfg-if",
"chrono",
"enum-iterator 0.8.1",
"enum-iterator",
"getset",
"git2",
"rustc_version 0.4.0",
@@ -6566,23 +6546,6 @@ dependencies = [
"thiserror",
]
[[package]]
name = "vergen"
version = "7.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "efadd36bc6fde40c6048443897d69511a19161c0756cb704ed403f8dfd2b7d1c"
dependencies = [
"anyhow",
"cfg-if",
"enum-iterator 1.1.3",
"getset",
"git2",
"rustc_version 0.4.0",
"rustversion",
"thiserror",
"time 0.3.17",
]
[[package]]
name = "version-checker"
version = "0.1.0"
@@ -6619,7 +6582,7 @@ dependencies = [
"schemars",
"serde",
"thiserror",
"vergen 5.1.17",
"vergen",
"vesting-contract-common",
]
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@nym/nym-connect",
"version": "1.1.4",
"version": "1.1.3",
"main": "index.js",
"license": "MIT",
"scripts": {
+2 -2
View File
@@ -130,11 +130,11 @@ pub async fn init_socks5_config(provider_address: String, chosen_gateway_id: Str
if let Ok(raw_validators) = std::env::var(config_common::defaults::var_names::API_VALIDATOR) {
config
.get_base_mut()
.set_custom_nym_apis(config_common::parse_urls(&raw_validators));
.set_custom_nym_apis(config_common::parse_validators(&raw_validators));
}
// Setup gateway by either registering a new one, or reusing exiting keys
let gateway = client_core::init::setup_gateway::<Socks5Config, _>(
let gateway = client_core::init::setup_gateway::<_, Socks5Config, _>(
register_gateway,
Some(chosen_gateway_id),
config.get_base(),
+2 -1
View File
@@ -1,3 +1,4 @@
use client_core::client::replies::reply_storage::fs_backend;
use client_core::error::ClientCoreError;
use serde::{Serialize, Serializer};
use thiserror::Error;
@@ -38,7 +39,7 @@ pub enum BackendError {
#[error("{source}")]
ClientCoreError {
#[from]
source: ClientCoreError,
source: ClientCoreError<fs_backend::Backend>,
},
#[error("{source}")]
ApiClientError {
+3 -1
View File
@@ -16,7 +16,9 @@ impl AddDefaultSubmenus for Menu {
fn add_default_app_submenus(self) -> Self {
let submenu = Submenu::new(
"Help",
Menu::new().add_item(CustomMenuItem::new(SHOW_LOG_WINDOW, "Show logs")),
Menu::new()
.add_item(CustomMenuItem::new(SHOW_LOG_WINDOW, "Show logs"))
.add_item(CustomMenuItem::new(CLEAR_STORAGE, "Clear all settings")),
);
self.add_submenu(submenu)
}

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