smoldot 1.0.4 → 1.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +58 -0
- package/dist/cjs/bytecode-browser.d.ts +5 -0
- package/dist/cjs/bytecode-browser.js +42 -0
- package/dist/cjs/bytecode-deno.d.ts +5 -0
- package/dist/cjs/bytecode-deno.js +87 -0
- package/dist/cjs/bytecode-nodejs.d.ts +5 -0
- package/dist/cjs/bytecode-nodejs.js +41 -0
- package/dist/cjs/index-browser.d.ts +2 -2
- package/dist/cjs/index-browser.js +10 -507
- package/dist/cjs/index-deno.d.ts +2 -2
- package/dist/cjs/index-deno.js +10 -283
- package/dist/cjs/index-nodejs.d.ts +2 -2
- package/dist/cjs/index-nodejs.js +10 -211
- package/dist/cjs/internals/bytecode/wasm0.js +4 -0
- package/dist/cjs/internals/bytecode/wasm1.js +4 -0
- package/dist/cjs/internals/bytecode/wasm2.js +4 -0
- package/dist/cjs/{instance/bindings-smoldot-light.d.ts → internals/client.d.ts} +15 -34
- package/dist/cjs/internals/client.js +376 -0
- package/dist/cjs/internals/local-instance.d.ts +144 -0
- package/dist/cjs/internals/local-instance.js +566 -0
- package/dist/cjs/internals/remote-instance.d.ts +38 -0
- package/dist/cjs/internals/remote-instance.js +374 -0
- package/dist/cjs/no-auto-bytecode-browser.d.ts +11 -0
- package/dist/cjs/no-auto-bytecode-browser.js +481 -0
- package/dist/cjs/no-auto-bytecode-deno.d.ts +10 -0
- package/dist/cjs/no-auto-bytecode-deno.js +220 -0
- package/dist/cjs/no-auto-bytecode-nodejs.d.ts +10 -0
- package/dist/cjs/no-auto-bytecode-nodejs.js +189 -0
- package/dist/cjs/{client.d.ts → public-types.d.ts} +51 -3
- package/dist/cjs/public-types.js +76 -0
- package/dist/cjs/worker-browser.d.ts +11 -0
- package/dist/cjs/worker-browser.js +63 -0
- package/dist/cjs/worker-deno.d.ts +11 -0
- package/dist/cjs/worker-deno.js +54 -0
- package/dist/cjs/worker-nodejs.d.ts +11 -0
- package/dist/cjs/worker-nodejs.js +55 -0
- package/dist/mjs/bytecode-browser.d.ts +5 -0
- package/dist/mjs/bytecode-browser.js +38 -0
- package/dist/mjs/bytecode-deno.d.ts +5 -0
- package/dist/mjs/bytecode-deno.js +83 -0
- package/dist/mjs/bytecode-nodejs.d.ts +5 -0
- package/dist/mjs/bytecode-nodejs.js +37 -0
- package/dist/mjs/index-browser.d.ts +2 -2
- package/dist/mjs/index-browser.js +4 -501
- package/dist/mjs/index-deno.d.ts +2 -2
- package/dist/mjs/index-deno.js +4 -277
- package/dist/mjs/index-nodejs.d.ts +2 -2
- package/dist/mjs/index-nodejs.js +4 -205
- package/dist/mjs/internals/bytecode/wasm0.js +1 -0
- package/dist/mjs/internals/bytecode/wasm1.js +1 -0
- package/dist/mjs/internals/bytecode/wasm2.js +1 -0
- package/dist/mjs/{instance/bindings-smoldot-light.d.ts → internals/client.d.ts} +15 -34
- package/dist/mjs/internals/client.js +372 -0
- package/dist/mjs/internals/local-instance.d.ts +144 -0
- package/dist/mjs/internals/local-instance.js +561 -0
- package/dist/mjs/internals/remote-instance.d.ts +38 -0
- package/dist/mjs/internals/remote-instance.js +369 -0
- package/dist/mjs/no-auto-bytecode-browser.d.ts +11 -0
- package/dist/mjs/no-auto-bytecode-browser.js +471 -0
- package/dist/mjs/no-auto-bytecode-deno.d.ts +10 -0
- package/dist/mjs/no-auto-bytecode-deno.js +210 -0
- package/dist/mjs/no-auto-bytecode-nodejs.d.ts +10 -0
- package/dist/mjs/no-auto-bytecode-nodejs.js +179 -0
- package/dist/mjs/{client.d.ts → public-types.d.ts} +51 -3
- package/dist/mjs/public-types.js +67 -0
- package/dist/mjs/worker-browser.d.ts +11 -0
- package/dist/mjs/worker-browser.js +59 -0
- package/dist/mjs/worker-deno.d.ts +11 -0
- package/dist/mjs/worker-deno.js +50 -0
- package/dist/mjs/worker-nodejs.d.ts +11 -0
- package/dist/mjs/worker-nodejs.js +51 -0
- package/package.json +40 -8
- package/dist/cjs/client.js +0 -172
- package/dist/cjs/instance/autogen/wasm0.js +0 -4
- package/dist/cjs/instance/autogen/wasm1.js +0 -4
- package/dist/cjs/instance/autogen/wasm2.js +0 -4
- package/dist/cjs/instance/bindings-smoldot-light.js +0 -285
- package/dist/cjs/instance/bindings-wasi.d.ts +0 -27
- package/dist/cjs/instance/bindings-wasi.js +0 -172
- package/dist/cjs/instance/bindings.d.ts +0 -31
- package/dist/cjs/instance/bindings.js +0 -5
- package/dist/cjs/instance/instance.d.ts +0 -45
- package/dist/cjs/instance/instance.js +0 -277
- package/dist/cjs/instance/raw-instance.d.ts +0 -56
- package/dist/cjs/instance/raw-instance.js +0 -129
- package/dist/mjs/client.js +0 -162
- package/dist/mjs/instance/autogen/wasm0.js +0 -1
- package/dist/mjs/instance/autogen/wasm1.js +0 -1
- package/dist/mjs/instance/autogen/wasm2.js +0 -1
- package/dist/mjs/instance/bindings-smoldot-light.js +0 -280
- package/dist/mjs/instance/bindings-wasi.d.ts +0 -27
- package/dist/mjs/instance/bindings-wasi.js +0 -170
- package/dist/mjs/instance/bindings.d.ts +0 -31
- package/dist/mjs/instance/bindings.js +0 -4
- package/dist/mjs/instance/instance.d.ts +0 -45
- package/dist/mjs/instance/instance.js +0 -269
- package/dist/mjs/instance/raw-instance.d.ts +0 -56
- package/dist/mjs/instance/raw-instance.js +0 -124
- /package/dist/cjs/{base64.d.ts → internals/base64.d.ts} +0 -0
- /package/dist/cjs/{base64.js → internals/base64.js} +0 -0
- /package/dist/cjs/{instance → internals}/buffer.d.ts +0 -0
- /package/dist/cjs/{instance → internals}/buffer.js +0 -0
- /package/dist/cjs/{instance/autogen → internals/bytecode}/wasm.d.ts +0 -0
- /package/dist/cjs/{instance/autogen → internals/bytecode}/wasm.js +0 -0
- /package/dist/cjs/{instance/autogen → internals/bytecode}/wasm0.d.ts +0 -0
- /package/dist/cjs/{instance/autogen → internals/bytecode}/wasm1.d.ts +0 -0
- /package/dist/cjs/{instance/autogen → internals/bytecode}/wasm2.d.ts +0 -0
- /package/dist/mjs/{base64.d.ts → internals/base64.d.ts} +0 -0
- /package/dist/mjs/{base64.js → internals/base64.js} +0 -0
- /package/dist/mjs/{instance → internals}/buffer.d.ts +0 -0
- /package/dist/mjs/{instance → internals}/buffer.js +0 -0
- /package/dist/mjs/{instance/autogen → internals/bytecode}/wasm.d.ts +0 -0
- /package/dist/mjs/{instance/autogen → internals/bytecode}/wasm.js +0 -0
- /package/dist/mjs/{instance/autogen → internals/bytecode}/wasm0.d.ts +0 -0
- /package/dist/mjs/{instance/autogen → internals/bytecode}/wasm1.d.ts +0 -0
- /package/dist/mjs/{instance/autogen → internals/bytecode}/wasm2.d.ts +0 -0
|
@@ -1,277 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
// Smoldot
|
|
3
|
-
// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd.
|
|
4
|
-
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
|
|
5
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
6
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
7
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
8
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
9
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
10
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
11
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
12
|
-
});
|
|
13
|
-
};
|
|
14
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
-
exports.start = exports.QueueFullError = exports.MalformedJsonRpcError = exports.CrashError = exports.ConnectionError = void 0;
|
|
16
|
-
// This program is free software: you can redistribute it and/or modify
|
|
17
|
-
// it under the terms of the GNU General Public License as published by
|
|
18
|
-
// the Free Software Foundation, either version 3 of the License, or
|
|
19
|
-
// (at your option) any later version.
|
|
20
|
-
// This program is distributed in the hope that it will be useful,
|
|
21
|
-
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
22
|
-
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
23
|
-
// GNU General Public License for more details.
|
|
24
|
-
// You should have received a copy of the GNU General Public License
|
|
25
|
-
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
26
|
-
const buffer = require("./buffer.js");
|
|
27
|
-
const instance = require("./raw-instance.js");
|
|
28
|
-
const client_js_1 = require("../client.js");
|
|
29
|
-
var raw_instance_js_1 = require("./raw-instance.js");
|
|
30
|
-
Object.defineProperty(exports, "ConnectionError", { enumerable: true, get: function () { return raw_instance_js_1.ConnectionError; } });
|
|
31
|
-
/**
|
|
32
|
-
* Thrown in case the underlying client encounters an unexpected crash.
|
|
33
|
-
*
|
|
34
|
-
* This is always an internal bug in smoldot and is never supposed to happen.
|
|
35
|
-
*/
|
|
36
|
-
class CrashError extends Error {
|
|
37
|
-
constructor(message) {
|
|
38
|
-
super(message);
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
exports.CrashError = CrashError;
|
|
42
|
-
/**
|
|
43
|
-
* Thrown in case a malformed JSON-RPC request is sent.
|
|
44
|
-
*/
|
|
45
|
-
class MalformedJsonRpcError extends Error {
|
|
46
|
-
constructor() {
|
|
47
|
-
super("JSON-RPC request is malformed");
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
exports.MalformedJsonRpcError = MalformedJsonRpcError;
|
|
51
|
-
/**
|
|
52
|
-
* Thrown in case the buffer of JSON-RPC requests is full and cannot accept any more request.
|
|
53
|
-
*/
|
|
54
|
-
class QueueFullError extends Error {
|
|
55
|
-
constructor() {
|
|
56
|
-
super("JSON-RPC requests queue is full");
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
exports.QueueFullError = QueueFullError;
|
|
60
|
-
function start(configMessage, platformBindings) {
|
|
61
|
-
// This variable represents the state of the instance, and serves two different purposes:
|
|
62
|
-
//
|
|
63
|
-
// - At initialization, it is a Promise containing the Wasm VM is still initializing.
|
|
64
|
-
// - After the Wasm VM has finished initialization, contains the `WebAssembly.Instance` object.
|
|
65
|
-
//
|
|
66
|
-
let state;
|
|
67
|
-
const crashError = {};
|
|
68
|
-
const currentTask = { name: null };
|
|
69
|
-
const printError = { printError: true };
|
|
70
|
-
// Contains the information of each chain that is currently alive.
|
|
71
|
-
let chains = new Map();
|
|
72
|
-
const initPromise = (() => __awaiter(this, void 0, void 0, function* () {
|
|
73
|
-
const module = yield configMessage.wasmModule;
|
|
74
|
-
// Start initialization of the Wasm VM.
|
|
75
|
-
const config = {
|
|
76
|
-
onWasmPanic: (message) => {
|
|
77
|
-
// TODO: consider obtaining a backtrace here
|
|
78
|
-
crashError.error = new CrashError(message);
|
|
79
|
-
if (!printError.printError)
|
|
80
|
-
return;
|
|
81
|
-
console.error("Smoldot has panicked" +
|
|
82
|
-
(currentTask.name ? (" while executing task `" + currentTask.name + "`") : "") +
|
|
83
|
-
". This is a bug in smoldot. Please open an issue at " +
|
|
84
|
-
"https://github.com/smol-dot/smoldot/issues with the following message:\n" +
|
|
85
|
-
message);
|
|
86
|
-
for (const chain of Array.from(chains.values())) {
|
|
87
|
-
for (const promise of chain.jsonRpcResponsesPromises) {
|
|
88
|
-
promise.reject(crashError.error);
|
|
89
|
-
}
|
|
90
|
-
chain.jsonRpcResponsesPromises = [];
|
|
91
|
-
}
|
|
92
|
-
},
|
|
93
|
-
logCallback: (level, target, message) => {
|
|
94
|
-
configMessage.logCallback(level, target, message);
|
|
95
|
-
},
|
|
96
|
-
wasmModule: module,
|
|
97
|
-
jsonRpcResponsesNonEmptyCallback: (chainId) => {
|
|
98
|
-
// Notify every single promise found in `jsonRpcResponsesPromises`.
|
|
99
|
-
const promises = chains.get(chainId).jsonRpcResponsesPromises;
|
|
100
|
-
while (promises.length !== 0) {
|
|
101
|
-
promises.shift().resolve();
|
|
102
|
-
}
|
|
103
|
-
},
|
|
104
|
-
currentTaskCallback: (taskName) => {
|
|
105
|
-
currentTask.name = taskName;
|
|
106
|
-
},
|
|
107
|
-
cpuRateLimit: configMessage.cpuRateLimit,
|
|
108
|
-
maxLogLevel: configMessage.maxLogLevel,
|
|
109
|
-
};
|
|
110
|
-
return yield instance.startInstance(config, platformBindings);
|
|
111
|
-
}))();
|
|
112
|
-
state = {
|
|
113
|
-
initialized: false, promise: initPromise.then(([instance, bufferIndices]) => {
|
|
114
|
-
state = { initialized: true, instance, bufferIndices };
|
|
115
|
-
return [instance, bufferIndices];
|
|
116
|
-
})
|
|
117
|
-
};
|
|
118
|
-
function queueOperation(operation) {
|
|
119
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
120
|
-
// What to do depends on the type of `state`.
|
|
121
|
-
// See the documentation of the `state` variable for information.
|
|
122
|
-
if (!state.initialized) {
|
|
123
|
-
// A message has been received while the Wasm VM is still initializing. Queue it for when
|
|
124
|
-
// initialization is over.
|
|
125
|
-
return state.promise.then(([instance, bufferIndices]) => operation(instance, bufferIndices));
|
|
126
|
-
}
|
|
127
|
-
else {
|
|
128
|
-
// Everything is already initialized. Process the message synchronously.
|
|
129
|
-
return operation(state.instance, state.bufferIndices);
|
|
130
|
-
}
|
|
131
|
-
});
|
|
132
|
-
}
|
|
133
|
-
return {
|
|
134
|
-
request: (request, chainId) => {
|
|
135
|
-
// Because `request` is passed as parameter an identifier returned by `addChain`, it is
|
|
136
|
-
// always the case that the Wasm instance is already initialized. The only possibility for
|
|
137
|
-
// it to not be the case is if the user completely invented the `chainId`.
|
|
138
|
-
if (!state.initialized)
|
|
139
|
-
throw new Error("Internal error");
|
|
140
|
-
if (crashError.error)
|
|
141
|
-
throw crashError.error;
|
|
142
|
-
let retVal;
|
|
143
|
-
try {
|
|
144
|
-
state.bufferIndices[0] = new TextEncoder().encode(request);
|
|
145
|
-
retVal = state.instance.exports.json_rpc_send(0, chainId) >>> 0;
|
|
146
|
-
}
|
|
147
|
-
catch (_error) {
|
|
148
|
-
console.assert(crashError.error);
|
|
149
|
-
throw crashError.error;
|
|
150
|
-
}
|
|
151
|
-
switch (retVal) {
|
|
152
|
-
case 0: break;
|
|
153
|
-
case 1: throw new MalformedJsonRpcError();
|
|
154
|
-
case 2: throw new QueueFullError();
|
|
155
|
-
default: throw new Error("Internal error: unknown json_rpc_send error code: " + retVal);
|
|
156
|
-
}
|
|
157
|
-
},
|
|
158
|
-
nextJsonRpcResponse: (chainId) => __awaiter(this, void 0, void 0, function* () {
|
|
159
|
-
// Because `nextJsonRpcResponse` is passed as parameter an identifier returned by `addChain`,
|
|
160
|
-
// it is always the case that the Wasm instance is already initialized. The only possibility
|
|
161
|
-
// for it to not be the case is if the user completely invented the `chainId`.
|
|
162
|
-
if (!state.initialized)
|
|
163
|
-
throw new Error("Internal error");
|
|
164
|
-
while (true) {
|
|
165
|
-
if (crashError.error)
|
|
166
|
-
throw crashError.error;
|
|
167
|
-
// Try to pop a message from the queue.
|
|
168
|
-
try {
|
|
169
|
-
const mem = new Uint8Array(state.instance.exports.memory.buffer);
|
|
170
|
-
const responseInfo = state.instance.exports.json_rpc_responses_peek(chainId) >>> 0;
|
|
171
|
-
const ptr = buffer.readUInt32LE(mem, responseInfo) >>> 0;
|
|
172
|
-
const len = buffer.readUInt32LE(mem, responseInfo + 4) >>> 0;
|
|
173
|
-
// `len === 0` means "queue is empty" according to the API.
|
|
174
|
-
// In that situation, queue the resolve/reject.
|
|
175
|
-
if (len !== 0) {
|
|
176
|
-
const message = buffer.utf8BytesToString(mem, ptr, len);
|
|
177
|
-
state.instance.exports.json_rpc_responses_pop(chainId);
|
|
178
|
-
return message;
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
catch (_error) {
|
|
182
|
-
console.assert(crashError.error);
|
|
183
|
-
throw crashError.error;
|
|
184
|
-
}
|
|
185
|
-
// If no message is available, wait for one to be.
|
|
186
|
-
yield new Promise((resolve, reject) => {
|
|
187
|
-
chains.get(chainId).jsonRpcResponsesPromises.push({ resolve: () => resolve(undefined), reject });
|
|
188
|
-
});
|
|
189
|
-
}
|
|
190
|
-
}),
|
|
191
|
-
addChain: (chainSpec, databaseContent, potentialRelayChains, disableJsonRpc) => {
|
|
192
|
-
return queueOperation((instance, bufferIndices) => {
|
|
193
|
-
if (crashError.error)
|
|
194
|
-
throw crashError.error;
|
|
195
|
-
try {
|
|
196
|
-
// `add_chain` unconditionally allocates a chain id. If an error occurs, however, this chain
|
|
197
|
-
// id will refer to an *erroneous* chain. `chain_is_ok` is used below to determine whether it
|
|
198
|
-
// has succeeeded or not.
|
|
199
|
-
// Note that `add_chain` properly de-allocates buffers even if it failed.
|
|
200
|
-
bufferIndices[0] = new TextEncoder().encode(chainSpec);
|
|
201
|
-
bufferIndices[1] = new TextEncoder().encode(databaseContent);
|
|
202
|
-
const potentialRelayChainsEncoded = new Uint8Array(potentialRelayChains.length * 4);
|
|
203
|
-
for (let idx = 0; idx < potentialRelayChains.length; ++idx) {
|
|
204
|
-
buffer.writeUInt32LE(potentialRelayChainsEncoded, idx * 4, potentialRelayChains[idx]);
|
|
205
|
-
}
|
|
206
|
-
bufferIndices[2] = potentialRelayChainsEncoded;
|
|
207
|
-
const chainId = instance.exports.add_chain(0, 1, disableJsonRpc ? 0 : 1, 2);
|
|
208
|
-
delete bufferIndices[0];
|
|
209
|
-
delete bufferIndices[1];
|
|
210
|
-
delete bufferIndices[2];
|
|
211
|
-
if (instance.exports.chain_is_ok(chainId) != 0) {
|
|
212
|
-
console.assert(!chains.has(chainId));
|
|
213
|
-
chains.set(chainId, {
|
|
214
|
-
jsonRpcResponsesPromises: new Array()
|
|
215
|
-
});
|
|
216
|
-
return { success: true, chainId };
|
|
217
|
-
}
|
|
218
|
-
else {
|
|
219
|
-
const errorMsgLen = instance.exports.chain_error_len(chainId) >>> 0;
|
|
220
|
-
const errorMsgPtr = instance.exports.chain_error_ptr(chainId) >>> 0;
|
|
221
|
-
const errorMsg = buffer.utf8BytesToString(new Uint8Array(instance.exports.memory.buffer), errorMsgPtr, errorMsgLen);
|
|
222
|
-
instance.exports.remove_chain(chainId);
|
|
223
|
-
return { success: false, error: errorMsg };
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
catch (_error) {
|
|
227
|
-
console.assert(crashError.error);
|
|
228
|
-
throw crashError.error;
|
|
229
|
-
}
|
|
230
|
-
});
|
|
231
|
-
},
|
|
232
|
-
removeChain: (chainId) => {
|
|
233
|
-
// Because `removeChain` is passed as parameter an identifier returned by `addChain`, it is
|
|
234
|
-
// always the case that the Wasm instance is already initialized. The only possibility for
|
|
235
|
-
// it to not be the case is if the user completely invented the `chainId`.
|
|
236
|
-
if (!state.initialized)
|
|
237
|
-
throw new Error("Internal error");
|
|
238
|
-
if (crashError.error)
|
|
239
|
-
throw crashError.error;
|
|
240
|
-
// Removing the chain synchronously avoids having to deal with race conditions such as a
|
|
241
|
-
// JSON-RPC response corresponding to a chain that is going to be deleted but hasn't been yet.
|
|
242
|
-
// These kind of race conditions are already delt with within smoldot.
|
|
243
|
-
console.assert(chains.has(chainId));
|
|
244
|
-
for (const { reject } of chains.get(chainId).jsonRpcResponsesPromises) {
|
|
245
|
-
reject(new client_js_1.AlreadyDestroyedError());
|
|
246
|
-
}
|
|
247
|
-
chains.delete(chainId);
|
|
248
|
-
try {
|
|
249
|
-
state.instance.exports.remove_chain(chainId);
|
|
250
|
-
}
|
|
251
|
-
catch (_error) {
|
|
252
|
-
console.assert(crashError.error);
|
|
253
|
-
throw crashError.error;
|
|
254
|
-
}
|
|
255
|
-
},
|
|
256
|
-
startShutdown: () => {
|
|
257
|
-
return queueOperation((instance) => {
|
|
258
|
-
// `startShutdown` is a bit special in its handling of crashes.
|
|
259
|
-
// Shutting down will lead to `onWasmPanic` being called at some point, possibly during
|
|
260
|
-
// the call to `start_shutdown` itself. As such, we move into "don't print errors anymore"
|
|
261
|
-
// mode even before calling `start_shutdown`.
|
|
262
|
-
//
|
|
263
|
-
// Furthermore, if a crash happened in the past, there is no point in throwing an
|
|
264
|
-
// exception when the user wants the shutdown to happen.
|
|
265
|
-
if (crashError.error)
|
|
266
|
-
return;
|
|
267
|
-
try {
|
|
268
|
-
printError.printError = false;
|
|
269
|
-
instance.exports.start_shutdown();
|
|
270
|
-
}
|
|
271
|
-
catch (_error) {
|
|
272
|
-
}
|
|
273
|
-
});
|
|
274
|
-
}
|
|
275
|
-
};
|
|
276
|
-
}
|
|
277
|
-
exports.start = start;
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import { ConnectionConfig, Connection } from './bindings-smoldot-light.js';
|
|
2
|
-
import { SmoldotWasmInstance } from './bindings.js';
|
|
3
|
-
export { ConnectionConfig, ConnectionError, Connection } from './bindings-smoldot-light.js';
|
|
4
|
-
export interface Config {
|
|
5
|
-
/**
|
|
6
|
-
* Closure to call when the Wasm instance panics.
|
|
7
|
-
*
|
|
8
|
-
* This callback will always be invoked from within a binding called the Wasm instance.
|
|
9
|
-
*
|
|
10
|
-
* After this callback has been called, it is forbidden to invoke any function from the Wasm
|
|
11
|
-
* VM.
|
|
12
|
-
*
|
|
13
|
-
* If this callback is called while invoking a function from the Wasm VM, this function will
|
|
14
|
-
* throw a dummy exception.
|
|
15
|
-
*/
|
|
16
|
-
onWasmPanic: (message: string) => void;
|
|
17
|
-
logCallback: (level: number, target: string, message: string) => void;
|
|
18
|
-
wasmModule: WebAssembly.Module;
|
|
19
|
-
jsonRpcResponsesNonEmptyCallback: (chainId: number) => void;
|
|
20
|
-
currentTaskCallback?: (taskName: string | null) => void;
|
|
21
|
-
maxLogLevel: number;
|
|
22
|
-
cpuRateLimit: number;
|
|
23
|
-
}
|
|
24
|
-
/**
|
|
25
|
-
* Contains functions that the client will use when it needs to leverage the platform.
|
|
26
|
-
*/
|
|
27
|
-
export interface PlatformBindings {
|
|
28
|
-
/**
|
|
29
|
-
* Returns the number of milliseconds since an arbitrary epoch.
|
|
30
|
-
*/
|
|
31
|
-
performanceNow: () => number;
|
|
32
|
-
/**
|
|
33
|
-
* Fills the given buffer with randomly-generated bytes.
|
|
34
|
-
*/
|
|
35
|
-
getRandomValues: (buffer: Uint8Array) => void;
|
|
36
|
-
/**
|
|
37
|
-
* The "should periodically yield" setting indicates whether the execution should periodically
|
|
38
|
-
* yield back control by using `setTimeout(..., 0)`.
|
|
39
|
-
*
|
|
40
|
-
* On platforms such as browsers where `setTimeout(..., 0)` takes way more than 0 milliseconds,
|
|
41
|
-
* this setting should be set to `false`.
|
|
42
|
-
*
|
|
43
|
-
* This function registers a callback that is called when the setting should be updated with
|
|
44
|
-
* a new value. It returns the initial value of the setting and a function used to unregister
|
|
45
|
-
* the callback.
|
|
46
|
-
*/
|
|
47
|
-
registerShouldPeriodicallyYield: (callback: (newValue: boolean) => void) => [boolean, () => void];
|
|
48
|
-
/**
|
|
49
|
-
* Tries to open a new connection using the given configuration.
|
|
50
|
-
*
|
|
51
|
-
* @see Connection
|
|
52
|
-
* @throws {@link ConnectionError} If the multiaddress couldn't be parsed or contains an invalid protocol.
|
|
53
|
-
*/
|
|
54
|
-
connect(config: ConnectionConfig): Connection;
|
|
55
|
-
}
|
|
56
|
-
export declare function startInstance(config: Config, platformBindings: PlatformBindings): Promise<[SmoldotWasmInstance, Array<Uint8Array>]>;
|
|
@@ -1,129 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
// Smoldot
|
|
3
|
-
// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd.
|
|
4
|
-
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
|
|
5
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
6
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
7
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
8
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
9
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
10
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
11
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
12
|
-
});
|
|
13
|
-
};
|
|
14
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
-
exports.startInstance = exports.ConnectionError = void 0;
|
|
16
|
-
// This program is free software: you can redistribute it and/or modify
|
|
17
|
-
// it under the terms of the GNU General Public License as published by
|
|
18
|
-
// the Free Software Foundation, either version 3 of the License, or
|
|
19
|
-
// (at your option) any later version.
|
|
20
|
-
// This program is distributed in the hope that it will be useful,
|
|
21
|
-
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
22
|
-
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
23
|
-
// GNU General Public License for more details.
|
|
24
|
-
// You should have received a copy of the GNU General Public License
|
|
25
|
-
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
26
|
-
const bindings_smoldot_light_js_1 = require("./bindings-smoldot-light.js");
|
|
27
|
-
const bindings_wasi_js_1 = require("./bindings-wasi.js");
|
|
28
|
-
var bindings_smoldot_light_js_2 = require("./bindings-smoldot-light.js");
|
|
29
|
-
Object.defineProperty(exports, "ConnectionError", { enumerable: true, get: function () { return bindings_smoldot_light_js_2.ConnectionError; } });
|
|
30
|
-
function startInstance(config, platformBindings) {
|
|
31
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
32
|
-
let killAll;
|
|
33
|
-
const bufferIndices = new Array;
|
|
34
|
-
// Callback called when `advance_execution_ready` is called by the Rust code, if any.
|
|
35
|
-
const advanceExecutionPromise = { value: null };
|
|
36
|
-
// Used to bind with the smoldot-light bindings. See the `bindings-smoldot-light.js` file.
|
|
37
|
-
const smoldotJsConfig = Object.assign({ bufferIndices, connect: platformBindings.connect, onPanic: (message) => {
|
|
38
|
-
killAll();
|
|
39
|
-
config.onWasmPanic(message);
|
|
40
|
-
throw new Error();
|
|
41
|
-
}, advanceExecutionReadyCallback: () => {
|
|
42
|
-
if (advanceExecutionPromise.value)
|
|
43
|
-
advanceExecutionPromise.value();
|
|
44
|
-
advanceExecutionPromise.value = null;
|
|
45
|
-
} }, config);
|
|
46
|
-
// Used to bind with the Wasi bindings. See the `bindings-wasi.js` file.
|
|
47
|
-
const wasiConfig = {
|
|
48
|
-
envVars: [],
|
|
49
|
-
getRandomValues: platformBindings.getRandomValues,
|
|
50
|
-
performanceNow: platformBindings.performanceNow,
|
|
51
|
-
onProcExit: (retCode) => {
|
|
52
|
-
killAll();
|
|
53
|
-
config.onWasmPanic(`proc_exit called: ${retCode}`);
|
|
54
|
-
throw new Error();
|
|
55
|
-
}
|
|
56
|
-
};
|
|
57
|
-
const { imports: smoldotBindings, killAll: smoldotBindingsKillAll } = (0, bindings_smoldot_light_js_1.default)(smoldotJsConfig);
|
|
58
|
-
killAll = smoldotBindingsKillAll;
|
|
59
|
-
// Start the Wasm virtual machine.
|
|
60
|
-
// The Rust code defines a list of imports that must be fulfilled by the environment. The second
|
|
61
|
-
// parameter provides their implementations.
|
|
62
|
-
const result = yield WebAssembly.instantiate(config.wasmModule, {
|
|
63
|
-
// The functions with the "smoldot" prefix are specific to smoldot.
|
|
64
|
-
"smoldot": smoldotBindings,
|
|
65
|
-
// As the Rust code is compiled for wasi, some more wasi-specific imports exist.
|
|
66
|
-
"wasi_snapshot_preview1": (0, bindings_wasi_js_1.default)(wasiConfig),
|
|
67
|
-
});
|
|
68
|
-
const instance = result;
|
|
69
|
-
smoldotJsConfig.instance = instance;
|
|
70
|
-
wasiConfig.instance = instance;
|
|
71
|
-
// Smoldot requires an initial call to the `init` function in order to do its internal
|
|
72
|
-
// configuration.
|
|
73
|
-
instance.exports.init(config.maxLogLevel);
|
|
74
|
-
(() => __awaiter(this, void 0, void 0, function* () {
|
|
75
|
-
// In order to avoid calling `setTimeout` too often, we accumulate sleep up until
|
|
76
|
-
// a certain threshold.
|
|
77
|
-
let missingSleep = 0;
|
|
78
|
-
// Extract (to make sure the value doesn't change) and sanitize `cpuRateLimit`.
|
|
79
|
-
let cpuRateLimit = config.cpuRateLimit;
|
|
80
|
-
if (isNaN(cpuRateLimit))
|
|
81
|
-
cpuRateLimit = 1.0;
|
|
82
|
-
if (cpuRateLimit > 1.0)
|
|
83
|
-
cpuRateLimit = 1.0;
|
|
84
|
-
if (cpuRateLimit < 0.0)
|
|
85
|
-
cpuRateLimit = 0.0;
|
|
86
|
-
const periodicallyYield = { value: false };
|
|
87
|
-
const [periodicallyYieldInit, unregisterCallback] = platformBindings.registerShouldPeriodicallyYield((newValue) => {
|
|
88
|
-
periodicallyYield.value = newValue;
|
|
89
|
-
});
|
|
90
|
-
periodicallyYield.value = periodicallyYieldInit;
|
|
91
|
-
let now = platformBindings.performanceNow();
|
|
92
|
-
while (true) {
|
|
93
|
-
const whenReadyAgain = new Promise((resolve) => advanceExecutionPromise.value = resolve);
|
|
94
|
-
const outcome = instance.exports.advance_execution();
|
|
95
|
-
if (outcome === 0) {
|
|
96
|
-
unregisterCallback();
|
|
97
|
-
break;
|
|
98
|
-
}
|
|
99
|
-
const afterExec = platformBindings.performanceNow();
|
|
100
|
-
const elapsed = afterExec - now;
|
|
101
|
-
now = afterExec;
|
|
102
|
-
// In order to enforce the rate limiting, we stop executing for a certain
|
|
103
|
-
// amount of time.
|
|
104
|
-
// The base equation here is: `(sleep + elapsed) * rateLimit == elapsed`,
|
|
105
|
-
// from which the calculation below is derived.
|
|
106
|
-
const sleep = elapsed * (1.0 / cpuRateLimit - 1.0);
|
|
107
|
-
missingSleep += sleep;
|
|
108
|
-
if (missingSleep > (periodicallyYield ? 5 : 1000)) {
|
|
109
|
-
// `setTimeout` has a maximum value, after which it will overflow. 🤦
|
|
110
|
-
// See <https://developer.mozilla.org/en-US/docs/Web/API/setTimeout#maximum_delay_value>
|
|
111
|
-
// While adding a cap technically skews the CPU rate limiting algorithm, we don't
|
|
112
|
-
// really care for such extreme values.
|
|
113
|
-
if (missingSleep > 2147483646) // Doc says `> 2147483647`, but I don't really trust their pedanticism so let's be safe
|
|
114
|
-
missingSleep = 2147483646;
|
|
115
|
-
yield new Promise((resolve) => setTimeout(resolve, missingSleep));
|
|
116
|
-
missingSleep = 0;
|
|
117
|
-
}
|
|
118
|
-
yield whenReadyAgain;
|
|
119
|
-
const afterWait = platformBindings.performanceNow();
|
|
120
|
-
missingSleep -= (afterWait - now);
|
|
121
|
-
if (missingSleep < 0)
|
|
122
|
-
missingSleep = 0;
|
|
123
|
-
now = afterWait;
|
|
124
|
-
}
|
|
125
|
-
}))();
|
|
126
|
-
return [instance, bufferIndices];
|
|
127
|
-
});
|
|
128
|
-
}
|
|
129
|
-
exports.startInstance = startInstance;
|
package/dist/mjs/client.js
DELETED
|
@@ -1,162 +0,0 @@
|
|
|
1
|
-
// Smoldot
|
|
2
|
-
// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd.
|
|
3
|
-
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
|
|
4
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
5
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
6
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
7
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
8
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
9
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
10
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
11
|
-
});
|
|
12
|
-
};
|
|
13
|
-
// This program is free software: you can redistribute it and/or modify
|
|
14
|
-
// it under the terms of the GNU General Public License as published by
|
|
15
|
-
// the Free Software Foundation, either version 3 of the License, or
|
|
16
|
-
// (at your option) any later version.
|
|
17
|
-
// This program is distributed in the hope that it will be useful,
|
|
18
|
-
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
19
|
-
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
20
|
-
// GNU General Public License for more details.
|
|
21
|
-
// You should have received a copy of the GNU General Public License
|
|
22
|
-
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
23
|
-
import { MalformedJsonRpcError, start as startInstance } from './instance/instance.js';
|
|
24
|
-
export { MalformedJsonRpcError, QueueFullError, CrashError } from './instance/instance.js';
|
|
25
|
-
/**
|
|
26
|
-
* Thrown in case of a problem when initializing the chain.
|
|
27
|
-
*/
|
|
28
|
-
export class AddChainError extends Error {
|
|
29
|
-
constructor(message) {
|
|
30
|
-
super(message);
|
|
31
|
-
this.name = "AddChainError";
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
/**
|
|
35
|
-
* Thrown in case the API user tries to use a chain or client that has already been destroyed.
|
|
36
|
-
*/
|
|
37
|
-
export class AlreadyDestroyedError extends Error {
|
|
38
|
-
constructor() {
|
|
39
|
-
super();
|
|
40
|
-
this.name = "AlreadyDestroyedError";
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
/**
|
|
44
|
-
* Thrown when trying to send a JSON-RPC message to a chain whose JSON-RPC system hasn't been
|
|
45
|
-
* enabled.
|
|
46
|
-
*/
|
|
47
|
-
export class JsonRpcDisabledError extends Error {
|
|
48
|
-
constructor() {
|
|
49
|
-
super();
|
|
50
|
-
this.name = "JsonRpcDisabledError";
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
// This function is similar to the `start` function found in `index.ts`, except with an extra
|
|
54
|
-
// parameter containing the platform-specific bindings.
|
|
55
|
-
// Contrary to the one within `index.js`, this function is not supposed to be directly used.
|
|
56
|
-
export function start(options, wasmModule, platformBindings) {
|
|
57
|
-
const logCallback = options.logCallback || ((level, target, message) => {
|
|
58
|
-
// The first parameter of the methods of `console` has some printf-like substitution
|
|
59
|
-
// capabilities. We don't really need to use this, but not using it means that the logs might
|
|
60
|
-
// not get printed correctly if they contain `%`.
|
|
61
|
-
if (level <= 1) {
|
|
62
|
-
console.error("[%s] %s", target, message);
|
|
63
|
-
}
|
|
64
|
-
else if (level == 2) {
|
|
65
|
-
console.warn("[%s] %s", target, message);
|
|
66
|
-
}
|
|
67
|
-
else if (level == 3) {
|
|
68
|
-
console.info("[%s] %s", target, message);
|
|
69
|
-
}
|
|
70
|
-
else if (level == 4) {
|
|
71
|
-
console.debug("[%s] %s", target, message);
|
|
72
|
-
}
|
|
73
|
-
else {
|
|
74
|
-
console.trace("[%s] %s", target, message);
|
|
75
|
-
}
|
|
76
|
-
});
|
|
77
|
-
// For each chain object returned by `addChain`, the associated internal chain id.
|
|
78
|
-
//
|
|
79
|
-
// Immediately cleared when `remove()` is called on a chain.
|
|
80
|
-
const chainIds = new WeakMap();
|
|
81
|
-
// If `Client.terminate()̀ is called, this error is set to a value.
|
|
82
|
-
// All the functions of the public API check if this contains a value.
|
|
83
|
-
const alreadyDestroyedError = { value: null };
|
|
84
|
-
const instance = startInstance({
|
|
85
|
-
wasmModule,
|
|
86
|
-
// Maximum level of log entries sent by the client.
|
|
87
|
-
// 0 = Logging disabled, 1 = Error, 2 = Warn, 3 = Info, 4 = Debug, 5 = Trace
|
|
88
|
-
maxLogLevel: options.maxLogLevel || 3,
|
|
89
|
-
logCallback,
|
|
90
|
-
cpuRateLimit: options.cpuRateLimit || 1.0,
|
|
91
|
-
}, platformBindings);
|
|
92
|
-
return {
|
|
93
|
-
addChain: (options) => __awaiter(this, void 0, void 0, function* () {
|
|
94
|
-
if (alreadyDestroyedError.value)
|
|
95
|
-
throw alreadyDestroyedError.value;
|
|
96
|
-
// Passing a JSON object for the chain spec is an easy mistake, so we provide a more
|
|
97
|
-
// readable error.
|
|
98
|
-
if (!(typeof options.chainSpec === 'string'))
|
|
99
|
-
throw new Error("Chain specification must be a string");
|
|
100
|
-
let potentialRelayChainsIds = [];
|
|
101
|
-
if (!!options.potentialRelayChains) {
|
|
102
|
-
for (const chain of options.potentialRelayChains) {
|
|
103
|
-
// The content of `options.potentialRelayChains` are supposed to be chains earlier
|
|
104
|
-
// returned by `addChain`.
|
|
105
|
-
const id = chainIds.get(chain);
|
|
106
|
-
if (id === undefined) // It is possible for `id` to be missing if it has earlier been removed.
|
|
107
|
-
continue;
|
|
108
|
-
potentialRelayChainsIds.push(id);
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
const outcome = yield instance.addChain(options.chainSpec, typeof options.databaseContent === 'string' ? options.databaseContent : "", potentialRelayChainsIds, !!options.disableJsonRpc);
|
|
112
|
-
if (!outcome.success)
|
|
113
|
-
throw new AddChainError(outcome.error);
|
|
114
|
-
const chainId = outcome.chainId;
|
|
115
|
-
const wasDestroyed = { destroyed: false };
|
|
116
|
-
// `expected` was pushed by the `addChain` method.
|
|
117
|
-
// Resolve the promise that `addChain` returned to the user.
|
|
118
|
-
const newChain = {
|
|
119
|
-
sendJsonRpc: (request) => {
|
|
120
|
-
if (alreadyDestroyedError.value)
|
|
121
|
-
throw alreadyDestroyedError.value;
|
|
122
|
-
if (wasDestroyed.destroyed)
|
|
123
|
-
throw new AlreadyDestroyedError();
|
|
124
|
-
if (options.disableJsonRpc)
|
|
125
|
-
throw new JsonRpcDisabledError();
|
|
126
|
-
if (request.length >= 64 * 1024 * 1024) {
|
|
127
|
-
throw new MalformedJsonRpcError();
|
|
128
|
-
}
|
|
129
|
-
;
|
|
130
|
-
instance.request(request, chainId);
|
|
131
|
-
},
|
|
132
|
-
nextJsonRpcResponse: () => {
|
|
133
|
-
if (alreadyDestroyedError.value)
|
|
134
|
-
return Promise.reject(alreadyDestroyedError.value);
|
|
135
|
-
if (wasDestroyed.destroyed)
|
|
136
|
-
return Promise.reject(new AlreadyDestroyedError());
|
|
137
|
-
if (options.disableJsonRpc)
|
|
138
|
-
return Promise.reject(new JsonRpcDisabledError());
|
|
139
|
-
return instance.nextJsonRpcResponse(chainId);
|
|
140
|
-
},
|
|
141
|
-
remove: () => {
|
|
142
|
-
if (alreadyDestroyedError.value)
|
|
143
|
-
throw alreadyDestroyedError.value;
|
|
144
|
-
if (wasDestroyed.destroyed)
|
|
145
|
-
throw new AlreadyDestroyedError();
|
|
146
|
-
wasDestroyed.destroyed = true;
|
|
147
|
-
console.assert(chainIds.has(newChain));
|
|
148
|
-
chainIds.delete(newChain);
|
|
149
|
-
instance.removeChain(chainId);
|
|
150
|
-
},
|
|
151
|
-
};
|
|
152
|
-
chainIds.set(newChain, chainId);
|
|
153
|
-
return newChain;
|
|
154
|
-
}),
|
|
155
|
-
terminate: () => __awaiter(this, void 0, void 0, function* () {
|
|
156
|
-
if (alreadyDestroyedError.value)
|
|
157
|
-
throw alreadyDestroyedError.value;
|
|
158
|
-
alreadyDestroyedError.value = new AlreadyDestroyedError();
|
|
159
|
-
instance.startShutdown();
|
|
160
|
-
})
|
|
161
|
-
};
|
|
162
|
-
}
|