WIP trying to get libp2p working

This commit is contained in:
Valery Antopol 2022-08-07 22:04:56 +03:00
parent 83c587af34
commit 8007b06e4b
19 changed files with 19675 additions and 0 deletions

1882
libp2p-wasm/Cargo.lock generated Normal file

File diff suppressed because it is too large Load Diff

23
libp2p-wasm/Cargo.toml Normal file
View File

@ -0,0 +1,23 @@
[package]
name = "libp2p-wasm"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[lib]
crate-type = ["cdylib", "rlib"]
[workspace]
[dependencies]
libp2p = { version = "0.45.0", default-features = false, features = ["wasm-bindgen", "mplex", "noise", "identify", "yamux", "ping", "wasm-ext", "wasm-ext-websocket"] }
console_error_panic_hook = "0.1.7"
wasm-rs-dbg = "0.1.2"
tokio = { version = "1.17.0", features = ["macros", "sync"] }
wasm-bindgen-futures = { version = "0.4.30"}
wasm-bindgen = "0.2.82"
web-sys = { version = "0.3.57"}
js-sys = {version = "0.3.57"}
[patch.crates-io]
gloo-timers = {version = "0.2.4", path = "../../gloo/crates/timers"}

6
libp2p-wasm/build.sh Executable file
View File

@ -0,0 +1,6 @@
wasm-pack build --target web --dev
(
cd npm-package || exit;
npm i;
npm run build
)

7
libp2p-wasm/npm-package/.gitignore vendored Normal file
View File

@ -0,0 +1,7 @@
dist
node_modules
*.tgz
# auto-generated files
src/*.wasm
snippets

View File

@ -0,0 +1,8 @@
module.exports = {
semi: true,
trailingComma: 'all',
singleQuote: true,
printWidth: 120,
tabWidth: 4,
useTabs: false,
};

View File

@ -0,0 +1,7 @@
module.exports = {
testEnvironment: 'node',
testPathIgnorePatterns: ['dist'],
transform: {
'^.+\\.(ts|js)x?$': 'ts-jest',
},
};

16604
libp2p-wasm/npm-package/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,43 @@
{
"name": "@fluencelabs/libp2p-wasm",
"description": "Libp2p-wasm",
"version": "0.1.0",
"main": "./dist/index.js",
"typings": "./dist/index.d.ts",
"repository": "",
"author": "Fluence Labs",
"license": "Apache 2.0",
"files": [
"dist/*",
"!lib/__test__/*"
],
"scripts": {
"build": "npm run build:tsc && npm run build:web && npm run build:node",
"build:tsc": "tsc",
"build:web": "webpack -c webpack.config.web.js",
"build:node": "webpack -c webpack.config.node.js",
"postbuild": "cp ../pkg/libp2p_wasm_bg.wasm ./dist/libp2p_wasm_bg.wasm",
"test": "jest"
},
"private": false,
"dependencies": {
"browser-or-node": "^2.0.0",
"buffer": "^6.0.3",
"threads": "^1.7.0",
"ts-jest": "^27.1.4"
},
"devDependencies": {
"@fluencelabs/avm": "0.22.2",
"@types/download": "^8.0.1",
"@types/jest": "^27.4.0",
"@types/node": "^14.0.0",
"@types/tmp": "^0.2.3",
"download": "^8.0.0",
"ifdef-loader": "^2.3.2",
"jest": "^27.2.4",
"ts-loader": "^8.3.0",
"typescript": "^4.0.0",
"webpack": "^4.46.0",
"webpack-cli": "^4.9.1"
}
}

View File

@ -0,0 +1,26 @@
/*
* Copyright 2022 Fluence Labs Limited
*
* 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.
*/
import { expose } from 'threads';
import {test} from './index'
const toExpose = {
init: () => {test()},
};
expose(toExpose);

View File

@ -0,0 +1 @@
export * from './libp2p_wasm'

View File

@ -0,0 +1,687 @@
import { websocket_transport } from './snippets/libp2p-wasm-ext-0a95fd7509554c17/src/websockets.js';
let wasm;
const heap = new Array(32).fill(undefined);
heap.push(undefined, null, true, false);
function getObject(idx) { return heap[idx]; }
let heap_next = heap.length;
function dropObject(idx) {
if (idx < 36) return;
heap[idx] = heap_next;
heap_next = idx;
}
function takeObject(idx) {
const ret = getObject(idx);
dropObject(idx);
return ret;
}
function _assertBoolean(n) {
if (typeof(n) !== 'boolean') {
throw new Error('expected a boolean argument');
}
}
const cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
cachedTextDecoder.decode();
let cachedUint8Memory0 = new Uint8Array();
function getUint8Memory0() {
if (cachedUint8Memory0.byteLength === 0) {
cachedUint8Memory0 = new Uint8Array(wasm.memory.buffer);
}
return cachedUint8Memory0;
}
function getStringFromWasm0(ptr, len) {
return cachedTextDecoder.decode(getUint8Memory0().subarray(ptr, ptr + len));
}
function addHeapObject(obj) {
if (heap_next === heap.length) heap.push(heap.length + 1);
const idx = heap_next;
heap_next = heap[idx];
if (typeof(heap_next) !== 'number') throw new Error('corrupt heap');
heap[idx] = obj;
return idx;
}
let WASM_VECTOR_LEN = 0;
const cachedTextEncoder = new TextEncoder('utf-8');
const encodeString = (typeof cachedTextEncoder.encodeInto === 'function'
? function (arg, view) {
return cachedTextEncoder.encodeInto(arg, view);
}
: function (arg, view) {
const buf = cachedTextEncoder.encode(arg);
view.set(buf);
return {
read: arg.length,
written: buf.length
};
});
function passStringToWasm0(arg, malloc, realloc) {
if (typeof(arg) !== 'string') throw new Error('expected a string argument');
if (realloc === undefined) {
const buf = cachedTextEncoder.encode(arg);
const ptr = malloc(buf.length);
getUint8Memory0().subarray(ptr, ptr + buf.length).set(buf);
WASM_VECTOR_LEN = buf.length;
return ptr;
}
let len = arg.length;
let ptr = malloc(len);
const mem = getUint8Memory0();
let offset = 0;
for (; offset < len; offset++) {
const code = arg.charCodeAt(offset);
if (code > 0x7F) break;
mem[ptr + offset] = code;
}
if (offset !== len) {
if (offset !== 0) {
arg = arg.slice(offset);
}
ptr = realloc(ptr, len, len = offset + arg.length * 3);
const view = getUint8Memory0().subarray(ptr + offset, ptr + len);
const ret = encodeString(arg, view);
if (ret.read !== arg.length) throw new Error('failed to pass whole string');
offset += ret.written;
}
WASM_VECTOR_LEN = offset;
return ptr;
}
function isLikeNone(x) {
return x === undefined || x === null;
}
let cachedInt32Memory0 = new Int32Array();
function getInt32Memory0() {
if (cachedInt32Memory0.byteLength === 0) {
cachedInt32Memory0 = new Int32Array(wasm.memory.buffer);
}
return cachedInt32Memory0;
}
function debugString(val) {
// primitive types
const type = typeof val;
if (type == 'number' || type == 'boolean' || val == null) {
return `${val}`;
}
if (type == 'string') {
return `"${val}"`;
}
if (type == 'symbol') {
const description = val.description;
if (description == null) {
return 'Symbol';
} else {
return `Symbol(${description})`;
}
}
if (type == 'function') {
const name = val.name;
if (typeof name == 'string' && name.length > 0) {
return `Function(${name})`;
} else {
return 'Function';
}
}
// objects
if (Array.isArray(val)) {
const length = val.length;
let debug = '[';
if (length > 0) {
debug += debugString(val[0]);
}
for(let i = 1; i < length; i++) {
debug += ', ' + debugString(val[i]);
}
debug += ']';
return debug;
}
// Test for built-in
const builtInMatches = /\[object ([^\]]+)\]/.exec(toString.call(val));
let className;
if (builtInMatches.length > 1) {
className = builtInMatches[1];
} else {
// Failed to match the standard '[object ClassName]'
return toString.call(val);
}
if (className == 'Object') {
// we're a user defined class or Object
// JSON.stringify avoids problems with cycles, and is generally much
// easier than looping through ownProperties of `val`.
try {
return 'Object(' + JSON.stringify(val) + ')';
} catch (_) {
return 'Object';
}
}
// errors
if (val instanceof Error) {
return `${val.name}: ${val.message}\n${val.stack}`;
}
// TODO we could test for more things here, like `Set`s and `Map`s.
return className;
}
function makeMutClosure(arg0, arg1, dtor, f) {
const state = { a: arg0, b: arg1, cnt: 1, dtor };
const real = (...args) => {
// First up with a closure we increment the internal reference
// count. This ensures that the Rust closure environment won't
// be deallocated while we're invoking it.
state.cnt++;
const a = state.a;
state.a = 0;
try {
return f(a, state.b, ...args);
} finally {
if (--state.cnt === 0) {
wasm.__wbindgen_export_2.get(state.dtor)(a, state.b);
} else {
state.a = a;
}
}
};
real.original = state;
return real;
}
function logError(f, args) {
try {
return f.apply(this, args);
} catch (e) {
let error = (function () {
try {
return e instanceof Error ? `${e.message}\n\nStack:\n${e.stack}` : e.toString();
} catch(_) {
return "<failed to stringify thrown value>";
}
}());
console.error("wasm-bindgen: imported JS function that was not marked as `catch` threw an error:", error);
throw e;
}
}
function _assertNum(n) {
if (typeof(n) !== 'number') throw new Error('expected a number argument');
}
function __wbg_adapter_28(arg0, arg1) {
_assertNum(arg0);
_assertNum(arg1);
wasm._dyn_core__ops__function__FnMut_____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__hb95e93aa35c6b9ad(arg0, arg1);
}
function __wbg_adapter_31(arg0, arg1, arg2) {
_assertNum(arg0);
_assertNum(arg1);
wasm._dyn_core__ops__function__FnMut__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h699b03a15e2220af(arg0, arg1, addHeapObject(arg2));
}
/**
*/
export function test() {
wasm.test();
}
function handleError(f, args) {
try {
return f.apply(this, args);
} catch (e) {
wasm.__wbindgen_exn_store(addHeapObject(e));
}
}
function getArrayU8FromWasm0(ptr, len) {
return getUint8Memory0().subarray(ptr / 1, ptr / 1 + len);
}
let cachedUint32Memory0 = new Uint32Array();
function getUint32Memory0() {
if (cachedUint32Memory0.byteLength === 0) {
cachedUint32Memory0 = new Uint32Array(wasm.memory.buffer);
}
return cachedUint32Memory0;
}
function passArrayJsValueToWasm0(array, malloc) {
const ptr = malloc(array.length * 4);
const mem = getUint32Memory0();
for (let i = 0; i < array.length; i++) {
mem[ptr / 4 + i] = addHeapObject(array[i]);
}
WASM_VECTOR_LEN = array.length;
return ptr;
}
function notDefined(what) { return () => { throw new Error(`${what} is not defined`); }; }
async function load(module, imports) {
if (typeof Response === 'function' && module instanceof Response) {
if (typeof WebAssembly.instantiateStreaming === 'function') {
try {
return await WebAssembly.instantiateStreaming(module, imports);
} catch (e) {
if (module.headers.get('Content-Type') != 'application/wasm') {
console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", e);
} else {
throw e;
}
}
}
const bytes = await module.arrayBuffer();
return await WebAssembly.instantiate(bytes, imports);
} else {
const instance = await WebAssembly.instantiate(module, imports);
if (instance instanceof WebAssembly.Instance) {
return { instance, module };
} else {
return instance;
}
}
}
function getImports() {
const imports = {};
imports.wbg = {};
imports.wbg.__wbg_error_09919627ac0992f5 = function() { return logError(function (arg0, arg1) {
try {
console.error(getStringFromWasm0(arg0, arg1));
} finally {
wasm.__wbindgen_free(arg0, arg1);
}
}, arguments) };
imports.wbg.__wbg_new_693216e109162396 = function() { return logError(function () {
const ret = new Error();
return addHeapObject(ret);
}, arguments) };
imports.wbg.__wbg_stack_0ddaca5d1abfb52f = function() { return logError(function (arg0, arg1) {
const ret = getObject(arg1).stack;
const ptr0 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
const len0 = WASM_VECTOR_LEN;
getInt32Memory0()[arg0 / 4 + 1] = len0;
getInt32Memory0()[arg0 / 4 + 0] = ptr0;
}, arguments) };
imports.wbg.__wbindgen_object_drop_ref = function(arg0) {
takeObject(arg0);
};
imports.wbg.__wbindgen_is_null = function(arg0) {
const ret = getObject(arg0) === null;
_assertBoolean(ret);
return ret;
};
imports.wbg.__wbindgen_string_new = function(arg0, arg1) {
const ret = getStringFromWasm0(arg0, arg1);
return addHeapObject(ret);
};
imports.wbg.__wbindgen_string_get = function(arg0, arg1) {
const obj = getObject(arg1);
const ret = typeof(obj) === 'string' ? obj : undefined;
var ptr0 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
var len0 = WASM_VECTOR_LEN;
getInt32Memory0()[arg0 / 4 + 1] = len0;
getInt32Memory0()[arg0 / 4 + 0] = ptr0;
};
imports.wbg.__wbindgen_object_clone_ref = function(arg0) {
const ret = getObject(arg0);
return addHeapObject(ret);
};
imports.wbg.__wbg_dial_1f8e56b305fcf44d = function() { return handleError(function (arg0, arg1, arg2, arg3) {
const ret = getObject(arg0).dial(getStringFromWasm0(arg1, arg2), arg3 !== 0);
return addHeapObject(ret);
}, arguments) };
imports.wbg.__wbg_listenon_1885247979b88a8b = function() { return handleError(function (arg0, arg1, arg2) {
const ret = getObject(arg0).listen_on(getStringFromWasm0(arg1, arg2));
return addHeapObject(ret);
}, arguments) };
imports.wbg.__wbg_read_9eaaf1fd1e03eb9b = function() { return logError(function (arg0) {
const ret = getObject(arg0).read;
return addHeapObject(ret);
}, arguments) };
imports.wbg.__wbg_write_2f7a1194eabf9ee5 = function() { return handleError(function (arg0, arg1, arg2) {
const ret = getObject(arg0).write(getArrayU8FromWasm0(arg1, arg2));
return addHeapObject(ret);
}, arguments) };
imports.wbg.__wbg_shutdown_bad4cd66f1b432a3 = function() { return handleError(function (arg0) {
getObject(arg0).shutdown();
}, arguments) };
imports.wbg.__wbg_close_11019f9c9666b272 = function() { return logError(function (arg0) {
getObject(arg0).close();
}, arguments) };
imports.wbg.__wbg_newaddrs_ff4981cbf3ee4ad9 = function() { return logError(function (arg0, arg1) {
const ret = getObject(arg1).new_addrs;
var ptr0 = isLikeNone(ret) ? 0 : passArrayJsValueToWasm0(ret, wasm.__wbindgen_malloc);
var len0 = WASM_VECTOR_LEN;
getInt32Memory0()[arg0 / 4 + 1] = len0;
getInt32Memory0()[arg0 / 4 + 0] = ptr0;
}, arguments) };
imports.wbg.__wbg_expiredaddrs_244331d0d5f5e28c = function() { return logError(function (arg0, arg1) {
const ret = getObject(arg1).expired_addrs;
var ptr0 = isLikeNone(ret) ? 0 : passArrayJsValueToWasm0(ret, wasm.__wbindgen_malloc);
var len0 = WASM_VECTOR_LEN;
getInt32Memory0()[arg0 / 4 + 1] = len0;
getInt32Memory0()[arg0 / 4 + 0] = ptr0;
}, arguments) };
imports.wbg.__wbg_newconnections_9525a8138f43e4fd = function() { return logError(function (arg0, arg1) {
const ret = getObject(arg1).new_connections;
var ptr0 = isLikeNone(ret) ? 0 : passArrayJsValueToWasm0(ret, wasm.__wbindgen_malloc);
var len0 = WASM_VECTOR_LEN;
getInt32Memory0()[arg0 / 4 + 1] = len0;
getInt32Memory0()[arg0 / 4 + 0] = ptr0;
}, arguments) };
imports.wbg.__wbg_connection_7fead32f5c4871eb = function() { return logError(function (arg0) {
const ret = getObject(arg0).connection;
return addHeapObject(ret);
}, arguments) };
imports.wbg.__wbg_observedaddr_28299220e170cc00 = function() { return logError(function (arg0, arg1) {
const ret = getObject(arg1).observed_addr;
const ptr0 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
const len0 = WASM_VECTOR_LEN;
getInt32Memory0()[arg0 / 4 + 1] = len0;
getInt32Memory0()[arg0 / 4 + 0] = ptr0;
}, arguments) };
imports.wbg.__wbg_localaddr_2f6f404984d02a3c = function() { return logError(function (arg0, arg1) {
const ret = getObject(arg1).local_addr;
const ptr0 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
const len0 = WASM_VECTOR_LEN;
getInt32Memory0()[arg0 / 4 + 1] = len0;
getInt32Memory0()[arg0 / 4 + 0] = ptr0;
}, arguments) };
imports.wbg.__wbg_websockettransport_35fc39b2551cb920 = function() { return logError(function () {
const ret = websocket_transport();
return addHeapObject(ret);
}, arguments) };
imports.wbg.__wbindgen_cb_drop = function(arg0) {
const obj = takeObject(arg0).original;
if (obj.cnt-- == 1) {
obj.a = 0;
return true;
}
const ret = false;
_assertBoolean(ret);
return ret;
};
imports.wbg.__wbg_setTimeout_131fc254e1bd5624 = function() { return handleError(function (arg0, arg1) {
const ret = setTimeout(getObject(arg0), arg1);
//_assertNum(ret);
return ret;
}, arguments) };
imports.wbg.__wbg_clearTimeout_65417660fe82f08d = typeof clearTimeout == 'function' ? clearTimeout : notDefined('clearTimeout');
imports.wbg.__wbg_self_86b4b13392c7af56 = function() { return handleError(function () {
const ret = self.self;
return addHeapObject(ret);
}, arguments) };
imports.wbg.__wbg_msCrypto_9ad6677321a08dd8 = function() { return logError(function (arg0) {
const ret = getObject(arg0).msCrypto;
return addHeapObject(ret);
}, arguments) };
imports.wbg.__wbg_crypto_b8c92eaac23d0d80 = function() { return logError(function (arg0) {
const ret = getObject(arg0).crypto;
return addHeapObject(ret);
}, arguments) };
imports.wbg.__wbg_getRandomValues_dd27e6b0652b3236 = function() { return logError(function (arg0) {
const ret = getObject(arg0).getRandomValues;
return addHeapObject(ret);
}, arguments) };
imports.wbg.__wbg_getRandomValues_e57c9b75ddead065 = function() { return logError(function (arg0, arg1) {
getObject(arg0).getRandomValues(getObject(arg1));
}, arguments) };
imports.wbg.__wbg_randomFillSync_d2ba53160aec6aba = function() { return logError(function (arg0, arg1, arg2) {
getObject(arg0).randomFillSync(getArrayU8FromWasm0(arg1, arg2));
}, arguments) };
imports.wbg.__wbg_static_accessor_MODULE_452b4680e8614c81 = function() { return logError(function () {
const ret = module;
return addHeapObject(ret);
}, arguments) };
imports.wbg.__wbg_require_f5521a5b85ad2542 = function() { return logError(function (arg0, arg1, arg2) {
const ret = getObject(arg0).require(getStringFromWasm0(arg1, arg2));
return addHeapObject(ret);
}, arguments) };
imports.wbg.__wbindgen_is_undefined = function(arg0) {
const ret = getObject(arg0) === undefined;
_assertBoolean(ret);
return ret;
};
imports.wbg.__wbindgen_is_object = function(arg0) {
const val = getObject(arg0);
const ret = typeof(val) === 'object' && val !== null;
_assertBoolean(ret);
return ret;
};
imports.wbg.__wbindgen_is_string = function(arg0) {
const ret = typeof(getObject(arg0)) === 'string';
_assertBoolean(ret);
return ret;
};
imports.wbg.__wbg_msCrypto_5a86d77a66230f81 = function() { return logError(function (arg0) {
const ret = getObject(arg0).msCrypto;
return addHeapObject(ret);
}, arguments) };
imports.wbg.__wbg_crypto_b95d7173266618a9 = function() { return logError(function (arg0) {
const ret = getObject(arg0).crypto;
return addHeapObject(ret);
}, arguments) };
imports.wbg.__wbg_getRandomValues_b14734aa289bc356 = function() { return handleError(function (arg0, arg1) {
getObject(arg0).getRandomValues(getObject(arg1));
}, arguments) };
imports.wbg.__wbg_static_accessor_NODE_MODULE_26b231378c1be7dd = function() { return logError(function () {
const ret = module;
return addHeapObject(ret);
}, arguments) };
imports.wbg.__wbg_require_0db1598d9ccecb30 = function() { return handleError(function (arg0, arg1, arg2) {
const ret = getObject(arg0).require(getStringFromWasm0(arg1, arg2));
return addHeapObject(ret);
}, arguments) };
imports.wbg.__wbg_randomFillSync_91e2b39becca6147 = function() { return handleError(function (arg0, arg1, arg2) {
getObject(arg0).randomFillSync(getArrayU8FromWasm0(arg1, arg2));
}, arguments) };
imports.wbg.__wbg_process_e56fd54cf6319b6c = function() { return logError(function (arg0) {
const ret = getObject(arg0).process;
return addHeapObject(ret);
}, arguments) };
imports.wbg.__wbg_versions_77e21455908dad33 = function() { return logError(function (arg0) {
const ret = getObject(arg0).versions;
return addHeapObject(ret);
}, arguments) };
imports.wbg.__wbg_node_0dd25d832e4785d5 = function() { return logError(function (arg0) {
const ret = getObject(arg0).node;
return addHeapObject(ret);
}, arguments) };
imports.wbg.__wbg_instanceof_Error_2082612c1902c887 = function() { return logError(function (arg0) {
const ret = getObject(arg0) instanceof Error;
_assertBoolean(ret);
return ret;
}, arguments) };
imports.wbg.__wbg_message_924b46658b69b295 = function() { return logError(function (arg0) {
const ret = getObject(arg0).message;
return addHeapObject(ret);
}, arguments) };
imports.wbg.__wbg_name_e88a3b3a0f6b23c2 = function() { return logError(function (arg0) {
const ret = getObject(arg0).name;
return addHeapObject(ret);
}, arguments) };
imports.wbg.__wbg_newnoargs_971e9a5abe185139 = function() { return logError(function (arg0, arg1) {
const ret = new Function(getStringFromWasm0(arg0, arg1));
return addHeapObject(ret);
}, arguments) };
imports.wbg.__wbg_call_33d7bcddbbfa394a = function() { return handleError(function (arg0, arg1) {
const ret = getObject(arg0).call(getObject(arg1));
return addHeapObject(ret);
}, arguments) };
imports.wbg.__wbg_next_3d0c4cc33e7418c9 = function() { return handleError(function (arg0) {
const ret = getObject(arg0).next();
return addHeapObject(ret);
}, arguments) };
imports.wbg.__wbg_done_e5655b169bb04f60 = function() { return logError(function (arg0) {
const ret = getObject(arg0).done;
_assertBoolean(ret);
return ret;
}, arguments) };
imports.wbg.__wbg_value_8f901bca1014f843 = function() { return logError(function (arg0) {
const ret = getObject(arg0).value;
return addHeapObject(ret);
}, arguments) };
imports.wbg.__wbg_instanceof_Object_9657a9e91b05959b = function() { return logError(function (arg0) {
const ret = getObject(arg0) instanceof Object;
_assertBoolean(ret);
return ret;
}, arguments) };
imports.wbg.__wbg_toString_6b8020d208a4584e = function() { return logError(function (arg0) {
const ret = getObject(arg0).toString();
return addHeapObject(ret);
}, arguments) };
imports.wbg.__wbg_resolve_0107b3a501450ba0 = function() { return logError(function (arg0) {
const ret = Promise.resolve(getObject(arg0));
return addHeapObject(ret);
}, arguments) };
imports.wbg.__wbg_then_18da6e5453572fc8 = function() { return logError(function (arg0, arg1) {
const ret = getObject(arg0).then(getObject(arg1));
return addHeapObject(ret);
}, arguments) };
imports.wbg.__wbg_then_e5489f796341454b = function() { return logError(function (arg0, arg1, arg2) {
const ret = getObject(arg0).then(getObject(arg1), getObject(arg2));
return addHeapObject(ret);
}, arguments) };
imports.wbg.__wbg_globalThis_3348936ac49df00a = function() { return handleError(function () {
const ret = globalThis.globalThis;
return addHeapObject(ret);
}, arguments) };
imports.wbg.__wbg_self_fd00a1ef86d1b2ed = function() { return handleError(function () {
const ret = self.self;
return addHeapObject(ret);
}, arguments) };
imports.wbg.__wbg_window_6f6e346d8bbd61d7 = function() { return handleError(function () {
const ret = window.window;
return addHeapObject(ret);
}, arguments) };
imports.wbg.__wbg_global_67175caf56f55ca9 = function() { return handleError(function () {
const ret = global.global;
return addHeapObject(ret);
}, arguments) };
imports.wbg.__wbg_new_cda198d9dbc6d7ea = function() { return logError(function (arg0) {
const ret = new Uint8Array(getObject(arg0));
return addHeapObject(ret);
}, arguments) };
imports.wbg.__wbg_newwithlength_66e5530e7079ea1b = function() { return logError(function (arg0) {
const ret = new Uint8Array(arg0 >>> 0);
return addHeapObject(ret);
}, arguments) };
imports.wbg.__wbg_subarray_270ff8dd5582c1ac = function() { return logError(function (arg0, arg1, arg2) {
const ret = getObject(arg0).subarray(arg1 >>> 0, arg2 >>> 0);
return addHeapObject(ret);
}, arguments) };
imports.wbg.__wbg_length_51f19f73d6d9eff3 = function() { return logError(function (arg0) {
const ret = getObject(arg0).length;
_assertNum(ret);
return ret;
}, arguments) };
imports.wbg.__wbg_set_1a930cfcda1a8067 = function() { return logError(function (arg0, arg1, arg2) {
getObject(arg0).set(getObject(arg1), arg2 >>> 0);
}, arguments) };
imports.wbg.__wbg_buffer_34f5ec9f8a838ba0 = function() { return logError(function (arg0) {
const ret = getObject(arg0).buffer;
return addHeapObject(ret);
}, arguments) };
imports.wbg.__wbindgen_debug_string = function(arg0, arg1) {
const ret = debugString(getObject(arg1));
const ptr0 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
const len0 = WASM_VECTOR_LEN;
getInt32Memory0()[arg0 / 4 + 1] = len0;
getInt32Memory0()[arg0 / 4 + 0] = ptr0;
};
imports.wbg.__wbindgen_throw = function(arg0, arg1) {
throw new Error(getStringFromWasm0(arg0, arg1));
};
imports.wbg.__wbindgen_rethrow = function(arg0) {
throw takeObject(arg0);
};
imports.wbg.__wbindgen_memory = function() {
const ret = wasm.memory;
return addHeapObject(ret);
};
imports.wbg.__wbindgen_closure_wrapper6843 = function() { return logError(function (arg0, arg1, arg2) {
const ret = makeMutClosure(arg0, arg1, 436, __wbg_adapter_28);
return addHeapObject(ret);
}, arguments) };
imports.wbg.__wbindgen_closure_wrapper13284 = function() { return logError(function (arg0, arg1, arg2) {
const ret = makeMutClosure(arg0, arg1, 727, __wbg_adapter_31);
return addHeapObject(ret);
}, arguments) };
return imports;
}
function initMemory(imports, maybe_memory) {
}
function finalizeInit(instance, module) {
wasm = instance.exports;
init.__wbindgen_wasm_module = module;
cachedInt32Memory0 = new Int32Array();
cachedUint32Memory0 = new Uint32Array();
cachedUint8Memory0 = new Uint8Array();
return wasm;
}
function initSync(bytes) {
const imports = getImports();
initMemory(imports);
const module = new WebAssembly.Module(bytes);
const instance = new WebAssembly.Instance(module, imports);
return finalizeInit(instance, module);
}
async function init(input) {
const imports = getImports();
initMemory(imports);
const { instance, module } = await load(await input, imports);
return finalizeInit(instance, module);
}
export { initSync }
export default init;

View File

@ -0,0 +1,174 @@
// Copyright 2020 Parity Technologies (UK) Ltd.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
export const websocket_transport = () => {
return {
dial: dial,
listen_on: (addr) => {
let err = new Error("Listening on WebSockets is not possible from within a browser");
err.name = "NotSupportedError";
throw err;
},
};
}
/// Turns a string multiaddress into a WebSockets string URL.
const multiaddr_to_ws = (addr) => {
let parsed = addr.match(/^\/(ip4|ip6|dns4|dns6|dns)\/(.*?)\/tcp\/(.*?)\/(ws|wss|x-parity-ws\/(.*)|x-parity-wss\/(.*))(|\/p2p\/[a-zA-Z0-9]+)$/);
if (parsed != null) {
let proto = 'wss';
if (parsed[4] == 'ws' || parsed[4].startsWith('x-parity-ws/')) {
proto = 'ws';
}
let url = decodeURIComponent(parsed[5] || parsed[6] || '');
if (parsed[1] == 'ip6') {
return proto + "://[" + parsed[2] + "]:" + parsed[3] + url;
} else {
return proto + "://" + parsed[2] + ":" + parsed[3] + url;
}
}
let err = new Error("Address not supported: " + addr);
err.name = "NotSupportedError";
throw err;
}
// Attempt to dial a multiaddress.
const dial = (addr) => {
let ws = new WebSocket(multiaddr_to_ws(addr));
ws.binaryType = "arraybuffer";
let reader = read_queue();
return new Promise((open_resolve, open_reject) => {
ws.onerror = (ev) => {
// If `open_resolve` has been called earlier, calling `open_reject` seems to be
// silently ignored. It is easier to unconditionally call `open_reject` rather than
// check in which state the connection is, which would be error-prone.
open_reject(ev);
// Injecting an EOF is how we report to the reading side that the connection has been
// closed. Injecting multiple EOFs is harmless.
reader.inject_eof();
};
ws.onclose = (ev) => {
// Same remarks as above.
open_reject(ev);
reader.inject_eof();
};
// We inject all incoming messages into the queue unconditionally. The caller isn't
// supposed to access this queue unless the connection is open.
ws.onmessage = (ev) => reader.inject_array_buffer(ev.data);
ws.onopen = () => open_resolve({
read: (function*() { while(ws.readyState == 1) { yield reader.next(); } })(),
write: (data) => {
if (ws.readyState == 1) {
// The passed in `data` is an `ArrayBufferView` [0]. If the
// underlying typed array is a `SharedArrayBuffer` (when
// using WASM threads, so multiple web workers sharing
// memory) the WebSocket's `send` method errors [1][2][3].
// This limitation will probably be lifted in the future,
// but for now we have to make a copy here ..
//
// [0]: https://developer.mozilla.org/en-US/docs/Web/API/ArrayBufferView
// [1]: https://chromium.googlesource.com/chromium/src/+/1438f63f369fed3766fa5031e7a252c986c69be6%5E%21/
// [2]: https://bugreports.qt.io/browse/QTBUG-78078
// [3]: https://chromium.googlesource.com/chromium/src/+/HEAD/third_party/blink/renderer/bindings/IDLExtendedAttributes.md#AllowShared_p
ws.send(data.slice(0));
return promise_when_send_finished(ws);
} else {
return Promise.reject("WebSocket is closed");
}
},
shutdown: () => ws.close(),
close: () => {}
});
});
}
// Takes a WebSocket object and returns a Promise that resolves when bufferedAmount is low enough
// to allow more data to be sent.
const promise_when_send_finished = (ws) => {
return new Promise((resolve, reject) => {
function check() {
if (ws.readyState != 1) {
reject("WebSocket is closed");
return;
}
// We put an arbitrary threshold of 8 kiB of buffered data.
if (ws.bufferedAmount < 8 * 1024) {
resolve();
} else {
setTimeout(check, 100);
}
}
check();
})
}
// Creates a queue reading system.
const read_queue = () => {
// State of the queue.
let state = {
// Array of promises resolving to `ArrayBuffer`s, that haven't been transmitted back with
// `next` yet.
queue: new Array(),
// If `resolve` isn't null, it is a "resolve" function of a promise that has already been
// returned by `next`. It should be called with some data.
resolve: null,
};
return {
// Inserts a new Blob in the queue.
inject_array_buffer: (buffer) => {
if (state.resolve != null) {
state.resolve(buffer);
state.resolve = null;
} else {
state.queue.push(Promise.resolve(buffer));
}
},
// Inserts an EOF message in the queue.
inject_eof: () => {
if (state.resolve != null) {
state.resolve(null);
state.resolve = null;
} else {
state.queue.push(Promise.resolve(null));
}
},
// Returns a Promise that yields the next entry as an ArrayBuffer.
next: () => {
if (state.queue.length != 0) {
return state.queue.shift(0);
} else {
if (state.resolve !== null)
throw "Internal error: already have a pending promise";
return new Promise((resolve, reject) => {
state.resolve = resolve;
});
}
}
};
};

View File

@ -0,0 +1,26 @@
{
"compilerOptions": {
"lib": [
"es2015",
"dom"
],
"outDir": "./dist/",
"target": "es5",
"module": "commonjs",
"allowJs": true,
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"declaration": true,
"declarationMap": false,
"sourceMap": true,
},
"exclude": [
"node_modules",
"dist"
],
"include": [
"src"
],
}

View File

@ -0,0 +1,41 @@
// Generated using webpack-cli https://github.com/webpack/webpack-cli
const path = require('path');
// const isProduction = true;
// uncomment to debug
const isProduction = false;
const config = (ifDefOpts) => ({
entry: './src/backgroundScript.ts',
output: {
path: path.resolve('dist'),
},
module: {
rules: [
{
test: /\.(js|ts|tsx)$/i,
use: [
// force new line
{ loader: 'ts-loader' },
{ loader: 'ifdef-loader', options: ifDefOpts },
],
exclude: ['/node_modules/'],
},
],
},
resolve: {
extensions: ['.tsx', '.ts', '.js'],
},
});
module.exports = (ifDefConfig) => {
const res = config(ifDefConfig);
if (isProduction) {
res.mode = 'production';
} else {
res.mode = 'development';
}
return res;
};

View File

@ -0,0 +1,13 @@
// Generated using webpack-cli https://github.com/webpack/webpack-cli
const config = require('./webpack.config.js');
module.exports = () => {
const cfg = config({
NODE: true,
WEB: false,
});
cfg.output.filename = 'libp2p-wasm.node.js';
cfg.target = 'node';
return cfg;
};

View File

@ -0,0 +1,13 @@
// Generated using webpack-cli https://github.com/webpack/webpack-cli
const config = require('./webpack.config.js');
module.exports = () => {
const cfg = config({
NODE: true,
WEB: false,
});
cfg.output.filename = 'libp2p-wasm.web.js';
cfg.target = 'web';
return cfg;
};

94
libp2p-wasm/src/lib.rs Normal file
View File

@ -0,0 +1,94 @@
use std::str::FromStr;
use std::time::Duration;
use wasm_bindgen::prelude::wasm_bindgen;
use wasm_bindgen_futures::{spawn_local, JsFuture};
use libp2p::core::either::EitherTransport;
use libp2p::core::muxing::StreamMuxerBox;
use libp2p::core::transport;
use libp2p::core::upgrade::Version;
use libp2p::futures::select;
use libp2p::futures::StreamExt;
use libp2p::identify::{Identify, IdentifyConfig, IdentifyEvent};
use libp2p::mplex::MplexConfig;
use libp2p::swarm::NetworkBehaviourEventProcess;
pub use libp2p::wasm_ext::ffi::websocket_transport;
pub use libp2p::wasm_ext::ffi::{Connection, ConnectionEvent, ListenEvent};
use libp2p::wasm_ext::ExtTransport;
use libp2p::yamux::YamuxConfig;
use libp2p::{identity, noise, Multiaddr, NetworkBehaviour, PeerId, Swarm, Transport};
use libp2p::swarm::SwarmEvent;
use wasm_bindgen::throw_str;
pub const PROTOCOL_NAME: &'static str = "/fluence/particle/2.0.0";
#[wasm_bindgen]
pub fn test() {
console_error_panic_hook::set_once();
spawn_local(async move {
// Create a Swarm to manage peers and events
// Create a random PeerId
let local_key = identity::Keypair::generate_ed25519();
let local_peer_id = PeerId::from(local_key.public());
println!("using random peer id: {:?}", local_peer_id);
let transport = build_transport(local_key.clone());
let mut swarm = {
let mut behaviour = MyBehaviour {
identify: Identify::new(IdentifyConfig::new(
PROTOCOL_NAME.into(),
local_key.public(),
)),
};
Swarm::new(transport, behaviour, local_peer_id)
};
let addr = Multiaddr::from_str("/dns4/kras-00.fluence.dev/tcp/19990/wss/p2p/12D3KooWSD5PToNiLQwKDXsu8JSysCwUt8BVUJEqCHcDe7P5h45e")
.unwrap_or_else(|_| panic!("failed to parse multiaddr"));
swarm.dial(addr).unwrap_or_else(|_| panic!("failed to dial"));
wasm_rs_dbg::dbg!("dial succeed");
loop {
select! {
event = swarm.select_next_some() => {
if let SwarmEvent::NewListenAddr { address, .. } = event {
println!("Listening on {:?}", address);
}
}
}
}
})
}
/// Builds the transport that serves as a common ground for all connections.
pub fn build_transport(key_pair: identity::Keypair) -> transport::Boxed<(PeerId, StreamMuxerBox)> {
let noise_keys = noise::Keypair::<noise::X25519Spec>::new()
.into_authentic(&key_pair)
.unwrap();
let noise_config = noise::NoiseConfig::xx(noise_keys).into_authenticated();
let mplex_config = MplexConfig::default();
let ws = ExtTransport::new(websocket_transport());
let base = Transport::boxed(ws);
base.upgrade(Version::V1)
.authenticate(noise_config)
.multiplex(mplex_config)
.timeout(Duration::from_secs(20))
.boxed()
}
#[derive(NetworkBehaviour)]
#[behaviour(event_process = true)]
struct MyBehaviour {
identify: Identify,
}
impl NetworkBehaviourEventProcess<IdentifyEvent> for MyBehaviour {
// Called when `identify` produces an event.
fn inject_event(&mut self, event: IdentifyEvent) {
println!("identify: {:?}", event);
}
}

15
package-lock.json generated
View File

@ -11,6 +11,7 @@
"dependencies": { "dependencies": {
"@chainsafe/libp2p-noise": "^4.1.1", "@chainsafe/libp2p-noise": "^4.1.1",
"@fluencelabs/avm": "0.25.0", "@fluencelabs/avm": "0.25.0",
"@fluencelabs/libp2p-wasm": "file:./libp2p-wasm/pkg",
"@fluencelabs/marine-js": "0.3.5", "@fluencelabs/marine-js": "0.3.5",
"async": "3.2.3", "async": "3.2.3",
"browser-or-node": "^2.0.0", "browser-or-node": "^2.0.0",
@ -49,6 +50,13 @@
"typescript": "^4.6.4" "typescript": "^4.6.4"
} }
}, },
"../../../../libp2p-wasm/pkg": {
"extraneous": true
},
"libp2p-wasm/pkg": {
"name": "libp2p-wasm",
"version": "0.1.0"
},
"node_modules/@ampproject/remapping": { "node_modules/@ampproject/remapping": {
"version": "2.2.0", "version": "2.2.0",
"resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz",
@ -2292,6 +2300,10 @@
"node": ">=10" "node": ">=10"
} }
}, },
"node_modules/@fluencelabs/libp2p-wasm": {
"resolved": "libp2p-wasm/pkg",
"link": true
},
"node_modules/@fluencelabs/marine-js": { "node_modules/@fluencelabs/marine-js": {
"version": "0.3.5", "version": "0.3.5",
"resolved": "https://registry.npmjs.org/@fluencelabs/marine-js/-/marine-js-0.3.5.tgz", "resolved": "https://registry.npmjs.org/@fluencelabs/marine-js/-/marine-js-0.3.5.tgz",
@ -12446,6 +12458,9 @@
"integrity": "sha512-2pci3T0sUHE08jwEs1r/vHKVT4XUh/A3j/QJ0eIhddsxyIjEksjdn05X7DF6STD14CF8GgBVOJEPgav8qaUMpA==", "integrity": "sha512-2pci3T0sUHE08jwEs1r/vHKVT4XUh/A3j/QJ0eIhddsxyIjEksjdn05X7DF6STD14CF8GgBVOJEPgav8qaUMpA==",
"dev": true "dev": true
}, },
"@fluencelabs/libp2p-wasm": {
"version": "file:libp2p-wasm/pkg"
},
"@fluencelabs/marine-js": { "@fluencelabs/marine-js": {
"version": "0.3.5", "version": "0.3.5",
"resolved": "https://registry.npmjs.org/@fluencelabs/marine-js/-/marine-js-0.3.5.tgz", "resolved": "https://registry.npmjs.org/@fluencelabs/marine-js/-/marine-js-0.3.5.tgz",

View File

@ -29,6 +29,7 @@ import { Multiaddr } from 'multiaddr';
import { all as allow_all } from 'libp2p-websockets/src/filters'; import { all as allow_all } from 'libp2p-websockets/src/filters';
import { Connection } from 'libp2p-interfaces/src/topology'; import { Connection } from 'libp2p-interfaces/src/topology';
import Buffer from './Buffer'; import Buffer from './Buffer';
import {test, initSync} from '../../libp2p-wasm/npm-package'
export const PROTOCOL_NAME = '/fluence/particle/2.0.0'; export const PROTOCOL_NAME = '/fluence/particle/2.0.0';
@ -63,6 +64,10 @@ export class FluenceConnection {
private _connection?: Connection; private _connection?: Connection;
static async createConnection(options: FluenceConnectionOptions): Promise<FluenceConnection> { static async createConnection(options: FluenceConnectionOptions): Promise<FluenceConnection> {
let fs = require('fs')
let data = fs.readFileSync("libp2p-wasm/pkg/libp2p_wasm_bg.wasm")
initSync(data);
test();
const transportKey = Websockets.prototype[Symbol.toStringTag]; const transportKey = Websockets.prototype[Symbol.toStringTag];
const lib2p2Peer = await Lib2p2Peer.create({ const lib2p2Peer = await Lib2p2Peer.create({
peerId: options.peerId, peerId: options.peerId,