Feature/clean up (#238)

* validator: fixing a warning, untestify this when you need it for real code

* webassembly: minor readme changes.

* README changes in wasm

* Updated wasm version

* clients/webassembly: security vuln updates

* typo fix

* WIP commit

* Significantly simplified the API

* Changed switch to have default branch

* Managed to get rid of `this` bind

* Filled in a missing word

Co-authored-by: jstuczyn <jedrzej.stuczynski@gmail.com>
This commit is contained in:
Dave Hrycyszyn
2020-05-19 10:32:52 +01:00
committed by GitHub
parent a38a9f604d
commit 8745fb4230
15 changed files with 2058 additions and 2582 deletions
Generated
+1 -1
View File
@@ -1697,7 +1697,7 @@ dependencies = [
[[package]]
name = "nym-client-wasm"
version = "0.1.3"
version = "0.7.0-pre"
dependencies = [
"console_error_panic_hook",
"crypto",
+3 -2
View File
@@ -1,10 +1,11 @@
[package]
name = "nym-client-wasm"
version = "0.1.3"
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jedrzej Stuczynski <andrew@nymtech.net>"]
version = "0.7.0-pre"
edition = "2018"
repository = "https://github.com/nymtech/nym"
keywords = ["nym", "sphinx", "wasm", "webassembly", "privacy", "client"]
license = "Apache-2.0"
repository = "https://github.com/nymtech/nym"
[lib]
crate-type = ["cdylib", "rlib"]
+27 -10
View File
@@ -1,25 +1,42 @@
## Nym Sphinx in WebAssembly
This is a Rust crate which is set up to automatically cross-compile the contents of `lib.rs` to WebAssembly (aka wasm).
## About
Wasm is pretty close to bare metal. Browser-based or server-side JavaScript (or other wasm-using environments) can use the wasm output from this crate to create Sphinx packets at much higher speeds than would be possible using (interpreted) JavaScript. This enables browser-based and mobile applications get stronger privacy, in a way that wasn't previously possible.
This is an npm package which allows JavaScript programmers (or anyone else who can use WebAssembly in their applications) to produce layer-encrypted [Sphinx](http://www0.cs.ucl.ac.uk/staff/G.Danezis/papers/sphinx-eprint.pdf) packets for use with [Nym](https://nymtech.net/docs) mixnets. It's written in Rust and compiled to WebAssembly.
### Compiling
Sphinx packets are designed to ensure the privacy of information in transit, even when the adversary is able to monitor the network in its entirety. When used with a mixnet, both content (what you said) and metadata (who you said it to, when you said it) are protected.
First, make sure you've got all the [Rust wasm toolchain](https://rustwasm.github.io/book/game-of-life/setup.html) installed. Cross-compilation sounds scary but the Rust crew have enabled a remarkably simple setup.
This helps browser-based and mobile applications get stronger privacy, in a way that wasn't previously possible.
### Using it as a JavaScripter
## Security Status
See our [docs](https://nymtech.net/docs).
From a security point of view, this module is not yet complete. A key missing feature, cover traffic, will be implemented soon. You can build your applications, but don't rely on it for strong anonymity yet if your application needs cover traffic.
## Using it
See the [Nym docs](https://nymtech.net/docs).
### Demo
There's a demo web application in the `js-example` folder. To run it, first make sure you've got a recent `npm` installed, then follow the instructions in its README.
### Developing
## Developing
Whenever you change your Rust, run `wasm-pack build` to update the built was artefact in the `pkg` directory.
This is a Rust crate which is set up to automatically cross-compile the contents of `src` to WebAssembly (aka wasm). It's published from the main [Nym platform monorepo](https://github.com/nymtech/nym) in the `clients/webassembly` directory.
# IMPORTANT!!
First, make sure you've got all the [Rust wasm toolchain](https://rustwasm.github.io/book/game-of-life/setup.html) installed. Cross-compilation sounds scary but the Rust crew have enabled a remarkably simple setup.
You also need to manually copy `helpers.js` file into the `pkg` and add it to `package.json`. I'm 100% sure one of the hundreds JS packagers could do that for us, but I didn't feel like spending 10 hours figuring this one out.
Whenever you change any Rust in the `src` directory, run `wasm-pack build --scope nymproject` to update the built wasm artefact in the `pkg` directory.
For now, when you compile `nym-client-wasm` using `wasm-pack build --scope nymproject` you will need to manually copy the file `client.js` into the `pkg` and add it to `package.json`. Once [these](https://github.com/rustwasm/wasm-pack/issues/840) [issues](https://github.com/rustwasm/rfcs/pull/8#issuecomment-564725214) get closed, this annoying extra step will go away.
To be clear, this is not something that most JS developers need to worry about, this is only for Nym devs. The packages on NPM have all files in place. Just install and enjoy!
### Packaging
If you're a Nym platform developer who's made changes to the Rust (or JS) files and wants to re-publish the package to NPM, here's how you do it:
1. `wasm-pack build --scope nymproject` builds the wasm binaries into the `pkg` directory (not in source control)
2. copy `client.js` into the `pkg` folder and add it to the `package.json` manifest
3. bump version numbers as necessary for SemVer
4. `wasm-pack publish --access=public` will publish your changed package to NPM
+240
View File
@@ -0,0 +1,240 @@
import * as wasm from "nym-client-wasm";
export class Identity {
// in the future this should allow for loading from local storage
constructor() {
const raw_identity = JSON.parse(wasm.keygen());
this.address = raw_identity.address;
this.privateKey = raw_identity.private_key;
this.publicKey = raw_identity.public_key;
}
}
export class Client {
// constructor(gateway_url, ownAddress, registeredCallback) {
constructor(directoryUrl, identity, authToken) {
this.authToken = authToken
this.gateway = null; // {socketAddress, mixAddress, conn}
this.identity = identity;
this.topology = null;
this.topologyEndpoint = directoryUrl + "/api/presence/topology";
}
async start() {
await this.updateTopology();
this._getInitialGateway();
await this.establishGatewayConnection();
// TODO: a way to somehow await for our authenticate response to be processed
}
_isRegistered() {
return this.authToken !== null
}
async updateTopology() {
let response = await http('get', this.topologyEndpoint);
let topology = JSON.parse(response); // make sure it's a valid json
console.log(topology);
this.topology = topology;
this.onUpdatedTopology();
return topology;
}
/* Gets the address of a Nym gateway to send the Sphinx packet to.
At present we choose the first gateway as the network should only be running
one. Later, we will implement multiple gateways. */
_getInitialGateway() {
if (this.gateway !== null) {
console.error("tried to re-initialise gateway data");
return;
}
if (this.topology === null || this.topology.gatewayNodes.length === 0) {
console.error("No gateways available on the network")
}
this.gateway = {
socketAddress: this.topology.gatewayNodes[0].clientListener,
mixAddress: this.topology.gatewayNodes[0].pubKey,
conn: null,
}
}
establishGatewayConnection() {
return new Promise((resolve, reject) => {
const conn = new WebSocket(this.gateway.socketAddress);
conn.onclose = this.onGatewayConnectionClose;
conn.onerror = (event) => {
this.onGatewayConnectionError(event);
reject(event);
};
conn.onmessage = (event) => this.onGatewayMessage(event);
conn.onopen = (event) => {
this.onEstablishedGatewayConnection(event);
if (this._isRegistered()) {
this.sendAuthenticateRequest();
resolve(); // TODO: we should wait for authenticateResponse...
} else {
this.sendRegisterRequest();
resolve(); // TODO: we should wait for registerResponse...
}
}
this.gateway.conn = conn;
})
}
sendRegisterRequest() {
const registerReq = makeRegisterRequest(this.identity.address);
this.gateway.conn.send(registerReq);
this.onRegisterRequestSend();
}
sendAuthenticateRequest(token) {
const authenticateReq = makeAuthenticateRequest(this.identity.address, token);
this.conn.send(authenticateReq);
this.onAuthenticateRequestSend();
}
/*
NOTE: this currently does not implement chunking and messages over ~1KB
will cause a panic. This will be fixed in a future version.
*/
sendMessage(message, recipient) {
if (this.gateway === null || this.gateway.conn === null) {
console.error("Client was not initialised");
return
}
if (message instanceof Blob || message instanceof ArrayBuffer) {
// but it wouldn't be difficult to implement it.
console.error("Binary messages are not yet supported");
return
}
// TODO: CURRENTLY WE ONLY ACCEPT "recipient", not recipient@gateway
// this will be changed in the very next PR
console.log("send", this.topology)
const sphinxPacket = wasm.create_sphinx_packet(JSON.stringify(this.topology), message, recipient);
this.gateway.conn.send(sphinxPacket);
this.onMessageSend();
}
onGatewayMessage(event) {
if (event.data instanceof Blob) {
this.onBlobResponse(event);
} else {
const receivedData = JSON.parse(event.data);
switch (receivedData.type) {
case "send": return this.onSendConfirmation(event);
case "authenticate": return this.onAuthenticateResponse(event);
case "error": return this.onErrorResponse(event);
case "register": return this.onRegisterResponse(event);
default: return this.onUnknownResponse(event);
}
}
}
// all the callbacks that can be overwritten
onUpdatedTopology() {
console.log("Default: Updated topology")
}
onEstablishedGatewayConnection(event) {
console.log("Default: Established gateway connection", event);
}
onGatewayConnectionClose(event) {
console.log("Default: The the connection to gateway was closed", event);
}
onGatewayConnectionError(event) {
console.error("Default: Gateway connection error: ", event);
}
onAuthenticateRequestSend() {
console.log("Default: sent authentication request");
}
onRegisterRequestSend() {
console.log("Default: sent register request");
}
onMessageSend() {
console.log("Default: sent message through gateway to the mixnet");
}
onAuthenticated() {
console.log("Default: we are authenticated");
}
onSendConfirmation(event) {
console.log("Default: received send confirmation", event.data);
}
onRegisterResponse(event) {
console.log("Default: received register response", event.data);
}
onAuthenticateResponse(event) {
console.log("Default: received authentication response", event.data);
}
onErrorResponse(event) {
console.error("Received error response", event.data);
}
onUnknownResponse(event) {
console.error("Received unknown response", event);
}
// Gateway returns any received data from the mix network as a Blob,
// So most likely this is your best bet to override
onBlobResponse(event) {
// note that the actual handling depends on the expected content, however,
// in this example we're just sending a text messages to ourselves and hence
// we can safely read it as text
let reader = new FileReader();
reader.onload = () => {
this.onParsedBlobResponse(reader.result)
};
reader.readAsText(event.data);
}
// Alternatively you may use default implementation and get everything as a text
onParsedBlobResponse(data) {
console.log("Default: parsed the following data", data);
}
}
function makeRegisterRequest(address) {
return JSON.stringify({ "type": "register", "address": address });
}
function makeAuthenticateRequest(address, token) {
return JSON.stringify({ "type": "authenticate", "address": address, "token": token });
}
function http(method, url) {
return new Promise(function (resolve, reject) {
let xhr = new XMLHttpRequest();
xhr.open(method, url);
xhr.onload = function () {
if (this.status >= 200 && this.status < 300) {
resolve(xhr.response);
} else {
reject({
status: this.status,
statusText: xhr.statusText
});
}
};
xhr.onerror = function () {
reject({
status: this.status,
statusText: xhr.statusText
});
};
xhr.send();
});
}
-52
View File
@@ -1,52 +0,0 @@
import * as wasm from "nym-client-wasm";
export function makeRegisterRequest(address) {
return JSON.stringify({ "type": "register", "address": address });
}
export function makeAuthenticateRequest(address, token) {
return JSON.stringify({ "type": "authenticate", "address": address, "token": token });
}
export async function getInitialGatewayAddress(directoryUrl) {
const topology = await getTopology(directoryUrl);
if (topology.gatewayNodes.length > 0) {
return topology.gatewayNodes[0].clientListener;
}
return "";
}
// NOTE: this currently does not implement chunking and too long messages will cause a panic
export function makeSendablePacket(topology, message, recipient) {
return wasm.create_gateway_sphinx_packet(topology, message, recipient);
}
export async function getTopology(directoryUrl) {
let response = await http('get', directoryUrl);
let topology = JSON.parse(response);
return topology;
}
function http(method, url) {
return new Promise(function (resolve, reject) {
let xhr = new XMLHttpRequest();
xhr.open(method, url);
xhr.onload = function () {
if (this.status >= 200 && this.status < 300) {
resolve(xhr.response);
} else {
reject({
status: this.status,
statusText: xhr.statusText
});
}
};
xhr.onerror = function () {
reject({
status: this.status,
statusText: xhr.statusText
});
};
xhr.send();
});
}
+2 -1
View File
@@ -5,7 +5,8 @@ This example application demonstrates how to use WebAssembly to create Sphinx pa
## 🚴 Usage
```
npm run start # fires up a web page at http://localhost:8001
npm install # set up dependencies
npm run start # starts a web server at http://localhost:8001
```
Check your dev console for output.
+8 -4
View File
@@ -9,11 +9,15 @@
<body>
<p>
<label for="fname">Recipient address: </label><input type="text" id="recipient" name="recipient"
value="">
<label for="fname">Our address: </label><input disabled="true" size="40" type="text" id="sender" value="">
</p>
<label for="fname">Text to send: </label><input type="text" id="sendtext" name="sendtext" value="Hello mixnet!">
<button id="send-button">Send</button>
<p>
<label for="fname">Recipient address: </label><input size="40" type="text" id="recipient" value="">
</p>
<label for="fname">Text to send: </label><input type="text" id="sendtext" value="Hello mixnet!">
<button id="send-button">Send</button><button id="refresh-button">Refresh</button>
<p>Send messages to the mixnet using the "send" button.</p>
<p><span style='color: blue;'>Sent</span> messages show in blue, <span style='color: green;'>received</span>
+26 -150
View File
@@ -12,174 +12,50 @@
// See the License for the specific language governing permissions and
// limitations under the License.
import * as wasm from "nym-client-wasm";
import { makeRegisterRequest, makeAuthenticateRequest, makeSendablePacket, getTopology, getInitialGatewayAddress } from "nym-client-wasm/helpers"
import {
Client,
Identity
} from "nym-client-wasm/client"
class GatewayConnection {
constructor(gateway_url, ownAddress, registeredCallback) {
const conn = new WebSocket(gateway_url);
// lovely bindings here we go!
this.onSocketMessage = this.onSocketMessage.bind(this);
this.handleBlobResponse = this.handleBlobResponse.bind(this);
this.handleRegisterResponse = this.handleRegisterResponse.bind(this);
this.handleAuthenticateResponse = this.handleAuthenticateResponse.bind(this);
this.handleErrorResponse = this.handleErrorResponse.bind(this);
this.handleSendConfirmation = this.handleSendConfirmation.bind(this);
conn.onclose = this.onSocketClose;
conn.onmessage = this.onSocketMessage;
conn.onerror = (ev) => console.error("Socket error: ", ev);
conn.onopen = this.onSocketOpen.bind(this);
this.ownAddress = ownAddress;
this.conn = conn;
this.registeredCallback = registeredCallback
}
closeConnection() {
this.conn.close();
}
sendMessage(topology, message, recipient) {
let gatewaySphinxPacket = makeSendablePacket(topology, message, recipient);
this.conn.send(gatewaySphinxPacket)
}
sendRegisterRequest() {
const registerReq = makeRegisterRequest(this.ownAddress);
this.conn.send(registerReq);
}
sendAuthenticateRequest(token) {
const authenticateReq = makeAuthenticateRequest(this.ownAddress, token);
this.conn.send(authenticateReq);
}
onSocketOpen() {
console.log("opened socket connection!")
// the first message you should send is either register or authenticate, otherwise your sphinx packets
// are not going to be accepted (nor you will receive any)
this.sendRegisterRequest()
}
onSocketClose(ev) {
console.log("The websocket was closed", ev);
}
handleSendConfirmation(additionalData) {
console.log("received send confirmation", additionalData);
}
handleRegisterResponse(additionalData) {
console.log("registered! - ", additionalData);
this.registeredCallback();
}
handleAuthenticateResponse(additionalData) {
console.log("authenticated! - ", additionalData);
}
handleErrorResponse(additionalData) {
console.error("received error response: ", additionalData)
}
handleBlobResponse(data) {
// note that the actual handling depends on the expected content, however,
// in this example we're just sending a text messages to ourselves and hence
// we can safely read it as text
let reader = new FileReader();
reader.onload = () => {
displayReceived(reader.result)
};
reader.readAsText(data);
}
onSocketMessage(ev) {
if (ev.data instanceof Blob) {
this.handleBlobResponse(ev.data)
} else {
const receivedData = JSON.parse(ev.data);
switch (receivedData.type) {
case "send": return this.handleSendConfirmation(receivedData);
case "register": return this.handleRegisterResponse(receivedData);
case "authenticate": return this.handleAuthenticateResponse(receivedData);
case "error": return this.handleErrorResponse(receivedData);
}
console.log("Received unknown response!");
console.log(receivedData);
}
}
}
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function main() {
var directoryUrl = "http://127.0.0.1:8080/api/presence/topology";
let directory = "https://qa-directory.nymtech.net";
// let identity = new Identity(); // or load one from storage if you have one already
// because I'm about to make a new PR tomorrow, just hardcode it to not recreate client every single recompilation
let identity = { address: "7mVwY9uFRBBTW91dAWaDtuusSpzc16ZwANLSXxXVYT7M", privateKey: "H4cp7DFMsPXD4Qm7ZW3TgsJETr2CpJhxmBJohko7HrDE", publicKey: "7mVwY9uFRBBTW91dAWaDtuusSpzc16ZwANLSXxXVYT7M" }
const gatewayUrl = await getInitialGatewayAddress(directoryUrl);
if (gatewayUrl == "") {
alert("No gateways detected - cannot procede");
return;
document.getElementById("sender").value = identity.address;
let nymClient = new Client(directory, identity, null); // provide your authToken if you've registered before
nymClient.onParsedBlobResponse = displayReceived // overwrite default behaviour with our implementation
await nymClient.start();
const sendButton = document.querySelector('#send-button');
sendButton.onclick = function () {
sendMessageTo(nymClient);
}
// NOTE: in an actual application, you should save those keys somewhere and only generate them a single time
// then reuse them in subsequent runs
const keypair_address = JSON.parse(wasm.keygen());
console.log("our keypair and address are: ", keypair_address);
document.getElementById("recipient").value = keypair_address.address
document.querySelector('#send-button').disabled = true;
// basically to ensure connection is established before we do anything else
// and more importantly to ensure we are registered so that we could send messages to ourselves
// (i.e. we exist in the topology we're about to pull
let registered_callback = async () => {
// this function is called immediately after we receive registration response
// however, gateways are sending their presence data every 1.5s, so it might take at most 1.5s before
// our address is present in the topology, so just wait that long
// (JS to DH: this is done so that we could have multiple gateways online even for the wasm client)
await sleep(1500);
// Get the topology, then the mixnode and provider data
const topology = await getTopology(directoryUrl);
// Set up the send button
const string_topology = JSON.stringify(topology);
const sendButton = document.querySelector('#send-button');
sendButton.disabled = false;
sendButton.onclick = function () {
sendMessageToMixnet(conn, string_topology);
}
}
// Set up a websocket connection to the gateway node
let conn = new GatewayConnection(gatewayUrl, keypair_address.address, registered_callback);
}
// Create a Sphinx packet and send it to the mixnet through the Gateway node.
function sendMessageToMixnet(connection, topology) {
function sendMessageTo(client) {
var message = document.getElementById("sendtext").value;
var recipient = document.getElementById("recipient").value;
var sendText = document.getElementById("sendtext").value;
connection.sendMessage(topology, sendText, recipient);
displaySend(sendText);
client.sendMessage(message, recipient);
displaySend(message);
}
function displaySend(message) {
let timestamp = new Date().toISOString().substr(11, 12);
document.getElementById("output").innerHTML = document.getElementById("output").innerHTML + "<p style='color: blue; word-break: break-all;'>" + timestamp + " <b>sent</b> >>> " + message + "</p >";
let out = "<p style='color: blue; word-break: break-all;'>" + timestamp + " <b>sent</b> >>> " + message + "</p >";
document.getElementById("output").innerHTML = out + document.getElementById("output").innerHTML;
}
function displayReceived(message) {
let timestamp = new Date().toISOString().substr(11, 12);
document.getElementById("output").innerHTML = document.getElementById("output").innerHTML + "<p style='color: green; word-break: break-all;'>" + timestamp + " <b>received</b> >>> " + message + "</p >";
let out = "<p style='color: green; word-break: break-all;'>" + timestamp + " <b>received</b> >>> " + message + "</p >";
document.getElementById("output").innerHTML = out + document.getElementById("output").innerHTML;
}
// Let's get started!
main();
File diff suppressed because it is too large Load Diff
+6 -6
View File
@@ -26,14 +26,14 @@
"url": "https://github.com/rustwasm/create-wasm-app/issues"
},
"homepage": "https://github.com/rustwasm/create-wasm-app#readme",
"dependencies": {
"nym-client-wasm": "^0.1.3"
},
"devDependencies": {
"copy-webpack-plugin": "^5.0.0",
"hello-wasm-pack": "^0.1.0",
"webpack": "^4.29.3",
"webpack-cli": "^3.1.0",
"webpack-dev-server": "^3.1.5",
"copy-webpack-plugin": "^5.0.0"
"webpack-dev-server": "^3.11.0"
},
"dependencies": {
"nym-client-wasm": "file:../pkg"
}
}
}
+50 -127
View File
@@ -229,11 +229,6 @@ ansi-regex@^2.0.0:
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df"
integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8=
ansi-regex@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998"
integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=
ansi-regex@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997"
@@ -660,15 +655,6 @@ class-utils@^0.3.5:
isobject "^3.0.0"
static-extend "^0.1.1"
cliui@^4.0.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/cliui/-/cliui-4.1.0.tgz#348422dbe82d800b3022eef4f6ac10bf2e4d1b49"
integrity sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==
dependencies:
string-width "^2.1.1"
strip-ansi "^4.0.0"
wrap-ansi "^2.0.0"
cliui@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5"
@@ -678,11 +664,6 @@ cliui@^5.0.0:
strip-ansi "^5.2.0"
wrap-ansi "^5.1.0"
code-point-at@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=
collection-visit@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0"
@@ -1476,11 +1457,6 @@ function-bind@^1.1.1:
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
get-caller-file@^1.0.1:
version "1.0.3"
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a"
integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==
get-caller-file@^2.0.1:
version "2.0.5"
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
@@ -1683,7 +1659,7 @@ hpack.js@^2.1.6:
readable-stream "^2.0.1"
wbuf "^1.1.0"
html-entities@^1.2.1:
html-entities@^1.3.1:
version "1.3.1"
resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-1.3.1.tgz#fb9a1a4b5b14c5daba82d3e34c6ae4fe701a0e44"
integrity sha512-rhE/4Z3hIhzHAUKbW8jVcCyuT5oJCXXqhN/6mXXVCpzTmvJnoH2HL/bt3EZ6p55jbFJBeAe1ZNpL5BugLujxNA==
@@ -1950,13 +1926,6 @@ is-extglob@^2.1.0, is-extglob@^2.1.1:
resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=
is-fullwidth-code-point@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb"
integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs=
dependencies:
number-is-nan "^1.0.0"
is-fullwidth-code-point@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f"
@@ -2154,7 +2123,7 @@ lodash@^4.17.11, lodash@^4.17.14:
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548"
integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==
loglevel@^1.6.6:
loglevel@^1.6.8:
version "1.6.8"
resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.6.8.tgz#8a25fb75d092230ecd4457270d80b54e28011171"
integrity sha512-bsU7+gc9AJ2SqpzxwU3+1fedl8zAntbtC5XYlt3s2j1hJcn2PsXSmgN8TaLG/J1/2mod4+cE/3vNL70/c1RNCA==
@@ -2479,15 +2448,8 @@ npm-run-path@^2.0.0:
dependencies:
path-key "^2.0.0"
number-is-nan@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"
integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=
nym-client-wasm@^0.1.3:
version "0.1.3"
resolved "https://registry.yarnpkg.com/nym-client-wasm/-/nym-client-wasm-0.1.3.tgz#49f93a6a6db0e26dfe94337625a69ea922b05cda"
integrity sha512-ce8JojJ5sXIuY2hbFmgo2W1Nyy56uQ8GnsG6yBt3rzu6+seIRdxPd5ilN86L0Ps7uYLpAyydcwWLErjR6W9S+g==
"nym-client-wasm@file:../pkg":
version "0.7.0-pre"
object-assign@^4.0.1, object-assign@^4.1.1:
version "4.1.1"
@@ -2588,7 +2550,7 @@ os-browserify@^0.3.0:
resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27"
integrity sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=
os-locale@^3.0.0, os-locale@^3.1.0:
os-locale@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-3.1.0.tgz#a802a6ee17f24c10483ab9935719cef4ed16bf1a"
integrity sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==
@@ -2771,7 +2733,7 @@ pkg-dir@^3.0.0:
dependencies:
find-up "^3.0.0"
portfinder@^1.0.25:
portfinder@^1.0.26:
version "1.0.26"
resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.26.tgz#475658d56ca30bed72ac7f1378ed350bd1b64e70"
integrity sha512-Xi7mKxJHHMI3rIUrnm/jjUgwhbYMkp/XKEcZX3aG4BrumLpq3nmoQMX+ClYnDZnZ/New7IatC1no5RX0zo1vXQ==
@@ -2982,11 +2944,6 @@ require-directory@^2.1.1:
resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I=
require-main-filename@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1"
integrity sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=
require-main-filename@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b"
@@ -3256,13 +3213,14 @@ sockjs-client@1.4.0:
json3 "^3.3.2"
url-parse "^1.4.3"
sockjs@0.3.19:
version "0.3.19"
resolved "https://registry.yarnpkg.com/sockjs/-/sockjs-0.3.19.tgz#d976bbe800af7bd20ae08598d582393508993c0d"
integrity sha512-V48klKZl8T6MzatbLlzzRNhMepEys9Y4oGFpypBFFn1gLI/QQ9HtLLyWJNbPlwGLelOVOEijUbTTJeLLI59jLw==
sockjs@0.3.20:
version "0.3.20"
resolved "https://registry.yarnpkg.com/sockjs/-/sockjs-0.3.20.tgz#b26a283ec562ef8b2687b44033a4eeceac75d855"
integrity sha512-SpmVOVpdq0DJc0qArhF3E5xsxvaiqGNb73XfgBpK1y3UD5gs8DSo8aCTsuT5pX8rssdc2NDIzANwP9eCAiSdTA==
dependencies:
faye-websocket "^0.10.0"
uuid "^3.0.1"
uuid "^3.4.0"
websocket-driver "0.6.5"
source-list-map@^2.0.0:
version "2.0.1"
@@ -3315,7 +3273,7 @@ spdy-transport@^3.0.0:
readable-stream "^3.0.6"
wbuf "^1.7.3"
spdy@^4.0.1:
spdy@^4.0.2:
version "4.0.2"
resolved "https://registry.yarnpkg.com/spdy/-/spdy-4.0.2.tgz#b74f466203a3eda452c02492b91fb9e84a27677b"
integrity sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==
@@ -3385,23 +3343,6 @@ stream-shift@^1.0.0:
resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.1.tgz#d7088281559ab2778424279b0877da3c392d5a3d"
integrity sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==
string-width@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3"
integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=
dependencies:
code-point-at "^1.0.0"
is-fullwidth-code-point "^1.0.0"
strip-ansi "^3.0.0"
string-width@^2.0.0, string-width@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e"
integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==
dependencies:
is-fullwidth-code-point "^2.0.0"
strip-ansi "^4.0.0"
string-width@^3.0.0, string-width@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961"
@@ -3459,20 +3400,13 @@ string_decoder@~1.1.1:
dependencies:
safe-buffer "~5.1.0"
strip-ansi@^3.0.0, strip-ansi@^3.0.1:
strip-ansi@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf"
integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=
dependencies:
ansi-regex "^2.0.0"
strip-ansi@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f"
integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8=
dependencies:
ansi-regex "^3.0.0"
strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0:
version "5.2.0"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae"
@@ -3705,7 +3639,7 @@ utils-merge@1.0.1:
resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"
integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=
uuid@^3.0.1, uuid@^3.3.2:
uuid@^3.3.2, uuid@^3.4.0:
version "3.4.0"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee"
integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==
@@ -3769,10 +3703,10 @@ webpack-dev-middleware@^3.7.2:
range-parser "^1.2.1"
webpack-log "^2.0.0"
webpack-dev-server@^3.1.5:
version "3.10.3"
resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-3.10.3.tgz#f35945036813e57ef582c2420ef7b470e14d3af0"
integrity sha512-e4nWev8YzEVNdOMcNzNeCN947sWJNd43E5XvsJzbAL08kGc2frm1tQ32hTJslRS+H65LCb/AaUCYU7fjHCpDeQ==
webpack-dev-server@^3.11.0:
version "3.11.0"
resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-3.11.0.tgz#8f154a3bce1bcfd1cc618ef4e703278855e7ff8c"
integrity sha512-PUxZ+oSTxogFQgkTtFndEtJIPNmml7ExwufBZ9L2/Xyyd5PnOL5UreWe5ZT7IU25DSdykL9p1MLQzmLh2ljSeg==
dependencies:
ansi-html "0.0.7"
bonjour "^3.5.0"
@@ -3782,31 +3716,31 @@ webpack-dev-server@^3.1.5:
debug "^4.1.1"
del "^4.1.1"
express "^4.17.1"
html-entities "^1.2.1"
html-entities "^1.3.1"
http-proxy-middleware "0.19.1"
import-local "^2.0.0"
internal-ip "^4.3.0"
ip "^1.1.5"
is-absolute-url "^3.0.3"
killable "^1.0.1"
loglevel "^1.6.6"
loglevel "^1.6.8"
opn "^5.5.0"
p-retry "^3.0.1"
portfinder "^1.0.25"
portfinder "^1.0.26"
schema-utils "^1.0.0"
selfsigned "^1.10.7"
semver "^6.3.0"
serve-index "^1.9.1"
sockjs "0.3.19"
sockjs "0.3.20"
sockjs-client "1.4.0"
spdy "^4.0.1"
spdy "^4.0.2"
strip-ansi "^3.0.1"
supports-color "^6.1.0"
url "^0.11.0"
webpack-dev-middleware "^3.7.2"
webpack-log "^2.0.0"
ws "^6.2.1"
yargs "12.0.5"
yargs "^13.3.2"
webpack-log@^2.0.0:
version "2.0.0"
@@ -3853,6 +3787,13 @@ webpack@^4.29.3:
watchpack "^1.6.1"
webpack-sources "^1.4.1"
websocket-driver@0.6.5:
version "0.6.5"
resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.6.5.tgz#5cb2556ceb85f4373c6d8238aa691c8454e13a36"
integrity sha1-XLJVbOuF9Dc8bYI4qmkchFThOjY=
dependencies:
websocket-extensions ">=0.1.1"
websocket-driver@>=0.5.1:
version "0.7.3"
resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.3.tgz#a2d4e0d4f4f116f1e6297eba58b05d430100e9f9"
@@ -3886,14 +3827,6 @@ worker-farm@^1.7.0:
dependencies:
errno "~0.1.7"
wrap-ansi@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85"
integrity sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=
dependencies:
string-width "^1.0.1"
strip-ansi "^3.0.1"
wrap-ansi@^5.1.0:
version "5.1.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09"
@@ -3920,7 +3853,7 @@ xtend@^4.0.0, xtend@~4.0.1:
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==
"y18n@^3.2.1 || ^4.0.0", y18n@^4.0.0:
y18n@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b"
integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==
@@ -3930,15 +3863,7 @@ yallist@^3.0.2:
resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd"
integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==
yargs-parser@^11.1.1:
version "11.1.1"
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-11.1.1.tgz#879a0865973bca9f6bab5cbdf3b1c67ec7d3bcf4"
integrity sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==
dependencies:
camelcase "^5.0.0"
decamelize "^1.2.0"
yargs-parser@^13.1.0:
yargs-parser@^13.1.0, yargs-parser@^13.1.2:
version "13.1.2"
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38"
integrity sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==
@@ -3946,24 +3871,6 @@ yargs-parser@^13.1.0:
camelcase "^5.0.0"
decamelize "^1.2.0"
yargs@12.0.5:
version "12.0.5"
resolved "https://registry.yarnpkg.com/yargs/-/yargs-12.0.5.tgz#05f5997b609647b64f66b81e3b4b10a368e7ad13"
integrity sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==
dependencies:
cliui "^4.0.0"
decamelize "^1.2.0"
find-up "^3.0.0"
get-caller-file "^1.0.1"
os-locale "^3.0.0"
require-directory "^2.1.1"
require-main-filename "^1.0.1"
set-blocking "^2.0.0"
string-width "^2.0.0"
which-module "^2.0.0"
y18n "^3.2.1 || ^4.0.0"
yargs-parser "^11.1.1"
yargs@13.2.4:
version "13.2.4"
resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.2.4.tgz#0b562b794016eb9651b98bd37acf364aa5d6dc83"
@@ -3980,3 +3887,19 @@ yargs@13.2.4:
which-module "^2.0.0"
y18n "^4.0.0"
yargs-parser "^13.1.0"
yargs@^13.3.2:
version "13.3.2"
resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.2.tgz#ad7ffefec1aa59565ac915f82dccb38a9c31a2dd"
integrity sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==
dependencies:
cliui "^5.0.0"
find-up "^3.0.0"
get-caller-file "^2.0.1"
require-directory "^2.1.1"
require-main-filename "^2.0.0"
set-blocking "^2.0.0"
string-width "^3.0.0"
which-module "^2.0.0"
y18n "^4.0.0"
yargs-parser "^13.1.2"
+8 -5
View File
@@ -55,9 +55,12 @@ pub struct NodeData {
/// Message chunking is currently not implemented. If the message exceeds the
/// capacity of a single Sphinx packet, the extra information will be discarded.
#[wasm_bindgen]
pub fn create_gateway_sphinx_packet(topology_json: &str, msg: &str, destination: &str) -> Vec<u8> {
pub fn create_sphinx_packet(topology_json: &str, msg: &str, destination: &str) -> Vec<u8> {
utils::set_panic_hook(); // nicer js errors.
if topology_json.len() == 0 {
panic!("WTF2?");
}
let route = sphinx_route_to(topology_json, destination);
let average_delay = Duration::from_secs_f64(0.1);
let delays = delays::generate_from_average_duration(route.len(), average_delay);
@@ -72,16 +75,16 @@ pub fn create_gateway_sphinx_packet(topology_json: &str, msg: &str, destination:
let message = msg.as_bytes().to_vec();
let sphinx_packet = SphinxPacket::new(message, &route, &dest, &delays, None).unwrap();
gateway_payload(sphinx_packet, route)
payload(sphinx_packet, route)
}
/// Concatenate the first mix address bytes with the Sphinx packet.
/// Concatenate the gateway address bytes with the Sphinx packet.
///
/// The Nym gateway node has no idea what is inside the Sphinx packet, or where
/// it should send a packet it receives. So we prepend the packet with the
/// address bytes of the first mix inside the packet, so that the gateway can
/// forward the packet to it.
fn gateway_payload(sphinx_packet: SphinxPacket, route: Vec<SphinxNode>) -> Vec<u8> {
fn payload(sphinx_packet: SphinxPacket, route: Vec<SphinxNode>) -> Vec<u8> {
let packet = sphinx_packet.to_bytes();
let first_node_address =
NymNodeRoutingAddress::try_from(route.first().unwrap().address.clone()).unwrap();
@@ -149,7 +152,7 @@ mod test_constructing_a_sphinx_packet {
#[test]
fn starts_with_a_mix_address() {
let mut payload = create_gateway_sphinx_packet(
let mut payload = create_sphinx_packet(
topology_fixture(),
"foomp",
"5pgrc4gPHP2tBQgfezcdJ2ZAjipoAsy6evrqHdxBbVXq",
+4 -4
View File
@@ -4,13 +4,13 @@ use std::convert::{TryFrom, TryInto};
use wasm_bindgen::prelude::*;
#[derive(Serialize, Deserialize, Debug)]
pub struct FullJSONKeypair {
pub struct GatewayIdentity {
private_key: String,
public_key: String,
address: String,
}
impl TryFrom<String> for FullJSONKeypair {
impl TryFrom<String> for GatewayIdentity {
type Error = serde_json::Error;
fn try_from(msg: String) -> Result<Self, Self::Error> {
@@ -18,7 +18,7 @@ impl TryFrom<String> for FullJSONKeypair {
}
}
impl TryInto<String> for FullJSONKeypair {
impl TryInto<String> for GatewayIdentity {
type Error = serde_json::Error;
fn try_into(self) -> Result<String, Self::Error> {
@@ -31,7 +31,7 @@ pub fn keygen() -> String {
let keypair = MixIdentityKeyPair::new();
let address = keypair.public_key().derive_address();
FullJSONKeypair {
GatewayIdentity {
private_key: keypair.private_key().to_base58_string(),
public_key: keypair.public_key().to_base58_string(),
address: address.to_base58_string(),
+3
View File
@@ -39,6 +39,9 @@ pub struct Topology {
impl Topology {
pub fn new(json: &str) -> Self {
if json.len() == 0 {
panic!("WTF?");
}
serde_json::from_str(json).unwrap()
}
@@ -33,6 +33,7 @@ impl From<ServiceMixnode> for RestMixnode {
}
impl ServiceTopology {
#[cfg(test)] // un-testify this when you need it for real code, this kills warning
pub fn from_rest_topology_with_timestamp(
rest_topology: RestTopology,
timestamp: Timestamp,