Compare commits

..

3 Commits

264 changed files with 1604 additions and 12658 deletions
+1 -1
View File
@@ -14,7 +14,7 @@ GEOIPUPDATE_LICENSE_KEY=xxx
# List of space-separated database edition IDs. Edition IDs may
# consist of letters, digits, and dashes. For example, GeoIP2-City
# would download the GeoIP2 City database (GeoIP2-City).
GEOIPUPDATE_EDITION_IDS=GeoLite2-City
GEOIPUPDATE_EDITION_IDS=GeoLite2-Country
# The number of hours between geoipupdate runs. If this is not set
# or is set to 0, geoipupdate will run once and exit.
GEOIPUPDATE_FREQUENCY=72
+31 -55
View File
@@ -4,43 +4,13 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
## [Unreleased]
### Added
### Changed
## [v1.1.5] (2023-01-10)
- all-binaries: improved error logging ([#2686])
- native client: bring shutdown logic up to the same level as socks5-client
### Added
[#2686]: https://github.com/nymtech/nym/pull/2686
- socks5: send status message for service ready, and network-requester error response in https://github.com/nymtech/nym/pull/2715
### Changed
- all-binaries: improved error logging in https://github.com/nymtech/nym/pull/2686
- native client: bring shutdown logic up to the same level as socks5-client in https://github.com/nymtech/nym/pull/2695
- nym-api, coconut-dkg contract: automatic, time-based dkg epoch state advancement in https://github.com/nymtech/nym/pull/2670
- DKG resharing unit test by @neacsu in https://github.com/nymtech/nym/pull/2668
- Renaming validator-api to nym-api by @futurechimp in https://github.com/nymtech/nym/pull/1863
- Modify wasm specific make targets by @neacsu in https://github.com/nymtech/nym/pull/2693
- client: create websocket handler builder by @octol in https://github.com/nymtech/nym/pull/2700
- Outfox and Lion by @durch in https://github.com/nymtech/nym/pull/2730
- Feature/multi surb transmission lanes by @jstuczyn in https://github.com/nymtech/nym/pull/2723
## [v1.1.4] (2022-12-20)
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)
@@ -55,7 +25,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])
@@ -75,7 +45,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)
@@ -111,6 +81,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
@@ -137,7 +108,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])
@@ -165,6 +136,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
@@ -218,7 +190,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
@@ -312,9 +285,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))
@@ -323,7 +296,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))
@@ -363,13 +336,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:**
@@ -399,7 +373,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:**
@@ -414,7 +388,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)
@@ -424,7 +398,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)
@@ -480,10 +454,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))
@@ -496,7 +470,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))
@@ -514,7 +488,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))
@@ -530,7 +504,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))
@@ -554,8 +528,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))
@@ -564,14 +538,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))
@@ -583,7 +557,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))
@@ -620,4 +594,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
+23 -171
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"
@@ -459,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"
@@ -496,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"
@@ -534,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"
@@ -578,7 +505,6 @@ checksum = "d1873270f8f7942c191139cb8a40fd228da6c3fd2fc376d7e92d47aa14aeb59e"
dependencies = [
"crypto-common",
"inout",
"zeroize",
]
[[package]]
@@ -660,7 +586,7 @@ dependencies = [
[[package]]
name = "client-core"
version = "1.1.5"
version = "1.1.3"
dependencies = [
"async-trait",
"client-connections",
@@ -1054,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",
@@ -1073,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",
]
@@ -1244,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",
]
@@ -1577,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",
@@ -1762,7 +1651,7 @@ dependencies = [
[[package]]
name = "explorer-api"
version = "1.1.2"
version = "1.1.1"
dependencies = [
"chrono",
"clap 3.2.8",
@@ -1809,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",
]
@@ -3234,7 +3123,7 @@ dependencies = [
[[package]]
name = "nym-cli"
version = "1.1.5"
version = "1.1.3"
dependencies = [
"anyhow",
"base64",
@@ -3288,7 +3177,7 @@ dependencies = [
[[package]]
name = "nym-client"
version = "1.1.5"
version = "1.1.3"
dependencies = [
"clap 3.2.8",
"client-connections",
@@ -3327,7 +3216,7 @@ dependencies = [
[[package]]
name = "nym-gateway"
version = "1.1.5"
version = "1.1.3"
dependencies = [
"anyhow",
"async-trait",
@@ -3374,7 +3263,7 @@ dependencies = [
[[package]]
name = "nym-mixnode"
version = "1.1.5"
version = "1.1.3"
dependencies = [
"anyhow",
"bs58",
@@ -3416,7 +3305,7 @@ dependencies = [
[[package]]
name = "nym-network-requester"
version = "1.1.5"
version = "1.1.3"
dependencies = [
"async-trait",
"clap 3.2.8",
@@ -3448,7 +3337,7 @@ dependencies = [
[[package]]
name = "nym-network-statistics"
version = "1.1.5"
version = "1.1.3"
dependencies = [
"dirs",
"log",
@@ -3462,25 +3351,9 @@ 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.5"
version = "1.1.3"
dependencies = [
"clap 3.2.8",
"client-connections",
@@ -3547,7 +3420,7 @@ dependencies = [
[[package]]
name = "nym-validator-api"
version = "1.1.5"
version = "1.1.3"
dependencies = [
"anyhow",
"async-trait",
@@ -3636,7 +3509,7 @@ dependencies = [
"bincode",
"bls12_381 0.6.0",
"bs58",
"criterion 0.3.5",
"criterion",
"digest 0.9.0",
"dkg",
"doc-comment",
@@ -4148,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"
@@ -4168,7 +4030,7 @@ dependencies = [
"cfg-if 1.0.0",
"cpufeatures",
"opaque-debug 0.3.0",
"universal-hash 0.4.1",
"universal-hash",
]
[[package]]
@@ -6526,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"
@@ -7059,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",
]
-1
View File
@@ -76,7 +76,6 @@ members = [
"service-providers/network-statistics",
"nym-api",
"nym-api/nym-api-requests",
"nym-outfox",
"tools/nym-cli",
"tools/ts-rs-cli"
]
+4 -1
View File
@@ -28,7 +28,7 @@ clippy-coconut:
cargo clippy --workspace --features coconut -- -D warnings
clippy-wasm:
cargo clippy --manifest-path clients/webassembly/Cargo.toml --target wasm32-unknown-unknown --workspace -- -D warnings
cargo clippy --workspace --features wasm -- -D warnings
clippy-all-contracts:
@@ -49,6 +49,9 @@ test-main:
test-coconut:
cargo test --workspace --features coconut
test-wasm:
cargo test --workspace --features wasm
test-main-expensive:
cargo test --workspace -- --ignored
+1 -2
View File
@@ -1,9 +1,8 @@
[package]
name = "client-core"
version = "1.1.5"
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
@@ -371,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();
@@ -437,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,
@@ -471,7 +471,6 @@ where
received_buffer_request_sender,
},
},
reply_controller_sender,
task_manager,
})
}
@@ -481,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,
}
@@ -8,57 +8,6 @@ use crate::config::DebugConfig;
use crate::error::ClientCoreError;
use log::{error, info};
use std::path::Path;
use std::{fs, io};
use time::OffsetDateTime;
async fn setup_fresh_backend<P: AsRef<Path>>(
db_path: P,
debug_config: &DebugConfig,
) -> 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: err });
}
};
// while I kinda hate that we're going to be creating `CombinedReplyStorage` twice,
// it will only be happening on the very first run and in practice won't incur huge
// costs since the storage is going to be empty
let mem_store = CombinedReplyStorage::new(
debug_config.minimum_reply_surb_storage_threshold,
debug_config.maximum_reply_surb_storage_threshold,
);
storage_backend
.init_fresh(&mem_store)
.await
.map_err(|err| ClientCoreError::SurbStorageError { source: err })?;
Ok(storage_backend)
}
fn archive_corrupted_database<P: AsRef<Path>>(db_path: P) -> io::Result<()> {
let db_path = db_path.as_ref();
debug_assert!(db_path.exists());
let now = OffsetDateTime::now_utc().unix_timestamp();
let suffix = format!("_{now}.corrupted");
let new_extension =
if let Some(existing_extension) = db_path.extension().and_then(|ext| ext.to_str()) {
format!("{existing_extension}.{}", suffix)
} else {
suffix
};
let mut renamed = db_path.to_owned();
renamed.set_extension(new_extension);
fs::rename(db_path, renamed)
}
pub async fn setup_fs_reply_surb_backend<P: AsRef<Path>>(
db_path: P,
@@ -71,13 +20,32 @@ pub async fn setup_fs_reply_surb_backend<P: AsRef<Path>>(
match fs_backend::Backend::try_load(db_path).await {
Ok(backend) => Ok(backend),
Err(err) => {
error!("failed to setup persistent storage backend for our reply needs: {err}. We're going to create a fresh database instead. This behaviour might change in the future");
archive_corrupted_database(db_path)?;
setup_fresh_backend(db_path, debug_config).await
error!("failed to setup persistent storage backend for our reply needs: {err}");
Err(ClientCoreError::SurbStorageError { source: err })
}
}
} else {
setup_fresh_backend(db_path, debug_config).await
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: err });
}
};
// while I kinda hate that we're going to be creating `CombinedReplyStorage` twice,
// it will only be happening on the very first run and in practice won't incur huge
// costs since the storage is going to be empty
let mem_store = CombinedReplyStorage::new(
debug_config.minimum_reply_surb_storage_threshold,
debug_config.maximum_reply_surb_storage_threshold,
);
storage_backend
.init_fresh(&mem_store)
.await
.map_err(|err| ClientCoreError::SurbStorageError { source: err })?;
Ok(storage_backend)
}
}
@@ -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;
@@ -149,7 +149,7 @@ where
break;
}
},
_ = shutdown.recv() => {
_ = shutdown.recv_with_delay() => {
log::trace!("RetransmissionRequestListener: Received shutdown");
}
}
@@ -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,
},
}
@@ -1,6 +1,7 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
pub use self::error::StorageError;
use crate::client::replies::reply_storage::backend::fs_backend::manager::StorageManager;
use crate::client::replies::reply_storage::backend::fs_backend::models::{
ReplySurbStorageMetadata, StoredReplyKey, StoredReplySurb, StoredSenderTag, StoredSurbSender,
@@ -16,8 +17,6 @@ use std::fs;
use std::path::{Path, PathBuf};
use time::OffsetDateTime;
pub use self::error::StorageError;
mod error;
mod manager;
mod models;
@@ -67,12 +66,6 @@ impl Backend {
return Err(StorageError::IncompleteDataFlush);
}
let last_flush_timestamp = manager.get_previous_flush_timestamp().await?;
if last_flush_timestamp == 0 {
// either this client has been running since 1970 or the flush failed
return Err(StorageError::IncompleteDataFlush);
}
// the process has gone down without full graceful shutdown,
// meaning the database doesn't contain valid data anymore
// so we have to purge it
@@ -82,12 +75,7 @@ impl Backend {
manager.delete_all_reply_keys().await?;
}
if let Err(err) = manager.get_reply_surb_storage_metadata().await {
// we can't recover here, we HAVE TO initialise fresh (because we don't know correct starting metadata)
error!("it seems the client has been shutdown gracefully - we're missing valid surb data dump. the existing database cannot be used");
return Err(err.into());
}
let last_flush_timestamp = manager.get_previous_flush_timestamp().await?;
let last_flush = match OffsetDateTime::from_unix_timestamp(last_flush_timestamp) {
Ok(last_flush) => last_flush,
Err(err) => {
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "nym-client"
version = "1.1.5"
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"
+3 -7
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;
@@ -87,8 +86,7 @@ impl SocketClient {
config: &Config,
client_input: ClientInput,
client_output: ClientOutput,
self_address: &Recipient,
reply_controller_sender: ReplyControllerSender,
self_address: Recipient,
shutdown: task::TaskClient,
) {
info!("Starting websocket listener...");
@@ -103,13 +101,12 @@ impl SocketClient {
received_buffer_request_sender,
} = client_output;
let websocket_handler = websocket::HandlerBuilder::new(
let websocket_handler = websocket::Handler::new(
input_sender,
connection_command_sender,
received_buffer_request_sender,
self_address,
shared_lane_queue_lengths,
reply_controller_sender,
);
websocket::Listener::new(config.get_listening_port()).start(websocket_handler, shutdown);
@@ -156,8 +153,7 @@ impl SocketClient {
&self.config,
client_input,
client_output,
&self_address,
started_client.reply_controller_sender,
self_address,
started_client.task_manager.subscribe(),
);
+109 -102
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},
@@ -38,49 +35,6 @@ impl Default for ReceivedResponseType {
}
}
pub(crate) struct HandlerBuilder {
msg_input: InputMessageSender,
client_connection_tx: ConnectionCommandSender,
buffer_requester: ReceivedBufferRequestSender,
self_full_address: Recipient,
lane_queue_lengths: LaneQueueLengths,
reply_controller_sender: ReplyControllerSender,
}
impl HandlerBuilder {
pub(crate) fn new(
msg_input: InputMessageSender,
client_connection_tx: ConnectionCommandSender,
buffer_requester: ReceivedBufferRequestSender,
self_full_address: &Recipient,
lane_queue_lengths: LaneQueueLengths,
reply_controller_sender: ReplyControllerSender,
) -> Self {
Self {
msg_input,
client_connection_tx,
buffer_requester,
self_full_address: *self_full_address,
lane_queue_lengths,
reply_controller_sender,
}
}
// TODO: make sure we only ever have one active handler
pub fn create_active_handler(&self) -> Handler {
Handler {
msg_input: self.msg_input.clone(),
client_connection_tx: self.client_connection_tx.clone(),
buffer_requester: self.buffer_requester.clone(),
self_full_address: self.self_full_address,
socket: None,
received_response_type: Default::default(),
lane_queue_lengths: self.lane_queue_lengths.clone(),
reply_controller_sender: self.reply_controller_sender.clone(),
}
}
}
pub(crate) struct Handler {
msg_input: InputMessageSender,
client_connection_tx: ConnectionCommandSender,
@@ -89,15 +43,16 @@ pub(crate) struct Handler {
socket: Option<WebSocketStream<TcpStream>>,
received_response_type: ReceivedResponseType,
lane_queue_lengths: LaneQueueLengths,
reply_controller_sender: ReplyControllerSender,
is_active: bool,
}
impl Drop for Handler {
fn drop(&mut self) {
if self
.buffer_requester
.unbounded_send(ReceivedBufferMessage::ReceiverDisconnect)
.is_err()
if self.is_active
&& self
.buffer_requester
.unbounded_send(ReceivedBufferMessage::ReceiverDisconnect)
.is_err()
{
error!("we failed to disconnect the receiver from the buffer! presumably the shutdown procedure has been initiated!")
}
@@ -105,46 +60,38 @@ 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}");
pub(crate) fn new(
msg_input: InputMessageSender,
client_connection_tx: ConnectionCommandSender,
buffer_requester: ReceivedBufferRequestSender,
self_full_address: Recipient,
lane_queue_lengths: LaneQueueLengths,
) -> Self {
Handler {
msg_input,
client_connection_tx,
buffer_requester,
self_full_address,
socket: None,
received_response_type: Default::default(),
lane_queue_lengths,
is_active: false,
}
}
Some(ServerResponse::LaneQueueLength {
lane: connection_id,
queue_length,
})
// Used to use handler on a new connection, which initially is `None`
// TODO: make sure we only ever have one active handler
pub fn create_active_handler(&self) -> Self {
Handler {
msg_input: self.msg_input.clone(),
client_connection_tx: self.client_connection_tx.clone(),
buffer_requester: self.buffer_requester.clone(),
self_full_address: self.self_full_address,
socket: None,
received_response_type: Default::default(),
lane_queue_lengths: self.lane_queue_lengths.clone(),
is_active: true,
}
}
async fn handle_send(
@@ -171,11 +118,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 +165,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 +208,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 +242,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 +284,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),
}
}
+3 -7
View File
@@ -1,7 +1,7 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use super::handler::HandlerBuilder;
use super::handler::Handler;
use log::*;
use std::{net::SocketAddr, process, sync::Arc};
use tokio::io::AsyncWriteExt;
@@ -32,7 +32,7 @@ impl Listener {
}
}
pub(crate) async fn run(&mut self, handler: HandlerBuilder, mut task_client: task::TaskClient) {
pub(crate) async fn run(&mut self, handler: Handler, mut task_client: task::TaskClient) {
let tcp_listener = match tokio::net::TcpListener::bind(self.address).await {
Ok(listener) => listener,
Err(err) => {
@@ -100,11 +100,7 @@ impl Listener {
log::debug!("Websocket listener: Exiting");
}
pub(crate) fn start(
mut self,
handler: HandlerBuilder,
shutdown: task::TaskClient,
) -> JoinHandle<()> {
pub(crate) fn start(mut self, handler: Handler, shutdown: task::TaskClient) -> JoinHandle<()> {
info!("Running websocket on {:?}", self.address.to_string());
tokio::spawn(async move { self.run(handler, shutdown).await })
+1 -1
View File
@@ -1,7 +1,7 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
pub(crate) use handler::HandlerBuilder;
pub(crate) use handler::Handler;
pub(crate) use listener::Listener;
pub(crate) mod handler;
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "nym-socks5-client"
version = "1.1.5"
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"
+1 -1
View File
@@ -166,7 +166,7 @@ impl NymClient {
let mut shutdown = self.start().await?;
// Listen to status messages from task, that we forward back to the caller
shutdown.start_status_listener(sender).await;
shutdown.start_status_listener(sender);
let res = tokio::select! {
biased;
-7
View File
@@ -1,7 +1,6 @@
use crate::socks::types::SocksProxyError;
use client_core::client::replies::reply_storage::fs_backend;
use client_core::error::ClientCoreError;
use socks5_requests::ConnectionId;
#[derive(thiserror::Error, Debug)]
pub enum Socks5ClientError {
@@ -22,10 +21,4 @@ pub enum Socks5ClientError {
#[error("Fail to bind address")]
FailToBindAddress,
#[error("Network requester: connection id {connection_id}: {error}")]
NetworkRequesterError {
connection_id: ConnectionId,
error: String,
},
}
+9 -20
View File
@@ -11,8 +11,6 @@ use proxy_helpers::connection_controller::{ControllerCommand, ControllerSender};
use socks5_requests::Message;
use task::TaskClient;
use crate::error::Socks5ClientError;
pub(crate) struct MixnetResponseListener {
buffer_requester: ReceivedBufferRequestSender,
mix_response_receiver: ReconstructedMessagesReceiver,
@@ -54,10 +52,7 @@ impl MixnetResponseListener {
}
}
fn on_message(
&self,
reconstructed_message: ReconstructedMessage,
) -> Result<(), Socks5ClientError> {
async fn on_message(&self, reconstructed_message: ReconstructedMessage) {
let raw_message = reconstructed_message.message;
if reconstructed_message.sender_tag.is_some() {
warn!("this message was sent anonymously - it couldn't have come from the service provider");
@@ -66,11 +61,11 @@ impl MixnetResponseListener {
let response = match Message::try_from_bytes(&raw_message) {
Err(err) => {
warn!("failed to parse received response - {err}");
return Ok(());
return;
}
Ok(Message::Request(_)) => {
warn!("unexpected request");
return Ok(());
return;
}
Ok(Message::Response(data)) => data,
Ok(Message::NetworkRequesterResponse(r)) => {
@@ -78,10 +73,7 @@ impl MixnetResponseListener {
"Network requester failed on connection id {} with error: {}",
r.connection_id, r.network_requester_error
);
return Err(Socks5ClientError::NetworkRequesterError {
connection_id: r.connection_id,
error: r.network_requester_error,
});
return;
}
};
@@ -92,21 +84,18 @@ impl MixnetResponseListener {
response.is_closed,
))
.unwrap();
Ok(())
}
pub(crate) async fn run(&mut self) {
while !self.shutdown.is_shutdown() {
tokio::select! {
received_responses = self.mix_response_receiver.next() => {
if let Some(received_responses) = received_responses {
received_responses = self.mix_response_receiver.next() => match received_responses {
Some(received_responses) => {
for reconstructed_message in received_responses {
if let Err(err) = self.on_message(reconstructed_message) {
self.shutdown.send_status_msg(Box::new(err));
}
self.on_message(reconstructed_message).await;
}
} else {
},
None => {
log::trace!("MixnetResponseListener: Stopping since channel closed");
break;
}
+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)]
@@ -108,7 +108,7 @@ async fn test_nymd_connection(
log::debug!("Checking: nymd_url: {url}: {}: {}", "failed".red(), e);
false
}
Ok(Err(NymdError::AbciError { code, log, .. })) => {
Ok(Err(NymdError::AbciError(code, log))) => {
// We accept the mixnet contract not found as ok from a connection standpoint. This happens
// for example on a pre-launch network.
log::debug!(
@@ -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";
@@ -1,7 +1,6 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::nymd;
use crate::nymd::coin::Coin;
use crate::nymd::cosmwasm_client::helpers::{create_pagination, next_page_key};
use crate::nymd::cosmwasm_client::types::{
@@ -24,6 +23,7 @@ use cosmrs::rpc::endpoint::broadcast;
use cosmrs::rpc::endpoint::tx::Response as TxResponse;
use cosmrs::rpc::query::Query;
use cosmrs::rpc::{self, HttpClient, Order};
use cosmrs::tendermint::abci::Code as AbciCode;
use cosmrs::tendermint::abci::Transaction;
use cosmrs::tendermint::{abci, block, chain};
use cosmrs::{tx, AccountId, Coin as CosmosCoin, Tx};
@@ -66,9 +66,13 @@ pub trait CosmWasmClient: rpc::Client {
req.encode(&mut buf)?;
let res = self.abci_query(path, buf, None, false).await?;
let res_success = nymd::error::parse_abci_query_result(res)?;
Ok(Res::decode(res_success.value.as_ref())?)
match res.code {
AbciCode::Err(code) => return Err(NymdError::AbciError(code, res.log)),
AbciCode::Ok => (),
}
Ok(Res::decode(res.value.as_ref())?)
}
async fn get_chain_id(&self) -> Result<chain::Id, NymdError> {
@@ -2,23 +2,16 @@
// SPDX-License-Identifier: Apache-2.0
use crate::nymd::cosmwasm_client::types::ContractCodeId;
use cosmrs::{
bip32,
rpc::endpoint::abci_query::AbciQuery,
tendermint::{
abci::{self, Code as AbciCode},
block,
},
tx, AccountId,
};
use cosmrs::tendermint::{abci, block};
use cosmrs::{bip32, tx, AccountId};
use std::io;
use std::time::Duration;
use thiserror::Error;
use std::{io, time::Duration};
pub use cosmrs::rpc::{
error::{Error as TendermintRpcError, ErrorDetail as TendermintRpcErrorDetail},
response_error::{Code, ResponseError},
pub use cosmrs::rpc::error::{
Error as TendermintRpcError, ErrorDetail as TendermintRpcErrorDetail,
};
pub use cosmrs::rpc::response_error::{Code, ResponseError};
#[derive(Debug, Error)]
pub enum NymdError {
@@ -117,12 +110,8 @@ pub enum NymdError {
#[error("Failed to estimate gas price for the transaction")]
GasEstimationFailure,
#[error("Abci query failed with code {code} - {log}")]
AbciError {
code: u32,
log: abci::Log,
pretty_log: Option<String>,
},
#[error("Abci query failed with code {0} - {1}")]
AbciError(u32, abci::Log),
#[error("Unsupported account type: {type_url}")]
UnsupportedAccountType { type_url: String },
@@ -146,32 +135,6 @@ pub enum NymdError {
UnexpectedBech32Prefix { got: String, expected: String },
}
// The purpose of parsing the abci query result is that we want to generate the `pretty_log` if
// possible.
pub fn parse_abci_query_result(query_result: AbciQuery) -> Result<AbciQuery, NymdError> {
match query_result.code {
AbciCode::Ok => Ok(query_result),
AbciCode::Err(code) => Err(NymdError::AbciError {
code,
log: query_result.log.clone(),
pretty_log: try_parse_abci_log(&query_result.log),
}),
}
}
// Some of the error strings returned by the query are a bit too technical to present to the
// enduser. So we special case some commonly encountered errors.
fn try_parse_abci_log(log: &abci::Log) -> Option<String> {
if log
.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())
} else {
None
}
}
impl NymdError {
pub fn is_tendermint_response_timeout(&self) -> bool {
match &self {
@@ -8,13 +8,13 @@ use coconut_dkg_common::dealer::{
DealerDetailsResponse, PagedDealerResponse, PagedDealingsResponse,
};
use coconut_dkg_common::msg::QueryMsg as DkgQueryMsg;
use coconut_dkg_common::types::Epoch;
use coconut_dkg_common::types::EpochState;
use coconut_dkg_common::verification_key::PagedVKSharesResponse;
use cosmrs::AccountId;
#[async_trait]
pub trait DkgQueryClient {
async fn get_current_epoch(&self) -> Result<Epoch, NymdError>;
async fn get_current_epoch_state(&self) -> Result<EpochState, NymdError>;
async fn get_current_epoch_threshold(&self) -> Result<Option<u64>, NymdError>;
async fn get_dealer_details(
&self,
@@ -49,7 +49,7 @@ impl<C> DkgQueryClient for NymdClient<C>
where
C: CosmWasmClient + Send + Sync,
{
async fn get_current_epoch(&self) -> Result<Epoch, NymdError> {
async fn get_current_epoch_state(&self) -> Result<EpochState, NymdError> {
let request = DkgQueryMsg::GetCurrentEpochState {};
self.client
.query_contract_smart(self.coconut_dkg_contract_address(), &request)
@@ -12,7 +12,6 @@ use contracts_common::dealings::ContractSafeBytes;
#[async_trait]
pub trait DkgSigningClient {
async fn advance_dkg_epoch_state(&self, fee: Option<Fee>) -> Result<ExecuteResult, NymdError>;
async fn register_dealer(
&self,
bte_key: EncodedBTEPublicKeyWithProof,
@@ -38,21 +37,6 @@ impl<C> DkgSigningClient for NymdClient<C>
where
C: SigningCosmWasmClient + Send + Sync,
{
async fn advance_dkg_epoch_state(&self, fee: Option<Fee>) -> Result<ExecuteResult, NymdError> {
let req = DkgExecuteMsg::AdvanceEpochState {};
self.client
.execute(
self.address(),
self.coconut_dkg_contract_address(),
&req,
fee.unwrap_or_default(),
"advancing DKG state",
vec![],
)
.await
}
async fn register_dealer(
&self,
bte_key: EncodedBTEPublicKeyWithProof,
@@ -11,6 +11,7 @@ use serde::{Deserialize, Serialize};
pub struct InstantiateMsg {
pub group_addr: String,
pub multisig_addr: String,
pub admin: String,
pub mix_denom: String,
}
@@ -6,48 +6,15 @@ use std::fmt::{Display, Formatter};
pub use crate::dealer::{DealerDetails, PagedDealerResponse};
pub use contracts_common::dealings::ContractSafeBytes;
pub use cosmwasm_std::{Addr, Coin, Timestamp};
pub use cosmwasm_std::{Addr, Coin};
pub type EncodedBTEPublicKeyWithProof = String;
pub type EncodedBTEPublicKeyWithProofRef<'a> = &'a str;
pub type NodeIndex = u64;
// The time sign-up is open for dealers to join (2 minutes)
pub const PUBLIC_KEY_SUBMISSION_TIME_SECS: u64 = 60 * 2;
pub const DEALING_EXCHANGE_TIME_SECS: u64 = 60 * 5;
pub const VERIFICATION_KEY_SUBMISSION_TIME_SECS: u64 = 60 * 5;
pub const VERIFICATION_KEY_VALIDATION_TIME_SECS: u64 = 60;
pub const VERIFICATION_KEY_FINALIZATION_TIME_SECS: u64 = 60;
// The time an epoch lasts (2 weeks)
pub const IN_PROGRESS_TIME_SECS: u64 = 60 * 60 * 24 * 14;
// 2 public attributes, 2 private attributes, 1 fixed for coconut credential
pub const TOTAL_DEALINGS: usize = 2 + 2 + 1;
#[derive(Serialize, Deserialize, Default, Clone, Copy, Debug, PartialEq, Eq, Ord, PartialOrd)]
#[serde(rename_all = "snake_case")]
pub struct Epoch {
pub state: EpochState,
pub finish_timestamp: Timestamp,
}
impl Epoch {
pub fn new(state: EpochState, current_timestamp: Timestamp) -> Self {
let duration = match state {
EpochState::PublicKeySubmission => PUBLIC_KEY_SUBMISSION_TIME_SECS,
EpochState::DealingExchange => DEALING_EXCHANGE_TIME_SECS,
EpochState::VerificationKeySubmission => VERIFICATION_KEY_SUBMISSION_TIME_SECS,
EpochState::VerificationKeyValidation => VERIFICATION_KEY_VALIDATION_TIME_SECS,
EpochState::VerificationKeyFinalization => VERIFICATION_KEY_FINALIZATION_TIME_SECS,
EpochState::InProgress => IN_PROGRESS_TIME_SECS,
};
Epoch {
state,
finish_timestamp: current_timestamp.plus_seconds(duration),
}
}
}
// currently (it is still extremely likely to change, we might be able to get rid of verification key-related complaints),
// the epoch can be in the following states (in order):
// 1. PublicKeySubmission -> potential dealers are submitting their BTE and ed25519 public keys to participate in dealing exchange
@@ -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
@@ -63,7 +63,7 @@ impl NetworkRequesterResponse {
self.connection_id
.to_be_bytes()
.iter()
.copied()
.cloned()
.chain(self.network_requester_error.into_bytes().into_iter())
.collect()
}
+5 -18
View File
@@ -28,13 +28,6 @@ enum TaskError {
UnexpectedHalt,
}
// TODO: possibly we should create a `Status` trait instead of reusing `Error`
#[derive(thiserror::Error, Debug)]
pub enum TaskStatus {
#[error("Ready")]
Ready,
}
/// Listens to status and error messages from tasks, as well as notifying them to gracefully
/// shutdown. Keeps track of if task stop unexpectedly, such as in a panic.
#[derive(Debug)]
@@ -108,21 +101,15 @@ impl TaskManager {
self.notify_tx.send(())
}
pub async fn start_status_listener(&mut self, mut sender: StatusSender) {
// Announce that we are operational. This means that in the application where this is used,
// everything is up and running and ready to go.
if let Err(msg) = sender.send(Box::new(TaskStatus::Ready)).await {
log::error!("Error sending status message: {}", msg);
};
pub fn start_status_listener(&mut self, mut sender: StatusSender) {
if let Some(mut task_status_rx) = self.task_status_rx.take() {
log::info!("Starting status message listener");
crate::spawn::spawn(async move {
loop {
if let Some(msg) = task_status_rx.next().await {
log::trace!("Got msg: {}", msg);
if let Err(msg) = sender.send(msg).await {
log::error!("Error sending status message: {}", msg);
if sender.send(msg).await.is_err() {
log::error!("Error sending status message");
}
} else {
log::trace!("Stopping since channel closed");
@@ -158,7 +145,7 @@ impl TaskManager {
}
pub async fn wait_for_shutdown(&mut self) {
log::debug!("Waiting for shutdown");
log::info!("Waiting for shutdown");
if let Some(notify_rx) = self.notify_rx.take() {
drop(notify_rx);
}
@@ -269,7 +256,7 @@ impl TaskClient {
pub async fn recv_with_delay(&mut self) {
self.recv()
.then(|msg| async move {
sleep(Duration::from_secs(2)).await;
sleep(Duration::from_secs(1)).await;
msg
})
.await
+14 -12
View File
@@ -7,16 +7,16 @@ use crate::dealers::queries::{
use crate::dealers::transactions::try_add_dealer;
use crate::dealings::queries::query_dealings_paged;
use crate::dealings::transactions::try_commit_dealings;
use crate::epoch_state::queries::{query_current_epoch, query_current_epoch_threshold};
use crate::epoch_state::storage::CURRENT_EPOCH;
use crate::epoch_state::queries::{query_current_epoch_state, query_current_epoch_threshold};
use crate::epoch_state::storage::CURRENT_EPOCH_STATE;
use crate::epoch_state::transactions::advance_epoch_state;
use crate::error::ContractError;
use crate::state::{State, MULTISIG, STATE};
use crate::state::{State, ADMIN, MULTISIG, STATE};
use crate::verification_key_shares::queries::query_vk_shares_paged;
use crate::verification_key_shares::transactions::try_commit_verification_key_share;
use crate::verification_key_shares::transactions::try_verify_verification_key_share;
use coconut_dkg_common::msg::{ExecuteMsg, InstantiateMsg, MigrateMsg, QueryMsg};
use coconut_dkg_common::types::{Epoch, EpochState};
use coconut_dkg_common::types::EpochState;
use cosmwasm_std::{
entry_point, to_binary, Deps, DepsMut, Env, MessageInfo, QueryResponse, Response,
};
@@ -30,11 +30,13 @@ use cw4::Cw4Contract;
#[entry_point]
pub fn instantiate(
mut deps: DepsMut<'_>,
env: Env,
_env: Env,
_info: MessageInfo,
msg: InstantiateMsg,
) -> Result<Response, ContractError> {
let admin_addr = deps.api.addr_validate(&msg.admin)?;
let multisig_addr = deps.api.addr_validate(&msg.multisig_addr)?;
ADMIN.set(deps.branch(), Some(admin_addr))?;
MULTISIG.set(deps.branch(), Some(multisig_addr.clone()))?;
let group_addr = Cw4Contract(deps.api.addr_validate(&msg.group_addr).map_err(|_| {
@@ -50,10 +52,7 @@ pub fn instantiate(
};
STATE.save(deps.storage, &state)?;
CURRENT_EPOCH.save(
deps.storage,
&Epoch::new(EpochState::default(), env.block.time),
)?;
CURRENT_EPOCH_STATE.save(deps.storage, &EpochState::default())?;
Ok(Response::default())
}
@@ -80,14 +79,14 @@ pub fn execute(
ExecuteMsg::VerifyVerificationKeyShare { owner } => {
try_verify_verification_key_share(deps, info, owner)
}
ExecuteMsg::AdvanceEpochState {} => advance_epoch_state(deps, env),
ExecuteMsg::AdvanceEpochState {} => advance_epoch_state(deps, info),
}
}
#[entry_point]
pub fn query(deps: Deps<'_>, _env: Env, msg: QueryMsg) -> Result<QueryResponse, ContractError> {
let response = match msg {
QueryMsg::GetCurrentEpochState {} => to_binary(&query_current_epoch(deps.storage)?)?,
QueryMsg::GetCurrentEpochState {} => to_binary(&query_current_epoch_state(deps.storage)?)?,
QueryMsg::GetCurrentEpochThreshold {} => {
to_binary(&query_current_epoch_threshold(deps.storage)?)?
}
@@ -121,8 +120,9 @@ pub fn migrate(_deps: DepsMut<'_>, _env: Env, _msg: MigrateMsg) -> Result<Respon
#[cfg(test)]
mod tests {
use super::*;
use crate::support::tests::fixtures::TEST_MIX_DENOM;
use crate::support::tests::fixtures::{dealer_details_fixture, TEST_MIX_DENOM};
use crate::support::tests::helpers::{ADMIN_ADDRESS, MULTISIG_CONTRACT};
use coconut_dkg_common::dealer::DealerDetails;
use coconut_dkg_common::msg::ExecuteMsg::RegisterDealer;
use coconut_dkg_common::types::NodeIndex;
use cosmwasm_std::testing::{mock_dependencies, mock_env, mock_info};
@@ -163,6 +163,7 @@ mod tests {
let msg = InstantiateMsg {
group_addr: group_contract_addr.to_string(),
multisig_addr: MULTISIG_CONTRACT.to_string(),
admin: Addr::unchecked(ADMIN_ADDRESS).to_string(),
mix_denom: TEST_MIX_DENOM.to_string(),
};
app.instantiate_contract(
@@ -197,6 +198,7 @@ mod tests {
let msg = InstantiateMsg {
group_addr: "group_addr".to_string(),
multisig_addr: "multisig_addr".to_string(),
admin: "admin".to_string(),
mix_denom: "nym".to_string(),
};
let info = mock_info("creator", &[]);
+9 -2
View File
@@ -72,7 +72,8 @@ pub(crate) mod tests {
use crate::dealers::storage::{DEALERS_PAGE_DEFAULT_LIMIT, DEALERS_PAGE_MAX_LIMIT};
use crate::support::tests::fixtures::dealer_details_fixture;
use crate::support::tests::helpers::init_contract;
use cosmwasm_std::DepsMut;
use cosmwasm_std::testing::mock_env;
use cosmwasm_std::{Addr, DepsMut};
fn fill_dealers(deps: DepsMut<'_>, mapping: &IndexedDealersMap<'_>, size: usize) {
for n in 0..size {
@@ -94,7 +95,8 @@ pub(crate) mod tests {
#[test]
fn dealers_empty_on_init() {
let deps = init_contract();
let mut deps = init_contract();
let env = mock_env();
for mapping in [storage::current_dealers(), storage::past_dealers()] {
let page1 = query_dealers(deps.as_ref(), None, None, &mapping).unwrap();
@@ -105,6 +107,8 @@ pub(crate) mod tests {
#[test]
fn dealers_paged_retrieval_obeys_limits() {
let mut deps = init_contract();
let env = mock_env();
let owner = Addr::unchecked("owner");
let limit = 2;
for mapping in [storage::current_dealers(), storage::past_dealers()] {
@@ -120,6 +124,7 @@ pub(crate) mod tests {
#[test]
fn dealers_paged_retrieval_has_default_limit() {
let mut deps = init_contract();
let env = mock_env();
for mapping in [storage::current_dealers(), storage::past_dealers()] {
fill_dealers(deps.as_mut(), &mapping, 1000);
@@ -136,6 +141,7 @@ pub(crate) mod tests {
#[test]
fn dealers_paged_retrieval_has_max_limit() {
let mut deps = init_contract();
let env = mock_env();
// query with a crazily high limit in an attempt to use too many resources
let crazy_limit = 1000 * DEALERS_PAGE_MAX_LIMIT;
@@ -157,6 +163,7 @@ pub(crate) mod tests {
#[test]
fn dealers_pagination_works() {
let mut deps = init_contract();
let env = mock_env();
let per_page = 2;
@@ -70,21 +70,21 @@ pub fn try_add_dealer(
pub(crate) mod tests {
use super::*;
use crate::epoch_state::transactions::advance_epoch_state;
use crate::support::tests::fixtures::dealer_details_fixture;
use crate::support::tests::helpers;
use coconut_dkg_common::types::PUBLIC_KEY_SUBMISSION_TIME_SECS;
use cosmwasm_std::testing::{mock_env, mock_info};
use crate::support::tests::helpers::ADMIN_ADDRESS;
use cosmwasm_std::testing::mock_info;
#[test]
fn invalid_state() {
let mut deps = helpers::init_contract();
let owner = Addr::unchecked("owner");
let mut env = mock_env();
let info = mock_info(owner.as_str(), &[]);
let dealer_details = dealer_details_fixture(1);
let bte_key_with_proof = String::from("bte_key_with_proof");
let announce_address = String::from("localhost:8000");
env.block.time = env.block.time.plus_seconds(PUBLIC_KEY_SUBMISSION_TIME_SECS);
advance_epoch_state(deps.as_mut(), env).unwrap();
advance_epoch_state(deps.as_mut(), mock_info(ADMIN_ADDRESS, &[])).unwrap();
let ret = try_add_dealer(
deps.as_mut(),
@@ -50,6 +50,7 @@ pub(crate) mod tests {
use crate::dealings::storage::{DEALINGS_PAGE_DEFAULT_LIMIT, DEALINGS_PAGE_MAX_LIMIT};
use crate::support::tests::fixtures::dealing_bytes_fixture;
use crate::support::tests::helpers::init_contract;
use cosmwasm_std::testing::mock_env;
use cosmwasm_std::{Addr, DepsMut};
fn fill_dealings(deps: DepsMut<'_>, size: usize) {
@@ -67,6 +68,7 @@ pub(crate) mod tests {
#[test]
fn empty_on_bad_idx() {
let mut deps = init_contract();
let env = mock_env();
fill_dealings(deps.as_mut(), 1000);
for idx in TOTAL_DEALINGS as u64..100 * TOTAL_DEALINGS as u64 {
@@ -87,6 +89,7 @@ pub(crate) mod tests {
#[test]
fn dealings_paged_retrieval_obeys_limits() {
let mut deps = init_contract();
let env = mock_env();
let limit = 2;
fill_dealings(deps.as_mut(), 1000);
@@ -100,6 +103,7 @@ pub(crate) mod tests {
#[test]
fn dealings_paged_retrieval_has_default_limit() {
let mut deps = init_contract();
let env = mock_env();
fill_dealings(deps.as_mut(), 1000);
for idx in 0..TOTAL_DEALINGS as u64 {
@@ -113,6 +117,7 @@ pub(crate) mod tests {
#[test]
fn dealings_paged_retrieval_has_max_limit() {
let mut deps = init_contract();
let env = mock_env();
fill_dealings(deps.as_mut(), 1000);
// query with a crazily high limit in an attempt to use too many resources
@@ -130,6 +135,7 @@ pub(crate) mod tests {
#[test]
fn dealings_pagination_works() {
let mut deps = init_contract();
let env = mock_env();
fill_dealings(deps.as_mut(), 1);
@@ -42,16 +42,16 @@ pub(crate) mod tests {
use crate::epoch_state::transactions::advance_epoch_state;
use crate::support::tests::fixtures::dealing_bytes_fixture;
use crate::support::tests::helpers;
use crate::support::tests::helpers::ADMIN_ADDRESS;
use coconut_dkg_common::dealer::DealerDetails;
use coconut_dkg_common::types::PUBLIC_KEY_SUBMISSION_TIME_SECS;
use cosmwasm_std::testing::{mock_env, mock_info};
use coconut_dkg_common::types::TOTAL_DEALINGS;
use cosmwasm_std::testing::mock_info;
use cosmwasm_std::Addr;
#[test]
fn invalid_commit_dealing() {
let mut deps = helpers::init_contract();
let owner = Addr::unchecked("owner");
let mut env = mock_env();
let info = mock_info(owner.as_str(), &[]);
let dealing_bytes = dealing_bytes_fixture();
@@ -65,8 +65,7 @@ pub(crate) mod tests {
}
);
env.block.time = env.block.time.plus_seconds(PUBLIC_KEY_SUBMISSION_TIME_SECS);
advance_epoch_state(deps.as_mut(), env).unwrap();
advance_epoch_state(deps.as_mut(), mock_info(ADMIN_ADDRESS, &[])).unwrap();
let ret =
try_commit_dealings(deps.as_mut(), info.clone(), dealing_bytes.clone()).unwrap_err();
@@ -1,13 +1,15 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::epoch_state::storage::{CURRENT_EPOCH, THRESHOLD};
use crate::epoch_state::storage::{CURRENT_EPOCH_STATE, THRESHOLD};
use crate::error::ContractError;
use coconut_dkg_common::types::Epoch;
use coconut_dkg_common::types::EpochState;
use cosmwasm_std::Storage;
pub(crate) fn query_current_epoch(storage: &dyn Storage) -> Result<Epoch, ContractError> {
CURRENT_EPOCH
pub(crate) fn query_current_epoch_state(
storage: &dyn Storage,
) -> Result<EpochState, ContractError> {
CURRENT_EPOCH_STATE
.load(storage)
.map_err(|_| ContractError::EpochNotInitialised)
}
@@ -22,21 +24,12 @@ pub(crate) fn query_current_epoch_threshold(
pub(crate) mod test {
use super::*;
use crate::support::tests::helpers::init_contract;
use coconut_dkg_common::types::{EpochState, PUBLIC_KEY_SUBMISSION_TIME_SECS};
use cosmwasm_std::testing::mock_env;
#[test]
fn query_state() {
let mut deps = init_contract();
let epoch = query_current_epoch(deps.as_mut().storage).unwrap();
assert_eq!(epoch.state, EpochState::PublicKeySubmission);
assert_eq!(
epoch.finish_timestamp,
mock_env()
.block
.time
.plus_seconds(PUBLIC_KEY_SUBMISSION_TIME_SECS)
);
let state = query_current_epoch_state(deps.as_mut().storage).unwrap();
assert_eq!(state, EpochState::PublicKeySubmission);
}
#[test]
@@ -1,8 +1,8 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use coconut_dkg_common::types::Epoch;
use coconut_dkg_common::types::EpochState;
use cw_storage_plus::Item;
pub(crate) const CURRENT_EPOCH: Item<'_, Epoch> = Item::new("current_epoch");
pub(crate) const CURRENT_EPOCH_STATE: Item<'_, EpochState> = Item::new("current_epoch_state");
pub const THRESHOLD: Item<u64> = Item::new("threshold");
@@ -2,29 +2,25 @@
// SPDX-License-Identifier: Apache-2.0
use crate::dealers::storage::current_dealers;
use crate::epoch_state::storage::{CURRENT_EPOCH, THRESHOLD};
use crate::epoch_state::storage::{CURRENT_EPOCH_STATE, THRESHOLD};
use crate::error::ContractError;
use coconut_dkg_common::types::{Epoch, EpochState};
use cosmwasm_std::{DepsMut, Env, Order, Response};
use crate::state::ADMIN;
use coconut_dkg_common::types::EpochState;
use cosmwasm_std::{DepsMut, MessageInfo, Order, Response};
pub(crate) fn advance_epoch_state(deps: DepsMut<'_>, env: Env) -> Result<Response, ContractError> {
let epoch = CURRENT_EPOCH.load(deps.storage)?;
if epoch.finish_timestamp > env.block.time {
return Err(ContractError::EarlyEpochStateAdvancement(
epoch
.finish_timestamp
.minus_seconds(env.block.time.seconds())
.seconds(),
));
}
let current_epoch = CURRENT_EPOCH.update::<_, ContractError>(deps.storage, |mut epoch| {
// TODO: When defaulting to the first state, some action will probably need to be taken on the
// rest of the contract, as we're starting with a new set of signers
epoch = Epoch::new(epoch.state.next().unwrap_or_default(), env.block.time);
Ok(epoch)
})?;
if current_epoch.state == EpochState::DealingExchange {
pub(crate) fn advance_epoch_state(
deps: DepsMut<'_>,
info: MessageInfo,
) -> Result<Response, ContractError> {
ADMIN.assert_admin(deps.as_ref(), &info.sender)?;
let current_epoch_state =
CURRENT_EPOCH_STATE.update::<_, ContractError>(deps.storage, |mut epoch_state| {
// TODO: When defaulting to the first state, some action will probably need to be taken on the
// rest of the contract, as we're starting with a new set of signers
epoch_state = epoch_state.next().unwrap_or_default();
Ok(epoch_state)
})?;
if current_epoch_state == EpochState::DealingExchange {
let current_dealer_count = current_dealers()
.keys(deps.storage, None, None, Order::Ascending)
.count();
@@ -38,147 +34,64 @@ pub(crate) fn advance_epoch_state(deps: DepsMut<'_>, env: Env) -> Result<Respons
#[cfg(test)]
pub(crate) mod tests {
use super::*;
use crate::error::ContractError::EarlyEpochStateAdvancement;
use crate::support::tests::helpers::init_contract;
use coconut_dkg_common::types::{
DealerDetails, EpochState, DEALING_EXCHANGE_TIME_SECS, IN_PROGRESS_TIME_SECS,
PUBLIC_KEY_SUBMISSION_TIME_SECS, VERIFICATION_KEY_FINALIZATION_TIME_SECS,
VERIFICATION_KEY_SUBMISSION_TIME_SECS, VERIFICATION_KEY_VALIDATION_TIME_SECS,
};
use cosmwasm_std::testing::mock_env;
use crate::support::tests::helpers::{init_contract, ADMIN_ADDRESS};
use coconut_dkg_common::types::{DealerDetails, EpochState};
use cosmwasm_std::testing::mock_info;
use cosmwasm_std::Addr;
use cw_controllers::AdminError;
#[test]
fn advance_state() {
let mut deps = init_contract();
let mut env = mock_env();
let info = mock_info("requester", &[]);
let admin_info = mock_info(ADMIN_ADDRESS, &[]);
let epoch = CURRENT_EPOCH.load(deps.as_mut().storage).unwrap();
assert_eq!(epoch.state, EpochState::PublicKeySubmission);
assert_eq!(
epoch.finish_timestamp,
env.block.time.plus_seconds(PUBLIC_KEY_SUBMISSION_TIME_SECS)
advance_epoch_state(deps.as_mut(), info).unwrap_err(),
ContractError::Admin(AdminError::NotAdmin {})
);
env.block.time = env
.block
.time
.plus_seconds(PUBLIC_KEY_SUBMISSION_TIME_SECS - 1);
advance_epoch_state(deps.as_mut(), admin_info.clone()).unwrap();
assert_eq!(
advance_epoch_state(deps.as_mut(), env.clone()).unwrap_err(),
EarlyEpochStateAdvancement(1)
CURRENT_EPOCH_STATE.load(deps.as_mut().storage).unwrap(),
EpochState::DealingExchange
);
env.block.time = env.block.time.plus_seconds(1);
advance_epoch_state(deps.as_mut(), env.clone()).unwrap();
let epoch = CURRENT_EPOCH.load(deps.as_mut().storage).unwrap();
assert_eq!(epoch.state, EpochState::DealingExchange);
advance_epoch_state(deps.as_mut(), admin_info.clone()).unwrap();
assert_eq!(
epoch.finish_timestamp,
env.block.time.plus_seconds(DEALING_EXCHANGE_TIME_SECS)
CURRENT_EPOCH_STATE.load(deps.as_mut().storage).unwrap(),
EpochState::VerificationKeySubmission
);
env.block.time = env.block.time.plus_seconds(DEALING_EXCHANGE_TIME_SECS - 2);
advance_epoch_state(deps.as_mut(), admin_info.clone()).unwrap();
assert_eq!(
advance_epoch_state(deps.as_mut(), env.clone()).unwrap_err(),
EarlyEpochStateAdvancement(2)
CURRENT_EPOCH_STATE.load(deps.as_mut().storage).unwrap(),
EpochState::VerificationKeyValidation
);
env.block.time = env.block.time.plus_seconds(3);
advance_epoch_state(deps.as_mut(), env.clone()).unwrap();
let epoch = CURRENT_EPOCH.load(deps.as_mut().storage).unwrap();
assert_eq!(epoch.state, EpochState::VerificationKeySubmission);
advance_epoch_state(deps.as_mut(), admin_info.clone()).unwrap();
assert_eq!(
epoch.finish_timestamp,
env.block
.time
.plus_seconds(VERIFICATION_KEY_SUBMISSION_TIME_SECS)
CURRENT_EPOCH_STATE.load(deps.as_mut().storage).unwrap(),
EpochState::VerificationKeyFinalization
);
env.block.time = env
.block
.time
.plus_seconds(VERIFICATION_KEY_SUBMISSION_TIME_SECS - 2);
advance_epoch_state(deps.as_mut(), admin_info.clone()).unwrap();
assert_eq!(
advance_epoch_state(deps.as_mut(), env.clone()).unwrap_err(),
EarlyEpochStateAdvancement(2)
CURRENT_EPOCH_STATE.load(deps.as_mut().storage).unwrap(),
EpochState::InProgress
);
env.block.time = env.block.time.plus_seconds(3);
advance_epoch_state(deps.as_mut(), env.clone()).unwrap();
let epoch = CURRENT_EPOCH.load(deps.as_mut().storage).unwrap();
assert_eq!(epoch.state, EpochState::VerificationKeyValidation);
advance_epoch_state(deps.as_mut(), admin_info.clone()).unwrap();
assert_eq!(
epoch.finish_timestamp,
env.block
.time
.plus_seconds(VERIFICATION_KEY_VALIDATION_TIME_SECS)
);
env.block.time = env
.block
.time
.plus_seconds(VERIFICATION_KEY_VALIDATION_TIME_SECS - 3);
assert_eq!(
advance_epoch_state(deps.as_mut(), env.clone()).unwrap_err(),
EarlyEpochStateAdvancement(3)
);
env.block.time = env.block.time.plus_seconds(3);
advance_epoch_state(deps.as_mut(), env.clone()).unwrap();
let epoch = CURRENT_EPOCH.load(deps.as_mut().storage).unwrap();
assert_eq!(epoch.state, EpochState::VerificationKeyFinalization);
assert_eq!(
epoch.finish_timestamp,
env.block
.time
.plus_seconds(VERIFICATION_KEY_FINALIZATION_TIME_SECS)
);
env.block.time = env
.block
.time
.plus_seconds(VERIFICATION_KEY_FINALIZATION_TIME_SECS - 1);
assert_eq!(
advance_epoch_state(deps.as_mut(), env.clone()).unwrap_err(),
EarlyEpochStateAdvancement(1)
);
env.block.time = env.block.time.plus_seconds(1);
advance_epoch_state(deps.as_mut(), env.clone()).unwrap();
let epoch = CURRENT_EPOCH.load(deps.as_mut().storage).unwrap();
assert_eq!(epoch.state, EpochState::InProgress);
assert_eq!(
epoch.finish_timestamp,
env.block.time.plus_seconds(IN_PROGRESS_TIME_SECS)
);
env.block.time = env.block.time.plus_seconds(IN_PROGRESS_TIME_SECS - 100);
assert_eq!(
advance_epoch_state(deps.as_mut(), env.clone()).unwrap_err(),
EarlyEpochStateAdvancement(100)
);
env.block.time = env.block.time.plus_seconds(50);
assert_eq!(
advance_epoch_state(deps.as_mut(), env.clone()).unwrap_err(),
EarlyEpochStateAdvancement(50)
);
env.block.time = env.block.time.plus_seconds(100);
advance_epoch_state(deps.as_mut(), env.clone()).unwrap();
let epoch = CURRENT_EPOCH.load(deps.as_mut().storage).unwrap();
assert_eq!(epoch.state, EpochState::PublicKeySubmission);
assert_eq!(
epoch.finish_timestamp,
env.block.time.plus_seconds(PUBLIC_KEY_SUBMISSION_TIME_SECS)
CURRENT_EPOCH_STATE.load(deps.as_mut().storage).unwrap(),
EpochState::PublicKeySubmission
);
}
#[test]
fn verify_threshold() {
let mut deps = init_contract();
let mut env = mock_env();
let admin_info = mock_info(ADMIN_ADDRESS, &[]);
assert!(THRESHOLD.may_load(deps.as_mut().storage).unwrap().is_none());
@@ -198,8 +111,7 @@ pub(crate) mod tests {
.unwrap();
}
env.block.time = env.block.time.plus_seconds(PUBLIC_KEY_SUBMISSION_TIME_SECS);
advance_epoch_state(deps.as_mut(), env).unwrap();
advance_epoch_state(deps.as_mut(), admin_info.clone()).unwrap();
assert_eq!(
THRESHOLD.may_load(deps.as_mut().storage).unwrap().unwrap(),
67
+4 -10
View File
@@ -1,7 +1,7 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::epoch_state::storage::CURRENT_EPOCH;
use crate::epoch_state::storage::CURRENT_EPOCH_STATE;
use crate::error::ContractError;
use coconut_dkg_common::types::EpochState;
use cosmwasm_std::Storage;
@@ -10,7 +10,7 @@ pub(crate) fn check_epoch_state(
storage: &dyn Storage,
against: EpochState,
) -> Result<(), ContractError> {
let epoch_state = CURRENT_EPOCH.load(storage)?.state;
let epoch_state = CURRENT_EPOCH_STATE.load(storage)?;
if epoch_state != against {
Err(ContractError::IncorrectEpochState {
current_state: epoch_state.to_string(),
@@ -25,20 +25,14 @@ pub(crate) fn check_epoch_state(
pub(crate) mod test {
use super::*;
use crate::support::tests::helpers::init_contract;
use coconut_dkg_common::types::Epoch;
use cosmwasm_std::testing::mock_env;
#[test]
pub fn check_state() {
let mut deps = init_contract();
let env = mock_env();
for fixed_state in EpochState::default().all_until(EpochState::InProgress) {
CURRENT_EPOCH
.save(
deps.as_mut().storage,
&Epoch::new(fixed_state, env.block.time),
)
CURRENT_EPOCH_STATE
.save(deps.as_mut().storage, &fixed_state)
.unwrap();
for against_state in EpochState::default().all_until(EpochState::InProgress) {
let ret = check_epoch_state(deps.as_mut().storage, against_state);
-3
View File
@@ -23,9 +23,6 @@ pub enum ContractError {
#[error("This sender is already a dealer for the epoch")]
AlreadyADealer,
#[error("Too soon to advance epoch state. {0} more seconds until it can be advanced")]
EarlyEpochStateAdvancement(u64),
#[error("Epoch hasn't been correctly initialised!")]
EpochNotInitialised,
+1
View File
@@ -10,6 +10,7 @@ use serde::{Deserialize, Serialize};
// unique items
pub const STATE: Item<State> = Item::new("state");
pub const ADMIN: Admin = Admin::new("admin");
pub const MULTISIG: Admin = Admin::new("multisig");
#[derive(Serialize, Deserialize, Clone, PartialEq, JsonSchema, Debug)]
@@ -1,7 +1,7 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use coconut_dkg_common::dealer::DealerDetails;
use coconut_dkg_common::dealer::{ContractDealing, DealerDetails};
use coconut_dkg_common::types::ContractSafeBytes;
use coconut_dkg_common::verification_key::ContractVKShare;
use cosmwasm_std::Addr;
@@ -17,6 +17,7 @@ pub fn init_contract() -> OwnedDeps<MemoryStorage, MockApi, MockQuerier<Empty>>
let msg = InstantiateMsg {
group_addr: String::from(GROUP_CONTRACT),
multisig_addr: String::from(MULTISIG_CONTRACT),
admin: String::from(ADMIN_ADDRESS),
mix_denom: TEST_MIX_DENOM.to_string(),
};
let env = mock_env();
@@ -45,6 +45,7 @@ pub(crate) mod tests {
use crate::verification_key_shares::storage::{
VERIFICATION_KEY_SHARES_PAGE_DEFAULT_LIMIT, VERIFICATION_KEY_SHARES_PAGE_MAX_LIMIT,
};
use cosmwasm_std::testing::mock_env;
use cosmwasm_std::Addr;
#[test]
@@ -57,6 +58,7 @@ pub(crate) mod tests {
#[test]
fn vk_shares_paged_retrieval_obeys_limits() {
let mut deps = init_contract();
let env = mock_env();
let limit = 2;
for n in 0..1000 {
let vk_share = vk_share_fixture(n);
@@ -73,6 +75,7 @@ pub(crate) mod tests {
#[test]
fn vk_shares_paged_retrieval_has_default_limit() {
let mut deps = init_contract();
let env = mock_env();
for n in 0..1000 {
let vk_share = vk_share_fixture(n);
let sender = Addr::unchecked(format!("owner{}", n));
@@ -93,6 +96,7 @@ pub(crate) mod tests {
#[test]
fn vk_shares_paged_retrieval_has_max_limit() {
let mut deps = init_contract();
let env = mock_env();
for n in 0..1000 {
let vk_share = vk_share_fixture(n);
let sender = Addr::unchecked(format!("owner{}", n));
@@ -113,6 +117,7 @@ pub(crate) mod tests {
#[test]
fn vk_shares_pagination_works() {
let mut deps = init_contract();
let env = mock_env();
let vk_share = vk_share_fixture(1);
let sender = Addr::unchecked(format!("owner{}", 1));
@@ -73,21 +73,20 @@ pub fn try_verify_verification_key_share(
#[cfg(test)]
mod tests {
use super::*;
use crate::epoch_state::storage::CURRENT_EPOCH_STATE;
use crate::epoch_state::transactions::advance_epoch_state;
use crate::support::tests::helpers;
use crate::support::tests::helpers::MULTISIG_CONTRACT;
use crate::support::tests::helpers::{ADMIN_ADDRESS, MULTISIG_CONTRACT};
use coconut_dkg_common::dealer::DealerDetails;
use coconut_dkg_common::types::{
EpochState, DEALING_EXCHANGE_TIME_SECS, PUBLIC_KEY_SUBMISSION_TIME_SECS,
VERIFICATION_KEY_SUBMISSION_TIME_SECS, VERIFICATION_KEY_VALIDATION_TIME_SECS,
};
use coconut_dkg_common::types::EpochState;
use cosmwasm_std::testing::{mock_env, mock_info};
use cosmwasm_std::Storage;
use cw_controllers::AdminError;
#[test]
fn commit_vk_share() {
let mut deps = helpers::init_contract();
let mut env = mock_env();
let env = mock_env();
let info = mock_info("requester", &[]);
let share = "share".to_string();
@@ -105,10 +104,8 @@ mod tests {
expected_state: EpochState::VerificationKeySubmission.to_string()
}
);
env.block.time = env.block.time.plus_seconds(PUBLIC_KEY_SUBMISSION_TIME_SECS);
advance_epoch_state(deps.as_mut(), env.clone()).unwrap();
env.block.time = env.block.time.plus_seconds(DEALING_EXCHANGE_TIME_SECS);
advance_epoch_state(deps.as_mut(), env.clone()).unwrap();
advance_epoch_state(deps.as_mut(), mock_info(ADMIN_ADDRESS, &[])).unwrap();
advance_epoch_state(deps.as_mut(), mock_info(ADMIN_ADDRESS, &[])).unwrap();
let ret = try_commit_verification_key_share(
deps.as_mut(),
env.clone(),
@@ -150,7 +147,6 @@ mod tests {
#[test]
fn invalid_verify_vk_share() {
let mut deps = helpers::init_contract();
let mut env = mock_env();
let info = mock_info("requester", &[]);
let owner = Addr::unchecked("owner");
let multisig_info = mock_info(MULTISIG_CONTRACT, &[]);
@@ -165,20 +161,10 @@ mod tests {
}
);
env.block.time = env.block.time.plus_seconds(PUBLIC_KEY_SUBMISSION_TIME_SECS);
advance_epoch_state(deps.as_mut(), env.clone()).unwrap();
env.block.time = env.block.time.plus_seconds(DEALING_EXCHANGE_TIME_SECS);
advance_epoch_state(deps.as_mut(), env.clone()).unwrap();
env.block.time = env
.block
.time
.plus_seconds(VERIFICATION_KEY_SUBMISSION_TIME_SECS);
advance_epoch_state(deps.as_mut(), env.clone()).unwrap();
env.block.time = env
.block
.time
.plus_seconds(VERIFICATION_KEY_VALIDATION_TIME_SECS);
advance_epoch_state(deps.as_mut(), env).unwrap();
advance_epoch_state(deps.as_mut(), mock_info(ADMIN_ADDRESS, &[])).unwrap();
advance_epoch_state(deps.as_mut(), mock_info(ADMIN_ADDRESS, &[])).unwrap();
advance_epoch_state(deps.as_mut(), mock_info(ADMIN_ADDRESS, &[])).unwrap();
advance_epoch_state(deps.as_mut(), mock_info(ADMIN_ADDRESS, &[])).unwrap();
let ret =
try_verify_verification_key_share(deps.as_mut(), info, owner.clone()).unwrap_err();
@@ -197,16 +183,14 @@ mod tests {
#[test]
fn verify_vk_share() {
let mut deps = helpers::init_contract();
let mut env = mock_env();
let env = mock_env();
let owner = Addr::unchecked("owner");
let info = mock_info(owner.as_ref(), &[]);
let share = "share".to_string();
let multisig_info = mock_info(MULTISIG_CONTRACT, &[]);
env.block.time = env.block.time.plus_seconds(PUBLIC_KEY_SUBMISSION_TIME_SECS);
advance_epoch_state(deps.as_mut(), env.clone()).unwrap();
env.block.time = env.block.time.plus_seconds(DEALING_EXCHANGE_TIME_SECS);
advance_epoch_state(deps.as_mut(), env.clone()).unwrap();
advance_epoch_state(deps.as_mut(), mock_info(ADMIN_ADDRESS, &[])).unwrap();
advance_epoch_state(deps.as_mut(), mock_info(ADMIN_ADDRESS, &[])).unwrap();
let dealer_details = DealerDetails {
address: owner.clone(),
@@ -220,16 +204,8 @@ mod tests {
try_commit_verification_key_share(deps.as_mut(), env.clone(), info.clone(), share.clone())
.unwrap();
env.block.time = env
.block
.time
.plus_seconds(VERIFICATION_KEY_SUBMISSION_TIME_SECS);
advance_epoch_state(deps.as_mut(), env.clone()).unwrap();
env.block.time = env
.block
.time
.plus_seconds(VERIFICATION_KEY_VALIDATION_TIME_SECS);
advance_epoch_state(deps.as_mut(), env).unwrap();
advance_epoch_state(deps.as_mut(), mock_info(ADMIN_ADDRESS, &[])).unwrap();
advance_epoch_state(deps.as_mut(), mock_info(ADMIN_ADDRESS, &[])).unwrap();
try_verify_verification_key_share(deps.as_mut(), multisig_info, owner.clone()).unwrap();
}
@@ -71,6 +71,7 @@ fn dkg_proposal() {
let msg = DkgInstantiateMsg {
group_addr: group_contract_addr.to_string(),
multisig_addr: multisig_contract_addr.to_string(),
admin: Addr::unchecked(OWNER).to_string(),
mix_denom: TEST_COIN_DENOM.to_string(),
};
let coconut_dkg_contract_addr = app
@@ -108,7 +109,6 @@ fn dkg_proposal() {
.unwrap();
for _ in 0..2 {
app.update_block(|block| block.time = block.time.plus_seconds(1000));
app.execute_contract(
Addr::unchecked(OWNER),
coconut_dkg_contract_addr.clone(),
@@ -175,7 +175,6 @@ fn dkg_proposal() {
.unwrap();
for _ in 0..2 {
app.update_block(|block| block.time = block.time.plus_seconds(1000));
app.execute_contract(
Addr::unchecked(OWNER),
coconut_dkg_contract_addr.clone(),
+1 -1
View File
@@ -1,2 +1,2 @@
# The path to the geoip database file
GEOIP_DB_PATH=./geo_ip/GeoLite2-City.mmdb
GEOIP_DB_PATH=./geo_ip/GeoLite2-Country.mmdb
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "explorer-api"
version = "1.1.2"
version = "1.1.1"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+1 -1
View File
@@ -40,7 +40,7 @@ It should be previously installed thanks to `geoipupdate` service.
For example:
```shell
GEOIP_DB_PATH=./geo_ip/GeoLite2-City.mmdb cargo run
GEOIP_DB_PATH=./geo_ip/GeoLite2-Country.mmdb cargo run
```
Note: explorer-api binary reads the provided `.env` file.
+26
View File
@@ -0,0 +1,26 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::geo_ip::location::Location;
use crate::state::ExplorerApiStateContext;
use rocket::response::status;
use rocket::serde::json::Json;
use rocket::{Route, State};
use rocket_okapi::okapi::openapi3::OpenApi;
use rocket_okapi::settings::OpenApiSettings;
pub fn nym_terms_make_default_routes(settings: &OpenApiSettings) -> (Vec<Route>, OpenApi) {
openapi_get_routes_spec![settings: terms]
}
#[openapi(tag = "terms")]
#[get("/")]
pub(crate) async fn terms(
_state: &State<ExplorerApiStateContext>,
location: Location,
) -> Result<Json<String>, status::Forbidden<String>> {
if location.iso_alpha2 == "US" {
return Err(status::Forbidden(Some("US government sucks".to_string())));
}
Ok(Json("Nym Terms & Conditions: Welcome".to_string()))
}
+1
View File
@@ -0,0 +1 @@
pub(crate) mod http;
+6 -11
View File
@@ -3,14 +3,14 @@
use isocountry::CountryCode;
use log::warn;
use maxminddb::{geoip2::City, MaxMindDBError, Reader};
use maxminddb::{geoip2::Country, MaxMindDBError, Reader};
use std::{
net::{IpAddr, ToSocketAddrs},
str::FromStr,
sync::Arc,
};
const DEFAULT_DATABASE_PATH: &str = "./geo_ip/GeoLite2-City.mmdb";
const DEFAULT_DATABASE_PATH: &str = "./geo_ip/GeoLite2-Country.mmdb";
const FAKE_PORT: u16 = 1234;
#[derive(Debug)]
@@ -38,8 +38,6 @@ pub(crate) struct Location {
pub(crate) iso_alpha3: String,
/// English country short name (ISO 3166-1)
pub(crate) name: String,
pub(crate) latitude: Option<f64>,
pub(crate) longitude: Option<f64>,
}
impl GeoIp {
@@ -88,7 +86,7 @@ impl GeoIp {
error!("No registered GeoIP database");
GeoIpError::InternalError
})?
.lookup::<City>(ip);
.lookup::<Country>(ip);
match &result {
Ok(v) => Ok(Some(
Location::try_from(v).map_err(|_| GeoIpError::InternalError)?,
@@ -101,11 +99,11 @@ impl GeoIp {
}
}
impl<'a> TryFrom<&City<'a>> for Location {
impl<'a> TryFrom<&Country<'a>> for Location {
type Error = String;
fn try_from(city: &City) -> Result<Self, Self::Error> {
let data = city.country.as_ref().ok_or_else(|| {
fn try_from(country: &Country) -> Result<Self, Self::Error> {
let data = country.country.as_ref().ok_or_else(|| {
warn!("No Country data found");
"No Country data found"
})?;
@@ -121,13 +119,10 @@ impl<'a> TryFrom<&City<'a>> for Location {
warn!("{}", &message);
message
})?;
Ok(Location {
iso_alpha2,
iso_alpha3: String::from(iso_codes.alpha3()),
name: String::from(iso_codes.name()),
latitude: city.location.as_ref().and_then(|l| l.latitude),
longitude: city.location.as_ref().and_then(|l| l.longitude),
})
}
}
+2
View File
@@ -5,6 +5,7 @@ use rocket::{Build, Request, Rocket};
use rocket_cors::{AllowedHeaders, AllowedOrigins};
use rocket_okapi::swagger_ui::make_swagger_ui;
use crate::buy_terms::http::nym_terms_make_default_routes;
use crate::country_statistics::http::country_statistics_make_default_routes;
use crate::gateways::http::gateways_make_default_routes;
use crate::http::swagger::get_docs;
@@ -56,6 +57,7 @@ fn configure_rocket(state: ExplorerApiStateContext) -> Rocket<Build> {
"/overview" => overview_make_default_routes(&openapi_settings),
"/ping" => ping_make_default_routes(&openapi_settings),
"/validators" => validators_make_default_routes(&openapi_settings),
"/terms" => nym_terms_make_default_routes(&openapi_settings),
};
building_rocket
+1
View File
@@ -10,6 +10,7 @@ use logging::setup_logging;
use network_defaults::setup_env;
use task::TaskManager;
mod buy_terms;
pub(crate) mod cache;
mod client;
pub(crate) mod commands;
-4
View File
@@ -36,8 +36,6 @@ pub(crate) struct Location {
pub(crate) two_letter_iso_country_code: String,
pub(crate) three_letter_iso_country_code: String,
pub(crate) country_name: String,
pub(crate) latitude: Option<f64>,
pub(crate) longitude: Option<f64>,
}
impl Location {
@@ -46,8 +44,6 @@ impl Location {
country_name: location.name,
two_letter_iso_country_code: location.iso_alpha2,
three_letter_iso_country_code: location.iso_alpha3,
latitude: location.latitude,
longitude: location.longitude,
}
}
}
-8
View File
@@ -1,8 +0,0 @@
## UNRELEASED
## [nym-explorer-v1.0.1](https://github.com/nymtech/nym/tree/nym-explorer-v1.0.1) (2023-01-10)
- Feat/2161 ne gate version by @gala1234 in https://github.com/nymtech/nym/pull/2743
- fix(explorer): set gateway bond 6 decimals by @doums in https://github.com/nymtech/nym/pull/2741
- Feat/2130 tables update rebase by @gala1234 in https://github.com/nymtech/nym/pull/2742
- fix(explorer,explorer-api): mixnode location by @doums in https://github.com/nymtech/nym-api
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@nym/network-explorer",
"version": "1.0.1",
"version": "1.0.0",
"private": true,
"license": "Apache-2.0",
"dependencies": {
+2 -2
View File
@@ -5,7 +5,7 @@ import { Tooltip } from '@nymproject/react/tooltip/Tooltip';
import { CopyToClipboard } from '@nymproject/react/clipboard/CopyToClipboard';
import { Box } from '@mui/system';
import { cellStyles } from './Universal-DataGrid';
import { unymToNym } from '../utils/currency';
import { currencyToString } from '../utils/currency';
import { GatewayEnrichedRowType } from './Gateways';
import { MixnodeRowType } from './MixNodes';
@@ -38,7 +38,7 @@ function formatCellValues(val: string | number, field: string) {
);
}
if (field === 'bond') {
return unymToNym(val, 6);
return currencyToString(val.toString());
}
return val;
}
-3
View File
@@ -7,7 +7,6 @@ export type GatewayRowType = {
bond: number;
host: string;
location: string;
version: string;
};
export type GatewayEnrichedRowType = GatewayRowType & {
@@ -27,7 +26,6 @@ export function gatewayToGridRow(arrayOfGateways: GatewayResponse): GatewayRowTy
location: gw?.gateway?.location || '',
bond: gw.pledge_amount.amount || 0,
host: gw.gateway.host || '',
version: gw.gateway.version || '',
}));
}
@@ -42,7 +40,6 @@ export function gatewayEnrichedToGridRow(
location: gateway?.gateway?.location || '',
bond: gateway.pledge_amount.amount || 0,
host: gateway.gateway.host || '',
version: gateway.gateway.version || '',
clientsPort: gateway.gateway.clients_port || 0,
mixPort: gateway.gateway.mix_port || 0,
routingScore: `${report.most_recent}%`,
@@ -58,12 +58,6 @@ const columns: ColumnsType[] = [
headerAlign: 'left',
flex: 1,
},
{
field: 'version',
title: 'Version',
headerAlign: 'left',
flex: 1,
},
];
/**
+3 -21
View File
@@ -10,7 +10,7 @@ import { TableToolbar } from '../../components/TableToolbar';
import { CustomColumnHeading } from '../../components/CustomColumnHeading';
import { Title } from '../../components/Title';
import { cellStyles, UniversalDataGrid } from '../../components/Universal-DataGrid';
import { unymToNym } from '../../utils/currency';
import { currencyToString } from '../../utils/currency';
import { Tooltip } from '../../components/Tooltip';
import { BIG_DIPPER } from '../../api/constants';
import { splice } from '../../utils';
@@ -77,7 +77,7 @@ export const PageGateways: React.FC = () => {
to={`/network-components/gateway/${params.row.identityKey}`}
data-testid="pledge-amount"
>
{unymToNym(params.value, 6)}
{currencyToString(params.value)}
</MuiLink>
),
},
@@ -128,7 +128,7 @@ export const PageGateways: React.FC = () => {
field: 'owner',
headerName: 'Owner',
renderHeader: () => <CustomColumnHeading headingTitle="Owner" />,
width: 180,
width: 380,
headerAlign: 'left',
headerClassName: 'MuiDataGrid-header-override',
renderCell: (params: GridRenderCellParams) => (
@@ -142,24 +142,6 @@ export const PageGateways: React.FC = () => {
</MuiLink>
),
},
{
field: 'version',
headerName: 'Version',
renderHeader: () => <CustomColumnHeading headingTitle="Version" />,
width: 150,
headerAlign: 'left',
headerClassName: 'MuiDataGrid-header-override',
renderCell: (params: GridRenderCellParams) => (
<MuiLink
sx={{ ...cellStyles }}
href={`${BIG_DIPPER}/account/${params.value}`}
target="_blank"
data-testid="owner"
>
{params.value}
</MuiLink>
),
},
];
const handlePageSize = (event: SelectChangeEvent<string>) => {
+2 -2
View File
@@ -164,10 +164,10 @@ const PageMixnodeDetailWithState: React.FC = () => {
{mixNode && (
<ContentCard title="Location">
{mixNode?.error && <ComponentError text="There was a problem retrieving this mixnode location" />}
{mixNode?.data?.location?.latitude && mixNode?.data?.location?.longitude && (
{mixNode.data && mixNode?.data?.location && (
<WorldMap
loading={mixNode.isLoading}
userLocation={[mixNode.data.location.longitude, mixNode.data.location.latitude]}
userLocation={[mixNode?.data?.location?.lng, mixNode?.data?.location?.lat]}
/>
)}
</ContentCard>
+2 -2
View File
@@ -77,8 +77,8 @@ export interface MixNodeResponseItem {
status: MixnodeStatus;
location: {
country_name: string;
latitude?: number;
longitude?: number;
lat: number;
lng: number;
three_letter_iso_country_code: string;
two_letter_iso_country_code: string;
};
+1 -1
View File
@@ -3,7 +3,7 @@
[package]
name = "nym-gateway"
version = "1.1.5"
version = "1.1.3"
authors = [
"Dave Hrycyszyn <futurechimp@users.noreply.github.com>",
"Jędrzej Stuczyński <andrew@nymtech.net>",
+1 -1
View File
@@ -3,7 +3,7 @@
[package]
name = "nym-mixnode"
version = "1.1.5"
version = "1.1.3"
authors = [
"Dave Hrycyszyn <futurechimp@users.noreply.github.com>",
"Jędrzej Stuczyński <andrew@nymtech.net>",
+1 -1
View File
@@ -3,7 +3,7 @@
[package]
name = "nym-validator-api"
version = "1.1.5"
version = "1.1.3"
authors = [
"Dave Hrycyszyn <futurechimp@users.noreply.github.com>",
"Jędrzej Stuczyński <andrew@nymtech.net>",
+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 -3
View File
@@ -4,7 +4,7 @@
use crate::coconut::error::Result;
use coconut_bandwidth_contract_common::spend_credential::SpendCredentialResponse;
use coconut_dkg_common::dealer::{ContractDealing, DealerDetails, DealerDetailsResponse};
use coconut_dkg_common::types::{EncodedBTEPublicKeyWithProof, Epoch};
use coconut_dkg_common::types::{EncodedBTEPublicKeyWithProof, EpochState};
use coconut_dkg_common::verification_key::{ContractVKShare, VerificationKeyShare};
use contracts_common::dealings::ContractSafeBytes;
use cw3::ProposalResponse;
@@ -22,7 +22,7 @@ pub trait Client {
&self,
blinded_serial_number: String,
) -> Result<SpendCredentialResponse>;
async fn get_current_epoch(&self) -> Result<Epoch>;
async fn get_current_epoch_state(&self) -> Result<EpochState>;
async fn get_current_epoch_threshold(&self) -> Result<Option<Threshold>>;
async fn get_self_registered_dealer_details(&self) -> Result<DealerDetailsResponse>;
async fn get_current_dealers(&self) -> Result<Vec<DealerDetails>>;
@@ -31,7 +31,6 @@ pub trait Client {
async fn vote_proposal(&self, proposal_id: u64, vote_yes: bool, fee: Option<Fee>)
-> Result<()>;
async fn execute_proposal(&self, proposal_id: u64) -> Result<()>;
async fn advance_epoch_state(&self) -> Result<()>;
async fn register_dealer(
&self,
bte_key: EncodedBTEPublicKeyWithProof,
+4 -8
View File
@@ -4,7 +4,7 @@
use crate::coconut::client::Client;
use crate::coconut::error::CoconutError;
use coconut_dkg_common::dealer::{ContractDealing, DealerDetails, DealerDetailsResponse};
use coconut_dkg_common::types::{EncodedBTEPublicKeyWithProof, Epoch, NodeIndex};
use coconut_dkg_common::types::{EncodedBTEPublicKeyWithProof, EpochState, NodeIndex};
use coconut_dkg_common::verification_key::{ContractVKShare, VerificationKeyShare};
use contracts_common::dealings::ContractSafeBytes;
use cw3::ProposalResponse;
@@ -35,13 +35,13 @@ impl DkgClient {
self.inner.address().await
}
pub(crate) async fn get_current_epoch(&self) -> Result<Epoch, CoconutError> {
let mut ret = self.inner.get_current_epoch().await;
pub(crate) async fn get_current_epoch_state(&self) -> Result<EpochState, CoconutError> {
let mut ret = self.inner.get_current_epoch_state().await;
for _ in 0..Self::RETRIES {
if ret.is_ok() {
return ret;
}
ret = self.inner.get_current_epoch().await;
ret = self.inner.get_current_epoch_state().await;
}
ret
}
@@ -86,10 +86,6 @@ impl DkgClient {
self.inner.list_proposals().await
}
pub(crate) async fn advance_epoch_state(&self) -> Result<(), CoconutError> {
self.inner.advance_epoch_state().await
}
pub(crate) async fn register_dealer(
&self,
bte_key: EncodedBTEPublicKeyWithProof,
+6 -15
View File
@@ -18,7 +18,7 @@ use dkg::bte::keys::KeyPair as DkgKeyPair;
use rand::rngs::OsRng;
use rand::RngCore;
use std::path::PathBuf;
use std::time::{Duration, SystemTime};
use std::time::Duration;
use task::TaskClient;
use tokio::time::interval;
use validator_client::nymd::SigningNymdClient;
@@ -83,16 +83,16 @@ impl<R: RngCore + Clone> DkgController<R> {
}
pub(crate) async fn handle_epoch_state(&mut self) {
match self.dkg_client.get_current_epoch().await {
match self.dkg_client.get_current_epoch_state().await {
Err(e) => warn!("Could not get current epoch state {}", e),
Ok(epoch) => {
if let Err(e) = self.state.is_consistent(epoch.state).await {
Ok(epoch_state) => {
if let Err(e) = self.state.is_consistent(epoch_state).await {
error!(
"Epoch state is corrupted - {}, the process should be terminated",
e
);
}
let ret = match epoch.state {
let ret = match epoch_state {
EpochState::PublicKeySubmission => {
public_key_submission(&self.dkg_client, &mut self.state).await
}
@@ -122,7 +122,7 @@ impl<R: RngCore + Clone> DkgController<R> {
};
if let Err(e) = ret {
warn!("Could not handle this iteration for the epoch state: {}", e);
} else if epoch.state != EpochState::InProgress {
} else if epoch_state != EpochState::InProgress {
let persistent_state = PersistentState::from(&self.state);
if let Err(e) =
persistent_state.save_to_file(self.state.persistent_state_path())
@@ -130,15 +130,6 @@ impl<R: RngCore + Clone> DkgController<R> {
warn!("Could not backup the state for this iteration: {}", e);
}
}
if let Ok(current_timestamp) =
SystemTime::now().duration_since(SystemTime::UNIX_EPOCH)
{
if current_timestamp.as_secs() >= epoch.finish_timestamp.seconds() {
// We try advancing the epoch state, on a best-effort basis
info!("Trying to advance the epoch");
self.dkg_client.advance_epoch_state().await.ok();
}
}
}
}
}
+8 -12
View File
@@ -40,7 +40,7 @@ use coconut_dkg_common::dealer::{
ContractDealing, DealerDetails, DealerDetailsResponse, DealerType,
};
use coconut_dkg_common::event_attributes::{DKG_PROPOSAL_ID, NODE_INDEX};
use coconut_dkg_common::types::{EncodedBTEPublicKeyWithProof, Epoch, TOTAL_DEALINGS};
use coconut_dkg_common::types::{EncodedBTEPublicKeyWithProof, EpochState, TOTAL_DEALINGS};
use coconut_dkg_common::verification_key::{ContractVKShare, VerificationKeyShare};
use contracts_common::dealings::ContractSafeBytes;
use crypto::asymmetric::{encryption, identity};
@@ -66,7 +66,7 @@ pub(crate) struct DummyClient {
proposal_db: Arc<RwLock<HashMap<u64, ProposalResponse>>>,
spent_credential_db: Arc<RwLock<HashMap<String, SpendCredentialResponse>>>,
epoch: Arc<RwLock<Epoch>>,
epoch_state: Arc<RwLock<EpochState>>,
dealer_details: Arc<RwLock<HashMap<String, DealerDetails>>>,
threshold: Arc<RwLock<Option<Threshold>>>,
dealings: Arc<RwLock<HashMap<String, Vec<ContractSafeBytes>>>>,
@@ -80,7 +80,7 @@ impl DummyClient {
tx_db: Arc::new(RwLock::new(HashMap::new())),
proposal_db: Arc::new(RwLock::new(HashMap::new())),
spent_credential_db: Arc::new(RwLock::new(HashMap::new())),
epoch: Arc::new(RwLock::new(Epoch::default())),
epoch_state: Arc::new(RwLock::new(EpochState::default())),
dealer_details: Arc::new(RwLock::new(HashMap::new())),
threshold: Arc::new(RwLock::new(None)),
dealings: Arc::new(RwLock::new(HashMap::new())),
@@ -109,8 +109,8 @@ impl DummyClient {
self
}
pub fn _with_epoch(mut self, epoch: &Arc<RwLock<Epoch>>) -> Self {
self.epoch = Arc::clone(epoch);
pub fn _with_epoch_state(mut self, epoch_state: &Arc<RwLock<EpochState>>) -> Self {
self.epoch_state = Arc::clone(epoch_state);
self
}
@@ -188,8 +188,8 @@ impl super::client::Client for DummyClient {
})
}
async fn get_current_epoch(&self) -> Result<Epoch> {
Ok(*self.epoch.read().unwrap())
async fn get_current_epoch_state(&self) -> Result<EpochState> {
Ok(*self.epoch_state.read().unwrap())
}
async fn get_current_epoch_threshold(&self) -> Result<Option<Threshold>> {
@@ -273,10 +273,6 @@ impl super::client::Client for DummyClient {
Ok(())
}
async fn advance_epoch_state(&self) -> Result<()> {
todo!()
}
async fn register_dealer(
&self,
bte_public_key_with_proof: EncodedBTEPublicKeyWithProof,
@@ -286,7 +282,7 @@ impl super::client::Client for DummyClient {
self.dealer_details.write().unwrap().insert(
self.validator_address.to_string(),
DealerDetails {
address: Addr::unchecked(self.validator_address.to_string()),
address: Addr::unchecked(&self.validator_address.to_string()),
bte_public_key_with_proof,
announce_address,
assigned_index,
+3 -13
View File
@@ -30,7 +30,7 @@ use coconut_bandwidth_contract_common::spend_credential::SpendCredentialResponse
#[cfg(feature = "coconut")]
use coconut_dkg_common::dealer::{ContractDealing, DealerDetails, DealerDetailsResponse};
#[cfg(feature = "coconut")]
use coconut_dkg_common::types::{EncodedBTEPublicKeyWithProof, Epoch};
use coconut_dkg_common::types::{EncodedBTEPublicKeyWithProof, EpochState};
#[cfg(feature = "coconut")]
use coconut_dkg_common::verification_key::{ContractVKShare, VerificationKeyShare};
#[cfg(feature = "coconut")]
@@ -329,8 +329,8 @@ where
.await?)
}
async fn get_current_epoch(&self) -> crate::coconut::error::Result<Epoch> {
Ok(self.0.read().await.nymd.get_current_epoch().await?)
async fn get_current_epoch_state(&self) -> crate::coconut::error::Result<EpochState> {
Ok(self.0.read().await.nymd.get_current_epoch_state().await?)
}
async fn get_current_epoch_threshold(
@@ -405,16 +405,6 @@ where
Ok(())
}
async fn advance_epoch_state(&self) -> crate::coconut::error::Result<()> {
self.0
.write()
.await
.nymd
.advance_dkg_epoch_state(None)
.await?;
Ok(())
}
async fn register_dealer(
&self,
bte_key: EncodedBTEPublicKeyWithProof,
-13
View File
@@ -30,19 +30,6 @@ module.exports = {
use: ['@svgr/webpack'],
});
config.module.rules.unshift({
test: /\.ya?ml$/,
type: 'json',
use: [
{
loader: 'yaml-loader',
options: {
asJSON: true,
},
},
],
});
config.resolve.extensions = ['.tsx', '.ts', '.js'];
config.resolve.plugins = [new TsconfigPathsPlugin()];
@@ -1,10 +0,0 @@
/**
* This is a mock for Tauri's API package (@tauri-apps/api/notification), to prevent stories from being excluded, because they either use
* or import dependencies that use Tauri.
*/
module.exports = {
isPermissionGranted: () => undefined,
requestPermission: () => undefined,
sendNotification: () => undefined,
};
+1 -16
View File
@@ -1,25 +1,10 @@
## UNRELEASED
## [nym-connect-v1.1.5](https://github.com/nymtech/nym/tree/nym-connect-v1.1.5) (2023-01-10)
- get version number from tauri and display by @fmtabbara in https://github.com/nymtech/nym/pull/2684
- Feature/nym connect experimental software text by @fmtabbara in https://github.com/nymtech/nym/pull/2692
- NymConnect - Display service info in tooltip **1.1.5 Release** by @fmtabbara in https://github.com/nymtech/nym/pull/2704
- Feat/2130 tables update rebase by @gala1234 in https://github.com/nymtech/nym/pull/2742
## [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.
+92 -230
View File
@@ -14,6 +14,12 @@ version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "adler32"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234"
[[package]]
name = "aes"
version = "0.7.5"
@@ -463,11 +469,12 @@ dependencies = [
[[package]]
name = "cargo_toml"
version = "0.13.0"
version = "0.11.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa0e3586af56b3bfa51fca452bd56e8dbbbd5d8d81cbf0b7e4e35b695b537eb8"
checksum = "a4419e9adae9fd7e231b60d50467481bf8181ddeef6ed54683b23ae925c74c9c"
dependencies = [
"serde",
"serde_derive",
"toml",
]
@@ -632,7 +639,7 @@ dependencies = [
[[package]]
name = "client-core"
version = "1.1.4"
version = "1.1.3"
dependencies = [
"async-trait",
"client-connections",
@@ -747,17 +754,6 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"
[[package]]
name = "colored"
version = "1.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f4ffc801dacf156c5854b9df4f425a626539c3a6ef7893cc0c5084a23f0b6c59"
dependencies = [
"atty",
"lazy_static",
"winapi",
]
[[package]]
name = "colored"
version = "2.0.0"
@@ -1320,14 +1316,13 @@ dependencies = [
]
[[package]]
name = "dbus"
version = "0.9.6"
name = "deflate"
version = "0.7.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f8bcdd56d2e5c4ed26a529c5a9029f5db8290d433497506f958eae3be148eb6"
checksum = "707b6a7b384888a70c8d2e8650b3e60170dfc6a67bb4aa67b6dfca57af4bedb4"
dependencies = [
"libc",
"libdbus-sys",
"winapi",
"adler32",
"byteorder",
]
[[package]]
@@ -1476,12 +1471,6 @@ dependencies = [
"dtoa",
]
[[package]]
name = "dunce"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0bd4b30a6560bbd9b4620f4de34c3f14f60848e58a9b7216801afcb4c7b31c3c"
[[package]]
name = "dyn-clone"
version = "1.0.9"
@@ -1643,16 +1632,6 @@ dependencies = [
"instant",
]
[[package]]
name = "fern"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3bdd7b0849075e79ee9a1836df22c717d1eba30451796fdc631b04565dd11e2a"
dependencies = [
"colored 1.9.3",
"log",
]
[[package]]
name = "ff"
version = "0.10.1"
@@ -2641,12 +2620,12 @@ dependencies = [
[[package]]
name = "ico"
version = "0.2.0"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "031530fe562d8c8d71c0635013d6d155bbfe8ba0aa4b4d2d24ce8af6b71047bd"
checksum = "6a4b3331534254a9b64095ae60d3dc2a8225a7a70229cd5888be127cdc1f6804"
dependencies = [
"byteorder",
"png",
"png 0.11.0",
]
[[package]]
@@ -2723,6 +2702,15 @@ dependencies = [
"cfb",
]
[[package]]
name = "inflate"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f5f9f47468e9a76a6452271efadc88fe865a82be91fe75e6c0c57b87ccea59d4"
dependencies = [
"adler32",
]
[[package]]
name = "inout"
version = "0.1.3"
@@ -2761,9 +2749,9 @@ checksum = "879d54834c8c76457ef4293a689b2a8c59b076067ad77b15efafbb05f92a592b"
[[package]]
name = "itertools"
version = "0.10.5"
version = "0.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
checksum = "d8bf247779e67a9082a4790b45e71ac7cfd1321331a5c856a74a9faebdab78d0"
dependencies = [
"either",
]
@@ -2805,9 +2793,9 @@ dependencies = [
[[package]]
name = "jni"
version = "0.20.0"
version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "039022cdf4d7b1cf548d31f60ae783138e5fd42013f6271049d7df7afadef96c"
checksum = "c6df18c2e3db7e453d3c6ac5b3e9d5182664d28788126d39b91f2d1e22b017ec"
dependencies = [
"cesu8",
"combine",
@@ -2926,15 +2914,6 @@ version = "0.2.132"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8371e4e5341c3a96db127eb2465ac681ced4c433e01dd0e938adbef26ba93ba5"
[[package]]
name = "libdbus-sys"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c185b5b7ad900923ef3a8ff594083d4d9b5aea80bb4f32b8342363138c0d456b"
dependencies = [
"pkg-config",
]
[[package]]
name = "libgit2-sys"
version = "0.14.0+1.5.0"
@@ -2995,12 +2974,6 @@ dependencies = [
"safemem",
]
[[package]]
name = "linked-hash-map"
version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
[[package]]
name = "lioness"
version = "0.1.2"
@@ -3030,7 +3003,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
dependencies = [
"cfg-if",
"serde",
]
[[package]]
@@ -3062,19 +3034,6 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4"
[[package]]
name = "mac-notification-sys"
version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e72d50edb17756489e79d52eb146927bec8eba9dd48faadf9ef08bca3791ad5"
dependencies = [
"cc",
"dirs-next",
"objc-foundation",
"objc_id",
"time 0.3.17",
]
[[package]]
name = "malloc_buf"
version = "0.0.6"
@@ -3296,17 +3255,6 @@ dependencies = [
"wasm-timer",
]
[[package]]
name = "notify-rust"
version = "4.5.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "368e89ea58df747ce88be669ae44e79783c1d30bfd540ad0fc520b3f41f0b3b0"
dependencies = [
"dbus",
"mac-notification-sys",
"tauri-winrt-notification",
]
[[package]]
name = "num-derive"
version = "0.3.3"
@@ -3328,6 +3276,17 @@ dependencies = [
"num-traits",
]
[[package]]
name = "num-iter"
version = "0.1.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252"
dependencies = [
"autocfg 1.1.0",
"num-integer",
"num-traits",
]
[[package]]
name = "num-rational"
version = "0.4.1"
@@ -3398,28 +3357,21 @@ dependencies = [
name = "nym-connect"
version = "1.1.4"
dependencies = [
"anyhow",
"bip39",
"chrono",
"client-core",
"config",
"crypto",
"dirs",
"eyre",
"fern",
"fix-path-env",
"futures",
"itertools",
"log",
"logging",
"nym-socks5-client",
"pretty_env_logger",
"rand 0.8.5",
"reqwest",
"rust-embed",
"serde",
"serde_json",
"serde_repr",
"tap",
"task",
"tauri",
@@ -3433,12 +3385,11 @@ dependencies = [
"topology",
"ts-rs",
"url",
"yaml-rust",
]
[[package]]
name = "nym-socks5-client"
version = "1.1.4"
version = "1.1.3"
dependencies = [
"clap",
"client-connections",
@@ -3661,9 +3612,9 @@ dependencies = [
[[package]]
name = "once_cell"
version = "1.16.0"
version = "1.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860"
checksum = "2f7254b99e31cad77da24b08ebf628882739a608578bb1bcdfc1f9c21260d7c0"
[[package]]
name = "opaque-debug"
@@ -4114,6 +4065,18 @@ dependencies = [
"xml-rs",
]
[[package]]
name = "png"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0b0cabbbd20c2d7f06dbf015e06aad59b6ca3d9ed14848783e98af9aaf19925"
dependencies = [
"bitflags",
"deflate",
"inflate",
"num-iter",
]
[[package]]
name = "png"
version = "0.17.6"
@@ -4258,15 +4221,6 @@ version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3"
[[package]]
name = "quick-xml"
version = "0.23.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "11bafc859c6815fbaffbbbf4229ecb767ac913fecb27f9ad4343662e9ef099ea"
dependencies = [
"memchr",
]
[[package]]
name = "quote"
version = "1.0.21"
@@ -4519,9 +4473,9 @@ dependencies = [
[[package]]
name = "regex"
version = "1.7.0"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a"
checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b"
dependencies = [
"aho-corasick",
"memchr",
@@ -4581,7 +4535,6 @@ dependencies = [
"serde_urlencoded",
"tokio",
"tokio-native-tls",
"tokio-socks",
"tower-service",
"url",
"wasm-bindgen",
@@ -4651,41 +4604,6 @@ dependencies = [
"opaque-debug 0.3.0",
]
[[package]]
name = "rust-embed"
version = "6.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "283ffe2f866869428c92e0d61c2f35dfb4355293cdfdc48f49e895c15f1333d1"
dependencies = [
"rust-embed-impl",
"rust-embed-utils",
"walkdir",
]
[[package]]
name = "rust-embed-impl"
version = "6.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "31ab23d42d71fb9be1b643fe6765d292c5e14d46912d13f3ae2815ca048ea04d"
dependencies = [
"proc-macro2",
"quote",
"rust-embed-utils",
"syn",
"walkdir",
]
[[package]]
name = "rust-embed-utils"
version = "7.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1669d81dfabd1b5f8e2856b8bbe146c6192b0ba22162edc738ac0a5de18f054"
dependencies = [
"globset",
"sha2 0.10.6",
"walkdir",
]
[[package]]
name = "rustc_version"
version = "0.3.3"
@@ -5541,27 +5459,6 @@ version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "strum"
version = "0.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7ac893c7d471c8a21f31cfe213ec4f6d9afeed25537c772e08ef3f005f8729e"
dependencies = [
"strum_macros",
]
[[package]]
name = "strum_macros"
version = "0.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "339f799d8b549e3744c7ac7feb216383e4005d94bdb22561b3ab8f3b808ae9fb"
dependencies = [
"heck 0.3.3",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "subtle"
version = "1.0.0"
@@ -5634,9 +5531,9 @@ dependencies = [
[[package]]
name = "tao"
version = "0.15.7"
version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1fa15735311b4816d030ff54da58560b047daca0970e1031aed5502e84231a8"
checksum = "43336f5d1793543ba96e2a1e75f3a5c7dcd592743be06a0ab3a190f4fcb4b934"
dependencies = [
"bitflags",
"cairo-rs",
@@ -5669,12 +5566,12 @@ dependencies = [
"once_cell",
"parking_lot 0.12.1",
"paste",
"png",
"png 0.17.6",
"raw-window-handle",
"scopeguard",
"serde",
"unicode-segmentation",
"uuid 1.2.2",
"uuid 1.1.2",
"windows 0.39.0",
"windows-implement",
"x11-dl",
@@ -5711,9 +5608,9 @@ dependencies = [
[[package]]
name = "tauri"
version = "1.2.2"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8ea1d785ab2164373703817bff144c4610a69ad3f659becaca0e1ea004b98d8"
checksum = "efbf22abd61d95ca9b2becd77f9db4c093892f73e8a07d21d8b0b2bf71a7bcea"
dependencies = [
"anyhow",
"attohttpc",
@@ -5731,7 +5628,6 @@ dependencies = [
"http",
"ignore",
"minisign-verify",
"notify-rust",
"objc",
"once_cell",
"open",
@@ -5756,7 +5652,7 @@ dependencies = [
"time 0.3.17",
"tokio",
"url",
"uuid 1.2.2",
"uuid 1.1.2",
"webkit2gtk",
"webview2-com",
"windows 0.39.0",
@@ -5765,9 +5661,9 @@ dependencies = [
[[package]]
name = "tauri-build"
version = "1.2.1"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8807c85d656b2b93927c19fe5a5f1f1f348f96c2de8b90763b3c2d561511f9b4"
checksum = "0991fb306849897439dbd4a72e4cbed2413e2eb26cb4b3ba220b94edba8b4b88"
dependencies = [
"anyhow",
"cargo_toml",
@@ -5781,16 +5677,16 @@ dependencies = [
[[package]]
name = "tauri-codegen"
version = "1.2.1"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14388d484b6b1b5dc0f6a7d6cc6433b3b230bec85eaa576adcdf3f9fafa49251"
checksum = "356fa253e40ae4d6ff02075011f2f2bb4066f5c9d8c1e16ca6912d7b75903ba6"
dependencies = [
"base64",
"brotli",
"ico",
"json-patch",
"plist",
"png",
"png 0.17.6",
"proc-macro2",
"quote",
"regex",
@@ -5801,15 +5697,15 @@ dependencies = [
"tauri-utils",
"thiserror",
"time 0.3.17",
"uuid 1.2.2",
"uuid 1.1.2",
"walkdir",
]
[[package]]
name = "tauri-macros"
version = "1.2.1"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "069319e5ecbe653a799b94b0690d9f9bf5d00f7b1d3989aa331c524d4e354075"
checksum = "d6051fd6940ddb22af452340d03c66a3e2f5d72e0788d4081d91e31528ccdc4d"
dependencies = [
"heck 0.4.0",
"proc-macro2",
@@ -5821,29 +5717,30 @@ dependencies = [
[[package]]
name = "tauri-runtime"
version = "0.12.1"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c507d954d08ac8705d235bc70ec6975b9054fb95ff7823af72dbb04186596f3b"
checksum = "d49439a5ea47f474572b854972f42eda2e02a470be5ca9609cc83bb66945abe2"
dependencies = [
"gtk",
"http",
"http-range",
"infer",
"rand 0.8.5",
"raw-window-handle",
"serde",
"serde_json",
"tauri-utils",
"thiserror",
"uuid 1.2.2",
"uuid 1.1.2",
"webview2-com",
"windows 0.39.0",
]
[[package]]
name = "tauri-runtime-wry"
version = "0.12.2"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "36b1c5764a41a13176a4599b5b7bd0881bea7d94dfe45e1e755f789b98317e30"
checksum = "28dce920995fd49907aa9bea7249ed1771454f11f7611924c920a1f75fb614d4"
dependencies = [
"cocoa",
"gtk",
@@ -5852,7 +5749,7 @@ dependencies = [
"raw-window-handle",
"tauri-runtime",
"tauri-utils",
"uuid 1.2.2",
"uuid 1.1.2",
"webkit2gtk",
"webview2-com",
"windows 0.39.0",
@@ -5861,16 +5758,15 @@ dependencies = [
[[package]]
name = "tauri-utils"
version = "1.2.1"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5abbc109a6eb45127956ffcc26ef0e875d160150ac16cfa45d26a6b2871686f1"
checksum = "1e8fdae6f29cef959809a3c3afef510c5b715a446a597ab8b791497585363f39"
dependencies = [
"brotli",
"ctor",
"glob",
"heck 0.4.0",
"html5ever",
"infer",
"json-patch",
"kuchiki",
"memchr",
@@ -5887,17 +5783,6 @@ dependencies = [
"windows 0.39.0",
]
[[package]]
name = "tauri-winrt-notification"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c58de036c4d2e20717024de2a3c4bf56c301f07b21bc8ef9b57189fce06f1f3b"
dependencies = [
"quick-xml",
"strum",
"windows 0.39.0",
]
[[package]]
name = "tempfile"
version = "3.3.0"
@@ -6170,18 +6055,6 @@ dependencies = [
"webpki 0.22.0",
]
[[package]]
name = "tokio-socks"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51165dfa029d2a65969413a6cc96f354b86b464498702f174a4efa13608fd8c0"
dependencies = [
"either",
"futures-util",
"thiserror",
"tokio",
]
[[package]]
name = "tokio-stream"
version = "0.1.10"
@@ -6473,9 +6346,9 @@ checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7"
[[package]]
name = "uuid"
version = "1.2.2"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "422ee0de9031b5b948b97a8fc04e3aa35230001a722ddd27943e0be31564ce4c"
checksum = "dd6469f4314d5f1ffec476e05f17cc9a78bc7a27a6a857842170bdf8d6f98d2f"
dependencies = [
"getrandom 0.2.7",
]
@@ -6490,7 +6363,7 @@ dependencies = [
"coconut-bandwidth-contract-common",
"coconut-dkg-common",
"coconut-interface",
"colored 2.0.0",
"colored",
"config",
"contracts-common",
"cosmrs",
@@ -6761,9 +6634,9 @@ dependencies = [
[[package]]
name = "webkit2gtk"
version = "0.18.2"
version = "0.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8f859735e4a452aeb28c6c56a852967a8a76c8eb1cc32dbf931ad28a13d6370"
checksum = "29952969fb5e10fe834a52eb29ad0814ccdfd8387159b0933edf1344a1c9cdcc"
dependencies = [
"bitflags",
"cairo-rs",
@@ -7138,16 +7011,15 @@ dependencies = [
[[package]]
name = "wry"
version = "0.23.4"
version = "0.21.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c1ad8e2424f554cc5bdebe8aa374ef5b433feff817aebabca0389961fc7ef98"
checksum = "ff5c1352b4266fdf92c63479d2f58ab4cd29dc4e78fbc1b62011ed1227926945"
dependencies = [
"base64",
"block",
"cocoa",
"core-graphics",
"crossbeam-channel",
"dunce",
"gdk",
"gio",
"glib",
@@ -7163,7 +7035,6 @@ dependencies = [
"serde",
"serde_json",
"sha2 0.10.6",
"soup2",
"tao",
"thiserror",
"url",
@@ -7230,15 +7101,6 @@ version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2d7d3948613f75c98fd9328cfdcc45acc4d360655289d0a7d4ec931392200a3"
[[package]]
name = "yaml-rust"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85"
dependencies = [
"linked-hash-map",
]
[[package]]
name = "zeroize"
version = "1.5.7"
@@ -7262,9 +7124,9 @@ dependencies = [
[[package]]
name = "zip"
version = "0.6.3"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "537ce7411d25e54e8ae21a7ce0b15840e7bfcff15b51d697ec3266cc76bdf080"
checksum = "bf225bcf73bb52cbb496e70475c7bd7a3f769df699c0020f6c7bd9a96dcf0b8d"
dependencies = [
"byteorder",
"crc32fast",
+4 -8
View File
@@ -1,12 +1,11 @@
{
"name": "@nym/nym-connect",
"version": "1.1.5",
"version": "1.1.3",
"main": "index.js",
"license": "MIT",
"scripts": {
"prewebpack:dev": "yarn --cwd .. build",
"webpack:dev": "yarn webpack serve --config webpack.dev.js",
"webpack:dev:onlyThis": "yarn webpack serve --config webpack.dev.js",
"webpack:prod": "yarn webpack --progress --config webpack.prod.js",
"tauri:dev": "RUST_DEBUG=1 yarn tauri dev",
"tauri:build": "yarn tauri build",
@@ -31,7 +30,7 @@
"@mui/material": "^5.2.2",
"@mui/styles": "^5.2.2",
"@nymproject/react": "^1.0.0",
"@tauri-apps/api": "^1.2.0",
"@tauri-apps/api": "^1.1.0",
"@tauri-apps/tauri-forage": "^1.0.0-beta.2",
"clsx": "^1.1.1",
"luxon": "^2.3.0",
@@ -40,7 +39,6 @@
"react-dom": "^17.0.2",
"react-error-boundary": "^3.1.3",
"react-hook-form": "^7.14.2",
"react-markdown": "^8.0.4",
"react-router-dom": "^5.2.0",
"semver": "^6.3.0",
"yup": "^0.32.9"
@@ -51,12 +49,11 @@
"@babel/preset-env": "^7.15.0",
"@babel/preset-react": "^7.14.5",
"@babel/preset-typescript": "^7.15.0",
"@mdx-js/loader": "^2.1.5",
"@nymproject/eslint-config-react-typescript": "^1.0.0",
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.4",
"@storybook/react": "^6.5.8",
"@svgr/webpack": "^6.1.1",
"@tauri-apps/cli": "^1.2.2",
"@tauri-apps/cli": "^1.1.0",
"@testing-library/jest-dom": "^5.14.1",
"@testing-library/react": "^12.0.0",
"@types/jest": "^27.0.1",
@@ -108,7 +105,6 @@
"webpack-cli": "^4.8.0",
"webpack-dev-server": "^4.5.0",
"webpack-favicons": "^1.3.8",
"webpack-merge": "^5.8.0",
"yaml-loader": "^0.8.0"
"webpack-merge": "^5.8.0"
}
}
-11
View File
@@ -1,11 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Nym Connect</title>
</head>
<body style="background: rgb(29, 33, 37);">
<div id="root-growth"></div>
</body>
</html>
+1 -1
View File
@@ -3,7 +3,7 @@
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Nym Connect</title>
<title>nym-connect</title>
</head>
<body>
<div id="root"></div>
-11
View File
@@ -1,11 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Nym Wallet Logs</title>
</head>
<body>
<div id="root-log"></div>
</body>
</html>
+8 -15
View File
@@ -1,6 +1,6 @@
[package]
name = "nym-connect"
version = "1.1.5"
version = "1.1.4"
description = "nym-connect"
authors = ["Nym Technologies SA"]
license = ""
@@ -13,40 +13,33 @@ rust-version = "1.58"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[build-dependencies]
tauri-build = { version = "^1.2.1", features = [] }
tauri-build = { version = "^1.1.1", features = [] }
tauri-codegen = "^1.2.1"
tauri-macros = "^1.2.1"
tauri-codegen = "^1.1.1"
tauri-macros = "^1.1.1"
[dependencies]
anyhow = "1.0"
bip39 = "1.0"
chrono = "0.4"
dirs = "4.0"
eyre = "0.6.5"
fix-path-env = { git = "https://github.com/tauri-apps/fix-path-env-rs", branch = "release"}
futures = "0.3"
fern = { version = "0.6.1", features = ["colored"] }
itertools = "0.10.5"
log = { version = "0.4", features = ["serde"] }
log = "0.4"
pretty_env_logger = "0.4.0"
rand = "0.8"
reqwest = { version = "0.11", features = ["json", "socks"] }
rust-embed = { version = "6.4.2", features = ["include-exclude"] }
reqwest = { version = "0.11", features = ["json"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
serde_repr = "0.1"
tap = "1.0.1"
tauri = { version = "^1.2.2", features = ["clipboard-write-text", "macos-private-api", "notification-all", "shell-open", "system-tray", "updater", "window-close", "window-minimize", "window-start-dragging"] }
tauri = { version = "^1.1.1", features = ["clipboard-write-text", "macos-private-api", "shell-open", "system-tray", "updater", "window-close", "window-minimize", "window-start-dragging"] }
tendermint-rpc = "0.23.0"
thiserror = "1.0"
tokio = { version = "1.21.2", features = ["sync", "time"] }
url = "2.2"
yaml-rust = "0.4"
client-core = { path = "../../clients/client-core" }
config-common = { path = "../../common/config", package = "config" }
crypto = { path = "../../common/crypto" }
logging = { path = "../../common/logging"}
nym-socks5-client = { path = "../../clients/socks5" }
task = { path = "../../common/task" }
-7
View File
@@ -44,13 +44,6 @@ impl Config {
}
}
#[allow(unused)]
pub fn new_with_port<S: Into<String>>(id: S, provider_mix_address: S, port: u16) -> Self {
Config {
socks5: Socks5Config::new(id, provider_mix_address).with_port(port),
}
}
pub fn get_socks5(&self) -> &Socks5Config {
&self.socks5
}
-12
View File
@@ -27,11 +27,6 @@ pub enum BackendError {
source: tauri::Error,
},
#[error("{source}")]
TauriApiError {
#[from]
source: tauri::api::Error,
},
#[error("{source}")]
SerdeJsonError {
#[from]
source: serde_json::Error,
@@ -41,11 +36,6 @@ pub enum BackendError {
#[from]
source: ClientCoreError<fs_backend::Backend>,
},
#[error("{source}")]
ApiClientError {
#[from]
source: crate::operations::growth::api_client::ApiClientError,
},
#[error("Could not send disconnect signal to the SOCKS5 client")]
CoundNotSendDisconnectSignal,
@@ -67,8 +57,6 @@ pub enum BackendError {
CouldNotGetConfigFilename,
#[error("Could not load existing gateway configuration")]
CouldNotLoadExistingGatewayConfiguration(std::io::Error),
#[error("Unable to open a new window")]
NewWindowError,
}
impl Serialize for BackendError {
-113
View File
@@ -1,113 +0,0 @@
use std::str::FromStr;
use fern::colors::ColoredLevelConfig;
use serde::Serialize;
use serde_repr::{Deserialize_repr, Serialize_repr};
use tauri::Manager;
pub fn setup_logging(app_handle: tauri::AppHandle) -> Result<(), log::SetLoggerError> {
let colors = ColoredLevelConfig::new();
let base_config = fern::Dispatch::new()
.level(global_level())
.filter_lowlevel_external_components()
.show_operations();
let stdout_config = fern::Dispatch::new()
.format(move |out, message, record| {
out.finish(format_args!(
"{}[{}][{}] {}",
chrono::Local::now().format("[%Y-%m-%d][%H:%M:%S]"),
record.target(),
colors.color(record.level()),
message,
))
})
.chain(std::io::stdout());
let tauri_event_config = fern::Dispatch::new()
.format(move |out, message, record| {
out.finish(format_args!(
"{}[{}] {}",
chrono::Local::now().format("[%Y-%m-%d][%H:%M:%S]"),
record.target(),
message,
))
})
.chain(fern::Output::call(move |record| {
let msg = LogMessage {
message: record.args().to_string(),
level: record.level().into(),
};
app_handle.emit_all("log://log", msg).unwrap();
}));
base_config
.chain(stdout_config)
.chain(tauri_event_config)
.apply()
}
trait FernExt {
fn show_operations(self) -> Self;
fn filter_lowlevel_external_components(self) -> Self;
}
impl FernExt for fern::Dispatch {
fn show_operations(self) -> Self {
if ::std::env::var("RUST_TRACE_OPERATIONS").is_ok() {
self.level_for("nym_connect::operations", log::LevelFilter::Trace)
} else {
self
}
}
fn filter_lowlevel_external_components(self) -> Self {
self.level_for("hyper", log::LevelFilter::Warn)
.level_for("tokio_reactor", log::LevelFilter::Warn)
.level_for("reqwest", log::LevelFilter::Warn)
.level_for("mio", log::LevelFilter::Warn)
.level_for("want", log::LevelFilter::Warn)
.level_for("sled", log::LevelFilter::Warn)
.level_for("tungstenite", log::LevelFilter::Warn)
.level_for("tokio_tungstenite", log::LevelFilter::Warn)
.level_for("rustls", log::LevelFilter::Warn)
.level_for("tokio_util", log::LevelFilter::Warn)
}
}
fn global_level() -> log::LevelFilter {
if let Ok(s) = ::std::env::var("RUST_LOG") {
log::LevelFilter::from_str(&s).unwrap_or(log::LevelFilter::Info)
} else {
log::LevelFilter::Info
}
}
#[derive(Debug, Serialize, Clone)]
struct LogMessage {
message: String,
level: LogLevel,
}
// Serialize to u16 instead of strings.
#[derive(Debug, Clone, Deserialize_repr, Serialize_repr)]
#[repr(u16)]
enum LogLevel {
Trace = 1,
Debug,
Info,
Warn,
Error,
}
impl From<log::Level> for LogLevel {
fn from(level: log::Level) -> Self {
match level {
log::Level::Trace => LogLevel::Trace,
log::Level::Debug => LogLevel::Debug,
log::Level::Info => LogLevel::Info,
log::Level::Warn => LogLevel::Warn,
log::Level::Error => LogLevel::Error,
}
}
}
+5 -27
View File
@@ -6,7 +6,8 @@
use std::sync::Arc;
use config_common::defaults::setup_env;
use tauri::{Manager, Menu};
use logging::setup_logging;
use tauri::Menu;
use tokio::sync::RwLock;
use crate::menu::AddDefaultSubmenus;
@@ -16,7 +17,6 @@ use crate::window::window_toggle;
mod config;
mod error;
mod logging;
mod menu;
mod models;
mod operations;
@@ -25,6 +25,7 @@ mod tasks;
mod window;
fn main() {
setup_logging();
setup_env(None);
println!("Starting up...");
@@ -34,13 +35,11 @@ fn main() {
log::warn!("Failed to fix PATH: {error}");
}
let context = tauri::generate_context!();
tauri::Builder::default()
.manage(Arc::new(RwLock::new(State::new())))
.invoke_handler(tauri::generate_handler![
crate::config::get_config_file_location,
crate::config::get_config_id,
crate::operations::connection::status::get_connection_status,
crate::operations::connection::connect::get_gateway,
crate::operations::connection::connect::get_service_provider,
crate::operations::connection::connect::set_gateway,
@@ -50,31 +49,10 @@ fn main() {
crate::operations::directory::get_services,
crate::operations::export::export_keys,
crate::operations::window::hide_window,
crate::operations::growth::test_and_earn::growth_tne_get_client_id,
crate::operations::growth::test_and_earn::growth_tne_take_part,
crate::operations::growth::test_and_earn::growth_tne_get_draws,
crate::operations::growth::test_and_earn::growth_tne_ping,
crate::operations::growth::test_and_earn::growth_tne_submit_wallet_address,
crate::operations::growth::test_and_earn::growth_tne_enter_draw,
crate::operations::growth::test_and_earn::growth_tne_toggle_window,
crate::operations::help::log::help_log_toggle_window,
])
.menu(Menu::os_default(&context.package_info().name).add_default_app_submenus())
.on_menu_event(|event| {
if event.menu_item_id() == menu::SHOW_LOG_WINDOW {
let _r = crate::operations::help::log::help_log_toggle_window(
event.window().app_handle(),
);
}
if event.menu_item_id() == menu::CLEAR_STORAGE {
let _r = crate::operations::help::storage::help_clear_storage(
event.window().app_handle(),
);
}
})
.setup(|app| Ok(crate::logging::setup_logging(app.app_handle())?))
.menu(Menu::new().add_default_app_submenu_if_macos())
.system_tray(create_tray_menu())
.on_system_tray_event(tray_menu_event_handler)
.run(context)
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
+29 -13
View File
@@ -1,24 +1,40 @@
use crate::window_toggle;
use tauri::{
AppHandle, CustomMenuItem, Menu, Submenu, SystemTray, SystemTrayEvent, SystemTrayMenu,
AppHandle, CustomMenuItem, Menu, SystemTray, SystemTrayEvent, SystemTrayMenu,
SystemTrayMenuItem, Wry,
};
use crate::window_toggle;
pub const SHOW_LOG_WINDOW: &str = "show_log_window";
pub const CLEAR_STORAGE: &str = "clear_storage";
#[cfg(target_os = "macos")]
use tauri::{MenuItem, Submenu};
pub trait AddDefaultSubmenus {
fn add_default_app_submenus(self) -> Self;
fn add_default_app_submenu_if_macos(self) -> Self;
}
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")),
);
self.add_submenu(submenu)
fn add_default_app_submenu_if_macos(self) -> Menu {
#[cfg(target_os = "macos")]
return self
.add_submenu(Submenu::new(
"File",
Menu::new().add_native_item(MenuItem::Quit),
))
.add_submenu(Submenu::new(
"Edit",
Menu::new()
.add_native_item(MenuItem::Copy)
.add_native_item(MenuItem::Cut)
.add_native_item(MenuItem::Paste)
.add_native_item(MenuItem::SelectAll),
))
.add_submenu(Submenu::new(
"Window",
Menu::new()
.add_native_item(MenuItem::Hide)
.add_native_item(MenuItem::HideOthers)
.add_native_item(MenuItem::ShowAll),
));
#[cfg(not(target_os = "macos"))]
return self;
}
}
+3 -21
View File
@@ -39,31 +39,21 @@ impl fmt::Display for ConnectionStatusKind {
pub const APP_EVENT_CONNECTION_STATUS_CHANGED: &str = "app:connection-status-changed";
#[cfg_attr(test, derive(ts_rs::TS))]
#[derive(Clone, Serialize)]
#[derive(Clone, serde::Serialize)]
pub struct AppEventConnectionStatusChangedPayload {
pub status: ConnectionStatusKind,
}
#[cfg_attr(test, derive(ts_rs::TS))]
#[derive(Clone, Debug, Serialize, Deserialize)]
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
pub struct DirectoryService {
pub id: String,
pub description: String,
pub items: Vec<DirectoryServiceProvider>,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct HarbourMasterService {
pub service_provider_client_id: String,
pub gateway_identity_key: String,
pub ip_address: String,
pub last_successful_ping_utc: String,
pub last_updated_utc: String,
pub routing_score: f32,
}
#[cfg_attr(test, derive(ts_rs::TS))]
#[derive(Clone, Debug, Serialize, Deserialize)]
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
pub struct DirectoryServiceProvider {
pub id: String,
pub description: String,
@@ -73,11 +63,3 @@ pub struct DirectoryServiceProvider {
/// Address of the gateway, e.g. 2BuMSfMW3zpeAjKXyKLhmY4QW1DXurrtSPEJ6CjX3SEh
pub gateway: String,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct PagedResult<T> {
pub page: u32,
pub size: u32,
pub total: i32,
pub items: Vec<T>,
}
@@ -37,10 +37,10 @@ pub async fn get_service_provider(state: tauri::State<'_, Arc<RwLock<State>>>) -
#[tauri::command]
pub async fn set_service_provider(
service_provider: Option<String>,
service_provider: String,
state: tauri::State<'_, Arc<RwLock<State>>>,
) -> Result<()> {
log::trace!("Setting service_provider: {:?}", &service_provider);
log::trace!("Setting service_provider: {service_provider}");
let mut guard = state.write().await;
guard.set_service_provider(service_provider);
Ok(())
@@ -57,10 +57,10 @@ pub async fn get_gateway(state: tauri::State<'_, Arc<RwLock<State>>>) -> Result<
#[tauri::command]
pub async fn set_gateway(
gateway: Option<String>,
gateway: String,
state: tauri::State<'_, Arc<RwLock<State>>>,
) -> Result<()> {
log::trace!("Setting gateway: {:?}", &gateway);
log::trace!("Setting gateway: {gateway}");
let mut guard = state.write().await;
guard.set_gateway(gateway);
Ok(())

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