Compare commits

...

110 Commits

Author SHA1 Message Date
jmwample ffabf06715 Cherry-pick from https://github.com/nymtech/nym/commit/f6846bf94a190baf07eec4edac9ddb3a34451d30 2025-05-16 18:20:18 +02:00
benedetta davico 22539c3e7d Update wallet mac runner 2025-04-01 15:41:12 +02:00
benedetta davico edde411568 Update publish-nym-wallet-macos.yml 2025-04-01 15:29:25 +02:00
benedetta davico 75f2fb7039 Update publish-nym-wallet-macos.yml 2025-04-01 12:14:48 +02:00
benedetta davico f768c8e8e2 Update publish-nym-wallet-ubuntu.yml 2025-04-01 12:14:12 +02:00
benedetta davico 200efebc37 Update publish-nym-wallet-win11.yml 2025-04-01 12:12:14 +02:00
benedettadavico a429d6528e bump wallet version 2025-04-01 11:41:15 +02:00
benedettadavico ebed210de2 update wallet changelog 2025-04-01 10:16:08 +02:00
benedettadavico f1d3c33391 Update changelog 2025-03-31 16:20:56 +02:00
benedettadavico 42fbb6684d update issued-ticketbook-count to be GET 2025-03-27 12:58:04 +01:00
Andrej Mihajlov 2f55c031da Remove Google public DNS (#5660) 2025-03-25 11:47:02 -06:00
benedettadavico a9eb6052ff bump binary versions 2025-03-25 11:41:30 +01:00
dynco-nym 3bc7ced2cf Remove UNIQUE constraint on node pubkey (#5649)
* Migration to remove UNIQUE constraint

* Don't remove old nodes

* Bump package version

* Update function name
2025-03-24 11:21:09 +01:00
Bogdan-Ștefan Neacşu 8abcc58055 Add fd callback for initial authentication (#5654) 2025-03-24 11:24:38 +02:00
Jon Häggblad 76ff03b248 Revert using AsyncWrite sink in IPR (#5656) 2025-03-24 10:19:04 +01:00
Tommy Verrall ccf3420aab Merge pull request #5653 from nymtech/feature/wallet-revamp
Wallet-revamp to be in line with new nym-theming
2025-03-21 14:02:22 +00:00
Jędrzej Stuczyński 5df76ea2a9 Feature/paginated ticketbooks challenge (#5619)
* change ticketbook data request to allow for pagination

* implemented api endpoints on nym-api side

* auxiliary nym-api queries for number of issued ticketbooks

* ensure that challenged issuers support new queries

* addeed persistent identity to the rewarder

* clippy

* stupid chrono feature workaround

* clippy

* debugging issuance verification

* remove redundant closure

* added a minimum issuance threshold
2025-03-21 13:44:25 +00:00
Jędrzej Stuczyński 33992542b1 feature: upgrade cosmwasm to 2.2 (#5479)
* updated contracts to cosmwasm2.2 and fixed build issues

* removed old coconut contract code + additional dkg fixes

* replace deprecated to_binary and from_binary functions

* mixnet contract tests compiling

some are failing due to incorrect addresses

* made other contract tests compile

* fixed remaining tests

* allow usage of manually dispatching contract replies

* nym-api test fixes

* removed old toolchain from contracts CI

* linter fixes

* regenerated contract schema

* fixed easy_addr

* further license fixes

* post rebase fixes + update to 2.2.2

* change ci runner

* minor CI adjustments

* change wallet CI to use node 20

* more CI changes...

* run cosmwasm-check against release contracts

* test ci changes

* wip...
2025-03-21 13:43:35 +00:00
Tommy Verrall a95ee3f334 wallet-revamp to be in line with new nym-theming
- updating colour pallete to match the nym.com sites
- used the same font too
- updated icons
2025-03-21 14:07:50 +01:00
Tommy Verrall 0a92f04048 Merge pull request #5652 from nymtech/feature/params
Update wallet to include Interval Operator Cost and Profit Margin
2025-03-21 12:08:19 +00:00
Tommy Verrall 368b105e27 few more broken links 2025-03-21 12:55:31 +01:00
Tommy Verrall 813cbda891 lint of delegations 2025-03-21 12:43:17 +01:00
Tommy Verrall a8af641ec4 fix up all broken links 2025-03-21 12:32:35 +01:00
Tommy Verrall f41a2d3a99 Update all deprecated links and use different explorers 2025-03-21 12:26:08 +01:00
Tommy Verrall a3b7cb52c9 Merge remote-tracking branch 'origin/feature/params' into feature/params 2025-03-21 11:54:57 +01:00
Tommy Verrall 60846b57f6 yarn linting 2025-03-21 11:54:44 +01:00
Jon Häggblad 8ed09d74b3 Add RUSTUP_PERMIT_COPY_RENAME to ci-lint-typescript 2025-03-21 11:39:58 +01:00
Tommy Verrall cd52bc577c Merge branch 'develop' into feature/params 2025-03-21 10:36:43 +00:00
Tommy Verrall ed021ff467 fix issues with profit margin throwing non required errors
- all is working
2025-03-21 11:26:45 +01:00
Tommy Verrall 4f67998127 adjust memo field again
- add additional warning about profit margin changing
2025-03-21 10:23:59 +01:00
Tommy Verrall d06a8e0b21 working with a few errors in the console at present
- successful blockchain txs though
2025-03-21 09:58:54 +01:00
dynco-nym 3f05c0d4b9 Add concurrency limit to CI (#5651) 2025-03-20 20:13:41 +01:00
Jon Häggblad 1a37e60483 Add max_retransmissions flag on each message (#5642) 2025-03-20 19:54:07 +01:00
Tommy Verrall 19775cf917 remove duplicate file
- simulated txs fee works
- now the method just needs to be called
2025-03-20 19:09:58 +01:00
Yana Matrosova 0abc07c96f Merge pull request #5636 from nymtech/BugFix/explorer_styling_broken
/ regenerated yarn.lock
2025-03-20 19:08:02 +02:00
Jędrzej Stuczyński fbfeacf539 fixed type conversion 2025-03-20 16:03:43 +00:00
Tommy Verrall e1583daaa3 no need for everything else 2025-03-20 16:43:31 +01:00
Tommy Verrall e904627513 operator interval cost and profit margin
- the submission to the chain probably needs changing to create a new nym-node rust type for updating the cost params
- a few things may been changing in terms of display and submission
- the simulate txs fee is failing - because i don't know what to put
2025-03-20 16:42:04 +01:00
Jon Häggblad 04664c8ae1 Rework IPR codec to extract out timer and implement AsyncWrite (#5632)
* Update ipr codec

* Tweak conditional

* Fix sending empty packet for flush

* Remove unneeded log

* Bump mix_traffic and real_message channel from size 1 to 8
2025-03-20 15:59:44 +01:00
import this 4da68438c0 [DOCs/operators]: Monor fix (#5650) 2025-03-20 13:13:55 +01:00
Tommy Verrall 05c1554109 test 2025-03-20 12:51:12 +01:00
import this 2b83442a6d [DOCs/operators]: Updates and release notes for v2025.5-chokito (#5648)
* replace dead token page with live dashboard

* add dev release notes

* fix urls

* add IPv6 KVM guide

* simplify node setup command

* add operator updates

* PR finished: add WG exit policy steps andfinish changelog

* PR finished: fix typo

* add components to the branch

* fix styling
2025-03-20 10:55:33 +00:00
Yana f982cb49c2 Fix NS api endpoint for dev and prod, add env variables 2025-03-20 11:57:50 +02:00
dependabot[bot] 0c05727e58 build(deps): bump dtolnay/rust-toolchain from 1.90.0 to 1.100.0 (#5638)
Bumps [dtolnay/rust-toolchain](https://github.com/dtolnay/rust-toolchain) from 1.90.0 to 1.100.0.
- [Release notes](https://github.com/dtolnay/rust-toolchain/releases)
- [Commits](https://github.com/dtolnay/rust-toolchain/compare/1.90.0...1.100.0)

---
updated-dependencies:
- dependency-name: dtolnay/rust-toolchain
  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-03-20 09:52:50 +00:00
Jon Häggblad 3c432ac073 Clean stale partially received buffers (#5536)
* Clean stale partially received buffers

* Tweak timeout

* Do cleanup after handling new messages instead of in the select loop

* Debug logging and remove unreachable

* Downgrade log

* Tweak logs

* tweak whitespace

* Only run the stale check every 10 sec
2025-03-20 10:01:42 +01:00
Yana 52ffd2e798 fix build 2025-03-19 15:30:39 +02:00
dependabot[bot] be8c7b4953 build(deps): bump golang.org/x/net from 0.23.0 to 0.36.0 in /wasm/mix-fetch/go-mix-conn (#5613)
* build(deps): bump golang.org/x/net in /wasm/mix-fetch/go-mix-conn

Bumps [golang.org/x/net](https://github.com/golang/net) from 0.23.0 to 0.36.0.
- [Commits](https://github.com/golang/net/compare/v0.23.0...v0.36.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: direct:production
...

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

* update used go compiler

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jędrzej Stuczyński <jedrzej.stuczynski@gmail.com>
2025-03-19 11:00:55 +00:00
dependabot[bot] 8e4bc12b87 Bump http-proxy-middleware from 2.0.6 to 2.0.7 (#5019)
Bumps [http-proxy-middleware](https://github.com/chimurai/http-proxy-middleware) from 2.0.6 to 2.0.7.
- [Release notes](https://github.com/chimurai/http-proxy-middleware/releases)
- [Changelog](https://github.com/chimurai/http-proxy-middleware/blob/v2.0.7/CHANGELOG.md)
- [Commits](https://github.com/chimurai/http-proxy-middleware/compare/v2.0.6...v2.0.7)

---
updated-dependencies:
- dependency-name: http-proxy-middleware
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-19 10:10:17 +00:00
dependabot[bot] 4895820985 build(deps): bump next from 13.5.7 to 14.2.15 in /documentation/docs (#5281)
Bumps [next](https://github.com/vercel/next.js) from 13.5.7 to 14.2.15.
- [Release notes](https://github.com/vercel/next.js/releases)
- [Changelog](https://github.com/vercel/next.js/blob/canary/release.js)
- [Commits](https://github.com/vercel/next.js/compare/v13.5.7...v14.2.15)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-19 10:10:02 +00:00
dependabot[bot] 8500618fe9 build(deps): bump next from 14.1.4 to 14.2.21 in /explorer-nextjs (#5308)
Bumps [next](https://github.com/vercel/next.js) from 14.1.4 to 14.2.21.
- [Release notes](https://github.com/vercel/next.js/releases)
- [Changelog](https://github.com/vercel/next.js/blob/canary/release.js)
- [Commits](https://github.com/vercel/next.js/compare/v14.1.4...v14.2.21)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-19 10:09:54 +00:00
dependabot[bot] a5b390b98f build(deps): bump nanoid from 3.3.7 to 3.3.8 in /documentation/docs (#5335)
Bumps [nanoid](https://github.com/ai/nanoid) from 3.3.7 to 3.3.8.
- [Release notes](https://github.com/ai/nanoid/releases)
- [Changelog](https://github.com/ai/nanoid/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ai/nanoid/compare/3.3.7...3.3.8)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-19 10:09:46 +00:00
dependabot[bot] ff66674f61 build(deps): bump store2 from 2.14.3 to 2.14.4 (#5391)
Bumps [store2](https://github.com/nbubna/store) from 2.14.3 to 2.14.4.
- [Commits](https://github.com/nbubna/store/compare/2.14.3...2.14.4)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-19 10:09:38 +00:00
dependabot[bot] a7cf34e812 build(deps): bump @octokit/plugin-paginate-rest and @actions/github (#5488)
Bumps [@octokit/plugin-paginate-rest](https://github.com/octokit/plugin-paginate-rest.js) to 9.2.2 and updates ancestor dependency [@actions/github](https://github.com/actions/toolkit/tree/HEAD/packages/github). These dependencies need to be updated together.


Updates `@octokit/plugin-paginate-rest` from 9.2.1 to 9.2.2
- [Release notes](https://github.com/octokit/plugin-paginate-rest.js/releases)
- [Commits](https://github.com/octokit/plugin-paginate-rest.js/compare/v9.2.1...v9.2.2)

Updates `@actions/github` from 5.1.1 to 6.0.0
- [Changelog](https://github.com/actions/toolkit/blob/main/packages/github/RELEASES.md)
- [Commits](https://github.com/actions/toolkit/commits/HEAD/packages/github)

---
updated-dependencies:
- dependency-name: "@octokit/plugin-paginate-rest"
  dependency-type: indirect
- dependency-name: "@actions/github"
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-19 10:09:05 +00:00
dependabot[bot] a85dad6bd7 build(deps): bump braces in /sdk/typescript/packages/mix-fetch-node (#5612)
Bumps [braces](https://github.com/micromatch/braces) from 3.0.2 to 3.0.3.
- [Changelog](https://github.com/micromatch/braces/blob/master/CHANGELOG.md)
- [Commits](https://github.com/micromatch/braces/compare/3.0.2...3.0.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-19 10:08:56 +00:00
dependabot[bot] 5b8a14f74b build(deps-dev): bump ws in /wasm/client/internal-dev (#5614)
Bumps [ws](https://github.com/websockets/ws) from 8.13.0 to 8.18.1.
- [Release notes](https://github.com/websockets/ws/releases)
- [Commits](https://github.com/websockets/ws/compare/8.13.0...8.18.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-19 10:08:45 +00:00
dependabot[bot] 730c2efea6 build(deps-dev): bump webpack in /wasm/client/internal-dev (#5615)
Bumps [webpack](https://github.com/webpack/webpack) from 5.77.0 to 5.98.0.
- [Release notes](https://github.com/webpack/webpack/releases)
- [Commits](https://github.com/webpack/webpack/compare/v5.77.0...v5.98.0)

---
updated-dependencies:
- dependency-name: webpack
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-19 10:08:36 +00:00
dependabot[bot] c9d6a8cc25 build(deps): bump @babel/runtime in /testnet-faucet (#5621)
Bumps [@babel/runtime](https://github.com/babel/babel/tree/HEAD/packages/babel-runtime) from 7.16.3 to 7.26.10.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.26.10/packages/babel-runtime)

---
updated-dependencies:
- dependency-name: "@babel/runtime"
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-19 10:06:52 +00:00
Jon Häggblad 230b2b1784 Upgrade sha2 to workspace version or validator-client (#5644) 2025-03-19 10:46:15 +01:00
Jon Häggblad e4e9615535 Add RUSTUP_PERMIT_COPY_RENAME in two workflows that we forgot about (#5646) 2025-03-19 09:18:25 +01:00
mfahampshire a19ee8f2aa fix accidental localhost link (#5643) 2025-03-18 17:23:22 +01:00
benedetta davico abfc68108a Merge pull request #5497 from helicopter-1/spelling
Corrected typos
2025-03-18 16:53:37 +01:00
Yana 7bf1adff28 Fixes 2025-03-18 17:45:38 +02:00
dependabot[bot] ed90e358fb build(deps): bump zeroize from 1.6.0 to 1.8.1 (#5630)
Bumps [zeroize](https://github.com/RustCrypto/utils) from 1.6.0 to 1.8.1.
- [Commits](https://github.com/RustCrypto/utils/compare/zeroize-v1.6.0...zeroize-v1.8.1)

---
updated-dependencies:
- dependency-name: zeroize
  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-03-18 15:23:16 +01:00
benedetta davico c7d0e26946 Merge pull request #5640 from nymtech/release/2025.5-chokito
Merge chokito to develop
2025-03-18 14:50:45 +01:00
Jon Häggblad 8d65c25986 Remove explorer-api from the main workspace (#5635) 2025-03-18 14:09:24 +01:00
benedetta davico a143d5f4f6 Merge pull request #5557 from nymtech/feature/exit-policies
Wireguard exit policies (and tests)
2025-03-18 12:29:40 +01:00
dependabot[bot] c041d11673 build(deps): bump zip from 2.2.2 to 2.4.1 (#5639)
Bumps [zip](https://github.com/zip-rs/zip2) from 2.2.2 to 2.4.1.
- [Release notes](https://github.com/zip-rs/zip2/releases)
- [Changelog](https://github.com/zip-rs/zip2/blob/master/CHANGELOG.md)
- [Commits](https://github.com/zip-rs/zip2/compare/v2.2.2...v2.4.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-18 10:59:08 +01:00
benedettadavico 82e82943aa update changelog 2025-03-18 10:39:55 +01:00
RadekSabacky e4fd87be2c / regenerated yarn.lock 2025-03-17 19:04:51 +01:00
dependabot[bot] 19ffe217f1 build(deps): bump http from 1.2.0 to 1.3.1 (#5626) 2025-03-17 18:47:40 +01:00
dependabot[bot] 079bfa52e7 build(deps): bump the patch-updates group with 8 updates (#5624)
Bumps the patch-updates group with 8 updates:

| Package | From | To |
| --- | --- | --- |
| [async-trait](https://github.com/dtolnay/async-trait) | `0.1.87` | `0.1.88` |
| [clap](https://github.com/clap-rs/clap) | `4.5.31` | `4.5.32` |
| [env_logger](https://github.com/rust-cli/env_logger) | `0.11.6` | `0.11.7` |
| [http-body-util](https://github.com/hyperium/http-body) | `0.1.2` | `0.1.3` |
| [quote](https://github.com/dtolnay/quote) | `1.0.39` | `1.0.40` |
| [tokio](https://github.com/tokio-rs/tokio) | `1.44.0` | `1.44.1` |
| [tokio-util](https://github.com/tokio-rs/tokio) | `0.7.13` | `0.7.14` |
| [indexed_db_futures](https://github.com/Alorel/rust-indexed-db) | `0.6.0` | `0.6.1` |


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

Updates `clap` from 4.5.31 to 4.5.32
- [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/v4.5.31...clap_complete-v4.5.32)

Updates `env_logger` from 0.11.6 to 0.11.7
- [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.6...v0.11.7)

Updates `http-body-util` from 0.1.2 to 0.1.3
- [Release notes](https://github.com/hyperium/http-body/releases)
- [Commits](https://github.com/hyperium/http-body/compare/http-body-util-v0.1.2...http-body-util-v0.1.3)

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

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

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

Updates `indexed_db_futures` from 0.6.0 to 0.6.1
- [Release notes](https://github.com/Alorel/rust-indexed-db/releases)
- [Commits](https://github.com/Alorel/rust-indexed-db/compare/v0.6.0...v0.6.1)

---
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: env_logger
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch-updates
- dependency-name: http-body-util
  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: tokio
  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: indexed_db_futures
  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-03-17 16:30:29 +01:00
dependabot[bot] be9a2c26e7 build(deps): bump once_cell from 1.20.3 to 1.21.1 (#5629)
Bumps [once_cell](https://github.com/matklad/once_cell) from 1.20.3 to 1.21.1.
- [Changelog](https://github.com/matklad/once_cell/blob/master/CHANGELOG.md)
- [Commits](https://github.com/matklad/once_cell/compare/v1.20.3...v1.21.1)

---
updated-dependencies:
- dependency-name: once_cell
  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-03-17 16:29:02 +01:00
mfahampshire d6f3eb6411 Max/new explorer url (#5522)
* new api link for explorer v2

* remove footer add explorer to navbar

* include image

* @ fix menu icons

* + explorer link in footer

---------

Co-authored-by: RadekSabacky <radek@nymtech.net>
2025-03-17 14:15:10 +00:00
dependabot[bot] 144f3bed9c build(deps): bump celes from 2.5.0 to 2.6.0 (#5627)
Bumps [celes](https://github.com/mikelodder7/celes) from 2.5.0 to 2.6.0.
- [Commits](https://github.com/mikelodder7/celes/commits)

---
updated-dependencies:
- dependency-name: celes
  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-03-17 13:46:33 +01:00
dependabot[bot] c1174e64d4 build(deps): bump humantime from 2.1.0 to 2.2.0 (#5625) 2025-03-17 12:59:56 +01:00
dependabot[bot] 312ecbe4dc build(deps): bump tempfile from 3.18.0 to 3.19.0 (#5631) 2025-03-17 12:53:24 +01:00
dependabot[bot] d2afa587e4 build(deps): bump uuid from 1.15.1 to 1.16.0 (#5628) 2025-03-17 12:52:17 +01:00
Tommy Verrall 224c4c1870 fix tests and ensure everything is working... 2025-03-17 11:07:54 +01:00
dynco-nym 3f8abdb74f Add /v3/nym-nodes (#5569)
* Add /v3/nym-nodes
- returns extended node info from local DB
- endpoint caching
- add bond_info & self_described to DB nym_nodes
- update mixnode & gateway bond status on data refresh
- add `active` column to DB nym_nodes
- use only active & bonded nodes in scraping/testrun tasks

* Improve log

* PR feedback
- remove active field from nym_nodes
- delete obsolete nym_nodes

* node-status-api: cargo sqlx prepare

* Remove guardrails in CI file

* Revert "node-status-api: cargo sqlx prepare"

This reverts commit 1fcd895f0d.

* Try to ignore sqlx files

* cargo sqlx prepare

* Repair harbor tag check

* Try without checkout action

* add awk

* Update log
2025-03-15 00:17:40 +01:00
Jędrzej Stuczyński 0f6ec8610e hotfix: correctly increment ws connection counter (#5620) 2025-03-14 15:47:17 +00:00
dynco-nym 3baac1292d Add workflow to check if tag exists (#5617)
* Add workflow

* Check harbor for tag

* Remove leftover comments

* Try out cargo metadata

* Revert "Try out cargo metadata"

This reverts commit b83fbad1ca.
2025-03-14 16:31:49 +01:00
benedetta davico c3b8c4b2f7 Merge pull request #5616 from nymtech/bd/remove-explorer-api-ci
Remove explorer-api from ci-build-binaries
2025-03-13 13:36:30 +01:00
benedettadavico 271b9e545c remove bump to explorer-api 2025-03-13 13:35:06 +01:00
benedetta davico 9641f01670 remove explorer-api from ci-build-binaries 2025-03-13 13:31:46 +01:00
benedettadavico a7bb3e8d91 bump versions for chokito 2025-03-13 13:19:37 +01:00
Fouad dc88650d6d Explorer V2 (#5548)
* remove pnpm lock file (should only be using yarn)

* Add lefthook configuration for pre-commit checks

* Add explorer-v2 to package.json dependencies

* add explorer v2

* update explorer v2 package name

* + basepath
+ redirect to basepath
+ blog icons refactor
+ icons refactor

* Add Getting Started instructions to README

* fix noise graph bug and line graph UI

* Delete unused translations, clean up console logs

* / test image url

* update yarn.lock

---------

Co-authored-by: RadekSabacky <radek@nymtech.net>
Co-authored-by: windy-ux <75579979+windy-ux@users.noreply.github.com>
Co-authored-by: Yana <iana.matrosova@gmail.com>
Co-authored-by: Mark Sinclair <mmsinclair@users.noreply.github.com>
2025-03-13 11:31:59 +00:00
Jack Wampler 79ce611d21 Server Side internal DoT/DoH opt out (#5577) 2025-03-12 10:14:04 -06:00
benedetta davico 960e817b8f Merge pull request #5578 from nymtech/yana/fix-double-memo
delete double memo field in send modal
2025-03-12 15:03:04 +01:00
dependabot[bot] 8b03e66ba7 build(deps): bump braces in /sdk/typescript/packages/nodejs-client (#5611)
Bumps [braces](https://github.com/micromatch/braces) from 3.0.2 to 3.0.3.
- [Changelog](https://github.com/micromatch/braces/blob/master/CHANGELOG.md)
- [Commits](https://github.com/micromatch/braces/compare/3.0.2...3.0.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-12 13:41:18 +00:00
dependabot[bot] 6a35581299 build(deps-dev): bump webpack-dev-middleware (#5610)
Bumps [webpack-dev-middleware](https://github.com/webpack/webpack-dev-middleware) from 5.3.3 to 5.3.4.
- [Release notes](https://github.com/webpack/webpack-dev-middleware/releases)
- [Changelog](https://github.com/webpack/webpack-dev-middleware/blob/v5.3.4/CHANGELOG.md)
- [Commits](https://github.com/webpack/webpack-dev-middleware/compare/v5.3.3...v5.3.4)

---
updated-dependencies:
- dependency-name: webpack-dev-middleware
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-12 13:40:54 +00:00
Jędrzej Stuczyński ce124a29a7 Chore/more payment watcher debug endpoints (#5608)
* add new endpoints for health and build information

* fixed timestamp serialisation in api responses

* status routes for price scraper

* state for processing bank msg

* clippy
2025-03-12 12:12:28 +00:00
Jędrzej Stuczyński f62d8813e0 chore: start sending v2 sphinx packets (#5554)
* chore: start sending v2 sphinx packets

* updated surb construction to use current format
2025-03-12 12:01:58 +00:00
dependabot[bot] a9cf016af2 build(deps-dev): bump ws in /wasm/mix-fetch/internal-dev (#5593)
Bumps [ws](https://github.com/websockets/ws) from 8.13.0 to 8.18.1.
- [Release notes](https://github.com/websockets/ws/releases)
- [Commits](https://github.com/websockets/ws/compare/8.13.0...8.18.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-12 11:58:19 +00:00
dependabot[bot] a8403b585b build(deps-dev): bump webpack in /wasm/mix-fetch/internal-dev (#5597)
Bumps [webpack](https://github.com/webpack/webpack) from 5.77.0 to 5.98.0.
- [Release notes](https://github.com/webpack/webpack/releases)
- [Commits](https://github.com/webpack/webpack/compare/v5.77.0...v5.98.0)

---
updated-dependencies:
- dependency-name: webpack
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-12 11:58:12 +00:00
Jon Häggblad e9a7b48da0 Export lane queue lengths in sdk (#5609) 2025-03-12 12:57:17 +01:00
dependabot[bot] 66792f57ed build(deps): bump @babel/helpers from 7.24.4 to 7.26.10 (#5606)
Bumps [@babel/helpers](https://github.com/babel/babel/tree/HEAD/packages/babel-helpers) from 7.24.4 to 7.26.10.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.26.10/packages/babel-helpers)

---
updated-dependencies:
- dependency-name: "@babel/helpers"
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-12 11:02:53 +00:00
Jędrzej Stuczyński f8d863249e Merge pull request #5605 from nymtech/chore/update-bls12_381-fork
Chore/update bls12 381 fork
2025-03-12 11:02:34 +00:00
Jędrzej Stuczyński 7d59a2477a chore: change auth v2 timestamp skew and allow values from the future (#5604)
* chore: change auth v2 timestamp skew and allow values from the future

* made the if statement more readable
2025-03-12 11:02:19 +00:00
Jędrzej Stuczyński eca88b0fa4 introduce internal tool for checking signer status (#5598)
* introduce internal tool for checking signer status

* fixed nym-api types due to moving values around

* added abci version
2025-03-12 11:02:03 +00:00
dependabot[bot] b80a4c8614 build(deps): bump body-parser and express (#5596)
Bumps [body-parser](https://github.com/expressjs/body-parser) and [express](https://github.com/expressjs/express). These dependencies needed to be updated together.

Updates `body-parser` from 1.20.2 to 1.20.3
- [Release notes](https://github.com/expressjs/body-parser/releases)
- [Changelog](https://github.com/expressjs/body-parser/blob/master/HISTORY.md)
- [Commits](https://github.com/expressjs/body-parser/compare/1.20.2...1.20.3)

Updates `express` from 4.19.2 to 4.21.2
- [Release notes](https://github.com/expressjs/express/releases)
- [Changelog](https://github.com/expressjs/express/blob/4.21.2/History.md)
- [Commits](https://github.com/expressjs/express/compare/4.19.2...4.21.2)

---
updated-dependencies:
- dependency-name: body-parser
  dependency-type: indirect
- dependency-name: express
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-12 11:00:38 +00:00
dependabot[bot] ec5d342e3a build(deps): bump serve-static and express (#5594)
Bumps [serve-static](https://github.com/expressjs/serve-static) and [express](https://github.com/expressjs/express). These dependencies needed to be updated together.

Updates `serve-static` from 1.15.0 to 1.16.2
- [Release notes](https://github.com/expressjs/serve-static/releases)
- [Changelog](https://github.com/expressjs/serve-static/blob/v1.16.2/HISTORY.md)
- [Commits](https://github.com/expressjs/serve-static/compare/v1.15.0...v1.16.2)

Updates `express` from 4.19.2 to 4.21.2
- [Release notes](https://github.com/expressjs/express/releases)
- [Changelog](https://github.com/expressjs/express/blob/4.21.2/History.md)
- [Commits](https://github.com/expressjs/express/compare/4.19.2...4.21.2)

---
updated-dependencies:
- dependency-name: serve-static
  dependency-type: indirect
- dependency-name: express
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-12 11:00:21 +00:00
dependabot[bot] 6565655861 build(deps): bump cookie and express in /wasm/client/internal-dev (#5592)
Bumps [cookie](https://github.com/jshttp/cookie) and [express](https://github.com/expressjs/express). These dependencies needed to be updated together.

Updates `cookie` from 0.6.0 to 0.7.1
- [Release notes](https://github.com/jshttp/cookie/releases)
- [Commits](https://github.com/jshttp/cookie/compare/v0.6.0...v0.7.1)

Updates `express` from 4.19.2 to 4.21.2
- [Release notes](https://github.com/expressjs/express/releases)
- [Changelog](https://github.com/expressjs/express/blob/4.21.2/History.md)
- [Commits](https://github.com/expressjs/express/compare/4.19.2...4.21.2)

---
updated-dependencies:
- dependency-name: cookie
  dependency-type: indirect
- dependency-name: express
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-12 10:59:36 +00:00
dependabot[bot] 5aba886f14 build(deps): bump cookie and express in /wasm/mix-fetch/internal-dev (#5591)
Bumps [cookie](https://github.com/jshttp/cookie) and [express](https://github.com/expressjs/express). These dependencies needed to be updated together.

Updates `cookie` from 0.6.0 to 0.7.1
- [Release notes](https://github.com/jshttp/cookie/releases)
- [Commits](https://github.com/jshttp/cookie/compare/v0.6.0...v0.7.1)

Updates `express` from 4.19.2 to 4.21.2
- [Release notes](https://github.com/expressjs/express/releases)
- [Changelog](https://github.com/expressjs/express/blob/4.21.2/History.md)
- [Commits](https://github.com/expressjs/express/compare/4.19.2...4.21.2)

---
updated-dependencies:
- dependency-name: cookie
  dependency-type: indirect
- dependency-name: express
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-12 10:59:20 +00:00
dependabot[bot] 3ee73d541e build(deps): bump braces in /wasm/zknym-lib/internal-dev (#5590)
Bumps [braces](https://github.com/micromatch/braces) from 3.0.2 to 3.0.3.
- [Changelog](https://github.com/micromatch/braces/blob/master/CHANGELOG.md)
- [Commits](https://github.com/micromatch/braces/compare/3.0.2...3.0.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-12 10:58:56 +00:00
dependabot[bot] 4588a3036e build(deps): bump webpack-dev-middleware in /wasm/zknym-lib/internal-dev (#5589)
Bumps [webpack-dev-middleware](https://github.com/webpack/webpack-dev-middleware) from 5.3.3 to 5.3.4.
- [Release notes](https://github.com/webpack/webpack-dev-middleware/releases)
- [Changelog](https://github.com/webpack/webpack-dev-middleware/blob/v5.3.4/CHANGELOG.md)
- [Commits](https://github.com/webpack/webpack-dev-middleware/compare/v5.3.3...v5.3.4)

---
updated-dependencies:
- dependency-name: webpack-dev-middleware
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-12 10:58:41 +00:00
dependabot[bot] 6194ac07b8 build(deps): bump ring from 0.17.3 to 0.17.13 in /nym-wallet (#5582)
Bumps [ring](https://github.com/briansmith/ring) from 0.17.3 to 0.17.13.
- [Changelog](https://github.com/briansmith/ring/blob/main/RELEASES.md)
- [Commits](https://github.com/briansmith/ring/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-12 10:57:02 +00:00
Yana 3880971e57 delete double memo field in send modal 2025-03-06 21:34:22 +02:00
Tommy Verrall 681c054890 rename file 2025-03-04 18:08:26 +01:00
Tommy Verrall f623bbd57c wireguard exit policy rules 2025-03-04 18:06:01 +01:00
helicopter-1 d4d576f363 Fix typos in CHANGELOG.md 2025-02-20 21:28:47 +01:00
772 changed files with 81089 additions and 26878 deletions
+1
View File
@@ -1 +1,2 @@
nym-validator-rewarder/.sqlx/** diff=nodiff
nym-node-status-api/nym-node-status-api/.sqlx/** diff=nodiff
+149 -265
View File
@@ -9,7 +9,7 @@
"version": "1.0.0",
"dependencies": {
"@actions/core": "^1.10.1",
"@actions/github": "^5.1.1",
"@actions/github": "^6.0.0",
"@octokit/auth-action": "^4.0.1",
"@octokit/rest": "^20.0.2",
"hasha": "^5.2.0",
@@ -29,22 +29,34 @@
}
},
"node_modules/@actions/github": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/@actions/github/-/github-5.1.1.tgz",
"integrity": "sha512-Nk59rMDoJaV+mHCOJPXuvB1zIbomlKS0dmSIqPGxd0enAXBnOfn4VWF+CGtRCwXZG9Epa54tZA7VIRlJDS8A6g==",
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/@actions/github/-/github-6.0.0.tgz",
"integrity": "sha512-alScpSVnYmjNEXboZjarjukQEzgCRmjMv6Xj47fsdnqGS73bjJNDpiiXmp8jr0UZLdUB6d9jW63IcmddUP+l0g==",
"license": "MIT",
"dependencies": {
"@actions/http-client": "^2.0.1",
"@octokit/core": "^3.6.0",
"@octokit/plugin-paginate-rest": "^2.17.0",
"@octokit/plugin-rest-endpoint-methods": "^5.13.0"
"@actions/http-client": "^2.2.0",
"@octokit/core": "^5.0.1",
"@octokit/plugin-paginate-rest": "^9.0.0",
"@octokit/plugin-rest-endpoint-methods": "^10.0.0"
}
},
"node_modules/@actions/http-client": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.1.1.tgz",
"integrity": "sha512-qhrkRMB40bbbLo7gF+0vu+X+UawOvQQqNAA/5Unx774RS8poaOhThDOG6BGmxvAnxhQnDp2BG/ZUm65xZILTpw==",
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.2.3.tgz",
"integrity": "sha512-mx8hyJi/hjFvbPokCg4uRd4ZX78t+YyRPtnKWwIl+RzNaVuFpQHfmlGVfsKEJN8LwTCvL+DfVgAM04XaHkm6bA==",
"license": "MIT",
"dependencies": {
"tunnel": "^0.0.6"
"tunnel": "^0.0.6",
"undici": "^5.25.4"
}
},
"node_modules/@fastify/busboy": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz",
"integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==",
"license": "MIT",
"engines": {
"node": ">=14"
}
},
"node_modules/@octokit/auth-action": {
@@ -59,14 +71,6 @@
"node": ">= 18"
}
},
"node_modules/@octokit/auth-action/node_modules/@octokit/auth-token": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-4.0.0.tgz",
"integrity": "sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==",
"engines": {
"node": ">= 18"
}
},
"node_modules/@octokit/auth-action/node_modules/@octokit/openapi-types": {
"version": "20.0.0",
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-20.0.0.tgz",
@@ -81,115 +85,152 @@
}
},
"node_modules/@octokit/auth-token": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.5.0.tgz",
"integrity": "sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g==",
"dependencies": {
"@octokit/types": "^6.0.3"
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-4.0.0.tgz",
"integrity": "sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==",
"license": "MIT",
"engines": {
"node": ">= 18"
}
},
"node_modules/@octokit/core": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.6.0.tgz",
"integrity": "sha512-7RKRKuA4xTjMhY+eG3jthb3hlZCsOwg3rztWh75Xc+ShDWOfDDATWbeZpAHBNRpm4Tv9WgBMOy1zEJYXG6NJ7Q==",
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/@octokit/core/-/core-5.2.0.tgz",
"integrity": "sha512-1LFfa/qnMQvEOAdzlQymH0ulepxbxnCYAKJZfMci/5XJyIHWgEYnDmgnKakbTh7CH2tFQ5O60oYDvns4i9RAIg==",
"license": "MIT",
"dependencies": {
"@octokit/auth-token": "^2.4.4",
"@octokit/graphql": "^4.5.8",
"@octokit/request": "^5.6.3",
"@octokit/request-error": "^2.0.5",
"@octokit/types": "^6.0.3",
"@octokit/auth-token": "^4.0.0",
"@octokit/graphql": "^7.1.0",
"@octokit/request": "^8.3.1",
"@octokit/request-error": "^5.1.0",
"@octokit/types": "^13.0.0",
"before-after-hook": "^2.2.0",
"universal-user-agent": "^6.0.0"
},
"engines": {
"node": ">= 18"
}
},
"node_modules/@octokit/endpoint": {
"version": "6.0.12",
"resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz",
"integrity": "sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==",
"version": "9.0.6",
"resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-9.0.6.tgz",
"integrity": "sha512-H1fNTMA57HbkFESSt3Y9+FBICv+0jFceJFPWDePYlR/iMGrwM5ph+Dd4XRQs+8X+PUFURLQgX9ChPfhJ/1uNQw==",
"license": "MIT",
"dependencies": {
"@octokit/types": "^6.0.3",
"is-plain-object": "^5.0.0",
"@octokit/types": "^13.1.0",
"universal-user-agent": "^6.0.0"
},
"engines": {
"node": ">= 18"
}
},
"node_modules/@octokit/graphql": {
"version": "4.8.0",
"resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.8.0.tgz",
"integrity": "sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==",
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-7.1.0.tgz",
"integrity": "sha512-r+oZUH7aMFui1ypZnAvZmn0KSqAUgE1/tUXIWaqUCa1758ts/Jio84GZuzsvUkme98kv0WFY8//n0J1Z+vsIsQ==",
"license": "MIT",
"dependencies": {
"@octokit/request": "^5.6.0",
"@octokit/types": "^6.0.3",
"@octokit/request": "^8.3.0",
"@octokit/types": "^13.0.0",
"universal-user-agent": "^6.0.0"
},
"engines": {
"node": ">= 18"
}
},
"node_modules/@octokit/openapi-types": {
"version": "12.11.0",
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz",
"integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ=="
"version": "23.0.1",
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-23.0.1.tgz",
"integrity": "sha512-izFjMJ1sir0jn0ldEKhZ7xegCTj/ObmEDlEfpFrx4k/JyZSMRHbO3/rBwgE7f3m2DHt+RrNGIVw4wSmwnm3t/g==",
"license": "MIT"
},
"node_modules/@octokit/plugin-paginate-rest": {
"version": "2.21.3",
"resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.21.3.tgz",
"integrity": "sha512-aCZTEf0y2h3OLbrgKkrfFdjRL6eSOo8komneVQJnYecAxIej7Bafor2xhuDJOIFau4pk0i/P28/XgtbyPF0ZHw==",
"version": "9.2.2",
"resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-9.2.2.tgz",
"integrity": "sha512-u3KYkGF7GcZnSD/3UP0S7K5XUFT2FkOQdcfXZGZQPGv3lm4F2Xbf71lvjldr8c1H3nNbF+33cLEkWYbokGWqiQ==",
"license": "MIT",
"dependencies": {
"@octokit/types": "^6.40.0"
"@octokit/types": "^12.6.0"
},
"engines": {
"node": ">= 18"
},
"peerDependencies": {
"@octokit/core": ">=2"
"@octokit/core": "5"
}
},
"node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/openapi-types": {
"version": "20.0.0",
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-20.0.0.tgz",
"integrity": "sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA==",
"license": "MIT"
},
"node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/types": {
"version": "12.6.0",
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.6.0.tgz",
"integrity": "sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==",
"license": "MIT",
"dependencies": {
"@octokit/openapi-types": "^20.0.0"
}
},
"node_modules/@octokit/plugin-rest-endpoint-methods": {
"version": "5.16.2",
"resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.16.2.tgz",
"integrity": "sha512-8QFz29Fg5jDuTPXVtey05BLm7OB+M8fnvE64RNegzX7U+5NUXcOcnpTIK0YfSHBg8gYd0oxIq3IZTe9SfPZiRw==",
"version": "10.4.1",
"resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-10.4.1.tgz",
"integrity": "sha512-xV1b+ceKV9KytQe3zCVqjg+8GTGfDYwaT1ATU5isiUyVtlVAO3HNdzpS4sr4GBx4hxQ46s7ITtZrAsxG22+rVg==",
"license": "MIT",
"dependencies": {
"@octokit/types": "^6.39.0",
"deprecation": "^2.3.1"
"@octokit/types": "^12.6.0"
},
"engines": {
"node": ">= 18"
},
"peerDependencies": {
"@octokit/core": ">=3"
"@octokit/core": "5"
}
},
"node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/openapi-types": {
"version": "20.0.0",
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-20.0.0.tgz",
"integrity": "sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA==",
"license": "MIT"
},
"node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/types": {
"version": "12.6.0",
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.6.0.tgz",
"integrity": "sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==",
"license": "MIT",
"dependencies": {
"@octokit/openapi-types": "^20.0.0"
}
},
"node_modules/@octokit/request": {
"version": "5.6.3",
"resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.3.tgz",
"integrity": "sha512-bFJl0I1KVc9jYTe9tdGGpAMPy32dLBXXo1dS/YwSCTL/2nd9XeHsY616RE3HPXDVk+a+dBuzyz5YdlXwcDTr2A==",
"version": "8.4.1",
"resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.4.1.tgz",
"integrity": "sha512-qnB2+SY3hkCmBxZsR/MPCybNmbJe4KAlfWErXq+rBKkQJlbjdJeS85VI9r8UqeLYLvnAenU8Q1okM/0MBsAGXw==",
"license": "MIT",
"dependencies": {
"@octokit/endpoint": "^6.0.1",
"@octokit/request-error": "^2.1.0",
"@octokit/types": "^6.16.1",
"is-plain-object": "^5.0.0",
"node-fetch": "^2.6.7",
"@octokit/endpoint": "^9.0.6",
"@octokit/request-error": "^5.1.1",
"@octokit/types": "^13.1.0",
"universal-user-agent": "^6.0.0"
},
"engines": {
"node": ">= 18"
}
},
"node_modules/@octokit/request-error": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz",
"integrity": "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==",
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-5.1.1.tgz",
"integrity": "sha512-v9iyEQJH6ZntoENr9/yXxjuezh4My67CBSu9r6Ve/05Iu5gNgnisNWOsoJHTP6k0Rr0+HQIpnH+kyammu90q/g==",
"license": "MIT",
"dependencies": {
"@octokit/types": "^6.0.3",
"@octokit/types": "^13.1.0",
"deprecation": "^2.0.0",
"once": "^1.4.0"
}
},
"node_modules/@octokit/request/node_modules/node-fetch": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
"integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
"dependencies": {
"whatwg-url": "^5.0.0"
},
"engines": {
"node": "4.x || >=6.0.0"
},
"peerDependencies": {
"encoding": "^0.1.0"
},
"peerDependenciesMeta": {
"encoding": {
"optional": true
}
"node": ">= 18"
}
},
"node_modules/@octokit/rest": {
@@ -206,89 +247,6 @@
"node": ">= 18"
}
},
"node_modules/@octokit/rest/node_modules/@octokit/auth-token": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-4.0.0.tgz",
"integrity": "sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==",
"engines": {
"node": ">= 18"
}
},
"node_modules/@octokit/rest/node_modules/@octokit/core": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/@octokit/core/-/core-5.0.0.tgz",
"integrity": "sha512-YbAtMWIrbZ9FCXbLwT9wWB8TyLjq9mxpKdgB3dUNxQcIVTf9hJ70gRPwAcqGZdY6WdJPZ0I7jLaaNDCiloGN2A==",
"dependencies": {
"@octokit/auth-token": "^4.0.0",
"@octokit/graphql": "^7.0.0",
"@octokit/request": "^8.0.2",
"@octokit/request-error": "^5.0.0",
"@octokit/types": "^11.0.0",
"before-after-hook": "^2.2.0",
"universal-user-agent": "^6.0.0"
},
"engines": {
"node": ">= 18"
}
},
"node_modules/@octokit/rest/node_modules/@octokit/endpoint": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-9.0.0.tgz",
"integrity": "sha512-szrQhiqJ88gghWY2Htt8MqUDO6++E/EIXqJ2ZEp5ma3uGS46o7LZAzSLt49myB7rT+Hfw5Y6gO3LmOxGzHijAQ==",
"dependencies": {
"@octokit/types": "^11.0.0",
"is-plain-object": "^5.0.0",
"universal-user-agent": "^6.0.0"
},
"engines": {
"node": ">= 18"
}
},
"node_modules/@octokit/rest/node_modules/@octokit/graphql": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-7.0.1.tgz",
"integrity": "sha512-T5S3oZ1JOE58gom6MIcrgwZXzTaxRnxBso58xhozxHpOqSTgDS6YNeEUvZ/kRvXgPrRz/KHnZhtb7jUMRi9E6w==",
"dependencies": {
"@octokit/request": "^8.0.1",
"@octokit/types": "^11.0.0",
"universal-user-agent": "^6.0.0"
},
"engines": {
"node": ">= 18"
}
},
"node_modules/@octokit/rest/node_modules/@octokit/openapi-types": {
"version": "18.0.0",
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-18.0.0.tgz",
"integrity": "sha512-V8GImKs3TeQRxRtXFpG2wl19V7444NIOTDF24AWuIbmNaNYOQMWRbjcGDXV5B+0n887fgDcuMNOmlul+k+oJtw=="
},
"node_modules/@octokit/rest/node_modules/@octokit/plugin-paginate-rest": {
"version": "9.2.1",
"resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-9.2.1.tgz",
"integrity": "sha512-wfGhE/TAkXZRLjksFXuDZdmGnJQHvtU/joFQdweXUgzo1XwvBCD4o4+75NtFfjfLK5IwLf9vHTfSiU3sLRYpRw==",
"dependencies": {
"@octokit/types": "^12.6.0"
},
"engines": {
"node": ">= 18"
},
"peerDependencies": {
"@octokit/core": "5"
}
},
"node_modules/@octokit/rest/node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/openapi-types": {
"version": "20.0.0",
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-20.0.0.tgz",
"integrity": "sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA=="
},
"node_modules/@octokit/rest/node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/types": {
"version": "12.6.0",
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.6.0.tgz",
"integrity": "sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==",
"dependencies": {
"@octokit/openapi-types": "^20.0.0"
}
},
"node_modules/@octokit/rest/node_modules/@octokit/plugin-request-log": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-4.0.0.tgz",
@@ -300,75 +258,13 @@
"@octokit/core": ">=5"
}
},
"node_modules/@octokit/rest/node_modules/@octokit/plugin-rest-endpoint-methods": {
"version": "10.4.1",
"resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-10.4.1.tgz",
"integrity": "sha512-xV1b+ceKV9KytQe3zCVqjg+8GTGfDYwaT1ATU5isiUyVtlVAO3HNdzpS4sr4GBx4hxQ46s7ITtZrAsxG22+rVg==",
"dependencies": {
"@octokit/types": "^12.6.0"
},
"engines": {
"node": ">= 18"
},
"peerDependencies": {
"@octokit/core": "5"
}
},
"node_modules/@octokit/rest/node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/openapi-types": {
"version": "20.0.0",
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-20.0.0.tgz",
"integrity": "sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA=="
},
"node_modules/@octokit/rest/node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/types": {
"version": "12.6.0",
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.6.0.tgz",
"integrity": "sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==",
"dependencies": {
"@octokit/openapi-types": "^20.0.0"
}
},
"node_modules/@octokit/rest/node_modules/@octokit/request": {
"version": "8.1.1",
"resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.1.1.tgz",
"integrity": "sha512-8N+tdUz4aCqQmXl8FpHYfKG9GelDFd7XGVzyN8rc6WxVlYcfpHECnuRkgquzz+WzvHTK62co5di8gSXnzASZPQ==",
"dependencies": {
"@octokit/endpoint": "^9.0.0",
"@octokit/request-error": "^5.0.0",
"@octokit/types": "^11.1.0",
"is-plain-object": "^5.0.0",
"universal-user-agent": "^6.0.0"
},
"engines": {
"node": ">= 18"
}
},
"node_modules/@octokit/rest/node_modules/@octokit/request-error": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-5.0.0.tgz",
"integrity": "sha512-1ue0DH0Lif5iEqT52+Rf/hf0RmGO9NWFjrzmrkArpG9trFfDM/efx00BJHdLGuro4BR/gECxCU2Twf5OKrRFsQ==",
"dependencies": {
"@octokit/types": "^11.0.0",
"deprecation": "^2.0.0",
"once": "^1.4.0"
},
"engines": {
"node": ">= 18"
}
},
"node_modules/@octokit/rest/node_modules/@octokit/types": {
"version": "11.1.0",
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-11.1.0.tgz",
"integrity": "sha512-Fz0+7GyLm/bHt8fwEqgvRBWwIV1S6wRRyq+V6exRKLVWaKGsuy6H9QFYeBVDV7rK6fO3XwHgQOPxv+cLj2zpXQ==",
"dependencies": {
"@octokit/openapi-types": "^18.0.0"
}
},
"node_modules/@octokit/types": {
"version": "6.41.0",
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz",
"integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==",
"version": "13.8.0",
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.8.0.tgz",
"integrity": "sha512-x7DjTIbEpEWXK99DMd01QfWy0hd5h4EN+Q7shkdKds3otGQP+oWE/y0A76i1OvH9fygo4ddvNf7ZvF0t78P98A==",
"license": "MIT",
"dependencies": {
"@octokit/openapi-types": "^12.11.0"
"@octokit/openapi-types": "^23.0.1"
}
},
"node_modules/@vercel/ncc": {
@@ -396,7 +292,8 @@
"node_modules/deprecation": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz",
"integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ=="
"integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==",
"license": "ISC"
},
"node_modules/fetch-blob": {
"version": "3.2.0",
@@ -446,14 +343,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/is-plain-object": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz",
"integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/is-stream": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
@@ -504,15 +393,11 @@
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
"license": "ISC",
"dependencies": {
"wrappy": "1"
}
},
"node_modules/tr46": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
},
"node_modules/tunnel": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz",
@@ -529,6 +414,18 @@
"node": ">=8"
}
},
"node_modules/undici": {
"version": "5.28.5",
"resolved": "https://registry.npmjs.org/undici/-/undici-5.28.5.tgz",
"integrity": "sha512-zICwjrDrcrUE0pyyJc1I2QzBkLM8FINsgOrt6WjA+BgajVq9Nxu2PbFFXUrAggLfDXlZGZBVZYw7WNV5KiBiBA==",
"license": "MIT",
"dependencies": {
"@fastify/busboy": "^2.0.0"
},
"engines": {
"node": ">=14.0"
}
},
"node_modules/universal-user-agent": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz",
@@ -550,24 +447,11 @@
"node": ">= 8"
}
},
"node_modules/webidl-conversions": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
"integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
},
"node_modules/whatwg-url": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
"integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
"dependencies": {
"tr46": "~0.0.3",
"webidl-conversions": "^3.0.0"
}
},
"node_modules/wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
"license": "ISC"
}
}
}
@@ -11,7 +11,7 @@
},
"dependencies": {
"@actions/core": "^1.10.1",
"@actions/github": "^5.1.1",
"@actions/github": "^6.0.0",
"@octokit/auth-action": "^4.0.1",
"@octokit/rest": "^20.0.2",
"hasha": "^5.2.0",
@@ -100,7 +100,6 @@ jobs:
cp target/release/nymvisor $OUTPUT_DIR
cp target/release/nym-node $OUTPUT_DIR
cp target/release/nym-cli $OUTPUT_DIR
cp target/release/explorer-api $OUTPUT_DIR
if [ ${{ github.event_name == 'workflow_dispatch' && inputs.enable_deb == true }} = true ]; then
cp target/debian/*.deb $OUTPUT_DIR
fi
+6
View File
@@ -27,6 +27,12 @@ on:
- '.github/workflows/ci-build.yml'
workflow_dispatch:
concurrency:
# only 1 concurrent `ci-build` allowed per branch
# https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions#example-using-concurrency-and-the-default-behavior
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
build:
strategy:
@@ -0,0 +1,57 @@
name: ci-check-ns-api-version
on:
pull_request:
paths:
- "nym-node-status-api/**"
env:
WORKING_DIRECTORY: "nym-node-status-api/nym-node-status-api"
jobs:
check-if-tag-exists:
runs-on: arc-ubuntu-22.04-dind
steps:
- name: Checkout repo
uses: actions/checkout@v4
- name: Get version from cargo.toml
uses: mikefarah/yq@v4.45.1
id: get_version
with:
cmd: yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/Cargo.toml
- name: Check if git tag exists
run: |
TAG=${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.result }}
if [[ -z "$TAG" ]]; then
echo "Tag is empty"
exit 1
fi
git ls-remote --tags origin | awk '{print $2}'
if git ls-remote --tags origin | awk '{print $2}' | grep -q "refs/tags/$TAG$" ; then
echo "Tag '$TAG' ALREADY EXISTS on the remote"
exit 1
else
echo "Tag '$TAG' does not exist on the remote"
fi
- name: Check if harbor tag exists
run: |
TAG=${{ steps.get_version.outputs.result }}
registry=https://harbor.nymte.ch
repo_name=nym/node-status-api
if [[ -z $TAG ]]; then
echo "Tag is empty"
exit 1
fi
curl -su ${{ secrets.HARBOR_ROBOT_USERNAME }}:${{ secrets.HARBOR_ROBOT_SECRET }} "$registry/v2/$repo_name/tags/list" | jq
exists=$(curl -su ${{ secrets.HARBOR_ROBOT_USERNAME }}:${{ secrets.HARBOR_ROBOT_SECRET }} "$registry/v2/$repo_name/tags/list" | jq --arg tag $TAG '.tags | contains([$tag])' )
if [[ $exists = "true" ]]; then
echo "Version '$TAG' defined in Cargo.toml ALREADY EXISTS as tag in harbor repo"
exit 1
elif [[ $exists = "false" ]]; then
echo "Version '$TAG' doesn't exist on the remote"
else
echo "Unknown output '$exists'"
exit 1
fi
@@ -1,6 +0,0 @@
[
{
"rust":"stable",
"runOnEvent":"always"
}
]
@@ -31,7 +31,6 @@ jobs:
- name: Install Rust stable
uses: actions-rs/toolchain@v1
with:
toolchain: 1.77
target: wasm32-unknown-unknown
override: true
@@ -40,6 +39,9 @@ jobs:
with:
version: '114'
- name: Install cosmwasm-check
run: cargo install cosmwasm-check
- name: Build release contracts
run: make contracts
@@ -50,7 +52,6 @@ jobs:
run: |
cp contracts/target/wasm32-unknown-unknown/release/mixnet_contract.wasm $OUTPUT_DIR
cp contracts/target/wasm32-unknown-unknown/release/vesting_contract.wasm $OUTPUT_DIR
cp contracts/target/wasm32-unknown-unknown/release/nym_coconut_bandwidth.wasm $OUTPUT_DIR
cp contracts/target/wasm32-unknown-unknown/release/nym_coconut_dkg.wasm $OUTPUT_DIR
cp contracts/target/wasm32-unknown-unknown/release/cw3_flex_multisig.wasm $OUTPUT_DIR
cp contracts/target/wasm32-unknown-unknown/release/cw4_group.wasm $OUTPUT_DIR
+13 -17
View File
@@ -14,28 +14,12 @@ on:
- '.github/workflows/ci-contracts.yml'
jobs:
matrix_prep:
runs-on: ubuntu-20.04
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
steps:
# creates the matrix strategy from ci-contracts-matrix-includes.json
- uses: actions/checkout@v4
- id: set-matrix
uses: JoshuaTheMiller/conditional-build-matrix@main
with:
inputFile: '.github/workflows/ci-contracts-matrix-includes.json'
filter: '[?runOnEvent==`${{ github.event_name }}` || runOnEvent==`always`]'
build:
# since it's going to be compiled into wasm, there's absolutely
# no point in running CI on different OS-es
runs-on: ubuntu-20.04
env:
CARGO_TERM_COLOR: always
needs: matrix_prep
strategy:
fail-fast: false
matrix: ${{fromJson(needs.matrix_prep.outputs.matrix)}}
steps:
- uses: actions/checkout@v4
@@ -43,11 +27,19 @@ jobs:
uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: ${{ matrix.rust }}
toolchain: stable
target: wasm32-unknown-unknown
override: true
components: rustfmt, clippy
- name: Install cosmwasm-check
run: cargo install cosmwasm-check
- name: Install wasm-opt
uses: ./.github/actions/install-wasm-opt
with:
version: '114'
- name: Build contracts
uses: actions-rs/cargo@v1
env:
@@ -73,3 +65,7 @@ jobs:
with:
command: clippy
args: --lib --manifest-path contracts/Cargo.toml --workspace --all-targets -- -D warnings
- name: Check chain compatibility against release build
# this will build contracts in release mode, run wasm-opt and finally cosmwasm-check
run: make contracts
+2
View File
@@ -11,6 +11,8 @@ on:
jobs:
build:
runs-on: arc-ubuntu-20.04
env:
RUSTUP_PERMIT_COPY_RENAME: 1
defaults:
run:
working-directory: documentation/docs
+3 -1
View File
@@ -16,6 +16,8 @@ on:
jobs:
build:
runs-on: arc-ubuntu-20.04
env:
RUSTUP_PERMIT_COPY_RENAME: 1
steps:
- uses: actions/checkout@v4
- uses: rlespinasse/github-slug-action@v3.x
@@ -42,7 +44,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.20'
go-version: "1.23.7"
- name: Install
run: yarn
+1
View File
@@ -14,6 +14,7 @@ jobs:
runs-on: arc-ubuntu-20.04
env:
CARGO_TERM_COLOR: always
RUSTUP_PERMIT_COPY_RENAME: 1
steps:
- name: Install Dependencies (Linux)
run: sudo apt-get update && sudo apt-get -y install libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev squashfs-tools
+52 -52
View File
@@ -10,66 +10,66 @@ jobs:
build:
runs-on: custom-linux
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v4
- name: Install rsync
run: sudo apt-get install rsync
continue-on-error: true
- name: Install rsync
run: sudo apt-get install rsync
continue-on-error: true
- uses: rlespinasse/github-slug-action@v3.x
- uses: rlespinasse/github-slug-action@v3.x
- uses: actions/setup-node@v4
with:
node-version: 18
- uses: actions/setup-node@v4
with:
node-version: 20
- name: Setup yarn
run: npm install -g yarn
- name: Setup yarn
run: npm install -g yarn
- name: Install Rust stable
uses: actions-rs/toolchain@v1
with:
toolchain: stable
- name: Install Rust stable
uses: actions-rs/toolchain@v1
with:
toolchain: stable
- name: Install wasm-pack
run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
- name: Install wasm-pack
run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
- name: Build dependencies
run: yarn && yarn build
- name: Build dependencies
run: yarn && yarn build
- name: Build storybook
run: yarn storybook:build
working-directory: ./nym-wallet
- name: Build storybook
run: yarn storybook:build
working-directory: ./nym-wallet
- name: Deploy branch to CI www (storybook)
continue-on-error: true
uses: easingthemes/ssh-deploy@main
env:
SSH_PRIVATE_KEY: ${{ secrets.CI_WWW_SSH_PRIVATE_KEY }}
ARGS: "-rltgoDzvO --delete"
SOURCE: "nym-wallet/storybook-static/"
REMOTE_HOST: ${{ secrets.CI_WWW_REMOTE_HOST }}
REMOTE_USER: ${{ secrets.CI_WWW_REMOTE_USER }}
TARGET: ${{ secrets.CI_WWW_REMOTE_TARGET }}/wallet-${{ env.GITHUB_REF_SLUG }}
EXCLUDE: "/dist/, /node_modules/"
- name: Deploy branch to CI www (storybook)
continue-on-error: true
uses: easingthemes/ssh-deploy@main
env:
SSH_PRIVATE_KEY: ${{ secrets.CI_WWW_SSH_PRIVATE_KEY }}
ARGS: "-rltgoDzvO --delete"
SOURCE: "nym-wallet/storybook-static/"
REMOTE_HOST: ${{ secrets.CI_WWW_REMOTE_HOST }}
REMOTE_USER: ${{ secrets.CI_WWW_REMOTE_USER }}
TARGET: ${{ secrets.CI_WWW_REMOTE_TARGET }}/wallet-${{ env.GITHUB_REF_SLUG }}
EXCLUDE: "/dist/, /node_modules/"
- name: Matrix - Node Install
run: npm install
working-directory: .github/workflows/support-files
- name: Matrix - Node Install
run: npm install
working-directory: .github/workflows/support-files
- name: Matrix - Send Notification
env:
NYM_NOTIFICATION_KIND: nym-wallet
NYM_PROJECT_NAME: "nym-wallet"
NYM_CI_WWW_BASE: "${{ secrets.NYM_CI_WWW_BASE }}"
NYM_CI_WWW_LOCATION: "wallet-${{ env.GITHUB_REF_SLUG }}"
GIT_COMMIT_MESSAGE: "${{ github.event.head_commit.message }}"
GIT_BRANCH: "${GITHUB_REF##*/}"
IS_SUCCESS: "${{ job.status == 'success' }}"
MATRIX_SERVER: "${{ secrets.MATRIX_SERVER }}"
MATRIX_ROOM: "${{ secrets.MATRIX_ROOM }}"
MATRIX_USER_ID: "${{ secrets.MATRIX_USER_ID }}"
MATRIX_TOKEN: "${{ secrets.MATRIX_TOKEN }}"
MATRIX_DEVICE_ID: "${{ secrets.MATRIX_DEVICE_ID }}"
uses: docker://keybaseio/client:stable-node
with:
args: .github/workflows/support-files/notifications/entry_point.sh
- name: Matrix - Send Notification
env:
NYM_NOTIFICATION_KIND: nym-wallet
NYM_PROJECT_NAME: "nym-wallet"
NYM_CI_WWW_BASE: "${{ secrets.NYM_CI_WWW_BASE }}"
NYM_CI_WWW_LOCATION: "wallet-${{ env.GITHUB_REF_SLUG }}"
GIT_COMMIT_MESSAGE: "${{ github.event.head_commit.message }}"
GIT_BRANCH: "${GITHUB_REF##*/}"
IS_SUCCESS: "${{ job.status == 'success' }}"
MATRIX_SERVER: "${{ secrets.MATRIX_SERVER }}"
MATRIX_ROOM: "${{ secrets.MATRIX_ROOM }}"
MATRIX_USER_ID: "${{ secrets.MATRIX_USER_ID }}"
MATRIX_TOKEN: "${{ secrets.MATRIX_TOKEN }}"
MATRIX_DEVICE_ID: "${{ secrets.MATRIX_DEVICE_ID }}"
uses: docker://keybaseio/client:stable-node
with:
args: .github/workflows/support-files/notifications/entry_point.sh
+2 -1
View File
@@ -14,6 +14,7 @@ jobs:
runs-on: arc-ubuntu-20.04
env:
CARGO_TERM_COLOR: always
RUSTUP_PERMIT_COPY_RENAME: 1
steps:
- uses: actions/checkout@v4
@@ -32,7 +33,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.20'
go-version: "1.23.7"
- name: Install wasm-pack
run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
+2 -3
View File
@@ -2,19 +2,18 @@ name: publish-nym-contracts
on:
workflow_dispatch:
release:
types: [created]
types: [ created ]
jobs:
build:
if: ${{ (startsWith(github.ref, 'refs/tags/nym-contracts-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }}
runs-on: [self-hosted, custom-ubuntu-20.04]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Rust stable
uses: actions-rs/toolchain@v1
with:
toolchain: 1.77
target: wasm32-unknown-unknown
override: true
@@ -14,7 +14,7 @@ jobs:
strategy:
fail-fast: false
matrix:
platform: [macos-12-large]
platform: [macos-15]
runs-on: ${{ matrix.platform }}
outputs:
@@ -30,7 +30,7 @@ jobs:
- name: Node
uses: actions/setup-node@v4
with:
node-version: 18
node-version: 21
- name: Install Rust stable
uses: actions-rs/toolchain@v1
with:
@@ -36,7 +36,7 @@ jobs:
- name: Node
uses: actions/setup-node@v4
with:
node-version: 18
node-version: 21
- name: Install Rust stable
uses: actions-rs/toolchain@v1
@@ -49,7 +49,7 @@ jobs:
- name: Node
uses: actions/setup-node@v4
with:
node-version: 18
node-version: 21
- name: Install Rust stable
uses: actions-rs/toolchain@v1
@@ -49,7 +49,7 @@ jobs:
"build-tools;$SDK_BUILDTOOLS_VERSION"
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@1.90.0
uses: dtolnay/rust-toolchain@1.100.0
- name: Install rust android targets
run: |
+1 -6
View File
@@ -31,12 +31,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: "1.20"
- name: Install TinyGo
uses: acifani/setup-tinygo@v2
with:
tinygo-version: "0.27.0"
go-version: "1.23.7"
- name: Install dependencies
run: yarn
+184 -10
View File
@@ -4,6 +4,180 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
## [Unreleased]
## [2025.6-chuckles] (2025-03-31)
- Remove Google public DNS ([#5660])
- Revert using AsyncWrite sink in IPR ([#5656])
- Add fd callback for initial authentication ([#5654])
- Add concurrency limit to CI ([#5651])
- Remove UNIQUE constraint on node pubkey ([#5649])
- Add RUSTUP_PERMIT_COPY_RENAME in two workflows that we forgot about ([#5646])
- Upgrade sha2 to workspace version for validator-client ([#5644])
- Add max_retransmissions flag on each message ([#5642])
- build(deps): bump zip from 2.2.2 to 2.4.1 ([#5639])
- build(deps): bump dtolnay/rust-toolchain from 1.90.0 to 1.100.0 ([#5638])
- / regenerated yarn.lock ([#5636])
- Rework IPR codec to extract out timer and implement AsyncWrite ([#5632])
- build(deps): bump tempfile from 3.18.0 to 3.19.0 ([#5631])
- build(deps): bump zeroize from 1.6.0 to 1.8.1 ([#5630])
- build(deps): bump once_cell from 1.20.3 to 1.21.1 ([#5629])
- build(deps): bump uuid from 1.15.1 to 1.16.0 ([#5628])
- build(deps): bump celes from 2.5.0 to 2.6.0 ([#5627])
- build(deps): bump http from 1.2.0 to 1.3.1 ([#5626])
- build(deps): bump humantime from 2.1.0 to 2.2.0 ([#5625])
- build(deps): bump the patch-updates group with 8 updates ([#5624])
- build(deps): bump @babel/runtime from 7.16.3 to 7.26.10 in /testnet-faucet ([#5621])
- Feature/paginated ticketbooks challenge ([#5619])
- build(deps-dev): bump webpack from 5.77.0 to 5.98.0 in /wasm/client/internal-dev ([#5615])
- build(deps-dev): bump ws from 8.13.0 to 8.18.1 in /wasm/client/internal-dev ([#5614])
- build(deps): bump golang.org/x/net from 0.23.0 to 0.36.0 in /wasm/mix-fetch/go-mix-conn ([#5613])
- build(deps): bump braces from 3.0.2 to 3.0.3 in /sdk/typescript/packages/mix-fetch-node ([#5612])
- Wireguard exit policies (and tests) ([#5557])
- Explorer V2 ([#5548])
- Clean stale partially received buffers ([#5536])
- Corrected typos ([#5497])
- build(deps): bump @octokit/plugin-paginate-rest and @actions/github in /.github/actions/nym-hash-releases/src ([#5488])
- feature: upgrade cosmwasm to 2.2 ([#5479])
- build(deps): bump store2 from 2.14.3 to 2.14.4 ([#5391])
- build(deps): bump nanoid from 3.3.7 to 3.3.8 in /documentation/docs ([#5335])
- build(deps): bump next from 13.5.7 to 14.2.15 in /documentation/docs ([#5281])
- Bump http-proxy-middleware from 2.0.6 to 2.0.7 ([#5019])
[#5660]: https://github.com/nymtech/nym/pull/5660
[#5656]: https://github.com/nymtech/nym/pull/5656
[#5654]: https://github.com/nymtech/nym/pull/5654
[#5651]: https://github.com/nymtech/nym/pull/5651
[#5649]: https://github.com/nymtech/nym/pull/5649
[#5646]: https://github.com/nymtech/nym/pull/5646
[#5644]: https://github.com/nymtech/nym/pull/5644
[#5642]: https://github.com/nymtech/nym/pull/5642
[#5639]: https://github.com/nymtech/nym/pull/5639
[#5638]: https://github.com/nymtech/nym/pull/5638
[#5636]: https://github.com/nymtech/nym/pull/5636
[#5632]: https://github.com/nymtech/nym/pull/5632
[#5631]: https://github.com/nymtech/nym/pull/5631
[#5630]: https://github.com/nymtech/nym/pull/5630
[#5629]: https://github.com/nymtech/nym/pull/5629
[#5628]: https://github.com/nymtech/nym/pull/5628
[#5627]: https://github.com/nymtech/nym/pull/5627
[#5626]: https://github.com/nymtech/nym/pull/5626
[#5625]: https://github.com/nymtech/nym/pull/5625
[#5624]: https://github.com/nymtech/nym/pull/5624
[#5621]: https://github.com/nymtech/nym/pull/5621
[#5619]: https://github.com/nymtech/nym/pull/5619
[#5615]: https://github.com/nymtech/nym/pull/5615
[#5614]: https://github.com/nymtech/nym/pull/5614
[#5613]: https://github.com/nymtech/nym/pull/5613
[#5612]: https://github.com/nymtech/nym/pull/5612
[#5557]: https://github.com/nymtech/nym/pull/5557
[#5548]: https://github.com/nymtech/nym/pull/5548
[#5536]: https://github.com/nymtech/nym/pull/5536
[#5497]: https://github.com/nymtech/nym/pull/5497
[#5488]: https://github.com/nymtech/nym/pull/5488
[#5479]: https://github.com/nymtech/nym/pull/5479
[#5391]: https://github.com/nymtech/nym/pull/5391
[#5335]: https://github.com/nymtech/nym/pull/5335
[#5281]: https://github.com/nymtech/nym/pull/5281
[#5019]: https://github.com/nymtech/nym/pull/5019
## [2025.5-chokito] (2025-03-18)
- build(deps): bump braces from 3.0.2 to 3.0.3 in /sdk/typescript/packages/nodejs-client ([#5611])
- build(deps-dev): bump webpack-dev-middleware from 5.3.3 to 5.3.4 in /wasm/client/internal-dev ([#5610])
- Export lane queue lengths in sdk ([#5609])
- Chore/more payment watcher debug endpoints ([#5608])
- build(deps): bump @babel/helpers from 7.24.4 to 7.26.10 ([#5606])
- Chore/update bls12 381 fork ([#5605])
- chore: change auth v2 timestamp skew and allow values from the future ([#5604])
- Chore/payment watcher debug endpoints ([#5601])
- Allow resetting all SURB sender tags ([#5600])
- introduce internal tool for checking signer status ([#5598])
- build(deps-dev): bump webpack from 5.77.0 to 5.98.0 in /wasm/mix-fetch/internal-dev ([#5597])
- build(deps): bump body-parser and express in /wasm/mix-fetch/internal-dev ([#5596])
- build(deps): bump serve-static and express in /wasm/mix-fetch/internal-dev ([#5594])
- build(deps-dev): bump ws from 8.13.0 to 8.18.1 in /wasm/mix-fetch/internal-dev ([#5593])
- build(deps): bump cookie and express in /wasm/client/internal-dev ([#5592])
- build(deps): bump cookie and express in /wasm/mix-fetch/internal-dev ([#5591])
- build(deps): bump braces from 3.0.2 to 3.0.3 in /wasm/zknym-lib/internal-dev ([#5590])
- build(deps): bump webpack-dev-middleware from 5.3.3 to 5.3.4 in /wasm/zknym-lib/internal-dev ([#5589])
- build(deps): bump tempfile from 3.17.1 to 3.18.0 ([#5588])
- build(deps): bump tokio from 1.43.0 to 1.44.0 ([#5587])
- build(deps): bump the patch-updates group with 8 updates ([#5585])
- build(deps): bump ring from 0.17.9 to 0.17.13 ([#5583])
- delete double memo field in send modal ([#5578])
- Server Side internal DoT/DoH opt out ([#5577])
- Rust SDK SURB example: change hardcoded file to tempdir ([#5576])
- Add /v3/nym-nodes ([#5569])
- chore: start sending v2 sphinx packets ([#5554])
- build(deps): bump the patch-updates group across 1 directory with 14 updates ([#5549])
- build(deps): bump uuid from 1.13.2 to 1.15.1 ([#5542])
- build(deps): bump rs_merkle from 1.4.2 to 1.5.0 ([#5541])
- feature: v2 authentication request ([#5537])
- Set RUSTUP_PERMIT_COPY_RENAME ([#5533])
- feature: disallow routing mix packets to nodes not present in the topology ([#5526])
- Make "Memo" visible per default on send NYM ([#5524])
- feat: make sure any terminated task kills the watcher and write run info to db ([#5517])
- Another total_stake SQL fix ([#5516])
- Fix total_stake on SQL update ([#5514])
- build(deps): bump flate2 from 1.0.35 to 1.1.0 ([#5510])
- build(deps): bump itertools from 0.13.0 to 0.14.0 ([#5509])
- build(deps): bump the patch-updates group with 2 updates ([#5505])
- Treat gateways as Nym Nodes ([#5504])
- Update version in Cargo.toml ([#5503])
- feat: use ct_eq for checking bearer token ([#5501])
- Add extra args for the probe ([#5499])
- Fix stats bug & remove HM caching ([#5495])
- fix: Cargo.lock for contracts ([#5489])
- Display error messages if IPv4 or IPv6 address not found on nymtun0 ([#5465])
[#5611]: https://github.com/nymtech/nym/pull/5611
[#5610]: https://github.com/nymtech/nym/pull/5610
[#5609]: https://github.com/nymtech/nym/pull/5609
[#5608]: https://github.com/nymtech/nym/pull/5608
[#5606]: https://github.com/nymtech/nym/pull/5606
[#5605]: https://github.com/nymtech/nym/pull/5605
[#5604]: https://github.com/nymtech/nym/pull/5604
[#5601]: https://github.com/nymtech/nym/pull/5601
[#5600]: https://github.com/nymtech/nym/pull/5600
[#5598]: https://github.com/nymtech/nym/pull/5598
[#5597]: https://github.com/nymtech/nym/pull/5597
[#5596]: https://github.com/nymtech/nym/pull/5596
[#5594]: https://github.com/nymtech/nym/pull/5594
[#5593]: https://github.com/nymtech/nym/pull/5593
[#5592]: https://github.com/nymtech/nym/pull/5592
[#5591]: https://github.com/nymtech/nym/pull/5591
[#5590]: https://github.com/nymtech/nym/pull/5590
[#5589]: https://github.com/nymtech/nym/pull/5589
[#5588]: https://github.com/nymtech/nym/pull/5588
[#5587]: https://github.com/nymtech/nym/pull/5587
[#5585]: https://github.com/nymtech/nym/pull/5585
[#5583]: https://github.com/nymtech/nym/pull/5583
[#5578]: https://github.com/nymtech/nym/pull/5578
[#5577]: https://github.com/nymtech/nym/pull/5577
[#5576]: https://github.com/nymtech/nym/pull/5576
[#5569]: https://github.com/nymtech/nym/pull/5569
[#5554]: https://github.com/nymtech/nym/pull/5554
[#5549]: https://github.com/nymtech/nym/pull/5549
[#5542]: https://github.com/nymtech/nym/pull/5542
[#5541]: https://github.com/nymtech/nym/pull/5541
[#5537]: https://github.com/nymtech/nym/pull/5537
[#5533]: https://github.com/nymtech/nym/pull/5533
[#5526]: https://github.com/nymtech/nym/pull/5526
[#5524]: https://github.com/nymtech/nym/pull/5524
[#5517]: https://github.com/nymtech/nym/pull/5517
[#5516]: https://github.com/nymtech/nym/pull/5516
[#5514]: https://github.com/nymtech/nym/pull/5514
[#5510]: https://github.com/nymtech/nym/pull/5510
[#5509]: https://github.com/nymtech/nym/pull/5509
[#5505]: https://github.com/nymtech/nym/pull/5505
[#5504]: https://github.com/nymtech/nym/pull/5504
[#5503]: https://github.com/nymtech/nym/pull/5503
[#5501]: https://github.com/nymtech/nym/pull/5501
[#5499]: https://github.com/nymtech/nym/pull/5499
[#5495]: https://github.com/nymtech/nym/pull/5495
[#5489]: https://github.com/nymtech/nym/pull/5489
[#5465]: https://github.com/nymtech/nym/pull/5465
## [2025.4-dorina-patched] (2025-03-06)
- use legacy crypto for constructing SURB headers ([#5579])
@@ -160,7 +334,7 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
- 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: correctly handle ignore 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])
@@ -181,7 +355,7 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
- 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])
- Add dependabot assigns 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])
@@ -234,7 +408,7 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
## [2025.1-reeses] (2025-01-15)
- Feture/legacy alert ([#5346])
- Feature, Future/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])
@@ -314,7 +488,7 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
## [2024.14-crunch-patched] (2024-12-17)
- Fixes an issue to allow previously registred clients to connect to latest nym-nodes
- Fixes an issue to allow previously registered clients to connect to latest nym-nodes
- Fixes compatibility issues between nym-nodes and older clients
## [2024.14-crunch] (2024-12-11)
@@ -322,7 +496,7 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
- Merge/release/2024.14-crunch ([#5242])
- bugfix: added explicit openapi servers to account for route prefixes ([#5237])
- Further config score adjustments ([#5225])
- feature: remve any filtering on node semver ([#5224])
- feature: remove any filtering on node semver ([#5224])
- Backport #5218 ([#5220])
- Derive serialize for UserAgent (#5210) ([#5217])
- dont consider legacy nodes for rewarded set selection ([#5215])
@@ -501,7 +675,7 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
- bugfix/feature: added NymApiClient method to get all skimmed nodes ([#5062])
- Merge1/release/2024.13 magura ([#5061])
- added hacky routes to return nymnodes alongside legacy nodes ([#5051])
- bugfix: mark migrated gateways as rewarded in the previous epoch in case theyre in the rewarded set ([#5049])
- bugfix: mark migrated gateways as rewarded in the previous epoch in case they're, their, there in the rewarded set ([#5049])
- bugfix: adjust runtime storage migration ([#5047])
- bugfix: supersede 'cb13be27f8f61d9ae74d924e85d2e6787895eb14' by using… ([#5046])
- bugfix: restore default http port for nym-api ([#5045])
@@ -562,7 +736,7 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
- Fix broken build after merge ([#4937])
- bugfix: correctly paginate through 'search_tx' endpoint ([#4936])
- Add more conversions for responses of authenticator messages ([#4929])
- Directory Sevices v2.1 ([#4903])
- Directory Services, Devices v2.1 ([#4903])
- Migrate Legacy Node (Frontend) ([#4826])
- Fix critical issues SI84 and SI85 from Cure53 ([#4758])
@@ -946,7 +1120,7 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
- Remove stale peers ([#4640])
- Add generic wg private network routing ([#4636])
- Feature/new node endpoints ([#4635])
- standarised ContractBuildInformation and added it to all contracts ([#4631])
- standardised ContractBuildInformation and added it to all contracts ([#4631])
- validate nym-node public ips on startup ([#4630])
- Bump defguard wg ([#4625])
- Fix cargo warnings ([#4624])
@@ -1567,7 +1741,7 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
- clean-up nym-api startup arguments/flags to use clap 3 and its macro-derived arguments ([#2772])
- renamed all references to validator_api to nym_api
- renamed all references to nymd to nyxd ([#2696])
- all-binaries: standarised argument names (note: old names should still be accepted) ([#2762]
- all-binaries: standardised argument names (note: old names should still be accepted) ([#2762]
### Fixed
@@ -2072,7 +2246,7 @@ The release also include some additional work for distributed key generation in
- Explorer UI tests missing data-testid [\#903](https://github.com/nymtech/nym/pull/903) ([tommyv1987](https://github.com/tommyv1987))
- Fix up Nym-Wallet README.md [\#899](https://github.com/nymtech/nym/pull/899) ([tommyv1987](https://github.com/tommyv1987))
- Feature/batch delegator rewarding [\#898](https://github.com/nymtech/nym/pull/898) ([jstuczyn](https://github.com/jstuczyn))
- Bug mapp nodemap [\#897](https://github.com/nymtech/nym/pull/897) ([Aid19801](https://github.com/Aid19801))
- Bug map nodemap [\#897](https://github.com/nymtech/nym/pull/897) ([Aid19801](https://github.com/Aid19801))
- Bug fix/macos keyboard shortcuts [\#896](https://github.com/nymtech/nym/pull/896) ([fmtabbara](https://github.com/fmtabbara))
- Add a Mobile Nav to the Network Explorer [\#895](https://github.com/nymtech/nym/pull/895) ([Aid19801](https://github.com/Aid19801))
- Only use ts-rs in tests [\#894](https://github.com/nymtech/nym/pull/894) ([durch](https://github.com/durch))
Generated
+462 -857
View File
File diff suppressed because it is too large Load Diff
+27 -30
View File
@@ -32,9 +32,8 @@ members = [
"common/client-libs/validator-client",
"common/commands",
"common/config",
"common/cosmwasm-smart-contracts/coconut-bandwidth-contract",
"common/cosmwasm-smart-contracts/coconut-dkg",
"common/cosmwasm-smart-contracts/contracts-common",
"common/cosmwasm-smart-contracts/contracts-common", "common/cosmwasm-smart-contracts/easy_addr",
"common/cosmwasm-smart-contracts/ecash-contract",
"common/cosmwasm-smart-contracts/group-contract",
"common/cosmwasm-smart-contracts/mixnet-contract",
@@ -98,9 +97,9 @@ members = [
"common/wireguard",
"common/wireguard-types",
"documentation/autodoc",
"explorer-api",
"explorer-api/explorer-api-requests",
"explorer-api/explorer-client",
# "explorer-api",
# "explorer-api/explorer-api-requests",
# "explorer-api/explorer-client",
"gateway",
"integrations/bity",
"nym-api",
@@ -137,7 +136,7 @@ members = [
"tools/internal/testnet-manager",
"tools/internal/testnet-manager",
"tools/internal/testnet-manager/dkg-bypass-contract",
"tools/internal/testnet-manager/dkg-bypass-contract",
"tools/internal/testnet-manager/dkg-bypass-contract", "tools/internal/validator-status-check",
"tools/nym-cli",
"tools/nym-id-cli",
"tools/nym-nr-query",
@@ -153,7 +152,6 @@ members = [
default-members = [
"clients/native",
"clients/socks5",
"explorer-api",
"nym-api",
"nym-credential-proxy/nym-credential-proxy",
"nym-node",
@@ -194,7 +192,7 @@ ammonia = "4"
anyhow = "1.0.97"
arc-swap = "1.7.1"
argon2 = "0.5.0"
async-trait = "0.1.87"
async-trait = "0.1.88"
axum = "0.7.5"
axum-client-ip = "0.6.1"
axum-extra = "0.9.4"
@@ -211,13 +209,13 @@ bs58 = "0.5.1"
bytecodec = "0.4.15"
bytes = "1.10.1"
cargo_metadata = "0.18.1"
celes = "2.5.0"
celes = "2.6.0"
cfg-if = "1.0.0"
chacha20 = "0.9.0"
chacha20poly1305 = "0.10.1"
chrono = "0.4.40"
cipher = "0.4.3"
clap = "4.5.31"
clap = "4.5.32"
clap_complete = "4.5"
clap_complete_fig = "4.5"
colored = "2.2"
@@ -242,7 +240,7 @@ dotenvy = "0.15.6"
ecdsa = "0.16"
ed25519-dalek = "2.1"
encoding_rs = "0.8.35"
env_logger = "0.11.6"
env_logger = "0.11.7"
envy = "0.4"
etherparse = "0.13.0"
eyre = "0.6.9"
@@ -264,7 +262,7 @@ http = "1"
http-body-util = "0.1"
httpcodec = "0.2.3"
human-repr = "1.1.0"
humantime = "2.1.0"
humantime = "2.2.0"
humantime-serde = "1.1.1"
hyper = "1.6.0"
hyper-util = "0.1"
@@ -285,7 +283,7 @@ moka = { version = "0.12", features = ["future"] }
nix = "0.27.1"
notify = "5.1.0"
okapi = "0.7.0"
once_cell = "1.20.3"
once_cell = "1.21.1"
opentelemetry = "0.19.0"
opentelemetry-jaeger = "0.18.0"
parking_lot = "0.12.3"
@@ -331,7 +329,7 @@ syn = "1"
sysinfo = "0.33.0"
tap = "1.0.1"
tar = "0.4.44"
tempfile = "3.18"
tempfile = "3.19"
thiserror = "2.0"
time = "0.3.39"
tokio = "1.44"
@@ -340,7 +338,7 @@ 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.13"
tokio-util = "0.7.14"
toml = "0.8.20"
tower = "0.5.2"
tower-http = "0.5.2"
@@ -362,7 +360,7 @@ vergen = { version = "=8.3.1", default-features = false }
walkdir = "2"
wasm-bindgen-test = "0.3.49"
x25519-dalek = "2.0.0"
zeroize = "1.6.0"
zeroize = "1.7.0"
prometheus = { version = "0.13.0" }
@@ -370,25 +368,24 @@ prometheus = { version = "0.13.0" }
# unfortunately until https://github.com/zkcrypto/bls12_381/issues/10 is resolved, we have to rely on the fork
# as we need to be able to serialize Gt so that we could create the lookup table for baby-step-giant-step algorithm
# plus to make our live easier we need serde support from https://github.com/zkcrypto/bls12_381/pull/125
bls12_381 = { git = "https://github.com/jstuczyn/bls12_381", default-features = false, branch = "temp/experimental-serdect" }
bls12_381 = { git = "https://github.com/jstuczyn/bls12_381", default-features = false, branch = "temp/experimental-serdect-updated" }
group = { version = "0.13.0", default-features = false }
ff = { version = "0.13.1", default-features = false }
subtle = "2.5.0"
# cosmwasm-related
cosmwasm-schema = "=1.4.3"
cosmwasm-std = "=1.4.3"
# use 0.5.0 as that's the version used by cosmwasm-std 1.4.3
cosmwasm-schema = "=2.2.2"
cosmwasm-std = "=2.2.2"
# use 1.0.1 as that's the version used by cosmwasm-std 2.2.1
# (and ideally we don't want to pull the same dependency twice)
serde-json-wasm = "=0.5.0"
cosmwasm-storage = "=1.4.3"
serde-json-wasm = "=1.0.1"
# same version as used by cosmwasm
cw-utils = "=1.0.1"
cw-storage-plus = "=1.2.0"
cw2 = { version = "=1.1.2" }
cw3 = { version = "=1.1.2" }
cw4 = { version = "=1.1.2" }
cw-controllers = { version = "=1.1.0" }
cw-utils = "=2.0.0"
cw-storage-plus = "=2.0.0"
cw2 = { version = "=2.0.0" }
cw3 = { version = "=2.0.0" }
cw4 = { version = "=2.0.0" }
cw-controllers = { version = "=2.0.0" }
# cosmrs-related
bip32 = { version = "0.5.3", default-features = false }
@@ -403,7 +400,7 @@ prost = { version = "0.13", default-features = false }
gloo-utils = "0.2.0"
gloo-net = "0.6.0"
indexed_db_futures = "0.6.0"
indexed_db_futures = "0.6.1"
js-sys = "0.3.76"
serde-wasm-bindgen = "0.6.5"
tsify = "0.4.5"
@@ -447,4 +444,4 @@ dbg_macro = "deny"
exit = "deny"
panic = "deny"
unimplemented = "deny"
unreachable = "deny"
unreachable = "deny"
+8 -18
View File
@@ -133,17 +133,22 @@ clippy: sdk-wasm-lint
# Build contracts ready for deploy
# -----------------------------------------------------------------------------
CONTRACTS=vesting_contract mixnet_contract nym_ecash
CONTRACTS=vesting_contract mixnet_contract nym_ecash cw3_flex_multisig cw4_group nym_coconut_dkg
CONTRACTS_WASM=$(addsuffix .wasm, $(CONTRACTS))
CONTRACTS_OUT_DIR=contracts/target/wasm32-unknown-unknown/release
contracts: build-release-contracts wasm-opt-contracts
contracts: build-release-contracts wasm-opt-contracts cosmwasm-check-contracts
wasm-opt-contracts:
for contract in $(CONTRACTS_WASM); do \
wasm-opt --signext-lowering -Os $(CONTRACTS_OUT_DIR)/$$contract -o $(CONTRACTS_OUT_DIR)/$$contract; \
done
cosmwasm-check-contracts:
for contract in $(CONTRACTS_WASM); do \
cosmwasm-check $(CONTRACTS_OUT_DIR)/$$contract; \
done
# Consider adding 's' to make plural consistent (beware: used in github workflow)
contract-schema:
$(MAKE) -C contracts schema
@@ -152,18 +157,9 @@ contract-schema:
# Convenience targets for crates that are already part of the main workspace
# -----------------------------------------------------------------------------
build-explorer-api:
cargo build -p explorer-api
build-nym-cli:
cargo build -p nym-cli --release
build-nym-gateway:
cargo build -p nym-gateway --release
build-nym-mixnode:
cargo build -p nym-mixnode --release
# -----------------------------------------------------------------------------
# Misc
# -----------------------------------------------------------------------------
@@ -176,13 +172,7 @@ run-api-tests:
cd nym-api/tests/functional_test && yarn test:qa
# Build debian package, and update PPA
deb-mixnode: build-nym-mixnode
cargo deb -p nym-mixnode
deb-gateway: build-nym-gateway
cargo deb -p nym-gateway
deb-cli: build-nym-cli
cargo deb -p nym-cli
deb: deb-mixnode deb-gateway deb-cli
deb: deb-cli
+10
View File
@@ -67,3 +67,13 @@ As a general approach, licensing is as follows this pattern:
- documentation is Apache 2.0 or CC0-1.0
Nym Node Operators and Validators Terms and Conditions can be found [here](https://nym.com/operators-validators-terms).
## Getting Started
```bash
yarn install
```
```bash
yarn build
```
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "nym-client"
version = "1.1.50"
version = "1.1.52"
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jędrzej Stuczyński <andrew@nymtech.net>"]
description = "Implementation of the Nym Client"
edition = "2021"
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "nym-socks5-client"
version = "1.1.50"
version = "1.1.52"
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"
@@ -139,6 +139,8 @@ where
let gateway_setup = GatewaySetup::New {
specification: selection_spec,
available_gateways,
#[cfg(unix)]
connection_fd_callback: None,
};
let init_details =
@@ -187,6 +187,8 @@ where
let gateway_setup = GatewaySetup::New {
specification: selection_spec,
available_gateways,
#[cfg(unix)]
connection_fd_callback: None,
};
let init_details =
@@ -28,6 +28,7 @@ pub enum InputMessage {
recipient: Recipient,
data: Vec<u8>,
lane: TransmissionLane,
max_retransmissions: Option<u32>,
},
/// Creates a message used for a duplex anonymous communication where the recipient
@@ -43,6 +44,7 @@ pub enum InputMessage {
data: Vec<u8>,
reply_surbs: u32,
lane: TransmissionLane,
max_retransmissions: Option<u32>,
},
/// Attempt to use our internally received and stored `ReplySurb` to send the message back
@@ -53,6 +55,7 @@ pub enum InputMessage {
recipient_tag: AnonymousSenderTag,
data: Vec<u8>,
lane: TransmissionLane,
max_retransmissions: Option<u32>,
},
MessageWrapper {
@@ -92,6 +95,7 @@ impl InputMessage {
recipient,
data,
lane,
max_retransmissions: None,
};
if let Some(packet_type) = packet_type {
InputMessage::new_wrapper(message, packet_type)
@@ -112,28 +116,7 @@ impl InputMessage {
data,
reply_surbs,
lane,
};
if let Some(packet_type) = packet_type {
InputMessage::new_wrapper(message, packet_type)
} else {
message
}
}
// IMHO `new_anonymous` should take `mix_hops: Option<u8>` as an argument instead of creating
// this function, but that would potentially break backwards compatibility with the current API
pub fn new_anonymous_with_custom_hops(
recipient: Recipient,
data: Vec<u8>,
reply_surbs: u32,
lane: TransmissionLane,
packet_type: Option<PacketType>,
) -> Self {
let message = InputMessage::Anonymous {
recipient,
data,
reply_surbs,
lane,
max_retransmissions: None,
};
if let Some(packet_type) = packet_type {
InputMessage::new_wrapper(message, packet_type)
@@ -152,6 +135,7 @@ impl InputMessage {
recipient_tag,
data,
lane,
max_retransmissions: None,
};
if let Some(packet_type) = packet_type {
InputMessage::new_wrapper(message, packet_type)
@@ -169,4 +153,34 @@ impl InputMessage {
InputMessage::MessageWrapper { message, .. } => message.lane(),
}
}
pub fn set_max_retransmissions(&mut self, max_retransmissions: u32) -> &mut Self {
match self {
InputMessage::Regular {
max_retransmissions: m,
..
}
| InputMessage::Anonymous {
max_retransmissions: m,
..
}
| InputMessage::Reply {
max_retransmissions: m,
..
} => {
*m = Some(max_retransmissions);
}
InputMessage::Premade { .. } => {}
InputMessage::MessageWrapper { message, .. } => {
message.set_max_retransmissions(max_retransmissions);
}
}
self
}
pub fn with_max_retransmissions(mut self, max_retransmissions: u32) -> Self {
self.set_max_retransmissions(max_retransmissions);
self
}
}
@@ -52,7 +52,7 @@ impl MixTrafficController {
let (message_sender, message_receiver) =
tokio::sync::mpsc::channel(MIX_MESSAGE_RECEIVER_BUFFER_SIZE);
let (client_sender, client_receiver) = tokio::sync::mpsc::channel(1);
let (client_sender, client_receiver) = tokio::sync::mpsc::channel(8);
(
MixTrafficController {
@@ -77,7 +77,7 @@ impl MixTrafficController {
) {
let (message_sender, message_receiver) =
tokio::sync::mpsc::channel(MIX_MESSAGE_RECEIVER_BUFFER_SIZE);
let (client_sender, client_receiver) = tokio::sync::mpsc::channel(1);
let (client_sender, client_receiver) = tokio::sync::mpsc::channel(8);
(
MixTrafficController {
gateway_transceiver,
@@ -222,9 +222,6 @@ impl ActionController {
// note: when the entry expires it's automatically removed from pending_acks_timers
fn handle_expired_ack_timer(&mut self, expired_ack: Expired<FragmentIdentifier>) {
// I'm honestly not sure how to handle it, because getting it means other things in our
// system are already misbehaving. If we ever see this panic, then I guess we should worry
// about it. Perhaps just reschedule it at later point?
let frag_id = expired_ack.into_inner();
trace!("{frag_id} has expired");
@@ -65,11 +65,12 @@ where
recipient_tag: AnonymousSenderTag,
data: Vec<u8>,
lane: TransmissionLane,
max_retransmissions: Option<u32>,
) {
// offload reply handling to the dedicated task
if let Err(err) = self
.reply_controller_sender
.send_reply(recipient_tag, data, lane)
if let Err(err) =
self.reply_controller_sender
.send_reply(recipient_tag, data, lane, max_retransmissions)
{
if !self.task_client.is_shutdown_poll() {
error!("failed to send a reply - {err}");
@@ -83,10 +84,11 @@ where
content: Vec<u8>,
lane: TransmissionLane,
packet_type: PacketType,
max_retransmissions: Option<u32>,
) {
if let Err(err) = self
.message_handler
.try_send_plain_message(recipient, content, lane, packet_type)
.try_send_plain_message(recipient, content, lane, packet_type, max_retransmissions)
.await
{
warn!("failed to send a plain message - {err}")
@@ -100,10 +102,18 @@ where
reply_surbs: u32,
lane: TransmissionLane,
packet_type: PacketType,
max_retransmissions: Option<u32>,
) {
if let Err(err) = self
.message_handler
.try_send_message_with_reply_surbs(recipient, content, reply_surbs, lane, packet_type)
.try_send_message_with_reply_surbs(
recipient,
content,
reply_surbs,
lane,
packet_type,
max_retransmissions,
)
.await
{
warn!("failed to send a repliable message - {err}")
@@ -116,25 +126,42 @@ where
recipient,
data,
lane,
max_retransmissions,
} => {
self.handle_plain_message(recipient, data, lane, PacketType::Mix)
.await
self.handle_plain_message(
recipient,
data,
lane,
PacketType::Mix,
max_retransmissions,
)
.await
}
InputMessage::Anonymous {
recipient,
data,
reply_surbs,
lane,
max_retransmissions,
} => {
self.handle_repliable_message(recipient, data, reply_surbs, lane, PacketType::Mix)
.await
self.handle_repliable_message(
recipient,
data,
reply_surbs,
lane,
PacketType::Mix,
max_retransmissions,
)
.await
}
InputMessage::Reply {
recipient_tag,
data,
lane,
max_retransmissions,
} => {
self.handle_reply(recipient_tag, data, lane).await;
self.handle_reply(recipient_tag, data, lane, max_retransmissions)
.await;
}
InputMessage::Premade { msgs, lane } => self.handle_premade_packets(msgs, lane).await,
InputMessage::MessageWrapper {
@@ -145,25 +172,42 @@ where
recipient,
data,
lane,
max_retransmissions,
} => {
self.handle_plain_message(recipient, data, lane, packet_type)
.await
self.handle_plain_message(
recipient,
data,
lane,
packet_type,
max_retransmissions,
)
.await
}
InputMessage::Anonymous {
recipient,
data,
reply_surbs,
lane,
max_retransmissions,
} => {
self.handle_repliable_message(recipient, data, reply_surbs, lane, packet_type)
.await
self.handle_repliable_message(
recipient,
data,
reply_surbs,
lane,
packet_type,
max_retransmissions,
)
.await
}
InputMessage::Reply {
recipient_tag,
data,
lane,
max_retransmissions,
} => {
self.handle_reply(recipient_tag, data, lane).await;
self.handle_reply(recipient_tag, data, lane, max_retransmissions)
.await;
}
InputMessage::Premade { msgs, lane } => {
self.handle_premade_packets(msgs, lane).await
@@ -72,6 +72,7 @@ pub struct PendingAcknowledgement {
delay: SphinxDelay,
destination: PacketDestination,
retransmissions: u32,
max_retransmissions: Option<u32>,
}
impl PendingAcknowledgement {
@@ -80,12 +81,14 @@ impl PendingAcknowledgement {
message_chunk: Fragment,
delay: SphinxDelay,
recipient: Recipient,
max_retransmissions: Option<u32>,
) -> Self {
PendingAcknowledgement {
message_chunk,
delay,
destination: PacketDestination::KnownRecipient(recipient.into()),
retransmissions: 0,
max_retransmissions,
}
}
@@ -94,6 +97,7 @@ impl PendingAcknowledgement {
delay: SphinxDelay,
recipient_tag: AnonymousSenderTag,
extra_surb_request: bool,
max_retransmissions: Option<u32>,
) -> Self {
PendingAcknowledgement {
message_chunk,
@@ -103,6 +107,7 @@ impl PendingAcknowledgement {
extra_surb_request,
},
retransmissions: 0,
max_retransmissions,
}
}
@@ -118,6 +123,18 @@ impl PendingAcknowledgement {
self.delay = new_delay;
self.retransmissions += 1;
}
pub(crate) fn reached_max_retransmissions(
&self,
global_max_retransmissions: Option<u32>,
) -> bool {
let reached_local_max = self
.max_retransmissions
.is_some_and(|limit| self.retransmissions >= limit);
let reached_global_max =
global_max_retransmissions.is_some_and(|limit| self.retransmissions >= limit);
reached_local_max || reached_global_max
}
}
/// AcknowledgementControllerConnectors represents set of channels for communication with
@@ -79,17 +79,15 @@ where
let frag_id = timed_out_ack.message_chunk.fragment_identifier();
if let Some(limit) = self.maximum_retransmissions {
if timed_out_ack.retransmissions >= limit {
warn!("reached maximum number of allowed retransmissions for the packet");
if let Err(err) = self
.action_sender
.unbounded_send(Action::new_remove(frag_id))
{
error!("Failed to send remove action to the controller: {err}");
}
return;
if timed_out_ack.reached_max_retransmissions(self.maximum_retransmissions) {
debug!("reached maximum number of allowed retransmissions for the packet");
if let Err(err) = self
.action_sender
.unbounded_send(Action::new_remove(frag_id))
{
error!("Failed to send remove action to the controller: {err}");
}
return;
}
let maybe_prepared_fragment = match &timed_out_ack.destination {
@@ -6,6 +6,7 @@ use crate::client::real_messages_control::real_traffic_stream::{
BatchRealMessageSender, RealMessage,
};
use crate::client::real_messages_control::{AckActionSender, Action};
use crate::client::replies::reply_controller::MaxRetransmissions;
use crate::client::replies::reply_storage::{ReceivedReplySurbsMap, SentReplyKeys, UsedSenderTags};
use crate::client::topology_control::{TopologyAccessor, TopologyReadPermit};
use log::{debug, error, info, trace, warn};
@@ -142,6 +143,12 @@ impl Config {
}
}
#[derive(Clone)]
pub(crate) struct FragmentWithMaxRetransmissions {
pub(crate) fragment: Fragment,
pub(crate) max_retransmissions: MaxRetransmissions,
}
#[derive(Clone)]
pub(crate) struct MessageHandler<R> {
config: Config,
@@ -198,10 +205,10 @@ where
trace!("we already had sender tag for {recipient}");
existing
} else {
info!("creating new sender tag for {recipient}");
debug!("creating new sender tag for {recipient}");
let new_tag = AnonymousSenderTag::new_random(&mut self.rng);
self.tag_storage.insert_new(recipient, new_tag);
info!("we'll be using {new_tag} for all anonymous messages sent to {recipient}");
info!("using {new_tag} for all anonymous messages sent to {recipient}");
new_tag
}
}
@@ -294,8 +301,14 @@ where
Some(chunk.fragment_identifier()),
);
let delay = prepared_fragment.total_delay;
let pending_ack =
PendingAcknowledgement::new_anonymous(chunk, delay, target, is_extra_surb_request);
let max_retransmissions = None;
let pending_ack = PendingAcknowledgement::new_anonymous(
chunk,
delay,
target,
is_extra_surb_request,
max_retransmissions,
);
let lane = if is_extra_surb_request {
TransmissionLane::ReplySurbRequest
@@ -350,7 +363,7 @@ where
pub(crate) async fn try_send_reply_chunks_on_lane(
&mut self,
target: AnonymousSenderTag,
fragments: Vec<Fragment>,
fragments: Vec<FragmentWithMaxRetransmissions>,
reply_surbs: Vec<ReplySurb>,
lane: TransmissionLane,
) -> Result<(), SurbWrappedPreparationError> {
@@ -367,12 +380,12 @@ where
pub(crate) async fn try_send_reply_chunks(
&mut self,
target: AnonymousSenderTag,
fragments: Vec<(TransmissionLane, Fragment)>,
fragments: Vec<(TransmissionLane, FragmentWithMaxRetransmissions)>,
reply_surbs: Vec<ReplySurb>,
) -> Result<(), SurbWrappedPreparationError> {
let prepared_fragments = self
.prepare_reply_chunks_for_sending(
fragments.iter().map(|(_, f)| f.clone()).collect(),
fragments.iter().map(|(_, f)| f.fragment.clone()).collect(),
reply_surbs,
)
.await?;
@@ -382,12 +395,21 @@ where
for (raw, prepared) in fragments.into_iter().zip(prepared_fragments.into_iter()) {
let lane = raw.0;
let fragment = raw.1;
let FragmentWithMaxRetransmissions {
fragment,
max_retransmissions,
} = raw.1;
let real_message =
RealMessage::new(prepared.mix_packet, Some(prepared.fragment_identifier));
let delay = prepared.total_delay;
let pending_ack = PendingAcknowledgement::new_anonymous(fragment, delay, target, false);
let pending_ack = PendingAcknowledgement::new_anonymous(
fragment,
delay,
target,
false,
max_retransmissions,
);
let entry = to_forward.entry(lane).or_default();
entry.push(real_message);
@@ -416,10 +438,17 @@ where
message: Vec<u8>,
lane: TransmissionLane,
packet_type: PacketType,
max_retransmissions: Option<u32>,
) -> Result<(), PreparationError> {
let message = NymMessage::new_plain(message);
self.try_split_and_send_non_reply_message(message, recipient, lane, packet_type)
.await
self.try_split_and_send_non_reply_message(
message,
recipient,
lane,
packet_type,
max_retransmissions,
)
.await
}
pub(crate) async fn try_split_and_send_non_reply_message(
@@ -428,6 +457,7 @@ where
recipient: Recipient,
lane: TransmissionLane,
packet_type: PacketType,
max_retransmissions: Option<u32>,
) -> Result<(), PreparationError> {
debug!("Sending non-reply message with packet type {packet_type}");
// TODO: I really dislike existence of this assertion, it implies code has to be re-organised
@@ -467,7 +497,8 @@ where
Some(fragment.fragment_identifier()),
);
let delay = prepared_fragment.total_delay;
let pending_ack = PendingAcknowledgement::new_known(fragment, delay, recipient);
let pending_ack =
PendingAcknowledgement::new_known(fragment, delay, recipient, max_retransmissions);
real_messages.push(real_message);
pending_acks.push(pending_ack);
@@ -495,11 +526,15 @@ where
reply_surbs,
));
// When sending SURBs we want to retransmit
let max_retransmissions = None;
self.try_split_and_send_non_reply_message(
message,
recipient,
TransmissionLane::AdditionalReplySurbs,
packet_type,
max_retransmissions,
)
.await?;
@@ -516,6 +551,7 @@ where
num_reply_surbs: u32,
lane: TransmissionLane,
packet_type: PacketType,
max_retransmissions: Option<u32>,
) -> Result<(), SurbWrappedPreparationError> {
debug!("Sending message with reply SURBs with packet type {packet_type}");
let sender_tag = self.get_or_create_sender_tag(&recipient);
@@ -526,8 +562,14 @@ where
let message =
NymMessage::new_repliable(RepliableMessage::new_data(message, sender_tag, reply_surbs));
self.try_split_and_send_non_reply_message(message, recipient, lane, packet_type)
.await?;
self.try_split_and_send_non_reply_message(
message,
recipient,
lane,
packet_type,
max_retransmissions,
)
.await?;
log::trace!("storing {} reply keys", reply_keys.len());
self.reply_key_storage.insert_multiple(reply_keys);
@@ -153,7 +153,7 @@ impl RealMessagesController<OsRng> {
let rng = OsRng;
// create channels for inter-task communication
let (real_message_sender, real_message_receiver) = tokio::sync::mpsc::channel(1);
let (real_message_sender, real_message_receiver) = tokio::sync::mpsc::channel(8);
let (sent_notifier_tx, sent_notifier_rx) = mpsc::unbounded();
let (ack_action_tx, ack_action_rx) = mpsc::unbounded();
let ack_controller_connectors = AcknowledgementControllerConnectors::new(
@@ -23,6 +23,10 @@ use nym_statistics_common::clients::{packet_statistics::PacketStatisticsEvent, C
use nym_task::TaskClient;
use std::collections::HashSet;
use std::sync::Arc;
use std::time::{Duration, Instant};
// The interval at which we check for stale buffers
const STALE_BUFFER_CHECK_INTERVAL: Duration = Duration::from_secs(10);
// Buffer Requests to say "hey, send any reconstructed messages to this channel"
// or to say "hey, I'm going offline, don't send anything more to me. Just buffer them instead"
@@ -48,6 +52,9 @@ struct ReceivedMessagesBufferInner<R: MessageReceiver> {
recently_reconstructed: HashSet<i32>,
stats_tx: ClientStatsSender,
// Periodically check for stale buffers to clean up
last_stale_check: Instant,
}
impl<R: MessageReceiver> ReceivedMessagesBufferInner<R> {
@@ -96,9 +103,10 @@ impl<R: MessageReceiver> ReceivedMessagesBufferInner<R> {
}
None
}
_ => unreachable!(
"no other error kind should have been returned here! If so, it's a bug!"
),
_ => {
error!("unexpected error occurred during message reconstruction: {err}");
None
}
},
Ok(reconstruction_result) => match reconstruction_result {
Some((reconstructed_message, used_sets)) => {
@@ -144,6 +152,16 @@ impl<R: MessageReceiver> ReceivedMessagesBufferInner<R> {
self.recover_from_fragment(fragment_data, raw_fragment_size)
}
fn cleanup_stale_buffers(&mut self) {
let now = Instant::now();
if now - self.last_stale_check > STALE_BUFFER_CHECK_INTERVAL {
self.last_stale_check = now;
self.message_receiver
.reconstructor()
.cleanup_stale_buffers();
}
}
}
#[derive(Debug, Clone)]
@@ -172,6 +190,7 @@ impl<R: MessageReceiver> ReceivedMessagesBuffer<R> {
message_sender: None,
recently_reconstructed: HashSet::new(),
stats_tx,
last_stale_check: Instant::now(),
})),
reply_key_storage,
reply_controller_sender,
@@ -392,6 +411,11 @@ impl<R: MessageReceiver> ReceivedMessagesBuffer<R> {
}
}
// Cleanup stale buffers, if there are any fragments that simply never arrived.
// We do this here as part of handling new received fragments so that we can keep the event
// loop focused on processing new messages.
inner_guard.cleanup_stale_buffers();
drop(inner_guard);
if !completed_messages.is_empty() {
@@ -2,7 +2,9 @@
// SPDX-License-Identifier: Apache-2.0
use crate::client::real_messages_control::acknowledgement_control::PendingAcknowledgement;
use crate::client::real_messages_control::message_handler::{MessageHandler, PreparationError};
use crate::client::real_messages_control::message_handler::{
FragmentWithMaxRetransmissions, MessageHandler, PreparationError,
};
use crate::client::replies::reply_storage::CombinedReplyStorage;
use futures::channel::oneshot;
use futures::StreamExt;
@@ -10,7 +12,7 @@ use log::{debug, error, info, trace, warn};
use nym_sphinx::addressing::clients::Recipient;
use nym_sphinx::anonymous_replies::requests::AnonymousSenderTag;
use nym_sphinx::anonymous_replies::ReplySurb;
use nym_sphinx::chunking::fragment::{Fragment, FragmentIdentifier};
use nym_sphinx::chunking::fragment::FragmentIdentifier;
use nym_task::connections::{ConnectionId, TransmissionLane};
use nym_task::TaskClient;
use rand::{CryptoRng, Rng};
@@ -49,6 +51,8 @@ impl Config {
// - replies to "give additional surbs" requests
// - will reply to future heartbeats
pub type MaxRetransmissions = Option<u32>;
// TODO: this should be split into ingress and egress controllers
// because currently its trying to perform two distinct jobs
pub struct ReplyController<R> {
@@ -59,7 +63,8 @@ pub struct ReplyController<R> {
// of surbs required to send the message through
// expected_reliability: f32,
request_receiver: ReplyControllerReceiver,
pending_replies: HashMap<AnonymousSenderTag, TransmissionBuffer<Fragment>>,
pending_replies:
HashMap<AnonymousSenderTag, TransmissionBuffer<FragmentWithMaxRetransmissions>>,
/// Retransmission packets that have already timed out and are waiting for additional reply SURBs
/// so that they could be sent back to the network. Once we receive more SURBs, we should send them ASAP.
@@ -96,7 +101,7 @@ where
}
}
fn insert_pending_replies<I: IntoIterator<Item = Fragment>>(
fn insert_pending_replies<I: IntoIterator<Item = FragmentWithMaxRetransmissions>>(
&mut self,
recipient: &AnonymousSenderTag,
fragments: I,
@@ -112,7 +117,7 @@ where
fn re_insert_pending_replies(
&mut self,
recipient: &AnonymousSenderTag,
fragments: Vec<(TransmissionLane, Fragment)>,
fragments: Vec<(TransmissionLane, FragmentWithMaxRetransmissions)>,
) {
trace!("re-inserting pending replies for {recipient}");
// the buffer should ALWAYS exist at this point, if it doesn't, it's a bug...
@@ -205,6 +210,7 @@ where
recipient_tag: AnonymousSenderTag,
data: Vec<u8>,
lane: TransmissionLane,
max_retransmissions: Option<u32>,
) {
if !self
.full_reply_storage
@@ -242,7 +248,14 @@ where
.get_reply_surbs(&recipient_tag, max_to_send);
if let Some(reply_surbs) = surbs {
let to_send = fragments.drain(..max_to_send).collect::<Vec<_>>();
let to_send = fragments
.drain(..max_to_send)
.map(|f| FragmentWithMaxRetransmissions {
fragment: f,
max_retransmissions,
})
.collect::<Vec<_>>();
if let Err(err) = self
.message_handler
.try_send_reply_chunks_on_lane(
@@ -276,6 +289,13 @@ where
"buffering {no_fragments} fragments for {recipient_tag}",
no_fragments = fragments.len()
);
let fragments: Vec<_> = fragments
.into_iter()
.map(|fragment| FragmentWithMaxRetransmissions {
fragment,
max_retransmissions,
})
.collect();
self.insert_pending_replies(&recipient_tag, fragments, lane);
}
@@ -409,7 +429,7 @@ where
&mut self,
from: &AnonymousSenderTag,
amount: usize,
) -> Option<Vec<(TransmissionLane, Fragment)>> {
) -> Option<Vec<(TransmissionLane, FragmentWithMaxRetransmissions)>> {
// if possible, pop all pending replies, if not, pop only entries for which we'd have a reply surb
let total = self.pending_replies.get(from)?.total_size();
trace!("pending queue has {total} elements");
@@ -689,7 +709,11 @@ where
recipient,
message,
lane,
} => self.handle_send_reply(recipient, message, lane).await,
max_retransmissions,
} => {
self.handle_send_reply(recipient, message, lane, max_retransmissions)
.await
}
ReplyControllerMessage::AdditionalSurbs {
sender_tag,
reply_surbs,
@@ -66,12 +66,14 @@ impl ReplyControllerSender {
recipient: AnonymousSenderTag,
message: Vec<u8>,
lane: TransmissionLane,
max_retransmissions: Option<u32>,
) -> Result<(), ReplyControllerSenderError> {
self.0
.unbounded_send(ReplyControllerMessage::SendReply {
recipient,
message,
lane,
max_retransmissions,
})
.map_err(ReplyControllerSenderError::SendReply)
}
@@ -160,6 +162,7 @@ pub enum ReplyControllerMessage {
recipient: AnonymousSenderTag,
message: Vec<u8>,
lane: TransmissionLane,
max_retransmissions: Option<u32>,
},
AdditionalSurbs {
+10 -2
View File
@@ -11,6 +11,8 @@ use nym_topology::node::RoutingNode;
use nym_validator_client::client::IdentityKeyRef;
use nym_validator_client::UserAgent;
use rand::{seq::SliceRandom, Rng};
#[cfg(unix)]
use std::os::fd::RawFd;
use std::{sync::Arc, time::Duration};
use tungstenite::Message;
use url::Url;
@@ -313,9 +315,15 @@ pub(super) async fn register_with_gateway(
gateway_id: identity::PublicKey,
gateway_listener: Url,
our_identity: Arc<identity::KeyPair>,
#[cfg(unix)] connection_fd_callback: Option<Arc<dyn Fn(RawFd) + Send + Sync>>,
) -> Result<RegistrationResult, ClientCoreError> {
let mut gateway_client =
GatewayClient::new_init(gateway_listener, gateway_id, our_identity.clone());
let mut gateway_client = GatewayClient::new_init(
gateway_listener,
gateway_id,
our_identity.clone(),
#[cfg(unix)]
connection_fd_callback,
);
gateway_client.establish_connection().await.map_err(|err| {
log::warn!("Failed to establish connection with gateway!");
+22 -4
View File
@@ -23,6 +23,8 @@ use nym_topology::node::RoutingNode;
use rand::rngs::OsRng;
use rand::{CryptoRng, RngCore};
use serde::Serialize;
#[cfg(unix)]
use std::{os::fd::RawFd, sync::Arc};
pub mod helpers;
pub mod types;
@@ -53,6 +55,7 @@ async fn setup_new_gateway<K, D>(
details_store: &D,
selection_specification: GatewaySelectionSpecification,
available_gateways: Vec<RoutingNode>,
#[cfg(unix)] connection_fd_callback: Option<Arc<dyn Fn(RawFd) + Send + Sync>>,
) -> Result<InitialisationResult, ClientCoreError>
where
K: KeyStore,
@@ -108,9 +111,14 @@ where
// if we're using a 'normal' gateway setup, do register
let our_identity = client_keys.identity_keypair();
let registration =
helpers::register_with_gateway(gateway_id, gateway_listener.clone(), our_identity)
.await?;
let registration = helpers::register_with_gateway(
gateway_id,
gateway_listener.clone(),
our_identity,
#[cfg(unix)]
connection_fd_callback,
)
.await?;
(
GatewayDetails::new_remote(
gateway_id,
@@ -203,9 +211,19 @@ where
GatewaySetup::New {
specification,
available_gateways,
#[cfg(unix)]
connection_fd_callback,
} => {
log::debug!("GatewaySetup::New with spec: {specification:?}");
setup_new_gateway(key_store, details_store, specification, available_gateways).await
setup_new_gateway(
key_store,
details_store,
specification,
available_gateways,
#[cfg(unix)]
connection_fd_callback,
)
.await
}
GatewaySetup::ReuseConnection {
authenticated_ephemeral_client,
+10
View File
@@ -18,6 +18,8 @@ use nym_validator_client::client::IdentityKey;
use nym_validator_client::nyxd::AccountId;
use serde::Serialize;
use std::fmt::{Debug, Display};
#[cfg(unix)]
use std::os::fd::RawFd;
use std::sync::Arc;
use time::OffsetDateTime;
use url::Url;
@@ -208,6 +210,10 @@ pub enum GatewaySetup {
// TODO: seems to be a bit inefficient to pass them by value
available_gateways: Vec<RoutingNode>,
/// Callback useful for allowing initial connection to gateway
#[cfg(unix)]
connection_fd_callback: Option<Arc<dyn Fn(RawFd) + Send + Sync>>,
},
ReuseConnection {
@@ -231,6 +237,8 @@ impl Debug for GatewaySetup {
GatewaySetup::New {
specification,
available_gateways,
#[cfg(unix)]
connection_fd_callback: _,
} => f
.debug_struct("GatewaySetup::New")
.field("specification", specification)
@@ -270,6 +278,8 @@ impl GatewaySetup {
additional_data: None,
},
available_gateways: vec![],
#[cfg(unix)]
connection_fd_callback: None,
}
}
@@ -1065,6 +1065,7 @@ impl GatewayClient<InitOnly, EphemeralCredentialStorage> {
gateway_listener: Url,
gateway_identity: identity::PublicKey,
local_identity: Arc<identity::KeyPair>,
#[cfg(unix)] connection_fd_callback: Option<Arc<dyn Fn(RawFd) + Send + Sync>>,
) -> Self {
log::trace!("Initialising gateway client");
use futures::channel::mpsc;
@@ -1090,7 +1091,7 @@ impl GatewayClient<InitOnly, EphemeralCredentialStorage> {
stats_reporter: ClientStatsSender::new(None, task_client.clone()),
negotiated_protocol: None,
#[cfg(unix)]
connection_fd_callback: None,
connection_fd_callback,
task_client,
}
}
@@ -16,7 +16,6 @@ nym-coconut-dkg-common = { path = "../../cosmwasm-smart-contracts/coconut-dkg" }
nym-contracts-common = { path = "../../cosmwasm-smart-contracts/contracts-common" }
nym-mixnet-contract-common = { path = "../../cosmwasm-smart-contracts/mixnet-contract" }
nym-vesting-contract-common = { path = "../../cosmwasm-smart-contracts/vesting-contract" }
nym-coconut-bandwidth-contract-common = { path = "../../cosmwasm-smart-contracts/coconut-bandwidth-contract" }
nym-ecash-contract-common = { path = "../../cosmwasm-smart-contracts/ecash-contract" }
nym-multisig-contract-common = { path = "../../cosmwasm-smart-contracts/multisig-contract" }
nym-group-contract-common = { path = "../../cosmwasm-smart-contracts/group-contract" }
@@ -56,7 +55,7 @@ cw4 = { workspace = true }
cw-controllers = { workspace = true }
prost = { workspace = true, default-features = false }
flate2 = { workspace = true }
sha2 = { version = "0.9.5" }
sha2 = { workspace = true }
itertools = { workspace = true }
zeroize = { workspace = true, features = ["zeroize_derive"] }
cosmwasm-std = { workspace = true }
@@ -11,7 +11,9 @@ use crate::{
use nym_api_requests::ecash::models::{
AggregatedCoinIndicesSignatureResponse, AggregatedExpirationDateSignatureResponse,
BatchRedeemTicketsBody, EcashBatchTicketRedemptionResponse, EcashTicketVerificationResponse,
IssuedTicketbooksChallengeResponse, IssuedTicketbooksForResponse, VerifyEcashTicketBody,
IssuedTicketbooksChallengeCommitmentRequest, IssuedTicketbooksChallengeCommitmentResponse,
IssuedTicketbooksDataRequest, IssuedTicketbooksDataResponse, IssuedTicketbooksForCountResponse,
IssuedTicketbooksForResponse, VerifyEcashTicketBody,
};
use nym_api_requests::ecash::{
BlindSignRequestBody, BlindedSignatureResponse, PartialCoinIndicesSignatureResponse,
@@ -25,15 +27,14 @@ use nym_api_requests::models::{
use nym_api_requests::models::{LegacyDescribedGateway, MixNodeBondAnnotated};
use nym_api_requests::nym_nodes::{NodesByAddressesResponse, SkimmedNode};
use nym_coconut_dkg_common::types::EpochId;
use nym_ecash_contract_common::deposit::DepositId;
use nym_http_api_client::UserAgent;
use nym_mixnet_contract_common::EpochRewardedSet;
use nym_network_defaults::NymNetworkDetails;
use std::net::IpAddr;
use time::Date;
use url::Url;
pub use crate::nym_api::NymApiClientExt;
use nym_mixnet_contract_common::EpochRewardedSet;
pub use nym_mixnet_contract_common::{
mixnode::MixNodeDetails, GatewayBond, IdentityKey, IdentityKeyRef, NodeId, NymNodeDetails,
};
@@ -701,17 +702,33 @@ impl NymApiClient {
Ok(self.nym_api.issued_ticketbooks_for(expiration_date).await?)
}
pub async fn issued_ticketbooks_challenge(
pub async fn issued_ticketbooks_for_count(
&self,
expiration_date: Date,
deposits: Vec<DepositId>,
) -> Result<IssuedTicketbooksChallengeResponse, ValidatorClientError> {
) -> Result<IssuedTicketbooksForCountResponse, ValidatorClientError> {
Ok(self
.nym_api
.issued_ticketbooks_challenge(expiration_date, deposits)
.issued_ticketbooks_for_count(expiration_date)
.await?)
}
pub async fn issued_ticketbooks_challenge_commitment(
&self,
request: &IssuedTicketbooksChallengeCommitmentRequest,
) -> Result<IssuedTicketbooksChallengeCommitmentResponse, ValidatorClientError> {
Ok(self
.nym_api
.issued_ticketbooks_challenge_commitment(request)
.await?)
}
pub async fn issued_ticketbooks_data(
&self,
request: &IssuedTicketbooksDataRequest,
) -> Result<IssuedTicketbooksDataResponse, ValidatorClientError> {
Ok(self.nym_api.issued_ticketbooks_data(request).await?)
}
pub async fn nodes_by_addresses(
&self,
addresses: Vec<IpAddr>,
@@ -83,6 +83,12 @@ impl TryFrom<ContractVKShare> for EcashApiClient {
let url_address = Url::parse(&share.announce_address)?;
// The NymApiClient constructed here uses the default (hickory DoT/DoH) resolver because
// this EcashApiClient is used by both client and non-client applications.
//
// In non-client applications this resolver can cause warning logs about H2 connection
// failure. This indicates that the long lived https connection was closed by the remote
// peer and the resolver will have to reconnect. It should not impact actual functionality
Ok(EcashApiClient {
api_client: NymApiClient::new(url_address),
verification_key: VerificationKeyAuth::try_from_bs58(&share.share)?,
@@ -7,13 +7,15 @@ use async_trait::async_trait;
use nym_api_requests::ecash::models::{
AggregatedCoinIndicesSignatureResponse, AggregatedExpirationDateSignatureResponse,
BatchRedeemTicketsBody, EcashBatchTicketRedemptionResponse, EcashTicketVerificationResponse,
IssuedTicketbooksChallengeRequest, IssuedTicketbooksChallengeResponse,
IssuedTicketbooksChallengeCommitmentRequest, IssuedTicketbooksChallengeCommitmentResponse,
IssuedTicketbooksDataRequest, IssuedTicketbooksDataResponse, IssuedTicketbooksForCountResponse,
IssuedTicketbooksForResponse, VerifyEcashTicketBody,
};
use nym_api_requests::ecash::VerificationKeyResponse;
use nym_api_requests::models::{
AnnotationResponse, ApiHealthResponse, LegacyDescribedMixNode, NodePerformanceResponse,
NodeRefreshBody, NymNodeDescription, PerformanceHistoryResponse, RewardedSetResponse,
AnnotationResponse, ApiHealthResponse, BinaryBuildInformationOwned, ChainStatusResponse,
LegacyDescribedMixNode, NodePerformanceResponse, NodeRefreshBody, NymNodeDescription,
PerformanceHistoryResponse, RewardedSetResponse,
};
use nym_api_requests::nym_nodes::{
NodesByAddressesRequestBody, NodesByAddressesResponse, PaginatedCachedNodesResponse,
@@ -35,10 +37,7 @@ pub use nym_api_requests::{
nym_nodes::{CachedNodesResponse, SkimmedNode},
NymNetworkDetailsResponse,
};
pub use nym_coconut_dkg_common::types::EpochId;
use nym_contracts_common::IdentityKey;
use nym_ecash_contract_common::deposit::DepositId;
pub use nym_http_api_client::Client;
use nym_http_api_client::{ApiClient, NO_PARAMS};
use nym_mixnet_contract_common::mixnode::MixNodeDetails;
use nym_mixnet_contract_common::{GatewayBond, IdentityKeyRef, NodeId, NymNodeDetails};
@@ -47,6 +46,9 @@ use time::format_description::BorrowedFormatItem;
use time::Date;
use tracing::instrument;
pub use nym_coconut_dkg_common::types::EpochId;
pub use nym_http_api_client::Client;
pub mod error;
pub mod routes;
@@ -69,6 +71,19 @@ pub trait NymApiClientExt: ApiClient {
.await
}
#[instrument(level = "debug", skip(self))]
async fn build_information(&self) -> Result<BinaryBuildInformationOwned, NymAPIError> {
self.get_json(
&[
routes::API_VERSION,
routes::API_STATUS_ROUTES,
routes::BUILD_INFORMATION,
],
NO_PARAMS,
)
.await
}
#[deprecated]
#[instrument(level = "debug", skip(self))]
async fn get_mixnodes(&self) -> Result<Vec<MixNodeDetails>, NymAPIError> {
@@ -998,22 +1013,52 @@ pub trait NymApiClientExt: ApiClient {
}
#[instrument(level = "debug", skip(self))]
async fn issued_ticketbooks_challenge(
async fn issued_ticketbooks_for_count(
&self,
expiration_date: Date,
deposits: Vec<DepositId>,
) -> Result<IssuedTicketbooksChallengeResponse, NymAPIError> {
) -> Result<IssuedTicketbooksForCountResponse, NymAPIError> {
self.get_json(
&[
routes::API_VERSION,
routes::ECASH_ROUTES,
routes::ECASH_ISSUED_TICKETBOOKS_FOR_COUNT,
&expiration_date.to_string(),
],
NO_PARAMS,
)
.await
}
#[instrument(level = "debug", skip(self))]
async fn issued_ticketbooks_challenge_commitment(
&self,
request: &IssuedTicketbooksChallengeCommitmentRequest,
) -> Result<IssuedTicketbooksChallengeCommitmentResponse, NymAPIError> {
self.post_json(
&[
routes::API_VERSION,
routes::ECASH_ROUTES,
routes::ECASH_ISSUED_TICKETBOOKS_CHALLENGE,
routes::ECASH_ISSUED_TICKETBOOKS_CHALLENGE_COMMITMENT,
],
NO_PARAMS,
&IssuedTicketbooksChallengeRequest {
expiration_date,
deposits,
},
request,
)
.await
}
#[instrument(level = "debug", skip(self))]
async fn issued_ticketbooks_data(
&self,
request: &IssuedTicketbooksDataRequest,
) -> Result<IssuedTicketbooksDataResponse, NymAPIError> {
self.post_json(
&[
routes::API_VERSION,
routes::ECASH_ROUTES,
routes::ECASH_ISSUED_TICKETBOOKS_DATA,
],
NO_PARAMS,
request,
)
.await
}
@@ -1043,6 +1088,15 @@ pub trait NymApiClientExt: ApiClient {
)
.await
}
#[instrument(level = "debug", skip(self))]
async fn get_chain_status(&self) -> Result<ChainStatusResponse, NymAPIError> {
self.get_json(
&[routes::API_VERSION, routes::NETWORK, routes::CHAIN_STATUS],
NO_PARAMS,
)
.await
}
}
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
@@ -26,7 +26,12 @@ pub mod ecash {
pub const GLOBAL_COIN_INDICES_SIGNATURES: &str = "aggregated-coin-indices-signatures";
pub const MASTER_VERIFICATION_KEY: &str = "master-verification-key";
pub const ECASH_ISSUED_TICKETBOOKS_FOR: &str = "issued-ticketbooks-for";
pub const ECASH_ISSUED_TICKETBOOKS_CHALLENGE: &str = "issued-ticketbooks-challenge";
pub const ECASH_ISSUED_TICKETBOOKS_COUNT: &str = "issued-ticketbooks-count";
pub const ECASH_ISSUED_TICKETBOOKS_FOR_COUNT: &str = "issued-ticketbooks-for-count";
pub const ECASH_ISSUED_TICKETBOOKS_ON_COUNT: &str = "issued-ticketbooks-on-count";
pub const ECASH_ISSUED_TICKETBOOKS_CHALLENGE_COMMITMENT: &str =
"issued-ticketbooks-challenge-commitment";
pub const ECASH_ISSUED_TICKETBOOKS_DATA: &str = "issued-ticketbooks-data";
pub const EXPIRATION_DATE_PARAM: &str = "expiration_date";
pub const EPOCH_ID_PARAM: &str = "epoch_id";
@@ -49,6 +54,8 @@ pub mod nym_nodes {
pub const STATUS_ROUTES: &str = "status";
pub const API_STATUS_ROUTES: &str = "api-status";
pub const HEALTH: &str = "health";
pub const BUILD_INFORMATION: &str = "build-information";
pub const MIXNODE: &str = "mixnode";
pub const GATEWAY: &str = "gateway";
pub const NYM_NODES: &str = "nym-nodes";
@@ -70,4 +77,5 @@ pub const SUBMIT_NODE: &str = "submit-node-monitoring-results";
pub const SERVICE_PROVIDERS: &str = "services";
pub const DETAILS: &str = "details";
pub const CHAIN_STATUS: &str = "chain-status";
pub const NETWORK: &str = "network";
@@ -48,7 +48,7 @@ impl Div<GasPrice> for &Coin {
panic!("attempted to divide by zero!")
};
let implicit_gas_limit = gas_price_inv * Uint128::new(self.amount);
let implicit_gas_limit = Uint128::new(self.amount).mul_floor(gas_price_inv);
if implicit_gas_limit.u128() >= u64::MAX as u128 {
u64::MAX
} else {
@@ -169,13 +169,7 @@ impl CoinConverter for CosmosCoin {
type Target = CosmWasmCoin;
fn convert_coin(&self) -> Self::Target {
CosmWasmCoin::new(
self.amount
.to_string()
.parse()
.expect("cosmos coin had an invalid amount assigned"),
self.denom.to_string(),
)
CosmWasmCoin::new(self.amount, self.denom.to_string())
}
}
@@ -7,10 +7,10 @@ use crate::nyxd::error::NyxdError;
use crate::nyxd::{Coin, Fee, SigningCosmWasmClient};
use crate::signing::signer::OfflineSigner;
use async_trait::async_trait;
use cosmwasm_std::{to_binary, CosmosMsg, WasmMsg};
use cosmwasm_std::{CosmosMsg, Empty};
use cw3::Vote;
use cw4::{MemberChangedHookMsg, MemberDiff};
use nym_coconut_bandwidth_contract_common::msg::ExecuteMsg as CoconutBandwidthExecuteMsg;
use cw_utils::Expiration;
use nym_multisig_contract_common::msg::ExecuteMsg as MultisigExecuteMsg;
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
@@ -24,35 +24,23 @@ pub trait MultisigSigningClient: NymContractsProvider {
funds: Vec<Coin>,
) -> Result<ExecuteResult, NyxdError>;
async fn propose_release_funds(
async fn propose(
&self,
title: String,
blinded_serial_number: String,
voucher_value: Coin,
description: String,
msgs: Vec<CosmosMsg<Empty>>,
latest: Option<Expiration>,
fee: Option<Fee>,
) -> Result<ExecuteResult, NyxdError> {
let ecash_contract_address = self
.ecash_contract_address()
.ok_or_else(|| NyxdError::unavailable_contract_address("coconut bandwidth contract"))?;
let release_funds_req = CoconutBandwidthExecuteMsg::ReleaseFunds {
funds: voucher_value.into(),
};
let release_funds_msg = CosmosMsg::Wasm(WasmMsg::Execute {
contract_addr: ecash_contract_address.to_string(),
msg: to_binary(&release_funds_req)?,
funds: vec![],
});
let req = MultisigExecuteMsg::Propose {
title,
description: blinded_serial_number,
msgs: vec![release_funds_msg],
latest: None,
};
self.execute_multisig_contract(
fee,
req,
"Multisig::Propose::Execute::ReleaseFunds".to_string(),
MultisigExecuteMsg::Propose {
title,
description,
msgs,
latest,
},
"Multisig::Propose".to_string(),
vec![],
)
.await
@@ -161,7 +149,7 @@ where
#[cfg(test)]
mod tests {
use super::*;
use crate::nyxd::contract_traits::tests::{mock_coin, IgnoreValue};
use crate::nyxd::contract_traits::tests::IgnoreValue;
// it's enough that this compiles and clippy is happy about it
#[allow(dead_code)]
@@ -171,9 +159,12 @@ mod tests {
) {
match msg {
MultisigExecuteMsg::Propose {
title, description, ..
title,
description,
msgs,
latest,
} => client
.propose_release_funds(title, description, mock_coin(), None)
.propose(title, description, msgs, latest, None)
.ignore(),
MultisigExecuteMsg::Vote { proposal_id, vote } => {
client.vote(proposal_id, vote, None).ignore()
@@ -27,7 +27,7 @@ impl Mul<Gas> for &GasPrice {
fn mul(self, gas_limit: Gas) -> Self::Output {
let limit_uint128 = Uint128::from(gas_limit);
let mut amount = self.amount * limit_uint128;
let mut amount = limit_uint128.mul_floor(self.amount);
let gas_price_numerator = self.amount.numerator();
let gas_price_denominator = self.amount.denominator();
@@ -35,7 +35,7 @@ impl Mul<Gas> for &GasPrice {
// gas price is a fraction of the smallest fee token unit, so we must ensure that
// for any multiplication, we have rounded up
//
// I don't really like the this solution as it has a theoretical chance of
// I don't really like this solution as it has a theoretical chance of
// overflowing (internally cosmwasm uses U256 to avoid that)
// however, realistically that is impossible to happen as the resultant value
// would have to be way higher than our token limit of 10^15 (1 billion of tokens * 1 million for denomination)
@@ -62,6 +62,7 @@ pub use cw3;
pub use cw4;
pub use cw_controllers;
pub use fee::{gas_price::GasPrice, GasAdjustable, GasAdjustment};
pub use prost::Name;
pub use tendermint_rpc::endpoint::block::Response as BlockResponse;
pub use tendermint_rpc::{
endpoint::{tx::Response as TxResponse, validators::Response as ValidatorResponse},
@@ -155,7 +155,7 @@ async fn fetch_delegation_data(
match event.event.kind {
// If a pending undelegate tx is found, remove it from delegation map
PendingEpochEventKind::Undelegate { owner, node_id, .. } => {
if owner == address.as_ref()
if owner.as_str() == address.as_ref()
&& existing_delegation_map.contains_key(&node_id.to_string())
{
existing_delegation_map.remove(&node_id.to_string());
@@ -169,7 +169,7 @@ async fn fetch_delegation_data(
amount,
..
} => {
if owner == address.as_ref() {
if owner.as_str() == address.as_ref() {
let mut amount = Coin::from(amount);
if let Some(pending_record) = pending_delegation_map.get(&node_id.to_string()) {
amount.amount += pending_record.amount;
@@ -54,7 +54,7 @@ pub async fn create(args: Args, client: SigningClient, network_details: &NymNetw
let denom = network_details.chain_details.mix_denom.base.to_string();
let coin = Coin::new(args.amount.into(), &denom);
let coin = Coin::new(args.amount, &denom);
let res = client
.create_periodic_vesting_account(
@@ -1,16 +0,0 @@
[package]
name = "nym-coconut-bandwidth-contract-common"
version = "0.1.0"
edition = "2021"
license.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
cosmwasm-std = { workspace = true }
cosmwasm-schema = { workspace = true }
cw2 = { workspace = true, optional = true }
nym-multisig-contract-common = { path = "../multisig-contract" }
[features]
schema = ["cw2"]
@@ -1,33 +0,0 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use cosmwasm_schema::cw_serde;
#[cw_serde]
pub struct DepositData {
deposit_info: String,
identity_key: String,
encryption_key: String,
}
impl DepositData {
pub fn new(deposit_info: String, identity_key: String, encryption_key: String) -> Self {
DepositData {
deposit_info,
identity_key,
encryption_key,
}
}
pub fn deposit_info(&self) -> &str {
&self.deposit_info
}
pub fn identity_key(&self) -> &str {
&self.identity_key
}
pub fn encryption_key(&self) -> &str {
&self.encryption_key
}
}
@@ -1,4 +0,0 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
pub const BANDWIDTH_PROPOSAL_ID: &str = "proposal_id";
@@ -1,11 +0,0 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
// event types
pub const DEPOSITED_FUNDS_EVENT_TYPE: &str = "deposited-funds";
// attributes that are used in multiple places
pub const DEPOSIT_VALUE: &str = "deposit-value";
pub const DEPOSIT_INFO: &str = "deposit-info";
pub const DEPOSIT_IDENTITY_KEY: &str = "deposit-identity-key";
pub const DEPOSIT_ENCRYPTION_KEY: &str = "deposit-encryption-key";
@@ -1,5 +0,0 @@
pub mod deposit;
pub mod event_attributes;
pub mod events;
pub mod msg;
pub mod spend_credential;
@@ -1,41 +0,0 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::{deposit::DepositData, spend_credential::SpendCredentialData};
use cosmwasm_schema::cw_serde;
use cosmwasm_std::Coin;
#[cfg(feature = "schema")]
use crate::spend_credential::{PagedSpendCredentialResponse, SpendCredentialResponse};
#[cfg(feature = "schema")]
use cosmwasm_schema::QueryResponses;
#[cw_serde]
pub struct InstantiateMsg {
pub multisig_addr: String,
pub pool_addr: String,
pub mix_denom: String,
}
#[cw_serde]
pub enum ExecuteMsg {
DepositFunds { data: DepositData },
SpendCredential { data: SpendCredentialData },
ReleaseFunds { funds: Coin },
}
#[cw_serde]
#[cfg_attr(feature = "schema", derive(QueryResponses))]
pub enum QueryMsg {
#[cfg_attr(feature = "schema", returns(SpendCredentialResponse))]
GetSpentCredential { blinded_serial_number: String },
#[cfg_attr(feature = "schema", returns(PagedSpendCredentialResponse))]
GetAllSpentCredentials {
limit: Option<u32>,
start_after: Option<String>,
},
}
#[cw_serde]
pub struct MigrateMsg {}
@@ -1,152 +0,0 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use cosmwasm_schema::cw_serde;
use cosmwasm_std::{from_binary, to_binary, Addr, Coin, CosmosMsg, StdResult, WasmMsg};
use nym_multisig_contract_common::msg::ExecuteMsg as MultisigExecuteMsg;
use crate::msg::ExecuteMsg;
#[cw_serde]
pub struct SpendCredentialData {
funds: Coin,
blinded_serial_number: String,
gateway_cosmos_address: String,
}
impl SpendCredentialData {
pub fn new(funds: Coin, blinded_serial_number: String, gateway_cosmos_address: String) -> Self {
SpendCredentialData {
funds,
blinded_serial_number,
gateway_cosmos_address,
}
}
pub fn funds(&self) -> &Coin {
&self.funds
}
pub fn blinded_serial_number(&self) -> &str {
&self.blinded_serial_number
}
pub fn gateway_cosmos_address(&self) -> &str {
&self.gateway_cosmos_address
}
}
#[cw_serde]
#[derive(Copy)]
pub enum SpendCredentialStatus {
#[serde(alias = "InProgress")]
InProgress,
#[serde(alias = "Spent")]
Spent,
}
#[cw_serde]
pub struct SpendCredential {
funds: Coin,
blinded_serial_number: String,
gateway_cosmos_address: Addr,
status: SpendCredentialStatus,
}
impl SpendCredential {
pub fn new(funds: Coin, blinded_serial_number: String, gateway_cosmos_address: Addr) -> Self {
SpendCredential {
funds,
blinded_serial_number,
gateway_cosmos_address,
status: SpendCredentialStatus::InProgress,
}
}
pub fn blinded_serial_number(&self) -> &str {
&self.blinded_serial_number
}
pub fn status(&self) -> SpendCredentialStatus {
self.status
}
pub fn mark_as_spent(&mut self) {
self.status = SpendCredentialStatus::Spent;
}
}
#[cw_serde]
pub struct PagedSpendCredentialResponse {
pub spend_credentials: Vec<SpendCredential>,
pub per_page: usize,
/// Field indicating paging information for the following queries if the caller wishes to get further entries.
pub start_next_after: Option<String>,
}
impl PagedSpendCredentialResponse {
pub fn new(
spend_credentials: Vec<SpendCredential>,
per_page: usize,
start_next_after: Option<String>,
) -> Self {
PagedSpendCredentialResponse {
spend_credentials,
per_page,
start_next_after,
}
}
}
#[cw_serde]
pub struct SpendCredentialResponse {
pub spend_credential: Option<SpendCredential>,
}
impl SpendCredentialResponse {
pub fn new(spend_credential: Option<SpendCredential>) -> Self {
SpendCredentialResponse { spend_credential }
}
}
pub fn to_cosmos_msg(
funds: Coin,
blinded_serial_number: String,
coconut_bandwidth_addr: String,
multisig_addr: String,
) -> StdResult<CosmosMsg> {
let release_funds_req = ExecuteMsg::ReleaseFunds { funds };
let release_funds_msg = CosmosMsg::Wasm(WasmMsg::Execute {
contract_addr: coconut_bandwidth_addr,
msg: to_binary(&release_funds_req)?,
funds: vec![],
});
let req = MultisigExecuteMsg::Propose {
title: String::from("Release funds, as ordered by Coconut Bandwidth Contract"),
description: blinded_serial_number,
msgs: vec![release_funds_msg],
latest: None,
};
let msg = CosmosMsg::Wasm(WasmMsg::Execute {
contract_addr: multisig_addr,
msg: to_binary(&req)?,
funds: vec![],
});
Ok(msg)
}
pub fn funds_from_cosmos_msgs(msgs: Vec<CosmosMsg>) -> Option<Coin> {
if let Some(CosmosMsg::Wasm(WasmMsg::Execute {
contract_addr: _,
msg,
funds: _,
})) = msgs.first()
{
if let Ok(ExecuteMsg::ReleaseFunds { funds }) = from_binary::<ExecuteMsg>(msg) {
return Some(funds);
}
}
None
}
@@ -4,7 +4,7 @@
use crate::msg::ExecuteMsg;
use crate::types::{EpochId, NodeIndex};
use cosmwasm_schema::cw_serde;
use cosmwasm_std::{from_binary, to_binary, Addr, CosmosMsg, StdResult, Timestamp, WasmMsg};
use cosmwasm_std::{from_json, to_json_binary, Addr, CosmosMsg, StdResult, Timestamp, WasmMsg};
use cw_utils::Expiration;
use nym_multisig_contract_common::msg::ExecuteMsg as MultisigExecuteMsg;
@@ -49,7 +49,7 @@ pub fn to_cosmos_msg(
};
let verify_vk_share_msg = CosmosMsg::Wasm(WasmMsg::Execute {
contract_addr: coconut_dkg_addr,
msg: to_binary(&verify_vk_share_req)?,
msg: to_json_binary(&verify_vk_share_req)?,
funds: vec![],
});
let req = MultisigExecuteMsg::Propose {
@@ -60,7 +60,7 @@ pub fn to_cosmos_msg(
};
let msg = CosmosMsg::Wasm(WasmMsg::Execute {
contract_addr: multisig_addr,
msg: to_binary(&req)?,
msg: to_json_binary(&req)?,
funds: vec![],
});
@@ -82,7 +82,7 @@ pub fn owner_from_cosmos_msgs(msgs: &[CosmosMsg]) -> Option<String> {
})) = msgs.first()
{
if let Ok(ExecuteMsg::VerifyVerificationKeyShare { owner, .. }) =
from_binary::<ExecuteMsg>(msg)
from_json::<ExecuteMsg>(msg)
{
return Some(owner);
}
@@ -1,7 +1,7 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use cosmwasm_std::{from_slice, to_vec, Addr, Coin, MessageInfo, StdResult};
use cosmwasm_std::{from_json, to_json_vec, Addr, Coin, MessageInfo, StdResult};
use schemars::JsonSchema;
use serde::de::DeserializeOwned;
use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
@@ -164,7 +164,7 @@ where
where
T: Serialize,
{
to_vec(self)
to_json_vec(self)
}
pub fn to_sha256_plaintext_digest(&self) -> StdResult<Vec<u8>>
@@ -195,7 +195,7 @@ where
where
T: DeserializeOwned,
{
from_slice(bytes)
from_json(bytes)
}
pub fn try_from_string(raw: &str) -> StdResult<SignableMessage<T>>
@@ -2,9 +2,9 @@
// SPDX-License-Identifier: Apache-2.0
use cosmwasm_schema::cw_serde;
use cosmwasm_std::Decimal;
use cosmwasm_std::OverflowError;
use cosmwasm_std::Uint128;
use cosmwasm_std::{Decimal, Fraction};
use serde::de::Error;
use serde::{Deserialize, Deserializer};
use std::fmt::{self, Display, Formatter};
@@ -17,7 +17,7 @@ pub type IdentityKey = String;
pub type IdentityKeyRef<'a> = &'a str;
pub fn truncate_decimal(amount: Decimal) -> Uint128 {
amount * Uint128::new(1)
Uint128::new(1).mul_floor(amount)
}
#[derive(Error, Debug)]
@@ -113,11 +113,17 @@ impl Mul<Percent> for Decimal {
}
}
impl Mul<Uint128> for Percent {
type Output = Uint128;
impl Fraction<Uint128> for Percent {
fn numerator(&self) -> Uint128 {
self.0.numerator()
}
fn mul(self, rhs: Uint128) -> Self::Output {
self.0 * rhs
fn denominator(&self) -> Uint128 {
self.0.denominator()
}
fn inv(&self) -> Option<Self> {
Percent::new(self.0.inv()?).ok()
}
}
@@ -0,0 +1,14 @@
[package]
name = "easy-addr"
version = "0.1.0"
edition = "2021"
publish = false
license.workspace = true
[lib]
proc-macro = true
[dependencies]
cosmwasm-std = { workspace = true }
quote = { workspace = true }
syn = { workspace = true, features = ["full", "printing", "extra-traits"] }
@@ -0,0 +1,12 @@
use cosmwasm_std::testing::MockApi;
use proc_macro::TokenStream;
use quote::quote;
use syn::parse_macro_input;
#[proc_macro]
pub fn addr(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as syn::LitStr).value();
let addr = MockApi::default().addr_make(input.as_str()).to_string();
TokenStream::from(quote! {#addr})
}
@@ -241,10 +241,10 @@ mod tests {
#[test]
fn gateway_bond_partial_ord() {
let _150foos = Coin::new(150, "foo");
let _140foos = Coin::new(140, "foo");
let _50foos = Coin::new(50, "foo");
let _0foos = Coin::new(0, "foo");
let _150foos = Coin::new(150u32, "foo");
let _140foos = Coin::new(140u32, "foo");
let _50foos = Coin::new(50u32, "foo");
let _0foos = Coin::new(0u32, "foo");
let gate1 = GatewayBond {
pledge_amount: _150foos.clone(),
@@ -34,8 +34,10 @@ where
{
fn into_base_decimal(self) -> StdResult<Decimal> {
let atomics = self.into();
Decimal::from_atomics(atomics, 0).map_err(|_| StdError::GenericErr {
msg: format!("Decimal range exceeded for {atomics} with 0 decimal places."),
Decimal::from_atomics(atomics, 0).map_err(|_| {
StdError::generic_err(format!(
"Decimal range exceeded for {atomics} with 0 decimal places."
))
})
}
}
@@ -77,6 +77,8 @@ impl<'a> PrimaryKey<'a> for Role {
impl KeyDeserialize for Role {
type Output = Role;
const KEY_ELEMS: u16 = 1;
fn from_vec(value: Vec<u8>) -> StdResult<Self::Output> {
let u8_key: <u8 as KeyDeserialize>::Output = <u8 as KeyDeserialize>::from_vec(value)?;
Role::try_from(u8_key).map_err(|err| StdError::generic_err(err.to_string()))
@@ -242,7 +242,7 @@ mod tests {
#[allow(clippy::unwrap_used)]
fn base_simulator(initial_pledge: u128) -> Simulator {
let profit_margin = Percent::from_percentage_value(10).unwrap();
let interval_operating_cost = Coin::new(40_000_000, "unym");
let interval_operating_cost = Coin::new(40_000_000u64, "unym");
let epochs_in_interval = 720u32;
let interval_pool_emission = Percent::from_percentage_value(2).unwrap();
@@ -347,7 +347,7 @@ mod tests {
fn single_delegation_at_genesis() {
let mut simulator = base_simulator(10000_000000);
simulator
.delegate("alice", Coin::new(18000_000000, "unym"), 0)
.delegate("alice", Coin::new(18000_000000u64, "unym"), 0)
.unwrap();
let node_params = NodeRewardingParameters::new(
@@ -393,7 +393,7 @@ mod tests {
compare_decimals(rewards1.operator, expected_operator1, None);
simulator
.delegate("alice", Coin::new(18000_000000, "unym"), 0)
.delegate("alice", Coin::new(18000_000000u64, "unym"), 0)
.unwrap();
let rewards2 = simulator.simulate_epoch_single_node(node_params).unwrap();
@@ -439,10 +439,10 @@ mod tests {
// add 2 delegations at genesis (because it makes things easier and as shown with previous tests
// delegating at different times still work)
simulator
.delegate("alice", Coin::new(18000_000000, "unym"), 0)
.delegate("alice", Coin::new(18000_000000u64, "unym"), 0)
.unwrap();
simulator
.delegate("bob", Coin::new(4000_000000, "unym"), 0)
.delegate("bob", Coin::new(4000_000000u64, "unym"), 0)
.unwrap();
// "normal", sanity check rewarding
@@ -484,10 +484,10 @@ mod tests {
// add 2 delegations at genesis (because it makes things easier and as shown with previous tests
// delegating at different times still work)
simulator
.delegate("alice", Coin::new(18000_000000, "unym"), 0)
.delegate("alice", Coin::new(18000_000000u64, "unym"), 0)
.unwrap();
simulator
.delegate("bob", Coin::new(4000_000000, "unym"), 0)
.delegate("bob", Coin::new(4000_000000u64, "unym"), 0)
.unwrap();
// "normal", sanity check rewarding
@@ -553,12 +553,12 @@ mod tests {
for epoch in 0..720 {
if epoch == 0 {
simulator
.delegate("a", Coin::new(18000_000000, "unym"), 0)
.delegate("a", Coin::new(18000_000000u64, "unym"), 0)
.unwrap()
}
if epoch == 42 {
simulator
.delegate("b", Coin::new(2000_000000, "unym"), 0)
.delegate("b", Coin::new(2000_000000u64, "unym"), 0)
.unwrap()
}
if epoch == 89 {
@@ -566,7 +566,7 @@ mod tests {
}
if epoch == 123 {
simulator
.delegate("c", Coin::new(6666_000000, "unym"), 0)
.delegate("c", Coin::new(6666_000000u64, "unym"), 0)
.unwrap()
}
if epoch == 167 {
@@ -574,7 +574,7 @@ mod tests {
}
if epoch == 245 {
simulator
.delegate("d", Coin::new(2050_000000, "unym"), 0)
.delegate("d", Coin::new(2050_000000u64, "unym"), 0)
.unwrap()
}
if epoch == 264 {
@@ -597,7 +597,7 @@ mod tests {
}
if epoch == 545 {
simulator
.delegate("e", Coin::new(5000_000000, "unym"), 0)
.delegate("e", Coin::new(5000_000000u64, "unym"), 0)
.unwrap()
}
@@ -666,132 +666,132 @@ mod tests {
let n0 = simulator
.bond(
Coin::new(11_000_000_000000, "unym"),
Coin::new(11_000_000_000000u64, "unym"),
NodeCostParams {
profit_margin_percent: Percent::from_percentage_value(10).unwrap(),
interval_operating_cost: Coin::new(40_000_000, "unym"),
interval_operating_cost: Coin::new(40_000_000u64, "unym"),
},
)
.unwrap();
simulator
.delegate("delegator", Coin::new(1_000_000_000000, "unym"), n0)
.delegate("delegator", Coin::new(1_000_000_000000u64, "unym"), n0)
.unwrap();
let n1 = simulator
.bond(
Coin::new(1_000_000_000000, "unym"),
Coin::new(1_000_000_000000u64, "unym"),
NodeCostParams {
profit_margin_percent: Percent::from_percentage_value(10).unwrap(),
interval_operating_cost: Coin::new(40_000_000, "unym"),
interval_operating_cost: Coin::new(40_000_000u64, "unym"),
},
)
.unwrap();
simulator
.delegate("delegator", Coin::new(11_000_000_000000, "unym"), n1)
.delegate("delegator", Coin::new(11_000_000_000000u64, "unym"), n1)
.unwrap();
let n2 = simulator
.bond(
Coin::new(1_000_000_000000, "unym"),
Coin::new(1_000_000_000000u64, "unym"),
NodeCostParams {
profit_margin_percent: Percent::from_percentage_value(10).unwrap(),
interval_operating_cost: Coin::new(40_000_000, "unym"),
interval_operating_cost: Coin::new(40_000_000u64, "unym"),
},
)
.unwrap();
simulator
.delegate("delegator", Coin::new(9_000_000_000000, "unym"), n2)
.delegate("delegator", Coin::new(9_000_000_000000u64, "unym"), n2)
.unwrap();
let n3 = simulator
.bond(
Coin::new(1_000_000_000000, "unym"),
Coin::new(1_000_000_000000u64, "unym"),
NodeCostParams {
profit_margin_percent: Percent::from_percentage_value(0).unwrap(),
interval_operating_cost: Coin::new(500_000_000, "unym"),
interval_operating_cost: Coin::new(500_000_000u64, "unym"),
},
)
.unwrap();
simulator
.delegate("delegator", Coin::new(7_000_000_000000, "unym"), n3)
.delegate("delegator", Coin::new(7_000_000_000000u64, "unym"), n3)
.unwrap();
let n4 = simulator
.bond(
Coin::new(1000_000000, "unym"),
Coin::new(1000_000000u64, "unym"),
NodeCostParams {
profit_margin_percent: Percent::from_percentage_value(10).unwrap(),
interval_operating_cost: Coin::new(40_000_000, "unym"),
interval_operating_cost: Coin::new(40_000_000u64, "unym"),
},
)
.unwrap();
simulator
.delegate("delegator", Coin::new(7_999_000_000000, "unym"), n4)
.delegate("delegator", Coin::new(7_999_000_000000u64, "unym"), n4)
.unwrap();
let n5 = simulator
.bond(
Coin::new(1_000_000_000000, "unym"),
Coin::new(1_000_000_000000u64, "unym"),
NodeCostParams {
profit_margin_percent: Percent::from_percentage_value(10).unwrap(),
interval_operating_cost: Coin::new(40_000_000, "unym"),
interval_operating_cost: Coin::new(40_000_000u64, "unym"),
},
)
.unwrap();
simulator
.delegate("delegator", Coin::new(7_000_000_000000, "unym"), n5)
.delegate("delegator", Coin::new(7_000_000_000000u64, "unym"), n5)
.unwrap();
let n6 = simulator
.bond(
Coin::new(11_000_000_000000, "unym"),
Coin::new(11_000_000_000000u64, "unym"),
NodeCostParams {
profit_margin_percent: Percent::from_percentage_value(10).unwrap(),
interval_operating_cost: Coin::new(40_000_000, "unym"),
interval_operating_cost: Coin::new(40_000_000u64, "unym"),
},
)
.unwrap();
simulator
.delegate("delegator", Coin::new(1_000_000_000000, "unym"), n6)
.delegate("delegator", Coin::new(1_000_000_000000u64, "unym"), n6)
.unwrap();
let n7 = simulator
.bond(
Coin::new(1_000_000_000000, "unym"),
Coin::new(1_000_000_000000u64, "unym"),
NodeCostParams {
profit_margin_percent: Percent::from_percentage_value(10).unwrap(),
interval_operating_cost: Coin::new(40_000_000, "unym"),
interval_operating_cost: Coin::new(40_000_000u64, "unym"),
},
)
.unwrap();
simulator
.delegate("delegator", Coin::new(9_000_000_000000, "unym"), n7)
.delegate("delegator", Coin::new(9_000_000_000000u64, "unym"), n7)
.unwrap();
let n8 = simulator
.bond(
Coin::new(1_000_000_000000, "unym"),
Coin::new(1_000_000_000000u64, "unym"),
NodeCostParams {
profit_margin_percent: Percent::from_percentage_value(0).unwrap(),
interval_operating_cost: Coin::new(500_000_000, "unym"),
interval_operating_cost: Coin::new(500_000_000u64, "unym"),
},
)
.unwrap();
simulator
.delegate("delegator", Coin::new(7_000_000_000000, "unym"), n8)
.delegate("delegator", Coin::new(7_000_000_000000u64, "unym"), n8)
.unwrap();
let n9 = simulator
.bond(
Coin::new(1_000_000_000000, "unym"),
Coin::new(1_000_000_000000u64, "unym"),
NodeCostParams {
profit_margin_percent: Percent::from_percentage_value(10).unwrap(),
interval_operating_cost: Coin::new(40_000_000, "unym"),
interval_operating_cost: Coin::new(40_000_000u64, "unym"),
},
)
.unwrap();
simulator
.delegate("delegator", Coin::new(7_000_000_000000, "unym"), n9)
.delegate("delegator", Coin::new(7_000_000_000000u64, "unym"), n9)
.unwrap();
let uptime_1 = Percent::from_percentage_value(100).unwrap();
@@ -3,7 +3,7 @@
use crate::ecash::error::EcashTicketError;
use crate::Error;
use cosmwasm_std::{from_binary, CosmosMsg, WasmMsg};
use cosmwasm_std::{from_json, CosmosMsg, WasmMsg};
use nym_credentials_interface::VerificationKeyAuth;
use nym_ecash_contract_common::msg::ExecuteMsg;
use nym_gateway_storage::GatewayStorage;
@@ -72,7 +72,7 @@ impl SharedState {
let CosmosMsg::Wasm(WasmMsg::Execute { msg, .. }) = msg else {
return false;
};
let Ok(ExecuteMsg::RedeemTickets { gw, .. }) = from_binary(msg) else {
let Ok(ExecuteMsg::RedeemTickets { gw, .. }) = from_json(msg) else {
return false;
};
@@ -16,3 +16,20 @@ pub mod bs58_ed25519_pubkey {
PublicKey::from_base58_string(s).map_err(serde::de::Error::custom)
}
}
pub mod bs58_ed25519_signature {
use crate::asymmetric::identity::Signature;
use serde::{Deserialize, Deserializer, Serializer};
pub fn serialize<S: Serializer>(
signature: &Signature,
serializer: S,
) -> Result<S::Ok, S::Error> {
serializer.serialize_str(&signature.to_base58_string())
}
pub fn deserialize<'de, D: Deserializer<'de>>(deserializer: D) -> Result<Signature, D::Error> {
let s = String::deserialize(deserializer)?;
Signature::from_base58_string(s).map_err(serde::de::Error::custom)
}
}
+1 -1
View File
@@ -21,7 +21,7 @@ lazy_static = { workspace = true }
rand = { workspace = true }
rand_chacha = { workspace = true }
rand_core = { workspace = true }
sha2 = "0.9"
sha2 = { workspace = true }
serde = { workspace = true }
serde_derive = { workspace = true }
thiserror = { workspace = true }
+96 -2
View File
@@ -54,12 +54,12 @@ pub(crate) fn hash_to_scalar<M: AsRef<[u8]>>(msg: M, domain: &[u8]) -> Scalar {
pub(crate) fn hash_to_scalars<M: AsRef<[u8]>>(msg: M, domain: &[u8], n: usize) -> Vec<Scalar> {
let mut output = vec![Scalar::zero(); n];
Scalar::hash_to_field::<ExpandMsgXmd<Sha256>>(msg.as_ref(), domain, &mut output);
Scalar::hash_to_field::<ExpandMsgXmd<Sha256>, _>([msg], domain, &mut output);
output
}
pub(crate) fn hash_g2<M: AsRef<[u8]>>(msg: M, domain: &[u8]) -> G2Projective {
<G2Projective as HashToCurve<ExpandMsgXmd<Sha256>>>::hash_to_curve(msg, domain)
<G2Projective as HashToCurve<ExpandMsgXmd<Sha256>>>::hash_to_curve([msg], domain)
}
pub(crate) fn combine_scalar_chunks(chunks: &[Scalar]) -> Scalar {
@@ -112,3 +112,97 @@ pub(crate) fn deserialize_g2(b: &[u8]) -> Option<G2Projective> {
G2Projective::from_bytes(&encoding).into()
}
}
#[cfg(test)]
mod tests {
use super::*;
use bls12_381::G2Affine;
#[test]
fn test_hash_to_scalar() {
let msg1 = "foo";
let expected1 = Scalar::from_bytes(&[
253, 57, 224, 227, 175, 195, 226, 82, 46, 175, 33, 126, 171, 239, 255, 92, 108, 168, 6,
79, 90, 11, 235, 236, 221, 10, 85, 133, 42, 81, 95, 30,
])
.unwrap();
let msg2 = "bar";
let expected2 = Scalar::from_bytes(&[
48, 83, 69, 52, 42, 18, 135, 244, 211, 190, 160, 196, 118, 154, 24, 126, 0, 125, 72,
201, 170, 225, 123, 201, 52, 120, 171, 132, 235, 182, 20, 26,
])
.unwrap();
let msg3 = [
33, 135, 76, 234, 71, 35, 247, 216, 39, 242, 42, 88, 152, 29, 74, 135, 9, 29, 216, 123,
250, 87, 108, 29, 245, 126, 109, 102, 84, 71, 158, 224, 145, 243, 49, 121, 244, 27,
115, 121, 25, 66, 216, 67, 97, 101, 140, 160, 77, 239, 114, 215, 152, 48, 15, 231, 101,
60, 42, 92, 128, 131, 161, 43,
];
let expected3 = Scalar::from_bytes(&[
128, 189, 8, 43, 186, 55, 52, 61, 171, 196, 159, 177, 162, 100, 27, 143, 85, 83, 218,
171, 91, 220, 155, 25, 7, 38, 2, 36, 4, 93, 136, 4,
])
.unwrap();
assert_eq!(
hash_to_scalar(msg1, b"NYMECASH-V01-CS02-with-expander-SHA256"),
expected1
);
assert_eq!(
hash_to_scalar(msg2, b"NYMECASH-V01-CS02-with-expander-SHA256"),
expected2
);
assert_eq!(
hash_to_scalar(msg3, b"NYMECASH-V01-CS02-with-expander-SHA256"),
expected3
);
}
#[test]
fn test_hash_g2() {
let msg1 = "foo";
let expected1 = G2Affine::from_compressed(&[
175, 187, 62, 7, 29, 17, 42, 93, 28, 93, 234, 253, 101, 166, 158, 187, 153, 82, 93, 18,
11, 233, 36, 107, 51, 117, 30, 127, 32, 254, 210, 77, 133, 12, 253, 255, 84, 128, 36,
214, 234, 103, 50, 21, 26, 78, 112, 49, 20, 69, 19, 109, 7, 78, 33, 227, 196, 180, 168,
219, 73, 251, 192, 221, 41, 138, 160, 131, 191, 186, 156, 117, 179, 179, 191, 235, 171,
26, 219, 148, 170, 179, 11, 38, 137, 14, 95, 115, 171, 186, 163, 82, 158, 6, 239, 88,
])
.unwrap()
.into();
let msg2 = "bar";
let expected2 = G2Affine::from_compressed(&[
183, 25, 90, 187, 34, 184, 30, 182, 215, 242, 158, 83, 116, 34, 210, 96, 188, 79, 83,
255, 100, 122, 90, 188, 196, 93, 164, 253, 20, 106, 205, 33, 48, 140, 60, 149, 66, 246,
121, 244, 146, 66, 170, 60, 113, 95, 102, 237, 25, 231, 8, 42, 121, 124, 180, 140, 34,
104, 173, 251, 89, 189, 28, 196, 49, 66, 101, 38, 68, 44, 40, 235, 21, 35, 204, 123,
218, 238, 216, 92, 134, 217, 212, 246, 176, 77, 187, 0, 245, 134, 132, 73, 31, 44, 137,
197,
])
.unwrap()
.into();
let msg3 = [
33, 135, 76, 234, 71, 35, 247, 216, 39, 242, 42, 88, 152, 29, 74, 135, 9, 29, 216, 123,
250, 87, 108, 29, 245, 126, 109, 102, 84, 71, 158, 224, 145, 243, 49, 121, 244, 27,
115, 121, 25, 66, 216, 67, 97, 101, 140, 160, 77, 239, 114, 215, 152, 48, 15, 231, 101,
60, 42, 92, 128, 131, 161, 43,
];
let expected3 = G2Affine::from_compressed(&[
151, 185, 8, 123, 223, 150, 192, 192, 115, 10, 3, 129, 49, 179, 31, 108, 0, 17, 46,
231, 184, 164, 247, 228, 22, 142, 87, 70, 120, 111, 154, 15, 245, 110, 32, 84, 53, 117,
239, 93, 89, 119, 32, 17, 39, 250, 198, 137, 6, 95, 137, 202, 54, 244, 238, 190, 11,
217, 237, 95, 72, 59, 140, 56, 3, 42, 61, 195, 192, 101, 46, 204, 207, 75, 70, 176,
207, 48, 24, 195, 248, 234, 178, 168, 54, 109, 19, 189, 51, 52, 120, 69, 248, 226, 102,
91,
])
.unwrap()
.into();
assert_eq!(hash_g2(msg1, b"DUMMY_TEST_DOMAIN"), expected1);
assert_eq!(hash_g2(msg2, b"DUMMY_TEST_DOMAIN"), expected2);
assert_eq!(hash_g2(msg3, b"DUMMY_TEST_DOMAIN"), expected3);
}
}
+7 -6
View File
@@ -10,6 +10,7 @@ use nym_sphinx::params::packet_sizes::PacketSize;
use serde::{Deserialize, Serialize};
use std::string::FromUtf8Error;
use thiserror::Error;
use time::OffsetDateTime;
// specific errors (that should not be nested!!) for clients to match on
#[derive(Debug, Copy, Clone, Error, Serialize, Deserialize)]
@@ -112,15 +113,15 @@ pub enum AuthenticationFailure {
#[error("failed to verify request signature")]
InvalidSignature(#[from] SignatureError),
#[error("provided request timestamp is in the future")]
RequestTimestampInFuture,
#[error("the client is not registered")]
NotRegistered,
#[error("the provided request is too stale to process")]
StaleRequest,
#[error("the provided request timestamp is excessively skewed. got {received} whilst the server time is {server}")]
ExcessiveTimestampSkew {
received: OffsetDateTime,
server: OffsetDateTime,
},
#[error("the provided request timestamp is smaller or equal to a one previously used")]
#[error("the provided request timestamp is smaller or equal to one previously used")]
RequestReuse,
}
@@ -38,13 +38,22 @@ impl AuthenticateRequest {
})
}
pub fn verify_timestamp(&self, max_request_age: Duration) -> Result<(), AuthenticationFailure> {
pub fn verify_timestamp(
&self,
max_request_timestamp_skew: Duration,
) -> Result<(), AuthenticationFailure> {
let now = OffsetDateTime::now_utc();
if self.content.request_timestamp() + max_request_age < now {
return Err(AuthenticationFailure::StaleRequest);
if self.content.request_timestamp() < now - max_request_timestamp_skew {
return Err(AuthenticationFailure::ExcessiveTimestampSkew {
received: self.content.request_timestamp(),
server: now,
});
}
if self.content.request_timestamp() > now {
return Err(AuthenticationFailure::RequestTimestampInFuture);
if self.content.request_timestamp() - max_request_timestamp_skew > now {
return Err(AuthenticationFailure::ExcessiveTimestampSkew {
received: self.content.request_timestamp(),
server: now,
});
}
Ok(())
}
+11 -2
View File
@@ -12,7 +12,13 @@ license.workspace = true
[dependencies]
async-trait = { workspace = true }
reqwest = { workspace = true, features = ["json", "gzip"] }
reqwest = { workspace = true, features = [
"json",
"gzip",
"deflate",
"brotli",
"zstd",
] }
http.workspace = true
url = { workspace = true }
once_cell = { workspace = true }
@@ -30,7 +36,10 @@ mime = { 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"] }
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]
+26 -7
View File
@@ -1,3 +1,6 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
//! DNS resolver configuration for internal lookups.
//!
//! The resolver itself is the set combination of the google, cloudflare, and quad9 endpoints
@@ -9,6 +12,19 @@
//!
//! Requires the `dns-over-https-rustls`, `webpki-roots` feature for the
//! `hickory-resolver` crate
//!
//!
//! Note: The hickory DoH resolver can cause warning logs about H2 connection failure. This
//! indicates that the long lived https connection was closed by the remote peer and the resolver
//! will have to reconnect. It should not impact actual functionality.
//!
//! code ref: https://github.com/hickory-dns/hickory-dns/blob/06a8b1ce9bd9322d8e6accf857d30257e1274427/crates/proto/src/h2/h2_client_stream.rs#L534
//!
//! example log:
//!
//! ```txt
//! WARN /home/ubuntu/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/hickory-proto-0.24.3/src/h2/h2_client_stream.rs:493: h2 connection failed: unexpected end of file
//! ```
#![deny(missing_docs)]
use crate::ClientBuilder;
@@ -20,11 +36,10 @@ use std::{
use hickory_resolver::{
config::{LookupIpStrategy, NameServerConfigGroup, ResolverConfig, ResolverOpts},
error::ResolveError,
lookup_ip::LookupIpIntoIter,
error::{ResolveError, ResolveErrorKind},
lookup_ip::{LookupIp, LookupIpIntoIter},
TokioAsyncResolver,
};
use hickory_resolver::{error::ResolveErrorKind, lookup_ip::LookupIp};
use once_cell::sync::OnceCell;
use reqwest::dns::{Addrs, Name, Resolve, Resolving};
use tracing::warn;
@@ -33,6 +48,13 @@ 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.use_secure_dns = false;
self
}
/// Override the DNS resolver implementation used by the underlying http client.
pub fn no_hickory_dns(mut self) -> Self {
self.use_secure_dns = false;
self
}
}
@@ -191,10 +213,7 @@ impl HickoryDnsResolver {
/// 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());
let mut name_servers = NameServerConfigGroup::quad9_tls();
name_servers.merge(NameServerConfigGroup::quad9_https());
name_servers.merge(NameServerConfigGroup::cloudflare_tls());
name_servers.merge(NameServerConfigGroup::cloudflare_https());
+46 -25
View File
@@ -228,6 +228,8 @@ pub struct ClientBuilder {
timeout: Option<Duration>,
custom_user_agent: bool,
reqwest_client_builder: reqwest::ClientBuilder,
#[allow(dead_code)] // not dead code, just unused in wasm
use_secure_dns: bool,
}
impl ClientBuilder {
@@ -239,37 +241,50 @@ impl ClientBuilder {
U: IntoUrl,
E: Display,
{
// a naive check: if the provided URL does not start with http(s), add that scheme
let str_url = url.as_str();
// a naive check: if the provided URL does not start with http(s), add that scheme
if !str_url.starts_with("http") {
let alt = format!("http://{str_url}");
warn!("the provided url ('{str_url}') does not contain scheme information. Changing it to '{alt}' ...");
// TODO: or should we maybe default to https?
Self::new(alt)
} else {
#[cfg(target_arch = "wasm32")]
let reqwest_client_builder = reqwest::ClientBuilder::new();
Ok(Self::new_with_url(url.into_url()?))
}
}
#[cfg(not(target_arch = "wasm32"))]
let reqwest_client_builder = {
let r = reqwest::ClientBuilder::new()
.dns_resolver(Arc::new(HickoryDnsResolver::default()));
/// Constructs a new http `ClientBuilder` from a valid url.
pub fn new_with_url(url: Url) -> Self {
if !url.scheme().starts_with("http") {
warn!("the provided url ('{url}') does not use HTTP / HTTPS scheme");
}
// Note this is extra as the `gzip` feature for `reqwest` crate should be enabled which
// `"Enable[s] auto gzip decompression by checking the Content-Encoding response header."`
//
// I am going to leave it here anyways so that gzip decompression is attempted even if
// that feature is removed.
r.gzip(true)
};
#[cfg(target_arch = "wasm32")]
let reqwest_client_builder = reqwest::ClientBuilder::new();
Ok(ClientBuilder {
url: url.into_url()?,
timeout: None,
custom_user_agent: false,
reqwest_client_builder,
})
#[cfg(not(target_arch = "wasm32"))]
let reqwest_client_builder = {
// Note: I believe the manual enable calls for the compression methods are extra
// as the various compression features for `reqwest` crate should be enabled
// just by including the feature which:
// `"Enable[s] auto decompression by checking the Content-Encoding response header."`
//
// I am going to leave these here anyways so that removing a decompression method
// from the features list will throw an error if it is not also removed here.
reqwest::ClientBuilder::new()
.gzip(true)
.deflate(true)
.brotli(true)
.zstd(true)
};
ClientBuilder {
url,
timeout: None,
custom_user_agent: false,
reqwest_client_builder,
use_secure_dns: true,
}
}
@@ -325,10 +340,18 @@ impl ClientBuilder {
let mut builder = self
.reqwest_client_builder
.timeout(self.timeout.unwrap_or(DEFAULT_TIMEOUT));
// if no custom user agent was set, use a default
if !self.custom_user_agent {
builder =
builder.user_agent(format!("nym-http-api-client/{}", env!("CARGO_PKG_VERSION")))
}
// unless explicitly disabled use the DoT/DoH enabled resolver
if self.use_secure_dns {
builder = builder.dns_resolver(Arc::new(HickoryDnsResolver::default()));
}
builder.build()?
};
@@ -355,6 +378,9 @@ pub struct Client {
impl Client {
/// Create a new http `Client`
// no timeout until https://github.com/seanmonstar/reqwest/issues/1135 is fixed
//
// In order to prevent interference in API requests at the DNS phase we default to a resolver
// that uses DoT and DoH.
pub fn new(base_url: Url, timeout: Option<Duration>) -> Self {
Self::new_url::<_, String>(base_url, timeout).expect(
"we provided valid url and we were unwrapping previous construction errors anyway",
@@ -513,11 +539,6 @@ impl ApiClientCore for Client {
let mut request = self.reqwest_client.request(method.clone(), url);
// Indicate that compressed responses are preferred, but if not supported other encodings are fine.
// TODO: Down the road we can be more selective about adding this, but it's inclusion here guarantees
// that we use compression when available.
request = request.header(reqwest::header::ACCEPT_ENCODING, "gzip;q=1.0, *;q=0.5");
if let Some(body) = json_body {
request = request.json(body);
}
+143 -40
View File
@@ -23,14 +23,12 @@ const LENGTH_PREFIX_SIZE: usize = 2;
// long for the buffer to fill up, since this kills latency.
pub struct MultiIpPacketCodec {
buffer: BytesMut,
buffer_timeout: tokio::time::Interval,
}
impl MultiIpPacketCodec {
pub fn new(buffer_timeout: Duration) -> Self {
pub fn new() -> Self {
MultiIpPacketCodec {
buffer: BytesMut::new(),
buffer_timeout: tokio::time::interval(buffer_timeout),
}
}
@@ -40,56 +38,81 @@ impl MultiIpPacketCodec {
bundled_packets.extend_from_slice(&packet);
bundled_packets.freeze()
}
}
// Append a packet to the buffer and return the buffer if it's full
pub fn append_packet(&mut self, packet: Bytes) -> Option<Bytes> {
let mut bundled_packets = BytesMut::new();
self.encode(packet, &mut bundled_packets).unwrap();
if bundled_packets.is_empty() {
None
} else {
// log::info!("Sphinx packet utilization: {:.2}", self.buffer.len() as f64 / MAX_PACKET_SIZE as f64);
Some(bundled_packets.freeze())
impl Default for MultiIpPacketCodec {
fn default() -> Self {
Self::new()
}
}
/// The packet that we encode and decode with the MultiIpPacketCodec into bundled multi-ip packets.
/// The data here is the actual IP packet that we want to send, not the bundled packets.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum IprPacket {
Data(Bytes),
Flush,
}
impl IprPacket {
pub fn as_bytes(&self) -> &[u8] {
match self {
IprPacket::Data(bytes) => bytes.as_ref(),
IprPacket::Flush => &[],
}
}
// Flush the current buffer and return it.
pub fn flush_current_buffer(&mut self) -> Bytes {
let mut output_buffer = BytesMut::new();
std::mem::swap(&mut output_buffer, &mut self.buffer);
output_buffer.freeze()
}
// Wait for the buffer_timeout to tick and then flush the buffer.
// This is useful when we want to send the buffer even if it's not full.
pub async fn buffer_timeout(&mut self) -> Option<Bytes> {
// Wait for buffer_timeout to tick
let _ = self.buffer_timeout.tick().await;
// Flush the buffer and return it
let packets = self.flush_current_buffer();
if packets.is_empty() {
None
} else {
Some(packets)
pub fn into_bytes(self) -> Bytes {
match self {
IprPacket::Data(bytes) => bytes,
IprPacket::Flush => Bytes::new(),
}
}
}
impl Encoder<Bytes> for MultiIpPacketCodec {
impl From<Bytes> for IprPacket {
fn from(bytes: Bytes) -> Self {
IprPacket::Data(bytes)
}
}
impl From<Vec<u8>> for IprPacket {
fn from(bytes: Vec<u8>) -> Self {
IprPacket::Data(Bytes::from(bytes))
}
}
impl Encoder<IprPacket> for MultiIpPacketCodec {
type Error = Error;
fn encode(&mut self, packet: Bytes, dst: &mut BytesMut) -> Result<(), Self::Error> {
if self.buffer.is_empty() {
self.buffer_timeout.reset();
}
fn encode(&mut self, packet: IprPacket, dst: &mut BytesMut) -> Result<(), Self::Error> {
let packet = match packet {
IprPacket::Flush => {
dst.extend_from_slice(&self.buffer);
self.buffer = BytesMut::new();
return Ok(());
}
IprPacket::Data(packet) => packet,
};
let packet_size = packet.len();
// If the existing buffer is empty, and the packet is too large, send it directly
if self.buffer.is_empty() && packet_size + LENGTH_PREFIX_SIZE > MAX_PACKET_SIZE {
// Add the packet size
dst.extend_from_slice(&(packet_size as u16).to_be_bytes());
// Add the packet to the buffer
dst.extend_from_slice(&packet);
return Ok(());
}
// If the packet doesn't fit in the existing buffer, send what we have now in the buffer
// and then add it to the next buffer
if self.buffer.len() + packet_size + LENGTH_PREFIX_SIZE > MAX_PACKET_SIZE {
// If the packet doesn't fit in the buffer, send the buffer and then add it to the buffer
// Send the existing buffer
dst.extend_from_slice(&self.buffer);
// Start a new buffer
self.buffer = BytesMut::new();
self.buffer_timeout.reset();
}
// Add the packet size
@@ -103,7 +126,7 @@ impl Encoder<Bytes> for MultiIpPacketCodec {
}
impl Decoder for MultiIpPacketCodec {
type Item = Bytes;
type Item = IprPacket;
type Error = Error;
fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
@@ -125,6 +148,86 @@ impl Decoder for MultiIpPacketCodec {
// Read the packet
let packet = src.split_to(packet_size);
Ok(Some(packet.freeze()))
Ok(Some(IprPacket::Data(packet.freeze())))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_multi_ip_packet_codec_max_packet_size() {
let mut codec = MultiIpPacketCodec::new();
let mut buffer = BytesMut::new();
// A packet size that is large enough that two packets won't fit in the buffer
const PACKET_SIZE: usize = MAX_PACKET_SIZE - 100;
let packet1 = IprPacket::from(Bytes::from_static(&[0u8; PACKET_SIZE]));
let packet2 = IprPacket::from(Bytes::from_static(&[0u8; PACKET_SIZE]));
codec.encode(packet1.clone(), &mut buffer).unwrap();
assert_eq!(buffer.len(), 0);
codec.encode(packet2.clone(), &mut buffer).unwrap();
assert_eq!(buffer.len(), LENGTH_PREFIX_SIZE + PACKET_SIZE);
// First is the length prefix
assert_eq!(buffer[..2], (PACKET_SIZE as u16).to_be_bytes());
// Next is the packet
assert_eq!(&buffer[2..], packet1.as_bytes());
}
#[test]
fn encode_and_then_decode() {
let mut codec = MultiIpPacketCodec::new();
let mut buffer = BytesMut::new();
let packet = IprPacket::from(Bytes::from_static(&[0u8; 1000]));
codec.encode(packet.clone(), &mut buffer).unwrap();
codec.encode(packet.clone(), &mut buffer).unwrap();
let mut decoded_packets = Vec::new();
while let Some(decoded_packet) = codec.decode(&mut buffer).unwrap() {
decoded_packets.push(decoded_packet);
}
assert_eq!(decoded_packets.len(), 1);
assert_eq!(decoded_packets[0].as_bytes(), packet.as_bytes());
}
#[test]
fn encode_a_packat_that_is_too_large() {
let mut codec = MultiIpPacketCodec::new();
let mut buffer = BytesMut::new();
let packet = IprPacket::from(Bytes::from_static(
&[0u8; MAX_PACKET_SIZE + MAX_PACKET_SIZE],
));
codec.encode(packet, &mut buffer).unwrap();
assert_eq!(
buffer.len(),
MAX_PACKET_SIZE + MAX_PACKET_SIZE + LENGTH_PREFIX_SIZE
);
codec.encode(IprPacket::Flush, &mut buffer).unwrap();
assert_eq!(
buffer.len(),
MAX_PACKET_SIZE + MAX_PACKET_SIZE + LENGTH_PREFIX_SIZE
);
}
#[test]
fn check_that_max_size_does_not_flush() {
let mut codec = MultiIpPacketCodec::new();
let mut buffer = BytesMut::new();
let packet = IprPacket::from(Bytes::from_static(&[0u8; MAX_PACKET_SIZE - 2]));
codec.encode(packet.clone(), &mut buffer).unwrap();
assert_eq!(buffer.len(), 0);
let packet = IprPacket::from(Bytes::from_static(&[0u8; MAX_PACKET_SIZE - 2]));
codec.encode(packet.clone(), &mut buffer).unwrap();
assert_eq!(buffer.len(), MAX_PACKET_SIZE);
}
}
+3
View File
@@ -7,6 +7,9 @@ pub const TICKETBOOK_VALIDITY_DAYS: u32 = 7;
/// Specifies the number of tickets in each issued ticketbook.
pub const TICKETBOOK_SIZE: u64 = 50;
/// Specifies the minimum request size each signer must support
pub const MINIMUM_TICKETBOOK_DATA_REQUEST_SIZE: usize = 50;
/// This type is defined mostly for the purposes of having constants (like sizes) associated with given variants
/// It's not meant to be serialised or have any fancy traits defined on it (in this crate)
#[derive(Copy, Clone, Debug, PartialEq)]
+2 -2
View File
@@ -15,10 +15,10 @@ bls12_381 = { workspace = true, features = ["alloc", "pairings", "experimental",
bincode.workspace = true
cfg-if.workspace = true
itertools = { workspace = true }
digest = "0.9"
digest = { workspace = true }
rand = { workspace = true }
thiserror = { workspace = true }
sha2 = "0.9"
sha2 = { workspace = true }
bs58 = { workspace = true }
serde = { workspace = true, features = ["derive"] }
rayon = { workspace = true, optional = true }
+74 -8
View File
@@ -113,17 +113,13 @@ const G1_HASH_DOMAIN: &[u8] = b"NYMECASH-V01-CS02-with-BLS12381G1_XMD:SHA-256_SS
const SCALAR_HASH_DOMAIN: &[u8] = b"NYMECASH-V01-CS02-with-expander-SHA256";
pub fn hash_g1<M: AsRef<[u8]>>(msg: M) -> G1Projective {
<G1Projective as HashToCurve<ExpandMsgXmd<sha2::Sha256>>>::hash_to_curve(msg, G1_HASH_DOMAIN)
<G1Projective as HashToCurve<ExpandMsgXmd<sha2::Sha256>>>::hash_to_curve([msg], G1_HASH_DOMAIN)
}
pub fn hash_to_scalar<M: AsRef<[u8]>>(msg: M) -> Scalar {
let mut output = vec![Scalar::zero()];
Scalar::hash_to_field::<ExpandMsgXmd<sha2::Sha256>>(
msg.as_ref(),
SCALAR_HASH_DOMAIN,
&mut output,
);
Scalar::hash_to_field::<ExpandMsgXmd<sha2::Sha256>, _>([msg], SCALAR_HASH_DOMAIN, &mut output);
output[0]
}
@@ -273,9 +269,8 @@ pub fn check_vk_pairing(
#[cfg(test)]
mod tests {
use rand::RngCore;
use super::*;
use rand::RngCore;
#[test]
fn polynomial_evaluation() {
@@ -401,4 +396,75 @@ mod tests {
assert_eq!(hash_to_scalar(msg2), hash_to_scalar(msg2));
assert_ne!(hash_to_scalar(msg1), hash_to_scalar(msg2));
}
#[test]
fn test_hash_to_scalar() {
let msg1 = "foo";
let expected1 = Scalar::from_bytes(&[
253, 57, 224, 227, 175, 195, 226, 82, 46, 175, 33, 126, 171, 239, 255, 92, 108, 168, 6,
79, 90, 11, 235, 236, 221, 10, 85, 133, 42, 81, 95, 30,
])
.unwrap();
let msg2 = "bar";
let expected2 = Scalar::from_bytes(&[
48, 83, 69, 52, 42, 18, 135, 244, 211, 190, 160, 196, 118, 154, 24, 126, 0, 125, 72,
201, 170, 225, 123, 201, 52, 120, 171, 132, 235, 182, 20, 26,
])
.unwrap();
let msg3 = [
33, 135, 76, 234, 71, 35, 247, 216, 39, 242, 42, 88, 152, 29, 74, 135, 9, 29, 216, 123,
250, 87, 108, 29, 245, 126, 109, 102, 84, 71, 158, 224, 145, 243, 49, 121, 244, 27,
115, 121, 25, 66, 216, 67, 97, 101, 140, 160, 77, 239, 114, 215, 152, 48, 15, 231, 101,
60, 42, 92, 128, 131, 161, 43,
];
let expected3 = Scalar::from_bytes(&[
128, 189, 8, 43, 186, 55, 52, 61, 171, 196, 159, 177, 162, 100, 27, 143, 85, 83, 218,
171, 91, 220, 155, 25, 7, 38, 2, 36, 4, 93, 136, 4,
])
.unwrap();
assert_eq!(hash_to_scalar(msg1), expected1);
assert_eq!(hash_to_scalar(msg2), expected2);
assert_eq!(hash_to_scalar(msg3), expected3);
}
#[test]
fn test_hash_to_g1() {
let msg1 = "foo";
let expected1 = G1Affine::from_compressed(&[
161, 109, 186, 0, 192, 221, 83, 87, 71, 31, 120, 201, 185, 35, 62, 239, 46, 120, 117,
150, 191, 227, 128, 161, 78, 201, 207, 167, 86, 181, 229, 115, 2, 6, 178, 16, 251, 118,
219, 115, 184, 96, 2, 10, 31, 63, 150, 70,
])
.unwrap()
.into();
let msg2 = "bar";
let expected2 = G1Affine::from_compressed(&[
135, 102, 204, 42, 221, 49, 209, 192, 250, 87, 59, 255, 197, 93, 37, 113, 38, 2, 154,
233, 68, 234, 206, 182, 121, 212, 166, 210, 74, 155, 190, 33, 203, 237, 176, 60, 249,
241, 53, 170, 18, 168, 49, 35, 1, 151, 205, 174,
])
.unwrap()
.into();
let msg3 = [
33, 135, 76, 234, 71, 35, 247, 216, 39, 242, 42, 88, 152, 29, 74, 135, 9, 29, 216, 123,
250, 87, 108, 29, 245, 126, 109, 102, 84, 71, 158, 224, 145, 243, 49, 121, 244, 27,
115, 121, 25, 66, 216, 67, 97, 101, 140, 160, 77, 239, 114, 215, 152, 48, 15, 231, 101,
60, 42, 92, 128, 131, 161, 43,
];
let expected3 = G1Affine::from_compressed(&[
184, 200, 211, 115, 47, 45, 39, 185, 105, 9, 222, 247, 132, 241, 121, 130, 238, 224,
155, 109, 105, 201, 137, 154, 132, 149, 214, 233, 136, 69, 77, 132, 174, 30, 46, 123,
20, 92, 219, 18, 45, 29, 208, 127, 158, 145, 130, 41,
])
.unwrap()
.into();
assert_eq!(hash_g1(msg1), expected1);
assert_eq!(hash_g1(msg2), expected2);
assert_eq!(hash_g1(msg3), expected3);
}
}
@@ -7,7 +7,7 @@ use nym_sphinx_addressing::clients::Recipient;
use nym_sphinx_addressing::nodes::{NymNodeRoutingAddress, MAX_NODE_ADDRESS_UNPADDED_LEN};
use nym_sphinx_params::packet_sizes::PacketSize;
use nym_sphinx_params::{PacketType, ReplySurbKeyDigestAlgorithm};
use nym_sphinx_types::{NymPacket, SURBMaterial, SphinxError, SURB, UPDATED_LEGACY_VERSION};
use nym_sphinx_types::{NymPacket, SURBMaterial, SphinxError, SURB};
use nym_topology::{NymRouteProvider, NymTopologyError};
use rand::{CryptoRng, RngCore};
use serde::de::{Error as SerdeError, Visitor};
@@ -101,8 +101,7 @@ impl ReplySurb {
let delays = nym_sphinx_routing::generate_hop_delays(average_delay, route.len());
let destination = recipient.as_sphinx_destination();
let surb_material =
SURBMaterial::new(route, delays, destination).with_version(UPDATED_LEGACY_VERSION);
let surb_material = SURBMaterial::new(route, delays, destination);
// this can't fail as we know we have a valid route to gateway and have correct number of delays
Ok(ReplySurb {
@@ -4,6 +4,7 @@ use crate::fragment::Fragment;
use crate::{monitoring, ChunkingError};
use log::*;
use std::collections::HashMap;
use std::time::{Duration, Instant};
// TODO: perhaps a more sophisticated approach with writing to disk periodically in case
// we're receiving fast & furious in uncompressed 4K - we don't want to keep that in memory;
@@ -31,6 +32,9 @@ struct ReconstructionBuffer {
/// appropriately resized and all missing fragments are set to a `None`, thus keeping
/// everything in order the whole time, allowing for O(1) insertions and O(n) reconstruction.
fragments: Vec<Option<Fragment>>,
/// The timestamp of the last received fragment. Used for cleaning up stale buffers.
last_fragment_timestamp: Instant,
}
/// Type alias representing fully reconstructed message - its original data and list of all
@@ -56,6 +60,7 @@ impl ReconstructionBuffer {
previous_fragments_set_id: None,
next_fragments_set_id: None,
fragments: fragments_buffer,
last_fragment_timestamp: Instant::now(),
}
}
@@ -99,6 +104,8 @@ impl ReconstructionBuffer {
/// `previous_fragments_set_id` and `next_fragments_set_id` are set for the ease
/// of access.
fn insert_fragment(&mut self, fragment: Fragment) {
self.last_fragment_timestamp = Instant::now();
// all fragments in the buffer should always have the same id as before inserting an element,
// the correct buffer instance is looked up based on the fragment to be inserted.
debug_assert!({
@@ -158,6 +165,10 @@ pub struct MessageReconstructor {
}
impl MessageReconstructor {
// We want to be very conservative here. We remove these to avoid memory leaks, but it's okay
// to wait for a long time before we do so.
const INCOMPLETE_MESSAGE_TIMEOUT: Duration = Duration::from_secs(30 * 60);
/// Creates an empty `MessageReconstructor`.
pub fn new() -> Self {
Default::default()
@@ -296,6 +307,25 @@ impl MessageReconstructor {
pub fn recover_fragment(&self, fragment_data: Vec<u8>) -> Result<Fragment, ChunkingError> {
Fragment::try_from_bytes(&fragment_data)
}
pub fn cleanup_stale_buffers(&mut self) {
trace!("Cleaning up stale buffers");
let now = Instant::now();
self.reconstructed_sets.retain(|_, set_buf| {
let keep = now.duration_since(set_buf.last_fragment_timestamp)
< Self::INCOMPLETE_MESSAGE_TIMEOUT;
if !keep {
debug!(
"Removing stale buffer for set id {:?}",
set_buf
.fragments
.first()
.and_then(|f| f.as_ref().map(|f| f.id()))
);
}
keep
});
}
}
#[cfg(test)]
@@ -508,6 +538,8 @@ mod reconstruction_buffer {
#[cfg(test)]
mod message_reconstructor {
use std::time::Instant;
use super::*;
use crate::fragment::unlinked_fragment_payload_max_len;
use crate::set::{max_one_way_linked_set_payload_length, two_way_linked_set_payload_length};
@@ -869,6 +901,7 @@ mod message_reconstructor {
previous_fragments_set_id: None,
next_fragments_set_id: None,
fragments: vec![],
last_fragment_timestamp: Instant::now(),
},
);
@@ -879,6 +912,7 @@ mod message_reconstructor {
previous_fragments_set_id: None,
next_fragments_set_id: None,
fragments: vec![],
last_fragment_timestamp: Instant::now(),
},
);
@@ -1006,6 +1040,7 @@ mod message_reconstructor {
previous_fragments_set_id: None,
next_fragments_set_id: Some(1234),
fragments: vec![],
last_fragment_timestamp: Instant::now(),
},
);
@@ -1016,6 +1051,7 @@ mod message_reconstructor {
previous_fragments_set_id: Some(12345),
next_fragments_set_id: Some(123),
fragments: vec![],
last_fragment_timestamp: Instant::now(),
},
);
@@ -1026,6 +1062,7 @@ mod message_reconstructor {
previous_fragments_set_id: Some(1234),
next_fragments_set_id: Some(12),
fragments: vec![],
last_fragment_timestamp: Instant::now(),
},
);
@@ -1036,6 +1073,7 @@ mod message_reconstructor {
previous_fragments_set_id: Some(123),
next_fragments_set_id: None,
fragments: vec![],
last_fragment_timestamp: Instant::now(),
},
);
@@ -1083,6 +1121,7 @@ mod message_reconstructor {
previous_fragments_set_id: None,
next_fragments_set_id: Some(1234),
fragments: vec![],
last_fragment_timestamp: Instant::now(),
},
);
reconstructor.reconstructed_sets.insert(
@@ -1092,6 +1131,7 @@ mod message_reconstructor {
previous_fragments_set_id: Some(12345),
next_fragments_set_id: None,
fragments: vec![],
last_fragment_timestamp: Instant::now(),
},
);
assert_eq!(reconstructor.previous_linked_set_id(12345), None);
@@ -1139,6 +1179,7 @@ mod message_reconstructor {
previous_fragments_set_id: None,
next_fragments_set_id: Some(1234),
fragments: vec![],
last_fragment_timestamp: Instant::now(),
},
);
reconstructor.reconstructed_sets.insert(
@@ -1148,6 +1189,7 @@ mod message_reconstructor {
previous_fragments_set_id: Some(12345),
next_fragments_set_id: None,
fragments: vec![],
last_fragment_timestamp: Instant::now(),
},
);
assert_eq!(reconstructor.next_linked_set_id(12345), Some(1234));
-5
View File
@@ -30,7 +30,6 @@ pub use sphinx_packet::{
route::{Destination, DestinationAddressBytes, Node, NodeAddressBytes, SURBIdentifier},
surb::{SURBMaterial, SURB},
version::Version,
version::UPDATED_LEGACY_VERSION,
Error as SphinxError, ProcessedPacket, ProcessedPacketData,
};
@@ -91,12 +90,8 @@ impl NymPacket {
destination: &Destination,
delays: &[Delay],
) -> Result<NymPacket, NymPacketError> {
// FIXME:
// for now explicitly use the legacy version until sufficient number of nodes
// understand both variants
Ok(NymPacket::Sphinx(
SphinxPacketBuilder::new()
.with_version(UPDATED_LEGACY_VERSION)
.with_payload_size(size)
.build_packet(message, route, destination, delays)?,
))
@@ -182,9 +182,11 @@ impl BlockProcessor {
// the ones concerned with individual messages
for (index, msg) in block_tx.tx.body.messages.iter().enumerate() {
for msg_module in &mut self.msg_modules {
msg_module
.handle_msg(index, msg, &block_tx, &mut tx)
.await?
if msg.type_url == msg_module.type_url() {
msg_module
.handle_msg(index, msg, &block_tx, &mut tx)
.await?
}
}
}
}
+9
View File
@@ -83,6 +83,15 @@ pub enum ScraperError {
source: cosmrs::ErrorReport,
},
#[error("could not parse msg in tx {hash} at index {index} into {type_url}: {source}")]
MsgParseFailure {
hash: Hash,
index: usize,
type_url: String,
#[source]
source: cosmrs::ErrorReport,
},
#[error("received an invalid chain subscription event of kind {kind} while we were waiting for new block data (query: '{query}')")]
InvalidSubscriptionEvent { query: String, kind: String },
@@ -9,6 +9,8 @@ use cosmrs::Any;
#[async_trait]
pub trait MsgModule {
fn type_url(&self) -> String;
async fn handle_msg(
&mut self,
index: usize,
+36 -1
View File
@@ -2,7 +2,12 @@
// SPDX-License-Identifier: Apache-2.0
use futures::channel::mpsc;
use std::collections::HashMap;
use std::{
collections::HashMap,
time::{Duration, Instant},
};
const LANE_CONSIDERED_CLEAR: usize = 10;
pub type ConnectionId = u64;
@@ -67,6 +72,32 @@ impl LaneQueueLengths {
}
}
}
pub fn total(&self) -> usize {
match self.0.lock() {
Ok(inner) => inner.values().sum(),
Err(err) => {
log::warn!("Failed to get total queue length: {err}");
0
}
}
}
pub async fn wait_until_clear(&self, lane: &TransmissionLane, timeout: Option<Duration>) {
let total_time_waited = Instant::now();
loop {
let lane_length = self.get(lane).unwrap_or_default();
if lane_length < LANE_CONSIDERED_CLEAR {
break;
}
if timeout.is_some_and(|timeout| total_time_waited.elapsed() > timeout) {
log::warn!("Timeout reached while waiting for queue to clear");
break;
}
log::trace!("Waiting for queue to clear ({} items left)", lane_length);
tokio::time::sleep(Duration::from_millis(100)).await;
}
}
}
impl Default for LaneQueueLengths {
@@ -103,4 +134,8 @@ impl LaneQueueLengthsInner {
{
self.map.entry(*lane).and_modify(f);
}
pub fn total(&self) -> usize {
self.map.values().sum()
}
}
+1
View File
@@ -176,6 +176,7 @@ pub struct IssuedTicketbooksFullMerkleProof {
included_leaves: Vec<MerkleLeaf>,
total_leaves: usize,
#[schemars(with = "String")]
#[schema(value_type = String)]
#[serde(with = "nym_serde_helpers::hex")]
root: Vec<u8>,
}
+595 -485
View File
File diff suppressed because it is too large Load Diff
+17 -19
View File
@@ -1,9 +1,7 @@
[workspace]
resolver = "2"
members = [
# "coconut-bandwidth",
"coconut-dkg",
"coconut-test",
"ecash",
"mixnet",
"mixnet-vesting-integration-tests",
@@ -33,24 +31,24 @@ overflow-checks = true
[workspace.dependencies]
anyhow = "1.0.86"
bs58 = "0.4.0"
cosmwasm-crypto = "=1.4.3"
cosmwasm-derive = "=1.4.3"
cosmwasm-schema = "=1.4.3"
cosmwasm-std = "=1.4.3"
cosmwasm-storage = "=1.4.3"
cw-controllers = "=1.1.0"
cw-multi-test = "=0.16.5"
cw-storage-plus = "=1.2.0"
cw-utils = "=1.0.1"
cw2 = "=1.1.2"
cw3 = "=1.1.2"
cw3-fixed-multisig = "=1.1.2"
cw4 = "=1.1.2"
cw20 = "=1.1.2"
bs58 = "0.5.1"
cosmwasm-crypto = "=2.2.2"
cosmwasm-derive = "=2.2.2"
cosmwasm-schema = "=2.2.2"
cosmwasm-std = "=2.2.2"
cw-controllers = "=2.0.0"
cw-multi-test = "=2.3.2"
cw-storage-plus = "=2.0.0"
cw-utils = "=2.0.0"
cw2 = "=2.0.0"
cw3 = "=2.0.0"
cw3-fixed-multisig = "=2.0.0"
cw4 = "=2.0.0"
cw20 = "=2.0.0"
cw20-base = "2.0.0"
semver = "1.0.21"
serde = "1.0.196"
sylvia = "0.8.0"
sylvia = "1.3.3"
schemars = "0.8.16"
thiserror = "1.0.48"
thiserror = "2.0.11"
-3
View File
@@ -1,8 +1,5 @@
schema: coconut-dkg-schema mixnet-schema vesting-schema multisig-schema group-schema ecash-schema
#coconut-bandwidth-schema:
# $(MAKE) -C coconut-bandwidth generate-schema
coconut-dkg-schema:
$(MAKE) -C coconut-dkg generate-schema
@@ -1,4 +0,0 @@
[alias]
wasm = "build --release --lib --target wasm32-unknown-unknown"
unit-test = "test --lib"
schema = "run --bin schema --features=schema-gen"
-29
View File
@@ -1,29 +0,0 @@
[package]
name = "nym-coconut-bandwidth"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[[bin]]
name = "schema"
required-features = ["schema-gen"]
[lib]
crate-type = ["cdylib", "rlib"]
[dependencies]
nym-coconut-bandwidth-contract-common = { path = "../../common/cosmwasm-smart-contracts/coconut-bandwidth-contract" }
nym-multisig-contract-common = { path = "../../common/cosmwasm-smart-contracts/multisig-contract" }
cosmwasm-std = { workspace = true }
cosmwasm-schema = { workspace = true, optional = true }
cosmwasm-storage = { workspace = true }
cw-storage-plus = { workspace = true }
cw-controllers = { workspace = true }
serde = { version = "1.0.103", default-features = false, features = ["derive"] }
thiserror = { workspace = true }
[features]
schema-gen = ["nym-coconut-bandwidth-contract-common/schema", "cosmwasm-schema"]
-2
View File
@@ -1,2 +0,0 @@
generate-schema:
cargo schema
@@ -1,382 +0,0 @@
{
"contract_name": "nym-coconut-bandwidth",
"contract_version": "0.1.0",
"idl_version": "1.0.0",
"instantiate": {
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "InstantiateMsg",
"type": "object",
"required": [
"mix_denom",
"multisig_addr",
"pool_addr"
],
"properties": {
"mix_denom": {
"type": "string"
},
"multisig_addr": {
"type": "string"
},
"pool_addr": {
"type": "string"
}
},
"additionalProperties": false
},
"execute": {
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "ExecuteMsg",
"oneOf": [
{
"type": "object",
"required": [
"deposit_funds"
],
"properties": {
"deposit_funds": {
"type": "object",
"required": [
"data"
],
"properties": {
"data": {
"$ref": "#/definitions/DepositData"
}
},
"additionalProperties": false
}
},
"additionalProperties": false
},
{
"type": "object",
"required": [
"spend_credential"
],
"properties": {
"spend_credential": {
"type": "object",
"required": [
"data"
],
"properties": {
"data": {
"$ref": "#/definitions/SpendCredentialData"
}
},
"additionalProperties": false
}
},
"additionalProperties": false
},
{
"type": "object",
"required": [
"release_funds"
],
"properties": {
"release_funds": {
"type": "object",
"required": [
"funds"
],
"properties": {
"funds": {
"$ref": "#/definitions/Coin"
}
},
"additionalProperties": false
}
},
"additionalProperties": false
}
],
"definitions": {
"Coin": {
"type": "object",
"required": [
"amount",
"denom"
],
"properties": {
"amount": {
"$ref": "#/definitions/Uint128"
},
"denom": {
"type": "string"
}
}
},
"DepositData": {
"type": "object",
"required": [
"deposit_info",
"encryption_key",
"identity_key"
],
"properties": {
"deposit_info": {
"type": "string"
},
"encryption_key": {
"type": "string"
},
"identity_key": {
"type": "string"
}
},
"additionalProperties": false
},
"SpendCredentialData": {
"type": "object",
"required": [
"blinded_serial_number",
"funds",
"gateway_cosmos_address"
],
"properties": {
"blinded_serial_number": {
"type": "string"
},
"funds": {
"$ref": "#/definitions/Coin"
},
"gateway_cosmos_address": {
"type": "string"
}
},
"additionalProperties": false
},
"Uint128": {
"description": "A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```",
"type": "string"
}
}
},
"query": {
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "QueryMsg",
"oneOf": [
{
"type": "object",
"required": [
"get_spent_credential"
],
"properties": {
"get_spent_credential": {
"type": "object",
"required": [
"blinded_serial_number"
],
"properties": {
"blinded_serial_number": {
"type": "string"
}
},
"additionalProperties": false
}
},
"additionalProperties": false
},
{
"type": "object",
"required": [
"get_all_spent_credentials"
],
"properties": {
"get_all_spent_credentials": {
"type": "object",
"properties": {
"limit": {
"type": [
"integer",
"null"
],
"format": "uint32",
"minimum": 0.0
},
"start_after": {
"type": [
"string",
"null"
]
}
},
"additionalProperties": false
}
},
"additionalProperties": false
}
]
},
"migrate": {
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "MigrateMsg",
"type": "object",
"additionalProperties": false
},
"sudo": null,
"responses": {
"get_all_spent_credentials": {
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "PagedSpendCredentialResponse",
"type": "object",
"required": [
"per_page",
"spend_credentials"
],
"properties": {
"per_page": {
"type": "integer",
"format": "uint",
"minimum": 0.0
},
"spend_credentials": {
"type": "array",
"items": {
"$ref": "#/definitions/SpendCredential"
}
},
"start_next_after": {
"description": "Field indicating paging information for the following queries if the caller wishes to get further entries.",
"type": [
"string",
"null"
]
}
},
"additionalProperties": false,
"definitions": {
"Addr": {
"description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.",
"type": "string"
},
"Coin": {
"type": "object",
"required": [
"amount",
"denom"
],
"properties": {
"amount": {
"$ref": "#/definitions/Uint128"
},
"denom": {
"type": "string"
}
}
},
"SpendCredential": {
"type": "object",
"required": [
"blinded_serial_number",
"funds",
"gateway_cosmos_address",
"status"
],
"properties": {
"blinded_serial_number": {
"type": "string"
},
"funds": {
"$ref": "#/definitions/Coin"
},
"gateway_cosmos_address": {
"$ref": "#/definitions/Addr"
},
"status": {
"$ref": "#/definitions/SpendCredentialStatus"
}
},
"additionalProperties": false
},
"SpendCredentialStatus": {
"type": "string",
"enum": [
"in_progress",
"spent"
]
},
"Uint128": {
"description": "A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```",
"type": "string"
}
}
},
"get_spent_credential": {
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "SpendCredentialResponse",
"type": "object",
"properties": {
"spend_credential": {
"anyOf": [
{
"$ref": "#/definitions/SpendCredential"
},
{
"type": "null"
}
]
}
},
"additionalProperties": false,
"definitions": {
"Addr": {
"description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.",
"type": "string"
},
"Coin": {
"type": "object",
"required": [
"amount",
"denom"
],
"properties": {
"amount": {
"$ref": "#/definitions/Uint128"
},
"denom": {
"type": "string"
}
}
},
"SpendCredential": {
"type": "object",
"required": [
"blinded_serial_number",
"funds",
"gateway_cosmos_address",
"status"
],
"properties": {
"blinded_serial_number": {
"type": "string"
},
"funds": {
"$ref": "#/definitions/Coin"
},
"gateway_cosmos_address": {
"$ref": "#/definitions/Addr"
},
"status": {
"$ref": "#/definitions/SpendCredentialStatus"
}
},
"additionalProperties": false
},
"SpendCredentialStatus": {
"type": "string",
"enum": [
"in_progress",
"spent"
]
},
"Uint128": {
"description": "A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```",
"type": "string"
}
}
}
}
}
@@ -1,130 +0,0 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "ExecuteMsg",
"oneOf": [
{
"type": "object",
"required": [
"deposit_funds"
],
"properties": {
"deposit_funds": {
"type": "object",
"required": [
"data"
],
"properties": {
"data": {
"$ref": "#/definitions/DepositData"
}
},
"additionalProperties": false
}
},
"additionalProperties": false
},
{
"type": "object",
"required": [
"spend_credential"
],
"properties": {
"spend_credential": {
"type": "object",
"required": [
"data"
],
"properties": {
"data": {
"$ref": "#/definitions/SpendCredentialData"
}
},
"additionalProperties": false
}
},
"additionalProperties": false
},
{
"type": "object",
"required": [
"release_funds"
],
"properties": {
"release_funds": {
"type": "object",
"required": [
"funds"
],
"properties": {
"funds": {
"$ref": "#/definitions/Coin"
}
},
"additionalProperties": false
}
},
"additionalProperties": false
}
],
"definitions": {
"Coin": {
"type": "object",
"required": [
"amount",
"denom"
],
"properties": {
"amount": {
"$ref": "#/definitions/Uint128"
},
"denom": {
"type": "string"
}
}
},
"DepositData": {
"type": "object",
"required": [
"deposit_info",
"encryption_key",
"identity_key"
],
"properties": {
"deposit_info": {
"type": "string"
},
"encryption_key": {
"type": "string"
},
"identity_key": {
"type": "string"
}
},
"additionalProperties": false
},
"SpendCredentialData": {
"type": "object",
"required": [
"blinded_serial_number",
"funds",
"gateway_cosmos_address"
],
"properties": {
"blinded_serial_number": {
"type": "string"
},
"funds": {
"$ref": "#/definitions/Coin"
},
"gateway_cosmos_address": {
"type": "string"
}
},
"additionalProperties": false
},
"Uint128": {
"description": "A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```",
"type": "string"
}
}
}

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