Compare commits

..

158 Commits

Author SHA1 Message Date
dainius-nym 7528109693 fix: update fx average rate calcs to ignore 0 values (#5454)
* fix: update fx average rate calcs to ignore 0 values

* chore: bump version and format the code
2025-02-13 09:50:32 +00:00
Jon Häggblad 203d682f2c Upgrade tower to 0.5.2 (#5446) 2025-02-13 10:43:39 +01:00
dependabot[bot] 589575eed8 build(deps): bump publicsuffix from 2.2.3 to 2.3.0 (#5367)
Bumps [publicsuffix](https://github.com/rushmorem/publicsuffix) from 2.2.3 to 2.3.0.
- [Release notes](https://github.com/rushmorem/publicsuffix/releases)
- [Commits](https://github.com/rushmorem/publicsuffix/compare/v2.2.3...v2.3.0)

---
updated-dependencies:
- dependency-name: publicsuffix
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-13 00:50:34 +01:00
Jon Häggblad 35bf1cc717 Disable debug in wasm and wallet workflows too (#5459) 2025-02-13 00:16:32 +01:00
dependabot[bot] f5e02d5652 build(deps): bump hickory-proto from 0.24.2 to 0.24.3 (#5444)
* build(deps): bump hickory-proto from 0.24.2 to 0.24.3

Bumps [hickory-proto](https://github.com/hickory-dns/hickory-dns) from 0.24.2 to 0.24.3.
- [Release notes](https://github.com/hickory-dns/hickory-dns/releases)
- [Changelog](https://github.com/hickory-dns/hickory-dns/blob/v0.24.3/CHANGELOG.md)
- [Commits](https://github.com/hickory-dns/hickory-dns/compare/v0.24.2...v0.24.3)

---
updated-dependencies:
- dependency-name: hickory-proto
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

* Don't downgrade rand_core

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jon Häggblad <jon.haggblad@gmail.com>
2025-02-13 00:09:03 +01:00
dependabot[bot] 2fc641a7ff build(deps): bump hyper from 1.4.1 to 1.6.0 (#5416)
Bumps [hyper](https://github.com/hyperium/hyper) from 1.4.1 to 1.6.0.
- [Release notes](https://github.com/hyperium/hyper/releases)
- [Changelog](https://github.com/hyperium/hyper/blob/master/CHANGELOG.md)
- [Commits](https://github.com/hyperium/hyper/compare/v1.4.1...v1.6.0)

---
updated-dependencies:
- dependency-name: hyper
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-13 00:05:39 +01:00
dependabot[bot] 0ccca19cc2 build(deps): bump uniffi_build from 0.25.3 to 0.29.0 (#5448)
* build(deps): bump uniffi_build from 0.25.3 to 0.29.0

Bumps [uniffi_build](https://github.com/mozilla/uniffi-rs) from 0.25.3 to 0.29.0.
- [Changelog](https://github.com/mozilla/uniffi-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/mozilla/uniffi-rs/compare/v0.25.3...v0.29.0)

---
updated-dependencies:
- dependency-name: uniffi_build
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* Also update uniffi to match uniffi_build

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jon Häggblad <jon.haggblad@gmail.com>
2025-02-12 23:56:02 +01:00
Jon Häggblad a07e567eb2 Set debug to false in ci-build.yml (#5458) 2025-02-12 23:08:44 +01:00
Jon Häggblad f3400a0aa5 Add helper to extract a list of sqlite files with journal files wal/shm (#5452)
Co-authored-by: Andrej Mihajlov <andrej@nymtech.net>
2025-02-12 17:29:06 +01:00
dainius-nym bf8614a545 Feature/add gbp currency (#5453)
* features: add gbp currency to the fx price scrapper

* regenerated sqlx queries

* nump cargo version

---------

Co-authored-by: Jędrzej Stuczyński <jedrzej.stuczynski@gmail.com>
2025-02-12 13:16:34 +00:00
dynco-nym b7e3687757 Dz nym node stats (#5418)
* Remove blacklisted, inactive, reserve fields

* Remove gw.blacklisted

* Remove blacklisted and bonded count

* DB operations

* Improve logging

* Remove unused functions

* get_nym_nodes for scraping WIP

* Separate nym_nodes from mixnode stats
- fixes FOREIGN_KEY_CONSTRAINT error when storing
  stats for nym_nodes which aren't in mixnodes table

* Daily aggregation works

* mixnodes/stats exposes correct info

* Undo unnecessary tidbits

* Replace obsolete stats

* Add total_stake

* Bump cargo.toml version

* Rename MixingNodeKind for better clarity
2025-02-11 12:07:15 +01:00
windy-ux b9b969b7d3 + specify worker-src (#5443)
+ CSP from main website

Co-authored-by: benedetta davico <46782255+benedettadavico@users.noreply.github.com>
2025-02-11 10:19:12 +00:00
dependabot[bot] 47303e5b3b build(deps): bump openssl from 0.10.56 to 0.10.70 in /nym-wallet (#5422)
Bumps [openssl](https://github.com/sfackler/rust-openssl) from 0.10.56 to 0.10.70.
- [Release notes](https://github.com/sfackler/rust-openssl/releases)
- [Commits](https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.56...openssl-v0.10.70)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-10 22:27:42 +01:00
dependabot[bot] 6b38ffd4f3 build(deps): bump hickory-proto from 0.24.2 to 0.24.3 in /nym-wallet (#5445)
Bumps [hickory-proto](https://github.com/hickory-dns/hickory-dns) from 0.24.2 to 0.24.3.
- [Release notes](https://github.com/hickory-dns/hickory-dns/releases)
- [Changelog](https://github.com/hickory-dns/hickory-dns/blob/v0.24.3/CHANGELOG.md)
- [Commits](https://github.com/hickory-dns/hickory-dns/compare/v0.24.2...v0.24.3)

---
updated-dependencies:
- dependency-name: hickory-proto
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-10 22:19:43 +01:00
import this 169c313404 [DOCs/operators]: Email templates update (#5441)
* new intro template

* Update dmca_response.md
2025-02-10 19:11:03 +00:00
dependabot[bot] ccf430ea62 build(deps): bump the patch-updates group across 1 directory with 10 updates (#5439)
Bumps the patch-updates group with 10 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [async-trait](https://github.com/dtolnay/async-trait) | `0.1.85` | `0.1.86` |
| [clap](https://github.com/clap-rs/clap) | `4.5.27` | `4.5.28` |
| [comfy-table](https://github.com/nukesor/comfy-table) | `7.1.3` | `7.1.4` |
| [hickory-resolver](https://github.com/hickory-dns/hickory-dns) | `0.24.2` | `0.24.3` |
| [once_cell](https://github.com/matklad/once_cell) | `1.20.2` | `1.20.3` |
| [pin-project](https://github.com/taiki-e/pin-project) | `1.1.8` | `1.1.9` |
| [serde_json_path](https://github.com/hiltontj/serde_json_path) | `0.7.1` | `0.7.2` |
| [toml](https://github.com/toml-rs/toml) | `0.8.19` | `0.8.20` |
| [cosmrs](https://github.com/cosmos/cosmos-rust) | `0.21.0` | `0.21.1` |
| [tokio-postgres](https://github.com/sfackler/rust-postgres) | `0.7.12` | `0.7.13` |



Updates `async-trait` from 0.1.85 to 0.1.86
- [Release notes](https://github.com/dtolnay/async-trait/releases)
- [Commits](https://github.com/dtolnay/async-trait/compare/0.1.85...0.1.86)

Updates `clap` from 4.5.27 to 4.5.28
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.27...clap_complete-v4.5.28)

Updates `comfy-table` from 7.1.3 to 7.1.4
- [Release notes](https://github.com/nukesor/comfy-table/releases)
- [Changelog](https://github.com/Nukesor/comfy-table/blob/main/CHANGELOG.md)
- [Commits](https://github.com/nukesor/comfy-table/compare/v7.1.3...v7.1.4)

Updates `hickory-resolver` from 0.24.2 to 0.24.3
- [Release notes](https://github.com/hickory-dns/hickory-dns/releases)
- [Changelog](https://github.com/hickory-dns/hickory-dns/blob/v0.24.3/CHANGELOG.md)
- [Commits](https://github.com/hickory-dns/hickory-dns/compare/v0.24.2...v0.24.3)

Updates `once_cell` from 1.20.2 to 1.20.3
- [Changelog](https://github.com/matklad/once_cell/blob/master/CHANGELOG.md)
- [Commits](https://github.com/matklad/once_cell/compare/v1.20.2...v1.20.3)

Updates `pin-project` from 1.1.8 to 1.1.9
- [Release notes](https://github.com/taiki-e/pin-project/releases)
- [Changelog](https://github.com/taiki-e/pin-project/blob/main/CHANGELOG.md)
- [Commits](https://github.com/taiki-e/pin-project/compare/v1.1.8...v1.1.9)

Updates `serde_json_path` from 0.7.1 to 0.7.2
- [Release notes](https://github.com/hiltontj/serde_json_path/releases)
- [Changelog](https://github.com/hiltontj/serde_json_path/blob/main/CHANGELOG.md)
- [Commits](https://github.com/hiltontj/serde_json_path/compare/v0.7.1...v0.7.2)

Updates `toml` from 0.8.19 to 0.8.20
- [Commits](https://github.com/toml-rs/toml/compare/toml-v0.8.19...toml-v0.8.20)

Updates `cosmrs` from 0.21.0 to 0.21.1
- [Commits](https://github.com/cosmos/cosmos-rust/compare/cosmrs/v0.21.0...cosmrs/v0.21.1)

Updates `tokio-postgres` from 0.7.12 to 0.7.13
- [Release notes](https://github.com/sfackler/rust-postgres/releases)
- [Commits](https://github.com/sfackler/rust-postgres/compare/tokio-postgres-v0.7.12...tokio-postgres-v0.7.13)

---
updated-dependencies:
- dependency-name: async-trait
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch-updates
- dependency-name: clap
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch-updates
- dependency-name: comfy-table
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch-updates
- dependency-name: hickory-resolver
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch-updates
- dependency-name: once_cell
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch-updates
- dependency-name: pin-project
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch-updates
- dependency-name: serde_json_path
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch-updates
- dependency-name: toml
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch-updates
- dependency-name: cosmrs
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch-updates
- dependency-name: tokio-postgres
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch-updates
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-10 14:59:07 +01:00
import this cf13b79e93 [DOCs/operators]: Clarify SGPv2 program rules (#5434) 2025-02-07 11:31:34 +00:00
Jon Häggblad 134a0196f8 Disable the test for checking the remaining bandwidth in nym-node-status-api (#5425)
* Disable the test for checking the remaining bandwidth in nym-node-status-api

This check fails almost every time on CI, possibly due to rate limiting?
It's not good to disable the check, but it's blocking CI as it stands
now. Given that we have the check above for locating the ip, we at least
have a little coverage.

* Remove unused
2025-02-07 11:39:37 +01:00
benedetta davico 6c45c9f0b0 Merge pull request #5396 from nymtech/fix/wallet-explorer-url
Change Explorer URL to new smooshed nodes
2025-02-06 16:47:26 +01:00
import this b5afae0916 [DOCs:operators]: Update nym-node specs (#5433)
* Update nym-node-specs.mdx

* update specs - PR finished
2025-02-06 15:43:33 +00:00
benedetta davico 988eca857f Merge pull request #5431 from nymtech/drazen/forget-cli-client
Push down forget me to client configs
2025-02-06 15:25:04 +01:00
benedetta davico 3c05db2874 Merge pull request #5428 from nymtech/release/2025.2-hu
Merge release/2025.2-hu to develop
2025-02-06 13:58:47 +01:00
durch a8e268f84a Push down forget me to client configs 2025-02-06 13:15:58 +01:00
benedetta davico ac22533ecd Merge pull request #5429 from nymtech/feature/fix_develop_merge
Feature/fix develop merge
2025-02-06 13:12:31 +01:00
Bogdan-Ștefan Neacşu bdc0b875a4 Merge remote-tracking branch 'origin/develop' into release/2025.2-hu 2025-02-06 13:16:51 +02:00
import this d7b67c1408 [DOCs]: hotfix relative path url (#5427) 2025-02-06 10:15:45 +00:00
import this 606e29ebb0 [DOCs/operators]: Release notes, new specs, legal pages (#5419)
* add legal support notes

* write dev release notes

* create new legal page and add templates

* remove node_api_check to backup

* templates page

* update specs

* update backup and restore node

* PR ready for review

* address review comment

* last tweaks - PR finished

* last tweaks - PR finished
2025-02-05 15:19:56 +00:00
Bogdan-Ștefan Neacşu 21e3c1538d Fix statistics shutdown (#5426) 2025-02-05 16:06:46 +02:00
mfahampshire 0fc7cc657d Max/openapi docs update (#5292)
* spacing + working openapi local for nymapi

* sandbox nyx rest api

* add now working nym-api openapi json url to component
2025-02-05 14:05:44 +00:00
dependabot[bot] 23a7f01c05 build(deps): bump tokio from 1.40.0 to 1.43.0 (#5370)
* build(deps): bump tokio from 1.40.0 to 1.43.0

Bumps [tokio](https://github.com/tokio-rs/tokio) from 1.40.0 to 1.43.0.
- [Release notes](https://github.com/tokio-rs/tokio/releases)
- [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.40.0...tokio-1.43.0)

---
updated-dependencies:
- dependency-name: tokio
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* wip: test if token is set

* Try with an artifical delay between calls

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jon Häggblad <jon.haggblad@gmail.com>
2025-02-05 10:38:28 +01:00
Jon Häggblad 3a21cfa1ab Make wait_for_graceful_shutdown to be pub (#5424) 2025-02-05 08:58:25 +01:00
Jack Wampler 1d2e6d916c Use secure DNS for websocket connection establishment (#5386)
implementation of secure dns for websocket connection establishment. depends on #5355
2025-02-04 11:20:39 -07:00
benedettadavico 4c2bf3642e update changelong 2025-02-04 10:29:48 +01:00
Jędrzej Stuczyński 70e2e32385 Feature/remove double spending bloomfilter (#5417)
* removed all uses of the bloomfilter inside nym-api

* changed http status code on bf queries
2025-02-03 16:11:13 +00:00
Jon Häggblad 68a192daa3 Upgrade to thiserror 2.0 (#5414)
* Upgrade to thiserror 2.0

* Remove line macros in vesting contract error type

* Name positional arguments in GatewayRequestsError

* Named positional argument

* Revert "Remove line macros in vesting contract error type"

This reverts commit 49f937da3f.

* Use positional arguments for line
2025-02-03 10:50:11 +01:00
dependabot[bot] d6aacae14e build(deps): bump the patch-updates group across 1 directory with 9 updates (#5406)
Bumps the patch-updates group with 9 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [clap](https://github.com/clap-rs/clap) | `4.5.26` | `4.5.27` |
| [clap_complete](https://github.com/clap-rs/clap) | `4.5.40` | `4.5.44` |
| [getset](https://github.com/jbaublitz/getset) | `0.1.3` | `0.1.4` |
| [indicatif](https://github.com/console-rs/indicatif) | `0.17.9` | `0.17.11` |
| [log](https://github.com/rust-lang/log) | `0.4.22` | `0.4.25` |
| [pin-project](https://github.com/taiki-e/pin-project) | `1.1.7` | `1.1.8` |
| [semver](https://github.com/dtolnay/semver) | `1.0.24` | `1.0.25` |
| [serde_json](https://github.com/serde-rs/json) | `1.0.135` | `1.0.138` |
| [bip32](https://github.com/iqlusioninc/crates) | `0.5.2` | `0.5.3` |



Updates `clap` from 4.5.26 to 4.5.27
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.26...clap_complete-v4.5.27)

Updates `clap_complete` from 4.5.40 to 4.5.44
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.40...clap_complete-v4.5.44)

Updates `getset` from 0.1.3 to 0.1.4
- [Release notes](https://github.com/jbaublitz/getset/releases)
- [Commits](https://github.com/jbaublitz/getset/compare/0.1.3...0.1.4)

Updates `indicatif` from 0.17.9 to 0.17.11
- [Release notes](https://github.com/console-rs/indicatif/releases)
- [Commits](https://github.com/console-rs/indicatif/compare/0.17.9...0.17.11)

Updates `log` from 0.4.22 to 0.4.25
- [Release notes](https://github.com/rust-lang/log/releases)
- [Changelog](https://github.com/rust-lang/log/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/log/compare/0.4.22...0.4.25)

Updates `pin-project` from 1.1.7 to 1.1.8
- [Release notes](https://github.com/taiki-e/pin-project/releases)
- [Changelog](https://github.com/taiki-e/pin-project/blob/main/CHANGELOG.md)
- [Commits](https://github.com/taiki-e/pin-project/compare/v1.1.7...v1.1.8)

Updates `semver` from 1.0.24 to 1.0.25
- [Release notes](https://github.com/dtolnay/semver/releases)
- [Commits](https://github.com/dtolnay/semver/compare/1.0.24...1.0.25)

Updates `serde_json` from 1.0.135 to 1.0.138
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.135...v1.0.138)

Updates `bip32` from 0.5.2 to 0.5.3
- [Commits](https://github.com/iqlusioninc/crates/compare/bip32/v0.5.2...bip32/v0.5.3)

---
updated-dependencies:
- dependency-name: clap
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch-updates
- dependency-name: clap_complete
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch-updates
- dependency-name: getset
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch-updates
- dependency-name: indicatif
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch-updates
- dependency-name: log
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch-updates
- dependency-name: pin-project
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch-updates
- dependency-name: semver
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch-updates
- dependency-name: serde_json
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch-updates
- dependency-name: bip32
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch-updates
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-31 11:27:52 +01:00
Jon Häggblad 6f00023d09 Send shutdown instead of panic when reaching max fail (#5398)
* Send shutdown instead of panic when reaching max fail

* Stop quicker on failure

* Update comment
2025-01-31 10:39:37 +01:00
Tommy Verrall 982ec56874 Merge pull request #5300 from nymtech/feat/nymnode-entrypoint-docker
Nymnode entrypoint docker
2025-01-31 09:08:50 +01:00
Jack Wampler 5dcc1ed6dc Merge pull request #5401 from nymtech/jmwample/nym-api-route
Relocate a validator api function
2025-01-30 09:50:58 -07:00
Jon Häggblad d62bc0a10b Downgrade harmless log message from info to debug (#5403) 2025-01-30 13:36:06 +01:00
benedetta davico d1fb926a2a Merge pull request #5405 from nymtech/downgrade-to-debug
HU - Downgrade harmless log message from info to debug
2025-01-30 11:34:14 +01:00
benedettadavico dea69acd49 Downgrade harmless log message from info to debug 2025-01-30 11:32:54 +01:00
Tommy Verrall ada2d2247a Merge pull request #5404 from nymtech/jstuczyn-patch-1
lower default ticket verification quorum to 0.7
2025-01-30 11:28:32 +01:00
Jędrzej Stuczyński 0159d7c27a lower default ticket verification quorum to 0.7 2025-01-30 10:16:41 +00:00
jmwample 882003c08c fmt 2025-01-29 14:58:04 -07:00
jmwample b71a491872 relocate a validator api function 2025-01-29 14:55:16 -07:00
Yana Matrosova 8f48ae08c4 Redirect from mixnode page to nodes page (#5397)
Co-authored-by: Yana <yanok87@users.noreply.github.com>
2025-01-28 17:30:45 +00:00
Yana 31b9623407 Change Explorer URL to new smooshed nodes 2025-01-28 13:00:01 +02:00
Jędrzej Stuczyński 6d90ffdd2c reduce log severity for checking topology validity (#5395) 2025-01-28 09:29:51 +00:00
benedettadavico 28997c7f97 adding changelog for hu 2025-01-28 09:02:54 +01:00
Drazen Urch 9550934d1f Pre shutdown hooks for GatewayClient (#5381) 2025-01-27 20:00:37 +01:00
Jędrzej Stuczyński a6c586a33b chore :update version of chain watcher and validator rewarder (#5394) 2025-01-27 15:47:37 +00:00
Jędrzej Stuczyński 7c85c1a271 bugfix: correctly handle ingore epoch roles flag (#5390) 2025-01-24 15:35:06 +00:00
Jędrzej Stuczyński 92c8d1b73f bugfix: terminate mixnet socket listener on shutdown (#5389) 2025-01-24 12:59:14 +00:00
Jędrzej Stuczyński 554e9ca490 feat: make client ignore dual mode nodes by default (#5388) 2025-01-24 12:07:25 +00:00
import this ff91d4619e [HOTFIX/DOCs]: Update pre-built-binaries.mdx (#5385) 2025-01-24 10:31:19 +00:00
Jack Wampler 9d01474277 Merge pull request #5355 from nymtech/jmwample/dot
DNS resolver configuration for internal HTTP client lookups
2025-01-23 10:41:39 -07:00
jmwample 8d10552d7c hickory dns error mgmt 2025-01-23 08:29:56 -07:00
import this 04fd197f5a [DOCs]: Add more backup guides, clean up deprecated, fix URLs, add sha verf (#5384)
* fix socks5 syntax

* reshape backup and restore and add proxy

* fix URLS

* remove deprecated node-api-check - archived for when there is time to maintain the tool

* add hash verification step
2025-01-23 15:14:31 +00:00
Jon Häggblad 4eadaf8292 Fix missing path triggers for CI (#5380)
* Fix missing path triggers for CI

* Sort alphabetically to make it easier to maintain
2025-01-22 23:46:07 +01:00
jmwample 32e39ebc6b square cargo.lock with upstream branch 2025-01-22 14:32:04 -07:00
jmwample 117eb83a0b managing returned iterators 2025-01-22 14:30:16 -07:00
jmwample c964c137f4 fmt 2025-01-22 14:30:16 -07:00
jmwample 35b43d5b20 missed Lookup strategy 2025-01-22 14:30:16 -07:00
jmwample bf88b34898 fix wasm compile (exclude wasm target from DoH / DoT) 2025-01-22 14:30:16 -07:00
jmwample 93140a1aa7 minor fixes for clarity, interface access, and wasm exclusion 2025-01-22 14:30:16 -07:00
jmwample f594bfc9ab remove h3 because it causes an error 2025-01-22 14:30:12 -07:00
jmwample 4327e2945a DNS-over-X for internal domain name (i.e. API client) lookups 2025-01-22 14:29:44 -07:00
Bogdan-Ștefan Neacşu 6e6675f7bf Handle ecash network errors differently (#5378) 2025-01-22 15:46:05 +01:00
Bogdan-Ștefan Neacşu 8670693952 Uncouple storage reference for bandwidth client (#5372) 2025-01-22 12:12:06 +01:00
Bogdan-Ștefan Neacşu a7f7ebfbae Remove empty ephemeral keys (#5376) 2025-01-22 12:11:01 +01:00
mfahampshire 57c38ef222 temp remove cargodoc command (#5375) 2025-01-22 10:09:47 +00:00
Jędrzej Stuczyński 1aec8be85e fixed sql migration for adding default message timestamp (#5374) 2025-01-21 10:00:11 +00:00
benedettadavico 4b474dd8ff bump versions for hu 2025-01-20 15:34:23 +01:00
mfahampshire 8e05386a0b Max/tssdk docs maintenance (#5364)
* add temp warning
2025-01-20 13:02:56 +00:00
Tommy Verrall 13cfa55e6c Merge pull request #5327 from nymtech/marcdbz-patch-1
Update README.md
2025-01-20 09:36:25 +01:00
Tommy Verrall 18e628acde Merge pull request #5328 from nymtech/marcdbz-patch-2
Update README.md
2025-01-20 09:35:58 +01:00
Tommy Verrall b163dba2d4 Merge pull request #5356 from nymtech/release/2025.1-reeses
2025.1-reeses to master
2025-01-20 09:35:09 +01:00
import this e67b2b020a [DOCs/operators]: Bump release version (#5362)
* bump release version

* bump version in setup guide

* PR finished
2025-01-17 18:12:12 +00:00
benedetta davico 9b627dd70f Merge pull request #5363 from nymtech/fix-ci 2025-01-17 11:35:04 +01:00
Bogdan-Ștefan Neacşu 9a0b769425 Bind to [::] on nym-node for both IP versions (#5361)
* Bind to [::] on nym-node for both IP versions

* Force update to be run

* Fix after merging develop
2025-01-17 11:32:33 +01:00
Sachin Kamath 8e14f5f884 Update ci-build-upload-binaries.yml
remove observatory
2025-01-17 15:11:53 +05:30
import this 1b64cb42b0 [DOCs/operators]: Guides, changes and release-notes for v2025.1-reeses (#5340)
* create ToC snippet

* fund node client account

* revamp node guide

* finish setup page revamp

* add new update to changelog

* fix wallet dowload uls

* fix operator steps urls

* fix operator steps urls

* fix operator steps urls

* finish release notes

* finish changelog

* debug build

* correct links syntax

* add remote mnemonic pull command
2025-01-16 15:23:58 +00:00
Jędrzej Stuczyński 03c4895f2b feature: introduce /load endpoint for self-reported quantised NymNode load (#5326)
* feature: introduce /load endpoint for self-reported quantised NymNode load

* return Load::Unknown for value of 0 because it means we misread some data

* add additional filtering on 'en...' endpoints
2025-01-16 15:13:08 +00:00
Jędrzej Stuczyński dcfb092758 updated cosmrs and tendermint-rpc to their most recent versions (#5339) 2025-01-16 14:52:36 +00:00
Jędrzej Stuczyński 9305ad5364 exposed NymApiClient method for obtaining node performance history (#5360)
* exposed NymApiClient method for obtaining node performance history

* using path constants for route definition
2025-01-16 14:50:09 +00:00
Jędrzej Stuczyński ea5aef6c2f Client gateway selection (#5358)
* filter out dual-role gateways during selection

* changed behaviour of egress node validitiy
2025-01-16 14:24:27 +00:00
Jędrzej Stuczyński 61a4433cd9 chore: update indexed_db_futures (#5347)
* chore: update indexed_db_futures

* clippy
2025-01-16 14:23:43 +00:00
benedetta davico 5c89d36140 Merge pull request #5359 from nymtech/release/2025.1-reeses
merge reeses patch to develop
2025-01-16 13:34:36 +01:00
benedetta davico 5ab164d229 Update Cargo.toml 2025-01-16 12:51:53 +01:00
Jędrzej Stuczyński 26538c5884 bugfix: only consider pre-existing peers for wg bytes metric (#5357) 2025-01-16 11:50:26 +00:00
Jędrzej Stuczyński adb248dbcc chore: refresh wasm sdk (#5353)
* make packet statistics wasm-compatible

* fixed possible overflow issue in delay controller

* updated wasm-client to be compatible with the current network

* applied same logic to mixfetch client

* removed dead imports

* updated versions
2025-01-15 17:11:17 +00:00
Sachin Kamath fffec65cab NS API: add mixnet scraper (#5200)
* ns-api: add mixnode scraper

* clippy

* rebase
2025-01-15 13:12:11 +01:00
benedetta davico bb24004d46 Merge pull request #5352 from nymtech/merge/release/2025.1-reeses 2025-01-15 11:34:39 +01:00
Jędrzej Stuczyński c487eff7ca Merge branch 'release/2025.1-reeses' into develop 2025-01-15 10:18:45 +00:00
Jędrzej Stuczyński 5fa21c9aae chore: remove performed mixnet contract migration (#5350) 2025-01-15 10:06:04 +00:00
dependabot[bot] fd18aae0d6 build(deps): bump log in the patch-updates group across 1 directory (#5348)
Bumps the patch-updates group with 1 update in the / directory: [log](https://github.com/rust-lang/log).


Updates `log` from 0.4.22 to 0.4.25
- [Release notes](https://github.com/rust-lang/log/releases)
- [Changelog](https://github.com/rust-lang/log/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/log/compare/0.4.22...0.4.25)

---
updated-dependencies:
- dependency-name: log
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch-updates
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-15 10:01:25 +00:00
benedettadavico c202e2d598 adding changelog for reeses 2025-01-15 10:27:39 +01:00
mfahampshire 62d23cff9f removed old todos (#5349) 2025-01-14 16:37:30 +00:00
mfahampshire e454d71b78 Max/client pool (#5188)
* tcp conn tracker

* make default decay const

* first pass connpool

* err handling conpool start

* added notes for next features

* first version working

* first pass spin out client_pool

* cancel token

* logging change

* bump default decay time

* bugfix: make sure to apply gateway score filtering when choosing initial node

* add duplicate packets received to troubleshooting

* client_pool.rs mod

* client pool example

* clippy

* client pool example done

* added disconnect to client pool

* update mod file

* add cancel token disconnect fn

* comments

* comments

* add clone

* added disconnect thread

* update example files tcpproxy

* client pool docs

* remove comments for future ffi push + lower default pool size from 4 to 2

* comment on ffi

* update command help

* clone impl

* remove clone

* fix clippy

* fix clippy again

* fix test

* tweaked text grammar

* updated comment in example

* future is now

* cherry

* cherry

* fix borked rebase

* fix fmt

* wasm fix

---------

Co-authored-by: Jędrzej Stuczyński <jedrzej.stuczynski@gmail.com>
2025-01-14 16:11:47 +00:00
huximaxi a7874add88 Merge pull request #5346 from nymtech/feture/legacy_alert
Feture/legacy alert
2025-01-14 15:00:49 +01:00
dependabot[bot] 0a47d5dcf8 build(deps): bump criterion from 0.4.0 to 0.5.1 (#4911)
Bumps [criterion](https://github.com/bheisler/criterion.rs) from 0.4.0 to 0.5.1.
- [Changelog](https://github.com/bheisler/criterion.rs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/bheisler/criterion.rs/compare/0.4.0...0.5.1)

---
updated-dependencies:
- dependency-name: criterion
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-14 13:47:58 +00:00
RadekSabacky 3d84be22e2 + add releaseAlert component 2025-01-14 13:41:30 +01:00
dependabot[bot] 6ccbb30491 build(deps): bump http from 1.1.0 to 1.2.0 (#5228)
Bumps [http](https://github.com/hyperium/http) from 1.1.0 to 1.2.0.
- [Release notes](https://github.com/hyperium/http/releases)
- [Changelog](https://github.com/hyperium/http/blob/master/CHANGELOG.md)
- [Commits](https://github.com/hyperium/http/compare/v1.1.0...v1.2.0)

---
updated-dependencies:
- dependency-name: http
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-14 12:33:17 +00:00
dependabot[bot] 91c205f83a build(deps): bump the patch-updates group with 8 updates (#5336)
Bumps the patch-updates group with 8 updates:

| Package | From | To |
| --- | --- | --- |
| [async-trait](https://github.com/dtolnay/async-trait) | `0.1.84` | `0.1.85` |
| [clap](https://github.com/clap-rs/clap) | `4.5.23` | `4.5.26` |
| [clap_complete](https://github.com/clap-rs/clap) | `4.5.40` | `4.5.42` |
| [futures](https://github.com/rust-lang/futures-rs) | `0.3.30` | `0.3.31` |
| [pin-project](https://github.com/taiki-e/pin-project) | `1.1.7` | `1.1.8` |
| [pin-project-lite](https://github.com/taiki-e/pin-project-lite) | `0.2.15` | `0.2.16` |
| [serde_json](https://github.com/serde-rs/json) | `1.0.134` | `1.0.135` |
| [wasm-bindgen-test](https://github.com/rustwasm/wasm-bindgen) | `0.3.45` | `0.3.49` |


Updates `async-trait` from 0.1.84 to 0.1.85
- [Release notes](https://github.com/dtolnay/async-trait/releases)
- [Commits](https://github.com/dtolnay/async-trait/compare/0.1.84...0.1.85)

Updates `clap` from 4.5.23 to 4.5.26
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.23...clap_complete-v4.5.26)

Updates `clap_complete` from 4.5.40 to 4.5.42
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.40...clap_complete-v4.5.42)

Updates `futures` from 0.3.30 to 0.3.31
- [Release notes](https://github.com/rust-lang/futures-rs/releases)
- [Changelog](https://github.com/rust-lang/futures-rs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/futures-rs/compare/0.3.30...0.3.31)

Updates `pin-project` from 1.1.7 to 1.1.8
- [Release notes](https://github.com/taiki-e/pin-project/releases)
- [Changelog](https://github.com/taiki-e/pin-project/blob/main/CHANGELOG.md)
- [Commits](https://github.com/taiki-e/pin-project/compare/v1.1.7...v1.1.8)

Updates `pin-project-lite` from 0.2.15 to 0.2.16
- [Release notes](https://github.com/taiki-e/pin-project-lite/releases)
- [Changelog](https://github.com/taiki-e/pin-project-lite/blob/main/CHANGELOG.md)
- [Commits](https://github.com/taiki-e/pin-project-lite/compare/v0.2.15...v0.2.16)

Updates `serde_json` from 1.0.134 to 1.0.135
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.134...v1.0.135)

Updates `wasm-bindgen-test` from 0.3.45 to 0.3.49
- [Release notes](https://github.com/rustwasm/wasm-bindgen/releases)
- [Changelog](https://github.com/rustwasm/wasm-bindgen/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rustwasm/wasm-bindgen/commits)

---
updated-dependencies:
- dependency-name: async-trait
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch-updates
- dependency-name: clap
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch-updates
- dependency-name: clap_complete
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch-updates
- dependency-name: futures
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch-updates
- dependency-name: pin-project
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch-updates
- dependency-name: pin-project-lite
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch-updates
- dependency-name: serde_json
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch-updates
- dependency-name: wasm-bindgen-test
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch-updates
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-14 12:30:31 +00:00
dependabot[bot] 4a704e992a build(deps): bump tempfile from 3.14.0 to 3.15.0 (#5337)
Bumps [tempfile](https://github.com/Stebalien/tempfile) from 3.14.0 to 3.15.0.
- [Changelog](https://github.com/Stebalien/tempfile/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Stebalien/tempfile/compare/v3.14.0...v3.15.0)

---
updated-dependencies:
- dependency-name: tempfile
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-14 12:29:40 +00:00
dependabot[bot] 6c88c7df42 build(deps): bump ts-rs from 10.0.0 to 10.1.0 (#5338)
Bumps [ts-rs](https://github.com/Aleph-Alpha/ts-rs) from 10.0.0 to 10.1.0.
- [Release notes](https://github.com/Aleph-Alpha/ts-rs/releases)
- [Changelog](https://github.com/Aleph-Alpha/ts-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/Aleph-Alpha/ts-rs/compare/v10.0.0...v10.1.0)

---
updated-dependencies:
- dependency-name: ts-rs
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-14 12:29:13 +00:00
dependabot[bot] 2a748fc968 build(deps): bump mikefarah/yq from 4.44.6 to 4.45.1 (#5342)
Bumps [mikefarah/yq](https://github.com/mikefarah/yq) from 4.44.6 to 4.45.1.
- [Release notes](https://github.com/mikefarah/yq/releases)
- [Changelog](https://github.com/mikefarah/yq/blob/master/release_notes.txt)
- [Commits](https://github.com/mikefarah/yq/compare/v4.44.6...v4.45.1)

---
updated-dependencies:
- dependency-name: mikefarah/yq
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-14 12:28:43 +00:00
RadekSabacky 25766dc0ec + add alert message into nav components 2025-01-14 13:22:31 +01:00
mfahampshire 07544d939e Max/docs gen update (#5333)
* update landing page icons

* new architecture diagram

* force dark theme

* new nyx consolidated page

* epoch page

* overhaul traffic flow + add diagram

* note on dvpn mode

* fix formatting of lists

* remove old todo
2025-01-14 11:25:06 +00:00
Jędrzej Stuczyński 102cd1033c feature: CancellationToken-based shutdowns (#5325)
* initial stub for ShutdownToken

* attempting to start using new ShutdownManager in NymNode

* migrated verloc tasks

* added custom shutdown signal registration

* integrated legacy task support

* migrated additional tasks inside nym-node

* removed import thats unused in wasm

* apply review comments

* windows fixes
2025-01-13 09:13:13 +00:00
Jędrzej Stuczyński 676e93a372 bugfix: make sure refresh data key matches bond info (#5329) 2025-01-10 14:52:52 +00:00
Jędrzej Stuczyński 5a6770e5e2 chore: readjusted --mode behaviour to fix the regression (#5331) 2025-01-10 13:17:03 +00:00
Jędrzej Stuczyński 529e8d49ee chore: apply 1.84 linter suggestions (#5330)
* chore: apply 1.84 linter suggestions

* updated wasm dependencies to fix the macro issue

* second batch of clippy fixes
2025-01-10 13:00:18 +00:00
Marc 01c7ea72dd Update README.md
Fixed typo and updated operators link
2025-01-09 20:28:18 +01:00
Marc dfd1df5706 Update README.md
Updated the Tauri link
2025-01-09 20:26:04 +01:00
mfahampshire 11d6ee2fdb update links readme (#5323) 2025-01-09 14:44:45 +00:00
mfahampshire d704c428fc update landing page colour highlight (#5322) 2025-01-09 14:44:21 +00:00
import this bca070c1bd [DOCs]: Readiness for nym-dot-com (#5319)
* url rewrites and redirects

* url rewrites and redirects
2025-01-09 14:44:12 +00:00
benedettadavico a94c035c0a correct the nym-node bumped version 2025-01-09 12:36:05 +01:00
Jędrzej Stuczyński 24480418f0 Bugfix/contract version assignment (#5318)
* fixed contract version being overwritten

* introduced migration to fix existing [mainnet] state

* updated contract schema

* updated testnet manager migrate msg code
2025-01-09 10:00:37 +00:00
Jędrzej Stuczyński 226c040a13 feature: periodically remove stale gateway messages (#5312)
* add timestamp to stored client messages

* removed dead code

* starting node task to remove old messages

* added log for number of removed messages

* debug log on task finishing
2025-01-09 09:03:19 +00:00
Jędrzej Stuczyński a46245ffe3 feat: warn users if node is run in exit mode only (#5320)
* added 'full-gateway' nymnode mode to enable both entry and exit at the same time

* warning for running node in exit mode only
2025-01-09 09:02:52 +00:00
Jędrzej Stuczyński 7c1c13e139 reduce log severity for number of packets being delayed (#5321) 2025-01-09 09:02:37 +00:00
Jędrzej Stuczyński 836a93cd96 fixed client session histogram buckets (#5316) 2025-01-08 10:26:40 +00:00
dependabot[bot] 3d2914b3e5 build(deps): bump the patch-updates group across 1 directory with 35 updates (#5310)
* build(deps): bump the patch-updates group across 1 directory with 35 updates

Bumps the patch-updates group with 33 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [anyhow](https://github.com/dtolnay/anyhow) | `1.0.90` | `1.0.95` |
| [async-trait](https://github.com/dtolnay/async-trait) | `0.1.83` | `0.1.84` |
| [blake3](https://github.com/BLAKE3-team/BLAKE3) | `1.5.4` | `1.5.5` |
| [chrono](https://github.com/chronotope/chrono) | `0.4.38` | `0.4.39` |
| [clap](https://github.com/clap-rs/clap) | `4.5.20` | `4.5.23` |
| [clap_complete](https://github.com/clap-rs/clap) | `4.5.33` | `4.5.40` |
| [comfy-table](https://github.com/nukesor/comfy-table) | `7.1.1` | `7.1.3` |
| [console](https://github.com/console-rs/console) | `0.15.8` | `0.15.10` |
| [const_format](https://github.com/rodrimati1992/const_format_crates) | `0.2.33` | `0.2.34` |
| [csv](https://github.com/BurntSushi/rust-csv) | `1.3.0` | `1.3.1` |
| [flate2](https://github.com/rust-lang/flate2-rs) | `1.0.34` | `1.0.35` |
| [futures-util](https://github.com/rust-lang/futures-rs) | `0.3.30` | `0.3.31` |
| [hyper-util](https://github.com/hyperium/hyper-util) | `0.1.9` | `0.1.10` |
| [indicatif](https://github.com/console-rs/indicatif) | `0.17.8` | `0.17.9` |
| [moka](https://github.com/moka-rs/moka) | `0.12.8` | `0.12.10` |
| [pin-project](https://github.com/taiki-e/pin-project) | `1.1.6` | `1.1.7` |
| [pin-project-lite](https://github.com/taiki-e/pin-project-lite) | `0.2.14` | `0.2.15` |
| [quote](https://github.com/dtolnay/quote) | `1.0.37` | `1.0.38` |
| [semver](https://github.com/dtolnay/semver) | `1.0.23` | `1.0.24` |
| [serde](https://github.com/serde-rs/serde) | `1.0.215` | `1.0.217` |
| [serde_json](https://github.com/serde-rs/json) | `1.0.132` | `1.0.134` |
| [tar](https://github.com/alexcrichton/tar-rs) | `0.4.42` | `0.4.43` |
| [time](https://github.com/time-rs/time) | `0.3.36` | `0.3.37` |
| [tokio-stream](https://github.com/tokio-rs/tokio) | `0.1.16` | `0.1.17` |
| [tokio-util](https://github.com/tokio-rs/tokio) | `0.7.12` | `0.7.13` |
| [toml](https://github.com/toml-rs/toml) | `0.8.14` | `0.8.19` |
| [tracing](https://github.com/tokio-rs/tracing) | `0.1.40` | `0.1.41` |
| [tracing-subscriber](https://github.com/tokio-rs/tracing) | `0.3.18` | `0.3.19` |
| [url](https://github.com/servo/rust-url) | `2.5.2` | `2.5.4` |
| [wasm-bindgen-test](https://github.com/rustwasm/wasm-bindgen) | `0.3.43` | `0.3.45` |
| [js-sys](https://github.com/rustwasm/wasm-bindgen) | `0.3.72` | `0.3.76` |
| [wasm-bindgen-futures](https://github.com/rustwasm/wasm-bindgen) | `0.4.45` | `0.4.49` |
| [env_logger](https://github.com/rust-cli/env_logger) | `0.11.5` | `0.11.6` |



Updates `anyhow` from 1.0.90 to 1.0.95
- [Release notes](https://github.com/dtolnay/anyhow/releases)
- [Commits](https://github.com/dtolnay/anyhow/compare/1.0.90...1.0.95)

Updates `async-trait` from 0.1.83 to 0.1.84
- [Release notes](https://github.com/dtolnay/async-trait/releases)
- [Commits](https://github.com/dtolnay/async-trait/compare/0.1.83...0.1.84)

Updates `blake3` from 1.5.4 to 1.5.5
- [Release notes](https://github.com/BLAKE3-team/BLAKE3/releases)
- [Commits](https://github.com/BLAKE3-team/BLAKE3/compare/1.5.4...1.5.5)

Updates `chrono` from 0.4.38 to 0.4.39
- [Release notes](https://github.com/chronotope/chrono/releases)
- [Changelog](https://github.com/chronotope/chrono/blob/main/CHANGELOG.md)
- [Commits](https://github.com/chronotope/chrono/compare/v0.4.38...v0.4.39)

Updates `clap` from 4.5.20 to 4.5.23
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.20...clap_complete-v4.5.23)

Updates `clap_complete` from 4.5.33 to 4.5.40
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.33...clap_complete-v4.5.40)

Updates `comfy-table` from 7.1.1 to 7.1.3
- [Release notes](https://github.com/nukesor/comfy-table/releases)
- [Changelog](https://github.com/Nukesor/comfy-table/blob/main/CHANGELOG.md)
- [Commits](https://github.com/nukesor/comfy-table/compare/v7.1.1...v7.1.3)

Updates `console` from 0.15.8 to 0.15.10
- [Release notes](https://github.com/console-rs/console/releases)
- [Changelog](https://github.com/console-rs/console/blob/main/CHANGELOG.md)
- [Commits](https://github.com/console-rs/console/compare/0.15.8...0.15.10)

Updates `const_format` from 0.2.33 to 0.2.34
- [Release notes](https://github.com/rodrimati1992/const_format_crates/releases)
- [Changelog](https://github.com/rodrimati1992/const_format_crates/blob/master/Changelog.md)
- [Commits](https://github.com/rodrimati1992/const_format_crates/commits/0.2.34)

Updates `csv` from 1.3.0 to 1.3.1
- [Commits](https://github.com/BurntSushi/rust-csv/compare/1.3.0...1.3.1)

Updates `flate2` from 1.0.34 to 1.0.35
- [Release notes](https://github.com/rust-lang/flate2-rs/releases)
- [Changelog](https://github.com/rust-lang/flate2-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/flate2-rs/compare/1.0.34...1.0.35)

Updates `futures-util` from 0.3.30 to 0.3.31
- [Release notes](https://github.com/rust-lang/futures-rs/releases)
- [Changelog](https://github.com/rust-lang/futures-rs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/futures-rs/compare/0.3.30...0.3.31)

Updates `hyper-util` from 0.1.9 to 0.1.10
- [Release notes](https://github.com/hyperium/hyper-util/releases)
- [Changelog](https://github.com/hyperium/hyper-util/blob/master/CHANGELOG.md)
- [Commits](https://github.com/hyperium/hyper-util/compare/v0.1.9...v0.1.10)

Updates `indicatif` from 0.17.8 to 0.17.9
- [Release notes](https://github.com/console-rs/indicatif/releases)
- [Commits](https://github.com/console-rs/indicatif/compare/0.17.8...0.17.9)

Updates `moka` from 0.12.8 to 0.12.10
- [Changelog](https://github.com/moka-rs/moka/blob/main/CHANGELOG.md)
- [Commits](https://github.com/moka-rs/moka/compare/v0.12.8...v0.12.10)

Updates `pin-project` from 1.1.6 to 1.1.7
- [Release notes](https://github.com/taiki-e/pin-project/releases)
- [Changelog](https://github.com/taiki-e/pin-project/blob/main/CHANGELOG.md)
- [Commits](https://github.com/taiki-e/pin-project/compare/v1.1.6...v1.1.7)

Updates `pin-project-lite` from 0.2.14 to 0.2.15
- [Release notes](https://github.com/taiki-e/pin-project-lite/releases)
- [Changelog](https://github.com/taiki-e/pin-project-lite/blob/main/CHANGELOG.md)
- [Commits](https://github.com/taiki-e/pin-project-lite/compare/v0.2.14...v0.2.15)

Updates `quote` from 1.0.37 to 1.0.38
- [Release notes](https://github.com/dtolnay/quote/releases)
- [Commits](https://github.com/dtolnay/quote/compare/1.0.37...1.0.38)

Updates `semver` from 1.0.23 to 1.0.24
- [Release notes](https://github.com/dtolnay/semver/releases)
- [Commits](https://github.com/dtolnay/semver/compare/1.0.23...1.0.24)

Updates `serde` from 1.0.215 to 1.0.217
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.215...v1.0.217)

Updates `serde_derive` from 1.0.215 to 1.0.217
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.215...v1.0.217)

Updates `serde_json` from 1.0.132 to 1.0.134
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.132...v1.0.134)

Updates `tar` from 0.4.42 to 0.4.43
- [Commits](https://github.com/alexcrichton/tar-rs/compare/0.4.42...0.4.43)

Updates `time` from 0.3.36 to 0.3.37
- [Release notes](https://github.com/time-rs/time/releases)
- [Changelog](https://github.com/time-rs/time/blob/main/CHANGELOG.md)
- [Commits](https://github.com/time-rs/time/compare/v0.3.36...v0.3.37)

Updates `tokio-stream` from 0.1.16 to 0.1.17
- [Release notes](https://github.com/tokio-rs/tokio/releases)
- [Commits](https://github.com/tokio-rs/tokio/compare/tokio-stream-0.1.16...tokio-stream-0.1.17)

Updates `tokio-util` from 0.7.12 to 0.7.13
- [Release notes](https://github.com/tokio-rs/tokio/releases)
- [Commits](https://github.com/tokio-rs/tokio/compare/tokio-util-0.7.12...tokio-util-0.7.13)

Updates `toml` from 0.8.14 to 0.8.19
- [Commits](https://github.com/toml-rs/toml/compare/toml-v0.8.14...toml-v0.8.19)

Updates `tracing` from 0.1.40 to 0.1.41
- [Release notes](https://github.com/tokio-rs/tracing/releases)
- [Commits](https://github.com/tokio-rs/tracing/compare/tracing-0.1.40...tracing-0.1.41)

Updates `tracing-subscriber` from 0.3.18 to 0.3.19
- [Release notes](https://github.com/tokio-rs/tracing/releases)
- [Commits](https://github.com/tokio-rs/tracing/compare/tracing-subscriber-0.3.18...tracing-subscriber-0.3.19)

Updates `url` from 2.5.2 to 2.5.4
- [Release notes](https://github.com/servo/rust-url/releases)
- [Commits](https://github.com/servo/rust-url/compare/v2.5.2...v2.5.4)

Updates `wasm-bindgen-test` from 0.3.43 to 0.3.45
- [Release notes](https://github.com/rustwasm/wasm-bindgen/releases)
- [Changelog](https://github.com/rustwasm/wasm-bindgen/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rustwasm/wasm-bindgen/commits)

Updates `js-sys` from 0.3.72 to 0.3.76
- [Release notes](https://github.com/rustwasm/wasm-bindgen/releases)
- [Changelog](https://github.com/rustwasm/wasm-bindgen/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rustwasm/wasm-bindgen/commits)

Updates `wasm-bindgen-futures` from 0.4.45 to 0.4.49
- [Release notes](https://github.com/rustwasm/wasm-bindgen/releases)
- [Changelog](https://github.com/rustwasm/wasm-bindgen/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rustwasm/wasm-bindgen/commits)

Updates `web-sys` from 0.3.72 to 0.3.76
- [Release notes](https://github.com/rustwasm/wasm-bindgen/releases)
- [Changelog](https://github.com/rustwasm/wasm-bindgen/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rustwasm/wasm-bindgen/commits)

Updates `env_logger` from 0.11.5 to 0.11.6
- [Release notes](https://github.com/rust-cli/env_logger/releases)
- [Changelog](https://github.com/rust-cli/env_logger/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-cli/env_logger/compare/v0.11.5...v0.11.6)

---
updated-dependencies:
- dependency-name: anyhow
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch-updates
- dependency-name: async-trait
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch-updates
- dependency-name: blake3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch-updates
- dependency-name: chrono
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch-updates
- dependency-name: clap
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch-updates
- dependency-name: clap_complete
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch-updates
- dependency-name: comfy-table
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch-updates
- dependency-name: console
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch-updates
- dependency-name: const_format
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch-updates
- dependency-name: csv
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch-updates
- dependency-name: flate2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch-updates
- dependency-name: futures-util
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch-updates
- dependency-name: hyper-util
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch-updates
- dependency-name: indicatif
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch-updates
- dependency-name: moka
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch-updates
- dependency-name: pin-project
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch-updates
- dependency-name: pin-project-lite
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch-updates
- dependency-name: quote
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch-updates
- dependency-name: semver
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch-updates
- dependency-name: serde
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch-updates
- dependency-name: serde_derive
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch-updates
- dependency-name: serde_json
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch-updates
- dependency-name: tar
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch-updates
- dependency-name: time
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch-updates
- dependency-name: tokio-stream
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch-updates
- dependency-name: tokio-util
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch-updates
- dependency-name: toml
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch-updates
- dependency-name: tracing
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch-updates
- dependency-name: tracing-subscriber
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch-updates
- dependency-name: url
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch-updates
- dependency-name: wasm-bindgen-test
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch-updates
- dependency-name: js-sys
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch-updates
- dependency-name: wasm-bindgen-futures
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch-updates
- dependency-name: web-sys
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch-updates
- dependency-name: env_logger
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch-updates
...

Signed-off-by: dependabot[bot] <support@github.com>

* Use expect in geodata test to give error message on failure

I keep hitting this error on CI, from what I think is network hickup.
But it's hard to tell form the log since the error is swallowed.

Explicitly unwrap the result so we get a more detailed error output

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jon Häggblad <jon.haggblad@gmail.com>
2025-01-08 10:56:39 +01:00
Jon Häggblad 9b02de3e75 Use expect in geodata test to give error message on failure (#5314)
* Use expect in geodata test to give error message on failure

I keep hitting this error on CI, from what I think is network hickup.
But it's hard to tell form the log since the error is swallowed.

Explicitly unwrap the result so we get a more detailed error output

* Add nym-node-status-api to ci-build
2025-01-08 10:56:26 +01:00
benedettadavico b47a742dd0 update nym-node binary version 2025-01-08 10:37:48 +01:00
benedetta davico 6e14882246 Merge pull request #5315 from nymtech/release/2024.14-crunch-patched
Merge crunch patched to reeses
2025-01-08 10:35:54 +01:00
benedetta davico f3d8aba82c Merge pull request #5288 from nymtech/release/2024.14-crunch-patched
Merge patched crunch to develop
2025-01-08 10:34:12 +01:00
benedetta davico aa83501ed0 Merge pull request #5289 from nymtech/release/2024.14-crunch-patched
Merging patched crunch to master
2025-01-08 10:33:03 +01:00
Tommy Verrall a7466a0e02 Merge pull request #5313 from nymtech/bugfix/append-gb-cap
amend 250gb limit
2025-01-08 09:50:04 +01:00
Tommy Verrall 78f45012db amend 250gb limit 2025-01-08 09:44:14 +01:00
benedettadavico f6a2f62ea9 bump versions of binaries 2025-01-08 09:28:48 +01:00
Jędrzej Stuczyński 3efeededc5 feature: expand nym-node prometheus metrics (#5298)
* fixed bearer auth for prometheus route

* basic prometheus metrics

* added rates on global values

* improved structure on the prometheus metrics

* added additional metrics for ingress websockets and egress mixnet connections

* some channel business metrics

* fixed metrics registration and added additional variants

* added counter for number of disk persisted packets

* counter for pending egress packets

* counter for pending egress forward packets

* clippy
2025-01-07 13:34:18 +00:00
Jędrzej Stuczyński c482350ec6 feature: wireguard metrics (#5278)
* experimental log

* introduce wireguard metrics updates

* add wireguard traffic rates to console logger

* missing import

* changed order of displayed values

* expose bytes information via rest endpoint

* clippy
2025-01-07 13:32:07 +00:00
import this 72a4a26c40 [DOCs/operators]: smooth operators (#5311)
* smooth minimum expectation

* simplify simplify

* quick fix

* feedback edits

* feedback edits

* feedback edits
2025-01-06 12:46:16 +00:00
import this 5d9b5a0d70 initialise minimum requirements page (#5304) 2025-01-06 10:50:43 +00:00
import this c070e4bfee [DOCs]: Fixes (#5299)
* correct url

* version fix
2025-01-06 10:50:31 +00:00
mfahampshire 4d3d60b78e tweak format (#5295)
* tweak format

* auto commit generated command files

* auto commit generated command files

* push components

* edit migration page (#5303)

---------

Co-authored-by: import this <97586125+serinko@users.noreply.github.com>
2024-12-23 11:51:24 +00:00
dynco-nym 41fb17a31b Extend swagger docs (#5235)
* WIP adding derive(ToSchema)

* Derive ToSchema for more types

* ContractBuildInformation on /nym_contracts_detailed

* rustfmt

* Add cfg_attr

* A bunch of annotations

* Compiles with utoipa 5.2

* WIP

* Post rebase fixes

* Gitattributes to ignore .sqlx diffs

* generate Sqlx schema files

* Improvements

* Move ecash schema out of ecash crate

* Move redocly config to nym-api/

* Move redocly config to nym-api/

* Remove ErrorResponse

* Move generated openapi spec to .gitignore

* Include BSL licence

* Remove utoipa from ecash toml file

* Remove placeholder annotations

* Chain-watcher rebase changes

* Update licence info

* Treat Scalar as String in OpenAPI
2024-12-20 12:18:45 +01:00
Jędrzej Stuczyński 7d5e3ef7d3 feature: expand nym-node prometheus metrics (#5298)
* fixed bearer auth for prometheus route

* basic prometheus metrics

* added rates on global values

* improved structure on the prometheus metrics

* added additional metrics for ingress websockets and egress mixnet connections

* some channel business metrics

* fixed metrics registration and added additional variants

* added counter for number of disk persisted packets

* counter for pending egress packets

* counter for pending egress forward packets

* clippy
2024-12-20 10:32:56 +00:00
Jon Häggblad 4f283f565c Add assignes for the root cargo ecosystem (#5297) 2024-12-20 01:16:39 +01:00
Bogdan-Ștefan Neacşu f7a7a8072f Move tun constants to network defaults (#5286) (#5287) 2024-12-18 16:23:18 +02:00
Jon Häggblad acd068e5ab Add close to credential storage (#5283)
* Add close method to credential storage

* wip
2024-12-18 12:37:16 +01:00
benedetta davico 8d5a41a790 Merge pull request #5277 from nymtech/feature/modify_changelog
Modify CHANGELOG
2024-12-18 11:07:49 +01:00
Bogdan-Ștefan Neacşu caa17d933c Add windows to CI builds (#5269)
* Add windows to CI builds

* Fix win build for node status api

* Fix win build for sdk

* Fix win build for cred proxy
2024-12-17 22:26:38 +01:00
Bogdan-Ștefan Neacşu 039b05cf7e Modify CHANGELOG 2024-12-17 18:59:49 +02:00
benedetta davico 37b10b59aa update changelog for nym-node v1.2.1 2024-12-17 17:54:18 +01:00
benedetta davico a9ede22bbd update nym-node version 2024-12-17 17:41:12 +01:00
Bogdan-Ștefan Neacşu b656003306 Expect that previously regitrated clients don't have v6 addr 2024-12-17 16:59:01 +02:00
benedetta davico b628a5f814 Merge pull request #5263 from nymtech/release/2024.14-crunch
Merge release/2024.14-crunch to master
2024-12-13 11:49:27 +01:00
benedetta davico 62045d76b3 Merge pull request #5172 from nymtech/release/2024.13-magura-patched
Update master with latest releases
2024-11-26 11:53:05 +01:00
benedetta davico f8317f5a03 Merge pull request #5025 from nymtech/release/2024.12-aero
Aero to master
2024-10-24 10:54:37 +02:00
benedetta davico c3ec970a37 Merge pull request #4928 from nymtech/release/2024.11-wedel
Release/2024.11-wedel to master
2024-09-26 08:24:53 +02:00
Jędrzej Stuczyński 5a573bc278 Merge pull request #4866 from nymtech/release/2024.10-caramello
Release/2024.10 caramello
2024-09-11 15:09:50 +01:00
benedetta davico 3d200db722 Merge pull request #4749 from nymtech/release/2024.9-topdeck-pre-develop-merge
release/2024.9 topdeck pre develop merge
2024-08-06 17:14:17 +02:00
Tommy Verrall e4139713cb Merge pull request #4724 from nymtech/release/2024.8-wispa
Merge release/2024.8-wispa into master
2024-07-24 08:25:52 +01:00
596 changed files with 26382 additions and 7800 deletions
+1
View File
@@ -0,0 +1 @@
nym-validator-rewarder/.sqlx/** diff=nodiff
+2
View File
@@ -31,3 +31,5 @@ updates:
update-types:
- "patch"
open-pull-requests-limit: 10
assignees:
- "octol"
@@ -79,7 +79,6 @@ jobs:
target/release/nym-socks5-client
target/release/nym-api
target/release/nym-network-requester
target/release/nym-data-observatory
target/release/nym-cli
target/release/nymvisor
target/release/nym-node
@@ -97,7 +96,6 @@ jobs:
cp target/release/nym-socks5-client $OUTPUT_DIR
cp target/release/nym-api $OUTPUT_DIR
cp target/release/nym-network-requester $OUTPUT_DIR
cp target/release/nym-data-observatory $OUTPUT_DIR
cp target/release/nymvisor $OUTPUT_DIR
cp target/release/nym-node $OUTPUT_DIR
cp target/release/nym-cli $OUTPUT_DIR
+22 -6
View File
@@ -8,16 +8,18 @@ on:
- 'explorer-api/**'
- 'gateway/**'
- 'integrations/**'
- 'mixnode/**'
- 'sdk/rust/**'
- 'sdk/lib/**'
- 'service-providers/**'
- 'nym-network-monitor/**'
- 'nym-api/**'
- 'nym-credential-proxy/**'
- 'nym-network-monitor/**'
- 'nym-node/**'
- 'nym-node-status-api/**'
- 'nym-outfox/**'
- 'nym-data-observatory/**'
- 'nym-validator-rewarder/**'
- 'nyx-chain-watcher/**'
- 'sdk/ffi/**'
- 'sdk/rust/**'
- 'service-providers/**'
- 'nym-browser-extension/storage/**'
- 'tools/**'
- 'wasm/**'
- 'Cargo.toml'
@@ -52,6 +54,20 @@ jobs:
override: true
components: rustfmt, clippy
# To avoid running out of disk space, skip generating debug symbols
- name: Set debug to false (unix)
if: contains(matrix.os, 'ubuntu') || contains(matrix.os, 'mac')
run: |
sed -i.bak 's/\[profile.dev\]/\[profile.dev\]\ndebug = false/' Cargo.toml
git diff
- name: Set debug to false (win)
if: contains(matrix.os, 'windows')
shell: pwsh
run: |
(Get-Content Cargo.toml) -replace '\[profile.dev\]', "`$&`ndebug = false" | Set-Content Cargo.toml
git diff
- name: Check formatting
uses: actions-rs/cargo@v1
with:
+6
View File
@@ -30,6 +30,12 @@ jobs:
override: true
components: rustfmt, clippy
- name: Set debug to false
working-directory: nym-wallet
run: |
sed -i.bak '1s/^/\[profile.dev\]\ndebug = false\n\n/' Cargo.toml
git diff
- name: Build all binaries
uses: actions-rs/cargo@v1
with:
+6
View File
@@ -1,6 +1,7 @@
name: ci-sdk-wasm
on:
workflow_dispatch:
pull_request:
paths:
- 'wasm/**'
@@ -44,6 +45,11 @@ jobs:
- name: Install wasm-bindgen-cli
run: cargo install wasm-bindgen-cli
- name: Set debug to false
run: |
sed -i.bak 's/\[profile.dev\]/\[profile.dev\]\ndebug = false/' Cargo.toml
git diff
- name: "Build"
run: make sdk-wasm-build
+1 -1
View File
@@ -26,7 +26,7 @@ jobs:
git config --global user.name "Lawrence Stalder"
- name: Get version from cargo.toml
uses: mikefarah/yq@v4.44.6
uses: mikefarah/yq@v4.45.1
id: get_version
with:
cmd: yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/nym-credential-proxy/Cargo.toml
+1 -1
View File
@@ -26,7 +26,7 @@ jobs:
git config --global user.name "Lawrence Stalder"
- name: Get version from cargo.toml
uses: mikefarah/yq@v4.44.6
uses: mikefarah/yq@v4.45.1
id: get_version
with:
cmd: yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/Cargo.toml
+1 -1
View File
@@ -26,7 +26,7 @@ jobs:
git config --global user.name "Lawrence Stalder"
- name: Get version from cargo.toml
uses: mikefarah/yq@v4.44.6
uses: mikefarah/yq@v4.45.1
id: get_version
with:
cmd: yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/nym-network-monitor/Cargo.toml
@@ -31,7 +31,7 @@ jobs:
git config --global user.name "Lawrence Stalder"
- name: Get version from cargo.toml
uses: mikefarah/yq@v4.44.6
uses: mikefarah/yq@v4.45.1
id: get_version
with:
cmd: yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/Cargo.toml
+1 -1
View File
@@ -26,7 +26,7 @@ jobs:
git config --global user.name "Lawrence Stalder"
- name: Get version from cargo.toml
uses: mikefarah/yq@v4.44.6
uses: mikefarah/yq@v4.45.1
id: get_version
with:
cmd: yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/Cargo.toml
+1 -1
View File
@@ -26,7 +26,7 @@ jobs:
git config --global user.name "Lawrence Stalder"
- name: Get version from cargo.toml
uses: mikefarah/yq@v4.44.6
uses: mikefarah/yq@v4.45.1
id: get_version
with:
cmd: yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/Cargo.toml
@@ -26,7 +26,7 @@ jobs:
git config --global user.name "Lawrence Stalder"
- name: Get version from cargo.toml
uses: mikefarah/yq@v4.44.6
uses: mikefarah/yq@v4.45.1
id: get_version
with:
cmd: yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/Cargo.toml
@@ -26,7 +26,7 @@ jobs:
git config --global user.name "Lawrence Stalder"
- name: Get version from cargo.toml
uses: mikefarah/yq@v4.44.6
uses: mikefarah/yq@v4.45.1
id: get_version
with:
cmd: yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/Cargo.toml
+2 -1
View File
@@ -54,7 +54,8 @@ nym-network-monitor/__pycache__
nym-network-monitor/*.key
nym-network-monitor/.envrc
nym-network-monitor/.envrc
nym-api/redocly/formatted-openapi.json
*.sqlite
.build
.build
+165
View File
@@ -4,6 +4,171 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
## [Unreleased]
## [2025.2-hu] (2025-02-04)
- Feature/remove double spending bloomfilter ([#5417])
- HU - Downgrade harmless log message from info to debug ([#5405])
- lower default ticket verification quorum to 0.7 ([#5404])
- Downgrade harmless log message from info to debug ([#5403])
- Redirect from mixnode page to nodes page ([#5397])
- chore :update version of chain watcher and validator rewarder ([#5394])
- bugfix: correctly handle ingore epoch roles flag ([#5390])
- bugfix: terminate mixnet socket listener on shutdown ([#5389])
- feat: make client ignore dual mode nodes by default ([#5388])
- Handle ecash network errors differently ([#5378])
- Remove empty ephemeral keys ([#5376])
- fixed sql migration for adding default message timestamp ([#5374])
- Bind to [::] on nym-node for both IP versions ([#5361])
- exposed NymApiClient method for obtaining node performance history ([#5360])
- Client gateway selection ([#5358])
- chore: refresh wasm sdk ([#5353])
- chore: update indexed_db_futures ([#5347])
- build(deps): bump mikefarah/yq from 4.44.6 to 4.45.1 ([#5342])
- updated cosmrs and tendermint-rpc to their most recent versions ([#5339])
- build(deps): bump ts-rs from 10.0.0 to 10.1.0 ([#5338])
- build(deps): bump tempfile from 3.14.0 to 3.15.0 ([#5337])
- build(deps): bump the patch-updates group with 8 updates ([#5336])
- feature: introduce /load endpoint for self-reported quantised NymNode load ([#5326])
- feature: `CancellationToken`-based shutdowns ([#5325])
- Use expect in geodata test to give error message on failure ([#5314])
- feature: periodically remove stale gateway messages ([#5312])
- build(deps): bump the patch-updates group across 1 directory with 35 updates ([#5310])
- Add dependabot assignes for the root cargo ecosystem ([#5297])
- Move tun constants to network defaults ([#5286])
- Include IPINFO_API_TOKEN in nightly CI ([#5285])
- Nyx Chain Watcher ([#5274])
- bugfix: remove unnecessary arguments for nym-api swagger endpoints ([#5272])
- feature: nym topology revamp ([#5271])
- Add windows to CI builds ([#5269])
- http-api-client: deduplicate code ([#5267])
- build(deps): bump http from 1.1.0 to 1.2.0 ([#5228])
- NS API: add mixnet scraper ([#5200])
- build(deps): bump criterion from 0.4.0 to 0.5.1 ([#4911])
[#5417]: https://github.com/nymtech/nym/pull/5417
[#5405]: https://github.com/nymtech/nym/pull/5405
[#5404]: https://github.com/nymtech/nym/pull/5404
[#5403]: https://github.com/nymtech/nym/pull/5403
[#5397]: https://github.com/nymtech/nym/pull/5397
[#5394]: https://github.com/nymtech/nym/pull/5394
[#5390]: https://github.com/nymtech/nym/pull/5390
[#5389]: https://github.com/nymtech/nym/pull/5389
[#5388]: https://github.com/nymtech/nym/pull/5388
[#5378]: https://github.com/nymtech/nym/pull/5378
[#5376]: https://github.com/nymtech/nym/pull/5376
[#5374]: https://github.com/nymtech/nym/pull/5374
[#5361]: https://github.com/nymtech/nym/pull/5361
[#5360]: https://github.com/nymtech/nym/pull/5360
[#5358]: https://github.com/nymtech/nym/pull/5358
[#5353]: https://github.com/nymtech/nym/pull/5353
[#5347]: https://github.com/nymtech/nym/pull/5347
[#5342]: https://github.com/nymtech/nym/pull/5342
[#5339]: https://github.com/nymtech/nym/pull/5339
[#5338]: https://github.com/nymtech/nym/pull/5338
[#5337]: https://github.com/nymtech/nym/pull/5337
[#5336]: https://github.com/nymtech/nym/pull/5336
[#5326]: https://github.com/nymtech/nym/pull/5326
[#5325]: https://github.com/nymtech/nym/pull/5325
[#5314]: https://github.com/nymtech/nym/pull/5314
[#5312]: https://github.com/nymtech/nym/pull/5312
[#5310]: https://github.com/nymtech/nym/pull/5310
[#5297]: https://github.com/nymtech/nym/pull/5297
[#5286]: https://github.com/nymtech/nym/pull/5286
[#5285]: https://github.com/nymtech/nym/pull/5285
[#5274]: https://github.com/nymtech/nym/pull/5274
[#5272]: https://github.com/nymtech/nym/pull/5272
[#5271]: https://github.com/nymtech/nym/pull/5271
[#5269]: https://github.com/nymtech/nym/pull/5269
[#5267]: https://github.com/nymtech/nym/pull/5267
[#5228]: https://github.com/nymtech/nym/pull/5228
[#5200]: https://github.com/nymtech/nym/pull/5200
[#4911]: https://github.com/nymtech/nym/pull/4911
## [2025.1-reeses] (2025-01-15)
- Feture/legacy alert ([#5346])
- chore: readjusted --mode behaviour to fix the regression ([#5331])
- chore: apply 1.84 linter suggestions ([#5330])
- bugfix: make sure refresh data key matches bond info ([#5329])
- reduce log severity for number of packets being delayed ([#5321])
- feat: warn users if node is run in exit mode only ([#5320])
- Bugfix/contract version assignment ([#5318])
- fixed client session histogram buckets ([#5316])
- amend 250gb limit ([#5313])
- feature: expand nym-node prometheus metrics ([#5298])
- Cherry picked #5286 ([#5287])
- Add close to credential storage ([#5283])
- feature: wireguard metrics ([#5278])
- Add PATCH support to nym-http-api-client ([#5260])
- chore: removed legacy socks5 listener ([#5259])
- bugfix: make sure to apply gateway score filtering when choosing initial node ([#5256])
- Update TS bindings ([#5255])
- Add conversion unit tests for auth msg ([#5251])
- Add control messages to GatewayTransciver ([#5247])
- Remove unneeded async function annotation ([#5246])
- bugfix: make sure to update timestamp of last batch verification to prevent double redemption ([#5239])
- Add FromStr impl for UserAgent ([#5236])
- Extend swagger docs ([#5235])
- TicketType derive Hash and Eq ([#5233])
- Add fd callback to client core ([#5230])
- Extend raw ws fd for gateway client ([#5218])
- Shipping raw metrics to PG ([#5216])
- Change sqlite journal mode to WAL ([#5213])
- Derive serialize for UserAgent ([#5210])
- Restore Location fields ([#5208])
- better date serialization ([#5207])
- Fix overflow ([#5204])
- feature: hopefully final steps of the smoosh™️ ([#5201])
- Fix overflow ([#5184])
- NS API - Gateway stats scraping ([#5180])
- introduced initial internal commands for nym-cli: ecash key and request generation ([#5174])
- Move NS client to separate package under NS API ([#5171])
- build(deps): bump micromatch from 4.0.4 to 4.0.8 in /testnet-faucet ([#4813])
[#5346]: https://github.com/nymtech/nym/pull/5346
[#5331]: https://github.com/nymtech/nym/pull/5331
[#5330]: https://github.com/nymtech/nym/pull/5330
[#5329]: https://github.com/nymtech/nym/pull/5329
[#5321]: https://github.com/nymtech/nym/pull/5321
[#5320]: https://github.com/nymtech/nym/pull/5320
[#5318]: https://github.com/nymtech/nym/pull/5318
[#5316]: https://github.com/nymtech/nym/pull/5316
[#5313]: https://github.com/nymtech/nym/pull/5313
[#5298]: https://github.com/nymtech/nym/pull/5298
[#5287]: https://github.com/nymtech/nym/pull/5287
[#5283]: https://github.com/nymtech/nym/pull/5283
[#5278]: https://github.com/nymtech/nym/pull/5278
[#5260]: https://github.com/nymtech/nym/pull/5260
[#5259]: https://github.com/nymtech/nym/pull/5259
[#5256]: https://github.com/nymtech/nym/pull/5256
[#5255]: https://github.com/nymtech/nym/pull/5255
[#5251]: https://github.com/nymtech/nym/pull/5251
[#5247]: https://github.com/nymtech/nym/pull/5247
[#5246]: https://github.com/nymtech/nym/pull/5246
[#5239]: https://github.com/nymtech/nym/pull/5239
[#5236]: https://github.com/nymtech/nym/pull/5236
[#5235]: https://github.com/nymtech/nym/pull/5235
[#5233]: https://github.com/nymtech/nym/pull/5233
[#5230]: https://github.com/nymtech/nym/pull/5230
[#5218]: https://github.com/nymtech/nym/pull/5218
[#5216]: https://github.com/nymtech/nym/pull/5216
[#5213]: https://github.com/nymtech/nym/pull/5213
[#5210]: https://github.com/nymtech/nym/pull/5210
[#5208]: https://github.com/nymtech/nym/pull/5208
[#5207]: https://github.com/nymtech/nym/pull/5207
[#5204]: https://github.com/nymtech/nym/pull/5204
[#5201]: https://github.com/nymtech/nym/pull/5201
[#5184]: https://github.com/nymtech/nym/pull/5184
[#5180]: https://github.com/nymtech/nym/pull/5180
[#5174]: https://github.com/nymtech/nym/pull/5174
[#5171]: https://github.com/nymtech/nym/pull/5171
[#4813]: https://github.com/nymtech/nym/pull/4813
## [2024.14-crunch-patched] (2024-12-17)
- Fixes an issue to allow previously registred clients to connect to latest nym-nodes
- Fixes compatibility issues between nym-nodes and older clients
## [2024.14-crunch] (2024-12-11)
- Merge/release/2024.14-crunch ([#5242])
Generated
+1678 -943
View File
File diff suppressed because it is too large Load Diff
+78 -83
View File
@@ -48,13 +48,12 @@ members = [
"common/credentials-interface",
"common/crypto",
"common/dkg",
"common/ecash-double-spending",
"common/ecash-time",
"common/execute",
"common/exit-policy",
"common/gateway-requests",
"common/gateway-storage",
"common/gateway-stats-storage",
"common/gateway-storage",
"common/http-api-client",
"common/http-api-common",
"common/inclusion-probability",
@@ -93,6 +92,7 @@ members = [
"common/topology",
"common/tun",
"common/types",
"common/verloc",
"common/wasm/client-core",
"common/wasm/storage",
"common/wasm/utils",
@@ -104,6 +104,22 @@ members = [
"explorer-api/explorer-client",
"gateway",
"integrations/bity",
"nym-api",
"nym-api/nym-api-requests",
"nym-browser-extension/storage",
"nym-credential-proxy/nym-credential-proxy",
"nym-credential-proxy/nym-credential-proxy-requests",
"nym-credential-proxy/vpn-api-lib-wasm",
"nym-network-monitor",
"nym-node",
"nym-node-status-api/nym-node-status-agent",
"nym-node-status-api/nym-node-status-api",
"nym-node-status-api/nym-node-status-client",
"nym-node/nym-node-metrics",
"nym-node/nym-node-requests",
"nym-outfox",
"nym-validator-rewarder",
"nyx-chain-watcher",
"sdk/ffi/cpp",
"sdk/ffi/go",
"sdk/ffi/shared",
@@ -112,26 +128,16 @@ members = [
"service-providers/common",
"service-providers/ip-packet-router",
"service-providers/network-requester",
"nym-api",
"nym-api/nym-api-requests",
"nym-browser-extension/storage",
"nym-credential-proxy/nym-credential-proxy",
"nym-credential-proxy/nym-credential-proxy-requests",
"nym-credential-proxy/vpn-api-lib-wasm",
"nym-network-monitor",
"nyx-chain-watcher",
"nym-node",
"nym-node/nym-node-requests",
"nym-node/nym-node-metrics",
"nym-node-status-api/nym-node-status-agent",
"nym-node-status-api/nym-node-status-api",
"nym-node-status-api/nym-node-status-client",
"nym-outfox",
"nym-validator-rewarder",
"tools/echo-server",
"tools/internal/ssl-inject",
"tools/echo-server",
"tools/internal/contract-state-importer/importer-cli",
"tools/internal/contract-state-importer/importer-contract",
"tools/internal/mixnet-connectivity-check",
# "tools/internal/sdk-version-bump",
"tools/internal/ssl-inject",
"tools/internal/testnet-manager",
"tools/internal/testnet-manager",
"tools/internal/testnet-manager/dkg-bypass-contract",
"tools/internal/testnet-manager/dkg-bypass-contract",
"tools/nym-cli",
"tools/nym-id-cli",
@@ -143,13 +149,6 @@ members = [
"wasm/mix-fetch",
"wasm/node-tester",
"wasm/zknym-lib",
"tools/echo-server",
"tools/internal/contract-state-importer/importer-cli",
"tools/internal/contract-state-importer/importer-contract",
"tools/internal/testnet-manager",
"tools/internal/testnet-manager/dkg-bypass-contract",
"common/verloc",
"tools/internal/mixnet-connectivity-check",
]
default-members = [
@@ -173,7 +172,6 @@ exclude = [
"explorer",
"contracts",
"nym-wallet",
"nym-vpn/ui/src-tauri",
"cpu-cycles",
]
@@ -193,9 +191,10 @@ aes = "0.8.1"
aes-gcm = "0.10.1"
aes-gcm-siv = "0.11.1"
aead = "0.5.2"
anyhow = "1.0.90"
anyhow = "1.0.95"
arc-swap = "1.7.1"
argon2 = "0.5.0"
async-trait = "0.1.83"
async-trait = "0.1.86"
axum-client-ip = "0.6.1"
axum = "0.7.5"
axum-extra = "0.9.4"
@@ -204,7 +203,7 @@ bincode = "1.3.3"
bip39 = { version = "2.0.0", features = ["zeroize"] }
bit-vec = "0.7.0" # can we unify those?
bitvec = "1.0.0"
blake3 = "1.5.4"
blake3 = "1.5.5"
bloomfilter = "1.0.14"
bs58 = "0.5.1"
bytecodec = "0.4.15"
@@ -214,20 +213,20 @@ celes = "2.4.0"
cfg-if = "1.0.0"
chacha20 = "0.9.0"
chacha20poly1305 = "0.10.1"
chrono = "0.4.31"
chrono = "0.4.39"
cipher = "0.4.3"
clap = "4.5.20"
clap = "4.5.28"
clap_complete = "4.5"
clap_complete_fig = "4.5"
colored = "2.0"
comfy-table = "7.1.1"
console = "0.15.8"
comfy-table = "7.1.4"
console = "0.15.10"
console-subscriber = "0.1.1"
console_error_panic_hook = "0.1"
const-str = "0.5.6"
const_format = "0.2.33"
criterion = "0.4"
csv = "1.3.0"
const_format = "0.2.34"
criterion = "0.5"
csv = "1.3.1"
ctr = "0.9.1"
cupid = "0.6.1"
curve25519-dalek = "4.1"
@@ -244,16 +243,17 @@ etherparse = "0.13.0"
envy = "0.4"
eyre = "0.6.9"
fastrand = "2.1.1"
flate2 = "1.0.34"
futures = "0.3.28"
flate2 = "1.0.35"
futures = "0.3.31"
futures-util = "0.3"
generic-array = "0.14.7"
getrandom = "0.2.10"
getset = "0.1.3"
getset = "0.1.4"
handlebars = "3.5.5"
headers = "0.4.0"
hex = "0.4.3"
hex-literal = "0.3.3"
hickory-resolver = "0.24.3"
hkdf = "0.12.3"
hmac = "0.12.1"
http = "1"
@@ -262,9 +262,9 @@ httpcodec = "0.2.3"
humantime = "2.1.0"
humantime-serde = "1.1.1"
human-repr = "1.1.0"
hyper = "1.4.1"
hyper = "1.6.0"
hyper-util = "0.1"
indicatif = "0.17.8"
indicatif = "0.17.11"
inquire = "0.6.2"
ip_network = "0.4.1"
ipnetwork = "0.20"
@@ -282,16 +282,16 @@ moka = { version = "0.12", features = ["future"] }
nix = "0.27.1"
notify = "5.1.0"
okapi = "0.7.0"
once_cell = "1.20.2"
once_cell = "1.20.3"
opentelemetry = "0.19.0"
opentelemetry-jaeger = "0.18.0"
parking_lot = "0.12.3"
pem = "0.8"
petgraph = "0.6.5"
pin-project = "1.1"
pin-project-lite = "0.2.14"
pin-project-lite = "0.2.16"
pretty_env_logger = "0.4.0"
publicsuffix = "2.2.3"
publicsuffix = "2.3.0"
quote = "1"
rand = "0.8.5"
rand_chacha = "0.3"
@@ -307,12 +307,12 @@ rocket_cors = "0.6.0"
rocket_okapi = "0.8.0"
safer-ffi = "0.1.13"
schemars = "0.8.21"
semver = "1.0.23"
serde = "1.0.211"
semver = "1.0.25"
serde = "1.0.217"
serde_bytes = "0.11.15"
serde_derive = "1.0"
serde_json = "1.0.132"
serde_json_path = "0.7.1"
serde_json = "1.0.138"
serde_json_path = "0.7.2"
serde_repr = "0.1"
serde_with = "3.9.0"
serde_yaml = "0.9.25"
@@ -324,36 +324,36 @@ strum = "0.26"
strum_macros = "0.26"
subtle-encoding = "0.5"
syn = "1"
sysinfo = "0.30.13"
sysinfo = "0.33.0"
tap = "1.0.1"
tar = "0.4.42"
tempfile = "3.14"
thiserror = "1.0.64"
time = "0.3.30"
tokio = "1.39"
tokio-stream = "0.1.16"
tar = "0.4.43"
tempfile = "3.15"
thiserror = "2.0"
time = "0.3.37"
tokio = "1.43"
tokio-stream = "0.1.17"
tokio-test = "0.4.4"
tokio-tun = "0.11.5"
tokio-tungstenite = { version = "0.20.1" }
tokio-util = "0.7.12"
toml = "0.8.14"
tower = "0.4.13"
tokio-util = "0.7.13"
toml = "0.8.20"
tower = "0.5.2"
tower-http = "0.5.2"
tracing = "0.1.37"
tracing = "0.1.41"
tracing-opentelemetry = "0.19.0"
tracing-subscriber = "0.3.16"
tracing-subscriber = "0.3.19"
tracing-tree = "0.2.2"
tracing-log = "0.2"
ts-rs = "10.0.0"
ts-rs = "10.1.0"
tungstenite = { version = "0.20.1", default-features = false }
url = "2.5"
utoipa = "4.2"
utoipa-swagger-ui = "7.1"
utoipauto = "0.1"
utoipa = "5.2"
utoipa-swagger-ui = "8.0"
utoipauto = "0.2"
uuid = "*"
vergen = { version = "=8.3.1", default-features = false }
walkdir = "2"
wasm-bindgen-test = "0.3.43"
wasm-bindgen-test = "0.3.49"
x25519-dalek = "2.0.0"
zeroize = "1.6.0"
@@ -384,31 +384,26 @@ cw4 = { version = "=1.1.2" }
cw-controllers = { version = "=1.1.0" }
# cosmrs-related
bip32 = { version = "0.5.2", default-features = false }
bip32 = { version = "0.5.3", default-features = false }
# temporarily using a fork again (yay.) because we need staking and slashing support (which are already on main but not released)
# plus response message parsing (which is, as of the time of writing this message, waiting to get merged)
#cosmrs = { path = "../cosmos-rust-fork/cosmos-rust/cosmrs" }
cosmrs = { git = "https://github.com/cosmos/cosmos-rust", rev = "4b1332e6d8258ac845cef71589c8d362a669675a" } # unfortuntely we need a fork by yours truly to get the staking support
tendermint = "0.37.0" # same version as used by cosmrs
tendermint-rpc = "0.37.0" # same version as used by cosmrs
prost = { version = "0.12", default-features = false }
cosmrs = { version = "0.21.1" }
tendermint = "0.40.0"
tendermint-rpc = "0.40.0"
prost = { version = "0.13", default-features = false }
# wasm-related dependencies
gloo-utils = "0.2.0"
gloo-net = "0.5.0"
gloo-net = "0.6.0"
# use a separate branch due to feature unification failures
# this is blocked until the upstream removes outdates `wasm_bindgen` feature usage
# indexed_db_futures = "0.4.1"
indexed_db_futures = { git = "https://github.com/TiemenSch/rust-indexed-db", branch = "update-uuid" }
js-sys = "0.3.70"
indexed_db_futures = "0.6.0"
js-sys = "0.3.76"
serde-wasm-bindgen = "0.6.5"
tsify = "0.4.5"
wasm-bindgen = "0.2.99"
wasm-bindgen-futures = "0.4.45"
wasmtimer = "0.2.0"
web-sys = "0.3.72"
wasm-bindgen-futures = "0.4.49"
wasmtimer = "0.4.1"
web-sys = "0.3.76"
# Profile settings for individual crates
+23
View File
@@ -0,0 +1,23 @@
Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
+7 -7
View File
@@ -13,8 +13,8 @@ The platform is composed of multiple Rust crates. Top-level executable binary cr
* `nym-client` - an executable which you can build into your own applications. Use it for interacting with Nym nodes.
* `nym-socks5-client` - a Socks5 proxy you can run on your machine and use with existing applications.
* `nym-explorer` - a (projected) block explorer and (existing) mixnet viewer.
* `nym-wallet` - a desktop wallet implemented using the [Tauri](https://tauri.studio/en/docs/about/intro) framework.
* `nym-cli` - a tool for interacting with the network from the CLI.
* `nym-wallet` - a desktop wallet implemented using the [Tauri](https://tauri.app)) framework.
* `nym-cli` - a tool for interacting with the network from the CLI.
<!-- coming soon
* `nym-network-monitor` - sends packets through the full system to check that they are working as expected, and stores node uptime histories as the basis of a rewards system ("mixmining" or "proof-of-mixing").
-->
@@ -42,10 +42,10 @@ client ───► Gateway ──┘ mix │ mix ┌─►mix ───►
References for developers:
* [Dev Docs](https://nymtech.net/docs/developers)
* [SDKs](https://nymtech.net/docs/developers/rust)
* [Network Docs](https://nymtech.net/docs/network)
* [Release Cycle - git flow](https://nymtech.net/docs/operators/release-cycle)
* [Dev Docs](https://nym.com/docs/developers)
* [SDKs](https://nym.com/docs/developers/rust)
* [Network Docs](https://nym.com/docs/network)
* [Release Cycle - git flow](https://nym.com/docs/operators/release-cycle)
### Developer chat
@@ -66,4 +66,4 @@ As a general approach, licensing is as follows this pattern:
- libraries and components are Apache 2.0 or MIT
- documentation is Apache 2.0 or CC0-1.0
Nym Node Operators and Validators Temrs and Conditions can be found [here](https://nymtech.net/terms-and-conditions/operators/v1.0.0).
Nym Node Operators and Validators Terms and Conditions can be found [here](https://nym.com/operators-validators-terms).
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "nym-client"
version = "1.1.45"
version = "1.1.47"
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jędrzej Stuczyński <andrew@nymtech.net>"]
description = "Implementation of the Nym Client"
edition = "2021"
+6 -2
View File
@@ -56,7 +56,7 @@ pub fn default_data_directory<P: AsRef<Path>>(id: P) -> PathBuf {
.join(DEFAULT_DATA_DIR)
}
#[derive(Debug, Deserialize, PartialEq, Serialize)]
#[derive(Debug, Deserialize, PartialEq, Serialize, Clone)]
pub struct Config {
#[serde(flatten)]
pub base: BaseClientConfig,
@@ -94,6 +94,10 @@ impl CliClientConfig for Config {
}
impl Config {
pub fn base(&self) -> BaseClientConfig {
self.base.clone()
}
pub fn new<S: AsRef<str>>(id: S) -> Self {
Config {
base: BaseClientConfig::new(id.as_ref(), env!("CARGO_PKG_VERSION")),
@@ -209,7 +213,7 @@ impl SocketType {
}
}
#[derive(Debug, Deserialize, PartialEq, Eq, Serialize)]
#[derive(Debug, Deserialize, PartialEq, Eq, Serialize, Clone)]
#[serde(default, deny_unknown_fields)]
pub struct Socket {
pub socket_type: SocketType,
@@ -107,5 +107,8 @@ enabled = {{ debug.stats_reporting.enabled }}
provider_address = '{{ debug.stats_reporting.provider_address }}'
reporting_interval = '{{ debug.stats_reporting.reporting_interval }}'
[debug.forget_me]
client = {{ debug.forget_me.client }}
stats = {{ debug.forget_me.stats }}
"#;
+8 -3
View File
@@ -20,7 +20,7 @@ pub use nym_sphinx::addressing::clients::Recipient;
pub mod config;
type NativeClientBuilder<'a> = BaseClientBuilder<'a, QueryHttpRpcNyxdClient, OnDiskPersistent>;
type NativeClientBuilder = BaseClientBuilder<QueryHttpRpcNyxdClient, OnDiskPersistent>;
pub struct SocketClient {
/// Client configuration options, including, among other things, packet sending rates,
@@ -32,6 +32,10 @@ pub struct SocketClient {
}
impl SocketClient {
pub fn config(&self) -> Config {
self.config.clone()
}
pub fn new(config: Config, custom_mixnet: Option<PathBuf>) -> Self {
SocketClient {
config,
@@ -108,8 +112,9 @@ impl SocketClient {
let storage = self.initialise_storage().await?;
let user_agent = nym_bin_common::bin_info!().into();
let mut base_client = BaseClientBuilder::new(&self.config.base, storage, dkg_query_client)
.with_user_agent(user_agent);
let mut base_client =
BaseClientBuilder::new(self.config().base(), storage, dkg_query_client)
.with_user_agent(user_agent);
if let Some(custom_mixnet) = &self.custom_mixnet {
base_client = base_client.with_stored_topology(custom_mixnet)?;
+1
View File
@@ -82,6 +82,7 @@ impl From<Init> for OverrideConfig {
nyxd_urls: init_config.common_args.nyxd_urls,
enabled_credentials_mode: init_config.common_args.enabled_credentials_mode,
stats_reporting_address: init_config.common_args.stats_reporting_address,
forget_me: init_config.common_args.forget_me.into(),
}
}
}
+3
View File
@@ -16,6 +16,7 @@ use nym_bin_common::completions::{fig_generate, ArgShell};
use nym_client::client::Recipient;
use nym_client_core::cli_helpers::CliClient;
use nym_client_core::client::base_client::storage::migration_helpers::v1_1_33;
use nym_client_core::config::ForgetMe;
use nym_config::OptionalSet;
use std::error::Error;
use std::net::IpAddr;
@@ -106,6 +107,7 @@ pub(crate) struct OverrideConfig {
nyxd_urls: Option<Vec<url::Url>>,
enabled_credentials_mode: Option<bool>,
stats_reporting_address: Option<Recipient>,
forget_me: ForgetMe,
}
pub(crate) async fn execute(args: Cli) -> Result<(), Box<dyn Error + Send + Sync>> {
@@ -133,6 +135,7 @@ pub(crate) fn override_config(config: Config, args: OverrideConfig) -> Config {
args.fastmode,
)
.with_base(BaseClientConfig::with_disabled_cover_traffic, args.no_cover)
.with_base(BaseClientConfig::with_forget_me, args.forget_me)
.with_optional(Config::with_port, args.port)
.with_optional(Config::with_host, args.host)
.with_optional_custom_env_ext(
+1
View File
@@ -41,6 +41,7 @@ impl From<Run> for OverrideConfig {
nyxd_urls: run_config.common_args.nyxd_urls,
enabled_credentials_mode: run_config.common_args.enabled_credentials_mode,
stats_reporting_address: run_config.common_args.stats_reporting_address,
forget_me: run_config.common_args.forget_me.into(),
}
}
}
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "nym-socks5-client"
version = "1.1.45"
version = "1.1.47"
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
View File
@@ -93,6 +93,7 @@ impl From<Init> for OverrideConfig {
enabled_credentials_mode: init_config.common_args.enabled_credentials_mode,
outfox: false,
stats_reporting_address: init_config.common_args.stats_reporting_address,
forget_me: init_config.common_args.forget_me.into(),
}
}
}
+3 -1
View File
@@ -17,7 +17,7 @@ use nym_bin_common::completions::{fig_generate, ArgShell};
use nym_client_core::cli_helpers::CliClient;
use nym_client_core::client::base_client::storage::migration_helpers::v1_1_33;
use nym_client_core::client::topology_control::geo_aware_provider::CountryGroup;
use nym_client_core::config::{GroupBy, TopologyStructure};
use nym_client_core::config::{ForgetMe, GroupBy, TopologyStructure};
use nym_config::OptionalSet;
use nym_sphinx::addressing::Recipient;
use nym_sphinx::params::{PacketSize, PacketType};
@@ -113,6 +113,7 @@ pub(crate) struct OverrideConfig {
enabled_credentials_mode: Option<bool>,
outfox: bool,
stats_reporting_address: Option<Recipient>,
forget_me: ForgetMe,
}
pub(crate) async fn execute(args: Cli) -> Result<(), Box<dyn Error + Send + Sync>> {
@@ -179,6 +180,7 @@ pub(crate) fn override_config(config: Config, args: OverrideConfig) -> Config {
BaseClientConfig::with_topology_structure,
topology_structure,
)
.with_base(BaseClientConfig::with_forget_me, args.forget_me)
.with_optional(Config::with_anonymous_replies, args.use_anonymous_replies)
.with_optional(Config::with_port, args.port)
.with_optional(Config::with_ip, args.ip)
+1
View File
@@ -65,6 +65,7 @@ impl From<Run> for OverrideConfig {
enabled_credentials_mode: run_config.common_args.enabled_credentials_mode,
outfox: run_config.outfox,
stats_reporting_address: run_config.common_args.stats_reporting_address,
forget_me: run_config.common_args.forget_me.into(),
}
}
}
+4
View File
@@ -113,4 +113,8 @@ enabled = {{ core.debug.stats_reporting.enabled }}
provider_address = '{{ core.debug.stats_reporting.provider_address }}'
reporting_interval = '{{ core.debug.stats_reporting.reporting_interval }}'
[core.debug.forget_me]
client = {{ core.debug.forget_me.client }}
stats = {{ core.debug.forget_me.stats }}
"#;
@@ -28,7 +28,7 @@ pub type HmacSha256 = Hmac<Sha256>;
pub type Nonce = u64;
pub type Taken = Option<SystemTime>;
pub const BANDWIDTH_CAP_PER_DAY: u64 = 1024 * 1024 * 1024; // 1 GB
pub const BANDWIDTH_CAP_PER_DAY: u64 = 250 * 1024 * 1024 * 1024; // 250 GB
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct IpPair {
+1
View File
@@ -40,6 +40,7 @@ nym-crypto = { path = "../crypto" }
nym-explorer-client = { path = "../../explorer-api/explorer-client" }
nym-gateway-client = { path = "../client-libs/gateway-client" }
nym-gateway-requests = { path = "../gateway-requests" }
nym-http-api-client = { path = "../http-api-client" }
nym-metrics = { path = "../nym-metrics" }
nym-nonexhaustive-delayqueue = { path = "../nonexhaustive-delayqueue" }
nym-sphinx = { path = "../nymsphinx" }
+79 -3
View File
@@ -145,6 +145,11 @@ impl Config {
self
}
pub fn with_forget_me(mut self, forget_me: ForgetMe) -> Self {
self.debug.forget_me = forget_me;
self
}
// TODO: this should be refactored properly
// as of 12.09.23 the below is true (not sure how this comment will rot in the future)
// medium_toggle:
@@ -517,7 +522,7 @@ impl Default for Acknowledgements {
}
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
#[serde(default, deny_unknown_fields)]
#[serde(default)]
pub struct Topology {
/// The uniform delay every which clients are querying the directory server
/// to try to obtain a compatible network topology to send sphinx packets through.
@@ -553,12 +558,15 @@ pub struct Topology {
/// Specifies whether this client should attempt to retrieve all available network nodes
/// as opposed to just active mixnodes/gateways.
/// Useless without `ignore_epoch_roles = true`
pub use_extended_topology: bool,
/// Specifies whether this client should ignore the current epoch role of the target egress node
/// when constructing the final hop packets.
pub ignore_egress_epoch_role: bool,
/// Specifies whether this client should ignore the current epoch role of the ingress node
/// when attempting to establish new connection
pub ignore_ingress_epoch_role: bool,
}
#[allow(clippy::large_enum_variant)]
@@ -596,7 +604,9 @@ impl Default for Topology {
minimum_mixnode_performance: DEFAULT_MIN_MIXNODE_PERFORMANCE,
minimum_gateway_performance: DEFAULT_MIN_GATEWAY_PERFORMANCE,
use_extended_topology: false,
ignore_egress_epoch_role: false,
ignore_egress_epoch_role: true,
ignore_ingress_epoch_role: true,
}
}
}
@@ -714,6 +724,9 @@ pub struct DebugConfig {
/// Defines all configuration options related to stats reporting.
pub stats_reporting: StatsReporting,
/// Defines all configuration options related to the forget me flag.
pub forget_me: ForgetMe,
}
impl DebugConfig {
@@ -736,6 +749,69 @@ impl Default for DebugConfig {
topology: Default::default(),
reply_surbs: Default::default(),
stats_reporting: Default::default(),
forget_me: Default::default(),
}
}
}
#[derive(Clone, Default, Debug, Deserialize, PartialEq, Serialize, Copy)]
pub struct ForgetMe {
client: bool,
stats: bool,
}
impl From<bool> for ForgetMe {
fn from(value: bool) -> Self {
if value {
Self::new_all()
} else {
Self::new_none()
}
}
}
impl ForgetMe {
pub fn new_all() -> Self {
Self {
client: true,
stats: true,
}
}
pub fn new_client() -> Self {
Self {
client: true,
stats: false,
}
}
pub fn new_stats() -> Self {
Self {
client: false,
stats: true,
}
}
pub fn new(client: bool, stats: bool) -> Self {
Self { client, stats }
}
pub fn any(&self) -> bool {
self.client || self.stats
}
pub fn client(&self) -> bool {
self.client
}
pub fn stats(&self) -> bool {
self.stats
}
pub fn new_none() -> Self {
Self {
client: false,
stats: false,
}
}
}
@@ -182,7 +182,7 @@ impl From<ConfigV5> for Config {
maximum_reply_key_age: value.debug.reply_surbs.maximum_reply_key_age,
surb_mix_hops: value.debug.reply_surbs.surb_mix_hops,
},
stats_reporting: Default::default(),
..Default::default()
},
}
}
@@ -15,6 +15,7 @@ pub mod error;
mod manager;
mod models;
#[derive(Clone)]
pub struct OnDiskGatewaysDetails {
manager: StorageManager,
}
@@ -20,12 +20,12 @@ pub enum InMemStorageError {
MalformedGateway(#[from] BadGateway),
}
#[derive(Debug, Default)]
#[derive(Clone, Debug, Default)]
pub struct InMemGatewaysDetails {
inner: Arc<RwLock<InMemStorageInner>>,
}
#[derive(Debug, Default)]
#[derive(Clone, Debug, Default)]
struct InMemStorageInner {
active_gateway: Option<String>,
gateways: HashMap<String, GatewayRegistration>,
@@ -115,11 +115,12 @@ where
hardcoded_topology.entry_capable_nodes().cloned().collect()
} else {
let mut rng = rand::thread_rng();
crate::init::helpers::current_gateways(
crate::init::helpers::gateways_for_init(
&mut rng,
&core.client.nym_api_urls,
user_agent,
core.debug.topology.minimum_gateway_performance,
core.debug.topology.ignore_ingress_epoch_role,
)
.await?
};
@@ -93,6 +93,10 @@ pub struct CommonClientInitArgs {
/// Sets the address to report statistics
#[cfg_attr(feature = "cli", clap(long, hide = true))]
pub stats_reporting_address: Option<Recipient>,
/// Sets the forget me flag
#[cfg_attr(feature = "cli", clap(long, hide = true, default_value_t = false))]
pub forget_me: bool,
}
pub struct InitResultsWithConfig<T> {
@@ -170,11 +174,12 @@ where
hardcoded_topology.entry_capable_nodes().cloned().collect()
} else {
let mut rng = rand::thread_rng();
crate::init::helpers::current_gateways(
crate::init::helpers::gateways_for_init(
&mut rng,
&core.client.nym_api_urls,
user_agent,
core.debug.topology.minimum_gateway_performance,
core.debug.topology.ignore_ingress_epoch_role,
)
.await?
};
@@ -61,4 +61,8 @@ pub struct CommonClientRunArgs {
/// Sets the address to report statistics
#[cfg_attr(feature = "cli", clap(long, hide = true))]
pub stats_reporting_address: Option<Recipient>,
/// Sets the forget me flag
#[cfg_attr(feature = "cli", clap(long, hide = true, default_value_t = false))]
pub forget_me: bool,
}
@@ -1,6 +1,7 @@
// Copyright 2022-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use super::mix_traffic::ClientRequestSender;
use super::received_buffer::ReceivedBufferMessage;
use super::statistics_control::StatisticsControl;
use crate::client::base_client::storage::helpers::store_client_keys;
@@ -31,10 +32,11 @@ use crate::init::{
setup_gateway,
types::{GatewaySetup, InitialisationResult},
};
use crate::{config, spawn_future, ForgetMe};
use crate::{config, spawn_future};
use futures::channel::mpsc;
use log::*;
use nym_bandwidth_controller::BandwidthController;
use nym_client_core_config_types::ForgetMe;
use nym_client_core_gateways_storage::{GatewayDetails, GatewaysDetailsStore};
use nym_credential_storage::storage::Storage as CredentialStorage;
use nym_crypto::asymmetric::{encryption, identity};
@@ -175,8 +177,8 @@ impl From<bool> for CredentialsToggle {
}
}
pub struct BaseClientBuilder<'a, C, S: MixnetClientStorage> {
config: &'a Config,
pub struct BaseClientBuilder<C, S: MixnetClientStorage> {
config: Config,
client_store: S,
dkg_query_client: Option<C>,
@@ -190,20 +192,18 @@ pub struct BaseClientBuilder<'a, C, S: MixnetClientStorage> {
#[cfg(unix)]
connection_fd_callback: Option<Arc<dyn Fn(RawFd) + Send + Sync>>,
forget_me: ForgetMe,
}
impl<'a, C, S> BaseClientBuilder<'a, C, S>
impl<C, S> BaseClientBuilder<C, S>
where
S: MixnetClientStorage + 'static,
C: DkgQueryClient + Send + Sync + 'static,
{
pub fn new(
base_config: &'a Config,
base_config: Config,
client_store: S,
dkg_query_client: Option<C>,
) -> BaseClientBuilder<'a, C, S> {
) -> BaseClientBuilder<C, S> {
BaseClientBuilder {
config: base_config,
client_store,
@@ -216,13 +216,12 @@ where
setup_method: GatewaySetup::MustLoad { gateway_id: None },
#[cfg(unix)]
connection_fd_callback: None,
forget_me: Default::default(),
}
}
#[must_use]
pub fn with_forget_me(mut self, forget_me: &ForgetMe) -> Self {
self.forget_me = forget_me.clone();
self.config.debug.forget_me = *forget_me;
self
}
@@ -472,6 +471,7 @@ where
.claim_initial_bandwidth()
.await
.map_err(gateway_failure)?;
gateway_client
.start_listening_for_mixnet_messages()
.map_err(gateway_failure)?;
@@ -644,13 +644,12 @@ where
fn start_mix_traffic_controller(
gateway_transceiver: Box<dyn GatewayTransceiver + Send>,
shutdown: TaskClient,
forget_me: ForgetMe,
) -> BatchMixMessageSender {
) -> (BatchMixMessageSender, ClientRequestSender) {
info!("Starting mix traffic controller...");
let (mix_traffic_controller, mix_tx) =
MixTrafficController::new(gateway_transceiver, forget_me);
let (mix_traffic_controller, mix_tx, client_tx) =
MixTrafficController::new(gateway_transceiver);
mix_traffic_controller.start_with_shutdown(shutdown);
mix_tx
(mix_tx, client_tx)
}
// TODO: rename it as it implies the data is persistent whilst one can use InMemBackend
@@ -772,7 +771,7 @@ where
);
let stats_reporter = Self::start_statistics_control(
self.config,
&self.config,
self.user_agent.clone(),
generate_client_stats_id(*self_address.identity()),
input_sender.clone(),
@@ -798,7 +797,7 @@ where
let gateway_transceiver = Self::setup_gateway_transceiver(
self.custom_gateway_transceiver,
self.config,
&self.config,
init_res,
bandwidth_controller,
&details_store,
@@ -832,10 +831,9 @@ where
// traffic stream.
// The MixTrafficController then sends the actual traffic
let message_sender = Self::start_mix_traffic_controller(
let (message_sender, client_request_sender) = Self::start_mix_traffic_controller(
gateway_transceiver,
shutdown.fork("mix_traffic_controller"),
self.forget_me,
);
// Channels that the websocket listener can use to signal downstream to the real traffic
@@ -910,6 +908,8 @@ where
},
stats_reporter,
task_handle: shutdown,
client_request_sender,
forget_me: self.config.debug.forget_me,
})
}
}
@@ -921,6 +921,7 @@ pub struct BaseClient {
pub client_output: ClientOutputStatus,
pub client_state: ClientState,
pub stats_reporter: ClientStatsSender,
pub client_request_sender: ClientRequestSender,
pub task_handle: TaskHandle,
pub forget_me: ForgetMe,
}
@@ -4,6 +4,8 @@
// TODO: combine those more closely. Perhaps into a single underlying store.
// Like for persistent, on-disk, storage, what's the point of having 3 different databases?
use rand::rngs::OsRng;
use crate::client::key_manager::persistence::{InMemEphemeralKeys, KeyStore};
use crate::client::replies::reply_storage;
use crate::client::replies::reply_storage::ReplyStorageBackend;
@@ -63,7 +65,7 @@ pub trait MixnetClientStorage {
fn gateway_details_store(&self) -> &Self::GatewaysDetailsStore;
}
#[derive(Default)]
#[derive(Clone)]
pub struct Ephemeral {
key_store: InMemEphemeralKeys,
reply_store: reply_storage::Empty,
@@ -71,9 +73,14 @@ pub struct Ephemeral {
gateway_details_store: InMemGatewaysDetails,
}
impl Ephemeral {
pub fn new() -> Self {
Default::default()
impl Default for Ephemeral {
fn default() -> Self {
Ephemeral {
key_store: InMemEphemeralKeys::new(&mut OsRng),
reply_store: Default::default(),
credential_store: Default::default(),
gateway_details_store: Default::default(),
}
}
}
@@ -114,6 +121,7 @@ impl MixnetClientStorage for Ephemeral {
}
}
#[derive(Clone)]
#[cfg(all(
not(target_arch = "wasm32"),
feature = "fs-surb-storage",
@@ -3,7 +3,9 @@
use crate::client::key_manager::ClientKeys;
use async_trait::async_trait;
use rand::{CryptoRng, RngCore};
use std::error::Error;
use std::sync::Arc;
use tokio::sync::Mutex;
#[cfg(not(target_arch = "wasm32"))]
@@ -64,6 +66,7 @@ pub enum OnDiskKeysError {
},
}
#[derive(Clone)]
#[cfg(not(target_arch = "wasm32"))]
pub struct OnDiskKeys {
paths: ClientKeysPaths,
@@ -193,9 +196,20 @@ impl KeyStore for OnDiskKeys {
}
}
#[derive(Default)]
#[derive(Clone)]
pub struct InMemEphemeralKeys {
keys: Mutex<Option<ClientKeys>>,
keys: Arc<Mutex<ClientKeys>>,
}
impl InMemEphemeralKeys {
pub fn new<R>(rng: &mut R) -> Self
where
R: RngCore + CryptoRng,
{
InMemEphemeralKeys {
keys: Arc::new(Mutex::new(ClientKeys::generate_new(rng))),
}
}
}
#[derive(Debug, thiserror::Error)]
@@ -208,11 +222,11 @@ impl KeyStore for InMemEphemeralKeys {
type StorageError = EphemeralKeysError;
async fn load_keys(&self) -> Result<ClientKeys, Self::StorageError> {
self.keys.lock().await.clone().ok_or(EphemeralKeysError)
Ok(self.keys.lock().await.clone())
}
async fn store_keys(&self, keys: &ClientKeys) -> Result<(), Self::StorageError> {
*self.keys.lock().await = Some(keys.clone());
*self.keys.lock().await = keys.clone();
Ok(())
}
}
@@ -2,13 +2,17 @@
// SPDX-License-Identifier: Apache-2.0
use crate::client::mix_traffic::transceiver::GatewayTransceiver;
use crate::{spawn_future, ForgetMe};
use crate::error::ClientCoreError;
use crate::spawn_future;
use log::*;
use nym_gateway_requests::ClientRequest;
use nym_sphinx::forwarding::packet::MixPacket;
use transceiver::ErasedGatewayError;
pub type BatchMixMessageSender = tokio::sync::mpsc::Sender<Vec<MixPacket>>;
pub type BatchMixMessageReceiver = tokio::sync::mpsc::Receiver<Vec<MixPacket>>;
pub type ClientRequestReceiver = tokio::sync::mpsc::Receiver<ClientRequest>;
pub type ClientRequestSender = tokio::sync::mpsc::Sender<ClientRequest>;
pub mod transceiver;
@@ -23,52 +27,67 @@ pub struct MixTrafficController {
gateway_transceiver: Box<dyn GatewayTransceiver + Send>,
mix_rx: BatchMixMessageReceiver,
client_rx: ClientRequestReceiver,
// TODO: this is temporary work-around.
// in long run `gateway_client` will be moved away from `MixTrafficController` anyway.
consecutive_gateway_failure_count: usize,
forget_me: ForgetMe,
}
impl MixTrafficController {
pub fn new<T>(
gateway_transceiver: T,
forget_me: ForgetMe,
) -> (MixTrafficController, BatchMixMessageSender)
) -> (
MixTrafficController,
BatchMixMessageSender,
ClientRequestSender,
)
where
T: GatewayTransceiver + Send + 'static,
{
let (message_sender, message_receiver) =
tokio::sync::mpsc::channel(MIX_MESSAGE_RECEIVER_BUFFER_SIZE);
let (client_sender, client_receiver) = tokio::sync::mpsc::channel(1);
(
MixTrafficController {
gateway_transceiver: Box::new(gateway_transceiver),
mix_rx: message_receiver,
client_rx: client_receiver,
consecutive_gateway_failure_count: 0,
forget_me,
},
message_sender,
client_sender,
)
}
pub fn new_dynamic(
gateway_transceiver: Box<dyn GatewayTransceiver + Send>,
forget_me: ForgetMe,
) -> (MixTrafficController, BatchMixMessageSender) {
) -> (
MixTrafficController,
BatchMixMessageSender,
ClientRequestSender,
) {
let (message_sender, message_receiver) =
tokio::sync::mpsc::channel(MIX_MESSAGE_RECEIVER_BUFFER_SIZE);
let (client_sender, client_receiver) = tokio::sync::mpsc::channel(1);
(
MixTrafficController {
gateway_transceiver,
mix_rx: message_receiver,
client_rx: client_receiver,
consecutive_gateway_failure_count: 0,
forget_me,
},
message_sender,
client_sender,
)
}
async fn on_messages(&mut self, mut mix_packets: Vec<MixPacket>) {
async fn on_messages(
&mut self,
mut mix_packets: Vec<MixPacket>,
) -> Result<(), ErasedGatewayError> {
debug_assert!(!mix_packets.is_empty());
let result = if mix_packets.len() == 1 {
@@ -80,21 +99,14 @@ impl MixTrafficController {
.await
};
match result {
Err(err) => {
error!("Failed to send sphinx packet(s) to the gateway: {err}");
self.consecutive_gateway_failure_count += 1;
if self.consecutive_gateway_failure_count == MAX_FAILURE_COUNT {
// todo: in the future this should initiate a 'graceful' shutdown or try
// to reconnect?
panic!("failed to send sphinx packet to the gateway {MAX_FAILURE_COUNT} times in a row - assuming the gateway is dead. Can't do anything about it yet :(")
}
}
Ok(_) => {
trace!("We *might* have managed to forward sphinx packet(s) to the gateway!");
self.consecutive_gateway_failure_count = 0;
}
if result.is_err() {
self.consecutive_gateway_failure_count += 1;
} else {
trace!("We *might* have managed to forward sphinx packet(s) to the gateway!");
self.consecutive_gateway_failure_count = 0;
}
result
}
pub fn start_with_shutdown(mut self, mut shutdown: nym_task::TaskClient) {
@@ -105,13 +117,35 @@ impl MixTrafficController {
tokio::select! {
mix_packets = self.mix_rx.recv() => match mix_packets {
Some(mix_packets) => {
self.on_messages(mix_packets).await;
if let Err(err) = self.on_messages(mix_packets).await {
error!("Failed to send sphinx packet(s) to the gateway: {err}");
if self.consecutive_gateway_failure_count == MAX_FAILURE_COUNT {
// Disconnect from the gateway. If we should try to re-connect
// is handled at a higher layer.
error!("Failed to send sphinx packet to the gateway {MAX_FAILURE_COUNT} times in a row - assuming the gateway is dead");
// Do we need to handle the embedded mixnet client case
// separately?
shutdown.send_we_stopped(Box::new(ClientCoreError::GatewayFailedToForwardMessages));
break;
}
}
},
None => {
log::trace!("MixTrafficController: Stopping since channel closed");
break;
}
},
client_request = self.client_rx.recv() => match client_request {
Some(client_request) => {
match self.gateway_transceiver.send_client_request(client_request).await {
Ok(_) => (),
Err(e) => error!("Failed to send client request: {}", e),
};
},
None => {
log::trace!("MixTrafficController, client request channel closed");
}
},
_ = shutdown.recv_with_delay() => {
log::trace!("MixTrafficController: Received shutdown");
break;
@@ -120,25 +154,6 @@ impl MixTrafficController {
}
shutdown.recv_timeout().await;
if self.forget_me.any() {
log::info!("Sending forget me request to the gateway");
match self
.gateway_transceiver
.send_client_request(ClientRequest::ForgetMe {
client: self.forget_me.client(),
stats: self.forget_me.stats(),
})
.await
{
Ok(_) => {
log::info!("Successfully sent forget me request to the gateway");
}
Err(err) => {
log::error!("Failed to send forget me request to the gateway: {err}");
}
}
}
log::debug!("MixTrafficController: Exiting");
});
}
@@ -86,7 +86,9 @@ impl<G: GatewayTransceiver + ?Sized + Send> GatewayTransceiver for Box<G> {
&mut self,
message: ClientRequest,
) -> Result<(), GatewayClientError> {
(**self).send_client_request(message).await
let _ = (**self).send_client_request(message.clone()).await?;
log::debug!("Sent client request: {:?}", message);
Ok(())
}
}
@@ -143,14 +145,7 @@ where
&mut self,
message: ClientRequest,
) -> Result<(), GatewayClientError> {
if let Some(shared_key) = self.gateway_client.shared_key() {
self.gateway_client
.send_websocket_message(message.encrypt(&*shared_key)?)
.await?;
Ok(())
} else {
Err(GatewayClientError::ConnectionInInvalidState)
}
self.gateway_client.send_client_request(message).await
}
}
@@ -626,9 +626,14 @@ where
messages: Vec<RealMessage>,
transmission_lane: TransmissionLane,
) {
self.real_message_sender
if let Err(err) = self
.real_message_sender
.send((messages, transmission_lane))
.await
.expect("real message receiver task (OutQueueControl) has died");
{
error!(
"Failed to forward messages to the real message sender (OutQueueControl): {err}"
);
}
}
}
@@ -9,10 +9,12 @@ use self::{
acknowledgement_control::AcknowledgementController, real_traffic_stream::OutQueueControl,
};
use crate::client::real_messages_control::message_handler::MessageHandler;
use crate::client::replies::reply_controller;
use crate::client::replies::reply_controller::{
ReplyController, ReplyControllerReceiver, ReplyControllerSender,
};
use crate::client::replies::reply_storage::CombinedReplyStorage;
use crate::config;
use crate::{
client::{
inbound_messages::InputMessageReceiver, mix_traffic::BatchMixMessageSender,
@@ -27,16 +29,13 @@ use nym_gateway_client::AcknowledgementReceiver;
use nym_sphinx::acknowledgements::AckKey;
use nym_sphinx::addressing::clients::Recipient;
use nym_sphinx::params::PacketType;
use nym_statistics_common::clients::ClientStatsSender;
use nym_task::connections::{ConnectionCommandReceiver, LaneQueueLengths};
use rand::{rngs::OsRng, CryptoRng, Rng};
use std::sync::Arc;
use crate::client::replies::reply_controller;
use crate::config;
pub(crate) use acknowledgement_control::{AckActionSender, Action};
use nym_statistics_common::clients::ClientStatsSender;
pub(crate) mod acknowledgement_control;
pub(crate) mod message_handler;
pub(crate) mod real_traffic_stream;
@@ -545,7 +545,7 @@ where
loop {
tokio::select! {
biased;
_ = shutdown.recv_with_delay() => {
_ = shutdown.recv() => {
log::trace!("OutQueueControl: Received shutdown");
break;
}
@@ -70,7 +70,10 @@ impl SendingDelayController {
lower_bound,
multiplier_elevated_counter: 0,
time_when_logged_about_elevated_multiplier: now
- Duration::from_secs(INTERVAL_BETWEEN_WARNING_ABOUT_ELEVATED_MULTIPLIER_SECS),
.checked_sub(Duration::from_secs(
INTERVAL_BETWEEN_WARNING_ABOUT_ELEVATED_MULTIPLIER_SECS,
))
.unwrap_or(now),
time_when_changed: now,
time_when_backpressure_detected: now,
}
@@ -16,14 +16,14 @@
#![warn(clippy::todo)]
#![warn(clippy::dbg_macro)]
use std::time::Duration;
use futures::StreamExt;
use nym_client_core_config_types::StatsReporting;
use nym_sphinx::addressing::Recipient;
use nym_statistics_common::clients::{
ClientStatsController, ClientStatsReceiver, ClientStatsSender,
};
use nym_task::connections::TransmissionLane;
use std::time::Duration;
use crate::{
client::inbound_messages::{InputMessage, InputMessageSender},
@@ -94,13 +94,40 @@ impl StatisticsControl {
async fn run_with_shutdown(&mut self, mut task_client: nym_task::TaskClient) {
log::debug!("Started StatisticsControl with graceful shutdown support");
let mut stats_report_interval =
tokio::time::interval(self.reporting_config.reporting_interval);
let mut local_report_interval = tokio::time::interval(LOCAL_REPORT_INTERVAL);
let mut snapshot_interval = tokio::time::interval(SNAPSHOT_INTERVAL);
#[cfg(not(target_arch = "wasm32"))]
let mut stats_report_interval = tokio_stream::wrappers::IntervalStream::new(
tokio::time::interval(self.reporting_config.reporting_interval),
);
#[cfg(not(target_arch = "wasm32"))]
let mut local_report_interval = tokio_stream::wrappers::IntervalStream::new(
tokio::time::interval(LOCAL_REPORT_INTERVAL),
);
#[cfg(not(target_arch = "wasm32"))]
let mut snapshot_interval =
tokio_stream::wrappers::IntervalStream::new(tokio::time::interval(SNAPSHOT_INTERVAL));
#[cfg(target_arch = "wasm32")]
let mut stats_report_interval = gloo_timers::future::IntervalStream::new(
self.reporting_config.reporting_interval.as_millis() as u32,
);
#[cfg(target_arch = "wasm32")]
let mut local_report_interval =
gloo_timers::future::IntervalStream::new(LOCAL_REPORT_INTERVAL.as_millis() as u32);
#[cfg(target_arch = "wasm32")]
let mut snapshot_interval =
gloo_timers::future::IntervalStream::new(SNAPSHOT_INTERVAL.as_millis() as u32);
loop {
tokio::select! {
biased;
_ = task_client.recv() => {
log::trace!("StatisticsControl: Received shutdown");
break;
},
stats_event = self.stats_rx.recv() => match stats_event {
Some(stats_event) => self.stats.handle_event(stats_event),
None => {
@@ -108,25 +135,24 @@ impl StatisticsControl {
break;
}
},
_ = snapshot_interval.tick() => {
_ = snapshot_interval.next() => {
self.stats.snapshot();
}
_ = stats_report_interval.tick(), if self.reporting_config.enabled && self.reporting_config.provider_address.is_some() => {
// SAFTEY : this branch executes only if reporting is not none, so unwrapp is fine
#[allow(clippy::unwrap_used)]
self.report_stats(self.reporting_config.provider_address.unwrap()).await;
_ = stats_report_interval.next() => {
let Some(recipient) = self.reporting_config.provider_address else {
continue
};
if self.reporting_config.enabled {
self.report_stats(recipient).await;
}
}
_ = local_report_interval.tick() => {
_ = local_report_interval.next() => {
self.stats.local_report(&mut task_client);
}
_ = task_client.recv_with_delay() => {
log::trace!("StatisticsControl: Received shutdown");
break;
},
}
}
task_client.recv_timeout().await;
log::debug!("StatisticsControl: Exiting");
}
+10
View File
@@ -36,6 +36,13 @@ pub enum ClientCoreError {
#[error("no gateway with id: {0}")]
NoGatewayWithId(String),
#[error("Invalid URL: {0}")]
InvalidUrl(String),
#[cfg(not(target_arch = "wasm32"))]
#[error("resolution failed: {0}")]
ResolutionFailed(#[from] nym_http_api_client::HickoryDnsError),
#[error("no gateways on network")]
NoGatewaysOnNetwork,
@@ -96,6 +103,9 @@ pub enum ClientCoreError {
#[error("timed out while trying to establish gateway connection")]
GatewayConnectionTimeout,
#[error("failed to forward mix messages to gateway")]
GatewayFailedToForwardMessages,
#[error("no ping measurements for the gateway ({identity}) performed")]
NoGatewayMeasurements { identity: String },
+9 -4
View File
@@ -15,6 +15,9 @@ use std::{sync::Arc, time::Duration};
use tungstenite::Message;
use url::Url;
#[cfg(not(target_arch = "wasm32"))]
use crate::init::websockets::connect_async;
use nym_topology::NodeId;
#[cfg(not(target_arch = "wasm32"))]
use tokio::net::TcpStream;
@@ -23,8 +26,6 @@ use tokio::time::sleep;
#[cfg(not(target_arch = "wasm32"))]
use tokio::time::Instant;
#[cfg(not(target_arch = "wasm32"))]
use tokio_tungstenite::connect_async;
#[cfg(not(target_arch = "wasm32"))]
use tokio_tungstenite::{MaybeTlsStream, WebSocketStream};
#[cfg(target_arch = "wasm32")]
use wasm_utils::websocket::JSWebsocket;
@@ -86,11 +87,12 @@ impl<'a, G: ConnectableGateway> GatewayWithLatency<'a, G> {
}
}
pub async fn current_gateways<R: Rng>(
pub async fn gateways_for_init<R: Rng>(
rng: &mut R,
nym_apis: &[Url],
user_agent: Option<UserAgent>,
minimum_performance: u8,
ignore_epoch_roles: bool,
) -> Result<Vec<RoutingNode>, ClientCoreError> {
let nym_api = nym_apis
.choose(rng)
@@ -108,8 +110,11 @@ pub async fn current_gateways<R: Rng>(
log::trace!("Gateways: {:#?}", gateways);
// filter out gateways below minimum performance and ones that could operate as a mixnode
// (we don't want instability)
let valid_gateways = gateways
.iter()
.filter(|g| ignore_epoch_roles || !g.supported_roles.mixnode)
.filter(|g| g.performance.round_to_integer() >= minimum_performance)
.filter_map(|gateway| gateway.try_into().ok())
.collect::<Vec<_>>();
@@ -128,7 +133,7 @@ pub async fn current_gateways<R: Rng>(
async fn connect(endpoint: &str) -> Result<WsConn, ClientCoreError> {
match tokio::time::timeout(CONN_TIMEOUT, connect_async(endpoint)).await {
Err(_elapsed) => Err(ClientCoreError::GatewayConnectionTimeout),
Ok(Err(conn_failure)) => Err(conn_failure.into()),
Ok(Err(conn_failure)) => Err(conn_failure),
Ok(Ok((stream, _))) => Ok(stream),
}
}
+2
View File
@@ -26,6 +26,8 @@ use serde::Serialize;
pub mod helpers;
pub mod types;
#[cfg(not(target_arch = "wasm32"))]
pub(crate) mod websockets;
// helpers for error wrapping
+29 -1
View File
@@ -17,7 +17,7 @@ use nym_topology::node::RoutingNode;
use nym_validator_client::client::IdentityKey;
use nym_validator_client::nyxd::AccountId;
use serde::Serialize;
use std::fmt::Display;
use std::fmt::{Debug, Display};
use std::sync::Arc;
use time::OffsetDateTime;
use url::Url;
@@ -221,6 +221,34 @@ pub enum GatewaySetup {
},
}
impl Debug for GatewaySetup {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
GatewaySetup::MustLoad { gateway_id } => f
.debug_struct("GatewaySetup::MustLoad")
.field("gateway_id", gateway_id)
.finish(),
GatewaySetup::New {
specification,
available_gateways,
} => f
.debug_struct("GatewaySetup::New")
.field("specification", specification)
.field("available_gateways", available_gateways)
.field("gateways", specification)
.finish(),
GatewaySetup::ReuseConnection {
gateway_details, ..
} => f
.debug_struct("GatewaySetup::ReuseConnection")
.field("authenticated_ephemeral_client", &"***")
.field("gateway_details", gateway_details)
.field("client_keys", &"***")
.finish(),
}
}
}
impl GatewaySetup {
pub fn try_reuse_connection(init_res: InitialisationResult) -> Result<Self, ClientCoreError> {
if let Some(authenticated_ephemeral_client) = init_res.authenticated_ephemeral_client {
+44
View File
@@ -0,0 +1,44 @@
use crate::error::ClientCoreError;
use nym_http_api_client::HickoryDnsResolver;
use tokio::net::TcpStream;
use tokio_tungstenite::{MaybeTlsStream, WebSocketStream};
use tungstenite::handshake::client::Response;
use url::{Host, Url};
use std::net::SocketAddr;
#[cfg(not(target_arch = "wasm32"))]
pub(crate) async fn connect_async(
endpoint: &str,
) -> Result<(WebSocketStream<MaybeTlsStream<TcpStream>>, Response), ClientCoreError> {
let resolver = HickoryDnsResolver::default();
let uri = Url::parse(endpoint).map_err(|_| ClientCoreError::InvalidUrl(endpoint.to_owned()))?;
let port: u16 = uri.port_or_known_default().unwrap_or(443);
let host = uri
.host()
.ok_or(ClientCoreError::InvalidUrl(endpoint.to_owned()))?;
// Get address for tcp connection, if a domain is provided use our preferred resolver rather than
// the default std resolve
let sock_addrs: Vec<SocketAddr> = match host {
Host::Ipv4(addr) => vec![SocketAddr::new(addr.into(), port)],
Host::Ipv6(addr) => vec![SocketAddr::new(addr.into(), port)],
Host::Domain(domain) => {
// Do a DNS lookup for the domain using our custom DNS resolver
resolver
.resolve_str(domain)
.await?
.into_iter()
.map(|a| SocketAddr::new(a, port))
.collect()
}
};
let stream = TcpStream::connect(&sock_addrs[..]).await?;
tokio_tungstenite::client_async_tls(endpoint, stream)
.await
.map_err(Into::into)
}
-45
View File
@@ -33,48 +33,3 @@ where
{
tokio::spawn(future);
}
#[derive(Clone, Default, Debug)]
pub struct ForgetMe {
client: bool,
stats: bool,
}
impl ForgetMe {
pub fn new_all() -> Self {
Self {
client: true,
stats: true,
}
}
pub fn new_client() -> Self {
Self {
client: true,
stats: false,
}
}
pub fn new_stats() -> Self {
Self {
client: false,
stats: true,
}
}
pub fn new(client: bool, stats: bool) -> Self {
Self { client, stats }
}
pub fn any(&self) -> bool {
self.client || self.stats
}
pub fn client(&self) -> bool {
self.client
}
pub fn stats(&self) -> bool {
self.stats
}
}
@@ -22,7 +22,7 @@ mod error;
mod manager;
mod models;
#[derive(Debug)]
#[derive(Clone, Debug)]
pub struct Backend {
temporary_old_path: Option<PathBuf>,
database_path: PathBuf,
@@ -19,7 +19,7 @@ pub mod fs_backend;
#[error("no information provided")]
pub struct UndefinedError;
#[derive(Debug)]
#[derive(Clone, Debug)]
pub struct Empty {
// we need to keep 'basic' metadata here to "load" the CombinedReplyStorage
pub min_surb_threshold: usize,
@@ -27,6 +27,7 @@ nym-credential-storage = { path = "../../credential-storage" }
nym-credentials-interface = { path = "../../credentials-interface" }
nym-crypto = { path = "../../crypto" }
nym-gateway-requests = { path = "../../gateway-requests" }
nym-http-api-client = { path = "../../http-api-client" }
nym-network-defaults = { path = "../../network-defaults" }
nym-sphinx = { path = "../../nymsphinx" }
nym-statistics-common = { path = "../../statistics" }
@@ -40,8 +40,6 @@ use url::Url;
use std::os::fd::RawFd;
#[cfg(not(target_arch = "wasm32"))]
use tokio::time::sleep;
#[cfg(not(target_arch = "wasm32"))]
use tokio_tungstenite::connect_async;
#[cfg(not(unix))]
use std::os::raw::c_int as RawFd;
@@ -53,6 +51,11 @@ use zeroize::Zeroizing;
pub mod config;
#[cfg(not(target_arch = "wasm32"))]
pub(crate) mod websockets;
#[cfg(not(target_arch = "wasm32"))]
use websockets::connect_async;
pub struct GatewayConfig {
pub gateway_identity: identity::PublicKey,
@@ -201,15 +204,7 @@ impl<C, St> GatewayClient<C, St> {
"Attemting to establish connection to gateway at: {}",
self.gateway_address
);
let ws_stream = match connect_async(&self.gateway_address).await {
Ok((ws_stream, _)) => ws_stream,
Err(error) => {
return Err(GatewayClientError::NetworkConnectionFailed {
address: self.gateway_address.clone(),
source: error,
})
}
};
let (ws_stream, _) = connect_async(&self.gateway_address).await?;
self.connection = SocketState::Available(Box::new(ws_stream));
@@ -271,6 +266,19 @@ impl<C, St> GatewayClient<C, St> {
}
}
pub async fn send_client_request(
&mut self,
message: ClientRequest,
) -> Result<(), GatewayClientError> {
if let Some(shared_key) = self.shared_key() {
let encrypted = message.encrypt(&*shared_key)?;
Box::pin(self.send_websocket_message(encrypted)).await?;
Ok(())
} else {
Err(GatewayClientError::ConnectionInInvalidState)
}
}
async fn read_control_response(&mut self) -> Result<ServerResponse, GatewayClientError> {
// we use the fact that all request responses are Message::Text and only pushed
// sphinx packets are Message::Binary
@@ -0,0 +1,53 @@
use crate::error::GatewayClientError;
use nym_http_api_client::HickoryDnsResolver;
use tokio::net::TcpStream;
use tokio_tungstenite::{MaybeTlsStream, WebSocketStream};
use tungstenite::handshake::client::Response;
use url::{Host, Url};
use std::net::SocketAddr;
#[cfg(not(target_arch = "wasm32"))]
pub(crate) async fn connect_async(
endpoint: &str,
) -> Result<(WebSocketStream<MaybeTlsStream<TcpStream>>, Response), GatewayClientError> {
let resolver = HickoryDnsResolver::default();
let uri =
Url::parse(endpoint).map_err(|_| GatewayClientError::InvalidUrl(endpoint.to_owned()))?;
let port: u16 = uri.port_or_known_default().unwrap_or(443);
let host = uri
.host()
.ok_or(GatewayClientError::InvalidUrl(endpoint.to_owned()))?;
// Get address for tcp connection, if a domain is provided use our preferred resolver rather than
// the default std resolve
let sock_addrs: Vec<SocketAddr> = match host {
Host::Ipv4(addr) => vec![SocketAddr::new(addr.into(), port)],
Host::Ipv6(addr) => vec![SocketAddr::new(addr.into(), port)],
Host::Domain(domain) => {
// Do a DNS lookup for the domain using our custom DNS resolver
resolver
.resolve_str(domain)
.await?
.into_iter()
.map(|a| SocketAddr::new(a, port))
.collect()
}
};
let stream = TcpStream::connect(&sock_addrs[..]).await.map_err(|error| {
GatewayClientError::NetworkConnectionFailed {
address: endpoint.to_owned(),
source: error.into(),
}
})?;
tokio_tungstenite::client_async_tls(endpoint, stream)
.await
.map_err(|error| GatewayClientError::NetworkConnectionFailed {
address: endpoint.to_owned(),
source: error,
})
}
@@ -44,7 +44,11 @@ pub enum GatewayClientError {
NetworkConnectionFailed { address: String, source: WsError },
#[error("Invalid URL: {0}")]
InvalidURL(String),
InvalidUrl(String),
#[cfg(not(target_arch = "wasm32"))]
#[error("resolution failed: {0}")]
ResolutionFailed(#[from] nym_http_api_client::HickoryDnsError),
#[error("No shared key was provided or obtained")]
NoSharedKeyAvailable,
+3 -1
View File
@@ -8,10 +8,12 @@ license.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
dashmap = { workspace = true }
futures = { workspace = true }
tracing = { workspace = true }
tokio = { workspace = true, features = ["time"] }
tokio = { workspace = true, features = ["time", "sync"] }
tokio-util = { workspace = true, features = ["codec"], optional = true }
tokio-stream = { workspace = true }
# internal
nym-sphinx = { path = "../../nymsphinx" }
+141 -86
View File
@@ -1,21 +1,24 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2021-2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use futures::channel::mpsc;
use dashmap::DashMap;
use futures::StreamExt;
use nym_sphinx::addressing::nodes::NymNodeRoutingAddress;
use nym_sphinx::framing::codec::NymCodec;
use nym_sphinx::framing::packet::FramedNymPacket;
use nym_sphinx::params::PacketType;
use nym_sphinx::NymPacket;
use std::collections::HashMap;
use std::io;
use std::net::SocketAddr;
use std::sync::atomic::{AtomicU32, Ordering};
use std::ops::Deref;
use std::sync::atomic::{AtomicU32, AtomicUsize, Ordering};
use std::sync::Arc;
use std::time::Duration;
use tokio::net::TcpStream;
use tokio::sync::mpsc;
use tokio::sync::mpsc::error::TrySendError;
use tokio::time::sleep;
use tokio_stream::wrappers::ReceiverStream;
use tokio_util::codec::Framed;
use tracing::*;
@@ -55,11 +58,37 @@ pub trait SendWithoutResponse {
}
pub struct Client {
conn_new: HashMap<NymNodeRoutingAddress, ConnectionSender>,
active_connections: ActiveConnections,
connections_count: Arc<AtomicUsize>,
config: Config,
}
struct ConnectionSender {
#[derive(Default, Clone)]
pub struct ActiveConnections {
inner: Arc<DashMap<NymNodeRoutingAddress, ConnectionSender>>,
}
impl ActiveConnections {
pub fn pending_packets(&self) -> usize {
self.inner
.iter()
.map(|sender| {
let max_capacity = sender.channel.max_capacity();
let capacity = sender.channel.capacity();
max_capacity - capacity
})
.sum()
}
}
impl Deref for ActiveConnections {
type Target = DashMap<NymNodeRoutingAddress, ConnectionSender>;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
pub struct ConnectionSender {
channel: mpsc::Sender<FramedNymPacket>,
current_reconnection_attempt: Arc<AtomicU32>,
}
@@ -73,46 +102,53 @@ impl ConnectionSender {
}
}
impl Client {
pub fn new(config: Config) -> Client {
Client {
conn_new: HashMap::new(),
config,
struct ManagedConnection {
address: SocketAddr,
message_receiver: ReceiverStream<FramedNymPacket>,
connection_timeout: Duration,
current_reconnection: Arc<AtomicU32>,
}
impl ManagedConnection {
fn new(
address: SocketAddr,
message_receiver: mpsc::Receiver<FramedNymPacket>,
connection_timeout: Duration,
current_reconnection: Arc<AtomicU32>,
) -> Self {
ManagedConnection {
address,
message_receiver: ReceiverStream::new(message_receiver),
connection_timeout,
current_reconnection,
}
}
async fn manage_connection(
address: SocketAddr,
receiver: mpsc::Receiver<FramedNymPacket>,
connection_timeout: Duration,
current_reconnection: &AtomicU32,
) {
async fn run(self) {
let address = self.address;
let connection_fut = TcpStream::connect(address);
let conn = match tokio::time::timeout(connection_timeout, connection_fut).await {
let conn = match tokio::time::timeout(self.connection_timeout, connection_fut).await {
Ok(stream_res) => match stream_res {
Ok(stream) => {
debug!("Managed to establish connection to {}", address);
debug!("Managed to establish connection to {}", self.address);
// if we managed to connect, reset the reconnection count (whatever it might have been)
current_reconnection.store(0, Ordering::Release);
self.current_reconnection.store(0, Ordering::Release);
Framed::new(stream, NymCodec)
}
Err(err) => {
debug!(
"failed to establish connection to {} (err: {})",
address, err
);
debug!("failed to establish connection to {address} (err: {err})",);
return;
}
},
Err(_) => {
debug!(
"failed to connect to {} within {:?}",
address, connection_timeout
"failed to connect to {address} within {:?}",
self.connection_timeout
);
// we failed to connect - increase reconnection attempt
current_reconnection.fetch_add(1, Ordering::SeqCst);
self.current_reconnection.fetch_add(1, Ordering::SeqCst);
return;
}
};
@@ -120,15 +156,28 @@ impl Client {
// Take whatever the receiver channel produces and put it on the connection.
// We could have as well used conn.send_all(receiver.map(Ok)), but considering we don't care
// about neither receiver nor the connection, it doesn't matter which one gets consumed
if let Err(err) = receiver.map(Ok).forward(conn).await {
warn!("Failed to forward packets to {} - {err}", address);
if let Err(err) = self.message_receiver.map(Ok).forward(conn).await {
warn!("Failed to forward packets to {address}: {err}");
}
debug!(
"connection manager to {} is finished. Either the connection failed or mixnet client got dropped",
address
"connection manager to {address} is finished. Either the connection failed or mixnet client got dropped",
);
}
}
impl Client {
pub fn new(config: Config, connections_count: Arc<AtomicUsize>) -> Client {
Client {
active_connections: Default::default(),
connections_count,
config,
}
}
pub fn active_connections(&self) -> ActiveConnections {
self.active_connections.clone()
}
/// If we're trying to reconnect, determine how long we should wait.
fn determine_backoff(&self, current_attempt: u32) -> Option<Duration> {
@@ -148,7 +197,7 @@ impl Client {
}
fn make_connection(&mut self, address: NymNodeRoutingAddress, pending_packet: FramedNymPacket) {
let (mut sender, receiver) = mpsc::channel(self.config.maximum_connection_buffer_size);
let (sender, receiver) = mpsc::channel(self.config.maximum_connection_buffer_size);
// this CAN'T fail because we just created the channel which has a non-zero capacity
if self.config.maximum_connection_buffer_size > 0 {
@@ -156,15 +205,16 @@ impl Client {
}
// if we already tried to connect to `address` before, grab the current attempt count
let current_reconnection_attempt = if let Some(existing) = self.conn_new.get_mut(&address) {
existing.channel = sender;
Arc::clone(&existing.current_reconnection_attempt)
} else {
let new_entry = ConnectionSender::new(sender);
let current_attempt = Arc::clone(&new_entry.current_reconnection_attempt);
self.conn_new.insert(address, new_entry);
current_attempt
};
let current_reconnection_attempt =
if let Some(mut existing) = self.active_connections.get_mut(&address) {
existing.channel = sender;
Arc::clone(&existing.current_reconnection_attempt)
} else {
let new_entry = ConnectionSender::new(sender);
let current_attempt = Arc::clone(&new_entry.current_reconnection_attempt);
self.active_connections.insert(address, new_entry);
current_attempt
};
// load the actual value.
let reconnection_attempt = current_reconnection_attempt.load(Ordering::Acquire);
@@ -173,6 +223,7 @@ impl Client {
// copy the value before moving into another task
let initial_connection_timeout = self.config.initial_connection_timeout;
let connections_count = self.connections_count.clone();
tokio::spawn(async move {
// before executing the manager, wait for what was specified, if anything
if let Some(backoff) = backoff {
@@ -180,13 +231,16 @@ impl Client {
sleep(backoff).await;
}
Self::manage_connection(
connections_count.fetch_add(1, Ordering::SeqCst);
ManagedConnection::new(
address.into(),
receiver,
initial_connection_timeout,
&current_reconnection_attempt,
current_reconnection_attempt,
)
.await
.run()
.await;
connections_count.fetch_sub(1, Ordering::SeqCst);
});
}
}
@@ -201,49 +255,47 @@ impl SendWithoutResponse for Client {
trace!("Sending packet to {address:?}");
let framed_packet = FramedNymPacket::new(packet, packet_type);
if let Some(sender) = self.conn_new.get_mut(&address) {
if let Err(err) = sender.channel.try_send(framed_packet) {
if err.is_full() {
debug!("Connection to {} seems to not be able to handle all the traffic - dropping the current packet", address);
// it's not a 'big' error, but we did not manage to send the packet
// if the queue is full, we can't really do anything but to drop the packet
Err(io::Error::new(
io::ErrorKind::WouldBlock,
"connection queue is full",
))
} else if err.is_disconnected() {
debug!(
"Connection to {} seems to be dead. attempting to re-establish it...",
address
);
// it's not a 'big' error, but we did not manage to send the packet, but queue
// it up to send it as soon as the connection is re-established
self.make_connection(address, err.into_inner());
Err(io::Error::new(
io::ErrorKind::ConnectionAborted,
"reconnection attempt is in progress",
))
} else {
// this can't really happen, but let's safe-guard against it in case something changes in futures library
Err(io::Error::new(
io::ErrorKind::Other,
"unknown connection buffer error",
))
}
} else {
Ok(())
}
} else {
let Some(sender) = self.active_connections.get_mut(&address) else {
// there was never a connection to begin with
debug!("establishing initial connection to {}", address);
// it's not a 'big' error, but we did not manage to send the packet, but queue the packet
// for sending for as soon as the connection is created
self.make_connection(address, framed_packet);
Err(io::Error::new(
return Err(io::Error::new(
io::ErrorKind::NotConnected,
"connection is in progress",
))
}
));
};
let sending_res = sender.channel.try_send(framed_packet);
drop(sender);
sending_res.map_err(|err| {
match err {
TrySendError::Full(_) => {
debug!("Connection to {address} seems to not be able to handle all the traffic - dropping the current packet");
// it's not a 'big' error, but we did not manage to send the packet
// if the queue is full, we can't really do anything but to drop the packet
io::Error::new(
io::ErrorKind::WouldBlock,
"connection queue is full",
)
}
TrySendError::Closed(dropped) => {
debug!(
"Connection to {address} seems to be dead. attempting to re-establish it...",
);
// it's not a 'big' error, but we did not manage to send the packet, but queue
// it up to send it as soon as the connection is re-established
self.make_connection(address, dropped);
io::Error::new(
io::ErrorKind::ConnectionAborted,
"reconnection attempt is in progress",
)
}
}
} )
}
}
@@ -252,12 +304,15 @@ mod tests {
use super::*;
fn dummy_client() -> Client {
Client::new(Config {
initial_reconnection_backoff: Duration::from_millis(10_000),
maximum_reconnection_backoff: Duration::from_millis(300_000),
initial_connection_timeout: Duration::from_millis(1_500),
maximum_connection_buffer_size: 128,
})
Client::new(
Config {
initial_reconnection_backoff: Duration::from_millis(10_000),
maximum_reconnection_backoff: Duration::from_millis(300_000),
initial_connection_timeout: Duration::from_millis(1_500),
maximum_connection_buffer_size: 128,
},
Default::default(),
)
}
#[test]
@@ -11,16 +11,16 @@ use crate::{
use nym_api_requests::ecash::models::{
AggregatedCoinIndicesSignatureResponse, AggregatedExpirationDateSignatureResponse,
BatchRedeemTicketsBody, EcashBatchTicketRedemptionResponse, EcashTicketVerificationResponse,
IssuedTicketbooksChallengeResponse, IssuedTicketbooksForResponse, SpentCredentialsResponse,
VerifyEcashTicketBody,
IssuedTicketbooksChallengeResponse, IssuedTicketbooksForResponse, VerifyEcashTicketBody,
};
use nym_api_requests::ecash::{
BlindSignRequestBody, BlindedSignatureResponse, PartialCoinIndicesSignatureResponse,
PartialExpirationDateSignatureResponse, VerificationKeyResponse,
};
use nym_api_requests::models::{
ApiHealthResponse, GatewayBondAnnotated, GatewayCoreStatusResponse, MixnodeCoreStatusResponse,
MixnodeStatusResponse, NymNodeDescription, RewardEstimationResponse, StakeSaturationResponse,
ApiHealthResponse, GatewayBondAnnotated, GatewayCoreStatusResponse,
HistoricalPerformanceResponse, MixnodeCoreStatusResponse, MixnodeStatusResponse,
NymNodeDescription, RewardEstimationResponse, StakeSaturationResponse,
};
use nym_api_requests::models::{LegacyDescribedGateway, MixNodeBondAnnotated};
use nym_api_requests::nym_nodes::SkimmedNode;
@@ -264,6 +264,31 @@ impl<C, S> Client<C, S> {
Ok(self.nym_api.get_gateways_detailed_unfiltered().await?)
}
pub async fn get_full_node_performance_history(
&self,
node_id: NodeId,
) -> Result<Vec<HistoricalPerformanceResponse>, ValidatorClientError> {
// TODO: deal with paging in macro or some helper function or something, because it's the same pattern everywhere
let mut page = 0;
let mut history = Vec::new();
loop {
let mut res = self
.nym_api
.get_node_performance_history(node_id, Some(page), None)
.await?;
history.append(&mut res.history.data);
if history.len() < res.history.pagination.total {
page += 1
} else {
break;
}
}
Ok(history)
}
// TODO: combine with NymApiClient...
pub async fn get_all_cached_described_nodes(
&self,
@@ -621,13 +646,6 @@ impl NymApiClient {
.await?)
}
#[deprecated]
pub async fn spent_credentials_filter(
&self,
) -> Result<SpentCredentialsResponse, ValidatorClientError> {
Ok(self.nym_api.double_spending_filter_v1().await?)
}
pub async fn partial_expiration_date_signatures(
&self,
expiration_date: Option<Date>,
@@ -65,6 +65,12 @@ pub enum EcashApiError {
#[from]
source: cosmrs::ErrorReport,
},
#[error("nym api error")]
NymApi {
#[from]
source: crate::ValidatorClientError,
},
}
impl TryFrom<ContractVKShare> for EcashApiClient {
@@ -13,7 +13,7 @@ use nym_api_requests::ecash::models::{
use nym_api_requests::ecash::VerificationKeyResponse;
use nym_api_requests::models::{
AnnotationResponse, ApiHealthResponse, LegacyDescribedMixNode, NodePerformanceResponse,
NodeRefreshBody, NymNodeDescription, RewardedSetResponse,
NodeRefreshBody, NymNodeDescription, PerformanceHistoryResponse, RewardedSetResponse,
};
use nym_api_requests::nym_nodes::PaginatedCachedNodesResponse;
use nym_api_requests::pagination::PaginatedResponse;
@@ -31,6 +31,7 @@ pub use nym_api_requests::{
StakeSaturationResponse, UptimeResponse,
},
nym_nodes::{CachedNodesResponse, SkimmedNode},
NymNetworkDetailsResponse,
};
pub use nym_coconut_dkg_common::types::EpochId;
use nym_contracts_common::IdentityKey;
@@ -163,6 +164,35 @@ pub trait NymApiClientExt: ApiClient {
.await
}
#[tracing::instrument(level = "debug", skip_all)]
async fn get_node_performance_history(
&self,
node_id: NodeId,
page: Option<u32>,
per_page: Option<u32>,
) -> Result<PerformanceHistoryResponse, NymAPIError> {
let mut params = Vec::new();
if let Some(page) = page {
params.push(("page", page.to_string()))
}
if let Some(per_page) = per_page {
params.push(("per_page", per_page.to_string()))
}
self.get_json(
&[
routes::API_VERSION,
routes::NYM_NODES_ROUTES,
routes::NYM_NODES_PERFORMANCE_HISTORY,
&*node_id.to_string(),
],
&params,
)
.await
}
#[tracing::instrument(level = "debug", skip_all)]
async fn get_nodes_described(
&self,
@@ -179,8 +209,15 @@ pub trait NymApiClientExt: ApiClient {
params.push(("per_page", per_page.to_string()))
}
self.get_json(&[routes::API_VERSION, "nym-nodes", "described"], &params)
.await
self.get_json(
&[
routes::API_VERSION,
routes::NYM_NODES_ROUTES,
routes::NYM_NODES_DESCRIBED,
],
&params,
)
.await
}
#[tracing::instrument(level = "debug", skip_all)]
@@ -199,8 +236,15 @@ pub trait NymApiClientExt: ApiClient {
params.push(("per_page", per_page.to_string()))
}
self.get_json(&[routes::API_VERSION, "nym-nodes", "bonded"], &params)
.await
self.get_json(
&[
routes::API_VERSION,
routes::NYM_NODES_ROUTES,
routes::NYM_NODES_BONDED,
],
&params,
)
.await
}
#[deprecated]
@@ -210,7 +254,7 @@ pub trait NymApiClientExt: ApiClient {
&[
routes::API_VERSION,
"unstable",
"nym-nodes",
routes::NYM_NODES_ROUTES,
"mixnodes",
"skimmed",
],
@@ -226,7 +270,7 @@ pub trait NymApiClientExt: ApiClient {
&[
routes::API_VERSION,
"unstable",
"nym-nodes",
routes::NYM_NODES_ROUTES,
"gateways",
"skimmed",
],
@@ -238,7 +282,11 @@ pub trait NymApiClientExt: ApiClient {
#[instrument(level = "debug", skip(self))]
async fn get_rewarded_set(&self) -> Result<RewardedSetResponse, NymAPIError> {
self.get_json(
&[routes::API_VERSION, "nym-nodes", "rewarded-set"],
&[
routes::API_VERSION,
routes::NYM_NODES_ROUTES,
routes::NYM_NODES_REWARDED_SET,
],
NO_PARAMS,
)
.await
@@ -271,7 +319,7 @@ pub trait NymApiClientExt: ApiClient {
&[
routes::API_VERSION,
"unstable",
"nym-nodes",
routes::NYM_NODES_ROUTES,
"skimmed",
"entry-gateways",
"all",
@@ -308,7 +356,7 @@ pub trait NymApiClientExt: ApiClient {
&[
routes::API_VERSION,
"unstable",
"nym-nodes",
routes::NYM_NODES_ROUTES,
"skimmed",
"mixnodes",
"active",
@@ -345,7 +393,7 @@ pub trait NymApiClientExt: ApiClient {
&[
routes::API_VERSION,
"unstable",
"nym-nodes",
routes::NYM_NODES_ROUTES,
"skimmed",
"mixnodes",
"all",
@@ -377,7 +425,12 @@ pub trait NymApiClientExt: ApiClient {
}
self.get_json(
&[routes::API_VERSION, "unstable", "nym-nodes", "skimmed"],
&[
routes::API_VERSION,
"unstable",
routes::NYM_NODES_ROUTES,
"skimmed",
],
&params,
)
.await
@@ -686,8 +739,8 @@ pub trait NymApiClientExt: ApiClient {
self.get_json(
&[
routes::API_VERSION,
"nym-nodes",
"performance",
routes::NYM_NODES_ROUTES,
routes::NYM_NODES_PERFORMANCE,
&node_id.to_string(),
],
NO_PARAMS,
@@ -702,8 +755,8 @@ pub trait NymApiClientExt: ApiClient {
self.get_json(
&[
routes::API_VERSION,
"nym-nodes",
"annotation",
routes::NYM_NODES_ROUTES,
routes::NYM_NODES_ANNOTATION,
&node_id.to_string(),
],
NO_PARAMS,
@@ -797,20 +850,6 @@ pub trait NymApiClientExt: ApiClient {
.await
}
#[deprecated]
#[instrument(level = "debug", skip(self))]
async fn double_spending_filter_v1(&self) -> Result<SpentCredentialsResponse, NymAPIError> {
self.get_json(
&[
routes::API_VERSION,
routes::ECASH_ROUTES,
routes::DOUBLE_SPENDING_FILTER_V1,
],
NO_PARAMS,
)
.await
}
#[instrument(level = "debug", skip(self))]
async fn partial_expiration_date_signatures(
&self,
@@ -927,7 +966,11 @@ pub trait NymApiClientExt: ApiClient {
request: &NodeRefreshBody,
) -> Result<(), NymAPIError> {
self.post_json(
&[routes::API_VERSION, "nym-nodes", "refresh-described"],
&[
routes::API_VERSION,
routes::NYM_NODES_ROUTES,
routes::NYM_NODES_REFRESH_DESCRIBED,
],
NO_PARAMS,
request,
)
@@ -971,6 +1014,15 @@ pub trait NymApiClientExt: ApiClient {
)
.await
}
#[instrument(level = "debug", skip(self))]
async fn get_network_details(&self) -> Result<NymNetworkDetailsResponse, NymAPIError> {
self.get_json(
&[routes::API_VERSION, routes::NETWORK, routes::DETAILS],
NO_PARAMS,
)
.await
}
}
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
@@ -13,8 +13,6 @@ pub const DETAILED: &str = "detailed";
pub const DETAILED_UNFILTERED: &str = "detailed-unfiltered";
pub const ACTIVE: &str = "active";
pub const REWARDED: &str = "rewarded";
pub const DOUBLE_SPENDING_FILTER_V1: &str = "double-spending-filter-v1";
pub const ECASH_ROUTES: &str = "ecash";
pub use ecash::*;
@@ -34,6 +32,19 @@ pub mod ecash {
pub const EPOCH_ID_PARAM: &str = "epoch_id";
}
pub const NYM_NODES_ROUTES: &str = "nym-nodes";
pub use nym_nodes::*;
pub mod nym_nodes {
pub const NYM_NODES_PERFORMANCE_HISTORY: &str = "performance-history";
pub const NYM_NODES_PERFORMANCE: &str = "performance";
pub const NYM_NODES_ANNOTATION: &str = "annotation";
pub const NYM_NODES_DESCRIBED: &str = "described";
pub const NYM_NODES_BONDED: &str = "bonded";
pub const NYM_NODES_REWARDED_SET: &str = "rewarded-set";
pub const NYM_NODES_REFRESH_DESCRIBED: &str = "refresh-described";
}
pub const STATUS_ROUTES: &str = "status";
pub const API_STATUS_ROUTES: &str = "api-status";
pub const HEALTH: &str = "health";
@@ -54,6 +65,8 @@ pub const STAKE_SATURATION: &str = "stake-saturation";
pub const INCLUSION_CHANCE: &str = "inclusion-probability";
pub const SUBMIT_GATEWAY: &str = "submit-gateway-monitoring-results";
pub const SUBMIT_NODE: &str = "submit-node-monitoring-results";
pub const PERFORMANCE: &str = "performance";
pub const SERVICE_PROVIDERS: &str = "services";
pub const DETAILS: &str = "details";
pub const NETWORK: &str = "network";
@@ -153,13 +153,20 @@ pub trait CosmWasmClient: TendermintRpcClient {
let req = QueryAllBalancesRequest {
address: address.to_string(),
pagination,
resolve_denom: false,
};
let mut res = self
.make_abci_query::<_, QueryAllBalancesResponse>(path.clone(), req)
.await?;
let early_break = res.balances.is_empty();
raw_balances.append(&mut res.balances);
if early_break {
break;
}
if let Some(next_key) = next_page_key(res.pagination) {
pagination = Some(create_pagination(next_key))
} else {
@@ -187,7 +194,13 @@ pub trait CosmWasmClient: TendermintRpcClient {
.make_abci_query::<_, QueryTotalSupplyResponse>(path.clone(), req)
.await?;
let early_break = res.supply.is_empty();
supply.append(&mut res.supply);
if early_break {
break;
}
if let Some(next_key) = next_page_key(res.pagination) {
pagination = Some(create_pagination(next_key))
} else {
@@ -328,7 +341,13 @@ pub trait CosmWasmClient: TendermintRpcClient {
.make_abci_query::<_, QueryCodesResponse>(path.clone(), req)
.await?;
let early_break = res.code_infos.is_empty();
raw_codes.append(&mut res.code_infos);
if early_break {
break;
}
if let Some(next_key) = next_page_key(res.pagination) {
pagination = Some(create_pagination(next_key))
} else {
@@ -373,7 +392,13 @@ pub trait CosmWasmClient: TendermintRpcClient {
.make_abci_query::<_, QueryContractsByCodeResponse>(path.clone(), req)
.await?;
let early_break = res.contracts.is_empty();
raw_contracts.append(&mut res.contracts);
if early_break {
break;
}
if let Some(next_key) = next_page_key(res.pagination) {
pagination = Some(create_pagination(next_key))
} else {
@@ -429,7 +454,13 @@ pub trait CosmWasmClient: TendermintRpcClient {
.make_abci_query::<_, QueryContractHistoryResponse>(path.clone(), req)
.await?;
let early_break = res.entries.is_empty();
raw_entries.append(&mut res.entries);
if early_break {
break;
}
if let Some(next_key) = next_page_key(res.pagination) {
pagination = Some(create_pagination(next_key))
} else {
@@ -4,9 +4,11 @@
use crate::rpc::TendermintRpcClient;
use async_trait::async_trait;
use base64::Engine;
use cosmrs::tendermint;
use cosmrs::tendermint::{block::Height, evidence::Evidence, Hash};
use reqwest::header::HeaderMap;
use reqwest::{header, RequestBuilder};
use tendermint_rpc::dialect::{v0_34, v0_37, v0_38, LatestDialect};
use tendermint_rpc::{
client::CompatMode,
dialect::{self, Dialect},
@@ -21,8 +23,21 @@ macro_rules! perform_with_compat {
($self:expr, $request:expr) => {{
let request = $request;
match $self.compat {
CompatMode::V0_37 => $self.perform_v0_37(request).await,
CompatMode::V0_34 => $self.perform_v0_34(request).await,
CompatMode::V0_38 => {
$self
.perform_request_with_dialect(request, dialect::v0_38::Dialect)
.await
}
CompatMode::V0_37 => {
$self
.perform_request_with_dialect(request, dialect::v0_37::Dialect)
.await
}
CompatMode::V0_34 => {
$self
.perform_request_with_dialect(request, dialect::v0_34::Dialect)
.await
}
}
}};
}
@@ -70,7 +85,11 @@ impl ReqwestRpcClient {
.headers(headers)
}
async fn perform_request<R, S>(&self, request: R) -> Result<R::Output, Error>
async fn perform_request_with_dialect<R, S>(
&self,
request: R,
_dialect: S,
) -> Result<R::Output, Error>
where
R: SimpleRequest<S>,
S: Dialect,
@@ -81,26 +100,25 @@ impl ReqwestRpcClient {
.send()
.await
.map_err(TendermintRpcErrorMap::into_rpc_err)?;
let response_status = response.status();
let bytes = response
.bytes()
.await
.map_err(TendermintRpcErrorMap::into_rpc_err)?;
// Successful JSON-RPC requests are expected to return a 200 OK HTTP status.
// Otherwise, this means that the HTTP request failed as a whole,
// as opposed to the JSON-RPC request returning an error,
// and we cannot expect the response body to be a valid JSON-RPC response.
if response_status != reqwest::StatusCode::OK {
// hehe, that's so nasty but we have to somehow convert between different versions of the same lib
return Err(Error::http_request_failed(
response_status.as_u16().try_into().unwrap(),
));
}
R::Response::from_string(bytes).map(Into::into)
}
async fn perform_v0_34<R>(&self, request: R) -> Result<R::Output, Error>
where
R: SimpleRequest<dialect::v0_34::Dialect>,
{
self.perform_request(request).await
}
async fn perform_v0_37<R>(&self, request: R) -> Result<R::Output, Error>
where
R: SimpleRequest<dialect::v0_37::Dialect>,
{
self.perform_request(request).await
}
}
trait TendermintRpcErrorMap {
@@ -120,18 +138,50 @@ impl TendermintRpcClient for ReqwestRpcClient {
where
R: SimpleRequest,
{
self.perform_request(request).await
self.perform_request_with_dialect(request, LatestDialect)
.await
}
async fn block_results<H>(&self, height: H) -> Result<block_results::Response, Error>
async fn block<H>(&self, height: H) -> Result<endpoint::block::Response, Error>
where
H: Into<Height> + Send,
{
perform_with_compat!(self, block_results::Request::new(height.into()))
perform_with_compat!(self, endpoint::block::Request::new(height.into()))
}
async fn latest_block_results(&self) -> Result<block_results::Response, Error> {
perform_with_compat!(self, block_results::Request::default())
async fn block_by_hash(
&self,
hash: tendermint::Hash,
) -> Result<endpoint::block_by_hash::Response, Error> {
perform_with_compat!(self, endpoint::block_by_hash::Request::new(hash))
}
async fn latest_block(&self) -> Result<endpoint::block::Response, Error> {
perform_with_compat!(self, endpoint::block::Request::default())
}
async fn block_results<H>(&self, height: H) -> Result<endpoint::block_results::Response, Error>
where
H: Into<Height> + Send,
{
perform_with_compat!(self, endpoint::block_results::Request::new(height.into()))
}
async fn latest_block_results(&self) -> Result<endpoint::block_results::Response, Error> {
perform_with_compat!(self, endpoint::block_results::Request::default())
}
async fn block_search(
&self,
query: Query,
page: u32,
per_page: u8,
order: Order,
) -> Result<endpoint::block_search::Response, Error> {
perform_with_compat!(
self,
endpoint::block_search::Request::new(query, page, per_page, order)
)
}
async fn header<H>(&self, height: H) -> Result<endpoint::header::Response, Error>
@@ -140,11 +190,26 @@ impl TendermintRpcClient for ReqwestRpcClient {
{
let height = height.into();
match self.compat {
CompatMode::V0_37 => self.perform(endpoint::header::Request::new(height)).await,
CompatMode::V0_38 => {
self.perform_request_with_dialect(
endpoint::header::Request::new(height),
v0_38::Dialect,
)
.await
}
CompatMode::V0_37 => {
self.perform_request_with_dialect(
endpoint::header::Request::new(height),
v0_37::Dialect,
)
.await
}
CompatMode::V0_34 => {
// Back-fill with a request to /block endpoint and
// taking just the header from the response.
let resp = self.perform_v0_34(block::Request::new(height)).await?;
let resp = self
.perform_request_with_dialect(block::Request::new(height), v0_34::Dialect)
.await?;
Ok(resp.into())
}
}
@@ -152,12 +217,25 @@ impl TendermintRpcClient for ReqwestRpcClient {
async fn header_by_hash(&self, hash: Hash) -> Result<header_by_hash::Response, Error> {
match self.compat {
CompatMode::V0_37 => self.perform(header_by_hash::Request::new(hash)).await,
CompatMode::V0_38 => {
self.perform_request_with_dialect(
header_by_hash::Request::new(hash),
v0_38::Dialect,
)
.await
}
CompatMode::V0_37 => {
self.perform_request_with_dialect(
header_by_hash::Request::new(hash),
v0_37::Dialect,
)
.await
}
CompatMode::V0_34 => {
// Back-fill with a request to /block_by_hash endpoint and
// taking just the header from the response.
let resp = self
.perform_v0_34(block_by_hash::Request::new(hash))
.perform_request_with_dialect(block_by_hash::Request::new(hash), v0_34::Dialect)
.await?;
Ok(resp.into())
}
@@ -167,8 +245,18 @@ impl TendermintRpcClient for ReqwestRpcClient {
/// `/broadcast_evidence`: broadcast an evidence.
async fn broadcast_evidence(&self, e: Evidence) -> Result<evidence::Response, Error> {
match self.compat {
CompatMode::V0_37 => self.perform(evidence::Request::new(e)).await,
CompatMode::V0_34 => self.perform_v0_34(evidence::Request::new(e)).await,
CompatMode::V0_38 => {
self.perform_request_with_dialect(evidence::Request::new(e), v0_38::Dialect)
.await
}
CompatMode::V0_37 => {
self.perform_request_with_dialect(evidence::Request::new(e), v0_37::Dialect)
.await
}
CompatMode::V0_34 => {
self.perform_request_with_dialect(evidence::Request::new(e), v0_34::Dialect)
.await
}
}
}
@@ -13,6 +13,7 @@ cosmwasm-std = { workspace = true }
cosmwasm-schema = { workspace = true }
cw-storage-plus = { workspace = true }
schemars = { workspace = true }
utoipa = { workspace = true, optional = true }
serde = { workspace = true, features = ["derive"] }
thiserror = { workspace = true }
@@ -23,4 +24,5 @@ serde_json = { workspace = true }
vergen = { workspace = true, features = ["build", "git", "gitcl", "rustc", "cargo"] }
[features]
naive_float = []
naive_float = []
utoipa = ["dep:utoipa"]
@@ -221,6 +221,7 @@ fn default_unknown() -> String {
// TODO: there's no reason this couldn't be used for proper binaries, but in that case
// perhaps the struct should get renamed and moved to a "more" common crate
#[cw_serde]
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
pub struct ContractBuildInformation {
/// Provides the name of the binary, i.e. the content of `CARGO_PKG_NAME` environmental variable.
#[serde(default = "default_unknown")]
@@ -42,9 +42,11 @@ pub struct Gateway {
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
pub struct GatewayBond {
/// Original amount pledged by the operator of this node.
#[cfg_attr(feature = "utoipa", schema(value_type = crate::CoinSchema))]
pub pledge_amount: Coin,
/// Address of the owner of this gateway.
#[cfg_attr(feature = "utoipa", schema(value_type = String))]
pub owner: Addr,
/// Block height at which this gateway has been bonded.
@@ -55,6 +57,7 @@ pub struct GatewayBond {
/// Entity who bonded this gateway on behalf of the owner.
/// If exists, it's most likely the address of the vesting contract.
#[cfg_attr(feature = "utoipa", schema(value_type = String))]
pub proxy: Option<Addr>,
}
@@ -82,20 +82,25 @@ impl MixNodeDetails {
// currently this struct is shared between mixnodes and nymnodes
#[cw_serde]
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
pub struct NodeRewarding {
/// Information provided by the operator that influence the cost function.
pub cost_params: NodeCostParams,
/// Total pledge and compounded reward earned by the node operator.
#[cfg_attr(feature = "utoipa", schema(value_type = String))]
pub operator: Decimal,
/// Total delegation and compounded reward earned by all node delegators.
#[cfg_attr(feature = "utoipa", schema(value_type = String))]
pub delegates: Decimal,
/// Cumulative reward earned by the "unit delegation" since the block 0.
#[cfg_attr(feature = "utoipa", schema(value_type = String))]
pub total_unit_reward: Decimal,
/// Value of the theoretical "unit delegation" that has delegated to this node at block 0.
#[cfg_attr(feature = "utoipa", schema(value_type = String))]
pub unit_delegation: Decimal,
/// Marks the epoch when this node was last rewarded so that we wouldn't accidentally attempt
@@ -492,14 +497,17 @@ impl NodeRewarding {
::cosmwasm_schema::schemars::JsonSchema,
)]
#[schemars(crate = "::cosmwasm_schema::schemars")]
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
pub struct MixNodeBond {
/// Unique id assigned to the bonded mixnode.
pub mix_id: NodeId,
/// Address of the owner of this mixnode.
#[cfg_attr(feature = "utoipa", schema(value_type = String))]
pub owner: Addr,
/// Original amount pledged by the operator of this node.
#[cfg_attr(feature = "utoipa", schema(value_type = crate::CoinSchema))]
pub original_pledge: Coin,
// REMOVED (but might be needed due to legacy things, idk yet)
@@ -510,6 +518,7 @@ pub struct MixNodeBond {
/// Entity who bonded this mixnode on behalf of the owner.
/// If exists, it's most likely the address of the vesting contract.
#[cfg_attr(feature = "utoipa", schema(value_type = Option<String>))]
pub proxy: Option<Addr>,
/// Block height at which this mixnode has been bonded.
@@ -545,6 +554,7 @@ impl MixNodeBond {
feature = "generate-ts",
ts(export, export_to = "ts-packages/types/src/types/rust/Mixnode.ts")
)]
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
pub struct MixNode {
/// Network address of this mixnode, for example 1.1.1.1 or foo.mixnode.com
pub host: String,
@@ -571,11 +581,14 @@ pub struct MixNode {
/// The cost parameters, or the cost function, defined for the particular mixnode that influences
/// how the rewards should be split between the node operator and its delegators.
#[cw_serde]
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
pub struct NodeCostParams {
/// The profit margin of the associated node, i.e. the desired percent of the reward to be distributed to the operator.
#[cfg_attr(feature = "utoipa", schema(value_type = String))]
pub profit_margin_percent: Percent,
/// Operating cost of the associated node per the entire interval.
#[cfg_attr(feature = "utoipa", schema(value_type = crate::CoinSchema))]
pub interval_operating_cost: Coin,
}
@@ -680,7 +693,9 @@ pub struct PendingMixNodeChanges {
}
#[derive(Default, Copy, Clone, Debug, Serialize, Deserialize, JsonSchema)]
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
pub struct LegacyPendingMixNodeChanges {
#[cfg_attr(feature = "utoipa", schema(value_type = Option<u32>))]
pub pledge_change: Option<EpochEventId>,
}
@@ -863,11 +863,4 @@ pub enum QueryMsg {
pub struct MigrateMsg {
pub unsafe_skip_state_updates: Option<bool>,
pub vesting_contract_address: Option<String>,
pub current_nym_node_semver: String,
#[serde(default)]
pub version_score_weights: OutdatedVersionWeights,
#[serde(default)]
pub version_score_params: VersionScoreFormulaParams,
}
@@ -113,6 +113,10 @@ impl Role {
pub fn is_standby(&self) -> bool {
matches!(self, Role::Standby)
}
pub fn is_mixnode(&self) -> bool {
matches!(self, Role::Layer1 | Role::Layer2 | Role::Layer3)
}
}
impl Display for Role {
@@ -231,6 +235,7 @@ pub struct RoleMetadata {
/// Full details associated with given node.
#[cw_serde]
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
pub struct NymNodeDetails {
/// Basic bond information of this node, such as owner address, original pledge, etc.
pub bond_information: NymNodeBond,
@@ -288,14 +293,19 @@ impl NymNodeDetails {
}
#[cw_serde]
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
pub struct NymNodeBond {
/// Unique id assigned to the bonded node.
#[cfg_attr(feature = "utoipa", schema(value_type = u32))]
pub node_id: NodeId,
/// Address of the owner of this nym-node.
#[cfg_attr(feature = "utoipa", schema(value_type = String))]
pub owner: Addr,
/// Original amount pledged by the operator of this node.
#[cfg_attr(feature = "utoipa", schema(value_type = crate::CoinSchema))]
pub original_pledge: Coin,
/// Block height at which this nym-node has been bonded.
@@ -348,6 +358,7 @@ impl NymNodeBond {
feature = "generate-ts",
ts(export, export_to = "ts-packages/types/src/types/rust/NymNode.ts")
)]
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
pub struct NymNode {
/// Network address of this nym-node, for example 1.1.1.1 or foo.mixnode.com
/// that is used to discover other capabilities of this node.
@@ -358,6 +369,7 @@ pub struct NymNode {
pub custom_http_port: Option<u16>,
/// Base58-encoded ed25519 EdDSA public key.
#[cfg_attr(feature = "utoipa", schema(value_type = String))]
pub identity_key: IdentityKey,
// TODO: I don't think we want to include sphinx keys here,
// given we want to rotate them and keeping that in sync with contract will be a PITA
@@ -435,8 +447,11 @@ pub struct NodeConfigUpdate {
export_to = "ts-packages/types/src/types/rust/PendingNodeChanges.ts"
)
)]
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
pub struct PendingNodeChanges {
#[cfg_attr(feature = "utoipa", schema(value_type = Option<u32>))]
pub pledge_change: Option<EpochEventId>,
#[cfg_attr(feature = "utoipa", schema(value_type = Option<u32>))]
pub cost_params_change: Option<IntervalEventId>,
}
@@ -21,31 +21,37 @@ pub type WorkFactor = Decimal;
)]
#[cw_serde]
#[derive(Copy)]
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
pub struct IntervalRewardParams {
/// Current value of the rewarding pool.
/// It is expected to be constant throughout the interval.
#[cfg_attr(feature = "generate-ts", ts(type = "string"))]
#[cfg_attr(feature = "utoipa", schema(value_type = String))]
pub reward_pool: Decimal,
/// Current value of the staking supply.
/// It is expected to be constant throughout the interval.
#[cfg_attr(feature = "generate-ts", ts(type = "string"))]
#[cfg_attr(feature = "utoipa", schema(value_type = String))]
pub staking_supply: Decimal,
/// Defines the percentage of stake needed to reach saturation for all of the nodes in the rewarded set.
/// Also known as `beta`.
#[cfg_attr(feature = "generate-ts", ts(type = "string"))]
#[cfg_attr(feature = "utoipa", schema(value_type = String))]
pub staking_supply_scale_factor: Percent,
// computed values
/// Current value of the computed reward budget per epoch, per node.
/// It is expected to be constant throughout the interval.
#[cfg_attr(feature = "generate-ts", ts(type = "string"))]
#[cfg_attr(feature = "utoipa", schema(value_type = String))]
pub epoch_reward_budget: Decimal,
/// Current value of the stake saturation point.
/// It is expected to be constant throughout the interval.
#[cfg_attr(feature = "generate-ts", ts(type = "string"))]
#[cfg_attr(feature = "utoipa", schema(value_type = String))]
pub stake_saturation_point: Decimal,
// constants(-ish)
@@ -54,6 +60,7 @@ pub struct IntervalRewardParams {
/// It is not really expected to be changing very often.
/// As a matter of fact, unless there's a very specific reason, it should remain constant.
#[cfg_attr(feature = "generate-ts", ts(type = "string"))]
#[cfg_attr(feature = "utoipa", schema(value_type = String))]
pub sybil_resistance: Percent,
// default: 10
@@ -61,6 +68,7 @@ pub struct IntervalRewardParams {
/// It is not really expected to be changing very often.
/// As a matter of fact, unless there's a very specific reason, it should remain constant.
#[cfg_attr(feature = "generate-ts", ts(type = "string"))]
#[cfg_attr(feature = "utoipa", schema(value_type = String))]
pub active_set_work_factor: Decimal,
// default: 2%
@@ -70,6 +78,7 @@ pub struct IntervalRewardParams {
/// It is not really expected to be changing very often.
/// As a matter of fact, unless there's a very specific reason, it should remain constant.
#[cfg_attr(feature = "generate-ts", ts(type = "string"))]
#[cfg_attr(feature = "utoipa", schema(value_type = String))]
pub interval_pool_emission: Percent,
}
@@ -90,6 +99,7 @@ impl IntervalRewardParams {
)]
#[cw_serde]
#[derive(Copy)]
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
pub struct RewardingParams {
/// Parameters that should remain unchanged throughout an interval.
pub interval: IntervalRewardParams,
@@ -254,6 +264,7 @@ impl RewardingParams {
)]
#[cw_serde]
#[derive(Copy)]
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
pub struct RewardedSetParams {
/// The expected number of nodes assigned entry gateway role (i.e. [`Role::EntryGateway`])
pub entry_gateways: u32,
@@ -17,10 +17,12 @@ pub mod simulator;
)]
#[cw_serde]
#[derive(Copy, Default)]
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
pub struct RewardEstimate {
/// The amount of **decimal** coins that are going to get distributed to the node,
/// i.e. the operator and all its delegators.
#[cfg_attr(feature = "generate-ts", ts(type = "string"))]
#[cfg_attr(feature = "utoipa", schema(value_type = String))]
pub total_node_reward: Decimal,
// note that operator reward includes the operating_cost,
@@ -28,14 +30,17 @@ pub struct RewardEstimate {
// in that case the operator reward would still be `1nym` as opposed to 0
/// The share of the reward that is going to get distributed to the node operator.
#[cfg_attr(feature = "generate-ts", ts(type = "string"))]
#[cfg_attr(feature = "utoipa", schema(value_type = String))]
pub operator: Decimal,
/// The share of the reward that is going to get distributed among the node delegators.
#[cfg_attr(feature = "generate-ts", ts(type = "string"))]
#[cfg_attr(feature = "utoipa", schema(value_type = String))]
pub delegates: Decimal,
/// The operating cost of this node. Note: it's already included in the operator reward.
#[cfg_attr(feature = "generate-ts", ts(type = "string"))]
#[cfg_attr(feature = "utoipa", schema(value_type = String))]
pub operating_cost: Decimal,
}
@@ -175,6 +175,14 @@ where
}
}
#[cfg(feature = "utoipa")]
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
#[cfg_attr(feature = "utoipa", schema(title = "Coin"))]
pub struct CoinSchema {
pub denom: String,
pub amount: String,
}
/// The current state of the mixnet contract.
#[cw_serde]
pub struct ContractState {
@@ -8,81 +8,81 @@ use thiserror::Error;
#[derive(Error, Debug, PartialEq)]
pub enum VestingContractError {
#[error("VESTING ({}): {0}", line!())]
#[error("VESTING ({l}): {0}", l = line!())]
Std(#[from] StdError),
#[error("VESTING: {0}")]
OverflowError(#[from] OverflowError),
#[error("VESTING ({}): Account does not exist - {0}", line!())]
#[error("VESTING ({l}): Account does not exist - {0}", l = line!())]
NoAccountForAddress(String),
#[error("VESTING ({}): Only admin can perform this action, {0} is not admin", line!())]
#[error("VESTING ({l}): Only admin can perform this action, {0} is not admin", l = line!())]
NotAdmin(String),
#[error("VESTING ({}): Balance not found for existing account ({0}), this is a bug", line!())]
#[error("VESTING ({l}): Balance not found for existing account ({0}), this is a bug", l = line!())]
NoBalanceForAddress(String),
#[error("VESTING ({}): Insufficient balance for address {0} -> {1}", line!())]
#[error("VESTING ({l}): Insufficient balance for address {0} -> {1}", l = line!())]
InsufficientBalance(String, u128),
#[error("VESTING ({}): Insufficient spendable balance for address {0} -> {1}", line!())]
#[error("VESTING ({l}): Insufficient spendable balance for address {0} -> {1}", l = line!())]
InsufficientSpendable(String, u128),
#[error(
"VESTING ({}):Only delegation owner can perform delegation actions, {0} is not the delegation owner"
, line!())]
"VESTING ({l}):Only delegation owner can perform delegation actions, {0} is not the delegation owner"
, l = line!())]
NotDelegate(String),
#[error("VESTING ({}): Total vesting amount is inprobably low -> {0}, this is likely an error", line!())]
#[error("VESTING ({l}): Total vesting amount is inprobably low -> {0}, this is likely an error", l = line!())]
ImprobableVestingAmount(u128),
#[error("VESTING ({}): Address {0} has already bonded a node", line!())]
#[error("VESTING ({l}): Address {0} has already bonded a node", l = line!())]
AlreadyBonded(String),
#[error("VESTING ({}): Received empty funds vector", line!())]
#[error("VESTING ({l}): Received empty funds vector", l = line!())]
EmptyFunds,
#[error("VESTING ({}): Received wrong denom: {0}, expected {1}", line!())]
#[error("VESTING ({l}): Received wrong denom: {0}, expected {1}", l = line!())]
WrongDenom(String, String),
#[error("VESTING ({}): Received multiple denoms, expected 1", line!())]
#[error("VESTING ({l}): Received multiple denoms, expected 1", l = line!())]
MultipleDenoms,
#[error("VESTING ({}): No delegations found for account {0}, mix_identity {1}", line!())]
#[error("VESTING ({l}): No delegations found for account {0}, mix_identity {1}", l = line!())]
NoSuchDelegation(Addr, NodeId),
#[error("VESTING ({}): Only mixnet contract can perform this operation, got {0}", line!())]
#[error("VESTING ({l}): Only mixnet contract can perform this operation, got {0}", l = line!())]
NotMixnetContract(Addr),
#[error("VESTING ({}): Calculation underflowed", line!())]
#[error("VESTING ({l}): Calculation underflowed", l = line!())]
Underflow,
#[error("VESTING ({}): No bond found for account {0}", line!())]
#[error("VESTING ({l}): No bond found for account {0}", l = line!())]
NoBondFound(String),
#[error("VESTING: Attempted to reduce mixnode bond pledge below zero! The current pledge is {current} and we attempted to reduce it by {decrease_by}.")]
InvalidBondPledgeReduction { current: Coin, decrease_by: Coin },
#[error("VESTING ({}): Action can only be executed by account owner -> {0}", line!())]
#[error("VESTING ({l}): Action can only be executed by account owner -> {0}", l = line!())]
NotOwner(String),
#[error("VESTING ({}): Invalid address: {0}", line!())]
#[error("VESTING ({l}): Invalid address: {0}", l = line!())]
InvalidAddress(String),
#[error("VESTING ({}): Account already exists: {0}", line!())]
#[error("VESTING ({l}): Account already exists: {0}", l = line!())]
AccountAlreadyExists(String),
#[error("VESTING ({}): Staking account already exists: {0}", line!())]
#[error("VESTING ({l}): Staking account already exists: {0}", l = line!())]
StakingAccountAlreadyExists(String),
#[error("VESTING ({}): Too few coins sent for vesting account creation, sent {sent}, need at least {need}", line!())]
#[error("VESTING ({l}): Too few coins sent for vesting account creation, sent {sent}, need at least {need}", l = line!())]
MinVestingFunds { sent: u128, need: u128 },
#[error("VESTING ({}): Maximum amount of locked coins has already been pledged: {current}, cap is {cap}", line!())]
#[error("VESTING ({l}): Maximum amount of locked coins has already been pledged: {current}, cap is {cap}", l = line!())]
LockedPledgeCapReached { current: Uint128, cap: Uint128 },
#[error("VESTING: ({}: Account owned by {owner} has unpopulated vesting periods!", line!())]
#[error("VESTING: ({l}: Account owned by {owner} has unpopulated vesting periods!", l = line!())]
UnpopulatedVestingPeriods { owner: Addr },
#[error("VESTING: Vesting account associated with {0} already exists, only addresses with not existing vesting accounts can be added as staking addresses")]
+1 -1
View File
@@ -19,7 +19,7 @@ use std::error::Error;
// `SELECT total_tickets, used_tickets FROM ecash_ticketbook WHERE expiration_date >= ?`, today_date
// then for each calculate the diff total_tickets - used_tickets and multiply the result by the size of the ticket
#[async_trait]
pub trait Storage: Send + Sync {
pub trait Storage: Clone + Send + Sync {
type StorageError: Error;
async fn close(&self);
@@ -26,7 +26,6 @@ nym-api-requests = { path = "../../nym-api/nym-api-requests" }
nym-credentials = { path = "../credentials" }
nym-credentials-interface = { path = "../credentials-interface" }
nym-ecash-contract-common = { path = "../cosmwasm-smart-contracts/ecash-contract" }
nym-ecash-double-spending = { path = "../ecash-double-spending" }
nym-gateway-requests = { path = "../gateway-requests" }
nym-gateway-storage = { path = "../gateway-storage" }
nym-task = { path = "../task" }
@@ -13,6 +13,7 @@ use nym_api_requests::constants::MIN_BATCH_REDEMPTION_DELAY;
use nym_api_requests::ecash::models::{BatchRedeemTicketsBody, VerifyEcashTicketBody};
use nym_credentials_interface::Bandwidth;
use nym_credentials_interface::{ClientTicket, TicketType};
use nym_validator_client::coconut::EcashApiError;
use nym_validator_client::nym_api::EpochId;
use nym_validator_client::nyxd::contract_traits::{
EcashSigningClient, MultisigQueryClient, MultisigSigningClient, PagedMultisigQueryClient,
@@ -352,7 +353,9 @@ impl CredentialHandler {
}
Err(err) => {
error!("failed to send ticket {ticket_id} for verification to ecash signer '{client}': {err}. if we don't reach quorum, we'll retry later");
Ok(false)
Err(EcashTicketError::ApiFailure(EcashApiError::NymApi {
source: err,
}))
}
}
}
+1
View File
@@ -16,6 +16,7 @@ serde = { workspace = true, features = ["derive"] }
thiserror = { workspace = true }
strum = { workspace = true, features = ["derive"] }
time = { workspace = true, features = ["serde"] }
utoipa = { workspace = true }
rand = { workspace = true }
nym-compact-ecash = { path = "../nym_offline_compact_ecash" }
-14
View File
@@ -1,14 +0,0 @@
[package]
name = "nym-ecash-double-spending"
version = "0.1.0"
authors.workspace = true
repository.workspace = true
homepage.workspace = true
documentation.workspace = true
edition.workspace = true
license.workspace = true
[dependencies]
bit-vec = { workspace = true }
bloomfilter = { workspace = true }
nym-network-defaults = { path = "../network-defaults" }
-136
View File
@@ -1,136 +0,0 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use bit_vec::BitVec;
use bloomfilter::Bloom;
use nym_network_defaults::{BloomfilterParameters, ECASH_DS_BLOOMFILTER_PARAMS};
pub struct DoubleSpendingFilter {
params: BloomfilterParameters,
inner: Bloom<Vec<u8>>,
}
impl Default for DoubleSpendingFilter {
fn default() -> Self {
DoubleSpendingFilter::new_empty_ecash()
}
}
pub fn bloom_from_params<T>(params: &BloomfilterParameters, bitvec: BitVec) -> Bloom<Vec<T>> {
assert_eq!(params.bitmap_size, bitvec.len() as u64);
Bloom::from_bit_vec(
bitvec,
params.bitmap_size,
params.num_hashes,
params.sip_keys,
)
}
impl DoubleSpendingFilter {
pub fn new_empty(params: BloomfilterParameters) -> Self {
let bitvec = BitVec::from_elem(params.bitmap_size as usize, false);
DoubleSpendingFilter {
inner: bloom_from_params(&params, bitvec),
params,
}
}
pub fn params(&self) -> BloomfilterParameters {
self.params
}
pub fn rebuild(&self) -> DoubleSpendingFilterBuilder {
DoubleSpendingFilterBuilder::new(self.params)
}
pub fn reset(&mut self) {
self.inner.clear()
}
pub fn new_empty_ecash() -> Self {
DoubleSpendingFilter::new_empty(ECASH_DS_BLOOMFILTER_PARAMS)
}
pub fn builder(params: BloomfilterParameters) -> DoubleSpendingFilterBuilder {
DoubleSpendingFilterBuilder::new(params)
}
pub fn from_bytes(params: BloomfilterParameters, bitmap: &[u8]) -> Self {
DoubleSpendingFilter {
inner: bloom_from_params(&params, BitVec::from_bytes(bitmap)),
params,
}
}
pub fn replace_bitvec(&mut self, new: BitVec) {
self.inner = bloom_from_params(&self.params, new)
}
pub fn dump_bitmap(&self) -> Vec<u8> {
self.inner.bitmap()
}
pub fn set(&mut self, b: &Vec<u8>) {
self.inner.set(b);
}
pub fn check(&self, b: &Vec<u8>) -> bool {
self.inner.check(b)
}
}
pub struct DoubleSpendingFilterBuilder {
params: BloomfilterParameters,
bit_vec_builder: Option<BitVecBuilder>,
}
impl DoubleSpendingFilterBuilder {
pub fn new(params: BloomfilterParameters) -> Self {
DoubleSpendingFilterBuilder {
params,
bit_vec_builder: None,
}
}
pub fn add_bytes(&mut self, b: &[u8]) -> bool {
match &mut self.bit_vec_builder {
None => {
self.bit_vec_builder = Some(BitVecBuilder::new(b));
true
}
Some(builder) => builder.add_bytes(b),
}
}
pub fn build(self) -> DoubleSpendingFilter {
match self.bit_vec_builder {
None => DoubleSpendingFilter::new_empty(self.params),
Some(builder) => DoubleSpendingFilter {
inner: bloom_from_params(&self.params, builder.finish()),
params: self.params,
},
}
}
}
pub struct BitVecBuilder(BitVec);
impl BitVecBuilder {
pub fn new(initial_bitmap: &[u8]) -> Self {
BitVecBuilder(BitVec::from_bytes(initial_bitmap))
}
pub fn add_bytes(&mut self, b: &[u8]) -> bool {
let add = BitVec::from_bytes(b);
if self.0.len() != add.len() {
return false;
}
self.0.or(&add);
true
}
pub fn finish(self) -> BitVec {
self.0
}
}
@@ -86,7 +86,6 @@ impl Display for AddressPolicyAction {
/// ```
#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq)]
#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
#[cfg_attr(feature = "openapi", aliases(ExitPolicy))]
pub struct AddressPolicy {
/// A list of rules to apply to find out whether an address is
/// contained by this policy.
@@ -727,10 +726,10 @@ mod test {
let policy = AddressPolicy::parse_from_torrc(
r#"
ExitPolicy reject 1.2.3.4/32:*
ExitPolicy reject 1.2.3.5:*
ExitPolicy reject 1.2.3.5:*
ExitPolicy reject 1.2.3.6/16:*
ExitPolicy reject 1.2.3.6/16:123-456
ExitPolicy accept *:53
ExitPolicy reject 1.2.3.6/16:123-456
ExitPolicy accept *:53
ExitPolicy accept6 *6:119
ExitPolicy accept *4:120
ExitPolicy reject6 [FC00::]/7:*
+6 -6
View File
@@ -59,12 +59,12 @@ pub enum GatewayRequestsError {
source: NymNodeRoutingAddressError,
},
#[error("received request had invalid size. (actual: {0}, but expected one of: {} (ACK), {} (REGULAR), {}, {}, {} (EXTENDED))",
PacketSize::AckPacket.size(),
PacketSize::RegularPacket.size(),
PacketSize::ExtendedPacket8.size(),
PacketSize::ExtendedPacket16.size(),
PacketSize::ExtendedPacket32.size())
#[error("received request had invalid size. (actual: {0}, but expected one of: {a} (ACK), {r} (REGULAR), {e8}, {e16}, {e32} (EXTENDED))",
a = PacketSize::AckPacket.size(),
r = PacketSize::RegularPacket.size(),
e8 = PacketSize::ExtendedPacket8.size(),
e16 = PacketSize::ExtendedPacket16.size(),
e32 = PacketSize::ExtendedPacket32.size())
]
RequestOfInvalidSize(usize),
@@ -13,7 +13,7 @@ use std::str::FromStr;
use tungstenite::Message;
// wrapper for all encrypted requests for ease of use
#[derive(Serialize, Deserialize, Debug)]
#[derive(Serialize, Deserialize, Debug, Clone)]
#[non_exhaustive]
pub enum ClientRequest {
UpgradeKey {
-1
View File
@@ -11,7 +11,6 @@ license.workspace = true
[dependencies]
bincode = { workspace = true }
defguard_wireguard_rs = { workspace = true }
log = { workspace = true }
sqlx = { workspace = true, features = [
"runtime-tokio-rustls",
"sqlite",
@@ -0,0 +1,24 @@
/*
* Copyright 2025 - Nym Technologies SA <contact@nymtech.net>
* SPDX-License-Identifier: GPL-3.0-only
*/
ALTER TABLE message_store
RENAME TO message_store_old;
-- add new column with message timestamp.
-- note: we can't simply alter existing table to add it since the default value is non-constant
CREATE TABLE message_store
(
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
client_address_bs58 TEXT NOT NULL,
content BLOB NOT NULL,
timestamp TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP
);
INSERT INTO message_store(id, client_address_bs58, content)
SELECT id, client_address_bs58, content
FROM message_store_old;
DROP TABLE message_store_old;
+28 -39
View File
@@ -2,9 +2,11 @@
// SPDX-License-Identifier: GPL-3.0-only
use crate::models::StoredMessage;
use time::OffsetDateTime;
use tracing::debug;
#[derive(Clone)]
pub(crate) struct InboxManager {
pub struct InboxManager {
connection_pool: sqlx::SqlitePool,
/// Maximum number of messages that can be obtained from the database per operation.
/// It is used to prevent out of memory errors in the case of client receiving a lot of data while
@@ -71,44 +73,22 @@ impl InboxManager {
// get 1 additional message to check whether there will be more to grab
// next time
let limit = self.retrieval_limit + 1;
let mut res = if let Some(start_after) = start_after {
sqlx::query_as!(
StoredMessage,
r#"
SELECT
id as "id!",
client_address_bs58 as "client_address_bs58!",
content as "content!"
FROM message_store
WHERE client_address_bs58 = ? AND id > ?
ORDER BY id ASC
LIMIT ?;
"#,
client_address_bs58,
start_after,
limit
)
.fetch_all(&self.connection_pool)
.await?
} else {
sqlx::query_as!(
StoredMessage,
r#"
SELECT
id as "id!",
client_address_bs58 as "client_address_bs58!",
content as "content!"
FROM message_store
WHERE client_address_bs58 = ?
ORDER BY id ASC
LIMIT ?;
"#,
client_address_bs58,
limit
)
.fetch_all(&self.connection_pool)
.await?
};
let start_after = start_after.unwrap_or(-1);
let mut res: Vec<StoredMessage> = sqlx::query_as(
r#"
SELECT id, client_address_bs58, content, timestamp
FROM message_store
WHERE client_address_bs58 = ? AND id > ?
ORDER BY id ASC
LIMIT ?;
"#,
)
.bind(client_address_bs58)
.bind(start_after)
.bind(limit)
.fetch_all(&self.connection_pool)
.await?;
if res.len() > self.retrieval_limit as usize {
res.truncate(self.retrieval_limit as usize);
@@ -146,4 +126,13 @@ impl InboxManager {
.await?;
Ok(())
}
pub async fn remove_stale(&self, cutoff: OffsetDateTime) -> Result<(), sqlx::Error> {
let affected = sqlx::query!("DELETE FROM message_store WHERE timestamp < ?", cutoff)
.execute(&self.connection_pool)
.await?
.rows_affected();
debug!("Removed {affected} stale messages");
Ok(())
}
}
+2 -2
View File
@@ -3,7 +3,6 @@
use bandwidth::BandwidthManager;
use clients::{ClientManager, ClientType};
use inboxes::InboxManager;
use models::{
Client, PersistedBandwidth, PersistedSharedKeys, RedemptionProposal, StoredMessage,
VerifiedTicket, WireguardPeer,
@@ -31,6 +30,7 @@ mod tickets;
mod wireguard_peers;
pub use error::GatewayStorageError;
pub use inboxes::InboxManager;
// note that clone here is fine as upon cloning the same underlying pool will be used
#[derive(Clone)]
@@ -53,7 +53,7 @@ impl GatewayStorage {
&self.shared_key_manager
}
pub(crate) fn inbox_manager(&self) -> &InboxManager {
pub fn inbox_manager(&self) -> &InboxManager {
&self.inbox_manager
}
+2
View File
@@ -48,11 +48,13 @@ impl TryFrom<PersistedSharedKeys> for SharedGatewayKey {
}
}
#[derive(FromRow)]
pub struct StoredMessage {
pub id: i64,
#[allow(dead_code)]
pub client_address_bs58: String,
pub content: Vec<u8>,
pub timestamp: OffsetDateTime,
}
#[derive(Debug, Clone, FromRow)]
+7
View File
@@ -15,6 +15,7 @@ async-trait = { workspace = true }
reqwest = { workspace = true, features = ["json"] }
http.workspace = true
url = { workspace = true }
once_cell = { workspace = true }
serde = { workspace = true }
serde_json = { workspace = true }
thiserror = { workspace = true }
@@ -22,7 +23,13 @@ tracing = { workspace = true }
nym-bin-common = { path = "../bin-common" }
[target."cfg(not(target_arch = \"wasm32\"))".dependencies]
hickory-resolver = { workspace = true, features = ["dns-over-https-rustls", "webpki-roots"] }
# for request timeout until https://github.com/seanmonstar/reqwest/issues/1135 is fixed
[target."cfg(target_arch = \"wasm32\")".dependencies.wasmtimer]
workspace = true
features = ["tokio"]
[dev-dependencies]
tokio = { workspace = true, features=["rt", "macros"] }
+178
View File
@@ -0,0 +1,178 @@
//! DNS resolver configuration for internal lookups.
//!
//! The resolver itself is the set combination of the google, cloudflare, and quad9 endpoints
//! supporting DoH and DoT.
//!
//! This resolver implements a fallback mechanism where, should the DNS-over-TLS resolution fail, a
//! followup resolution will be done using the hosts configured default (e.g. `/etc/resolve.conf` on
//! linux).
//!
//! Requires the `dns-over-https-rustls`, `webpki-roots` feature for the
//! `hickory-resolver` crate
#![deny(missing_docs)]
use crate::ClientBuilder;
use std::{net::SocketAddr, sync::Arc};
use hickory_resolver::lookup_ip::LookupIp;
use hickory_resolver::{
config::{LookupIpStrategy, NameServerConfigGroup, ResolverConfig, ResolverOpts},
error::ResolveError,
lookup_ip::LookupIpIntoIter,
TokioAsyncResolver,
};
use once_cell::sync::OnceCell;
use reqwest::dns::{Addrs, Name, Resolve, Resolving};
use tracing::warn;
impl ClientBuilder {
/// Override the DNS resolver implementation used by the underlying http client.
pub fn dns_resolver<R: Resolve + 'static>(mut self, resolver: Arc<R>) -> Self {
self.reqwest_client_builder = self.reqwest_client_builder.dns_resolver(resolver);
self
}
}
struct SocketAddrs {
iter: LookupIpIntoIter,
}
#[derive(Debug, thiserror::Error)]
#[error("hickory-dns resolver error: {hickory_error}")]
/// Error occurring while resolving a hostname into an IP address.
pub struct HickoryDnsError {
#[from]
hickory_error: ResolveError,
}
/// Wrapper around an `AsyncResolver`, which implements the `Resolve` trait.
#[derive(Debug, Default, Clone)]
pub struct HickoryDnsResolver {
/// Since we might not have been called in the context of a
/// Tokio Runtime in initialization, so we must delay the actual
/// construction of the resolver.
state: Arc<OnceCell<TokioAsyncResolver>>,
fallback: Arc<OnceCell<TokioAsyncResolver>>,
}
impl Resolve for HickoryDnsResolver {
fn resolve(&self, name: Name) -> Resolving {
let resolver = self.state.clone();
let fallback = self.fallback.clone();
Box::pin(async move {
let resolver = resolver.get_or_try_init(new_resolver)?;
// try the primary DNS resolver that we set up (DoH or DoT or whatever)
let lookup = match resolver.lookup_ip(name.as_str()).await {
Ok(res) => res,
Err(e) => {
// on failure use the fall back system configured DNS resolver
warn!("primary DNS failed w/ error {e}: using system fallback");
let resolver = fallback.get_or_try_init(new_resolver_system)?;
resolver.lookup_ip(name.as_str()).await?
}
};
let addrs: Addrs = Box::new(SocketAddrs {
iter: lookup.into_iter(),
});
Ok(addrs)
})
}
}
impl Iterator for SocketAddrs {
type Item = SocketAddr;
fn next(&mut self) -> Option<Self::Item> {
self.iter.next().map(|ip_addr| SocketAddr::new(ip_addr, 0))
}
}
impl HickoryDnsResolver {
/// Attempt to resolve a domain name to a set of ['IpAddr']s
pub async fn resolve_str(&self, name: &str) -> Result<LookupIp, HickoryDnsError> {
let resolver = self.state.get_or_try_init(new_resolver)?;
// try the primary DNS resolver that we set up (DoH or DoT or whatever)
let lookup = match resolver.lookup_ip(name).await {
Ok(res) => res,
Err(e) => {
// on failure use the fall back system configured DNS resolver
warn!("primary DNS failed w/ error {e}: using system fallback");
let resolver = self.fallback.get_or_try_init(new_resolver_system)?;
resolver.lookup_ip(name).await?
}
};
Ok(lookup)
}
}
/// Create a new resolver with a custom DoT based configuration. The options are overridden to look
/// up for both IPv4 and IPv6 addresses to work with "happy eyeballs" algorithm.
fn new_resolver() -> Result<TokioAsyncResolver, HickoryDnsError> {
let mut name_servers = NameServerConfigGroup::google_tls();
name_servers.merge(NameServerConfigGroup::google_https());
// name_servers.merge(NameServerConfigGroup::google_h3());
name_servers.merge(NameServerConfigGroup::quad9_tls());
name_servers.merge(NameServerConfigGroup::quad9_https());
name_servers.merge(NameServerConfigGroup::cloudflare_tls());
name_servers.merge(NameServerConfigGroup::cloudflare_https());
let config = ResolverConfig::from_parts(None, Vec::new(), name_servers);
let mut opts = ResolverOpts::default();
opts.ip_strategy = LookupIpStrategy::Ipv4AndIpv6;
// Would like to enable this when 0.25 stabilizes
// opts.server_ordering_strategy = ServerOrderingStrategy::RoundRobin;
Ok(TokioAsyncResolver::tokio(config, opts))
}
/// Create a new resolver with the default configuration, which reads from the system DNS config
/// (i.e. `/etc/resolve.conf` in unix). The options are overridden to look up for both IPv4 and IPv6
/// addresses to work with "happy eyeballs" algorithm.
fn new_resolver_system() -> Result<TokioAsyncResolver, HickoryDnsError> {
let (config, mut opts) = hickory_resolver::system_conf::read_system_conf()?;
opts.ip_strategy = LookupIpStrategy::Ipv4AndIpv6;
Ok(TokioAsyncResolver::tokio(config, opts))
}
#[cfg(test)]
mod test {
use super::*;
#[tokio::test]
async fn reqwest_hickory_doh() {
let resolver = HickoryDnsResolver::default();
let client = reqwest::ClientBuilder::new()
.dns_resolver(resolver.into())
.build()
.unwrap();
let resp = client
.get("http://ifconfig.me:80")
.send()
.await
.unwrap()
.bytes()
.await
.unwrap();
assert!(!resp.is_empty());
}
#[tokio::test]
async fn dns_lookup() -> Result<(), HickoryDnsError> {
let resolver = HickoryDnsResolver::default();
let domain = "ifconfig.me";
let addrs = resolver.resolve_str(domain).await?;
assert!(addrs.into_iter().next().is_some());
Ok(())
}
}
+18 -5
View File
@@ -6,17 +6,23 @@ use reqwest::header::HeaderValue;
use reqwest::{RequestBuilder, Response, StatusCode};
use serde::de::DeserializeOwned;
use serde::{Deserialize, Serialize};
use std::fmt::Display;
use std::time::Duration;
use thiserror::Error;
use tracing::{instrument, warn};
use url::Url;
#[cfg(not(target_arch = "wasm32"))]
use std::sync::Arc;
use std::{fmt::Display, time::Duration};
pub use reqwest::IntoUrl;
mod user_agent;
pub use user_agent::UserAgent;
mod user_agent;
#[cfg(not(target_arch = "wasm32"))]
mod dns;
#[cfg(not(target_arch = "wasm32"))]
pub use dns::{HickoryDnsError, HickoryDnsResolver};
// The timeout is relatively high as we are often making requests over the mixnet, where latency is
// high and chatty protocols take a while to complete.
@@ -86,11 +92,18 @@ impl ClientBuilder {
// TODO: or should we maybe default to https?
Self::new(alt)
} else {
#[cfg(target_arch = "wasm32")]
let reqwest_client_builder = reqwest::ClientBuilder::new();
#[cfg(not(target_arch = "wasm32"))]
let reqwest_client_builder =
reqwest::ClientBuilder::new().dns_resolver(Arc::new(HickoryDnsResolver::default()));
Ok(ClientBuilder {
url: url.into_url()?,
timeout: None,
custom_user_agent: false,
reqwest_client_builder: reqwest::ClientBuilder::new(),
reqwest_client_builder,
})
}
}
@@ -755,7 +768,7 @@ where
E: DeserializeOwned + Display,
{
let status = res.status();
tracing::debug!("Status: {} (success: {})", &status, status.is_success());
tracing::trace!("Status: {} (success: {})", &status, status.is_success());
if !allow_empty {
if let Some(0) = res.content_length() {
-1
View File
@@ -10,7 +10,6 @@ use serde::{Deserialize, Serialize};
pub mod middleware;
#[derive(Debug, Clone)]
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
pub enum FormattedResponse<T> {
Json(Json<T>),
Yaml(Yaml<T>),
@@ -65,6 +65,14 @@ impl<T> NonExhaustiveDelayQueue<T> {
pub fn remove(&mut self, key: &QueueKey) -> Expired<T> {
self.inner.remove(key)
}
pub fn len(&self) -> usize {
self.inner.len()
}
pub fn is_empty(&self) -> bool {
self.inner.is_empty()
}
}
impl<T> Default for NonExhaustiveDelayQueue<T> {

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