diff --git a/.github/workflows/ci-build-upload-binaries.yml b/.github/workflows/ci-build-upload-binaries.yml index 778cf58050..04d9b9673c 100644 --- a/.github/workflows/ci-build-upload-binaries.yml +++ b/.github/workflows/ci-build-upload-binaries.yml @@ -63,10 +63,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: diff --git a/.github/workflows/ci-build.yml b/.github/workflows/ci-build.yml index 53932a6806..65fc3afd38 100644 --- a/.github/workflows/ci-build.yml +++ b/.github/workflows/ci-build.yml @@ -75,8 +75,6 @@ jobs: uses: actions-rs/cargo@v1 with: command: build - # Enable wireguard by default on linux only - args: --workspace --features wireguard # while disabled by default, this build ensures nothing is broken within # `axum` feature @@ -91,21 +89,21 @@ jobs: uses: actions-rs/cargo@v1 with: command: build - args: --workspace --examples --features wireguard + args: --workspace --examples - name: Run all tests if: contains(matrix.os, 'ubuntu') 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') && contains(matrix.os, 'ubuntu') uses: actions-rs/cargo@v1 with: command: test - args: --workspace --features wireguard -- --ignored + args: --workspace -- --ignored - name: Annotate with clippy checks if: contains(matrix.os, 'ubuntu') @@ -113,10 +111,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,axum -- -D warnings + args: --workspace --all-targets --features axum -- -D warnings diff --git a/.github/workflows/publish-nym-binaries.yml b/.github/workflows/publish-nym-binaries.yml index 0b87eb5380..e64825e425 100644 --- a/.github/workflows/publish-nym-binaries.yml +++ b/.github/workflows/publish-nym-binaries.yml @@ -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: diff --git a/.github/workflows/publish-nym-wallet-win10.yml b/.github/workflows/publish-nym-wallet-win11.yml similarity index 96% rename from .github/workflows/publish-nym-wallet-win10.yml rename to .github/workflows/publish-nym-wallet-win11.yml index 86b2b2f275..2dc2be1503 100644 --- a/.github/workflows/publish-nym-wallet-win10.yml +++ b/.github/workflows/publish-nym-wallet-win11.yml @@ -1,4 +1,4 @@ -name: publish-nym-wallet-win10 +name: publish-nym-wallet-win11 on: workflow_dispatch: release: @@ -14,7 +14,7 @@ jobs: strategy: fail-fast: false matrix: - platform: [windows10] + platform: [custom-windows-11] runs-on: ${{ matrix.platform }} outputs: @@ -62,6 +62,9 @@ jobs: fileName: '.env' encodedString: ${{ secrets.WALLET_ADMIN_ADDRESS }} + - name: Install Yarn + run: npm install -g yarn + - name: Install project dependencies shell: bash run: cd .. && yarn --network-timeout 100000 diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a39429e55..fbed61bd54 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,60 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https:// ## [Unreleased] +## [2024.10-caramello] (2024-09-10) + +- Backport 4844 and 4845 ([#4857]) +- Bugfix/client registration vol2 ([#4856]) +- Remove wireguard feature flag and pass runtime enabled flag ([#4839]) +- Eliminate cancel unsafe sig awaiting ([#4834]) +- added explicit updateable admin to the mixnet contract ([#4822]) +- using legacy signing payload in CLI and verifying both variants in contract ([#4821]) +- adding ecash contract address ([#4819]) +- Check profit margin of node before defaulting to hardcoded value ([#4802]) +- Sync last_seen_bandwidth immediately ([#4774]) +- Feature/additional ecash nym cli utils ([#4773]) +- Better storage error logging ([#4772]) +- 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]) + +[#4857]: https://github.com/nymtech/nym/pull/4857 +[#4856]: https://github.com/nymtech/nym/pull/4856 +[#4839]: https://github.com/nymtech/nym/pull/4839 +[#4834]: https://github.com/nymtech/nym/pull/4834 +[#4822]: https://github.com/nymtech/nym/pull/4822 +[#4821]: https://github.com/nymtech/nym/pull/4821 +[#4819]: https://github.com/nymtech/nym/pull/4819 +[#4802]: https://github.com/nymtech/nym/pull/4802 +[#4774]: https://github.com/nymtech/nym/pull/4774 +[#4773]: https://github.com/nymtech/nym/pull/4773 +[#4772]: https://github.com/nymtech/nym/pull/4772 +[#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]) diff --git a/Cargo.lock b/Cargo.lock index b5602a891e..30f5a6da4c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,7 +17,7 @@ dependencies = [ "macroific", "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.66", ] [[package]] @@ -32,9 +32,9 @@ dependencies = [ [[package]] name = "addr2line" -version = "0.21.0" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" dependencies = [ "gimli", ] @@ -194,9 +194,9 @@ dependencies = [ [[package]] name = "anstyle-query" -version = "1.0.3" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a64c907d4e79225ac72e2a354c9ce84d50ebb4586dee56c82b3ee73004f537f5" +checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391" dependencies = [ "windows-sys 0.52.0", ] @@ -280,7 +280,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.66", ] [[package]] @@ -291,7 +291,7 @@ checksum = "a27b8a3a6e1a44fa4c8baf1f653e4172e81486d4941f2237e20dc2d0cf4ddff1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.66", ] [[package]] @@ -304,7 +304,7 @@ dependencies = [ "futures-util", "log", "pin-project-lite", - "rustls-native-certs 0.7.3", + "rustls-native-certs 0.7.0", "rustls-pki-types", "tokio", "tokio-rustls 0.25.0", @@ -365,7 +365,7 @@ dependencies = [ "futures-util", "http 0.2.12", "http-body 0.4.6", - "hyper 0.14.28", + "hyper 0.14.29", "itoa", "matchit", "memchr", @@ -477,15 +477,15 @@ dependencies = [ [[package]] name = "backtrace" -version = "0.3.71" +version = "0.3.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" dependencies = [ "addr2line", "cc", "cfg-if", "libc", - "miniz_oxide 0.7.2", + "miniz_oxide 0.7.3", "object", "rustc-demangle", ] @@ -751,9 +751,9 @@ dependencies = [ [[package]] name = "camino" -version = "1.1.6" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c59e92b5a388f549b863a7bea62612c09f24c8393560709a54558a9abdfb3b9c" +checksum = "e0ec6b951b160caa93cc0c7b209e5a3bff7aae9062213451ac99493cd844c239" dependencies = [ "serde", ] @@ -795,9 +795,9 @@ checksum = "a2698f953def977c68f935bb0dfa959375ad4638570e969e2f1e9f433cbf1af6" [[package]] name = "cc" -version = "1.1.15" +version = "1.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57b6a275aa2903740dc87da01c62040406b8812552e97129a63ea8850a17c6e6" +checksum = "b62ac837cdb5cb22e10a256099b4fc502b1dfe560cb282963a974d7abd80e476" dependencies = [ "shlex", ] @@ -946,24 +946,24 @@ checksum = "8cf2dd12af7a047ad9d6da2b6b249759a22a7abc0f474c1dae1777afa4b21a73" dependencies = [ "anstream", "anstyle", - "clap_lex 0.7.0", + "clap_lex 0.7.1", "strsim 0.11.1", ] [[package]] name = "clap_complete" -version = "4.5.26" +version = "4.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "205d5ef6d485fa47606b98b0ddc4ead26eb850aaa86abfb562a94fb3280ecba0" +checksum = "d2020fa13af48afc65a9a87335bda648309ab3d154cd03c7ff95b378c7ed39c4" dependencies = [ "clap 4.5.17", ] [[package]] name = "clap_complete_fig" -version = "4.5.2" +version = "4.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d494102c8ff3951810c72baf96910b980fb065ca5d3101243e6a8dc19747c86b" +checksum = "fb4bc503cddc1cd320736fb555d6598309ad07c2ddeaa23891a10ffb759ee612" dependencies = [ "clap 4.5.17", "clap_complete", @@ -978,7 +978,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.66", ] [[package]] @@ -992,9 +992,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" +checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70" [[package]] name = "colorchoice" @@ -1185,8 +1185,8 @@ version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32560304ab4c365791fd307282f76637213d8083c1a98490c35159cd67852237" dependencies = [ - "prost 0.12.4", - "prost-types 0.12.4", + "prost 0.12.6", + "prost-types 0.12.6", "tendermint-proto 0.34.1", ] @@ -1195,8 +1195,8 @@ name = "cosmos-sdk-proto" version = "0.22.0-pre" source = "git+https://github.com/cosmos/cosmos-rust?rev=4b1332e6d8258ac845cef71589c8d362a669675a#4b1332e6d8258ac845cef71589c8d362a669675a" dependencies = [ - "prost 0.12.4", - "prost-types 0.12.4", + "prost 0.12.6", + "prost-types 0.12.6", "tendermint-proto 0.37.0", ] @@ -1343,9 +1343,9 @@ checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" [[package]] name = "crc32fast" -version = "1.4.0" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" dependencies = [ "cfg-if", ] @@ -1414,9 +1414,9 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.12" +version = "0.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab3db02a9c5b5121e1e42fbdb1aeb65f5e02624cc58c43f2884c6ccac0b82f95" +checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" dependencies = [ "crossbeam-utils", ] @@ -1451,9 +1451,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.19" +version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" [[package]] name = "crossterm" @@ -1633,15 +1633,16 @@ dependencies = [ [[package]] name = "curve25519-dalek" -version = "4.1.3" +version = "4.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" +checksum = "0a677b8922c94e01bdbb12126b0bc852f00447528dee1782229af9c720c3f348" dependencies = [ "cfg-if", "cpufeatures", "curve25519-dalek-derive", "digest 0.10.7", "fiat-crypto", + "platforms", "rustc_version 0.4.0", "serde", "subtle 2.5.0", @@ -1656,7 +1657,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.66", ] [[package]] @@ -1781,12 +1782,12 @@ dependencies = [ [[package]] name = "darling" -version = "0.20.8" +version = "0.20.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54e36fcd13ed84ffdfda6f5be89b31287cbb80c439841fe69e04841435464391" +checksum = "83b2eb4d90d12bdda5ed17de686c2acb4c57914f8f921b8da7e112b5a36f3fe1" dependencies = [ - "darling_core 0.20.8", - "darling_macro 0.20.8", + "darling_core 0.20.9", + "darling_macro 0.20.9", ] [[package]] @@ -1805,16 +1806,16 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.20.8" +version = "0.20.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c2cf1c23a687a1feeb728783b993c4e1ad83d99f351801977dd809b48d0a70f" +checksum = "622687fe0bac72a04e5599029151f5796111b90f1baaa9b544d807a5e31cd120" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", - "strsim 0.10.0", - "syn 2.0.63", + "strsim 0.11.1", + "syn 2.0.66", ] [[package]] @@ -1830,13 +1831,13 @@ dependencies = [ [[package]] name = "darling_macro" -version = "0.20.8" +version = "0.20.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f" +checksum = "733cabb43482b1a1b53eee8583c2b9e8684d592215ea83efd305dd31bc2f0178" dependencies = [ - "darling_core 0.20.8", + "darling_core 0.20.9", "quote", - "syn 2.0.63", + "syn 2.0.66", ] [[package]] @@ -1888,7 +1889,7 @@ dependencies = [ "macroific", "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.66", ] [[package]] @@ -1930,7 +1931,7 @@ checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611" dependencies = [ "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.66", ] [[package]] @@ -1963,7 +1964,7 @@ dependencies = [ "proc-macro2", "proc-macro2-diagnostics", "quote", - "syn 2.0.63", + "syn 2.0.66", ] [[package]] @@ -2019,13 +2020,13 @@ dependencies = [ [[package]] name = "displaydoc" -version = "0.2.5" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.66", ] [[package]] @@ -2103,7 +2104,7 @@ version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871" dependencies = [ - "curve25519-dalek 4.1.3", + "curve25519-dalek 4.1.2", "ed25519", "rand_core 0.6.4", "serde", @@ -2129,9 +2130,9 @@ dependencies = [ [[package]] name = "either" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2" +checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" [[package]] name = "elliptic-curve" @@ -2224,7 +2225,7 @@ checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" [[package]] name = "explorer-api" -version = "1.1.38" +version = "1.1.39" dependencies = [ "chrono", "clap 4.5.17", @@ -2314,14 +2315,14 @@ dependencies = [ [[package]] name = "fancy_constructor" -version = "1.3.0" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07b19d0e43eae2bfbafe4931b5e79c73fb1a849ca15cd41a761a7b8587f9a1a2" +checksum = "f71f317e4af73b2f8f608fac190c52eac4b1879d2145df1db2fe48881ca69435" dependencies = [ "macroific", "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.66", ] [[package]] @@ -2357,9 +2358,9 @@ checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" [[package]] name = "figment" -version = "0.10.18" +version = "0.10.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d032832d74006f99547004d49410a4b4218e4c33382d56ca3ff89df74f86b953" +checksum = "8cb01cd46b0cf372153850f4c6c272d9cbea2da513e07538405148f95bd789f3" dependencies = [ "atomic 0.6.0", "pear", @@ -2381,12 +2382,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "finl_unicode" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fcfdc7a0362c9f4444381a9e697c79d435fe65b52a37466fc2c1184cee9edc6" - [[package]] name = "fixedbitset" version = "0.4.2" @@ -2543,7 +2538,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.66", ] [[package]] @@ -2653,9 +2648,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.28.1" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" [[package]] name = "glob" @@ -2986,9 +2981,9 @@ checksum = "08a397c49fec283e3d6211adbe480be95aae5f304cfb923e9970e08956d5168a" [[package]] name = "httparse" -version = "1.8.0" +version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" +checksum = "d0e7a4dd27b9476dc40cb050d3632d3bba3a70ddbff012285f7f8559a1e7e545" [[package]] name = "httpcodec" @@ -3033,9 +3028,9 @@ dependencies = [ [[package]] name = "hyper" -version = "0.14.28" +version = "0.14.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" +checksum = "f361cde2f109281a220d4307746cdfd5ee3f410da58a70377762396775634b33" dependencies = [ "bytes", "futures-channel", @@ -3083,7 +3078,7 @@ checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" dependencies = [ "futures-util", "http 0.2.12", - "hyper 0.14.28", + "hyper 0.14.29", "rustls 0.21.12", "tokio", "tokio-rustls 0.24.1", @@ -3112,7 +3107,7 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1" dependencies = [ - "hyper 0.14.28", + "hyper 0.14.29", "pin-project-lite", "tokio", "tokio-io-timeout", @@ -3161,6 +3156,124 @@ dependencies = [ "cc", ] +[[package]] +name = "icu_collections" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locid" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_locid_transform" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_locid_transform_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_locid_transform_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" + +[[package]] +name = "icu_normalizer" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "utf16_iter", + "utf8_iter", + "write16", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" + +[[package]] +name = "icu_properties" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f8ac670d7422d7f76b32e17a5db556510825b29ec9154f235977c9caba61036" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locid_transform", + "icu_properties_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" + +[[package]] +name = "icu_provider" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_provider_macros", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_provider_macros" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] + [[package]] name = "ident_case" version = "1.0.1" @@ -3179,12 +3292,14 @@ dependencies = [ [[package]] name = "idna" -version = "0.5.0" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +checksum = "4716a3a0933a1d01c2f72450e89596eb51dd34ef3c211ccd875acdf1f8fe47ed" dependencies = [ - "unicode-bidi", - "unicode-normalization", + "icu_normalizer", + "icu_properties", + "smallvec", + "utf8_iter", ] [[package]] @@ -3195,8 +3310,8 @@ checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" [[package]] name = "indexed_db_futures" -version = "0.4.1" -source = "git+https://github.com/TiemenSch/rust-indexed-db?branch=update-uuid#65ba1be4fec562e0cff55116e004ae081b460144" +version = "0.4.2" +source = "git+https://github.com/TiemenSch/rust-indexed-db?branch=update-uuid#9745d015707008b0c410115d787014a6d1af2efb" dependencies = [ "accessory", "cfg-if", @@ -3298,9 +3413,9 @@ dependencies = [ [[package]] name = "instant" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" dependencies = [ "cfg-if", ] @@ -3548,9 +3663,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.158" +version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" [[package]] name = "libm" @@ -3581,9 +3696,9 @@ dependencies = [ [[package]] name = "libz-sys" -version = "1.1.16" +version = "1.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e143b5e666b2695d28f6bca6497720813f699c9602dd7f5cac91008b8ada7f9" +checksum = "c15da26e5af7e25c90b37a2d75cdbf940cf4a55316de9d84c679c9b8bfabf82e" dependencies = [ "cc", "libc", @@ -3593,9 +3708,9 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" [[package]] name = "lioness" @@ -3609,6 +3724,12 @@ dependencies = [ "keystream", ] +[[package]] +name = "litemap" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "643cb0b8d4fcc284004d5fd0d67ccf61dfffadb7f75e1e71bc420f4688a3a704" + [[package]] name = "lock_api" version = "0.4.12" @@ -3621,9 +3742,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.22" +version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" [[package]] name = "loom" @@ -3676,7 +3797,7 @@ dependencies = [ "cfg-if", "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.66", ] [[package]] @@ -3687,7 +3808,7 @@ checksum = "13198c120864097a565ccb3ff947672d969932b7975ebd4085732c9f09435e55" dependencies = [ "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.66", ] [[package]] @@ -3700,7 +3821,7 @@ dependencies = [ "macroific_core", "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.66", ] [[package]] @@ -3779,9 +3900,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +checksum = "87dfd01fe195c66b572b37921ad8803d010623c0aca821bea2302239d155cdae" dependencies = [ "adler", ] @@ -3809,9 +3930,9 @@ dependencies = [ [[package]] name = "mio" -version = "1.0.2" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" +checksum = "4569e456d394deccd22ce1c1913e6ea0e54519f577285001215d33557431afe4" dependencies = [ "hermit-abi 0.3.9", "libc", @@ -4079,7 +4200,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.66", ] [[package]] @@ -4099,7 +4220,7 @@ checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" [[package]] name = "nym-api" -version = "1.1.42" +version = "1.1.43" dependencies = [ "anyhow", "async-trait", @@ -4332,7 +4453,7 @@ dependencies = [ [[package]] name = "nym-cli" -version = "1.1.40" +version = "1.1.41" dependencies = [ "anyhow", "base64 0.22.1", @@ -4365,6 +4486,7 @@ dependencies = [ "bs58", "cfg-if", "clap 4.5.17", + "colored", "comfy-table 6.2.0", "cosmrs 0.17.0-pre", "cosmwasm-std", @@ -4405,14 +4527,14 @@ dependencies = [ "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", "clap 4.5.17", @@ -5022,6 +5144,7 @@ dependencies = [ "nym-crypto", "nym-pemstore", "nym-sphinx", + "nym-task", "rand", "serde", "serde_json", @@ -5227,6 +5350,7 @@ dependencies = [ "bs58", "cosmwasm-schema", "cosmwasm-std", + "cw-controllers", "cw2", "humantime-serde", "log", @@ -5376,7 +5500,7 @@ dependencies = [ [[package]] name = "nym-network-requester" -version = "1.1.40" +version = "1.1.41" dependencies = [ "addr", "anyhow", @@ -5427,7 +5551,7 @@ dependencies = [ [[package]] name = "nym-node" -version = "1.1.6" +version = "1.1.7" dependencies = [ "anyhow", "bip39", @@ -5609,7 +5733,7 @@ dependencies = [ "chacha20", "chacha20poly1305", "criterion 0.4.0", - "curve25519-dalek 4.1.3", + "curve25519-dalek 4.1.2", "fastrand 2.1.1", "getrandom", "log", @@ -5703,7 +5827,7 @@ dependencies = [ [[package]] name = "nym-socks5-client" -version = "1.1.39" +version = "1.1.40" dependencies = [ "bs58", "clap 4.5.17", @@ -6104,7 +6228,7 @@ dependencies = [ "nym-multisig-contract-common", "nym-network-defaults", "nym-vesting-contract-common", - "prost 0.12.4", + "prost 0.12.6", "reqwest 0.12.4", "serde", "serde_json", @@ -6232,7 +6356,7 @@ dependencies = [ [[package]] name = "nymvisor" -version = "0.1.5" +version = "0.1.6" dependencies = [ "anyhow", "bytes", @@ -6286,9 +6410,9 @@ dependencies = [ [[package]] name = "object" -version = "0.32.2" +version = "0.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +checksum = "576dfe1fc8f9df304abb159d767a29d0476f7750fbf8aa7ad07816004a207434" dependencies = [ "memchr", ] @@ -6564,14 +6688,14 @@ dependencies = [ "proc-macro2", "proc-macro2-diagnostics", "quote", - "syn 2.0.63", + "syn 2.0.66", ] [[package]] name = "peg" -version = "0.8.4" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "295283b02df346d1ef66052a757869b2876ac29a6bb0ac3f5f7cd44aebe40e8f" +checksum = "8a625d12ad770914cbf7eff6f9314c3ef803bfe364a1b20bc36ddf56673e71e5" dependencies = [ "peg-macros", "peg-runtime", @@ -6579,9 +6703,9 @@ dependencies = [ [[package]] name = "peg-macros" -version = "0.8.4" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdad6a1d9cf116a059582ce415d5f5566aabcd4008646779dab7fdc2a9a9d426" +checksum = "f241d42067ed3ab6a4fece1db720838e1418f36d868585a27931f95d6bc03582" dependencies = [ "peg-runtime", "proc-macro2", @@ -6642,7 +6766,7 @@ dependencies = [ "pest_meta", "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.66", ] [[package]] @@ -6683,7 +6807,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.66", ] [[package]] @@ -6715,10 +6839,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" [[package]] -name = "plotters" -version = "0.3.5" +name = "platforms" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2c224ba00d7cadd4d5c660deaf2098e5e80e07846537c51f9cfa4be50c1fd45" +checksum = "db23d408679286588f4d4644f965003d056e3dd5abcaaa938116871d7ce2fee7" + +[[package]] +name = "plotters" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a15b6eccb8484002195a3e44fe65a4ce8e93a625797a063735536fd59cb01cf3" dependencies = [ "num-traits", "plotters-backend", @@ -6729,15 +6859,15 @@ dependencies = [ [[package]] name = "plotters-backend" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e76628b4d3a7581389a35d5b6e2139607ad7c75b17aed325f210aa91f4a9609" +checksum = "414cec62c6634ae900ea1c56128dfe87cf63e7caece0852ec76aba307cebadb7" [[package]] name = "plotters-svg" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38f6d39893cca0701371e3c27294f09797214b86f1fb951b89ade8ec04e2abab" +checksum = "81b30686a7d9c3e010b84284bdd26a29f2138574f52f5eb6f794fc0ad924e705" dependencies = [ "plotters-backend", ] @@ -6783,9 +6913,9 @@ dependencies = [ [[package]] name = "portable-atomic" -version = "1.7.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da544ee218f0d287a911e9c99a39a8c9bc8fcad3cb8db5959940044ecfc67265" +checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0" [[package]] name = "powerfmt" @@ -6854,9 +6984,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.82" +version = "1.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ad3d49ab951a01fbaafe34f2ec74122942fe18a3f9814c3268f1bb72042131b" +checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23" dependencies = [ "unicode-ident", ] @@ -6869,7 +6999,7 @@ checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.66", "version_check", "yansi", ] @@ -6901,12 +7031,12 @@ dependencies = [ [[package]] name = "prost" -version = "0.12.4" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0f5d036824e4761737860779c906171497f6d55681139d8312388f8fe398922" +checksum = "deb1435c188b76130da55f17a466d252ff7b1418b2ad3e037d127b94e3411f29" dependencies = [ "bytes", - "prost-derive 0.12.5", + "prost-derive 0.12.6", ] [[package]] @@ -6924,15 +7054,15 @@ dependencies = [ [[package]] name = "prost-derive" -version = "0.12.5" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9554e3ab233f0a932403704f1a1d08c30d5ccd931adfdfa1e8b5a19b52c1d55a" +checksum = "81bddcdb20abf9501610992b6759a4c888aef7d1a7247ef75e2404275ac24af1" dependencies = [ "anyhow", "itertools 0.12.1", "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.66", ] [[package]] @@ -6946,11 +7076,11 @@ dependencies = [ [[package]] name = "prost-types" -version = "0.12.4" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3235c33eb02c1f1e212abdbe34c78b264b038fb58ca612664343271e36e55ffe" +checksum = "9091c90b0a32608e984ff2fa4091273cbdd755d54935c51d520887f4a1dbd5b0" dependencies = [ - "prost 0.12.4", + "prost 0.12.6", ] [[package]] @@ -6961,9 +7091,9 @@ checksum = "106dd99e98437432fed6519dedecfade6a06a73bb7b2a1e019fdd2bee5778d94" [[package]] name = "psl" -version = "2.1.39" +version = "2.1.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b320cda4ad7e8f4269fa415754418f83b38c666a5e2e99ea48825b274a373f3" +checksum = "ecec637c2e9d0c8c4bf78df069a53a103ebe3dbd0dc7eff1d60c1006a1c97254" dependencies = [ "psl-types", ] @@ -6998,9 +7128,9 @@ checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" [[package]] name = "quote" -version = "1.0.37" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ "proc-macro2", ] @@ -7150,7 +7280,7 @@ checksum = "bcc303e793d3734489387d205e9b186fac9c6cfacedd98cbb2e8a5943595f3e6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.66", ] [[package]] @@ -7161,8 +7291,8 @@ checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.6", - "regex-syntax 0.8.3", + "regex-automata 0.4.7", + "regex-syntax 0.8.4", ] [[package]] @@ -7176,13 +7306,13 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.3", + "regex-syntax 0.8.4", ] [[package]] @@ -7193,9 +7323,9 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" [[package]] name = "reqwest" @@ -7211,7 +7341,7 @@ dependencies = [ "h2", "http 0.2.12", "http-body 0.4.6", - "hyper 0.14.28", + "hyper 0.14.29", "hyper-rustls 0.24.2", "ipnet", "js-sys", @@ -7279,7 +7409,7 @@ dependencies = [ "wasm-bindgen-futures", "wasm-streams", "web-sys", - "webpki-roots 0.26.1", + "webpki-roots 0.26.2", "winreg 0.52.0", ] @@ -7382,7 +7512,7 @@ dependencies = [ "proc-macro2", "quote", "rocket_http", - "syn 2.0.63", + "syn 2.0.66", "unicode-xid", "version_check", ] @@ -7414,7 +7544,7 @@ dependencies = [ "either", "futures", "http 0.2.12", - "hyper 0.14.28", + "hyper 0.14.29", "indexmap 2.2.6", "log", "memchr", @@ -7479,7 +7609,7 @@ dependencies = [ "proc-macro2", "quote", "rust-embed-utils", - "syn 2.0.63", + "syn 2.0.66", "walkdir", ] @@ -7563,7 +7693,7 @@ dependencies = [ "log", "ring 0.17.8", "rustls-pki-types", - "rustls-webpki 0.102.3", + "rustls-webpki 0.102.4", "subtle 2.5.0", "zeroize", ] @@ -7582,9 +7712,9 @@ dependencies = [ [[package]] name = "rustls-native-certs" -version = "0.7.3" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5bfb394eeed242e909609f56089eecfe5fda225042e8b171791b9c95f5931e5" +checksum = "8f1fb85efa936c42c6d5fc28d2629bb51e4b2f4b8a5211e297d599cc5a093792" dependencies = [ "openssl-probe", "rustls-pemfile 2.1.2", @@ -7630,9 +7760,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.102.3" +version = "0.102.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3bce581c0dd41bce533ce695a1437fa16a7ab5ac3ccfa99fe1a620a7885eabf" +checksum = "ff448f7e92e913c4b7d4c6d8e4540a1724b319b4152b8aef6d4cf8339712b33e" dependencies = [ "ring 0.17.8", "rustls-pki-types", @@ -7641,9 +7771,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.16" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "092474d1a01ea8278f69e6a358998405fae5b8b963ddaeb2b0b04a128bf1dfb0" +checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" [[package]] name = "ryu" @@ -7721,8 +7851,8 @@ checksum = "b1eee588578aff73f856ab961cd2f79e36bc45d7ded33a7562adba4667aecc0e" dependencies = [ "proc-macro2", "quote", - "serde_derive_internals 0.29.0", - "syn 2.0.63", + "serde_derive_internals 0.29.1", + "syn 2.0.66", ] [[package]] @@ -7884,7 +8014,7 @@ checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.66", ] [[package]] @@ -7895,18 +8025,18 @@ checksum = "e578a843d40b4189a4d66bba51d7684f57da5bd7c304c64e14bd63efbef49509" dependencies = [ "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.66", ] [[package]] name = "serde_derive_internals" -version = "0.29.0" +version = "0.29.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "330f01ce65a3a5fe59a60c82f3c9a024b573b8a6e875bd233fe5f934e71d54e3" +checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.66", ] [[package]] @@ -7939,7 +8069,7 @@ checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.66", ] [[package]] @@ -7987,10 +8117,10 @@ version = "3.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8fee4991ef4f274617a51ad4af30519438dacb2f56ac773b08a1922ff743350" dependencies = [ - "darling 0.20.8", + "darling 0.20.9", "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.66", ] [[package]] @@ -8205,7 +8335,7 @@ dependencies = [ "byteorder", "chacha", "ctr", - "curve25519-dalek 4.1.3", + "curve25519-dalek 4.1.2", "digest 0.10.7", "hkdf", "hmac", @@ -8244,11 +8374,10 @@ dependencies = [ [[package]] name = "sqlformat" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce81b7bd7c4493975347ef60d8c7e8b742d4694f4c49f93e0a12ea263938176c" +checksum = "f895e3734318cc55f1fe66258926c9b910c124d47520339efecbb6c59cec7c1f" dependencies = [ - "itertools 0.12.1", "nom", "unicode_categories", ] @@ -8394,6 +8523,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + [[package]] name = "state" version = "0.6.0" @@ -8405,13 +8540,13 @@ dependencies = [ [[package]] name = "stringprep" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb41d74e231a107a1b4ee36bd1214b11285b77768d2e3824aedafa988fd36ee6" +checksum = "7b4df3d392d81bd458a8a621b8bffbd2302a12ffe288a9d931670948749463b1" dependencies = [ - "finl_unicode", "unicode-bidi", "unicode-normalization", + "unicode-properties", ] [[package]] @@ -8492,7 +8627,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.63", + "syn 2.0.66", ] [[package]] @@ -8505,7 +8640,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.63", + "syn 2.0.66", ] [[package]] @@ -8548,9 +8683,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.63" +version = "2.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf5be731623ca1a1fb7d8be6f261a3be6d3e2337b8a1f97be944d020c8fcb704" +checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" dependencies = [ "proc-macro2", "quote", @@ -8569,6 +8704,17 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" +[[package]] +name = "synstructure" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] + [[package]] name = "sysinfo" version = "0.30.12" @@ -8649,8 +8795,8 @@ dependencies = [ "k256", "num-traits", "once_cell", - "prost 0.12.4", - "prost-types 0.12.4", + "prost 0.12.6", + "prost-types 0.12.6", "ripemd", "serde", "serde_bytes", @@ -8680,8 +8826,8 @@ dependencies = [ "k256", "num-traits", "once_cell", - "prost 0.12.4", - "prost-types 0.12.4", + "prost 0.12.6", + "prost-types 0.12.6", "ripemd", "serde", "serde_bytes", @@ -8720,8 +8866,8 @@ dependencies = [ "flex-error", "num-derive", "num-traits", - "prost 0.12.4", - "prost-types 0.12.4", + "prost 0.12.6", + "prost-types 0.12.6", "serde", "serde_bytes", "subtle-encoding", @@ -8736,8 +8882,8 @@ checksum = "dc87024548c7f3da479885201e3da20ef29e85a3b13d04606b380ac4c7120d87" dependencies = [ "bytes", "flex-error", - "prost 0.12.4", - "prost-types 0.12.4", + "prost 0.12.6", + "prost-types 0.12.6", "serde", "serde_bytes", "subtle-encoding", @@ -8849,7 +8995,7 @@ checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" dependencies = [ "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.66", ] [[package]] @@ -8918,6 +9064,16 @@ dependencies = [ "time-core", ] +[[package]] +name = "tinystr" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" +dependencies = [ + "displaydoc", + "zerovec", +] + [[package]] name = "tinytemplate" version = "1.2.1" @@ -8945,14 +9101,14 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.39.3" +version = "1.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9babc99b9923bfa4804bd74722ff02c0381021eafa4db9949217e3be8e84fff5" +checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" dependencies = [ "backtrace", "bytes", "libc", - "mio 1.0.2", + "mio 1.0.1", "parking_lot 0.12.3", "pin-project-lite", "signal-hook-registry", @@ -8980,7 +9136,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.66", ] [[package]] @@ -9171,7 +9327,7 @@ dependencies = [ "serde", "serde_spanned", "toml_datetime", - "winnow 0.6.8", + "winnow 0.6.13", ] [[package]] @@ -9189,7 +9345,7 @@ dependencies = [ "h2", "http 0.2.12", "http-body 0.4.6", - "hyper 0.14.28", + "hyper 0.14.29", "hyper-timeout", "percent-encoding", "pin-project", @@ -9279,7 +9435,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.66", ] [[package]] @@ -9437,7 +9593,7 @@ dependencies = [ "Inflector", "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.66", "termcolor", ] @@ -9464,7 +9620,7 @@ dependencies = [ "proc-macro2", "quote", "serde_derive_internals 0.28.0", - "syn 2.0.63", + "syn 2.0.66", ] [[package]] @@ -9580,6 +9736,12 @@ dependencies = [ "tinyvec", ] +[[package]] +name = "unicode-properties" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4259d9d4425d9f0661581b804cb85fe66a4c631cadd8f490d1c13a35d5d9291" + [[package]] name = "unicode-segmentation" version = "1.11.0" @@ -9588,9 +9750,9 @@ checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" [[package]] name = "unicode-width" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68f5e5f3158ecfd4b8ff6fe086db7c8467a2dfdac97fe420f2b7c4aa97af66d6" +checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" [[package]] name = "unicode-xid" @@ -9649,12 +9811,12 @@ checksum = "0976c77def3f1f75c4ef892a292c31c0bbe9e3d0702c63044d7c76db298171a3" [[package]] name = "url" -version = "2.5.2" +version = "2.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" +checksum = "f7c25da092f0a868cdf09e8674cd3b7ef3a7d92a24253e663a2fb85e2496de56" dependencies = [ "form_urlencoded", - "idna 0.5.0", + "idna 1.0.0", "percent-encoding", "serde", ] @@ -9672,10 +9834,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" [[package]] -name = "utf8parse" -version = "0.2.1" +name = "utf16_iter" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" +checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "utoipa" @@ -9699,7 +9873,7 @@ dependencies = [ "proc-macro2", "quote", "regex", - "syn 2.0.63", + "syn 2.0.66", ] [[package]] @@ -9737,7 +9911,7 @@ checksum = "17e82ab96c5a55263b5bed151b8426410d93aa909a453acdbd4b6792b5af7d64" dependencies = [ "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.66", ] [[package]] @@ -9748,15 +9922,15 @@ checksum = "86b8338dc3c9526011ffaa2aa6bd60ddfda9d49d2123108690755c6e34844212" dependencies = [ "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.66", "utoipauto-core", ] [[package]] name = "uuid" -version = "1.10.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314" +checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0" dependencies = [ "getrandom", "serde", @@ -9849,7 +10023,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.66", "wasm-bindgen-shared", ] @@ -9883,7 +10057,7 @@ checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" dependencies = [ "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.66", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -9917,7 +10091,7 @@ checksum = "4b8220be1fa9e4c889b30fd207d4906657e7e90b12e0e6b0c8b8d8709f5de021" dependencies = [ "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.66", ] [[package]] @@ -10057,9 +10231,9 @@ checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" [[package]] name = "webpki-roots" -version = "0.26.1" +version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3de34ae270483955a94f4b21bdaaeb83d508bb84a01435f393818edb0012009" +checksum = "3c452ad30530b54a4d8e71952716a212b08efd0f3562baa66c29a618b07da7c3" dependencies = [ "rustls-pki-types", ] @@ -10339,9 +10513,9 @@ dependencies = [ [[package]] name = "winnow" -version = "0.6.8" +version = "0.6.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3c52e9c97a68071b23e836c9380edae937f17b9c4667bd021973efc689f618d" +checksum = "59b5e5f6c299a3c7890b876a2a587f3115162487e704907d9b6cd29473052ba1" dependencies = [ "memchr", ] @@ -10386,6 +10560,18 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "write16" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" + +[[package]] +name = "writeable" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" + [[package]] name = "wyz" version = "0.5.1" @@ -10401,7 +10587,7 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7e468321c81fb07fa7f4c636c3972b9100f0346e5b6a9f2bd0603a52f7ed277" dependencies = [ - "curve25519-dalek 4.1.3", + "curve25519-dalek 4.1.2", "rand_core 0.6.4", "serde", "zeroize", @@ -10427,6 +10613,30 @@ dependencies = [ "is-terminal", ] +[[package]] +name = "yoke" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c5b1314b079b0930c31e3af543d8ee1757b1951ae1e1565ec704403a7240ca5" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", + "synstructure", +] + [[package]] name = "zerocopy" version = "0.7.34" @@ -10444,7 +10654,28 @@ checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.66", +] + +[[package]] +name = "zerofrom" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91ec111ce797d0e0784a1116d0ddcdbea84322cd79e5d5ad173daeba4f93ab55" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", + "synstructure", ] [[package]] @@ -10464,7 +10695,29 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.66", +] + +[[package]] +name = "zerovec" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb2cc8827d6c0994478a15c53f374f46fbd41bea663d809b14744bc42e6b109c" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97cf56601ee5052b4417d90c8755c6683473c926039908196cf35d99f893ebe7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", ] [[package]] diff --git a/clients/native/Cargo.toml b/clients/native/Cargo.toml index f57505eb66..7e253719c2 100644 --- a/clients/native/Cargo.toml +++ b/clients/native/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nym-client" -version = "1.1.39" +version = "1.1.40" authors = ["Dave Hrycyszyn ", "Jędrzej Stuczyński "] description = "Implementation of the Nym Client" edition = "2021" diff --git a/clients/socks5/Cargo.toml b/clients/socks5/Cargo.toml index 06754b0b76..ee15f6747c 100644 --- a/clients/socks5/Cargo.toml +++ b/clients/socks5/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nym-socks5-client" -version = "1.1.39" +version = "1.1.40" authors = ["Dave Hrycyszyn "] description = "A SOCKS5 localhost proxy that converts incoming messages to Sphinx and sends them to a Nym address" edition = "2021" diff --git a/common/bandwidth-controller/src/acquire/mod.rs b/common/bandwidth-controller/src/acquire/mod.rs index 51afe221fe..e2d18d5545 100644 --- a/common/bandwidth-controller/src/acquire/mod.rs +++ b/common/bandwidth-controller/src/acquire/mod.rs @@ -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( +pub async fn query_and_persist_required_global_data( storage: &S, epoch_id: EpochId, expiration_date: Date, @@ -65,6 +67,10 @@ where S: 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?; diff --git a/common/bandwidth-controller/src/lib.rs b/common/bandwidth-controller/src/lib.rs index 4485009b68..a164d3df60 100644 --- a/common/bandwidth-controller/src/lib.rs +++ b/common/bandwidth-controller/src/lib.rs @@ -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 BandwidthController { .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, diff --git a/common/client-libs/gateway-client/src/client/mod.rs b/common/client-libs/gateway-client/src/client/mod.rs index e544a610b6..d899ec2928 100644 --- a/common/client-libs/gateway-client/src/client/mod.rs +++ b/common/client-libs/gateway-client/src/client/mod.rs @@ -417,6 +417,8 @@ impl GatewayClient { 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), diff --git a/common/client-libs/validator-client/src/nyxd/contract_traits/mixnet_query_client.rs b/common/client-libs/validator-client/src/nyxd/contract_traits/mixnet_query_client.rs index 95d692d592..47b67d8f16 100644 --- a/common/client-libs/validator-client/src/nyxd/contract_traits/mixnet_query_client.rs +++ b/common/client-libs/validator-client/src/nyxd/contract_traits/mixnet_query_client.rs @@ -42,6 +42,10 @@ pub trait MixnetQueryClient { // state/sys-params-related + async fn admin(&self) -> Result { + self.query_mixnet_contract(MixnetQueryMsg::Admin {}).await + } + async fn get_mixnet_contract_version(&self) -> Result { self.query_mixnet_contract(MixnetQueryMsg::GetContractVersion {}) .await @@ -580,6 +584,7 @@ mod tests { msg: MixnetQueryMsg, ) -> u32 { match msg { + MixnetQueryMsg::Admin {} => client.admin().ignore(), MixnetQueryMsg::GetAllFamiliesPaged { limit, start_after } => client .get_all_family_members_paged(start_after, limit) .ignore(), diff --git a/common/client-libs/validator-client/src/nyxd/contract_traits/mixnet_signing_client.rs b/common/client-libs/validator-client/src/nyxd/contract_traits/mixnet_signing_client.rs index 26a766a190..f84becb55f 100644 --- a/common/client-libs/validator-client/src/nyxd/contract_traits/mixnet_signing_client.rs +++ b/common/client-libs/validator-client/src/nyxd/contract_traits/mixnet_signing_client.rs @@ -31,6 +31,15 @@ pub trait MixnetSigningClient { // state/sys-params-related + async fn update_admin( + &self, + admin: String, + fee: Option, + ) -> Result { + self.execute_mixnet_contract(fee, MixnetExecuteMsg::UpdateAdmin { admin }, vec![]) + .await + } + async fn update_rewarding_validator_address( &self, address: AccountId, @@ -760,6 +769,7 @@ mod tests { msg: MixnetExecuteMsg, ) { match msg { + MixnetExecuteMsg::UpdateAdmin { admin } => client.update_admin(admin, None).ignore(), MixnetExecuteMsg::AssignNodeLayer { mix_id, layer } => { client.assign_node_layer(mix_id, layer, None).ignore() } diff --git a/common/client-libs/validator-client/src/nyxd/cosmwasm_client/helpers.rs b/common/client-libs/validator-client/src/nyxd/cosmwasm_client/helpers.rs index b60b4982cd..d6e42daac7 100644 --- a/common/client-libs/validator-client/src/nyxd/cosmwasm_client/helpers.rs +++ b/common/client-libs/validator-client/src/nyxd/cosmwasm_client/helpers.rs @@ -1,6 +1,7 @@ // Copyright 2021 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 +use crate::nyxd::cosmwasm_client::types::ExecuteResult; use crate::nyxd::error::NyxdError; use base64::Engine; use cosmrs::abci::TxMsgData; @@ -10,7 +11,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 { diff --git a/common/client-libs/validator-client/src/nyxd/cosmwasm_client/logs.rs b/common/client-libs/validator-client/src/nyxd/cosmwasm_client/logs.rs index 4a31a1fc7e..3d5ecab961 100644 --- a/common/client-libs/validator-client/src/nyxd/cosmwasm_client/logs.rs +++ b/common/client-libs/validator-client/src/nyxd/cosmwasm_client/logs.rs @@ -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 { let maybe_attributes = logs .iter() diff --git a/common/client-libs/validator-client/src/nyxd/helpers.rs b/common/client-libs/validator-client/src/nyxd/helpers.rs index cec865252a..3fbfdaaaf3 100644 --- a/common/client-libs/validator-client/src/nyxd/helpers.rs +++ b/common/client-libs/validator-client/src/nyxd/helpers.rs @@ -1,12 +1,24 @@ // Copyright 2023 - Nym Technologies SA // 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 { - 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 { + 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 { + // 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) +} diff --git a/common/commands/Cargo.toml b/common/commands/Cargo.toml index b922baa10b..c9bd11775d 100644 --- a/common/commands/Cargo.toml +++ b/common/commands/Cargo.toml @@ -10,6 +10,7 @@ anyhow = { workspace = true } 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"] } @@ -28,7 +29,7 @@ thiserror = { workspace = true } tempfile = { workspace = true } time = { workspace = true, features = ["parsing", "formatting"] } tokio = { workspace = true, features = ["sync"] } -toml = "0.5.6" +toml = { workspace = true } url = { workspace = true } tap = { workspace = true } zeroize = { workspace = true } diff --git a/common/commands/src/ecash/generate_ticket.rs b/common/commands/src/ecash/generate_ticket.rs new file mode 100644 index 0000000000..67a85ab093 --- /dev/null +++ b/common/commands/src/ecash/generate_ticket.rs @@ -0,0 +1,178 @@ +// Copyright 2024 - Nym Technologies SA +// 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, + + /// 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, + + /// Path to the dedicated credential storage database + #[clap(long, group = "source")] + pub(crate) credential_storage: Option, +} + +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(()) +} diff --git a/common/commands/src/ecash/import_ticket_book.rs b/common/commands/src/ecash/import_ticket_book.rs index 4900b37ef5..2c5d597659 100644 --- a/common/commands/src/ecash/import_ticket_book.rs +++ b/common/commands/src/ecash/import_ticket_book.rs @@ -10,9 +10,17 @@ use nym_id::import_credential::import_full_ticketbook; use nym_id::import_standalone_ticketbook; use std::fs; use std::path::PathBuf; +use std::str::FromStr; -fn parse_encoded_credential_data(raw: &str) -> bs58::decode::Result> { - bs58::decode(raw).into_vec() +#[derive(Debug, Clone)] +pub struct CredentialDataWrapper(Vec); + +impl FromStr for CredentialDataWrapper { + type Err = bs58::decode::Error; + + fn from_str(s: &str) -> Result { + bs58::decode(s).into_vec().map(CredentialDataWrapper) + } } #[derive(Debug, Parser)] @@ -26,8 +34,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>, + #[clap(long, group = "cred_data")] + pub(crate) credential_data: Option, /// Specifies the path to file containing binary credential data #[clap(long, group = "cred_data")] @@ -50,7 +58,7 @@ pub struct Args { impl Args { fn credential_data(self) -> anyhow::Result> { let data = match self.credential_data { - Some(data) => data, + Some(data) => data.0, None => { // SAFETY: one of those arguments must have been set #[allow(clippy::unwrap_used)] diff --git a/common/commands/src/ecash/mod.rs b/common/commands/src/ecash/mod.rs index b307e8dc8c..72f9211ff4 100644 --- a/common/commands/src/ecash/mod.rs +++ b/common/commands/src/ecash/mod.rs @@ -3,6 +3,7 @@ use clap::{Args, Subcommand}; +pub mod generate_ticket; pub mod import_coin_index_signatures; pub mod import_expiration_date_signatures; pub mod import_master_verification_key; @@ -22,6 +23,7 @@ pub enum EcashCommands { IssueTicketBook(issue_ticket_book::Args), RecoverTicketBook(recover_ticket_book::Args), ImportTicketBook(import_ticket_book::Args), + GenerateTicket(generate_ticket::Args), ImportCoinIndexSignatures(import_coin_index_signatures::Args), ImportExpirationDateSignatures(import_expiration_date_signatures::Args), ImportMasterVerificationKey(import_master_verification_key::Args), diff --git a/common/commands/src/validator/mixnet/operators/gateway/gateway_bonding_sign_payload.rs b/common/commands/src/validator/mixnet/operators/gateway/gateway_bonding_sign_payload.rs index ba19f61867..0747dcac3c 100644 --- a/common/commands/src/validator/mixnet/operators/gateway/gateway_bonding_sign_payload.rs +++ b/common/commands/src/validator/mixnet/operators/gateway/gateway_bonding_sign_payload.rs @@ -6,7 +6,7 @@ use crate::utils::{account_id_to_cw_addr, DataWrapper}; use clap::Parser; use cosmwasm_std::Coin; use nym_bin_common::output_format::OutputFormat; -use nym_mixnet_contract_common::construct_gateway_bonding_sign_payload; +use nym_mixnet_contract_common::construct_legacy_gateway_bonding_sign_payload; use nym_network_defaults::{DEFAULT_CLIENT_LISTENING_PORT, DEFAULT_MIX_LISTENING_PORT}; use nym_validator_client::nyxd::contract_traits::MixnetQueryClient; @@ -71,7 +71,7 @@ pub async fn create_payload(args: Args, client: SigningClient) { let address = account_id_to_cw_addr(&client.address()); - let payload = construct_gateway_bonding_sign_payload(nonce, address, coin, gateway); + let payload = construct_legacy_gateway_bonding_sign_payload(nonce, address, coin, gateway); let wrapper = DataWrapper::new(payload.to_base58_string().unwrap()); println!("{}", args.output.format(&wrapper)) } diff --git a/common/commands/src/validator/mixnet/operators/mixnode/keys/decode_mixnode_key.rs b/common/commands/src/validator/mixnet/operators/mixnode/keys/decode_mixnode_key.rs index 54d00010af..fc16a067d2 100644 --- a/common/commands/src/validator/mixnet/operators/mixnode/keys/decode_mixnode_key.rs +++ b/common/commands/src/validator/mixnet/operators/mixnode/keys/decode_mixnode_key.rs @@ -1,7 +1,6 @@ // Copyright 2021 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use base64::Engine; use clap::Parser; #[derive(Debug, Parser)] @@ -11,7 +10,9 @@ pub struct Args { } pub fn decode_mixnode_key(args: Args) { - let b64_decoded = base64::prelude::BASE64_STANDARD + 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(); diff --git a/common/commands/src/validator/mixnet/operators/mixnode/mixnode_bonding_sign_payload.rs b/common/commands/src/validator/mixnet/operators/mixnode/mixnode_bonding_sign_payload.rs index a492b3a0b6..3eda67a2e9 100644 --- a/common/commands/src/validator/mixnet/operators/mixnode/mixnode_bonding_sign_payload.rs +++ b/common/commands/src/validator/mixnet/operators/mixnode/mixnode_bonding_sign_payload.rs @@ -7,7 +7,9 @@ use clap::Parser; use cosmwasm_std::{Coin, Uint128}; use nym_bin_common::output_format::OutputFormat; use nym_contracts_common::Percent; -use nym_mixnet_contract_common::{construct_mixnode_bonding_sign_payload, MixNodeCostParams}; +use nym_mixnet_contract_common::{ + construct_legacy_mixnode_bonding_sign_payload, MixNodeCostParams, +}; use nym_network_defaults::{ DEFAULT_HTTP_API_LISTENING_PORT, DEFAULT_MIX_LISTENING_PORT, DEFAULT_VERLOC_LISTENING_PORT, }; @@ -98,7 +100,7 @@ pub async fn create_payload(args: Args, client: SigningClient) { let address = account_id_to_cw_addr(&client.address()); let payload = - construct_mixnode_bonding_sign_payload(nonce, address, coin, mixnode, cost_params); + construct_legacy_mixnode_bonding_sign_payload(nonce, address, coin, mixnode, cost_params); let wrapper = DataWrapper::new(payload.to_base58_string().unwrap()); println!("{}", args.output.format(&wrapper)) } diff --git a/common/commands/src/validator/mixnet/operators/mixnode/settings/update_cost_params.rs b/common/commands/src/validator/mixnet/operators/mixnode/settings/update_cost_params.rs index 0616a81d33..7c09ba2946 100644 --- a/common/commands/src/validator/mixnet/operators/mixnode/settings/update_cost_params.rs +++ b/common/commands/src/validator/mixnet/operators/mixnode/settings/update_cost_params.rs @@ -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, @@ -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)), diff --git a/common/cosmwasm-smart-contracts/contracts-common/src/signing/mod.rs b/common/cosmwasm-smart-contracts/contracts-common/src/signing/mod.rs index d2722b2f59..228e188b84 100644 --- a/common/cosmwasm-smart-contracts/contracts-common/src/signing/mod.rs +++ b/common/cosmwasm-smart-contracts/contracts-common/src/signing/mod.rs @@ -248,3 +248,31 @@ impl ContractMessageContent { } } } + +impl From> for LegacyContractMessageContent { + fn from(value: ContractMessageContent) -> Self { + LegacyContractMessageContent { + sender: value.sender, + proxy: None, + funds: value.funds, + data: value.data, + } + } +} + +#[derive(Serialize)] +pub struct LegacyContractMessageContent { + pub sender: Addr, + pub proxy: Option, + pub funds: Vec, + pub data: T, +} + +impl SigningPurpose for LegacyContractMessageContent +where + T: SigningPurpose, +{ + fn message_type() -> MessageType { + T::message_type() + } +} diff --git a/common/cosmwasm-smart-contracts/mixnet-contract/Cargo.toml b/common/cosmwasm-smart-contracts/mixnet-contract/Cargo.toml index f75b1777f4..a121f544ee 100644 --- a/common/cosmwasm-smart-contracts/mixnet-contract/Cargo.toml +++ b/common/cosmwasm-smart-contracts/mixnet-contract/Cargo.toml @@ -12,6 +12,7 @@ repository = { workspace = true } bs58 = "0.5.1" cosmwasm-std = { workspace = true } cosmwasm-schema = { workspace = true } +cw-controllers = { workspace = true } cw2 = { workspace = true, optional = true } serde = { workspace = true, features = ["derive"] } serde_repr = { workspace = true } diff --git a/common/cosmwasm-smart-contracts/mixnet-contract/src/error.rs b/common/cosmwasm-smart-contracts/mixnet-contract/src/error.rs index 710ca20b16..12f2030acc 100644 --- a/common/cosmwasm-smart-contracts/mixnet-contract/src/error.rs +++ b/common/cosmwasm-smart-contracts/mixnet-contract/src/error.rs @@ -5,6 +5,7 @@ use crate::{EpochEventId, EpochState, IdentityKey, MixId, OperatingCostRange, Pr use contracts_common::signing::verifier::ApiVerifierError; use contracts_common::Percent; use cosmwasm_std::{Addr, Coin, Decimal, Uint128}; +use cw_controllers::AdminError; use thiserror::Error; #[derive(Error, Debug, PartialEq)] @@ -12,6 +13,9 @@ pub enum MixnetContractError { #[error("could not perform contract migration: {comment}")] FailedMigration { comment: String }, + #[error(transparent)] + Admin(#[from] AdminError), + #[error("{source}")] StdErr { #[from] diff --git a/common/cosmwasm-smart-contracts/mixnet-contract/src/msg.rs b/common/cosmwasm-smart-contracts/mixnet-contract/src/msg.rs index 90110e0dc6..863fdc0327 100644 --- a/common/cosmwasm-smart-contracts/mixnet-contract/src/msg.rs +++ b/common/cosmwasm-smart-contracts/mixnet-contract/src/msg.rs @@ -110,6 +110,11 @@ impl InitialRewardingParams { #[cw_serde] pub enum ExecuteMsg { + /// Change the admin + UpdateAdmin { + admin: String, + }, + AssignNodeLayer { mix_id: MixId, layer: Layer, @@ -292,6 +297,7 @@ pub enum ExecuteMsg { impl ExecuteMsg { pub fn default_memo(&self) -> String { match self { + ExecuteMsg::UpdateAdmin { admin } => format!("updating contract admin to {admin}"), ExecuteMsg::AssignNodeLayer { mix_id, layer } => { format!("assigning mix {mix_id} for layer {layer:?}") } @@ -408,6 +414,9 @@ impl ExecuteMsg { #[cw_serde] #[cfg_attr(feature = "schema", derive(QueryResponses))] pub enum QueryMsg { + #[cfg_attr(feature = "schema", returns(cw_controllers::AdminResponse))] + Admin {}, + // families /// Gets the list of families registered in this contract. #[cfg_attr(feature = "schema", returns(PagedFamiliesResponse))] diff --git a/common/cosmwasm-smart-contracts/mixnet-contract/src/signing_types.rs b/common/cosmwasm-smart-contracts/mixnet-contract/src/signing_types.rs index 84c9b8b4aa..261fa99ff0 100644 --- a/common/cosmwasm-smart-contracts/mixnet-contract/src/signing_types.rs +++ b/common/cosmwasm-smart-contracts/mixnet-contract/src/signing_types.rs @@ -4,13 +4,18 @@ use crate::families::FamilyHead; use crate::{Gateway, IdentityKey, MixNode, MixNodeCostParams}; use contracts_common::signing::{ - ContractMessageContent, MessageType, Nonce, SignableMessage, SigningPurpose, + ContractMessageContent, LegacyContractMessageContent, MessageType, Nonce, SignableMessage, + SigningPurpose, }; use cosmwasm_std::{Addr, Coin}; use serde::Serialize; pub type SignableMixNodeBondingMsg = SignableMessage>; pub type SignableGatewayBondingMsg = SignableMessage>; +pub type SignableLegacyMixNodeBondingMsg = + SignableMessage>; +pub type SignableLegacyGatewayBondingMsg = + SignableMessage>; pub type SignableFamilyJoinPermitMsg = SignableMessage; #[derive(Serialize)] @@ -47,6 +52,20 @@ pub fn construct_mixnode_bonding_sign_payload( SignableMessage::new(nonce, content) } +pub fn construct_legacy_mixnode_bonding_sign_payload( + nonce: Nonce, + sender: Addr, + pledge: Coin, + mix_node: MixNode, + cost_params: MixNodeCostParams, +) -> SignableLegacyMixNodeBondingMsg { + let payload = MixnodeBondingPayload::new(mix_node, cost_params); + let content: LegacyContractMessageContent<_> = + ContractMessageContent::new(sender, vec![pledge], payload).into(); + + SignableMessage::new(nonce, content) +} + #[derive(Serialize)] pub struct GatewayBondingPayload { gateway: Gateway, @@ -76,6 +95,19 @@ pub fn construct_gateway_bonding_sign_payload( SignableMessage::new(nonce, content) } +pub fn construct_legacy_gateway_bonding_sign_payload( + nonce: Nonce, + sender: Addr, + pledge: Coin, + gateway: Gateway, +) -> SignableLegacyGatewayBondingMsg { + let payload = GatewayBondingPayload::new(gateway); + let content: LegacyContractMessageContent<_> = + ContractMessageContent::new(sender, vec![pledge], payload).into(); + + SignableMessage::new(nonce, content) +} + #[derive(Serialize)] pub struct FamilyJoinPermit { // the granter of this permit diff --git a/common/cosmwasm-smart-contracts/mixnet-contract/src/types.rs b/common/cosmwasm-smart-contracts/mixnet-contract/src/types.rs index 18c7fc6606..f95c15eb34 100644 --- a/common/cosmwasm-smart-contracts/mixnet-contract/src/types.rs +++ b/common/cosmwasm-smart-contracts/mixnet-contract/src/types.rs @@ -187,7 +187,11 @@ impl Index for LayerDistribution { #[cw_serde] pub struct ContractState { /// Address of the contract owner. - pub owner: Addr, + #[deprecated( + note = "use explicit ADMIN instead. this field will be removed in future release" + )] + #[serde(default)] + pub owner: Option, /// Address of "rewarding validator" (nym-api) that's allowed to send any rewarding-related transactions. pub rewarding_validator_address: Addr, diff --git a/common/credential-utils/src/utils.rs b/common/credential-utils/src/utils.rs index 41381d53f9..be7133b4c2 100644 --- a/common/credential-utils/src/utils.rs +++ b/common/credential-utils/src/utils.rs @@ -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, diff --git a/common/credential-verification/src/ecash/credential_sender.rs b/common/credential-verification/src/ecash/credential_sender.rs index 47653cf334..4da2095f43 100644 --- a/common/credential-verification/src/ecash/credential_sender.rs +++ b/common/credential-verification/src/ecash/credential_sender.rs @@ -122,7 +122,7 @@ pub struct CredentialHandlerConfig { 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. pub maximum_time_between_redemption: Duration, } diff --git a/common/credentials/src/ecash/bandwidth/issued.rs b/common/credentials/src/ecash/bandwidth/issued.rs index a471e7901d..f8e42a3538 100644 --- a/common/credentials/src/ecash/bandwidth/issued.rs +++ b/common/credentials/src/ecash/bandwidth/issued.rs @@ -7,7 +7,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; @@ -115,6 +115,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( &mut self, verification_key: &VerificationKeyAuth, diff --git a/common/crypto/src/asymmetric/encryption/mod.rs b/common/crypto/src/asymmetric/encryption/mod.rs index 7f501445b9..1ea4b9d95a 100644 --- a/common/crypto/src/asymmetric/encryption/mod.rs +++ b/common/crypto/src/asymmetric/encryption/mod.rs @@ -80,6 +80,15 @@ impl KeyPair { } } +impl From for KeyPair { + fn from(private_key: PrivateKey) -> Self { + KeyPair { + public_key: (&private_key).into(), + private_key, + } + } +} + impl PemStorableKeyPair for KeyPair { type PrivatePemKey = PrivateKey; type PublicPemKey = PublicKey; diff --git a/common/crypto/src/asymmetric/identity/mod.rs b/common/crypto/src/asymmetric/identity/mod.rs index 3536782e94..e2d3df624d 100644 --- a/common/crypto/src/asymmetric/identity/mod.rs +++ b/common/crypto/src/asymmetric/identity/mod.rs @@ -90,6 +90,15 @@ impl KeyPair { } } +impl From for KeyPair { + fn from(private_key: PrivateKey) -> Self { + KeyPair { + public_key: (&private_key).into(), + private_key, + } + } +} + impl PemStorableKeyPair for KeyPair { type PrivatePemKey = PrivateKey; type PublicPemKey = PublicKey; diff --git a/common/gateway-requests/Cargo.toml b/common/gateway-requests/Cargo.toml index c1dadc4732..72a2bdfe9d 100644 --- a/common/gateway-requests/Cargo.toml +++ b/common/gateway-requests/Cargo.toml @@ -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" } diff --git a/common/gateway-requests/src/registration/handshake/client.rs b/common/gateway-requests/src/registration/handshake/client.rs index edb30ebf20..902a520bca 100644 --- a/common/gateway-requests/src/registration/handshake/client.rs +++ b/common/gateway-requests/src/registration/handshake/client.rs @@ -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 + Sink + 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 { diff --git a/common/gateway-requests/src/registration/handshake/error.rs b/common/gateway-requests/src/registration/handshake/error.rs index 8fee78fd38..6e82ef040c 100644 --- a/common/gateway-requests/src/registration/handshake/error.rs +++ b/common/gateway-requests/src/registration/handshake/error.rs @@ -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, diff --git a/common/gateway-requests/src/registration/handshake/gateway.rs b/common/gateway-requests/src/registration/handshake/gateway.rs index bb0003d0a3..a42851a320 100644 --- a/common/gateway-requests/src/registration/handshake/gateway.rs +++ b/common/gateway-requests/src/registration/handshake/gateway.rs @@ -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, + shutdown: TaskClient, ) -> Self where S: Stream + Sink + 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), diff --git a/common/gateway-requests/src/registration/handshake/mod.rs b/common/gateway-requests/src/registration/handshake/mod.rs index 4e21fcfc0d..d3faec7903 100644 --- a/common/gateway-requests/src/registration/handshake/mod.rs +++ b/common/gateway-requests/src/registration/handshake/mod.rs @@ -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 where S: Stream + Sink + 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, + shutdown: TaskClient, ) -> Result where S: Stream + Sink + Unpin + Send + 'a, { - GatewayHandshake::new(rng, ws_stream, identity, received_init_payload).await + GatewayHandshake::new(rng, ws_stream, identity, received_init_payload, shutdown).await } /* diff --git a/common/gateway-requests/src/registration/handshake/state.rs b/common/gateway-requests/src/registration/handshake/state.rs index 328b5d59cb..70cd48620c 100644 --- a/common/gateway-requests/src/registration/handshake/state.rs +++ b/common/gateway-requests/src/registration/handshake/state.rs @@ -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, 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) -> Result>, 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, HandshakeError> where S: Stream + 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, HandshakeError> + where + S: Stream + 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, HandshakeError> where S: Stream + Unpin, diff --git a/common/gateway-storage/Cargo.toml b/common/gateway-storage/Cargo.toml index eb18f1444e..26b2be56a1 100644 --- a/common/gateway-storage/Cargo.toml +++ b/common/gateway-storage/Cargo.toml @@ -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"] diff --git a/common/gateway-storage/src/lib.rs b/common/gateway-storage/src/lib.rs index a0a78fdb91..01612c7340 100644 --- a/common/gateway-storage/src/lib.rs +++ b/common/gateway-storage/src/lib.rs @@ -25,7 +25,6 @@ mod inboxes; pub 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, StorageError>; /// Retrieves all wireguard peers. - #[cfg(feature = "wireguard")] async fn get_all_wireguard_peers(&self) -> Result, 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, 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) diff --git a/common/gateway-storage/src/models.rs b/common/gateway-storage/src/models.rs index e1973ac1e3..dc0229d1f3 100644 --- a/common/gateway-storage/src/models.rs +++ b/common/gateway-storage/src/models.rs @@ -72,7 +72,6 @@ impl TryFrom 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 for WireguardPeer { fn from(value: defguard_wireguard_rs::host::Peer) -> Self { WireguardPeer { @@ -120,7 +118,6 @@ impl From for WireguardPeer { } } -#[cfg(feature = "wireguard")] impl TryFrom for defguard_wireguard_rs::host::Peer { type Error = crate::error::StorageError; diff --git a/common/gateway-storage/src/shared_keys.rs b/common/gateway-storage/src/shared_keys.rs index 8d16ca5ba5..97171eab85 100644 --- a/common/gateway-storage/src/shared_keys.rs +++ b/common/gateway-storage/src/shared_keys.rs @@ -40,9 +40,17 @@ impl SharedKeysManager { client_address_bs58: String, derived_aes128_ctr_blake3_hmac_keys_bs58: String, ) -> Result { - sqlx::query!("INSERT OR REPLACE INTO shared_keys(client_address_bs58, derived_aes128_ctr_blake3_hmac_keys_bs58) VALUES (?, ?)", + // https://stackoverflow.com/a/20310838 + // we don't want to be using `INSERT OR REPLACE INTO` due to the foreign key on `available_bandwidth` if the entry already exists + sqlx::query!( + r#" + INSERT OR IGNORE INTO shared_keys(client_address_bs58, derived_aes128_ctr_blake3_hmac_keys_bs58) VALUES (?, ?); + UPDATE shared_keys SET derived_aes128_ctr_blake3_hmac_keys_bs58 = ? WHERE client_address_bs58 = ? + "#, client_address_bs58, derived_aes128_ctr_blake3_hmac_keys_bs58, + derived_aes128_ctr_blake3_hmac_keys_bs58, + client_address_bs58, ).execute(&self.connection_pool).await?; self.client_id(&client_address_bs58).await diff --git a/common/gateway-storage/src/wireguard_peers.rs b/common/gateway-storage/src/wireguard_peers.rs index 436cdc3475..c90eb9647d 100644 --- a/common/gateway-storage/src/wireguard_peers.rs +++ b/common/gateway-storage/src/wireguard_peers.rs @@ -26,8 +26,17 @@ impl WgPeerManager { /// * `peer`: peer information needed by wireguard interface. pub(crate) async fn insert_peer(&self, peer: &WireguardPeer) -> Result<(), sqlx::Error> { sqlx::query!( - "INSERT OR REPLACE INTO wireguard_peer(public_key, preshared_key, protocol_version, endpoint, last_handshake, tx_bytes, rx_bytes, persistent_keepalive_interval, allowed_ips, suspended) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", - peer.public_key, peer.preshared_key, peer.protocol_version, peer.endpoint, peer.last_handshake, peer.tx_bytes, peer.rx_bytes, peer.persistent_keepalive_interval, peer.allowed_ips, peer.suspended + r#" + INSERT OR IGNORE INTO wireguard_peer(public_key, preshared_key, protocol_version, endpoint, last_handshake, tx_bytes, rx_bytes, persistent_keepalive_interval, allowed_ips, suspended) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?); + + UPDATE wireguard_peer + SET preshared_key = ?, protocol_version = ?, endpoint = ?, last_handshake = ?, tx_bytes = ?, rx_bytes = ?, persistent_keepalive_interval = ?, allowed_ips = ?, suspended = ? + WHERE public_key = ? + "#, + peer.public_key, peer.preshared_key, peer.protocol_version, peer.endpoint, peer.last_handshake, peer.tx_bytes, peer.rx_bytes, peer.persistent_keepalive_interval, peer.allowed_ips, peer.suspended, + + peer.preshared_key, peer.protocol_version, peer.endpoint, peer.last_handshake, peer.tx_bytes, peer.rx_bytes, peer.persistent_keepalive_interval, peer.allowed_ips, peer.suspended,peer.public_key, ) .execute(&self.connection_pool) .await?; diff --git a/common/network-defaults/src/mainnet.rs b/common/network-defaults/src/mainnet.rs index b6723c1a4a..8ebe2e044e 100644 --- a/common/network-defaults/src/mainnet.rs +++ b/common/network-defaults/src/mainnet.rs @@ -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 = diff --git a/common/task/src/manager.rs b/common/task/src/manager.rs index f880629bac..d354a06db8 100644 --- a/common/task/src/manager.rs +++ b/common/task/src/manager.rs @@ -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(&mut self, fut: Fut) -> Option - where - Fut: Future, - { - 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(()); diff --git a/common/wireguard/Cargo.toml b/common/wireguard/Cargo.toml index 18759fa641..f90708a68d 100644 --- a/common/wireguard/Cargo.toml +++ b/common/wireguard/Cargo.toml @@ -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" } diff --git a/common/wireguard/src/peer_controller.rs b/common/wireguard/src/peer_controller.rs index 9097f155ac..77375c23d7 100644 --- a/common/wireguard/src/peer_controller.rs +++ b/common/wireguard/src/peer_controller.rs @@ -61,14 +61,19 @@ impl PeerController { let timeout_check_interval = tokio_stream::wrappers::IntervalStream::new( tokio::time::interval(DEFAULT_PEER_TIMEOUT_CHECK), ); - let active_peers = peers + let active_peers: HashMap = peers .into_iter() .map(|peer| (peer.public_key.clone(), peer)) .collect(); - let suspended_peers = suspended_peers + let suspended_peers: HashMap = 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, @@ -78,7 +83,7 @@ impl PeerController { timeout_check_interval, active_peers, suspended_peers, - last_seen_bandwidth: HashMap::new(), + last_seen_bandwidth, timeout_count: 0, } } @@ -199,6 +204,7 @@ impl PeerController { 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 }; diff --git a/contracts/Cargo.lock b/contracts/Cargo.lock index d4b7aa57ae..2f57ea58ef 100644 --- a/contracts/Cargo.lock +++ b/contracts/Cargo.lock @@ -1276,6 +1276,7 @@ dependencies = [ "cosmwasm-schema", "cosmwasm-std", "cosmwasm-storage", + "cw-controllers", "cw-storage-plus", "cw2", "nym-contracts-common", @@ -1295,6 +1296,7 @@ dependencies = [ "bs58 0.5.1", "cosmwasm-schema", "cosmwasm-std", + "cw-controllers", "cw2", "humantime-serde", "log", diff --git a/contracts/mixnet/Cargo.toml b/contracts/mixnet/Cargo.toml index 94133686d5..957f981f2e 100644 --- a/contracts/mixnet/Cargo.toml +++ b/contracts/mixnet/Cargo.toml @@ -34,6 +34,7 @@ cosmwasm-schema = { workspace = true, optional = true } cosmwasm-std = { workspace = true } cosmwasm-storage = { workspace = true } cosmwasm-derive = { workspace = true } +cw-controllers = { workspace = true } cw2 = { workspace = true } cw-storage-plus = { workspace = true } diff --git a/contracts/mixnet/schema/nym-mixnet-contract.json b/contracts/mixnet/schema/nym-mixnet-contract.json index dc3e521bd2..c754e65fdb 100644 --- a/contracts/mixnet/schema/nym-mixnet-contract.json +++ b/contracts/mixnet/schema/nym-mixnet-contract.json @@ -177,6 +177,28 @@ "$schema": "http://json-schema.org/draft-07/schema#", "title": "ExecuteMsg", "oneOf": [ + { + "description": "Change the admin", + "type": "object", + "required": [ + "update_admin" + ], + "properties": { + "update_admin": { + "type": "object", + "required": [ + "admin" + ], + "properties": { + "admin": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, { "type": "object", "required": [ @@ -1692,6 +1714,19 @@ "$schema": "http://json-schema.org/draft-07/schema#", "title": "QueryMsg", "oneOf": [ + { + "type": "object", + "required": [ + "admin" + ], + "properties": { + "admin": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + }, { "description": "Gets the list of families registered in this contract.", "type": "object", @@ -2937,6 +2972,21 @@ }, "sudo": null, "responses": { + "admin": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "AdminResponse", + "description": "Returned from Admin.query_admin()", + "type": "object", + "properties": { + "admin": { + "type": [ + "string", + "null" + ] + } + }, + "additionalProperties": false + }, "get_all_delegations": { "$schema": "http://json-schema.org/draft-07/schema#", "title": "PagedAllDelegationsResponse", @@ -8140,7 +8190,6 @@ "description": "The current state of the mixnet contract.", "type": "object", "required": [ - "owner", "params", "rewarding_denom", "rewarding_validator_address", @@ -8149,9 +8198,14 @@ "properties": { "owner": { "description": "Address of the contract owner.", - "allOf": [ + "default": null, + "deprecated": true, + "anyOf": [ { "$ref": "#/definitions/Addr" + }, + { + "type": "null" } ] }, diff --git a/contracts/mixnet/schema/raw/execute.json b/contracts/mixnet/schema/raw/execute.json index 688b57db0b..c5c773e76d 100644 --- a/contracts/mixnet/schema/raw/execute.json +++ b/contracts/mixnet/schema/raw/execute.json @@ -2,6 +2,28 @@ "$schema": "http://json-schema.org/draft-07/schema#", "title": "ExecuteMsg", "oneOf": [ + { + "description": "Change the admin", + "type": "object", + "required": [ + "update_admin" + ], + "properties": { + "update_admin": { + "type": "object", + "required": [ + "admin" + ], + "properties": { + "admin": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, { "type": "object", "required": [ diff --git a/contracts/mixnet/schema/raw/query.json b/contracts/mixnet/schema/raw/query.json index f4738a91fe..c938a56f64 100644 --- a/contracts/mixnet/schema/raw/query.json +++ b/contracts/mixnet/schema/raw/query.json @@ -2,6 +2,19 @@ "$schema": "http://json-schema.org/draft-07/schema#", "title": "QueryMsg", "oneOf": [ + { + "type": "object", + "required": [ + "admin" + ], + "properties": { + "admin": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + }, { "description": "Gets the list of families registered in this contract.", "type": "object", diff --git a/contracts/mixnet/schema/raw/response_to_admin.json b/contracts/mixnet/schema/raw/response_to_admin.json new file mode 100644 index 0000000000..c73969ab04 --- /dev/null +++ b/contracts/mixnet/schema/raw/response_to_admin.json @@ -0,0 +1,15 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "AdminResponse", + "description": "Returned from Admin.query_admin()", + "type": "object", + "properties": { + "admin": { + "type": [ + "string", + "null" + ] + } + }, + "additionalProperties": false +} diff --git a/contracts/mixnet/schema/raw/response_to_get_state.json b/contracts/mixnet/schema/raw/response_to_get_state.json index d8c9dc5383..9103e87b72 100644 --- a/contracts/mixnet/schema/raw/response_to_get_state.json +++ b/contracts/mixnet/schema/raw/response_to_get_state.json @@ -4,7 +4,6 @@ "description": "The current state of the mixnet contract.", "type": "object", "required": [ - "owner", "params", "rewarding_denom", "rewarding_validator_address", @@ -13,9 +12,14 @@ "properties": { "owner": { "description": "Address of the contract owner.", - "allOf": [ + "default": null, + "deprecated": true, + "anyOf": [ { "$ref": "#/definitions/Addr" + }, + { + "type": "null" } ] }, diff --git a/contracts/mixnet/src/constants.rs b/contracts/mixnet/src/constants.rs index 17a62a25a8..0ea867c00c 100644 --- a/contracts/mixnet/src/constants.rs +++ b/contracts/mixnet/src/constants.rs @@ -57,6 +57,7 @@ pub const PENDING_INTERVAL_EVENTS_NAMESPACE: &str = "pie"; pub const LAST_EPOCH_EVENT_ID_KEY: &str = "lee"; pub const LAST_INTERVAL_EVENT_ID_KEY: &str = "lie"; +pub const ADMIN_STORAGE_KEY: &str = "admin"; pub const CONTRACT_STATE_KEY: &str = "state"; pub const LAYER_DISTRIBUTION_KEY: &str = "layers"; diff --git a/contracts/mixnet/src/contract.rs b/contracts/mixnet/src/contract.rs index a2c85dd959..99ade0ff72 100644 --- a/contracts/mixnet/src/contract.rs +++ b/contracts/mixnet/src/contract.rs @@ -28,8 +28,10 @@ fn default_initial_state( profit_margin: ProfitMarginRange, interval_operating_cost: OperatingCostRange, ) -> ContractState { + // we have to temporarily preserve this functionalities until it can be removed + #[allow(deprecated)] ContractState { - owner, + owner: Some(owner), rewarding_validator_address, vesting_contract_address, rewarding_denom: rewarding_denom.clone(), @@ -56,7 +58,7 @@ fn default_initial_state( /// `msg` is the contract initialization message, sort of like a constructor call. #[entry_point] pub fn instantiate( - deps: DepsMut<'_>, + mut deps: DepsMut<'_>, env: Env, info: MessageInfo, msg: InstantiateMsg, @@ -72,7 +74,7 @@ pub fn instantiate( let rewarding_validator_address = deps.api.addr_validate(&msg.rewarding_validator_address)?; let vesting_contract_address = deps.api.addr_validate(&msg.vesting_contract_address)?; let state = default_initial_state( - info.sender, + info.sender.clone(), rewarding_validator_address.clone(), msg.rewarding_denom, vesting_contract_address, @@ -90,7 +92,7 @@ pub fn instantiate( starting_interval, rewarding_validator_address, )?; - mixnet_params_storage::initialise_storage(deps.storage, state)?; + mixnet_params_storage::initialise_storage(deps.branch(), state, info.sender)?; mixnode_storage::initialise_storage(deps.storage)?; rewards_storage::initialise_storage(deps.storage, reward_params)?; cw2::set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?; @@ -108,6 +110,11 @@ pub fn execute( msg: ExecuteMsg, ) -> Result { match msg { + ExecuteMsg::UpdateAdmin { admin } => { + crate::mixnet_contract_settings::transactions::try_update_contract_admin( + deps, info, admin, + ) + } ExecuteMsg::AssignNodeLayer { mix_id, layer } => { crate::mixnodes::transactions::assign_mixnode_layer(deps, info, mix_id, layer) } @@ -335,6 +342,9 @@ pub fn query( QueryMsg::GetState {} => { to_binary(&crate::mixnet_contract_settings::queries::query_contract_state(deps)?) } + QueryMsg::Admin {} => to_binary(&crate::mixnet_contract_settings::queries::query_admin( + deps, + )?), QueryMsg::GetRewardingParams {} => { to_binary(&crate::rewards::queries::query_rewarding_params(deps)?) } @@ -528,13 +538,15 @@ pub fn query( #[entry_point] pub fn migrate( - deps: DepsMut<'_>, + mut deps: DepsMut<'_>, _env: Env, msg: MigrateMsg, ) -> Result { set_build_information!(deps.storage)?; cw2::ensure_from_older_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?; + crate::queued_migrations::explicit_contract_admin(deps.branch())?; + // due to circular dependency on contract addresses (i.e. mixnet contract requiring vesting contract address // and vesting contract requiring the mixnet contract address), if we ever want to deploy any new fresh // environment, one of the contracts will HAVE TO go through a migration @@ -592,8 +604,9 @@ mod tests { let res = instantiate(deps.as_mut(), env, sender, init_msg); assert!(res.is_ok()); + #[allow(deprecated)] let expected_state = ContractState { - owner: Addr::unchecked("sender"), + owner: Some(Addr::unchecked("sender")), rewarding_validator_address: Addr::unchecked("foomp123"), vesting_contract_address: Addr::unchecked("bar456"), rewarding_denom: "uatom".into(), diff --git a/contracts/mixnet/src/gateways/signature_helpers.rs b/contracts/mixnet/src/gateways/signature_helpers.rs index 46d37c6073..6f9b712554 100644 --- a/contracts/mixnet/src/gateways/signature_helpers.rs +++ b/contracts/mixnet/src/gateways/signature_helpers.rs @@ -5,7 +5,9 @@ use crate::signing::storage as signing_storage; use crate::support::helpers::decode_ed25519_identity_key; use cosmwasm_std::{Addr, Coin, Deps}; use mixnet_contract_common::error::MixnetContractError; -use mixnet_contract_common::{construct_gateway_bonding_sign_payload, Gateway}; +use mixnet_contract_common::{ + construct_gateway_bonding_sign_payload, construct_legacy_gateway_bonding_sign_payload, Gateway, +}; use nym_contracts_common::signing::MessageSignature; use nym_contracts_common::signing::Verifier; @@ -19,13 +21,31 @@ pub(crate) fn verify_gateway_bonding_signature( // recover the public key let public_key = decode_ed25519_identity_key(&gateway.identity_key)?; - // reconstruct the payload + // reconstruct the payload, first try the current format, then attempt legacy let nonce = signing_storage::get_signing_nonce(deps.storage, sender.clone())?; - let msg = construct_gateway_bonding_sign_payload(nonce, sender, pledge, gateway); + let msg = construct_gateway_bonding_sign_payload( + nonce, + sender.clone(), + pledge.clone(), + gateway.clone(), + ); - if deps.api.verify_message(msg, signature, &public_key)? { + if deps + .api + .verify_message(msg, signature.clone(), &public_key)? + { Ok(()) } else { - Err(MixnetContractError::InvalidEd25519Signature) + // attempt to use legacy + let msg_legacy = + construct_legacy_gateway_bonding_sign_payload(nonce, sender, pledge, gateway); + if deps + .api + .verify_message(msg_legacy, signature, &public_key)? + { + Ok(()) + } else { + Err(MixnetContractError::InvalidEd25519Signature) + } } } diff --git a/contracts/mixnet/src/interval/transactions.rs b/contracts/mixnet/src/interval/transactions.rs index 349545984f..adc8faa9cc 100644 --- a/contracts/mixnet/src/interval/transactions.rs +++ b/contracts/mixnet/src/interval/transactions.rs @@ -5,11 +5,12 @@ use super::storage; use crate::interval::helpers::change_interval_config; use crate::interval::pending_events::ContractExecutableEvent; use crate::interval::storage::push_new_interval_event; +use crate::mixnet_contract_settings::storage::ADMIN; use crate::mixnodes::transactions::update_mixnode_layer; use crate::rewards; use crate::rewards::storage as rewards_storage; use crate::support::helpers::{ - ensure_can_advance_epoch, ensure_epoch_in_progress_state, ensure_is_authorized, ensure_is_owner, + ensure_can_advance_epoch, ensure_epoch_in_progress_state, ensure_is_authorized, }; use cosmwasm_std::{DepsMut, Env, MessageInfo, Order, Response, Storage}; use mixnet_contract_common::error::MixnetContractError; @@ -325,7 +326,7 @@ pub(crate) fn try_update_interval_config( epoch_duration_secs: u64, force_immediately: bool, ) -> Result { - ensure_is_owner(info.sender, deps.storage)?; + ADMIN.assert_admin(deps.as_ref(), &info.sender)?; if epochs_in_interval == 0 { return Err(MixnetContractError::EpochsInIntervalZero); @@ -1766,6 +1767,7 @@ mod tests { use super::*; use cosmwasm_std::testing::mock_info; use cosmwasm_std::Decimal; + use cw_controllers::AdminError::NotAdmin; use std::time::Duration; #[test] @@ -1831,11 +1833,11 @@ mod tests { 1000, false, ); - assert_eq!(res, Err(MixnetContractError::Unauthorized)); + assert_eq!(res, Err(MixnetContractError::Admin(NotAdmin {}))); let res = try_update_interval_config(test.deps_mut(), env.clone(), random, 100, 1000, false); - assert_eq!(res, Err(MixnetContractError::Unauthorized)); + assert_eq!(res, Err(MixnetContractError::Admin(NotAdmin {}))); let res = try_update_interval_config(test.deps_mut(), env, owner, 100, 1000, false); assert!(res.is_ok()) diff --git a/contracts/mixnet/src/mixnet_contract_settings/queries.rs b/contracts/mixnet/src/mixnet_contract_settings/queries.rs index ca939d4334..5d80fec78a 100644 --- a/contracts/mixnet/src/mixnet_contract_settings/queries.rs +++ b/contracts/mixnet/src/mixnet_contract_settings/queries.rs @@ -2,10 +2,16 @@ // SPDX-License-Identifier: Apache-2.0 use super::storage; +use crate::mixnet_contract_settings::storage::ADMIN; use cosmwasm_std::{Deps, StdResult}; +use cw_controllers::AdminResponse; use mixnet_contract_common::{ContractBuildInformation, ContractState, ContractStateParams}; use nym_contracts_common::get_build_information; +pub(crate) fn query_admin(deps: Deps<'_>) -> StdResult { + ADMIN.query_admin(deps) +} + pub(crate) fn query_contract_state(deps: Deps<'_>) -> StdResult { storage::CONTRACT_STATE.load(deps.storage) } @@ -36,8 +42,9 @@ pub(crate) mod tests { fn query_for_contract_settings_works() { let mut deps = test_helpers::init_contract(); + #[allow(deprecated)] let dummy_state = ContractState { - owner: Addr::unchecked("someowner"), + owner: Some(Addr::unchecked("foomp")), rewarding_validator_address: Addr::unchecked("monitor"), vesting_contract_address: Addr::unchecked("foomp"), rewarding_denom: "unym".to_string(), diff --git a/contracts/mixnet/src/mixnet_contract_settings/storage.rs b/contracts/mixnet/src/mixnet_contract_settings/storage.rs index 278b6baacf..0c8502089e 100644 --- a/contracts/mixnet/src/mixnet_contract_settings/storage.rs +++ b/contracts/mixnet/src/mixnet_contract_settings/storage.rs @@ -1,14 +1,16 @@ // Copyright 2021-2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use crate::constants::CONTRACT_STATE_KEY; -use cosmwasm_std::{Addr, Storage}; +use crate::constants::{ADMIN_STORAGE_KEY, CONTRACT_STATE_KEY}; +use cosmwasm_std::{Addr, DepsMut, Storage}; use cosmwasm_std::{Coin, StdResult}; +use cw_controllers::Admin; use cw_storage_plus::Item; use mixnet_contract_common::error::MixnetContractError; use mixnet_contract_common::{ContractState, OperatingCostRange, ProfitMarginRange}; pub(crate) const CONTRACT_STATE: Item<'_, ContractState> = Item::new(CONTRACT_STATE_KEY); +pub(crate) const ADMIN: Admin = Admin::new(ADMIN_STORAGE_KEY); pub fn rewarding_validator_address(storage: &dyn Storage) -> Result { Ok(CONTRACT_STATE @@ -66,8 +68,10 @@ pub(crate) fn vesting_contract_address(storage: &dyn Storage) -> Result, initial_state: ContractState, + initial_admin: Addr, ) -> StdResult<()> { - CONTRACT_STATE.save(storage, &initial_state) + CONTRACT_STATE.save(deps.storage, &initial_state)?; + ADMIN.set(deps, Some(initial_admin)) } diff --git a/contracts/mixnet/src/mixnet_contract_settings/transactions.rs b/contracts/mixnet/src/mixnet_contract_settings/transactions.rs index 19b753189e..b458f6fbbc 100644 --- a/contracts/mixnet/src/mixnet_contract_settings/transactions.rs +++ b/contracts/mixnet/src/mixnet_contract_settings/transactions.rs @@ -2,15 +2,36 @@ // SPDX-License-Identifier: Apache-2.0 use super::storage; -use cosmwasm_std::DepsMut; +use crate::mixnet_contract_settings::storage::ADMIN; use cosmwasm_std::MessageInfo; use cosmwasm_std::Response; +use cosmwasm_std::{DepsMut, StdResult}; use mixnet_contract_common::error::MixnetContractError; use mixnet_contract_common::events::{ new_rewarding_validator_address_update_event, new_settings_update_event, }; use mixnet_contract_common::ContractStateParams; +pub fn try_update_contract_admin( + mut deps: DepsMut<'_>, + info: MessageInfo, + new_admin: String, +) -> Result { + let new_admin = deps.api.addr_validate(&new_admin)?; + + let res = ADMIN.execute_update_admin(deps.branch(), info, Some(new_admin.clone()))?; + + // SAFETY: we don't need to perform any authentication checks on the sender as it was performed + // during 'execute_update_admin' call + #[allow(deprecated)] + storage::CONTRACT_STATE.update(deps.storage, |mut state| -> StdResult<_> { + state.owner = Some(new_admin); + Ok(state) + })?; + + Ok(res) +} + pub fn try_update_rewarding_validator_address( deps: DepsMut<'_>, info: MessageInfo, @@ -18,9 +39,7 @@ pub fn try_update_rewarding_validator_address( ) -> Result { let mut state = storage::CONTRACT_STATE.load(deps.storage)?; - if info.sender != state.owner { - return Err(MixnetContractError::Unauthorized); - } + ADMIN.assert_admin(deps.as_ref(), &info.sender)?; let new_address = deps.api.addr_validate(&address)?; let old_address = state.rewarding_validator_address; @@ -43,10 +62,7 @@ pub(crate) fn try_update_contract_settings( ) -> Result { let mut state = storage::CONTRACT_STATE.load(deps.storage)?; - // check if this is executed by the owner, if not reject the transaction - if info.sender != state.owner { - return Err(MixnetContractError::Unauthorized); - } + ADMIN.assert_admin(deps.as_ref(), &info.sender)?; let response = Response::new().add_event(new_settings_update_event(&state.params, ¶ms)); @@ -65,6 +81,7 @@ pub mod tests { use crate::support::tests::test_helpers; use cosmwasm_std::testing::mock_info; use cosmwasm_std::{Addr, Coin, Uint128}; + use cw_controllers::AdminError::NotAdmin; #[test] fn update_contract_rewarding_validtor_address() { @@ -76,7 +93,7 @@ pub mod tests { info, "not-the-creator".to_string(), ); - assert_eq!(res, Err(MixnetContractError::Unauthorized)); + assert_eq!(res, Err(MixnetContractError::Admin(NotAdmin {}))); let info = mock_info("creator", &[]); let res = try_update_rewarding_validator_address( @@ -136,7 +153,7 @@ pub mod tests { // cannot be updated from non-owner account let info = mock_info("not-the-creator", &[]); let res = try_update_contract_settings(deps.as_mut(), info, new_params.clone()); - assert_eq!(res, Err(MixnetContractError::Unauthorized)); + assert_eq!(res, Err(MixnetContractError::Admin(NotAdmin {}))); // but works fine from the creator account let info = mock_info("creator", &[]); diff --git a/contracts/mixnet/src/mixnodes/signature_helpers.rs b/contracts/mixnet/src/mixnodes/signature_helpers.rs index 975bb55669..04942aaff5 100644 --- a/contracts/mixnet/src/mixnodes/signature_helpers.rs +++ b/contracts/mixnet/src/mixnodes/signature_helpers.rs @@ -5,7 +5,10 @@ use crate::signing::storage as signing_storage; use crate::support::helpers::decode_ed25519_identity_key; use cosmwasm_std::{Addr, Coin, Deps}; use mixnet_contract_common::error::MixnetContractError; -use mixnet_contract_common::{construct_mixnode_bonding_sign_payload, MixNode, MixNodeCostParams}; +use mixnet_contract_common::{ + construct_legacy_mixnode_bonding_sign_payload, construct_mixnode_bonding_sign_payload, MixNode, + MixNodeCostParams, +}; use nym_contracts_common::signing::MessageSignature; use nym_contracts_common::signing::Verifier; @@ -20,13 +23,37 @@ pub(crate) fn verify_mixnode_bonding_signature( // recover the public key let public_key = decode_ed25519_identity_key(&mixnode.identity_key)?; - // reconstruct the payload + // reconstruct the payload, first try the current format, then attempt legacy let nonce = signing_storage::get_signing_nonce(deps.storage, sender.clone())?; - let msg = construct_mixnode_bonding_sign_payload(nonce, sender, pledge, mixnode, cost_params); + let msg = construct_mixnode_bonding_sign_payload( + nonce, + sender.clone(), + pledge.clone(), + mixnode.clone(), + cost_params.clone(), + ); - if deps.api.verify_message(msg, signature, &public_key)? { + if deps + .api + .verify_message(msg, signature.clone(), &public_key)? + { Ok(()) } else { - Err(MixnetContractError::InvalidEd25519Signature) + // attempt to use legacy + let msg_legacy = construct_legacy_mixnode_bonding_sign_payload( + nonce, + sender, + pledge, + mixnode, + cost_params, + ); + if deps + .api + .verify_message(msg_legacy, signature, &public_key)? + { + Ok(()) + } else { + Err(MixnetContractError::InvalidEd25519Signature) + } } } diff --git a/contracts/mixnet/src/queued_migrations.rs b/contracts/mixnet/src/queued_migrations.rs index 8df3ef5d86..3f704917bd 100644 --- a/contracts/mixnet/src/queued_migrations.rs +++ b/contracts/mixnet/src/queued_migrations.rs @@ -1,2 +1,20 @@ // Copyright 2022-2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 + +use crate::mixnet_contract_settings::storage as mixnet_params_storage; +use cosmwasm_std::DepsMut; +use mixnet_contract_common::error::MixnetContractError; + +pub(crate) fn explicit_contract_admin(deps: DepsMut) -> Result<(), MixnetContractError> { + // we need to read the deprecated field to migrate it over + #[allow(deprecated)] + // SAFETY: this value should ALWAYS exist on the first execution of this migration; + // as a matter of fact, it should ALWAYS continue existing until another migration + #[allow(clippy::expect_used)] + let existing_admin = mixnet_params_storage::CONTRACT_STATE + .load(deps.storage)? + .owner + .expect("the contract state is corrupt - there's no admin set"); + mixnet_params_storage::ADMIN.set(deps, Some(existing_admin))?; + Ok(()) +} diff --git a/contracts/mixnet/src/rewards/transactions.rs b/contracts/mixnet/src/rewards/transactions.rs index 3f9b0e329a..f772dca800 100644 --- a/contracts/mixnet/src/rewards/transactions.rs +++ b/contracts/mixnet/src/rewards/transactions.rs @@ -6,13 +6,13 @@ use crate::delegations::storage as delegations_storage; use crate::interval::storage as interval_storage; use crate::interval::storage::{push_new_epoch_event, push_new_interval_event}; use crate::mixnet_contract_settings::storage as mixnet_params_storage; +use crate::mixnet_contract_settings::storage::ADMIN; use crate::mixnodes::helpers::get_mixnode_details_by_owner; use crate::mixnodes::storage as mixnodes_storage; use crate::rewards::helpers; use crate::rewards::helpers::update_and_save_last_rewarded; use crate::support::helpers::{ - ensure_bonded, ensure_can_advance_epoch, ensure_epoch_in_progress_state, ensure_is_owner, - AttachSendTokens, + ensure_bonded, ensure_can_advance_epoch, ensure_epoch_in_progress_state, AttachSendTokens, }; use cosmwasm_std::{DepsMut, Env, MessageInfo, Response}; use mixnet_contract_common::error::MixnetContractError; @@ -227,7 +227,7 @@ pub(crate) fn try_update_active_set_size( active_set_size: u32, force_immediately: bool, ) -> Result { - ensure_is_owner(info.sender, deps.storage)?; + ADMIN.assert_admin(deps.as_ref(), &info.sender)?; let mut rewarding_params = storage::REWARDING_PARAMS.load(deps.storage)?; if active_set_size == 0 { @@ -273,7 +273,7 @@ pub(crate) fn try_update_rewarding_params( updated_params: IntervalRewardingParamsUpdate, force_immediately: bool, ) -> Result { - ensure_is_owner(info.sender, deps.storage)?; + ADMIN.assert_admin(deps.as_ref(), &info.sender)?; if !updated_params.contains_updates() { return Err(MixnetContractError::EmptyParamsChangeMsg); @@ -1796,6 +1796,7 @@ pub mod tests { #[cfg(test)] mod updating_active_set { + use cw_controllers::AdminError::NotAdmin; use mixnet_contract_common::EpochStatus; use crate::support::tests::test_helpers::TestSetup; @@ -1858,10 +1859,10 @@ pub mod tests { 42, false, ); - assert_eq!(res, Err(MixnetContractError::Unauthorized)); + assert_eq!(res, Err(MixnetContractError::Admin(NotAdmin {}))); let res = try_update_active_set_size(test.deps_mut(), env.clone(), random, 42, false); - assert_eq!(res, Err(MixnetContractError::Unauthorized)); + assert_eq!(res, Err(MixnetContractError::Admin(NotAdmin {}))); let res = try_update_active_set_size(test.deps_mut(), env, owner, 42, false); assert!(res.is_ok()) @@ -2002,6 +2003,7 @@ pub mod tests { #[cfg(test)] mod updating_rewarding_params { use cosmwasm_std::Decimal; + use cw_controllers::AdminError::NotAdmin; use mixnet_contract_common::EpochStatus; @@ -2085,11 +2087,11 @@ pub mod tests { update, false, ); - assert_eq!(res, Err(MixnetContractError::Unauthorized)); + assert_eq!(res, Err(MixnetContractError::Admin(NotAdmin {}))); let res = try_update_rewarding_params(test.deps_mut(), env.clone(), random, update, false); - assert_eq!(res, Err(MixnetContractError::Unauthorized)); + assert_eq!(res, Err(MixnetContractError::Admin(NotAdmin {}))); let res = try_update_rewarding_params(test.deps_mut(), env, owner, update, false); assert!(res.is_ok()) diff --git a/contracts/mixnet/src/support/helpers.rs b/contracts/mixnet/src/support/helpers.rs index 09738cea81..19ddf2bb6e 100644 --- a/contracts/mixnet/src/support/helpers.rs +++ b/contracts/mixnet/src/support/helpers.rs @@ -194,20 +194,6 @@ pub(crate) fn ensure_can_advance_epoch( Ok(epoch_status) } -pub(crate) fn ensure_is_owner( - sender: Addr, - storage: &dyn Storage, -) -> Result<(), MixnetContractError> { - if sender - != crate::mixnet_contract_settings::storage::CONTRACT_STATE - .load(storage)? - .owner - { - return Err(MixnetContractError::Unauthorized); - } - Ok(()) -} - pub(crate) fn ensure_bonded(bond: &MixNodeBond) -> Result<(), MixnetContractError> { if bond.is_unbonding { return Err(MixnetContractError::MixnodeIsUnbonding { diff --git a/contracts/mixnet/src/support/tests/mod.rs b/contracts/mixnet/src/support/tests/mod.rs index 976138fdc2..dee121b2f0 100644 --- a/contracts/mixnet/src/support/tests/mod.rs +++ b/contracts/mixnet/src/support/tests/mod.rs @@ -105,10 +105,11 @@ pub mod test_helpers { let deps = init_contract(); let rewarding_validator_address = rewarding_validator_address(deps.as_ref().storage).unwrap(); - let owner = mixnet_params_storage::CONTRACT_STATE - .load(deps.as_ref().storage) + let owner = mixnet_params_storage::ADMIN + .query_admin(deps.as_ref()) .unwrap() - .owner; + .admin + .unwrap(); TestSetup { deps, diff --git a/envs/canary.env b/envs/canary.env index 1c38b89a1a..c4aac15082 100644 --- a/envs/canary.env +++ b/envs/canary.env @@ -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 diff --git a/envs/mainnet.env b/envs/mainnet.env index 17f546028c..e40e54a471 100644 --- a/envs/mainnet.env +++ b/envs/mainnet.env @@ -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 diff --git a/explorer-api/.env.dev b/explorer-api/.env.dev index 61113ab13d..f332cff85e 100644 --- a/explorer-api/.env.dev +++ b/explorer-api/.env.dev @@ -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" diff --git a/explorer-api/Cargo.toml b/explorer-api/Cargo.toml index a7cf940f9c..0ab11f2859 100644 --- a/explorer-api/Cargo.toml +++ b/explorer-api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "explorer-api" -version = "1.1.38" +version = "1.1.39" edition = "2021" license.workspace = true diff --git a/gateway/Cargo.toml b/gateway/Cargo.toml index 2a2e7ac51e..cbdcfc1ad2 100644 --- a/gateway/Cargo.toml +++ b/gateway/Cargo.toml @@ -88,10 +88,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] @@ -104,11 +104,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] diff --git a/gateway/src/config/mod.rs b/gateway/src/config/mod.rs index 0750b3bf0d..7605987a79 100644 --- a/gateway/src/config/mod.rs +++ b/gateway/src/config/mod.rs @@ -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(), } } } diff --git a/gateway/src/error.rs b/gateway/src/error.rs index e7786db443..dc37c4c710 100644 --- a/gateway/src/error.rs +++ b/gateway/src/error.rs @@ -189,11 +189,12 @@ pub enum GatewayError { source: ipnetwork::IpNetworkError, }, - #[cfg(all(feature = "wireguard", target_os = "linux"))] + #[error("the current multisig contract is not using 'AbsolutePercentage' threshold!")] + InvalidMultisigThreshold, + #[error("failed to remove wireguard interface: {0}")] WireguardInterfaceError(#[from] defguard_wireguard_rs::error::WireguardInterfaceError), - #[cfg(all(feature = "wireguard", target_os = "linux"))] #[error("internal wireguard error {0}")] InternalWireguardError(String), diff --git a/gateway/src/node/client_handling/websocket/connection_handler/fresh.rs b/gateway/src/node/client_handling/websocket/connection_handler/fresh.rs index f56f14e0eb..289d7922bb 100644 --- a/gateway/src/node/client_handling/websocket/connection_handler/fresh.rs +++ b/gateway/src/node/client_handling/websocket/connection_handler/fresh.rs @@ -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 { pub(crate) outbound_mix_sender: MixForwardingSender, pub(crate) socket_connection: SocketStream, pub(crate) peer_address: SocketAddr, + pub(crate) shutdown: TaskClient, // currently unused (but populated) pub(crate) negotiated_protocol: Option, @@ -149,6 +154,7 @@ where active_clients_store: ActiveClientsStore, shared_state: CommonHandlerState, 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 } @@ -521,6 +529,11 @@ where /// * `client_address`: address of the client wishing to authenticate. /// * `encrypted_address`: ciphertext of the address of the client wishing to authenticate. /// * `iv`: fresh IV received with the request. + #[instrument(skip_all + fields( + address = %address, + ) + )] async fn handle_authenticate( &mut self, client_protocol_version: Option, @@ -531,6 +544,8 @@ where where S: AsyncRead + AsyncWrite + Unpin, { + debug!("handling client registration"); + let negotiated_protocol = self.negotiate_client_protocol(client_protocol_version)?; // populate the negotiated protocol for future uses self.negotiated_protocol = Some(negotiated_protocol); @@ -650,6 +665,8 @@ where let remote_identity = Self::extract_remote_identity_from_register_init(&init_data)?; let remote_address = remote_identity.derive_destination_address(); + debug!(remote_client = %remote_identity); + if self.active_clients_store.is_active(remote_address) { return Err(InitialAuthenticationError::DuplicateConnection); } @@ -657,6 +674,8 @@ where let shared_keys = self.perform_registration_handshake(init_data).await?; let client_id = self.register_client(remote_address, &shared_keys).await?; + debug!(client_id = %client_id, "managed to finalize client registration"); + let client_details = ClientDetails::new(client_id, remote_address, shared_keys); Ok(InitialAuthResult::new( @@ -716,111 +735,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 } } diff --git a/gateway/src/node/client_handling/websocket/connection_handler/mod.rs b/gateway/src/node/client_handling/websocket/connection_handler/mod.rs index 0ffde8feed..6e1d8a9b5a 100644 --- a/gateway/src/node/client_handling/websocket/connection_handler/mod.rs +++ b/gateway/src/node/client_handling/websocket/connection_handler/mod.rs @@ -2,13 +2,14 @@ // SPDX-License-Identifier: GPL-3.0-only use crate::config::Config; +use fresh::InitialAuthenticationError; use nym_credential_verification::BandwidthFlushingBehaviourConfig; 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 tokio::io::{AsyncRead, AsyncWrite}; use tokio_tungstenite::WebSocketStream; use tracing::{instrument, trace, warn}; @@ -20,6 +21,8 @@ pub(crate) use self::fresh::FreshHandler; pub(crate) mod authenticated; 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 @@ -83,47 +86,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( - mut handle: FreshHandler, - mut shutdown: TaskClient, -) where +pub(crate) async fn handle_connection(mut handle: FreshHandler) +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.disarm(); + handle.shutdown.disarm(); - 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!"); diff --git a/gateway/src/node/client_handling/websocket/listener.rs b/gateway/src/node/client_handling/websocket/listener.rs index 8c0b98a440..be3c6c51a2 100644 --- a/gateway/src/node/client_handling/websocket/listener.rs +++ b/gateway/src/node/client_handling/websocket/listener.rs @@ -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}"), } diff --git a/gateway/src/node/mod.rs b/gateway/src/node/mod.rs index 94cdcf7776..e6eece9139 100644 --- a/gateway/src/node/mod.rs +++ b/gateway/src/node/mod.rs @@ -51,7 +51,6 @@ struct StartedNetworkRequester { // TODO: should this struct live here? #[allow(unused)] struct StartedAuthenticator { - #[cfg(feature = "wireguard")] wg_api: Arc, /// Handle to interact with the local authenticator @@ -146,7 +145,6 @@ pub struct Gateway { storage: St, - #[cfg(all(feature = "wireguard", target_os = "linux"))] wireguard_data: Option, run_http_server: bool, @@ -169,7 +167,6 @@ impl Gateway { 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, @@ -193,7 +190,6 @@ impl Gateway { identity_keypair, sphinx_keypair, storage, - #[cfg(all(feature = "wireguard", target_os = "linux"))] wireguard_data: None, run_http_server: true, task_client: None, @@ -208,7 +204,6 @@ impl Gateway { 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) } @@ -246,7 +241,7 @@ impl Gateway { 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, @@ -342,7 +337,7 @@ impl Gateway { } } - #[cfg(all(feature = "wireguard", not(target_os = "linux")))] + #[cfg(not(target_os = "linux"))] async fn start_authenticator( &self, _forwarding_channel: MixForwardingSender, @@ -673,14 +668,15 @@ impl Gateway { 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 { diff --git a/nym-api/Cargo.toml b/nym-api/Cargo.toml index f776ca226f..4b2f7f776e 100644 --- a/nym-api/Cargo.toml +++ b/nym-api/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "nym-api" license = "GPL-3.0" -version = "1.1.42" +version = "1.1.43" authors = [ "Dave Hrycyszyn ", "Jędrzej Stuczyński ", diff --git a/nym-api/src/ecash/dkg/client.rs b/nym-api/src/ecash/dkg/client.rs index 1471083060..5c8f993690 100644 --- a/nym-api/src/ecash/dkg/client.rs +++ b/nym-api/src/ecash/dkg/client.rs @@ -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::() - .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::() + .map_err(|_| EcashError::NodeIndexRecoveryError { + reason: String::from("node index could not be parsed"), + })?; Ok(node_index) } diff --git a/nym-api/src/ecash/dkg/key_derivation.rs b/nym-api/src/ecash/dkg/key_derivation.rs index e2ad2a7cb2..23291806b8 100644 --- a/nym-api/src/ecash/dkg/key_derivation.rs +++ b/nym-api/src/ecash/dkg/key_derivation.rs @@ -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 DkgController { key: &VerificationKeyAuth, resharing: bool, ) -> Result { - fn extract_proposal_id_from_logs( + fn extract_proposal_id( logs: &[Log], + events: &[Event], tx_hash: Hash, ) -> Result { 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 DkgController { .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) diff --git a/nym-api/src/ecash/state/helpers.rs b/nym-api/src/ecash/state/helpers.rs index ffcab88644..2fcfd18a31 100644 --- a/nym-api/src/ecash/state/helpers.rs +++ b/nym-api/src/ecash/state/helpers.rs @@ -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) { diff --git a/nym-node/Cargo.toml b/nym-node/Cargo.toml index b897f2d008..f33229d4bb 100644 --- a/nym-node/Cargo.toml +++ b/nym-node/Cargo.toml @@ -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"] diff --git a/nym-node/src/config/entry_gateway.rs b/nym-node/src/config/entry_gateway.rs index dd3670f42f..6807e55d58 100644 --- a/nym-node/src/config/entry_gateway.rs +++ b/nym-node/src/config/entry_gateway.rs @@ -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(), } } } diff --git a/nym-node/src/node/mod.rs b/nym-node/src/node/mod.rs index e8347e2f62..1e1b42ff54 100644 --- a/nym-node/src/node/mod.rs +++ b/nym-node/src/node/mod.rs @@ -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 { diff --git a/nym-wallet/Cargo.lock b/nym-wallet/Cargo.lock index e905f79d5f..0a83cfc727 100644 --- a/nym-wallet/Cargo.lock +++ b/nym-wallet/Cargo.lock @@ -3282,6 +3282,7 @@ dependencies = [ "bs58", "cosmwasm-schema", "cosmwasm-std", + "cw-controllers", "humantime-serde", "log", "nym-contracts-common", @@ -3521,7 +3522,7 @@ dependencies = [ [[package]] name = "nym_wallet" -version = "1.2.13" +version = "1.2.14" dependencies = [ "async-trait", "base64 0.13.1", @@ -4664,9 +4665,9 @@ dependencies = [ [[package]] name = "schemars" -version = "0.8.16" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45a28f4c49489add4ce10783f7911893516f15afe45d015608d41faca6bc4d29" +checksum = "09c024468a378b7e36765cd36702b7a90cc3cba11654f6685c8f233408e89e92" dependencies = [ "dyn-clone", "indexmap 1.9.3", @@ -4677,14 +4678,14 @@ dependencies = [ [[package]] name = "schemars_derive" -version = "0.8.16" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c767fd6fa65d9ccf9cf026122c1b555f2ef9a4f0cea69da4d7dbc3e258d30967" +checksum = "b1eee588578aff73f856ab961cd2f79e36bc45d7ded33a7562adba4667aecc0e" dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 1.0.109", + "syn 2.0.55", ] [[package]] @@ -4834,13 +4835,13 @@ dependencies = [ [[package]] name = "serde_derive_internals" -version = "0.26.0" +version = "0.29.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85bf8229e7920a9f636479437026331ce11aa132b4dde37d121944a44d6e5f3c" +checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.55", ] [[package]] diff --git a/nym-wallet/nym-wallet-types/src/network/qa.rs b/nym-wallet/nym-wallet-types/src/network/qa.rs index 00e9f1160f..761d08f614 100644 --- a/nym-wallet/nym-wallet-types/src/network/qa.rs +++ b/nym-wallet/nym-wallet-types/src/network/qa.rs @@ -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), diff --git a/nym-wallet/nym-wallet-types/src/network/sandbox.rs b/nym-wallet/nym-wallet-types/src/network/sandbox.rs index b545dd134b..c436c9f09e 100644 --- a/nym-wallet/nym-wallet-types/src/network/sandbox.rs +++ b/nym-wallet/nym-wallet-types/src/network/sandbox.rs @@ -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), diff --git a/nym-wallet/package.json b/nym-wallet/package.json index e9098e8c15..3d97eefd26 100644 --- a/nym-wallet/package.json +++ b/nym-wallet/package.json @@ -1,6 +1,6 @@ { "name": "@nymproject/nym-wallet-app", - "version": "1.2.13", + "version": "1.2.14", "license": "MIT", "main": "index.js", "scripts": { diff --git a/nym-wallet/src-tauri/Cargo.toml b/nym-wallet/src-tauri/Cargo.toml index f3d463f188..8e995a784f 100644 --- a/nym-wallet/src-tauri/Cargo.toml +++ b/nym-wallet/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nym_wallet" -version = "1.2.13" +version = "1.2.14" description = "Nym Native Wallet" authors = ["Nym Technologies SA"] license = "" diff --git a/nym-wallet/src-tauri/src/operations/helpers.rs b/nym-wallet/src-tauri/src/operations/helpers.rs index 2b5631eb58..da0093e293 100644 --- a/nym-wallet/src-tauri/src/operations/helpers.rs +++ b/nym-wallet/src-tauri/src/operations/helpers.rs @@ -9,8 +9,8 @@ use nym_contracts_common::signing::{ }; use nym_crypto::asymmetric::identity; use nym_mixnet_contract_common::{ - construct_mixnode_bonding_sign_payload, Gateway, GatewayBondingPayload, MixNode, - MixNodeCostParams, SignableGatewayBondingMsg, SignableMixNodeBondingMsg, + construct_legacy_mixnode_bonding_sign_payload, Gateway, GatewayBondingPayload, MixNode, + MixNodeCostParams, SignableGatewayBondingMsg, SignableLegacyMixNodeBondingMsg, }; use nym_validator_client::nyxd::contract_traits::MixnetQueryClient; use nym_validator_client::nyxd::error::NyxdError; @@ -42,14 +42,14 @@ pub(crate) async fn create_mixnode_bonding_sign_payload Result { +) -> Result { if vesting { return Err(BackendError::UnsupportedVestingOperation); } let sender = client.cw_address(); let nonce = client.get_signing_nonce().await?; - Ok(construct_mixnode_bonding_sign_payload( + Ok(construct_legacy_mixnode_bonding_sign_payload( nonce, sender, pledge.into(), diff --git a/nym-wallet/src-tauri/tauri.conf.json b/nym-wallet/src-tauri/tauri.conf.json index 5236817066..0067868c37 100644 --- a/nym-wallet/src-tauri/tauri.conf.json +++ b/nym-wallet/src-tauri/tauri.conf.json @@ -1,7 +1,7 @@ { "package": { "productName": "nym-wallet", - "version": "1.2.13" + "version": "1.2.14" }, "build": { "distDir": "../dist", diff --git a/sdk/rust/nym-sdk/src/bandwidth/client.rs b/sdk/rust/nym-sdk/src/bandwidth/client.rs index 19da50eccb..3f5acbd5e9 100644 --- a/sdk/rust/nym-sdk/src/bandwidth/client.rs +++ b/sdk/rust/nym-sdk/src/bandwidth/client.rs @@ -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, + client_id: Zeroizing>, ticketbook_type: TicketType, } @@ -30,7 +31,7 @@ where network_details: NymNetworkDetails, mnemonic: String, storage: &'a St, - client_id: String, + client_id: Vec, ticketbook_type: TicketType, ) -> Result { 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?; diff --git a/sdk/rust/nym-sdk/src/mixnet/client.rs b/sdk/rust/nym-sdk/src/mixnet/client.rs index 72b14cbebc..558109f4de 100644 --- a/sdk/rust/nym-sdk/src/mixnet/client.rs +++ b/sdk/rust/nym-sdk/src/mixnet/client.rs @@ -38,6 +38,7 @@ use rand::rngs::OsRng; 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; @@ -532,17 +533,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, diff --git a/service-providers/network-requester/Cargo.toml b/service-providers/network-requester/Cargo.toml index 61d3e9cfdd..e449911693 100644 --- a/service-providers/network-requester/Cargo.toml +++ b/service-providers/network-requester/Cargo.toml @@ -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" diff --git a/tools/nym-cli/Cargo.toml b/tools/nym-cli/Cargo.toml index f7ac9b56f4..f930eba02b 100644 --- a/tools/nym-cli/Cargo.toml +++ b/tools/nym-cli/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nym-cli" -version = "1.1.40" +version = "1.1.41" authors.workspace = true edition = "2021" license.workspace = true diff --git a/tools/nym-cli/src/coconut/mod.rs b/tools/nym-cli/src/ecash/mod.rs similarity index 87% rename from tools/nym-cli/src/coconut/mod.rs rename to tools/nym-cli/src/ecash/mod.rs index ccf0836d05..27d7ce52b3 100644 --- a/tools/nym-cli/src/coconut/mod.rs +++ b/tools/nym-cli/src/ecash/mod.rs @@ -4,10 +4,10 @@ use nym_network_defaults::NymNetworkDetails; pub(crate) async fn execute( global_args: ClientArgs, - coconut: nym_cli_commands::ecash::Ecash, + ecash: nym_cli_commands::ecash::Ecash, network_details: &NymNetworkDetails, ) -> anyhow::Result<()> { - match coconut.command { + match ecash.command { EcashCommands::IssueTicketBook(args) => { nym_cli_commands::ecash::issue_ticket_book::execute( args, @@ -25,6 +25,9 @@ pub(crate) async fn execute( EcashCommands::ImportTicketBook(args) => { nym_cli_commands::ecash::import_ticket_book::execute(args).await? } + EcashCommands::GenerateTicket(args) => { + nym_cli_commands::ecash::generate_ticket::execute(args).await? + } EcashCommands::ImportCoinIndexSignatures(args) => { nym_cli_commands::ecash::import_coin_index_signatures::execute(args).await? } diff --git a/tools/nym-cli/src/main.rs b/tools/nym-cli/src/main.rs index a7255ab9a9..c5b4cc51e3 100644 --- a/tools/nym-cli/src/main.rs +++ b/tools/nym-cli/src/main.rs @@ -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)] @@ -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? diff --git a/tools/nymvisor/Cargo.toml b/tools/nymvisor/Cargo.toml index 8f5658c8d3..6fb6a36e5e 100644 --- a/tools/nymvisor/Cargo.toml +++ b/tools/nymvisor/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nymvisor" -version = "0.1.5" +version = "0.1.6" authors.workspace = true repository.workspace = true homepage.workspace = true