Compare commits

...

229 Commits

Author SHA1 Message Date
Bogdan-Ștefan Neacşu 697d55248d Simplify pub key translatations 2024-05-23 13:31:28 +00:00
Bogdan-Ștefan Neacşu 570cc36385 Merge remote-tracking branch 'origin/feature/refine_wg_config' into bogdan/testing 2024-05-23 13:24:06 +00:00
Bogdan-Ștefan Neacşu ee64762b87 Init wireguard on migration 2024-05-20 14:32:30 +00:00
Bogdan-Ștefan Neacşu f4528bb521 Remove upgrade code 2024-05-20 11:25:32 +00:00
Bogdan-Ștefan Neacşu f4630e0b8a Bump gateway version number 2024-05-20 10:59:56 +00:00
Bogdan-Ștefan Neacşu 65f948d012 Remove logs 2024-05-20 10:26:13 +00:00
Bogdan-Ștefan Neacşu d16a288b6d Propagate wireguard setup error message 2024-05-20 10:06:55 +00:00
Bogdan-Ștefan Neacşu 72c40d8576 Rename network to ip for wg gw 2024-05-20 09:48:06 +00:00
Bogdan-Ștefan Neacşu 34e1709b75 Generate and use own private key 2024-05-20 09:05:07 +00:00
Jon Häggblad a06ae48e2f Add methods to MixnetClient to sign messages (#4602) 2024-05-20 10:22:28 +02:00
Bogdan-Ștefan Neacşu 257df97e3a Use client reg 2024-05-17 12:48:46 +00:00
Bogdan-Ștefan Neacşu 870570d5c3 Move key paths to separate structure 2024-05-17 11:33:30 +00:00
Bogdan-Ștefan Neacşu 0000baa343 Activate wg feature in gw dep 2024-05-17 11:33:30 +00:00
Bogdan-Ștefan Neacşu 6a307d59b4 Create wg keypair 2024-05-17 11:33:30 +00:00
Bogdan-Ștefan Neacşu a4808635f9 Support nym node first 2024-05-17 11:33:30 +00:00
Bogdan-Ștefan Neacşu 29965782a2 Include wireguard in gw config 2024-05-17 11:33:30 +00:00
Fouad e5f41731ae Explorer NextJS Rebuild (#4534)
* bootstrap next app + add overview page

* fix AssetList type

* fix up nav stuff

* Refactor Nav component and add network components pages

* Refactor WorldMap component and update TelegramIcon, GitHubIcon, NymVpnIcon, DiscordIcon, and TwitterIcon components

* add service providers page

* mixnodes page

* delegations page + use material react table for all tables

* nodes map page

* Refactor StyledLink component and remove unnecessary console.log statements

* Refactor ESLint configuration, remove unused dependencies, and update component imports

* update deps

* Refactor imports and update dependencies

* fix dark mode

* build single mixnode page

* build single gateway page

* Refactor handleOnDelegate function to use useCallback in mixnodes page.tsx

* Add defaults for constants

---------

Co-authored-by: Mark Sinclair <mmsinclair@users.noreply.github.com>
2024-05-16 16:12:06 +01:00
Jędrzej Stuczyński a6fda391ae Feature/rewarder voucher issuance (#4548)
* retrieve ed25519 identities of issuers

* signature verification on issued credentials

* wip

* persisting information about verified deposits, any failures and foul plays

* clippy
2024-05-16 10:15:24 +02:00
Tommy Verrall 1ded24dcfc Merge pull request #4586 from nymtech/bugfix/nym-api-noop-nobanner
[bugfix] noop flag for nym-api for nymvisor compatibility
2024-05-15 14:07:30 +01:00
Tommy Verrall 8c42640853 Merge pull request #4591 from nymtech/jon/described-offsettime-parsing
Use rfc3339 for last_polled in described nym-api endpoint
2024-05-15 14:03:42 +01:00
Tommy Verrall 38aabc7983 Merge pull request #4593 from nymtech/feature/extend-max-freepass-validity
change maximum validity of issuable freepass
2024-05-15 13:40:49 +01:00
Tommy Verrall 4324845d29 Merge pull request #4596 from nymtech/update-contract-addr
update mainnet contract addresses
2024-05-15 10:07:08 +01:00
Jędrzej Stuczyński b9524a0f58 Chore/additional helpers (#4585)
* exposed additional helpers

* changes lost in rebasing
2024-05-14 18:33:56 +02:00
Sachin Kamath e7cd417894 update mainnet contract addresses 2024-05-14 21:30:31 +05:30
benedetta davico ca25db845a Merge pull request #4573 from nymtech/feature/axum-upgrade
upgraded axum and related deps to the most recent version
2024-05-14 17:38:15 +02:00
benedetta davico 64a0ce31a8 Merge branch 'develop' into feature/axum-upgrade 2024-05-14 17:21:44 +02:00
Jędrzej Stuczyński a8fe8d9bfb change maximum validity of issuable freepass 2024-05-14 14:35:53 +01:00
Jędrzej Stuczyński c346f145d1 backwards compatibility to fallback to default in case of failures 2024-05-14 10:15:16 +01:00
Jon Häggblad 45dd6f2632 Fix typo for StorageError::ConstraintUnique (#4592) 2024-05-13 17:48:58 +02:00
Jon Häggblad 22d28759ab Explicitly use rfc3339 for last_polled 2024-05-13 15:55:32 +02:00
Jędrzej Stuczyński 890d0f7440 fixed incorrect dependency path for 'axum-extra' 2024-05-13 14:18:33 +01:00
Jędrzej Stuczyński b342eb870e removed explicit drops 2024-05-13 11:31:34 +01:00
Jędrzej Stuczyński fc71e0cafd fixed tests 2024-05-13 11:31:33 +01:00
Tommy Verrall 1ecb57fda0 Merge pull request #4588 from nymtech/jon/explicitly-handle-sqlite-constraint-violation
Explicitly handle constraint unique violation when importing credential
2024-05-13 11:30:31 +01:00
Tommy Verrall 3c1ec82289 Merge pull request #4588 from nymtech/jon/explicitly-handle-sqlite-constraint-violation
Explicitly handle constraint unique violation when importing credential
2024-05-13 09:57:42 +01:00
Tommy Verrall 089e403d87 Merge pull request #4589 from nymtech/master
merge latest master to develop
2024-05-13 09:56:34 +01:00
Tommy Verrall dd2b477cda Merge pull request #4587 from nymtech/jon/lock-files
Update stale lock files
2024-05-13 09:54:52 +01:00
benedetta davico 0902539332 Merge pull request #4583 from nymtech/release/2024.4-nutella
Release 2024.4-nutella to master
2024-05-13 10:27:08 +02:00
Jon Häggblad 0783c532de Explicitly handle constraint unique violation when importing credential 2024-05-13 10:19:01 +02:00
Jon Häggblad 8817ae7805 Update stale lock files 2024-05-13 08:57:49 +02:00
Jędrzej Stuczyński 6a900c3c42 fixed linter issue in nyxd-scraper 2024-05-10 15:05:37 +01:00
Jędrzej Stuczyński 0ba80c9a86 moved startup 'Starting nym api...' message from stdout to stderr 2024-05-10 11:16:10 +01:00
Jędrzej Stuczyński d712b65ec5 [bugfix] noop flag for nym-api for nymvisor compatibility 2024-05-10 11:02:21 +01:00
Tommy Verrall 383b2c1351 Merge pull request #4552 from nymtech/jon/validator-client-rustls
Add rustls-tls to reqwest in validator-client
2024-05-08 16:51:46 +01:00
benedetta davico fe7484f0f4 Merge pull request #4564 from nymtech/feature/nyxd-scraper-pruning
Feature/nyxd scraper pruning
2024-05-08 11:08:06 +02:00
benedettadavico f0a4350e83 pruning
version bump and changelog updates
2024-05-08 11:01:50 +02:00
Jędrzej Stuczyński b63d04b10c Merge pull request #4574 from nymtech/feature/coconut-unchecked-aggregation
[feature]: expose coconut methods for aggregation without verification
2024-05-08 09:03:43 +01:00
Jędrzej Stuczyński 5a35068c87 fixing clippy issues in the workspace 2024-05-08 08:44:09 +01:00
Jędrzej Stuczyński 4899773e61 fixed unblind call in tests 2024-05-08 08:43:14 +01:00
Jędrzej Stuczyński 996f4afaf7 [feature]: expose coconut methods for aggregation without verification 2024-05-08 08:43:13 +01:00
import this d5c2a01a34 [DOCs/operators]: 2024.4 nutella release changelog & mixnode ipv6 clarification (#4581)
* edit IPv6 mixnode info

* add mixnode ipv6 info and nuttela changelog

* syntax edit
2024-05-07 15:49:29 +00:00
benedetta davico b1c58b36fe Merge pull request #4578 from nymtech/update-sign-nym-node
updating sign commands to include nym-node
2024-05-07 14:50:51 +02:00
benedettadavico dfbcc781db extra space.. 2024-05-07 14:36:43 +02:00
benedettadavico 5026960169 linting 2024-05-07 14:10:57 +02:00
benedetta davico 7c2710b61a Merge pull request #4579 from nymtech/bugfix/exit-poisson
[fix] apply disable_poisson_rate from internal NR/IPR cfgs
2024-05-07 14:09:44 +02:00
Jędrzej Stuczyński 0af807ac92 fixed overflow subtraction 2024-05-07 12:14:20 +01:00
Jędrzej Stuczyński bf9fc2d537 external clippy 2024-05-07 11:49:25 +01:00
Jędrzej Stuczyński 4182af9199 [fix] apply disable_poisson_rate from internal NR/IPR cfgs 2024-05-07 11:41:57 +01:00
benedettadavico 408d803344 adding both options 2024-05-07 12:34:26 +02:00
benedettadavico c2a5d6c035 updating sign commands to nym-node 2024-05-07 12:20:55 +02:00
Tommy Verrall 1136901daf Merge pull request #4572 from nymtech/bugfix/change-redirects
changed nym-node redirects from 308 'Permanent Redirect' to 303: 'See Other'
2024-05-07 09:29:41 +01:00
Tommy Verrall 593a1da0ff Merge pull request #4565 from nymtech/bugfix/delegations
Bug fix: wallet delegations list is empty when RPC node doesn't hold block
2024-05-07 09:07:04 +01:00
Tommy Verrall 9c17b7c269 Merge pull request #4571 from nymtech/operators/ipv6-troubleshooting
[DOC/operators]: More troubleshooting for IPv6 & install dependencies guides
2024-05-07 08:50:55 +01:00
serinko df398dbe05 add mixnode IPv6 setup 2024-05-06 13:00:51 +02:00
Tommy Verrall effd03b2f5 Merge pull request #4567 from nymtech/dependabot/npm_and_yarn/ejs-3.1.10
Bump ejs from 3.1.9 to 3.1.10
2024-05-06 11:49:46 +01:00
Sachin Kamath e00db6adb9 docs: fix links to archive (#4576) 2024-05-06 09:08:21 +00:00
Jędrzej Stuczyński fd207d4699 changed nym-node redirects from 308 'Permanent Redirect' to 303: 'See Other' 2024-05-03 15:43:49 +01:00
serinko b9126dfc0e add troubleshooting for IPv6 & install dependencies 2024-05-03 13:19:59 +02:00
Jon Häggblad 7bbe153b8f Add AuthenticationFailureWithPreexistingSharedKey and a few log statements (#4568) 2024-05-03 09:53:53 +02:00
import this 36e1e73ed2 [DOCs]/operators: Create changelog page & add more nym-node troubleshooting (#4570)
* add note to binary download

* initialise changelog page

* finalise changelog draft

* add local ID rename guide

* remove old id

* syntax edit

* syntax edit

* syntax edit
2024-05-02 19:11:02 +02:00
Mark Sinclair 6e23322ac4 Update nym-wallet/src/components/Delegation/DelegationList.tsx 2024-05-02 14:57:00 +01:00
Mark Sinclair 729eedc960 Update publish-nym-wallet-win10.yml 2024-05-02 13:45:51 +01:00
Mark Sinclair 025cbf5231 Update publish-nym-wallet-ubuntu.yml 2024-05-02 13:45:46 +01:00
Mark Sinclair 3db3959a74 Update publish-nym-wallet-macos.yml 2024-05-02 13:45:39 +01:00
fmtabbara 3ba83795d4 add error dialog 2024-05-02 11:22:34 +01:00
dependabot[bot] 39b01d10bd Bump ejs from 3.1.9 to 3.1.10
Bumps [ejs](https://github.com/mde/ejs) from 3.1.9 to 3.1.10.
- [Release notes](https://github.com/mde/ejs/releases)
- [Commits](https://github.com/mde/ejs/compare/v3.1.9...v3.1.10)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-02 07:02:37 +00:00
Tommy Verrall f99bedd7e8 Merge pull request #4566 from nymtech/dependabot/npm_and_yarn/nym-wallet/webdriver/ejs-3.1.10
Bump ejs from 3.1.7 to 3.1.10 in /nym-wallet/webdriver
2024-05-02 08:01:12 +01:00
dependabot[bot] 7717bf5cf9 Bump ejs from 3.1.7 to 3.1.10 in /nym-wallet/webdriver
Bumps [ejs](https://github.com/mde/ejs) from 3.1.7 to 3.1.10.
- [Release notes](https://github.com/mde/ejs/releases)
- [Commits](https://github.com/mde/ejs/compare/v3.1.7...v3.1.10)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-02 00:47:12 +00:00
fmtabbara 6060ce5fb8 fix error tooltip overflow 2024-05-01 23:38:06 +01:00
Mark Sinclair 8fbad9cad8 Remove test errors 2024-05-01 19:33:10 +01:00
Mark Sinclair 650865e59a Wallet delegations: slow refresh from 1 min to 5 mins 2024-05-01 18:02:34 +01:00
Mark Sinclair 08e580ec8b Wallet delegations list - add an error to each row, and display as a tooltip if present 2024-05-01 17:59:46 +01:00
Mark Sinclair ad86ec9315 Wallet delegations: add more error information 2024-05-01 15:59:45 +01:00
Mark Sinclair 53ab4c8ec9 Wallet delegations: tap errors in requests per delegation. Return an error with strings of all sub errors. 2024-05-01 15:24:29 +01:00
Jędrzej Stuczyński f827eb4242 storage pruning implementation + additional logging 2024-04-30 15:53:45 +01:00
Jon Häggblad 6f4b00b5c2 Add default-features = true for tungstenite and non-wasm in client-core 2024-04-30 14:14:44 +02:00
Jon Häggblad d681ad20cf Keep default features off for tungstenite and wasm 2024-04-30 14:14:44 +02:00
Jon Häggblad 5818d58caf tweak feature args to tungstenite 2024-04-30 14:14:42 +02:00
Jon Häggblad da4eab8fdb Add rustls-tls to reqwest in validator-client 2024-04-30 14:14:00 +02:00
Jędrzej Stuczyński 9323ca9339 defined basic pruning types 2024-04-30 12:32:46 +01:00
import this f34c9d5d28 [DOCs]: Get nym-vpn guides ready for launch (#4563)
* update nymvpn cli guide

* update nymvpn landing page

* update nymvpn landing page

* syntax edit

* final version for review

* final version for review

* fix on feedback

* fix on feedback
2024-04-29 15:07:51 +00:00
import this b93afe7756 add useful feedback and edits (#4562) 2024-04-26 17:22:24 +00:00
benedetta davico 140cd7d940 Merge pull request #4560 from nymtech/master
Master to develop
2024-04-25 12:59:58 +02:00
benedetta davico 7d233a4a2f Merge pull request #4559 from nymtech/release/2024.3-eclipse
Merge release/2024.3 eclipse to master
2024-04-25 11:27:18 +02:00
import this 5f60344c2b HOTFIX ci-docs (#4558)
* HOTFIX ci-docs

* add a flag to bonding
2024-04-24 15:09:51 +00:00
import this c53b46ee1d [DOCs]: HOTFix CI/CD GH runners (#4554)
* build on master first

* rename pages to unique names

* rename pages to unique names

* module updates

* rm old cmrdun and fix modules

* syntax fix

* comment out cmdrun

* comment out cmdrun

* feedback fix

* TEMP hack to build books

* adding sleep to build script

* adding test to mdbook script

* TEMP hack to build books

* add cmdrun back

* add cmdrun back

* final commit - ready to go
2024-04-24 15:00:56 +02:00
benedetta davico 7fc9eca46f Update publish-nym-binaries.yml 2024-04-24 11:28:04 +02:00
Jon Häggblad 4e5c765a0d Quickfix for unused warnings after manually disabling legacy routes for release (#4557) 2024-04-23 16:24:59 +02:00
Jon Häggblad e1abbc0b5b Disable legacy endpoints in mixnode http client (#4556) 2024-04-23 13:46:02 +02:00
import this ce067db401 [DOCs]: Guides for NYM-NODE (#4541)
* initialise nym node pages

* new TOC flow and archive section

* vps setup page draft

* syntax fix

* syntax fix

* syntax fix

* add ulimit setup

* initialise nym-node page

* add ports

* syntax edit

* syntax edit

* add flags

* add setup, run and bonding pages

* add info

* syntax edit

* add configuration page

* syntax fix

* syntax fix

* add vps troubleshooting

* add vps troubleshooting

* create nyx configuration page

* add quickflow

* add quickflow

* add quickflow

* add quickflow

* add quickflow

* add quickflow

* syntax fix

* syntax fix

* move vps setup to configuration

* syntax fix

* syntax fix

* syntax fix

* edit points

* finish nym-node setup.md page

* new connnectivity configuration - page finished

* finish proxy and landing page guide

* finish nymvisor update

* finish performance testing upgdate

* finish faq pages update

* fix troubleshooting

* fix troubleshooting

* fix manual-upgrade

* finish introduction page

* update introduction

* update summary

* correct all links

* update graphs

* update cmdruns

* syntax edit and spellcheck

* updated mdbook plugins

* mdbook update

* update modules

* remove redundant

* fix version cmdrun

* removed smoosh-faw to archive

* syntax fix

* attempt to update mdbook admonish

* try dirty workaround hack

* try dirty workaround hack

* try dirty workaround hack

* try dirty workaround hack

* try dirty workaround hack

* try dirty workaround hack

* try dirty workaround hack

* try dirty workaround hack

* try dirty workaround hack

* address review comments

* address review comments

* address review comments

* PR ready to merge
2024-04-23 09:14:27 +00:00
Jon Häggblad 373cc54f3f cargo update -p rustls@0.21.10 (#4551) 2024-04-22 16:29:19 +02:00
benedettadavico a276608fd0 updating versions and changelog 2024-04-22 15:44:16 +02:00
Jędrzej Stuczyński b332a6b556 attach 'last_polled' metadata to node descriptions (#4550) 2024-04-22 09:54:01 +02:00
Tommy Verrall c610389198 Merge pull request #4549 from nymtech/dependabot/go_modules/wasm/mix-fetch/go-mix-conn/golang.org/x/net-0.23.0
Bump golang.org/x/net from 0.17.0 to 0.23.0 in /wasm/mix-fetch/go-mix-conn
2024-04-19 17:46:36 +02:00
dependabot[bot] d283ecae22 Bump golang.org/x/net in /wasm/mix-fetch/go-mix-conn
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.17.0 to 0.23.0.
- [Commits](https://github.com/golang/net/compare/v0.17.0...v0.23.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-19 12:20:51 +00:00
Jędrzej Stuczyński 2120acfdad Merge pull request #4547 from nymtech/feature/update-nymnode-bonding-version
Feature/update nymnode bonding version
2024-04-19 10:12:18 +01:00
Jędrzej Stuczyński b613775551 updated post-migration message 2024-04-18 15:16:18 +01:00
Jędrzej Stuczyński 73d4896b0b use {nym-node-binary-version}+nymnode rather than {nym-mixnode-binary-version}+nymnode for bonding info 2024-04-18 15:03:28 +01:00
Simon Wicky b8b66fa4ad rerandomize outfox's secret for each hop (#4544) 2024-04-18 13:48:08 +02:00
Jędrzej Stuczyński ba59022160 Merge pull request #4546 from nymtech/feature/disable-noise-key-announcement
don't announce noise keys
2024-04-18 12:18:24 +01:00
Jędrzej Stuczyński 8e2c64a867 don't announce noise keys 2024-04-18 11:25:29 +01:00
benedetta davico 73ae09cb76 Update Cargo.toml (#4543) 2024-04-17 14:00:58 +02:00
Simon Wicky fd238b1d1b fix dependency workspace typo (#4542) 2024-04-17 10:14:00 +02:00
Jon Häggblad 1f2d888626 Handle selected gateway in rust sdk (#4515)
* Set active gateway after setting up gateway in base client

* Elevate log statements in gateway setup

* Add debug implementations for some gateway setup types

* Rework gateway setup in rust sdk mixnet client

* Remove unused KeyMode type

* Remove pub from internal setters

* Remove pseudo builder methods

* Make create_bandwidth_client pub

* Downgrade log statement to debug

* Revert set_active_gateway in base_client

* Rename to set_active_gateway_if_previously_registered
2024-04-15 14:11:26 +02:00
Tommy Verrall 9f47b05ed6 Merge pull request #4537 from nymtech/dependabot/npm_and_yarn/wasm/mix-fetch/internal-dev-node/tar-6.2.1
Bump tar from 6.1.15 to 6.2.1 in /wasm/mix-fetch/internal-dev-node
2024-04-15 09:21:37 +01:00
Tommy Verrall f559a03732 Merge pull request #4538 from nymtech/dependabot/npm_and_yarn/wasm/client/internal-dev-node/tar-6.2.1
Bump tar from 6.1.15 to 6.2.1 in /wasm/client/internal-dev-node
2024-04-15 09:21:06 +01:00
Jędrzej Stuczyński 3e12766afd expose info whether entry gateway enforces zk-nym in self-described api (#4529) 2024-04-12 19:05:28 +02:00
Jędrzej Stuczyński 1c93cc8a68 Merge pull request #4437 from nymtech/feature/freepass-expiration
expire freepass bandwidth + stagger db flushes
2024-04-12 17:48:37 +01:00
Jędrzej Stuczyński 4865f7f205 [bugfix] Prevent generation of free passes with expiry date in the past (#4535) 2024-04-12 17:44:32 +02:00
Jędrzej Stuczyński a785950d76 [bugfix] don't shutdown NR on failed connection (#4539) 2024-04-12 17:43:22 +02:00
Jędrzej Stuczyński 328d1c25b7 removed old debug code 2024-04-12 15:23:37 +01:00
Jędrzej Stuczyński 862a248902 missing cli argument for controlling nyxd 2024-04-12 15:14:55 +01:00
Jędrzej Stuczyński f826904407 fix credential expiration + improve errors + naively stop client when out of bandwidth 2024-04-12 15:00:49 +01:00
Jędrzej Stuczyński 67467ca76d renamed 'shared_state' to 'common_state' 2024-04-12 15:00:49 +01:00
Jędrzej Stuczyński a53ae5b6b5 using lock guard in dedicated scope 2024-04-12 15:00:49 +01:00
Jędrzej Stuczyński bfc495ef29 expire freepass bandwidth + stagger db flushes 2024-04-12 15:00:48 +01:00
Jędrzej Stuczyński 9d74c22f9b Merge pull request #4536 from nymtech/bugfix/localnet
[bugfix] make sure localnet script works in post nym-node era
2024-04-12 12:41:53 +01:00
import this f978552a3a [DOC]: NymVPN testing Guides update (#4528)
* simplify cli - comment redundant pages

* unite mac and linux cli guide to one page

* finalise cli guide

* syntax edit

* book built

* syntax edit

* final version - ready to review

* final version - ready to review
2024-04-11 12:09:58 +00:00
dependabot[bot] b2477dd81b Bump tar from 6.1.15 to 6.2.1 in /wasm/client/internal-dev-node
Bumps [tar](https://github.com/isaacs/node-tar) from 6.1.15 to 6.2.1.
- [Release notes](https://github.com/isaacs/node-tar/releases)
- [Changelog](https://github.com/isaacs/node-tar/blob/main/CHANGELOG.md)
- [Commits](https://github.com/isaacs/node-tar/compare/v6.1.15...v6.2.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-11 10:51:16 +00:00
dependabot[bot] dcd712430e Bump tar from 6.1.15 to 6.2.1 in /wasm/mix-fetch/internal-dev-node
Bumps [tar](https://github.com/isaacs/node-tar) from 6.1.15 to 6.2.1.
- [Release notes](https://github.com/isaacs/node-tar/releases)
- [Changelog](https://github.com/isaacs/node-tar/blob/main/CHANGELOG.md)
- [Commits](https://github.com/isaacs/node-tar/compare/v6.1.15...v6.2.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-11 10:51:15 +00:00
Jędrzej Stuczyński 5dcad5ffd4 [bugfix] make sure localnet script works in post nym-node era 2024-04-11 10:25:04 +01:00
Jędrzej Stuczyński 210269cb9c [bugfix] restore old serialisation of 'NymNodeDescription' (#4533) 2024-04-11 10:11:46 +02:00
Jędrzej Stuczyński 8c59106add introduced /api-status routes for nym-api (#4527)
* introduced /api-status routes for nym-api

* added additional information to the signer-information endpoint
2024-04-11 09:28:42 +02:00
Tommy Verrall 264771f8cf Merge pull request #4428 from nymtech/sachin/delegate_from_file
nym-cli: delegations from a file
2024-04-10 15:36:11 +01:00
Tommy Verrall 28d27eb84e Merge pull request #4517 from nymtech/dependabot/cargo/sdk/ffi/shared/eyre-0.6.12
Bump eyre from 0.6.11 to 0.6.12 in /sdk/ffi/shared
2024-04-10 11:16:27 +01:00
Tommy Verrall d57757584c Merge pull request #4518 from nymtech/dependabot/cargo/sdk/ffi/cpp/eyre-0.6.12
Bump eyre from 0.6.11 to 0.6.12 in /sdk/ffi/cpp
2024-04-10 10:35:25 +01:00
Tommy Verrall 6da00513a7 Merge pull request #4519 from nymtech/dependabot/cargo/sdk/ffi/go/eyre-0.6.12
Bump eyre from 0.6.11 to 0.6.12 in /sdk/ffi/go
2024-04-10 10:25:38 +01:00
dependabot[bot] 035faf70e4 Bump eyre from 0.6.11 to 0.6.12 in /sdk/ffi/cpp
Bumps [eyre](https://github.com/eyre-rs/eyre) from 0.6.11 to 0.6.12.
- [Commits](https://github.com/eyre-rs/eyre/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-10 09:02:46 +00:00
Tommy Verrall b238d108e6 Merge pull request #4520 from nymtech/dependabot/cargo/sdk/ffi/cpp/h2-0.3.26
Bump h2 from 0.3.24 to 0.3.26 in /sdk/ffi/cpp
2024-04-10 10:01:47 +01:00
dependabot[bot] 5581b15094 Bump eyre from 0.6.11 to 0.6.12 in /sdk/ffi/go
Bumps [eyre](https://github.com/eyre-rs/eyre) from 0.6.11 to 0.6.12.
- [Commits](https://github.com/eyre-rs/eyre/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-10 08:34:13 +00:00
Tommy Verrall af19c4ecfd Merge pull request #4521 from nymtech/dependabot/cargo/sdk/ffi/go/h2-0.3.26
Bump h2 from 0.3.24 to 0.3.26 in /sdk/ffi/go
2024-04-10 09:31:31 +01:00
Jędrzej Stuczyński 1855423981 Merge pull request #4531 from nymtech/bugfix/self-described-backwards-compat
Bugfix/self described backwards compat
2024-04-09 16:49:18 +01:00
benedetta davico 229561bab9 update sandbox .env (#4530) 2024-04-09 17:47:30 +02:00
Jędrzej Stuczyński 7d2044c177 Merge pull request #4532 from nymtech/bugfix/standalone-node-http-api
run http api by default
2024-04-09 16:47:20 +01:00
Jędrzej Stuczyński 7885d3c986 removed dead code
removed dead code
2024-04-09 16:36:05 +01:00
Jędrzej Stuczyński 78fb3c2293 run http api by default 2024-04-09 16:26:54 +01:00
Jędrzej Stuczyński 0ed43d2439 allow nym-api to understand signatures on legacy host information 2024-04-09 16:17:39 +01:00
Jędrzej Stuczyński 69c1a32392 error prefix 2024-04-09 16:16:39 +01:00
Sachin Kamath 30ffea19a1 docs: add credential signing steps for nym-api (#4523)
* docs: add credential signing steps for nym-api

* review comments
2024-04-09 10:04:24 +02:00
Jon Häggblad 9e3bd8588d Re-export TransmissionLane type (#4525) 2024-04-08 16:05:12 +02:00
import this ac7b821782 [DOC]: Feature: cmdrun scripts (#4514)
* initialise cmdrun script dir

* initialise api_targets_config

* initialise api_targets

* first version of argparser cli

* create a token api stats table

* add format function

* initiate nym_vpn command

* add github to get api url

* add github api to config

* create nym_vpn releases dataframe

* menu headers tweak
2024-04-08 09:13:31 +00:00
dependabot[bot] bb372fb35c Bump eyre from 0.6.11 to 0.6.12 in /sdk/ffi/shared
Bumps [eyre](https://github.com/eyre-rs/eyre) from 0.6.11 to 0.6.12.
- [Commits](https://github.com/eyre-rs/eyre/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-08 08:28:10 +00:00
Tommy Verrall 5f4220867a Merge pull request #4522 from nymtech/dependabot/cargo/sdk/ffi/shared/h2-0.3.26
Bump h2 from 0.3.24 to 0.3.26 in /sdk/ffi/shared
2024-04-08 09:27:12 +01:00
Jon Häggblad bfa029f284 Use client-core default db names in sdk (#4524) 2024-04-06 09:54:53 +02:00
Jędrzej Stuczyński 4c5351ba60 Feature/one binary to rule them all (#4500) 2024-04-05 19:34:31 +02:00
dependabot[bot] 3a6058be60 Bump h2 from 0.3.24 to 0.3.26 in /sdk/ffi/shared
Bumps [h2](https://github.com/hyperium/h2) from 0.3.24 to 0.3.26.
- [Release notes](https://github.com/hyperium/h2/releases)
- [Changelog](https://github.com/hyperium/h2/blob/v0.3.26/CHANGELOG.md)
- [Commits](https://github.com/hyperium/h2/compare/v0.3.24...v0.3.26)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-05 16:24:23 +00:00
dependabot[bot] 7fcc8cdd19 Bump h2 from 0.3.24 to 0.3.26 in /sdk/ffi/go
Bumps [h2](https://github.com/hyperium/h2) from 0.3.24 to 0.3.26.
- [Release notes](https://github.com/hyperium/h2/releases)
- [Changelog](https://github.com/hyperium/h2/blob/v0.3.26/CHANGELOG.md)
- [Commits](https://github.com/hyperium/h2/compare/v0.3.24...v0.3.26)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-05 16:24:03 +00:00
dependabot[bot] 098bd4eb3c Bump h2 from 0.3.24 to 0.3.26 in /sdk/ffi/cpp
Bumps [h2](https://github.com/hyperium/h2) from 0.3.24 to 0.3.26.
- [Release notes](https://github.com/hyperium/h2/releases)
- [Changelog](https://github.com/hyperium/h2/blob/v0.3.26/CHANGELOG.md)
- [Commits](https://github.com/hyperium/h2/compare/v0.3.24...v0.3.26)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-05 16:18:54 +00:00
Jon Häggblad fa1e9988b3 Add credentials mode command to SDK mixnet builder (#4516) 2024-04-05 15:51:48 +02:00
Tommy Verrall 999b4f743e Merge pull request #4470 from nymtech/feature/explorer-delegation-mobile
Feature/explorer delegation mobile
2024-04-02 08:20:26 +01:00
Tommy Verrall cc55abf7fb Merge pull request #4510 from nymtech/dependabot/npm_and_yarn/clients/native/examples/js-examples/websocket/express-4.19.2
Bump express from 4.18.2 to 4.19.2 in /clients/native/examples/js-examples/websocket
2024-04-02 08:17:35 +01:00
Tommy Verrall 020edb8f84 Merge pull request #4512 from nymtech/dependabot/npm_and_yarn/wasm/node-tester/internal-dev/express-4.19.2
Bump express from 4.18.2 to 4.19.2 in /wasm/node-tester/internal-dev
2024-04-02 08:17:05 +01:00
Tommy Verrall ae2079272b Merge pull request #4511 from nymtech/dependabot/npm_and_yarn/wasm/client/internal-dev/express-4.19.2
Bump express from 4.18.2 to 4.19.2 in /wasm/client/internal-dev
2024-04-02 08:16:53 +01:00
Tommy Verrall a656429376 Merge pull request #4513 from nymtech/dependabot/npm_and_yarn/wasm/mix-fetch/internal-dev/express-4.19.2
Bump express from 4.18.2 to 4.19.2 in /wasm/mix-fetch/internal-dev
2024-04-02 08:13:49 +01:00
dependabot[bot] 2086946e16 Bump express from 4.18.2 to 4.19.2 in /wasm/mix-fetch/internal-dev
Bumps [express](https://github.com/expressjs/express) from 4.18.2 to 4.19.2.
- [Release notes](https://github.com/expressjs/express/releases)
- [Changelog](https://github.com/expressjs/express/blob/master/History.md)
- [Commits](https://github.com/expressjs/express/compare/4.18.2...4.19.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-29 08:31:27 +00:00
dependabot[bot] 08e0892327 Bump express from 4.18.2 to 4.19.2 in /wasm/node-tester/internal-dev
Bumps [express](https://github.com/expressjs/express) from 4.18.2 to 4.19.2.
- [Release notes](https://github.com/expressjs/express/releases)
- [Changelog](https://github.com/expressjs/express/blob/master/History.md)
- [Commits](https://github.com/expressjs/express/compare/4.18.2...4.19.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-29 08:31:25 +00:00
dependabot[bot] d28783cb2a Bump express from 4.18.2 to 4.19.2 in /wasm/client/internal-dev
Bumps [express](https://github.com/expressjs/express) from 4.18.2 to 4.19.2.
- [Release notes](https://github.com/expressjs/express/releases)
- [Changelog](https://github.com/expressjs/express/blob/master/History.md)
- [Commits](https://github.com/expressjs/express/compare/4.18.2...4.19.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-29 08:31:24 +00:00
dependabot[bot] 1815a2d3a5 Bump express in /clients/native/examples/js-examples/websocket
Bumps [express](https://github.com/expressjs/express) from 4.18.2 to 4.19.2.
- [Release notes](https://github.com/expressjs/express/releases)
- [Changelog](https://github.com/expressjs/express/blob/master/History.md)
- [Commits](https://github.com/expressjs/express/compare/4.18.2...4.19.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-28 18:44:49 +00:00
Tommy Verrall 1429f63d9d Merge pull request #4464 from nymtech/feature/remove-allowlist
removed the usage of allow.list
2024-03-28 16:10:59 +00:00
Jędrzej Stuczyński 1ed087e801 fixed NR template 2024-03-28 15:43:37 +00:00
Jędrzej Stuczyński 7fce0a9692 remove explicit deref 2024-03-28 15:43:37 +00:00
Jędrzej Stuczyński bef0a537b2 config migration for removing allow.list 2024-03-28 15:43:37 +00:00
Jędrzej Stuczyński fb2b2c963b moved and renamed NR old config structs 2024-03-28 15:43:37 +00:00
Jędrzej Stuczyński 2aa5e25532 removed the usage of allow.list 2024-03-28 15:43:36 +00:00
Tommy Verrall 588ed7dead Merge pull request #4509 from nymtech/bugfix/metrics-precondition
bugfix: use OptionFuture for creating metrics server
2024-03-28 15:39:33 +00:00
Jędrzej Stuczyński 519d419bbf bugfix: use OptionFuture for creating metrics server 2024-03-28 15:16:28 +00:00
fmtabbara f5e72cefcc Update dependencies in yarn.lock file 2024-03-28 10:15:16 +00:00
fmtabbara 1223f50fe8 Merge branch 'develop' into feature/explorer-delegation-mobile 2024-03-27 16:29:58 +00:00
fmtabbara 635ae1118a Add mobile delegations beta banner 2024-03-22 12:19:54 +00:00
fmtabbara 68e0dd1f29 update success tx wording 2024-03-21 14:57:12 +00:00
fmtabbara cf201cba53 only use keplr wallet + add info banner 2024-03-21 14:27:16 +00:00
fmtabbara efe952fdf2 explorer package updates 2024-03-20 16:30:59 +00:00
fmtabbara 6d2e761319 Merge branch 'develop' into feature/explorer-delegation-mobile 2024-03-20 14:58:36 +00:00
fmtabbara e699f1ad79 explorer env configuration updates 2024-03-20 13:45:29 +00:00
fmtabbara 01e4abc95f Update width of confirmation modal 2024-03-19 21:03:11 +00:00
fmtabbara 2195310d06 remove walletconnect (for now) 2024-03-19 18:20:17 +00:00
fmtabbara b6cd9b2bae add leap wallet 2024-03-19 14:37:10 +00:00
fmtabbara 682db85268 try to fix rpc endpoint 2024-03-19 12:46:17 +00:00
Sachin Kamath 1ebb0c7daa don't use bigdecimal 2024-03-18 20:28:55 +05:30
fmtabbara 70b15c9226 test mainnet mixnodes 2024-03-15 21:08:14 +00:00
fmtabbara f7e6677878 update dotenv config 2024-03-15 16:28:01 +00:00
fmtabbara 73e87b2deb test wallet connect projectId 2024-03-15 16:17:02 +00:00
fmtabbara 6735c1ae58 append to env (dont overwrite) 2024-03-14 21:30:59 +00:00
fmtabbara b037c8fbeb test mobile delegations config 2024-03-14 14:15:41 +00:00
fmtabbara 3fcfbad4c0 add sandbox to cosmos-kit 2024-03-13 14:35:17 +00:00
fmtabbara 43e4cabb85 Merge branch 'develop' into feature/explorer-delegation 2024-03-12 14:28:16 +00:00
fmtabbara 496a1bc97d package updates 2024-03-12 10:20:38 +00:00
fmtabbara 7db4ddff56 use url as unique nav selection state 2024-03-12 10:20:26 +00:00
fmtabbara 6b25f83ee3 small UI updates
tidy up some text layouts + allow mixnode row selections
2024-03-12 10:19:03 +00:00
fmtabbara 7602f4b130 create delegations context and page 2024-03-12 10:17:29 +00:00
fmtabbara f762062f9f create wallet context + wallet components
create wallet context using cosmoskit + include nymclient + create wallet components
2024-03-12 10:16:06 +00:00
fmtabbara 28a0c3eb17 Add buffer module to webpack.common.js 2024-02-28 11:50:19 +00:00
fmtabbara a3d7b541e2 Fix currencyToString function call in Mixnodes page 2024-02-28 10:16:20 +00:00
Mark Sinclair 7861a0081a Add mixnet contract to env and add CI targets to package.json 2024-02-28 10:16:20 +00:00
Mark Sinclair c8b911d5d0 Make mixnet contract configurable 2024-02-28 10:16:20 +00:00
fmtabbara 22979ce245 add ledger intergration 2024-02-28 10:16:20 +00:00
fmtabbara b5a3a720a4 fix up delegate button in mobile view 2024-02-28 10:16:20 +00:00
fmtabbara 0ec5fb37c2 replace delegate icon button with button
fix linting
2024-02-28 10:16:20 +00:00
fmtabbara 2817c68e2e make mobile nav neater 2024-02-28 10:16:20 +00:00
fmtabbara c3050e5d02 allow clear search entry
fix react hooks error
2024-02-28 10:16:19 +00:00
fmtabbara 8f1901b6e0 tidy up mixnode and gateway tables 2024-02-28 10:16:19 +00:00
fmtabbara 96a42fa03d Fix table layouts
tidy up exports
2024-02-28 10:16:18 +00:00
fmtabbara 718de1f102 fix up mobile view
fix deps issues
2024-02-28 10:16:12 +00:00
fmtabbara cb9d730c16 display user message when wallet is not connected
fix linting
2024-02-28 10:16:12 +00:00
Yana 0e17fe5581 Add delegate button to each mixnode raw
relocate code

code refactor

wip

refactor

wip
2024-02-28 10:16:07 +00:00
Yana b25747dd60 Fix ModalError styles 2024-02-28 10:16:06 +00:00
Yana b16349f2e9 Add confirmation models 2024-02-28 10:16:06 +00:00
Yana f4b5693bcb Add CosmWasmSigningClient
WIP

wip
2024-02-28 10:16:06 +00:00
Yana 42a53a1c49 Remove identity key, mixId and amount validation
WIP
2024-02-28 10:16:06 +00:00
Yana 081fec72e5 Connect delegate modal to keplr balance
WIP

WIP

WIP

WIP
2024-02-28 10:16:06 +00:00
Yana f2223dddca Add Delegations Modal UI 2024-02-28 10:16:06 +00:00
Yana 9be7b8ab56 Add TokenSVG 2024-02-28 10:16:06 +00:00
Yana 40dc0d2cc7 fix ui bug in ts.config 2024-02-28 10:16:06 +00:00
Yana 19de5cb792 WIP
WIP
2024-02-28 10:16:06 +00:00
Sachin Kamath 377e06daab nym-cli: clippy fixes 2024-02-22 18:10:41 +05:30
Sachin Kamath b54d82a01a nym-cli: batch transactions 2024-02-22 17:55:35 +05:30
Sachin Kamath ad052ef498 fmt + clippy 2024-02-21 19:14:12 +05:30
Sachin Kamath a3bc4af8fe fmt + clippy 2024-02-21 19:12:02 +05:30
Sachin Kamath b6d57e2862 nym-cli: delegate to mixnodes from input csv file
nym-cli: delegate to mixnodes from input csv file
2024-02-21 18:44:15 +05:30
617 changed files with 73650 additions and 13512 deletions
+18 -3
View File
@@ -9,7 +9,7 @@ jobs:
steps:
- uses: actions/checkout@v3
- name: Install Dependencies (Linux)
run: sudo apt-get update && sudo apt-get install -y build-essential curl wget libssl-dev libudev-dev squashfs-tools protobuf-compiler
run: sudo apt-get update && sudo apt-get install -y build-essential curl wget libssl-dev libudev-dev squashfs-tools protobuf-compiler git
- name: Install rsync
run: sudo apt-get install rsync
- uses: rlespinasse/github-slug-action@v3.x
@@ -30,9 +30,24 @@ jobs:
- name: Remove existing Nym config directory (`~/.nym/`)
run: cd documentation && ./remove_existing_config.sh
continue-on-error: false
- name: Build all projects in documentation/ & move to ~/dist/docs/
# This is the original flow
# - name: Build all projects in documentation/ & move to ~/dist/docs/
# run: cd documentation && ./build_all_to_dist.sh
# This is a workaround replacement which builds on the last working commit b332a6b55668f60988e36961f3f62a794ba82ddb and then on current branch
- name: Save current branch to ~/current_branch
run: git rev-parse --abbrev-ref HEAD > ~/current_branch
- name: Git pull & switch to b332a6b55668f60988e36961f3f62a794ba82ddb
run: git pull && git checkout b332a6b55668f60988e36961f3f62a794ba82ddb
- name: Build all projects in documentation/ & move to ~/dist/docs/ from b332a6b55668f60988e36961f3f62a794ba82ddb
run: cd documentation && ./build_all_to_dist.sh
continue-on-error: false
- name: Switch to current branch
run: git checkout $echo "$(cat ~/current_branch)"
- name: Build all projects in documentation/ & move to ~/dist/docs/ on current branch
run: cd documentation && ./build_all_to_dist.sh && rm ~/current_branch
# End of replacemet
- name: Post process
run: cd documentation && ./post_process.sh
@@ -112,6 +112,7 @@ jobs:
target/release/nym-network-statistics
target/release/nym-cli
target/release/nymvisor
target/release/nym-node
retention-days: 30
# If this was a pull_request or nightly, upload to build server
@@ -130,6 +131,7 @@ jobs:
cp target/release/nym-network-requester $OUTPUT_DIR
cp target/release/nym-network-statistics $OUTPUT_DIR
cp target/release/nymvisor $OUTPUT_DIR
cp target/release/nym-node $OUTPUT_DIR
cp target/release/nym-cli $OUTPUT_DIR
cp target/release/explorer-api $OUTPUT_DIR
if [ ${{ github.event_name == 'workflow_dispatch' && inputs.enable_deb == true }} = true ]; then
+19 -3
View File
@@ -13,7 +13,7 @@ jobs:
steps:
- uses: actions/checkout@v3
- name: Install Dependencies (Linux)
run: sudo apt-get update && sudo apt-get install -y build-essential curl wget libssl-dev libudev-dev squashfs-tools protobuf-compiler
run: sudo apt-get update && sudo apt-get install -y build-essential curl wget libssl-dev libudev-dev squashfs-tools protobuf-compiler git
- name: Install rsync
run: sudo apt-get install rsync
- uses: rlespinasse/github-slug-action@v3.x
@@ -34,9 +34,25 @@ jobs:
- name: Remove existing Nym config directory (`~/.nym/`)
run: cd documentation && ./remove_existing_config.sh
continue-on-error: false
- name: Build all projects in documentation/ & move to ~/dist/docs/
# This is the original flow
# - name: Build all projects in documentation/ & move to ~/dist/docs/
# run: cd documentation && ./build_all_to_dist.sh
# This is a workaround replacement which builds on the last working commit b332a6b55668f60988e36961f3f62a794ba82ddb and then on current branch
- name: Save current branch to ~/current_branch
run: git rev-parse --abbrev-ref HEAD > ~/current_branch
- name: Git pull & switch to b332a6b55668f60988e36961f3f62a794ba82ddb
run: git pull && git checkout b332a6b55668f60988e36961f3f62a794ba82ddb
- name: Build all projects in documentation/ & move to ~/dist/docs/ from b332a6b55668f60988e36961f3f62a794ba82ddb
run: cd documentation && ./build_all_to_dist.sh
continue-on-error: false
- name: Switch to current branch
run: git checkout $echo "$(cat ~/current_branch)"
- name: Build all projects in documentation/ & move to ~/dist/docs/ on current branch
run: cd documentation && ./build_all_to_dist.sh && rm ~/current_branch
# End of replacemet
- name: Deploy branch to CI www
continue-on-error: true
@@ -30,6 +30,7 @@ jobs:
mixnode_hash: ${{ steps.binary-hashes.outputs.mixnode_hash }}
gateway_hash: ${{ steps.binary-hashes.outputs.gateway_hash }}
nymvisor_hash: ${{ steps.binary-hashes.outputs.nymvisor_hash }}
nymnode_hash: ${{ steps.binary-hashes.outputs.nymnode_hash }}
socks5_hash: ${{ steps.binary-hashes.outputs.socks5_hash }}
netreq_hash: ${{ steps.binary-hashes.outputs.netreq_hash }}
cli_hash: ${{ steps.binary-hashes.outputs.cli_hash }}
@@ -38,6 +39,7 @@ jobs:
mixnode_version: ${{ steps.binary-versions.outputs.mixnode_version }}
gateway_version: ${{ steps.binary-versions.outputs.gateway_version }}
nymvisor_version: ${{ steps.binary-versions.outputs.nymvisor_version }}
nymnode_version: ${{ steps.binary-versions.outputs.nymnode_version }}
socks5_version: ${{ steps.binary-versions.outputs.socks5_version }}
netreq_version: ${{ steps.binary-versions.outputs.netreq_version }}
cli_version: ${{ steps.binary-versions.outputs.cli_version }}
@@ -81,6 +83,7 @@ jobs:
target/release/nym-network-statistics
target/release/nym-cli
target/release/nymvisor
target/release/nym-node
retention-days: 30
- id: create-release
@@ -99,6 +102,7 @@ jobs:
target/release/nym-network-statistics
target/release/nym-cli
target/release/nymvisor
target/release/nym-node
push-release-data-client:
if: ${{ (startsWith(github.ref, 'refs/tags/nym-binaries-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }}
@@ -102,6 +102,18 @@ jobs:
nym-wallet/target/release/bundle/dmg/*.dmg
nym-wallet/target/release/bundle/macos/*.app.tar.gz*
- name: Deploy artifacts to CI www
continue-on-error: true
uses: easingthemes/ssh-deploy@main
env:
SSH_PRIVATE_KEY: ${{ secrets.CI_WWW_SSH_PRIVATE_KEY }}
ARGS: "-avzr"
SOURCE: "nym-wallet/target/release/bundle/macos/nym-wallet.app.tar.gz"
REMOTE_HOST: ${{ secrets.CI_WWW_REMOTE_HOST }}
REMOTE_USER: ${{ secrets.CI_WWW_REMOTE_USER }}
TARGET: ${{ secrets.CI_WWW_REMOTE_TARGET }}/builds/${{ github.ref_name }}/nym-wallet
EXCLUDE: "/dist/, /node_modules/"
push-release-data:
if: ${{ (startsWith(github.ref, 'refs/tags/nym-wallet-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }}
uses: ./.github/workflows/release-calculate-hash.yml
@@ -77,6 +77,18 @@ jobs:
nym-wallet/target/release/bundle/appimage/*.AppImage
nym-wallet/target/release/bundle/appimage/*.AppImage.tar.gz*
- name: Deploy artifacts to CI www
continue-on-error: true
uses: easingthemes/ssh-deploy@main
env:
SSH_PRIVATE_KEY: ${{ secrets.CI_WWW_SSH_PRIVATE_KEY }}
ARGS: "-avzr"
SOURCE: "nym-wallet/target/release/bundle/appimage/nym-wallet*.AppImage.tar.gz"
REMOTE_HOST: ${{ secrets.CI_WWW_REMOTE_HOST }}
REMOTE_USER: ${{ secrets.CI_WWW_REMOTE_USER }}
TARGET: ${{ secrets.CI_WWW_REMOTE_TARGET }}/builds/${{ github.ref_name }}/nym-wallet
EXCLUDE: "/dist/, /node_modules/"
push-release-data:
if: ${{ (startsWith(github.ref, 'refs/tags/nym-wallet-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }}
uses: ./.github/workflows/release-calculate-hash.yml
@@ -97,6 +97,18 @@ jobs:
nym-wallet/target/release/bundle/msi/*.msi
nym-wallet/target/release/bundle/msi/*.msi.zip*
- name: Deploy artifacts to CI www
continue-on-error: true
uses: easingthemes/ssh-deploy@main
env:
SSH_PRIVATE_KEY: ${{ secrets.CI_WWW_SSH_PRIVATE_KEY }}
ARGS: "-avzr"
SOURCE: "nym-wallet/target/release/bundle/msi/nym-wallet_1.*.msi"
REMOTE_HOST: ${{ secrets.CI_WWW_REMOTE_HOST }}
REMOTE_USER: ${{ secrets.CI_WWW_REMOTE_USER }}
TARGET: ${{ secrets.CI_WWW_REMOTE_TARGET }}/builds/${{ github.ref_name }}/nym-wallet
EXCLUDE: "/dist/, /node_modules/"
push-release-data:
if: ${{ (startsWith(github.ref, 'refs/tags/nym-wallet-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }}
uses: ./.github/workflows/release-calculate-hash.yml
+24
View File
@@ -4,6 +4,30 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
## [Unreleased]
## [2024.4-nutella] (2024-05-08)
- [fix] apply disable_poisson_rate from internal NR/IPR cfgs ([#4579])
- updating sign commands to include nym-node ([#4578])
- changed nym-node redirects from 308 'Permanent Redirect' to 303: 'See Other' ([#4572])
[#4579]: https://github.com/nymtech/nym/pull/4579
[#4578]: https://github.com/nymtech/nym/pull/4578
[#4572]: https://github.com/nymtech/nym/pull/4572
## [2024.3-eclipse] (2024-04-22)
- Initial release of the first iteration of the Nym Node
- Improvements to gateway functionality
- IPR development
- Removal of allow list in favour of implementing an exit policy
- Explorer delegation: enables direct delegation to nodes via the Nym Explorer
## [2024.2-fast-and-furious] (2024-03-25)
- Internal testing pre-release
## [2024.1-marabou] (2024-02-15)
**New Features:**
Generated
+1507 -3090
View File
File diff suppressed because it is too large Load Diff
+13 -6
View File
@@ -24,6 +24,7 @@ members = [
"common/bandwidth-controller",
"common/bin-common",
"common/client-core",
"common/client-core/config-types",
"common/client-core/surb-storage",
"common/client-core/gateways-storage",
"common/client-libs/gateway-client",
@@ -41,6 +42,7 @@ members = [
"common/cosmwasm-smart-contracts/name-service",
"common/cosmwasm-smart-contracts/service-provider-directory",
"common/cosmwasm-smart-contracts/vesting-contract",
"common/country-group",
"common/credential-storage",
"common/credentials",
"common/credential-utils",
@@ -50,6 +52,7 @@ members = [
"common/execute",
"common/exit-policy",
"common/http-api-client",
"common/http-api-common",
"common/inclusion-probability",
"common/ip-packet-requests",
"common/ledger",
@@ -104,6 +107,7 @@ members = [
"nym-browser-extension/storage",
"nym-api/nym-api-requests",
"nym-node",
"nym-node/nym-node-http-api",
"nym-node/nym-node-requests",
"nym-outfox",
"nym-validator-rewarder",
@@ -118,7 +122,6 @@ members = [
# "wasm/full-nym-wasm",
"wasm/mix-fetch",
"wasm/node-tester",
"common/nym-metrics",
]
default-members = [
@@ -132,6 +135,7 @@ default-members = [
"tools/nymvisor",
"explorer-api",
"nym-validator-rewarder",
"nym-node"
]
exclude = [
@@ -156,7 +160,8 @@ license = "Apache-2.0"
[workspace.dependencies]
anyhow = "1.0.71"
async-trait = "0.1.68"
axum = "0.6.20"
axum = "0.7.5"
axum-extra = "0.9.3"
base64 = "0.21.4"
bs58 = "0.5.0"
bip39 = { version = "2.0.0", features = ["zeroize"] }
@@ -167,14 +172,16 @@ dotenvy = "0.15.6"
futures = "0.3.28"
generic-array = "0.14.7"
getrandom = "0.2.10"
hyper = "0.14.27"
headers = "0.4.0"
humantime-serde = "1.1.1"
hyper = "1.3.1"
k256 = "0.13"
lazy_static = "1.4.0"
log = "0.4"
once_cell = "1.7.2"
parking_lot = "0.12.1"
rand = "0.8.5"
reqwest = { version = "0.11.22", default-features = false }
reqwest = { version = "0.12.4", default-features = false }
schemars = "0.8.1"
serde = "1.0.152"
serde_json = "1.0.91"
@@ -188,8 +195,8 @@ tokio-tungstenite = { version = "0.20.1" }
tracing = "0.1.37"
tungstenite = { version = "0.20.1", default-features = false }
ts-rs = "7.0.0"
utoipa = "3.5.0"
utoipa-swagger-ui = "3.1.5"
utoipa = "4.2.0"
utoipa-swagger-ui = "6.0.0"
url = "2.4"
zeroize = "1.6.0"
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "nym-client"
version = "1.1.33"
version = "1.1.34"
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jędrzej Stuczyński <andrew@nymtech.net>"]
description = "Implementation of the Nym Client"
edition = "2021"
+291 -91
View File
@@ -674,13 +674,13 @@
}
},
"node_modules/body-parser": {
"version": "1.20.1",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz",
"integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==",
"version": "1.20.2",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz",
"integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==",
"dev": true,
"dependencies": {
"bytes": "3.1.2",
"content-type": "~1.0.4",
"content-type": "~1.0.5",
"debug": "2.6.9",
"depd": "2.0.0",
"destroy": "1.2.0",
@@ -688,7 +688,7 @@
"iconv-lite": "0.4.24",
"on-finished": "2.4.1",
"qs": "6.11.0",
"raw-body": "2.5.1",
"raw-body": "2.5.2",
"type-is": "~1.6.18",
"unpipe": "1.0.0"
},
@@ -793,13 +793,19 @@
}
},
"node_modules/call-bind": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
"integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz",
"integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==",
"dev": true,
"dependencies": {
"function-bind": "^1.1.1",
"get-intrinsic": "^1.0.2"
"es-define-property": "^1.0.0",
"es-errors": "^1.3.0",
"function-bind": "^1.1.2",
"get-intrinsic": "^1.2.4",
"set-function-length": "^1.2.1"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
@@ -1030,18 +1036,18 @@
}
},
"node_modules/content-type": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
"integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==",
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
"integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
"dev": true,
"engines": {
"node": ">= 0.6"
}
},
"node_modules/cookie": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz",
"integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==",
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz",
"integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==",
"dev": true,
"engines": {
"node": ">= 0.6"
@@ -1137,6 +1143,23 @@
"node": ">= 10"
}
},
"node_modules/define-data-property": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
"integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
"dev": true,
"dependencies": {
"es-define-property": "^1.0.0",
"es-errors": "^1.3.0",
"gopd": "^1.0.1"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/define-lazy-prop": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz",
@@ -1358,6 +1381,27 @@
"node": ">=4"
}
},
"node_modules/es-define-property": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz",
"integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==",
"dev": true,
"dependencies": {
"get-intrinsic": "^1.2.4"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/es-errors": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
"dev": true,
"engines": {
"node": ">= 0.4"
}
},
"node_modules/es-module-lexer": {
"version": "0.9.3",
"resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz",
@@ -1463,17 +1507,17 @@
}
},
"node_modules/express": {
"version": "4.18.2",
"resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz",
"integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==",
"version": "4.19.2",
"resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz",
"integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==",
"dev": true,
"dependencies": {
"accepts": "~1.3.8",
"array-flatten": "1.1.1",
"body-parser": "1.20.1",
"body-parser": "1.20.2",
"content-disposition": "0.5.4",
"content-type": "~1.0.4",
"cookie": "0.5.0",
"cookie": "0.6.0",
"cookie-signature": "1.0.6",
"debug": "2.6.9",
"depd": "2.0.0",
@@ -1731,20 +1775,28 @@
}
},
"node_modules/function-bind": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
"dev": true
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
"dev": true,
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/get-intrinsic": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz",
"integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==",
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz",
"integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==",
"dev": true,
"dependencies": {
"function-bind": "^1.1.1",
"has": "^1.0.3",
"has-symbols": "^1.0.1"
"es-errors": "^1.3.0",
"function-bind": "^1.1.2",
"has-proto": "^1.0.1",
"has-symbols": "^1.0.3",
"hasown": "^2.0.0"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
@@ -1824,6 +1876,18 @@
"node": ">=0.10.0"
}
},
"node_modules/gopd": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
"integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
"dev": true,
"dependencies": {
"get-intrinsic": "^1.1.3"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/graceful-fs": {
"version": "4.2.9",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
@@ -1855,10 +1919,22 @@
"node": ">=8"
}
},
"node_modules/has-symbols": {
"node_modules/has-property-descriptors": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz",
"integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==",
"resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
"integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
"dev": true,
"dependencies": {
"es-define-property": "^1.0.0"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/has-proto": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz",
"integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==",
"dev": true,
"engines": {
"node": ">= 0.4"
@@ -1867,6 +1943,30 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/has-symbols": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
"integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
"dev": true,
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/hasown": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
"dev": true,
"dependencies": {
"function-bind": "^1.1.2"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/he": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
@@ -2650,9 +2750,9 @@
}
},
"node_modules/object-inspect": {
"version": "1.12.2",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz",
"integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==",
"version": "1.13.1",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz",
"integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==",
"dev": true,
"funding": {
"url": "https://github.com/sponsors/ljharb"
@@ -3038,9 +3138,9 @@
}
},
"node_modules/raw-body": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz",
"integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==",
"version": "2.5.2",
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz",
"integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==",
"dev": true,
"dependencies": {
"bytes": "3.1.2",
@@ -3413,6 +3513,23 @@
"node": ">= 0.8.0"
}
},
"node_modules/set-function-length": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
"integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
"dev": true,
"dependencies": {
"define-data-property": "^1.1.4",
"es-errors": "^1.3.0",
"function-bind": "^1.1.2",
"get-intrinsic": "^1.2.4",
"gopd": "^1.0.1",
"has-property-descriptors": "^1.0.2"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/setprototypeof": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
@@ -3453,14 +3570,18 @@
}
},
"node_modules/side-channel": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
"integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz",
"integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==",
"dev": true,
"dependencies": {
"call-bind": "^1.0.0",
"get-intrinsic": "^1.0.2",
"object-inspect": "^1.9.0"
"call-bind": "^1.0.7",
"es-errors": "^1.3.0",
"get-intrinsic": "^1.2.4",
"object-inspect": "^1.13.1"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
@@ -5030,13 +5151,13 @@
"dev": true
},
"body-parser": {
"version": "1.20.1",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz",
"integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==",
"version": "1.20.2",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz",
"integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==",
"dev": true,
"requires": {
"bytes": "3.1.2",
"content-type": "~1.0.4",
"content-type": "~1.0.5",
"debug": "2.6.9",
"depd": "2.0.0",
"destroy": "1.2.0",
@@ -5044,7 +5165,7 @@
"iconv-lite": "0.4.24",
"on-finished": "2.4.1",
"qs": "6.11.0",
"raw-body": "2.5.1",
"raw-body": "2.5.2",
"type-is": "~1.6.18",
"unpipe": "1.0.0"
},
@@ -5122,13 +5243,16 @@
"dev": true
},
"call-bind": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
"integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz",
"integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==",
"dev": true,
"requires": {
"function-bind": "^1.1.1",
"get-intrinsic": "^1.0.2"
"es-define-property": "^1.0.0",
"es-errors": "^1.3.0",
"function-bind": "^1.1.2",
"get-intrinsic": "^1.2.4",
"set-function-length": "^1.2.1"
}
},
"camel-case": {
@@ -5294,15 +5418,15 @@
}
},
"content-type": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
"integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==",
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
"integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
"dev": true
},
"cookie": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz",
"integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==",
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz",
"integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==",
"dev": true
},
"cookie-signature": {
@@ -5377,6 +5501,17 @@
"execa": "^5.0.0"
}
},
"define-data-property": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
"integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
"dev": true,
"requires": {
"es-define-property": "^1.0.0",
"es-errors": "^1.3.0",
"gopd": "^1.0.1"
}
},
"define-lazy-prop": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz",
@@ -5546,6 +5681,21 @@
"integrity": "sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw==",
"dev": true
},
"es-define-property": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz",
"integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==",
"dev": true,
"requires": {
"get-intrinsic": "^1.2.4"
}
},
"es-errors": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
"dev": true
},
"es-module-lexer": {
"version": "0.9.3",
"resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz",
@@ -5626,17 +5776,17 @@
}
},
"express": {
"version": "4.18.2",
"resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz",
"integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==",
"version": "4.19.2",
"resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz",
"integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==",
"dev": true,
"requires": {
"accepts": "~1.3.8",
"array-flatten": "1.1.1",
"body-parser": "1.20.1",
"body-parser": "1.20.2",
"content-disposition": "0.5.4",
"content-type": "~1.0.4",
"cookie": "0.5.0",
"cookie": "0.6.0",
"cookie-signature": "1.0.6",
"debug": "2.6.9",
"depd": "2.0.0",
@@ -5837,20 +5987,22 @@
"optional": true
},
"function-bind": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
"dev": true
},
"get-intrinsic": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz",
"integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==",
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz",
"integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==",
"dev": true,
"requires": {
"function-bind": "^1.1.1",
"has": "^1.0.3",
"has-symbols": "^1.0.1"
"es-errors": "^1.3.0",
"function-bind": "^1.1.2",
"has-proto": "^1.0.1",
"has-symbols": "^1.0.3",
"hasown": "^2.0.0"
}
},
"get-stream": {
@@ -5908,6 +6060,15 @@
}
}
},
"gopd": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
"integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
"dev": true,
"requires": {
"get-intrinsic": "^1.1.3"
}
},
"graceful-fs": {
"version": "4.2.9",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
@@ -5933,12 +6094,36 @@
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="
},
"has-symbols": {
"has-property-descriptors": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz",
"integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==",
"resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
"integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
"dev": true,
"requires": {
"es-define-property": "^1.0.0"
}
},
"has-proto": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz",
"integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==",
"dev": true
},
"has-symbols": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
"integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
"dev": true
},
"hasown": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
"dev": true,
"requires": {
"function-bind": "^1.1.2"
}
},
"he": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
@@ -6515,9 +6700,9 @@
"dev": true
},
"object-inspect": {
"version": "1.12.2",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz",
"integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==",
"version": "1.13.1",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz",
"integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==",
"dev": true
},
"object-is": {
@@ -6803,9 +6988,9 @@
"dev": true
},
"raw-body": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz",
"integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==",
"version": "2.5.2",
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz",
"integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==",
"dev": true,
"requires": {
"bytes": "3.1.2",
@@ -7090,6 +7275,20 @@
"send": "0.18.0"
}
},
"set-function-length": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
"integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
"dev": true,
"requires": {
"define-data-property": "^1.1.4",
"es-errors": "^1.3.0",
"function-bind": "^1.1.2",
"get-intrinsic": "^1.2.4",
"gopd": "^1.0.1",
"has-property-descriptors": "^1.0.2"
}
},
"setprototypeof": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
@@ -7121,14 +7320,15 @@
"dev": true
},
"side-channel": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
"integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz",
"integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==",
"dev": true,
"requires": {
"call-bind": "^1.0.0",
"get-intrinsic": "^1.0.2",
"object-inspect": "^1.9.0"
"call-bind": "^1.0.7",
"es-errors": "^1.3.0",
"get-intrinsic": "^1.2.4",
"object-inspect": "^1.13.1"
}
},
"signal-exit": {
@@ -8,5 +8,7 @@ use nym_client_core::cli_helpers::client_import_credential::{
};
pub(crate) async fn execute(args: CommonClientImportCredentialArgs) -> Result<(), ClientError> {
import_credential::<CliNativeClient, _>(args).await
import_credential::<CliNativeClient, _>(args).await?;
println!("successfully imported credential!");
Ok(())
}
+3
View File
@@ -23,6 +23,9 @@ pub enum ClientError {
#[error("Attempted to start the client in invalid socket mode")]
InvalidSocketMode,
#[error(transparent)]
ConfigUpgradeFailure(#[from] nym_client_core::config::ConfigUpgradeFailure),
#[error(transparent)]
NymIdError(#[from] NymIdError),
}
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "nym-socks5-client"
version = "1.1.33"
version = "1.1.34"
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"
@@ -10,5 +10,7 @@ use nym_client_core::cli_helpers::client_import_credential::{
pub(crate) async fn execute(
args: CommonClientImportCredentialArgs,
) -> Result<(), Socks5ClientError> {
import_credential::<CliSocks5Client, _>(args).await
import_credential::<CliSocks5Client, _>(args).await?;
println!("successfully imported credential!");
Ok(())
}
+3
View File
@@ -23,6 +23,9 @@ pub enum Socks5ClientError {
#[error(transparent)]
ClientCoreError(#[from] ClientCoreError),
#[error(transparent)]
ConfigUpgradeFailure(#[from] nym_client_core::config::ConfigUpgradeFailure),
#[error(transparent)]
NymIdError(#[from] NymIdError),
}
+1
View File
@@ -18,6 +18,7 @@ pub mod acquire;
pub mod error;
mod utils;
#[derive(Debug)]
pub struct BandwidthController<C, St> {
storage: St,
client: C,
-1
View File
@@ -8,7 +8,6 @@ license = { workspace = true }
repository = { workspace = true }
[dependencies]
atty = "0.2"
const-str = "0.5.6"
clap = { workspace = true, features = ["derive"] }
clap_complete = "4.0"
+3 -2
View File
@@ -2,6 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
use serde::{Deserialize, Serialize};
use std::io::IsTerminal;
#[cfg(feature = "tracing")]
pub use opentelemetry;
@@ -14,7 +15,7 @@ pub use tracing_subscriber;
#[cfg(feature = "tracing")]
pub use tracing_tree;
#[derive(Debug, Default, Clone, Deserialize, PartialEq, Eq, Serialize)]
#[derive(Debug, Default, Copy, Clone, Deserialize, PartialEq, Eq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct LoggingSettings {
// well, we need to implement something here at some point...
@@ -120,7 +121,7 @@ pub fn banner(crate_name: &str, crate_version: &str) -> String {
}
pub fn maybe_print_banner(crate_name: &str, crate_version: &str) {
if atty::is(atty::Stream::Stdout) {
if std::io::stdout().is_terminal() {
println!("{}", banner(crate_name, crate_version))
}
}
+15 -5
View File
@@ -3,7 +3,7 @@ name = "nym-client-core"
version = "1.1.15"
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"]
edition = "2021"
rust-version = "1.66"
rust-version = "1.70"
license.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@@ -15,7 +15,7 @@ bs58 = { workspace = true }
cfg-if = "1.0.0"
clap = { workspace = true, optional = true }
futures = { workspace = true }
humantime-serde = "1.0"
humantime-serde = { workspace = true }
log = { workspace = true }
rand = { version = "0.7.3", features = ["wasm-bindgen"] }
serde = { workspace = true, features = ["derive"] }
@@ -25,7 +25,6 @@ si-scale = "0.2.2"
tap = "1.0.1"
thiserror = { workspace = true }
url = { workspace = true, features = ["serde"] }
tungstenite = { workspace = true, default-features = false }
tokio = { workspace = true, features = ["macros"] }
time = { workspace = true }
zeroize = { workspace = true }
@@ -34,6 +33,7 @@ zeroize = { workspace = true }
nym-id = { path = "../nym-id" }
nym-bandwidth-controller = { path = "../bandwidth-controller" }
nym-config = { path = "../config" }
nym-country-group = { path = "../country-group" }
nym-crypto = { path = "../crypto" }
nym-explorer-client = { path = "../../explorer-api/explorer-client" }
nym-gateway-client = { path = "../client-libs/gateway-client" }
@@ -47,6 +47,7 @@ nym-validator-client = { path = "../client-libs/validator-client", default-featu
nym-task = { path = "../task" }
nym-credential-storage = { path = "../credential-storage" }
nym-network-defaults = { path = "../network-defaults" }
nym-client-core-config-types = { path = "./config-types", features = ["disk-persistence"] }
nym-client-core-surb-storage = { path = "./surb-storage" }
nym-client-core-gateways-storage = { path = "./gateways-storage" }
@@ -72,8 +73,17 @@ workspace = true
features = ["time"]
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.tokio-tungstenite]
version = "0.20.1"
features = ["rustls-tls-native-roots"]
workspace = true
features = ["rustls-tls-webpki-roots"]
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.tungstenite]
workspace = true
default-features = true
features = ["rustls-tls-webpki-roots"]
[target."cfg(target_arch = \"wasm32\")".dependencies.tungstenite]
workspace = true
default-features = false
[target."cfg(target_arch = \"wasm32\")".dependencies.wasm-bindgen-futures]
workspace = true
@@ -0,0 +1,26 @@
[package]
name = "nym-client-core-config-types"
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]
humantime-serde = { workspace = true }
serde = { workspace = true, features = ["derive"] }
thiserror.workspace = true
url = { workspace = true, features = ["serde"] }
nym-config = { path = "../../config" }
nym-country-group = { path = "../../country-group" }
nym-pemstore = { path = "../../pemstore", optional = true }
# those are pulling so many deps T.T
nym-sphinx-params = { path = "../../nymsphinx/params" }
nym-sphinx-addressing = { path = "../../nymsphinx/addressing" }
[features]
disk-persistence = ["nym-pemstore"]
@@ -1,15 +1,53 @@
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use serde::{Deserialize, Serialize};
use std::path::{Path, PathBuf};
pub mod old;
// preserve old structure for easier migration
pub use old::{old_v1_1_20_2, old_v1_1_33};
pub const DEFAULT_REPLY_SURB_DB_FILENAME: &str = "persistent_reply_store.sqlite";
pub const DEFAULT_CREDENTIALS_DB_FILENAME: &str = "credentials_database.db";
pub const DEFAULT_GATEWAYS_DETAILS_DB_FILENAME: &str = "gateways_registrations.sqlite";
pub const DEFAULT_PRIVATE_IDENTITY_KEY_FILENAME: &str = "private_identity.pem";
pub const DEFAULT_PUBLIC_IDENTITY_KEY_FILENAME: &str = "public_identity.pem";
pub const DEFAULT_PRIVATE_ENCRYPTION_KEY_FILENAME: &str = "private_encryption.pem";
pub const DEFAULT_PUBLIC_ENCRYPTION_KEY_FILENAME: &str = "public_encryption.pem";
pub const DEFAULT_ACK_KEY_FILENAME: &str = "ack_key.pem";
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct CommonClientPaths {
pub keys: ClientKeysPaths,
/// Path to the file containing information about gateways used by this client,
/// i.e. details such as their public keys, owner addresses or the network information.
pub gateway_registrations: PathBuf,
/// Path to the database containing bandwidth credentials of this client.
pub credentials_database: PathBuf,
/// Path to the persistent store for received reply surbs, unused encryption keys and used sender tags.
pub reply_surb_database: PathBuf,
}
impl CommonClientPaths {
pub fn new_base<P: AsRef<Path>>(base_data_directory: P) -> Self {
let base_dir = base_data_directory.as_ref();
CommonClientPaths {
credentials_database: base_dir.join(DEFAULT_CREDENTIALS_DB_FILENAME),
reply_surb_database: base_dir.join(DEFAULT_REPLY_SURB_DB_FILENAME),
gateway_registrations: base_dir.join(DEFAULT_GATEWAYS_DETAILS_DB_FILENAME),
keys: ClientKeysPaths::new_base(base_data_directory),
}
}
}
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
pub struct ClientKeysPaths {
/// Path to file containing private identity key.
@@ -0,0 +1,9 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
pub mod v1;
pub mod v2;
// aliases for backwards compatibility
pub use v1 as old_v1_1_20_2;
pub use v2 as old_v1_1_33;
@@ -0,0 +1,37 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::disk_persistence::old::v2::{
ClientKeysPathsV2, CommonClientPathsV2, DEFAULT_GATEWAY_DETAILS_FILENAME,
};
use crate::error::ConfigUpgradeFailure;
use serde::{Deserialize, Serialize};
use std::path::PathBuf;
// aliases for backwards compatibility
pub type CommonClientPathsV1_1_20_2 = CommonClientPathsV1;
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct CommonClientPathsV1 {
pub keys: ClientKeysPathsV2,
pub credentials_database: PathBuf,
pub reply_surb_database: PathBuf,
}
impl CommonClientPathsV1 {
pub fn upgrade_default(self) -> Result<CommonClientPathsV2, ConfigUpgradeFailure> {
let data_dir = self
.reply_surb_database
.parent()
.ok_or_else(|| ConfigUpgradeFailure {
current_version: "1.1.20-2".to_string(),
})?;
Ok(CommonClientPathsV2 {
keys: self.keys,
gateway_details: data_dir.join(DEFAULT_GATEWAY_DETAILS_FILENAME),
credentials_database: self.credentials_database,
reply_surb_database: self.reply_surb_database,
})
}
}
@@ -1,16 +1,20 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::config::disk_persistence::keys_paths::ClientKeysPaths;
use crate::config::disk_persistence::{CommonClientPaths, DEFAULT_GATEWAYS_DETAILS_DB_FILENAME};
use crate::error::ClientCoreError;
use crate::disk_persistence::ClientKeysPaths;
use crate::disk_persistence::{CommonClientPaths, DEFAULT_GATEWAYS_DETAILS_DB_FILENAME};
use crate::error::ConfigUpgradeFailure;
use serde::{Deserialize, Serialize};
use std::path::PathBuf;
pub const DEFAULT_GATEWAY_DETAILS_FILENAME: &str = "gateway_details.json";
// aliases for backwards compatibility
pub type CommonClientPathsV1_1_33 = CommonClientPathsV2;
pub type ClientKeysPathsV1_1_33 = ClientKeysPathsV2;
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
pub struct ClientKeysPathsV1_1_33 {
pub struct ClientKeysPathsV2 {
/// Path to file containing private identity key.
pub private_identity_key_file: PathBuf,
@@ -32,7 +36,7 @@ pub struct ClientKeysPathsV1_1_33 {
pub ack_key_file: PathBuf,
}
impl ClientKeysPathsV1_1_33 {
impl ClientKeysPathsV2 {
pub fn upgrade(self) -> ClientKeysPaths {
ClientKeysPaths {
private_identity_key_file: self.private_identity_key_file,
@@ -46,8 +50,8 @@ impl ClientKeysPathsV1_1_33 {
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct CommonClientPathsV1_1_33 {
pub keys: ClientKeysPathsV1_1_33,
pub struct CommonClientPathsV2 {
pub keys: ClientKeysPathsV2,
/// Path to the file containing information about gateway used by this client,
/// i.e. details such as its public key, owner address or the network information.
@@ -60,15 +64,16 @@ pub struct CommonClientPathsV1_1_33 {
pub reply_surb_database: PathBuf,
}
impl CommonClientPathsV1_1_33 {
impl CommonClientPathsV2 {
// note that during the upgrade process, the caller will need to extract the key and gateway details
// manually and resave them in the new database
pub fn upgrade_default(self) -> Result<CommonClientPaths, ClientCoreError> {
let data_dir = self.gateway_details.parent().ok_or_else(|| {
ClientCoreError::ConfigFileUpgradeFailure {
pub fn upgrade_default(self) -> Result<CommonClientPaths, ConfigUpgradeFailure> {
let data_dir = self
.gateway_details
.parent()
.ok_or_else(|| ConfigUpgradeFailure {
current_version: "1.1.33".to_string(),
}
})?;
})?;
Ok(CommonClientPaths {
keys: self.keys.upgrade(),
@@ -0,0 +1,19 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use thiserror::Error;
#[derive(Debug, Error)]
#[error("unable to upgrade config file from `{current_version}`")]
pub struct ConfigUpgradeFailure {
pub current_version: String,
}
#[derive(Error, Debug)]
pub enum InvalidTrafficModeFailure {
#[error("attempted to set medium toggle traffic mode with fast mode flag")]
MediumToggleWithFastMode,
#[error("attempted to set medium toggle traffic mode with no cover flag")]
MediumToggleWithNoCover,
}
+662
View File
@@ -0,0 +1,662 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use nym_config::defaults::NymNetworkDetails;
use nym_sphinx_addressing::Recipient;
use nym_sphinx_params::{PacketSize, PacketType};
use serde::{Deserialize, Serialize};
use std::time::Duration;
use url::Url;
#[cfg(feature = "disk-persistence")]
pub mod disk_persistence;
pub mod error;
pub mod old;
pub use error::ConfigUpgradeFailure;
// 'DEBUG'
const DEFAULT_ACK_WAIT_MULTIPLIER: f64 = 1.5;
const DEFAULT_ACK_WAIT_ADDITION: Duration = Duration::from_millis(1_500);
const DEFAULT_LOOP_COVER_STREAM_AVERAGE_DELAY: Duration = Duration::from_millis(200);
const DEFAULT_MESSAGE_STREAM_AVERAGE_DELAY: Duration = Duration::from_millis(20);
const DEFAULT_AVERAGE_PACKET_DELAY: Duration = Duration::from_millis(50);
const DEFAULT_TOPOLOGY_REFRESH_RATE: Duration = Duration::from_secs(5 * 60); // every 5min
const DEFAULT_TOPOLOGY_RESOLUTION_TIMEOUT: Duration = Duration::from_millis(5_000);
const DEFAULT_MAX_STARTUP_GATEWAY_WAITING_PERIOD: Duration = Duration::from_secs(70 * 60); // 70min -> full epoch (1h) + a bit of overhead
// Set this to a high value for now, so that we don't risk sporadic timeouts that might cause
// bought bandwidth tokens to not have time to be spent; Once we remove the gateway from the
// bandwidth bridging protocol, we can come back to a smaller timeout value
const DEFAULT_GATEWAY_RESPONSE_TIMEOUT: Duration = Duration::from_secs(5 * 60);
const DEFAULT_COVER_TRAFFIC_PRIMARY_SIZE_RATIO: f64 = 0.70;
// reply-surbs related:
// define when to request
// clients/client-core/src/client/replies/reply_storage/surb_storage.rs
const DEFAULT_MINIMUM_REPLY_SURB_STORAGE_THRESHOLD: usize = 10;
const DEFAULT_MAXIMUM_REPLY_SURB_STORAGE_THRESHOLD: usize = 200;
// define how much to request at once
// clients/client-core/src/client/replies/reply_controller.rs
const DEFAULT_MINIMUM_REPLY_SURB_REQUEST_SIZE: u32 = 10;
const DEFAULT_MAXIMUM_REPLY_SURB_REQUEST_SIZE: u32 = 100;
const DEFAULT_MAXIMUM_ALLOWED_SURB_REQUEST_SIZE: u32 = 500;
const DEFAULT_MAXIMUM_REPLY_SURB_REREQUEST_WAITING_PERIOD: Duration = Duration::from_secs(10);
const DEFAULT_MAXIMUM_REPLY_SURB_DROP_WAITING_PERIOD: Duration = Duration::from_secs(5 * 60);
// 12 hours
const DEFAULT_MAXIMUM_REPLY_SURB_AGE: Duration = Duration::from_secs(12 * 60 * 60);
// 24 hours
const DEFAULT_MAXIMUM_REPLY_KEY_AGE: Duration = Duration::from_secs(24 * 60 * 60);
use crate::error::InvalidTrafficModeFailure;
pub use nym_country_group::CountryGroup;
#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct Config {
pub client: Client,
#[serde(default)]
pub debug: DebugConfig,
}
impl Config {
pub fn new<S1, S2>(id: S1, version: S2) -> Self
where
S1: Into<String>,
S2: Into<String>,
{
Config {
client: Client::new_default(id, version),
debug: Default::default(),
}
}
pub fn from_client_config(client: Client, debug: DebugConfig) -> Self {
Config { client, debug }
}
pub fn validate(&self) -> bool {
self.debug.validate()
}
pub fn with_debug_config(mut self, debug: DebugConfig) -> Self {
self.debug = debug;
self
}
pub fn with_disabled_credentials(mut self, disabled_credentials_mode: bool) -> Self {
self.client.disabled_credentials_mode = disabled_credentials_mode;
self
}
pub fn with_custom_nyxd(mut self, urls: Vec<Url>) -> Self {
self.client.nyxd_urls = urls;
self
}
pub fn set_custom_nyxd(&mut self, nyxd_urls: Vec<Url>) {
self.client.nyxd_urls = nyxd_urls;
}
pub fn with_custom_nym_apis(mut self, nym_api_urls: Vec<Url>) -> Self {
self.client.nym_api_urls = nym_api_urls;
self
}
pub fn set_custom_nym_apis(&mut self, nym_api_urls: Vec<Url>) {
self.client.nym_api_urls = nym_api_urls;
}
pub fn with_high_default_traffic_volume(mut self, enabled: bool) -> Self {
if enabled {
self.set_high_default_traffic_volume();
}
self
}
pub fn with_packet_type(mut self, packet_type: PacketType) -> Self {
self.debug.traffic.packet_type = packet_type;
self
}
// TODO: this should be refactored properly
// as of 12.09.23 the below is true (not sure how this comment will rot in the future)
// medium_toggle:
// - sets secondary packet size to 16kb
// - disables poisson distribution of the main traffic stream
// - sets the cover traffic stream to 1 packet / 5s (on average)
// - disables per hop delay
//
// fastmode (to be renamed to `fast-poisson`):
// - sets average per hop delay to 10ms
// - sets the cover traffic stream to 1 packet / 2000s (on average); for all intents and purposes it disables the stream
// - sets the poisson distribution of the main traffic stream to 4ms, i.e. 250 packets / s on average
//
// no_cover:
// - disables poisson distribution of the main traffic stream
// - disables the secondary cover traffic stream
#[doc(hidden)]
pub fn try_apply_traffic_modes(
&mut self,
disable_poisson_process: bool,
medium_toggle: bool,
fast_mode: bool,
no_cover: bool,
) -> Result<(), InvalidTrafficModeFailure> {
if disable_poisson_process {
self.set_no_poisson_process()
}
if medium_toggle {
if fast_mode {
return Err(InvalidTrafficModeFailure::MediumToggleWithFastMode);
}
if no_cover {
return Err(InvalidTrafficModeFailure::MediumToggleWithNoCover);
}
self.set_experimental_medium_toggle();
}
if fast_mode {
self.set_high_default_traffic_volume()
}
if no_cover {
self.set_no_cover_traffic();
}
Ok(())
}
pub fn set_high_default_traffic_volume(&mut self) {
self.debug.traffic.average_packet_delay = Duration::from_millis(10);
// basically don't really send cover messages
self.debug.cover_traffic.loop_cover_traffic_average_delay =
Duration::from_millis(2_000_000);
// 250 "real" messages / s
self.debug.traffic.message_sending_average_delay = Duration::from_millis(4);
}
/// Enable medium mixnet traffic, for experiments only.
/// This includes things like disabling cover traffic, no per hop delays, etc.
#[doc(hidden)]
pub fn set_experimental_medium_toggle(&mut self) {
self.set_no_cover_traffic_with_keepalive();
self.set_no_per_hop_delays();
self.debug.traffic.secondary_packet_size = Some(PacketSize::ExtendedPacket16);
}
pub fn with_disabled_poisson_process(mut self, disabled: bool) -> Self {
if disabled {
self.set_no_poisson_process()
}
self
}
pub fn set_no_poisson_process(&mut self) {
self.debug.traffic.disable_main_poisson_packet_distribution = true;
}
pub fn with_disabled_cover_traffic(mut self, disabled: bool) -> Self {
if disabled {
self.set_no_cover_traffic()
}
self
}
pub fn set_no_cover_traffic(&mut self) {
self.debug.cover_traffic.disable_loop_cover_traffic_stream = true;
self.debug.traffic.disable_main_poisson_packet_distribution = true;
}
pub fn with_disabled_cover_traffic_with_keepalive(mut self, disabled: bool) -> Self {
if disabled {
self.set_no_cover_traffic_with_keepalive()
}
self
}
pub fn set_no_cover_traffic_with_keepalive(&mut self) {
self.debug.traffic.disable_main_poisson_packet_distribution = true;
self.debug.cover_traffic.loop_cover_traffic_average_delay = Duration::from_secs(5);
}
pub fn with_disabled_topology_refresh(mut self, disable_topology_refresh: bool) -> Self {
self.debug.topology.disable_refreshing = disable_topology_refresh;
self
}
pub fn with_topology_structure(mut self, topology_structure: TopologyStructure) -> Self {
self.set_topology_structure(topology_structure);
self
}
pub fn set_topology_structure(&mut self, topology_structure: TopologyStructure) {
self.debug.topology.topology_structure = topology_structure;
}
pub fn with_no_per_hop_delays(mut self, no_per_hop_delays: bool) -> Self {
if no_per_hop_delays {
self.set_no_per_hop_delays()
}
self
}
pub fn set_no_per_hop_delays(&mut self) {
self.debug.traffic.average_packet_delay = Duration::ZERO;
self.debug.acknowledgements.average_ack_delay = Duration::ZERO;
}
pub fn with_secondary_packet_size(mut self, secondary_packet_size: Option<PacketSize>) -> Self {
self.set_secondary_packet_size(secondary_packet_size);
self
}
pub fn set_secondary_packet_size(&mut self, secondary_packet_size: Option<PacketSize>) {
self.debug.traffic.secondary_packet_size = secondary_packet_size;
}
pub fn set_custom_version(&mut self, version: &str) {
self.client.version = version.to_string();
}
pub fn get_id(&self) -> String {
self.client.id.clone()
}
pub fn get_disabled_credentials_mode(&self) -> bool {
self.client.disabled_credentials_mode
}
pub fn get_validator_endpoints(&self) -> Vec<Url> {
self.client.nyxd_urls.clone()
}
pub fn get_nym_api_endpoints(&self) -> Vec<Url> {
self.client.nym_api_urls.clone()
}
}
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
// note: the deny_unknown_fields is VITAL here to allow upgrades from v1.1.20_2
#[serde(deny_unknown_fields)]
pub struct Client {
/// Version of the client for which this configuration was created.
pub version: String,
/// ID specifies the human readable ID of this particular client.
pub id: String,
/// Indicates whether this client is running in a disabled credentials mode, thus attempting
/// to claim bandwidth without presenting bandwidth credentials.
// TODO: this should be moved to `debug.gateway_connection`
#[serde(default)]
pub disabled_credentials_mode: bool,
/// Addresses to nyxd validators via which the client can communicate with the chain.
#[serde(alias = "validator_urls")]
pub nyxd_urls: Vec<Url>,
/// Addresses to APIs running on validator from which the client gets the view of the network.
#[serde(alias = "validator_api_urls")]
pub nym_api_urls: Vec<Url>,
}
impl Client {
pub fn new_default<S1, S2>(id: S1, version: S2) -> Self
where
S1: Into<String>,
S2: Into<String>,
{
let network = NymNetworkDetails::new_mainnet();
let nyxd_urls = network
.endpoints
.iter()
.map(|validator| validator.nyxd_url())
.collect();
let nym_api_urls = network
.endpoints
.iter()
.filter_map(|validator| validator.api_url())
.collect::<Vec<_>>();
Client {
version: version.into(),
id: id.into(),
disabled_credentials_mode: true,
nyxd_urls,
nym_api_urls,
}
}
pub fn new<S: Into<String>>(
id: S,
version: S,
disabled_credentials_mode: bool,
nyxd_urls: Vec<Url>,
nym_api_urls: Vec<Url>,
) -> Self {
Client {
version: version.into(),
id: id.into(),
disabled_credentials_mode,
nyxd_urls,
nym_api_urls,
}
}
}
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct Traffic {
/// The parameter of Poisson distribution determining how long, on average,
/// sent packet is going to be delayed at any given mix node.
/// So for a packet going through three mix nodes, on average, it will take three times this value
/// until the packet reaches its destination.
#[serde(with = "humantime_serde")]
pub average_packet_delay: Duration,
/// The parameter of Poisson distribution determining how long, on average,
/// it is going to take another 'real traffic stream' message to be sent.
/// If no real packets are available and cover traffic is enabled,
/// a loop cover message is sent instead in order to preserve the rate.
#[serde(with = "humantime_serde")]
pub message_sending_average_delay: Duration,
/// Controls whether the main packet stream constantly produces packets according to the predefined
/// poisson distribution.
pub disable_main_poisson_packet_distribution: bool,
/// Specifies the packet size used for sent messages.
/// Do not override it unless you understand the consequences of that change.
pub primary_packet_size: PacketSize,
/// Specifies the optional auxiliary packet size for optimizing message streams.
/// Note that its use decreases overall anonymity.
/// Do not set it it unless you understand the consequences of that change.
pub secondary_packet_size: Option<PacketSize>,
pub packet_type: PacketType,
}
impl Traffic {
pub fn validate(&self) -> bool {
if let Some(secondary_packet_size) = self.secondary_packet_size {
if secondary_packet_size == PacketSize::AckPacket
|| secondary_packet_size == self.primary_packet_size
{
return false;
}
}
true
}
}
impl Default for Traffic {
fn default() -> Self {
Traffic {
average_packet_delay: DEFAULT_AVERAGE_PACKET_DELAY,
message_sending_average_delay: DEFAULT_MESSAGE_STREAM_AVERAGE_DELAY,
disable_main_poisson_packet_distribution: false,
primary_packet_size: PacketSize::RegularPacket,
secondary_packet_size: None,
packet_type: PacketType::Mix,
}
}
}
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct CoverTraffic {
/// The parameter of Poisson distribution determining how long, on average,
/// it is going to take for another loop cover traffic message to be sent.
#[serde(with = "humantime_serde")]
pub loop_cover_traffic_average_delay: Duration,
/// Specifies the ratio of `primary_packet_size` to `secondary_packet_size` used in cover traffic.
/// Only applicable if `secondary_packet_size` is enabled.
pub cover_traffic_primary_size_ratio: f64,
/// Controls whether the dedicated loop cover traffic stream should be enabled.
/// (and sending packets, on average, every [Self::loop_cover_traffic_average_delay])
pub disable_loop_cover_traffic_stream: bool,
}
impl Default for CoverTraffic {
fn default() -> Self {
CoverTraffic {
loop_cover_traffic_average_delay: DEFAULT_LOOP_COVER_STREAM_AVERAGE_DELAY,
cover_traffic_primary_size_ratio: DEFAULT_COVER_TRAFFIC_PRIMARY_SIZE_RATIO,
disable_loop_cover_traffic_stream: false,
}
}
}
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct GatewayConnection {
/// How long we're willing to wait for a response to a message sent to the gateway,
/// before giving up on it.
#[serde(with = "humantime_serde")]
pub gateway_response_timeout: Duration,
}
impl Default for GatewayConnection {
fn default() -> Self {
GatewayConnection {
gateway_response_timeout: DEFAULT_GATEWAY_RESPONSE_TIMEOUT,
}
}
}
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct Acknowledgements {
/// The parameter of Poisson distribution determining how long, on average,
/// sent acknowledgement is going to be delayed at any given mix node.
/// So for an ack going through three mix nodes, on average, it will take three times this value
/// until the packet reaches its destination.
#[serde(with = "humantime_serde")]
pub average_ack_delay: Duration,
/// Value multiplied with the expected round trip time of an acknowledgement packet before
/// it is assumed it was lost and retransmission of the data packet happens.
/// In an ideal network with 0 latency, this value would have been 1.
pub ack_wait_multiplier: f64,
/// Value added to the expected round trip time of an acknowledgement packet before
/// it is assumed it was lost and retransmission of the data packet happens.
/// In an ideal network with 0 latency, this value would have been 0.
#[serde(with = "humantime_serde")]
pub ack_wait_addition: Duration,
}
impl Default for Acknowledgements {
fn default() -> Self {
Acknowledgements {
average_ack_delay: DEFAULT_AVERAGE_PACKET_DELAY,
ack_wait_multiplier: DEFAULT_ACK_WAIT_MULTIPLIER,
ack_wait_addition: DEFAULT_ACK_WAIT_ADDITION,
}
}
}
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct Topology {
/// The uniform delay every which clients are querying the directory server
/// to try to obtain a compatible network topology to send sphinx packets through.
#[serde(with = "humantime_serde")]
pub topology_refresh_rate: Duration,
/// During topology refresh, test packets are sent through every single possible network
/// path. This timeout determines waiting period until it is decided that the packet
/// did not reach its destination.
#[serde(with = "humantime_serde")]
pub topology_resolution_timeout: Duration,
/// Specifies whether the client should not refresh the network topology after obtaining
/// the first valid instance.
/// Supersedes `topology_refresh_rate_ms`.
pub disable_refreshing: bool,
/// Defines how long the client is going to wait on startup for its gateway to come online,
/// before abandoning the procedure.
#[serde(with = "humantime_serde")]
pub max_startup_gateway_waiting_period: Duration,
/// Specifies the mixnode topology to be used for sending packets.
pub topology_structure: TopologyStructure,
}
#[allow(clippy::large_enum_variant)]
#[derive(Default, Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
pub enum TopologyStructure {
#[default]
NymApi,
GeoAware(GroupBy),
}
#[allow(clippy::large_enum_variant)]
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
pub enum GroupBy {
CountryGroup(CountryGroup),
NymAddress(Recipient),
}
impl std::fmt::Display for GroupBy {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
GroupBy::CountryGroup(group) => write!(f, "group: {group}"),
GroupBy::NymAddress(address) => write!(f, "address: {address}"),
}
}
}
impl Default for Topology {
fn default() -> Self {
Topology {
topology_refresh_rate: DEFAULT_TOPOLOGY_REFRESH_RATE,
topology_resolution_timeout: DEFAULT_TOPOLOGY_RESOLUTION_TIMEOUT,
disable_refreshing: false,
max_startup_gateway_waiting_period: DEFAULT_MAX_STARTUP_GATEWAY_WAITING_PERIOD,
topology_structure: TopologyStructure::default(),
}
}
}
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct ReplySurbs {
/// Defines the minimum number of reply surbs the client wants to keep in its storage at all times.
/// It can only allow to go below that value if its to request additional reply surbs.
pub minimum_reply_surb_storage_threshold: usize,
/// Defines the maximum number of reply surbs the client wants to keep in its storage at any times.
pub maximum_reply_surb_storage_threshold: usize,
/// Defines the minimum number of reply surbs the client would request.
pub minimum_reply_surb_request_size: u32,
/// Defines the maximum number of reply surbs the client would request.
pub maximum_reply_surb_request_size: u32,
/// Defines the maximum number of reply surbs a remote party is allowed to request from this client at once.
pub maximum_allowed_reply_surb_request_size: u32,
/// Defines maximum amount of time the client is going to wait for reply surbs before explicitly asking
/// for more even though in theory they wouldn't need to.
#[serde(with = "humantime_serde")]
pub maximum_reply_surb_rerequest_waiting_period: Duration,
/// Defines maximum amount of time the client is going to wait for reply surbs before
/// deciding it's never going to get them and would drop all pending messages
#[serde(with = "humantime_serde")]
pub maximum_reply_surb_drop_waiting_period: Duration,
/// Defines maximum amount of time given reply surb is going to be valid for.
/// This is going to be superseded by key rotation once implemented.
#[serde(with = "humantime_serde")]
pub maximum_reply_surb_age: Duration,
/// Defines maximum amount of time given reply key is going to be valid for.
/// This is going to be superseded by key rotation once implemented.
#[serde(with = "humantime_serde")]
pub maximum_reply_key_age: Duration,
/// Specifies the number of mixnet hops the packet should go through. If not specified, then
/// the default value is used.
pub surb_mix_hops: Option<u8>,
}
impl Default for ReplySurbs {
fn default() -> Self {
ReplySurbs {
minimum_reply_surb_storage_threshold: DEFAULT_MINIMUM_REPLY_SURB_STORAGE_THRESHOLD,
maximum_reply_surb_storage_threshold: DEFAULT_MAXIMUM_REPLY_SURB_STORAGE_THRESHOLD,
minimum_reply_surb_request_size: DEFAULT_MINIMUM_REPLY_SURB_REQUEST_SIZE,
maximum_reply_surb_request_size: DEFAULT_MAXIMUM_REPLY_SURB_REQUEST_SIZE,
maximum_allowed_reply_surb_request_size: DEFAULT_MAXIMUM_ALLOWED_SURB_REQUEST_SIZE,
maximum_reply_surb_rerequest_waiting_period:
DEFAULT_MAXIMUM_REPLY_SURB_REREQUEST_WAITING_PERIOD,
maximum_reply_surb_drop_waiting_period: DEFAULT_MAXIMUM_REPLY_SURB_DROP_WAITING_PERIOD,
maximum_reply_surb_age: DEFAULT_MAXIMUM_REPLY_SURB_AGE,
maximum_reply_key_age: DEFAULT_MAXIMUM_REPLY_KEY_AGE,
surb_mix_hops: None,
}
}
}
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct DebugConfig {
/// Defines all configuration options related to traffic streams.
pub traffic: Traffic,
/// Defines all configuration options related to cover traffic stream(s).
pub cover_traffic: CoverTraffic,
/// Defines all configuration options related to the gateway connection.
pub gateway_connection: GatewayConnection,
/// Defines all configuration options related to acknowledgements, such as delays or wait timeouts.
pub acknowledgements: Acknowledgements,
/// Defines all configuration options related topology, such as refresh rates or timeouts.
pub topology: Topology,
/// Defines all configuration options related to reply SURBs.
pub reply_surbs: ReplySurbs,
}
impl DebugConfig {
pub fn validate(&self) -> bool {
// no other sections have explicit requirements (yet)
self.traffic.validate()
}
}
// it could be derived, sure, but I'd rather have an explicit implementation in case we had to change
// something manually at some point
#[allow(clippy::derivable_impls)]
impl Default for DebugConfig {
fn default() -> Self {
DebugConfig {
traffic: Default::default(),
cover_traffic: Default::default(),
gateway_connection: Default::default(),
acknowledgements: Default::default(),
topology: Default::default(),
reply_surbs: Default::default(),
}
}
}
@@ -0,0 +1,15 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
pub mod v1;
pub mod v2;
pub mod v3;
pub mod v4;
pub mod v5;
// aliases for backwards compatibility
pub use v1 as old_config_v1_1_13;
pub use v2 as old_config_v1_1_20;
pub use v3 as old_config_v1_1_20_2;
pub use v4 as old_config_v1_1_30;
pub use v5 as old_config_v1_1_33;
@@ -1,23 +1,28 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::config::old_config_v1_1_20::{
AcknowledgementsV1_1_20, ClientV1_1_20, ConfigV1_1_20, CoverTrafficV1_1_20, DebugConfigV1_1_20,
GatewayConnectionV1_1_20, LoggingV1_1_20, ReplySurbsV1_1_20, TopologyV1_1_20, TrafficV1_1_20,
DEFAULT_ACK_WAIT_ADDITION, DEFAULT_ACK_WAIT_MULTIPLIER, DEFAULT_AVERAGE_PACKET_DELAY,
DEFAULT_GATEWAY_RESPONSE_TIMEOUT, DEFAULT_LOOP_COVER_STREAM_AVERAGE_DELAY,
DEFAULT_MAXIMUM_ALLOWED_SURB_REQUEST_SIZE, DEFAULT_MAXIMUM_REPLY_KEY_AGE,
DEFAULT_MAXIMUM_REPLY_SURB_AGE, DEFAULT_MAXIMUM_REPLY_SURB_DROP_WAITING_PERIOD,
DEFAULT_MAXIMUM_REPLY_SURB_REQUEST_SIZE, DEFAULT_MAXIMUM_REPLY_SURB_REREQUEST_WAITING_PERIOD,
use crate::old::v2::{
AcknowledgementsV2, ClientV2, ConfigV2, CoverTrafficV2, DebugConfigV2, GatewayConnectionV2,
LoggingV2, ReplySurbsV2, TopologyV2, TrafficV2, DEFAULT_ACK_WAIT_ADDITION,
DEFAULT_ACK_WAIT_MULTIPLIER, DEFAULT_AVERAGE_PACKET_DELAY, DEFAULT_GATEWAY_RESPONSE_TIMEOUT,
DEFAULT_LOOP_COVER_STREAM_AVERAGE_DELAY, DEFAULT_MAXIMUM_ALLOWED_SURB_REQUEST_SIZE,
DEFAULT_MAXIMUM_REPLY_KEY_AGE, DEFAULT_MAXIMUM_REPLY_SURB_AGE,
DEFAULT_MAXIMUM_REPLY_SURB_DROP_WAITING_PERIOD, DEFAULT_MAXIMUM_REPLY_SURB_REQUEST_SIZE,
DEFAULT_MAXIMUM_REPLY_SURB_REREQUEST_WAITING_PERIOD,
DEFAULT_MAXIMUM_REPLY_SURB_STORAGE_THRESHOLD, DEFAULT_MESSAGE_STREAM_AVERAGE_DELAY,
DEFAULT_MINIMUM_REPLY_SURB_REQUEST_SIZE, DEFAULT_MINIMUM_REPLY_SURB_STORAGE_THRESHOLD,
DEFAULT_TOPOLOGY_REFRESH_RATE, DEFAULT_TOPOLOGY_RESOLUTION_TIMEOUT,
};
use nym_sphinx::params::PacketSize;
use nym_sphinx_params::PacketSize;
use serde::{Deserialize, Serialize};
use std::marker::PhantomData;
use std::time::Duration;
// aliases for backwards compatibility
pub type OldConfigV1_1_13<T> = ConfigV1<T>;
pub type OldLoggingV1_1_13 = LoggingV1;
pub type OldDebugConfigV1_1_13 = DebugConfigV1;
#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "lowercase")]
pub enum ExtendedPacketSize {
@@ -38,28 +43,28 @@ impl From<ExtendedPacketSize> for PacketSize {
#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct OldConfigV1_1_13<T> {
pub client: ClientV1_1_20<T>,
pub struct ConfigV1<T> {
pub client: ClientV2<T>,
#[serde(default)]
pub logging: OldLoggingV1_1_13,
pub logging: LoggingV1,
#[serde(default)]
pub debug: OldDebugConfigV1_1_13,
pub debug: DebugConfigV1,
}
#[derive(Debug, Clone, Default, Deserialize, PartialEq, Eq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct OldLoggingV1_1_13 {}
pub struct LoggingV1 {}
impl From<OldLoggingV1_1_13> for LoggingV1_1_20 {
fn from(_value: OldLoggingV1_1_13) -> Self {
LoggingV1_1_20 {}
impl From<LoggingV1> for LoggingV2 {
fn from(_value: LoggingV1) -> Self {
LoggingV2 {}
}
}
#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct OldDebugConfigV1_1_13 {
pub struct DebugConfigV1 {
#[serde(with = "humantime_serde")]
pub average_packet_delay: Duration,
@@ -114,10 +119,10 @@ pub struct OldDebugConfigV1_1_13 {
pub maximum_reply_key_age: Duration,
}
impl From<OldDebugConfigV1_1_13> for DebugConfigV1_1_20 {
fn from(value: OldDebugConfigV1_1_13) -> Self {
DebugConfigV1_1_20 {
traffic: TrafficV1_1_20 {
impl From<DebugConfigV1> for DebugConfigV2 {
fn from(value: DebugConfigV1) -> Self {
DebugConfigV2 {
traffic: TrafficV2 {
average_packet_delay: value.average_packet_delay,
message_sending_average_delay: value.message_sending_average_delay,
disable_main_poisson_packet_distribution: value
@@ -125,25 +130,25 @@ impl From<OldDebugConfigV1_1_13> for DebugConfigV1_1_20 {
primary_packet_size: PacketSize::RegularPacket,
secondary_packet_size: value.use_extended_packet_size.map(Into::into),
},
cover_traffic: CoverTrafficV1_1_20 {
cover_traffic: CoverTrafficV2 {
loop_cover_traffic_average_delay: value.loop_cover_traffic_average_delay,
disable_loop_cover_traffic_stream: value.disable_loop_cover_traffic_stream,
..CoverTrafficV1_1_20::default()
..CoverTrafficV2::default()
},
gateway_connection: GatewayConnectionV1_1_20 {
gateway_connection: GatewayConnectionV2 {
gateway_response_timeout: value.gateway_response_timeout,
},
acknowledgements: AcknowledgementsV1_1_20 {
acknowledgements: AcknowledgementsV2 {
average_ack_delay: value.average_ack_delay,
ack_wait_multiplier: value.ack_wait_multiplier,
ack_wait_addition: value.ack_wait_addition,
},
topology: TopologyV1_1_20 {
topology: TopologyV2 {
topology_refresh_rate: value.topology_refresh_rate,
topology_resolution_timeout: value.topology_resolution_timeout,
disable_refreshing: false,
},
reply_surbs: ReplySurbsV1_1_20 {
reply_surbs: ReplySurbsV2 {
minimum_reply_surb_storage_threshold: value.minimum_reply_surb_storage_threshold,
maximum_reply_surb_storage_threshold: value.maximum_reply_surb_storage_threshold,
minimum_reply_surb_request_size: value.minimum_reply_surb_request_size,
@@ -161,9 +166,9 @@ impl From<OldDebugConfigV1_1_13> for DebugConfigV1_1_20 {
}
}
impl Default for OldDebugConfigV1_1_13 {
impl Default for DebugConfigV1 {
fn default() -> Self {
OldDebugConfigV1_1_13 {
DebugConfigV1 {
average_packet_delay: DEFAULT_AVERAGE_PACKET_DELAY,
average_ack_delay: DEFAULT_AVERAGE_PACKET_DELAY,
ack_wait_multiplier: DEFAULT_ACK_WAIT_MULTIPLIER,
@@ -190,10 +195,10 @@ impl Default for OldDebugConfigV1_1_13 {
}
}
impl<T, U> From<OldConfigV1_1_13<T>> for ConfigV1_1_20<U> {
fn from(value: OldConfigV1_1_13<T>) -> Self {
ConfigV1_1_20 {
client: ClientV1_1_20 {
impl<T, U> From<ConfigV1<T>> for ConfigV2<U> {
fn from(value: ConfigV1<T>) -> Self {
ConfigV2 {
client: ClientV2 {
version: value.client.version,
id: value.client.id,
disabled_credentials_mode: value.client.disabled_credentials_mode,
@@ -1,12 +1,11 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::config::old_config_v1_1_20_2::{
AcknowledgementsV1_1_20_2, CoverTrafficV1_1_20_2, DebugConfigV1_1_20_2,
GatewayConnectionV1_1_20_2, GatewayEndpointConfigV1_1_20_2, ReplySurbsV1_1_20_2,
TopologyV1_1_20_2, TrafficV1_1_20_2,
use crate::old::v3::{
AcknowledgementsV3, CoverTrafficV3, DebugConfigV3, GatewayConnectionV3,
GatewayEndpointConfigV3, ReplySurbsV3, TopologyV3, TrafficV3,
};
use nym_sphinx::params::{PacketSize, PacketType};
use nym_sphinx_params::{PacketSize, PacketType};
use serde::{Deserialize, Serialize};
use std::marker::PhantomData;
use std::path::PathBuf;
@@ -54,27 +53,41 @@ pub(crate) const DEFAULT_MAXIMUM_REPLY_SURB_AGE: Duration = Duration::from_secs(
// 24 hours
pub(crate) const DEFAULT_MAXIMUM_REPLY_KEY_AGE: Duration = Duration::from_secs(24 * 60 * 60);
// aliases for backwards compatibility
pub type ConfigV1_1_20<T> = ConfigV2<T>;
pub type ClientV1_1_20<T> = ClientV2<T>;
pub type LoggingV1_1_20 = LoggingV2;
pub type DebugConfigV1_1_20 = DebugConfigV2;
pub type GatewayEndpointConfigV1_1_20 = GatewayEndpointConfigV2;
pub type TrafficV1_1_20 = TrafficV2;
pub type CoverTrafficV1_1_20 = CoverTrafficV2;
pub type GatewayConnectionV1_1_20 = GatewayConnectionV2;
pub type AcknowledgementsV1_1_20 = AcknowledgementsV2;
pub type TopologyV1_1_20 = TopologyV2;
pub type ReplySurbsV1_1_20 = ReplySurbsV2;
#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct ConfigV1_1_20<T> {
pub client: ClientV1_1_20<T>,
pub struct ConfigV2<T> {
pub client: ClientV2<T>,
#[serde(default)]
pub logging: LoggingV1_1_20,
pub logging: LoggingV2,
#[serde(default)]
pub debug: DebugConfigV1_1_20,
pub debug: DebugConfigV2,
}
#[derive(Clone, Debug, Default, Deserialize, PartialEq, Eq, Serialize)]
pub struct GatewayEndpointConfigV1_1_20 {
pub struct GatewayEndpointConfigV2 {
pub gateway_id: String,
pub gateway_owner: String,
pub gateway_listener: String,
}
impl From<GatewayEndpointConfigV1_1_20> for GatewayEndpointConfigV1_1_20_2 {
fn from(value: GatewayEndpointConfigV1_1_20) -> Self {
GatewayEndpointConfigV1_1_20_2 {
impl From<GatewayEndpointConfigV2> for GatewayEndpointConfigV3 {
fn from(value: GatewayEndpointConfigV2) -> Self {
GatewayEndpointConfigV3 {
gateway_id: value.gateway_id,
gateway_owner: value.gateway_owner,
gateway_listener: value.gateway_listener,
@@ -83,7 +96,7 @@ impl From<GatewayEndpointConfigV1_1_20> for GatewayEndpointConfigV1_1_20_2 {
}
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
pub struct ClientV1_1_20<T> {
pub struct ClientV2<T> {
pub version: String,
pub id: String,
#[serde(default)]
@@ -98,7 +111,7 @@ pub struct ClientV1_1_20<T> {
pub public_encryption_key_file: PathBuf,
pub gateway_shared_key_file: PathBuf,
pub ack_key_file: PathBuf,
pub gateway_endpoint: GatewayEndpointConfigV1_1_20,
pub gateway_endpoint: GatewayEndpointConfigV2,
pub database_path: PathBuf,
#[serde(default)]
pub reply_surb_database_path: PathBuf,
@@ -110,11 +123,11 @@ pub struct ClientV1_1_20<T> {
#[derive(Debug, Clone, Default, Deserialize, PartialEq, Eq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct LoggingV1_1_20 {}
pub struct LoggingV2 {}
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
#[serde(default)]
pub struct TrafficV1_1_20 {
pub struct TrafficV2 {
#[serde(with = "humantime_serde")]
pub average_packet_delay: Duration,
#[serde(with = "humantime_serde")]
@@ -124,9 +137,9 @@ pub struct TrafficV1_1_20 {
pub secondary_packet_size: Option<PacketSize>,
}
impl From<TrafficV1_1_20> for TrafficV1_1_20_2 {
fn from(value: TrafficV1_1_20) -> Self {
TrafficV1_1_20_2 {
impl From<TrafficV2> for TrafficV3 {
fn from(value: TrafficV2) -> Self {
TrafficV3 {
average_packet_delay: value.average_packet_delay,
message_sending_average_delay: value.message_sending_average_delay,
disable_main_poisson_packet_distribution: value
@@ -138,9 +151,9 @@ impl From<TrafficV1_1_20> for TrafficV1_1_20_2 {
}
}
impl Default for TrafficV1_1_20 {
impl Default for TrafficV2 {
fn default() -> Self {
TrafficV1_1_20 {
TrafficV2 {
average_packet_delay: DEFAULT_AVERAGE_PACKET_DELAY,
message_sending_average_delay: DEFAULT_MESSAGE_STREAM_AVERAGE_DELAY,
disable_main_poisson_packet_distribution: false,
@@ -152,16 +165,16 @@ impl Default for TrafficV1_1_20 {
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct CoverTrafficV1_1_20 {
pub struct CoverTrafficV2 {
#[serde(with = "humantime_serde")]
pub loop_cover_traffic_average_delay: Duration,
pub cover_traffic_primary_size_ratio: f64,
pub disable_loop_cover_traffic_stream: bool,
}
impl From<CoverTrafficV1_1_20> for CoverTrafficV1_1_20_2 {
fn from(value: CoverTrafficV1_1_20) -> Self {
CoverTrafficV1_1_20_2 {
impl From<CoverTrafficV2> for CoverTrafficV3 {
fn from(value: CoverTrafficV2) -> Self {
CoverTrafficV3 {
loop_cover_traffic_average_delay: value.loop_cover_traffic_average_delay,
cover_traffic_primary_size_ratio: value.cover_traffic_primary_size_ratio,
disable_loop_cover_traffic_stream: value.disable_loop_cover_traffic_stream,
@@ -169,9 +182,9 @@ impl From<CoverTrafficV1_1_20> for CoverTrafficV1_1_20_2 {
}
}
impl Default for CoverTrafficV1_1_20 {
impl Default for CoverTrafficV2 {
fn default() -> Self {
CoverTrafficV1_1_20 {
CoverTrafficV2 {
loop_cover_traffic_average_delay: DEFAULT_LOOP_COVER_STREAM_AVERAGE_DELAY,
cover_traffic_primary_size_ratio: DEFAULT_COVER_TRAFFIC_PRIMARY_SIZE_RATIO,
disable_loop_cover_traffic_stream: false,
@@ -181,22 +194,22 @@ impl Default for CoverTrafficV1_1_20 {
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct GatewayConnectionV1_1_20 {
pub struct GatewayConnectionV2 {
#[serde(with = "humantime_serde")]
pub gateway_response_timeout: Duration,
}
impl From<GatewayConnectionV1_1_20> for GatewayConnectionV1_1_20_2 {
fn from(value: GatewayConnectionV1_1_20) -> Self {
GatewayConnectionV1_1_20_2 {
impl From<GatewayConnectionV2> for GatewayConnectionV3 {
fn from(value: GatewayConnectionV2) -> Self {
GatewayConnectionV3 {
gateway_response_timeout: value.gateway_response_timeout,
}
}
}
impl Default for GatewayConnectionV1_1_20 {
impl Default for GatewayConnectionV2 {
fn default() -> Self {
GatewayConnectionV1_1_20 {
GatewayConnectionV2 {
gateway_response_timeout: DEFAULT_GATEWAY_RESPONSE_TIMEOUT,
}
}
@@ -204,7 +217,7 @@ impl Default for GatewayConnectionV1_1_20 {
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct AcknowledgementsV1_1_20 {
pub struct AcknowledgementsV2 {
#[serde(with = "humantime_serde")]
pub average_ack_delay: Duration,
pub ack_wait_multiplier: f64,
@@ -212,9 +225,9 @@ pub struct AcknowledgementsV1_1_20 {
pub ack_wait_addition: Duration,
}
impl From<AcknowledgementsV1_1_20> for AcknowledgementsV1_1_20_2 {
fn from(value: AcknowledgementsV1_1_20) -> Self {
AcknowledgementsV1_1_20_2 {
impl From<AcknowledgementsV2> for AcknowledgementsV3 {
fn from(value: AcknowledgementsV2) -> Self {
AcknowledgementsV3 {
average_ack_delay: value.average_ack_delay,
ack_wait_multiplier: value.ack_wait_multiplier,
ack_wait_addition: value.ack_wait_addition,
@@ -222,9 +235,9 @@ impl From<AcknowledgementsV1_1_20> for AcknowledgementsV1_1_20_2 {
}
}
impl Default for AcknowledgementsV1_1_20 {
impl Default for AcknowledgementsV2 {
fn default() -> Self {
AcknowledgementsV1_1_20 {
AcknowledgementsV2 {
average_ack_delay: DEFAULT_AVERAGE_PACKET_DELAY,
ack_wait_multiplier: DEFAULT_ACK_WAIT_MULTIPLIER,
ack_wait_addition: DEFAULT_ACK_WAIT_ADDITION,
@@ -234,7 +247,7 @@ impl Default for AcknowledgementsV1_1_20 {
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct TopologyV1_1_20 {
pub struct TopologyV2 {
#[serde(with = "humantime_serde")]
pub topology_refresh_rate: Duration,
#[serde(with = "humantime_serde")]
@@ -242,9 +255,9 @@ pub struct TopologyV1_1_20 {
pub disable_refreshing: bool,
}
impl From<TopologyV1_1_20> for TopologyV1_1_20_2 {
fn from(value: TopologyV1_1_20) -> Self {
TopologyV1_1_20_2 {
impl From<TopologyV2> for TopologyV3 {
fn from(value: TopologyV2) -> Self {
TopologyV3 {
topology_refresh_rate: value.topology_refresh_rate,
topology_resolution_timeout: value.topology_resolution_timeout,
disable_refreshing: value.disable_refreshing,
@@ -252,9 +265,9 @@ impl From<TopologyV1_1_20> for TopologyV1_1_20_2 {
}
}
impl Default for TopologyV1_1_20 {
impl Default for TopologyV2 {
fn default() -> Self {
TopologyV1_1_20 {
TopologyV2 {
topology_refresh_rate: DEFAULT_TOPOLOGY_REFRESH_RATE,
topology_resolution_timeout: DEFAULT_TOPOLOGY_RESOLUTION_TIMEOUT,
disable_refreshing: false,
@@ -264,7 +277,7 @@ impl Default for TopologyV1_1_20 {
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct ReplySurbsV1_1_20 {
pub struct ReplySurbsV2 {
pub minimum_reply_surb_storage_threshold: usize,
pub maximum_reply_surb_storage_threshold: usize,
pub minimum_reply_surb_request_size: u32,
@@ -280,9 +293,9 @@ pub struct ReplySurbsV1_1_20 {
pub maximum_reply_key_age: Duration,
}
impl From<ReplySurbsV1_1_20> for ReplySurbsV1_1_20_2 {
fn from(value: ReplySurbsV1_1_20) -> Self {
ReplySurbsV1_1_20_2 {
impl From<ReplySurbsV2> for ReplySurbsV3 {
fn from(value: ReplySurbsV2) -> Self {
ReplySurbsV3 {
minimum_reply_surb_storage_threshold: value.minimum_reply_surb_storage_threshold,
maximum_reply_surb_storage_threshold: value.maximum_reply_surb_storage_threshold,
minimum_reply_surb_request_size: value.minimum_reply_surb_request_size,
@@ -297,9 +310,9 @@ impl From<ReplySurbsV1_1_20> for ReplySurbsV1_1_20_2 {
}
}
impl Default for ReplySurbsV1_1_20 {
impl Default for ReplySurbsV2 {
fn default() -> Self {
ReplySurbsV1_1_20 {
ReplySurbsV2 {
minimum_reply_surb_storage_threshold: DEFAULT_MINIMUM_REPLY_SURB_STORAGE_THRESHOLD,
maximum_reply_surb_storage_threshold: DEFAULT_MAXIMUM_REPLY_SURB_STORAGE_THRESHOLD,
minimum_reply_surb_request_size: DEFAULT_MINIMUM_REPLY_SURB_REQUEST_SIZE,
@@ -316,18 +329,18 @@ impl Default for ReplySurbsV1_1_20 {
#[derive(Debug, Default, Clone, Copy, Deserialize, PartialEq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct DebugConfigV1_1_20 {
pub traffic: TrafficV1_1_20,
pub cover_traffic: CoverTrafficV1_1_20,
pub gateway_connection: GatewayConnectionV1_1_20,
pub acknowledgements: AcknowledgementsV1_1_20,
pub topology: TopologyV1_1_20,
pub reply_surbs: ReplySurbsV1_1_20,
pub struct DebugConfigV2 {
pub traffic: TrafficV2,
pub cover_traffic: CoverTrafficV2,
pub gateway_connection: GatewayConnectionV2,
pub acknowledgements: AcknowledgementsV2,
pub topology: TopologyV2,
pub reply_surbs: ReplySurbsV2,
}
impl From<DebugConfigV1_1_20> for DebugConfigV1_1_20_2 {
fn from(value: DebugConfigV1_1_20) -> Self {
DebugConfigV1_1_20_2 {
impl From<DebugConfigV2> for DebugConfigV3 {
fn from(value: DebugConfigV2) -> Self {
DebugConfigV3 {
traffic: value.traffic.into(),
cover_traffic: value.cover_traffic.into(),
gateway_connection: value.gateway_connection.into(),
@@ -1,12 +1,12 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::config::old_config_v1_1_30::{
AcknowledgementsV1_1_30, ClientV1_1_30, ConfigV1_1_30, CoverTrafficV1_1_30, DebugConfigV1_1_30,
GatewayConnectionV1_1_30, ReplySurbsV1_1_30, TopologyV1_1_30, TrafficV1_1_30,
use crate::old::v4::{
AcknowledgementsV4, ClientV4, ConfigV4, CoverTrafficV4, DebugConfigV4, GatewayConnectionV4,
ReplySurbsV4, TopologyV4, TrafficV4,
};
use crate::config::old_config_v1_1_33::OldGatewayEndpointConfigV1_1_33;
use nym_sphinx::params::{PacketSize, PacketType};
use crate::old::v5::GatewayEndpointConfigV5;
use nym_sphinx_params::{PacketSize, PacketType};
use serde::{Deserialize, Serialize};
use std::time::Duration;
use url::Url;
@@ -50,18 +50,31 @@ const DEFAULT_MAXIMUM_REPLY_SURB_AGE: Duration = Duration::from_secs(12 * 60 * 6
// 24 hours
const DEFAULT_MAXIMUM_REPLY_KEY_AGE: Duration = Duration::from_secs(24 * 60 * 60);
// aliases for backwards compatibility
pub type ConfigV1_1_20_2 = ConfigV3;
pub type ClientV1_1_20_2 = ClientV3;
pub type DebugConfigV1_1_20_2 = DebugConfigV3;
pub type GatewayEndpointConfigV1_1_20_2 = GatewayEndpointConfigV3;
pub type TrafficV1_1_20_2 = TrafficV3;
pub type CoverTrafficV1_1_20_2 = CoverTrafficV3;
pub type GatewayConnectionV1_1_20_2 = GatewayConnectionV3;
pub type AcknowledgementsV1_1_20_2 = AcknowledgementsV3;
pub type TopologyV1_1_20_2 = TopologyV3;
pub type ReplySurbsV1_1_20_2 = ReplySurbsV3;
#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct ConfigV1_1_20_2 {
pub client: ClientV1_1_20_2,
pub struct ConfigV3 {
pub client: ClientV3,
#[serde(default)]
pub debug: DebugConfigV1_1_20_2,
pub debug: DebugConfigV3,
}
impl From<ConfigV1_1_20_2> for ConfigV1_1_30 {
fn from(value: ConfigV1_1_20_2) -> Self {
ConfigV1_1_30 {
impl From<ConfigV3> for ConfigV4 {
fn from(value: ConfigV3) -> Self {
ConfigV4 {
client: value.client.into(),
debug: value.debug.into(),
}
@@ -69,7 +82,7 @@ impl From<ConfigV1_1_20_2> for ConfigV1_1_30 {
}
#[derive(Clone, Debug, Default, Deserialize, PartialEq, Eq, Serialize)]
pub struct GatewayEndpointConfigV1_1_20_2 {
pub struct GatewayEndpointConfigV3 {
/// gateway_id specifies ID of the gateway to which the client should send messages.
/// If initially omitted, a random gateway will be chosen from the available topology.
pub gateway_id: String,
@@ -81,9 +94,9 @@ pub struct GatewayEndpointConfigV1_1_20_2 {
pub gateway_listener: String,
}
impl From<GatewayEndpointConfigV1_1_20_2> for OldGatewayEndpointConfigV1_1_33 {
fn from(value: GatewayEndpointConfigV1_1_20_2) -> Self {
OldGatewayEndpointConfigV1_1_33 {
impl From<GatewayEndpointConfigV3> for GatewayEndpointConfigV5 {
fn from(value: GatewayEndpointConfigV3) -> Self {
GatewayEndpointConfigV5 {
gateway_id: value.gateway_id,
gateway_owner: value.gateway_owner,
gateway_listener: value.gateway_listener,
@@ -92,7 +105,7 @@ impl From<GatewayEndpointConfigV1_1_20_2> for OldGatewayEndpointConfigV1_1_33 {
}
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
pub struct ClientV1_1_20_2 {
pub struct ClientV3 {
pub version: String,
pub id: String,
@@ -105,12 +118,12 @@ pub struct ClientV1_1_20_2 {
#[serde(alias = "validator_api_urls")]
pub nym_api_urls: Vec<Url>,
pub gateway_endpoint: GatewayEndpointConfigV1_1_20_2,
pub gateway_endpoint: GatewayEndpointConfigV3,
}
impl From<ClientV1_1_20_2> for ClientV1_1_30 {
fn from(value: ClientV1_1_20_2) -> Self {
ClientV1_1_30 {
impl From<ClientV3> for ClientV4 {
fn from(value: ClientV3) -> Self {
ClientV4 {
version: value.version,
id: value.id,
disabled_credentials_mode: value.disabled_credentials_mode,
@@ -122,7 +135,7 @@ impl From<ClientV1_1_20_2> for ClientV1_1_30 {
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
#[serde(default)]
pub struct TrafficV1_1_20_2 {
pub struct TrafficV3 {
#[serde(with = "humantime_serde")]
pub average_packet_delay: Duration,
#[serde(with = "humantime_serde")]
@@ -133,9 +146,9 @@ pub struct TrafficV1_1_20_2 {
pub packet_type: PacketType,
}
impl From<TrafficV1_1_20_2> for TrafficV1_1_30 {
fn from(value: TrafficV1_1_20_2) -> Self {
TrafficV1_1_30 {
impl From<TrafficV3> for TrafficV4 {
fn from(value: TrafficV3) -> Self {
TrafficV4 {
average_packet_delay: value.average_packet_delay,
message_sending_average_delay: value.message_sending_average_delay,
disable_main_poisson_packet_distribution: value
@@ -147,9 +160,9 @@ impl From<TrafficV1_1_20_2> for TrafficV1_1_30 {
}
}
impl Default for TrafficV1_1_20_2 {
impl Default for TrafficV3 {
fn default() -> Self {
TrafficV1_1_20_2 {
TrafficV3 {
average_packet_delay: DEFAULT_AVERAGE_PACKET_DELAY,
message_sending_average_delay: DEFAULT_MESSAGE_STREAM_AVERAGE_DELAY,
disable_main_poisson_packet_distribution: false,
@@ -162,16 +175,16 @@ impl Default for TrafficV1_1_20_2 {
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct CoverTrafficV1_1_20_2 {
pub struct CoverTrafficV3 {
#[serde(with = "humantime_serde")]
pub loop_cover_traffic_average_delay: Duration,
pub cover_traffic_primary_size_ratio: f64,
pub disable_loop_cover_traffic_stream: bool,
}
impl From<CoverTrafficV1_1_20_2> for CoverTrafficV1_1_30 {
fn from(value: CoverTrafficV1_1_20_2) -> Self {
CoverTrafficV1_1_30 {
impl From<CoverTrafficV3> for CoverTrafficV4 {
fn from(value: CoverTrafficV3) -> Self {
CoverTrafficV4 {
loop_cover_traffic_average_delay: value.loop_cover_traffic_average_delay,
cover_traffic_primary_size_ratio: value.cover_traffic_primary_size_ratio,
disable_loop_cover_traffic_stream: value.disable_loop_cover_traffic_stream,
@@ -179,9 +192,9 @@ impl From<CoverTrafficV1_1_20_2> for CoverTrafficV1_1_30 {
}
}
impl Default for CoverTrafficV1_1_20_2 {
impl Default for CoverTrafficV3 {
fn default() -> Self {
CoverTrafficV1_1_20_2 {
CoverTrafficV3 {
loop_cover_traffic_average_delay: DEFAULT_LOOP_COVER_STREAM_AVERAGE_DELAY,
cover_traffic_primary_size_ratio: DEFAULT_COVER_TRAFFIC_PRIMARY_SIZE_RATIO,
disable_loop_cover_traffic_stream: false,
@@ -191,22 +204,22 @@ impl Default for CoverTrafficV1_1_20_2 {
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct GatewayConnectionV1_1_20_2 {
pub struct GatewayConnectionV3 {
#[serde(with = "humantime_serde")]
pub gateway_response_timeout: Duration,
}
impl From<GatewayConnectionV1_1_20_2> for GatewayConnectionV1_1_30 {
fn from(value: GatewayConnectionV1_1_20_2) -> Self {
GatewayConnectionV1_1_30 {
impl From<GatewayConnectionV3> for GatewayConnectionV4 {
fn from(value: GatewayConnectionV3) -> Self {
GatewayConnectionV4 {
gateway_response_timeout: value.gateway_response_timeout,
}
}
}
impl Default for GatewayConnectionV1_1_20_2 {
impl Default for GatewayConnectionV3 {
fn default() -> Self {
GatewayConnectionV1_1_20_2 {
GatewayConnectionV3 {
gateway_response_timeout: DEFAULT_GATEWAY_RESPONSE_TIMEOUT,
}
}
@@ -214,7 +227,7 @@ impl Default for GatewayConnectionV1_1_20_2 {
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct AcknowledgementsV1_1_20_2 {
pub struct AcknowledgementsV3 {
#[serde(with = "humantime_serde")]
pub average_ack_delay: Duration,
pub ack_wait_multiplier: f64,
@@ -222,9 +235,9 @@ pub struct AcknowledgementsV1_1_20_2 {
pub ack_wait_addition: Duration,
}
impl From<AcknowledgementsV1_1_20_2> for AcknowledgementsV1_1_30 {
fn from(value: AcknowledgementsV1_1_20_2) -> Self {
AcknowledgementsV1_1_30 {
impl From<AcknowledgementsV3> for AcknowledgementsV4 {
fn from(value: AcknowledgementsV3) -> Self {
AcknowledgementsV4 {
average_ack_delay: value.average_ack_delay,
ack_wait_multiplier: value.ack_wait_multiplier,
ack_wait_addition: value.ack_wait_addition,
@@ -232,9 +245,9 @@ impl From<AcknowledgementsV1_1_20_2> for AcknowledgementsV1_1_30 {
}
}
impl Default for AcknowledgementsV1_1_20_2 {
impl Default for AcknowledgementsV3 {
fn default() -> Self {
AcknowledgementsV1_1_20_2 {
AcknowledgementsV3 {
average_ack_delay: DEFAULT_AVERAGE_PACKET_DELAY,
ack_wait_multiplier: DEFAULT_ACK_WAIT_MULTIPLIER,
ack_wait_addition: DEFAULT_ACK_WAIT_ADDITION,
@@ -244,7 +257,7 @@ impl Default for AcknowledgementsV1_1_20_2 {
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct TopologyV1_1_20_2 {
pub struct TopologyV3 {
#[serde(with = "humantime_serde")]
pub topology_refresh_rate: Duration,
#[serde(with = "humantime_serde")]
@@ -252,9 +265,9 @@ pub struct TopologyV1_1_20_2 {
pub disable_refreshing: bool,
}
impl Default for TopologyV1_1_20_2 {
impl Default for TopologyV3 {
fn default() -> Self {
TopologyV1_1_20_2 {
TopologyV3 {
topology_refresh_rate: DEFAULT_TOPOLOGY_REFRESH_RATE,
topology_resolution_timeout: DEFAULT_TOPOLOGY_RESOLUTION_TIMEOUT,
disable_refreshing: false,
@@ -262,9 +275,9 @@ impl Default for TopologyV1_1_20_2 {
}
}
impl From<TopologyV1_1_20_2> for TopologyV1_1_30 {
fn from(value: TopologyV1_1_20_2) -> Self {
TopologyV1_1_30 {
impl From<TopologyV3> for TopologyV4 {
fn from(value: TopologyV3) -> Self {
TopologyV4 {
topology_refresh_rate: value.topology_refresh_rate,
topology_resolution_timeout: value.topology_resolution_timeout,
disable_refreshing: value.disable_refreshing,
@@ -275,7 +288,7 @@ impl From<TopologyV1_1_20_2> for TopologyV1_1_30 {
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct ReplySurbsV1_1_20_2 {
pub struct ReplySurbsV3 {
pub minimum_reply_surb_storage_threshold: usize,
pub maximum_reply_surb_storage_threshold: usize,
pub minimum_reply_surb_request_size: u32,
@@ -291,9 +304,9 @@ pub struct ReplySurbsV1_1_20_2 {
pub maximum_reply_key_age: Duration,
}
impl Default for ReplySurbsV1_1_20_2 {
impl Default for ReplySurbsV3 {
fn default() -> Self {
ReplySurbsV1_1_20_2 {
ReplySurbsV3 {
minimum_reply_surb_storage_threshold: DEFAULT_MINIMUM_REPLY_SURB_STORAGE_THRESHOLD,
maximum_reply_surb_storage_threshold: DEFAULT_MAXIMUM_REPLY_SURB_STORAGE_THRESHOLD,
minimum_reply_surb_request_size: DEFAULT_MINIMUM_REPLY_SURB_REQUEST_SIZE,
@@ -308,9 +321,9 @@ impl Default for ReplySurbsV1_1_20_2 {
}
}
impl From<ReplySurbsV1_1_20_2> for ReplySurbsV1_1_30 {
fn from(value: ReplySurbsV1_1_20_2) -> Self {
ReplySurbsV1_1_30 {
impl From<ReplySurbsV3> for ReplySurbsV4 {
fn from(value: ReplySurbsV3) -> Self {
ReplySurbsV4 {
minimum_reply_surb_storage_threshold: value.minimum_reply_surb_storage_threshold,
maximum_reply_surb_storage_threshold: value.maximum_reply_surb_storage_threshold,
minimum_reply_surb_request_size: value.minimum_reply_surb_request_size,
@@ -327,18 +340,18 @@ impl From<ReplySurbsV1_1_20_2> for ReplySurbsV1_1_30 {
#[derive(Debug, Default, Clone, Copy, Deserialize, PartialEq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct DebugConfigV1_1_20_2 {
pub traffic: TrafficV1_1_20_2,
pub cover_traffic: CoverTrafficV1_1_20_2,
pub gateway_connection: GatewayConnectionV1_1_20_2,
pub acknowledgements: AcknowledgementsV1_1_20_2,
pub topology: TopologyV1_1_20_2,
pub reply_surbs: ReplySurbsV1_1_20_2,
pub struct DebugConfigV3 {
pub traffic: TrafficV3,
pub cover_traffic: CoverTrafficV3,
pub gateway_connection: GatewayConnectionV3,
pub acknowledgements: AcknowledgementsV3,
pub topology: TopologyV3,
pub reply_surbs: ReplySurbsV3,
}
impl From<DebugConfigV1_1_20_2> for DebugConfigV1_1_30 {
fn from(value: DebugConfigV1_1_20_2) -> Self {
DebugConfigV1_1_30 {
impl From<DebugConfigV3> for DebugConfigV4 {
fn from(value: DebugConfigV3) -> Self {
DebugConfigV4 {
traffic: value.traffic.into(),
cover_traffic: value.cover_traffic.into(),
gateway_connection: value.gateway_connection.into(),
@@ -1,16 +1,13 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::client::topology_control::geo_aware_provider::CountryGroup;
use crate::config::old_config_v1_1_33::{
AcknowledgementsV1_1_33, ClientV1_1_33, ConfigV1_1_33, CoverTrafficV1_1_33, DebugConfigV1_1_33,
GatewayConnectionV1_1_33, GroupByV1_1_33, ReplySurbsV1_1_33, TopologyStructureV1_1_33,
TopologyV1_1_33, TrafficV1_1_33,
};
use nym_sphinx::{
addressing::clients::Recipient,
params::{PacketSize, PacketType},
use crate::old::v5::{
AcknowledgementsV5, ClientV5, ConfigV5, CoverTrafficV5, DebugConfigV5, GatewayConnectionV5,
GroupByV5, ReplySurbsV5, TopologyStructureV5, TopologyV5, TrafficV5,
};
use crate::CountryGroup;
use nym_sphinx_addressing::Recipient;
use nym_sphinx_params::{PacketSize, PacketType};
use serde::{Deserialize, Serialize};
use std::time::Duration;
use url::Url;
@@ -56,27 +53,39 @@ const DEFAULT_MAXIMUM_REPLY_SURB_AGE: Duration = Duration::from_secs(12 * 60 * 6
// 24 hours
const DEFAULT_MAXIMUM_REPLY_KEY_AGE: Duration = Duration::from_secs(24 * 60 * 60);
// aliases for backwards compatibility
pub type ConfigV1_1_30 = ConfigV4;
pub type ClientV1_1_30 = ClientV4;
pub type DebugConfigV1_1_30 = DebugConfigV4;
pub type TrafficV1_1_30 = TrafficV4;
pub type CoverTrafficV1_1_30 = CoverTrafficV4;
pub type GatewayConnectionV1_1_30 = GatewayConnectionV4;
pub type AcknowledgementsV1_1_30 = AcknowledgementsV4;
pub type TopologyV1_1_30 = TopologyV4;
pub type ReplySurbsV1_1_30 = ReplySurbsV4;
#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct ConfigV1_1_30 {
pub client: ClientV1_1_30,
pub struct ConfigV4 {
pub client: ClientV4,
#[serde(default)]
pub debug: DebugConfigV1_1_30,
pub debug: DebugConfigV4,
}
impl From<ConfigV1_1_30> for ConfigV1_1_33 {
fn from(value: ConfigV1_1_30) -> Self {
ConfigV1_1_33 {
client: ClientV1_1_33 {
impl From<ConfigV4> for ConfigV5 {
fn from(value: ConfigV4) -> Self {
ConfigV5 {
client: ClientV5 {
version: value.client.version,
id: value.client.id,
disabled_credentials_mode: value.client.disabled_credentials_mode,
nyxd_urls: value.client.nyxd_urls,
nym_api_urls: value.client.nym_api_urls,
},
debug: DebugConfigV1_1_33 {
traffic: TrafficV1_1_33 {
debug: DebugConfigV5 {
traffic: TrafficV5 {
average_packet_delay: value.debug.traffic.average_packet_delay,
message_sending_average_delay: value
.debug
@@ -90,7 +99,7 @@ impl From<ConfigV1_1_30> for ConfigV1_1_33 {
secondary_packet_size: value.debug.traffic.secondary_packet_size,
packet_type: value.debug.traffic.packet_type,
},
cover_traffic: CoverTrafficV1_1_33 {
cover_traffic: CoverTrafficV5 {
loop_cover_traffic_average_delay: value
.debug
.cover_traffic
@@ -104,18 +113,18 @@ impl From<ConfigV1_1_30> for ConfigV1_1_33 {
.cover_traffic
.disable_loop_cover_traffic_stream,
},
gateway_connection: GatewayConnectionV1_1_33 {
gateway_connection: GatewayConnectionV5 {
gateway_response_timeout: value
.debug
.gateway_connection
.gateway_response_timeout,
},
acknowledgements: AcknowledgementsV1_1_33 {
acknowledgements: AcknowledgementsV5 {
average_ack_delay: value.debug.acknowledgements.average_ack_delay,
ack_wait_multiplier: value.debug.acknowledgements.ack_wait_multiplier,
ack_wait_addition: value.debug.acknowledgements.ack_wait_addition,
},
topology: TopologyV1_1_33 {
topology: TopologyV5 {
topology_refresh_rate: value.debug.topology.topology_refresh_rate,
topology_resolution_timeout: value.debug.topology.topology_resolution_timeout,
disable_refreshing: value.debug.topology.disable_refreshing,
@@ -125,7 +134,7 @@ impl From<ConfigV1_1_30> for ConfigV1_1_33 {
.max_startup_gateway_waiting_period,
topology_structure: value.debug.topology.topology_structure.into(),
},
reply_surbs: ReplySurbsV1_1_33 {
reply_surbs: ReplySurbsV5 {
minimum_reply_surb_storage_threshold: value
.debug
.reply_surbs
@@ -169,7 +178,7 @@ impl From<ConfigV1_1_30> for ConfigV1_1_33 {
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
// note: the deny_unknown_fields is VITAL here to allow upgrades from v1.1.20_2
#[serde(deny_unknown_fields)]
pub struct ClientV1_1_30 {
pub struct ClientV4 {
/// Version of the client for which this configuration was created.
pub version: String,
@@ -193,7 +202,7 @@ pub struct ClientV1_1_30 {
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct TrafficV1_1_30 {
pub struct TrafficV4 {
/// The parameter of Poisson distribution determining how long, on average,
/// sent packet is going to be delayed at any given mix node.
/// So for a packet going through three mix nodes, on average, it will take three times this value
@@ -224,9 +233,9 @@ pub struct TrafficV1_1_30 {
pub packet_type: PacketType,
}
impl Default for TrafficV1_1_30 {
impl Default for TrafficV4 {
fn default() -> Self {
TrafficV1_1_30 {
TrafficV4 {
average_packet_delay: DEFAULT_AVERAGE_PACKET_DELAY,
message_sending_average_delay: DEFAULT_MESSAGE_STREAM_AVERAGE_DELAY,
disable_main_poisson_packet_distribution: false,
@@ -239,7 +248,7 @@ impl Default for TrafficV1_1_30 {
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct CoverTrafficV1_1_30 {
pub struct CoverTrafficV4 {
/// The parameter of Poisson distribution determining how long, on average,
/// it is going to take for another loop cover traffic message to be sent.
#[serde(with = "humantime_serde")]
@@ -254,9 +263,9 @@ pub struct CoverTrafficV1_1_30 {
pub disable_loop_cover_traffic_stream: bool,
}
impl Default for CoverTrafficV1_1_30 {
impl Default for CoverTrafficV4 {
fn default() -> Self {
CoverTrafficV1_1_30 {
CoverTrafficV4 {
loop_cover_traffic_average_delay: DEFAULT_LOOP_COVER_STREAM_AVERAGE_DELAY,
cover_traffic_primary_size_ratio: DEFAULT_COVER_TRAFFIC_PRIMARY_SIZE_RATIO,
disable_loop_cover_traffic_stream: false,
@@ -266,16 +275,16 @@ impl Default for CoverTrafficV1_1_30 {
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct GatewayConnectionV1_1_30 {
pub struct GatewayConnectionV4 {
/// How long we're willing to wait for a response to a message sent to the gateway,
/// before giving up on it.
#[serde(with = "humantime_serde")]
pub gateway_response_timeout: Duration,
}
impl Default for GatewayConnectionV1_1_30 {
impl Default for GatewayConnectionV4 {
fn default() -> Self {
GatewayConnectionV1_1_30 {
GatewayConnectionV4 {
gateway_response_timeout: DEFAULT_GATEWAY_RESPONSE_TIMEOUT,
}
}
@@ -283,7 +292,7 @@ impl Default for GatewayConnectionV1_1_30 {
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct AcknowledgementsV1_1_30 {
pub struct AcknowledgementsV4 {
/// The parameter of Poisson distribution determining how long, on average,
/// sent acknowledgement is going to be delayed at any given mix node.
/// So for an ack going through three mix nodes, on average, it will take three times this value
@@ -303,9 +312,9 @@ pub struct AcknowledgementsV1_1_30 {
pub ack_wait_addition: Duration,
}
impl Default for AcknowledgementsV1_1_30 {
impl Default for AcknowledgementsV4 {
fn default() -> Self {
AcknowledgementsV1_1_30 {
AcknowledgementsV4 {
average_ack_delay: DEFAULT_AVERAGE_PACKET_DELAY,
ack_wait_multiplier: DEFAULT_ACK_WAIT_MULTIPLIER,
ack_wait_addition: DEFAULT_ACK_WAIT_ADDITION,
@@ -315,7 +324,7 @@ impl Default for AcknowledgementsV1_1_30 {
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct TopologyV1_1_30 {
pub struct TopologyV4 {
/// The uniform delay every which clients are querying the directory server
/// to try to obtain a compatible network topology to send sphinx packets through.
#[serde(with = "humantime_serde")]
@@ -338,23 +347,23 @@ pub struct TopologyV1_1_30 {
pub max_startup_gateway_waiting_period: Duration,
/// Specifies the mixnode topology to be used for sending packets.
pub topology_structure: TopologyStructureV1_1_30,
pub topology_structure: TopologyStructureV4,
}
#[allow(clippy::large_enum_variant)]
#[derive(Default, Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
pub enum TopologyStructureV1_1_30 {
pub enum TopologyStructureV4 {
#[default]
NymApi,
GeoAware(GroupByV1_1_30),
GeoAware(GroupByV4),
}
impl From<TopologyStructureV1_1_30> for TopologyStructureV1_1_33 {
fn from(value: TopologyStructureV1_1_30) -> Self {
impl From<TopologyStructureV4> for TopologyStructureV5 {
fn from(value: TopologyStructureV4) -> Self {
match value {
TopologyStructureV1_1_30::NymApi => TopologyStructureV1_1_33::NymApi,
TopologyStructureV1_1_30::GeoAware(group_by) => {
TopologyStructureV1_1_33::GeoAware(group_by.into())
TopologyStructureV4::NymApi => TopologyStructureV5::NymApi,
TopologyStructureV4::GeoAware(group_by) => {
TopologyStructureV5::GeoAware(group_by.into())
}
}
}
@@ -362,44 +371,44 @@ impl From<TopologyStructureV1_1_30> for TopologyStructureV1_1_33 {
#[allow(clippy::large_enum_variant)]
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
pub enum GroupByV1_1_30 {
pub enum GroupByV4 {
CountryGroup(CountryGroup),
NymAddress(Recipient),
}
impl From<GroupByV1_1_30> for GroupByV1_1_33 {
fn from(value: GroupByV1_1_30) -> Self {
impl From<GroupByV4> for GroupByV5 {
fn from(value: GroupByV4) -> Self {
match value {
GroupByV1_1_30::CountryGroup(country) => GroupByV1_1_33::CountryGroup(country),
GroupByV1_1_30::NymAddress(addr) => GroupByV1_1_33::NymAddress(addr),
GroupByV4::CountryGroup(country) => GroupByV5::CountryGroup(country),
GroupByV4::NymAddress(addr) => GroupByV5::NymAddress(addr),
}
}
}
impl std::fmt::Display for GroupByV1_1_30 {
impl std::fmt::Display for GroupByV4 {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
GroupByV1_1_30::CountryGroup(group) => write!(f, "group: {}", group),
GroupByV1_1_30::NymAddress(address) => write!(f, "address: {}", address),
GroupByV4::CountryGroup(group) => write!(f, "group: {}", group),
GroupByV4::NymAddress(address) => write!(f, "address: {}", address),
}
}
}
impl Default for TopologyV1_1_30 {
impl Default for TopologyV4 {
fn default() -> Self {
TopologyV1_1_30 {
TopologyV4 {
topology_refresh_rate: DEFAULT_TOPOLOGY_REFRESH_RATE,
topology_resolution_timeout: DEFAULT_TOPOLOGY_RESOLUTION_TIMEOUT,
disable_refreshing: false,
max_startup_gateway_waiting_period: DEFAULT_MAX_STARTUP_GATEWAY_WAITING_PERIOD,
topology_structure: TopologyStructureV1_1_30::default(),
topology_structure: TopologyStructureV4::default(),
}
}
}
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct ReplySurbsV1_1_30 {
pub struct ReplySurbsV4 {
/// Defines the minimum number of reply surbs the client wants to keep in its storage at all times.
/// It can only allow to go below that value if its to request additional reply surbs.
pub minimum_reply_surb_storage_threshold: usize,
@@ -437,9 +446,9 @@ pub struct ReplySurbsV1_1_30 {
pub maximum_reply_key_age: Duration,
}
impl Default for ReplySurbsV1_1_30 {
impl Default for ReplySurbsV4 {
fn default() -> Self {
ReplySurbsV1_1_30 {
ReplySurbsV4 {
minimum_reply_surb_storage_threshold: DEFAULT_MINIMUM_REPLY_SURB_STORAGE_THRESHOLD,
maximum_reply_surb_storage_threshold: DEFAULT_MAXIMUM_REPLY_SURB_STORAGE_THRESHOLD,
minimum_reply_surb_request_size: DEFAULT_MINIMUM_REPLY_SURB_REQUEST_SIZE,
@@ -456,22 +465,22 @@ impl Default for ReplySurbsV1_1_30 {
#[derive(Debug, Default, Clone, Copy, Deserialize, PartialEq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct DebugConfigV1_1_30 {
pub struct DebugConfigV4 {
/// Defines all configuration options related to traffic streams.
pub traffic: TrafficV1_1_30,
pub traffic: TrafficV4,
/// Defines all configuration options related to cover traffic stream(s).
pub cover_traffic: CoverTrafficV1_1_30,
pub cover_traffic: CoverTrafficV4,
/// Defines all configuration options related to the gateway connection.
pub gateway_connection: GatewayConnectionV1_1_30,
pub gateway_connection: GatewayConnectionV4,
/// Defines all configuration options related to acknowledgements, such as delays or wait timeouts.
pub acknowledgements: AcknowledgementsV1_1_30,
pub acknowledgements: AcknowledgementsV4,
/// Defines all configuration options related topology, such as refresh rates or timeouts.
pub topology: TopologyV1_1_30,
pub topology: TopologyV4,
/// Defines all configuration options related to reply SURBs.
pub reply_surbs: ReplySurbsV1_1_30,
pub reply_surbs: ReplySurbsV4,
}
@@ -1,15 +1,12 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::client::topology_control::geo_aware_provider::CountryGroup;
use crate::config::{
Acknowledgements, Client, Config, CoverTraffic, DebugConfig, GatewayConnection, GroupBy,
ReplySurbs, Topology, TopologyStructure, Traffic,
};
use nym_sphinx::{
addressing::clients::Recipient,
params::{PacketSize, PacketType},
use crate::{
Acknowledgements, Client, Config, CountryGroup, CoverTraffic, DebugConfig, GatewayConnection,
GroupBy, ReplySurbs, Topology, TopologyStructure, Traffic,
};
use nym_sphinx_addressing::Recipient;
use nym_sphinx_params::{PacketSize, PacketType};
use serde::{Deserialize, Serialize};
use std::time::Duration;
use url::Url;
@@ -55,8 +52,21 @@ const DEFAULT_MAXIMUM_REPLY_SURB_AGE: Duration = Duration::from_secs(12 * 60 * 6
// 24 hours
const DEFAULT_MAXIMUM_REPLY_KEY_AGE: Duration = Duration::from_secs(24 * 60 * 60);
// aliases for backwards compatibility
pub type ConfigV1_1_33 = ConfigV5;
pub type ClientV1_1_33 = ClientV5;
pub type DebugConfigV1_1_33 = DebugConfigV5;
pub type OldGatewayEndpointConfigV1_1_33 = GatewayEndpointConfigV5;
pub type TrafficV1_1_33 = TrafficV5;
pub type CoverTrafficV1_1_33 = CoverTrafficV5;
pub type GatewayConnectionV1_1_33 = GatewayConnectionV5;
pub type AcknowledgementsV1_1_33 = AcknowledgementsV5;
pub type TopologyV1_1_33 = TopologyV5;
pub type ReplySurbsV1_1_33 = ReplySurbsV5;
#[derive(Clone, Debug, Default, Deserialize, PartialEq, Eq, Serialize)]
pub struct OldGatewayEndpointConfigV1_1_33 {
pub struct GatewayEndpointConfigV5 {
/// gateway_id specifies ID of the gateway to which the client should send messages.
/// If initially omitted, a random gateway will be chosen from the available topology.
pub gateway_id: String,
@@ -70,15 +80,15 @@ pub struct OldGatewayEndpointConfigV1_1_33 {
#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct ConfigV1_1_33 {
pub client: ClientV1_1_33,
pub struct ConfigV5 {
pub client: ClientV5,
#[serde(default)]
pub debug: DebugConfigV1_1_33,
pub debug: DebugConfigV5,
}
impl From<ConfigV1_1_33> for Config {
fn from(value: ConfigV1_1_33) -> Self {
impl From<ConfigV5> for Config {
fn from(value: ConfigV5) -> Self {
Config {
client: Client {
version: value.client.version,
@@ -178,7 +188,7 @@ impl From<ConfigV1_1_33> for Config {
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
// note: the deny_unknown_fields is VITAL here to allow upgrades from v1.1.20_2
#[serde(deny_unknown_fields)]
pub struct ClientV1_1_33 {
pub struct ClientV5 {
/// Version of the client for which this configuration was created.
pub version: String,
@@ -202,7 +212,7 @@ pub struct ClientV1_1_33 {
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct TrafficV1_1_33 {
pub struct TrafficV5 {
/// The parameter of Poisson distribution determining how long, on average,
/// sent packet is going to be delayed at any given mix node.
/// So for a packet going through three mix nodes, on average, it will take three times this value
@@ -233,9 +243,9 @@ pub struct TrafficV1_1_33 {
pub packet_type: PacketType,
}
impl Default for TrafficV1_1_33 {
impl Default for TrafficV5 {
fn default() -> Self {
TrafficV1_1_33 {
TrafficV5 {
average_packet_delay: DEFAULT_AVERAGE_PACKET_DELAY,
message_sending_average_delay: DEFAULT_MESSAGE_STREAM_AVERAGE_DELAY,
disable_main_poisson_packet_distribution: false,
@@ -248,7 +258,7 @@ impl Default for TrafficV1_1_33 {
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct CoverTrafficV1_1_33 {
pub struct CoverTrafficV5 {
/// The parameter of Poisson distribution determining how long, on average,
/// it is going to take for another loop cover traffic message to be sent.
#[serde(with = "humantime_serde")]
@@ -263,9 +273,9 @@ pub struct CoverTrafficV1_1_33 {
pub disable_loop_cover_traffic_stream: bool,
}
impl Default for CoverTrafficV1_1_33 {
impl Default for CoverTrafficV5 {
fn default() -> Self {
CoverTrafficV1_1_33 {
CoverTrafficV5 {
loop_cover_traffic_average_delay: DEFAULT_LOOP_COVER_STREAM_AVERAGE_DELAY,
cover_traffic_primary_size_ratio: DEFAULT_COVER_TRAFFIC_PRIMARY_SIZE_RATIO,
disable_loop_cover_traffic_stream: false,
@@ -275,16 +285,16 @@ impl Default for CoverTrafficV1_1_33 {
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct GatewayConnectionV1_1_33 {
pub struct GatewayConnectionV5 {
/// How long we're willing to wait for a response to a message sent to the gateway,
/// before giving up on it.
#[serde(with = "humantime_serde")]
pub gateway_response_timeout: Duration,
}
impl Default for GatewayConnectionV1_1_33 {
impl Default for GatewayConnectionV5 {
fn default() -> Self {
GatewayConnectionV1_1_33 {
GatewayConnectionV5 {
gateway_response_timeout: DEFAULT_GATEWAY_RESPONSE_TIMEOUT,
}
}
@@ -292,7 +302,7 @@ impl Default for GatewayConnectionV1_1_33 {
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct AcknowledgementsV1_1_33 {
pub struct AcknowledgementsV5 {
/// The parameter of Poisson distribution determining how long, on average,
/// sent acknowledgement is going to be delayed at any given mix node.
/// So for an ack going through three mix nodes, on average, it will take three times this value
@@ -312,9 +322,9 @@ pub struct AcknowledgementsV1_1_33 {
pub ack_wait_addition: Duration,
}
impl Default for AcknowledgementsV1_1_33 {
impl Default for AcknowledgementsV5 {
fn default() -> Self {
AcknowledgementsV1_1_33 {
AcknowledgementsV5 {
average_ack_delay: DEFAULT_AVERAGE_PACKET_DELAY,
ack_wait_multiplier: DEFAULT_ACK_WAIT_MULTIPLIER,
ack_wait_addition: DEFAULT_ACK_WAIT_ADDITION,
@@ -324,7 +334,7 @@ impl Default for AcknowledgementsV1_1_33 {
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct TopologyV1_1_33 {
pub struct TopologyV5 {
/// The uniform delay every which clients are querying the directory server
/// to try to obtain a compatible network topology to send sphinx packets through.
#[serde(with = "humantime_serde")]
@@ -347,68 +357,66 @@ pub struct TopologyV1_1_33 {
pub max_startup_gateway_waiting_period: Duration,
/// Specifies the mixnode topology to be used for sending packets.
pub topology_structure: TopologyStructureV1_1_33,
pub topology_structure: TopologyStructureV5,
}
#[allow(clippy::large_enum_variant)]
#[derive(Default, Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
pub enum TopologyStructureV1_1_33 {
pub enum TopologyStructureV5 {
#[default]
NymApi,
GeoAware(GroupByV1_1_33),
GeoAware(GroupByV5),
}
impl From<TopologyStructureV1_1_33> for TopologyStructure {
fn from(value: TopologyStructureV1_1_33) -> Self {
impl From<TopologyStructureV5> for TopologyStructure {
fn from(value: TopologyStructureV5) -> Self {
match value {
TopologyStructureV1_1_33::NymApi => TopologyStructure::NymApi,
TopologyStructureV1_1_33::GeoAware(group_by) => {
TopologyStructure::GeoAware(group_by.into())
}
TopologyStructureV5::NymApi => TopologyStructure::NymApi,
TopologyStructureV5::GeoAware(group_by) => TopologyStructure::GeoAware(group_by.into()),
}
}
}
#[allow(clippy::large_enum_variant)]
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
pub enum GroupByV1_1_33 {
pub enum GroupByV5 {
CountryGroup(CountryGroup),
NymAddress(Recipient),
}
impl From<GroupByV1_1_33> for GroupBy {
fn from(value: GroupByV1_1_33) -> Self {
impl From<GroupByV5> for GroupBy {
fn from(value: GroupByV5) -> Self {
match value {
GroupByV1_1_33::CountryGroup(country) => GroupBy::CountryGroup(country),
GroupByV1_1_33::NymAddress(addr) => GroupBy::NymAddress(addr),
GroupByV5::CountryGroup(country) => GroupBy::CountryGroup(country),
GroupByV5::NymAddress(addr) => GroupBy::NymAddress(addr),
}
}
}
impl std::fmt::Display for GroupByV1_1_33 {
impl std::fmt::Display for GroupByV5 {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
GroupByV1_1_33::CountryGroup(group) => write!(f, "group: {}", group),
GroupByV1_1_33::NymAddress(address) => write!(f, "address: {}", address),
GroupByV5::CountryGroup(group) => write!(f, "group: {}", group),
GroupByV5::NymAddress(address) => write!(f, "address: {}", address),
}
}
}
impl Default for TopologyV1_1_33 {
impl Default for TopologyV5 {
fn default() -> Self {
TopologyV1_1_33 {
TopologyV5 {
topology_refresh_rate: DEFAULT_TOPOLOGY_REFRESH_RATE,
topology_resolution_timeout: DEFAULT_TOPOLOGY_RESOLUTION_TIMEOUT,
disable_refreshing: false,
max_startup_gateway_waiting_period: DEFAULT_MAX_STARTUP_GATEWAY_WAITING_PERIOD,
topology_structure: TopologyStructureV1_1_33::default(),
topology_structure: TopologyStructureV5::default(),
}
}
}
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct ReplySurbsV1_1_33 {
pub struct ReplySurbsV5 {
/// Defines the minimum number of reply surbs the client wants to keep in its storage at all times.
/// It can only allow to go below that value if its to request additional reply surbs.
pub minimum_reply_surb_storage_threshold: usize,
@@ -450,9 +458,9 @@ pub struct ReplySurbsV1_1_33 {
pub surb_mix_hops: Option<u8>,
}
impl Default for ReplySurbsV1_1_33 {
impl Default for ReplySurbsV5 {
fn default() -> Self {
ReplySurbsV1_1_33 {
ReplySurbsV5 {
minimum_reply_surb_storage_threshold: DEFAULT_MINIMUM_REPLY_SURB_STORAGE_THRESHOLD,
maximum_reply_surb_storage_threshold: DEFAULT_MAXIMUM_REPLY_SURB_STORAGE_THRESHOLD,
minimum_reply_surb_request_size: DEFAULT_MINIMUM_REPLY_SURB_REQUEST_SIZE,
@@ -470,22 +478,22 @@ impl Default for ReplySurbsV1_1_33 {
#[derive(Debug, Default, Clone, Copy, Deserialize, PartialEq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct DebugConfigV1_1_33 {
pub struct DebugConfigV5 {
/// Defines all configuration options related to traffic streams.
pub traffic: TrafficV1_1_33,
pub traffic: TrafficV5,
/// Defines all configuration options related to cover traffic stream(s).
pub cover_traffic: CoverTrafficV1_1_33,
pub cover_traffic: CoverTrafficV5,
/// Defines all configuration options related to the gateway connection.
pub gateway_connection: GatewayConnectionV1_1_33,
pub gateway_connection: GatewayConnectionV5,
/// Defines all configuration options related to acknowledgements, such as delays or wait timeouts.
pub acknowledgements: AcknowledgementsV1_1_33,
pub acknowledgements: AcknowledgementsV5,
/// Defines all configuration options related topology, such as refresh rates or timeouts.
pub topology: TopologyV1_1_33,
pub topology: TopologyV5,
/// Defines all configuration options related to reply SURBs.
pub reply_surbs: ReplySurbsV1_1_33,
pub reply_surbs: ReplySurbsV5,
}
@@ -27,6 +27,12 @@ pub struct GatewayRegistration {
pub registration_timestamp: OffsetDateTime,
}
impl GatewayRegistration {
pub fn gateway_id(&self) -> identity::PublicKey {
self.details.gateway_id()
}
}
impl<'a> From<&'a GatewayRegistration> for RawRegisteredGateway {
fn from(value: &'a GatewayRegistration) -> Self {
RawRegisteredGateway {
@@ -298,3 +304,12 @@ pub struct CustomGatewayDetails {
pub gateway_id: identity::PublicKey,
pub data: Option<Vec<u8>>,
}
impl CustomGatewayDetails {
pub fn new(gateway_id: identity::PublicKey) -> CustomGatewayDetails {
Self {
gateway_id,
data: None,
}
}
}
@@ -39,7 +39,7 @@ use log::{debug, error, info, warn};
use nym_bandwidth_controller::BandwidthController;
use nym_client_core_gateways_storage::{GatewayDetails, GatewaysDetailsStore};
use nym_credential_storage::storage::Storage as CredentialStorage;
use nym_crypto::asymmetric::encryption;
use nym_crypto::asymmetric::{encryption, identity};
use nym_gateway_client::{
AcknowledgementReceiver, GatewayClient, GatewayConfig, MixnetMessageReceiver, PacketRouter,
};
@@ -670,6 +670,7 @@ where
let self_address = Self::mix_address(&init_res);
let ack_key = init_res.client_keys.ack_key();
let encryption_keys = init_res.client_keys.encryption_keypair();
let identity_keys = init_res.client_keys.identity_keypair();
// the components are started in very specific order. Unless you know what you are doing,
// do not change that.
@@ -792,6 +793,7 @@ where
Ok(BaseClient {
address: self_address,
identity_keys,
client_input: ClientInputStatus::AwaitingProducer {
client_input: ClientInput {
connection_command_sender: client_connection_tx,
@@ -816,6 +818,7 @@ where
pub struct BaseClient {
pub address: Recipient,
pub identity_keys: Arc<identity::KeyPair>,
pub client_input: ClientInputStatus,
pub client_output: ClientOutputStatus,
pub client_state: ClientState,
@@ -7,7 +7,7 @@ use std::error::Error;
use tokio::sync::Mutex;
#[cfg(not(target_arch = "wasm32"))]
use crate::config::disk_persistence::keys_paths::ClientKeysPaths;
use crate::config::disk_persistence::ClientKeysPaths;
#[cfg(not(target_arch = "wasm32"))]
use nym_crypto::asymmetric::{encryption, identity};
#[cfg(not(target_arch = "wasm32"))]
@@ -7,6 +7,8 @@ use nym_metrics::{inc, inc_by};
use si_scale::helpers::bibytes2;
// Metrics server
use futures::future::{FusedFuture, OptionFuture};
use futures::FutureExt;
#[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))]
use http_body_util::Full;
#[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))]
@@ -535,6 +537,14 @@ impl PacketStatisticsControl {
}
loop {
// it seems at some point tokio changed its select precondition evaluation,
// and it's no longer checked before the future is evaluated.
let accept_future: OptionFuture<_> = listener
.as_ref()
.map(|l| l.accept())
.map(FutureExt::fuse)
.into();
tokio::select! {
stats_event = self.stats_rx.recv() => match stats_event {
Some(stats_event) => {
@@ -548,10 +558,10 @@ impl PacketStatisticsControl {
},
// conditional will disable the branch if we're in wasm32-unknown-unknown
// use `_` to calm down clippy when running for wasm
_result = listener.as_ref().unwrap().accept(), if listener.is_some() => {
_result = accept_future, if !accept_future.is_terminated() => {
cfg_if::cfg_if! {
if #[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))] {
if let Ok((stream, _)) = _result {
if let Some(Ok((stream, _))) = _result {
let io = TokioIo::new(stream);
tokio::task::spawn(async move {
@@ -1,6 +1,5 @@
use std::{collections::HashMap, fmt};
use log::{debug, error, info};
use crate::config::GroupBy;
use log::{debug, error};
use nym_explorer_client::{ExplorerClient, PrettyDetailedMixNodeBond};
use nym_network_defaults::var_names::EXPLORER_API;
use nym_topology::{
@@ -10,11 +9,11 @@ use nym_topology::{
};
use nym_validator_client::client::MixId;
use rand::{prelude::SliceRandom, thread_rng};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use tap::TapOptional;
use url::Url;
use crate::config::GroupBy;
pub use nym_country_group::CountryGroup;
const MIN_NODES_PER_LAYER: usize = 1;
@@ -38,158 +37,6 @@ fn create_explorer_client() -> Option<ExplorerClient> {
Some(client)
}
#[derive(Copy, Clone, Hash, PartialEq, Eq, Serialize, Deserialize, Debug)]
pub enum CountryGroup {
Europe,
NorthAmerica,
SouthAmerica,
Oceania,
Asia,
Africa,
Unknown,
}
impl CountryGroup {
// We map contry codes into group, which initially are continent codes to a first approximation,
// but we do it manually to reserve the right to tweak this distribution for our purposes.
// NOTE: I did this quickly and it's not a complete list of all countries, but only those that
// were present in the network at the time. Please add more as needed.
fn new(country_code: &str) -> Self {
let country_code = country_code.to_uppercase();
use CountryGroup::*;
match country_code.as_ref() {
// Europe
"AT" => Europe,
"BG" => Europe,
"CH" => Europe,
"CY" => Europe,
"CZ" => Europe,
"DE" => Europe,
"DK" => Europe,
"ES" => Europe,
"FI" => Europe,
"FR" => Europe,
"GB" => Europe,
"GR" => Europe,
"IE" => Europe,
"IT" => Europe,
"LT" => Europe,
"LU" => Europe,
"LV" => Europe,
"MD" => Europe,
"MT" => Europe,
"NL" => Europe,
"NO" => Europe,
"PL" => Europe,
"RO" => Europe,
"SE" => Europe,
"SK" => Europe,
"TR" => Europe,
"UA" => Europe,
// North America
"CA" => NorthAmerica,
"MX" => NorthAmerica,
"US" => NorthAmerica,
// South America
"AR" => SouthAmerica,
"BR" => SouthAmerica,
"CL" => SouthAmerica,
"CO" => SouthAmerica,
"CR" => SouthAmerica,
"GT" => SouthAmerica,
// Oceania
"AU" => Oceania,
// Asia
"AM" => Asia,
"BH" => Asia,
"CN" => Asia,
"GE" => Asia,
"HK" => Asia,
"ID" => Asia,
"IL" => Asia,
"IN" => Asia,
"JP" => Asia,
"KH" => Asia,
"KR" => Asia,
"KZ" => Asia,
"MY" => Asia,
"RU" => Asia,
"SG" => Asia,
"TH" => Asia,
"VN" => Asia,
// Africa
"SC" => Africa,
"UG" => Africa,
"ZA" => Africa,
// And group level codes work too
"EU" => Europe,
"NA" => NorthAmerica,
"SA" => SouthAmerica,
"OC" => Oceania,
"AS" => Asia,
"AF" => Africa,
// And some aliases
"EUROPE" => Europe,
"NORTHAMERICA" => NorthAmerica,
"SOUTHAMERICA" => SouthAmerica,
"OCEANIA" => Oceania,
"ASIA" => Asia,
"AFRICA" => Africa,
_ => {
info!("Unknown country code: {}", country_code);
Unknown
}
}
}
}
impl fmt::Display for CountryGroup {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use CountryGroup::*;
match self {
Europe => write!(f, "EU"),
NorthAmerica => write!(f, "NA"),
SouthAmerica => write!(f, "SA"),
Oceania => write!(f, "OC"),
Asia => write!(f, "AS"),
Africa => write!(f, "AF"),
Unknown => write!(f, "Unknown"),
}
}
}
impl std::str::FromStr for CountryGroup {
type Err = ();
fn from_str(s: &str) -> Result<Self, Self::Err> {
let group = CountryGroup::new(s);
if group == CountryGroup::Unknown {
Err(())
} else {
Ok(group)
}
}
}
impl CountryGroup {
#[allow(unused)]
fn known(self) -> Option<CountryGroup> {
use CountryGroup::*;
match self {
Europe | NorthAmerica | SouthAmerica | Oceania | Asia | Africa => Some(self),
Unknown => None,
}
}
}
fn group_mixnodes_by_country_code(
mixnodes: Vec<PrettyDetailedMixNodeBond>,
) -> HashMap<CountryGroup, Vec<MixId>> {
@@ -1,43 +0,0 @@
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::config::disk_persistence::keys_paths::ClientKeysPaths;
use serde::{Deserialize, Serialize};
use std::path::{Path, PathBuf};
pub mod keys_paths;
pub mod old_v1_1_20_2;
pub mod old_v1_1_33;
pub const DEFAULT_REPLY_SURB_DB_FILENAME: &str = "persistent_reply_store.sqlite";
pub const DEFAULT_CREDENTIALS_DB_FILENAME: &str = "credentials_database.db";
pub const DEFAULT_GATEWAYS_DETAILS_DB_FILENAME: &str = "gateways_registrations.sqlite";
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct CommonClientPaths {
pub keys: ClientKeysPaths,
/// Path to the file containing information about gateways used by this client,
/// i.e. details such as their public keys, owner addresses or the network information.
pub gateway_registrations: PathBuf,
/// Path to the database containing bandwidth credentials of this client.
pub credentials_database: PathBuf,
/// Path to the persistent store for received reply surbs, unused encryption keys and used sender tags.
pub reply_surb_database: PathBuf,
}
impl CommonClientPaths {
pub fn new_base<P: AsRef<Path>>(base_data_directory: P) -> Self {
let base_dir = base_data_directory.as_ref();
CommonClientPaths {
credentials_database: base_dir.join(DEFAULT_CREDENTIALS_DB_FILENAME),
reply_surb_database: base_dir.join(DEFAULT_REPLY_SURB_DB_FILENAME),
gateway_registrations: base_dir.join(DEFAULT_GATEWAYS_DETAILS_DB_FILENAME),
keys: ClientKeysPaths::new_base(base_data_directory),
}
}
}
@@ -1,33 +0,0 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::config::disk_persistence::old_v1_1_33::{
ClientKeysPathsV1_1_33, CommonClientPathsV1_1_33, DEFAULT_GATEWAY_DETAILS_FILENAME,
};
use crate::error::ClientCoreError;
use serde::{Deserialize, Serialize};
use std::path::PathBuf;
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct CommonClientPathsV1_1_20_2 {
pub keys: ClientKeysPathsV1_1_33,
pub credentials_database: PathBuf,
pub reply_surb_database: PathBuf,
}
impl CommonClientPathsV1_1_20_2 {
pub fn upgrade_default(self) -> Result<CommonClientPathsV1_1_33, ClientCoreError> {
let data_dir = self.reply_surb_database.parent().ok_or_else(|| {
ClientCoreError::ConfigFileUpgradeFailure {
current_version: "1.1.20-2".to_string(),
}
})?;
Ok(CommonClientPathsV1_1_33 {
keys: self.keys,
gateway_details: data_dir.join(DEFAULT_GATEWAY_DETAILS_FILENAME),
credentials_database: self.credentials_database,
reply_surb_database: self.reply_surb_database,
})
}
}
+6 -599
View File
@@ -1,602 +1,9 @@
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2021-2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::client::topology_control::geo_aware_provider::CountryGroup;
use nym_config::defaults::NymNetworkDetails;
use nym_sphinx::{
addressing::clients::Recipient,
params::{PacketSize, PacketType},
pub use nym_client_core_config_types::disk_persistence;
pub use nym_client_core_config_types::old::{
old_config_v1_1_13, old_config_v1_1_20, old_config_v1_1_20_2, old_config_v1_1_30,
old_config_v1_1_33,
};
use serde::{Deserialize, Serialize};
use std::time::Duration;
use url::Url;
pub mod disk_persistence;
pub mod old_config_v1_1_13;
pub mod old_config_v1_1_20;
pub mod old_config_v1_1_20_2;
pub mod old_config_v1_1_30;
pub mod old_config_v1_1_33;
// 'DEBUG'
const DEFAULT_ACK_WAIT_MULTIPLIER: f64 = 1.5;
const DEFAULT_ACK_WAIT_ADDITION: Duration = Duration::from_millis(1_500);
const DEFAULT_LOOP_COVER_STREAM_AVERAGE_DELAY: Duration = Duration::from_millis(200);
const DEFAULT_MESSAGE_STREAM_AVERAGE_DELAY: Duration = Duration::from_millis(20);
const DEFAULT_AVERAGE_PACKET_DELAY: Duration = Duration::from_millis(50);
const DEFAULT_TOPOLOGY_REFRESH_RATE: Duration = Duration::from_secs(5 * 60); // every 5min
const DEFAULT_TOPOLOGY_RESOLUTION_TIMEOUT: Duration = Duration::from_millis(5_000);
const DEFAULT_MAX_STARTUP_GATEWAY_WAITING_PERIOD: Duration = Duration::from_secs(70 * 60); // 70min -> full epoch (1h) + a bit of overhead
// Set this to a high value for now, so that we don't risk sporadic timeouts that might cause
// bought bandwidth tokens to not have time to be spent; Once we remove the gateway from the
// bandwidth bridging protocol, we can come back to a smaller timeout value
const DEFAULT_GATEWAY_RESPONSE_TIMEOUT: Duration = Duration::from_secs(5 * 60);
const DEFAULT_COVER_TRAFFIC_PRIMARY_SIZE_RATIO: f64 = 0.70;
// reply-surbs related:
// define when to request
// clients/client-core/src/client/replies/reply_storage/surb_storage.rs
const DEFAULT_MINIMUM_REPLY_SURB_STORAGE_THRESHOLD: usize = 10;
const DEFAULT_MAXIMUM_REPLY_SURB_STORAGE_THRESHOLD: usize = 200;
// define how much to request at once
// clients/client-core/src/client/replies/reply_controller.rs
const DEFAULT_MINIMUM_REPLY_SURB_REQUEST_SIZE: u32 = 10;
const DEFAULT_MAXIMUM_REPLY_SURB_REQUEST_SIZE: u32 = 100;
const DEFAULT_MAXIMUM_ALLOWED_SURB_REQUEST_SIZE: u32 = 500;
const DEFAULT_MAXIMUM_REPLY_SURB_REREQUEST_WAITING_PERIOD: Duration = Duration::from_secs(10);
const DEFAULT_MAXIMUM_REPLY_SURB_DROP_WAITING_PERIOD: Duration = Duration::from_secs(5 * 60);
// 12 hours
const DEFAULT_MAXIMUM_REPLY_SURB_AGE: Duration = Duration::from_secs(12 * 60 * 60);
// 24 hours
const DEFAULT_MAXIMUM_REPLY_KEY_AGE: Duration = Duration::from_secs(24 * 60 * 60);
#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct Config {
pub client: Client,
#[serde(default)]
pub debug: DebugConfig,
}
impl Config {
pub fn new<S1, S2>(id: S1, version: S2) -> Self
where
S1: Into<String>,
S2: Into<String>,
{
Config {
client: Client::new_default(id, version),
debug: Default::default(),
}
}
pub fn from_client_config(client: Client, debug: DebugConfig) -> Self {
Config { client, debug }
}
pub fn validate(&self) -> bool {
self.debug.validate()
}
pub fn with_debug_config(mut self, debug: DebugConfig) -> Self {
self.debug = debug;
self
}
pub fn with_disabled_credentials(mut self, disabled_credentials_mode: bool) -> Self {
self.client.disabled_credentials_mode = disabled_credentials_mode;
self
}
pub fn with_custom_nyxd(mut self, urls: Vec<Url>) -> Self {
self.client.nyxd_urls = urls;
self
}
pub fn set_custom_nyxd(&mut self, nyxd_urls: Vec<Url>) {
self.client.nyxd_urls = nyxd_urls;
}
pub fn with_custom_nym_apis(mut self, nym_api_urls: Vec<Url>) -> Self {
self.client.nym_api_urls = nym_api_urls;
self
}
pub fn set_custom_nym_apis(&mut self, nym_api_urls: Vec<Url>) {
self.client.nym_api_urls = nym_api_urls;
}
pub fn with_high_default_traffic_volume(mut self, enabled: bool) -> Self {
if enabled {
self.set_high_default_traffic_volume();
}
self
}
pub fn with_packet_type(mut self, packet_type: PacketType) -> Self {
self.debug.traffic.packet_type = packet_type;
self
}
pub fn set_high_default_traffic_volume(&mut self) {
self.debug.traffic.average_packet_delay = Duration::from_millis(10);
// basically don't really send cover messages
self.debug.cover_traffic.loop_cover_traffic_average_delay =
Duration::from_millis(2_000_000);
// 250 "real" messages / s
self.debug.traffic.message_sending_average_delay = Duration::from_millis(4);
}
pub fn with_disabled_poisson_process(mut self, disabled: bool) -> Self {
if disabled {
self.set_no_poisson_process()
}
self
}
pub fn set_no_poisson_process(&mut self) {
self.debug.traffic.disable_main_poisson_packet_distribution = true;
}
pub fn with_disabled_cover_traffic(mut self, disabled: bool) -> Self {
if disabled {
self.set_no_cover_traffic()
}
self
}
pub fn set_no_cover_traffic(&mut self) {
self.debug.cover_traffic.disable_loop_cover_traffic_stream = true;
self.debug.traffic.disable_main_poisson_packet_distribution = true;
}
pub fn with_disabled_cover_traffic_with_keepalive(mut self, disabled: bool) -> Self {
if disabled {
self.set_no_cover_traffic_with_keepalive()
}
self
}
pub fn set_no_cover_traffic_with_keepalive(&mut self) {
self.debug.traffic.disable_main_poisson_packet_distribution = true;
self.debug.cover_traffic.loop_cover_traffic_average_delay = Duration::from_secs(5);
}
pub fn with_disabled_topology_refresh(mut self, disable_topology_refresh: bool) -> Self {
self.debug.topology.disable_refreshing = disable_topology_refresh;
self
}
pub fn with_topology_structure(mut self, topology_structure: TopologyStructure) -> Self {
self.set_topology_structure(topology_structure);
self
}
pub fn set_topology_structure(&mut self, topology_structure: TopologyStructure) {
self.debug.topology.topology_structure = topology_structure;
}
pub fn with_no_per_hop_delays(mut self, no_per_hop_delays: bool) -> Self {
if no_per_hop_delays {
self.set_no_per_hop_delays()
}
self
}
pub fn set_no_per_hop_delays(&mut self) {
self.debug.traffic.average_packet_delay = Duration::ZERO;
self.debug.acknowledgements.average_ack_delay = Duration::ZERO;
}
pub fn with_secondary_packet_size(mut self, secondary_packet_size: Option<PacketSize>) -> Self {
self.set_secondary_packet_size(secondary_packet_size);
self
}
pub fn set_secondary_packet_size(&mut self, secondary_packet_size: Option<PacketSize>) {
self.debug.traffic.secondary_packet_size = secondary_packet_size;
}
pub fn set_custom_version(&mut self, version: &str) {
self.client.version = version.to_string();
}
pub fn get_id(&self) -> String {
self.client.id.clone()
}
pub fn get_disabled_credentials_mode(&self) -> bool {
self.client.disabled_credentials_mode
}
pub fn get_validator_endpoints(&self) -> Vec<Url> {
self.client.nyxd_urls.clone()
}
pub fn get_nym_api_endpoints(&self) -> Vec<Url> {
self.client.nym_api_urls.clone()
}
}
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
// note: the deny_unknown_fields is VITAL here to allow upgrades from v1.1.20_2
#[serde(deny_unknown_fields)]
pub struct Client {
/// Version of the client for which this configuration was created.
pub version: String,
/// ID specifies the human readable ID of this particular client.
pub id: String,
/// Indicates whether this client is running in a disabled credentials mode, thus attempting
/// to claim bandwidth without presenting bandwidth credentials.
// TODO: this should be moved to `debug.gateway_connection`
#[serde(default)]
pub disabled_credentials_mode: bool,
/// Addresses to nyxd validators via which the client can communicate with the chain.
#[serde(alias = "validator_urls")]
pub nyxd_urls: Vec<Url>,
/// Addresses to APIs running on validator from which the client gets the view of the network.
#[serde(alias = "validator_api_urls")]
pub nym_api_urls: Vec<Url>,
}
impl Client {
pub fn new_default<S1, S2>(id: S1, version: S2) -> Self
where
S1: Into<String>,
S2: Into<String>,
{
let network = NymNetworkDetails::new_mainnet();
let nyxd_urls = network
.endpoints
.iter()
.map(|validator| validator.nyxd_url())
.collect();
let nym_api_urls = network
.endpoints
.iter()
.filter_map(|validator| validator.api_url())
.collect::<Vec<_>>();
Client {
version: version.into(),
id: id.into(),
disabled_credentials_mode: true,
nyxd_urls,
nym_api_urls,
}
}
pub fn new<S: Into<String>>(
id: S,
disabled_credentials_mode: bool,
nyxd_urls: Vec<Url>,
nym_api_urls: Vec<Url>,
) -> Self {
Client {
version: env!("CARGO_PKG_VERSION").to_string(),
id: id.into(),
disabled_credentials_mode,
nyxd_urls,
nym_api_urls,
}
}
}
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct Traffic {
/// The parameter of Poisson distribution determining how long, on average,
/// sent packet is going to be delayed at any given mix node.
/// So for a packet going through three mix nodes, on average, it will take three times this value
/// until the packet reaches its destination.
#[serde(with = "humantime_serde")]
pub average_packet_delay: Duration,
/// The parameter of Poisson distribution determining how long, on average,
/// it is going to take another 'real traffic stream' message to be sent.
/// If no real packets are available and cover traffic is enabled,
/// a loop cover message is sent instead in order to preserve the rate.
#[serde(with = "humantime_serde")]
pub message_sending_average_delay: Duration,
/// Controls whether the main packet stream constantly produces packets according to the predefined
/// poisson distribution.
pub disable_main_poisson_packet_distribution: bool,
/// Specifies the packet size used for sent messages.
/// Do not override it unless you understand the consequences of that change.
pub primary_packet_size: PacketSize,
/// Specifies the optional auxiliary packet size for optimizing message streams.
/// Note that its use decreases overall anonymity.
/// Do not set it it unless you understand the consequences of that change.
pub secondary_packet_size: Option<PacketSize>,
pub packet_type: PacketType,
}
impl Traffic {
pub fn validate(&self) -> bool {
if let Some(secondary_packet_size) = self.secondary_packet_size {
if secondary_packet_size == PacketSize::AckPacket
|| secondary_packet_size == self.primary_packet_size
{
return false;
}
}
true
}
}
impl Default for Traffic {
fn default() -> Self {
Traffic {
average_packet_delay: DEFAULT_AVERAGE_PACKET_DELAY,
message_sending_average_delay: DEFAULT_MESSAGE_STREAM_AVERAGE_DELAY,
disable_main_poisson_packet_distribution: false,
primary_packet_size: PacketSize::RegularPacket,
secondary_packet_size: None,
packet_type: PacketType::Mix,
}
}
}
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct CoverTraffic {
/// The parameter of Poisson distribution determining how long, on average,
/// it is going to take for another loop cover traffic message to be sent.
#[serde(with = "humantime_serde")]
pub loop_cover_traffic_average_delay: Duration,
/// Specifies the ratio of `primary_packet_size` to `secondary_packet_size` used in cover traffic.
/// Only applicable if `secondary_packet_size` is enabled.
pub cover_traffic_primary_size_ratio: f64,
/// Controls whether the dedicated loop cover traffic stream should be enabled.
/// (and sending packets, on average, every [Self::loop_cover_traffic_average_delay])
pub disable_loop_cover_traffic_stream: bool,
}
impl Default for CoverTraffic {
fn default() -> Self {
CoverTraffic {
loop_cover_traffic_average_delay: DEFAULT_LOOP_COVER_STREAM_AVERAGE_DELAY,
cover_traffic_primary_size_ratio: DEFAULT_COVER_TRAFFIC_PRIMARY_SIZE_RATIO,
disable_loop_cover_traffic_stream: false,
}
}
}
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct GatewayConnection {
/// How long we're willing to wait for a response to a message sent to the gateway,
/// before giving up on it.
#[serde(with = "humantime_serde")]
pub gateway_response_timeout: Duration,
}
impl Default for GatewayConnection {
fn default() -> Self {
GatewayConnection {
gateway_response_timeout: DEFAULT_GATEWAY_RESPONSE_TIMEOUT,
}
}
}
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct Acknowledgements {
/// The parameter of Poisson distribution determining how long, on average,
/// sent acknowledgement is going to be delayed at any given mix node.
/// So for an ack going through three mix nodes, on average, it will take three times this value
/// until the packet reaches its destination.
#[serde(with = "humantime_serde")]
pub average_ack_delay: Duration,
/// Value multiplied with the expected round trip time of an acknowledgement packet before
/// it is assumed it was lost and retransmission of the data packet happens.
/// In an ideal network with 0 latency, this value would have been 1.
pub ack_wait_multiplier: f64,
/// Value added to the expected round trip time of an acknowledgement packet before
/// it is assumed it was lost and retransmission of the data packet happens.
/// In an ideal network with 0 latency, this value would have been 0.
#[serde(with = "humantime_serde")]
pub ack_wait_addition: Duration,
}
impl Default for Acknowledgements {
fn default() -> Self {
Acknowledgements {
average_ack_delay: DEFAULT_AVERAGE_PACKET_DELAY,
ack_wait_multiplier: DEFAULT_ACK_WAIT_MULTIPLIER,
ack_wait_addition: DEFAULT_ACK_WAIT_ADDITION,
}
}
}
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct Topology {
/// The uniform delay every which clients are querying the directory server
/// to try to obtain a compatible network topology to send sphinx packets through.
#[serde(with = "humantime_serde")]
pub topology_refresh_rate: Duration,
/// During topology refresh, test packets are sent through every single possible network
/// path. This timeout determines waiting period until it is decided that the packet
/// did not reach its destination.
#[serde(with = "humantime_serde")]
pub topology_resolution_timeout: Duration,
/// Specifies whether the client should not refresh the network topology after obtaining
/// the first valid instance.
/// Supersedes `topology_refresh_rate_ms`.
pub disable_refreshing: bool,
/// Defines how long the client is going to wait on startup for its gateway to come online,
/// before abandoning the procedure.
#[serde(with = "humantime_serde")]
pub max_startup_gateway_waiting_period: Duration,
/// Specifies the mixnode topology to be used for sending packets.
pub topology_structure: TopologyStructure,
}
#[allow(clippy::large_enum_variant)]
#[derive(Default, Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
pub enum TopologyStructure {
#[default]
NymApi,
GeoAware(GroupBy),
}
#[allow(clippy::large_enum_variant)]
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
pub enum GroupBy {
CountryGroup(CountryGroup),
NymAddress(Recipient),
}
impl std::fmt::Display for GroupBy {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
GroupBy::CountryGroup(group) => write!(f, "group: {}", group),
GroupBy::NymAddress(address) => write!(f, "address: {}", address),
}
}
}
impl Default for Topology {
fn default() -> Self {
Topology {
topology_refresh_rate: DEFAULT_TOPOLOGY_REFRESH_RATE,
topology_resolution_timeout: DEFAULT_TOPOLOGY_RESOLUTION_TIMEOUT,
disable_refreshing: false,
max_startup_gateway_waiting_period: DEFAULT_MAX_STARTUP_GATEWAY_WAITING_PERIOD,
topology_structure: TopologyStructure::default(),
}
}
}
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct ReplySurbs {
/// Defines the minimum number of reply surbs the client wants to keep in its storage at all times.
/// It can only allow to go below that value if its to request additional reply surbs.
pub minimum_reply_surb_storage_threshold: usize,
/// Defines the maximum number of reply surbs the client wants to keep in its storage at any times.
pub maximum_reply_surb_storage_threshold: usize,
/// Defines the minimum number of reply surbs the client would request.
pub minimum_reply_surb_request_size: u32,
/// Defines the maximum number of reply surbs the client would request.
pub maximum_reply_surb_request_size: u32,
/// Defines the maximum number of reply surbs a remote party is allowed to request from this client at once.
pub maximum_allowed_reply_surb_request_size: u32,
/// Defines maximum amount of time the client is going to wait for reply surbs before explicitly asking
/// for more even though in theory they wouldn't need to.
#[serde(with = "humantime_serde")]
pub maximum_reply_surb_rerequest_waiting_period: Duration,
/// Defines maximum amount of time the client is going to wait for reply surbs before
/// deciding it's never going to get them and would drop all pending messages
#[serde(with = "humantime_serde")]
pub maximum_reply_surb_drop_waiting_period: Duration,
/// Defines maximum amount of time given reply surb is going to be valid for.
/// This is going to be superseded by key rotation once implemented.
#[serde(with = "humantime_serde")]
pub maximum_reply_surb_age: Duration,
/// Defines maximum amount of time given reply key is going to be valid for.
/// This is going to be superseded by key rotation once implemented.
#[serde(with = "humantime_serde")]
pub maximum_reply_key_age: Duration,
/// Specifies the number of mixnet hops the packet should go through. If not specified, then
/// the default value is used.
pub surb_mix_hops: Option<u8>,
}
impl Default for ReplySurbs {
fn default() -> Self {
ReplySurbs {
minimum_reply_surb_storage_threshold: DEFAULT_MINIMUM_REPLY_SURB_STORAGE_THRESHOLD,
maximum_reply_surb_storage_threshold: DEFAULT_MAXIMUM_REPLY_SURB_STORAGE_THRESHOLD,
minimum_reply_surb_request_size: DEFAULT_MINIMUM_REPLY_SURB_REQUEST_SIZE,
maximum_reply_surb_request_size: DEFAULT_MAXIMUM_REPLY_SURB_REQUEST_SIZE,
maximum_allowed_reply_surb_request_size: DEFAULT_MAXIMUM_ALLOWED_SURB_REQUEST_SIZE,
maximum_reply_surb_rerequest_waiting_period:
DEFAULT_MAXIMUM_REPLY_SURB_REREQUEST_WAITING_PERIOD,
maximum_reply_surb_drop_waiting_period: DEFAULT_MAXIMUM_REPLY_SURB_DROP_WAITING_PERIOD,
maximum_reply_surb_age: DEFAULT_MAXIMUM_REPLY_SURB_AGE,
maximum_reply_key_age: DEFAULT_MAXIMUM_REPLY_KEY_AGE,
surb_mix_hops: None,
}
}
}
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct DebugConfig {
/// Defines all configuration options related to traffic streams.
pub traffic: Traffic,
/// Defines all configuration options related to cover traffic stream(s).
pub cover_traffic: CoverTraffic,
/// Defines all configuration options related to the gateway connection.
pub gateway_connection: GatewayConnection,
/// Defines all configuration options related to acknowledgements, such as delays or wait timeouts.
pub acknowledgements: Acknowledgements,
/// Defines all configuration options related topology, such as refresh rates or timeouts.
pub topology: Topology,
/// Defines all configuration options related to reply SURBs.
pub reply_surbs: ReplySurbs,
}
impl DebugConfig {
pub fn validate(&self) -> bool {
// no other sections have explicit requirements (yet)
self.traffic.validate()
}
}
// it could be derived, sure, but I'd rather have an explicit implementation in case we had to change
// something manually at some point
#[allow(clippy::derivable_impls)]
impl Default for DebugConfig {
fn default() -> Self {
DebugConfig {
traffic: Default::default(),
cover_traffic: Default::default(),
gateway_connection: Default::default(),
acknowledgements: Default::default(),
topology: Default::default(),
reply_surbs: Default::default(),
}
}
}
pub use nym_client_core_config_types::*;
+3 -3
View File
@@ -201,7 +201,7 @@ where
log::debug!("Setting up gateway");
match setup {
GatewaySetup::MustLoad { gateway_id } => {
log::trace!("GatewaySetup::MustLoad with id: {gateway_id:?}");
log::debug!("GatewaySetup::MustLoad with id: {gateway_id:?}");
use_loaded_gateway_details(key_store, details_store, gateway_id).await
}
GatewaySetup::New {
@@ -209,7 +209,7 @@ where
available_gateways,
wg_tun_address,
} => {
log::trace!("GatewaySetup::New with spec: {specification:?}");
log::debug!("GatewaySetup::New with spec: {specification:?}");
setup_new_gateway(
key_store,
details_store,
@@ -224,7 +224,7 @@ where
gateway_details,
client_keys: managed_keys,
} => {
log::trace!("GatewaySetup::ReuseConnection");
log::debug!("GatewaySetup::ReuseConnection");
Ok(reuse_gateway_connection(
authenticated_ephemeral_client,
*gateway_details,
+3 -4
View File
@@ -16,6 +16,8 @@ thiserror = { workspace = true }
url = { workspace = true }
rand = { version = "0.7.3", features = ["wasm-bindgen"] }
tokio = { version = "1.24.1", features = ["macros"] }
si-scale = "0.2.2"
time.workspace = true
# internal
nym-bandwidth-controller = { path = "../../bandwidth-controller" }
@@ -46,10 +48,7 @@ features = ["net", "sync", "time"]
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.tokio-tungstenite]
workspace = true
# the choice of this particular tls feature was arbitrary;
# if you reckon a different one would be more appropriate, feel free to change it
# features = ["native-tls"]
features = ["rustls-tls-native-roots"]
features = ["rustls-tls-webpki-roots"]
# wasm-only dependencies
[target."cfg(target_arch = \"wasm32\")".dependencies.wasm-bindgen]
@@ -79,6 +79,7 @@ impl GatewayConfig {
}
// TODO: this should be refactored into a state machine that keeps track of its authentication state
#[derive(Debug)]
pub struct GatewayClient<C, St = EphemeralCredentialStorage> {
authenticated: bool,
disabled_credentials_mode: bool,
@@ -441,7 +442,7 @@ impl<C, St> GatewayClient<C, St> {
}
debug_assert!(self.connection.is_available());
log::trace!("Registering gateway");
log::debug!("Registering gateway");
// it's fine to instantiate it here as it's only used once (during authentication or registration)
// and putting it into the GatewayClient struct would be a hassle
@@ -493,6 +494,7 @@ impl<C, St> GatewayClient<C, St> {
if !self.connection.is_established() {
return Err(GatewayClientError::ConnectionNotEstablished);
}
log::debug!("Authenticating with gateway");
// it's fine to instantiate it here as it's only used once (during authentication or registration)
// and putting it into the GatewayClient struct would be a hassle
@@ -528,6 +530,7 @@ impl<C, St> GatewayClient<C, St> {
self.authenticated = status;
self.bandwidth_remaining = bandwidth_remaining;
self.negotiated_protocol = protocol_version;
log::debug!("authenticated: {status}, bandwidth remaining: {bandwidth_remaining}");
Ok(())
}
ServerResponse::Error { message } => Err(GatewayClientError::GatewayError(message)),
@@ -540,10 +543,11 @@ impl<C, St> GatewayClient<C, St> {
&mut self,
) -> Result<Arc<SharedKeys>, GatewayClientError> {
if self.authenticated {
debug!("Already authenticated");
return if let Some(shared_key) = &self.shared_key {
Ok(Arc::clone(shared_key))
} else {
Err(GatewayClientError::AuthenticationFailure)
Err(GatewayClientError::AuthenticationFailureWithPreexistingSharedKey)
};
}
@@ -849,6 +853,7 @@ impl<C, St> GatewayClient<C, St> {
// type alias for an ease of use
pub type InitGatewayClient = GatewayClient<InitOnly>;
#[derive(Debug)]
pub struct InitOnly;
impl GatewayClient<InitOnly, EphemeralCredentialStorage> {
@@ -71,6 +71,9 @@ pub enum GatewayClientError {
#[error("Authentication failure")]
AuthenticationFailure,
#[error("Authentication failure with preexisting shared key")]
AuthenticationFailureWithPreexistingSharedKey,
#[error("Timed out")]
Timeout,
@@ -10,9 +10,14 @@ use futures::stream::{SplitSink, SplitStream};
use futures::{SinkExt, StreamExt};
use log::*;
use nym_gateway_requests::registration::handshake::SharedKeys;
use nym_gateway_requests::ServerResponse;
use nym_task::TaskClient;
use si_scale::helpers::bibytes2;
use std::os::raw::c_int as RawFd;
use std::sync::atomic::{AtomicI64, Ordering};
use std::sync::Arc;
use std::time::Duration;
use time::OffsetDateTime;
use tungstenite::Message;
#[cfg(unix)]
@@ -48,6 +53,22 @@ pub(crate) fn ws_fd(_conn: &WsConn) -> Option<RawFd> {
None
}
// disgusting? absolutely, but does the trick for now
static LAST_LOGGED_BANDWIDTH_TS: AtomicI64 = AtomicI64::new(0);
fn maybe_log_bandwidth(remaining: i64) {
// SAFETY: this value is always populated with valid timestamps
let last =
OffsetDateTime::from_unix_timestamp(LAST_LOGGED_BANDWIDTH_TS.load(Ordering::Relaxed))
.unwrap();
let now = OffsetDateTime::now_utc();
if last + Duration::from_secs(10) < now {
log::info!("remaining bandwidth: {}", bibytes2(remaining as f64));
LAST_LOGGED_BANDWIDTH_TS.store(now.unix_timestamp(), Ordering::Relaxed)
}
}
#[derive(Debug)]
pub(crate) struct PartiallyDelegated {
sink_half: SplitSink<WsConn, Message>,
delegated_stream: (SplitStreamReceiver, oneshot::Sender<()>),
@@ -55,7 +76,10 @@ pub(crate) struct PartiallyDelegated {
}
impl PartiallyDelegated {
fn recover_received_plaintexts(ws_msgs: Vec<Message>, shared_key: &SharedKeys) -> Vec<Vec<u8>> {
fn recover_received_plaintexts(
ws_msgs: Vec<Message>,
shared_key: &SharedKeys,
) -> Result<Vec<Vec<u8>>, GatewayClientError> {
let mut plaintexts = Vec::with_capacity(ws_msgs.len());
for ws_msg in ws_msgs {
match ws_msg {
@@ -73,15 +97,32 @@ impl PartiallyDelegated {
// TODO: those can return the "send confirmations" - perhaps it should be somehow worked around?
Message::Text(text) => {
trace!(
"received a text message - probably a response to some previous query! - {}",
text
"received a text message - probably a response to some previous query! - {text}",
);
match ServerResponse::try_from(text)
.map_err(|_| GatewayClientError::MalformedResponse)?
{
ServerResponse::Send {
remaining_bandwidth,
} => maybe_log_bandwidth(remaining_bandwidth),
ServerResponse::Error { message } => {
error!("gateway failure: {message}");
return Err(GatewayClientError::GatewayError(message));
}
other => {
warn!(
"received illegal message of type {} in an authenticated client",
other.name()
)
}
}
continue;
}
_ => continue,
}
}
plaintexts
Ok(plaintexts)
}
fn route_socket_messages(
@@ -89,7 +130,7 @@ impl PartiallyDelegated {
packet_router: &PacketRouter,
shared_key: &SharedKeys,
) -> Result<(), GatewayClientError> {
let plaintexts = Self::recover_received_plaintexts(ws_msgs, shared_key);
let plaintexts = Self::recover_received_plaintexts(ws_msgs, shared_key)?;
packet_router.route_received(plaintexts)
}
@@ -129,7 +170,8 @@ impl PartiallyDelegated {
};
if let Err(err) = Self::route_socket_messages(ws_msgs, &packet_router, shared_key.as_ref()) {
log::warn!("Route socket messages failed: {err}");
log::error!("Route socket messages failed: {err}");
break Err(err)
}
}
};
@@ -221,6 +263,7 @@ impl PartiallyDelegated {
// we can either have the stream itself or an option to re-obtain it
// by notifying the future owning it to finish the execution and awaiting the result
// which should be almost immediate (or an invalid state which should never, ever happen)
#[derive(Debug)]
pub(crate) enum SocketState {
Available(Box<WsConn>),
PartiallyDelegated(PartiallyDelegated),
@@ -24,7 +24,6 @@ nym-group-contract-common = { path = "../../cosmwasm-smart-contracts/group-contr
nym-service-provider-directory-common = { path = "../../cosmwasm-smart-contracts/service-provider-directory" }
serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true }
reqwest = { workspace = true, features = ["json"] }
nym-http-api-client = { path = "../../../common/http-api-client"}
thiserror = { workspace = true }
log = { workspace = true }
@@ -67,6 +66,14 @@ cosmwasm-std = { workspace = true }
workspace = true
features = ["tokio"]
[target."cfg(target_arch = \"wasm32\")".dependencies.reqwest]
workspace = true
features = ["json"]
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.reqwest]
workspace = true
features = ["json", "rustls-tls"]
[dev-dependencies]
bip39 = { workspace = true }
cosmrs = { workspace = true, features = ["bip32"] }
+1 -1
View File
@@ -17,7 +17,7 @@ csv = "1.3.0"
cw-utils = { workspace = true }
futures = { workspace = true }
handlebars = "3.0.1"
humantime-serde = "1.0"
humantime-serde = { workspace = true }
inquire = "0.6.2"
k256 = { workspace = true, features = ["ecdsa", "sha256"] }
log = { workspace = true }
@@ -148,6 +148,10 @@ pub async fn execute(args: Args, client: SigningClient) -> anyhow::Result<()> {
bail!("the provided free pass request has too long expiry (expiry is set to on {expiration_date})")
}
if expiration_date < now {
bail!("the provided free pass expiry is set in the past!")
}
// issuance start
block_until_coconut_is_available(&client).await?;
@@ -0,0 +1,354 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use std::cmp::Ordering;
use std::collections::{HashMap, HashSet};
use std::fs;
use std::fs::OpenOptions;
use clap::Parser;
use comfy_table::Table;
use csv::WriterBuilder;
use log::info;
use nym_mixnet_contract_common::ExecuteMsg;
use nym_mixnet_contract_common::ExecuteMsg::{DelegateToMixnode, UndelegateFromMixnode};
use nym_mixnet_contract_common::PendingEpochEventKind::{Delegate, Undelegate};
use nym_validator_client::nyxd::contract_traits::{NymContractsProvider, PagedMixnetQueryClient};
use nym_validator_client::nyxd::Coin;
use crate::context::SigningClient;
use crate::utils::pretty_coin;
#[derive(Debug, Parser)]
pub struct Args {
#[clap(long)]
pub memo: Option<String>,
#[clap(
long,
help = "Input csv files with delegation amounts. Format: (mixID, amount(in NYM))"
)]
pub input: String,
#[clap(
long,
help = "An output file path (CSV format) to create or append a log of results to"
)]
pub output: Option<String>,
}
#[derive(Debug)]
pub struct InputFileRow {
pub mix_id: String,
pub amount: Coin,
}
#[derive(Debug)]
pub struct InputFileReader {
pub rows: Vec<InputFileRow>,
}
impl InputFileReader {
pub fn new(path: &str) -> Result<InputFileReader, anyhow::Error> {
let file_contents = fs::read_to_string(path)?;
let mut rows = Vec::new();
let mut mix_id_set = HashSet::new();
for line in file_contents
.lines()
.map(str::trim)
.filter(|line| !line.is_empty())
{
let tokens: Vec<_> = line.split(',').collect();
if tokens.len() != 2 {
anyhow::bail!("Incorrect format: {}", line);
}
let mix_id = tokens[0].trim().to_string();
let input_amount = tokens[1]
.trim()
.parse::<u128>()
.map_err(|_| anyhow::anyhow!("'{}' has an invalid amount", line))?;
let micro_nym_amount = input_amount * 1_000_000;
if !mix_id_set.insert(mix_id.clone()) {
anyhow::bail!("Duplicate mix_id found: {}", mix_id);
}
rows.push(InputFileRow {
mix_id,
amount: Coin {
amount: micro_nym_amount,
denom: "unym".to_string(),
},
});
}
Ok(InputFileReader { rows })
}
}
fn write_to_csv(
output_details: Vec<[String; 3]>,
output_file: Option<String>,
) -> Result<(), anyhow::Error> {
if let Some(file_path) = output_file {
// Determine if the file exists and is not empty
let file_exists = fs::metadata(&file_path)
.map(|metadata| metadata.len() > 0)
.unwrap_or(false);
// Open the file for appending or creation
let file = OpenOptions::new()
.append(true)
.create(true)
.open(&file_path)?;
if !file_exists {
let mut wtr = csv::Writer::from_writer(&file);
wtr.write_record(["Operation", "Transaction Hash", "Timestamp"])?;
wtr.flush()?;
}
let mut wtr = WriterBuilder::new()
.has_headers(!file_exists)
.from_writer(file);
// Write the details to the CSV file
for detail in output_details {
wtr.write_record(&detail)?;
}
wtr.flush()?;
info!("All operations saved to output file");
}
Ok(())
}
async fn fetch_delegation_data(
client: &SigningClient,
) -> Result<HashMap<String, Coin>, anyhow::Error> {
let address = client.address();
// Fetch all delegations for the user
let delegations = match client.get_all_delegator_delegations(&address).await {
Ok(delegations) => delegations,
Err(e) => {
anyhow::bail!("Error fetching delegations: {}", e)
}
};
// Build a map to make it easier to handle delegation data
let mut existing_delegation_map: HashMap<String, Coin> = HashMap::new();
let mut pending_delegation_map: HashMap<String, Coin> = HashMap::new();
for delegation in delegations {
existing_delegation_map
.insert(delegation.mix_id.to_string(), Coin::from(delegation.amount));
}
// Look for pending delegate / undelegate events which might be of interest to us
let pending_events = match client.get_all_pending_epoch_events().await {
Ok(events) => events,
Err(e) => {
anyhow::bail!("Error fetching pending epoch events: {}", e);
}
};
for event in pending_events {
match event.event.kind {
// If a pending undelegate tx is found, remove it from delegation map
Undelegate { owner, mix_id, .. } => {
if owner == address.as_ref()
&& existing_delegation_map.contains_key(&mix_id.to_string())
{
existing_delegation_map.remove(&mix_id.to_string());
}
}
// If a pending delegation event is found, gather them to consolidate later
Delegate {
owner,
mix_id,
amount,
..
} => {
if owner == address.as_ref() {
let mut amount = Coin::from(amount);
if let Some(pending_record) = pending_delegation_map.get(&mix_id.to_string()) {
amount.amount += pending_record.amount;
}
pending_delegation_map.insert(mix_id.to_string(), amount);
}
}
_ => {}
};
}
// Consolidate pending events into delegation map
for (mix_id, amount) in pending_delegation_map {
existing_delegation_map
.entry(mix_id)
.and_modify(|e| e.amount += amount.amount)
.or_insert(amount);
}
Ok(existing_delegation_map)
}
pub async fn delegate_to_multiple_mixnodes(args: Args, client: SigningClient) {
let records = match InputFileReader::new(&args.input) {
Ok(records) => records,
Err(e) => {
println!("Error reading input file: {}", e);
return;
}
};
let existing_delegation_map = fetch_delegation_data(&client)
.await
.expect("Could not fetch existing delegations");
let mut delegation_table = Table::new();
let mut undelegation_table = Table::new();
let mut delegation_msgs: Vec<(ExecuteMsg, Vec<Coin>)> = Vec::new();
let mut undelegation_msgs: Vec<(ExecuteMsg, Vec<Coin>)> = Vec::new();
delegation_table.set_header(["Mix ID", "Input Amount", "Adjusted Amount"]);
undelegation_table.set_header(["Mix ID"]);
for row in &records.rows {
let input_amount = row.amount.amount;
let existing_delegation_amount = existing_delegation_map
.get(&row.mix_id)
.map_or(0, |coin| coin.amount);
match existing_delegation_amount.cmp(&input_amount) {
Ordering::Equal => continue, // No action needed if amounts are equal
Ordering::Less => {
// Delegate the difference if the existing delegation is less
let difference = Coin {
amount: input_amount - existing_delegation_amount,
denom: row.amount.denom.clone(),
};
let mix_id = row.mix_id.clone().parse::<u32>().unwrap();
delegation_msgs.push((DelegateToMixnode { mix_id }, vec![difference.clone()]));
delegation_table.add_row(&[
row.mix_id.clone(),
pretty_coin(&row.amount),
pretty_coin(&difference),
]);
}
Ordering::Greater => {
let mix_id = row.mix_id.clone().parse::<u32>().unwrap();
let coins: Vec<Coin> = vec![];
undelegation_msgs.push((UndelegateFromMixnode { mix_id }, coins));
undelegation_table.add_row(&[row.mix_id.clone()]);
if row.amount.amount > 0 {
delegation_msgs.push((DelegateToMixnode { mix_id }, vec![row.amount.clone()]));
delegation_table.add_row(&[
row.mix_id.clone(),
pretty_coin(&row.amount),
pretty_coin(&row.amount),
]);
}
}
}
}
if delegation_msgs.is_empty() && undelegation_msgs.is_empty() {
println!("Nothing to do. Delegations are up-to-date!");
return;
}
if !undelegation_msgs.is_empty() {
println!("Undelegation records : \n{}\n\n", undelegation_table);
}
if !delegation_msgs.is_empty() {
println!("Delegation records : \n{}\n\n", delegation_table);
}
let ans = inquire::Confirm::new("Do you want to continue with the shown operations?")
.with_default(false)
.with_help_message("You must confirm before the transactions are signed")
.prompt();
if let Err(e) = ans {
info!("Aborting, {}...", e);
return;
}
if let Ok(false) = ans {
info!("Aborting:: User denied proceeding with signing!");
return;
}
let mut output_details: Vec<[String; 3]> = Vec::new();
let now = time::OffsetDateTime::now_utc();
let now = now
.format(&time::format_description::well_known::Rfc3339)
.unwrap();
let mixnet_contract = client
.mixnet_contract_address()
.expect("mixnet contract address is not available");
// Execute all undelegation transactions
if !undelegation_msgs.is_empty() {
let res = client
.execute_multiple(
mixnet_contract,
undelegation_msgs.clone(),
None,
format!(
"Undelegate from {} nodes via nym-cli",
undelegation_msgs.len()
),
)
.await
.expect("Could not undelegate!");
println!(
"Undelegation transaction successful : {}",
res.transaction_hash
);
output_details.push([
"Undelegate".to_string(),
res.transaction_hash.to_string(),
now.clone(),
]);
}
// Execute all delegation delegations
if !delegation_msgs.is_empty() {
let res = client
.execute_multiple(
mixnet_contract,
delegation_msgs,
None,
format!(
"Delegatation to {} nodes via nym-cli",
undelegation_msgs.len()
),
)
.await
.expect("Could not delegate");
println!(
"Delegation transaction successful : {}",
res.transaction_hash
);
output_details.push([
"Delegate".to_string(),
res.transaction_hash.to_string(),
now.clone(),
]);
}
if args.output.is_some() {
if let Err(e) = write_to_csv(output_details, args.output) {
info!("Failed to write to CSV, {}", e);
}
}
}
@@ -6,6 +6,7 @@ use clap::{Args, Subcommand};
pub mod rewards;
pub mod delegate_to_mixnode;
pub mod delegate_to_multiple_mixnodes;
pub mod query_for_delegations;
pub mod undelegate_from_mixnode;
pub mod vesting_delegate_to_mixnode;
@@ -26,6 +27,8 @@ pub enum MixnetDelegatorsCommands {
Rewards(rewards::MixnetDelegatorsReward),
/// Delegate to a mixnode
Delegate(delegate_to_mixnode::Args),
/// Perform bulk delegations from an input file
DelegateMulti(delegate_to_multiple_mixnodes::Args),
/// Undelegate from a mixnode
Undelegate(undelegate_from_mixnode::Args),
/// Delegate to a mixnode with locked tokens
@@ -328,4 +328,8 @@ impl EpochState {
pub fn is_dealing_exchange(&self) -> bool {
matches!(self, EpochState::DealingExchange { .. })
}
pub fn is_waiting_initialisation(&self) -> bool {
matches!(self, EpochState::WaitingInitialisation)
}
}
+15
View File
@@ -0,0 +1,15 @@
[package]
name = "nym-country-group"
version = "0.1.0"
authors.workspace = true
repository.workspace = true
homepage.workspace = true
documentation.workspace = true
edition.workspace = true
license.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
serde = { workspace = true, features = ["derive"] }
tracing.workspace = true
+158
View File
@@ -0,0 +1,158 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use serde::{Deserialize, Serialize};
use std::fmt;
use tracing::info;
#[derive(Copy, Clone, Hash, PartialEq, Eq, Serialize, Deserialize, Debug)]
pub enum CountryGroup {
Europe,
NorthAmerica,
SouthAmerica,
Oceania,
Asia,
Africa,
Unknown,
}
impl CountryGroup {
// We map country codes into group, which initially are continent codes to a first approximation,
// but we do it manually to reserve the right to tweak this distribution for our purposes.
// NOTE: I did this quickly, and it's not a complete list of all countries, but only those that
// were present in the network at the time. Please add more as needed.
pub fn new(country_code: &str) -> Self {
let country_code = country_code.to_uppercase();
use CountryGroup::*;
match country_code.as_ref() {
// Europe
"AT" => Europe,
"BG" => Europe,
"CH" => Europe,
"CY" => Europe,
"CZ" => Europe,
"DE" => Europe,
"DK" => Europe,
"ES" => Europe,
"FI" => Europe,
"FR" => Europe,
"GB" => Europe,
"GR" => Europe,
"IE" => Europe,
"IT" => Europe,
"LT" => Europe,
"LU" => Europe,
"LV" => Europe,
"MD" => Europe,
"MT" => Europe,
"NL" => Europe,
"NO" => Europe,
"PL" => Europe,
"RO" => Europe,
"SE" => Europe,
"SK" => Europe,
"TR" => Europe,
"UA" => Europe,
// North America
"CA" => NorthAmerica,
"MX" => NorthAmerica,
"US" => NorthAmerica,
// South America
"AR" => SouthAmerica,
"BR" => SouthAmerica,
"CL" => SouthAmerica,
"CO" => SouthAmerica,
"CR" => SouthAmerica,
"GT" => SouthAmerica,
// Oceania
"AU" => Oceania,
// Asia
"AM" => Asia,
"BH" => Asia,
"CN" => Asia,
"GE" => Asia,
"HK" => Asia,
"ID" => Asia,
"IL" => Asia,
"IN" => Asia,
"JP" => Asia,
"KH" => Asia,
"KR" => Asia,
"KZ" => Asia,
"MY" => Asia,
"RU" => Asia,
"SG" => Asia,
"TH" => Asia,
"VN" => Asia,
// Africa
"SC" => Africa,
"UG" => Africa,
"ZA" => Africa,
// And group level codes work too
"EU" => Europe,
"NA" => NorthAmerica,
"SA" => SouthAmerica,
"OC" => Oceania,
"AS" => Asia,
"AF" => Africa,
// And some aliases
"EUROPE" => Europe,
"NORTHAMERICA" => NorthAmerica,
"SOUTHAMERICA" => SouthAmerica,
"OCEANIA" => Oceania,
"ASIA" => Asia,
"AFRICA" => Africa,
_ => {
info!("Unknown country code: {country_code}");
Unknown
}
}
}
}
impl fmt::Display for CountryGroup {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use CountryGroup::*;
match self {
Europe => write!(f, "EU"),
NorthAmerica => write!(f, "NA"),
SouthAmerica => write!(f, "SA"),
Oceania => write!(f, "OC"),
Asia => write!(f, "AS"),
Africa => write!(f, "AF"),
Unknown => write!(f, "Unknown"),
}
}
}
impl std::str::FromStr for CountryGroup {
type Err = ();
fn from_str(s: &str) -> Result<Self, Self::Err> {
let group = CountryGroup::new(s);
if group == CountryGroup::Unknown {
Err(())
} else {
Ok(group)
}
}
}
impl CountryGroup {
#[allow(unused)]
fn known(self) -> Option<CountryGroup> {
use CountryGroup::*;
match self {
Europe | NorthAmerica | SouthAmerica | Oceania | Asia | Africa => Some(self),
Unknown => None,
}
}
}
@@ -0,0 +1,48 @@
/*
* Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
* SPDX-License-Identifier: Apache-2.0
*/
ALTER TABLE coconut_credentials
RENAME TO old_coconut_credentials;
CREATE TABLE coconut_credentials
(
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
-- introduce a way for us to introduce breaking changes in serialization
serialization_revision INTEGER NOT NULL,
-- the best we can do without enums
credential_type TEXT CHECK ( credential_type IN ('BandwidthVoucher', 'FreeBandwidthPass') ) NOT NULL,
credential_data BLOB NOT NULL UNIQUE,
epoch_id INTEGER NOT NULL,
-- this field is only really applicable to free passes
expired BOOLEAN NOT NULL
);
ALTER TABLE credential_usage
RENAME TO old_credential_usage;
-- for bandwidth vouchers there's going to be only a single entry; for freepasses there can be as many as there are gateways
CREATE TABLE credential_usage
(
credential_id INTEGER NOT NULL REFERENCES coconut_credentials (id),
gateway_id_bs58 TEXT NOT NULL,
-- no matter credential type, we can't spend the same credential with the same gateway multiple times
UNIQUE (credential_id, gateway_id_bs58)
);
INSERT INTO coconut_credentials
SELECT *
FROM old_coconut_credentials;
INSERT INTO credential_usage
SELECT *
FROM old_credential_usage;
DROP TABLE old_coconut_credentials;
DROP TABLE old_credential_usage;
@@ -44,7 +44,7 @@ impl CoconutCredentialManager {
r#"
SELECT *
FROM coconut_credentials
WHERE coconut_credentials.credential_type == "FreeBandwidthPass"
WHERE coconut_credentials.credential_type == "FreeBandwidthPass" AND coconut_credentials.expired = false
AND NOT EXISTS (SELECT 1
FROM credential_usage
WHERE credential_usage.credential_id = coconut_credentials.id
@@ -1,6 +1,8 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use std::fmt::{self, Debug, Formatter};
use crate::backends::memory::CoconutCredentialManager;
use crate::error::StorageError;
use crate::models::{StorableIssuedCredential, StoredIssuedCredential};
@@ -23,6 +25,12 @@ impl Default for EphemeralStorage {
}
}
impl Debug for EphemeralStorage {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "EphemeralStorage")
}
}
#[async_trait]
impl Storage for EphemeralStorage {
type StorageError = StorageError;
+3
View File
@@ -18,4 +18,7 @@ pub enum StorageError {
#[error("No unused credential in database. You need to buy at least one")]
NoCredential,
#[error("Database unique constraint violation. Is the credential already imported?")]
ConstraintUnique,
}
@@ -69,9 +69,21 @@ impl Storage for PersistentStorage {
bandwidth_credential.credential_data,
bandwidth_credential.epoch_id,
)
.await?;
Ok(())
.await
.map_err(|err| {
// There is one error we want to handle specifically.
// Check if database_error is `SqliteError` with code 2067 which
// means UNIQUE constraint violation
if let Some(db_error) = err.as_database_error() {
if db_error.code().map_or(false, |code| code == "2067") {
StorageError::ConstraintUnique
} else {
err.into()
}
} else {
err.into()
}
})
}
async fn get_next_unspent_credential(
+5 -5
View File
@@ -8,11 +8,11 @@ use std::str::FromStr;
use thiserror::Error;
pub use nym_coconut::{
aggregate_signature_shares, aggregate_verification_keys, blind_sign, hash_to_scalar, keygen,
prepare_blind_sign, prove_bandwidth_credential, verify_credential, Attribute, Base58,
BlindSignRequest, BlindedSerialNumber, BlindedSignature, Bytable, CoconutError, KeyPair,
Parameters, PrivateAttribute, PublicAttribute, SecretKey, Signature, SignatureShare,
VerificationKey, VerifyCredentialRequest,
aggregate_signature_shares, aggregate_signature_shares_and_verify, aggregate_verification_keys,
blind_sign, hash_to_scalar, keygen, prepare_blind_sign, prove_bandwidth_credential,
verify_credential, Attribute, Base58, BlindSignRequest, BlindedSerialNumber, BlindedSignature,
Bytable, CoconutError, KeyPair, Parameters, PrivateAttribute, PublicAttribute, SecretKey,
Signature, SignatureShare, VerificationKey, VerifyCredentialRequest,
};
pub const VOUCHER_INFO_TYPE: &str = "BandwidthVoucher";
@@ -12,7 +12,8 @@ use serde::{Deserialize, Serialize};
use time::{Duration, OffsetDateTime, Time};
use zeroize::{Zeroize, ZeroizeOnDrop};
pub const MAX_FREE_PASS_VALIDITY: Duration = Duration::WEEK; // 1 week
pub const DEFAULT_FREE_PASS_VALIDITY: Duration = Duration::WEEK; // 1 week
pub const MAX_FREE_PASS_VALIDITY: Duration = Duration::weeks(12); // 12 weeks
#[derive(Debug, Zeroize, ZeroizeOnDrop, Serialize, Deserialize)]
pub struct FreePassIssuedData {
@@ -77,9 +78,9 @@ impl FreePassIssuanceData {
}
pub fn default_expiry_date() -> OffsetDateTime {
// set it to furthest midnight in the future such as it's no more than a week away,
// set it to the furthest midnight in the future such as it's no more than a week away,
// i.e. if it's currently for example 9:43 on 2nd March 2024, it will set it to 0:00 on 9th March 2024
(OffsetDateTime::now_utc() + MAX_FREE_PASS_VALIDITY).replace_time(Time::MIDNIGHT)
(OffsetDateTime::now_utc() + DEFAULT_FREE_PASS_VALIDITY).replace_time(Time::MIDNIGHT)
}
pub fn expiry_date_attribute(&self) -> &Attribute {
@@ -10,18 +10,19 @@ use crate::coconut::bandwidth::{
use crate::coconut::utils::scalar_serde_helper;
use crate::error::Error;
use nym_credentials_interface::{
aggregate_signature_shares, hash_to_scalar, prepare_blind_sign, Attribute, BlindedSerialNumber,
BlindedSignature, Parameters, PrivateAttribute, PublicAttribute, Signature, SignatureShare,
VerificationKey,
aggregate_signature_shares, aggregate_signature_shares_and_verify, hash_to_scalar,
prepare_blind_sign, Attribute, BlindedSerialNumber, BlindedSignature, Parameters,
PrivateAttribute, PublicAttribute, Signature, SignatureShare, VerificationKey,
};
use nym_crypto::asymmetric::{encryption, identity};
use nym_validator_client::nym_api::EpochId;
use nym_validator_client::nyxd::{Coin, Hash};
use nym_validator_client::signing::AccountData;
use serde::{Deserialize, Serialize};
use time::OffsetDateTime;
use zeroize::{Zeroize, ZeroizeOnDrop};
pub use nym_validator_client::nyxd::{Coin, Hash};
#[derive(Zeroize, ZeroizeOnDrop, Serialize, Deserialize)]
pub enum BandwidthCredentialIssuanceDataVariant {
Voucher(BandwidthVoucherIssuanceData),
@@ -265,6 +266,13 @@ impl IssuanceBandwidthCredential {
self.unblind_signature(validator_vk, &signing_data, blinded_signature)
}
pub fn unchecked_aggregate_signature_shares(
&self,
shares: &[SignatureShare],
) -> Result<Signature, Error> {
aggregate_signature_shares(shares).map_err(Error::SignatureAggregationError)
}
pub fn aggregate_signature_shares(
&self,
verification_key: &VerificationKey,
@@ -279,7 +287,7 @@ impl IssuanceBandwidthCredential {
attributes.extend_from_slice(&private_attributes);
attributes.extend_from_slice(&public_attributes);
aggregate_signature_shares(params, verification_key, &attributes, shares)
aggregate_signature_shares_and_verify(params, verification_key, &attributes, shares)
.map_err(Error::SignatureAggregationError)
}
@@ -6,7 +6,7 @@ use crate::coconut::utils::scalar_serde_helper;
use crate::error::Error;
use nym_api_requests::coconut::BlindSignRequestBody;
use nym_credentials_interface::{
hash_to_scalar, Attribute, BlindSignRequest, BlindedSignature, PublicAttribute,
hash_to_scalar, Attribute, BlindSignRequest, BlindedSignature, CredentialType, PublicAttribute,
};
use nym_crypto::asymmetric::{encryption, identity};
use nym_validator_client::nyxd::{Coin, Hash};
@@ -123,6 +123,10 @@ impl BandwidthVoucherIssuanceData {
&self.value_prehashed
}
pub fn typ() -> CredentialType {
CredentialType::Voucher
}
pub fn tx_hash(&self) -> Hash {
self.deposit_tx_hash
}
@@ -10,6 +10,9 @@ use std::str::FromStr;
use thiserror::Error;
use zeroize::{Zeroize, ZeroizeOnDrop};
#[cfg(feature = "serde")]
pub mod serde_helpers;
#[cfg(feature = "sphinx")]
use nym_sphinx_types::{DestinationAddressBytes, DESTINATION_ADDRESS_LENGTH};
@@ -0,0 +1,18 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use super::PublicKey;
pub mod bs58_pubkey {
use super::*;
use serde_crate::{Deserialize, Deserializer, Serializer};
pub fn serialize<S: Serializer>(key: &PublicKey, serializer: S) -> Result<S::Ok, S::Error> {
serializer.serialize_str(&key.to_base58_string())
}
pub fn deserialize<'de, D: Deserializer<'de>>(deserializer: D) -> Result<PublicKey, D::Error> {
let s = String::deserialize(deserializer)?;
PublicKey::from_base58_string(s).map_err(serde::de::Error::custom)
}
}
+3
View File
@@ -3,3 +3,6 @@
pub mod encryption;
pub mod identity;
pub use encryption as x25519;
pub use identity as ed25519;
+1 -1
View File
@@ -836,7 +836,7 @@ mod tests {
let share3 = chunks3.clone().try_into().unwrap();
let shares = vec![share1, share2, share3];
let chunks = &[chunks1, chunks2, chunks3];
let chunks = [chunks1, chunks2, chunks3];
for (i, pk_i) in pks.iter().enumerate() {
let mut ciphertext_chunk_i = Vec::with_capacity(NUM_CHUNKS);
+20
View File
@@ -0,0 +1,20 @@
[package]
name = "nym-http-api-common"
version = "0.1.0"
authors.workspace = true
repository.workspace = true
homepage.workspace = true
documentation.workspace = true
edition.workspace = true
license.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
axum.workspace = true
bytes = "1.5.0"
mime = "0.3.17"
serde = { workspace = true, features = ["derive"] }
serde_json.workspace = true
serde_yaml = "0.9.25"
utoipa = { workspace = true }
@@ -1,32 +1,13 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: GPL-3.0-only
// SPDX-License-Identifier: Apache-2.0
use axum::http::{header, HeaderValue, StatusCode};
use axum::response::{IntoResponse, Response};
use axum::{Json, Router};
use axum::Json;
use bytes::{BufMut, BytesMut};
use serde::{Deserialize, Serialize};
use utoipa::{IntoParams, ToSchema};
pub mod v1;
use crate::http::api::v1::gateway::client_interfaces::wireguard::WireguardAppState;
use crate::http::state::AppState;
pub use nym_node_requests::api as api_requests;
use nym_node_requests::routes;
#[derive(Debug, Clone)]
pub struct Config {
pub v1_config: v1::Config,
}
pub(super) fn routes(config: Config, initial_wg_state: WireguardAppState) -> Router<AppState> {
Router::new().nest(
routes::api::V1,
v1::routes(config.v1_config, initial_wg_state),
)
}
#[derive(Debug, Clone, ToSchema)]
pub enum FormattedResponse<T> {
Json(Json<T>),
+5 -3
View File
@@ -10,11 +10,11 @@ license.workspace = true
[dependencies]
bytes = "1.0"
futures = { workspace = true }
humantime-serde = "1.0"
humantime-serde = { workspace = true }
log = { workspace = true }
rand = "0.8"
serde = { version = "1.0", features = ["derive"] }
tokio = { version = "1.24.1", features = [
serde = { workspace = true, features = ["derive"] }
tokio = { workspace = true, features = [
"time",
"macros",
"rt",
@@ -23,6 +23,7 @@ tokio = { version = "1.24.1", features = [
] }
tokio-util = { workspace = true, features = ["codec"] }
url = { workspace = true }
time.workspace = true
thiserror = { workspace = true }
nym-crypto = { path = "../crypto" }
@@ -37,3 +38,4 @@ nym-task = { path = "../task" }
nym-validator-client = { path = "../client-libs/validator-client" }
nym-bin-common = { path = "../bin-common" }
nym-metrics = { path = "../nym-metrics" }
nym-node-http-api = { path = "../../nym-node/nym-node-http-api" }
+21 -245
View File
@@ -1,259 +1,35 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2021-2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use nym_crypto::asymmetric::identity;
use serde::{Serialize, Serializer};
use std::cmp::Ordering;
use std::fmt::{self, Display, Formatter};
use std::sync::Arc;
use std::time::Duration;
use tokio::sync::RwLock;
use nym_node_http_api::state::metrics::{SharedVerlocStats, VerlocNodeResult};
use std::mem;
use time::OffsetDateTime;
#[derive(Clone, Default)]
pub struct AtomicVerlocResult {
inner: Arc<RwLock<VerlocResult>>,
pub(crate) trait VerlocStatsUpdateExt {
async fn start_new_measurements(&self, nodes_to_test: usize);
async fn append_measurement_results(&self, new_data: Vec<VerlocNodeResult>);
async fn finish_measurements(&self);
}
#[derive(Debug, Clone, Serialize, Default)]
pub struct VerlocResult {
total_tested: usize,
#[serde(with = "humantime_serde")]
run_started: Option<std::time::SystemTime>,
#[serde(with = "humantime_serde")]
run_finished: Option<std::time::SystemTime>,
results: Vec<Verloc>,
}
impl AtomicVerlocResult {
pub(crate) fn new() -> Self {
AtomicVerlocResult {
inner: Arc::new(RwLock::new(VerlocResult {
total_tested: 0,
run_started: None,
run_finished: None,
results: Vec::new(),
})),
}
impl VerlocStatsUpdateExt for SharedVerlocStats {
async fn start_new_measurements(&self, nodes_to_test: usize) {
let mut guard = self.write().await;
guard.previous_run_data = mem::take(&mut guard.current_run_data);
guard.current_run_data.nodes_tested = nodes_to_test;
}
pub(crate) async fn reset_results(&self, new_tested: usize) {
let mut write_permit = self.inner.write().await;
write_permit.total_tested = new_tested;
write_permit.run_started = Some(std::time::SystemTime::now());
write_permit.run_finished = None;
write_permit.results = Vec::new()
}
pub(crate) async fn append_results(&self, mut new_data: Vec<Verloc>) {
let mut write_permit = self.inner.write().await;
write_permit.results.append(&mut new_data);
async fn append_measurement_results(&self, mut new_data: Vec<VerlocNodeResult>) {
let mut write_permit = self.write().await;
write_permit.current_run_data.results.append(&mut new_data);
// make sure the data always stays in order.
// TODO: considering the front of the results is guaranteed to be sorted, should perhaps
// a non-default sorting algorithm be used?
write_permit.results.sort()
write_permit.current_run_data.results.sort()
}
pub(crate) async fn finish_measurements(&self) {
self.inner.write().await.run_finished = Some(std::time::SystemTime::now());
}
// Considering that on every read we will need to clone data regardless, let's make our
// lives simpler and clone it here rather than deal with lifetime of the permit
pub async fn clone_data(&self) -> VerlocResult {
self.inner.read().await.clone()
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize)]
pub struct Verloc {
#[serde(serialize_with = "serialize_identity_as_string")]
pub identity: identity::PublicKey,
pub latest_measurement: Option<Measurement>,
}
fn serialize_identity_as_string<S>(
identity: &identity::PublicKey,
serializer: S,
) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_str(&identity.to_base58_string())
}
impl Display for Verloc {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
if let Some(measurement) = self.latest_measurement {
write!(f, "{} - {}", self.identity, measurement)
} else {
write!(f, "{} - COULD NOT MEASURE", self.identity)
}
}
}
impl PartialOrd for Verloc {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Ord for Verloc {
fn cmp(&self, other: &Self) -> Ordering {
// if both have measurement, compare measurements
// then if only one have measurement, prefer that one
// completely ignore identity as it makes no sense to order by it
if let Some(self_measurement) = &self.latest_measurement {
if let Some(other_measurement) = &other.latest_measurement {
self_measurement.cmp(other_measurement)
} else {
Ordering::Less
}
} else if other.latest_measurement.is_some() {
Ordering::Greater
} else {
Ordering::Equal
}
}
}
impl Verloc {
pub(crate) fn new(
identity: identity::PublicKey,
latest_measurement: Option<Measurement>,
) -> Self {
Verloc {
identity,
latest_measurement,
}
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize)]
pub struct Measurement {
#[serde(serialize_with = "humantime_serde::serialize")]
pub minimum: Duration,
#[serde(serialize_with = "humantime_serde::serialize")]
pub mean: Duration,
#[serde(serialize_with = "humantime_serde::serialize")]
pub maximum: Duration,
#[serde(serialize_with = "humantime_serde::serialize")]
pub standard_deviation: Duration,
}
impl Measurement {
pub(crate) fn new(raw_results: &[Duration]) -> Self {
let minimum = *raw_results.iter().min().expect("didn't get any results!");
let maximum = *raw_results.iter().max().expect("didn't get any results!");
let mean = Self::duration_mean(raw_results);
let standard_deviation = Self::duration_standard_deviation(raw_results, mean);
Measurement {
minimum,
mean,
maximum,
standard_deviation,
}
}
fn duration_mean(data: &[Duration]) -> Duration {
let sum = data.iter().sum::<Duration>();
let count = data.len() as u32;
sum / count
}
fn duration_standard_deviation(data: &[Duration], mean: Duration) -> Duration {
let variance_micros = data
.iter()
.map(|&value| {
// make sure we don't underflow
let diff = if mean > value {
mean - value
} else {
value - mean
};
// we don't need nanos precision
let diff_micros = diff.as_micros();
diff_micros * diff_micros
})
.sum::<u128>()
/ data.len() as u128;
// we shouldn't really overflow as our differences shouldn't be larger than couple seconds at the worst possible case scenario
let std_deviation_micros = (variance_micros as f64).sqrt() as u64;
Duration::from_micros(std_deviation_micros)
}
}
impl Display for Measurement {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(
f,
"rtt min/avg/max/mdev = {:?} / {:?} / {:?} / {:?}",
self.minimum, self.mean, self.maximum, self.standard_deviation
)
}
}
impl PartialOrd for Measurement {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Ord for Measurement {
fn cmp(&self, other: &Self) -> Ordering {
// minimum value is most important, then look at standard deviation, then mean and finally maximum
let min_cmp = self.minimum.cmp(&other.minimum);
if min_cmp != Ordering::Equal {
return min_cmp;
}
let std_dev_cmp = self.standard_deviation.cmp(&other.standard_deviation);
if std_dev_cmp != Ordering::Equal {
return std_dev_cmp;
}
let std_dev_cmp = self.mean.cmp(&other.mean);
if std_dev_cmp != Ordering::Equal {
return std_dev_cmp;
}
self.maximum.cmp(&other.maximum)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn sorting_vec_of_verlocs() {
let some_identity =
identity::PublicKey::from_base58_string("Be9wH7xuXBRJAuV1pC7MALZv6a61RvWQ3SypsNarqTt")
.unwrap();
let no_measurement = Verloc::new(some_identity, None);
let low_min = Verloc::new(
some_identity,
Some(Measurement {
minimum: Duration::from_millis(42),
mean: Duration::from_millis(43),
maximum: Duration::from_millis(44),
standard_deviation: Duration::from_millis(45),
}),
);
let higher_min = Verloc::new(
some_identity,
Some(Measurement {
minimum: Duration::from_millis(420),
mean: Duration::from_millis(430),
maximum: Duration::from_millis(440),
standard_deviation: Duration::from_millis(450),
}),
);
let mut vec_verloc = vec![no_measurement, low_min, no_measurement, higher_min];
vec_verloc.sort();
let expected_sorted = vec![low_min, higher_min, no_measurement, no_measurement];
assert_eq!(expected_sorted, vec_verloc);
async fn finish_measurements(&self) {
self.write().await.current_run_data.run_finished = Some(OffsetDateTime::now_utc())
}
}
+19 -18
View File
@@ -1,4 +1,4 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2021-2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::verloc::listener::PacketListener;
@@ -9,6 +9,7 @@ use log::*;
use nym_bin_common::version_checker::{self, parse_version};
use nym_crypto::asymmetric::identity;
use nym_network_defaults::mainnet::NYM_API;
use nym_node_http_api::state::metrics::{SharedVerlocStats, VerlocNodeResult};
use nym_task::TaskClient;
use rand::seq::SliceRandom;
use rand::thread_rng;
@@ -20,7 +21,9 @@ use tokio::task::JoinHandle;
use tokio::time::sleep;
use url::Url;
pub use crate::verloc::measurement::{AtomicVerlocResult, Verloc, VerlocResult};
use measurement::VerlocStatsUpdateExt;
// pub use crate::verloc::measurement::{AtomicVerlocResult, Verloc, VerlocResult};
pub mod error;
pub(crate) mod listener;
@@ -179,7 +182,7 @@ pub struct VerlocMeasurer {
// then it definitely cannot be constructed here and probably will need to be passed from outside,
// as mixnodes/gateways would already be using an instance of said client.
validator_client: nym_validator_client::NymApiClient,
results: AtomicVerlocResult,
state: SharedVerlocStats,
}
impl VerlocMeasurer {
@@ -210,10 +213,14 @@ impl VerlocMeasurer {
config.nym_api_urls[0].clone(),
),
config,
results: AtomicVerlocResult::new(),
state: SharedVerlocStats::default(),
}
}
pub fn set_shared_state(&mut self, state: SharedVerlocStats) {
self.state = state;
}
fn use_next_nym_api(&mut self) {
if self.config.nym_api_urls.len() == 1 {
warn!("There's only a single validator API available - it won't be possible to use a different one");
@@ -225,10 +232,6 @@ impl VerlocMeasurer {
.change_nym_api(self.config.nym_api_urls[self.currently_used_api].clone())
}
pub fn get_verloc_results_pointer(&self) -> AtomicVerlocResult {
self.results.clone()
}
fn start_listening(&self) -> JoinHandle<()> {
let packet_listener = Arc::clone(&self.packet_listener);
tokio::spawn(packet_listener.run())
@@ -270,7 +273,7 @@ impl VerlocMeasurer {
while !shutdown_listener.is_shutdown() {
tokio::select! {
measurement_result = measurement_chunk.next() => {
let Some(result) = measurement_result else {
let Some(result) = measurement_result else {
// if the stream has finished, it means we got everything we could have gotten
break
};
@@ -278,18 +281,16 @@ impl VerlocMeasurer {
// if we receive JoinError it means the task failed to get executed, so either there's a bigger issue with tokio
// or there was a panic inside the task itself. In either case, we should just terminate ourselves.
let execution_result = result.expect("the measurement task panicked!");
let identity = execution_result.1;
let measurement_result = match execution_result.0 {
Err(err) => {
debug!(
"Failed to perform measurement for {} - {}",
execution_result.1.to_base58_string(),
err
);
debug!("Failed to perform measurement for {identity}: {err}");
None
}
Ok(result) => Some(result),
};
chunk_results.push(Verloc::new(execution_result.1, measurement_result));
chunk_results.push(VerlocNodeResult::new(identity, measurement_result));
},
_ = shutdown_listener.recv() => {
trace!("Shutdown received while measuring");
@@ -299,7 +300,7 @@ impl VerlocMeasurer {
}
// update the results vector with chunks as they become available (by default every 50 nodes)
self.results.append_results(chunk_results).await;
self.state.append_measurement_results(chunk_results).await;
}
MeasurementOutcome::Done
@@ -358,7 +359,7 @@ impl VerlocMeasurer {
.collect::<Vec<_>>();
// on start of each run remove old results
self.results.reset_results(tested_nodes.len()).await;
self.state.start_new_measurements(tested_nodes.len()).await;
if let MeasurementOutcome::Shutdown = self.perform_measurement(tested_nodes).await {
log::trace!("Shutting down after aborting measurements");
@@ -366,7 +367,7 @@ impl VerlocMeasurer {
}
// write current time to "run finished" field
self.results.finish_measurements().await;
self.state.finish_measurements().await;
info!(
"Finished performing verloc measurements. The next one will happen in {:?}",
+4 -4
View File
@@ -1,11 +1,11 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2021-2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::verloc::error::RttError;
use crate::verloc::measurement::Measurement;
use crate::verloc::packet::{EchoPacket, ReplyPacket};
use log::*;
use nym_crypto::asymmetric::identity;
use nym_node_http_api::state::metrics::VerlocMeasurement;
use nym_task::TaskClient;
use rand::{thread_rng, Rng};
use std::net::SocketAddr;
@@ -82,7 +82,7 @@ impl PacketSender {
pub(super) async fn send_packets_to_node(
self: Arc<Self>,
tested_node: TestedNode,
) -> Result<Measurement, RttError> {
) -> Result<VerlocMeasurement, RttError> {
let mut shutdown_listener = self.shutdown_listener.fork(tested_node.address.to_string());
shutdown_listener.mark_as_success();
@@ -208,6 +208,6 @@ impl PacketSender {
sleep(self.delay_between_packets).await;
}
Ok(Measurement::new(&results))
Ok(VerlocMeasurement::new(&results))
}
}
+6 -3
View File
@@ -18,9 +18,12 @@ pub const VESTING_CONTRACT_ADDRESS: &str =
"n1nc5tatafv6eyq7llkr2gv50ff9e22mnf70qgjlv737ktmt4eswrq73f2nw";
pub const COCONUT_BANDWIDTH_CONTRACT_ADDRESS: &str = "";
pub const GROUP_CONTRACT_ADDRESS: &str = "";
pub const MULTISIG_CONTRACT_ADDRESS: &str = "";
pub const COCONUT_DKG_CONTRACT_ADDRESS: &str = "";
pub const GROUP_CONTRACT_ADDRESS: &str =
"n1e2zq4886zzewpvpucmlw8v9p7zv692f6yck4zjzxh699dkcmlrfqk2knsr";
pub const MULTISIG_CONTRACT_ADDRESS: &str =
"n1txayqfz5g9qww3rlflpg025xd26m9payz96u54x4fe3s2ktz39xqk67gzx";
pub const COCONUT_DKG_CONTRACT_ADDRESS: &str =
"n19604yflqggs9mk2z26mqygq43q2kr3n932egxx630svywd5mpxjsztfpvx";
pub const EPHEMERA_CONTRACT_ADDRESS: &str = "";
pub const REWARDING_VALIDATOR_ADDRESS: &str = "n10yyd98e2tuwu0f7ypz9dy3hhjw7v772q6287gy";
+5 -5
View File
@@ -6,10 +6,10 @@ use criterion::{criterion_group, criterion_main, Criterion};
use ff::Field;
use group::{Curve, Group};
use nym_coconut::{
aggregate_signature_shares, aggregate_verification_keys, blind_sign, prepare_blind_sign,
prove_bandwidth_credential, random_scalars_refs, setup, ttp_keygen, verify_credential,
verify_partial_blind_signature, Attribute, BlindedSignature, Parameters, Signature,
SignatureShare, VerificationKey,
aggregate_signature_shares_and_verify, aggregate_verification_keys, blind_sign,
prepare_blind_sign, prove_bandwidth_credential, random_scalars_refs, setup, ttp_keygen,
verify_credential, verify_partial_blind_signature, Attribute, BlindedSignature, Parameters,
Signature, SignatureShare, VerificationKey,
};
use rand::seq::SliceRandom;
use std::ops::Neg;
@@ -99,7 +99,7 @@ fn unblind_and_aggregate(
let mut attributes = vec![];
attributes.extend_from_slice(private_attributes);
attributes.extend_from_slice(public_attributes);
aggregate_signature_shares(
aggregate_signature_shares_and_verify(
params,
verification_key,
&attributes,
+7
View File
@@ -4,14 +4,18 @@
#![warn(clippy::expect_used)]
#![warn(clippy::unwrap_used)]
pub use bls12_381::Scalar;
pub use elgamal::elgamal_keygen;
pub use elgamal::ElGamalKeyPair;
pub use elgamal::PublicKey;
pub use error::CoconutError;
pub use scheme::aggregation::aggregate_key_shares;
pub use scheme::aggregation::aggregate_signature_shares;
pub use scheme::aggregation::aggregate_signature_shares_and_verify;
pub use scheme::aggregation::aggregate_verification_keys;
pub use scheme::issuance::blind_sign;
pub use scheme::issuance::prepare_blind_sign;
pub use scheme::issuance::sign;
pub use scheme::issuance::verify_partial_blind_signature;
pub use scheme::issuance::BlindSignRequest;
pub use scheme::keygen::keygen;
@@ -19,16 +23,19 @@ pub use scheme::keygen::ttp_keygen;
pub use scheme::keygen::KeyPair;
pub use scheme::keygen::SecretKey;
pub use scheme::keygen::VerificationKey;
pub use scheme::keygen::VerificationKeyShare;
pub use scheme::setup::setup;
pub use scheme::setup::Parameters;
pub use scheme::verification::check_vk_pairing;
pub use scheme::verification::prove_bandwidth_credential;
pub use scheme::verification::verify;
pub use scheme::verification::verify_credential;
pub use scheme::verification::BlindedSerialNumber;
pub use scheme::verification::VerifyCredentialRequest;
pub use scheme::BlindedSignature;
pub use scheme::Signature;
pub use scheme::SignatureShare;
pub use scheme::SignerIndex;
pub use traits::Base58;
pub use traits::Bytable;
pub use utils::hash_to_scalar;
+55 -25
View File
@@ -12,7 +12,7 @@ use crate::error::{CoconutError, Result};
use crate::scheme::verification::check_bilinear_pairing;
use crate::scheme::{PartialSignature, Signature, SignatureShare, SignerIndex, VerificationKey};
use crate::utils::perform_lagrangian_interpolation_at_origin;
use crate::{Attribute, Parameters};
use crate::{Attribute, Parameters, VerificationKeyShare};
pub(crate) trait Aggregatable: Sized {
fn aggregate(aggregatable: &[Self], indices: Option<&[SignerIndex]>) -> Result<Self>;
@@ -80,7 +80,23 @@ pub fn aggregate_verification_keys(
Aggregatable::aggregate(keys, indices)
}
pub fn aggregate_key_shares(shares: &[VerificationKeyShare]) -> Result<VerificationKey> {
let (keys, indices): (Vec<_>, Vec<_>) = shares
.iter()
.map(|share| (share.key.clone(), share.index))
.unzip();
aggregate_verification_keys(&keys, Some(&indices))
}
pub fn aggregate_signatures(
signatures: &[PartialSignature],
indices: Option<&[SignerIndex]>,
) -> Result<Signature> {
Aggregatable::aggregate(signatures, indices)
}
pub fn aggregate_signatures_and_verify(
params: &Parameters,
verification_key: &VerificationKey,
attributes: &[&Attribute],
@@ -88,11 +104,7 @@ pub fn aggregate_signatures(
indices: Option<&[SignerIndex]>,
) -> Result<Signature> {
// aggregate the signature
let signature = match Aggregatable::aggregate(signatures, indices) {
Ok(res) => res,
Err(err) => return Err(err),
};
let signature = aggregate_signatures(signatures, indices)?;
// Verify the signature
let alpha = verification_key.alpha;
@@ -116,7 +128,16 @@ pub fn aggregate_signatures(
Ok(signature)
}
pub fn aggregate_signature_shares(
pub fn aggregate_signature_shares(shares: &[SignatureShare]) -> Result<Signature> {
let (signatures, indices): (Vec<_>, Vec<_>) = shares
.iter()
.map(|share| (*share.signature(), share.index()))
.unzip();
aggregate_signatures(&signatures, Some(&indices))
}
pub fn aggregate_signature_shares_and_verify(
params: &Parameters,
verification_key: &VerificationKey,
attributes: &[&Attribute],
@@ -127,7 +148,7 @@ pub fn aggregate_signature_shares(
.map(|share| (*share.signature(), share.index()))
.unzip();
aggregate_signatures(
aggregate_signatures_and_verify(
params,
verification_key,
attributes,
@@ -210,7 +231,7 @@ mod tests {
#[test]
fn signature_aggregation_works_for_any_subset_of_signatures() {
let mut params = Parameters::new(2).unwrap();
let params = Parameters::new(2).unwrap();
random_scalars_refs!(attributes, params, 2);
let keypairs = ttp_keygen(&params, 3, 5).unwrap();
@@ -227,12 +248,12 @@ mod tests {
let sigs = sks
.iter()
.map(|sk| sign(&mut params, sk, &attributes).unwrap())
.map(|sk| sign(&params, sk, &attributes).unwrap())
.collect::<Vec<_>>();
// aggregating (any) threshold works
let aggr_vk_1 = aggregate_verification_keys(&vks[..3], Some(&[1, 2, 3])).unwrap();
let aggr_sig1 = aggregate_signatures(
let aggr_sig1 = aggregate_signatures_and_verify(
&params,
&aggr_vk_1,
&attributes,
@@ -242,7 +263,7 @@ mod tests {
.unwrap();
let aggr_vk_2 = aggregate_verification_keys(&vks[2..], Some(&[3, 4, 5])).unwrap();
let aggr_sig2 = aggregate_signatures(
let aggr_sig2 = aggregate_signatures_and_verify(
&params,
&aggr_vk_1,
&attributes,
@@ -258,7 +279,7 @@ mod tests {
// aggregating threshold+1 works
let aggr_vk_more = aggregate_verification_keys(&vks[1..], Some(&[2, 3, 4, 5])).unwrap();
let aggr_more = aggregate_signatures(
let aggr_more = aggregate_signatures_and_verify(
&params,
&aggr_vk_more,
&attributes,
@@ -270,7 +291,7 @@ mod tests {
// aggregating all
let aggr_vk_all = aggregate_verification_keys(&vks, Some(&[1, 2, 3, 4, 5])).unwrap();
let aggr_all = aggregate_signatures(
let aggr_all = aggregate_signatures_and_verify(
&params,
&aggr_vk_all,
&attributes,
@@ -282,7 +303,7 @@ mod tests {
// not taking enough points (threshold was 3) should fail
let aggr_vk_not_enough = aggregate_verification_keys(&vks[..2], Some(&[1, 2])).unwrap();
let aggr_not_enough = aggregate_signatures(
let aggr_not_enough = aggregate_signatures_and_verify(
&params,
&aggr_vk_not_enough,
&attributes,
@@ -294,7 +315,7 @@ mod tests {
// taking wrong index should fail
let aggr_vk_bad = aggregate_verification_keys(&vks[2..], Some(&[1, 2, 3])).unwrap();
assert!(aggregate_signatures(
assert!(aggregate_signatures_and_verify(
&params,
&aggr_vk_bad,
&attributes,
@@ -330,9 +351,14 @@ mod tests {
.unzip();
let aggr_vk_all = aggregate_verification_keys(&vks, None).unwrap();
assert!(
aggregate_signatures(&params, &aggr_vk_all, &attributes, &signatures, None).is_err()
);
assert!(aggregate_signatures_and_verify(
&params,
&aggr_vk_all,
&attributes,
&signatures,
None
)
.is_err());
}
#[test]
@@ -352,11 +378,15 @@ mod tests {
.unzip();
let aggr_vk_all = aggregate_verification_keys(&vks, None).unwrap();
assert!(
aggregate_signatures(&params, &aggr_vk_all, &attributes, &signatures, Some(&[]))
.is_err()
);
assert!(aggregate_signatures(
assert!(aggregate_signatures_and_verify(
&params,
&aggr_vk_all,
&attributes,
&signatures,
Some(&[])
)
.is_err());
assert!(aggregate_signatures_and_verify(
&params,
&aggr_vk_all,
&attributes,
@@ -383,7 +413,7 @@ mod tests {
.unzip();
let aggr_vk_all = aggregate_verification_keys(&vks, None).unwrap();
assert!(aggregate_signatures(
assert!(aggregate_signatures_and_verify(
&params,
&aggr_vk_all,
&attributes,
+7 -4
View File
@@ -13,9 +13,8 @@ use crate::scheme::setup::Parameters;
use crate::scheme::BlindedSignature;
use crate::scheme::SecretKey;
use crate::Attribute;
/// Creates a Coconut Signature under a given secret key on a set of public attributes only.
#[cfg(test)]
use crate::Signature;
// TODO: possibly completely remove those two functions.
// They only exist to have a simpler and smaller code snippets to test
// basic functionalities.
@@ -158,6 +157,10 @@ impl BlindSignRequest {
)
}
pub fn verify_commitment_hash(&self, public_attributes: &[&Attribute]) -> bool {
self.commitment_hash == compute_hash(self.commitment, public_attributes)
}
pub fn get_commitment_hash(&self) -> G1Projective {
self.commitment_hash
}
@@ -426,9 +429,9 @@ pub fn verify_partial_blind_signature(
.into()
}
#[cfg(test)]
/// Creates a Coconut Signature under a given secret key on a set of public attributes only.
pub fn sign(
params: &mut Parameters,
params: &Parameters,
secret_key: &SecretKey,
public_attributes: &[&Attribute],
) -> Result<Signature> {
+28 -8
View File
@@ -151,10 +151,6 @@ impl Base58 for SecretKey {}
// TODO: perhaps change points to affine representation
// to make verification slightly more efficient?
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(
feature = "key-zeroize",
derive(zeroize::Zeroize, zeroize::ZeroizeOnDrop)
)]
pub struct VerificationKey {
// TODO add gen2 as per the paper or imply it from the fact library is using bls381?
pub(crate) alpha: G2Projective,
@@ -411,12 +407,23 @@ impl Bytable for VerificationKey {
impl Base58 for VerificationKey {}
#[derive(Debug, Clone)]
pub struct VerificationKeyShare {
pub key: VerificationKey,
pub index: SignerIndex,
}
impl From<(VerificationKey, SignerIndex)> for VerificationKeyShare {
fn from(value: (VerificationKey, SignerIndex)) -> Self {
VerificationKeyShare {
key: value.0,
index: value.1,
}
}
}
#[derive(Debug, Serialize, Deserialize)]
#[cfg_attr(test, derive(PartialEq, Eq, Clone))]
#[cfg_attr(
feature = "key-zeroize",
derive(zeroize::Zeroize, zeroize::ZeroizeOnDrop)
)]
pub struct KeyPair {
secret_key: SecretKey,
verification_key: VerificationKey,
@@ -425,6 +432,12 @@ pub struct KeyPair {
pub index: Option<SignerIndex>,
}
impl From<KeyPair> for (SecretKey, VerificationKey) {
fn from(value: KeyPair) -> Self {
(value.secret_key, value.verification_key)
}
}
impl PemStorableKeyPair for KeyPair {
type PrivatePemKey = SecretKey;
type PublicPemKey = VerificationKey;
@@ -461,6 +474,13 @@ impl KeyPair {
&self.verification_key
}
pub fn to_verification_key_share(&self) -> Option<VerificationKeyShare> {
self.index.map(|index| VerificationKeyShare {
key: self.verification_key.clone(),
index,
})
}
pub fn to_bytes(&self) -> Vec<u8> {
// Schema is coconutkeypair[14]|secret_key_len[8]|secret_key[secret_key_len]|verification_key_len[8]|verification_key[verification_key_len]|signer_index[8] - optional
self.to_byte_vec()
+31 -13
View File
@@ -70,6 +70,11 @@ impl Signature {
&self.1
}
pub fn randomise_simple(&self, params: &Parameters) -> Signature {
let r = params.random_scalar();
Signature(self.0 * r, self.1 * r)
}
pub fn randomise(&self, params: &Parameters) -> (Signature, Scalar) {
let r = params.random_scalar();
let r_prime = params.random_scalar();
@@ -191,7 +196,7 @@ impl BlindedSignature {
&self,
partial_verification_key: &VerificationKey,
pedersen_commitments_openings: &[Scalar],
) -> Result<Signature> {
) -> Signature {
// parse the signature
let h = &self.0;
let c = &self.1;
@@ -204,7 +209,7 @@ impl BlindedSignature {
let unblinded_c = c - blinding_removers;
Ok(Signature(*h, unblinded_c))
Signature(*h, unblinded_c)
}
pub fn unblind_and_verify(
@@ -216,7 +221,7 @@ impl BlindedSignature {
commitment_hash: &G1Projective,
pedersen_commitments_openings: &[Scalar],
) -> Result<Signature> {
let unblinded = self.unblind(partial_verification_key, pedersen_commitments_openings)?;
let unblinded = self.unblind(partial_verification_key, pedersen_commitments_openings);
unblinded.verify(
params,
partial_verification_key,
@@ -240,6 +245,7 @@ impl BlindedSignature {
}
// perhaps this should take signature by reference? we'll see how it goes
#[derive(Clone, Copy)]
pub struct SignatureShare {
signature: Signature,
index: SignerIndex,
@@ -276,7 +282,9 @@ impl SignatureShare {
mod tests {
use super::*;
use crate::hash_to_scalar;
use crate::scheme::aggregation::{aggregate_signatures, aggregate_verification_keys};
use crate::scheme::aggregation::{
aggregate_signatures_and_verify, aggregate_verification_keys,
};
use crate::scheme::issuance::{blind_sign, compute_hash, prepare_blind_sign, sign};
use crate::scheme::keygen::{keygen, ttp_keygen};
use crate::scheme::verification::{prove_bandwidth_credential, verify, verify_credential};
@@ -418,13 +426,13 @@ mod tests {
#[test]
fn verification_on_two_public_attributes() {
let mut params = Parameters::new(2).unwrap();
let params = Parameters::new(2).unwrap();
random_scalars_refs!(attributes, params, 2);
let keypair1 = keygen(&params);
let keypair2 = keygen(&params);
let sig1 = sign(&mut params, keypair1.secret_key(), &attributes).unwrap();
let sig2 = sign(&mut params, keypair2.secret_key(), &attributes).unwrap();
let sig1 = sign(&params, keypair1.secret_key(), &attributes).unwrap();
let sig2 = sign(&params, keypair2.secret_key(), &attributes).unwrap();
assert!(verify(
&params,
@@ -568,9 +576,14 @@ mod tests {
attributes.extend_from_slice(&public_attributes);
let aggr_vk = aggregate_verification_keys(&vks[..2], Some(&[1, 2])).unwrap();
let aggr_sig =
aggregate_signatures(&params, &aggr_vk, &attributes, &sigs[..2], Some(&[1, 2]))
.unwrap();
let aggr_sig = aggregate_signatures_and_verify(
&params,
&aggr_vk,
&attributes,
&sigs[..2],
Some(&[1, 2]),
)
.unwrap();
let theta = prove_bandwidth_credential(
&params,
@@ -590,9 +603,14 @@ mod tests {
// taking different subset of keys and credentials
let aggr_vk = aggregate_verification_keys(&vks[1..], Some(&[2, 3])).unwrap();
let aggr_sig =
aggregate_signatures(&params, &aggr_vk, &attributes, &sigs[1..], Some(&[2, 3]))
.unwrap();
let aggr_sig = aggregate_signatures_and_verify(
&params,
&aggr_vk,
&attributes,
&sigs[1..],
Some(&[2, 3]),
)
.unwrap();
let theta = prove_bandwidth_credential(
&params,
+1
View File
@@ -10,6 +10,7 @@ use crate::error::{CoconutError, Result};
use crate::utils::hash_g1;
/// System-wide parameters used for the protocol
#[derive(Clone)]
pub struct Parameters {
/// Generator of the G1 group
g1: G1Affine,
@@ -288,7 +288,6 @@ pub fn verify_credential(
}
// Used in tests only
#[cfg(test)]
pub fn verify(
params: &Parameters,
verification_key: &VerificationKey,
+6 -2
View File
@@ -75,8 +75,12 @@ pub fn theta_from_keys_and_attributes(
attributes.extend_from_slice(public_attributes);
// Randomize credentials and generate any cryptographic material to verify them
let signature =
aggregate_signature_shares(params, &verification_key, &attributes, &signature_shares)?;
let signature = aggregate_signature_shares_and_verify(
params,
&verification_key,
&attributes,
&signature_shares,
)?;
// Generate cryptographic material to verify them
let theta = prove_bandwidth_credential(
+3
View File
@@ -3,3 +3,6 @@
pub mod clients;
pub mod nodes;
pub use clients::Recipient;
pub use nodes::NodeIdentity;
+4 -2
View File
@@ -16,7 +16,9 @@ const_format = "0.2.32"
cosmrs.workspace = true
eyre = "0.6.9"
futures.workspace = true
humantime = "2.1.0"
sha2 = "0.10.8"
serde = { workspace = true, features = ["derive"] }
sqlx = { workspace = true, features = ["runtime-tokio-rustls", "sqlite", "macros", "migrate", "time"] }
tendermint.workspace = true
tendermint-rpc = { workspace = true, features = ["websocket-client", "http-client"] }
@@ -24,13 +26,13 @@ thiserror.workspace = true
time = { workspace = true }
tokio = { workspace = true, features = ["full"] }
tokio-stream = "0.1.14"
tokio-util = { version = "0.7.10", features = ["rt"]}
tokio-util = { version = "0.7.10", features = ["rt"] }
tracing.workspace = true
url.workspace = true
# TEMP
nym-bin-common = { path = "../bin-common", features = ["basic_tracing"]}
#nym-bin-common = { path = "../bin-common", features = ["basic_tracing"]}
[build-dependencies]
+23
View File
@@ -0,0 +1,23 @@
# Nyxd Scraper
## Pruning
Similarly to cosmos-sdk, we incorporate pruning into our (scraped) chain data. We attempt to follow their strategies as
closely as possible for convenience's sake. Therefore, the following are available:
### Strategies
The strategies are configured in `config.toml`, with the format `pruning = "<strategy>"` where the options are:
* `default`: only the last 362,880 states(approximately 3.5 weeks worth of state) are kept; pruning at 10 block
intervals
* `nothing`: all historic states will be saved, nothing will be deleted (i.e. archiving node)
* `everything`: 2 latest states will be kept; pruning at 10 block intervals.
* `custom`: allow pruning options to be manually specified through `pruning.keep_recent`, and `pruning.interval`
### Custom Pruning
These are applied if and only if the pruning strategy is `custom`:
* `pruning.keep_recent`: N means to keep all of the last N blocks
* `pruning.interval`: N means to delete old block data from disk every Nth block.
+75 -2
View File
@@ -8,6 +8,7 @@ use crate::error::ScraperError;
use crate::modules::{BlockModule, MsgModule, TxModule};
use crate::rpc_client::RpcClient;
use crate::storage::{persist_block, ScraperStorage};
use crate::PruningOptions;
use futures::StreamExt;
use std::collections::{BTreeMap, HashSet, VecDeque};
use std::ops::{Add, Range};
@@ -18,9 +19,10 @@ use tokio::sync::Notify;
use tokio::time::{interval_at, Instant};
use tokio_stream::wrappers::UnboundedReceiverStream;
use tokio_util::sync::CancellationToken;
use tracing::{debug, error, info, warn};
use tracing::{debug, error, info, instrument, trace, warn};
mod helpers;
pub(crate) mod pruning;
pub(crate) mod types;
const MISSING_BLOCKS_CHECK_INTERVAL: Duration = Duration::from_secs(30);
@@ -40,9 +42,11 @@ impl PendingSync {
}
pub struct BlockProcessor {
pruning_options: PruningOptions,
cancel: CancellationToken,
synced: Arc<Notify>,
last_processed_height: u32,
last_pruned_height: u32,
last_processed_at: Instant,
pending_sync: PendingSync,
queued_blocks: BTreeMap<u32, BlockToProcess>,
@@ -62,6 +66,7 @@ pub struct BlockProcessor {
impl BlockProcessor {
pub async fn new(
pruning_options: PruningOptions,
cancel: CancellationToken,
synced: Arc<Notify>,
incoming: UnboundedReceiver<BlockToProcess>,
@@ -70,11 +75,17 @@ impl BlockProcessor {
rpc_client: RpcClient,
) -> Result<Self, ScraperError> {
let last_processed = storage.get_last_processed_height().await?;
let last_processed_height = last_processed.try_into().unwrap_or_default();
let last_pruned = storage.get_pruned_height().await?;
let last_pruned_height = last_pruned.try_into().unwrap_or_default();
Ok(BlockProcessor {
pruning_options,
cancel,
synced,
last_processed_height: last_processed.try_into().unwrap_or_default(),
last_processed_height,
last_pruned_height,
last_processed_at: Instant::now(),
pending_sync: Default::default(),
queued_blocks: Default::default(),
@@ -131,12 +142,17 @@ impl BlockProcessor {
}
}
let commit_start = Instant::now();
tx.commit()
.await
.map_err(|source| ScraperError::StorageTxCommitFailure { source })?;
crate::storage::log_db_operation_time("committing processing tx", commit_start);
self.last_processed_height = full_info.block.header.height.value() as u32;
self.last_processed_at = Instant::now();
if let Err(err) = self.maybe_prune_storage().await {
error!("failed to prune the storage: {err}");
}
Ok(())
}
@@ -210,6 +226,61 @@ impl BlockProcessor {
Ok(())
}
#[instrument(skip(self))]
async fn prune_storage(&mut self) -> Result<(), ScraperError> {
let keep_recent = self.pruning_options.strategy_keep_recent();
let last_to_keep = self.last_processed_height - keep_recent;
info!(
keep_recent,
oldest_to_keep = last_to_keep,
"pruning the storage"
);
let lowest: u32 = self
.storage
.lowest_block_height()
.await?
.unwrap_or_default()
.try_into()
.unwrap_or_default();
let to_prune = last_to_keep.saturating_sub(lowest);
match to_prune {
v if v > 1000 => warn!("approximately {v} blocks worth of data will be pruned"),
v if v > 100 => info!("approximately {v} blocks worth of data will be pruned"),
0 => trace!("no blocks to prune"),
v => debug!("approximately {v} blocks worth of data will be pruned"),
}
if to_prune == 0 {
return Ok(());
}
self.storage
.prune_storage(last_to_keep, self.last_processed_height)
.await?;
self.last_pruned_height = self.last_processed_height;
Ok(())
}
async fn maybe_prune_storage(&mut self) -> Result<(), ScraperError> {
debug!("checking for storage pruning");
if self.pruning_options.strategy.is_nothing() {
trace!("the current pruning strategy is 'nothing'");
return Ok(());
}
let interval = self.pruning_options.strategy_interval();
if self.last_pruned_height + interval <= self.last_processed_height {
self.prune_storage().await?;
}
Ok(())
}
async fn next_incoming(&mut self, block: BlockToProcess) {
let height = block.height;
@@ -279,6 +350,8 @@ impl BlockProcessor {
async fn startup_resync(&mut self) -> Result<(), ScraperError> {
assert!(self.pending_sync.is_empty());
self.maybe_prune_storage().await?;
let latest_block = self.rpc_client.current_block_height().await? as u32;
if latest_block > self.last_processed_height && self.last_processed_height != 0 {
let request_range = self.last_processed_height + 1..latest_block + 1;
@@ -0,0 +1,122 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::error::ScraperError;
use serde::{Deserialize, Serialize};
pub const DEFAULT_PRUNING_KEEP_RECENT: u32 = 362880;
pub const DEFAULT_PRUNING_INTERVAL: u32 = 10;
pub const EVERYTHING_PRUNING_KEEP_RECENT: u32 = 2;
pub const EVERYTHING_PRUNING_INTERVAL: u32 = 10;
/// We follow cosmos-sdk pruning strategies for conveniences sake.
#[derive(Debug, Default, Clone, Copy, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum PruningStrategy {
/// 'Default' strategy defines a pruning strategy where the last 362880 heights are
/// kept where to-be pruned heights are pruned at every 10th height.
/// The last 362880 heights are kept(approximately 3.5 weeks worth of state) assuming the typical
/// block time is 6s. If these values do not match the applications' requirements, use the "custom" option.
#[default]
Default,
/// 'Everything' strategy defines a pruning strategy where all committed heights are
/// deleted, storing only the current height and last 2 states. To-be pruned heights are
/// pruned at every 10th height.
Everything,
/// 'Nothing' strategy defines a pruning strategy where all heights are kept on disk.
Nothing,
/// 'Custom' strategy defines a pruning strategy where the user specifies the pruning.
Custom,
}
impl PruningStrategy {
pub fn is_custom(&self) -> bool {
matches!(self, PruningStrategy::Custom)
}
pub fn is_nothing(&self) -> bool {
matches!(self, PruningStrategy::Nothing)
}
pub fn is_everything(&self) -> bool {
matches!(self, PruningStrategy::Everything)
}
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub struct PruningOptions {
/// keep_recent defines how many recent heights to keep on disk.
pub keep_recent: u32,
/// interval defines the frequency of removing the pruned heights from the disk.
pub interval: u32,
/// strategy defines the currently used kind of [PruningStrategy].
pub strategy: PruningStrategy,
}
impl PruningOptions {
pub fn validate(&self) -> Result<(), ScraperError> {
// if strategy is not set to custom, other options are meaningless since they won't be applied
if !self.strategy.is_custom() {
return Ok(());
}
if self.interval == 0 {
return Err(ScraperError::ZeroPruningInterval);
}
if self.interval < EVERYTHING_PRUNING_INTERVAL {
return Err(ScraperError::TooSmallPruningInterval {
interval: self.interval,
});
}
if self.keep_recent < EVERYTHING_PRUNING_KEEP_RECENT {
return Err(ScraperError::TooSmallKeepRecent {
keep_recent: self.keep_recent,
});
}
Ok(())
}
pub fn nothing() -> Self {
PruningOptions {
keep_recent: 0,
interval: 0,
strategy: PruningStrategy::Nothing,
}
}
pub fn strategy_interval(&self) -> u32 {
match self.strategy {
PruningStrategy::Default => DEFAULT_PRUNING_INTERVAL,
PruningStrategy::Everything => EVERYTHING_PRUNING_INTERVAL,
PruningStrategy::Nothing => 0,
PruningStrategy::Custom => self.interval,
}
}
pub fn strategy_keep_recent(&self) -> u32 {
match self.strategy {
PruningStrategy::Default => DEFAULT_PRUNING_KEEP_RECENT,
PruningStrategy::Everything => EVERYTHING_PRUNING_KEEP_RECENT,
PruningStrategy::Nothing => 0,
PruningStrategy::Custom => self.keep_recent,
}
}
}
impl Default for PruningOptions {
fn default() -> Self {
PruningOptions {
keep_recent: DEFAULT_PRUNING_KEEP_RECENT,
interval: DEFAULT_PRUNING_INTERVAL,
strategy: Default::default(),
}
}
}
+12
View File
@@ -1,6 +1,9 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::block_processor::pruning::{
EVERYTHING_PRUNING_INTERVAL, EVERYTHING_PRUNING_KEEP_RECENT,
};
use tendermint::Hash;
use thiserror::Error;
use tokio::sync::mpsc::error::SendError;
@@ -122,6 +125,15 @@ pub enum ScraperError {
"could not find validator information for {address}; the validator has signed a commit"
)]
MissingValidatorInfoCommitted { address: String },
#[error("pruning.interval must not be set to 0. If you want to disable pruning, select pruning.strategy = \"nothing\"")]
ZeroPruningInterval,
#[error("pruning.interval must not be smaller than {}. got: {interval}. for most aggressive pruning, select pruning.strategy = \"everything\"", EVERYTHING_PRUNING_INTERVAL)]
TooSmallPruningInterval { interval: u32 },
#[error("pruning.keep_recent must not be smaller than {}. got: {keep_recent}. for most aggressive pruning, select pruning.strategy = \"everything\"", EVERYTHING_PRUNING_KEEP_RECENT)]
TooSmallKeepRecent { keep_recent: u32 },
}
impl<T> From<SendError<T>> for ScraperError {
+1
View File
@@ -14,6 +14,7 @@ pub(crate) mod rpc_client;
pub(crate) mod scraper;
pub mod storage;
pub use block_processor::pruning::{PruningOptions, PruningStrategy};
pub use modules::{BlockModule, MsgModule, TxModule};
pub use scraper::{Config, NyxdScraper};
pub use storage::models;
+6
View File
@@ -8,6 +8,7 @@ use crate::modules::{BlockModule, MsgModule, TxModule};
use crate::rpc_client::RpcClient;
use crate::scraper::subscriber::ChainSubscriber;
use crate::storage::ScraperStorage;
use crate::PruningOptions;
use std::path::PathBuf;
use std::sync::Arc;
use tokio::sync::mpsc::{channel, unbounded_channel};
@@ -27,6 +28,8 @@ pub struct Config {
pub rpc_url: Url,
pub database_path: PathBuf,
pub pruning_options: PruningOptions,
}
pub struct NyxdScraperBuilder {
@@ -54,6 +57,7 @@ impl NyxdScraperBuilder {
processing_tx.clone(),
);
let mut block_processor = BlockProcessor::new(
scraper.config.pruning_options,
scraper.cancel_token.clone(),
scraper.startup_sync.clone(),
processing_rx,
@@ -119,6 +123,7 @@ impl NyxdScraper {
}
pub async fn new(config: Config) -> Result<Self, ScraperError> {
config.pruning_options.validate()?;
let storage = ScraperStorage::init(&config.database_path).await?;
Ok(NyxdScraper {
@@ -160,6 +165,7 @@ impl NyxdScraper {
processing_tx.clone(),
);
let block_processor = BlockProcessor::new(
self.config.pruning_options,
self.cancel_token.clone(),
self.startup_sync.clone(),
processing_rx,
+191 -11
View File
@@ -1,9 +1,11 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::storage::log_db_operation_time;
use crate::storage::models::{CommitSignature, Validator};
use sqlx::types::time::OffsetDateTime;
use sqlx::{Executor, Sqlite};
use tokio::time::Instant;
use tracing::{instrument, trace};
#[derive(Clone)]
@@ -25,10 +27,36 @@ impl StorageManager {
Ok(())
}
pub(crate) async fn get_lowest_block(&self) -> Result<Option<i64>, sqlx::Error> {
trace!("get_lowest_block");
let start = Instant::now();
let maybe_record = sqlx::query!(
r#"
SELECT height
FROM block
ORDER BY height ASC
LIMIT 1
"#,
)
.fetch_optional(&self.connection_pool)
.await?;
log_db_operation_time("get_lowest_block", start);
if let Some(row) = maybe_record {
Ok(row.height)
} else {
Ok(None)
}
}
pub(crate) async fn get_first_block_height_after(
&self,
time: OffsetDateTime,
) -> Result<Option<i64>, sqlx::Error> {
trace!("get_first_block_height_after");
let start = Instant::now();
let maybe_record = sqlx::query!(
r#"
SELECT height
@@ -41,6 +69,7 @@ impl StorageManager {
)
.fetch_optional(&self.connection_pool)
.await?;
log_db_operation_time("get_first_block_height_after", start);
if let Some(row) = maybe_record {
Ok(row.height)
@@ -53,6 +82,9 @@ impl StorageManager {
&self,
time: OffsetDateTime,
) -> Result<Option<i64>, sqlx::Error> {
trace!("get_last_block_height_before");
let start = Instant::now();
let maybe_record = sqlx::query!(
r#"
SELECT height
@@ -65,6 +97,7 @@ impl StorageManager {
)
.fetch_optional(&self.connection_pool)
.await?;
log_db_operation_time("get_last_block_height_before", start);
if let Some(row) = maybe_record {
Ok(row.height)
@@ -79,6 +112,9 @@ impl StorageManager {
start_height: i64,
end_height: i64,
) -> Result<i32, sqlx::Error> {
trace!("get_signed_between");
let start = Instant::now();
let count = sqlx::query!(
r#"
SELECT COUNT(*) as count FROM pre_commit
@@ -94,6 +130,7 @@ impl StorageManager {
.fetch_one(&self.connection_pool)
.await?
.count;
log_db_operation_time("get_signed_between", start);
Ok(count)
}
@@ -103,7 +140,10 @@ impl StorageManager {
consensus_address: &str,
height: i64,
) -> Result<Option<CommitSignature>, sqlx::Error> {
sqlx::query_as(
trace!("get_precommit");
let start = Instant::now();
let res = sqlx::query_as(
r#"
SELECT * FROM pre_commit
WHERE validator_address = ?
@@ -113,14 +153,20 @@ impl StorageManager {
.bind(consensus_address)
.bind(height)
.fetch_optional(&self.connection_pool)
.await
.await?;
log_db_operation_time("get_precommit", start);
Ok(res)
}
pub(crate) async fn get_block_validators(
&self,
height: i64,
) -> Result<Vec<Validator>, sqlx::Error> {
sqlx::query_as!(
trace!("get_block_validators");
let start = Instant::now();
let res = sqlx::query_as!(
Validator,
r#"
SELECT * FROM validator
@@ -133,16 +179,28 @@ impl StorageManager {
height
)
.fetch_all(&self.connection_pool)
.await
.await?;
log_db_operation_time("get_block_validators", start);
Ok(res)
}
pub(crate) async fn get_validators(&self) -> Result<Vec<Validator>, sqlx::Error> {
sqlx::query_as("SELECT * FROM validator")
trace!("get_validators");
let start = Instant::now();
let res = sqlx::query_as("SELECT * FROM validator")
.fetch_all(&self.connection_pool)
.await
.await?;
log_db_operation_time("get_validators", start);
Ok(res)
}
pub(crate) async fn get_last_processed_height(&self) -> Result<i64, sqlx::Error> {
trace!("get_last_processed_height");
let start = Instant::now();
let maybe_record = sqlx::query!(
r#"
SELECT last_processed_height FROM metadata
@@ -150,6 +208,7 @@ impl StorageManager {
)
.fetch_optional(&self.connection_pool)
.await?;
log_db_operation_time("get_last_processed_height", start);
if let Some(row) = maybe_record {
Ok(row.last_processed_height)
@@ -157,6 +216,27 @@ impl StorageManager {
Ok(-1)
}
}
pub(crate) async fn get_pruned_height(&self) -> Result<i64, sqlx::Error> {
trace!("get_pruned_height");
let start = Instant::now();
let maybe_record = sqlx::query!(
r#"
SELECT last_pruned_height FROM pruning
"#
)
.fetch_optional(&self.connection_pool)
.await?;
log_db_operation_time("get_pruned_height", start);
if let Some(row) = maybe_record {
Ok(row.last_pruned_height)
} else {
Ok(-1)
}
}
}
// make those generic over executor so that they could be performed over connection pool and a tx
@@ -170,7 +250,8 @@ pub(crate) async fn insert_validator<'a, E>(
where
E: Executor<'a, Database = Sqlite>,
{
trace!("insert validator");
trace!("insert_validator");
let start = Instant::now();
sqlx::query!(
r#"
@@ -183,6 +264,7 @@ where
)
.execute(executor)
.await?;
log_db_operation_time("insert_validator", start);
Ok(())
}
@@ -200,7 +282,8 @@ pub(crate) async fn insert_block<'a, E>(
where
E: Executor<'a, Database = Sqlite>,
{
trace!("insert block");
trace!("insert_block");
let start = Instant::now();
sqlx::query!(
r#"
@@ -217,6 +300,7 @@ where
)
.execute(executor)
.await?;
log_db_operation_time("insert_block", start);
Ok(())
}
@@ -233,7 +317,8 @@ pub(crate) async fn insert_precommit<'a, E>(
where
E: Executor<'a, Database = Sqlite>,
{
trace!("insert precommit");
trace!("insert_precommit");
let start = Instant::now();
sqlx::query!(
r#"
@@ -249,6 +334,7 @@ where
)
.execute(executor)
.await?;
log_db_operation_time("insert_precommit", start);
Ok(())
}
@@ -270,7 +356,8 @@ pub(crate) async fn insert_transaction<'a, E>(
where
E: Executor<'a, Database = Sqlite>,
{
trace!("insert transaction");
trace!("insert_transaction");
let start = Instant::now();
sqlx::query!(
r#"
@@ -298,6 +385,7 @@ where
)
.execute(executor)
.await?;
log_db_operation_time("insert_transaction", start);
Ok(())
}
@@ -313,7 +401,8 @@ pub(crate) async fn insert_message<'a, E>(
where
E: Executor<'a, Database = Sqlite>,
{
trace!("insert message");
trace!("insert_message");
let start = Instant::now();
sqlx::query!(
r#"
@@ -330,6 +419,7 @@ where
)
.execute(executor)
.await?;
log_db_operation_time("insert_message", start);
Ok(())
}
@@ -343,10 +433,100 @@ where
E: Executor<'a, Database = Sqlite>,
{
trace!("update_last_processed");
let start = Instant::now();
sqlx::query!("UPDATE metadata SET last_processed_height = ?", height)
.execute(executor)
.await?;
log_db_operation_time("update_last_processed", start);
Ok(())
}
#[instrument(skip(executor))]
pub(crate) async fn update_last_pruned<'a, E>(height: i64, executor: E) -> Result<(), sqlx::Error>
where
E: Executor<'a, Database = Sqlite>,
{
trace!("update_last_pruned");
let start = Instant::now();
sqlx::query!("UPDATE pruning SET last_pruned_height = ?", height)
.execute(executor)
.await?;
log_db_operation_time("update_last_pruned", start);
Ok(())
}
pub(crate) async fn prune_blocks<'a, E>(oldest_to_keep: i64, executor: E) -> Result<(), sqlx::Error>
where
E: Executor<'a, Database = Sqlite>,
{
trace!("prune_blocks");
let start = Instant::now();
sqlx::query!("DELETE FROM block WHERE height < ?", oldest_to_keep)
.execute(executor)
.await?;
log_db_operation_time("prune_blocks", start);
Ok(())
}
pub(crate) async fn prune_pre_commits<'a, E>(
oldest_to_keep: i64,
executor: E,
) -> Result<(), sqlx::Error>
where
E: Executor<'a, Database = Sqlite>,
{
trace!("prune_pre_commits");
let start = Instant::now();
sqlx::query!("DELETE FROM pre_commit WHERE height < ?", oldest_to_keep)
.execute(executor)
.await?;
log_db_operation_time("prune_pre_commits", start);
Ok(())
}
pub(crate) async fn prune_transactions<'a, E>(
oldest_to_keep: i64,
executor: E,
) -> Result<(), sqlx::Error>
where
E: Executor<'a, Database = Sqlite>,
{
trace!("prune_transactions");
let start = Instant::now();
sqlx::query!(
"DELETE FROM \"transaction\" WHERE height < ?",
oldest_to_keep
)
.execute(executor)
.await?;
log_db_operation_time("prune_transactions", start);
Ok(())
}
pub(crate) async fn prune_messages<'a, E>(
oldest_to_keep: i64,
executor: E,
) -> Result<(), sqlx::Error>
where
E: Executor<'a, Database = Sqlite>,
{
trace!("prune_messages");
let start = Instant::now();
sqlx::query!("DELETE FROM message WHERE height < ?", oldest_to_keep)
.execute(executor)
.await?;
log_db_operation_time("prune_messages", start);
Ok(())
}
+50 -1
View File
@@ -5,7 +5,8 @@ use crate::block_processor::types::{FullBlockInformation, ParsedTransactionRespo
use crate::error::ScraperError;
use crate::storage::manager::{
insert_block, insert_message, insert_precommit, insert_transaction, insert_validator,
update_last_processed, StorageManager,
prune_blocks, prune_messages, prune_pre_commits, prune_transactions, update_last_processed,
update_last_pruned, StorageManager,
};
use crate::storage::models::{CommitSignature, Validator};
use sqlx::types::time::OffsetDateTime;
@@ -15,6 +16,7 @@ use std::path::Path;
use tendermint::block::{Commit, CommitSig};
use tendermint::Block;
use tendermint_rpc::endpoint::validators;
use tokio::time::Instant;
use tracing::{debug, error, info, instrument, trace, warn};
mod helpers;
@@ -28,6 +30,19 @@ pub struct ScraperStorage {
pub(crate) manager: StorageManager,
}
pub(crate) fn log_db_operation_time(op_name: &str, start_time: Instant) {
let elapsed = start_time.elapsed();
let formatted = humantime::format_duration(elapsed);
match elapsed.as_millis() {
v if v > 10000 => error!("{op_name} took {formatted} to execute"),
v if v > 1000 => warn!("{op_name} took {formatted} to execute"),
v if v > 100 => info!("{op_name} took {formatted} to execute"),
v if v > 10 => debug!("{op_name} took {formatted} to execute"),
_ => trace!("{op_name} took {formatted} to execute"),
}
}
impl ScraperStorage {
#[instrument]
pub async fn init<P: AsRef<Path> + Debug>(database_path: P) -> Result<Self, ScraperError> {
@@ -65,6 +80,32 @@ impl ScraperStorage {
Ok(storage)
}
#[instrument(skip(self))]
pub async fn prune_storage(
&self,
oldest_to_keep: u32,
current_height: u32,
) -> Result<(), ScraperError> {
let start = Instant::now();
let mut tx = self.begin_processing_tx().await?;
prune_messages(oldest_to_keep.into(), &mut tx).await?;
prune_transactions(oldest_to_keep.into(), &mut tx).await?;
prune_pre_commits(oldest_to_keep.into(), &mut tx).await?;
prune_blocks(oldest_to_keep.into(), &mut tx).await?;
update_last_pruned(current_height.into(), &mut tx).await?;
let commit_start = Instant::now();
tx.commit()
.await
.map_err(|source| ScraperError::StorageTxCommitFailure { source })?;
log_db_operation_time("committing pruning tx", commit_start);
log_db_operation_time("pruning storage", start);
Ok(())
}
#[instrument(skip_all)]
pub async fn begin_processing_tx(&self) -> Result<StorageTransaction, ScraperError> {
debug!("starting storage tx");
@@ -75,6 +116,10 @@ impl ScraperStorage {
.map_err(|source| ScraperError::StorageTxBeginFailure { source })
}
pub async fn lowest_block_height(&self) -> Result<Option<i64>, ScraperError> {
Ok(self.manager.get_lowest_block().await?)
}
pub async fn get_first_block_height_after(
&self,
time: OffsetDateTime,
@@ -155,6 +200,10 @@ impl ScraperStorage {
pub async fn get_last_processed_height(&self) -> Result<i64, ScraperError> {
Ok(self.manager.get_last_processed_height().await?)
}
pub async fn get_pruned_height(&self) -> Result<i64, ScraperError> {
Ok(self.manager.get_pruned_height().await?)
}
}
pub async fn persist_block(
+5 -1
View File
@@ -348,7 +348,7 @@ impl TaskClient {
"unnamed-TaskClient".to_string()
};
log!(target: target, level, "{msg}")
log!(target: target, level, "{}", format!("[{target}] {msg}"))
}
#[must_use]
@@ -474,6 +474,10 @@ impl TaskClient {
self.mode.set_should_not_signal_on_drop();
}
pub fn disarm(&mut self) {
self.mark_as_success();
}
pub fn send_we_stopped(&mut self, err: SentError) {
if self.mode.is_dummy() {
return;
+1 -1
View File
@@ -159,7 +159,7 @@ impl TunDevice {
"add",
&format!("{}/{}", ipv6, netmaskv6),
"dev",
&tun.name(),
(tun.name()),
])
.output()?;
Ok(tun)
+3 -1
View File
@@ -50,7 +50,7 @@ pub struct DelegationWithEverything {
pub accumulated_by_delegates: Option<DecCoin>,
pub accumulated_by_operator: Option<DecCoin>,
pub block_height: u64,
pub delegated_on_iso_datetime: String,
pub delegated_on_iso_datetime: Option<String>,
pub cost_params: Option<MixNodeCostParams>,
pub avg_uptime_percent: Option<u8>,
@@ -60,6 +60,8 @@ pub struct DelegationWithEverything {
pub uses_vesting_contract_tokens: bool,
pub unclaimed_rewards: Option<DecCoin>,
pub errors: Option<String>,
// DEPRECATED, IF POSSIBLE TRY TO DISCONTINUE USE OF IT!
pub pending_events: Vec<DelegationEvent>,
pub mixnode_is_unbonding: Option<bool>,
+23 -8
View File
@@ -124,15 +124,12 @@ pub struct GatewayNetworkRequesterDetails {
pub encryption_key: String,
pub open_proxy: bool,
pub exit_policy: bool,
pub enabled_statistics: bool,
// just a convenience wrapper around all the keys
pub address: String,
pub config_path: String,
pub allow_list_path: String,
pub unknown_list_path: String,
}
impl fmt::Display for GatewayNetworkRequesterDetails {
@@ -146,11 +143,7 @@ impl fmt::Display for GatewayNetworkRequesterDetails {
writeln!(f, "\taddress: {}", self.address)?;
writeln!(f, "\tuses open proxy: {}", self.open_proxy)?;
writeln!(f, "\tuses exit policy: {}", self.exit_policy)?;
writeln!(f, "\tsends statistics: {}", self.enabled_statistics)?;
writeln!(f, "\tallow list path: {}", self.allow_list_path)?;
writeln!(f, "\tunknown list path: {}", self.unknown_list_path)
writeln!(f, "\tsends statistics: {}", self.enabled_statistics)
}
}
@@ -178,3 +171,25 @@ impl fmt::Display for GatewayIpPacketRouterDetails {
writeln!(f, "\taddress: {}", self.address)
}
}
#[derive(Debug, Serialize, Deserialize)]
pub struct GatewayWireguardDetails {
pub enabled: bool,
pub announced_port: u16,
pub private_network_prefix: u8,
}
impl fmt::Display for GatewayWireguardDetails {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
writeln!(f, "wireguard:")?;
writeln!(f, "\tenabled: {}", self.enabled)?;
writeln!(f, "\tannounced_port: {}", self.announced_port)?;
writeln!(
f,
"\tprivate_network_prefix: {}",
self.private_network_prefix
)
}
}
+7
View File
@@ -6,6 +6,7 @@ use futures::{Sink, Stream};
use gloo_net::websocket::futures::WebSocket;
use gloo_net::websocket::{Message, WebSocketError};
use gloo_utils::errors::JsError;
use std::fmt::{self, Formatter};
use std::io;
use std::pin::Pin;
use std::task::{Context, Poll};
@@ -77,6 +78,12 @@ impl Stream for JSWebsocket {
}
}
impl fmt::Debug for JSWebsocket {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "JSWebSocket")
}
}
impl Sink<WsMessage> for JSWebsocket {
type Error = WsError;
+2
View File
@@ -17,7 +17,9 @@ log = { workspace = true }
serde = { workspace = true, features = ["derive"] }
thiserror = { workspace = true }
nym-config = { path = "../config" }
nym-crypto = { path = "../crypto", features = ["asymmetric"] }
nym-network-defaults = { path = "../network-defaults" }
# feature-specific dependencies:

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