Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/wasm client topology injection #3311

Merged
merged 30 commits into from
Apr 24, 2023
Merged
Show file tree
Hide file tree
Changes from 28 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
8b5496e
added cargo config file to explicitly specify build target
jstuczyn Apr 3, 2023
bba5c18
wip
jstuczyn Apr 4, 2023
2fe5b3b
Config option to disable topology refreshing
jstuczyn Apr 5, 2023
5ebc172
extracted common parsing code
jstuczyn Apr 6, 2023
b290ba7
helper trait for working on wasm topology
jstuczyn Apr 6, 2023
2daf3c9
wasm topology parsing
jstuczyn Apr 6, 2023
176e619
restored (slightly modified) old js-example
jstuczyn Apr 6, 2023
2893572
wip
jstuczyn Apr 6, 2023
9178758
Moved message preparation into a trait
jstuczyn Apr 11, 2023
cd3d8fc
wip
jstuczyn Apr 11, 2023
0f7cd67
long-winded way of sending test packet
jstuczyn Apr 11, 2023
63dbfb3
standalone NymNodeTester
jstuczyn Apr 14, 2023
52e1eb9
finishing the test upon receiving all packets even if timeout wasnt r…
jstuczyn Apr 14, 2023
d89cb0c
initial round of cleanup
jstuczyn Apr 14, 2023
0011106
sending multiple test packets in normal NymClient
jstuczyn Apr 14, 2023
8f04dfa
javascript-side cleanup
jstuczyn Apr 14, 2023
dd82001
starting mixnode test on btn click
jstuczyn Apr 14, 2023
9ff3717
Improved NymNodeTester constructors
jstuczyn Apr 14, 2023
b7e34b6
improved error handling and constructors
jstuczyn Apr 14, 2023
e5d94c6
tester utils error handling
jstuczyn Apr 14, 2023
90688de
further cleanup + using BTreeMap for NymTopology mixnodes
jstuczyn Apr 14, 2023
67833aa
handling missed errors
jstuczyn Apr 14, 2023
a34a0fb
splitting up 'test_node'
jstuczyn Apr 14, 2023
db95293
split up and cleaned up generation of test result
jstuczyn Apr 14, 2023
f16e7a4
clippy + fixed example
jstuczyn Apr 14, 2023
ab3d4e7
post rebase fixes
jstuczyn Apr 14, 2023
e669edc
another broken test
jstuczyn Apr 14, 2023
3f391b3
prevent running multiple parallel tests
jstuczyn Apr 14, 2023
0e283ba
cargo fmt
jstuczyn Apr 17, 2023
1117d07
Added nym- prefix to node tester utils
jstuczyn Apr 17, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ members = [
"common/ledger",
"common/mixnode-common",
"common/network-defaults",
"common/node-tester-utils",
"common/nonexhaustive-delayqueue",
"common/nymcoconut",
"common/nymsphinx",
Expand Down
2 changes: 2 additions & 0 deletions clients/webassembly/.cargo/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[build]
target = "wasm32-unknown-unknown"
7 changes: 7 additions & 0 deletions clients/webassembly/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ default = ["console_error_panic_hook"]
offline-test = []

[dependencies]
bs58 = "0.4.0"
futures = "0.3"
js-sys = "0.3"
rand = { version = "0.7.3", features = ["wasm-bindgen"] }
Expand All @@ -28,15 +29,21 @@ tokio = { version = "1.24.1", features = ["sync"] }
url = "2.2"
wasm-bindgen = { version = "=0.2.83", features = ["serde-serialize"] }
wasm-bindgen-futures = "0.4"
thiserror = "1.0.40"

wasm-timer = { git = "https://github.com/mmsinclair/wasm-timer", rev = "b9d1a54ad514c2f230a026afe0dde341e98cd7b6"}

# internal
node-tester-utils = { path = "../../common/node-tester-utils" }
nym-client-core = { path = "../../common/client-core", default-features = false, features = ["wasm"] }
nym-bandwidth-controller = { path = "../../common/bandwidth-controller" }
nym-coconut-interface = { path = "../../common/coconut-interface" }
nym-credentials = { path = "../../common/credentials" }
nym-credential-storage = { path = "../../common/credential-storage" }
nym-crypto = { path = "../../common/crypto" }
nym-sphinx = { path = "../../common/nymsphinx" }
nym-topology = { path = "../../common/topology" }
nym-gateway-client = { path = "../../common/client-libs/gateway-client", default-features = false, features = ["wasm"] }
nym-validator-client = { path = "../../common/client-libs/validator-client", default-features = false }
wasm-utils = { path = "../../common/wasm-utils" }
nym-task = { path = "../../common/task" }
Expand Down
2 changes: 2 additions & 0 deletions clients/webassembly/internal-dev/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
node_modules
dist
5 changes: 5 additions & 0 deletions clients/webassembly/internal-dev/bootstrap.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// A dependency graph that contains any wasm must all be imported
// asynchronously. This `bootstrap.js` file does the single async import, so
// that no one else needs to worry about it again.
import('./index.js')
.catch(e => console.error('Error importing `index.js`:', e));
43 changes: 43 additions & 0 deletions clients/webassembly/internal-dev/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Nym WebAssembly Demo</title>
</head>

<body>
<p>
<label>Sender: </label><input disabled="true" size="85" type="text" id="sender" value="">
</p>

<p>
<label>Recipient: </label><input size="85" type="text" id="recipient" value="">
</p>
<p>
<label>Message: </label><input type="text" id="message" value="Hello mixnet!">
</p>
<p>
<button id="send-button">Send</button>
</p>

<div>
<label>Mixnode Identity: </label>
<input type="text" size = "60" id="mixnode_identity" value="...">
<button id="magic-button">✨ Magic Test Button ✨</button>
</div>


<p>Send messages from your browser, through the mixnet, and to the recipient using the "send" button.</p>
<p><span style='color: blue;'>Sent</span> messages show in blue, <span style='color: green;'>received</span>
messages show in green.</p>

<hr>
<p>
<span id="output"></span>
</p>
<script src="./bootstrap.js"></script>
</body>

</html>
170 changes: 170 additions & 0 deletions clients/webassembly/internal-dev/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
// Copyright 2020-2023 Nym Technologies SA
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

class WebWorkerClient {
worker = null;

constructor() {
this.worker = new Worker('./worker.js');

this.worker.onmessage = (ev) => {
if (ev.data && ev.data.kind) {
switch (ev.data.kind) {
case 'Ready':
const {selfAddress} = ev.data.args;
displaySenderAddress(selfAddress);
break;
case 'ReceiveMessage':
const {message, senderTag, isTestPacket } = ev.data.args;
displayReceived(message, senderTag, isTestPacket);
break;
case 'DisableMagicTestButton':
const magicButton = document.querySelector('#magic-button');
magicButton.setAttribute('disabled', "true")
break;
case 'DisplayTesterResults':
const {score, sentPackets, receivedPackets, receivedAcks, duplicatePackets, duplicateAcks} = ev.data.args;
const resultText = `Test score: ${score}. Sent ${sentPackets} packets. Received ${receivedPackets} packets and ${receivedAcks} acks back. We also got ${duplicatePackets} duplicate packets and ${duplicateAcks} duplicate acks.`
displayReceivedRawString(resultText)
break;
}
}
};
}

sendMessage = (message, recipient) => {
if (!this.worker) {
console.error('Could not send message because worker does not exist');
return;
}

this.worker.postMessage({
kind: 'SendMessage',
args: {
message, recipient,
},
});
};

sendTestPacket = (mixnodeIdentity) => {
if (!this.worker) {
console.error('Could not send message because worker does not exist');
return;
}

this.worker.postMessage({
kind: 'TestPacket',
args: {
mixnodeIdentity,
},
});
}
}

let client = null;

async function main() {
client = new WebWorkerClient();

const sendButton = document.querySelector('#send-button');
sendButton.onclick = function () {
sendMessageTo();
};

const magicButton = document.querySelector('#magic-button');
magicButton.onclick = function () {
sendTestPacket();
}
}

/**
* Create a Sphinx packet and send it to the mixnet through the gateway node.
*
* Message and recipient are taken from the values in the user interface.
*
*/
async function sendMessageTo() {
const message = document.getElementById('message').value;
const recipient = document.getElementById('recipient').value;

await client.sendMessage(message, recipient);
displaySend(message);
}

async function sendTestPacket() {
const mixnodeIdentity = document.getElementById('mixnode_identity').value;

await client.sendTestPacket(mixnodeIdentity)
displaySend(`sending test packets to: ${mixnodeIdentity}...`);
}

/**
* Display messages that have been sent up the websocket. Colours them blue.
*
* @param {string} message
*/
function displaySend(message) {
let timestamp = new Date().toISOString().substr(11, 12);

let sendDiv = document.createElement('div');
let paragraph = document.createElement('p');
paragraph.setAttribute('style', 'color: blue');
let paragraphContent = document.createTextNode(timestamp + ' sent >>> ' + message);
paragraph.appendChild(paragraphContent);

sendDiv.appendChild(paragraph);
document.getElementById('output').appendChild(sendDiv);
}

/**
* Display received text messages in the browser. Colour them green.
*
* @param {Uint8Array} raw
*/
function displayReceived(raw, sender_tag, isTestPacket) {
let content = new TextDecoder().decode(raw);
if (sender_tag !== undefined) {
console.log("this message also contained some surbs from", sender_tag)
}

if (isTestPacket) {
const decoded = JSON.parse(content)
content = `Received packet ${decoded.msg_id} / ${decoded.total_msgs} for node ${decoded.encoded_node_identity} (test: ${decoded.test_id})`
}

displayReceivedRawString(content)
}


function displayReceivedRawString(raw) {
let timestamp = new Date().toISOString().substr(11, 12);
let receivedDiv = document.createElement('div');
let paragraph = document.createElement('p');
paragraph.setAttribute('style', 'color: green');
let paragraphContent = document.createTextNode(timestamp + ' received >>> ' + raw);
paragraph.appendChild(paragraphContent);
receivedDiv.appendChild(paragraph);
document.getElementById('output').appendChild(receivedDiv);
}

/**
* Display the nymClient's sender address in the user interface
*
* @param {String} address
*/
function displaySenderAddress(address) {
document.getElementById('sender').value = address;
}

main();
39 changes: 39 additions & 0 deletions clients/webassembly/internal-dev/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
{
"name": "create-wasm-app",
"version": "0.1.0",
"description": "create an app to consume rust-generated wasm packages",
"main": "index.js",
"bin": {
"create-wasm-app": ".bin/create-wasm-app.js"
},
"scripts": {
"build": "webpack --config webpack.config.js",
"start": "webpack-dev-server --port 8001"
},
"repository": {
"type": "git",
"url": "git+https://github.com/rustwasm/create-wasm-app.git"
},
"keywords": [
"webassembly",
"wasm",
"rust",
"webpack"
],
"author": "Dave Hrycyszyn <futurechimp@users.noreply.github.com>",
"license": "Apache-2.0",
"bugs": {
"url": "https://github.com/nymtech/nym/issues"
},
"homepage": "https://nymtech.net/docs",
"devDependencies": {
"copy-webpack-plugin": "^10.2.4",
"hello-wasm-pack": "^0.1.0",
"webpack": "^5.70.0",
"webpack-cli": "^4.9.2",
"webpack-dev-server": "^4.7.4"
},
"dependencies": {
"@nymproject/nym-client-wasm": "file:../pkg"
}
}
33 changes: 33 additions & 0 deletions clients/webassembly/internal-dev/webpack.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
const CopyWebpackPlugin = require('copy-webpack-plugin');
const path = require('path');

module.exports = {
performance: {
hints: false,
maxEntrypointSize: 512000,
maxAssetSize: 512000
},
entry: {
bootstrap: './bootstrap.js',
worker: './worker.js',
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].js',
},
// mode: 'development',
mode: 'production',
plugins: [
new CopyWebpackPlugin({
patterns: [
'index.html',
{
from: 'node_modules/@nymproject/nym-client-wasm/*.(js|wasm)',
to: '[name][ext]',
},
],
}),

],
experiments: { syncWebAssembly: true },
};
Loading