Compare commits
89 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 340960d957 | |||
| 554e446208 | |||
| a6325b922a | |||
| fae4768b99 | |||
| 2689a4dbd8 | |||
| 02e40ccaef | |||
| b216338364 | |||
| 4a83bb9ba8 | |||
| 66ec3b037f | |||
| 168baa5071 | |||
| 7aef468839 | |||
| cb3ccd7f7e | |||
| 16509dbace | |||
| b907ccbd5b | |||
| 7b3194d7d2 | |||
| 0b81edfc66 | |||
| 8c6150e5ef | |||
| 46164a389a | |||
| 96d256b48f | |||
| f98b93f60e | |||
| 0f6c356f39 | |||
| cf3f5d9a53 | |||
| 2f47e6349a | |||
| 4b2b5390d3 | |||
| 734ff63f6d | |||
| 910c24e7da | |||
| c96b73172a | |||
| 823c2c7262 | |||
| 03d1b72a9e | |||
| 066669440f | |||
| 9fb3443fd1 | |||
| cd89a590b5 | |||
| 06cb8bd969 | |||
| c72fef169c | |||
| 3c27eb41b8 | |||
| 2428374fe7 | |||
| 5a491f0a7e | |||
| 530f9ccb6f | |||
| 2228a81d43 | |||
| c8a1b53071 | |||
| b896aaaed1 | |||
| 828ffc6710 | |||
| 05cdb27029 | |||
| 3f29d3eba5 | |||
| aa2c41dc41 | |||
| 048de771ab | |||
| e1b06f02f3 | |||
| b5b8b8f224 | |||
| 2d7141dfb1 | |||
| a07522258f | |||
| 547a441002 | |||
| 93208fb5e0 | |||
| c9b50dd979 | |||
| 74cdfd5d94 | |||
| 953e813f0e | |||
| 29cf5058a6 | |||
| a2856552d8 | |||
| a33c603471 | |||
| a9f9266992 | |||
| cf34d0d24a | |||
| 5fa7b0a709 | |||
| e232b4fd24 | |||
| 609f174e8d | |||
| a0f4627647 | |||
| 258f8f5f5d | |||
| 38220e05f1 | |||
| 6250ebe235 | |||
| a55323c0e2 | |||
| baa8ac3610 | |||
| 933da11e8f | |||
| 0469036da4 | |||
| 63f9a856fa | |||
| c068948c62 | |||
| 0105f9fa5e | |||
| 004c737965 | |||
| 549121ca32 | |||
| 3f2278dafc | |||
| 25ce0ac814 | |||
| 38d313a101 | |||
| f67bc0ead5 | |||
| 90aaa3572d | |||
| ecc61e4a4a | |||
| 22ac4919e5 | |||
| a1e7cc8e87 | |||
| 57df00637c | |||
| c7eb3bdb7b | |||
| 8f9b704541 | |||
| 6a956c790a | |||
| 2ff5c7221a |
@@ -81,12 +81,21 @@ jobs:
|
|||||||
command: fmt
|
command: fmt
|
||||||
args: --all -- --check
|
args: --all -- --check
|
||||||
|
|
||||||
- name: Clippy
|
- name: Clippy (macos)
|
||||||
|
if: contains(matrix.os, 'mac')
|
||||||
|
uses: actions-rs/cargo@v1
|
||||||
|
with:
|
||||||
|
command: clippy
|
||||||
|
args: --workspace --all-targets --exclude nym-gateway-probe -- -D warnings
|
||||||
|
|
||||||
|
- name: Clippy (non-macos)
|
||||||
|
if: contains(matrix.os, 'linux') || contains(matrix.os, 'windows')
|
||||||
uses: actions-rs/cargo@v1
|
uses: actions-rs/cargo@v1
|
||||||
with:
|
with:
|
||||||
command: clippy
|
command: clippy
|
||||||
args: --workspace --all-targets -- -D warnings
|
args: --workspace --all-targets -- -D warnings
|
||||||
|
|
||||||
|
|
||||||
- name: Build all binaries
|
- name: Build all binaries
|
||||||
uses: actions-rs/cargo@v1
|
uses: actions-rs/cargo@v1
|
||||||
with:
|
with:
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ jobs:
|
|||||||
uses: actions-rs/cargo@v1
|
uses: actions-rs/cargo@v1
|
||||||
with:
|
with:
|
||||||
command: test
|
command: test
|
||||||
args: --lib --manifest-path contracts/Cargo.toml
|
args: --lib --manifest-path contracts/Cargo.toml --all-features
|
||||||
|
|
||||||
- name: Check formatting
|
- name: Check formatting
|
||||||
uses: actions-rs/cargo@v1
|
uses: actions-rs/cargo@v1
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ on:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: arc-ubuntu-22.04
|
runs-on: arc-linux-latest
|
||||||
env:
|
env:
|
||||||
RUSTUP_PERMIT_COPY_RENAME: 1
|
RUSTUP_PERMIT_COPY_RENAME: 1
|
||||||
defaults:
|
defaults:
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ on:
|
|||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
pull_request:
|
pull_request:
|
||||||
paths:
|
paths:
|
||||||
- 'wasm/**'
|
- "wasm/**"
|
||||||
- 'clients/client-core/**'
|
- "clients/client-core/**"
|
||||||
- 'common/**'
|
- "common/**"
|
||||||
- '.github/workflows/ci-sdk-wasm.yml'
|
- ".github/workflows/ci-sdk-wasm.yml"
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
wasm:
|
wasm:
|
||||||
@@ -33,7 +33,7 @@ jobs:
|
|||||||
- name: Set up Go
|
- name: Set up Go
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: "1.23.7"
|
go-version: "1.24.6"
|
||||||
|
|
||||||
- name: Install wasm-pack
|
- name: Install wasm-pack
|
||||||
run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
|
run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
|
||||||
@@ -41,7 +41,7 @@ jobs:
|
|||||||
- name: Install wasm-opt
|
- name: Install wasm-opt
|
||||||
uses: ./.github/actions/install-wasm-opt
|
uses: ./.github/actions/install-wasm-opt
|
||||||
with:
|
with:
|
||||||
version: '116'
|
version: "116"
|
||||||
|
|
||||||
- name: Install wasm-bindgen-cli
|
- name: Install wasm-bindgen-cli
|
||||||
run: cargo install wasm-bindgen-cli
|
run: cargo install wasm-bindgen-cli
|
||||||
|
|||||||
Generated
+281
-16
@@ -1,6 +1,6 @@
|
|||||||
# This file is automatically @generated by Cargo.
|
# This file is automatically @generated by Cargo.
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 3
|
version = 4
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "accessory"
|
name = "accessory"
|
||||||
@@ -133,9 +133,9 @@ checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ammonia"
|
name = "ammonia"
|
||||||
version = "4.1.1"
|
version = "4.1.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d6b346764dd0814805de8abf899fe03065bcee69bb1a4771c785817e39f3978f"
|
checksum = "17e913097e1a2124b46746c980134e8c954bc17a6a59bb3fde96f088d126dde6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cssparser",
|
"cssparser",
|
||||||
"html5ever",
|
"html5ever",
|
||||||
@@ -929,7 +929,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "bls12_381"
|
name = "bls12_381"
|
||||||
version = "0.8.0"
|
version = "0.8.0"
|
||||||
source = "git+https://github.com/jstuczyn/bls12_381?branch=temp/experimental-serdect-updated#9bf520059cb28323fc51469cae86868ef4fa6fbd"
|
source = "git+https://github.com/jstuczyn/bls12_381?branch=temp%2Fexperimental-serdect-updated#9bf520059cb28323fc51469cae86868ef4fa6fbd"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"digest 0.10.7",
|
"digest 0.10.7",
|
||||||
"ff",
|
"ff",
|
||||||
@@ -2135,6 +2135,37 @@ dependencies = [
|
|||||||
"syn 2.0.106",
|
"syn 2.0.106",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "derive_builder"
|
||||||
|
version = "0.20.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "507dfb09ea8b7fa618fcf76e953f4f5e192547945816d5358edffe39f6f94947"
|
||||||
|
dependencies = [
|
||||||
|
"derive_builder_macro",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "derive_builder_core"
|
||||||
|
version = "0.20.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8"
|
||||||
|
dependencies = [
|
||||||
|
"darling",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.106",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "derive_builder_macro"
|
||||||
|
version = "0.20.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c"
|
||||||
|
dependencies = [
|
||||||
|
"derive_builder_core",
|
||||||
|
"syn 2.0.106",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "derive_more"
|
name = "derive_more"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
@@ -2215,23 +2246,23 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dirs"
|
name = "dirs"
|
||||||
version = "5.0.1"
|
version = "6.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225"
|
checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"dirs-sys",
|
"dirs-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dirs-sys"
|
name = "dirs-sys"
|
||||||
version = "0.4.1"
|
version = "0.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c"
|
checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"option-ext",
|
"option-ext",
|
||||||
"redox_users",
|
"redox_users",
|
||||||
"windows-sys 0.48.0",
|
"windows-sys 0.60.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -4650,6 +4681,12 @@ version = "0.4.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b93853da6d84c2e3c7d730d6473e8817692dd89be387eb01b94d7f108ecb5b8c"
|
checksum = "b93853da6d84c2e3c7d730d6473e8817692dd89be387eb01b94d7f108ecb5b8c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "no-std-net"
|
||||||
|
version = "0.6.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "43794a0ace135be66a25d3ae77d41b91615fb68ae937f904090203e81f755b65"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nom"
|
name = "nom"
|
||||||
version = "7.1.3"
|
version = "7.1.3"
|
||||||
@@ -5001,7 +5038,7 @@ dependencies = [
|
|||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
"tracing-tree",
|
"tracing-tree",
|
||||||
"utoipa",
|
"utoipa",
|
||||||
"vergen",
|
"vergen 8.3.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -5181,6 +5218,7 @@ dependencies = [
|
|||||||
"tokio",
|
"tokio",
|
||||||
"tokio-stream",
|
"tokio-stream",
|
||||||
"tokio-tungstenite",
|
"tokio-tungstenite",
|
||||||
|
"tokio_with_wasm",
|
||||||
"tracing",
|
"tracing",
|
||||||
"tungstenite 0.20.1",
|
"tungstenite 0.20.1",
|
||||||
"url",
|
"url",
|
||||||
@@ -5249,21 +5287,26 @@ version = "1.4.0-rc.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"futures",
|
"futures",
|
||||||
|
"gloo-timers",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
"nym-bin-common",
|
"nym-bin-common",
|
||||||
|
"nym-gateway-requests",
|
||||||
"nym-node-tester-utils",
|
"nym-node-tester-utils",
|
||||||
"nym-node-tester-wasm",
|
"nym-node-tester-wasm",
|
||||||
|
"once_cell",
|
||||||
"rand 0.8.5",
|
"rand 0.8.5",
|
||||||
"serde",
|
"serde",
|
||||||
"serde-wasm-bindgen 0.6.5",
|
"serde-wasm-bindgen 0.6.5",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"thiserror 2.0.12",
|
"thiserror 2.0.12",
|
||||||
|
"tokio_with_wasm",
|
||||||
"tsify",
|
"tsify",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
"wasm-bindgen-futures",
|
"wasm-bindgen-futures",
|
||||||
"wasm-bindgen-test",
|
"wasm-bindgen-test",
|
||||||
"wasm-client-core",
|
"wasm-client-core",
|
||||||
"wasm-utils",
|
"wasm-utils",
|
||||||
|
"web-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -5288,6 +5331,14 @@ dependencies = [
|
|||||||
"nym-multisig-contract-common",
|
"nym-multisig-contract-common",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nym-common"
|
||||||
|
version = "1.18.0"
|
||||||
|
dependencies = [
|
||||||
|
"tracing",
|
||||||
|
"tracing-test",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nym-compact-ecash"
|
name = "nym-compact-ecash"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
@@ -5326,6 +5377,24 @@ dependencies = [
|
|||||||
"url",
|
"url",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nym-connection-monitor"
|
||||||
|
version = "1.18.0"
|
||||||
|
dependencies = [
|
||||||
|
"bincode",
|
||||||
|
"bytes",
|
||||||
|
"futures",
|
||||||
|
"nym-common",
|
||||||
|
"nym-config",
|
||||||
|
"nym-ip-packet-requests",
|
||||||
|
"nym-sdk",
|
||||||
|
"pnet_packet",
|
||||||
|
"thiserror 2.0.12",
|
||||||
|
"tokio",
|
||||||
|
"tokio-util",
|
||||||
|
"tracing",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nym-contracts-common"
|
name = "nym-contracts-common"
|
||||||
version = "0.5.0"
|
version = "0.5.0"
|
||||||
@@ -5340,7 +5409,7 @@ dependencies = [
|
|||||||
"serde_json",
|
"serde_json",
|
||||||
"thiserror 2.0.12",
|
"thiserror 2.0.12",
|
||||||
"utoipa",
|
"utoipa",
|
||||||
"vergen",
|
"vergen 8.3.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -5469,6 +5538,7 @@ dependencies = [
|
|||||||
"schemars 0.8.22",
|
"schemars 0.8.22",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
"serde_with",
|
||||||
"time",
|
"time",
|
||||||
"tsify",
|
"tsify",
|
||||||
"utoipa",
|
"utoipa",
|
||||||
@@ -5625,7 +5695,6 @@ dependencies = [
|
|||||||
"criterion",
|
"criterion",
|
||||||
"ff",
|
"ff",
|
||||||
"group",
|
"group",
|
||||||
"lazy_static",
|
|
||||||
"nym-contracts-common",
|
"nym-contracts-common",
|
||||||
"nym-pemstore",
|
"nym-pemstore",
|
||||||
"rand 0.8.5",
|
"rand 0.8.5",
|
||||||
@@ -5814,6 +5883,51 @@ dependencies = [
|
|||||||
"zeroize",
|
"zeroize",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nym-gateway-probe"
|
||||||
|
version = "1.18.0"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"base64 0.22.1",
|
||||||
|
"bincode",
|
||||||
|
"bs58",
|
||||||
|
"bytes",
|
||||||
|
"clap",
|
||||||
|
"futures",
|
||||||
|
"hex",
|
||||||
|
"nym-authenticator-client",
|
||||||
|
"nym-authenticator-requests",
|
||||||
|
"nym-bandwidth-controller",
|
||||||
|
"nym-bin-common",
|
||||||
|
"nym-client-core",
|
||||||
|
"nym-config",
|
||||||
|
"nym-connection-monitor",
|
||||||
|
"nym-credential-utils",
|
||||||
|
"nym-credentials",
|
||||||
|
"nym-credentials-interface",
|
||||||
|
"nym-crypto",
|
||||||
|
"nym-http-api-client",
|
||||||
|
"nym-http-api-client-macro",
|
||||||
|
"nym-ip-packet-client",
|
||||||
|
"nym-ip-packet-requests",
|
||||||
|
"nym-node-status-client",
|
||||||
|
"nym-sdk",
|
||||||
|
"nym-topology",
|
||||||
|
"nym-validator-client",
|
||||||
|
"pnet_packet",
|
||||||
|
"rand 0.8.5",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"thiserror 2.0.12",
|
||||||
|
"tokio",
|
||||||
|
"tokio-util",
|
||||||
|
"tracing",
|
||||||
|
"tracing-subscriber",
|
||||||
|
"url",
|
||||||
|
"vergen-gitcl",
|
||||||
|
"x25519-dalek",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nym-gateway-requests"
|
name = "nym-gateway-requests"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
@@ -6432,7 +6546,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nym-node-status-api"
|
name = "nym-node-status-api"
|
||||||
version = "4.0.5"
|
version = "4.0.11-rc1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ammonia",
|
"ammonia",
|
||||||
"anyhow",
|
"anyhow",
|
||||||
@@ -6671,6 +6785,7 @@ dependencies = [
|
|||||||
name = "nym-registration-client"
|
name = "nym-registration-client"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"futures",
|
||||||
"nym-authenticator-client",
|
"nym-authenticator-client",
|
||||||
"nym-bandwidth-controller",
|
"nym-bandwidth-controller",
|
||||||
"nym-credential-storage",
|
"nym-credential-storage",
|
||||||
@@ -6683,6 +6798,7 @@ dependencies = [
|
|||||||
"tokio",
|
"tokio",
|
||||||
"tokio-util",
|
"tokio-util",
|
||||||
"tracing",
|
"tracing",
|
||||||
|
"typed-builder",
|
||||||
"url",
|
"url",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -6998,6 +7114,7 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
"thiserror 2.0.12",
|
"thiserror 2.0.12",
|
||||||
"utoipa",
|
"utoipa",
|
||||||
|
"wasmtimer",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -8159,6 +8276,48 @@ dependencies = [
|
|||||||
"plotters-backend",
|
"plotters-backend",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pnet_base"
|
||||||
|
version = "0.35.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ffc190d4067df16af3aba49b3b74c469e611cad6314676eaf1157f31aa0fb2f7"
|
||||||
|
dependencies = [
|
||||||
|
"no-std-net",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pnet_macros"
|
||||||
|
version = "0.35.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "13325ac86ee1a80a480b0bc8e3d30c25d133616112bb16e86f712dcf8a71c863"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"regex",
|
||||||
|
"syn 2.0.106",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pnet_macros_support"
|
||||||
|
version = "0.35.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "eed67a952585d509dd0003049b1fc56b982ac665c8299b124b90ea2bdb3134ab"
|
||||||
|
dependencies = [
|
||||||
|
"pnet_base",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pnet_packet"
|
||||||
|
version = "0.35.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4c96ebadfab635fcc23036ba30a7d33a80c39e8461b8bd7dc7bb186acb96560f"
|
||||||
|
dependencies = [
|
||||||
|
"glob",
|
||||||
|
"pnet_base",
|
||||||
|
"pnet_macros",
|
||||||
|
"pnet_macros_support",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "polling"
|
name = "polling"
|
||||||
version = "2.8.0"
|
version = "2.8.0"
|
||||||
@@ -8614,13 +8773,13 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "redox_users"
|
name = "redox_users"
|
||||||
version = "0.4.6"
|
version = "0.5.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43"
|
checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"getrandom 0.2.16",
|
"getrandom 0.2.16",
|
||||||
"libredox",
|
"libredox",
|
||||||
"thiserror 1.0.69",
|
"thiserror 2.0.12",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -10753,6 +10912,30 @@ dependencies = [
|
|||||||
"tokio",
|
"tokio",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tokio_with_wasm"
|
||||||
|
version = "0.8.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4dfba9b946459940fb564dcf576631074cdfb0bfe4c962acd4c31f0dca7897e6"
|
||||||
|
dependencies = [
|
||||||
|
"js-sys",
|
||||||
|
"tokio",
|
||||||
|
"tokio_with_wasm_proc",
|
||||||
|
"wasm-bindgen",
|
||||||
|
"wasm-bindgen-futures",
|
||||||
|
"web-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tokio_with_wasm_proc"
|
||||||
|
version = "0.8.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "37e04c1865c281139e5ccf633cb9f76ffdaabeebfe53b703984cf82878e2aabb"
|
||||||
|
dependencies = [
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.106",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "toml"
|
name = "toml"
|
||||||
version = "0.5.11"
|
version = "0.5.11"
|
||||||
@@ -11035,6 +11218,27 @@ dependencies = [
|
|||||||
"tracing-log 0.2.0",
|
"tracing-log 0.2.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tracing-test"
|
||||||
|
version = "0.2.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "557b891436fe0d5e0e363427fc7f217abf9ccd510d5136549847bdcbcd011d68"
|
||||||
|
dependencies = [
|
||||||
|
"tracing-core",
|
||||||
|
"tracing-subscriber",
|
||||||
|
"tracing-test-macro",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tracing-test-macro"
|
||||||
|
version = "0.2.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "04659ddb06c87d233c566112c1c9c5b9e98256d9af50ec3bc9c8327f873a7568"
|
||||||
|
dependencies = [
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.106",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tracing-tree"
|
name = "tracing-tree"
|
||||||
version = "0.2.5"
|
version = "0.2.5"
|
||||||
@@ -11188,6 +11392,26 @@ dependencies = [
|
|||||||
"utf-8",
|
"utf-8",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "typed-builder"
|
||||||
|
version = "0.23.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0d0dd654273fc253fde1df4172c31fb6615cf8b041d3a4008a028ef8b1119e66"
|
||||||
|
dependencies = [
|
||||||
|
"typed-builder-macro",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "typed-builder-macro"
|
||||||
|
version = "0.23.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "016c26257f448222014296978b2c8456e2cad4de308c35bdb1e383acd569ef5b"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.106",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "typenum"
|
name = "typenum"
|
||||||
version = "1.18.0"
|
version = "1.18.0"
|
||||||
@@ -11587,6 +11811,47 @@ dependencies = [
|
|||||||
"time",
|
"time",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "vergen"
|
||||||
|
version = "9.0.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6b2bf58be11fc9414104c6d3a2e464163db5ef74b12296bda593cac37b6e4777"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"cargo_metadata 0.19.2",
|
||||||
|
"derive_builder",
|
||||||
|
"regex",
|
||||||
|
"rustc_version 0.4.1",
|
||||||
|
"rustversion",
|
||||||
|
"time",
|
||||||
|
"vergen-lib",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "vergen-gitcl"
|
||||||
|
version = "1.0.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b9dfc1de6eb2e08a4ddf152f1b179529638bedc0ea95e6d667c014506377aefe"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"derive_builder",
|
||||||
|
"rustversion",
|
||||||
|
"time",
|
||||||
|
"vergen 9.0.6",
|
||||||
|
"vergen-lib",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "vergen-lib"
|
||||||
|
version = "0.1.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9b07e6010c0f3e59fcb164e0163834597da68d1f864e2b8ca49f74de01e9c166"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"derive_builder",
|
||||||
|
"rustversion",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "version_check"
|
name = "version_check"
|
||||||
version = "0.9.5"
|
version = "0.9.5"
|
||||||
|
|||||||
+20
-21
@@ -31,6 +31,7 @@ members = [
|
|||||||
"common/client-libs/mixnet-client",
|
"common/client-libs/mixnet-client",
|
||||||
"common/client-libs/validator-client",
|
"common/client-libs/validator-client",
|
||||||
"common/commands",
|
"common/commands",
|
||||||
|
"common/nym-common",
|
||||||
"common/config",
|
"common/config",
|
||||||
"common/cosmwasm-smart-contracts/coconut-dkg",
|
"common/cosmwasm-smart-contracts/coconut-dkg",
|
||||||
"common/cosmwasm-smart-contracts/contracts-common",
|
"common/cosmwasm-smart-contracts/contracts-common",
|
||||||
@@ -58,7 +59,8 @@ members = [
|
|||||||
"common/gateway-requests",
|
"common/gateway-requests",
|
||||||
"common/gateway-stats-storage",
|
"common/gateway-stats-storage",
|
||||||
"common/gateway-storage",
|
"common/gateway-storage",
|
||||||
"common/http-api-client", "common/http-api-client-macro",
|
"common/http-api-client",
|
||||||
|
"common/http-api-client-macro",
|
||||||
"common/http-api-common",
|
"common/http-api-common",
|
||||||
"common/inclusion-probability",
|
"common/inclusion-probability",
|
||||||
"common/ip-packet-requests",
|
"common/ip-packet-requests",
|
||||||
@@ -66,7 +68,9 @@ members = [
|
|||||||
"common/mixnode-common",
|
"common/mixnode-common",
|
||||||
"common/network-defaults",
|
"common/network-defaults",
|
||||||
"common/node-tester-utils",
|
"common/node-tester-utils",
|
||||||
"common/nonexhaustive-delayqueue", "common/nym-cache",
|
"common/nonexhaustive-delayqueue",
|
||||||
|
"common/nym-cache",
|
||||||
|
"common/nym-connection-monitor",
|
||||||
"common/nym-id",
|
"common/nym-id",
|
||||||
"common/nym-metrics",
|
"common/nym-metrics",
|
||||||
"common/nym_offline_compact_ecash",
|
"common/nym_offline_compact_ecash",
|
||||||
@@ -98,7 +102,8 @@ members = [
|
|||||||
"common/ticketbooks-merkle",
|
"common/ticketbooks-merkle",
|
||||||
"common/topology",
|
"common/topology",
|
||||||
"common/tun",
|
"common/tun",
|
||||||
"common/types", "common/upgrade-mode-check",
|
"common/types",
|
||||||
|
"common/upgrade-mode-check",
|
||||||
"common/verloc",
|
"common/verloc",
|
||||||
"common/wasm/client-core",
|
"common/wasm/client-core",
|
||||||
"common/wasm/storage",
|
"common/wasm/storage",
|
||||||
@@ -127,7 +132,7 @@ members = [
|
|||||||
"nym-node-status-api/nym-node-status-client",
|
"nym-node-status-api/nym-node-status-client",
|
||||||
"nym-node/nym-node-metrics",
|
"nym-node/nym-node-metrics",
|
||||||
"nym-node/nym-node-requests",
|
"nym-node/nym-node-requests",
|
||||||
"nym-outfox",
|
"nym-outfox",
|
||||||
"nym-registration-client",
|
"nym-registration-client",
|
||||||
"nym-signers-monitor",
|
"nym-signers-monitor",
|
||||||
"nym-statistics-api",
|
"nym-statistics-api",
|
||||||
@@ -160,6 +165,7 @@ members = [
|
|||||||
"wasm/mix-fetch",
|
"wasm/mix-fetch",
|
||||||
"wasm/node-tester",
|
"wasm/node-tester",
|
||||||
"wasm/zknym-lib",
|
"wasm/zknym-lib",
|
||||||
|
"nym-gateway-probe"
|
||||||
]
|
]
|
||||||
|
|
||||||
default-members = [
|
default-members = [
|
||||||
@@ -178,16 +184,16 @@ default-members = [
|
|||||||
"tools/nymvisor",
|
"tools/nymvisor",
|
||||||
]
|
]
|
||||||
|
|
||||||
exclude = ["explorer", "contracts", "nym-wallet", "cpu-cycles"]
|
exclude = ["contracts", "nym-wallet", "cpu-cycles"]
|
||||||
|
|
||||||
[workspace.package]
|
[workspace.package]
|
||||||
authors = ["Nym Technologies SA"]
|
authors = ["Nym Technologies SA"]
|
||||||
repository = "https://github.com/nymtech/nym"
|
repository = "https://github.com/nymtech/nym"
|
||||||
homepage = "https://nymtech.net"
|
homepage = "https://nymtech.net"
|
||||||
documentation = "https://nymtech.net"
|
documentation = "https://nymtech.net"
|
||||||
edition = "2021"
|
edition = "2024"
|
||||||
license = "Apache-2.0"
|
license = "Apache-2.0"
|
||||||
rust-version = "1.81"
|
rust-version = "1.85"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
@@ -209,7 +215,6 @@ base64 = "0.22.1"
|
|||||||
base85rs = "0.1.3"
|
base85rs = "0.1.3"
|
||||||
bincode = "1.3.3"
|
bincode = "1.3.3"
|
||||||
bip39 = { version = "2.0.0", features = ["zeroize"] }
|
bip39 = { version = "2.0.0", features = ["zeroize"] }
|
||||||
bit-vec = "0.7.0" # can we unify those?
|
|
||||||
bitvec = "1.0.0"
|
bitvec = "1.0.0"
|
||||||
blake3 = "1.7.0"
|
blake3 = "1.7.0"
|
||||||
bloomfilter = "3.0.1"
|
bloomfilter = "3.0.1"
|
||||||
@@ -237,13 +242,11 @@ criterion = "0.5"
|
|||||||
csv = "1.3.1"
|
csv = "1.3.1"
|
||||||
ctr = "0.9.1"
|
ctr = "0.9.1"
|
||||||
cupid = "0.6.1"
|
cupid = "0.6.1"
|
||||||
curve25519-dalek = "4.1"
|
|
||||||
dashmap = "5.5.3"
|
dashmap = "5.5.3"
|
||||||
# We want https://github.com/DefGuard/wireguard-rs/pull/64 , but there's no crates.io release being pushed out anymore
|
# We want https://github.com/DefGuard/wireguard-rs/pull/64 , but there's no crates.io release being pushed out anymore
|
||||||
defguard_wireguard_rs = { git = "https://github.com/DefGuard/wireguard-rs.git", rev = "v0.4.7" }
|
defguard_wireguard_rs = { git = "https://github.com/DefGuard/wireguard-rs.git", rev = "v0.4.7" }
|
||||||
digest = "0.10.7"
|
digest = "0.10.7"
|
||||||
dirs = "5.0"
|
dirs = "6.0"
|
||||||
doc-comment = "0.3"
|
|
||||||
dotenvy = "0.15.6"
|
dotenvy = "0.15.6"
|
||||||
dyn-clone = "1.0.19"
|
dyn-clone = "1.0.19"
|
||||||
ecdsa = "0.16"
|
ecdsa = "0.16"
|
||||||
@@ -259,11 +262,8 @@ futures = "0.3.31"
|
|||||||
futures-util = "0.3"
|
futures-util = "0.3"
|
||||||
generic-array = "0.14.7"
|
generic-array = "0.14.7"
|
||||||
getrandom = "0.2.10"
|
getrandom = "0.2.10"
|
||||||
getset = "0.1.5"
|
|
||||||
handlebars = "3.5.5"
|
handlebars = "3.5.5"
|
||||||
headers = "0.4.0"
|
|
||||||
hex = "0.4.3"
|
hex = "0.4.3"
|
||||||
hex-literal = "0.3.3"
|
|
||||||
hickory-resolver = "0.25"
|
hickory-resolver = "0.25"
|
||||||
hkdf = "0.12.3"
|
hkdf = "0.12.3"
|
||||||
hmac = "0.12.1"
|
hmac = "0.12.1"
|
||||||
@@ -287,12 +287,10 @@ lazy_static = "1.5.0"
|
|||||||
ledger-transport = "0.10.0"
|
ledger-transport = "0.10.0"
|
||||||
ledger-transport-hid = "0.10.0"
|
ledger-transport-hid = "0.10.0"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
maxminddb = "0.23.0"
|
|
||||||
mime = "0.3.17"
|
mime = "0.3.17"
|
||||||
moka = { version = "0.12", features = ["future"] }
|
moka = { version = "0.12", features = ["future"] }
|
||||||
nix = "0.27.1"
|
nix = "0.27.1"
|
||||||
notify = "5.1.0"
|
notify = "5.1.0"
|
||||||
okapi = "0.7.0"
|
|
||||||
once_cell = "1.21.3"
|
once_cell = "1.21.3"
|
||||||
opentelemetry = "0.19.0"
|
opentelemetry = "0.19.0"
|
||||||
opentelemetry-jaeger = "0.18.0"
|
opentelemetry-jaeger = "0.18.0"
|
||||||
@@ -300,7 +298,7 @@ parking_lot = "0.12.3"
|
|||||||
pem = "0.8"
|
pem = "0.8"
|
||||||
petgraph = "0.6.5"
|
petgraph = "0.6.5"
|
||||||
pin-project = "1.1"
|
pin-project = "1.1"
|
||||||
pin-project-lite = "0.2.16"
|
pnet_packet = "0.35.0"
|
||||||
publicsuffix = "2.3.0"
|
publicsuffix = "2.3.0"
|
||||||
proc_pidinfo = "0.1.3"
|
proc_pidinfo = "0.1.3"
|
||||||
quote = "1"
|
quote = "1"
|
||||||
@@ -308,13 +306,10 @@ rand = "0.8.5"
|
|||||||
rand_chacha = "0.3"
|
rand_chacha = "0.3"
|
||||||
rand_core = "0.6.3"
|
rand_core = "0.6.3"
|
||||||
rand_distr = "0.4"
|
rand_distr = "0.4"
|
||||||
rand_pcg = "0.3.1"
|
|
||||||
rand_seeder = "0.2.3"
|
|
||||||
rayon = "1.5.1"
|
rayon = "1.5.1"
|
||||||
regex = "1.10.6"
|
regex = "1.10.6"
|
||||||
reqwest = { version = "0.12.15", default-features = false }
|
reqwest = { version = "0.12.15", default-features = false }
|
||||||
rs_merkle = "1.5.0"
|
rs_merkle = "1.5.0"
|
||||||
safer-ffi = "0.1.13"
|
|
||||||
schemars = "0.8.22"
|
schemars = "0.8.22"
|
||||||
semver = "1.0.26"
|
semver = "1.0.26"
|
||||||
serde = "1.0.219"
|
serde = "1.0.219"
|
||||||
@@ -358,8 +353,10 @@ tracing-opentelemetry = "0.19.0"
|
|||||||
tracing-subscriber = "0.3.19"
|
tracing-subscriber = "0.3.19"
|
||||||
tracing-tree = "0.2.2"
|
tracing-tree = "0.2.2"
|
||||||
tracing-indicatif = "0.3.9"
|
tracing-indicatif = "0.3.9"
|
||||||
|
tracing-test = "0.2.5"
|
||||||
ts-rs = "10.1.0"
|
ts-rs = "10.1.0"
|
||||||
tungstenite = { version = "0.20.1", default-features = false }
|
tungstenite = { version = "0.20.1", default-features = false }
|
||||||
|
typed-builder = "0.23.0"
|
||||||
uniffi = "0.29.2"
|
uniffi = "0.29.2"
|
||||||
uniffi_build = "0.29.0"
|
uniffi_build = "0.29.0"
|
||||||
url = "2.5"
|
url = "2.5"
|
||||||
@@ -368,6 +365,7 @@ utoipa-swagger-ui = "8.1"
|
|||||||
utoipauto = "0.2"
|
utoipauto = "0.2"
|
||||||
uuid = "*"
|
uuid = "*"
|
||||||
vergen = { version = "=8.3.1", default-features = false }
|
vergen = { version = "=8.3.1", default-features = false }
|
||||||
|
vergen-gitcl = { version = "1.0.8", default-features = false }
|
||||||
walkdir = "2"
|
walkdir = "2"
|
||||||
x25519-dalek = "2.0.0"
|
x25519-dalek = "2.0.0"
|
||||||
zeroize = "1.7.0"
|
zeroize = "1.7.0"
|
||||||
@@ -407,18 +405,19 @@ prost = { version = "0.13", default-features = false }
|
|||||||
# wasm-related dependencies
|
# wasm-related dependencies
|
||||||
gloo-utils = "0.2.0"
|
gloo-utils = "0.2.0"
|
||||||
gloo-net = "0.6.0"
|
gloo-net = "0.6.0"
|
||||||
|
gloo-timers = "0.3.0"
|
||||||
|
|
||||||
indexed_db_futures = "0.6.4"
|
indexed_db_futures = "0.6.4"
|
||||||
js-sys = "0.3.76"
|
js-sys = "0.3.76"
|
||||||
serde-wasm-bindgen = "0.6.5"
|
serde-wasm-bindgen = "0.6.5"
|
||||||
tsify = "0.4.5"
|
tsify = "0.4.5"
|
||||||
|
tokio_with_wasm = { version = "0.8.7" }
|
||||||
wasm-bindgen = "0.2.99"
|
wasm-bindgen = "0.2.99"
|
||||||
wasm-bindgen-futures = "0.4.49"
|
wasm-bindgen-futures = "0.4.49"
|
||||||
wasm-bindgen-test = "0.3.49"
|
wasm-bindgen-test = "0.3.49"
|
||||||
wasmtimer = "0.4.1"
|
wasmtimer = "0.4.1"
|
||||||
web-sys = "0.3.76"
|
web-sys = "0.3.76"
|
||||||
|
|
||||||
|
|
||||||
# for local development:
|
# for local development:
|
||||||
#[patch.crates-io]
|
#[patch.crates-io]
|
||||||
#sphinx-packet = { path = "../sphinx" }
|
#sphinx-packet = { path = "../sphinx" }
|
||||||
|
|||||||
@@ -107,16 +107,16 @@ sdk-wasm-build:
|
|||||||
$(MAKE) -C nym-browser-extension/storage wasm-pack
|
$(MAKE) -C nym-browser-extension/storage wasm-pack
|
||||||
$(MAKE) -C wasm/client
|
$(MAKE) -C wasm/client
|
||||||
$(MAKE) -C wasm/node-tester
|
$(MAKE) -C wasm/node-tester
|
||||||
$(MAKE) -C wasm/mix-fetch
|
# $(MAKE) -C wasm/mix-fetch
|
||||||
$(MAKE) -C wasm/zknym-lib
|
$(MAKE) -C wasm/zknym-lib
|
||||||
#$(MAKE) -C wasm/full-nym-wasm
|
# $(MAKE) -C wasm/full-nym-wasm
|
||||||
|
|
||||||
# run this from npm/yarn to ensure tools are in the path, e.g. yarn build:sdk from root of repo
|
# run this from npm/yarn to ensure tools are in the path, e.g. yarn build:sdk from root of repo
|
||||||
sdk-typescript-build:
|
sdk-typescript-build:
|
||||||
npx lerna run --scope @nymproject/sdk build --stream
|
npx lerna run --scope @nymproject/sdk build --stream
|
||||||
npx lerna run --scope @nymproject/mix-fetch build --stream
|
# npx lerna run --scope @nymproject/mix-fetch build --stream
|
||||||
npx lerna run --scope @nymproject/node-tester build --stream
|
# npx lerna run --scope @nymproject/node-tester build --stream
|
||||||
yarn --cwd sdk/typescript/codegen/contract-clients build
|
# yarn --cwd sdk/typescript/codegen/contract-clients build
|
||||||
|
|
||||||
# NOTE: These targets are part of the main workspace (but not as wasm32-unknown-unknown)
|
# NOTE: These targets are part of the main workspace (but not as wasm32-unknown-unknown)
|
||||||
WASM_CRATES = extension-storage nym-client-wasm nym-node-tester-wasm zknym-lib
|
WASM_CRATES = extension-storage nym-client-wasm nym-node-tester-wasm zknym-lib
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ version = "1.1.64"
|
|||||||
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jędrzej Stuczyński <andrew@nymtech.net>"]
|
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jędrzej Stuczyński <andrew@nymtech.net>"]
|
||||||
description = "Implementation of the Nym Client"
|
description = "Implementation of the Nym Client"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
rust-version = "1.70"
|
rust-version = "1.85"
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ impl SocketClient {
|
|||||||
let ClientInput {
|
let ClientInput {
|
||||||
connection_command_sender,
|
connection_command_sender,
|
||||||
input_sender,
|
input_sender,
|
||||||
|
..
|
||||||
} = client_input;
|
} = client_input;
|
||||||
|
|
||||||
let ClientOutput {
|
let ClientOutput {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ version = "1.1.64"
|
|||||||
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"]
|
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"]
|
||||||
description = "A SOCKS5 localhost proxy that converts incoming messages to Sphinx and sends them to a Nym address"
|
description = "A SOCKS5 localhost proxy that converts incoming messages to Sphinx and sends them to a Nym address"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
rust-version = "1.70"
|
rust-version = "1.85"
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
use futures::channel::mpsc;
|
|
||||||
use futures::StreamExt;
|
use futures::StreamExt;
|
||||||
|
use futures::channel::mpsc;
|
||||||
use notify::event::{DataChange, MetadataKind, ModifyKind};
|
use notify::event::{DataChange, MetadataKind, ModifyKind};
|
||||||
use notify::{Config, Event, EventKind, RecommendedWatcher, RecursiveMode, Watcher};
|
use notify::{Config, Event, EventKind, RecommendedWatcher, RecursiveMode, Watcher};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
@@ -96,10 +96,10 @@ impl AsyncFileWatcher {
|
|||||||
// when testing I was consistently getting two `Modify(Data(Any))` events in quick succession
|
// when testing I was consistently getting two `Modify(Data(Any))` events in quick succession
|
||||||
// (probably to modify content and metadata).
|
// (probably to modify content and metadata).
|
||||||
// we really only want to propagate one of them
|
// we really only want to propagate one of them
|
||||||
if let Some(previous) = self.last_received.get(&event.kind) {
|
if let Some(previous) = self.last_received.get(&event.kind)
|
||||||
if now.duration_since(*previous) < self.tick_duration {
|
&& now.duration_since(*previous) < self.tick_duration
|
||||||
return false;
|
{
|
||||||
}
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
let Some(filters) = &self.filters else {
|
let Some(filters) = &self.filters else {
|
||||||
|
|||||||
@@ -5,9 +5,10 @@ use nym_sphinx::addressing::Recipient;
|
|||||||
use nym_wireguard_types::PeerPublicKey;
|
use nym_wireguard_types::PeerPublicKey;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
AuthenticatorVersion, Error,
|
||||||
latest::registration::IpPair,
|
latest::registration::IpPair,
|
||||||
traits::{FinalMessage, InitMessage, QueryBandwidthMessage, TopUpMessage, Versionable},
|
traits::{FinalMessage, InitMessage, QueryBandwidthMessage, TopUpMessage, Versionable},
|
||||||
v2, v3, v4, v5, AuthenticatorVersion, Error,
|
v2, v3, v4, v5,
|
||||||
};
|
};
|
||||||
|
|
||||||
// This is very redundant with AuthenticatorRequest and I reckon they could be smooshed.
|
// This is very redundant with AuthenticatorRequest and I reckon they could be smooshed.
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ use nym_crypto::asymmetric::x25519::PrivateKey;
|
|||||||
use nym_wireguard_types::PeerPublicKey;
|
use nym_wireguard_types::PeerPublicKey;
|
||||||
|
|
||||||
use crate::latest::registration::IpPair;
|
use crate::latest::registration::IpPair;
|
||||||
use crate::{v1, v2, v3, v4, v5, AuthenticatorVersion, Error};
|
use crate::{AuthenticatorVersion, Error, v1, v2, v3, v4, v5};
|
||||||
|
|
||||||
pub trait Versionable {
|
pub trait Versionable {
|
||||||
fn version(&self) -> AuthenticatorVersion;
|
fn version(&self) -> AuthenticatorVersion;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
use base64::{engine::general_purpose, Engine};
|
use base64::{Engine, engine::general_purpose};
|
||||||
use nym_wireguard_types::PeerPublicKey;
|
use nym_wireguard_types::PeerPublicKey;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
use base64::{engine::general_purpose, Engine};
|
use base64::{Engine, engine::general_purpose};
|
||||||
use nym_credentials_interface::CredentialSpendingData;
|
use nym_credentials_interface::CredentialSpendingData;
|
||||||
use nym_wireguard_types::PeerPublicKey;
|
use nym_wireguard_types::PeerPublicKey;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
use base64::{engine::general_purpose, Engine};
|
use base64::{Engine, engine::general_purpose};
|
||||||
use nym_credentials_interface::CredentialSpendingData;
|
use nym_credentials_interface::CredentialSpendingData;
|
||||||
use nym_wireguard_types::PeerPublicKey;
|
use nym_wireguard_types::PeerPublicKey;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
use base64::{engine::general_purpose, Engine};
|
use base64::{Engine, engine::general_purpose};
|
||||||
use nym_credentials_interface::CredentialSpendingData;
|
use nym_credentials_interface::CredentialSpendingData;
|
||||||
use nym_network_defaults::constants::{WG_TUN_DEVICE_IP_ADDRESS_V4, WG_TUN_DEVICE_IP_ADDRESS_V6};
|
use nym_network_defaults::constants::{WG_TUN_DEVICE_IP_ADDRESS_V4, WG_TUN_DEVICE_IP_ADDRESS_V6};
|
||||||
use nym_wireguard_types::PeerPublicKey;
|
use nym_wireguard_types::PeerPublicKey;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
use base64::{engine::general_purpose, Engine};
|
use base64::{Engine, engine::general_purpose};
|
||||||
use nym_credentials_interface::CredentialSpendingData;
|
use nym_credentials_interface::CredentialSpendingData;
|
||||||
use nym_network_defaults::constants::{WG_TUN_DEVICE_IP_ADDRESS_V4, WG_TUN_DEVICE_IP_ADDRESS_V6};
|
use nym_network_defaults::constants::{WG_TUN_DEVICE_IP_ADDRESS_V4, WG_TUN_DEVICE_IP_ADDRESS_V6};
|
||||||
use nym_wireguard_types::PeerPublicKey;
|
use nym_wireguard_types::PeerPublicKey;
|
||||||
|
|||||||
@@ -129,7 +129,11 @@ impl From<semver::Version> for AuthenticatorVersion {
|
|||||||
// if provided version is higher (or equal) to release version of V5,
|
// if provided version is higher (or equal) to release version of V5,
|
||||||
// we return the latest (i.e. v5)
|
// we return the latest (i.e. v5)
|
||||||
|
|
||||||
debug_assert_eq!(Self::V5, Self::LATEST, "a new AuthenticatorVersion variant has been introduced without adjusting the `From<semver::Version>` trait");
|
debug_assert_eq!(
|
||||||
|
Self::V5,
|
||||||
|
Self::LATEST,
|
||||||
|
"a new AuthenticatorVersion variant has been introduced without adjusting the `From<semver::Version>` trait"
|
||||||
|
);
|
||||||
Self::LATEST
|
Self::LATEST
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
|
use clap::Args;
|
||||||
use clap::builder::Command;
|
use clap::builder::Command;
|
||||||
use clap::clap_derive::ValueEnum;
|
use clap::clap_derive::ValueEnum;
|
||||||
use clap::Args;
|
|
||||||
use clap_complete::generator::generate;
|
|
||||||
use clap_complete::Shell as ClapShell;
|
use clap_complete::Shell as ClapShell;
|
||||||
|
use clap_complete::generator::generate;
|
||||||
use std::io;
|
use std::io;
|
||||||
|
|
||||||
pub fn fig_generate(command: &mut Command, name: &str) {
|
pub fn fig_generate(command: &mut Command, name: &str) {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ name = "nym-client-core"
|
|||||||
version = "1.1.15"
|
version = "1.1.15"
|
||||||
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"]
|
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"]
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
rust-version = "1.76"
|
rust-version = "1.85"
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
@@ -36,7 +36,7 @@ nym-bandwidth-controller = { path = "../bandwidth-controller" }
|
|||||||
nym-crypto = { path = "../crypto" }
|
nym-crypto = { path = "../crypto" }
|
||||||
nym-gateway-client = { path = "../client-libs/gateway-client" }
|
nym-gateway-client = { path = "../client-libs/gateway-client" }
|
||||||
nym-gateway-requests = { path = "../gateway-requests" }
|
nym-gateway-requests = { path = "../gateway-requests" }
|
||||||
nym-http-api-client = { path = "../http-api-client" }
|
nym-http-api-client = { path = "../http-api-client", features = ["network-defaults"] }
|
||||||
nym-nonexhaustive-delayqueue = { path = "../nonexhaustive-delayqueue" }
|
nym-nonexhaustive-delayqueue = { path = "../nonexhaustive-delayqueue" }
|
||||||
nym-sphinx = { path = "../nymsphinx" }
|
nym-sphinx = { path = "../nymsphinx" }
|
||||||
nym-statistics-common = { path = "../statistics" }
|
nym-statistics-common = { path = "../statistics" }
|
||||||
@@ -69,7 +69,6 @@ workspace = true
|
|||||||
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.hyper-util]
|
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.hyper-util]
|
||||||
workspace = true
|
workspace = true
|
||||||
features = ["tokio"]
|
features = ["tokio"]
|
||||||
###
|
|
||||||
|
|
||||||
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.tokio-stream]
|
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.tokio-stream]
|
||||||
workspace = true
|
workspace = true
|
||||||
@@ -103,7 +102,7 @@ workspace = true
|
|||||||
features = ["tokio"]
|
features = ["tokio"]
|
||||||
|
|
||||||
[target."cfg(target_arch = \"wasm32\")".dependencies.gloo-timers]
|
[target."cfg(target_arch = \"wasm32\")".dependencies.gloo-timers]
|
||||||
version = "0.3.0"
|
workspace = true
|
||||||
features = ["futures"]
|
features = ["futures"]
|
||||||
|
|
||||||
[target."cfg(target_arch = \"wasm32\")".dependencies.wasm-utils]
|
[target."cfg(target_arch = \"wasm32\")".dependencies.wasm-utils]
|
||||||
@@ -114,6 +113,10 @@ features = ["websocket"]
|
|||||||
workspace = true
|
workspace = true
|
||||||
features = ["wasm-bindgen"]
|
features = ["wasm-bindgen"]
|
||||||
|
|
||||||
|
[target."cfg(target_arch = \"wasm32\")".dependencies.tokio_with_wasm]
|
||||||
|
workspace = true
|
||||||
|
features = ["full"]
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
tempfile = { workspace = true }
|
tempfile = { workspace = true }
|
||||||
|
|
||||||
|
|||||||
@@ -707,13 +707,10 @@ pub struct DebugConfig {
|
|||||||
|
|
||||||
/// Defines all configuration options related to reply SURBs.
|
/// Defines all configuration options related to reply SURBs.
|
||||||
pub reply_surbs: ReplySurbs,
|
pub reply_surbs: ReplySurbs,
|
||||||
|
|
||||||
/// Defines all configuration options related to stats reporting.
|
/// Defines all configuration options related to stats reporting.
|
||||||
pub stats_reporting: StatsReporting,
|
pub stats_reporting: StatsReporting,
|
||||||
|
|
||||||
/// Defines all configuration options related to the forget me flag.
|
/// Defines all configuration options related to the forget me flag.
|
||||||
pub forget_me: ForgetMe,
|
pub forget_me: ForgetMe,
|
||||||
|
|
||||||
/// Defines all configuration options related to the remember me flag.
|
/// Defines all configuration options related to the remember me flag.
|
||||||
pub remember_me: RememberMe,
|
pub remember_me: RememberMe,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -543,10 +543,8 @@ pub struct DebugConfigV6 {
|
|||||||
|
|
||||||
/// Defines all configuration options related to reply SURBs.
|
/// Defines all configuration options related to reply SURBs.
|
||||||
pub reply_surbs: ReplySurbsV6,
|
pub reply_surbs: ReplySurbsV6,
|
||||||
|
|
||||||
/// Defines all configuration options related to stats reporting.
|
/// Defines all configuration options related to stats reporting.
|
||||||
pub stats_reporting: StatsReportingV6,
|
pub stats_reporting: StatsReportingV6,
|
||||||
|
|
||||||
/// Defines all configuration options related to the forget me flag.
|
/// Defines all configuration options related to the forget me flag.
|
||||||
pub forget_me: ForgetMeV6,
|
pub forget_me: ForgetMeV6,
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,6 @@ impl StorageManager {
|
|||||||
}
|
}
|
||||||
})?;
|
})?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let opts = sqlx::sqlite::SqliteConnectOptions::new()
|
let opts = sqlx::sqlite::SqliteConnectOptions::new()
|
||||||
.journal_mode(sqlx::sqlite::SqliteJournalMode::Wal)
|
.journal_mode(sqlx::sqlite::SqliteJournalMode::Wal)
|
||||||
.synchronous(SqliteSynchronous::Normal)
|
.synchronous(SqliteSynchronous::Normal)
|
||||||
|
|||||||
@@ -114,13 +114,12 @@ where
|
|||||||
})?;
|
})?;
|
||||||
hardcoded_topology.entry_capable_nodes().cloned().collect()
|
hardcoded_topology.entry_capable_nodes().cloned().collect()
|
||||||
} else {
|
} else {
|
||||||
let mut rng = rand::thread_rng();
|
|
||||||
crate::init::helpers::gateways_for_init(
|
crate::init::helpers::gateways_for_init(
|
||||||
&mut rng,
|
|
||||||
&core.client.nym_api_urls,
|
&core.client.nym_api_urls,
|
||||||
user_agent,
|
user_agent,
|
||||||
core.debug.topology.minimum_gateway_performance,
|
core.debug.topology.minimum_gateway_performance,
|
||||||
core.debug.topology.ignore_ingress_epoch_role,
|
core.debug.topology.ignore_ingress_epoch_role,
|
||||||
|
None,
|
||||||
)
|
)
|
||||||
.await?
|
.await?
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -173,13 +173,12 @@ where
|
|||||||
})?;
|
})?;
|
||||||
hardcoded_topology.entry_capable_nodes().cloned().collect()
|
hardcoded_topology.entry_capable_nodes().cloned().collect()
|
||||||
} else {
|
} else {
|
||||||
let mut rng = rand::thread_rng();
|
|
||||||
crate::init::helpers::gateways_for_init(
|
crate::init::helpers::gateways_for_init(
|
||||||
&mut rng,
|
|
||||||
&core.client.nym_api_urls,
|
&core.client.nym_api_urls,
|
||||||
user_agent,
|
user_agent,
|
||||||
core.debug.topology.minimum_gateway_performance,
|
core.debug.topology.minimum_gateway_performance,
|
||||||
core.debug.topology.ignore_ingress_epoch_role,
|
core.debug.topology.ignore_ingress_epoch_role,
|
||||||
|
None,
|
||||||
)
|
)
|
||||||
.await?
|
.await?
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -7,11 +7,12 @@ use super::statistics_control::StatisticsControl;
|
|||||||
use crate::client::base_client::storage::helpers::store_client_keys;
|
use crate::client::base_client::storage::helpers::store_client_keys;
|
||||||
use crate::client::base_client::storage::MixnetClientStorage;
|
use crate::client::base_client::storage::MixnetClientStorage;
|
||||||
use crate::client::cover_traffic_stream::LoopCoverTrafficStream;
|
use crate::client::cover_traffic_stream::LoopCoverTrafficStream;
|
||||||
|
use crate::client::event_control::EventControl;
|
||||||
use crate::client::inbound_messages::{InputMessage, InputMessageReceiver, InputMessageSender};
|
use crate::client::inbound_messages::{InputMessage, InputMessageReceiver, InputMessageSender};
|
||||||
use crate::client::key_manager::persistence::KeyStore;
|
use crate::client::key_manager::persistence::KeyStore;
|
||||||
use crate::client::key_manager::ClientKeys;
|
use crate::client::key_manager::ClientKeys;
|
||||||
use crate::client::mix_traffic::transceiver::{GatewayReceiver, GatewayTransceiver, RemoteGateway};
|
use crate::client::mix_traffic::transceiver::{GatewayReceiver, GatewayTransceiver, RemoteGateway};
|
||||||
use crate::client::mix_traffic::{BatchMixMessageSender, MixTrafficController};
|
use crate::client::mix_traffic::{BatchMixMessageSender, MixTrafficController, MixTrafficEvent};
|
||||||
use crate::client::real_messages_control;
|
use crate::client::real_messages_control;
|
||||||
use crate::client::real_messages_control::RealMessagesController;
|
use crate::client::real_messages_control::RealMessagesController;
|
||||||
use crate::client::received_buffer::{
|
use crate::client::received_buffer::{
|
||||||
@@ -66,9 +67,16 @@ use std::path::Path;
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use time::OffsetDateTime;
|
use time::OffsetDateTime;
|
||||||
use tokio::sync::mpsc::Sender;
|
use tokio::sync::mpsc::Sender;
|
||||||
use tracing::*;
|
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
|
#[cfg(target_arch = "wasm32")]
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
use wasm_utils::console_log;
|
||||||
|
|
||||||
|
/// Default number of retries for Nym API requests when using network details with domain fronting.
|
||||||
|
/// This allows the client to try alternative URLs if the primary endpoint is unavailable.
|
||||||
|
const DEFAULT_NYM_API_RETRIES: usize = 3;
|
||||||
|
|
||||||
#[cfg(all(
|
#[cfg(all(
|
||||||
not(target_arch = "wasm32"),
|
not(target_arch = "wasm32"),
|
||||||
feature = "fs-surb-storage",
|
feature = "fs-surb-storage",
|
||||||
@@ -79,10 +87,28 @@ pub mod non_wasm_helpers;
|
|||||||
pub mod helpers;
|
pub mod helpers;
|
||||||
pub mod storage;
|
pub mod storage;
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
pub enum MixnetClientEvent {
|
||||||
|
Traffic(MixTrafficEvent),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type EventReceiver = mpsc::UnboundedReceiver<MixnetClientEvent>;
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct EventSender(pub mpsc::UnboundedSender<MixnetClientEvent>);
|
||||||
|
|
||||||
|
impl EventSender {
|
||||||
|
pub fn send(&self, event: MixnetClientEvent) {
|
||||||
|
if let Err(err) = self.0.unbounded_send(event) {
|
||||||
|
tracing::warn!("Failed to send error event. The caller event reader was closed: {err}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct ClientInput {
|
pub struct ClientInput {
|
||||||
pub connection_command_sender: ConnectionCommandSender,
|
pub connection_command_sender: ConnectionCommandSender,
|
||||||
pub input_sender: InputMessageSender,
|
pub input_sender: InputMessageSender,
|
||||||
|
pub client_request_sender: ClientRequestSender,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ClientInput {
|
impl ClientInput {
|
||||||
@@ -190,10 +216,14 @@ pub struct BaseClientBuilder<C, S: MixnetClientStorage> {
|
|||||||
client_store: S,
|
client_store: S,
|
||||||
dkg_query_client: Option<C>,
|
dkg_query_client: Option<C>,
|
||||||
|
|
||||||
|
// Optional API URLs for domain fronting support
|
||||||
|
nym_api_urls: Option<Vec<nym_network_defaults::ApiUrl>>,
|
||||||
|
|
||||||
wait_for_gateway: bool,
|
wait_for_gateway: bool,
|
||||||
custom_topology_provider: Option<Box<dyn TopologyProvider + Send + Sync>>,
|
custom_topology_provider: Option<Box<dyn TopologyProvider + Send + Sync>>,
|
||||||
custom_gateway_transceiver: Option<Box<dyn GatewayTransceiver + Send>>,
|
custom_gateway_transceiver: Option<Box<dyn GatewayTransceiver + Send>>,
|
||||||
shutdown: Option<ShutdownTracker>,
|
shutdown: Option<ShutdownTracker>,
|
||||||
|
event_tx: Option<EventSender>,
|
||||||
user_agent: Option<UserAgent>,
|
user_agent: Option<UserAgent>,
|
||||||
|
|
||||||
setup_method: GatewaySetup,
|
setup_method: GatewaySetup,
|
||||||
@@ -218,10 +248,12 @@ where
|
|||||||
config: base_config,
|
config: base_config,
|
||||||
client_store,
|
client_store,
|
||||||
dkg_query_client,
|
dkg_query_client,
|
||||||
|
nym_api_urls: None,
|
||||||
wait_for_gateway: false,
|
wait_for_gateway: false,
|
||||||
custom_topology_provider: None,
|
custom_topology_provider: None,
|
||||||
custom_gateway_transceiver: None,
|
custom_gateway_transceiver: None,
|
||||||
shutdown: None,
|
shutdown: None,
|
||||||
|
event_tx: None,
|
||||||
user_agent: None,
|
user_agent: None,
|
||||||
setup_method: GatewaySetup::MustLoad { gateway_id: None },
|
setup_method: GatewaySetup::MustLoad { gateway_id: None },
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
@@ -239,6 +271,16 @@ where
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set Nym API URLs for domain fronting support.
|
||||||
|
///
|
||||||
|
/// When provided, the client will use these API URLs (which include front_hosts)
|
||||||
|
/// to construct HTTP clients with domain fronting enabled.
|
||||||
|
#[must_use]
|
||||||
|
pub fn with_nym_api_urls(mut self, nym_api_urls: Vec<nym_network_defaults::ApiUrl>) -> Self {
|
||||||
|
self.nym_api_urls = Some(nym_api_urls);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn with_forget_me(mut self, forget_me: &ForgetMe) -> Self {
|
pub fn with_forget_me(mut self, forget_me: &ForgetMe) -> Self {
|
||||||
self.config.debug.forget_me = *forget_me;
|
self.config.debug.forget_me = *forget_me;
|
||||||
@@ -284,6 +326,12 @@ where
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn with_event_tx(mut self, event_tx: EventSender) -> Self {
|
||||||
|
self.event_tx = Some(event_tx);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn with_user_agent(mut self, user_agent: UserAgent) -> Self {
|
pub fn with_user_agent(mut self, user_agent: UserAgent) -> Self {
|
||||||
self.user_agent = Some(user_agent);
|
self.user_agent = Some(user_agent);
|
||||||
@@ -314,6 +362,18 @@ where
|
|||||||
details.client_address()
|
details.client_address()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn start_event_control(
|
||||||
|
parent_event_tx: Option<EventSender>,
|
||||||
|
children_event_rx: EventReceiver,
|
||||||
|
shutdown_tracker: &ShutdownTracker,
|
||||||
|
) {
|
||||||
|
let event_control = EventControl::new(parent_event_tx, children_event_rx);
|
||||||
|
shutdown_tracker.try_spawn_named_with_shutdown(
|
||||||
|
async move { event_control.run().await },
|
||||||
|
"EventControl",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// future constantly pumping loop cover traffic at some specified average rate
|
// future constantly pumping loop cover traffic at some specified average rate
|
||||||
// the pumped traffic goes to the MixTrafficController
|
// the pumped traffic goes to the MixTrafficController
|
||||||
fn start_cover_traffic_stream(
|
fn start_cover_traffic_stream(
|
||||||
@@ -325,7 +385,7 @@ where
|
|||||||
stats_tx: ClientStatsSender,
|
stats_tx: ClientStatsSender,
|
||||||
shutdown_tracker: &ShutdownTracker,
|
shutdown_tracker: &ShutdownTracker,
|
||||||
) {
|
) {
|
||||||
info!("Starting loop cover traffic stream...");
|
tracing::info!("Starting loop cover traffic stream...");
|
||||||
|
|
||||||
let mut stream = LoopCoverTrafficStream::new(
|
let mut stream = LoopCoverTrafficStream::new(
|
||||||
ack_key,
|
ack_key,
|
||||||
@@ -357,7 +417,7 @@ where
|
|||||||
stats_tx: ClientStatsSender,
|
stats_tx: ClientStatsSender,
|
||||||
shutdown_tracker: &ShutdownTracker,
|
shutdown_tracker: &ShutdownTracker,
|
||||||
) {
|
) {
|
||||||
info!("Starting real traffic stream...");
|
tracing::info!("Starting real traffic stream...");
|
||||||
|
|
||||||
let real_messages_controller = RealMessagesController::new(
|
let real_messages_controller = RealMessagesController::new(
|
||||||
controller_config,
|
controller_config,
|
||||||
@@ -442,7 +502,7 @@ where
|
|||||||
metrics_reporter: ClientStatsSender,
|
metrics_reporter: ClientStatsSender,
|
||||||
shutdown_tracker: &ShutdownTracker,
|
shutdown_tracker: &ShutdownTracker,
|
||||||
) {
|
) {
|
||||||
info!("Starting received messages buffer controller...");
|
tracing::info!("Starting received messages buffer controller...");
|
||||||
let controller = ReceivedMessagesBufferController::<SphinxMessageReceiver>::new(
|
let controller = ReceivedMessagesBufferController::<SphinxMessageReceiver>::new(
|
||||||
local_encryption_keypair,
|
local_encryption_keypair,
|
||||||
query_receiver,
|
query_receiver,
|
||||||
@@ -553,7 +613,7 @@ where
|
|||||||
details_store
|
details_store
|
||||||
.upgrade_stored_remote_gateway_key(gateway_client.gateway_identity(), &updated_key)
|
.upgrade_stored_remote_gateway_key(gateway_client.gateway_identity(), &updated_key)
|
||||||
.await.map_err(|err| {
|
.await.map_err(|err| {
|
||||||
error!("failed to store upgraded gateway key! this connection might be forever broken now: {err}");
|
tracing::error!("failed to store upgraded gateway key! this connection might be forever broken now: {err}");
|
||||||
ClientCoreError::GatewaysDetailsStoreError { source: Box::new(err) }
|
ClientCoreError::GatewaysDetailsStoreError { source: Box::new(err) }
|
||||||
})?
|
})?
|
||||||
}
|
}
|
||||||
@@ -650,7 +710,7 @@ where
|
|||||||
|
|
||||||
if topology_config.disable_refreshing {
|
if topology_config.disable_refreshing {
|
||||||
// if we're not spawning the refresher, don't cause shutdown immediately
|
// if we're not spawning the refresher, don't cause shutdown immediately
|
||||||
info!("The background topology refresher is not going to be started");
|
tracing::info!("The background topology refresher is not going to be started");
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut topology_refresher = TopologyRefresher::new(
|
let mut topology_refresher = TopologyRefresher::new(
|
||||||
@@ -660,7 +720,7 @@ where
|
|||||||
);
|
);
|
||||||
// before returning, block entire runtime to refresh the current network view so that any
|
// before returning, block entire runtime to refresh the current network view so that any
|
||||||
// components depending on topology would see a non-empty view
|
// components depending on topology would see a non-empty view
|
||||||
info!("Obtaining initial network topology");
|
tracing::info!("Obtaining initial network topology");
|
||||||
topology_refresher.try_refresh().await;
|
topology_refresher.try_refresh().await;
|
||||||
|
|
||||||
if let Err(err) = topology_refresher.ensure_topology_is_routable().await {
|
if let Err(err) = topology_refresher.ensure_topology_is_routable().await {
|
||||||
@@ -686,13 +746,13 @@ where
|
|||||||
.wait_for_gateway(local_gateway, waiting_timeout)
|
.wait_for_gateway(local_gateway, waiting_timeout)
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
error!(
|
tracing::error!(
|
||||||
"the gateway did not come back online within the specified timeout: {err}"
|
"the gateway did not come back online within the specified timeout: {err}"
|
||||||
);
|
);
|
||||||
return Err(err.into());
|
return Err(err.into());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
error!("the gateway we're supposedly connected to does not exist. We'll not be able to send any packets to ourselves: {err}");
|
tracing::error!("the gateway we're supposedly connected to does not exist. We'll not be able to send any packets to ourselves: {err}");
|
||||||
return Err(err.into());
|
return Err(err.into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -700,7 +760,7 @@ where
|
|||||||
if !topology_config.disable_refreshing {
|
if !topology_config.disable_refreshing {
|
||||||
// don't spawn the refresher if we don't want to be refreshing the topology.
|
// don't spawn the refresher if we don't want to be refreshing the topology.
|
||||||
// only use the initial values obtained
|
// only use the initial values obtained
|
||||||
info!("Starting topology refresher...");
|
tracing::info!("Starting topology refresher...");
|
||||||
shutdown_tracker.try_spawn_named_with_shutdown(
|
shutdown_tracker.try_spawn_named_with_shutdown(
|
||||||
async move { topology_refresher.run().await },
|
async move { topology_refresher.run().await },
|
||||||
"TopologyRefresher",
|
"TopologyRefresher",
|
||||||
@@ -717,7 +777,7 @@ where
|
|||||||
input_sender: Sender<InputMessage>,
|
input_sender: Sender<InputMessage>,
|
||||||
shutdown_tracker: &ShutdownTracker,
|
shutdown_tracker: &ShutdownTracker,
|
||||||
) -> ClientStatsSender {
|
) -> ClientStatsSender {
|
||||||
info!("Starting statistics control...");
|
tracing::info!("Starting statistics control...");
|
||||||
StatisticsControl::create_and_start(
|
StatisticsControl::create_and_start(
|
||||||
config.debug.stats_reporting,
|
config.debug.stats_reporting,
|
||||||
user_agent
|
user_agent
|
||||||
@@ -732,10 +792,17 @@ where
|
|||||||
fn start_mix_traffic_controller(
|
fn start_mix_traffic_controller(
|
||||||
gateway_transceiver: Box<dyn GatewayTransceiver + Send>,
|
gateway_transceiver: Box<dyn GatewayTransceiver + Send>,
|
||||||
shutdown_tracker: &ShutdownTracker,
|
shutdown_tracker: &ShutdownTracker,
|
||||||
|
event_tx: EventSender,
|
||||||
) -> (BatchMixMessageSender, ClientRequestSender) {
|
) -> (BatchMixMessageSender, ClientRequestSender) {
|
||||||
info!("Starting mix traffic controller...");
|
tracing::info!("Starting mix traffic controller...");
|
||||||
let (mut mix_traffic_controller, mix_tx, client_tx) =
|
let mut mix_traffic_controller = MixTrafficController::new(
|
||||||
MixTrafficController::new(gateway_transceiver, shutdown_tracker.clone_shutdown_token());
|
gateway_transceiver,
|
||||||
|
shutdown_tracker.clone_shutdown_token(),
|
||||||
|
event_tx,
|
||||||
|
);
|
||||||
|
|
||||||
|
let mix_tx = mix_traffic_controller.mix_tx();
|
||||||
|
let client_tx = mix_traffic_controller.client_tx();
|
||||||
|
|
||||||
shutdown_tracker.try_spawn_named(
|
shutdown_tracker.try_spawn_named(
|
||||||
async move { mix_traffic_controller.run().await },
|
async move { mix_traffic_controller.run().await },
|
||||||
@@ -799,7 +866,7 @@ where
|
|||||||
{
|
{
|
||||||
// if client keys do not exist already, create and persist them
|
// if client keys do not exist already, create and persist them
|
||||||
if key_store.load_keys().await.is_err() {
|
if key_store.load_keys().await.is_err() {
|
||||||
info!("could not find valid client keys - a new set will be generated");
|
tracing::info!("could not find valid client keys - a new set will be generated");
|
||||||
let mut rng = OsRng;
|
let mut rng = OsRng;
|
||||||
let keys = if let Some(derivation_material) = derivation_material {
|
let keys = if let Some(derivation_material) = derivation_material {
|
||||||
ClientKeys::from_master_key(&mut rng, &derivation_material)
|
ClientKeys::from_master_key(&mut rng, &derivation_material)
|
||||||
@@ -814,21 +881,67 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn construct_nym_api_client(
|
fn construct_nym_api_client(
|
||||||
|
nym_api_urls: Option<&Vec<nym_network_defaults::ApiUrl>>,
|
||||||
config: &Config,
|
config: &Config,
|
||||||
user_agent: Option<UserAgent>,
|
user_agent: Option<UserAgent>,
|
||||||
) -> Result<nym_http_api_client::Client, ClientCoreError> {
|
) -> Result<nym_http_api_client::Client, ClientCoreError> {
|
||||||
|
tracing::debug!(
|
||||||
|
"construct_nym_api_client called with nym_api_urls: {}",
|
||||||
|
nym_api_urls.is_some()
|
||||||
|
);
|
||||||
|
|
||||||
|
// If API URLs are provided, use new_with_fronted_urls() which handles domain fronting
|
||||||
|
if let Some(nym_api_urls) = nym_api_urls {
|
||||||
|
if nym_api_urls.is_empty() {
|
||||||
|
tracing::warn!("Provided nym_api_urls is empty, falling back to config endpoints");
|
||||||
|
} else {
|
||||||
|
tracing::info!(
|
||||||
|
"Building nym-api client from provided URLs (with domain fronting support): {} URLs",
|
||||||
|
nym_api_urls.len()
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut builder =
|
||||||
|
nym_http_api_client::ClientBuilder::new_with_fronted_urls(nym_api_urls.clone())
|
||||||
|
.map_err(ClientCoreError::from)?
|
||||||
|
.with_retries(DEFAULT_NYM_API_RETRIES);
|
||||||
|
|
||||||
|
if let Some(user_agent) = user_agent {
|
||||||
|
builder = builder.with_user_agent(user_agent);
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder.build().map_err(ClientCoreError::from);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback to basic client for backwards compatibility
|
||||||
|
tracing::debug!("Building basic nym-api HTTP client from config endpoints");
|
||||||
|
|
||||||
let mut nym_api_urls = config.get_nym_api_endpoints();
|
let mut nym_api_urls = config.get_nym_api_endpoints();
|
||||||
|
if nym_api_urls.is_empty() {
|
||||||
|
tracing::warn!("No API endpoints configured in config, this may cause issues");
|
||||||
|
}
|
||||||
nym_api_urls.shuffle(&mut thread_rng());
|
nym_api_urls.shuffle(&mut thread_rng());
|
||||||
|
|
||||||
let mut builder = nym_http_api_client::Client::builder(nym_api_urls[0].clone())
|
// Convert config URLs to ApiUrl format for consistency
|
||||||
.map_err(ClientCoreError::from)?;
|
let api_urls: Vec<nym_network_defaults::ApiUrl> = nym_api_urls
|
||||||
|
.into_iter()
|
||||||
|
.map(|url| nym_network_defaults::ApiUrl {
|
||||||
|
url: url.to_string(),
|
||||||
|
front_hosts: None,
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
tracing::debug!("Using {} config API endpoints", api_urls.len());
|
||||||
|
|
||||||
|
let mut builder = nym_http_api_client::ClientBuilder::new_with_fronted_urls(api_urls)
|
||||||
|
.map_err(ClientCoreError::from)?
|
||||||
|
.with_retries(DEFAULT_NYM_API_RETRIES)
|
||||||
|
.with_bincode();
|
||||||
|
|
||||||
if let Some(user_agent) = user_agent {
|
if let Some(user_agent) = user_agent {
|
||||||
builder = builder.with_user_agent(user_agent);
|
builder = builder.with_user_agent(user_agent);
|
||||||
}
|
}
|
||||||
|
|
||||||
builder = builder.with_bincode();
|
|
||||||
|
|
||||||
builder.build().map_err(ClientCoreError::from)
|
builder.build().map_err(ClientCoreError::from)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -846,7 +959,12 @@ where
|
|||||||
<S::CredentialStore as CredentialStorage>::StorageError: Send + Sync + 'static,
|
<S::CredentialStore as CredentialStorage>::StorageError: Send + Sync + 'static,
|
||||||
<S::GatewaysDetailsStore as GatewaysDetailsStore>::StorageError: Sync + Send,
|
<S::GatewaysDetailsStore as GatewaysDetailsStore>::StorageError: Sync + Send,
|
||||||
{
|
{
|
||||||
info!("Starting nym client");
|
tracing::info!("Starting nym client");
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
#[cfg(target_arch = "wasm32")]
|
||||||
|
{
|
||||||
|
console_log!("Starting base Nym Client");
|
||||||
|
}
|
||||||
|
|
||||||
// derive (or load) client keys and gateway configuration
|
// derive (or load) client keys and gateway configuration
|
||||||
let init_res = Self::initialise_keys_and_gateway(
|
let init_res = Self::initialise_keys_and_gateway(
|
||||||
@@ -875,6 +993,9 @@ where
|
|||||||
// channels responsible for controlling real messages
|
// channels responsible for controlling real messages
|
||||||
let (input_sender, input_receiver) = tokio::sync::mpsc::channel::<InputMessage>(1);
|
let (input_sender, input_receiver) = tokio::sync::mpsc::channel::<InputMessage>(1);
|
||||||
|
|
||||||
|
// channels responsible for event management
|
||||||
|
let (event_sender, event_receiver) = mpsc::unbounded();
|
||||||
|
|
||||||
// channels responsible for controlling ack messages
|
// channels responsible for controlling ack messages
|
||||||
let (ack_sender, ack_receiver) = mpsc::unbounded();
|
let (ack_sender, ack_receiver) = mpsc::unbounded();
|
||||||
let shared_topology_accessor =
|
let shared_topology_accessor =
|
||||||
@@ -883,10 +1004,12 @@ where
|
|||||||
// Create a shutdown tracker for this client - either as a child of provided tracker
|
// Create a shutdown tracker for this client - either as a child of provided tracker
|
||||||
// or get one from the registry
|
// or get one from the registry
|
||||||
let shutdown_tracker = match self.shutdown {
|
let shutdown_tracker = match self.shutdown {
|
||||||
Some(parent_tracker) => parent_tracker.child_tracker(),
|
Some(parent_tracker) => parent_tracker.clone(),
|
||||||
None => nym_task::get_sdk_shutdown_tracker()?,
|
None => nym_task::create_sdk_shutdown_tracker()?,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Self::start_event_control(self.event_tx, event_receiver, &shutdown_tracker);
|
||||||
|
|
||||||
// channels responsible for dealing with reply-related fun
|
// channels responsible for dealing with reply-related fun
|
||||||
let (reply_controller_sender, reply_controller_receiver) =
|
let (reply_controller_sender, reply_controller_receiver) =
|
||||||
reply_controller::requests::new_control_channels();
|
reply_controller::requests::new_control_channels();
|
||||||
@@ -902,7 +1025,11 @@ where
|
|||||||
.dkg_query_client
|
.dkg_query_client
|
||||||
.map(|client| BandwidthController::new(credential_store, client));
|
.map(|client| BandwidthController::new(credential_store, client));
|
||||||
|
|
||||||
let nym_api_client = Self::construct_nym_api_client(&self.config, self.user_agent.clone())?;
|
let nym_api_client = Self::construct_nym_api_client(
|
||||||
|
self.nym_api_urls.as_ref(),
|
||||||
|
&self.config,
|
||||||
|
self.user_agent.clone(),
|
||||||
|
)?;
|
||||||
let key_rotation_config = Self::determine_key_rotation_state(&nym_api_client).await?;
|
let key_rotation_config = Self::determine_key_rotation_state(&nym_api_client).await?;
|
||||||
|
|
||||||
let topology_provider = Self::setup_topology_provider(
|
let topology_provider = Self::setup_topology_provider(
|
||||||
@@ -917,7 +1044,7 @@ where
|
|||||||
self.user_agent.clone(),
|
self.user_agent.clone(),
|
||||||
generate_client_stats_id(*self_address.identity()),
|
generate_client_stats_id(*self_address.identity()),
|
||||||
input_sender.clone(),
|
input_sender.clone(),
|
||||||
&shutdown_tracker.child_tracker(),
|
&shutdown_tracker.clone(),
|
||||||
);
|
);
|
||||||
|
|
||||||
// needs to be started as the first thing to block if required waiting for the gateway
|
// needs to be started as the first thing to block if required waiting for the gateway
|
||||||
@@ -927,7 +1054,7 @@ where
|
|||||||
shared_topology_accessor.clone(),
|
shared_topology_accessor.clone(),
|
||||||
self_address.gateway(),
|
self_address.gateway(),
|
||||||
self.wait_for_gateway,
|
self.wait_for_gateway,
|
||||||
&shutdown_tracker.child_tracker(),
|
&shutdown_tracker.clone(),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
@@ -947,7 +1074,7 @@ where
|
|||||||
stats_reporter.clone(),
|
stats_reporter.clone(),
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
self.connection_fd_callback,
|
self.connection_fd_callback,
|
||||||
&shutdown_tracker.child_tracker(),
|
&shutdown_tracker.clone(),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
let gateway_ws_fd = gateway_transceiver.ws_fd();
|
let gateway_ws_fd = gateway_transceiver.ws_fd();
|
||||||
@@ -955,7 +1082,7 @@ where
|
|||||||
let reply_storage = Self::setup_persistent_reply_storage(
|
let reply_storage = Self::setup_persistent_reply_storage(
|
||||||
reply_storage_backend,
|
reply_storage_backend,
|
||||||
key_rotation_config,
|
key_rotation_config,
|
||||||
&shutdown_tracker.child_tracker(),
|
&shutdown_tracker.clone(),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
@@ -966,7 +1093,7 @@ where
|
|||||||
reply_storage.key_storage(),
|
reply_storage.key_storage(),
|
||||||
reply_controller_sender.clone(),
|
reply_controller_sender.clone(),
|
||||||
stats_reporter.clone(),
|
stats_reporter.clone(),
|
||||||
&shutdown_tracker.child_tracker(),
|
&shutdown_tracker.clone(),
|
||||||
);
|
);
|
||||||
|
|
||||||
// The message_sender is the transmitter for any component generating sphinx packets
|
// The message_sender is the transmitter for any component generating sphinx packets
|
||||||
@@ -976,7 +1103,8 @@ where
|
|||||||
|
|
||||||
let (message_sender, client_request_sender) = Self::start_mix_traffic_controller(
|
let (message_sender, client_request_sender) = Self::start_mix_traffic_controller(
|
||||||
gateway_transceiver,
|
gateway_transceiver,
|
||||||
&shutdown_tracker.child_tracker(),
|
&shutdown_tracker.clone(),
|
||||||
|
EventSender(event_sender),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Channels that the websocket listener can use to signal downstream to the real traffic
|
// Channels that the websocket listener can use to signal downstream to the real traffic
|
||||||
@@ -1006,7 +1134,7 @@ where
|
|||||||
shared_lane_queue_lengths.clone(),
|
shared_lane_queue_lengths.clone(),
|
||||||
client_connection_rx,
|
client_connection_rx,
|
||||||
stats_reporter.clone(),
|
stats_reporter.clone(),
|
||||||
&shutdown_tracker.child_tracker(),
|
&shutdown_tracker.clone(),
|
||||||
);
|
);
|
||||||
|
|
||||||
if !self
|
if !self
|
||||||
@@ -1022,12 +1150,19 @@ where
|
|||||||
shared_topology_accessor.clone(),
|
shared_topology_accessor.clone(),
|
||||||
message_sender,
|
message_sender,
|
||||||
stats_reporter.clone(),
|
stats_reporter.clone(),
|
||||||
&shutdown_tracker.child_tracker(),
|
&shutdown_tracker.clone(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
debug!("Core client startup finished!");
|
tracing::debug!("Core client startup finished!");
|
||||||
debug!("The address of this client is: {self_address}");
|
tracing::debug!("The address of this client is: {self_address}");
|
||||||
|
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
#[cfg(target_arch = "wasm32")]
|
||||||
|
{
|
||||||
|
console_log!("Core client startup finished!");
|
||||||
|
console_log!("Rust::start_base: the address of this client is: {self_address}");
|
||||||
|
}
|
||||||
|
|
||||||
Ok(BaseClient {
|
Ok(BaseClient {
|
||||||
address: self_address,
|
address: self_address,
|
||||||
@@ -1036,6 +1171,7 @@ where
|
|||||||
client_input: ClientInput {
|
client_input: ClientInput {
|
||||||
connection_command_sender: client_connection_tx,
|
connection_command_sender: client_connection_tx,
|
||||||
input_sender,
|
input_sender,
|
||||||
|
client_request_sender,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
client_output: ClientOutputStatus::AwaitingConsumer {
|
client_output: ClientOutputStatus::AwaitingConsumer {
|
||||||
@@ -1051,7 +1187,6 @@ where
|
|||||||
},
|
},
|
||||||
stats_reporter,
|
stats_reporter,
|
||||||
shutdown_handle: shutdown_tracker, // The primary tracker for this client
|
shutdown_handle: shutdown_tracker, // The primary tracker for this client
|
||||||
client_request_sender,
|
|
||||||
forget_me: self.config.debug.forget_me,
|
forget_me: self.config.debug.forget_me,
|
||||||
remember_me: self.config.debug.remember_me,
|
remember_me: self.config.debug.remember_me,
|
||||||
})
|
})
|
||||||
@@ -1065,8 +1200,57 @@ pub struct BaseClient {
|
|||||||
pub client_output: ClientOutputStatus,
|
pub client_output: ClientOutputStatus,
|
||||||
pub client_state: ClientState,
|
pub client_state: ClientState,
|
||||||
pub stats_reporter: ClientStatsSender,
|
pub stats_reporter: ClientStatsSender,
|
||||||
pub client_request_sender: ClientRequestSender,
|
|
||||||
pub shutdown_handle: ShutdownTracker,
|
pub shutdown_handle: ShutdownTracker,
|
||||||
pub forget_me: ForgetMe,
|
pub forget_me: ForgetMe,
|
||||||
pub remember_me: RememberMe,
|
pub remember_me: RememberMe,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
use nym_network_defaults::{ApiUrl, NymNetworkDetails};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_network_details_with_multiple_urls() {
|
||||||
|
// Verify that network details can be configured with multiple API URLs
|
||||||
|
let mut network_details = NymNetworkDetails::new_empty();
|
||||||
|
network_details.nym_api_urls = Some(vec![
|
||||||
|
ApiUrl {
|
||||||
|
url: "https://validator.nymtech.net/api/".to_string(),
|
||||||
|
front_hosts: None,
|
||||||
|
},
|
||||||
|
ApiUrl {
|
||||||
|
url: "https://nym-frontdoor.vercel.app/api/".to_string(),
|
||||||
|
front_hosts: Some(vec!["vercel.app".to_string(), "vercel.com".to_string()]),
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
assert_eq!(network_details.nym_api_urls.as_ref().unwrap().len(), 2);
|
||||||
|
assert!(network_details.nym_api_urls.as_ref().unwrap()[1]
|
||||||
|
.front_hosts
|
||||||
|
.is_some());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_network_details_with_front_hosts() {
|
||||||
|
// Verify that ApiUrl can store domain fronting configuration
|
||||||
|
let api_url = ApiUrl {
|
||||||
|
url: "https://nym-frontdoor.vercel.app/api/".to_string(),
|
||||||
|
front_hosts: Some(vec!["vercel.app".to_string(), "vercel.com".to_string()]),
|
||||||
|
};
|
||||||
|
|
||||||
|
assert_eq!(api_url.url, "https://nym-frontdoor.vercel.app/api/");
|
||||||
|
assert_eq!(api_url.front_hosts.as_ref().unwrap().len(), 2);
|
||||||
|
assert!(api_url
|
||||||
|
.front_hosts
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.contains(&"vercel.app".to_string()));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_default_nym_api_retries_constant() {
|
||||||
|
// Verify the retry constant is set correctly
|
||||||
|
assert_eq!(DEFAULT_NYM_API_RETRIES, 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -205,7 +205,7 @@ impl LoopCoverTrafficStream<OsRng> {
|
|||||||
TrySendError::Full(_) => {
|
TrySendError::Full(_) => {
|
||||||
// This isn't a problem, if the channel is full means we're already sending the
|
// This isn't a problem, if the channel is full means we're already sending the
|
||||||
// max amount of messages downstream can handle.
|
// max amount of messages downstream can handle.
|
||||||
tracing::debug!("Failed to send cover message - channel full");
|
tracing::trace!("Failed to send cover message - channel full");
|
||||||
}
|
}
|
||||||
TrySendError::Closed(_) => {
|
TrySendError::Closed(_) => {
|
||||||
tracing::warn!("Failed to send cover message - channel closed");
|
tracing::warn!("Failed to send cover message - channel closed");
|
||||||
@@ -225,9 +225,15 @@ impl LoopCoverTrafficStream<OsRng> {
|
|||||||
// JS: due to identical logical structure to OutQueueControl::on_message(), this is also
|
// JS: due to identical logical structure to OutQueueControl::on_message(), this is also
|
||||||
// presumably required to prevent bugs in the future. Exact reason is still unknown to me.
|
// presumably required to prevent bugs in the future. Exact reason is still unknown to me.
|
||||||
|
|
||||||
// TODO: temporary and BAD workaround for wasm (we should find a way to yield here in wasm)
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
tokio::task::yield_now().await;
|
{
|
||||||
|
tokio::task::yield_now().await;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_arch = "wasm32")]
|
||||||
|
{
|
||||||
|
tokio_with_wasm::task::yield_now().await;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// it's fine if cover traffic stream task gets killed whilst processing next message
|
// it's fine if cover traffic stream task gets killed whilst processing next message
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
// Copyright 2025 - Nym Technologies SA <contact@nymtech.net>
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
use futures::StreamExt;
|
||||||
|
|
||||||
|
use crate::client::base_client::{EventReceiver, EventSender, MixnetClientEvent};
|
||||||
|
|
||||||
|
/// Launches and manages task events, propagating upwards what is not strictly internal.
|
||||||
|
pub(crate) struct EventControl {
|
||||||
|
parent_event_tx: Option<EventSender>,
|
||||||
|
children_event_rx: EventReceiver,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EventControl {
|
||||||
|
pub(crate) fn new(
|
||||||
|
parent_event_tx: Option<EventSender>,
|
||||||
|
children_event_rx: EventReceiver,
|
||||||
|
) -> Self {
|
||||||
|
EventControl {
|
||||||
|
parent_event_tx,
|
||||||
|
children_event_rx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_internal(event: MixnetClientEvent) -> bool {
|
||||||
|
match event {
|
||||||
|
MixnetClientEvent::Traffic(_) => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) async fn run(mut self) {
|
||||||
|
while let Some(event) = self.children_event_rx.next().await {
|
||||||
|
if let Some(parent_event_tx) = &self.parent_event_tx {
|
||||||
|
if !Self::is_internal(event) {
|
||||||
|
parent_event_tx.send(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,9 +2,9 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
#![allow(unused_imports)]
|
#![allow(unused_imports)]
|
||||||
|
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
|
#[cfg(target_arch = "wasm32")]
|
||||||
pub use wasmtimer::{std::Instant, tokio::*};
|
pub use wasmtimer::{std::Instant, tokio::*};
|
||||||
pub type IntervalStream = gloo_timers::future::IntervalStream;
|
pub type IntervalStream = gloo_timers::future::IntervalStream;
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
use crate::client::mix_traffic::transceiver::GatewayTransceiver;
|
use crate::client::{
|
||||||
|
base_client::{EventSender, MixnetClientEvent},
|
||||||
|
mix_traffic::transceiver::GatewayTransceiver,
|
||||||
|
};
|
||||||
use nym_gateway_requests::ClientRequest;
|
use nym_gateway_requests::ClientRequest;
|
||||||
use nym_sphinx::forwarding::packet::MixPacket;
|
use nym_sphinx::forwarding::packet::MixPacket;
|
||||||
use nym_task::ShutdownToken;
|
use nym_task::ShutdownToken;
|
||||||
@@ -17,33 +20,41 @@ pub mod transceiver;
|
|||||||
|
|
||||||
// We remind ourselves that 32 x 32kb = 1024kb, a reasonable size for a network buffer.
|
// We remind ourselves that 32 x 32kb = 1024kb, a reasonable size for a network buffer.
|
||||||
pub const MIX_MESSAGE_RECEIVER_BUFFER_SIZE: usize = 32;
|
pub const MIX_MESSAGE_RECEIVER_BUFFER_SIZE: usize = 32;
|
||||||
const MAX_FAILURE_COUNT: usize = 100;
|
|
||||||
|
/// Reduced from 100 to 20 to fail fast (~1-2 seconds instead of ~6 seconds).
|
||||||
|
/// If we can't send 20 packets in a row, the gateway is unreachable.
|
||||||
|
const MAX_FAILURE_COUNT: usize = 20;
|
||||||
|
|
||||||
// that's also disgusting.
|
// that's also disgusting.
|
||||||
pub struct Empty;
|
pub struct Empty;
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
pub enum MixTrafficEvent {
|
||||||
|
FailedSendingSphinx,
|
||||||
|
}
|
||||||
|
|
||||||
pub struct MixTrafficController {
|
pub struct MixTrafficController {
|
||||||
gateway_transceiver: Box<dyn GatewayTransceiver + Send>,
|
gateway_transceiver: Box<dyn GatewayTransceiver + Send>,
|
||||||
|
|
||||||
|
mix_tx: BatchMixMessageSender,
|
||||||
mix_rx: BatchMixMessageReceiver,
|
mix_rx: BatchMixMessageReceiver,
|
||||||
client_rx: ClientRequestReceiver,
|
client_rx: ClientRequestReceiver,
|
||||||
|
client_tx: ClientRequestSender,
|
||||||
|
|
||||||
// TODO: this is temporary work-around.
|
// TODO: this is temporary work-around.
|
||||||
// in long run `gateway_client` will be moved away from `MixTrafficController` anyway.
|
// in long run `gateway_client` will be moved away from `MixTrafficController` anyway.
|
||||||
consecutive_gateway_failure_count: usize,
|
consecutive_gateway_failure_count: usize,
|
||||||
|
|
||||||
shutdown_token: ShutdownToken,
|
shutdown_token: ShutdownToken,
|
||||||
|
event_tx: EventSender,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MixTrafficController {
|
impl MixTrafficController {
|
||||||
pub fn new<T>(
|
pub fn new<T>(
|
||||||
gateway_transceiver: T,
|
gateway_transceiver: T,
|
||||||
shutdown_token: ShutdownToken,
|
shutdown_token: ShutdownToken,
|
||||||
) -> (
|
event_tx: EventSender,
|
||||||
MixTrafficController,
|
) -> MixTrafficController
|
||||||
BatchMixMessageSender,
|
|
||||||
ClientRequestSender,
|
|
||||||
)
|
|
||||||
where
|
where
|
||||||
T: GatewayTransceiver + Send + 'static,
|
T: GatewayTransceiver + Send + 'static,
|
||||||
{
|
{
|
||||||
@@ -52,41 +63,32 @@ impl MixTrafficController {
|
|||||||
|
|
||||||
let (client_sender, client_receiver) = tokio::sync::mpsc::channel(8);
|
let (client_sender, client_receiver) = tokio::sync::mpsc::channel(8);
|
||||||
|
|
||||||
(
|
MixTrafficController {
|
||||||
MixTrafficController {
|
gateway_transceiver: Box::new(gateway_transceiver),
|
||||||
gateway_transceiver: Box::new(gateway_transceiver),
|
mix_tx: message_sender,
|
||||||
mix_rx: message_receiver,
|
mix_rx: message_receiver,
|
||||||
client_rx: client_receiver,
|
client_rx: client_receiver,
|
||||||
consecutive_gateway_failure_count: 0,
|
client_tx: client_sender,
|
||||||
shutdown_token,
|
consecutive_gateway_failure_count: 0,
|
||||||
},
|
shutdown_token,
|
||||||
message_sender,
|
event_tx,
|
||||||
client_sender,
|
}
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_dynamic(
|
pub fn new_dynamic(
|
||||||
gateway_transceiver: Box<dyn GatewayTransceiver + Send>,
|
gateway_transceiver: Box<dyn GatewayTransceiver + Send>,
|
||||||
shutdown_token: ShutdownToken,
|
shutdown_token: ShutdownToken,
|
||||||
) -> (
|
event_tx: EventSender,
|
||||||
MixTrafficController,
|
) -> MixTrafficController {
|
||||||
BatchMixMessageSender,
|
Self::new(gateway_transceiver, shutdown_token, event_tx)
|
||||||
ClientRequestSender,
|
}
|
||||||
) {
|
|
||||||
let (message_sender, message_receiver) =
|
pub fn client_tx(&self) -> ClientRequestSender {
|
||||||
tokio::sync::mpsc::channel(MIX_MESSAGE_RECEIVER_BUFFER_SIZE);
|
self.client_tx.clone()
|
||||||
let (client_sender, client_receiver) = tokio::sync::mpsc::channel(8);
|
}
|
||||||
(
|
|
||||||
MixTrafficController {
|
pub fn mix_tx(&self) -> BatchMixMessageSender {
|
||||||
gateway_transceiver,
|
self.mix_tx.clone()
|
||||||
mix_rx: message_receiver,
|
|
||||||
client_rx: client_receiver,
|
|
||||||
consecutive_gateway_failure_count: 0,
|
|
||||||
shutdown_token,
|
|
||||||
},
|
|
||||||
message_sender,
|
|
||||||
client_sender,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn on_messages(
|
async fn on_messages(
|
||||||
@@ -145,34 +147,31 @@ impl MixTrafficController {
|
|||||||
trace!("MixTrafficController: Received shutdown");
|
trace!("MixTrafficController: Received shutdown");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
mix_packets = self.mix_rx.recv() => match mix_packets {
|
// mix_rx should never error out as we're holding one instance of the sender
|
||||||
Some(mix_packets) => {
|
|
||||||
if let Err(err) = self.on_messages(mix_packets).await {
|
Some(mix_packets) = self.mix_rx.recv() => {
|
||||||
error!("Failed to send sphinx packet(s) to the gateway: {err}");
|
if let Err(err) = self.on_messages(mix_packets).await {
|
||||||
if self.consecutive_gateway_failure_count == MAX_FAILURE_COUNT {
|
error!("Failed to send sphinx packet(s) to the gateway: {err}");
|
||||||
// Disconnect from the gateway. If we should try to re-connect
|
if self.consecutive_gateway_failure_count == MAX_FAILURE_COUNT {
|
||||||
// is handled at a higher layer.
|
// Disconnect from the gateway. If we should try to re-connect
|
||||||
error!("Failed to send sphinx packet to the gateway {MAX_FAILURE_COUNT} times in a row - assuming the gateway is dead");
|
// is handled at a higher layer.
|
||||||
// Do we need to handle the embedded mixnet client case
|
error!("Failed to send sphinx packet to the gateway {MAX_FAILURE_COUNT} times in a row - assuming the gateway is dead");
|
||||||
// separately?
|
// Do we need to handle the embedded mixnet client case
|
||||||
break;
|
// separately?
|
||||||
}
|
self.event_tx.send(MixnetClientEvent::Traffic(MixTrafficEvent::FailedSendingSphinx));
|
||||||
|
// IMO it shouldn't be signalled from there but it is how it is
|
||||||
|
// TODO : report the failure upwards and shutdown from upwards
|
||||||
|
// Gateway is dead, we have to shut down currently
|
||||||
|
error!("Signalling shutdown from the MixTrafficController");
|
||||||
|
self.shutdown_token.cancel();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
},
|
|
||||||
None => {
|
|
||||||
trace!("MixTrafficController: Stopping since channel closed");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
client_request = self.client_rx.recv() => match client_request {
|
|
||||||
Some(client_request) => {
|
|
||||||
self.on_client_request(client_request).await;
|
|
||||||
},
|
|
||||||
None => {
|
|
||||||
trace!("MixTrafficController, client request channel closed");
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
// client_rx should never error out as we're holding one instance of the sender
|
||||||
|
Some(client_request) = self.client_rx.recv() => {
|
||||||
|
self.on_client_request(client_request).await;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
debug!("MixTrafficController: Exiting");
|
debug!("MixTrafficController: Exiting");
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
pub mod base_client;
|
pub mod base_client;
|
||||||
pub mod cover_traffic_stream;
|
pub mod cover_traffic_stream;
|
||||||
|
pub(crate) mod event_control;
|
||||||
pub(crate) mod helpers;
|
pub(crate) mod helpers;
|
||||||
pub mod inbound_messages;
|
pub mod inbound_messages;
|
||||||
pub mod key_manager;
|
pub mod key_manager;
|
||||||
|
|||||||
@@ -31,9 +31,9 @@ use tracing::*;
|
|||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
use tokio::time::{sleep, Sleep};
|
use tokio::time::{sleep, Sleep};
|
||||||
|
|
||||||
|
// use wasm_utils::console_log;
|
||||||
#[cfg(target_arch = "wasm32")]
|
#[cfg(target_arch = "wasm32")]
|
||||||
use wasmtimer::tokio::{sleep, Sleep};
|
use wasmtimer::tokio::{sleep, Sleep};
|
||||||
|
|
||||||
mod sending_delay_controller;
|
mod sending_delay_controller;
|
||||||
|
|
||||||
/// Configurable parameters of the `OutQueueControl`
|
/// Configurable parameters of the `OutQueueControl`
|
||||||
@@ -298,6 +298,8 @@ where
|
|||||||
"failed to send mixnet packet due to closed channel (outside of shutdown!)"
|
"failed to send mixnet packet due to closed channel (outside of shutdown!)"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
// Early return to avoid further processing when channel is closed
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
let event = if fragment_id.is_some() {
|
let event = if fragment_id.is_some() {
|
||||||
@@ -325,9 +327,15 @@ where
|
|||||||
// ready and hence was immediately re-scheduled causing other tasks to be starved;
|
// ready and hence was immediately re-scheduled causing other tasks to be starved;
|
||||||
// yield makes it go back the scheduling queue regardless of its value availability
|
// yield makes it go back the scheduling queue regardless of its value availability
|
||||||
|
|
||||||
// TODO: temporary and BAD workaround for wasm (we should find a way to yield here in wasm)
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
tokio::task::yield_now().await;
|
{
|
||||||
|
tokio::task::yield_now().await;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_arch = "wasm32")]
|
||||||
|
{
|
||||||
|
tokio_with_wasm::task::yield_now().await;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_close_connection(&mut self, connection_id: ConnectionId) {
|
fn on_close_connection(&mut self, connection_id: ConnectionId) {
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ type WsConn = JSWebsocket;
|
|||||||
|
|
||||||
const CONCURRENT_GATEWAYS_MEASURED: usize = 20;
|
const CONCURRENT_GATEWAYS_MEASURED: usize = 20;
|
||||||
const MEASUREMENTS: usize = 3;
|
const MEASUREMENTS: usize = 3;
|
||||||
|
const DEFAULT_NYM_API_RETRIES: usize = 3;
|
||||||
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
const CONN_TIMEOUT: Duration = Duration::from_millis(1500);
|
const CONN_TIMEOUT: Duration = Duration::from_millis(1500);
|
||||||
@@ -132,25 +133,27 @@ impl<'a, G: ConnectableGateway> GatewayWithLatency<'a, G> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn gateways_for_init<R: Rng>(
|
pub async fn gateways_for_init(
|
||||||
rng: &mut R,
|
|
||||||
nym_apis: &[Url],
|
nym_apis: &[Url],
|
||||||
user_agent: Option<UserAgent>,
|
user_agent: Option<UserAgent>,
|
||||||
minimum_performance: u8,
|
minimum_performance: u8,
|
||||||
ignore_epoch_roles: bool,
|
ignore_epoch_roles: bool,
|
||||||
|
retry_count: Option<usize>,
|
||||||
) -> Result<Vec<RoutingNode>, ClientCoreError> {
|
) -> Result<Vec<RoutingNode>, ClientCoreError> {
|
||||||
let nym_api = nym_apis
|
// Build client with ALL URLs for fallback support
|
||||||
.choose(rng)
|
let nym_api_urls: Vec<nym_http_api_client::Url> = nym_apis
|
||||||
.ok_or(ClientCoreError::ListOfNymApisIsEmpty)?;
|
.iter()
|
||||||
|
.map(|url| nym_http_api_client::Url::from(url.clone()))
|
||||||
|
.collect();
|
||||||
|
|
||||||
// Use the unified HTTP client directly with optional user agent
|
if nym_api_urls.is_empty() {
|
||||||
let mut builder = nym_http_api_client::Client::builder(nym_api.clone())
|
return Err(ClientCoreError::ListOfNymApisIsEmpty);
|
||||||
.map_err(|e| {
|
}
|
||||||
ClientCoreError::ValidatorClientError(nym_validator_client::ValidatorClientError::from(
|
|
||||||
e,
|
let retry_count = retry_count.unwrap_or(DEFAULT_NYM_API_RETRIES);
|
||||||
))
|
let mut builder = nym_http_api_client::ClientBuilder::new_with_urls(nym_api_urls.clone())?
|
||||||
})?
|
.with_retries(retry_count)
|
||||||
.with_bincode(); // Use bincode for better performance
|
.with_bincode();
|
||||||
|
|
||||||
if let Some(user_agent) = user_agent {
|
if let Some(user_agent) = user_agent {
|
||||||
builder = builder.with_user_agent(user_agent);
|
builder = builder.with_user_agent(user_agent);
|
||||||
@@ -160,7 +163,7 @@ pub async fn gateways_for_init<R: Rng>(
|
|||||||
ClientCoreError::ValidatorClientError(nym_validator_client::ValidatorClientError::from(e))
|
ClientCoreError::ValidatorClientError(nym_validator_client::ValidatorClientError::from(e))
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
tracing::debug!("Fetching list of gateways from: {nym_api}");
|
tracing::debug!("Fetching list of gateways from: {:?}", nym_api_urls);
|
||||||
|
|
||||||
// Use our helper to handle pagination
|
// Use our helper to handle pagination
|
||||||
let gateways = get_all_basic_entry_nodes_with_metadata(&client, true)
|
let gateways = get_all_basic_entry_nodes_with_metadata(&client, true)
|
||||||
@@ -172,17 +175,15 @@ pub async fn gateways_for_init<R: Rng>(
|
|||||||
|
|
||||||
// filter out gateways below minimum performance and ones that could operate as a mixnode
|
// filter out gateways below minimum performance and ones that could operate as a mixnode
|
||||||
// (we don't want instability)
|
// (we don't want instability)
|
||||||
let valid_gateways = gateways
|
let valid_gateways: Vec<RoutingNode> = gateways
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|g| ignore_epoch_roles || !g.supported_roles.mixnode)
|
.filter(|g| ignore_epoch_roles || !g.supported_roles.mixnode)
|
||||||
.filter(|g| g.performance.round_to_integer() >= minimum_performance)
|
.filter(|g| g.performance.round_to_integer() >= minimum_performance)
|
||||||
.filter_map(|gateway| gateway.try_into().ok())
|
.filter_map(|gateway| gateway.try_into().ok())
|
||||||
.collect::<Vec<_>>();
|
.collect();
|
||||||
tracing::debug!("After checking validity: {}", valid_gateways.len());
|
|
||||||
tracing::trace!("Valid gateways: {valid_gateways:#?}");
|
|
||||||
|
|
||||||
tracing::info!(
|
tracing::info!(
|
||||||
"and {} after validity and performance filtering",
|
"Found {} valid gateways after filtering",
|
||||||
valid_gateways.len()
|
valid_gateways.len()
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -345,13 +346,20 @@ pub(super) fn get_specified_gateway(
|
|||||||
must_use_tls: bool,
|
must_use_tls: bool,
|
||||||
) -> Result<RoutingNode, ClientCoreError> {
|
) -> Result<RoutingNode, ClientCoreError> {
|
||||||
tracing::debug!("Requesting specified gateway: {gateway_identity}");
|
tracing::debug!("Requesting specified gateway: {gateway_identity}");
|
||||||
|
|
||||||
let user_gateway = ed25519::PublicKey::from_base58_string(gateway_identity)
|
let user_gateway = ed25519::PublicKey::from_base58_string(gateway_identity)
|
||||||
.map_err(ClientCoreError::UnableToCreatePublicKeyFromGatewayId)?;
|
.map_err(ClientCoreError::UnableToCreatePublicKeyFromGatewayId)?;
|
||||||
|
|
||||||
let gateway = gateways
|
let gateway = gateways
|
||||||
.iter()
|
.iter()
|
||||||
.find(|gateway| gateway.identity_key == user_gateway)
|
.find(|gateway| gateway.identity_key == user_gateway)
|
||||||
.ok_or_else(|| ClientCoreError::NoGatewayWithId(gateway_identity.to_string()))?;
|
.ok_or_else(|| {
|
||||||
|
tracing::debug!(
|
||||||
|
"Gateway {gateway_identity} not found in {} available gateways",
|
||||||
|
gateways.len()
|
||||||
|
);
|
||||||
|
ClientCoreError::NoGatewayWithId(gateway_identity.to_string())
|
||||||
|
})?;
|
||||||
|
|
||||||
let Some(entry_details) = gateway.entry.as_ref() else {
|
let Some(entry_details) = gateway.entry.as_ref() else {
|
||||||
return Err(ClientCoreError::UnsupportedEntry {
|
return Err(ClientCoreError::UnsupportedEntry {
|
||||||
@@ -414,3 +422,52 @@ pub(super) async fn register_with_gateway(
|
|||||||
authenticated_ephemeral_client: gateway_client,
|
authenticated_ephemeral_client: gateway_client,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use url::Url;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_single_url_builds_without_retries() {
|
||||||
|
let urls = [Url::parse("https://api.nym.com").unwrap()];
|
||||||
|
|
||||||
|
let nym_api_urls: Vec<nym_http_api_client::Url> = urls
|
||||||
|
.iter()
|
||||||
|
.map(|url| nym_http_api_client::Url::from(url.clone()))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
assert_eq!(nym_api_urls.len(), 1, "Should have exactly one URL");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_multiple_urls_prepared_for_retries() {
|
||||||
|
let urls = vec![
|
||||||
|
Url::parse("https://api1.nym.com").unwrap(),
|
||||||
|
Url::parse("https://api2.nym.com").unwrap(),
|
||||||
|
Url::parse("https://api3.nym.com").unwrap(),
|
||||||
|
];
|
||||||
|
|
||||||
|
let nym_api_urls: Vec<nym_http_api_client::Url> = urls
|
||||||
|
.iter()
|
||||||
|
.map(|url| nym_http_api_client::Url::from(url.clone()))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
assert_eq!(nym_api_urls.len(), 3, "Should have all three URLs");
|
||||||
|
assert!(
|
||||||
|
nym_api_urls.len() > 1,
|
||||||
|
"Multiple URLs trigger retry behavior"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_empty_url_list_is_detected() {
|
||||||
|
let urls: Vec<Url> = vec![];
|
||||||
|
|
||||||
|
let nym_api_urls: Vec<nym_http_api_client::Url> = urls
|
||||||
|
.iter()
|
||||||
|
.map(|url| nym_http_api_client::Url::from(url.clone()))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
assert!(nym_api_urls.is_empty(), "Empty list should remain empty");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -24,7 +24,9 @@ pub fn spawn_future<F>(future: F)
|
|||||||
where
|
where
|
||||||
F: Future<Output = ()> + 'static,
|
F: Future<Output = ()> + 'static,
|
||||||
{
|
{
|
||||||
wasm_bindgen_futures::spawn_local(future);
|
wasm_bindgen_futures::spawn_local(async move {
|
||||||
|
future.await;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
#[deprecated(note = "use spawn_future from nym_task crate instead")]
|
#[deprecated(note = "use spawn_future from nym_task crate instead")]
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ name = "nym-validator-client"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
authors = ["Jędrzej Stuczyński <andrew@nymtech.net>"]
|
authors = ["Jędrzej Stuczyński <andrew@nymtech.net>"]
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
rust-version = "1.56"
|
rust-version = "1.85"
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ use cosmrs::tx;
|
|||||||
use cosmrs::tx::SignDoc;
|
use cosmrs::tx::SignDoc;
|
||||||
use nym_config::defaults;
|
use nym_config::defaults;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use zeroize::{Zeroize, ZeroizeOnDrop};
|
use zeroize::{Zeroize, ZeroizeOnDrop, Zeroizing};
|
||||||
|
|
||||||
type Secp256k1Keypair = (SigningKey, PublicKey);
|
type Secp256k1Keypair = (SigningKey, PublicKey);
|
||||||
|
|
||||||
@@ -128,9 +128,20 @@ impl DirectSecp256k1HdWallet {
|
|||||||
Ok(accounts)
|
Ok(accounts)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn secret(&self) -> &bip39::Mnemonic {
|
||||||
|
&self.secret
|
||||||
|
}
|
||||||
|
|
||||||
|
#[deprecated(
|
||||||
|
note = "use either .secret() for obtaining &bip39::Mnemonic or .mnemonic_string() for Zeroizing wrapper around the String"
|
||||||
|
)]
|
||||||
pub fn mnemonic(&self) -> String {
|
pub fn mnemonic(&self) -> String {
|
||||||
self.secret.to_string()
|
self.secret.to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn mnemonic_string(&self) -> Zeroizing<String> {
|
||||||
|
Zeroizing::new(self.secret.to_string())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
|
|||||||
@@ -18,6 +18,6 @@ pub fn create_account(args: Args, prefix: &str) {
|
|||||||
let wallet = DirectSecp256k1HdWallet::from_mnemonic(prefix, mnemonic);
|
let wallet = DirectSecp256k1HdWallet::from_mnemonic(prefix, mnemonic);
|
||||||
|
|
||||||
// Output address and mnemonics into separate lines for easier parsing
|
// Output address and mnemonics into separate lines for easier parsing
|
||||||
println!("{}", wallet.mnemonic());
|
println!("{}", wallet.mnemonic_string().as_str());
|
||||||
println!("{}", wallet.try_derive_accounts().unwrap()[0].address());
|
println!("{}", wallet.try_derive_accounts().unwrap()[0].address());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
// Copyright 2025 - Nym Technologies SA <contact@nymtech.net>
|
// Copyright 2025 - Nym Technologies SA <contact@nymtech.net>
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
use cosmwasm_std::testing::{message_info, MockApi, MockQuerier, MockStorage};
|
use cosmwasm_std::testing::{MockApi, MockQuerier, MockStorage, message_info};
|
||||||
use cosmwasm_std::{
|
use cosmwasm_std::{
|
||||||
coins, Addr, BankMsg, CosmosMsg, Decimal, Empty, Env, MemoryStorage, MessageInfo, Order,
|
Addr, BankMsg, CosmosMsg, Decimal, Empty, Env, MemoryStorage, MessageInfo, Order, OwnedDeps,
|
||||||
OwnedDeps, Response, StdResult, Storage,
|
Response, StdResult, Storage, coins,
|
||||||
};
|
};
|
||||||
use cw_storage_plus::{KeyDeserialize, Map, Prefix, PrimaryKey};
|
use cw_storage_plus::{KeyDeserialize, Map, Prefix, PrimaryKey};
|
||||||
use nym_contracts_common::events::may_find_attribute;
|
use nym_contracts_common::events::may_find_attribute;
|
||||||
use rand::{RngCore, SeedableRng};
|
use rand::{RngCore, SeedableRng};
|
||||||
use rand_chacha::ChaCha20Rng;
|
use rand_chacha::ChaCha20Rng;
|
||||||
use serde::de::DeserializeOwned;
|
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
use serde::de::DeserializeOwned;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
|||||||
@@ -4,12 +4,12 @@
|
|||||||
use crate::{ContractTester, TestableNymContract};
|
use crate::{ContractTester, TestableNymContract};
|
||||||
use cosmwasm_std::testing::{message_info, mock_env};
|
use cosmwasm_std::testing::{message_info, mock_env};
|
||||||
use cosmwasm_std::{
|
use cosmwasm_std::{
|
||||||
from_json, Addr, BlockInfo, Coin, ContractInfo, Deps, DepsMut, Env, MessageInfo, Response,
|
Addr, BlockInfo, Coin, ContractInfo, Deps, DepsMut, Env, MessageInfo, Response, StdResult,
|
||||||
StdResult, Storage, Timestamp,
|
Storage, Timestamp, from_json,
|
||||||
};
|
};
|
||||||
use cw_multi_test::{next_block, AppResponse, Executor};
|
use cw_multi_test::{AppResponse, Executor, next_block};
|
||||||
use serde::de::DeserializeOwned;
|
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
use serde::de::DeserializeOwned;
|
||||||
use std::any::type_name;
|
use std::any::type_name;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
|
|
||||||
|
|||||||
@@ -2,18 +2,18 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
CommonStorageKeys, ContractOpts, ContractTester, StorageWrapper, TestableNymContract,
|
CommonStorageKeys, ContractOpts, ContractTester, StorageWrapper, TEST_DENOM,
|
||||||
TEST_DENOM,
|
TestableNymContract,
|
||||||
};
|
};
|
||||||
use cosmwasm_std::testing::message_info;
|
use cosmwasm_std::testing::message_info;
|
||||||
use cosmwasm_std::{
|
use cosmwasm_std::{
|
||||||
coin, coins, from_json, to_json_vec, Addr, Coin, MessageInfo, StdError, StdResult, Storage,
|
Addr, Coin, MessageInfo, StdError, StdResult, Storage, coin, coins, from_json, to_json_vec,
|
||||||
};
|
};
|
||||||
use cw_multi_test::Executor;
|
use cw_multi_test::Executor;
|
||||||
use cw_storage_plus::{Key, Path, PrimaryKey};
|
use cw_storage_plus::{Key, Path, PrimaryKey};
|
||||||
use rand_chacha::ChaCha20Rng;
|
use rand_chacha::ChaCha20Rng;
|
||||||
use serde::de::DeserializeOwned;
|
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
use serde::de::DeserializeOwned;
|
||||||
use std::any::type_name;
|
use std::any::type_name;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
// Copyright 2025 - Nym Technologies SA <contact@nymtech.net>
|
// Copyright 2025 - Nym Technologies SA <contact@nymtech.net>
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
use crate::{mock_api, test_rng, TEST_DENOM};
|
use crate::{TEST_DENOM, mock_api, test_rng};
|
||||||
use cosmwasm_std::testing::MockApi;
|
use cosmwasm_std::testing::MockApi;
|
||||||
use cosmwasm_std::{
|
use cosmwasm_std::{
|
||||||
coin, coins, Addr, Binary, Deps, DepsMut, Empty, Env, MessageInfo, Order, QuerierWrapper,
|
Addr, Binary, Deps, DepsMut, Empty, Env, MessageInfo, Order, QuerierWrapper, Record, Response,
|
||||||
Record, Response, Storage,
|
Storage, coin, coins,
|
||||||
};
|
};
|
||||||
use cw_multi_test::{App, AppBuilder, BankKeeper, Contract, ContractWrapper, Executor};
|
use cw_multi_test::{App, AppBuilder, BankKeeper, Contract, ContractWrapper, Executor};
|
||||||
use rand_chacha::ChaCha20Rng;
|
use rand_chacha::ChaCha20Rng;
|
||||||
use serde::de::DeserializeOwned;
|
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
use serde::de::DeserializeOwned;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::fmt::{Debug, Display};
|
use std::fmt::{Debug, Display};
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
// Copyright 2025 - Nym Technologies SA <contact@nymtech.net>
|
// Copyright 2025 - Nym Technologies SA <contact@nymtech.net>
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
use cosmwasm_std::{from_json, Binary, CustomQuery, QuerierWrapper, StdResult};
|
use cosmwasm_std::{Binary, CustomQuery, QuerierWrapper, StdResult, from_json};
|
||||||
use serde::de::DeserializeOwned;
|
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
use serde::de::DeserializeOwned;
|
||||||
|
|
||||||
// re-expose methods from QuerierWrapper as traits so that we could more easily define extension traits
|
// re-expose methods from QuerierWrapper as traits so that we could more easily define extension traits
|
||||||
pub trait ContractQuerier {
|
pub trait ContractQuerier {
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
use cosmwasm_std::{from_json, to_json_vec, Addr, Coin, MessageInfo, StdResult};
|
use cosmwasm_std::{Addr, Coin, MessageInfo, StdResult, from_json, to_json_vec};
|
||||||
use schemars::JsonSchema;
|
use schemars::JsonSchema;
|
||||||
use serde::de::DeserializeOwned;
|
use serde::de::DeserializeOwned;
|
||||||
use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
|
use serde::{Deserialize, Deserializer, Serialize, Serializer, de};
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
pub use verifier::Verifier;
|
pub use verifier::Verifier;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
name = "nym-mixnet-contract-common"
|
name = "nym-mixnet-contract-common"
|
||||||
version = "0.6.0"
|
version = "0.6.0"
|
||||||
description = "Common library for the Nym mixnet contract"
|
description = "Common library for the Nym mixnet contract"
|
||||||
rust-version = "1.62"
|
rust-version = "1.85"
|
||||||
edition = { workspace = true }
|
edition = { workspace = true }
|
||||||
authors = { workspace = true }
|
authors = { workspace = true }
|
||||||
license = { workspace = true }
|
license = { workspace = true }
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ use crate::nym_node::Role;
|
|||||||
use crate::{
|
use crate::{
|
||||||
EpochEventId, EpochState, IntervalEventId, NodeId, OperatingCostRange, ProfitMarginRange,
|
EpochEventId, EpochState, IntervalEventId, NodeId, OperatingCostRange, ProfitMarginRange,
|
||||||
};
|
};
|
||||||
use contracts_common::signing::verifier::ApiVerifierError;
|
|
||||||
use contracts_common::Percent;
|
use contracts_common::Percent;
|
||||||
|
use contracts_common::signing::verifier::ApiVerifierError;
|
||||||
use cosmwasm_std::{Addr, Coin, Decimal, Uint128};
|
use cosmwasm_std::{Addr, Coin, Decimal, Uint128};
|
||||||
use cw_controllers::AdminError;
|
use cw_controllers::AdminError;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
@@ -47,7 +47,9 @@ pub enum MixnetContractError {
|
|||||||
)]
|
)]
|
||||||
InvalidPubKey,
|
InvalidPubKey,
|
||||||
|
|
||||||
#[error("Attempted to reduce node pledge ({current}{denom} - {decrease_by}{denom}) below the minimum amount: {minimum}{denom}")]
|
#[error(
|
||||||
|
"Attempted to reduce node pledge ({current}{denom} - {decrease_by}{denom}) below the minimum amount: {minimum}{denom}"
|
||||||
|
)]
|
||||||
InvalidPledgeReduction {
|
InvalidPledgeReduction {
|
||||||
current: Uint128,
|
current: Uint128,
|
||||||
decrease_by: Uint128,
|
decrease_by: Uint128,
|
||||||
@@ -123,7 +125,9 @@ pub enum MixnetContractError {
|
|||||||
#[error("Provided ed25519 signature did not verify correctly")]
|
#[error("Provided ed25519 signature did not verify correctly")]
|
||||||
InvalidEd25519Signature,
|
InvalidEd25519Signature,
|
||||||
|
|
||||||
#[error("Can't perform the specified action as the current epoch is still progress. It started at {epoch_start} and finishes at {epoch_end}, while the current block time is {current_block_time}")]
|
#[error(
|
||||||
|
"Can't perform the specified action as the current epoch is still progress. It started at {epoch_start} and finishes at {epoch_end}, while the current block time is {current_block_time}"
|
||||||
|
)]
|
||||||
EpochInProgress {
|
EpochInProgress {
|
||||||
current_block_time: u64,
|
current_block_time: u64,
|
||||||
epoch_start: i64,
|
epoch_start: i64,
|
||||||
@@ -133,7 +137,9 @@ pub enum MixnetContractError {
|
|||||||
#[error("attempted to reward a gateway node - this has not been fully integrated yet")]
|
#[error("attempted to reward a gateway node - this has not been fully integrated yet")]
|
||||||
GatewayRewarding,
|
GatewayRewarding,
|
||||||
|
|
||||||
#[error("node {node_id} has already been rewarded during the current rewarding epoch ({absolute_epoch_id})")]
|
#[error(
|
||||||
|
"node {node_id} has already been rewarded during the current rewarding epoch ({absolute_epoch_id})"
|
||||||
|
)]
|
||||||
NodeAlreadyRewarded {
|
NodeAlreadyRewarded {
|
||||||
node_id: NodeId,
|
node_id: NodeId,
|
||||||
absolute_epoch_id: u32,
|
absolute_epoch_id: u32,
|
||||||
@@ -172,7 +178,9 @@ pub enum MixnetContractError {
|
|||||||
#[error("one of the roles in the new active set is empty")]
|
#[error("one of the roles in the new active set is empty")]
|
||||||
EmptyRoleAssignment,
|
EmptyRoleAssignment,
|
||||||
|
|
||||||
#[error("the number of mixnodes in the rewarded set is not divisible by the number of mix-layers (3)")]
|
#[error(
|
||||||
|
"the number of mixnodes in the rewarded set is not divisible by the number of mix-layers (3)"
|
||||||
|
)]
|
||||||
UnevenLayerAssignment,
|
UnevenLayerAssignment,
|
||||||
|
|
||||||
#[error("provided active set is bigger than the rewarded set")]
|
#[error("provided active set is bigger than the rewarded set")]
|
||||||
@@ -196,25 +204,35 @@ pub enum MixnetContractError {
|
|||||||
#[error("key rotation validity below minimum value")]
|
#[error("key rotation validity below minimum value")]
|
||||||
TooShortRotationInterval,
|
TooShortRotationInterval,
|
||||||
|
|
||||||
#[error("this validator ({current_validator}) is not the one responsible for advancing this epoch. It's responsibility of {chosen_validator}.")]
|
#[error(
|
||||||
|
"this validator ({current_validator}) is not the one responsible for advancing this epoch. It's responsibility of {chosen_validator}."
|
||||||
|
)]
|
||||||
RewardingValidatorMismatch {
|
RewardingValidatorMismatch {
|
||||||
current_validator: Addr,
|
current_validator: Addr,
|
||||||
chosen_validator: Addr,
|
chosen_validator: Addr,
|
||||||
},
|
},
|
||||||
|
|
||||||
#[error("the epoch is currently in the process of being advanced. (the state is {current_state}) Please try sending your transaction again once this has finished")]
|
#[error(
|
||||||
|
"the epoch is currently in the process of being advanced. (the state is {current_state}) Please try sending your transaction again once this has finished"
|
||||||
|
)]
|
||||||
EpochAdvancementInProgress { current_state: EpochState },
|
EpochAdvancementInProgress { current_state: EpochState },
|
||||||
|
|
||||||
#[error("the epoch is in an unexpected state. expected 'mix rewarding' state, but we're in {current_state} instead.")]
|
#[error(
|
||||||
|
"the epoch is in an unexpected state. expected 'mix rewarding' state, but we're in {current_state} instead."
|
||||||
|
)]
|
||||||
UnexpectedNonRewardingEpochState { current_state: EpochState },
|
UnexpectedNonRewardingEpochState { current_state: EpochState },
|
||||||
|
|
||||||
#[error("attempted to reward mixnode out of order. Attempted to reward {attempted_to_reward} while last rewarded was {last_rewarded}.")]
|
#[error(
|
||||||
|
"attempted to reward mixnode out of order. Attempted to reward {attempted_to_reward} while last rewarded was {last_rewarded}."
|
||||||
|
)]
|
||||||
RewardingOutOfOrder {
|
RewardingOutOfOrder {
|
||||||
last_rewarded: NodeId,
|
last_rewarded: NodeId,
|
||||||
attempted_to_reward: NodeId,
|
attempted_to_reward: NodeId,
|
||||||
},
|
},
|
||||||
|
|
||||||
#[error("the epoch is currently not in the 'event reconciliation' state. (the state is {current_state})")]
|
#[error(
|
||||||
|
"the epoch is currently not in the 'event reconciliation' state. (the state is {current_state})"
|
||||||
|
)]
|
||||||
EpochNotInEventReconciliationState { current_state: EpochState },
|
EpochNotInEventReconciliationState { current_state: EpochState },
|
||||||
|
|
||||||
#[error(
|
#[error(
|
||||||
@@ -225,14 +243,18 @@ pub enum MixnetContractError {
|
|||||||
#[error("unexpected role assignment. got: {got} while expected: {expected}")]
|
#[error("unexpected role assignment. got: {got} while expected: {expected}")]
|
||||||
UnexpectedRoleAssignment { expected: Role, got: Role },
|
UnexpectedRoleAssignment { expected: Role, got: Role },
|
||||||
|
|
||||||
#[error("attempted to assign an invalid number of nodes for a role of {role}. got {assigned}, but the maximum allowed is {allowed}")]
|
#[error(
|
||||||
|
"attempted to assign an invalid number of nodes for a role of {role}. got {assigned}, but the maximum allowed is {allowed}"
|
||||||
|
)]
|
||||||
IllegalRoleCount {
|
IllegalRoleCount {
|
||||||
role: Role,
|
role: Role,
|
||||||
assigned: u32,
|
assigned: u32,
|
||||||
allowed: u32,
|
allowed: u32,
|
||||||
},
|
},
|
||||||
|
|
||||||
#[error("the epoch is currently not in the 'epoch advancement' state. (the state is {current_state})")]
|
#[error(
|
||||||
|
"the epoch is currently not in the 'epoch advancement' state. (the state is {current_state})"
|
||||||
|
)]
|
||||||
EpochNotInAdvancementState { current_state: EpochState },
|
EpochNotInAdvancementState { current_state: EpochState },
|
||||||
|
|
||||||
#[error("failed to verify message signature: {source}")]
|
#[error("failed to verify message signature: {source}")]
|
||||||
@@ -241,7 +263,9 @@ pub enum MixnetContractError {
|
|||||||
source: ApiVerifierError,
|
source: ApiVerifierError,
|
||||||
},
|
},
|
||||||
|
|
||||||
#[error("this operation is no longer allowed to be performed with vesting tokens. please move them to your liquid balance and try again")]
|
#[error(
|
||||||
|
"this operation is no longer allowed to be performed with vesting tokens. please move them to your liquid balance and try again"
|
||||||
|
)]
|
||||||
DisabledVestingOperation,
|
DisabledVestingOperation,
|
||||||
|
|
||||||
#[error(
|
#[error(
|
||||||
@@ -249,7 +273,9 @@ pub enum MixnetContractError {
|
|||||||
)]
|
)]
|
||||||
NotAVestingMixnode,
|
NotAVestingMixnode,
|
||||||
|
|
||||||
#[error("this delegation has not been performed with the vesting tokens or has already been migrated")]
|
#[error(
|
||||||
|
"this delegation has not been performed with the vesting tokens or has already been migrated"
|
||||||
|
)]
|
||||||
NotAVestingDelegation,
|
NotAVestingDelegation,
|
||||||
|
|
||||||
#[error("the provided profit margin ({provided}) is outside the allowed range: {range}")]
|
#[error("the provided profit margin ({provided}) is outside the allowed range: {range}")]
|
||||||
@@ -258,7 +284,9 @@ pub enum MixnetContractError {
|
|||||||
range: ProfitMarginRange,
|
range: ProfitMarginRange,
|
||||||
},
|
},
|
||||||
|
|
||||||
#[error("the provided interval operating cost ({provided}{denom}) is outside the allowed range: {range}")]
|
#[error(
|
||||||
|
"the provided interval operating cost ({provided}{denom}) is outside the allowed range: {range}"
|
||||||
|
)]
|
||||||
OperatingCostOutsideRange {
|
OperatingCostOutsideRange {
|
||||||
denom: String,
|
denom: String,
|
||||||
provided: Uint128,
|
provided: Uint128,
|
||||||
@@ -279,7 +307,9 @@ pub enum MixnetContractError {
|
|||||||
#[error("the provided nym-node version is not a valid semver. got: {provided}")]
|
#[error("the provided nym-node version is not a valid semver. got: {provided}")]
|
||||||
InvalidNymNodeSemver { provided: String },
|
InvalidNymNodeSemver { provided: String },
|
||||||
|
|
||||||
#[error("the provided nym-node version is not greater than the current one. got: {provided}. current: {current}")]
|
#[error(
|
||||||
|
"the provided nym-node version is not greater than the current one. got: {provided}. current: {current}"
|
||||||
|
)]
|
||||||
NonIncreasingSemver { provided: String, current: String },
|
NonIncreasingSemver { provided: String, current: String },
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ use crate::reward_params::{ActiveSetUpdate, IntervalRewardParams, IntervalReward
|
|||||||
use crate::rewarding::RewardDistribution;
|
use crate::rewarding::RewardDistribution;
|
||||||
use crate::{BlockHeight, ContractStateParamsUpdate, EpochId, IdentityKeyRef, Interval, NodeId};
|
use crate::{BlockHeight, ContractStateParamsUpdate, EpochId, IdentityKeyRef, Interval, NodeId};
|
||||||
pub use contracts_common::events::*;
|
pub use contracts_common::events::*;
|
||||||
use cosmwasm_std::{attr, Addr, Coin, Decimal, Event};
|
use cosmwasm_std::{Addr, Coin, Decimal, Event, attr};
|
||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
|
|
||||||
pub const EVENT_VERSION_PREFIX: &str = "v2_";
|
pub const EVENT_VERSION_PREFIX: &str = "v2_";
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
use crate::{IdentityKey, NodeId, SphinxKey};
|
use crate::{IdentityKey, NodeId, SphinxKey};
|
||||||
use cosmwasm_schema::cw_serde;
|
use cosmwasm_schema::cw_serde;
|
||||||
use cosmwasm_std::{to_json_string, Addr, Coin};
|
use cosmwasm_std::{Addr, Coin, to_json_string};
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
use crate::NodeId;
|
||||||
use crate::error::MixnetContractError;
|
use crate::error::MixnetContractError;
|
||||||
use crate::nym_node::Role;
|
use crate::nym_node::Role;
|
||||||
use crate::NodeId;
|
|
||||||
use cosmwasm_schema::cw_serde;
|
use cosmwasm_schema::cw_serde;
|
||||||
use cosmwasm_schema::schemars::gen::SchemaGenerator;
|
|
||||||
use cosmwasm_schema::schemars::schema::{InstanceType, Schema, SchemaObject};
|
|
||||||
use cosmwasm_schema::schemars::JsonSchema;
|
use cosmwasm_schema::schemars::JsonSchema;
|
||||||
|
use cosmwasm_schema::schemars::r#gen::SchemaGenerator;
|
||||||
|
use cosmwasm_schema::schemars::schema::{InstanceType, Schema, SchemaObject};
|
||||||
use cosmwasm_std::{Addr, Env};
|
use cosmwasm_std::{Addr, Env};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter};
|
||||||
@@ -27,8 +27,8 @@ pub(crate) mod string_rfc3339_offset_date_time {
|
|||||||
use serde::ser::Error;
|
use serde::ser::Error;
|
||||||
use serde::{Deserializer, Serialize, Serializer};
|
use serde::{Deserializer, Serialize, Serializer};
|
||||||
use std::fmt::Formatter;
|
use std::fmt::Formatter;
|
||||||
use time::format_description::well_known::Rfc3339;
|
|
||||||
use time::OffsetDateTime;
|
use time::OffsetDateTime;
|
||||||
|
use time::format_description::well_known::Rfc3339;
|
||||||
|
|
||||||
struct Rfc3339OffsetDateTimeVisitor;
|
struct Rfc3339OffsetDateTimeVisitor;
|
||||||
|
|
||||||
@@ -91,7 +91,7 @@ impl EpochStatus {
|
|||||||
) -> Result<bool, MixnetContractError> {
|
) -> Result<bool, MixnetContractError> {
|
||||||
match &mut self.state {
|
match &mut self.state {
|
||||||
EpochState::Rewarding {
|
EpochState::Rewarding {
|
||||||
ref mut last_rewarded,
|
last_rewarded,
|
||||||
final_node_id,
|
final_node_id,
|
||||||
} => {
|
} => {
|
||||||
if new_last_rewarded <= *last_rewarded {
|
if new_last_rewarded <= *last_rewarded {
|
||||||
@@ -254,7 +254,7 @@ impl JsonSchema for Interval {
|
|||||||
"Interval".to_owned()
|
"Interval".to_owned()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn json_schema(gen: &mut SchemaGenerator) -> Schema {
|
fn json_schema(r#gen: &mut SchemaGenerator) -> Schema {
|
||||||
let mut schema_object = SchemaObject {
|
let mut schema_object = SchemaObject {
|
||||||
instance_type: Some(InstanceType::Object.into()),
|
instance_type: Some(InstanceType::Object.into()),
|
||||||
..SchemaObject::default()
|
..SchemaObject::default()
|
||||||
@@ -263,12 +263,13 @@ impl JsonSchema for Interval {
|
|||||||
let object_validation = schema_object.object();
|
let object_validation = schema_object.object();
|
||||||
object_validation
|
object_validation
|
||||||
.properties
|
.properties
|
||||||
.insert("id".to_owned(), gen.subschema_for::<IntervalId>());
|
.insert("id".to_owned(), r#gen.subschema_for::<IntervalId>());
|
||||||
object_validation.required.insert("id".to_owned());
|
object_validation.required.insert("id".to_owned());
|
||||||
|
|
||||||
object_validation
|
object_validation.properties.insert(
|
||||||
.properties
|
"epochs_in_interval".to_owned(),
|
||||||
.insert("epochs_in_interval".to_owned(), gen.subschema_for::<u32>());
|
r#gen.subschema_for::<u32>(),
|
||||||
|
);
|
||||||
object_validation
|
object_validation
|
||||||
.required
|
.required
|
||||||
.insert("epochs_in_interval".to_owned());
|
.insert("epochs_in_interval".to_owned());
|
||||||
@@ -277,7 +278,7 @@ impl JsonSchema for Interval {
|
|||||||
// serialization to string, so we just specify the schema to be String.
|
// serialization to string, so we just specify the schema to be String.
|
||||||
object_validation.properties.insert(
|
object_validation.properties.insert(
|
||||||
"current_epoch_start".to_owned(),
|
"current_epoch_start".to_owned(),
|
||||||
gen.subschema_for::<String>(),
|
r#gen.subschema_for::<String>(),
|
||||||
);
|
);
|
||||||
object_validation
|
object_validation
|
||||||
.required
|
.required
|
||||||
@@ -285,7 +286,7 @@ impl JsonSchema for Interval {
|
|||||||
|
|
||||||
object_validation.properties.insert(
|
object_validation.properties.insert(
|
||||||
"current_epoch_id".to_owned(),
|
"current_epoch_id".to_owned(),
|
||||||
gen.subschema_for::<EpochId>(),
|
r#gen.subschema_for::<EpochId>(),
|
||||||
);
|
);
|
||||||
object_validation
|
object_validation
|
||||||
.required
|
.required
|
||||||
@@ -293,12 +294,12 @@ impl JsonSchema for Interval {
|
|||||||
|
|
||||||
object_validation
|
object_validation
|
||||||
.properties
|
.properties
|
||||||
.insert("epoch_length".to_owned(), gen.subschema_for::<Duration>());
|
.insert("epoch_length".to_owned(), r#gen.subschema_for::<Duration>());
|
||||||
object_validation.required.insert("epoch_length".to_owned());
|
object_validation.required.insert("epoch_length".to_owned());
|
||||||
|
|
||||||
object_validation.properties.insert(
|
object_validation.properties.insert(
|
||||||
"total_elapsed_epochs".to_owned(),
|
"total_elapsed_epochs".to_owned(),
|
||||||
gen.subschema_for::<EpochId>(),
|
r#gen.subschema_for::<EpochId>(),
|
||||||
);
|
);
|
||||||
object_validation
|
object_validation
|
||||||
.required
|
.required
|
||||||
|
|||||||
@@ -9,14 +9,14 @@ use crate::error::MixnetContractError;
|
|||||||
use crate::helpers::IntoBaseDecimal;
|
use crate::helpers::IntoBaseDecimal;
|
||||||
use crate::nym_node::Role;
|
use crate::nym_node::Role;
|
||||||
use crate::reward_params::{NodeRewardingParameters, RewardingParams};
|
use crate::reward_params::{NodeRewardingParameters, RewardingParams};
|
||||||
use crate::rewarding::helpers::truncate_reward;
|
|
||||||
use crate::rewarding::RewardDistribution;
|
use crate::rewarding::RewardDistribution;
|
||||||
|
use crate::rewarding::helpers::truncate_reward;
|
||||||
use crate::{
|
use crate::{
|
||||||
Delegation, EpochEventId, EpochId, IdentityKey, IntervalEventId, NodeId, OperatingCostRange,
|
Delegation, EpochEventId, EpochId, IdentityKey, IntervalEventId, NodeId, OperatingCostRange,
|
||||||
Percent, ProfitMarginRange, SphinxKey,
|
Percent, ProfitMarginRange, SphinxKey,
|
||||||
};
|
};
|
||||||
use cosmwasm_schema::cw_serde;
|
use cosmwasm_schema::cw_serde;
|
||||||
use cosmwasm_std::{to_json_string, Addr, Coin, Decimal, StdResult, Uint128};
|
use cosmwasm_std::{Addr, Coin, Decimal, StdResult, Uint128, to_json_string};
|
||||||
use schemars::JsonSchema;
|
use schemars::JsonSchema;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_repr::{Deserialize_repr, Serialize_repr};
|
use serde_repr::{Deserialize_repr, Serialize_repr};
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ use crate::{
|
|||||||
VersionScoreFormulaParams,
|
VersionScoreFormulaParams,
|
||||||
};
|
};
|
||||||
use crate::{OperatingCostRange, ProfitMarginRange};
|
use crate::{OperatingCostRange, ProfitMarginRange};
|
||||||
use contracts_common::{signing::MessageSignature, IdentityKey, Percent};
|
use contracts_common::{IdentityKey, Percent, signing::MessageSignature};
|
||||||
use cosmwasm_schema::cw_serde;
|
use cosmwasm_schema::cw_serde;
|
||||||
use cosmwasm_std::{Coin, Decimal};
|
use cosmwasm_std::{Coin, Decimal};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
@@ -55,7 +55,7 @@ use crate::{
|
|||||||
types::{ContractState, ContractStateParams},
|
types::{ContractState, ContractStateParams},
|
||||||
};
|
};
|
||||||
#[cfg(feature = "schema")]
|
#[cfg(feature = "schema")]
|
||||||
use contracts_common::{signing::Nonce, ContractBuildInformation};
|
use contracts_common::{ContractBuildInformation, signing::Nonce};
|
||||||
#[cfg(feature = "schema")]
|
#[cfg(feature = "schema")]
|
||||||
use cosmwasm_schema::QueryResponses;
|
use cosmwasm_schema::QueryResponses;
|
||||||
|
|
||||||
|
|||||||
@@ -3,9 +3,9 @@
|
|||||||
|
|
||||||
use crate::helpers::IntoBaseDecimal;
|
use crate::helpers::IntoBaseDecimal;
|
||||||
use crate::nym_node::Role;
|
use crate::nym_node::Role;
|
||||||
use crate::{error::MixnetContractError, Percent};
|
use crate::{Percent, error::MixnetContractError};
|
||||||
use cosmwasm_schema::cw_serde;
|
use cosmwasm_schema::cw_serde;
|
||||||
use cosmwasm_std::{to_json_string, Decimal};
|
use cosmwasm_std::{Decimal, to_json_string};
|
||||||
|
|
||||||
pub type Performance = Percent;
|
pub type Performance = Percent;
|
||||||
pub type WorkFactor = Decimal;
|
pub type WorkFactor = Decimal;
|
||||||
|
|||||||
@@ -4,8 +4,8 @@
|
|||||||
use crate::error::MixnetContractError;
|
use crate::error::MixnetContractError;
|
||||||
use crate::helpers::IntoBaseDecimal;
|
use crate::helpers::IntoBaseDecimal;
|
||||||
use crate::reward_params::{NodeRewardingParameters, WorkFactor};
|
use crate::reward_params::{NodeRewardingParameters, WorkFactor};
|
||||||
use crate::rewarding::simulator::simulated_node::SimulatedNode;
|
|
||||||
use crate::rewarding::RewardDistribution;
|
use crate::rewarding::RewardDistribution;
|
||||||
|
use crate::rewarding::simulator::simulated_node::SimulatedNode;
|
||||||
use crate::{Delegation, Interval, IntervalRewardParams, NodeCostParams, NodeId, RewardingParams};
|
use crate::{Delegation, Interval, IntervalRewardParams, NodeCostParams, NodeId, RewardingParams};
|
||||||
use cosmwasm_std::{Coin, Decimal};
|
use cosmwasm_std::{Coin, Decimal};
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
@@ -226,9 +226,9 @@ impl Simulator {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use crate::Percent;
|
||||||
use crate::helpers::compare_decimals;
|
use crate::helpers::compare_decimals;
|
||||||
use crate::reward_params::RewardedSetParams;
|
use crate::reward_params::RewardedSetParams;
|
||||||
use crate::Percent;
|
|
||||||
use cosmwasm_std::testing::mock_env;
|
use cosmwasm_std::testing::mock_env;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
|
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
use crate::EpochId;
|
||||||
use crate::config_score::{ConfigScoreParams, OutdatedVersionWeights, VersionScoreFormulaParams};
|
use crate::config_score::{ConfigScoreParams, OutdatedVersionWeights, VersionScoreFormulaParams};
|
||||||
use crate::nym_node::Role;
|
use crate::nym_node::Role;
|
||||||
use crate::reward_params::RewardedSetParams;
|
use crate::reward_params::RewardedSetParams;
|
||||||
use crate::EpochId;
|
|
||||||
use contracts_common::Percent;
|
use contracts_common::Percent;
|
||||||
use cosmwasm_schema::cw_serde;
|
use cosmwasm_schema::cw_serde;
|
||||||
use cosmwasm_std::Coin;
|
use cosmwasm_std::Coin;
|
||||||
|
|||||||
@@ -23,7 +23,9 @@ pub enum NymPerformanceContractError {
|
|||||||
#[error("{address} is not an authorised network monitor")]
|
#[error("{address} is not an authorised network monitor")]
|
||||||
NotAuthorised { address: Addr },
|
NotAuthorised { address: Addr },
|
||||||
|
|
||||||
#[error("attempted to submit performance data for epoch {epoch_id} and node {node_id} whilst last submitted was {last_epoch_id} for node {last_node_id}")]
|
#[error(
|
||||||
|
"attempted to submit performance data for epoch {epoch_id} and node {node_id} whilst last submitted was {last_epoch_id} for node {last_node_id}"
|
||||||
|
)]
|
||||||
StalePerformanceSubmission {
|
StalePerformanceSubmission {
|
||||||
epoch_id: EpochId,
|
epoch_id: EpochId,
|
||||||
node_id: NodeId,
|
node_id: NodeId,
|
||||||
|
|||||||
@@ -16,7 +16,9 @@ pub enum NymPoolContractError {
|
|||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
StdErr(#[from] cosmwasm_std::StdError),
|
StdErr(#[from] cosmwasm_std::StdError),
|
||||||
|
|
||||||
#[error("this sender is not authorised to revoke this grant. its neither the admin or the original (and still whitelisted) granter")]
|
#[error(
|
||||||
|
"this sender is not authorised to revoke this grant. its neither the admin or the original (and still whitelisted) granter"
|
||||||
|
)]
|
||||||
UnauthorizedGrantRevocation,
|
UnauthorizedGrantRevocation,
|
||||||
|
|
||||||
#[error("the specified address is already a whitelisted granter")]
|
#[error("the specified address is already a whitelisted granter")]
|
||||||
@@ -28,7 +30,9 @@ pub enum NymPoolContractError {
|
|||||||
#[error("invalid coin denomination. got {got}, but expected {expected}")]
|
#[error("invalid coin denomination. got {got}, but expected {expected}")]
|
||||||
InvalidDenom { expected: String, got: String },
|
InvalidDenom { expected: String, got: String },
|
||||||
|
|
||||||
#[error("there already exists an active grant for {grantee}. it was granted by {granter} at block height {created_at_height}")]
|
#[error(
|
||||||
|
"there already exists an active grant for {grantee}. it was granted by {granter} at block height {created_at_height}"
|
||||||
|
)]
|
||||||
GrantAlreadyExist {
|
GrantAlreadyExist {
|
||||||
granter: String,
|
granter: String,
|
||||||
grantee: String,
|
grantee: String,
|
||||||
@@ -38,13 +42,17 @@ pub enum NymPoolContractError {
|
|||||||
#[error("could not find any active grants for {grantee}")]
|
#[error("could not find any active grants for {grantee}")]
|
||||||
GrantNotFound { grantee: String },
|
GrantNotFound { grantee: String },
|
||||||
|
|
||||||
#[error("the provided timestamp value ({timestamp}) is set in the past. the current block timestamp is {current_block_timestamp}")]
|
#[error(
|
||||||
|
"the provided timestamp value ({timestamp}) is set in the past. the current block timestamp is {current_block_timestamp}"
|
||||||
|
)]
|
||||||
TimestampInThePast {
|
TimestampInThePast {
|
||||||
timestamp: u64,
|
timestamp: u64,
|
||||||
current_block_timestamp: u64,
|
current_block_timestamp: u64,
|
||||||
},
|
},
|
||||||
|
|
||||||
#[error("there are not enough tokens to process this request. {available} are available, but {required} is needed.")]
|
#[error(
|
||||||
|
"there are not enough tokens to process this request. {available} are available, but {required} is needed."
|
||||||
|
)]
|
||||||
InsufficientTokens { available: Coin, required: Coin },
|
InsufficientTokens { available: Coin, required: Coin },
|
||||||
|
|
||||||
#[error("the period length can't be zero")]
|
#[error("the period length can't be zero")]
|
||||||
@@ -53,22 +61,30 @@ pub enum NymPoolContractError {
|
|||||||
#[error("the provided coin value is zero")]
|
#[error("the provided coin value is zero")]
|
||||||
ZeroAmount,
|
ZeroAmount,
|
||||||
|
|
||||||
#[error("the periodic spend limit of {periodic} was set to be higher than the total spend limit {total_limit}")]
|
#[error(
|
||||||
|
"the periodic spend limit of {periodic} was set to be higher than the total spend limit {total_limit}"
|
||||||
|
)]
|
||||||
PeriodicGrantOverSpendLimit { periodic: Coin, total_limit: Coin },
|
PeriodicGrantOverSpendLimit { periodic: Coin, total_limit: Coin },
|
||||||
|
|
||||||
#[error("the accumulation spend limit of {accumulation} was set to be lower than the periodic grant amount of {periodic_grant}")]
|
#[error(
|
||||||
|
"the accumulation spend limit of {accumulation} was set to be lower than the periodic grant amount of {periodic_grant}"
|
||||||
|
)]
|
||||||
AccumulationBelowGrantAmount {
|
AccumulationBelowGrantAmount {
|
||||||
accumulation: Coin,
|
accumulation: Coin,
|
||||||
periodic_grant: Coin,
|
periodic_grant: Coin,
|
||||||
},
|
},
|
||||||
|
|
||||||
#[error("the accumulation spend limit of {accumulation} was set to be higher than the total spend limit of {total_limit}")]
|
#[error(
|
||||||
|
"the accumulation spend limit of {accumulation} was set to be higher than the total spend limit of {total_limit}"
|
||||||
|
)]
|
||||||
AccumulationOverSpendLimit {
|
AccumulationOverSpendLimit {
|
||||||
accumulation: Coin,
|
accumulation: Coin,
|
||||||
total_limit: Coin,
|
total_limit: Coin,
|
||||||
},
|
},
|
||||||
|
|
||||||
#[error("the specified delayed allowance would never be available. it would become active at {available_timestamp} yet it expires at {expiration_timestamp}")]
|
#[error(
|
||||||
|
"the specified delayed allowance would never be available. it would become active at {available_timestamp} yet it expires at {expiration_timestamp}"
|
||||||
|
)]
|
||||||
UnattainableDelayedAllowance {
|
UnattainableDelayedAllowance {
|
||||||
expiration_timestamp: u64,
|
expiration_timestamp: u64,
|
||||||
available_timestamp: u64,
|
available_timestamp: u64,
|
||||||
|
|||||||
@@ -88,10 +88,10 @@ pub mod grants {
|
|||||||
|
|
||||||
pub fn basic_mut(&mut self) -> &mut BasicAllowance {
|
pub fn basic_mut(&mut self) -> &mut BasicAllowance {
|
||||||
match self {
|
match self {
|
||||||
Allowance::Basic(ref mut allowance) => allowance,
|
Allowance::Basic(allowance) => allowance,
|
||||||
Allowance::ClassicPeriodic(ref mut allowance) => &mut allowance.basic,
|
Allowance::ClassicPeriodic(allowance) => &mut allowance.basic,
|
||||||
Allowance::CumulativePeriodic(ref mut allowance) => &mut allowance.basic,
|
Allowance::CumulativePeriodic(allowance) => &mut allowance.basic,
|
||||||
Allowance::Delayed(ref mut allowance) => &mut allowance.basic,
|
Allowance::Delayed(allowance) => &mut allowance.basic,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -752,7 +752,7 @@ pub mod query_responses {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use cosmwasm_std::{coin, Uint128};
|
use cosmwasm_std::{Uint128, coin};
|
||||||
|
|
||||||
const TEST_DENOM: &str = "unym";
|
const TEST_DENOM: &str = "unym";
|
||||||
|
|
||||||
@@ -873,8 +873,8 @@ mod tests {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod basic_allowance {
|
mod basic_allowance {
|
||||||
use super::*;
|
use super::*;
|
||||||
use cosmwasm_std::testing::mock_env;
|
|
||||||
use cosmwasm_std::Timestamp;
|
use cosmwasm_std::Timestamp;
|
||||||
|
use cosmwasm_std::testing::mock_env;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn doesnt_allow_expirations_in_the_past() {
|
fn doesnt_allow_expirations_in_the_past() {
|
||||||
@@ -1158,8 +1158,8 @@ mod tests {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod delayed_allowance {
|
mod delayed_allowance {
|
||||||
use super::*;
|
use super::*;
|
||||||
use cosmwasm_std::testing::mock_env;
|
|
||||||
use cosmwasm_std::Timestamp;
|
use cosmwasm_std::Timestamp;
|
||||||
|
use cosmwasm_std::testing::mock_env;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn doesnt_allow_availability_in_the_past() {
|
fn doesnt_allow_availability_in_the_past() {
|
||||||
|
|||||||
@@ -20,8 +20,8 @@ pub fn ensure_unix_timestamp_not_in_the_past(
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use cosmwasm_std::testing::mock_env;
|
|
||||||
use cosmwasm_std::Timestamp;
|
use cosmwasm_std::Timestamp;
|
||||||
|
use cosmwasm_std::testing::mock_env;
|
||||||
use time::macros::datetime;
|
use time::macros::datetime;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
@@ -61,7 +61,9 @@ pub enum VestingContractError {
|
|||||||
#[error("VESTING ({l}): No bond found for account {0}", l = line!())]
|
#[error("VESTING ({l}): No bond found for account {0}", l = line!())]
|
||||||
NoBondFound(String),
|
NoBondFound(String),
|
||||||
|
|
||||||
#[error("VESTING: Attempted to reduce mixnode bond pledge below zero! The current pledge is {current} and we attempted to reduce it by {decrease_by}.")]
|
#[error(
|
||||||
|
"VESTING: Attempted to reduce mixnode bond pledge below zero! The current pledge is {current} and we attempted to reduce it by {decrease_by}."
|
||||||
|
)]
|
||||||
InvalidBondPledgeReduction { current: Coin, decrease_by: Coin },
|
InvalidBondPledgeReduction { current: Coin, decrease_by: Coin },
|
||||||
|
|
||||||
#[error("VESTING ({l}): Action can only be executed by account owner -> {0}", l = line!())]
|
#[error("VESTING ({l}): Action can only be executed by account owner -> {0}", l = line!())]
|
||||||
@@ -85,13 +87,17 @@ pub enum VestingContractError {
|
|||||||
#[error("VESTING: ({l}: Account owned by {owner} has unpopulated vesting periods!", l = line!())]
|
#[error("VESTING: ({l}: Account owned by {owner} has unpopulated vesting periods!", l = line!())]
|
||||||
UnpopulatedVestingPeriods { owner: Addr },
|
UnpopulatedVestingPeriods { owner: Addr },
|
||||||
|
|
||||||
#[error("VESTING: Vesting account associated with {0} already exists, only addresses with not existing vesting accounts can be added as staking addresses")]
|
#[error(
|
||||||
|
"VESTING: Vesting account associated with {0} already exists, only addresses with not existing vesting accounts can be added as staking addresses"
|
||||||
|
)]
|
||||||
StakingAccountExists(String),
|
StakingAccountExists(String),
|
||||||
|
|
||||||
#[error("VESTING: {address} is not permitted to perform staking on behalf of {for_account}")]
|
#[error("VESTING: {address} is not permitted to perform staking on behalf of {for_account}")]
|
||||||
InvalidStakingAccount { address: Addr, for_account: Addr },
|
InvalidStakingAccount { address: Addr, for_account: Addr },
|
||||||
|
|
||||||
#[error("VESTING: {address} ({acc_id} has already performed {num} individual delegations towards {mix_id}. No further delegations are allowed. Please consider consolidating those delegations instead. The current cap is {cap}.")]
|
#[error(
|
||||||
|
"VESTING: {address} ({acc_id} has already performed {num} individual delegations towards {mix_id}. No further delegations are allowed. Please consider consolidating those delegations instead. The current cap is {cap}."
|
||||||
|
)]
|
||||||
TooManyDelegations {
|
TooManyDelegations {
|
||||||
address: Addr,
|
address: Addr,
|
||||||
acc_id: VestingAccountStorageKey,
|
acc_id: VestingAccountStorageKey,
|
||||||
|
|||||||
@@ -6,9 +6,9 @@ use contracts_common::signing::MessageSignature;
|
|||||||
use cosmwasm_schema::cw_serde;
|
use cosmwasm_schema::cw_serde;
|
||||||
use cosmwasm_std::{Coin, Timestamp};
|
use cosmwasm_std::{Coin, Timestamp};
|
||||||
use mixnet_contract_common::{
|
use mixnet_contract_common::{
|
||||||
|
Gateway, MixNode, NodeId,
|
||||||
gateway::GatewayConfigUpdate,
|
gateway::GatewayConfigUpdate,
|
||||||
mixnode::{MixNodeConfigUpdate, NodeCostParams},
|
mixnode::{MixNodeConfigUpdate, NodeCostParams},
|
||||||
Gateway, MixNode, NodeId,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(feature = "schema")]
|
#[cfg(feature = "schema")]
|
||||||
@@ -18,10 +18,10 @@ use cosmwasm_schema::QueryResponses;
|
|||||||
|
|
||||||
#[cfg(feature = "schema")]
|
#[cfg(feature = "schema")]
|
||||||
use crate::{
|
use crate::{
|
||||||
account::Account,
|
|
||||||
types::{Period, PledgeData, VestingDelegation},
|
|
||||||
AccountsResponse, AllDelegationsResponse, DelegationTimesResponse, OriginalVestingResponse,
|
AccountsResponse, AllDelegationsResponse, DelegationTimesResponse, OriginalVestingResponse,
|
||||||
VestingCoinsResponse,
|
VestingCoinsResponse,
|
||||||
|
account::Account,
|
||||||
|
types::{Period, PledgeData, VestingDelegation},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cw_serde]
|
#[cw_serde]
|
||||||
|
|||||||
@@ -118,7 +118,9 @@ pub async fn make_deposits_request(
|
|||||||
// that one is tricky. deposits technically got made, but we somehow failed to parse response,
|
// that one is tricky. deposits technically got made, but we somehow failed to parse response,
|
||||||
// in this case terminate the proxy with 0 exit code so it wouldn't get automatically restarted
|
// in this case terminate the proxy with 0 exit code so it wouldn't get automatically restarted
|
||||||
// because it requires some serious MANUAL intervention
|
// because it requires some serious MANUAL intervention
|
||||||
error!("CRITICAL FAILURE: failed to parse out deposit information from the contract transaction. either the chain got upgraded and the schema changed or the ecash contract got changed! terminating the process. it has to be inspected manually. error was: {err}");
|
error!(
|
||||||
|
"CRITICAL FAILURE: failed to parse out deposit information from the contract transaction. either the chain got upgraded and the schema changed or the ecash contract got changed! terminating the process. it has to be inspected manually. error was: {err}"
|
||||||
|
);
|
||||||
cancellation_on_critical_failure.cancel();
|
cancellation_on_critical_failure.cancel();
|
||||||
return Err(CredentialProxyError::DepositFailure);
|
return Err(CredentialProxyError::DepositFailure);
|
||||||
}
|
}
|
||||||
@@ -126,7 +128,10 @@ pub async fn make_deposits_request(
|
|||||||
|
|
||||||
if contract_data.len() != amount {
|
if contract_data.len() != amount {
|
||||||
// another critical failure, that one should be quite impossible and thus has to be manually inspected
|
// another critical failure, that one should be quite impossible and thus has to be manually inspected
|
||||||
error!("CRITICAL FAILURE: failed to parse out all deposit information from the contract transaction. got {} responses while we sent {amount} deposits! either the chain got upgraded and the schema changed or the ecash contract got changed! terminating the process. it has to be inspected manually", contract_data.len());
|
error!(
|
||||||
|
"CRITICAL FAILURE: failed to parse out all deposit information from the contract transaction. got {} responses while we sent {amount} deposits! either the chain got upgraded and the schema changed or the ecash contract got changed! terminating the process. it has to be inspected manually",
|
||||||
|
contract_data.len()
|
||||||
|
);
|
||||||
cancellation_on_critical_failure.cancel();
|
cancellation_on_critical_failure.cancel();
|
||||||
return Err(CredentialProxyError::DepositFailure);
|
return Err(CredentialProxyError::DepositFailure);
|
||||||
}
|
}
|
||||||
@@ -138,7 +143,9 @@ pub async fn make_deposits_request(
|
|||||||
Ok(deposit_id) => deposit_id,
|
Ok(deposit_id) => deposit_id,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
// another impossibility
|
// another impossibility
|
||||||
error!("CRITICAL FAILURE: failed to parse out deposit id out of the response at index {response_index}: {err}. either the chain got upgraded and the schema changed or the ecash contract got changed! terminating the process. it has to be inspected manually");
|
error!(
|
||||||
|
"CRITICAL FAILURE: failed to parse out deposit id out of the response at index {response_index}: {err}. either the chain got upgraded and the schema changed or the ecash contract got changed! terminating the process. it has to be inspected manually"
|
||||||
|
);
|
||||||
cancellation_on_critical_failure.cancel();
|
cancellation_on_critical_failure.cancel();
|
||||||
return Err(CredentialProxyError::DepositFailure);
|
return Err(CredentialProxyError::DepositFailure);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ use tokio_util::sync::CancellationToken;
|
|||||||
use tracing::{debug, info, instrument, warn};
|
use tracing::{debug, info, instrument, warn};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
pub use helpers::{make_deposits_request, split_deposits, BufferedDeposit, PerformedDeposits};
|
pub use helpers::{BufferedDeposit, PerformedDeposits, make_deposits_request, split_deposits};
|
||||||
|
|
||||||
pub(crate) mod helpers;
|
pub(crate) mod helpers;
|
||||||
mod refill_task;
|
mod refill_task;
|
||||||
@@ -219,7 +219,9 @@ impl DepositsBuffer {
|
|||||||
|
|
||||||
match maybe_deposit {
|
match maybe_deposit {
|
||||||
None => {
|
None => {
|
||||||
warn!("we currently don't have any usable deposits! are we using them up faster than we request them?");
|
warn!(
|
||||||
|
"we currently don't have any usable deposits! are we using them up faster than we request them?"
|
||||||
|
);
|
||||||
|
|
||||||
// we have to wait until refill task has completed (either initiated by this or another fn call)
|
// we have to wait until refill task has completed (either initiated by this or another fn call)
|
||||||
self.wait_for_deposit(request_uuid, requested_on, client_pubkey)
|
self.wait_for_deposit(request_uuid, requested_on, client_pubkey)
|
||||||
@@ -242,7 +244,9 @@ impl DepositsBuffer {
|
|||||||
let task_handle = self.inner.deposits_refill_task.take_task_join_handle();
|
let task_handle = self.inner.deposits_refill_task.take_task_join_handle();
|
||||||
if let Some(task_handle) = task_handle {
|
if let Some(task_handle) = task_handle {
|
||||||
if !task_handle.is_finished() {
|
if !task_handle.is_finished() {
|
||||||
info!("the deposit refill task is currently in progress - waiting for the current transaction to finish before concluding shutdown");
|
info!(
|
||||||
|
"the deposit refill task is currently in progress - waiting for the current transaction to finish before concluding shutdown"
|
||||||
|
);
|
||||||
let _ = task_handle.await;
|
let _ = task_handle.await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,7 +42,9 @@ impl RefillTask {
|
|||||||
|
|
||||||
if let Some(existing_handle) = guard.as_ref() {
|
if let Some(existing_handle) = guard.as_ref() {
|
||||||
if !existing_handle.is_finished() {
|
if !existing_handle.is_finished() {
|
||||||
error!("CRITICAL BUG: there was already a deposit refill task spawned that hasn't yet finished")
|
error!(
|
||||||
|
"CRITICAL BUG: there was already a deposit refill task spawned that hasn't yet finished"
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
use nym_ecash_signer_check::SignerCheckError;
|
use nym_ecash_signer_check::SignerCheckError;
|
||||||
use nym_validator_client::coconut::EcashApiError;
|
use nym_validator_client::coconut::EcashApiError;
|
||||||
use nym_validator_client::nym_api::{error::NymAPIError, EpochId};
|
use nym_validator_client::nym_api::{EpochId, error::NymAPIError};
|
||||||
use nym_validator_client::nyxd::error::NyxdError;
|
use nym_validator_client::nyxd::error::NyxdError;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
@@ -33,7 +33,9 @@ pub enum CredentialProxyError {
|
|||||||
#[error("the provided expiration date is too early")]
|
#[error("the provided expiration date is too early")]
|
||||||
ExpirationDateTooEarly,
|
ExpirationDateTooEarly,
|
||||||
|
|
||||||
#[error("failed to bind to {address}: {source}. Are you sure nothing else is running on the specified port and your user has sufficient permission to bind to the requested address?")]
|
#[error(
|
||||||
|
"failed to bind to {address}: {source}. Are you sure nothing else is running on the specified port and your user has sufficient permission to bind to the requested address?"
|
||||||
|
)]
|
||||||
SocketBindFailure {
|
SocketBindFailure {
|
||||||
address: SocketAddr,
|
address: SocketAddr,
|
||||||
source: io::Error,
|
source: io::Error,
|
||||||
@@ -89,7 +91,7 @@ pub enum CredentialProxyError {
|
|||||||
InsufficientNumberOfSigners { available: usize, threshold: u64 },
|
InsufficientNumberOfSigners { available: usize, threshold: u64 },
|
||||||
|
|
||||||
#[error(
|
#[error(
|
||||||
"we have only managed to obtain {available} partial credentials while the minimum threshold is {threshold}"
|
"we have only managed to obtain {available} partial credentials while the minimum threshold is {threshold}"
|
||||||
)]
|
)]
|
||||||
InsufficientNumberOfCredentials { available: usize, threshold: u64 },
|
InsufficientNumberOfCredentials { available: usize, threshold: u64 },
|
||||||
|
|
||||||
@@ -102,7 +104,9 @@ pub enum CredentialProxyError {
|
|||||||
#[error("the DKG has not yet been initialised in the system")]
|
#[error("the DKG has not yet been initialised in the system")]
|
||||||
UninitialisedDkg,
|
UninitialisedDkg,
|
||||||
|
|
||||||
#[error("credentials can't yet be issued in the system. approximate expected availability: {availability}")]
|
#[error(
|
||||||
|
"credentials can't yet be issued in the system. approximate expected availability: {availability}"
|
||||||
|
)]
|
||||||
CredentialsNotYetIssuable { availability: OffsetDateTime },
|
CredentialsNotYetIssuable { availability: OffsetDateTime },
|
||||||
|
|
||||||
#[error("reached seemingly impossible ecash failure")]
|
#[error("reached seemingly impossible ecash failure")]
|
||||||
@@ -140,7 +144,9 @@ pub enum CredentialProxyError {
|
|||||||
#[error("failed to obtain wallet shares with id {id}: {message}")]
|
#[error("failed to obtain wallet shares with id {id}: {message}")]
|
||||||
ShareByIdLoadError { message: String, id: i64 },
|
ShareByIdLoadError { message: String, id: i64 },
|
||||||
|
|
||||||
#[error("failed to obtain wallet shares with device_id {device_id} and credential_id: {credential_id}: {message}")]
|
#[error(
|
||||||
|
"failed to obtain wallet shares with device_id {device_id} and credential_id: {credential_id}: {message}"
|
||||||
|
)]
|
||||||
ShareByDeviceLoadError {
|
ShareByDeviceLoadError {
|
||||||
message: String,
|
message: String,
|
||||||
device_id: String,
|
device_id: String,
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
// Copyright 2025 - Nym Technologies SA <contact@nymtech.net>
|
// Copyright 2025 - Nym Technologies SA <contact@nymtech.net>
|
||||||
// SPDX-License-Identifier: GPL-3.0-only
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
use rand::rngs::OsRng;
|
|
||||||
use rand::RngCore;
|
use rand::RngCore;
|
||||||
|
use rand::rngs::OsRng;
|
||||||
use time::OffsetDateTime;
|
use time::OffsetDateTime;
|
||||||
use tracing::{debug, info, warn};
|
use tracing::{debug, info, warn};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|||||||
@@ -2,9 +2,9 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
use crate::error::CredentialProxyError;
|
use crate::error::CredentialProxyError;
|
||||||
|
use axum::Json;
|
||||||
use axum::http::StatusCode;
|
use axum::http::StatusCode;
|
||||||
use axum::response::{IntoResponse, Response};
|
use axum::response::{IntoResponse, Response};
|
||||||
use axum::Json;
|
|
||||||
use nym_credential_proxy_requests::api::v1::ErrorResponse;
|
use nym_credential_proxy_requests::api::v1::ErrorResponse;
|
||||||
use tracing::warn;
|
use tracing::warn;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|||||||
@@ -5,12 +5,12 @@
|
|||||||
// it should have been therefore extracted to a common crate instead and imported as dependency
|
// it should have been therefore extracted to a common crate instead and imported as dependency
|
||||||
|
|
||||||
use crate::error::CredentialProxyError;
|
use crate::error::CredentialProxyError;
|
||||||
use futures::{stream, StreamExt};
|
use futures::{StreamExt, stream};
|
||||||
use nym_cache::CachedImmutableItems;
|
use nym_cache::CachedImmutableItems;
|
||||||
use nym_credentials::ecash::utils::{cred_exp_date, ecash_today, EcashTime};
|
use nym_credentials::ecash::utils::{EcashTime, cred_exp_date, ecash_today};
|
||||||
|
use nym_validator_client::EcashApiClient;
|
||||||
use nym_validator_client::nym_api::EpochId;
|
use nym_validator_client::nym_api::EpochId;
|
||||||
use nym_validator_client::nyxd::contract_traits::dkg_query_client::Epoch;
|
use nym_validator_client::nyxd::contract_traits::dkg_query_client::Epoch;
|
||||||
use nym_validator_client::EcashApiClient;
|
|
||||||
use std::cmp::min;
|
use std::cmp::min;
|
||||||
use std::future::Future;
|
use std::future::Future;
|
||||||
use time::{Date, OffsetDateTime};
|
use time::{Date, OffsetDateTime};
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ use crate::error::CredentialProxyError;
|
|||||||
use crate::shared_state::nyxd_client::ChainClient;
|
use crate::shared_state::nyxd_client::ChainClient;
|
||||||
use nym_ecash_signer_check::{check_known_dealers, dkg_details_with_client};
|
use nym_ecash_signer_check::{check_known_dealers, dkg_details_with_client};
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use tokio_util::sync::CancellationToken;
|
use tokio_util::sync::CancellationToken;
|
||||||
use tracing::{error, info, warn};
|
use tracing::{error, info, warn};
|
||||||
@@ -67,7 +67,9 @@ impl QuorumStateChecker {
|
|||||||
let res = check_known_dealers(dkg_details).await?;
|
let res = check_known_dealers(dkg_details).await?;
|
||||||
|
|
||||||
let Some(signing_threshold) = res.threshold else {
|
let Some(signing_threshold) = res.threshold else {
|
||||||
warn!("signing threshold is currently unavailable and we have not yet implemented credential issuance during DKG transition");
|
warn!(
|
||||||
|
"signing threshold is currently unavailable and we have not yet implemented credential issuance during DKG transition"
|
||||||
|
);
|
||||||
return Ok(false);
|
return Ok(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
use crate::error::CredentialProxyError;
|
use crate::error::CredentialProxyError;
|
||||||
use crate::nym_api_helpers::{
|
use crate::nym_api_helpers::{
|
||||||
ensure_sane_expiration_date, query_all_threshold_apis, CachedEpoch, CachedImmutableEpochItem,
|
CachedEpoch, CachedImmutableEpochItem, ensure_sane_expiration_date, query_all_threshold_apis,
|
||||||
};
|
};
|
||||||
use crate::quorum_checker::QuorumState;
|
use crate::quorum_checker::QuorumState;
|
||||||
use crate::shared_state::nyxd_client::ChainClient;
|
use crate::shared_state::nyxd_client::ChainClient;
|
||||||
@@ -16,20 +16,20 @@ use nym_credentials::ecash::utils::EcashTime;
|
|||||||
use nym_credentials::{
|
use nym_credentials::{
|
||||||
AggregatedCoinIndicesSignatures, AggregatedExpirationDateSignatures, EpochVerificationKey,
|
AggregatedCoinIndicesSignatures, AggregatedExpirationDateSignatures, EpochVerificationKey,
|
||||||
};
|
};
|
||||||
|
use nym_validator_client::EcashApiClient;
|
||||||
use nym_validator_client::client::NymApiClientExt;
|
use nym_validator_client::client::NymApiClientExt;
|
||||||
use nym_validator_client::coconut::EcashApiError;
|
use nym_validator_client::coconut::EcashApiError;
|
||||||
use nym_validator_client::nym_api::EpochId;
|
use nym_validator_client::nym_api::EpochId;
|
||||||
|
use nym_validator_client::nyxd::Coin;
|
||||||
use nym_validator_client::nyxd::contract_traits::dkg_query_client::Epoch;
|
use nym_validator_client::nyxd::contract_traits::dkg_query_client::Epoch;
|
||||||
use nym_validator_client::nyxd::contract_traits::{DkgQueryClient, PagedDkgQueryClient};
|
use nym_validator_client::nyxd::contract_traits::{DkgQueryClient, PagedDkgQueryClient};
|
||||||
use nym_validator_client::nyxd::Coin;
|
|
||||||
use nym_validator_client::EcashApiClient;
|
|
||||||
use time::{Date, OffsetDateTime};
|
use time::{Date, OffsetDateTime};
|
||||||
use tokio::sync::{RwLock, RwLockReadGuard};
|
use tokio::sync::{RwLock, RwLockReadGuard};
|
||||||
use tracing::info;
|
use tracing::info;
|
||||||
|
|
||||||
|
pub use nym_compact_ecash::VerificationKeyAuth;
|
||||||
pub use nym_compact_ecash::scheme::coin_indices_signatures::CoinIndexSignatureShare;
|
pub use nym_compact_ecash::scheme::coin_indices_signatures::CoinIndexSignatureShare;
|
||||||
pub use nym_compact_ecash::scheme::expiration_date_signatures::ExpirationDateSignatureShare;
|
pub use nym_compact_ecash::scheme::expiration_date_signatures::ExpirationDateSignatureShare;
|
||||||
pub use nym_compact_ecash::VerificationKeyAuth;
|
|
||||||
pub use nym_credentials::{IssuanceTicketBook, IssuedTicketBook};
|
pub use nym_credentials::{IssuanceTicketBook, IssuedTicketBook};
|
||||||
pub use nym_credentials_interface::{TicketType, TicketTypeRepr};
|
pub use nym_credentials_interface::{TicketType, TicketTypeRepr};
|
||||||
|
|
||||||
|
|||||||
@@ -13,10 +13,10 @@ use nym_credential_proxy_requests::api::v1::ticketbook::models::{
|
|||||||
};
|
};
|
||||||
use nym_credentials::{AggregatedCoinIndicesSignatures, AggregatedExpirationDateSignatures};
|
use nym_credentials::{AggregatedCoinIndicesSignatures, AggregatedExpirationDateSignatures};
|
||||||
use nym_ecash_contract_common::deposit::DepositId;
|
use nym_ecash_contract_common::deposit::DepositId;
|
||||||
use nym_validator_client::nym_api::EpochId;
|
|
||||||
use nym_validator_client::nyxd::contract_traits::dkg_query_client::Epoch;
|
|
||||||
use nym_validator_client::nyxd::Coin;
|
|
||||||
use nym_validator_client::EcashApiClient;
|
use nym_validator_client::EcashApiClient;
|
||||||
|
use nym_validator_client::nym_api::EpochId;
|
||||||
|
use nym_validator_client::nyxd::Coin;
|
||||||
|
use nym_validator_client::nyxd::contract_traits::dkg_query_client::Epoch;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use time::{Date, OffsetDateTime};
|
use time::{Date, OffsetDateTime};
|
||||||
@@ -92,7 +92,9 @@ impl CredentialProxyState {
|
|||||||
let time_taken = start.elapsed();
|
let time_taken = start.elapsed();
|
||||||
let formatted = humantime::format_duration(time_taken);
|
let formatted = humantime::format_duration(time_taken);
|
||||||
if time_taken > Duration::from_secs(10) {
|
if time_taken > Duration::from_secs(10) {
|
||||||
warn!("attempting to get buffered deposit took {formatted}. perhaps the buffer is too small or the process/chain is overloaded?")
|
warn!(
|
||||||
|
"attempting to get buffered deposit took {formatted}. perhaps the buffer is too small or the process/chain is overloaded?"
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
debug!("attempting to get buffered deposit took {formatted}")
|
debug!("attempting to get buffered deposit took {formatted}")
|
||||||
};
|
};
|
||||||
@@ -106,7 +108,9 @@ impl CredentialProxyState {
|
|||||||
.insert_deposit_usage_error(deposit_id, error)
|
.insert_deposit_usage_error(deposit_id, error)
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
error!("failed to insert information about deposit (id: {deposit_id}) usage failure: {err}")
|
error!(
|
||||||
|
"failed to insert information about deposit (id: {deposit_id}) usage failure: {err}"
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ use nym_ecash_contract_common::msg::ExecuteMsg;
|
|||||||
use nym_validator_client::nyxd::contract_traits::NymContractsProvider;
|
use nym_validator_client::nyxd::contract_traits::NymContractsProvider;
|
||||||
use nym_validator_client::nyxd::cosmwasm_client::types::ExecuteResult;
|
use nym_validator_client::nyxd::cosmwasm_client::types::ExecuteResult;
|
||||||
use nym_validator_client::nyxd::{Coin, Config, CosmWasmClient, NyxdClient};
|
use nym_validator_client::nyxd::{Coin, Config, CosmWasmClient, NyxdClient};
|
||||||
use nym_validator_client::{nyxd, DirectSigningHttpRpcNyxdClient};
|
use nym_validator_client::{DirectSigningHttpRpcNyxdClient, nyxd};
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|||||||
@@ -3,8 +3,8 @@
|
|||||||
|
|
||||||
use crate::error::CredentialProxyError;
|
use crate::error::CredentialProxyError;
|
||||||
use crate::shared_state::nyxd_client::ChainClient;
|
use crate::shared_state::nyxd_client::ChainClient;
|
||||||
use nym_validator_client::nyxd::contract_traits::EcashQueryClient;
|
|
||||||
use nym_validator_client::nyxd::Coin;
|
use nym_validator_client::nyxd::Coin;
|
||||||
|
use nym_validator_client::nyxd::contract_traits::EcashQueryClient;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use time::OffsetDateTime;
|
use time::OffsetDateTime;
|
||||||
use tokio::sync::RwLock;
|
use tokio::sync::RwLock;
|
||||||
|
|||||||
@@ -380,8 +380,9 @@ impl SqliteStorageManager {
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut query_builder =
|
let mut query_builder = sqlx::QueryBuilder::new(
|
||||||
sqlx::QueryBuilder::new("INSERT INTO ecash_deposit (deposit_id, deposit_tx_hash, requested_on, deposit_amount, ed25519_deposit_private_key) ");
|
"INSERT INTO ecash_deposit (deposit_id, deposit_tx_hash, requested_on, deposit_amount, ed25519_deposit_private_key) ",
|
||||||
|
);
|
||||||
|
|
||||||
query_builder.push_values(&deposits, |mut b, deposit| {
|
query_builder.push_values(&deposits, |mut b, deposit| {
|
||||||
b.push_bind(deposit.deposit_id)
|
b.push_bind(deposit.deposit_id)
|
||||||
|
|||||||
@@ -13,8 +13,8 @@ use nym_credentials::{
|
|||||||
use nym_validator_client::ecash::BlindedSignatureResponse;
|
use nym_validator_client::ecash::BlindedSignatureResponse;
|
||||||
use nym_validator_client::nym_api::EpochId;
|
use nym_validator_client::nym_api::EpochId;
|
||||||
use nym_validator_client::nyxd::contract_traits::ecash_query_client::DepositId;
|
use nym_validator_client::nyxd::contract_traits::ecash_query_client::DepositId;
|
||||||
use sqlx::sqlite::{SqliteAutoVacuum, SqliteSynchronous};
|
|
||||||
use sqlx::ConnectOptions;
|
use sqlx::ConnectOptions;
|
||||||
|
use sqlx::sqlite::{SqliteAutoVacuum, SqliteSynchronous};
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
@@ -405,8 +405,8 @@ mod tests {
|
|||||||
use nym_compact_ecash::scheme::keygen::KeyPairUser;
|
use nym_compact_ecash::scheme::keygen::KeyPairUser;
|
||||||
use nym_crypto::asymmetric::ed25519;
|
use nym_crypto::asymmetric::ed25519;
|
||||||
use nym_validator_client::nyxd::{Coin, Hash};
|
use nym_validator_client::nyxd::{Coin, Hash};
|
||||||
use rand::rngs::OsRng;
|
|
||||||
use rand::RngCore;
|
use rand::RngCore;
|
||||||
|
use rand::rngs::OsRng;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use tempfile::{NamedTempFile, TempPath};
|
use tempfile::{NamedTempFile, TempPath};
|
||||||
|
|
||||||
|
|||||||
@@ -4,12 +4,12 @@
|
|||||||
use crate::deposits_buffer::DepositsBuffer;
|
use crate::deposits_buffer::DepositsBuffer;
|
||||||
use crate::error::CredentialProxyError;
|
use crate::error::CredentialProxyError;
|
||||||
use crate::quorum_checker::QuorumStateChecker;
|
use crate::quorum_checker::QuorumStateChecker;
|
||||||
|
use crate::shared_state::CredentialProxyState;
|
||||||
use crate::shared_state::ecash_state::EcashState;
|
use crate::shared_state::ecash_state::EcashState;
|
||||||
use crate::shared_state::nyxd_client::ChainClient;
|
use crate::shared_state::nyxd_client::ChainClient;
|
||||||
use crate::shared_state::required_deposit_cache::RequiredDepositCache;
|
use crate::shared_state::required_deposit_cache::RequiredDepositCache;
|
||||||
use crate::shared_state::CredentialProxyState;
|
|
||||||
use crate::storage::pruner::StoragePruner;
|
|
||||||
use crate::storage::CredentialProxyStorage;
|
use crate::storage::CredentialProxyStorage;
|
||||||
|
use crate::storage::pruner::StoragePruner;
|
||||||
use crate::webhook::ZkNymWebhook;
|
use crate::webhook::ZkNymWebhook;
|
||||||
use nym_credentials::ecash::utils::ecash_default_expiration_date;
|
use nym_credentials::ecash::utils::ecash_default_expiration_date;
|
||||||
use nym_validator_client::nym_api::EpochId;
|
use nym_validator_client::nym_api::EpochId;
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ use nym_credential_proxy_requests::api::v1::ticketbook::models::{
|
|||||||
GlobalDataParams, TicketbookWalletSharesResponse,
|
GlobalDataParams, TicketbookWalletSharesResponse,
|
||||||
};
|
};
|
||||||
use nym_validator_client::nym_api::EpochId;
|
use nym_validator_client::nym_api::EpochId;
|
||||||
use tracing::{debug, span, Instrument, Level};
|
use tracing::{Instrument, Level, debug, span};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
impl TicketbookManager {
|
impl TicketbookManager {
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ use nym_credential_proxy_requests::api::v1::ticketbook::models::{
|
|||||||
TicketbookWalletSharesResponse,
|
TicketbookWalletSharesResponse,
|
||||||
};
|
};
|
||||||
use time::OffsetDateTime;
|
use time::OffsetDateTime;
|
||||||
use tracing::{error, info, span, warn, Instrument, Level};
|
use tracing::{Instrument, Level, error, info, span, warn};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
impl TicketbookManager {
|
impl TicketbookManager {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
use crate::error::CredentialProxyError;
|
use crate::error::CredentialProxyError;
|
||||||
use crate::storage::models::BlindedShares;
|
use crate::storage::models::BlindedShares;
|
||||||
use crate::ticketbook_manager::TicketbookManager;
|
use crate::ticketbook_manager::TicketbookManager;
|
||||||
use futures::{stream, StreamExt};
|
use futures::{StreamExt, stream};
|
||||||
use nym_compact_ecash::Base58;
|
use nym_compact_ecash::Base58;
|
||||||
use nym_credential_proxy_requests::api::v1::ticketbook::models::{
|
use nym_credential_proxy_requests::api::v1::ticketbook::models::{
|
||||||
TicketbookAsyncRequest, TicketbookObtainParams, TicketbookRequest,
|
TicketbookAsyncRequest, TicketbookObtainParams, TicketbookRequest,
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
use reqwest::header::AUTHORIZATION;
|
use reqwest::header::AUTHORIZATION;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use tracing::{debug, error, instrument, span, Instrument, Level};
|
use tracing::{Instrument, Level, debug, error, instrument, span};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
|||||||
@@ -58,7 +58,6 @@ impl PersistentStorage {
|
|||||||
"Attempting to connect to database {}",
|
"Attempting to connect to database {}",
|
||||||
database_path.as_ref().display()
|
database_path.as_ref().display()
|
||||||
);
|
);
|
||||||
|
|
||||||
let opts = sqlx::sqlite::SqliteConnectOptions::new()
|
let opts = sqlx::sqlite::SqliteConnectOptions::new()
|
||||||
.journal_mode(sqlx::sqlite::SqliteJournalMode::Wal)
|
.journal_mode(sqlx::sqlite::SqliteJournalMode::Wal)
|
||||||
.synchronous(SqliteSynchronous::Normal)
|
.synchronous(SqliteSynchronous::Normal)
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
use crate::error::*;
|
|
||||||
use crate::BandwidthFlushingBehaviourConfig;
|
use crate::BandwidthFlushingBehaviourConfig;
|
||||||
use crate::ClientBandwidth;
|
use crate::ClientBandwidth;
|
||||||
|
use crate::error::*;
|
||||||
use nym_credentials::ecash::utils::ecash_today;
|
use nym_credentials::ecash::utils::ecash_today;
|
||||||
use nym_credentials_interface::Bandwidth;
|
use nym_credentials_interface::Bandwidth;
|
||||||
use nym_gateway_requests::ServerResponse;
|
use nym_gateway_requests::ServerResponse;
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
// Copyright 2022-2024 - Nym Technologies SA <contact@nymtech.net>
|
// Copyright 2022-2024 - Nym Technologies SA <contact@nymtech.net>
|
||||||
// SPDX-License-Identifier: GPL-3.0-only
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
|
use crate::Error;
|
||||||
use crate::ecash::error::EcashTicketError;
|
use crate::ecash::error::EcashTicketError;
|
||||||
use crate::ecash::helpers::for_each_api_concurrent;
|
use crate::ecash::helpers::for_each_api_concurrent;
|
||||||
use crate::ecash::state::SharedState;
|
use crate::ecash::state::SharedState;
|
||||||
use crate::Error;
|
|
||||||
use cosmwasm_std::Fraction;
|
use cosmwasm_std::Fraction;
|
||||||
use cw_utils::ThresholdResponse;
|
use cw_utils::ThresholdResponse;
|
||||||
use futures::channel::mpsc::UnboundedReceiver;
|
use futures::channel::mpsc::UnboundedReceiver;
|
||||||
@@ -13,22 +13,22 @@ use nym_api_requests::constants::MIN_BATCH_REDEMPTION_DELAY;
|
|||||||
use nym_api_requests::ecash::models::{BatchRedeemTicketsBody, VerifyEcashTicketBody};
|
use nym_api_requests::ecash::models::{BatchRedeemTicketsBody, VerifyEcashTicketBody};
|
||||||
use nym_credentials_interface::Bandwidth;
|
use nym_credentials_interface::Bandwidth;
|
||||||
use nym_credentials_interface::{ClientTicket, TicketType};
|
use nym_credentials_interface::{ClientTicket, TicketType};
|
||||||
|
use nym_validator_client::EcashApiClient;
|
||||||
use nym_validator_client::coconut::EcashApiError;
|
use nym_validator_client::coconut::EcashApiError;
|
||||||
use nym_validator_client::nym_api::{EpochId, NymApiClientExt};
|
use nym_validator_client::nym_api::{EpochId, NymApiClientExt};
|
||||||
|
use nym_validator_client::nyxd::AccountId;
|
||||||
use nym_validator_client::nyxd::contract_traits::{
|
use nym_validator_client::nyxd::contract_traits::{
|
||||||
EcashSigningClient, MultisigQueryClient, MultisigSigningClient, PagedMultisigQueryClient,
|
EcashSigningClient, MultisigQueryClient, MultisigSigningClient, PagedMultisigQueryClient,
|
||||||
};
|
};
|
||||||
use nym_validator_client::nyxd::cosmwasm_client::ContractResponseData;
|
use nym_validator_client::nyxd::cosmwasm_client::ContractResponseData;
|
||||||
use nym_validator_client::nyxd::cw3::Status;
|
use nym_validator_client::nyxd::cw3::Status;
|
||||||
use nym_validator_client::nyxd::AccountId;
|
|
||||||
use nym_validator_client::EcashApiClient;
|
|
||||||
use si_scale::helpers::bibytes2;
|
use si_scale::helpers::bibytes2;
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||||
use time::OffsetDateTime;
|
use time::OffsetDateTime;
|
||||||
use tokio::sync::{Mutex, RwLockReadGuard};
|
use tokio::sync::{Mutex, RwLockReadGuard};
|
||||||
use tokio::time::{interval_at, Duration, Instant};
|
use tokio::time::{Duration, Instant, interval_at};
|
||||||
use tracing::{debug, error, info, instrument, trace, warn};
|
use tracing::{debug, error, info, instrument, trace, warn};
|
||||||
|
|
||||||
enum ProposalResult {
|
enum ProposalResult {
|
||||||
@@ -352,7 +352,9 @@ impl CredentialHandler {
|
|||||||
Ok(accepted)
|
Ok(accepted)
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
error!("failed to send ticket {ticket_id} for verification to ecash signer '{client}': {err}. if we don't reach quorum, we'll retry later");
|
error!(
|
||||||
|
"failed to send ticket {ticket_id} for verification to ecash signer '{client}': {err}. if we don't reach quorum, we'll retry later"
|
||||||
|
);
|
||||||
Err(EcashTicketError::ApiFailure(EcashApiError::NymApi {
|
Err(EcashTicketError::ApiFailure(EcashApiError::NymApi {
|
||||||
source: nym_validator_client::ValidatorClientError::from(err),
|
source: nym_validator_client::ValidatorClientError::from(err),
|
||||||
}))
|
}))
|
||||||
@@ -443,7 +445,9 @@ impl CredentialHandler {
|
|||||||
let rejected_ratio = rejected as f32 / total as f32;
|
let rejected_ratio = rejected as f32 / total as f32;
|
||||||
let rejected_perc = rejected_ratio * 100.;
|
let rejected_perc = rejected_ratio * 100.;
|
||||||
if rejected_ratio >= (1. - self.config.minimum_api_quorum) {
|
if rejected_ratio >= (1. - self.config.minimum_api_quorum) {
|
||||||
error!("{rejected_perc:.2}% of signers rejected ticket {ticket_id}. we won't be able to redeem it");
|
error!(
|
||||||
|
"{rejected_perc:.2}% of signers rejected ticket {ticket_id}. we won't be able to redeem it"
|
||||||
|
);
|
||||||
|
|
||||||
self.shared_state
|
self.shared_state
|
||||||
.storage
|
.storage
|
||||||
@@ -456,12 +460,19 @@ impl CredentialHandler {
|
|||||||
let accepted_ratio = (total - rejected - num_failures) as f32 / total as f32;
|
let accepted_ratio = (total - rejected - num_failures) as f32 / total as f32;
|
||||||
let accepted_perc = accepted_ratio * 100.;
|
let accepted_perc = accepted_ratio * 100.;
|
||||||
match accepted_ratio {
|
match accepted_ratio {
|
||||||
n if n < self.multisig_threshold => error!("less than 2/3 of signers ({accepted_perc:.2}%) accepted ticket {ticket_id}. we won't be able to spend it"),
|
n if n < self.multisig_threshold => error!(
|
||||||
n if n < self.config.minimum_api_quorum => warn!("less than 80%, but more than 67% of signers ({accepted_perc:.2}%) accepted ticket {ticket_id}. technically we could redeem it, but we'll wait for the bigger quorum"),
|
"less than 2/3 of signers ({accepted_perc:.2}%) accepted ticket {ticket_id}. we won't be able to spend it"
|
||||||
|
),
|
||||||
|
n if n < self.config.minimum_api_quorum => warn!(
|
||||||
|
"less than 80%, but more than 67% of signers ({accepted_perc:.2}%) accepted ticket {ticket_id}. technically we could redeem it, but we'll wait for the bigger quorum"
|
||||||
|
),
|
||||||
_ => {
|
_ => {
|
||||||
trace!("{accepted_perc:.2}% of signers accepted ticket {ticket_id}");
|
trace!("{accepted_perc:.2}% of signers accepted ticket {ticket_id}");
|
||||||
self.shared_state.storage.update_verified_ticket(pending.ticket.ticket_id).await?;
|
self.shared_state
|
||||||
return Ok(true)
|
.storage
|
||||||
|
.update_verified_ticket(pending.ticket.ticket_id)
|
||||||
|
.await?;
|
||||||
|
return Ok(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -484,7 +495,10 @@ impl CredentialHandler {
|
|||||||
.send_pending_ticket_for_verification(&mut pending, Some(api_clients))
|
.send_pending_ticket_for_verification(&mut pending, Some(api_clients))
|
||||||
.await?;
|
.await?;
|
||||||
if !got_quorum {
|
if !got_quorum {
|
||||||
debug!("failed to reach quorum for ticket {}. apis: {:?} haven't responded. we'll retry later", pending.ticket.ticket_id, pending.pending);
|
debug!(
|
||||||
|
"failed to reach quorum for ticket {}. apis: {:?} haven't responded. we'll retry later",
|
||||||
|
pending.ticket.ticket_id, pending.pending
|
||||||
|
);
|
||||||
self.pending_tickets.push(pending);
|
self.pending_tickets.push(pending);
|
||||||
} else {
|
} else {
|
||||||
// since we reached the quorum we no longer need to hold the ticket's binary data
|
// since we reached the quorum we no longer need to hold the ticket's binary data
|
||||||
@@ -513,7 +527,10 @@ impl CredentialHandler {
|
|||||||
match self.try_resolve_pending_proposal(&mut pending, None).await {
|
match self.try_resolve_pending_proposal(&mut pending, None).await {
|
||||||
Ok(resolution) => {
|
Ok(resolution) => {
|
||||||
if resolution.is_pending() {
|
if resolution.is_pending() {
|
||||||
warn!("still failed to reach quorum for proposal {}. apis: {:?} haven't responded. we'll retry later", pending.proposal_id, pending.pending);
|
warn!(
|
||||||
|
"still failed to reach quorum for proposal {}. apis: {:?} haven't responded. we'll retry later",
|
||||||
|
pending.proposal_id, pending.pending
|
||||||
|
);
|
||||||
still_failing.push(pending);
|
still_failing.push(pending);
|
||||||
} else {
|
} else {
|
||||||
self.shared_state
|
self.shared_state
|
||||||
@@ -527,7 +544,9 @@ impl CredentialHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
error!("experienced internal error when attempting to resolve pending proposal: {err}");
|
error!(
|
||||||
|
"experienced internal error when attempting to resolve pending proposal: {err}"
|
||||||
|
);
|
||||||
// make sure to update internal state to not lose any data
|
// make sure to update internal state to not lose any data
|
||||||
self.pending_redemptions.push(pending);
|
self.pending_redemptions.push(pending);
|
||||||
self.pending_redemptions.append(&mut still_failing);
|
self.pending_redemptions.append(&mut still_failing);
|
||||||
@@ -547,7 +566,10 @@ impl CredentialHandler {
|
|||||||
{
|
{
|
||||||
Ok(got_quorum) => {
|
Ok(got_quorum) => {
|
||||||
if !got_quorum {
|
if !got_quorum {
|
||||||
warn!("still failed to reach quorum for ticket {}. apis: {:?} haven't responded. we'll retry later", pending.ticket.ticket_id, pending.pending);
|
warn!(
|
||||||
|
"still failed to reach quorum for ticket {}. apis: {:?} haven't responded. we'll retry later",
|
||||||
|
pending.ticket.ticket_id, pending.pending
|
||||||
|
);
|
||||||
still_failing.push(pending);
|
still_failing.push(pending);
|
||||||
} else {
|
} else {
|
||||||
// since we reached the quorum we no longer need to hold the ticket's binary data
|
// since we reached the quorum we no longer need to hold the ticket's binary data
|
||||||
@@ -558,7 +580,9 @@ impl CredentialHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
error!("experienced internal error when attempting to resolve pending ticket: {err}");
|
error!(
|
||||||
|
"experienced internal error when attempting to resolve pending ticket: {err}"
|
||||||
|
);
|
||||||
// make sure to update internal state to not lose any data
|
// make sure to update internal state to not lose any data
|
||||||
self.pending_tickets.push(pending);
|
self.pending_tickets.push(pending);
|
||||||
self.pending_tickets.append(&mut still_failing);
|
self.pending_tickets.append(&mut still_failing);
|
||||||
@@ -591,7 +615,9 @@ impl CredentialHandler {
|
|||||||
Ok(accepted)
|
Ok(accepted)
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
error!("failed to send proposal {proposal_id} for redemption vote to ecash signer '{client}': {err}. if we don't reach quorum, we'll retry later");
|
error!(
|
||||||
|
"failed to send proposal {proposal_id} for redemption vote to ecash signer '{client}': {err}. if we don't reach quorum, we'll retry later"
|
||||||
|
);
|
||||||
Ok(false)
|
Ok(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -713,7 +739,9 @@ impl CredentialHandler {
|
|||||||
let rejected_ratio = rejected as f32 / total as f32;
|
let rejected_ratio = rejected as f32 / total as f32;
|
||||||
let rejected_perc = rejected_ratio * 100.;
|
let rejected_perc = rejected_ratio * 100.;
|
||||||
if rejected_ratio >= (1. - self.multisig_threshold) {
|
if rejected_ratio >= (1. - self.multisig_threshold) {
|
||||||
error!("{rejected_perc:.2}% of signers rejected proposal {proposal_id}. we won't be able to execute it");
|
error!(
|
||||||
|
"{rejected_perc:.2}% of signers rejected proposal {proposal_id}. we won't be able to execute it"
|
||||||
|
);
|
||||||
// no need to query the chain as with so many rejections it's impossible it has passed.
|
// no need to query the chain as with so many rejections it's impossible it has passed.
|
||||||
return Ok(ProposalResult::Rejected);
|
return Ok(ProposalResult::Rejected);
|
||||||
}
|
}
|
||||||
@@ -722,11 +750,15 @@ impl CredentialHandler {
|
|||||||
let accepted_perc = accepted_ratio * 100.;
|
let accepted_perc = accepted_ratio * 100.;
|
||||||
match accepted_ratio {
|
match accepted_ratio {
|
||||||
n if n < self.multisig_threshold => {
|
n if n < self.multisig_threshold => {
|
||||||
error!("less than 2/3 of signers ({accepted_perc:.2}%) accepted proposal {proposal_id}. we're not yet be able to execute it to get funds out");
|
error!(
|
||||||
|
"less than 2/3 of signers ({accepted_perc:.2}%) accepted proposal {proposal_id}. we're not yet be able to execute it to get funds out"
|
||||||
|
);
|
||||||
return Ok(ProposalResult::Pending);
|
return Ok(ProposalResult::Pending);
|
||||||
}
|
}
|
||||||
n if n < self.config.minimum_api_quorum => {
|
n if n < self.config.minimum_api_quorum => {
|
||||||
warn!("the system seems to be a bit unstable: less than 80%, but more than 67% of signers ({accepted_perc:.2}%) accepted proposal {proposal_id}");
|
warn!(
|
||||||
|
"the system seems to be a bit unstable: less than 80%, but more than 67% of signers ({accepted_perc:.2}%) accepted proposal {proposal_id}"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
trace!("{accepted_perc:.2}% of signers accepted proposal {proposal_id}");
|
trace!("{accepted_perc:.2}% of signers accepted proposal {proposal_id}");
|
||||||
@@ -784,7 +816,9 @@ impl CredentialHandler {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
(_, Some(on_chain)) => {
|
(_, Some(on_chain)) => {
|
||||||
warn!("we seem to have crashed after creating proposal, but before persisting it onto disk!");
|
warn!(
|
||||||
|
"we seem to have crashed after creating proposal, but before persisting it onto disk!"
|
||||||
|
);
|
||||||
|
|
||||||
Some(on_chain)
|
Some(on_chain)
|
||||||
}
|
}
|
||||||
@@ -805,12 +839,20 @@ impl CredentialHandler {
|
|||||||
if latest_stored.created_at + self.config.maximum_time_between_redemption < now {
|
if latest_stored.created_at + self.config.maximum_time_between_redemption < now {
|
||||||
{}
|
{}
|
||||||
} else {
|
} else {
|
||||||
debug!("we only have {} verified tickets. there's no point in creating a redemption request yet. (we need at least {} (configurable))", verified_tickets.len(), self.config.minimum_redemption_tickets);
|
debug!(
|
||||||
|
"we only have {} verified tickets. there's no point in creating a redemption request yet. (we need at least {} (configurable))",
|
||||||
|
verified_tickets.len(),
|
||||||
|
self.config.minimum_redemption_tickets
|
||||||
|
);
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// first proposal
|
// first proposal
|
||||||
debug!("we only have {} verified tickets. there's no point in creating a redemption request yet. (we need at least {} (configurable))", verified_tickets.len(), self.config.minimum_redemption_tickets);
|
debug!(
|
||||||
|
"we only have {} verified tickets. there's no point in creating a redemption request yet. (we need at least {} (configurable))",
|
||||||
|
verified_tickets.len(),
|
||||||
|
self.config.minimum_redemption_tickets
|
||||||
|
);
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -879,7 +921,10 @@ impl CredentialHandler {
|
|||||||
.try_resolve_pending_proposal(&mut pending, Some(api_clients))
|
.try_resolve_pending_proposal(&mut pending, Some(api_clients))
|
||||||
.await?;
|
.await?;
|
||||||
if resolution.is_pending() {
|
if resolution.is_pending() {
|
||||||
warn!("failed to reach quorum for proposal {proposal_id}. apis: {:?} haven't responded. we'll retry later", pending.pending);
|
warn!(
|
||||||
|
"failed to reach quorum for proposal {proposal_id}. apis: {:?} haven't responded. we'll retry later",
|
||||||
|
pending.pending
|
||||||
|
);
|
||||||
self.pending_redemptions.push(pending);
|
self.pending_redemptions.push(pending);
|
||||||
} else {
|
} else {
|
||||||
self.shared_state
|
self.shared_state
|
||||||
@@ -896,7 +941,9 @@ impl CredentialHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn periodic_operations(&mut self) -> Result<(), EcashTicketError> {
|
async fn periodic_operations(&mut self) -> Result<(), EcashTicketError> {
|
||||||
trace!("attempting to resolve all pending operations -> tickets that are waiting for verification and possibly redemption");
|
trace!(
|
||||||
|
"attempting to resolve all pending operations -> tickets that are waiting for verification and possibly redemption"
|
||||||
|
);
|
||||||
|
|
||||||
// 1. retry all operations that have failed in the past: verification requests and pending redemption
|
// 1. retry all operations that have failed in the past: verification requests and pending redemption
|
||||||
self.resolve_pending().await?;
|
self.resolve_pending().await?;
|
||||||
|
|||||||
@@ -72,7 +72,9 @@ pub enum EcashTicketError {
|
|||||||
#[error("the DKG contract is unavailable")]
|
#[error("the DKG contract is unavailable")]
|
||||||
UnavailableDkgContract,
|
UnavailableDkgContract,
|
||||||
|
|
||||||
#[error("the DKG threshold value for epoch {epoch_id} is currently unavailable. we're probably mid-epoch transition")]
|
#[error(
|
||||||
|
"the DKG threshold value for epoch {epoch_id} is currently unavailable. we're probably mid-epoch transition"
|
||||||
|
)]
|
||||||
DKGThresholdUnavailable { epoch_id: EpochId },
|
DKGThresholdUnavailable { epoch_id: EpochId },
|
||||||
|
|
||||||
#[error("could not create redemption proposal as we have tickets pending full verification")]
|
#[error("could not create redemption proposal as we have tickets pending full verification")]
|
||||||
|
|||||||
@@ -9,10 +9,10 @@ use error::EcashTicketError;
|
|||||||
use futures::channel::mpsc::{self, UnboundedSender};
|
use futures::channel::mpsc::{self, UnboundedSender};
|
||||||
use nym_credentials::CredentialSpendingData;
|
use nym_credentials::CredentialSpendingData;
|
||||||
use nym_credentials_interface::{ClientTicket, CompactEcashError, NymPayInfo, VerificationKeyAuth};
|
use nym_credentials_interface::{ClientTicket, CompactEcashError, NymPayInfo, VerificationKeyAuth};
|
||||||
use nym_gateway_storage::traits::BandwidthGatewayStorage;
|
|
||||||
use nym_gateway_storage::GatewayStorage;
|
use nym_gateway_storage::GatewayStorage;
|
||||||
use nym_validator_client::nym_api::EpochId;
|
use nym_gateway_storage::traits::BandwidthGatewayStorage;
|
||||||
use nym_validator_client::DirectSigningHttpRpcNyxdClient;
|
use nym_validator_client::DirectSigningHttpRpcNyxdClient;
|
||||||
|
use nym_validator_client::nym_api::EpochId;
|
||||||
use state::SharedState;
|
use state::SharedState;
|
||||||
use time::OffsetDateTime;
|
use time::OffsetDateTime;
|
||||||
use tokio::sync::{Mutex, RwLockReadGuard};
|
use tokio::sync::{Mutex, RwLockReadGuard};
|
||||||
|
|||||||
@@ -1,19 +1,19 @@
|
|||||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
use crate::ecash::error::EcashTicketError;
|
|
||||||
use crate::Error;
|
use crate::Error;
|
||||||
use cosmwasm_std::{from_json, CosmosMsg, WasmMsg};
|
use crate::ecash::error::EcashTicketError;
|
||||||
|
use cosmwasm_std::{CosmosMsg, WasmMsg, from_json};
|
||||||
use nym_credentials_interface::VerificationKeyAuth;
|
use nym_credentials_interface::VerificationKeyAuth;
|
||||||
use nym_ecash_contract_common::msg::ExecuteMsg;
|
use nym_ecash_contract_common::msg::ExecuteMsg;
|
||||||
use nym_gateway_storage::traits::BandwidthGatewayStorage;
|
use nym_gateway_storage::traits::BandwidthGatewayStorage;
|
||||||
use nym_validator_client::coconut::all_ecash_api_clients;
|
use nym_validator_client::coconut::all_ecash_api_clients;
|
||||||
use nym_validator_client::nym_api::EpochId;
|
use nym_validator_client::nym_api::EpochId;
|
||||||
|
use nym_validator_client::nyxd::AccountId;
|
||||||
use nym_validator_client::nyxd::contract_traits::{
|
use nym_validator_client::nyxd::contract_traits::{
|
||||||
DkgQueryClient, MultisigQueryClient, NymContractsProvider,
|
DkgQueryClient, MultisigQueryClient, NymContractsProvider,
|
||||||
};
|
};
|
||||||
use nym_validator_client::nyxd::cw3::ProposalResponse;
|
use nym_validator_client::nyxd::cw3::ProposalResponse;
|
||||||
use nym_validator_client::nyxd::AccountId;
|
|
||||||
use nym_validator_client::{DirectSigningHttpRpcNyxdClient, EcashApiClient};
|
use nym_validator_client::{DirectSigningHttpRpcNyxdClient, EcashApiClient};
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
@@ -53,7 +53,9 @@ impl SharedState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let Ok(current_epoch) = nyxd_client.get_current_epoch().await else {
|
let Ok(current_epoch) = nyxd_client.get_current_epoch().await else {
|
||||||
error!("the specified DKG contract address is invalid - no coconut credentials will be redeemable");
|
error!(
|
||||||
|
"the specified DKG contract address is invalid - no coconut credentials will be redeemable"
|
||||||
|
);
|
||||||
// if we require coconut credentials, we MUST have DKG contract available
|
// if we require coconut credentials, we MUST have DKG contract available
|
||||||
return Err(EcashTicketError::UnavailableDkgContract.into());
|
return Err(EcashTicketError::UnavailableDkgContract.into());
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -35,7 +35,9 @@ pub enum Error {
|
|||||||
#[error("This gateway is only accepting coconut credentials for bandwidth")]
|
#[error("This gateway is only accepting coconut credentials for bandwidth")]
|
||||||
OnlyCoconutCredentials,
|
OnlyCoconutCredentials,
|
||||||
|
|
||||||
#[error("insufficient bandwidth available to process the request. required: {required}B, available: {available}B")]
|
#[error(
|
||||||
|
"insufficient bandwidth available to process the request. required: {required}B, available: {available}B"
|
||||||
|
)]
|
||||||
OutOfBandwidth { required: i64, available: i64 },
|
OutOfBandwidth { required: i64, available: i64 },
|
||||||
|
|
||||||
#[error("Internal gateway storage error")]
|
#[error("Internal gateway storage error")]
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
use crate::ecash::traits::EcashManager;
|
use crate::ecash::traits::EcashManager;
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use bandwidth_storage_manager::BandwidthStorageManager;
|
use bandwidth_storage_manager::BandwidthStorageManager;
|
||||||
use nym_credentials::ecash::utils::{cred_exp_date, ecash_today, EcashTime};
|
use nym_credentials::ecash::utils::{EcashTime, cred_exp_date, ecash_today};
|
||||||
use nym_credentials_interface::{Bandwidth, ClientTicket, TicketType};
|
use nym_credentials_interface::{Bandwidth, ClientTicket, TicketType};
|
||||||
use nym_gateway_requests::models::CredentialSpendingRequest;
|
use nym_gateway_requests::models::CredentialSpendingRequest;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|||||||
@@ -7,9 +7,12 @@ use thiserror::Error;
|
|||||||
use time::{Date, OffsetDateTime};
|
use time::{Date, OffsetDateTime};
|
||||||
|
|
||||||
pub use nym_compact_ecash::{
|
pub use nym_compact_ecash::{
|
||||||
|
Base58, BlindedSignature, Bytable, EncodedDate, EncodedTicketType, PartialWallet, PayInfo,
|
||||||
|
PublicKeyUser, SecretKeyUser, VerificationKeyAuth, WithdrawalRequest,
|
||||||
aggregate_verification_keys, aggregate_wallets, constants, ecash_parameters,
|
aggregate_verification_keys, aggregate_wallets, constants, ecash_parameters,
|
||||||
error::CompactEcashError,
|
error::CompactEcashError,
|
||||||
generate_keypair_user, generate_keypair_user_from_seed, issue_verify,
|
generate_keypair_user, generate_keypair_user_from_seed, issue_verify,
|
||||||
|
scheme::Payment,
|
||||||
scheme::coin_indices_signatures::aggregate_indices_signatures,
|
scheme::coin_indices_signatures::aggregate_indices_signatures,
|
||||||
scheme::coin_indices_signatures::{
|
scheme::coin_indices_signatures::{
|
||||||
AnnotatedCoinIndexSignature, CoinIndexSignature, CoinIndexSignatureShare,
|
AnnotatedCoinIndexSignature, CoinIndexSignature, CoinIndexSignatureShare,
|
||||||
@@ -22,12 +25,10 @@ pub use nym_compact_ecash::{
|
|||||||
},
|
},
|
||||||
scheme::keygen::KeyPairUser,
|
scheme::keygen::KeyPairUser,
|
||||||
scheme::withdrawal::RequestInfo,
|
scheme::withdrawal::RequestInfo,
|
||||||
scheme::Payment,
|
|
||||||
scheme::{Wallet, WalletSignatures},
|
scheme::{Wallet, WalletSignatures},
|
||||||
withdrawal_request, Base58, BlindedSignature, Bytable, EncodedDate, EncodedTicketType,
|
withdrawal_request,
|
||||||
PartialWallet, PayInfo, PublicKeyUser, SecretKeyUser, VerificationKeyAuth, WithdrawalRequest,
|
|
||||||
};
|
};
|
||||||
pub use nym_ecash_time::{ecash_today, EcashTime};
|
pub use nym_ecash_time::{EcashTime, ecash_today};
|
||||||
pub use nym_network_defaults::TicketTypeRepr;
|
pub use nym_network_defaults::TicketTypeRepr;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
pub use ed25519_dalek::SignatureError;
|
pub use ed25519_dalek::SignatureError;
|
||||||
pub use ed25519_dalek::{Verifier, PUBLIC_KEY_LENGTH, SECRET_KEY_LENGTH, SIGNATURE_LENGTH};
|
pub use ed25519_dalek::{PUBLIC_KEY_LENGTH, SECRET_KEY_LENGTH, SIGNATURE_LENGTH, Verifier};
|
||||||
|
|
||||||
use ed25519_dalek::Signer;
|
use ed25519_dalek::Signer;
|
||||||
use nym_pemstore::traits::{PemStorableKey, PemStorableKeyPair};
|
use nym_pemstore::traits::{PemStorableKey, PemStorableKeyPair};
|
||||||
@@ -18,7 +18,7 @@ pub mod serde_helpers;
|
|||||||
pub use serde_helpers::*;
|
pub use serde_helpers::*;
|
||||||
|
|
||||||
#[cfg(feature = "sphinx")]
|
#[cfg(feature = "sphinx")]
|
||||||
use nym_sphinx_types::{DestinationAddressBytes, DESTINATION_ADDRESS_LENGTH};
|
use nym_sphinx_types::{DESTINATION_ADDRESS_LENGTH, DestinationAddressBytes};
|
||||||
|
|
||||||
#[cfg(feature = "rand")]
|
#[cfg(feature = "rand")]
|
||||||
use rand::{CryptoRng, Rng, RngCore};
|
use rand::{CryptoRng, Rng, RngCore};
|
||||||
@@ -75,7 +75,7 @@ pub struct KeyPair {
|
|||||||
impl KeyPair {
|
impl KeyPair {
|
||||||
#[cfg(feature = "rand")]
|
#[cfg(feature = "rand")]
|
||||||
pub fn new<R: RngCore + CryptoRng>(rng: &mut R) -> Self {
|
pub fn new<R: RngCore + CryptoRng>(rng: &mut R) -> Self {
|
||||||
let index = rng.gen();
|
let index = rng.r#gen();
|
||||||
let ed25519_signing_key = ed25519_dalek::SigningKey::generate(rng);
|
let ed25519_signing_key = ed25519_dalek::SigningKey::generate(rng);
|
||||||
|
|
||||||
KeyPair {
|
KeyPair {
|
||||||
@@ -504,10 +504,12 @@ mod tests {
|
|||||||
jwt_simple::algorithms::Edwards25519KeyPair::from_bytes(&jwt_keys.to_bytes()).unwrap();
|
jwt_simple::algorithms::Edwards25519KeyPair::from_bytes(&jwt_keys.to_bytes()).unwrap();
|
||||||
|
|
||||||
let compact_ed25519 = jwt_keys_inner.as_ref();
|
let compact_ed25519 = jwt_keys_inner.as_ref();
|
||||||
assert!(compact_ed25519
|
assert!(
|
||||||
.sk
|
compact_ed25519
|
||||||
.validate_public_key(&compact_ed25519.pk)
|
.sk
|
||||||
.is_ok());
|
.validate_public_key(&compact_ed25519.pk)
|
||||||
|
.is_ok()
|
||||||
|
);
|
||||||
|
|
||||||
let dummy_message = "hello world";
|
let dummy_message = "hello world";
|
||||||
let sig1 = keys.private_key.sign(dummy_message).to_bytes();
|
let sig1 = keys.private_key.sign(dummy_message).to_bytes();
|
||||||
|
|||||||
@@ -168,6 +168,10 @@ impl PublicKey {
|
|||||||
pub fn to_base64(&self) -> String {
|
pub fn to_base64(&self) -> String {
|
||||||
base64::engine::general_purpose::STANDARD.encode(self.as_bytes())
|
base64::engine::general_purpose::STANDARD.encode(self.as_bytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn inner(&self) -> x25519_dalek::PublicKey {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromStr for PublicKey {
|
impl FromStr for PublicKey {
|
||||||
|
|||||||
@@ -2,11 +2,11 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
use hkdf::{
|
use hkdf::{
|
||||||
hmac::{
|
|
||||||
digest::{crypto_common::BlockSizeUser, Digest},
|
|
||||||
SimpleHmac,
|
|
||||||
},
|
|
||||||
Hkdf,
|
Hkdf,
|
||||||
|
hmac::{
|
||||||
|
SimpleHmac,
|
||||||
|
digest::{Digest, crypto_common::BlockSizeUser},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
use sha2::{Sha256, Sha512};
|
use sha2::{Sha256, Sha512};
|
||||||
|
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
use hmac::{
|
use hmac::{
|
||||||
digest::{crypto_common::BlockSizeUser, CtOutput, Digest, Output},
|
|
||||||
Mac, SimpleHmac,
|
Mac, SimpleHmac,
|
||||||
|
digest::{CtOutput, Digest, Output, crypto_common::BlockSizeUser},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub use hmac;
|
pub use hmac;
|
||||||
|
|||||||
@@ -4,8 +4,8 @@
|
|||||||
use crate::asymmetric::x25519;
|
use crate::asymmetric::x25519;
|
||||||
use crate::hkdf;
|
use crate::hkdf;
|
||||||
use cipher::{Key, KeyIvInit, StreamCipher};
|
use cipher::{Key, KeyIvInit, StreamCipher};
|
||||||
use digest::crypto_common::BlockSizeUser;
|
|
||||||
use digest::Digest;
|
use digest::Digest;
|
||||||
|
use digest::crypto_common::BlockSizeUser;
|
||||||
|
|
||||||
#[cfg(feature = "rand")]
|
#[cfg(feature = "rand")]
|
||||||
use rand::{CryptoRng, RngCore};
|
use rand::{CryptoRng, RngCore};
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ nym-contracts-common = { path = "../cosmwasm-smart-contracts/contracts-common",
|
|||||||
bs58 = { workspace = true }
|
bs58 = { workspace = true }
|
||||||
|
|
||||||
|
|
||||||
lazy_static = { workspace = true }
|
|
||||||
rand = { workspace = true }
|
rand = { workspace = true }
|
||||||
rand_chacha = { workspace = true }
|
rand_chacha = { workspace = true }
|
||||||
rand_core = { workspace = true }
|
rand_core = { workspace = true }
|
||||||
|
|||||||
@@ -13,9 +13,9 @@ use rand::CryptoRng;
|
|||||||
use rand_core::RngCore;
|
use rand_core::RngCore;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::ops::Neg;
|
use std::ops::Neg;
|
||||||
use zeroize::Zeroize;
|
use zeroize::{Zeroize, ZeroizeOnDrop};
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq, Zeroize, ZeroizeOnDrop)]
|
||||||
pub struct Ciphertexts {
|
pub struct Ciphertexts {
|
||||||
pub rr: [G1Projective; NUM_CHUNKS],
|
pub rr: [G1Projective; NUM_CHUNKS],
|
||||||
pub ss: [G1Projective; NUM_CHUNKS],
|
pub ss: [G1Projective; NUM_CHUNKS],
|
||||||
@@ -164,8 +164,7 @@ impl Ciphertexts {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Zeroize)]
|
#[derive(Zeroize, ZeroizeOnDrop)]
|
||||||
#[zeroize(drop)]
|
|
||||||
/// Randomness generated during ciphertext generation that is required for proofs of knowledge.
|
/// Randomness generated during ciphertext generation that is required for proofs of knowledge.
|
||||||
///
|
///
|
||||||
/// It must be handled with extreme care as its misuse might help malicious parties to recover
|
/// It must be handled with extreme care as its misuse might help malicious parties to recover
|
||||||
@@ -399,7 +398,7 @@ pub fn baby_step_giant_step(
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::bte::{keygen, setup, DEFAULT_BSGS_TABLE};
|
use crate::bte::{keygen, setup, BSGS_TABLE};
|
||||||
use rand_core::SeedableRng;
|
use rand_core::SeedableRng;
|
||||||
|
|
||||||
fn verify_hazmat_rand(ciphertext: &Ciphertexts, randomness: &HazmatRandomness) {
|
fn verify_hazmat_rand(ciphertext: &Ciphertexts, randomness: &HazmatRandomness) {
|
||||||
@@ -457,8 +456,6 @@ mod tests {
|
|||||||
let (decryption_key1, public_key1) = keygen(¶ms, &mut rng);
|
let (decryption_key1, public_key1) = keygen(¶ms, &mut rng);
|
||||||
let (decryption_key2, public_key2) = keygen(¶ms, &mut rng);
|
let (decryption_key2, public_key2) = keygen(¶ms, &mut rng);
|
||||||
|
|
||||||
let lookup_table = &DEFAULT_BSGS_TABLE;
|
|
||||||
|
|
||||||
for _ in 0..10 {
|
for _ in 0..10 {
|
||||||
let m1 = Share::random(&mut rng);
|
let m1 = Share::random(&mut rng);
|
||||||
let m2 = Share::random(&mut rng);
|
let m2 = Share::random(&mut rng);
|
||||||
@@ -467,22 +464,12 @@ mod tests {
|
|||||||
let (ciphertext, hazmat) = encrypt_shares(shares, ¶ms, &mut rng);
|
let (ciphertext, hazmat) = encrypt_shares(shares, ¶ms, &mut rng);
|
||||||
verify_hazmat_rand(&ciphertext, &hazmat);
|
verify_hazmat_rand(&ciphertext, &hazmat);
|
||||||
|
|
||||||
let recovered1 = decrypt_share(
|
let recovered1 =
|
||||||
¶ms,
|
decrypt_share(¶ms, &decryption_key1, 0, &ciphertext, Some(&BSGS_TABLE))
|
||||||
&decryption_key1,
|
.unwrap();
|
||||||
0,
|
let recovered2 =
|
||||||
&ciphertext,
|
decrypt_share(¶ms, &decryption_key2, 1, &ciphertext, Some(&BSGS_TABLE))
|
||||||
Some(lookup_table),
|
.unwrap();
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
let recovered2 = decrypt_share(
|
|
||||||
¶ms,
|
|
||||||
&decryption_key2,
|
|
||||||
1,
|
|
||||||
&ciphertext,
|
|
||||||
Some(lookup_table),
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
assert_eq!(m1, recovered1);
|
assert_eq!(m1, recovered1);
|
||||||
assert_eq!(m2, recovered2);
|
assert_eq!(m2, recovered2);
|
||||||
}
|
}
|
||||||
@@ -498,8 +485,6 @@ mod tests {
|
|||||||
let (decryption_key1, public_key1) = keygen(¶ms, &mut rng);
|
let (decryption_key1, public_key1) = keygen(¶ms, &mut rng);
|
||||||
let (decryption_key2, public_key2) = keygen(¶ms, &mut rng);
|
let (decryption_key2, public_key2) = keygen(¶ms, &mut rng);
|
||||||
|
|
||||||
let lookup_table = &DEFAULT_BSGS_TABLE;
|
|
||||||
|
|
||||||
for _ in 0..10 {
|
for _ in 0..10 {
|
||||||
let m1 = Share::random(&mut rng);
|
let m1 = Share::random(&mut rng);
|
||||||
let m2 = Share::random(&mut rng);
|
let m2 = Share::random(&mut rng);
|
||||||
@@ -508,22 +493,12 @@ mod tests {
|
|||||||
let (ciphertext, hazmat) = encrypt_shares(shares, ¶ms, &mut rng);
|
let (ciphertext, hazmat) = encrypt_shares(shares, ¶ms, &mut rng);
|
||||||
verify_hazmat_rand(&ciphertext, &hazmat);
|
verify_hazmat_rand(&ciphertext, &hazmat);
|
||||||
|
|
||||||
let recovered1 = decrypt_share(
|
let recovered1 =
|
||||||
¶ms,
|
decrypt_share(¶ms, &decryption_key1, 0, &ciphertext, Some(&BSGS_TABLE))
|
||||||
&decryption_key1,
|
.unwrap();
|
||||||
0,
|
let recovered2 =
|
||||||
&ciphertext,
|
decrypt_share(¶ms, &decryption_key2, 1, &ciphertext, Some(&BSGS_TABLE))
|
||||||
Some(lookup_table),
|
.unwrap();
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
let recovered2 = decrypt_share(
|
|
||||||
¶ms,
|
|
||||||
&decryption_key2,
|
|
||||||
1,
|
|
||||||
&ciphertext,
|
|
||||||
Some(lookup_table),
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
assert_eq!(m1, recovered1);
|
assert_eq!(m1, recovered1);
|
||||||
assert_eq!(m2, recovered2);
|
assert_eq!(m2, recovered2);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ use group::GroupEncoding;
|
|||||||
use nym_pemstore::traits::{PemStorableKey, PemStorableKeyPair};
|
use nym_pemstore::traits::{PemStorableKey, PemStorableKeyPair};
|
||||||
use rand::CryptoRng;
|
use rand::CryptoRng;
|
||||||
use rand_core::RngCore;
|
use rand_core::RngCore;
|
||||||
use zeroize::Zeroize;
|
use zeroize::{Zeroize, ZeroizeOnDrop};
|
||||||
|
|
||||||
// produces public key and a decryption key for the root of the tree
|
// produces public key and a decryption key for the root of the tree
|
||||||
pub fn keygen(
|
pub fn keygen(
|
||||||
@@ -48,7 +48,7 @@ pub fn keygen(
|
|||||||
(dk, key_with_proof)
|
(dk, key_with_proof)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Zeroize)]
|
||||||
pub struct PublicKey(pub(crate) G1Projective);
|
pub struct PublicKey(pub(crate) G1Projective);
|
||||||
|
|
||||||
impl PublicKey {
|
impl PublicKey {
|
||||||
@@ -57,7 +57,7 @@ impl PublicKey {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq, Zeroize, ZeroizeOnDrop)]
|
||||||
pub struct PublicKeyWithProof {
|
pub struct PublicKeyWithProof {
|
||||||
pub(crate) key: PublicKey,
|
pub(crate) key: PublicKey,
|
||||||
pub(crate) proof: ProofOfDiscreteLog,
|
pub(crate) proof: ProofOfDiscreteLog,
|
||||||
@@ -136,8 +136,7 @@ impl PublicKeyWithProof {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Zeroize)]
|
#[derive(Debug, Zeroize, ZeroizeOnDrop)]
|
||||||
#[zeroize(drop)]
|
|
||||||
#[cfg_attr(test, derive(PartialEq, Eq))]
|
#[cfg_attr(test, derive(PartialEq, Eq))]
|
||||||
pub struct DecryptionKey {
|
pub struct DecryptionKey {
|
||||||
// g1^rho
|
// g1^rho
|
||||||
@@ -242,6 +241,7 @@ impl DecryptionKey {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Zeroize, ZeroizeOnDrop)]
|
||||||
pub struct KeyPair {
|
pub struct KeyPair {
|
||||||
pub(crate) private_key: DecryptionKey,
|
pub(crate) private_key: DecryptionKey,
|
||||||
pub(crate) public_key: PublicKeyWithProof,
|
pub(crate) public_key: PublicKeyWithProof,
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
use std::sync::LazyLock;
|
||||||
|
|
||||||
|
use crate::bte::encryption::BabyStepGiantStepLookup;
|
||||||
use crate::utils::hash_g2;
|
use crate::utils::hash_g2;
|
||||||
use crate::{Chunk, Share};
|
use crate::{Chunk, Share};
|
||||||
use bls12_381::{G1Affine, G2Affine, G2Prepared, G2Projective, Gt};
|
use bls12_381::{G1Affine, G2Affine, G2Prepared, G2Projective, Gt};
|
||||||
use group::Curve;
|
use group::Curve;
|
||||||
use lazy_static::lazy_static;
|
|
||||||
|
|
||||||
pub mod encryption;
|
pub mod encryption;
|
||||||
pub mod keys;
|
pub mod keys;
|
||||||
@@ -16,14 +18,12 @@ pub mod proof_sharing;
|
|||||||
pub use encryption::{decrypt_share, encrypt_shares, Ciphertexts};
|
pub use encryption::{decrypt_share, encrypt_shares, Ciphertexts};
|
||||||
pub use keys::{keygen, DecryptionKey, PublicKey, PublicKeyWithProof};
|
pub use keys::{keygen, DecryptionKey, PublicKey, PublicKeyWithProof};
|
||||||
|
|
||||||
lazy_static! {
|
pub(crate) static PAIRING_BASE: LazyLock<Gt> =
|
||||||
pub(crate) static ref PAIRING_BASE: Gt =
|
LazyLock::new(|| bls12_381::pairing(&G1Affine::generator(), &G2Affine::generator()));
|
||||||
bls12_381::pairing(&G1Affine::generator(), &G2Affine::generator());
|
pub(crate) static G2_GENERATOR_PREPARED: LazyLock<G2Prepared> =
|
||||||
pub(crate) static ref G2_GENERATOR_PREPARED: G2Prepared =
|
LazyLock::new(|| G2Prepared::from(G2Affine::generator()));
|
||||||
G2Prepared::from(G2Affine::generator());
|
pub static BSGS_TABLE: LazyLock<BabyStepGiantStepLookup> =
|
||||||
pub(crate) static ref DEFAULT_BSGS_TABLE: encryption::BabyStepGiantStepLookup =
|
LazyLock::new(BabyStepGiantStepLookup::default);
|
||||||
encryption::BabyStepGiantStepLookup::default();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Domain tries to follow guidelines specified by:
|
// Domain tries to follow guidelines specified by:
|
||||||
// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-3.1
|
// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-3.1
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ use ff::Field;
|
|||||||
use group::{Group, GroupEncoding};
|
use group::{Group, GroupEncoding};
|
||||||
use rand::{CryptoRng, Rng};
|
use rand::{CryptoRng, Rng};
|
||||||
use rand_core::{RngCore, SeedableRng};
|
use rand_core::{RngCore, SeedableRng};
|
||||||
|
use zeroize::{Zeroize, ZeroizeOnDrop};
|
||||||
|
|
||||||
const CHUNKING_ORACLE_DOMAIN: &[u8] =
|
const CHUNKING_ORACLE_DOMAIN: &[u8] =
|
||||||
b"NYM_COCONUT_NIDKG_V01_CS01_SHA-256_CHACHA20_CHUNKING_ORACLE";
|
b"NYM_COCONUT_NIDKG_V01_CS01_SHA-256_CHACHA20_CHUNKING_ORACLE";
|
||||||
@@ -67,7 +68,7 @@ impl<'a> Instance<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq, Zeroize, ZeroizeOnDrop)]
|
||||||
pub struct ProofOfChunking {
|
pub struct ProofOfChunking {
|
||||||
y0: G1Projective,
|
y0: G1Projective,
|
||||||
bb: Vec<G1Projective>,
|
bb: Vec<G1Projective>,
|
||||||
|
|||||||
@@ -7,14 +7,14 @@ use ff::Field;
|
|||||||
use group::GroupEncoding;
|
use group::GroupEncoding;
|
||||||
use rand::CryptoRng;
|
use rand::CryptoRng;
|
||||||
use rand_core::RngCore;
|
use rand_core::RngCore;
|
||||||
use zeroize::Zeroize;
|
use zeroize::{Zeroize, ZeroizeOnDrop};
|
||||||
|
|
||||||
// Domain tries to follow guidelines specified by:
|
// Domain tries to follow guidelines specified by:
|
||||||
// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-3.1
|
// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-3.1
|
||||||
const DISCRETE_LOG_DOMAIN: &[u8] =
|
const DISCRETE_LOG_DOMAIN: &[u8] =
|
||||||
b"NYM_COCONUT_NIDKG_V01_CS01_WITH_BLS12381_XMD:SHA-256_SSWU_RO_PROOF_DISCRETE_LOG";
|
b"NYM_COCONUT_NIDKG_V01_CS01_WITH_BLS12381_XMD:SHA-256_SSWU_RO_PROOF_DISCRETE_LOG";
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq, Zeroize, ZeroizeOnDrop)]
|
||||||
pub struct ProofOfDiscreteLog {
|
pub struct ProofOfDiscreteLog {
|
||||||
pub(crate) rand_commitment: G1Projective,
|
pub(crate) rand_commitment: G1Projective,
|
||||||
pub(crate) response: Scalar,
|
pub(crate) response: Scalar,
|
||||||
@@ -52,9 +52,9 @@ impl ProofOfDiscreteLog {
|
|||||||
let public_bytes = public.to_bytes();
|
let public_bytes = public.to_bytes();
|
||||||
let rand_commit_bytes = rand_commit.to_bytes();
|
let rand_commit_bytes = rand_commit.to_bytes();
|
||||||
|
|
||||||
let mut bytes = Vec::with_capacity(96);
|
let mut bytes = [0u8; 96];
|
||||||
bytes.extend_from_slice(public_bytes.as_ref());
|
bytes[0..48].copy_from_slice(public_bytes.as_ref());
|
||||||
bytes.extend_from_slice(rand_commit_bytes.as_ref());
|
bytes[48..96].copy_from_slice(rand_commit_bytes.as_ref());
|
||||||
|
|
||||||
hash_to_scalar(bytes, DISCRETE_LOG_DOMAIN)
|
hash_to_scalar(bytes, DISCRETE_LOG_DOMAIN)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ use group::GroupEncoding;
|
|||||||
use rand::CryptoRng;
|
use rand::CryptoRng;
|
||||||
use rand_core::RngCore;
|
use rand_core::RngCore;
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
use zeroize::{Zeroize, ZeroizeOnDrop};
|
||||||
|
|
||||||
// Domain tries to follow guidelines specified by:
|
// Domain tries to follow guidelines specified by:
|
||||||
// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-3.1
|
// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-3.1
|
||||||
@@ -77,7 +78,7 @@ impl<'a> Instance<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq, Zeroize, ZeroizeOnDrop)]
|
||||||
pub struct ProofOfSecretSharing {
|
pub struct ProofOfSecretSharing {
|
||||||
ff: G1Projective,
|
ff: G1Projective,
|
||||||
aa: G2Projective,
|
aa: G2Projective,
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user