Compare commits

..

23 Commits

Author SHA1 Message Date
fmtabbara 6a19e1a9dc use compiled wasm for wallet node tester 2023-06-27 14:33:51 +01:00
fmtabbara 23f7996b7c move client wasm to wallet dir 2023-06-27 12:53:21 +01:00
pierre 597f5e9545 ci: fix typescript-lint.yml workflow 2023-06-26 16:21:37 +02:00
pierre 54cb7be1e1 chore: update copyright notice in comment headers 2023-06-26 16:09:24 +02:00
pierre 431c98e591 chore: update copyright notice date 2023-06-26 15:46:11 +02:00
Jon Häggblad 35f2e71202 Don't fully turn off background task when cover traffic is disabled (#3596)
* Don't fully turn off background task when cover traffic is disabled

* Leave no_cover function alone

* Add methods on config struct instead of explicitly setting options

* Add medium toggle to network-requester run command

* clippy

* rustfmt

* Unused
2023-06-26 15:36:07 +02:00
Jon Häggblad f298f5d4fa Auto-upgrade nym-connect config files (#3589)
* nym-connect: auto-upgrade old config files

* Move upgrade functions to separate file
2023-06-26 10:09:45 +02:00
Fouad 0115b02be3 Wallet - Node Tester (#3551)
* error handling + edge cases + types

* use bonded node id

* add UI and move feature to node-settings dir

* use error modal

* add type for postMessage arg

* add timeout for node test

* update storybook ci

* fix CI for typescript linting

* fix print node test results

* replace react-to-print lib with vanilla solution

* async print

* update wallet changelog
2023-06-23 14:00:28 +01:00
Jon Häggblad a4ffd135e7 Fix the medium toggle in nym-connect (#3590) 2023-06-22 16:30:25 +02:00
Jon Häggblad 7be07c29c1 Cargo.lock 2023-06-22 10:59:59 +02:00
Jon Häggblad 4af70ef255 nym-connect: medium speed setting (#3585)
* Lock files

* Add flag to disable cover traffic

* Add flag to disable per hop delays

* Add flag to enable mixed size packets

* Add meta flag to set medium speed

* Special case zero averge hop delay to be exactly zero

* Extract out generate_hop_delays function
2023-06-22 10:55:35 +02:00
Jędrzej Stuczyński eba58f6451 NC: load old gateway configuration if we're not registering (#3586) 2023-06-22 08:49:00 +01:00
Jon Häggblad e14db00fc2 nym-cli: client identity signing support (#3575)
* Add client identity key signing to nym-cli

* Only load private key

* rustfmt

* Rename to identity key since it's generic

* Rename client_key to identity_key
2023-06-20 14:48:53 +02:00
benedettadavico 72b92784cc Merge remote-tracking branch 'origin/develop' into develop 2023-06-20 13:45:29 +02:00
benedettadavico 38b95c2673 nym connect version fix 2023-06-20 13:45:04 +02:00
Mark Sinclair f0f9899f82 Update package.json to fix build:dev target 2023-06-20 12:12:03 +01:00
benedettadavico 09c46e3403 Merge remote-tracking branch 'origin/master' into develop 2023-06-20 10:36:06 +02:00
Jędrzej Stuczyński 8f57919571 optional id argument for NymNodeTester (#3555) 2023-06-16 11:19:40 +01:00
pierre 3cdca0ad8d copy change 2023-06-16 11:20:20 +02:00
pierre 4c13d91bfb fix(nyms5-android): add check for worker and proxy states desync 2023-06-16 10:08:57 +02:00
Pierre Dommerc 8355e6ce5e feat(nc-desktop): add error reporting and monitoring setting (#3553) 2023-06-15 19:23:23 +02:00
Jędrzej Stuczyński bbb1e5e15a Feature/node tester disconnect (#3552)
* Ability to disconnect and reconnect GatewayClient

* usage of ibid. inside NodeTester

* example

* wasm-compatible `wait_for_shutdown` (for the future)
2023-06-13 17:25:42 +01:00
Drazen Urch 6d30e7ea8e Adjustments to cover traffic and ack handling (#3548) 2023-06-13 13:07:02 +02:00
129 changed files with 8022 additions and 2676 deletions
@@ -19,6 +19,10 @@ jobs:
node-version: 16
- name: Setup yarn
run: npm install -g yarn
- name: Install Rust stable
uses: actions-rs/toolchain@v1
with:
toolchain: stable
- name: Build dependencies
run: yarn && yarn build
- name: Build storybook
+4
View File
@@ -36,6 +36,10 @@ jobs:
node-version: 16
- name: Setup yarn
run: npm install -g yarn
- name: Install Rust stable
uses: actions-rs/toolchain@v1
with:
toolchain: stable
- name: Install
run: yarn
- name: Build packages
Generated
+11 -146
View File
@@ -1275,7 +1275,7 @@ dependencies = [
"openssl-probe",
"openssl-sys",
"schannel",
"socket2 0.4.9",
"socket2",
"winapi",
]
@@ -2518,7 +2518,7 @@ dependencies = [
"httpdate",
"itoa",
"pin-project-lite",
"socket2 0.4.9",
"socket2",
"tokio",
"tower-service",
"tracing",
@@ -2537,7 +2537,7 @@ dependencies = [
"http",
"hyper",
"hyper-rustls",
"rustls-native-certs 0.5.0",
"rustls-native-certs",
"tokio",
"tokio-rustls 0.22.0",
"tower-service",
@@ -2555,7 +2555,7 @@ dependencies = [
"hyper",
"log",
"rustls 0.19.1",
"rustls-native-certs 0.5.0",
"rustls-native-certs",
"tokio",
"tokio-rustls 0.22.0",
"webpki 0.21.4",
@@ -3507,8 +3507,10 @@ dependencies = [
"nym-multisig-contract-common",
"nym-name-service-common",
"nym-network-defaults",
"nym-pemstore",
"nym-service-provider-directory-common",
"nym-sphinx",
"nym-types",
"nym-validator-client",
"nym-vesting-contract-common",
"rand 0.6.5",
@@ -3804,7 +3806,6 @@ dependencies = [
"atty",
"bip39",
"bs58",
"bytes",
"clap 4.2.7",
"colored",
"dashmap 4.0.2",
@@ -3832,10 +3833,7 @@ dependencies = [
"nym-validator-client",
"once_cell",
"pretty_env_logger",
"quinn",
"rand 0.7.3",
"rcgen",
"rustls 0.21.2",
"serde",
"serde_json",
"sqlx 0.5.13",
@@ -3923,13 +3921,10 @@ dependencies = [
name = "nym-mixnet-client"
version = "0.1.0"
dependencies = [
"bytes",
"futures",
"log",
"nym-sphinx",
"nym-task",
"quinn",
"rustls 0.21.2",
"tokio",
"tokio-util",
]
@@ -3959,7 +3954,6 @@ version = "1.1.23"
dependencies = [
"anyhow",
"bs58",
"bytes",
"cfg-if",
"clap 4.2.7",
"colored",
@@ -3987,11 +3981,8 @@ dependencies = [
"nym-validator-client",
"opentelemetry",
"pretty_env_logger",
"quinn",
"rand 0.7.3",
"rcgen",
"rocket",
"rustls 0.21.2",
"serde",
"serde_json",
"sysinfo",
@@ -4208,7 +4199,7 @@ dependencies = [
name = "nym-pemstore"
version = "0.3.0"
dependencies = [
"pem 0.8.3",
"pem",
]
[[package]]
@@ -4413,6 +4404,7 @@ dependencies = [
"nym-pemstore",
"nym-sphinx-addressing",
"nym-sphinx-params",
"nym-sphinx-routing",
"nym-sphinx-types",
"nym-topology",
"rand 0.7.3",
@@ -4440,6 +4432,7 @@ dependencies = [
"nym-crypto",
"nym-sphinx-addressing",
"nym-sphinx-params",
"nym-sphinx-routing",
"nym-sphinx-types",
"nym-topology",
"rand 0.7.3",
@@ -4471,6 +4464,7 @@ dependencies = [
"nym-sphinx-chunking",
"nym-sphinx-forwarding",
"nym-sphinx-params",
"nym-sphinx-routing",
"nym-sphinx-types",
"nym-topology",
"rand 0.7.3",
@@ -5071,16 +5065,6 @@ dependencies = [
"regex",
]
[[package]]
name = "pem"
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6b13fe415cdf3c8e44518e18a7c95a13431d9bdf6d15367d82b23c377fdd441a"
dependencies = [
"base64 0.21.2",
"serde",
]
[[package]]
name = "percent-encoding"
version = "2.2.0"
@@ -5420,54 +5404,6 @@ version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3"
[[package]]
name = "quinn"
version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "21252f1c0fc131f1b69182db8f34837e8a69737b8251dff75636a9be0518c324"
dependencies = [
"bytes",
"pin-project-lite",
"quinn-proto",
"quinn-udp",
"rustc-hash",
"rustls 0.21.2",
"thiserror",
"tokio",
"tracing",
]
[[package]]
name = "quinn-proto"
version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85af4ed6ee5a89f26a26086e9089a6643650544c025158449a3626ebf72884b3"
dependencies = [
"bytes",
"rand 0.8.5",
"ring",
"rustc-hash",
"rustls 0.21.2",
"rustls-native-certs 0.6.3",
"slab",
"thiserror",
"tinyvec",
"tracing",
]
[[package]]
name = "quinn-udp"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6df19e284d93757a9fb91d63672f7741b129246a669db09d1c0063071debc0c0"
dependencies = [
"bytes",
"libc",
"socket2 0.5.3",
"tracing",
"windows-sys 0.48.0",
]
[[package]]
name = "quote"
version = "1.0.27"
@@ -5710,18 +5646,6 @@ dependencies = [
"num_cpus",
]
[[package]]
name = "rcgen"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4954fbc00dcd4d8282c987710e50ba513d351400dbdd00e803a05172a90d8976"
dependencies = [
"pem 2.0.1",
"ring",
"time 0.3.21",
"yasna",
]
[[package]]
name = "rdrand"
version = "0.4.0"
@@ -6013,12 +5937,6 @@ dependencies = [
"syn 1.0.109",
]
[[package]]
name = "rustc-hash"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
[[package]]
name = "rustc_version"
version = "0.2.3"
@@ -6076,18 +5994,6 @@ dependencies = [
"webpki 0.22.0",
]
[[package]]
name = "rustls"
version = "0.21.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e32ca28af694bc1bbf399c33a516dbdf1c90090b8ab23c2bc24f834aa2247f5f"
dependencies = [
"log",
"ring",
"rustls-webpki",
"sct 0.7.0",
]
[[package]]
name = "rustls-native-certs"
version = "0.5.0"
@@ -6100,18 +6006,6 @@ dependencies = [
"security-framework",
]
[[package]]
name = "rustls-native-certs"
version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00"
dependencies = [
"openssl-probe",
"rustls-pemfile",
"schannel",
"security-framework",
]
[[package]]
name = "rustls-pemfile"
version = "1.0.2"
@@ -6121,16 +6015,6 @@ dependencies = [
"base64 0.21.2",
]
[[package]]
name = "rustls-webpki"
version = "0.100.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d6207cd5ed3d8dca7816f8f3725513a34609c0c765bf652b8c3cb4cfd87db46b"
dependencies = [
"ring",
"untrusted",
]
[[package]]
name = "rustversion"
version = "1.0.12"
@@ -6604,16 +6488,6 @@ dependencies = [
"winapi",
]
[[package]]
name = "socket2"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2538b18701741680e0322a2302176d3253a35388e2e62f172f64f4f16605f877"
dependencies = [
"libc",
"windows-sys 0.48.0",
]
[[package]]
name = "sphinx-packet"
version = "0.1.0"
@@ -7263,7 +7137,7 @@ dependencies = [
"parking_lot 0.12.1",
"pin-project-lite",
"signal-hook-registry",
"socket2 0.4.9",
"socket2",
"tokio-macros",
"tracing",
"windows-sys 0.48.0",
@@ -8346,15 +8220,6 @@ version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec"
[[package]]
name = "yasna"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e17bb3549cc1321ae1296b9cdc2698e2b6cb1992adfa19a8c72e5b7a738f44cd"
dependencies = [
"time 0.3.21",
]
[[package]]
name = "zeroize"
version = "1.6.0"
@@ -1,4 +1,4 @@
// Copyright 2021-2022 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
// all variable size data is always prefixed with u64 length
@@ -1,4 +1,4 @@
// Copyright 2021-2022 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
// all variable size data is always prefixed with u64 length
@@ -1,4 +1,4 @@
// Copyright 2021-2022 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::error::ErrorKind;
+17 -3
View File
@@ -2240,7 +2240,7 @@ dependencies = [
[[package]]
name = "nym-bin-common"
version = "0.5.0"
version = "0.6.0"
dependencies = [
"atty",
"clap",
@@ -2255,7 +2255,7 @@ dependencies = [
[[package]]
name = "nym-client-core"
version = "1.1.14"
version = "1.1.15"
dependencies = [
"async-trait",
"base64 0.21.2",
@@ -2300,7 +2300,7 @@ dependencies = [
[[package]]
name = "nym-client-wasm"
version = "1.1.0"
version = "1.1.1"
dependencies = [
"anyhow",
"async-trait",
@@ -2697,6 +2697,7 @@ dependencies = [
"nym-pemstore",
"nym-sphinx-addressing",
"nym-sphinx-params",
"nym-sphinx-routing",
"nym-sphinx-types",
"nym-topology",
"rand 0.7.3",
@@ -2723,6 +2724,7 @@ dependencies = [
"nym-crypto",
"nym-sphinx-addressing",
"nym-sphinx-params",
"nym-sphinx-routing",
"nym-sphinx-types",
"nym-topology",
"rand 0.7.3",
@@ -2753,6 +2755,7 @@ dependencies = [
"nym-sphinx-chunking",
"nym-sphinx-forwarding",
"nym-sphinx-params",
"nym-sphinx-routing",
"nym-sphinx-types",
"nym-topology",
"rand 0.7.3",
@@ -2884,6 +2887,7 @@ dependencies = [
"nym-service-provider-directory-common",
"nym-vesting-contract",
"nym-vesting-contract-common",
"openssl",
"prost",
"reqwest",
"serde",
@@ -2974,6 +2978,15 @@ version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
[[package]]
name = "openssl-src"
version = "111.26.0+1.1.1u"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "efc62c9f12b22b8f5208c23a7200a442b2e5999f8bdf80233852122b5a4f6f37"
dependencies = [
"cc",
]
[[package]]
name = "openssl-sys"
version = "0.9.87"
@@ -2982,6 +2995,7 @@ checksum = "8e17f59264b2809d77ae94f0e1ebabc434773f370d6ca667bd223ea10e06cc7e"
dependencies = [
"cc",
"libc",
"openssl-src",
"pkg-config",
"vcpkg",
]
+3
View File
@@ -3,3 +3,6 @@ clippy:
test:
wasm-pack test --node
wasm-build:
wasm-pack build
@@ -8,6 +8,7 @@
},
"scripts": {
"build": "webpack --config webpack.config.js",
"build:wasm": "cd ../ && make wasm-build",
"start": "webpack-dev-server --port 8001"
},
"repository": {
@@ -36,4 +37,4 @@
"dependencies": {
"@nymproject/nym-client-wasm": "file:../pkg"
}
}
}
+302 -264
View File
@@ -12,333 +12,371 @@
// See the License for the specific language governing permissions and
// limitations under the License.
importScripts('nym_client_wasm.js');
importScripts("nym_client_wasm.js");
console.log('Initializing worker');
console.log("Initializing worker");
// wasm_bindgen creates a global variable (with the exports attached) that is in scope after `importScripts`
const {
NymNodeTester,
WasmGateway,
WasmMixNode,
WasmNymTopology,
default_debug,
NymClientBuilder,
NymClient,
set_panic_hook,
Config,
GatewayEndpointConfig,
ClientStorage,
current_network_topology,
make_key,
make_key2
NymNodeTester,
WasmGateway,
WasmMixNode,
WasmNymTopology,
default_debug,
NymClientBuilder,
NymClient,
set_panic_hook,
Config,
GatewayEndpointConfig,
ClientStorage,
current_network_topology,
make_key,
make_key2,
} = wasm_bindgen;
let client = null;
let tester = null;
const preferredGateway = "336yuXAeGEgedRfqTJZsG2YV7P13QH1bHv1SjCZYarc9";
function dummyTopology() {
const l1Mixnode = new WasmMixNode(
1,
'n1fzv4jc7fanl9s0qj02ge2ezk3kts545kjtek47',
'178.79.143.65',
1789,
'4Yr4qmEHd9sgsuQ83191FR2hD88RfsbMmB4tzhhZWriz',
'8ndjk5oZ6HxUZNScLJJ7hk39XtUqGexdKgW7hSX6kpWG',
1,
'1.10.0',
);
const l2Mixnode = new WasmMixNode(
2,
'n1z93z44vf8ssvdhujjvxcj4rd5e3lz0l60wdk70',
'109.74.197.180',
1789,
'7sVjiMrPYZrDWRujku9QLxgE8noT7NTgBAqizCsu7AoK',
'GepXwRnKZDd8x2nBWAajGGBVvF3mrpVMQBkgfrGuqRCN',
2,
'1.10.0',
);
const l3Mixnode = new WasmMixNode(
3,
'n1ptg680vnmef2cd8l0s9uyc4f0hgf3x8sed6w77',
'176.58.101.80',
1789,
'FoM5Mx9Pxk1g3zEqkS3APgtBeTtTo3M8k7Yu4bV6kK1R',
'DeYjrDC2AcQRVFshiKnbUo6bRvPyZ33QGYR2DLeFJ9qD',
3,
'1.10.0',
);
const l1Mixnode = new WasmMixNode(
1,
"n1fzv4jc7fanl9s0qj02ge2ezk3kts545kjtek47",
"178.79.143.65",
1789,
"4Yr4qmEHd9sgsuQ83191FR2hD88RfsbMmB4tzhhZWriz",
"8ndjk5oZ6HxUZNScLJJ7hk39XtUqGexdKgW7hSX6kpWG",
1,
"1.10.0"
);
const l2Mixnode = new WasmMixNode(
2,
"n1z93z44vf8ssvdhujjvxcj4rd5e3lz0l60wdk70",
"109.74.197.180",
1789,
"7sVjiMrPYZrDWRujku9QLxgE8noT7NTgBAqizCsu7AoK",
"GepXwRnKZDd8x2nBWAajGGBVvF3mrpVMQBkgfrGuqRCN",
2,
"1.10.0"
);
const l3Mixnode = new WasmMixNode(
3,
"n1ptg680vnmef2cd8l0s9uyc4f0hgf3x8sed6w77",
"176.58.101.80",
1789,
"FoM5Mx9Pxk1g3zEqkS3APgtBeTtTo3M8k7Yu4bV6kK1R",
"DeYjrDC2AcQRVFshiKnbUo6bRvPyZ33QGYR2DLeFJ9qD",
3,
"1.10.0"
);
const gateway = new WasmGateway(
'n16evnn8glr0sham3matj8rg2s24m6x56ayk87ts',
'85.159.212.96',
1789,
9000,
'336yuXAeGEgedRfqTJZsG2YV7P13QH1bHv1SjCZYarc9',
'BtYjoWihiuFihGKQypmpSspbhmWDPxzqeTVSd8ciCpWL',
'1.10.1',
);
const gateway = new WasmGateway(
"n16evnn8glr0sham3matj8rg2s24m6x56ayk87ts",
"85.159.212.96",
1789,
9000,
"336yuXAeGEgedRfqTJZsG2YV7P13QH1bHv1SjCZYarc9",
"BtYjoWihiuFihGKQypmpSspbhmWDPxzqeTVSd8ciCpWL",
"1.10.1"
);
const mixnodes = new Map();
mixnodes.set(1, [l1Mixnode]);
mixnodes.set(2, [l2Mixnode]);
mixnodes.set(3, [l3Mixnode]);
const mixnodes = new Map();
mixnodes.set(1, [l1Mixnode]);
mixnodes.set(2, [l2Mixnode]);
mixnodes.set(3, [l3Mixnode]);
const gateways = [gateway];
const gateways = [gateway];
return new WasmNymTopology(mixnodes, gateways)
return new WasmNymTopology(mixnodes, gateways);
}
function printAndDisplayTestResult(result) {
result.log_details();
result.log_details();
self.postMessage({
kind: 'DisplayTesterResults',
args: {
score: result.score(),
sentPackets: result.sent_packets,
receivedPackets: result.received_packets,
receivedAcks: result.received_acks,
duplicatePackets: result.duplicate_packets,
duplicateAcks: result.duplicate_acks,
},
});
self.postMessage({
kind: "DisplayTesterResults",
args: {
score: result.score(),
sentPackets: result.sent_packets,
receivedPackets: result.received_packets,
receivedAcks: result.received_acks,
duplicatePackets: result.duplicate_packets,
duplicateAcks: result.duplicate_acks,
},
});
}
async function testWithTester() {
const preferredGateway = "336yuXAeGEgedRfqTJZsG2YV7P13QH1bHv1SjCZYarc9";
// A) construct with hardcoded topology
const topology = dummyTopology();
const nodeTester = await new NymNodeTester(topology, preferredGateway);
// A) construct with hardcoded topology
const topology = dummyTopology()
const nodeTester = await new NymNodeTester(topology, preferredGateway);
// B) first get topology directly from nym-api
// const validator = 'https://qwerty-validator-api.qa.nymte.ch/api';
// const topology = await current_network_topology(validator)
// const nodeTester = await new NymNodeTester(topology, preferredGateway);
//
// C) use nym-api in the constructor (note: it does no filtering for 'good' nodes on other layers)
// const validator = 'https://qwerty-validator-api.qa.nymte.ch/api';
// const nodeTester = await NymNodeTester.new_with_api(validator, preferredGateway)
// B) first get topology directly from nym-api
// const validator = 'https://qwerty-validator-api.qa.nymte.ch/api';
// const topology = await current_network_topology(validator)
// const nodeTester = await new NymNodeTester(topology, preferredGateway);
//
// C) use nym-api in the constructor (note: it does no filtering for 'good' nodes on other layers)
// const validator = 'https://qwerty-validator-api.qa.nymte.ch/api';
// const nodeTester = await NymNodeTester.new_with_api(validator, preferredGateway)
// B) first get topology directly from nym-api
// const validator = 'https://qwerty-validator-api.qa.nymte.ch/api';
// const topology = await current_network_topology(validator)
// const nodeTester = await new NymNodeTester(topology, undefined, preferredGateway);
//
// C) use nym-api in the constructor (note: it does no filtering for 'good' nodes on other layers)
// const validator = 'https://qwerty-validator-api.qa.nymte.ch/api';
// const nodeTester = await NymNodeTester.new_with_api(validator, undefined, preferredGateway)
// D, E, F) you also don't have to specify the gateway. if you don't, a random one (from your topology) will be used
// const topology = dummyTopology()
// const nodeTester = await new NymNodeTester(topology);
// D, E, F) you also don't have to specify the gateway. if you don't, a random one (from your topology) will be used
// const topology = dummyTopology()
// const nodeTester = await new NymNodeTester(topology);
self.onmessage = async (event) => {
if (event.data && event.data.kind) {
switch (event.data.kind) {
case "TestPacket": {
const { mixnodeIdentity } = event.data.args;
console.log("starting node test...");
self.onmessage = async event => {
if (event.data && event.data.kind) {
switch (event.data.kind) {
case 'TestPacket': {
const {mixnodeIdentity} = event.data.args;
console.log("starting node test...");
let result = await nodeTester.test_node(mixnodeIdentity);
printAndDisplayTestResult(result)
}
}
let result = await nodeTester.test_node(mixnodeIdentity);
printAndDisplayTestResult(result);
}
};
}
}
};
}
async function testerReconnection() {
const validator = "https://qwerty-validator-api.qa.nymte.ch/api";
const nodeTester = await NymNodeTester.new_with_api(validator);
self.onmessage = async (event) => {
if (event.data && event.data.kind) {
switch (event.data.kind) {
case "TestPacket": {
const { mixnodeIdentity } = event.data.args;
console.log("starting node test...");
let result1 = await nodeTester.test_node(mixnodeIdentity);
console.log("sleeping for 5s");
await new Promise((r) => setTimeout(r, 5000));
await nodeTester.disconnect_from_gateway();
console.log("sleeping for 5s");
await new Promise((r) => setTimeout(r, 5000));
await nodeTester.reconnect_to_gateway();
let result2 = await nodeTester.test_node(mixnodeIdentity);
printAndDisplayTestResult(result1);
printAndDisplayTestResult(result2);
}
}
}
};
}
async function testWithNymClient() {
const preferredGateway = "336yuXAeGEgedRfqTJZsG2YV7P13QH1bHv1SjCZYarc9";
const topology = dummyTopology()
const topology = dummyTopology();
let received = 0
let received = 0;
const onMessageHandler = (message) => {
received += 1;
self.postMessage({
kind: 'ReceiveMessage',
args: {
message,
senderTag: undefined,
isTestPacket: true,
},
});
// it's really up to the user to create proper callback here...
console.log(`received ${received} packets so far`)
};
console.log('Instantiating WASM client...');
let clientBuilder = NymClientBuilder.new_tester(topology, onMessageHandler, preferredGateway)
console.log('Web worker creating WASM client...');
let local_client = await clientBuilder.start_client();
console.log('WASM client running!');
const selfAddress = local_client.self_address();
// set the global (I guess we don't have to anymore?)
client = local_client;
console.log(`Client address is ${selfAddress}`);
const onMessageHandler = (message) => {
received += 1;
self.postMessage({
kind: 'Ready',
args: {
selfAddress,
},
kind: "ReceiveMessage",
args: {
message,
senderTag: undefined,
isTestPacket: true,
},
});
// Set callback to handle messages passed to the worker.
self.onmessage = async event => {
console.log(event)
if (event.data && event.data.kind) {
switch (event.data.kind) {
case 'SendMessage': {
const {message, recipient} = event.data.args;
let uint8Array = new TextEncoder().encode(message);
await client.send_regular_message(uint8Array, recipient);
break;
}
case 'TestPacket': {
const {mixnodeIdentity} = event.data.args;
const req = await client.try_construct_test_packet_request(mixnodeIdentity);
await client.change_hardcoded_topology(req.injectable_topology());
await client.try_send_test_packets(req);
break;
}
}
// it's really up to the user to create proper callback here...
console.log(`received ${received} packets so far`);
};
console.log("Instantiating WASM client...");
let clientBuilder = NymClientBuilder.new_tester(
topology,
onMessageHandler,
preferredGateway
);
console.log("Web worker creating WASM client...");
let local_client = await clientBuilder.start_client();
console.log("WASM client running!");
const selfAddress = local_client.self_address();
// set the global (I guess we don't have to anymore?)
client = local_client;
console.log(`Client address is ${selfAddress}`);
self.postMessage({
kind: "Ready",
args: {
selfAddress,
},
});
// Set callback to handle messages passed to the worker.
self.onmessage = async (event) => {
console.log(event);
if (event.data && event.data.kind) {
switch (event.data.kind) {
case "SendMessage": {
const { message, recipient } = event.data.args;
let uint8Array = new TextEncoder().encode(message);
await client.send_regular_message(uint8Array, recipient);
break;
}
};
case "TestPacket": {
const { mixnodeIdentity } = event.data.args;
const req = await client.try_construct_test_packet_request(
mixnodeIdentity
);
await client.change_hardcoded_topology(req.injectable_topology());
await client.try_send_test_packets(req);
break;
}
}
}
};
}
async function normalNymClientUsage() {
self.postMessage({kind: 'DisableMagicTestButton'});
self.postMessage({ kind: "DisableMagicTestButton" });
// only really useful if you want to adjust some settings like traffic rate
// (if not needed you can just pass a null)
const debug = default_debug();
// only really useful if you want to adjust some settings like traffic rate
// (if not needed you can just pass a null)
const debug = default_debug();
debug.disable_main_poisson_packet_distribution = true;
debug.disable_loop_cover_traffic_stream = true;
debug.use_extended_packet_size = false;
// debug.average_packet_delay_ms = BigInt(10);
// debug.average_ack_delay_ms = BigInt(10);
// debug.ack_wait_addition_ms = BigInt(3000);
// debug.ack_wait_multiplier = 10;
debug.disable_main_poisson_packet_distribution = true;
debug.disable_loop_cover_traffic_stream = true;
debug.use_extended_packet_size = false;
// debug.average_packet_delay_ms = BigInt(10);
// debug.average_ack_delay_ms = BigInt(10);
// debug.ack_wait_addition_ms = BigInt(3000);
// debug.ack_wait_multiplier = 10;
debug.topology_refresh_rate_ms = BigInt(60000)
debug.topology_refresh_rate_ms = BigInt(60000);
const preferredGateway = "336yuXAeGEgedRfqTJZsG2YV7P13QH1bHv1SjCZYarc9";
const validator = 'https://qwerty-validator-api.qa.nymte.ch/api';
const preferredGateway = "336yuXAeGEgedRfqTJZsG2YV7P13QH1bHv1SjCZYarc9";
const validator = "https://qwerty-validator-api.qa.nymte.ch/api";
const config = new Config('my-awesome-wasm-client', validator, debug);
const config = new Config("my-awesome-wasm-client", validator, debug);
const onMessageHandler = (message) => {
console.log(message);
self.postMessage({
kind: 'ReceiveMessage',
args: {
message,
},
});
};
console.log('Instantiating WASM client...');
let localClient = await new NymClient(config, onMessageHandler)
console.log('WASM client running!');
const selfAddress = localClient.self_address();
// set the global (I guess we don't have to anymore?)
client = localClient;
console.log(`Client address is ${selfAddress}`);
const onMessageHandler = (message) => {
console.log(message);
self.postMessage({
kind: 'Ready',
args: {
selfAddress,
},
kind: "ReceiveMessage",
args: {
message,
},
});
};
// Set callback to handle messages passed to the worker.
self.onmessage = async event => {
console.log(event)
if (event.data && event.data.kind) {
switch (event.data.kind) {
case 'SendMessage': {
const {message, recipient} = event.data.args;
let uint8Array = new TextEncoder().encode(message);
await client.send_regular_message(uint8Array, recipient);
break;
}
}
console.log("Instantiating WASM client...");
let localClient = await new NymClient(config, onMessageHandler);
console.log("WASM client running!");
const selfAddress = localClient.self_address();
// set the global (I guess we don't have to anymore?)
client = localClient;
console.log(`Client address is ${selfAddress}`);
self.postMessage({
kind: "Ready",
args: {
selfAddress,
},
});
// Set callback to handle messages passed to the worker.
self.onmessage = async (event) => {
console.log(event);
if (event.data && event.data.kind) {
switch (event.data.kind) {
case "SendMessage": {
const { message, recipient } = event.data.args;
let uint8Array = new TextEncoder().encode(message);
await client.send_regular_message(uint8Array, recipient);
break;
}
};
}
}
};
}
async function messWithStorage() {
self.onmessage = async event => {
if (event.data && event.data.kind) {
switch (event.data.kind) {
case 'TestPacket': {
const { mixnodeIdentity } = event.data.args;
console.log("button clicked...", mixnodeIdentity);
self.onmessage = async (event) => {
if (event.data && event.data.kind) {
switch (event.data.kind) {
case "TestPacket": {
const { mixnodeIdentity } = event.data.args;
console.log("button clicked...", mixnodeIdentity);
let id1 = "one";
let id2 = "two";
let id1 = "one";
let id2 = "two";
console.log("making store1 NO-ENC");
let _storage1 = await ClientStorage.new_unencrypted(id1);
console.log("making store1 NO-ENC");
let _storage1 = await ClientStorage.new_unencrypted(id1);
console.log("making store2 ENC")
let _storage2 = await new ClientStorage(id2, "my-secret-password");
//
//
//
// console.log("attempting to use store1 WITH PASSWORD")
// let _storage1_alt = await new ClientStorage(id1, "password");
//
//
//
// console.log("attempting to use store2 WITHOUT PASSWORD")
// let _storage2_alt = await ClientStorage.new_unencrypted(id2);
//
//
//
// console.log("attempting to use store2 with WRONG PASSWORD")
// let _storage2_bad = await new ClientStorage(id2, "bad-password")
console.log("making store2 ENC");
let _storage2 = await new ClientStorage(id2, "my-secret-password");
//
//
//
// console.log("attempting to use store1 WITH PASSWORD")
// let _storage1_alt = await new ClientStorage(id1, "password");
//
//
//
// console.log("attempting to use store2 WITHOUT PASSWORD")
// let _storage2_alt = await ClientStorage.new_unencrypted(id2);
//
//
//
// console.log("attempting to use store2 with WRONG PASSWORD")
// let _storage2_bad = await new ClientStorage(id2, "bad-password")
//
// console.log("read1: ", await storage1.read());
// console.log("read2: ", await storage2.read());
//
// console.log("store1: ", await storage1.store("FOOMP"));
//
// console.log("read1: ", await storage1.read());
// console.log("read2: ", await storage2.read());
}
}
//
// console.log("read1: ", await storage1.read());
// console.log("read2: ", await storage2.read());
//
// console.log("store1: ", await storage1.store("FOOMP"));
//
// console.log("read1: ", await storage1.read());
// console.log("read2: ", await storage2.read());
}
};
}
}
};
}
async function main() {
// load WASM package
await wasm_bindgen('nym_client_wasm_bg.wasm');
console.log('Loaded WASM');
// load WASM package
await wasm_bindgen("nym_client_wasm_bg.wasm");
console.log("Loaded WASM");
// sets up better stack traces in case of in-rust panics
set_panic_hook();
// sets up better stack traces in case of in-rust panics
set_panic_hook();
// run test on simplified and dedicated tester:
// await testWithTester()
// show reconnection capabilities
// await testerReconnection()
// hook-up the whole client for testing
// await testWithNymClient()
// run test on simplified and dedicated tester:
await testWithTester();
// 'Normal' client setup (to send 'normal' messages)
await normalNymClientUsage()
// 'Normal' client setup (to send 'normal' messages)
// await normalNymClientUsage()
}
// Let's get started!
main();
main();
+38
View File
@@ -4,6 +4,9 @@
// due to expansion of #[wasm_bindgen] macro on NodeTestResult
#![allow(clippy::drop_non_drop)]
use crate::error::WasmClientError;
use crate::tester::LockedGatewayClient;
use js_sys::Promise;
use nym_node_tester_utils::processor::Received;
use nym_node_tester_utils::receiver::ReceivedReceiver;
use serde::{Deserialize, Serialize};
@@ -12,6 +15,7 @@ use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use tokio::sync::{Mutex as AsyncMutex, MutexGuard as AsyncMutexGuard};
use wasm_bindgen::prelude::*;
use wasm_bindgen_futures::future_to_promise;
use wasm_utils::{console_log, console_warn};
#[derive(Clone)]
@@ -107,3 +111,37 @@ impl Drop for TestMarker {
self.value.store(false, Ordering::SeqCst)
}
}
pub(crate) trait GatewayReconnection {
fn disconnect_from_gateway(&self) -> Promise;
fn reconnect_to_gateway(&self) -> Promise;
}
impl GatewayReconnection for LockedGatewayClient {
fn disconnect_from_gateway(&self) -> Promise {
let this = self.clone();
future_to_promise(async move {
let mut guard = this.lock().await;
guard
.disconnect()
.await
.map_err(|err| JsValue::from(WasmClientError::from(err)))?;
Ok(JsValue::undefined())
})
}
fn reconnect_to_gateway(&self) -> Promise {
let this = self.clone();
future_to_promise(async move {
let mut guard = this.lock().await;
guard
.try_reconnect()
.await
.map_err(|err| JsValue::from(WasmClientError::from(err)))?;
Ok(JsValue::undefined())
})
}
}
+41 -10
View File
@@ -7,7 +7,7 @@ use crate::helpers::{current_network_topology_async, setup_from_topology};
use crate::storage::ClientStorage;
use crate::tester::ephemeral_receiver::EphemeralTestReceiver;
use crate::tester::helpers::{
NodeTestResult, ReceivedReceiverWrapper, TestMarker, WasmTestMessageExt,
GatewayReconnection, NodeTestResult, ReceivedReceiverWrapper, TestMarker, WasmTestMessageExt,
};
use crate::topology::WasmNymTopology;
use futures::channel::mpsc;
@@ -73,6 +73,7 @@ pub struct NymNodeTester {
#[wasm_bindgen]
pub struct NymNodeTesterBuilder {
gateway: Option<IdentityKey>,
id: Option<String>,
base_topology: NymTopology,
@@ -94,9 +95,11 @@ impl NymNodeTesterBuilder {
#[wasm_bindgen(constructor)]
pub fn new(
base_topology: WasmNymTopology,
id: Option<String>,
gateway: Option<IdentityKey>,
) -> NymNodeTesterBuilder {
NymNodeTesterBuilder {
id,
gateway,
base_topology: base_topology.into(),
bandwidth_controller: None,
@@ -105,15 +108,20 @@ impl NymNodeTesterBuilder {
async fn _new_with_api(
api_url: String,
id: Option<String>,
gateway: Option<IdentityKey>,
) -> Result<Self, WasmClientError> {
let topology = current_network_topology_async(api_url).await?;
Ok(NymNodeTesterBuilder::new(topology, gateway))
Ok(NymNodeTesterBuilder::new(topology, id, gateway))
}
pub fn new_with_api(gateway: Option<IdentityKey>, api_url: String) -> Promise {
pub fn new_with_api(
api_url: String,
id: Option<String>,
gateway: Option<IdentityKey>,
) -> Promise {
future_to_promise(async move {
Self::_new_with_api(api_url, gateway)
Self::_new_with_api(api_url, id, gateway)
.await
.into_promise_result()
})
@@ -133,7 +141,13 @@ impl NymNodeTesterBuilder {
async fn _setup_client(mut self) -> Result<NymNodeTester, WasmClientError> {
let task_manager = TaskManager::default();
let client_store = ClientStorage::new_async(NODE_TESTER_ID, None).await?;
let storage_id = if let Some(client_id) = &self.id {
format!("{NODE_TESTER_ID}-{client_id}")
} else {
NODE_TESTER_ID.to_owned()
};
let client_store = ClientStorage::new_async(&storage_id, None).await?;
let init_details = self.gateway_info(&client_store).await?;
let gateway_endpoint = init_details.gateway_details;
@@ -234,29 +248,46 @@ async fn test_mixnode(
impl NymNodeTester {
#[wasm_bindgen(constructor)]
#[allow(clippy::new_ret_no_self)]
pub fn new(topology: WasmNymTopology, gateway: Option<IdentityKey>) -> Promise {
pub fn new(
topology: WasmNymTopology,
id: Option<String>,
gateway: Option<IdentityKey>,
) -> Promise {
console_log!("constructing node tester!");
NymNodeTesterBuilder::new(topology, gateway).setup_client()
NymNodeTesterBuilder::new(topology, id, gateway).setup_client()
}
async fn _new_with_api(
api_url: String,
id: Option<String>,
gateway: Option<IdentityKey>,
) -> Result<Self, WasmClientError> {
NymNodeTesterBuilder::_new_with_api(api_url, gateway)
NymNodeTesterBuilder::_new_with_api(api_url, id, gateway)
.await?
._setup_client()
.await
}
pub fn new_with_api(api_url: String, gateway: Option<IdentityKey>) -> Promise {
pub fn new_with_api(
api_url: String,
id: Option<String>,
gateway: Option<IdentityKey>,
) -> Promise {
future_to_promise(async move {
Self::_new_with_api(api_url, gateway)
Self::_new_with_api(api_url, id, gateway)
.await
.into_promise_result()
})
}
pub fn disconnect_from_gateway(&self) -> Promise {
self.gateway_client.disconnect_from_gateway()
}
pub fn reconnect_to_gateway(&self) -> Promise {
self.gateway_client.reconnect_to_gateway()
}
fn prepare_test_packets(
&self,
mixnode_identity: String,
-2
View File
@@ -40,8 +40,6 @@ pub fn setup_logging() {
.filter_module("tokio_tungstenite", log::LevelFilter::Warn)
.filter_module("handlebars", log::LevelFilter::Warn)
.filter_module("sled", log::LevelFilter::Warn)
.filter_module("quinn", log::LevelFilter::Warn)
.filter_module("rustls", log::LevelFilter::Warn)
.init();
}
@@ -10,7 +10,7 @@ use log::*;
use nym_sphinx::acknowledgements::AckKey;
use nym_sphinx::addressing::clients::Recipient;
use nym_sphinx::cover::generate_loop_cover_packet;
use nym_sphinx::params::PacketSize;
use nym_sphinx::params::{PacketSize, PacketType};
use nym_sphinx::utils::sample_poisson_duration;
use rand::{rngs::OsRng, CryptoRng, Rng};
use std::pin::Pin;
@@ -63,6 +63,8 @@ where
/// Optional secondary predefined packet size used for the loop cover messages.
secondary_packet_size: Option<PacketSize>,
packet_type: PacketType,
}
impl<R> Stream for LoopCoverTrafficStream<R>
@@ -135,6 +137,7 @@ impl LoopCoverTrafficStream<OsRng> {
topology_access,
primary_packet_size: traffic_config.primary_packet_size,
secondary_packet_size: traffic_config.secondary_packet_size,
packet_type: traffic_config.packet_type,
}
}
@@ -194,7 +197,7 @@ impl LoopCoverTrafficStream<OsRng> {
self.average_ack_delay,
self.cover_traffic.loop_cover_traffic_average_delay,
cover_traffic_packet_size,
nym_sphinx::params::PacketType::Mix,
self.packet_type,
)
.expect("Somehow failed to generate a loop cover message with a valid topology");
@@ -1,4 +1,4 @@
// Copyright 2021-2022 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::client::inbound_messages::{InputMessage, InputMessageReceiver};
@@ -1,4 +1,4 @@
// Copyright 2021-2022 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use super::{
+36 -4
View File
@@ -137,14 +137,46 @@ impl Config {
self
}
pub fn set_no_cover_traffic(&mut self) {
self.debug.cover_traffic.disable_loop_cover_traffic_stream = true;
self.debug.traffic.disable_main_poisson_packet_distribution = true;
}
pub fn with_disabled_cover_traffic_with_keepalive(mut self, disabled: bool) -> Self {
if disabled {
self.set_no_cover_traffic_with_keepalive()
}
self
}
pub fn set_no_cover_traffic_with_keepalive(&mut self) {
self.debug.traffic.disable_main_poisson_packet_distribution = true;
self.debug.cover_traffic.loop_cover_traffic_average_delay = Duration::from_secs(5);
}
pub fn with_disabled_topology_refresh(mut self, disable_topology_refresh: bool) -> Self {
self.debug.topology.disable_refreshing = disable_topology_refresh;
self
}
pub fn set_no_cover_traffic(&mut self) {
self.debug.cover_traffic.disable_loop_cover_traffic_stream = true;
self.debug.traffic.disable_main_poisson_packet_distribution = true;
pub fn with_no_per_hop_delays(mut self, no_per_hop_delays: bool) -> Self {
if no_per_hop_delays {
self.set_no_per_hop_delays()
}
self
}
pub fn set_no_per_hop_delays(&mut self) {
self.debug.traffic.average_packet_delay = Duration::ZERO;
self.debug.acknowledgements.average_ack_delay = Duration::ZERO;
}
pub fn with_secondary_packet_size(mut self, secondary_packet_size: Option<PacketSize>) -> Self {
self.set_secondary_packet_size(secondary_packet_size);
self
}
pub fn set_secondary_packet_size(&mut self, secondary_packet_size: Option<PacketSize>) {
self.debug.traffic.secondary_packet_size = secondary_packet_size;
}
pub fn set_custom_version(&mut self, version: &str) {
@@ -282,7 +314,7 @@ impl Client {
}
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
#[serde(default)]
#[serde(default, deny_unknown_fields)]
pub struct Traffic {
/// The parameter of Poisson distribution determining how long, on average,
/// sent packet is going to be delayed at any given mix node.
@@ -724,7 +724,7 @@ impl<C, St> GatewayClient<C, St> {
Ok(())
}
async fn try_reconnect(&mut self) -> Result<(), GatewayClientError> {
pub async fn try_reconnect(&mut self) -> Result<(), GatewayClientError> {
if !self.connection.is_established() {
self.establish_connection().await?;
}
@@ -738,6 +738,12 @@ impl<C, St> GatewayClient<C, St> {
Ok(())
}
pub async fn disconnect(&mut self) -> Result<(), GatewayClientError> {
self.recover_socket_connection().await?;
self.connection = SocketState::NotConnected;
Ok(())
}
pub async fn authenticate_and_start(&mut self) -> Result<Arc<SharedKeys>, GatewayClientError>
where
C: DkgQueryClient + Send + Sync,
@@ -48,17 +48,21 @@ impl PacketRouter {
// data he takes the SURB-ACK and first hop address.
// currently SURB-ACKs are attached in EVERY packet, even cover, so this is always true
let ack_overhead = PacketSize::AckPacket.size() + MAX_NODE_ADDRESS_UNPADDED_LEN;
let outfox_ack_overhead =
PacketSize::OutfoxAckPacket.size() + MAX_NODE_ADDRESS_UNPADDED_LEN;
for received_packet in unwrapped_packets {
if received_packet.len() == PacketSize::AckPacket.plaintext_size()
|| received_packet.len() == PacketSize::OutfoxAckPacket.plaintext_size()
// we don't know the real size of the payload, it could be anything <= 48 bytes
|| received_packet.len() <= PacketSize::OutfoxAckPacket.plaintext_size()
{
received_acks.push(received_packet);
} else if received_packet.len()
== PacketSize::RegularPacket.plaintext_size() - ack_overhead
|| received_packet.len()
== PacketSize::OutfoxRegularPacket.plaintext_size() - ack_overhead
|| received_packet.len() == PacketSize::OutfoxRegularPacket.size() - 6
== PacketSize::OutfoxRegularPacket.plaintext_size() - outfox_ack_overhead
|| received_packet.len()
== PacketSize::OutfoxRegularPacket.size() - outfox_ack_overhead
{
trace!("routing regular packet");
received_messages.push(received_packet);
@@ -1,4 +1,4 @@
// Copyright 2021-2022 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::error::GatewayClientError;
@@ -11,9 +11,6 @@ futures = "0.3"
log = { workspace = true }
tokio = { version = "1.24.1", features = ["time", "net", "rt"] }
tokio-util = { version = "0.7.4", features = ["codec"] }
rustls = {version = "0.21.1", features = ["dangerous_configuration", "quic"]}
quinn = "0.10.1"
bytes = "*"
# internal
nym-sphinx = { path = "../../nymsphinx" }
+48 -114
View File
@@ -2,23 +2,22 @@
// SPDX-License-Identifier: Apache-2.0
use futures::channel::mpsc;
use futures::{SinkExt, StreamExt};
use futures::StreamExt;
use log::*;
use nym_sphinx::addressing::nodes::NymNodeRoutingAddress;
use nym_sphinx::framing::codec::NymCodec;
use nym_sphinx::framing::packet::FramedNymPacket;
use nym_sphinx::params::PacketType;
use nym_sphinx::NymPacket;
use quinn::{ClientConfig, Endpoint};
use std::collections::HashMap;
use std::io;
use std::net::SocketAddr;
use std::sync::atomic::{AtomicU32, Ordering};
use std::sync::Arc;
use std::time::{Duration, Instant};
use std::time::Duration;
use tokio::net::TcpStream;
use tokio::time::sleep;
use tokio_util::codec::FramedWrite;
use tokio_util::codec::Framed;
pub struct Config {
initial_reconnection_backoff: Duration,
@@ -65,7 +64,6 @@ pub struct Client {
struct ConnectionSender {
channel: mpsc::Sender<FramedNymPacket>,
current_reconnection_attempt: Arc<AtomicU32>,
last_used: Instant,
}
impl ConnectionSender {
@@ -73,7 +71,6 @@ impl ConnectionSender {
ConnectionSender {
channel,
current_reconnection_attempt: Arc::new(AtomicU32::new(0)),
last_used: Instant::now(),
}
}
}
@@ -88,25 +85,19 @@ impl Client {
async fn manage_connection(
address: SocketAddr,
mut receiver: mpsc::Receiver<FramedNymPacket>,
receiver: mpsc::Receiver<FramedNymPacket>,
connection_timeout: Duration,
current_reconnection: &AtomicU32,
) {
let mut endpoint = Endpoint::client("0.0.0.0:0".parse::<SocketAddr>().unwrap()).unwrap();
endpoint.set_default_client_config(configure_client());
let connection_fut = TcpStream::connect(address);
let conn = match tokio::time::timeout(
connection_timeout,
endpoint.connect(address, "mixnode").unwrap(),
)
.await
{
let conn = match tokio::time::timeout(connection_timeout, connection_fut).await {
Ok(stream_res) => match stream_res {
Ok(connection) => {
Ok(stream) => {
debug!("Managed to establish connection to {}", address);
// if we managed to connect, reset the reconnection count (whatever it might have been)
current_reconnection.store(0, Ordering::Release);
connection
Framed::new(stream, NymCodec)
}
Err(err) => {
debug!(
@@ -127,26 +118,18 @@ impl Client {
return;
}
};
loop {
let pkt = match receiver.next().await {
Some(pkt) => pkt,
None => {
debug!("No more packet to send to {}", address);
return;
}
};
let send = match conn.open_uni().await {
Ok(send_stream) => send_stream,
Err(err) => {
error!("Failed to open uni stream, dropping packet - {err:?}");
return; //We shouldn't get a time out here, it should be handled higher
}
};
let mut framed_stream = FramedWrite::new(send, NymCodec);
if let Err(err) = framed_stream.send(pkt).await {
warn!("Failed to forward packets to {} - {err}", address);
}
// Take whatever the receiver channel produces and put it on the connection.
// We could have as well used conn.send_all(receiver.map(Ok)), but considering we don't care
// about neither receiver nor the connection, it doesn't matter which one gets consumed
if let Err(err) = receiver.map(Ok).forward(conn).await {
warn!("Failed to forward packets to {} - {err}", address);
}
debug!(
"connection manager to {} is finished. Either the connection failed or mixnet client got dropped",
address
);
}
/// If we're trying to reconnect, determine how long we should wait.
@@ -222,53 +205,36 @@ impl SendWithoutResponse for Client {
FramedNymPacket::new(packet, packet_type, self.config.use_legacy_version);
if let Some(sender) = self.conn_new.get_mut(&address) {
if sender.last_used.elapsed().as_millis() > 9_000 {
// default timeout is 10sec, let's take some margin for the operation to run.
//connection is near timeout, let's just recreate one
sender.channel.close_channel();
self.conn_new.remove(&address);
debug!(
"connection near or past timemout. Reconnecting to {}",
address
);
self.make_connection(address, framed_packet);
Err(io::Error::new(
io::ErrorKind::NotConnected,
"re-connection is in progress",
))
} else {
sender.last_used = Instant::now();
if let Err(err) = sender.channel.try_send(framed_packet) {
if err.is_full() {
debug!("Connection to {} seems to not be able to handle all the traffic - dropping the current packet", address);
// it's not a 'big' error, but we did not manage to send the packet
// if the queue is full, we can't really do anything but to drop the packet
Err(io::Error::new(
io::ErrorKind::WouldBlock,
"connection queue is full",
))
} else if err.is_disconnected() {
debug!(
"Connection to {} seems to be dead. attempting to re-establish it...",
address
);
// it's not a 'big' error, but we did not manage to send the packet, but queue
// it up to send it as soon as the connection is re-established
self.make_connection(address, err.into_inner());
Err(io::Error::new(
io::ErrorKind::ConnectionAborted,
"reconnection attempt is in progress",
))
} else {
// this can't really happen, but let's safe-guard against it in case something changes in futures library
Err(io::Error::new(
io::ErrorKind::Other,
"unknown connection buffer error",
))
}
if let Err(err) = sender.channel.try_send(framed_packet) {
if err.is_full() {
debug!("Connection to {} seems to not be able to handle all the traffic - dropping the current packet", address);
// it's not a 'big' error, but we did not manage to send the packet
// if the queue is full, we can't really do anything but to drop the packet
Err(io::Error::new(
io::ErrorKind::WouldBlock,
"connection queue is full",
))
} else if err.is_disconnected() {
debug!(
"Connection to {} seems to be dead. attempting to re-establish it...",
address
);
// it's not a 'big' error, but we did not manage to send the packet, but queue
// it up to send it as soon as the connection is re-established
self.make_connection(address, err.into_inner());
Err(io::Error::new(
io::ErrorKind::ConnectionAborted,
"reconnection attempt is in progress",
))
} else {
Ok(())
// this can't really happen, but let's safe-guard against it in case something changes in futures library
Err(io::Error::new(
io::ErrorKind::Other,
"unknown connection buffer error",
))
}
} else {
Ok(())
}
} else {
// there was never a connection to begin with
@@ -326,35 +292,3 @@ mod tests {
);
}
}
// Implementation of `ServerCertVerifier` that verifies everything as trustworthy.
struct SkipServerVerification;
impl SkipServerVerification {
fn new() -> Arc<Self> {
Arc::new(Self)
}
}
impl rustls::client::ServerCertVerifier for SkipServerVerification {
fn verify_server_cert(
&self,
_end_entity: &rustls::Certificate,
_intermediates: &[rustls::Certificate],
_server_name: &rustls::ServerName,
_scts: &mut dyn Iterator<Item = &[u8]>,
_ocsp_response: &[u8],
_now: std::time::SystemTime,
) -> Result<rustls::client::ServerCertVerified, rustls::Error> {
Ok(rustls::client::ServerCertVerified::assertion())
}
}
fn configure_client() -> ClientConfig {
let crypto = rustls::ClientConfig::builder()
.with_safe_defaults()
.with_custom_certificate_verifier(SkipServerVerification::new())
.with_no_client_auth();
ClientConfig::new(Arc::new(crypto))
}
@@ -1,4 +1,4 @@
// Copyright 2021-2022 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::{nym_api, ValidatorClientError};
@@ -1,4 +1,4 @@
// Copyright 2021-2022 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::nym_api::error::NymAPIError;
@@ -1,4 +1,4 @@
// Copyright 2021-2022 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
// TODO: There's a significant argument to pull those out of the package and make a PR on https://github.com/cosmos/cosmos-rust/
@@ -1,4 +1,4 @@
// Copyright 2021-2022 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
// TODO: expose query-related capabilities to wasm client...
+3
View File
@@ -41,3 +41,6 @@ nym-multisig-contract-common = { path = "../cosmwasm-smart-contracts/multisig-co
nym-service-provider-directory-common = { path = "../cosmwasm-smart-contracts/service-provider-directory" }
nym-name-service-common = { path = "../cosmwasm-smart-contracts/name-service" }
nym-sphinx = { path = "../../common/nymsphinx" }
nym-pemstore = { path = "../../common/pemstore", version = "0.3.0" }
nym-types = { path = "../../common/types" }
@@ -0,0 +1,68 @@
use clap::{Args, Parser, Subcommand};
use nym_bin_common::output_format::OutputFormat;
use nym_crypto::asymmetric::identity;
use nym_types::helpers::ConsoleSigningOutput;
use nym_validator_client::nyxd::error::NyxdError;
use std::path::PathBuf;
#[derive(Debug, Args)]
#[clap(args_conflicts_with_subcommands = true, subcommand_required = true)]
pub struct MixnetOperatorsIdentityKey {
#[clap(subcommand)]
pub command: MixnetOperatorsIdentityKeyCommands,
}
#[derive(Debug, Subcommand)]
pub enum MixnetOperatorsIdentityKeyCommands {
/// Register a name alias for a nym address
Sign(SignArgs),
}
#[derive(Debug, Parser)]
pub struct SignArgs {
/// Path to private identity key (example: private_identity_key.pem)
#[clap(long)]
private_key: PathBuf,
/// Base58 encoded message to sign
#[clap(long)]
base58_msg: String,
#[clap(short, long, default_value_t = OutputFormat::default())]
output: OutputFormat,
}
pub async fn sign(args: SignArgs) -> Result<(), NyxdError> {
eprintln!(">>> loading: {}", args.private_key.display());
let private_identity_key: identity::PrivateKey =
nym_pemstore::load_key(args.private_key).expect("failed to load key");
print_signed_msg(&private_identity_key, &args.base58_msg, args.output);
Ok(())
}
fn print_signed_msg(private_key: &identity::PrivateKey, raw_msg: &str, output: OutputFormat) {
let trimmed = raw_msg.trim();
eprintln!(">>> attempting to sign: {trimmed}");
let Ok(decoded) = bs58::decode(trimmed).into_vec() else {
println!("failed to base58 decode the message, did you copy it correctly?");
return;
};
eprintln!(">>> decoding the message...");
// we don't really care about what particular information is embedded inside of it,
// we just want to know if user correctly copied the string, i.e. whether it's a valid bs58 encoded json
if serde_json::from_slice::<serde_json::Value>(&decoded).is_err() {
println!("failed to parse the message after decoding, did you copy it correctly?");
return;
};
// if this is a valid json, it MUST be a valid string
let decoded_string = String::from_utf8(decoded.clone()).unwrap();
let signature = private_key.sign(&decoded).to_base58_string();
let sign_output = ConsoleSigningOutput::new(decoded_string, signature);
println!("{}", output.format(&sign_output));
}
@@ -4,6 +4,7 @@
use clap::{Args, Subcommand};
pub mod gateway;
pub mod identity_key;
pub mod mixnode;
pub mod name;
pub mod service;
@@ -26,4 +27,6 @@ pub enum MixnetOperatorsCommands {
ServiceProvider(service::MixnetOperatorsService),
/// Manage your registered name
Name(name::MixnetOperatorsName),
/// Sign messages using your private identity key
IdentityKey(identity_key::MixnetOperatorsIdentityKey),
}
@@ -1,4 +1,4 @@
// Copyright 2021-2022 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
// due to code generated by JsonSchema
@@ -1,4 +1,4 @@
// Copyright 2021-2022 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
// due to code generated by JsonSchema
@@ -1,4 +1,4 @@
// Copyright 2021-2022 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
// due to code generated by JsonSchema
@@ -88,7 +88,7 @@ impl MixNodeDetails {
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)]
pub struct MixNodeRewarding {
/// Information provided by the operator that influence the cost function.
/// Information provided by the operator that influence the cost function.
pub cost_params: MixNodeCostParams,
/// Total pledge and compounded reward earned by the node operator.
@@ -1,4 +1,4 @@
// Copyright 2021-2022 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::delegation::OwnerProxySubKey;
@@ -1,4 +1,4 @@
// Copyright 2021-2022 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::error::MixnetContractError;
@@ -3,7 +3,7 @@
use nym_sphinx_acknowledgements::surb_ack::SurbAckRecoveryError;
use nym_sphinx_addressing::nodes::NymNodeRoutingAddressError;
use nym_sphinx_types::{NymPacketError, SphinxError};
use nym_sphinx_types::{NymPacketError, OutfoxError, SphinxError};
use thiserror::Error;
#[derive(Error, Debug)]
@@ -25,4 +25,7 @@ pub enum MixProcessingError {
#[error("the received packet was set to use the very old and very much deprecated 'VPN' mode")]
ReceivedOldTypeVpnPacket,
#[error("failed to process received outfox packet: {0}")]
OutfoxProcessingError(#[from] OutfoxError),
}
@@ -20,12 +20,14 @@ use tracing::instrument;
type ForwardAck = MixPacket;
#[derive(Debug)]
pub struct ProcessedFinalHop {
pub destination: DestinationAddressBytes,
pub forward_ack: Option<ForwardAck>,
pub message: Vec<u8>,
}
#[derive(Debug)]
pub enum MixProcessingResult {
/// Contains unwrapped data that should first get delayed before being sent to next hop.
ForwardHop(MixPacket, Option<SphinxDelay>),
@@ -141,7 +143,7 @@ impl SphinxPacketProcessor {
match SurbAck::try_recover_first_hop_packet(&ack_data, packet_type) {
Ok((first_hop, packet)) => (first_hop, packet),
Err(err) => {
debug!("Failed to recover first hop from ack data: {err}");
info!("Failed to recover first hop from ack data: {err}");
return Err(err.into());
}
};
@@ -205,7 +207,7 @@ impl SphinxPacketProcessor {
if packet.is_final_hop() {
self.process_final_hop(
DestinationAddressBytes::from_bytes(next_address),
packet.recover_plaintext().to_vec(),
packet.recover_plaintext()?.to_vec(),
packet_size,
packet_type,
)
@@ -239,7 +241,14 @@ impl SphinxPacketProcessor {
// for forward packets, extract next hop and set delay (but do NOT delay here)
// for final packets, extract SURBAck
self.perform_final_processing(processed_packet, packet_size, packet_type)
let final_processing_result =
self.perform_final_processing(processed_packet, packet_size, packet_type);
if final_processing_result.is_err() {
error!("{:?}", final_processing_result)
}
final_processing_result
})
}
}
+3 -2
View File
@@ -15,11 +15,12 @@ thiserror = { workspace = true }
zeroize = { workspace = true }
nym-crypto = { path = "../../crypto", features = ["symmetric", "rand"] }
nym-pemstore = { path = "../../pemstore" }
nym-sphinx-addressing = { path = "../addressing" }
nym-sphinx-params = { path = "../params" }
nym-sphinx-routing = { path = "../routing" }
nym-sphinx-types = { path = "../types" }
nym-pemstore = { path = "../../pemstore" }
nym-topology = { path = "../../topology" }
[features]
serde = ["serde_crate", "generic-array"]
serde = ["serde_crate", "generic-array"]
@@ -9,7 +9,7 @@ use nym_sphinx_addressing::nodes::{
};
use nym_sphinx_params::packet_sizes::PacketSize;
use nym_sphinx_params::{PacketType, DEFAULT_NUM_MIX_HOPS};
use nym_sphinx_types::delays::{self, Delay};
use nym_sphinx_types::delays::Delay;
use nym_sphinx_types::{NymPacket, NymPacketError, MIN_PACKET_SIZE};
use nym_topology::{NymTopology, NymTopologyError};
use rand::{CryptoRng, RngCore};
@@ -51,7 +51,7 @@ impl SurbAck {
{
let route =
topology.random_route_to_gateway(rng, DEFAULT_NUM_MIX_HOPS, recipient.gateway())?;
let delays = delays::generate_from_average_duration(route.len(), average_delay);
let delays = nym_sphinx_routing::generate_hop_delays(average_delay, route.len());
let destination = recipient.as_sphinx_destination();
let surb_ack_payload = prepare_identifier(rng, ack_key, marshaled_fragment_id);
@@ -16,6 +16,7 @@ thiserror = "1"
nym-crypto = { path = "../../crypto", features = ["symmetric", "rand"] }
nym-sphinx-addressing = { path = "../addressing" }
nym-sphinx-params = { path = "../params" }
nym-sphinx-routing = { path = "../routing" }
nym-sphinx-types = { path = "../types" }
nym-topology = { path = "../../topology" }
@@ -1,4 +1,4 @@
// Copyright 2021-2022 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::encryption_key::{SurbEncryptionKey, SurbEncryptionKeyError, SurbEncryptionKeySize};
@@ -7,7 +7,7 @@ use nym_sphinx_addressing::clients::Recipient;
use nym_sphinx_addressing::nodes::{NymNodeRoutingAddress, MAX_NODE_ADDRESS_UNPADDED_LEN};
use nym_sphinx_params::packet_sizes::PacketSize;
use nym_sphinx_params::{PacketType, ReplySurbKeyDigestAlgorithm, DEFAULT_NUM_MIX_HOPS};
use nym_sphinx_types::{delays, NymPacket, SURBMaterial, SphinxError, SURB};
use nym_sphinx_types::{NymPacket, SURBMaterial, SphinxError, SURB};
use nym_topology::{NymTopology, NymTopologyError};
use rand::{CryptoRng, RngCore};
use serde::de::{Error as SerdeError, Visitor};
@@ -96,7 +96,7 @@ impl ReplySurb {
{
let route =
topology.random_route_to_gateway(rng, DEFAULT_NUM_MIX_HOPS, recipient.gateway())?;
let delays = delays::generate_from_average_duration(route.len(), average_delay);
let delays = nym_sphinx_routing::generate_hop_delays(average_delay, route.len());
let destination = recipient.as_sphinx_destination();
let surb_material = SURBMaterial::new(route, delays, destination);
+1 -1
View File
@@ -1,4 +1,4 @@
// Copyright 2021-2022 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::ChunkingError;
+2 -1
View File
@@ -15,7 +15,8 @@ nym-crypto = { path = "../../crypto" }
nym-sphinx-acknowledgements = { path = "../acknowledgements" }
nym-sphinx-addressing = { path = "../addressing" }
nym-sphinx-chunking = { path = "../chunking" }
nym-sphinx-params = { path = "../params" }
nym-sphinx-forwarding = { path = "../forwarding" }
nym-sphinx-params = { path = "../params" }
nym-sphinx-routing = { path = "../routing" }
nym-sphinx-types = { path = "../types" }
nym-topology = { path = "../../topology" }
+29 -12
View File
@@ -13,7 +13,7 @@ use nym_sphinx_params::packet_sizes::PacketSize;
use nym_sphinx_params::{
PacketEncryptionAlgorithm, PacketHkdfAlgorithm, PacketType, DEFAULT_NUM_MIX_HOPS,
};
use nym_sphinx_types::{delays, NymPacket};
use nym_sphinx_types::NymPacket;
use nym_topology::{NymTopology, NymTopologyError};
use rand::{CryptoRng, RngCore};
use std::convert::TryFrom;
@@ -91,6 +91,7 @@ where
>(rng, full_address.encryption_key());
let public_key_bytes = ephemeral_keypair.public_key().to_bytes();
let cover_size = packet_size.plaintext_size() - public_key_bytes.len() - ack_bytes.len();
let mut cover_content: Vec<_> = LOOP_COVER_MESSAGE_PAYLOAD
@@ -119,22 +120,38 @@ where
let route =
topology.random_route_to_gateway(rng, DEFAULT_NUM_MIX_HOPS, full_address.gateway())?;
let delays = delays::generate_from_average_duration(route.len(), average_packet_delay);
let delays = nym_sphinx_routing::generate_hop_delays(average_packet_delay, route.len());
let destination = full_address.as_sphinx_destination();
// once merged, that's an easy rng injection point for sphinx packets : )
let packet = NymPacket::sphinx_build(
packet_size.payload_size(),
packet_payload,
&route,
&destination,
&delays,
)?;
let first_hop_address =
NymNodeRoutingAddress::try_from(route.first().unwrap().address).unwrap();
Ok(MixPacket::new(first_hop_address, packet, PacketType::Mix))
// once merged, that's an easy rng injection point for sphinx packets : )
let packet = match packet_type {
PacketType::Mix => NymPacket::sphinx_build(
packet_size.payload_size(),
packet_payload,
&route,
&destination,
&delays,
)?,
#[allow(deprecated)]
PacketType::Vpn => NymPacket::sphinx_build(
packet_size.payload_size(),
packet_payload,
&route,
&destination,
&delays,
)?,
PacketType::Outfox => NymPacket::outfox_build(
packet_payload,
&route,
&destination,
Some(packet_size.plaintext_size()),
)?,
};
Ok(MixPacket::new(first_hop_address, packet, packet_type))
}
/// Helper function used to determine if given message represents a loop cover message.
+1 -1
View File
@@ -1,4 +1,4 @@
// Copyright 2021-2022 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::packet::{FramedNymPacket, Header};
+1 -1
View File
@@ -1,4 +1,4 @@
// Copyright 2021-2022 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
#![allow(deprecated)]
+11 -1
View File
@@ -1,8 +1,10 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use std::time::Duration;
use nym_sphinx_addressing::clients::Recipient;
use nym_sphinx_types::Node;
use nym_sphinx_types::{delays, Delay, Node};
use thiserror::Error;
pub trait SphinxRouteMaker {
@@ -41,3 +43,11 @@ impl SphinxRouteMaker for Vec<Node> {
}
}
}
pub fn generate_hop_delays(average_packet_delay: Duration, num_hops: usize) -> Vec<Delay> {
if average_packet_delay.is_zero() {
vec![nym_sphinx_types::Delay::new_from_millis(0); num_hops]
} else {
delays::generate_from_average_duration(num_hops, average_packet_delay)
}
}
+3 -3
View File
@@ -1,4 +1,4 @@
// Copyright 2021-2022 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::message::{NymMessage, ACK_OVERHEAD, OUTFOX_ACK_OVERHEAD};
@@ -14,7 +14,7 @@ use nym_sphinx_chunking::fragment::{Fragment, FragmentIdentifier};
use nym_sphinx_forwarding::packet::MixPacket;
use nym_sphinx_params::packet_sizes::PacketSize;
use nym_sphinx_params::{PacketType, ReplySurbKeyDigestAlgorithm, DEFAULT_NUM_MIX_HOPS};
use nym_sphinx_types::{delays, Delay, NymPacket};
use nym_sphinx_types::{Delay, NymPacket};
use nym_topology::{NymTopology, NymTopologyError};
use rand::{CryptoRng, Rng};
use std::convert::TryFrom;
@@ -233,7 +233,7 @@ pub trait FragmentPreparer {
// including set of delays
let delays =
delays::generate_from_average_duration(route.len(), self.average_packet_delay());
nym_sphinx_routing::generate_hop_delays(self.average_packet_delay(), route.len());
// create the actual sphinx packet here. With valid route and correct payload size,
// there's absolutely no reason for this call to fail.
+13 -4
View File
@@ -177,20 +177,29 @@ impl TaskManager {
drop(notify_rx);
}
#[cfg(not(target_arch = "wasm32"))]
let interrupt_future = tokio::signal::ctrl_c();
// in wasm we'll never get our shutdown anyway...
#[cfg(target_arch = "wasm32")]
futures::future::pending::<()>().await;
let interrupt_future = futures::future::pending::<()>();
#[cfg(not(target_arch = "wasm32"))]
let wait_future = tokio::time::sleep(Duration::from_secs(self.shutdown_timer_secs));
// TODO: we should be using a `Delay` here for wasm
#[cfg(target_arch = "wasm32")]
let wait_future = futures::future::pending::<()>();
tokio::select! {
_ = self.notify_tx.closed() => {
log::info!("All registered tasks succesfully shutdown");
},
_ = tokio::signal::ctrl_c() => {
_ = interrupt_future => {
log::info!("Forcing shutdown");
}
_ = tokio::time::sleep(Duration::from_secs(self.shutdown_timer_secs)) => {
log::info!("Timout reached, forcing shutdown");
_ = wait_future => {
log::info!("Timeout reached, forcing shutdown");
},
}
}
+1 -1
View File
@@ -1,4 +1,4 @@
// Copyright 2021-2022 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use super::storage;
+1 -1
View File
@@ -1,4 +1,4 @@
// Copyright 2021-2022 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::constants::{
@@ -1,4 +1,4 @@
// Copyright 2021-2022 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use super::storage;
+1 -1
View File
@@ -1,4 +1,4 @@
// Copyright 2021-2022 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use super::storage;
@@ -1,4 +1,4 @@
// Copyright 2021-2022 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use super::helpers::must_get_gateway_bond_by_owner;
@@ -1,4 +1,4 @@
// Copyright 2021-2022 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
pub mod queries;
@@ -1,4 +1,4 @@
// Copyright 2021-2022 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use super::storage;
@@ -1,4 +1,4 @@
// Copyright 2021-2022 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::constants::CONTRACT_STATE_KEY;
@@ -1,4 +1,4 @@
// Copyright 2021-2022 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use super::storage;
+1 -1
View File
@@ -1,4 +1,4 @@
// Copyright 2021-2022 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use super::storage;
@@ -1,4 +1,4 @@
// Copyright 2021-2022 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use cosmwasm_std::{coin, Addr, Coin, DepsMut, Env, MessageInfo, Response, Storage};
+1 -1
View File
@@ -1,4 +1,4 @@
// Copyright 2021-2022 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use super::storage;
+1 -1
View File
@@ -1,4 +1,4 @@
// Copyright 2021-2022 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::constants::{
+1 -1
View File
@@ -1,4 +1,4 @@
// Copyright 2021-2022 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
#[cfg(test)]
+1 -1
View File
@@ -1,4 +1,4 @@
// Copyright 2021-2022 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use nym_mixnet_contract_common::{MixId, MixNode};
-4
View File
@@ -43,10 +43,6 @@ tokio-tungstenite = "0.14"
tokio-util = { version = "0.7.4", features = ["codec"] }
url = { version = "2.2", features = ["serde"] }
zeroize = { workspace = true }
quinn = "0.10.1"
rustls = {version = "0.21.1", features = ["quic"]}
rcgen = "*"
bytes = "*"
# internal
nym-api-requests = { path = "../nym-api/nym-api-requests" }
@@ -15,9 +15,10 @@ use nym_sphinx::framing::codec::NymCodec;
use nym_sphinx::framing::packet::FramedNymPacket;
use nym_sphinx::DestinationAddressBytes;
use nym_task::TaskClient;
use quinn::{Connection, ConnectionError};
use std::collections::HashMap;
use tokio_util::codec::FramedRead;
use std::net::SocketAddr;
use tokio::net::TcpStream;
use tokio_util::codec::Framed;
pub(crate) struct ConnectionHandler<St: Storage> {
packet_processor: PacketProcessor,
@@ -173,37 +174,23 @@ impl<St: Storage> ConnectionHandler<St> {
self.handle_processed_packet(processed_final_hop).await
}
pub(crate) async fn handle_connection(mut self, conn: Connection, mut shutdown: TaskClient) {
debug!(
"Starting connection handler for {:?}",
conn.remote_address()
);
pub(crate) async fn handle_connection(
mut self,
conn: TcpStream,
remote: SocketAddr,
mut shutdown: TaskClient,
) {
debug!("Starting connection handler for {:?}", remote);
shutdown.mark_as_success();
let mut framed_conn = Framed::new(conn, NymCodec);
while !shutdown.is_shutdown() {
tokio::select! {
biased;
_ = shutdown.recv() => {
log::trace!("ConnectionHandler: received shutdown");
}
recv = conn.accept_uni() => {
let recv_stream = match recv {
Ok(recv_stream) => recv_stream,
Err(err) => {
match err {
ConnectionError::TimedOut => {
//normal timeout, we just need to drop the connection
break;
},
_ => {
error!("Error accepting uni stream - {err:?}");
break;
},
}
}
};
let mut framed_stream = FramedRead::new(recv_stream, NymCodec);
match framed_stream.next().await {
framed_sphinx_packet = framed_conn.next() => {
match framed_sphinx_packet {
Some(Ok(framed_sphinx_packet)) => {
// TODO: benchmark spawning tokio task with full processing vs just processing it
// synchronously under higher load in single and multi-threaded situation.
@@ -225,6 +212,9 @@ impl<St: Storage> ConnectionHandler<St> {
}
}
info!("Closing connection from {:?}", conn.remote_address());
info!(
"Closing connection from {:?}",
framed_conn.into_inner().peer_addr()
);
}
}
@@ -5,10 +5,8 @@ use crate::node::mixnet_handling::receiver::connection_handler::ConnectionHandle
use crate::node::storage::Storage;
use log::*;
use nym_task::TaskClient;
use quinn::{Endpoint, ServerConfig};
use rcgen::generate_simple_self_signed;
use rustls::{Certificate, PrivateKey};
use std::net::SocketAddr;
use std::process;
use tokio::task::JoinHandle;
pub(crate) struct Listener {
@@ -27,7 +25,13 @@ impl Listener {
St: Storage + Clone + 'static,
{
info!("Starting mixnet listener at {}", self.address);
let endpoint = Endpoint::server(server_config(), self.address).unwrap();
let tcp_listener = match tokio::net::TcpListener::bind(self.address).await {
Ok(listener) => listener,
Err(err) => {
error!("Failed to bind to {} - {err}. Are you sure nothing else is running on the specified port and your user has sufficient permission to bind to the requested address?", self.address);
process::exit(1);
}
};
while !self.shutdown.is_shutdown() {
tokio::select! {
@@ -35,22 +39,13 @@ impl Listener {
_ = self.shutdown.recv() => {
log::trace!("mixnet_handling::Listener: Received shutdown");
}
connection = endpoint.accept() => {
connection = tcp_listener.accept() => {
match connection {
Some(connecting) => {
match connecting.await {
Ok(conn) => {
debug!("Handling connection from {:?}", conn.remote_address());
let handler = connection_handler.clone();
tokio::spawn(handler.handle_connection(conn, self.shutdown.clone()));
},
Err(err) => error!("Failed to establish connection - {err:?}"),
}
Ok((socket, remote_addr)) => {
let handler = connection_handler.clone();
tokio::spawn(handler.handle_connection(socket, remote_addr, self.shutdown.clone()));
}
None => {
error!("Endpoint closed");
break;
}, // stream got closed by remote
Err(err) => warn!("failed to get client: {err}"),
}
}
}
@@ -66,13 +61,3 @@ impl Listener {
tokio::spawn(async move { self.run(connection_handler).await })
}
}
fn generate_self_signed_cert() -> Result<(Certificate, PrivateKey), Box<dyn std::error::Error>> {
let cert = generate_simple_self_signed(vec!["mixnode".to_string()])?;
let key = PrivateKey(cert.serialize_private_key_der());
Ok((Certificate(cert.serialize_der()?), key))
}
fn server_config() -> ServerConfig {
let (cert, key) = generate_self_signed_cert().expect("Failed to generate certificate");
ServerConfig::with_single_cert(vec![cert], key).expect("Failed to generate server config")
}
+1 -5
View File
@@ -33,14 +33,10 @@ serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true }
sysinfo = "0.27.7"
tokio = { version = "1.21.2", features = ["rt-multi-thread", "net", "signal"] }
tokio-util = { version = "0.7.3", features = ["codec", "net"] }
tokio-util = { version = "0.7.3", features = ["codec"] }
toml = "0.5.8"
url = { version = "2.2", features = ["serde"] }
cfg-if = "1.0.0"
quinn = "0.10.1"
rustls = {version = "0.21.1", features = ["quic"]}
rcgen = "*"
bytes = "*"
## tracing
tracing = { version = "0.1.37", optional = true }
@@ -12,10 +12,10 @@ use nym_sphinx::forwarding::packet::MixPacket;
use nym_sphinx::framing::codec::NymCodec;
use nym_sphinx::framing::packet::FramedNymPacket;
use nym_sphinx::Delay as SphinxDelay;
use quinn::{Connection, ConnectionError};
use std::net::SocketAddr;
use tokio::net::TcpStream;
use tokio::time::Instant;
use tokio_util::codec::FramedRead;
use tokio_util::codec::Framed;
#[cfg(feature = "cpucycles")]
use tracing::{error, info, instrument};
@@ -54,7 +54,7 @@ impl ConnectionHandler {
feature = "cpucycles",
instrument(skip(self, framed_sphinx_packet), fields(cpucycles))
)]
async fn handle_received_packet(&self, framed_sphinx_packet: FramedNymPacket) {
fn handle_received_packet(&self, framed_sphinx_packet: FramedNymPacket) {
//
// TODO: here be replay attack detection - it will require similar key cache to the one in
// packet processor for vpn packets,
@@ -78,51 +78,37 @@ impl ConnectionHandler {
})
}
pub(crate) async fn handle_connection(self, conn: Connection, mut shutdown: TaskClient) {
debug!(
"Starting connection handler for {:?}",
conn.remote_address()
);
pub(crate) async fn handle_connection(
self,
conn: TcpStream,
remote: SocketAddr,
mut shutdown: TaskClient,
) {
debug!("Starting connection handler for {:?}", remote);
shutdown.mark_as_success();
let mut framed_conn = Framed::new(conn, NymCodec);
while !shutdown.is_shutdown() {
tokio::select! {
biased;
_ = shutdown.recv() => {
log::trace!("ConnectionHandler: received shutdown");
}
recv = conn.accept_uni() => {
let recv_stream = match recv {
Ok(recv_stream) => recv_stream,
Err(err) => {
match err {
ConnectionError::TimedOut => {
//normal timeout, we just need to drop the connection
break;
},
_ => {
error!("Error accepting uni stream - {err:?}");
break;
},
}
}
};
let mut framed_stream = FramedRead::new(recv_stream, NymCodec);
match framed_stream.next().await {
framed_sphinx_packet = framed_conn.next() => {
match framed_sphinx_packet {
Some(Ok(framed_sphinx_packet)) => {
// TODO: benchmark spawning tokio task with full processing vs just processing it
// synchronously under higher load in single and multi-threaded situation.
// synchronously (without delaying inside of course,
// delay is moved to a global DelayQueue)
// under higher load in single and multi-threaded situation.
// in theory we could process multiple sphinx packet from the same connection in parallel,
// but we already handle multiple concurrent connections so if anything, making
// that change would only slow things down
self.handle_received_packet(framed_sphinx_packet).await;
self.handle_received_packet(framed_sphinx_packet);
}
Some(Err(err)) => {
error!(
"The socket connection got corrupted with error: {err}. Closing the socket",
"{remote:?} - The socket connection got corrupted with error: {err}. Closing the socket",
);
return;
}
@@ -132,7 +118,10 @@ impl ConnectionHandler {
}
}
info!("Closing connection from {:?}", conn.remote_address());
info!(
"Closing connection from {:?}",
framed_conn.into_inner().peer_addr()
);
log::trace!("ConnectionHandler: Exiting");
}
}
+15 -36
View File
@@ -2,10 +2,9 @@
// SPDX-License-Identifier: Apache-2.0
use crate::node::listener::connection_handler::ConnectionHandler;
use quinn::{Endpoint, ServerConfig};
use rcgen::generate_simple_self_signed;
use rustls::{Certificate, PrivateKey};
use std::net::SocketAddr;
use std::process;
use tokio::net::TcpListener;
use tokio::task::JoinHandle;
#[cfg(feature = "cpucycles")]
use tracing::error;
@@ -26,36 +25,27 @@ impl Listener {
async fn run(&mut self, connection_handler: ConnectionHandler) {
log::trace!("Starting Listener");
let endpoint = Endpoint::server(server_config(), self.address).unwrap();
let listener = match TcpListener::bind(self.address).await {
Ok(listener) => listener,
Err(err) => {
error!("Failed to bind to {} - {err}. Are you sure nothing else is running on the specified port and your user has sufficient permission to bind to the requested address?", self.address);
process::exit(1);
}
};
while !self.shutdown.is_shutdown() {
tokio::select! {
biased;
_ = self.shutdown.recv() => {
log::trace!("Listener: Received shutdown");
},
connection = endpoint.accept() => {
}
connection = listener.accept() => {
match connection {
Some(connecting) => {
match connecting.await {
Ok(conn) => {
debug!("Handling connection from {:?}", conn.remote_address());
let handler = connection_handler.clone();
tokio::spawn(handler.handle_connection(conn, self.shutdown.clone()));
},
Err(err) => error!("Failed to establish connection - {err:?}"),
}
Ok((socket, remote_addr)) => {
let handler = connection_handler.clone();
tokio::spawn(handler.handle_connection(socket, remote_addr, self.shutdown.clone()));
}
// Some(Err(err)) => {
// error!(
// "The socket connection got corrupted with error: {err}. Closing the socket",
// );
// return;
// }
None => {
error!("Endpoint closed");
break;
}, // stream got closed by remote
Err(err) => warn!("Failed to accept incoming connection - {err}"),
}
},
};
@@ -69,14 +59,3 @@ impl Listener {
tokio::spawn(async move { self.run(connection_handler).await })
}
}
fn generate_self_signed_cert(
) -> Result<(rustls::Certificate, rustls::PrivateKey), Box<dyn std::error::Error>> {
let cert = generate_simple_self_signed(vec!["mixnode".to_string()])?;
let key = PrivateKey(cert.serialize_private_key_der());
Ok((Certificate(cert.serialize_der()?), key))
}
fn server_config() -> ServerConfig {
let (cert, key) = generate_self_signed_cert().expect("Failed to generate certificate");
ServerConfig::with_single_cert(vec![cert], key).expect("Failed to generate server config")
}
+1 -1
View File
@@ -1,4 +1,4 @@
// Copyright 2021-2022 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::node_status_api::models::ErrorResponse;
@@ -1,4 +1,4 @@
// Copyright 2021-2022 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use cosmwasm_std::Decimal;
+1 -1
View File
@@ -1,4 +1,4 @@
// Copyright 2021-2022 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use super::helpers::_get_gateways_detailed;
+1 -1
View File
@@ -1,4 +1,4 @@
// Copyright 2021-2022 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::nym_contract_cache::cache::NymContractCache;
+1 -1
View File
@@ -1,4 +1,4 @@
// Copyright 2021-2022 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::{
+17 -2
View File
@@ -3220,7 +3220,7 @@ dependencies = [
[[package]]
name = "nym-bin-common"
version = "0.5.0"
version = "0.6.0"
dependencies = [
"atty",
"clap",
@@ -3235,7 +3235,7 @@ dependencies = [
[[package]]
name = "nym-client-core"
version = "1.1.14"
version = "1.1.15"
dependencies = [
"async-trait",
"base64 0.21.2",
@@ -3365,6 +3365,7 @@ dependencies = [
"nym-credential-storage",
"nym-crypto",
"nym-socks5-client-core",
"nym-sphinx",
"nym-task",
"pretty_env_logger",
"rand 0.8.5",
@@ -3735,6 +3736,7 @@ dependencies = [
"nym-pemstore",
"nym-sphinx-addressing",
"nym-sphinx-params",
"nym-sphinx-routing",
"nym-sphinx-types",
"nym-topology",
"rand 0.7.3",
@@ -3760,6 +3762,7 @@ dependencies = [
"nym-crypto",
"nym-sphinx-addressing",
"nym-sphinx-params",
"nym-sphinx-routing",
"nym-sphinx-types",
"nym-topology",
"rand 0.7.3",
@@ -3790,6 +3793,7 @@ dependencies = [
"nym-sphinx-chunking",
"nym-sphinx-forwarding",
"nym-sphinx-params",
"nym-sphinx-routing",
"nym-sphinx-types",
"nym-topology",
"rand 0.7.3",
@@ -3906,6 +3910,7 @@ dependencies = [
"nym-service-provider-directory-common",
"nym-vesting-contract",
"nym-vesting-contract-common",
"openssl",
"prost",
"reqwest",
"serde",
@@ -4045,6 +4050,15 @@ version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
[[package]]
name = "openssl-src"
version = "111.26.0+1.1.1u"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "efc62c9f12b22b8f5208c23a7200a442b2e5999f8bdf80233852122b5a4f6f37"
dependencies = [
"cc",
]
[[package]]
name = "openssl-sys"
version = "0.9.82"
@@ -4054,6 +4068,7 @@ dependencies = [
"autocfg",
"cc",
"libc",
"openssl-src",
"pkg-config",
"vcpkg",
]
+2 -1
View File
@@ -48,11 +48,12 @@ yaml-rust = "0.4"
nym-client-core = { path = "../../../common/client-core" }
nym-api-requests = { path = "../../../nym-api/nym-api-requests" }
nym-contracts-common = { path = "../../../common/cosmwasm-smart-contracts/contracts-common"}
nym-config-common = { path = "../../../common/config", package = "nym-config" }
nym-config = { path = "../../../common/config" }
nym-crypto = { path = "../../../common/crypto" }
nym-credential-storage = { path = "../../../common/credential-storage" }
nym-bin-common = { path = "../../../common/bin-common"}
nym-socks5-client-core = { path = "../../../common/socks5-client-core" }
nym-sphinx = { path = "../../../common/nymsphinx" }
nym-task = { path = "../../../common/task" }
[dev-dependencies]
@@ -3,12 +3,13 @@
use crate::config::persistence::NymConnectPaths;
use crate::config::template::CONFIG_TEMPLATE;
use crate::config::upgrade::try_upgrade_config;
use crate::error::{BackendError, Result};
use nym_client_core::client::base_client::storage::gateway_details::OnDiskGatewayDetails;
use nym_client_core::client::key_manager::persistence::OnDiskKeys;
use nym_client_core::config::GatewayEndpointConfig;
use nym_client_core::init::GatewaySetup;
use nym_config_common::{
use nym_config::{
must_get_home, read_config_from_toml_file, save_formatted_config_to_file, NymConfigTemplate,
DEFAULT_CONFIG_DIR, DEFAULT_CONFIG_FILENAME, DEFAULT_DATA_DIR, NYM_DIR,
};
@@ -19,8 +20,12 @@ use std::path::{Path, PathBuf};
use std::{fs, io};
use tap::TapFallible;
mod old_config_v1_1_13;
mod old_config_v1_1_20;
mod old_config_v1_1_20_2;
mod persistence;
mod template;
mod upgrade;
static SOCKS5_CONFIG_ID: &str = "nym-connect";
@@ -138,6 +143,9 @@ pub async fn init_socks5_config(provider_address: String, chosen_gateway_id: Str
.map_err(|_| BackendError::UnableToParseGateway)?;
let already_init = if default_config_filepath(&id).exists() {
// in case we're using old config, try to upgrade it
// (if we're using the current version, it's a no-op)
try_upgrade_config(&id)?;
eprintln!("SOCKS5 client \"{id}\" was already initialised before");
true
} else {
@@ -156,11 +164,15 @@ pub async fn init_socks5_config(provider_address: String, chosen_gateway_id: Str
log::trace!("Creating config for id: {id}");
let mut config = Config::new(&id, &provider_address);
if let Ok(raw_validators) = std::env::var(nym_config_common::defaults::var_names::NYM_API) {
config.core.base.client.nym_api_urls = nym_config_common::parse_urls(&raw_validators);
if let Ok(raw_validators) = std::env::var(nym_config::defaults::var_names::NYM_API) {
config.core.base.client.nym_api_urls = nym_config::parse_urls(&raw_validators);
}
let gateway_setup = GatewaySetup::new_fresh(Some(chosen_gateway_id), None);
let gateway_setup = if register_gateway {
GatewaySetup::new_fresh(Some(chosen_gateway_id), None)
} else {
GatewaySetup::MustLoad
};
// Setup gateway by either registering a new one, or reusing exiting keys
let key_store = OnDiskKeys::new(config.storage_paths.common_paths.keys.clone());
@@ -0,0 +1,38 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::config::old_config_v1_1_20::{ConfigV1_1_20, Socks5V1_1_20};
use nym_client_core::config::old_config_v1_1_13::OldConfigV1_1_13 as OldBaseConfigV1_1_13;
use nym_config::legacy_helpers::nym_config::MigrationNymConfig;
use nym_config::must_get_home;
use serde::{Deserialize, Serialize};
use std::path::PathBuf;
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct OldConfigV1_1_13 {
#[serde(flatten)]
pub base: OldBaseConfigV1_1_13<OldConfigV1_1_13>,
pub socks5: Socks5V1_1_20,
}
impl MigrationNymConfig for OldConfigV1_1_13 {
fn default_root_directory() -> PathBuf {
#[cfg(not(any(target_os = "android", target_os = "ios")))]
let base_dir = must_get_home();
#[cfg(any(target_os = "android", target_os = "ios"))]
let base_dir = PathBuf::from("/tmp");
base_dir.join(".nym").join("socks5-clients")
}
}
impl From<OldConfigV1_1_13> for ConfigV1_1_20 {
fn from(value: OldConfigV1_1_13) -> Self {
ConfigV1_1_20 {
base: value.base.into(),
socks5: value.socks5,
}
}
}
@@ -0,0 +1,137 @@
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::config::old_config_v1_1_20_2::{
ConfigV1_1_20_2, CoreConfigV1_1_20_2, SocksClientPathsV1_1_20_2,
};
use nym_bin_common::logging::LoggingSettings;
use nym_client_core::config::disk_persistence::keys_paths::ClientKeysPaths;
use nym_client_core::config::disk_persistence::old_v1_1_20_2::CommonClientPathsV1_1_20_2;
use nym_client_core::config::old_config_v1_1_20::ConfigV1_1_20 as BaseConfigV1_1_20;
use nym_client_core::config::old_config_v1_1_20_2::ClientV1_1_20_2;
use nym_config::legacy_helpers::nym_config::MigrationNymConfig;
use nym_config::must_get_home;
use nym_socks5_client_core::config::old_config_v1_1_20_2::{
BaseClientConfigV1_1_20_2, Socks5DebugV1_1_20_2, Socks5V1_1_20_2,
};
use nym_socks5_client_core::config::{ProviderInterfaceVersion, Socks5ProtocolVersion};
use serde::{Deserialize, Serialize};
use std::fmt::Debug;
use std::path::PathBuf;
const DEFAULT_CONNECTION_START_SURBS: u32 = 20;
const DEFAULT_PER_REQUEST_SURBS: u32 = 3;
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct ConfigV1_1_20 {
#[serde(flatten)]
pub base: BaseConfigV1_1_20<ConfigV1_1_20>,
pub socks5: Socks5V1_1_20,
}
impl From<ConfigV1_1_20> for ConfigV1_1_20_2 {
fn from(value: ConfigV1_1_20) -> Self {
ConfigV1_1_20_2 {
core: CoreConfigV1_1_20_2 {
base: BaseClientConfigV1_1_20_2 {
client: ClientV1_1_20_2 {
version: value.base.client.version,
id: value.base.client.id,
disabled_credentials_mode: value.base.client.disabled_credentials_mode,
nyxd_urls: value.base.client.nyxd_urls,
nym_api_urls: value.base.client.nym_api_urls,
gateway_endpoint: value.base.client.gateway_endpoint.into(),
},
debug: value.base.debug.into(),
},
socks5: value.socks5.into(),
},
storage_paths: SocksClientPathsV1_1_20_2 {
common_paths: CommonClientPathsV1_1_20_2 {
keys: ClientKeysPaths {
private_identity_key_file: value.base.client.private_identity_key_file,
public_identity_key_file: value.base.client.public_identity_key_file,
private_encryption_key_file: value.base.client.private_encryption_key_file,
public_encryption_key_file: value.base.client.public_encryption_key_file,
gateway_shared_key_file: value.base.client.gateway_shared_key_file,
ack_key_file: value.base.client.ack_key_file,
},
credentials_database: value.base.client.database_path,
reply_surb_database: value.base.client.reply_surb_database_path,
},
},
logging: LoggingSettings::default(),
}
}
}
impl MigrationNymConfig for ConfigV1_1_20 {
fn default_root_directory() -> PathBuf {
#[cfg(not(any(target_os = "android", target_os = "ios")))]
let base_dir = must_get_home();
#[cfg(any(target_os = "android", target_os = "ios"))]
let base_dir = PathBuf::from("/tmp");
base_dir.join(".nym").join("socks5-clients")
}
}
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct Socks5V1_1_20 {
pub listening_port: u16,
pub provider_mix_address: String,
#[serde(default = "ProviderInterfaceVersion::new_legacy")]
pub provider_interface_version: ProviderInterfaceVersion,
#[serde(default = "Socks5ProtocolVersion::new_legacy")]
pub socks5_protocol_version: Socks5ProtocolVersion,
#[serde(default)]
pub send_anonymously: bool,
#[serde(default)]
pub socks5_debug: Socks5DebugV1_1_20,
}
impl From<Socks5V1_1_20> for Socks5V1_1_20_2 {
fn from(value: Socks5V1_1_20) -> Self {
Socks5V1_1_20_2 {
listening_port: value.listening_port,
provider_mix_address: value.provider_mix_address,
provider_interface_version: value.provider_interface_version,
socks5_protocol_version: value.socks5_protocol_version,
send_anonymously: value.send_anonymously,
socks5_debug: value.socks5_debug.into(),
}
}
}
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct Socks5DebugV1_1_20 {
connection_start_surbs: u32,
per_request_surbs: u32,
}
impl From<Socks5DebugV1_1_20> for Socks5DebugV1_1_20_2 {
fn from(value: Socks5DebugV1_1_20) -> Self {
Socks5DebugV1_1_20_2 {
connection_start_surbs: value.connection_start_surbs,
per_request_surbs: value.per_request_surbs,
}
}
}
impl Default for Socks5DebugV1_1_20 {
fn default() -> Self {
Socks5DebugV1_1_20 {
connection_start_surbs: DEFAULT_CONNECTION_START_SURBS,
per_request_surbs: DEFAULT_PER_REQUEST_SURBS,
}
}
}
@@ -0,0 +1,54 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::config::persistence::NymConnectPaths;
use crate::config::{default_config_filepath, Config};
use nym_bin_common::logging::LoggingSettings;
use nym_client_core::config::disk_persistence::old_v1_1_20_2::CommonClientPathsV1_1_20_2;
use nym_client_core::config::GatewayEndpointConfig;
use nym_config::read_config_from_toml_file;
pub use nym_socks5_client_core::config::old_config_v1_1_20_2::ConfigV1_1_20_2 as CoreConfigV1_1_20_2;
use serde::{Deserialize, Serialize};
use std::io;
use std::path::Path;
#[derive(Debug, Deserialize, PartialEq, Eq, Serialize, Clone)]
pub struct SocksClientPathsV1_1_20_2 {
#[serde(flatten)]
pub common_paths: CommonClientPathsV1_1_20_2,
}
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct ConfigV1_1_20_2 {
pub core: CoreConfigV1_1_20_2,
pub storage_paths: SocksClientPathsV1_1_20_2,
pub logging: LoggingSettings,
}
impl ConfigV1_1_20_2 {
pub fn read_from_toml_file<P: AsRef<Path>>(path: P) -> io::Result<Self> {
read_config_from_toml_file(path)
}
pub fn read_from_default_path<P: AsRef<Path>>(id: P) -> io::Result<Self> {
Self::read_from_toml_file(default_config_filepath(id))
}
// in this upgrade, gateway endpoint configuration was moved out of the config file,
// so its returned to be stored elsewhere.
pub fn upgrade(self) -> (Config, GatewayEndpointConfig) {
let gateway_details = self.core.base.client.gateway_endpoint.clone().into();
let config = Config {
core: self.core.into(),
storage_paths: NymConnectPaths {
common_paths: self.storage_paths.common_paths.upgrade_default(),
},
// logging: self.logging,
};
(config, gateway_details)
}
}
@@ -0,0 +1,111 @@
// Copyright 2022-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::{
config::{
old_config_v1_1_13::OldConfigV1_1_13, old_config_v1_1_20::ConfigV1_1_20,
old_config_v1_1_20_2::ConfigV1_1_20_2, Config,
},
error::{BackendError, Result},
};
use log::info;
use nym_client_core::{
client::{
base_client::storage::gateway_details::{OnDiskGatewayDetails, PersistedGatewayDetails},
key_manager::persistence::OnDiskKeys,
},
config::GatewayEndpointConfig,
error::ClientCoreError,
};
fn persist_gateway_details(config: &Config, details: GatewayEndpointConfig) -> Result<()> {
let details_store =
OnDiskGatewayDetails::new(&config.storage_paths.common_paths.gateway_details);
let keys_store = OnDiskKeys::new(config.storage_paths.common_paths.keys.clone());
let shared_keys = keys_store.ephemeral_load_gateway_keys().map_err(|source| {
BackendError::ClientCoreError {
source: ClientCoreError::KeyStoreError {
source: Box::new(source),
},
}
})?;
let persisted_details = PersistedGatewayDetails::new(details, &shared_keys);
details_store
.store_to_disk(&persisted_details)
.map_err(|source| BackendError::ClientCoreError {
source: ClientCoreError::GatewayDetailsStoreError {
source: Box::new(source),
},
})
}
fn try_upgrade_v1_1_13_config(id: &str) -> Result<bool> {
use nym_config::legacy_helpers::nym_config::MigrationNymConfig;
// explicitly load it as v1.1.13 (which is incompatible with the next step, i.e. 1.1.19)
let Ok(old_config) = OldConfigV1_1_13::load_from_file(id) else {
// if we failed to load it, there might have been nothing to upgrade
// or maybe it was an even older file. in either way. just ignore it and carry on with our day
return Ok(false);
};
info!("It seems the client is using <= v1.1.13 config template.");
info!("It is going to get updated to the current specification.");
let updated_step1: ConfigV1_1_20 = old_config.into();
let updated_step2: ConfigV1_1_20_2 = updated_step1.into();
let (updated, gateway_config) = updated_step2.upgrade();
persist_gateway_details(&updated, gateway_config)?;
updated.save_to_default_location()?;
Ok(true)
}
fn try_upgrade_v1_1_20_config(id: &str) -> Result<bool> {
use nym_config::legacy_helpers::nym_config::MigrationNymConfig;
// explicitly load it as v1.1.20 (which is incompatible with the current one, i.e. +1.1.21)
let Ok(old_config) = ConfigV1_1_20::load_from_file(id) else {
// if we failed to load it, there might have been nothing to upgrade
// or maybe it was an even older file. in either way. just ignore it and carry on with our day
return Ok(false);
};
info!("It seems the client is using <= v1.1.20 config template.");
info!("It is going to get updated to the current specification.");
let updated_step1: ConfigV1_1_20_2 = old_config.into();
let (updated, gateway_config) = updated_step1.upgrade();
persist_gateway_details(&updated, gateway_config)?;
updated.save_to_default_location()?;
Ok(true)
}
fn try_upgrade_v1_1_20_2_config(id: &str) -> Result<bool> {
// explicitly load it as v1.1.20_2 (which is incompatible with the current one, i.e. +1.1.21)
let Ok(old_config) = ConfigV1_1_20_2::read_from_default_path(id) else {
// if we failed to load it, there might have been nothing to upgrade
// or maybe it was an even older file. in either way. just ignore it and carry on with our day
return Ok(false);
};
info!("It seems the client is using <= v1.1.20_2 config template.");
info!("It is going to get updated to the current specification.");
let (updated, gateway_config) = old_config.upgrade();
persist_gateway_details(&updated, gateway_config)?;
updated.save_to_default_location()?;
Ok(true)
}
pub fn try_upgrade_config(id: &str) -> Result<()> {
if try_upgrade_v1_1_13_config(id)? {
return Ok(());
}
if try_upgrade_v1_1_20_config(id)? {
return Ok(());
}
if try_upgrade_v1_1_20_2_config(id)? {
return Ok(());
}
Ok(())
}
+6 -1
View File
@@ -5,7 +5,7 @@
use std::sync::Arc;
use nym_config_common::defaults::setup_env;
use nym_config::defaults::setup_env;
use tauri::Manager;
use tokio::sync::RwLock;
@@ -25,6 +25,11 @@ mod tasks;
mod window;
fn main() {
if std::env::var("NYM_CONNECT_ENABLE_MEDIUM").is_ok() {
std::env::set_var("NYM_CONNECT_DISABLE_COVER", "1");
std::env::set_var("NYM_CONNECT_ENABLE_MIXED_SIZE_PACKETS", "1");
std::env::set_var("NYM_CONNECT_DISABLE_PER_HOP_DELAYS", "1");
}
setup_env(None);
println!("Starting up...");
+24 -1
View File
@@ -4,6 +4,7 @@ use nym_client_core::client::base_client::storage::{MixnetClientStorage, OnDiskP
use nym_client_core::{config::GatewayEndpointConfig, error::ClientCoreStatusMessage};
use nym_socks5_client_core::NymClient as Socks5NymClient;
use nym_socks5_client_core::Socks5ControlMessageSender;
use nym_sphinx::params::PacketSize;
use nym_task::manager::TaskStatus;
use std::sync::Arc;
use tap::TapFallible;
@@ -39,9 +40,31 @@ pub async fn start_nym_socks5_client(
GatewayEndpointConfig,
)> {
log::info!("Loading config from file: {id}");
let config = Config::read_from_default_path(id)
let mut config = Config::read_from_default_path(id)
.tap_err(|_| log::warn!("Failed to load configuration file"))?;
// Disable both the loop cover traffic that runs in the background as well as the Poisson
// process that injects cover traffic into the traffic stream.
if std::env::var("NYM_CONNECT_DISABLE_COVER").is_ok() {
log::warn!("Disabling cover traffic");
config.core.base.set_no_cover_traffic_with_keepalive();
}
if std::env::var("NYM_CONNECT_ENABLE_MIXED_SIZE_PACKETS").is_ok() {
log::warn!("Enabling mixed size packets");
config
.core
.base
.set_secondary_packet_size(Some(PacketSize::ExtendedPacket16));
}
if std::env::var("NYM_CONNECT_DISABLE_PER_HOP_DELAYS").is_ok() {
log::warn!("Disabling per-hop delay");
config.core.base.set_no_per_hop_delays();
}
log::trace!("Configuration used: {:#?}", config);
let storage =
OnDiskPersistent::from_paths(config.storage_paths.common_paths, &config.core.base.debug)
.await?;
@@ -28,7 +28,7 @@
],
"resources": [],
"externalBin": [],
"copyright": "Copyright © 2021-2022 Nym Technologies SA",
"copyright": "Copyright © 2021-2023 Nym Technologies SA",
"category": "Business",
"shortDescription": "Browse the internet privately using the Nym Mixnet",
"longDescription": "",
+1 -1
View File
@@ -23,7 +23,7 @@
],
"resources": [],
"externalBin": [],
"copyright": "Copyright © 2021-2022 Nym Technologies SA",
"copyright": "Copyright © 2021-2023 Nym Technologies SA",
"category": "Business",
"shortDescription": "Browse the internet privately using the Nym Mixnet",
"longDescription": "",
@@ -114,6 +114,11 @@ class MainActivity : ComponentActivity() {
}
}
}
override fun onStart() {
super.onStart()
viewModel.checkStateSync()
}
}
@OptIn(ExperimentalMaterial3Api::class)
@@ -56,8 +56,7 @@ class MainViewModel(
// this viewModel instance is cleared
// use GlobalScope instead
GlobalScope.launch(Dispatchers.IO) {
// if the proxy process is still running ie. connected
// kill it
// if the proxy process is still running ie. connected kill it
if (nymProxy.getState() == NymProxy.Companion.State.CONNECTED) {
Log.d(tag, "stopping proxy")
nymProxy.stop()
@@ -131,6 +130,29 @@ class MainViewModel(
setDisconnected()
}
}
fun checkStateSync() {
Log.d(tag, "check state sync")
viewModelScope.launch(Dispatchers.IO) {
val proxyState = nymProxy.getState()
val workInfo = workManager.getWorkInfoById(ProxyWorker.workId).get()
Log.d(tag, "proxy state $proxyState, work state ${workInfo?.state}")
if (proxyState == NymProxy.Companion.State.CONNECTED &&
workInfo?.state != WorkInfo.State.RUNNING
) {
Log.w(tag, "⚠ state desync")
Log.i(tag, "stopping proxy")
cancelProxyWork()
}
if (proxyState == NymProxy.Companion.State.DISCONNECTED &&
workInfo?.state == WorkInfo.State.RUNNING
) {
Log.w(tag, "⚠ state desync")
Log.i(tag, "stopping worker")
workManager.cancelAllWorkByTag(ProxyWorker.workTag)
}
}
}
}
class MainViewModelFactory(
+3 -1
View File
@@ -9,9 +9,11 @@ pub const DEFAULT_HOPS: usize = 4;
pub const ROUTING_INFORMATION_LENGTH_BY_STAGE: [u8; DEFAULT_HOPS] =
[DEFAULT_ROUTING_INFO_SIZE; DEFAULT_HOPS];
pub const MIN_PACKET_SIZE: usize = 48;
pub const MAGIC_SLICE: &[u8] = &[111, 102, 120];
pub const OUTFOX_PACKET_OVERHEAD: usize = MIX_PARAMS_LEN
+ (groupelementbytes() + tagbytes() + DEFAULT_ROUTING_INFO_SIZE as usize) * DEFAULT_HOPS;
+ (groupelementbytes() + tagbytes() + DEFAULT_ROUTING_INFO_SIZE as usize) * DEFAULT_HOPS
+ MAGIC_SLICE.len();
pub const fn groupelementbytes() -> usize {
GROUPELEMENTBYTES as usize
+3
View File
@@ -1,3 +1,4 @@
use crate::constants::MAGIC_SLICE;
use crate::constants::MIN_MESSAGE_LEN;
use crate::constants::MIX_PARAMS_LEN;
use chacha20::cipher::InvalidLength;
@@ -25,4 +26,6 @@ pub enum OutfoxError {
},
#[error("Header length must be {MIX_PARAMS_LEN}, got {0}")]
InvalidHeaderLength(usize),
#[error("Invalid magic bytes, expected: {:?}, got: {:?}", MAGIC_SLICE, 0)]
InvalidMagicBytes(Vec<u8>),
}
+15 -11
View File
@@ -7,7 +7,7 @@ use std::{
};
use crate::{
constants::{DEFAULT_HOPS, MIN_PACKET_SIZE, MIX_PARAMS_LEN},
constants::{DEFAULT_HOPS, MAGIC_SLICE, MIN_PACKET_SIZE, MIX_PARAMS_LEN},
error::OutfoxError,
format::{MixCreationParameters, MixStageParameters},
};
@@ -60,16 +60,19 @@ impl TryFrom<&[u8]> for OutfoxPacket {
}
impl OutfoxPacket {
pub fn recover_plaintext(&self) -> Vec<u8> {
pub fn recover_plaintext(&self) -> Result<Vec<u8>, OutfoxError> {
let plaintext = self.payload()[self.payload_range()].to_vec();
if plaintext.starts_with(&[0]) {
let mut plaintext = VecDeque::from_iter(plaintext);
while let Some(0) = plaintext.front() {
plaintext.pop_front();
}
return plaintext.make_contiguous().to_vec();
let mut plaintext = VecDeque::from_iter(plaintext);
while let Some(0) = plaintext.front() {
plaintext.pop_front();
}
let mut plaintext = plaintext.make_contiguous().to_vec();
let payload = plaintext.split_off(MAGIC_SLICE.len());
if plaintext != MAGIC_SLICE {
Err(OutfoxError::InvalidMagicBytes(plaintext))
} else {
Ok(payload)
}
plaintext
}
pub fn len(&self) -> usize {
@@ -100,11 +103,12 @@ impl OutfoxPacket {
MIN_PACKET_SIZE
} else {
packet_size
};
} + MAGIC_SLICE.len();
let mix_params = MixCreationParameters::new(packet_size as u16);
let padding = mix_params.total_packet_length() - payload.as_ref().len();
let padding = mix_params.total_packet_length() - payload.as_ref().len() - MAGIC_SLICE.len();
let mut buffer = vec![0; padding];
buffer.extend_from_slice(MAGIC_SLICE);
buffer.extend_from_slice(payload.as_ref());
// Last node in the route is a gateway, it will decrypt last, and get the final destination address
+59 -3
View File
@@ -88,7 +88,7 @@ mod tests {
}
#[test]
fn test_packet_params() {
fn test_packet_params_short() {
let (node1_pk, node1_pub) = sphinx_packet::crypto::keygen();
let node1 = Node::new(
NodeAddressBytes::from_bytes([0u8; NODE_ADDRESS_LENGTH]),
@@ -118,7 +118,7 @@ mod tests {
let route = [node1, node2.clone(), node3.clone(), gateway.clone()];
let payload = randombytes(21);
let payload = vec![0, 0, 1, 1, 1, 0, 0];
let packet =
OutfoxPacket::build(&payload, &route, &destination, Some(payload.len())).unwrap();
@@ -140,6 +140,62 @@ mod tests {
let destination_address = packet.decode_next_layer(&gateway_pk).unwrap();
assert_eq!(destination_address, destination.address.as_bytes());
assert_eq!(payload, packet.recover_plaintext());
assert_eq!(payload, packet.recover_plaintext().unwrap());
}
#[test]
fn test_packet_params_long() {
let (node1_pk, node1_pub) = sphinx_packet::crypto::keygen();
let node1 = Node::new(
NodeAddressBytes::from_bytes([0u8; NODE_ADDRESS_LENGTH]),
node1_pub,
);
let (node2_pk, node2_pub) = sphinx_packet::crypto::keygen();
let node2 = Node::new(
NodeAddressBytes::from_bytes([1u8; NODE_ADDRESS_LENGTH]),
node2_pub,
);
let (node3_pk, node3_pub) = sphinx_packet::crypto::keygen();
let node3 = Node::new(
NodeAddressBytes::from_bytes([2u8; NODE_ADDRESS_LENGTH]),
node3_pub,
);
let (gateway_pk, gateway_pub) = sphinx_packet::crypto::keygen();
let gateway = Node::new(
NodeAddressBytes::from_bytes([3u8; NODE_ADDRESS_LENGTH]),
gateway_pub,
);
let destination = Destination::new(
DestinationAddressBytes::from_bytes([9u8; NODE_ADDRESS_LENGTH]),
[0u8; 16],
);
let route = [node1, node2.clone(), node3.clone(), gateway.clone()];
let payload = randombytes(2048);
let packet =
OutfoxPacket::build(&payload, &route, &destination, Some(payload.len())).unwrap();
let packet_bytes = packet.to_bytes().unwrap();
println!(
"packet bytes length, {}, declared {}",
packet_bytes.len(),
packet.len()
);
let mut packet = OutfoxPacket::try_from(packet_bytes.as_slice()).unwrap();
let next_address = packet.decode_next_layer(&node1_pk).unwrap();
assert_eq!(next_address, node2.address.as_bytes());
let next_address = packet.decode_next_layer(&node2_pk).unwrap();
assert_eq!(next_address, node3.address.as_bytes());
let next_address = packet.decode_next_layer(&node3_pk).unwrap();
assert_eq!(next_address, gateway.address.as_bytes());
let destination_address = packet.decode_next_layer(&gateway_pk).unwrap();
assert_eq!(destination_address, destination.address.as_bytes());
assert_eq!(payload, packet.recover_plaintext().unwrap());
}
}
+4
View File
@@ -2,6 +2,10 @@
## [Unreleased]
## [v1.2.5] (2023-06-06)
- Wallet - Test my node feature. If a user has a node bonded, they can go to the node settings page and check whether their node is handling traffic well.
## [v1.2.4] (2023-06-06)
- Wallet - Bonding page does not load the node info automatically unless you navigate back and forth from it! ([#3478])
+83 -72
View File
@@ -128,13 +128,13 @@ checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6"
[[package]]
name = "async-trait"
version = "0.1.64"
version = "0.1.68"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1cd7fce9ba8c3c042128ce72d8b2ddbf3a05747efb67ea0313c635e10bda47a2"
checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.107",
"syn 2.0.15",
]
[[package]]
@@ -208,9 +208,9 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
[[package]]
name = "base64"
version = "0.21.0"
version = "0.21.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a"
checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d"
[[package]]
name = "base64ct"
@@ -605,7 +605,7 @@ dependencies = [
"proc-macro-error",
"proc-macro2",
"quote",
"syn 1.0.107",
"syn 1.0.109",
]
[[package]]
@@ -796,7 +796,7 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4b36e527620a2a3e00e46b6e731ab6c9b68d11069c986f7d7be8eba79ef081a4"
dependencies = [
"syn 1.0.107",
"syn 1.0.109",
]
[[package]]
@@ -940,7 +940,7 @@ dependencies = [
"proc-macro2",
"quote",
"smallvec",
"syn 1.0.107",
"syn 1.0.109",
]
[[package]]
@@ -950,7 +950,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dfae75de57f2b2e85e8768c3ea840fd159c8f33e2b6522c7835b7abac81be16e"
dependencies = [
"quote",
"syn 1.0.107",
"syn 1.0.109",
]
[[package]]
@@ -969,7 +969,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096"
dependencies = [
"quote",
"syn 1.0.107",
"syn 1.0.109",
]
[[package]]
@@ -1103,7 +1103,7 @@ dependencies = [
"proc-macro2",
"quote",
"strsim",
"syn 1.0.107",
"syn 1.0.109",
]
[[package]]
@@ -1114,7 +1114,7 @@ checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835"
dependencies = [
"darling_core",
"quote",
"syn 1.0.107",
"syn 1.0.109",
]
[[package]]
@@ -1136,7 +1136,7 @@ dependencies = [
"proc-macro2",
"quote",
"rustc_version 0.4.0",
"syn 1.0.107",
"syn 1.0.109",
]
[[package]]
@@ -1375,7 +1375,7 @@ checksum = "828de45d0ca18782232dfb8f3ea9cc428e8ced380eb26a520baaacfc70de39ce"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.107",
"syn 1.0.109",
]
[[package]]
@@ -1547,9 +1547,9 @@ dependencies = [
[[package]]
name = "futures"
version = "0.3.26"
version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13e2792b0ff0340399d58445b88fd9770e3489eff258a4cbc1523418f12abf84"
checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40"
dependencies = [
"futures-channel",
"futures-core",
@@ -1562,9 +1562,9 @@ dependencies = [
[[package]]
name = "futures-channel"
version = "0.3.26"
version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e5317663a9089767a1ec00a487df42e0ca174b61b4483213ac24448e4664df5"
checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2"
dependencies = [
"futures-core",
"futures-sink",
@@ -1572,15 +1572,15 @@ dependencies = [
[[package]]
name = "futures-core"
version = "0.3.26"
version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec90ff4d0fe1f57d600049061dc6bb68ed03c7d2fbd697274c41805dcb3f8608"
checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c"
[[package]]
name = "futures-executor"
version = "0.3.26"
version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8de0a35a6ab97ec8869e32a2473f4b1324459e14c29275d14b10cb1fd19b50e"
checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0"
dependencies = [
"futures-core",
"futures-task",
@@ -1589,38 +1589,38 @@ dependencies = [
[[package]]
name = "futures-io"
version = "0.3.26"
version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bfb8371b6fb2aeb2d280374607aeabfc99d95c72edfe51692e42d3d7f0d08531"
checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964"
[[package]]
name = "futures-macro"
version = "0.3.26"
version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95a73af87da33b5acf53acfebdc339fe592ecf5357ac7c0a7734ab9d8c876a70"
checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.107",
"syn 2.0.15",
]
[[package]]
name = "futures-sink"
version = "0.3.26"
version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f310820bb3e8cfd46c80db4d7fb8353e15dfff853a127158425f31e0be6c8364"
checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e"
[[package]]
name = "futures-task"
version = "0.3.26"
version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcf79a1bf610b10f42aea489289c5a2c478a786509693b80cd39c44ccd936366"
checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65"
[[package]]
name = "futures-util"
version = "0.3.26"
version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c1d6de3acfef38d2be4b1f543f553131788603495be83da675e180c8d6b7bd1"
checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533"
dependencies = [
"futures-channel",
"futures-core",
@@ -1783,7 +1783,7 @@ dependencies = [
"proc-macro-error",
"proc-macro2",
"quote",
"syn 1.0.107",
"syn 1.0.109",
]
[[package]]
@@ -1871,7 +1871,7 @@ dependencies = [
"proc-macro-error",
"proc-macro2",
"quote",
"syn 1.0.107",
"syn 1.0.109",
]
[[package]]
@@ -1978,7 +1978,7 @@ dependencies = [
"proc-macro-error",
"proc-macro2",
"quote",
"syn 1.0.107",
"syn 1.0.109",
]
[[package]]
@@ -2130,7 +2130,7 @@ dependencies = [
"markup5ever",
"proc-macro2",
"quote",
"syn 1.0.107",
"syn 1.0.109",
]
[[package]]
@@ -2825,7 +2825,7 @@ checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.107",
"syn 1.0.109",
]
[[package]]
@@ -2887,7 +2887,7 @@ dependencies = [
"proc-macro-crate",
"proc-macro2",
"quote",
"syn 1.0.107",
"syn 1.0.109",
]
[[package]]
@@ -2915,7 +2915,7 @@ dependencies = [
[[package]]
name = "nym-bin-common"
version = "0.5.0"
version = "0.6.0"
dependencies = [
"atty",
"clap",
@@ -3220,6 +3220,7 @@ dependencies = [
"nym-service-provider-directory-common",
"nym-vesting-contract",
"nym-vesting-contract-common",
"openssl",
"prost",
"reqwest",
"serde",
@@ -3297,7 +3298,7 @@ dependencies = [
[[package]]
name = "nym_wallet"
version = "1.2.4"
version = "1.2.5"
dependencies = [
"async-trait",
"base64 0.13.1",
@@ -3438,7 +3439,7 @@ checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.107",
"syn 1.0.109",
]
[[package]]
@@ -3447,6 +3448,15 @@ version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
[[package]]
name = "openssl-src"
version = "111.26.0+1.1.1u"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "efc62c9f12b22b8f5208c23a7200a442b2e5999f8bdf80233852122b5a4f6f37"
dependencies = [
"cc",
]
[[package]]
name = "openssl-sys"
version = "0.9.80"
@@ -3456,6 +3466,7 @@ dependencies = [
"autocfg",
"cc",
"libc",
"openssl-src",
"pkg-config",
"vcpkg",
]
@@ -3641,7 +3652,7 @@ dependencies = [
"pest_meta",
"proc-macro2",
"quote",
"syn 1.0.107",
"syn 1.0.109",
]
[[package]]
@@ -3718,7 +3729,7 @@ dependencies = [
"proc-macro-hack",
"proc-macro2",
"quote",
"syn 1.0.107",
"syn 1.0.109",
]
[[package]]
@@ -3732,7 +3743,7 @@ dependencies = [
"proc-macro-hack",
"proc-macro2",
"quote",
"syn 1.0.107",
"syn 1.0.109",
]
[[package]]
@@ -3770,7 +3781,7 @@ checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.107",
"syn 1.0.109",
]
[[package]]
@@ -3892,7 +3903,7 @@ dependencies = [
"proc-macro-error-attr",
"proc-macro2",
"quote",
"syn 1.0.107",
"syn 1.0.109",
"version_check",
]
@@ -3942,7 +3953,7 @@ dependencies = [
"itertools",
"proc-macro2",
"quote",
"syn 1.0.107",
"syn 1.0.109",
]
[[package]]
@@ -4174,7 +4185,7 @@ version = "0.11.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "21eed90ec8570952d53b772ecf8f206aa1ec9a3d76b2521c56c42973f2d91ee9"
dependencies = [
"base64 0.21.0",
"base64 0.21.2",
"bytes",
"encoding_rs",
"futures-core",
@@ -4381,7 +4392,7 @@ dependencies = [
"proc-macro2",
"quote",
"serde_derive_internals",
"syn 1.0.107",
"syn 1.0.109",
]
[[package]]
@@ -4535,7 +4546,7 @@ checksum = "85bf8229e7920a9f636479437026331ce11aa132b4dde37d121944a44d6e5f3c"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.107",
"syn 1.0.109",
]
[[package]]
@@ -4557,7 +4568,7 @@ checksum = "9a5ec9fa74a20ebbe5d9ac23dac1fc96ba0ecfe9f50f2843b52e537b10fbcb4e"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.107",
"syn 1.0.109",
]
[[package]]
@@ -4600,7 +4611,7 @@ dependencies = [
"darling",
"proc-macro2",
"quote",
"syn 1.0.107",
"syn 1.0.109",
]
[[package]]
@@ -4622,7 +4633,7 @@ checksum = "74064874e9f6a15f04c1f3cb627902d0e6b410abbf36668afa873c61889f1763"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.107",
"syn 1.0.109",
]
[[package]]
@@ -4881,7 +4892,7 @@ dependencies = [
"proc-macro2",
"quote",
"rustversion",
"syn 1.0.107",
"syn 1.0.109",
]
[[package]]
@@ -4907,9 +4918,9 @@ dependencies = [
[[package]]
name = "syn"
version = "1.0.107"
version = "1.0.109"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5"
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
dependencies = [
"proc-macro2",
"quote",
@@ -4935,7 +4946,7 @@ checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.107",
"syn 1.0.109",
"unicode-xid",
]
@@ -5132,7 +5143,7 @@ dependencies = [
"heck 0.4.1",
"proc-macro2",
"quote",
"syn 1.0.107",
"syn 1.0.109",
"tauri-codegen",
"tauri-utils",
]
@@ -5343,22 +5354,22 @@ checksum = "8eaa81235c7058867fa8c0e7314f33dcce9c215f535d1913822a2b3f5e289f3c"
[[package]]
name = "thiserror"
version = "1.0.38"
version = "1.0.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0"
checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.38"
version = "1.0.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f"
checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.107",
"syn 2.0.15",
]
[[package]]
@@ -5443,7 +5454,7 @@ checksum = "d266c00fde287f55d3f1c3e96c500c362a2b8c695076ec180f27918820bc6df8"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.107",
"syn 1.0.109",
]
[[package]]
@@ -5567,7 +5578,7 @@ checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.107",
"syn 1.0.109",
]
[[package]]
@@ -5643,7 +5654,7 @@ dependencies = [
"Inflector",
"proc-macro2",
"quote",
"syn 1.0.107",
"syn 1.0.109",
"termcolor",
]
@@ -5854,7 +5865,7 @@ dependencies = [
"once_cell",
"proc-macro2",
"quote",
"syn 1.0.107",
"syn 1.0.109",
"wasm-bindgen-shared",
]
@@ -5888,7 +5899,7 @@ checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.107",
"syn 1.0.109",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
@@ -5995,7 +6006,7 @@ checksum = "eaebe196c01691db62e9e4ca52c5ef1e4fd837dcae27dae3ada599b5a8fd05ac"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.107",
"syn 1.0.109",
]
[[package]]
@@ -6087,7 +6098,7 @@ version = "0.39.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba01f98f509cb5dc05f4e5fc95e535f78260f15fea8fe1a8abdd08f774f1cee7"
dependencies = [
"syn 1.0.107",
"syn 1.0.109",
"windows-tokens",
]
@@ -6443,7 +6454,7 @@ checksum = "44bf07cb3e50ea2003396695d58bf46bc9887a1f362260446fad6bc4e79bd36c"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.107",
"syn 1.0.109",
"synstructure",
]
+1 -1
View File
@@ -4,5 +4,5 @@ resolver = "2"
members = [
"src-tauri",
"nym-wallet-recovery-cli",
"nym-wallet-types"
"nym-wallet-types",
]
+585
View File
@@ -0,0 +1,585 @@
/* tslint:disable */
/* eslint-disable */
/**
* @param {string} api_server
* @param {string | undefined} preferred
* @returns {Promise<GatewayEndpointConfig>}
*/
export function get_gateway(api_server: string, preferred?: string): Promise<GatewayEndpointConfig>;
/**
* @param {string} nym_api_url
* @returns {Promise<any>}
*/
export function current_network_topology(nym_api_url: string): Promise<any>;
/**
* Encode a payload
* @param {string} mime_type
* @param {Uint8Array} payload
* @returns {Uint8Array}
*/
export function encode_payload(mime_type: string, payload: Uint8Array): Uint8Array;
/**
* Create a new binary message with a user-specified `kind`, and `headers` as a string.
* @param {string} mime_type
* @param {Uint8Array} payload
* @param {string | undefined} headers
* @returns {Uint8Array}
*/
export function encode_payload_with_headers(mime_type: string, payload: Uint8Array, headers?: string): Uint8Array;
/**
* Parse the `kind` and byte array `payload` from a byte array
* @param {Uint8Array} message
* @returns {EncodedPayload}
*/
export function decode_payload(message: Uint8Array): EncodedPayload;
/**
* Try parse a UTF-8 string from an array of bytes
* @param {Uint8Array} payload
* @returns {string}
*/
export function parse_utf8_string(payload: Uint8Array): string;
/**
* Converts a UTF-8 string into an array of bytes
*
* This method is provided as a replacement for the mess of `atob`
* (https://developer.mozilla.org/en-US/docs/Web/API/atob) helpers provided by browsers and NodeJS.
*
* Feel free to use `atob` if you know you won't have problems with polyfills or encoding issues.
* @param {string} message
* @returns {Uint8Array}
*/
export function utf8_string_to_byte_array(message: string): Uint8Array;
/**
* @param {string} recipient
*/
export function validate_recipient(recipient: string): void;
/**
*/
export function set_panic_hook(): void;
/**
* @returns {DebugWasm}
*/
export function default_debug(): DebugWasm;
export interface EncodedPayload {
mimeType: string,
payload: Uint8Array;
headers: string,
}
/**
*/
export class AcknowledgementsWasm {
free(): void;
/**
* Value added to the expected round trip time of an acknowledgement packet before
* it is assumed it was lost and retransmission of the data packet happens.
* In an ideal network with 0 latency, this value would have been 0.
*/
ack_wait_addition_ms: bigint;
/**
* Value multiplied with the expected round trip time of an acknowledgement packet before
* it is assumed it was lost and retransmission of the data packet happens.
* In an ideal network with 0 latency, this value would have been 1.
*/
ack_wait_multiplier: number;
/**
* The parameter of Poisson distribution determining how long, on average,
* sent acknowledgement is going to be delayed at any given mix node.
* So for an ack going through three mix nodes, on average, it will take three times this value
* until the packet reaches its destination.
*/
average_ack_delay_ms: bigint;
}
/**
*/
export class AnonymousSenderTag {
free(): void;
}
/**
*/
export class ClientStorage {
free(): void;
/**
* @param {string} client_id
* @param {string} passphrase
*/
constructor(client_id: string, passphrase: string);
/**
* @param {string} client_id
* @returns {Promise<any>}
*/
static new_unencrypted(client_id: string): Promise<any>;
}
/**
*/
export class Config {
free(): void;
/**
* @param {string} id
* @param {string} validator_server
* @param {DebugWasm | undefined} debug
*/
constructor(id: string, validator_server: string, debug?: DebugWasm);
}
/**
*/
export class CoverTrafficWasm {
free(): void;
/**
* Specifies the ratio of `primary_packet_size` to `secondary_packet_size` used in cover traffic.
* Only applicable if `secondary_packet_size` is enabled.
*/
cover_traffic_primary_size_ratio: number;
/**
* Controls whether the dedicated loop cover traffic stream should be enabled.
* (and sending packets, on average, every [Self::loop_cover_traffic_average_delay])
*/
disable_loop_cover_traffic_stream: boolean;
/**
* The parameter of Poisson distribution determining how long, on average,
* it is going to take for another loop cover traffic message to be sent.
*/
loop_cover_traffic_average_delay_ms: bigint;
}
/**
*/
export class DebugWasm {
free(): void;
/**
* Defines all configuration options related to acknowledgements, such as delays or wait timeouts.
*/
acknowledgements: AcknowledgementsWasm;
/**
* Defines all configuration options related to cover traffic stream(s).
*/
cover_traffic: CoverTrafficWasm;
/**
* Defines all configuration options related to the gateway connection.
*/
gateway_connection: GatewayConnectionWasm;
/**
* Defines all configuration options related to reply SURBs.
*/
reply_surbs: ReplySurbsWasm;
/**
* Defines all configuration options related topology, such as refresh rates or timeouts.
*/
topology: TopologyWasm;
/**
* Defines all configuration options related to traffic streams.
*/
traffic: TrafficWasm;
}
/**
*/
export class GatewayConnectionWasm {
free(): void;
/**
* How long we're willing to wait for a response to a message sent to the gateway,
* before giving up on it.
*/
gateway_response_timeout_ms: bigint;
}
/**
*/
export class GatewayEndpointConfig {
free(): void;
/**
* @param {string} gateway_id
* @param {string} gateway_owner
* @param {string} gateway_listener
*/
constructor(gateway_id: string, gateway_owner: string, gateway_listener: string);
/**
* gateway_id specifies ID of the gateway to which the client should send messages.
* If initially omitted, a random gateway will be chosen from the available topology.
*/
gateway_id: string;
/**
* Address of the gateway listener to which all client requests should be sent.
*/
gateway_listener: string;
/**
* Address of the gateway owner to which the client should send messages.
*/
gateway_owner: string;
}
/**
*/
export class NodeTestResult {
free(): void;
/**
*/
log_details(): void;
/**
* @returns {number}
*/
score(): number;
/**
*/
duplicate_acks: number;
/**
*/
duplicate_packets: number;
/**
*/
received_acks: number;
/**
*/
received_packets: number;
/**
*/
sent_packets: number;
}
/**
*/
export class NymClient {
free(): void;
/**
* @param {Config} config
* @param {Function} on_message
* @param {string | undefined} preferred_gateway
* @param {string | undefined} storage_passphrase
*/
constructor(config: Config, on_message: Function, preferred_gateway?: string, storage_passphrase?: string);
/**
* @returns {string}
*/
self_address(): string;
/**
* @param {string} mixnode_identity
* @param {number | undefined} num_test_packets
* @returns {Promise<any>}
*/
try_construct_test_packet_request(mixnode_identity: string, num_test_packets?: number): Promise<any>;
/**
* @param {WasmNymTopology} topology
* @returns {Promise<any>}
*/
change_hardcoded_topology(topology: WasmNymTopology): Promise<any>;
/**
* @returns {Promise<any>}
*/
current_network_topology(): Promise<any>;
/**
* Sends a test packet through the current network topology.
* It's the responsibility of the caller to ensure the correct topology has been injected and
* correct onmessage handlers have been setup.
* @param {NymClientTestRequest} request
* @returns {Promise<any>}
*/
try_send_test_packets(request: NymClientTestRequest): Promise<any>;
/**
* The simplest message variant where no additional information is attached.
* You're simply sending your `data` to specified `recipient` without any tagging.
*
* Ends up with `NymMessage::Plain` variant
* @param {Uint8Array} message
* @param {string} recipient
* @returns {Promise<any>}
*/
send_regular_message(message: Uint8Array, recipient: string): Promise<any>;
/**
* Creates a message used for a duplex anonymous communication where the recipient
* will never learn of our true identity. This is achieved by carefully sending `reply_surbs`.
*
* Note that if reply_surbs is set to zero then
* this variant requires the client having sent some reply_surbs in the past
* (and thus the recipient also knowing our sender tag).
*
* Ends up with `NymMessage::Repliable` variant
* @param {Uint8Array} message
* @param {string} recipient
* @param {number} reply_surbs
* @returns {Promise<any>}
*/
send_anonymous_message(message: Uint8Array, recipient: string, reply_surbs: number): Promise<any>;
/**
* Attempt to use our internally received and stored `ReplySurb` to send the message back
* to specified recipient whilst not knowing its full identity (or even gateway).
*
* Ends up with `NymMessage::Reply` variant
* @param {Uint8Array} message
* @param {string} recipient_tag
* @returns {Promise<any>}
*/
send_reply(message: Uint8Array, recipient_tag: string): Promise<any>;
}
/**
*/
export class NymClientBuilder {
free(): void;
/**
* @param {Config} config
* @param {Function} on_message
* @param {string | undefined} preferred_gateway
* @param {string | undefined} storage_passphrase
*/
constructor(config: Config, on_message: Function, preferred_gateway?: string, storage_passphrase?: string);
/**
* @param {WasmNymTopology} topology
* @param {Function} on_message
* @param {string | undefined} gateway
* @returns {NymClientBuilder}
*/
static new_tester(topology: WasmNymTopology, on_message: Function, gateway?: string): NymClientBuilder;
/**
* @returns {Promise<any>}
*/
start_client(): Promise<any>;
}
/**
*/
export class NymClientTestRequest {
free(): void;
/**
* @returns {WasmNymTopology}
*/
injectable_topology(): WasmNymTopology;
}
/**
*/
export class NymNodeTester {
free(): void;
/**
* @param {WasmNymTopology} topology
* @param {string | undefined} id
* @param {string | undefined} gateway
*/
constructor(topology: WasmNymTopology, id?: string, gateway?: string);
/**
* @param {string} api_url
* @param {string | undefined} id
* @param {string | undefined} gateway
* @returns {Promise<any>}
*/
static new_with_api(api_url: string, id?: string, gateway?: string): Promise<any>;
/**
* @returns {Promise<any>}
*/
disconnect_from_gateway(): Promise<any>;
/**
* @returns {Promise<any>}
*/
reconnect_to_gateway(): Promise<any>;
/**
* @param {string} mixnode_identity
* @param {bigint | undefined} timeout_millis
* @param {number | undefined} num_test_packets
* @returns {Promise<any>}
*/
test_node(mixnode_identity: string, timeout_millis?: bigint, num_test_packets?: number): Promise<any>;
}
/**
*/
export class NymNodeTesterBuilder {
free(): void;
/**
* @param {WasmNymTopology} base_topology
* @param {string | undefined} id
* @param {string | undefined} gateway
*/
constructor(base_topology: WasmNymTopology, id?: string, gateway?: string);
/**
* @param {string} api_url
* @param {string | undefined} id
* @param {string | undefined} gateway
* @returns {Promise<any>}
*/
static new_with_api(api_url: string, id?: string, gateway?: string): Promise<any>;
/**
* @returns {Promise<any>}
*/
setup_client(): Promise<any>;
}
/**
*/
export class ReplySurbsWasm {
free(): void;
/**
* Defines the maximum number of reply surbs a remote party is allowed to request from this client at once.
*/
maximum_allowed_reply_surb_request_size: number;
/**
* Defines maximum amount of time given reply key is going to be valid for.
* This is going to be superseded by key rotation once implemented.
*/
maximum_reply_key_age_ms: bigint;
/**
* Defines maximum amount of time given reply surb is going to be valid for.
* This is going to be superseded by key rotation once implemented.
*/
maximum_reply_surb_age_ms: bigint;
/**
* Defines maximum amount of time the client is going to wait for reply surbs before
* deciding it's never going to get them and would drop all pending messages
*/
maximum_reply_surb_drop_waiting_period_ms: bigint;
/**
* Defines the maximum number of reply surbs the client would request.
*/
maximum_reply_surb_request_size: number;
/**
* Defines maximum amount of time the client is going to wait for reply surbs before explicitly asking
* for more even though in theory they wouldn't need to.
*/
maximum_reply_surb_rerequest_waiting_period_ms: bigint;
/**
* Defines the maximum number of reply surbs the client wants to keep in its storage at any times.
*/
maximum_reply_surb_storage_threshold: number;
/**
* Defines the minimum number of reply surbs the client would request.
*/
minimum_reply_surb_request_size: number;
/**
* Defines the minimum number of reply surbs the client wants to keep in its storage at all times.
* It can only allow to go below that value if its to request additional reply surbs.
*/
minimum_reply_surb_storage_threshold: number;
}
/**
*/
export class TopologyWasm {
free(): void;
/**
* Specifies whether the client should not refresh the network topology after obtaining
* the first valid instance.
* Supersedes `topology_refresh_rate_ms`.
*/
disable_refreshing: boolean;
/**
* The uniform delay every which clients are querying the directory server
* to try to obtain a compatible network topology to send sphinx packets through.
*/
topology_refresh_rate_ms: bigint;
/**
* During topology refresh, test packets are sent through every single possible network
* path. This timeout determines waiting period until it is decided that the packet
* did not reach its destination.
*/
topology_resolution_timeout_ms: bigint;
}
/**
*/
export class TrafficWasm {
free(): void;
/**
* The parameter of Poisson distribution determining how long, on average,
* sent packet is going to be delayed at any given mix node.
* So for a packet going through three mix nodes, on average, it will take three times this value
* until the packet reaches its destination.
*/
average_packet_delay_ms: bigint;
/**
* Controls whether the main packet stream constantly produces packets according to the predefined
* poisson distribution.
*/
disable_main_poisson_packet_distribution: boolean;
/**
* The parameter of Poisson distribution determining how long, on average,
* it is going to take another 'real traffic stream' message to be sent.
* If no real packets are available and cover traffic is enabled,
* a loop cover message is sent instead in order to preserve the rate.
*/
message_sending_average_delay_ms: bigint;
/**
* Controls whether the sent sphinx packet use the NON-DEFAULT bigger size.
*/
use_extended_packet_size: boolean;
/**
* Controls whether the sent packets should use outfox as opposed to the default sphinx.
*/
use_outfox: boolean;
}
/**
*/
export class WasmGateway {
free(): void;
/**
* @param {string} owner
* @param {string} host
* @param {number} mix_port
* @param {number} clients_port
* @param {string} identity_key
* @param {string} sphinx_key
* @param {string} version
*/
constructor(owner: string, host: string, mix_port: number, clients_port: number, identity_key: string, sphinx_key: string, version: string);
/**
*/
clients_port: number;
/**
*/
host: string;
/**
*/
identity_key: string;
/**
*/
mix_port: number;
/**
*/
owner: string;
/**
*/
sphinx_key: string;
/**
*/
version: string;
}
/**
*/
export class WasmMixNode {
free(): void;
/**
* @param {number} mix_id
* @param {string} owner
* @param {string} host
* @param {number} mix_port
* @param {string} identity_key
* @param {string} sphinx_key
* @param {number} layer
* @param {string} version
*/
constructor(mix_id: number, owner: string, host: string, mix_port: number, identity_key: string, sphinx_key: string, layer: number, version: string);
/**
*/
host: string;
/**
*/
identity_key: string;
/**
*/
layer: number;
/**
*/
mix_id: number;
/**
*/
mix_port: number;
/**
*/
owner: string;
/**
*/
sphinx_key: string;
/**
*/
version: string;
}
/**
*/
export class WasmNymTopology {
free(): void;
/**
* @param {any} mixnodes
* @param {any} gateways
*/
constructor(mixnodes: any, gateways: any);
/**
*/
print(): void;
}
@@ -0,0 +1,2 @@
import * as wasm from "./nym_client_wasm_bg.wasm";
export * from "./nym_client_wasm_bg.js";
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,188 @@
/* tslint:disable */
/* eslint-disable */
export const memory: WebAssembly.Memory;
export function __wbg_nymclient_free(a: number): void;
export function __wbg_nymclientbuilder_free(a: number): void;
export function nymclientbuilder_new(a: number, b: number, c: number, d: number, e: number, f: number): number;
export function nymclientbuilder_new_tester(a: number, b: number, c: number, d: number): number;
export function nymclientbuilder_start_client(a: number): number;
export function nymclient_new(a: number, b: number, c: number, d: number, e: number, f: number): number;
export function nymclient_self_address(a: number, b: number): void;
export function nymclient_try_construct_test_packet_request(a: number, b: number, c: number, d: number, e: number): number;
export function nymclient_change_hardcoded_topology(a: number, b: number): number;
export function nymclient_current_network_topology(a: number): number;
export function nymclient_try_send_test_packets(a: number, b: number): number;
export function nymclient_send_regular_message(a: number, b: number, c: number, d: number, e: number): number;
export function nymclient_send_anonymous_message(a: number, b: number, c: number, d: number, e: number, f: number): number;
export function nymclient_send_reply(a: number, b: number, c: number, d: number, e: number): number;
export function get_gateway(a: number, b: number, c: number, d: number): number;
export function __wbg_wasmnymtopology_free(a: number): void;
export function wasmnymtopology_new(a: number, b: number, c: number): void;
export function wasmnymtopology_print(a: number): void;
export function __wbg_wasmmixnode_free(a: number): void;
export function __wbg_get_wasmmixnode_mix_id(a: number): number;
export function __wbg_set_wasmmixnode_mix_id(a: number, b: number): void;
export function __wbg_get_wasmmixnode_owner(a: number, b: number): void;
export function __wbg_set_wasmmixnode_owner(a: number, b: number, c: number): void;
export function __wbg_get_wasmmixnode_host(a: number, b: number): void;
export function __wbg_set_wasmmixnode_host(a: number, b: number, c: number): void;
export function __wbg_get_wasmmixnode_mix_port(a: number): number;
export function __wbg_set_wasmmixnode_mix_port(a: number, b: number): void;
export function __wbg_get_wasmmixnode_identity_key(a: number, b: number): void;
export function __wbg_set_wasmmixnode_identity_key(a: number, b: number, c: number): void;
export function __wbg_get_wasmmixnode_sphinx_key(a: number, b: number): void;
export function __wbg_set_wasmmixnode_sphinx_key(a: number, b: number, c: number): void;
export function __wbg_get_wasmmixnode_layer(a: number): number;
export function __wbg_set_wasmmixnode_layer(a: number, b: number): void;
export function __wbg_get_wasmmixnode_version(a: number, b: number): void;
export function __wbg_set_wasmmixnode_version(a: number, b: number, c: number): void;
export function wasmmixnode_new(a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number, k: number, l: number, m: number): number;
export function __wbg_wasmgateway_free(a: number): void;
export function __wbg_get_wasmgateway_owner(a: number, b: number): void;
export function __wbg_set_wasmgateway_owner(a: number, b: number, c: number): void;
export function __wbg_get_wasmgateway_host(a: number, b: number): void;
export function __wbg_set_wasmgateway_host(a: number, b: number, c: number): void;
export function __wbg_get_wasmgateway_mix_port(a: number): number;
export function __wbg_set_wasmgateway_mix_port(a: number, b: number): void;
export function __wbg_get_wasmgateway_clients_port(a: number): number;
export function __wbg_set_wasmgateway_clients_port(a: number, b: number): void;
export function __wbg_get_wasmgateway_identity_key(a: number, b: number): void;
export function __wbg_set_wasmgateway_identity_key(a: number, b: number, c: number): void;
export function __wbg_get_wasmgateway_sphinx_key(a: number, b: number): void;
export function __wbg_set_wasmgateway_sphinx_key(a: number, b: number, c: number): void;
export function __wbg_get_wasmgateway_version(a: number, b: number): void;
export function __wbg_set_wasmgateway_version(a: number, b: number, c: number): void;
export function wasmgateway_new(a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number, k: number, l: number): number;
export function current_network_topology(a: number, b: number): number;
export function __wbg_nodetestresult_free(a: number): void;
export function __wbg_get_nodetestresult_sent_packets(a: number): number;
export function __wbg_set_nodetestresult_sent_packets(a: number, b: number): void;
export function __wbg_get_nodetestresult_received_packets(a: number): number;
export function __wbg_set_nodetestresult_received_packets(a: number, b: number): void;
export function __wbg_get_nodetestresult_received_acks(a: number): number;
export function __wbg_set_nodetestresult_received_acks(a: number, b: number): void;
export function __wbg_get_nodetestresult_duplicate_packets(a: number): number;
export function __wbg_set_nodetestresult_duplicate_packets(a: number, b: number): void;
export function __wbg_get_nodetestresult_duplicate_acks(a: number): number;
export function __wbg_set_nodetestresult_duplicate_acks(a: number, b: number): void;
export function nodetestresult_log_details(a: number): void;
export function nodetestresult_score(a: number): number;
export function encode_payload(a: number, b: number, c: number, d: number, e: number): void;
export function encode_payload_with_headers(a: number, b: number, c: number, d: number, e: number, f: number, g: number): void;
export function decode_payload(a: number, b: number, c: number): void;
export function parse_utf8_string(a: number, b: number, c: number): void;
export function utf8_string_to_byte_array(a: number, b: number, c: number): void;
export function __wbg_clientstorage_free(a: number): void;
export function clientstorage_new(a: number, b: number, c: number, d: number): number;
export function clientstorage_new_unencrypted(a: number, b: number): number;
export function __wbg_nymnodetester_free(a: number): void;
export function __wbg_nymnodetesterbuilder_free(a: number): void;
export function nymnodetesterbuilder_new(a: number, b: number, c: number, d: number, e: number): number;
export function nymnodetesterbuilder_new_with_api(a: number, b: number, c: number, d: number, e: number, f: number): number;
export function nymnodetesterbuilder_setup_client(a: number): number;
export function nymnodetester_new(a: number, b: number, c: number, d: number, e: number): number;
export function nymnodetester_new_with_api(a: number, b: number, c: number, d: number, e: number, f: number): number;
export function nymnodetester_disconnect_from_gateway(a: number): number;
export function nymnodetester_reconnect_to_gateway(a: number): number;
export function nymnodetester_test_node(a: number, b: number, c: number, d: number, e: number, f: number, g: number): number;
export function validate_recipient(a: number, b: number, c: number): void;
export function set_panic_hook(): void;
export function __wbg_nymclienttestrequest_free(a: number): void;
export function nymclienttestrequest_injectable_topology(a: number): number;
export function __wbg_config_free(a: number): void;
export function config_new(a: number, b: number, c: number, d: number, e: number): number;
export function __wbg_get_trafficwasm_use_extended_packet_size(a: number): number;
export function __wbg_set_trafficwasm_use_extended_packet_size(a: number, b: number): void;
export function __wbg_get_trafficwasm_use_outfox(a: number): number;
export function __wbg_set_trafficwasm_use_outfox(a: number, b: number): void;
export function __wbg_get_covertrafficwasm_disable_loop_cover_traffic_stream(a: number): number;
export function __wbg_set_covertrafficwasm_disable_loop_cover_traffic_stream(a: number, b: number): void;
export function __wbg_gatewayconnectionwasm_free(a: number): void;
export function __wbg_acknowledgementswasm_free(a: number): void;
export function __wbg_get_acknowledgementswasm_average_ack_delay_ms(a: number): number;
export function __wbg_set_acknowledgementswasm_average_ack_delay_ms(a: number, b: number): void;
export function __wbg_get_acknowledgementswasm_ack_wait_multiplier(a: number): number;
export function __wbg_set_acknowledgementswasm_ack_wait_multiplier(a: number, b: number): void;
export function __wbg_get_acknowledgementswasm_ack_wait_addition_ms(a: number): number;
export function __wbg_set_acknowledgementswasm_ack_wait_addition_ms(a: number, b: number): void;
export function __wbg_replysurbswasm_free(a: number): void;
export function __wbg_get_replysurbswasm_minimum_reply_surb_storage_threshold(a: number): number;
export function __wbg_set_replysurbswasm_minimum_reply_surb_storage_threshold(a: number, b: number): void;
export function __wbg_get_replysurbswasm_maximum_reply_surb_storage_threshold(a: number): number;
export function __wbg_set_replysurbswasm_maximum_reply_surb_storage_threshold(a: number, b: number): void;
export function __wbg_get_replysurbswasm_minimum_reply_surb_request_size(a: number): number;
export function __wbg_set_replysurbswasm_minimum_reply_surb_request_size(a: number, b: number): void;
export function __wbg_get_replysurbswasm_maximum_reply_surb_request_size(a: number): number;
export function __wbg_set_replysurbswasm_maximum_reply_surb_request_size(a: number, b: number): void;
export function __wbg_get_replysurbswasm_maximum_allowed_reply_surb_request_size(a: number): number;
export function __wbg_set_replysurbswasm_maximum_allowed_reply_surb_request_size(a: number, b: number): void;
export function __wbg_get_replysurbswasm_maximum_reply_surb_drop_waiting_period_ms(a: number): number;
export function __wbg_set_replysurbswasm_maximum_reply_surb_drop_waiting_period_ms(a: number, b: number): void;
export function __wbg_get_replysurbswasm_maximum_reply_key_age_ms(a: number): number;
export function __wbg_set_replysurbswasm_maximum_reply_key_age_ms(a: number, b: number): void;
export function __wbg_debugwasm_free(a: number): void;
export function __wbg_get_debugwasm_traffic(a: number): number;
export function __wbg_set_debugwasm_traffic(a: number, b: number): void;
export function __wbg_get_debugwasm_cover_traffic(a: number): number;
export function __wbg_set_debugwasm_cover_traffic(a: number, b: number): void;
export function __wbg_get_debugwasm_gateway_connection(a: number): number;
export function __wbg_set_debugwasm_gateway_connection(a: number, b: number): void;
export function __wbg_get_debugwasm_acknowledgements(a: number): number;
export function __wbg_set_debugwasm_acknowledgements(a: number, b: number): void;
export function __wbg_get_debugwasm_topology(a: number): number;
export function __wbg_set_debugwasm_topology(a: number, b: number): void;
export function __wbg_get_debugwasm_reply_surbs(a: number): number;
export function __wbg_set_debugwasm_reply_surbs(a: number, b: number): void;
export function default_debug(): number;
export function __wbg_set_trafficwasm_average_packet_delay_ms(a: number, b: number): void;
export function __wbg_set_gatewayconnectionwasm_gateway_response_timeout_ms(a: number, b: number): void;
export function __wbg_set_covertrafficwasm_loop_cover_traffic_average_delay_ms(a: number, b: number): void;
export function __wbg_set_covertrafficwasm_cover_traffic_primary_size_ratio(a: number, b: number): void;
export function __wbg_set_topologywasm_topology_refresh_rate_ms(a: number, b: number): void;
export function __wbg_set_trafficwasm_message_sending_average_delay_ms(a: number, b: number): void;
export function __wbg_set_replysurbswasm_maximum_reply_surb_rerequest_waiting_period_ms(a: number, b: number): void;
export function __wbg_set_topologywasm_topology_resolution_timeout_ms(a: number, b: number): void;
export function __wbg_set_replysurbswasm_maximum_reply_surb_age_ms(a: number, b: number): void;
export function __wbg_get_trafficwasm_disable_main_poisson_packet_distribution(a: number): number;
export function __wbg_get_topologywasm_disable_refreshing(a: number): number;
export function __wbg_set_trafficwasm_disable_main_poisson_packet_distribution(a: number, b: number): void;
export function __wbg_set_topologywasm_disable_refreshing(a: number, b: number): void;
export function __wbg_get_trafficwasm_average_packet_delay_ms(a: number): number;
export function __wbg_get_gatewayconnectionwasm_gateway_response_timeout_ms(a: number): number;
export function __wbg_get_covertrafficwasm_loop_cover_traffic_average_delay_ms(a: number): number;
export function __wbg_get_covertrafficwasm_cover_traffic_primary_size_ratio(a: number): number;
export function __wbg_get_topologywasm_topology_refresh_rate_ms(a: number): number;
export function __wbg_get_trafficwasm_message_sending_average_delay_ms(a: number): number;
export function __wbg_get_replysurbswasm_maximum_reply_surb_rerequest_waiting_period_ms(a: number): number;
export function __wbg_get_topologywasm_topology_resolution_timeout_ms(a: number): number;
export function __wbg_get_replysurbswasm_maximum_reply_surb_age_ms(a: number): number;
export function __wbg_trafficwasm_free(a: number): void;
export function __wbg_covertrafficwasm_free(a: number): void;
export function __wbg_topologywasm_free(a: number): void;
export function __wbg_gatewayendpointconfig_free(a: number): void;
export function __wbg_get_gatewayendpointconfig_gateway_id(a: number, b: number): void;
export function __wbg_set_gatewayendpointconfig_gateway_id(a: number, b: number, c: number): void;
export function __wbg_get_gatewayendpointconfig_gateway_owner(a: number, b: number): void;
export function __wbg_set_gatewayendpointconfig_gateway_owner(a: number, b: number, c: number): void;
export function __wbg_get_gatewayendpointconfig_gateway_listener(a: number, b: number): void;
export function __wbg_set_gatewayendpointconfig_gateway_listener(a: number, b: number, c: number): void;
export function gatewayendpointconfig_new(a: number, b: number, c: number, d: number, e: number, f: number): number;
export function __wbg_anonymoussendertag_free(a: number): void;
export function interface_version_8(): void;
export function allocate(a: number): number;
export function deallocate(a: number): void;
export function requires_iterator(): void;
export function __wbindgen_malloc(a: number): number;
export function __wbindgen_realloc(a: number, b: number, c: number): number;
export const __wbindgen_export_2: WebAssembly.Table;
export function __wbindgen_add_to_stack_pointer(a: number): number;
export function _dyn_core__ops__function__FnMut__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__ha1e005bc9b57c90c(a: number, b: number, c: number, d: number): void;
export function _dyn_core__ops__function__FnMut_____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h71a148875a2c330f(a: number, b: number): void;
export function _dyn_core__ops__function__FnMut__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h07195fa7991e1ddf(a: number, b: number, c: number): void;
export function _dyn_core__ops__function__Fn_____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__hada7de604acd93c9(a: number, b: number): void;
export function _dyn_core__ops__function__Fn__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h844be727de79a10b(a: number, b: number, c: number): void;
export function _dyn_core__ops__function__FnMut_____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h62aac500ae55364d(a: number, b: number): void;
export function _dyn_core__ops__function__FnMut__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__ha67d0876201d9695(a: number, b: number, c: number): void;
export function __wbindgen_free(a: number, b: number): void;
export function __wbindgen_exn_store(a: number): void;
export function wasm_bindgen__convert__closures__invoke2_mut__ha2b01935184b2143(a: number, b: number, c: number, d: number): void;
@@ -0,0 +1,34 @@
{
"name": "@nymproject/nym-client-wasm",
"collaborators": [
"Dave Hrycyszyn <futurechimp@users.noreply.github.com>",
"Jedrzej Stuczynski <andrew@nymtech.net>"
],
"description": "A webassembly client which can be used to interact with the the Nym privacy platform. Wasm is used for Sphinx packet generation.",
"version": "1.1.1",
"license": "Apache-2.0",
"repository": {
"type": "git",
"url": "https://github.com/nymtech/nym"
},
"files": [
"nym_client_wasm_bg.wasm",
"nym_client_wasm.js",
"nym_client_wasm_bg.js",
"nym_client_wasm.d.ts"
],
"module": "nym_client_wasm.js",
"types": "nym_client_wasm.d.ts",
"sideEffects": [
"./nym_client_wasm.js",
"./snippets/*"
],
"keywords": [
"nym",
"sphinx",
"wasm",
"webassembly",
"privacy",
"client"
]
}

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