Compare commits

...

37 Commits

Author SHA1 Message Date
Bogdan-Ștefan Neacşu 1104911688 Configure bw reset via RESET_EVERY env var 2024-09-03 13:28:11 +00:00
benedettadavico 9c88f254a4 10 mins test 2024-09-03 13:28:11 +00:00
benedettadavico 3599078363 back to the original 2024-09-03 13:28:11 +00:00
benedettadavico 857521592a debug, 1 hour 2024-09-03 13:28:11 +00:00
benedettadavico f1ec92b5c5 debug 2024-09-03 13:28:11 +00:00
benedettadavico f1f84183ff more debug 2024-09-03 13:28:11 +00:00
benedettadavico 561c3db999 debugging more.. 2024-09-03 13:28:11 +00:00
Bogdan-Ștefan Neacşu f0e35599f1 Revert "Disable peer configuring"
This reverts commit 06d37352979d4dfdcc768493484cf5577e9e3221.
2024-09-03 13:28:11 +00:00
Bogdan-Ștefan Neacşu 6590bea1b1 Reset at xx:x5 2024-09-03 13:28:11 +00:00
Bogdan-Ștefan Neacşu ae5057195a Disable peer configuring 2024-09-03 13:28:11 +00:00
Bogdan-Ștefan Neacşu 128a624b2b Use xx:15 instead of o'clock 2024-09-03 13:28:11 +00:00
Bogdan-Ștefan Neacşu f0a8b125f7 Midnight to hourly wg bandwidth refresh 2024-09-03 13:28:11 +00:00
Bogdan-Ștefan Neacşu 7b4dc78f41 Remove wireguard feature flag and pass runtime enabled flag (#4839)
* Remove wireguard feature flag

* Use wg enabled runtime flag

* Fix unintended flag removal
2024-09-03 15:25:05 +02:00
Bogdan-Ștefan Neacşu bb7a8e84e4 Eliminate cancel unsafe sig awaiting (#4834)
* Eliminate cancel unsafe sig awaiting

* Fix wasm build

* Simplify spawn call

* Fix wasm lint
2024-09-03 15:24:49 +02:00
benedetta davico a3183ab313 Merge pull request #4819 from nymtech/add-ecash-contract
adding ecash contract address
2024-08-29 07:26:46 +02:00
benedettadavico 74cd73a58f fmt 2024-08-28 17:35:37 +02:00
benedetta davico dd89026065 Merge pull request #4802 from nymtech/fix/nym-cli-params
Check profit margin of node before defaulting to hardcoded value
2024-08-28 17:34:56 +02:00
benedettadavico 73fc2d6bb2 remove unused import 2024-08-28 11:43:16 +02:00
benedettadavico a5289cd431 update test env with ecash too 2024-08-28 11:39:49 +02:00
benedettadavico ec0e1b67a0 adding ecash contract address 2024-08-28 11:28:17 +02:00
benedettadavico eafbed6c9f wording 2024-08-28 11:21:11 +02:00
benedettadavico 4635db73f1 update code and fmt again 2024-08-27 16:20:44 +02:00
benedettadavico 9a43d1079a cargo fmt 2024-08-27 15:15:45 +02:00
benedettadavico 3238722ade WIP 2024-08-27 14:55:47 +02:00
Bogdan-Ștefan Neacşu a6ad6c7d49 Sync last_seen_bandwidth immediately (#4774) 2024-08-21 14:17:01 +02:00
Jędrzej Stuczyński cbc977c491 Merge pull request #4773 from nymtech/feature/additional-ecash-nym-cli-utils
Feature/additional ecash nym cli utils
2024-08-21 09:36:47 +01:00
Jędrzej Stuczyński f40c05a34c fixed incorrect propagation of client_id in the sdk 2024-08-20 17:01:43 +01:00
Jędrzej Stuczyński 776443131e fixed full display being always printed 2024-08-20 16:57:18 +01:00
Bogdan-Ștefan Neacşu b5eab7f07f Better storage error logging (#4772)
* Better storage error logging

* Print without including error returned to clients
2024-08-20 17:49:27 +02:00
Jędrzej Stuczyński eeeb4b3246 fixed incorrect assertion when validating maximum time between redemption 2024-08-20 16:43:36 +01:00
Jędrzej Stuczyński e3e4dc6db9 added an utility nym-cli command to output binary representation of ecash tickets 2024-08-20 16:31:00 +01:00
Jędrzej Stuczyński 461b7bcfb7 updated sandbox.env 2024-08-20 15:25:40 +01:00
Jędrzej Stuczyński bbf0d06583 updated constants depending on all 30 days expiration 2024-08-20 12:54:42 +01:00
Jędrzej Stuczyński 6393d6093f changed parsing of 'credential_data' when importing ticketbooks 2024-08-20 11:31:07 +01:00
benedettadavico c0ea599913 update changelog and version bump 2024-08-19 10:32:21 +02:00
benedetta davico 16d09a35ba Merge pull request #4764 from nymtech/bugfix/post-050-dkg
bugfix: make sure DKG parses data out of events if logs are empty
2024-08-16 13:46:15 +02:00
Jędrzej Stuczyński e6c5eddbe5 bugfix: make sure DKG parse data out of events if logs are empty
this will be the case on post 0.50 chains
2024-08-16 11:56:48 +01:00
67 changed files with 902 additions and 602 deletions
@@ -62,10 +62,6 @@ jobs:
echo 'RUSTFLAGS="--cfg tokio_unstable"' >> $GITHUB_ENV
if: github.event_name == 'workflow_dispatch' && inputs.add_tokio_unstable == true
- name: Set CARGO_FEATURES
run: |
echo 'CARGO_FEATURES=--features wireguard' >> $GITHUB_ENV
- name: Install Rust stable
uses: actions-rs/toolchain@v1
with:
+5 -7
View File
@@ -73,29 +73,27 @@ jobs:
uses: actions-rs/cargo@v1
with:
command: build
# Enable wireguard by default on linux only
args: --workspace --features wireguard
- name: Build all examples
if: matrix.os == 'custom-linux'
uses: actions-rs/cargo@v1
with:
command: build
args: --workspace --examples --features wireguard
args: --workspace --examples
- name: Run all tests
if: matrix.os == 'custom-linux'
uses: actions-rs/cargo@v1
with:
command: test
args: --workspace --features wireguard
args: --workspace
- name: Run expensive tests
if: (github.ref == 'refs/heads/develop' || github.event.pull_request.base.ref == 'develop' || github.event.pull_request.base.ref == 'master') && matrix.os == 'custom-linux'
uses: actions-rs/cargo@v1
with:
command: test
args: --workspace --features wireguard -- --ignored
args: --workspace -- --ignored
- name: Annotate with clippy checks
if: matrix.os == 'custom-linux'
@@ -103,10 +101,10 @@ jobs:
continue-on-error: true
with:
token: ${{ secrets.GITHUB_TOKEN }}
args: --workspace --features wireguard
args: --workspace
- name: Clippy
uses: actions-rs/cargo@v1
with:
command: clippy
args: --workspace --all-targets --features wireguard -- -D warnings
args: --workspace --all-targets -- -D warnings
@@ -51,10 +51,6 @@ jobs:
echo 'RUSTFLAGS="--cfg tokio_unstable"' >> $GITHUB_ENV
if: github.event_name == 'workflow_dispatch' && inputs.add_tokio_unstable == true
- name: Set CARGO_FEATURES
run: |
echo 'CARGO_FEATURES=--features wireguard' >> $GITHUB_ENV
- name: Install Rust stable
uses: actions-rs/toolchain@v1
with:
+32
View File
@@ -4,6 +4,38 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
## [Unreleased]
## [2024.10-caramello] (2024-08-19)
- bugfix: make sure DKG parses data out of events if logs are empty ([#4764])
- Fix clippy on rustc beta toolchain ([#4746])
- Fix clippy for beta toolchain ([#4742])
- Disable testnet-manager on non-unix ([#4741])
- Don't set NYM_VPN_API to default ([#4740])
- Update publish-nym-binaries.yml ([#4739])
- Update ci-build-upload-binaries.yml ([#4738])
- Add NYM_VPN_API to network config ([#4736])
- Re-export RecipientFormattingError in nym sdk ([#4735])
- Persist wireguard peers ([#4732])
- Fix tokio error in 1.39 ([#4730])
- Feature/vesting purge plus ranged cost params ([#4716])
- Fix (some) feature unification build failures ([#4681])
- Feature Compact Ecash : The One PR ([#4623])
[#4764]: https://github.com/nymtech/nym/pull/4764
[#4746]: https://github.com/nymtech/nym/pull/4746
[#4742]: https://github.com/nymtech/nym/pull/4742
[#4741]: https://github.com/nymtech/nym/pull/4741
[#4740]: https://github.com/nymtech/nym/pull/4740
[#4739]: https://github.com/nymtech/nym/pull/4739
[#4738]: https://github.com/nymtech/nym/pull/4738
[#4736]: https://github.com/nymtech/nym/pull/4736
[#4735]: https://github.com/nymtech/nym/pull/4735
[#4732]: https://github.com/nymtech/nym/pull/4732
[#4730]: https://github.com/nymtech/nym/pull/4730
[#4716]: https://github.com/nymtech/nym/pull/4716
[#4681]: https://github.com/nymtech/nym/pull/4681
[#4623]: https://github.com/nymtech/nym/pull/4623
## [2024.9-topdeck] (2024-07-26)
- chore: fix 1.80 lint issues ([#4731])
Generated
+83 -220
View File
@@ -332,15 +332,6 @@ dependencies = [
"winapi",
]
[[package]]
name = "autocfg"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0dde43e75fd43e8a1bf86103336bc699aa8d17ad1be60c76c0bdfd4828e19b78"
dependencies = [
"autocfg 1.3.0",
]
[[package]]
name = "autocfg"
version = "1.3.0"
@@ -553,7 +544,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93f2635620bf0b9d4576eb7bb9a38a55df78bd1205d26fa994b25911a69f212f"
dependencies = [
"bitcoin_hashes",
"rand 0.8.5",
"rand",
"rand_core 0.6.4",
"serde",
"unicode-normalization",
@@ -994,15 +985,6 @@ version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70"
[[package]]
name = "cloudabi"
version = "0.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
dependencies = [
"bitflags 1.3.2",
]
[[package]]
name = "colorchoice"
version = "1.0.1"
@@ -2240,7 +2222,7 @@ checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0"
[[package]]
name = "explorer-api"
version = "1.1.38"
version = "1.1.39"
dependencies = [
"chrono",
"clap 4.5.7",
@@ -2259,8 +2241,8 @@ dependencies = [
"nym-validator-client",
"okapi",
"pretty_env_logger",
"rand 0.8.5",
"rand_pcg 0.3.1",
"rand",
"rand_pcg",
"rand_seeder",
"reqwest 0.12.4",
"rocket",
@@ -2459,12 +2441,6 @@ dependencies = [
"libc",
]
[[package]]
name = "fuchsia-cprng"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
[[package]]
name = "funty"
version = "2.0.0"
@@ -3345,7 +3321,7 @@ version = "1.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
dependencies = [
"autocfg 1.3.0",
"autocfg",
"hashbrown 0.12.3",
"serde",
]
@@ -3760,7 +3736,7 @@ version = "0.4.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17"
dependencies = [
"autocfg 1.3.0",
"autocfg",
"scopeguard",
]
@@ -3887,7 +3863,7 @@ version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a"
dependencies = [
"autocfg 1.3.0",
"autocfg",
]
[[package]]
@@ -3957,7 +3933,7 @@ dependencies = [
"nym-ordered-buffer",
"nym-service-providers-common",
"nym-socks5-requests",
"rand 0.8.5",
"rand",
"serde",
"serde-wasm-bindgen 0.6.5",
"thiserror",
@@ -4173,7 +4149,7 @@ version = "0.2.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
dependencies = [
"autocfg 1.3.0",
"autocfg",
"libm",
]
@@ -4204,7 +4180,7 @@ checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3"
[[package]]
name = "nym-api"
version = "1.1.42"
version = "1.1.43"
dependencies = [
"anyhow",
"async-trait",
@@ -4257,8 +4233,8 @@ dependencies = [
"nym-vesting-contract-common",
"okapi",
"pin-project",
"rand 0.8.5",
"rand_chacha 0.3.1",
"rand",
"rand_chacha",
"reqwest 0.12.4",
"rocket",
"rocket_cors",
@@ -4344,7 +4320,7 @@ dependencies = [
"nym-types",
"nym-wireguard",
"nym-wireguard-types",
"rand 0.8.5",
"rand",
"serde",
"serde_json",
"thiserror",
@@ -4361,7 +4337,7 @@ dependencies = [
"bincode",
"nym-sphinx",
"nym-wireguard-types",
"rand 0.8.5",
"rand",
"serde",
]
@@ -4379,7 +4355,7 @@ dependencies = [
"nym-ecash-time",
"nym-network-defaults",
"nym-validator-client",
"rand 0.8.5",
"rand",
"thiserror",
"url",
"zeroize",
@@ -4425,7 +4401,7 @@ dependencies = [
[[package]]
name = "nym-cli"
version = "1.1.40"
version = "1.1.41"
dependencies = [
"anyhow",
"base64 0.13.1",
@@ -4453,11 +4429,12 @@ name = "nym-cli-commands"
version = "1.0.0"
dependencies = [
"anyhow",
"base64 0.13.1",
"base64 0.21.7",
"bip39",
"bs58 0.5.1",
"cfg-if",
"clap 4.5.7",
"colored",
"comfy-table 6.2.0",
"cosmrs 0.17.0-pre",
"cosmwasm-std",
@@ -4490,21 +4467,21 @@ dependencies = [
"nym-types",
"nym-validator-client",
"nym-vesting-contract-common",
"rand 0.6.5",
"rand",
"serde",
"serde_json",
"tap",
"thiserror",
"time",
"tokio",
"toml 0.5.11",
"toml 0.8.14",
"url",
"zeroize",
]
[[package]]
name = "nym-client"
version = "1.1.39"
version = "1.1.40"
dependencies = [
"bs58 0.5.1",
"clap 4.5.7",
@@ -4527,7 +4504,7 @@ dependencies = [
"nym-task",
"nym-topology",
"nym-validator-client",
"rand 0.8.5",
"rand",
"serde",
"serde_json",
"tap",
@@ -4578,7 +4555,7 @@ dependencies = [
"nym-task",
"nym-topology",
"nym-validator-client",
"rand 0.8.5",
"rand",
"serde",
"serde_json",
"sha2 0.10.8",
@@ -4658,7 +4635,7 @@ dependencies = [
"nym-bin-common",
"nym-node-tester-utils",
"nym-node-tester-wasm",
"rand 0.8.5",
"rand",
"serde",
"serde-wasm-bindgen 0.6.5",
"serde_json",
@@ -4695,8 +4672,8 @@ dependencies = [
"itertools 0.13.0",
"nym-dkg",
"nym-pemstore",
"rand 0.8.5",
"rand_chacha 0.3.1",
"rand",
"rand_chacha",
"serde",
"serde_derive",
"sha2 0.9.9",
@@ -4742,7 +4719,7 @@ dependencies = [
"itertools 0.12.1",
"nym-network-defaults",
"nym-pemstore",
"rand 0.8.5",
"rand",
"rayon",
"serde",
"sha2 0.9.9",
@@ -4836,7 +4813,7 @@ dependencies = [
"nym-ecash-time",
"nym-network-defaults",
"nym-validator-client",
"rand 0.8.5",
"rand",
"serde",
"thiserror",
"time",
@@ -4851,7 +4828,7 @@ dependencies = [
"nym-compact-ecash",
"nym-ecash-time",
"nym-network-defaults",
"rand 0.8.5",
"rand",
"serde",
"strum 0.25.0",
"thiserror",
@@ -4874,8 +4851,8 @@ dependencies = [
"hmac",
"nym-pemstore",
"nym-sphinx-types",
"rand 0.8.5",
"rand_chacha 0.3.1",
"rand",
"rand_chacha",
"serde",
"serde_bytes",
"subtle-encoding",
@@ -4897,8 +4874,8 @@ dependencies = [
"lazy_static",
"nym-contracts-common",
"nym-pemstore",
"rand 0.8.5",
"rand_chacha 0.3.1",
"rand",
"rand_chacha",
"rand_core 0.6.4",
"serde",
"serde_derive",
@@ -5028,7 +5005,7 @@ dependencies = [
"nym-wireguard",
"nym-wireguard-types",
"once_cell",
"rand 0.8.5",
"rand",
"serde",
"serde_json",
"si-scale",
@@ -5063,7 +5040,7 @@ dependencies = [
"nym-sphinx",
"nym-task",
"nym-validator-client",
"rand 0.8.5",
"rand",
"serde",
"si-scale",
"thiserror",
@@ -5092,7 +5069,8 @@ dependencies = [
"nym-crypto",
"nym-pemstore",
"nym-sphinx",
"rand 0.8.5",
"nym-task",
"rand",
"serde",
"serde_json",
"thiserror",
@@ -5192,7 +5170,7 @@ name = "nym-inclusion-probability"
version = "0.1.0"
dependencies = [
"log",
"rand 0.8.5",
"rand",
"thiserror",
]
@@ -5205,7 +5183,7 @@ dependencies = [
"nym-bin-common",
"nym-crypto",
"nym-sphinx",
"rand 0.8.5",
"rand",
"serde",
"thiserror",
"time",
@@ -5242,7 +5220,7 @@ dependencies = [
"nym-types",
"nym-wireguard",
"nym-wireguard-types",
"rand 0.8.5",
"rand",
"reqwest 0.12.4",
"serde",
"serde_json",
@@ -5299,7 +5277,7 @@ dependencies = [
"humantime-serde",
"log",
"nym-contracts-common",
"rand_chacha 0.3.1",
"rand_chacha",
"schemars",
"serde",
"serde-json-wasm",
@@ -5342,7 +5320,7 @@ dependencies = [
"nym-topology",
"nym-types",
"nym-validator-client",
"rand 0.8.5",
"rand",
"serde",
"serde_json",
"sysinfo 0.27.8",
@@ -5375,7 +5353,7 @@ dependencies = [
"nym-sphinx-types",
"nym-task",
"nym-validator-client",
"rand 0.8.5",
"rand",
"serde",
"thiserror",
"time",
@@ -5412,7 +5390,7 @@ dependencies = [
[[package]]
name = "nym-network-requester"
version = "1.1.40"
version = "1.1.41"
dependencies = [
"addr",
"anyhow",
@@ -5445,7 +5423,7 @@ dependencies = [
"nym-types",
"pretty_env_logger",
"publicsuffix",
"rand 0.8.5",
"rand",
"regex",
"reqwest 0.12.4",
"serde",
@@ -5463,7 +5441,7 @@ dependencies = [
[[package]]
name = "nym-node"
version = "1.1.6"
version = "1.1.7"
dependencies = [
"anyhow",
"bip39",
@@ -5492,7 +5470,7 @@ dependencies = [
"nym-types",
"nym-wireguard",
"nym-wireguard-types",
"rand 0.8.5",
"rand",
"semver 1.0.23",
"serde",
"serde_json",
@@ -5526,7 +5504,7 @@ dependencies = [
"nym-task",
"nym-wireguard",
"nym-wireguard-types",
"rand 0.8.5",
"rand",
"serde_json",
"thiserror",
"time",
@@ -5553,7 +5531,7 @@ dependencies = [
"nym-exit-policy",
"nym-http-api-client",
"nym-wireguard-types",
"rand_chacha 0.3.1",
"rand_chacha",
"schemars",
"serde",
"serde_json",
@@ -5574,7 +5552,7 @@ dependencies = [
"nym-sphinx-params",
"nym-task",
"nym-topology",
"rand 0.8.5",
"rand",
"serde",
"serde_json",
"thiserror",
@@ -5589,7 +5567,7 @@ dependencies = [
"futures",
"js-sys",
"nym-node-tester-utils",
"rand 0.8.5",
"rand",
"serde",
"serde-wasm-bindgen 0.6.5",
"thiserror",
@@ -5648,7 +5626,7 @@ dependencies = [
"fastrand 2.1.0",
"getrandom",
"log",
"rand 0.8.5",
"rand",
"rayon",
"sphinx-packet",
"thiserror",
@@ -5697,7 +5675,7 @@ dependencies = [
"nym-validator-client",
"parking_lot 0.12.3",
"pretty_env_logger",
"rand 0.8.5",
"rand",
"reqwest 0.12.4",
"tap",
"thiserror",
@@ -5737,7 +5715,7 @@ dependencies = [
[[package]]
name = "nym-socks5-client"
version = "1.1.39"
version = "1.1.40"
dependencies = [
"bs58 0.5.1",
"clap 4.5.7",
@@ -5757,7 +5735,7 @@ dependencies = [
"nym-sphinx",
"nym-topology",
"nym-validator-client",
"rand 0.8.5",
"rand",
"serde",
"serde_json",
"tap",
@@ -5790,7 +5768,7 @@ dependencies = [
"nym-task",
"nym-validator-client",
"pin-project",
"rand 0.8.5",
"rand",
"reqwest 0.12.4",
"schemars",
"serde",
@@ -5816,7 +5794,7 @@ dependencies = [
"nym-credential-storage",
"nym-crypto",
"nym-socks5-client-core",
"rand 0.8.5",
"rand",
"safer-ffi",
"serde",
"tokio",
@@ -5870,7 +5848,7 @@ dependencies = [
"nym-sphinx-routing",
"nym-sphinx-types",
"nym-topology",
"rand 0.8.5",
"rand",
"rand_distr",
"thiserror",
"tokio",
@@ -5888,7 +5866,7 @@ dependencies = [
"nym-sphinx-routing",
"nym-sphinx-types",
"nym-topology",
"rand 0.8.5",
"rand",
"serde",
"thiserror",
"zeroize",
@@ -5900,7 +5878,7 @@ version = "0.1.0"
dependencies = [
"nym-crypto",
"nym-sphinx-types",
"rand 0.8.5",
"rand",
"serde",
"thiserror",
]
@@ -5916,8 +5894,8 @@ dependencies = [
"nym-sphinx-routing",
"nym-sphinx-types",
"nym-topology",
"rand 0.8.5",
"rand_chacha 0.3.1",
"rand",
"rand_chacha",
"serde",
"thiserror",
"wasm-bindgen",
@@ -5931,7 +5909,7 @@ dependencies = [
"nym-sphinx-addressing",
"nym-sphinx-params",
"nym-sphinx-types",
"rand 0.8.5",
"rand",
"thiserror",
]
@@ -5948,7 +5926,7 @@ dependencies = [
"nym-sphinx-routing",
"nym-sphinx-types",
"nym-topology",
"rand 0.8.5",
"rand",
"thiserror",
]
@@ -6010,7 +5988,7 @@ dependencies = [
"argon2",
"generic-array 0.14.7",
"getrandom",
"rand 0.8.5",
"rand",
"serde",
"serde_json",
"thiserror",
@@ -6045,7 +6023,7 @@ dependencies = [
"nym-sphinx-addressing",
"nym-sphinx-routing",
"nym-sphinx-types",
"rand 0.8.5",
"rand",
"semver 0.11.0",
"serde",
"serde_json",
@@ -6169,7 +6147,7 @@ dependencies = [
"nym-task",
"nym-validator-client",
"nyxd-scraper",
"rand_chacha 0.3.1",
"rand_chacha",
"serde",
"serde_with",
"sha2 0.10.8",
@@ -6248,7 +6226,7 @@ dependencies = [
"nym-config",
"nym-crypto",
"nym-network-defaults",
"rand 0.8.5",
"rand",
"serde",
"serde_json",
"sha2 0.10.8",
@@ -6259,7 +6237,7 @@ dependencies = [
[[package]]
name = "nymvisor"
version = "0.1.5"
version = "0.1.6"
dependencies = [
"anyhow",
"bytes",
@@ -6458,7 +6436,7 @@ dependencies = [
"once_cell",
"opentelemetry_api",
"percent-encoding",
"rand 0.8.5",
"rand",
"thiserror",
"tokio",
"tokio-stream",
@@ -6771,7 +6749,7 @@ version = "2.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce"
dependencies = [
"autocfg 1.3.0",
"autocfg",
"bitflags 1.3.2",
"cfg-if",
"concurrent-queue",
@@ -7025,25 +7003,6 @@ version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09"
[[package]]
name = "rand"
version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca"
dependencies = [
"autocfg 0.1.8",
"libc",
"rand_chacha 0.1.1",
"rand_core 0.4.2",
"rand_hc",
"rand_isaac",
"rand_jitter",
"rand_os",
"rand_pcg 0.1.2",
"rand_xorshift",
"winapi",
]
[[package]]
name = "rand"
version = "0.8.5"
@@ -7051,20 +7010,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"libc",
"rand_chacha 0.3.1",
"rand_chacha",
"rand_core 0.6.4",
]
[[package]]
name = "rand_chacha"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef"
dependencies = [
"autocfg 0.1.8",
"rand_core 0.3.1",
]
[[package]]
name = "rand_chacha"
version = "0.3.1"
@@ -7075,21 +7024,6 @@ dependencies = [
"rand_core 0.6.4",
]
[[package]]
name = "rand_core"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
dependencies = [
"rand_core 0.4.2",
]
[[package]]
name = "rand_core"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
[[package]]
name = "rand_core"
version = "0.5.1"
@@ -7112,60 +7046,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32cb0b9bc82b0a0876c2dd994a7e7a2683d3e7390ca40e6886785ef0c7e3ee31"
dependencies = [
"num-traits",
"rand 0.8.5",
]
[[package]]
name = "rand_hc"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4"
dependencies = [
"rand_core 0.3.1",
]
[[package]]
name = "rand_isaac"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08"
dependencies = [
"rand_core 0.3.1",
]
[[package]]
name = "rand_jitter"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b"
dependencies = [
"libc",
"rand_core 0.4.2",
"winapi",
]
[[package]]
name = "rand_os"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071"
dependencies = [
"cloudabi",
"fuchsia-cprng",
"libc",
"rand_core 0.4.2",
"rdrand",
"winapi",
]
[[package]]
name = "rand_pcg"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44"
dependencies = [
"autocfg 0.1.8",
"rand_core 0.4.2",
"rand",
]
[[package]]
@@ -7186,15 +7067,6 @@ dependencies = [
"rand_core 0.6.4",
]
[[package]]
name = "rand_xorshift"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c"
dependencies = [
"rand_core 0.3.1",
]
[[package]]
name = "rayon"
version = "1.10.0"
@@ -7215,15 +7087,6 @@ dependencies = [
"crossbeam-utils",
]
[[package]]
name = "rdrand"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
dependencies = [
"rand_core 0.3.1",
]
[[package]]
name = "redox_syscall"
version = "0.2.16"
@@ -7481,7 +7344,7 @@ dependencies = [
"num_cpus",
"parking_lot 0.12.3",
"pin-project-lite",
"rand 0.8.5",
"rand",
"ref-cast",
"rocket_codegen",
"rocket_http",
@@ -8254,7 +8117,7 @@ version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67"
dependencies = [
"autocfg 1.3.0",
"autocfg",
]
[[package]]
@@ -8325,7 +8188,7 @@ dependencies = [
"hmac",
"lioness",
"log",
"rand 0.8.5",
"rand",
"rand_distr",
"sha2 0.10.8",
"subtle 2.5.0",
@@ -8869,7 +8732,7 @@ dependencies = [
"getrandom",
"peg",
"pin-project",
"rand 0.8.5",
"rand",
"reqwest 0.11.27",
"semver 1.0.23",
"serde",
@@ -8923,7 +8786,7 @@ dependencies = [
"nym-pemstore",
"nym-validator-client",
"nym-vesting-contract-common",
"rand 0.8.5",
"rand",
"serde",
"serde_json",
"sqlx",
@@ -9323,7 +9186,7 @@ dependencies = [
"indexmap 1.9.3",
"pin-project",
"pin-project-lite",
"rand 0.8.5",
"rand",
"slab",
"tokio",
"tokio-util",
@@ -9589,7 +9452,7 @@ dependencies = [
"http 0.2.12",
"httparse",
"log",
"rand 0.8.5",
"rand",
"rustls 0.21.12",
"sha1",
"thiserror",
@@ -9610,7 +9473,7 @@ dependencies = [
"http 1.1.0",
"httparse",
"log",
"rand 0.8.5",
"rand",
"rustls 0.22.4",
"rustls-pki-types",
"sha1",
@@ -10030,7 +9893,7 @@ dependencies = [
"nym-task",
"nym-topology",
"nym-validator-client",
"rand 0.8.5",
"rand",
"serde",
"serde-wasm-bindgen 0.6.5",
"thiserror",
@@ -10665,7 +10528,7 @@ dependencies = [
"nym-credentials",
"nym-crypto",
"nym-http-api-client",
"rand 0.8.5",
"rand",
"reqwest 0.12.4",
"serde",
"thiserror",
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "nym-client"
version = "1.1.39"
version = "1.1.40"
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jędrzej Stuczyński <andrew@nymtech.net>"]
description = "Implementation of the Nym Client"
edition = "2021"
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "nym-socks5-client"
version = "1.1.39"
version = "1.1.40"
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"
@@ -2,7 +2,9 @@
// SPDX-License-Identifier: Apache-2.0
use crate::error::BandwidthControllerError;
use crate::utils::{get_coin_index_signatures, get_expiration_date_signatures};
use crate::utils::{
get_aggregate_verification_key, get_coin_index_signatures, get_expiration_date_signatures,
};
use log::info;
use nym_credential_storage::storage::Storage;
use nym_credentials::ecash::bandwidth::IssuanceTicketBook;
@@ -55,7 +57,7 @@ where
))
}
pub async fn query_and_persist_required_global_signatures<S>(
pub async fn query_and_persist_required_global_data<S>(
storage: &S,
epoch_id: EpochId,
expiration_date: Date,
@@ -65,6 +67,10 @@ where
S: Storage,
<S as Storage>::StorageError: Send + Sync + 'static,
{
log::info!("Getting master verification key");
// this will also persist the key in the storage if was not there already
get_aggregate_verification_key(storage, epoch_id, apis.clone()).await?;
log::info!("Getting expiration date signatures");
// this will also persist the signatures in the storage if they were not there already
get_expiration_date_signatures(storage, epoch_id, expiration_date, apis.clone()).await?;
+4 -2
View File
@@ -16,7 +16,7 @@ use nym_credential_storage::models::RetrievedTicketbook;
use nym_credential_storage::storage::Storage;
use nym_credentials::ecash::bandwidth::CredentialSpendingData;
use nym_credentials_interface::{
AnnotatedCoinIndexSignature, AnnotatedExpirationDateSignature, NymPayInfo, VerificationKeyAuth,
AnnotatedCoinIndexSignature, AnnotatedExpirationDateSignature, VerificationKeyAuth,
};
use nym_ecash_time::Date;
use nym_validator_client::nym_api::EpochId;
@@ -165,7 +165,9 @@ impl<C, St: Storage> BandwidthController<C, St> {
.get_coin_index_signatures(epoch_id, &mut api_clients)
.await?;
let pay_info = NymPayInfo::generate(provider_pk);
let pay_info = retrieved_ticketbook
.ticketbook
.generate_pay_info(provider_pk);
let spend_request = retrieved_ticketbook.ticketbook.prepare_for_spending(
&verification_key,
@@ -417,6 +417,8 @@ impl<C, St> GatewayClient<C, St> {
self.local_identity.as_ref(),
self.gateway_identity,
self.cfg.bandwidth.require_tickets,
#[cfg(not(target_arch = "wasm32"))]
self.task_client.clone(),
)
.await
.map_err(GatewayClientError::RegistrationFailure),
@@ -1,6 +1,7 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::nyxd::cosmwasm_client::types::ExecuteResult;
use crate::nyxd::error::NyxdError;
use cosmrs::abci::TxMsgData;
use cosmrs::cosmwasm::MsgExecuteContractResponse;
@@ -9,7 +10,6 @@ use log::error;
use prost::bytes::Bytes;
use tendermint_rpc::endpoint::broadcast;
use crate::nyxd::cosmwasm_client::types::ExecuteResult;
pub use cosmrs::abci::MsgResponse;
pub fn parse_msg_responses(data: Bytes) -> Vec<MsgResponse> {
@@ -21,7 +21,8 @@ pub struct Log {
/// Searches in logs for the first event of the given event type and in that event
/// for the first attribute with the given attribute key.
pub fn find_attribute<'a>(
#[deprecated]
pub fn find_attribute_in_logs<'a>(
logs: &'a [Log],
event_type: &str,
attribute_key: &str,
@@ -35,6 +36,7 @@ pub fn find_attribute<'a>(
}
/// Search for the proposal id in the given log. It'll be in the LAST wasm event, with attribute key "proposal_id"
#[deprecated]
pub fn find_proposal_id(logs: &[Log]) -> Result<u64, NyxdError> {
let maybe_attributes = logs
.iter()
@@ -1,12 +1,24 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::nyxd::cosmwasm_client::logs::Log;
use crate::nyxd::TxResponse;
use cosmrs::tendermint::abci;
pub use abci::Event;
// Searches in events for an event of the given event type which contains an
// attribute for with the given key.
pub fn find_tx_attribute(tx: &TxResponse, event_type: &str, attribute_key: &str) -> Option<String> {
let event = tx.tx_result.events.iter().find(|e| e.kind == event_type)?;
find_event_attribute(&tx.tx_result.events, event_type, attribute_key)
}
pub fn find_event_attribute(
events: &[Event],
event_type: &str,
attribute_key: &str,
) -> Option<String> {
let event = events.iter().find(|e| e.kind == event_type)?;
let attribute = event.attributes.iter().find(|&attr| {
if let Ok(key_str) = attr.key_str() {
key_str == attribute_key
@@ -16,3 +28,23 @@ pub fn find_tx_attribute(tx: &TxResponse, event_type: &str, attribute_key: &str)
})?;
Some(attribute.value_str().ok().map(|str| str.to_string())).flatten()
}
pub fn find_attribute_value_in_logs_or_events(
logs: &[Log],
events: &[Event],
event_type: &str,
attribute_key: &str,
) -> Option<String> {
// if logs are empty, i.e. we're using post 0.50 code, parse the events instead
if !logs.is_empty() {
#[allow(deprecated)]
return crate::nyxd::cosmwasm_client::logs::find_attribute_in_logs(
logs,
event_type,
attribute_key,
)
.map(|attr| attr.value.clone());
}
find_event_attribute(events, event_type, attribute_key)
}
+5 -4
View File
@@ -7,9 +7,10 @@ license.workspace = true
[dependencies]
anyhow = { workspace = true }
base64 = "0.13.0"
base64 = { workspace = true }
bip39 = { workspace = true }
bs58 = { workspace = true }
colored = { workspace = true }
comfy-table = { workspace = true }
cfg-if = { workspace = true }
clap = { workspace = true, features = ["derive"] }
@@ -21,13 +22,13 @@ humantime-serde = { workspace = true }
inquire = { workspace = true }
k256 = { workspace = true, features = ["ecdsa", "sha256"] }
log = { workspace = true }
rand = {version = "0.6", features = ["std"] }
rand = { workspace = true, features = ["std"] }
serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true }
thiserror = { workspace = true }
time = { workspace = true, features = ["parsing", "formatting"] }
tokio = { workspace = true, features = ["sync"]}
toml = "0.5.6"
tokio = { workspace = true, features = ["sync"] }
toml = { workspace = true }
url = { workspace = true }
tap = { workspace = true }
zeroize = { workspace = true }
@@ -0,0 +1,178 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::utils::CommonConfigsWrapper;
use anyhow::{anyhow, bail};
use clap::Parser;
use colored::Colorize;
use comfy_table::Table;
use nym_credential_storage::initialise_persistent_storage;
use nym_credential_storage::storage::Storage;
use nym_credentials::ecash::bandwidth::serialiser::VersionedSerialise;
use std::path::PathBuf;
#[derive(Debug, Parser)]
pub struct Args {
/// Specify the index of the ticket to retrieve from the ticketbook.
/// By default, the current unspent value is used.
#[clap(long, group = "output")]
pub(crate) ticket_index: Option<u64>,
/// Specify whether we should display payments for ALL available tickets
#[clap(long, group = "output")]
pub(crate) full: bool,
/// Base58-encoded identity of the provider (must be 32 bytes long)
#[clap(long)]
pub(crate) provider: String,
/// Config file of the client that is supposed to use the credential.
#[clap(long, group = "source")]
pub(crate) client_config: Option<PathBuf>,
/// Path to the dedicated credential storage database
#[clap(long, group = "source")]
pub(crate) credential_storage: Option<PathBuf>,
}
pub async fn execute(args: Args) -> anyhow::Result<()> {
let credentials_store = if let Some(explicit) = args.credential_storage {
explicit
} else {
// SAFETY: at least one of them MUST HAVE been specified
let cfg = args.client_config.unwrap();
let loaded = CommonConfigsWrapper::try_load(cfg)?;
if let Ok(id) = loaded.try_get_id() {
println!("loaded config file for client '{id}'");
}
let Ok(credentials_store) = loaded.try_get_credentials_store() else {
bail!("the loaded config does not have a credentials store information")
};
credentials_store
};
let decoded_provider = bs58::decode(&args.provider).into_vec()?;
if decoded_provider.len() != 32 {
bail!("the provided provider information is malformed")
}
let provider_arr: [u8; 32] = decoded_provider.try_into().unwrap();
let persistent_storage = initialise_persistent_storage(&credentials_store).await;
let Some(mut next_ticketbook) = persistent_storage
.get_next_unspent_usable_ticketbook(0)
.await?
else {
bail!(
"there are no valid ticketbooks in the storage at {}",
credentials_store.display()
)
};
let epoch_id = next_ticketbook.ticketbook.epoch_id();
let expiration_date = next_ticketbook.ticketbook.expiration_date();
let verification_key = persistent_storage
.get_master_verification_key(epoch_id)
.await?
.ok_or_else(|| {
anyhow!("ticketbook got incorrectly imported - the master verification key is missing")
})?;
let expiration_signatures = persistent_storage
.get_expiration_date_signatures(expiration_date)
.await?
.ok_or_else(|| {
anyhow!(
"ticketbook got incorrectly imported - the expiration date signatures are missing"
)
})?;
let coin_indices_signatures = persistent_storage
.get_coin_index_signatures(epoch_id)
.await?
.ok_or_else(|| {
anyhow!("ticketbook got incorrectly imported - the coin index signatures are missing")
})?;
let ticketbook_data = next_ticketbook.ticketbook.pack();
let next_ticket = args
.ticket_index
.unwrap_or(next_ticketbook.ticketbook.spent_tickets());
let pay_info = next_ticketbook.ticketbook.generate_pay_info(provider_arr);
println!("{}", "TICKETBOOK DATA:".bold());
println!("{}", bs58::encode(&ticketbook_data.data).into_string());
println!();
// display it only for a single ticket
if !args.full {
println!("attempting to generate payment for ticket {next_ticket}...");
println!();
next_ticketbook.ticketbook.update_spent_tickets(next_ticket);
let req = next_ticketbook.ticketbook.prepare_for_spending(
&verification_key,
pay_info.into(),
&coin_indices_signatures,
&expiration_signatures,
1,
)?;
let payment = req.payment;
println!("{}", format!("PAYMENT FOR TICKET {next_ticket}: ").bold());
println!("{}", bs58::encode(&payment.to_bytes()).into_string());
return Ok(());
}
println!(
"generating payment information for {} tickets. this might take a while!...",
next_ticketbook.ticketbook.params_total_tickets()
);
// otherwise generate all the payments
let last_spent = next_ticketbook.ticketbook.spent_tickets();
let mut table = Table::new();
table.set_header(vec!["index", "binary data", "spend status"]);
for i in 0..next_ticketbook.ticketbook.params_total_tickets() {
let status = if i < last_spent {
"SPENT".red()
} else {
"NOT SPENT".green()
};
next_ticketbook.ticketbook.update_spent_tickets(i);
let req = next_ticketbook.ticketbook.prepare_for_spending(
&verification_key,
pay_info.into(),
&coin_indices_signatures,
&expiration_signatures,
1,
)?;
let payment = req.payment;
let payment_bytes = payment.to_bytes();
let len = payment_bytes.len();
let display_size = 100;
let remaining = len - display_size;
table.add_row(vec![
i.to_string(),
format!(
"{}{remaining}bytes remaining",
bs58::encode(&payment_bytes[..display_size]).into_string()
),
status.to_string(),
]);
}
println!("{}", "AVAILABLE TICKETS".bold());
println!("{table}");
Ok(())
}
@@ -9,9 +9,17 @@ use nym_credential_storage::initialise_persistent_storage;
use nym_id::import_credential;
use std::fs;
use std::path::PathBuf;
use std::str::FromStr;
fn parse_encoded_credential_data(raw: &str) -> bs58::decode::Result<Vec<u8>> {
bs58::decode(raw).into_vec()
#[derive(Debug, Clone)]
pub struct CredentialDataWrapper(Vec<u8>);
impl FromStr for CredentialDataWrapper {
type Err = bs58::decode::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
bs58::decode(s).into_vec().map(CredentialDataWrapper)
}
}
#[derive(Debug, Parser)]
@@ -22,8 +30,8 @@ pub struct Args {
pub(crate) client_config: PathBuf,
/// Explicitly provide the encoded credential data (as base58)
#[clap(long, group = "cred_data", value_parser = parse_encoded_credential_data)]
pub(crate) credential_data: Option<Vec<u8>>,
#[clap(long, group = "cred_data")]
pub(crate) credential_data: Option<CredentialDataWrapper>,
/// Specifies the path to file containing binary credential data
#[clap(long, group = "cred_data")]
@@ -52,7 +60,7 @@ pub async fn execute(args: Args) -> anyhow::Result<()> {
let credentials_store = initialise_persistent_storage(credentials_store).await;
let raw_credential = match args.credential_data {
Some(data) => data,
Some(data) => data.0,
None => {
// SAFETY: one of those arguments must have been set
fs::read(args.credential_path.unwrap())?
@@ -9,6 +9,9 @@ use nym_credential_storage::initialise_persistent_storage;
use nym_credential_utils::utils;
use nym_credentials_interface::TicketType;
use nym_crypto::asymmetric::identity;
use rand::rngs::OsRng;
use rand::RngCore;
use std::fs::create_dir_all;
use std::path::PathBuf;
#[derive(Debug, Parser)]
@@ -18,12 +21,20 @@ pub struct Args {
pub(crate) ticketbook_type: TicketType,
/// Config file of the client that is supposed to use the credential.
#[clap(long)]
pub(crate) client_config: PathBuf,
#[clap(long, group = "output")]
pub(crate) client_config: Option<PathBuf>,
/// Path to the dedicated credential storage database
#[clap(long, group = "output")]
pub(crate) credential_storage: Option<PathBuf>,
}
pub async fn execute(args: Args, client: SigningClient) -> anyhow::Result<()> {
let loaded = CommonConfigsWrapper::try_load(args.client_config)?;
async fn issue_client_ticketbook(
cfg: PathBuf,
typ: TicketType,
client: SigningClient,
) -> anyhow::Result<()> {
let loaded = CommonConfigsWrapper::try_load(cfg)?;
if let Ok(id) = loaded.try_get_id() {
println!("loaded config file for client '{id}'");
@@ -48,9 +59,40 @@ pub async fn execute(args: Args, client: SigningClient) -> anyhow::Result<()> {
&client,
&persistent_storage,
&private_id_key.to_bytes(),
args.ticketbook_type,
typ,
)
.await?;
Ok(())
}
async fn issue_standalone_ticketbook(
credentials_store: PathBuf,
typ: TicketType,
client: SigningClient,
) -> anyhow::Result<()> {
println!("attempting to issue a standalone ticketbook");
let mut rng = OsRng;
let mut random_seed = [0u8; 32];
rng.fill_bytes(&mut random_seed);
if let Some(parent) = credentials_store.parent() {
create_dir_all(parent)?;
}
let persistent_storage = initialise_persistent_storage(credentials_store).await;
utils::issue_credential(&client, &persistent_storage, &random_seed, typ).await?;
Ok(())
}
pub async fn execute(args: Args, client: SigningClient) -> anyhow::Result<()> {
match (args.client_config, args.credential_storage) {
(Some(cfg), None) => issue_client_ticketbook(cfg, args.ticketbook_type, client).await,
(None, Some(storage)) => {
issue_standalone_ticketbook(storage, args.ticketbook_type, client).await
}
_ => unreachable!("clap should have made this branch impossible to reach!"),
}
}
@@ -3,6 +3,7 @@
use clap::{Args, Subcommand};
pub mod generate_ticket;
pub mod import_ticket_book;
pub mod issue_ticket_book;
pub mod recover_ticket_book;
@@ -19,4 +20,5 @@ pub enum EcashCommands {
IssueTicketBook(issue_ticket_book::Args),
RecoverTicketBook(recover_ticket_book::Args),
ImportTicketBook(import_ticket_book::Args),
GenerateTicket(generate_ticket::Args),
}
+1 -1
View File
@@ -1,7 +1,7 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
pub mod coconut;
pub mod context;
pub mod ecash;
pub mod utils;
pub mod validator;
@@ -10,7 +10,11 @@ pub struct Args {
}
pub fn decode_mixnode_key(args: Args) {
let b64_decoded = base64::decode(args.key).expect("failed to decode base64 string");
use base64::{engine::general_purpose::STANDARD, Engine as _};
let b64_decoded = STANDARD
.decode(args.key)
.expect("failed to decode base64 string");
let b58_encoded = bs58::encode(&b64_decoded).into_string();
println!("{b58_encoded}")
@@ -6,14 +6,14 @@ use clap::Parser;
use cosmwasm_std::Uint128;
use log::info;
use nym_mixnet_contract_common::{MixNodeCostParams, Percent};
use nym_validator_client::nyxd::contract_traits::MixnetSigningClient;
use nym_validator_client::nyxd::contract_traits::{MixnetQueryClient, MixnetSigningClient};
use nym_validator_client::nyxd::CosmWasmCoin;
#[derive(Debug, Parser)]
pub struct Args {
#[clap(
long,
help = "input your profit margin as follows; (so it would be 10, rather than 0.1)"
help = "input your profit margin as follows; (so it would be 20, rather than 0.2)"
)]
pub profit_margin_percent: Option<u8>,
@@ -27,11 +27,48 @@ pub struct Args {
pub async fn update_cost_params(args: Args, client: SigningClient) {
let denom = client.current_chain_details().mix_denom.base.as_str();
fn convert_to_percent(value: u64) -> Percent {
Percent::from_percentage_value(value).expect("Invalid value")
}
let default_profit_margin: Percent = convert_to_percent(20);
let mixownership_response = match client.get_owned_mixnode(&client.address()).await {
Ok(response) => response,
Err(_) => {
eprintln!("Failed to obtain owned mixnode");
return;
}
};
let mix_id = match mixownership_response.mixnode_details {
Some(details) => details.bond_information.mix_id,
None => {
eprintln!("Failed to obtain mixnode details");
return;
}
};
let rewarding_response = match client.get_mixnode_rewarding_details(mix_id).await {
Ok(details) => details,
Err(_) => {
eprintln!("Failed to obtain rewarding details");
return;
}
};
let profit_margin_percent = rewarding_response
.rewarding_details
.map(|rd| rd.cost_params.profit_margin_percent)
.unwrap_or(default_profit_margin);
let profit_margin_value = args
.profit_margin_percent
.map(|pm| convert_to_percent(pm as u64))
.unwrap_or(profit_margin_percent);
let cost_params = MixNodeCostParams {
profit_margin_percent: Percent::from_percentage_value(
args.profit_margin_percent.unwrap_or(10) as u64,
)
.unwrap(),
profit_margin_percent: profit_margin_value,
interval_operating_cost: CosmWasmCoin {
denom: denom.into(),
amount: Uint128::new(args.interval_operating_cost.unwrap_or(40_000_000)),
+5 -11
View File
@@ -3,9 +3,7 @@
use crate::errors::{Error, Result};
use log::*;
use nym_bandwidth_controller::acquire::{
get_ticket_book, query_and_persist_required_global_signatures,
};
use nym_bandwidth_controller::acquire::{get_ticket_book, query_and_persist_required_global_data};
use nym_client_core::config::disk_persistence::CommonClientPaths;
use nym_config::DEFAULT_DATA_DIR;
use nym_credential_storage::persistent_storage::PersistentStorage;
@@ -45,14 +43,10 @@ where
let apis = all_ecash_api_clients(client, epoch_id).await?;
let ticketbook_expiration = ecash_default_expiration_date();
// make sure we have all required coin indices and expiration date signatures before attempting the deposit
query_and_persist_required_global_signatures(
storage,
epoch_id,
ticketbook_expiration,
apis.clone(),
)
.await?;
// make sure we have all required coin indices and expiration date signatures alongside the master verification key
// before attempting the deposit
query_and_persist_required_global_data(storage, epoch_id, ticketbook_expiration, apis.clone())
.await?;
let issuance_data = nym_bandwidth_controller::acquire::make_deposit(
client,
@@ -6,7 +6,7 @@ use crate::ecash::bandwidth::CredentialSpendingData;
use crate::ecash::utils::ecash_today;
use crate::error::Error;
use nym_credentials_interface::{
CoinIndexSignature, ExpirationDateSignature, PayInfo, SecretKeyUser, TicketType,
CoinIndexSignature, ExpirationDateSignature, NymPayInfo, PayInfo, SecretKeyUser, TicketType,
VerificationKeyAuth, Wallet, WalletSignatures,
};
use nym_ecash_time::EcashTime;
@@ -114,6 +114,10 @@ impl IssuedTicketBook {
&self.signatures_wallet
}
pub fn generate_pay_info(&self, provider_pk: [u8; 32]) -> NymPayInfo {
NymPayInfo::generate(provider_pk)
}
pub fn prepare_for_spending<BI, BE>(
&mut self,
verification_key: &VerificationKeyAuth,
+1
View File
@@ -24,6 +24,7 @@ zeroize = { workspace = true }
nym-crypto = { path = "../crypto" }
nym-pemstore = { path = "../pemstore" }
nym-sphinx = { path = "../nymsphinx" }
nym-task = { path = "../task" }
nym-credentials = { path = "../credentials" }
nym-credentials-interface = { path = "../credentials-interface" }
@@ -25,6 +25,7 @@ impl<'a> ClientHandshake<'a> {
identity: &'a nym_crypto::asymmetric::identity::KeyPair,
gateway_pubkey: identity::PublicKey,
expects_credential_usage: bool,
#[cfg(not(target_arch = "wasm32"))] shutdown: nym_task::TaskClient,
) -> Self
where
S: Stream<Item = WsItem> + Sink<WsMessage> + Unpin + Send + 'a,
@@ -35,6 +36,8 @@ impl<'a> ClientHandshake<'a> {
identity,
Some(gateway_pubkey),
expects_credential_usage,
#[cfg(not(target_arch = "wasm32"))]
shutdown,
);
ClientHandshake {
@@ -25,6 +25,8 @@ pub enum HandshakeError {
MalformedRequest,
#[error("sent request was malformed")]
HandshakeFailure,
#[error("received shutdown")]
ReceivedShutdown,
#[error("timed out waiting for a handshake message")]
Timeout,
@@ -8,6 +8,7 @@ use futures::future::BoxFuture;
use futures::task::{Context, Poll};
use futures::{Future, Sink, Stream};
use nym_crypto::asymmetric::encryption;
use nym_task::TaskClient;
use rand::{CryptoRng, RngCore};
use std::pin::Pin;
use tungstenite::Message as WsMessage;
@@ -22,11 +23,12 @@ impl<'a> GatewayHandshake<'a> {
ws_stream: &'a mut S,
identity: &'a nym_crypto::asymmetric::identity::KeyPair,
received_init_payload: Vec<u8>,
shutdown: TaskClient,
) -> Self
where
S: Stream<Item = WsItem> + Sink<WsMessage> + Unpin + Send + 'a,
{
let mut state = State::new(rng, ws_stream, identity, None, true);
let mut state = State::new(rng, ws_stream, identity, None, true, shutdown);
GatewayHandshake {
handshake_future: Box::pin(async move {
// If any step along the way failed (that are non-network related),
@@ -8,6 +8,8 @@ use self::gateway::GatewayHandshake;
pub use self::shared_key::{SharedKeySize, SharedKeys};
use futures::{Sink, Stream};
use nym_crypto::asymmetric::identity;
#[cfg(not(target_arch = "wasm32"))]
use nym_task::TaskClient;
use rand::{CryptoRng, RngCore};
use tungstenite::{Error as WsError, Message as WsMessage};
@@ -31,6 +33,7 @@ pub async fn client_handshake<'a, S>(
identity: &'a identity::KeyPair,
gateway_pubkey: identity::PublicKey,
expects_credential_usage: bool,
#[cfg(not(target_arch = "wasm32"))] shutdown: TaskClient,
) -> Result<SharedKeys, HandshakeError>
where
S: Stream<Item = WsItem> + Sink<WsMessage> + Unpin + Send + 'a,
@@ -41,6 +44,8 @@ where
identity,
gateway_pubkey,
expects_credential_usage,
#[cfg(not(target_arch = "wasm32"))]
shutdown,
)
.await
}
@@ -51,11 +56,12 @@ pub async fn gateway_handshake<'a, S>(
ws_stream: &'a mut S,
identity: &'a identity::KeyPair,
received_init_payload: Vec<u8>,
shutdown: TaskClient,
) -> Result<SharedKeys, HandshakeError>
where
S: Stream<Item = WsItem> + Sink<WsMessage> + Unpin + Send + 'a,
{
GatewayHandshake::new(rng, ws_stream, identity, received_init_payload).await
GatewayHandshake::new(rng, ws_stream, identity, received_init_payload, shutdown).await
}
/*
@@ -13,6 +13,8 @@ use nym_crypto::{
symmetric::stream_cipher,
};
use nym_sphinx::params::{GatewayEncryptionAlgorithm, GatewaySharedKeyHkdfAlgorithm};
#[cfg(not(target_arch = "wasm32"))]
use nym_task::TaskClient;
use rand::{CryptoRng, RngCore};
use tracing::log::*;
@@ -48,6 +50,10 @@ pub(crate) struct State<'a, S> {
// this field is really out of place here, however, we need to propagate this information somehow
// in order to establish correct protocol for backwards compatibility reasons
expects_credential_usage: bool,
// channel to receive shutdown signal
#[cfg(not(target_arch = "wasm32"))]
shutdown: TaskClient,
}
impl<'a, S> State<'a, S> {
@@ -57,6 +63,7 @@ impl<'a, S> State<'a, S> {
identity: &'a identity::KeyPair,
remote_pubkey: Option<identity::PublicKey>,
expects_credential_usage: bool,
#[cfg(not(target_arch = "wasm32"))] shutdown: TaskClient,
) -> Self {
let ephemeral_keypair = encryption::KeyPair::new(rng);
State {
@@ -66,6 +73,8 @@ impl<'a, S> State<'a, S> {
remote_pubkey,
derived_shared_keys: None,
expects_credential_usage,
#[cfg(not(target_arch = "wasm32"))]
shutdown,
}
}
@@ -199,46 +208,76 @@ impl<'a, S> State<'a, S> {
self.remote_pubkey = Some(remote_pubkey)
}
fn on_wg_msg(msg: Option<WsItem>) -> Result<Option<Vec<u8>>, HandshakeError> {
let Some(msg) = msg else {
return Err(HandshakeError::ClosedStream);
};
let Ok(msg) = msg else {
return Err(HandshakeError::NetworkError);
};
match msg {
WsMessage::Text(ref ws_msg) => {
match types::RegistrationHandshake::from_str(ws_msg) {
Ok(reg_handshake_msg) => {
match reg_handshake_msg {
// hehe, that's a bit disgusting that the type system requires we explicitly ignore the
// protocol_version field that we actually never attach at this point
// yet another reason for the overdue refactor
types::RegistrationHandshake::HandshakePayload { data, .. } => {
Ok(Some(data))
}
types::RegistrationHandshake::HandshakeError { message } => {
Err(HandshakeError::RemoteError(message))
}
}
}
Err(_) => {
error!("Received a non-handshake message during the registration handshake! It's getting dropped. The received content was: '{msg}'");
Ok(None)
}
}
}
_ => {
error!("Received non-text message during registration handshake");
Ok(None)
}
}
}
#[cfg(not(target_arch = "wasm32"))]
async fn _receive_handshake_message(&mut self) -> Result<Vec<u8>, HandshakeError>
where
S: Stream<Item = WsItem> + Unpin,
{
loop {
let Some(msg) = self.ws_stream.next().await else {
return Err(HandshakeError::ClosedStream);
};
let Ok(msg) = msg else {
return Err(HandshakeError::NetworkError);
};
match msg {
WsMessage::Text(ref ws_msg) => {
match types::RegistrationHandshake::from_str(ws_msg) {
Ok(reg_handshake_msg) => {
return match reg_handshake_msg {
// hehe, that's a bit disgusting that the type system requires we explicitly ignore the
// protocol_version field that we actually never attach at this point
// yet another reason for the overdue refactor
types::RegistrationHandshake::HandshakePayload { data, .. } => {
Ok(data)
}
types::RegistrationHandshake::HandshakeError { message } => {
Err(HandshakeError::RemoteError(message))
}
};
}
Err(_) => {
error!("Received a non-handshake message during the registration handshake! It's getting dropped. The received content was: '{msg}'");
continue;
}
}
tokio::select! {
biased;
_ = self.shutdown.recv() => return Err(HandshakeError::ReceivedShutdown),
msg = self.ws_stream.next() => {
let Some(ret) = Self::on_wg_msg(msg)? else {
continue;
};
return Ok(ret);
}
_ => error!("Received non-text message during registration handshake"),
}
}
}
#[cfg(target_arch = "wasm32")]
async fn _receive_handshake_message(&mut self) -> Result<Vec<u8>, HandshakeError>
where
S: Stream<Item = WsItem> + Unpin,
{
loop {
let msg = self.ws_stream.next().await;
let Some(ret) = Self::on_wg_msg(msg)? else {
continue;
};
return Ok(ret);
}
}
pub(crate) async fn receive_handshake_message(&mut self) -> Result<Vec<u8>, HandshakeError>
where
S: Stream<Item = WsItem> + Unpin,
+2 -5
View File
@@ -10,8 +10,8 @@ license.workspace = true
[dependencies]
async-trait = { workspace = true }
bincode = { workspace = true, optional = true }
defguard_wireguard_rs = { workspace = true, optional = true }
bincode = { workspace = true }
defguard_wireguard_rs = { workspace = true }
log = { workspace = true }
sqlx = { workspace = true, features = [
"runtime-tokio-rustls",
@@ -36,6 +36,3 @@ sqlx = { workspace = true, features = [
"macros",
"migrate",
] }
[features]
wireguard = ["defguard_wireguard_rs", "bincode"]
-11
View File
@@ -25,7 +25,6 @@ mod inboxes;
pub(crate) mod models;
mod shared_keys;
mod tickets;
#[cfg(feature = "wireguard")]
mod wireguard_peers;
#[async_trait]
@@ -217,7 +216,6 @@ pub trait Storage: Send + Sync {
///
/// * `peer`: wireguard peer data to be stored
/// * `suspended`: if peer exists, but it's currently suspended
#[cfg(feature = "wireguard")]
async fn insert_wireguard_peer(
&self,
peer: &defguard_wireguard_rs::host::Peer,
@@ -229,14 +227,12 @@ pub trait Storage: Send + Sync {
/// # Arguments
///
/// * `peer_public_key`: wireguard public key of the peer to be retrieved.
#[cfg(feature = "wireguard")]
async fn get_wireguard_peer(
&self,
peer_public_key: &str,
) -> Result<Option<WireguardPeer>, StorageError>;
/// Retrieves all wireguard peers.
#[cfg(feature = "wireguard")]
async fn get_all_wireguard_peers(&self) -> Result<Vec<WireguardPeer>, StorageError>;
/// Remove a wireguard peer from the storage.
@@ -244,7 +240,6 @@ pub trait Storage: Send + Sync {
/// # Arguments
///
/// * `peer_public_key`: wireguard public key of the peer to be removed.
#[cfg(feature = "wireguard")]
async fn remove_wireguard_peer(&self, peer_public_key: &str) -> Result<(), StorageError>;
}
@@ -255,7 +250,6 @@ pub struct PersistentStorage {
inbox_manager: InboxManager,
bandwidth_manager: BandwidthManager,
ticket_manager: TicketStorageManager,
#[cfg(feature = "wireguard")]
wireguard_peer_manager: wireguard_peers::WgPeerManager,
}
@@ -300,7 +294,6 @@ impl PersistentStorage {
// the cloning here are cheap as connection pool is stored behind an Arc
Ok(PersistentStorage {
#[cfg(feature = "wireguard")]
wireguard_peer_manager: wireguard_peers::WgPeerManager::new(connection_pool.clone()),
shared_key_manager: SharedKeysManager::new(connection_pool.clone()),
inbox_manager: InboxManager::new(connection_pool.clone(), message_retrieval_limit),
@@ -620,7 +613,6 @@ impl Storage for PersistentStorage {
Ok(self.ticket_manager.get_epoch_signers(epoch_id).await?)
}
#[cfg(feature = "wireguard")]
async fn insert_wireguard_peer(
&self,
peer: &defguard_wireguard_rs::host::Peer,
@@ -632,7 +624,6 @@ impl Storage for PersistentStorage {
Ok(())
}
#[cfg(feature = "wireguard")]
async fn get_wireguard_peer(
&self,
peer_public_key: &str,
@@ -644,13 +635,11 @@ impl Storage for PersistentStorage {
Ok(peer)
}
#[cfg(feature = "wireguard")]
async fn get_all_wireguard_peers(&self) -> Result<Vec<WireguardPeer>, StorageError> {
let ret = self.wireguard_peer_manager.retrieve_all_peers().await?;
Ok(ret)
}
#[cfg(feature = "wireguard")]
async fn remove_wireguard_peer(&self, peer_public_key: &str) -> Result<(), StorageError> {
self.wireguard_peer_manager
.remove_peer(peer_public_key)
-3
View File
@@ -72,7 +72,6 @@ impl TryFrom<UnverifiedTicketData> for ClientTicket {
}
}
#[cfg(feature = "wireguard")]
#[derive(Debug, Clone, FromRow)]
pub struct WireguardPeer {
pub public_key: String,
@@ -87,7 +86,6 @@ pub struct WireguardPeer {
pub suspended: bool,
}
#[cfg(feature = "wireguard")]
impl From<defguard_wireguard_rs::host::Peer> for WireguardPeer {
fn from(value: defguard_wireguard_rs::host::Peer) -> Self {
WireguardPeer {
@@ -120,7 +118,6 @@ impl From<defguard_wireguard_rs::host::Peer> for WireguardPeer {
}
}
#[cfg(feature = "wireguard")]
impl TryFrom<WireguardPeer> for defguard_wireguard_rs::host::Peer {
type Error = crate::error::StorageError;
+2 -2
View File
@@ -17,8 +17,8 @@ pub const MIXNET_CONTRACT_ADDRESS: &str =
"n17srjznxl9dvzdkpwpw24gg668wc73val88a6m5ajg6ankwvz9wtst0cznr";
pub const VESTING_CONTRACT_ADDRESS: &str =
"n1nc5tatafv6eyq7llkr2gv50ff9e22mnf70qgjlv737ktmt4eswrq73f2nw";
pub const ECASH_CONTRACT_ADDRESS: &str = "";
pub const ECASH_CONTRACT_ADDRESS: &str =
"n1r7s6aksyc6pqardx88k3rkgfagwvj4z4zum9mmz2sfk3zm2mha0sd4dnun";
pub const GROUP_CONTRACT_ADDRESS: &str =
"n1e2zq4886zzewpvpucmlw8v9p7zv692f6yck4zjzxh699dkcmlrfqk2knsr";
pub const MULTISIG_CONTRACT_ADDRESS: &str =
-12
View File
@@ -3,7 +3,6 @@
use futures::{future::pending, FutureExt, SinkExt, StreamExt};
use log::{log, Level};
use std::future::Future;
use std::sync::atomic::{AtomicBool, Ordering};
use std::{error::Error, time::Duration};
use tokio::sync::{
@@ -368,17 +367,6 @@ impl TaskClient {
self.named(name)
}
pub async fn run_future<Fut, T>(&mut self, fut: Fut) -> Option<T>
where
Fut: Future<Output = T>,
{
tokio::select! {
biased;
_ = self.recv() => None,
res = fut => Some(res)
}
}
// Create a dummy that will never report that we should shutdown.
pub fn dummy() -> TaskClient {
let (_notify_tx, notify_rx) = watch::channel(());
+1 -1
View File
@@ -23,7 +23,7 @@ x25519-dalek = { workspace = true }
ip_network = { workspace = true }
log.workspace = true
nym-crypto = { path = "../crypto", features = ["asymmetric"] }
nym-gateway-storage = { path = "../gateway-storage", features = ["wireguard"] }
nym-gateway-storage = { path = "../gateway-storage" }
nym-network-defaults = { path = "../network-defaults" }
nym-task = { path = "../task" }
nym-wireguard-types = { path = "../wireguard-types" }
+14 -7
View File
@@ -64,14 +64,19 @@ impl<St: Storage> PeerController<St> {
let timeout_check_interval = tokio_stream::wrappers::IntervalStream::new(
tokio::time::interval(DEFAULT_PEER_TIMEOUT_CHECK),
);
let active_peers = peers
let active_peers: HashMap<Key, Peer> = peers
.into_iter()
.map(|peer| (peer.public_key.clone(), peer))
.collect();
let suspended_peers = suspended_peers
let suspended_peers: HashMap<Key, Peer> = suspended_peers
.into_iter()
.map(|peer| (peer.public_key.clone(), peer))
.collect();
let last_seen_bandwidth = active_peers
.iter()
.map(|(k, p)| (k.clone(), p.rx_bytes + p.tx_bytes))
.chain(suspended_peers.keys().map(|k| (k.clone(), 0)))
.collect();
PeerController {
storage,
@@ -81,7 +86,7 @@ impl<St: Storage> PeerController<St> {
timeout_check_interval,
active_peers,
suspended_peers,
last_seen_bandwidth: HashMap::new(),
last_seen_bandwidth,
}
}
@@ -128,10 +133,11 @@ impl<St: Storage> PeerController<St> {
}
async fn check_peers(&mut self) -> Result<(), Error> {
// Add 10 seconds to cover edge cases. At worst, we give ten free seconds worth of bandwidth
// by resetting the bandwidth twice
let reset = Utc::now().num_seconds_from_midnight() as u64
<= DEFAULT_PEER_TIMEOUT_CHECK.as_secs() + 10;
let reset_every: u32 = std::env::var("RESET_EVERY")
.expect("RESET_EVERY should be set")
.parse()
.expect("RESET_EVERY should be a number");
let reset = Utc::now().minute() % reset_every == 0;
if reset {
for (_, peer) in self.suspended_peers.drain() {
@@ -192,6 +198,7 @@ impl<St: Storage> PeerController<St> {
log::error!("Could not configure peer: {:?}", e);
false
} else {
self.last_seen_bandwidth.insert(peer.public_key.clone(), peer.rx_bytes + peer.tx_bytes);
self.active_peers.insert(peer.public_key.clone(), peer);
true
};
+3 -2
View File
@@ -2,7 +2,7 @@ CONFIGURED=true
RUST_LOG=info
RUST_BACKTRACE=1
NETWORK_NAME=sandbox
NETWORK_NAME=canary
BECH32_PREFIX=n
MIX_DENOM=unym
MIX_DENOM_DISPLAY=nym
@@ -12,7 +12,8 @@ DENOMS_EXPONENT=6
REWARDING_VALIDATOR_ADDRESS=n1duuyj2th2y0z4u4f4wtljpdz9s3pxtu0xx6zdz
MIXNET_CONTRACT_ADDRESS=n14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9sjyvg3g
COCONUT_BANDWIDTH_CONTRACT_ADDRESS=n1mf6ptkssddfmxvhdx0ech0k03ktp6kf9yk59renau2gvht3nq2gqt5tdrk
VESTING_CONTRACT_ADDRESS=n1780emnrt7v9uqx5txhpxc0z8zfawq0czjmtd4q2maz83cckwjlfsx45u6c
ECASH_CONTRACT_ADDRESS=n14jf8r2kxlymgjkp3xj8xuyud7h974648qdn9tsgsj0pascmntt9s3lvlwm
GROUP_CONTRACT_ADDRESS=n1qg5ega6dykkxc307y25pecuufrjkxkaggkkxh7nad0vhyhtuhw3sa07c47
MULTISIG_CONTRACT_ADDRESS=n1zwv6feuzhy6a9wekh96cd57lsarmqlwxdypdsplw6zhfncqw6ftqx5a364
COCONUT_DKG_CONTRACT_ADDRESS=n1aakfpghcanxtc45gpqlx8j3rq0zcpyf49qmhm9mdjrfx036h4z5sy2vfh9
+1
View File
@@ -15,6 +15,7 @@ DENOMS_EXPONENT=6
MIXNET_CONTRACT_ADDRESS=n17srjznxl9dvzdkpwpw24gg668wc73val88a6m5ajg6ankwvz9wtst0cznr
VESTING_CONTRACT_ADDRESS=n1nc5tatafv6eyq7llkr2gv50ff9e22mnf70qgjlv737ktmt4eswrq73f2nw
GROUP_CONTRACT_ADDRESS=n1e2zq4886zzewpvpucmlw8v9p7zv692f6yck4zjzxh699dkcmlrfqk2knsr
ECASH_CONTRACT_ADDRESS=n1r7s6aksyc6pqardx88k3rkgfagwvj4z4zum9mmz2sfk3zm2mha0sd4dnun
MULTISIG_CONTRACT_ADDRESS=n1txayqfz5g9qww3rlflpg025xd26m9payz96u54x4fe3s2ktz39xqk67gzx
COCONUT_DKG_CONTRACT_ADDRESS=n19604yflqggs9mk2z26mqygq43q2kr3n932egxx630svywd5mpxjsztfpvx
+4 -5
View File
@@ -13,11 +13,10 @@ DENOMS_EXPONENT=6
REWARDING_VALIDATOR_ADDRESS=n1pefc2utwpy5w78p2kqdsfmpjxfwmn9d39k5mqa
MIXNET_CONTRACT_ADDRESS=n1xr3rq8yvd7qplsw5yx90ftsr2zdhg4e9z60h5duusgxpv72hud3sjkxkav
VESTING_CONTRACT_ADDRESS=n1unyuj8qnmygvzuex3dwmg9yzt9alhvyeat0uu0jedg2wj33efl5qackslz
ECASH_CONTRACT_ADDRESS=n1ljlwey4xdj0zs7zueepc48nkr033fca6fjgvurfvttqegm8dvsrswsul70
GROUP_CONTRACT_ADDRESS=n10v3rjnq4cjyccfykyams68ztce337gksuu6f0lvtl4meuwvkewaqru4uav
MULTISIG_CONTRACT_ADDRESS=n1cemnu8as0ls45v3caunpesl8jlsfw2ff9rlwnltlecp7zrxct4dsqc2y42
COCONUT_DKG_CONTRACT_ADDRESS=n1zx96qgd88vqlzcxkpwzks7kqs5ctrx36xtzfc58p7q6c4ng9anlqzc4nh8
GROUP_CONTRACT_ADDRESS=n1ewmwz97xm0h8rdk8sw7h9mwn866qkx9hl9zlmagqfkhuzvwk5hhq844ue9
MULTISIG_CONTRACT_ADDRESS=n1tz0setr8vkh9udp8xyxgpqc89ns27k4d0jx2h942hr0ax63yjhmqz6xct8
COCONUT_DKG_CONTRACT_ADDRESS=n1v3n2ly2dp3a9ng3ff6rh26yfkn0pc5hed7w2shc5u9ca5c865utqj5elvh
ECASH_CONTRACT_ADDRESS=n1v3vydvs2ued84yv3khqwtgldmgwn0elljsdh08dr5s2j9x4rc5fs9jlwz9
STATISTICS_SERVICE_DOMAIN_ADDRESS="http://0.0.0.0"
EXPLORER_API=https://sandbox-explorer.nymtech.net/api
+4 -5
View File
@@ -13,11 +13,10 @@ DENOMS_EXPONENT=6
REWARDING_VALIDATOR_ADDRESS=n1pefc2utwpy5w78p2kqdsfmpjxfwmn9d39k5mqa
MIXNET_CONTRACT_ADDRESS=n1xr3rq8yvd7qplsw5yx90ftsr2zdhg4e9z60h5duusgxpv72hud3sjkxkav
VESTING_CONTRACT_ADDRESS=n1unyuj8qnmygvzuex3dwmg9yzt9alhvyeat0uu0jedg2wj33efl5qackslz
BANDWIDTH_CLAIM_CONTRACT_ADDRESS=n19lc9u84cz0yz3fww5283nucc9yvr8gsjmgeul0
COCONUT_BANDWIDTH_CONTRACT_ADDRESS=n16a32stm6kknhq5cc8rx77elr66pygf2hfszw7wvpq746x3uffylqkjar4l
GROUP_CONTRACT_ADDRESS=n1pd7kfgvr5tpcv0xnlv46c4jsq9jg2r799xxrcwqdm4l2jhq2pjwqrmz5ju
MULTISIG_CONTRACT_ADDRESS=n14ph4e660eyqz0j36zlkaey4zgzexm5twkmjlqaequxr2cjm9eprqsmad6k
COCONUT_DKG_CONTRACT_ADDRESS=n1ahg0erc2fs6xx3j5m8sfx3ryuzdjh6kf6qm9plsf865fltekyrfsesac6a
ECASH_CONTRACT_ADDRESS=n1v3vydvs2ued84yv3khqwtgldmgwn0elljsdh08dr5s2j9x4rc5fs9jlwz9
GROUP_CONTRACT_ADDRESS=n1ewmwz97xm0h8rdk8sw7h9mwn866qkx9hl9zlmagqfkhuzvwk5hhq844ue9
MULTISIG_CONTRACT_ADDRESS=n1tz0setr8vkh9udp8xyxgpqc89ns27k4d0jx2h942hr0ax63yjhmqz6xct8
COCONUT_DKG_CONTRACT_ADDRESS=n1v3n2ly2dp3a9ng3ff6rh26yfkn0pc5hed7w2shc5u9ca5c865utqj5elvh
STATISTICS_SERVICE_DOMAIN_ADDRESS="http://0.0.0.0"
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "explorer-api"
version = "1.1.38"
version = "1.1.39"
edition = "2021"
license.workspace = true
+2 -7
View File
@@ -93,10 +93,10 @@ nym-types = { path = "../common/types" }
nym-validator-client = { path = "../common/client-libs/validator-client" }
nym-ip-packet-router = { path = "../service-providers/ip-packet-router" }
nym-wireguard = { path = "../common/wireguard", optional = true }
nym-wireguard = { path = "../common/wireguard" }
nym-wireguard-types = { path = "../common/wireguard-types", default-features = false }
defguard_wireguard_rs = { workspace = true, optional = true }
defguard_wireguard_rs = { workspace = true }
[build-dependencies]
@@ -109,11 +109,6 @@ sqlx = { workspace = true, features = [
] }
[features]
wireguard = [
"nym-wireguard",
"defguard_wireguard_rs",
"nym-gateway-storage/wireguard",
]
bin-deps = ["clap", 'nym-bin-common/output_format']
[package.metadata.deb]
+25 -4
View File
@@ -10,7 +10,7 @@ use nym_config::{
must_get_home, read_config_from_toml_file, save_formatted_config_to_file, NymConfigTemplate,
DEFAULT_CONFIG_DIR, DEFAULT_CONFIG_FILENAME, DEFAULT_DATA_DIR, NYM_DIR,
};
use nym_network_defaults::{mainnet, DEFAULT_NYM_NODE_HTTP_PORT};
use nym_network_defaults::{mainnet, DEFAULT_NYM_NODE_HTTP_PORT, TICKETBOOK_VALIDITY_DAYS};
use serde::{Deserialize, Serialize};
use std::io;
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
@@ -501,7 +501,7 @@ pub struct ZkNymTicketHandlerDebug {
pub minimum_redemption_tickets: usize,
/// Specifies the maximum time between two subsequent tickets redemptions.
/// That's required as nym-apis will purge all ticket information for tickets older than 30 days.
/// That's required as nym-apis will purge all ticket information for tickets older than maximum validity.
#[serde(with = "humantime_serde")]
pub maximum_time_between_redemption: Duration,
}
@@ -511,7 +511,28 @@ impl ZkNymTicketHandlerDebug {
pub const DEFAULT_PENDING_POLLER: Duration = Duration::from_secs(300);
pub const DEFAULT_MINIMUM_API_QUORUM: f32 = 0.8;
pub const DEFAULT_MINIMUM_REDEMPTION_TICKETS: usize = 100;
pub const DEFAULT_MAXIMUM_TIME_BETWEEN_REDEMPTION: Duration = Duration::from_secs(86400 * 25);
// use min(4/5 of max validity, validity - 1), but making sure it's no greater than 1 day
// ASSUMPTION: our validity period is AT LEAST 2 days
//
// this could have been a constant, but it's more readable as a function
pub const fn default_maximum_time_between_redemption() -> Duration {
let desired_secs = TICKETBOOK_VALIDITY_DAYS * (86400 * 4) / 5;
let desired_secs_alt = (TICKETBOOK_VALIDITY_DAYS - 1) * 86400;
// can't use `min` in const context
let target_secs = if desired_secs < desired_secs_alt {
desired_secs
} else {
desired_secs_alt
};
assert!(
target_secs > 86400,
"the maximum time between redemption can't be lower than 1 day!"
);
Duration::from_secs(target_secs as u64)
}
}
impl Default for ZkNymTicketHandlerDebug {
@@ -521,7 +542,7 @@ impl Default for ZkNymTicketHandlerDebug {
pending_poller: Self::DEFAULT_PENDING_POLLER,
minimum_api_quorum: Self::DEFAULT_MINIMUM_API_QUORUM,
minimum_redemption_tickets: Self::DEFAULT_MINIMUM_REDEMPTION_TICKETS,
maximum_time_between_redemption: Self::DEFAULT_MAXIMUM_TIME_BETWEEN_REDEMPTION,
maximum_time_between_redemption: Self::default_maximum_time_between_redemption(),
}
}
}
+2 -4
View File
@@ -199,13 +199,11 @@ pub enum GatewayError {
#[error("the current multisig contract is not using 'AbsolutePercentage' threshold!")]
InvalidMultisigThreshold,
#[cfg(all(feature = "wireguard", target_os = "linux"))]
#[error("failed to remove wireguard interface: {0}")]
WireguardInterfaceError(#[from] defguard_wireguard_rs::error::WireguardInterfaceError),
#[cfg(all(feature = "wireguard", target_os = "linux"))]
#[error("wireguard not set")]
WireguardNotSet,
#[error("internal wireguard error {0}")]
InternalWireguardError(String),
#[error("failed to start authenticator: {source}")]
AuthenticatorStartError {
@@ -122,7 +122,7 @@ pub(crate) struct CredentialHandlerConfig {
pub(crate) minimum_redemption_tickets: usize,
/// Specifies the maximum time between two subsequent tickets redemptions.
/// That's required as nym-apis will purge all ticket information for tickets older than 30 days.
/// That's required as nym-apis will purge all ticket information for tickets older than maximum validity.
pub(crate) maximum_time_between_redemption: Duration,
}
@@ -20,6 +20,7 @@ use nym_gateway_requests::{
};
use nym_mixnet_client::forwarder::MixForwardingSender;
use nym_sphinx::DestinationAddressBytes;
use nym_task::TaskClient;
use rand::{CryptoRng, Rng};
use std::net::SocketAddr;
use std::time::Duration;
@@ -111,6 +112,9 @@ pub(crate) enum InitialAuthenticationError {
#[error("failed to upgrade the client handler: {source}")]
HandlerUpgradeFailure { source: RequestHandlingError },
#[error("received shutdown")]
ReceivedShutdown,
}
impl InitialAuthenticationError {
@@ -127,6 +131,7 @@ pub(crate) struct FreshHandler<R, S, St> {
pub(crate) outbound_mix_sender: MixForwardingSender,
pub(crate) socket_connection: SocketStream<S>,
pub(crate) peer_address: SocketAddr,
pub(crate) shutdown: TaskClient,
// currently unused (but populated)
pub(crate) negotiated_protocol: Option<u8>,
@@ -149,6 +154,7 @@ where
active_clients_store: ActiveClientsStore,
shared_state: CommonHandlerState<St>,
peer_address: SocketAddr,
shutdown: TaskClient,
) -> Self {
FreshHandler {
rng,
@@ -158,6 +164,7 @@ where
peer_address,
negotiated_protocol: None,
shared_state,
shutdown,
}
}
@@ -201,6 +208,7 @@ where
ws_stream,
self.shared_state.local_identity.as_ref(),
init_msg,
self.shutdown.clone(),
)
.await
}
@@ -720,111 +728,125 @@ where
{
trace!("Started waiting for authenticate/register request...");
while let Some(msg) = self.read_websocket_message().await {
let msg = match msg {
Ok(msg) => msg,
Err(source) => {
debug!("failed to obtain message from websocket stream! stopping connection handler: {source}");
return Err(InitialAuthenticationError::FailedToReadMessage { source });
}
};
let mut shutdown = self.shutdown.clone();
loop {
tokio::select! {
biased;
_ = shutdown.recv() => {
trace!("received shutdown signal while performing initial authentication");
return Err(InitialAuthenticationError::ReceivedShutdown);
},
msg = self.read_websocket_message() => {
let Some(msg) = msg else {
break;
};
if msg.is_close() {
return Err(InitialAuthenticationError::CloseMessage);
}
let msg = match msg {
Ok(msg) => msg,
Err(source) => {
debug!("failed to obtain message from websocket stream! stopping connection handler: {source}");
return Err(InitialAuthenticationError::FailedToReadMessage { source });
}
};
// ONLY handle 'Authenticate' or 'Register' requests, ignore everything else
match msg {
// we have explicitly checked for close message
Message::Close(_) => unreachable!(),
Message::Text(text_msg) => {
let (mix_sender, mix_receiver) = mpsc::unbounded();
return match self.handle_initial_authentication_request(text_msg).await {
Err(err) => {
debug!("authentication failure: {err}");
if msg.is_close() {
return Err(InitialAuthenticationError::CloseMessage);
}
// try to send error to the client
if let Err(source) =
self.send_websocket_message(err.to_error_message()).await
// ONLY handle 'Authenticate' or 'Register' requests, ignore everything else
match msg {
// we have explicitly checked for close message
Message::Close(_) => unreachable!(),
Message::Text(text_msg) => {
let (mix_sender, mix_receiver) = mpsc::unbounded();
return match self.handle_initial_authentication_request(text_msg).await {
Err(err) => {
debug!("authentication failure: {err}");
// try to send error to the client
if let Err(source) =
self.send_websocket_message(err.to_error_message()).await
{
debug!("Failed to send authentication error response: {source}");
return Err(InitialAuthenticationError::ErrorResponseSendFailure {
source,
});
}
// return the underlying error
Err(err)
}
Ok(auth_result) => {
// try to send auth response back to the client
if let Err(source) = self
.send_websocket_message(auth_result.server_response.into())
.await
{
debug!("Failed to send authentication response: {source}");
return Err(InitialAuthenticationError::ResponseSendFailure {
source,
});
}
if let Some(client_details) = auth_result.client_details {
// Channel for handlers to ask other handlers if they are still active.
let (is_active_request_sender, is_active_request_receiver) =
mpsc::unbounded();
self.active_clients_store.insert_remote(
client_details.address,
mix_sender,
is_active_request_sender,
);
AuthenticatedHandler::upgrade(
self,
client_details,
mix_receiver,
is_active_request_receiver,
)
.await
.map_err(|source| {
InitialAuthenticationError::HandlerUpgradeFailure { source }
})
} else {
// honestly, it's been so long I don't remember under what conditions its possible (if at all)
// to have empty client details
Err(InitialAuthenticationError::EmptyClientDetails)
}
}
};
}
Message::Binary(_) => {
// perhaps logging level should be reduced here, let's leave it for now and see what happens
// if client is working correctly, this should have never happened
debug!("possibly received a sphinx packet without prior authentication. Request is going to be ignored");
if let Err(source) = self
.send_websocket_message(
ServerResponse::new_error(
"binary request without prior authentication",
)
.into(),
)
.await
{
debug!("Failed to send authentication error response: {source}");
return Err(InitialAuthenticationError::ErrorResponseSendFailure {
source,
});
}
// return the underlying error
Err(err)
return Err(InitialAuthenticationError::BinaryRequestWithoutAuthentication);
}
Ok(auth_result) => {
// try to send auth response back to the client
if let Err(source) = self
.send_websocket_message(auth_result.server_response.into())
.await
{
debug!("Failed to send authentication response: {source}");
return Err(InitialAuthenticationError::ResponseSendFailure {
source,
});
}
if let Some(client_details) = auth_result.client_details {
// Channel for handlers to ask other handlers if they are still active.
let (is_active_request_sender, is_active_request_receiver) =
mpsc::unbounded();
self.active_clients_store.insert_remote(
client_details.address,
mix_sender,
is_active_request_sender,
);
AuthenticatedHandler::upgrade(
self,
client_details,
mix_receiver,
is_active_request_receiver,
)
.await
.map_err(|source| {
InitialAuthenticationError::HandlerUpgradeFailure { source }
})
} else {
// honestly, it's been so long I don't remember under what conditions its possible (if at all)
// to have empty client details
Err(InitialAuthenticationError::EmptyClientDetails)
}
}
_ => continue,
};
}
Message::Binary(_) => {
// perhaps logging level should be reduced here, let's leave it for now and see what happens
// if client is working correctly, this should have never happened
debug!("possibly received a sphinx packet without prior authentication. Request is going to be ignored");
if let Err(source) = self
.send_websocket_message(
ServerResponse::new_error(
"binary request without prior authentication",
)
.into(),
)
.await
{
return Err(InitialAuthenticationError::ErrorResponseSendFailure {
source,
});
}
return Err(InitialAuthenticationError::BinaryRequestWithoutAuthentication);
}
_ => continue,
};
}
}
Err(InitialAuthenticationError::ClosedConnection)
}
pub(crate) async fn start_handling(self, shutdown: nym_task::TaskClient)
pub(crate) async fn start_handling(self)
where
S: AsyncRead + AsyncWrite + Unpin + Send,
{
super::handle_connection(self, shutdown).await
super::handle_connection(self).await
}
}
@@ -2,12 +2,12 @@
// SPDX-License-Identifier: GPL-3.0-only
use crate::config::Config;
use fresh::InitialAuthenticationError;
use nym_credentials_interface::AvailableBandwidth;
use nym_gateway_requests::registration::handshake::SharedKeys;
use nym_gateway_requests::ServerResponse;
use nym_gateway_storage::Storage;
use nym_sphinx::DestinationAddressBytes;
use nym_task::TaskClient;
use rand::{CryptoRng, Rng};
use std::time::Duration;
use time::OffsetDateTime;
@@ -23,6 +23,8 @@ pub(crate) mod authenticated;
pub(crate) mod ecash;
mod fresh;
const WEBSOCKET_HANDSHAKE_TIMEOUT: Duration = Duration::from_millis(1_500);
// TODO: note for my future self to consider the following idea:
// split the socket connection into sink and stream
// stream will be for reading explicit requests
@@ -86,47 +88,47 @@ impl InitialAuthResult {
// imo there's no point in including the peer address in anything higher than debug
#[instrument(level = "debug", skip_all, fields(peer = %handle.peer_address))]
pub(crate) async fn handle_connection<R, S, St>(
mut handle: FreshHandler<R, S, St>,
mut shutdown: TaskClient,
) where
pub(crate) async fn handle_connection<R, S, St>(mut handle: FreshHandler<R, S, St>)
where
R: Rng + CryptoRng,
S: AsyncRead + AsyncWrite + Unpin + Send,
St: Storage + Clone + 'static,
{
// If the connection handler abruptly stops, we shouldn't signal global shutdown
shutdown.mark_as_success();
handle.shutdown.mark_as_success();
match shutdown
.run_future(handle.perform_websocket_handshake())
.await
match tokio::time::timeout(
WEBSOCKET_HANDSHAKE_TIMEOUT,
handle.perform_websocket_handshake(),
)
.await
{
None => {
trace!("received shutdown signal while performing websocket handshake");
Err(timeout_err) => {
warn!("websocket handshake timedout: {timeout_err}");
return;
}
Some(Err(err)) => {
Ok(Err(err)) => {
warn!("Failed to complete WebSocket handshake: {err}. Stopping the handler");
return;
}
_ => (),
_ => {}
}
trace!("Managed to perform websocket handshake!");
match shutdown
.run_future(handle.perform_initial_authentication())
.await
{
None => {
trace!("received shutdown signal while performing initial authentication");
return;
}
Some(Err(err)) => {
let shutdown = handle.shutdown.clone();
match handle.perform_initial_authentication().await {
// For storage error, we want to print the extended storage error, but without
// including it in the error that's returned to the clients
Err(InitialAuthenticationError::StorageError(err)) => {
warn!("authentication has failed: {err}");
return;
}
Some(Ok(auth_handle)) => auth_handle.listen_for_requests(shutdown).await,
Err(err) => {
warn!("authentication has failed: {err}");
return;
}
Ok(auth_handle) => auth_handle.listen_for_requests(shutdown).await,
}
trace!("The handler is done!");
@@ -54,6 +54,7 @@ where
connection = tcp_listener.accept() => {
match connection {
Ok((socket, remote_addr)) => {
let shutdown = shutdown.clone().named(format!("ClientConnectionHandler_{remote_addr}"));
trace!("received a socket connection from {remote_addr}");
// TODO: I think we *REALLY* need a mechanism for having a maximum number of connected
// clients or spawned tokio tasks -> perhaps a worker system?
@@ -64,9 +65,9 @@ where
active_clients_store.clone(),
self.shared_state.clone(),
remote_addr,
shutdown,
);
let shutdown = shutdown.clone().named(format!("ClientConnectionHandler_{remote_addr}"));
tokio::spawn(async move { handle.start_handling(shutdown).await });
tokio::spawn(handle.start_handling());
}
Err(err) => warn!("failed to get client: {err}"),
}
+8 -10
View File
@@ -50,7 +50,6 @@ struct StartedNetworkRequester {
// TODO: should this struct live here?
#[allow(unused)]
struct StartedAuthenticator {
#[cfg(feature = "wireguard")]
wg_api: Arc<nym_wireguard::WgApiWrapper>,
/// Handle to interact with the local authenticator
@@ -145,7 +144,6 @@ pub struct Gateway<St = PersistentStorage> {
storage: St,
#[cfg(all(feature = "wireguard", target_os = "linux"))]
wireguard_data: Option<nym_wireguard::WireguardData>,
run_http_server: bool,
@@ -168,7 +166,6 @@ impl<St> Gateway<St> {
network_requester_opts,
ip_packet_router_opts,
authenticator_opts: None,
#[cfg(all(feature = "wireguard", target_os = "linux"))]
wireguard_data: None,
run_http_server: true,
task_client: None,
@@ -192,7 +189,6 @@ impl<St> Gateway<St> {
identity_keypair,
sphinx_keypair,
storage,
#[cfg(all(feature = "wireguard", target_os = "linux"))]
wireguard_data: None,
run_http_server: true,
task_client: None,
@@ -207,7 +203,6 @@ impl<St> Gateway<St> {
self.task_client = Some(task_client)
}
#[cfg(all(feature = "wireguard", target_os = "linux"))]
pub fn set_wireguard_data(&mut self, wireguard_data: nym_wireguard::WireguardData) {
self.wireguard_data = Some(wireguard_data)
}
@@ -245,7 +240,7 @@ impl<St> Gateway<St> {
mixnet_handling::Listener::new(listening_address, shutdown).start(connection_handler);
}
#[cfg(all(feature = "wireguard", target_os = "linux"))]
#[cfg(target_os = "linux")]
async fn start_authenticator(
&mut self,
forwarding_channel: MixForwardingSender,
@@ -317,11 +312,13 @@ impl<St> Gateway<St> {
handle: LocalEmbeddedClientHandle::new(start_data.address, auth_mix_sender),
})
} else {
Err(Box::new(GatewayError::WireguardNotSet))
Err(Box::new(GatewayError::InternalWireguardError(
"wireguard not set".to_string(),
)))
}
}
#[cfg(all(feature = "wireguard", not(target_os = "linux")))]
#[cfg(not(target_os = "linux"))]
async fn start_authenticator(
&self,
_forwarding_channel: MixForwardingSender,
@@ -654,14 +651,15 @@ impl<St> Gateway<St> {
info!("embedded ip packet router is disabled");
};
#[cfg(feature = "wireguard")]
let _wg_api = {
let _wg_api = if self.wireguard_data.is_some() {
let embedded_auth = self
.start_authenticator(mix_forwarding_channel, shutdown.fork("authenticator"))
.await
.map_err(|source| GatewayError::AuthenticatorStartError { source })?;
active_clients_store.insert_embedded(embedded_auth.handle);
Some(embedded_auth.wg_api)
} else {
None
};
if self.run_http_server {
+1 -1
View File
@@ -4,7 +4,7 @@
[package]
name = "nym-api"
license = "GPL-3.0"
version = "1.1.42"
version = "1.1.43"
authors = [
"Dave Hrycyszyn <futurechimp@users.noreply.github.com>",
"Jędrzej Stuczyński <andrew@nymtech.net>",
+11 -10
View File
@@ -16,8 +16,9 @@ use nym_coconut_dkg_common::types::{
use nym_coconut_dkg_common::verification_key::{ContractVKShare, VerificationKeyShare};
use nym_contracts_common::IdentityKey;
use nym_dkg::Threshold;
use nym_validator_client::nyxd::cosmwasm_client::logs::{find_attribute, NODE_INDEX};
use nym_validator_client::nyxd::cosmwasm_client::logs::NODE_INDEX;
use nym_validator_client::nyxd::cosmwasm_client::types::ExecuteResult;
use nym_validator_client::nyxd::helpers::find_attribute_value_in_logs_or_events;
use nym_validator_client::nyxd::AccountId;
pub(crate) struct DkgClient {
@@ -168,15 +169,15 @@ impl DkgClient {
.inner
.register_dealer(bte_key, identity_key, announce_address, resharing)
.await?;
let node_index = find_attribute(&res.logs, "wasm", NODE_INDEX)
.ok_or(EcashError::NodeIndexRecoveryError {
reason: String::from("node index not found"),
})?
.value
.parse::<NodeIndex>()
.map_err(|_| EcashError::NodeIndexRecoveryError {
reason: String::from("node index could not be parsed"),
})?;
let node_index =
find_attribute_value_in_logs_or_events(&res.logs, &res.events, "wasm", NODE_INDEX)
.ok_or(EcashError::NodeIndexRecoveryError {
reason: String::from("node index not found"),
})?
.parse::<NodeIndex>()
.map_err(|_| EcashError::NodeIndexRecoveryError {
reason: String::from("node index could not be parsed"),
})?;
Ok(node_index)
}
+15 -14
View File
@@ -18,8 +18,9 @@ use nym_dkg::{
bte::{self, decrypt_share},
combine_shares, try_recover_verification_keys, Dealing,
};
use nym_validator_client::nyxd::cosmwasm_client::logs::{find_attribute, Log};
use nym_validator_client::nyxd::Hash;
use nym_validator_client::nyxd::cosmwasm_client::logs::Log;
use nym_validator_client::nyxd::helpers::find_attribute_value_in_logs_or_events;
use nym_validator_client::nyxd::{Event, Hash};
use rand::{CryptoRng, RngCore};
use std::collections::{BTreeMap, HashMap};
use std::ops::Deref;
@@ -453,25 +454,25 @@ impl<R: RngCore + CryptoRng> DkgController<R> {
key: &VerificationKeyAuth,
resharing: bool,
) -> Result<u64, KeyDerivationError> {
fn extract_proposal_id_from_logs(
fn extract_proposal_id(
logs: &[Log],
events: &[Event],
tx_hash: Hash,
) -> Result<u64, KeyDerivationError> {
let event_type = "wasm";
let attribute_key = DKG_PROPOSAL_ID;
let proposal_attribute = find_attribute(logs, event_type, attribute_key).ok_or(
KeyDerivationError::MissingProposalIdAttribute {
tx_hash,
event_type: event_type.to_string(),
attribute_key: attribute_key.to_string(),
},
)?;
let proposal_value =
find_attribute_value_in_logs_or_events(logs, events, event_type, attribute_key)
.ok_or(KeyDerivationError::MissingProposalIdAttribute {
tx_hash,
event_type: event_type.to_string(),
attribute_key: attribute_key.to_string(),
})?;
proposal_attribute
.value
proposal_value
.parse()
.map_err(|_| KeyDerivationError::UnparsableProposalId {
raw: proposal_attribute.value.clone(),
raw: proposal_value.clone(),
})
}
@@ -481,7 +482,7 @@ impl<R: RngCore + CryptoRng> DkgController<R> {
.submit_verification_key_share(key.to_bs58(), resharing)
.await?;
let hash = res.transaction_hash;
let proposal_id = extract_proposal_id_from_logs(&res.logs, hash)?;
let proposal_id = extract_proposal_id(&res.logs, &res.events, hash)?;
debug!("Submitted own verification key share, proposal id {proposal_id} is attached to it. tx hash: {hash}");
Ok(proposal_id)
+1 -1
View File
@@ -56,7 +56,7 @@ pub(crate) async fn prepare_partial_bloomfilter_builder(
.try_load_partial_bloomfilter_bitmap(date, params_id)
.await?
else {
log::warn!("missing double spending bloomfilter bitmap for {date} (if this API hasn't been running for at least 30 days since 'ecash'-based zk-nyms were introduced this is expected)");
log::warn!("missing double spending bloomfilter bitmap for {date} (if this API hasn't been running for at least {days} day(s) since 'ecash'-based zk-nyms were introduced this is expected)");
continue;
};
if !filter_builder.add_bytes(&bitmap) {
+6 -6
View File
@@ -3,7 +3,7 @@
[package]
name = "nym-node"
version = "1.1.6"
version = "1.1.7"
authors.workspace = true
repository.workspace = true
homepage.workspace = true
@@ -17,7 +17,7 @@ license = "GPL-3.0"
anyhow.workspace = true
bip39 = { workspace = true, features = ["zeroize"] }
bs58.workspace = true
celes = { workspace = true } # country codes
celes = { workspace = true } # country codes
colored = { workspace = true }
clap = { workspace = true, features = ["cargo", "env"] }
humantime-serde = { workspace = true }
@@ -39,7 +39,10 @@ semver = { workspace = true }
cupid = { workspace = true }
sysinfo = { workspace = true }
nym-bin-common = { path = "../common/bin-common", features = ["basic_tracing", "output_format"] }
nym-bin-common = { path = "../common/bin-common", features = [
"basic_tracing",
"output_format",
] }
nym-client-core-config-types = { path = "../common/client-core/config-types" }
nym-config = { path = "../common/config" }
nym-crypto = { path = "../common/crypto", features = ["asymmetric", "rand"] }
@@ -62,6 +65,3 @@ nym-ip-packet-router = { path = "../service-providers/ip-packet-router" }
[build-dependencies]
# temporary bonding information v1 (to grab and parse nym-mixnode and nym-gateway package versions)
cargo_metadata = { workspace = true }
[features]
wireguard = ["nym-gateway/wireguard"]
+25 -4
View File
@@ -5,7 +5,7 @@ use crate::config::helpers::ephemeral_gateway_config;
use crate::config::persistence::EntryGatewayPaths;
use crate::config::Config;
use crate::error::EntryGatewayError;
use nym_config::defaults::DEFAULT_CLIENT_LISTENING_PORT;
use nym_config::defaults::{DEFAULT_CLIENT_LISTENING_PORT, TICKETBOOK_VALIDITY_DAYS};
use nym_config::helpers::inaddr_any;
use nym_config::serde_helpers::de_maybe_port;
use nym_gateway::node::LocalAuthenticatorOpts;
@@ -90,7 +90,7 @@ pub struct ZkNymTicketHandlerDebug {
pub minimum_redemption_tickets: usize,
/// Specifies the maximum time between two subsequent tickets redemptions.
/// That's required as nym-apis will purge all ticket information for tickets older than 30 days.
/// That's required as nym-apis will purge all ticket information for tickets older than maximum validity.
#[serde(with = "humantime_serde")]
pub maximum_time_between_redemption: Duration,
}
@@ -100,7 +100,28 @@ impl ZkNymTicketHandlerDebug {
pub const DEFAULT_PENDING_POLLER: Duration = Duration::from_secs(300);
pub const DEFAULT_MINIMUM_API_QUORUM: f32 = 0.8;
pub const DEFAULT_MINIMUM_REDEMPTION_TICKETS: usize = 100;
pub const DEFAULT_MAXIMUM_TIME_BETWEEN_REDEMPTION: Duration = Duration::from_secs(86400 * 25);
// use min(4/5 of max validity, validity - 1), but making sure it's no greater than 1 day
// ASSUMPTION: our validity period is AT LEAST 2 days
//
// this could have been a constant, but it's more readable as a function
pub const fn default_maximum_time_between_redemption() -> Duration {
let desired_secs = TICKETBOOK_VALIDITY_DAYS * (86400 * 4) / 5;
let desired_secs_alt = (TICKETBOOK_VALIDITY_DAYS - 1) * 86400;
// can't use `min` in const context
let target_secs = if desired_secs < desired_secs_alt {
desired_secs
} else {
desired_secs_alt
};
assert!(
target_secs > 86400,
"the maximum time between redemption can't be lower than 1 day!"
);
Duration::from_secs(target_secs as u64)
}
}
impl Default for ZkNymTicketHandlerDebug {
@@ -110,7 +131,7 @@ impl Default for ZkNymTicketHandlerDebug {
pending_poller: Self::DEFAULT_PENDING_POLLER,
minimum_api_quorum: Self::DEFAULT_MINIMUM_API_QUORUM,
minimum_redemption_tickets: Self::DEFAULT_MINIMUM_REDEMPTION_TICKETS,
maximum_time_between_redemption: Self::DEFAULT_MAXIMUM_TIME_BETWEEN_REDEMPTION,
maximum_time_between_redemption: Self::default_maximum_time_between_redemption(),
}
}
}
+6 -4
View File
@@ -580,8 +580,9 @@ impl NymNode {
);
entry_gateway.disable_http_server();
entry_gateway.set_task_client(task_client);
#[cfg(all(feature = "wireguard", target_os = "linux"))]
entry_gateway.set_wireguard_data(self.wireguard.into());
if self.config.wireguard.enabled {
entry_gateway.set_wireguard_data(self.wireguard.into());
}
tokio::spawn(async move {
if let Err(err) = entry_gateway.run().await {
@@ -608,8 +609,9 @@ impl NymNode {
);
exit_gateway.disable_http_server();
exit_gateway.set_task_client(task_client);
#[cfg(all(feature = "wireguard", target_os = "linux"))]
exit_gateway.set_wireguard_data(self.wireguard.into());
if self.config.wireguard.enabled {
exit_gateway.set_wireguard_data(self.wireguard.into());
}
tokio::spawn(async move {
if let Err(err) = exit_gateway.run().await {
@@ -15,14 +15,14 @@ pub(crate) const MIXNET_CONTRACT_ADDRESS: &str =
"n1hm4y6fzgxgu688jgf7ek66px6xkrtmn3gyk8fax3eawhp68c2d5qujz296";
pub(crate) const VESTING_CONTRACT_ADDRESS: &str =
"n1jlzdxnyces4hrhqz68dqk28mrw5jgwtcfq0c2funcwrmw0dx9l9s8nnnvj";
pub(crate) const COCONUT_BANDWIDTH_CONTRACT_ADDRESS: &str =
"n1w798gp0zqv3s9hjl3jlnwxtwhykga6rn93p46q2crsdqhaj3y4gs68f74j";
pub(crate) const ECASH_CONTRACT_ADDRESS: &str =
"n13xspq62y9gq6nueqmywxcdv2yep4p6nzv98w2889k25v3nhdy2dq2rkrk7";
pub(crate) const GROUP_CONTRACT_ADDRESS: &str =
"n1sthrn5ep8ls5vzz8f9gp89khhmedahhdqd244dh9uqzk3hx2pzrsvf7zgk";
"n13l7rwuwktklrwskc7m6lv70zws07en85uma28j7dxwsz9y5hvvhspl7a2t";
pub(crate) const MULTISIG_CONTRACT_ADDRESS: &str =
"n1sr06m8yqg0wzqqyqvzvp5t07dj4nevx9u8qc7j4qa72qu8e3ct8qledthy";
"n138c9pyf7f3hyx0j3t6vmsz7ultnw2wj0lu6hzndep9z5grgq9haqlc25k0";
pub(crate) const COCONUT_DKG_CONTRACT_ADDRESS: &str =
"n1udfs22xpxle475m2nz7u47jfa3vngncdegmczwwdx00cmetypa3s7uyuqn";
"n1pk8jgr6y4c5k93gz7qf3xc0hvygmp7csk88c2tf8l39tkq6834wq2a6dtr";
// -- Constructor functions --
@@ -48,7 +48,7 @@ pub(crate) fn network_details() -> nym_network_defaults::NymNetworkDetails {
contracts: NymContracts {
mixnet_contract_address: parse_optional_str(MIXNET_CONTRACT_ADDRESS),
vesting_contract_address: parse_optional_str(VESTING_CONTRACT_ADDRESS),
ecash_contract_address: parse_optional_str(COCONUT_BANDWIDTH_CONTRACT_ADDRESS),
ecash_contract_address: parse_optional_str(ECASH_CONTRACT_ADDRESS),
group_contract_address: parse_optional_str(GROUP_CONTRACT_ADDRESS),
multisig_contract_address: parse_optional_str(MULTISIG_CONTRACT_ADDRESS),
coconut_dkg_contract_address: parse_optional_str(COCONUT_DKG_CONTRACT_ADDRESS),
@@ -15,14 +15,14 @@ pub(crate) const MIXNET_CONTRACT_ADDRESS: &str =
"n1xr3rq8yvd7qplsw5yx90ftsr2zdhg4e9z60h5duusgxpv72hud3sjkxkav";
pub(crate) const VESTING_CONTRACT_ADDRESS: &str =
"n1unyuj8qnmygvzuex3dwmg9yzt9alhvyeat0uu0jedg2wj33efl5qackslz";
pub(crate) const COCONUT_BANDWIDTH_CONTRACT_ADDRESS: &str =
"n16a32stm6kknhq5cc8rx77elr66pygf2hfszw7wvpq746x3uffylqkjar4l";
pub(crate) const ECASH_CONTRACT_ADDRESS: &str =
"n1v3vydvs2ued84yv3khqwtgldmgwn0elljsdh08dr5s2j9x4rc5fs9jlwz9";
pub(crate) const GROUP_CONTRACT_ADDRESS: &str =
"n1pd7kfgvr5tpcv0xnlv46c4jsq9jg2r799xxrcwqdm4l2jhq2pjwqrmz5ju";
"n1ewmwz97xm0h8rdk8sw7h9mwn866qkx9hl9zlmagqfkhuzvwk5hhq844ue9";
pub(crate) const MULTISIG_CONTRACT_ADDRESS: &str =
"n14ph4e660eyqz0j36zlkaey4zgzexm5twkmjlqaequxr2cjm9eprqsmad6k";
"n1tz0setr8vkh9udp8xyxgpqc89ns27k4d0jx2h942hr0ax63yjhmqz6xct8";
pub(crate) const COCONUT_DKG_CONTRACT_ADDRESS: &str =
"n1ahg0erc2fs6xx3j5m8sfx3ryuzdjh6kf6qm9plsf865fltekyrfsesac6a";
"n1v3n2ly2dp3a9ng3ff6rh26yfkn0pc5hed7w2shc5u9ca5c865utqj5elvh";
// -- Constructor functions --
@@ -48,7 +48,7 @@ pub(crate) fn network_details() -> nym_network_defaults::NymNetworkDetails {
contracts: NymContracts {
mixnet_contract_address: parse_optional_str(MIXNET_CONTRACT_ADDRESS),
vesting_contract_address: parse_optional_str(VESTING_CONTRACT_ADDRESS),
ecash_contract_address: parse_optional_str(COCONUT_BANDWIDTH_CONTRACT_ADDRESS),
ecash_contract_address: parse_optional_str(ECASH_CONTRACT_ADDRESS),
group_contract_address: parse_optional_str(GROUP_CONTRACT_ADDRESS),
multisig_contract_address: parse_optional_str(MULTISIG_CONTRACT_ADDRESS),
coconut_dkg_contract_address: parse_optional_str(COCONUT_DKG_CONTRACT_ADDRESS),
+4 -3
View File
@@ -7,6 +7,7 @@ use nym_credential_utils::utils::issue_credential;
use nym_credentials_interface::TicketType;
use nym_network_defaults::NymNetworkDetails;
use nym_validator_client::{nyxd, DirectSigningHttpRpcNyxdClient};
use std::ops::Deref;
use zeroize::Zeroizing;
/// Represents a client that can be used to acquire bandwidth. You typically create one when you
@@ -17,7 +18,7 @@ use zeroize::Zeroizing;
pub struct BandwidthAcquireClient<'a, St: Storage> {
client: DirectSigningHttpRpcNyxdClient,
storage: &'a St,
client_id: Zeroizing<String>,
client_id: Zeroizing<Vec<u8>>,
ticketbook_type: TicketType,
}
@@ -30,7 +31,7 @@ where
network_details: NymNetworkDetails,
mnemonic: String,
storage: &'a St,
client_id: String,
client_id: Vec<u8>,
ticketbook_type: TicketType,
) -> Result<Self> {
let nyxd_url = network_details.endpoints[0].nyxd_url.as_str();
@@ -53,7 +54,7 @@ where
issue_credential(
&self.client,
self.storage,
self.client_id.as_bytes(),
self.client_id.deref(),
self.ticketbook_type,
)
.await?;
+15 -11
View File
@@ -40,6 +40,7 @@ use std::net::IpAddr;
use std::path::Path;
use std::path::PathBuf;
use url::Url;
use zeroize::Zeroizing;
// The number of surbs to include in a message by default
const DEFAULT_NUMBER_OF_SURBS: u32 = 10;
@@ -560,17 +561,20 @@ where
if !self.config.enabled_credentials_mode {
return Err(Error::DisabledCredentialsMode);
}
let client_id = self
.storage
.key_store()
.load_keys()
.await
.map_err(|e| Error::KeyStorageError {
source: Box::new(e),
})?
.identity_keypair()
.private_key()
.to_base58_string();
let client_id_array = Zeroizing::new(
self.storage
.key_store()
.load_keys()
.await
.map_err(|e| Error::KeyStorageError {
source: Box::new(e),
})?
.identity_keypair()
.private_key()
.to_bytes(),
);
let client_id = client_id_array.to_vec();
BandwidthAcquireClient::new(
self.config.network_details.clone(),
mnemonic,
@@ -4,7 +4,7 @@
[package]
name = "nym-network-requester"
license = "GPL-3.0"
version = "1.1.40"
version = "1.1.41"
authors.workspace = true
edition.workspace = true
rust-version = "1.70"
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "nym-cli"
version = "1.1.40"
version = "1.1.41"
authors.workspace = true
edition = "2021"
license.workspace = true
-29
View File
@@ -1,29 +0,0 @@
use nym_cli_commands::context::{create_query_client, create_signing_client, ClientArgs};
use nym_network_defaults::NymNetworkDetails;
pub(crate) async fn execute(
global_args: ClientArgs,
coconut: nym_cli_commands::coconut::Ecash,
network_details: &NymNetworkDetails,
) -> anyhow::Result<()> {
match coconut.command {
nym_cli_commands::coconut::EcashCommands::IssueTicketBook(args) => {
nym_cli_commands::coconut::issue_ticket_book::execute(
args,
create_signing_client(global_args, network_details)?,
)
.await?
}
nym_cli_commands::coconut::EcashCommands::RecoverTicketBook(args) => {
nym_cli_commands::coconut::recover_ticket_book::execute(
args,
create_query_client(network_details)?,
)
.await?
}
nym_cli_commands::coconut::EcashCommands::ImportTicketBook(args) => {
nym_cli_commands::coconut::import_ticket_book::execute(args).await?
}
}
Ok(())
}
+32
View File
@@ -0,0 +1,32 @@
use nym_cli_commands::context::{create_query_client, create_signing_client, ClientArgs};
use nym_network_defaults::NymNetworkDetails;
pub(crate) async fn execute(
global_args: ClientArgs,
coconut: nym_cli_commands::ecash::Ecash,
network_details: &NymNetworkDetails,
) -> anyhow::Result<()> {
match coconut.command {
nym_cli_commands::ecash::EcashCommands::IssueTicketBook(args) => {
nym_cli_commands::ecash::issue_ticket_book::execute(
args,
create_signing_client(global_args, network_details)?,
)
.await?
}
nym_cli_commands::ecash::EcashCommands::RecoverTicketBook(args) => {
nym_cli_commands::ecash::recover_ticket_book::execute(
args,
create_query_client(network_details)?,
)
.await?
}
nym_cli_commands::ecash::EcashCommands::ImportTicketBook(args) => {
nym_cli_commands::ecash::import_ticket_book::execute(args).await?
}
nym_cli_commands::ecash::EcashCommands::GenerateTicket(args) => {
nym_cli_commands::ecash::generate_ticket::execute(args).await?
}
}
Ok(())
}
+3 -3
View File
@@ -7,8 +7,8 @@ use nym_bin_common::logging::setup_logging;
use nym_cli_commands::context::{get_network_details, ClientArgs};
use nym_validator_client::nyxd::AccountId;
mod coconut;
mod completion;
mod ecash;
mod validator;
#[derive(Debug, Parser)]
@@ -63,7 +63,7 @@ pub(crate) enum Commands {
/// Sign and verify messages
Signature(nym_cli_commands::validator::signature::Signature),
/// Ecash related stuff
Ecash(nym_cli_commands::coconut::Ecash),
Ecash(nym_cli_commands::ecash::Ecash),
/// Query chain blocks
Block(nym_cli_commands::validator::block::Block),
/// Manage and execute WASM smart contracts
@@ -104,7 +104,7 @@ async fn execute(cli: Cli) -> anyhow::Result<()> {
Commands::Signature(signature) => {
validator::signature::execute(signature, &network_details, mnemonic).await?
}
Commands::Ecash(coconut) => coconut::execute(args, coconut, &network_details).await?,
Commands::Ecash(coconut) => ecash::execute(args, coconut, &network_details).await?,
Commands::Block(block) => validator::block::execute(block, &network_details).await?,
Commands::Cosmwasm(cosmwasm) => {
validator::cosmwasm::execute(args, cosmwasm, &network_details).await?
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "nymvisor"
version = "0.1.5"
version = "0.1.6"
authors.workspace = true
repository.workspace = true
homepage.workspace = true