@hazae41/bobine 0.0.17 → 0.0.19
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 +4 -0
- package/out/mods/helper/bin.js +1 -1
- package/out/mods/server/mod.js +14 -13
- package/out/mods/worker/bin.js +70 -46
- package/package.json +3 -3
package/README.md
CHANGED
package/out/mods/helper/bin.js
CHANGED
|
@@ -50,7 +50,7 @@ self.addEventListener("message", async (event) => {
|
|
|
50
50
|
}
|
|
51
51
|
if (request.method === "ed25519_verify") {
|
|
52
52
|
const [pubkeyAsBytes, signatureAsBytes, payloadAsBytes] = request.params;
|
|
53
|
-
const pubkeyAsKey = await crypto.subtle.importKey("
|
|
53
|
+
const pubkeyAsKey = await crypto.subtle.importKey("spki", pubkeyAsBytes, "Ed25519", true, ["verify"]);
|
|
54
54
|
const verified = await crypto.subtle.verify("Ed25519", pubkeyAsKey, signatureAsBytes, payloadAsBytes);
|
|
55
55
|
request.result[0] = 1;
|
|
56
56
|
request.result[1] = verified ? 1 : 0;
|
package/out/mods/server/mod.js
CHANGED
|
@@ -51,7 +51,7 @@ var __disposeResources = (this && this.__disposeResources) || (function (Suppres
|
|
|
51
51
|
var e = new Error(message);
|
|
52
52
|
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
53
53
|
});
|
|
54
|
-
import { Writable } from "@hazae41/binary";
|
|
54
|
+
import { Readable, Writable } from "@hazae41/binary";
|
|
55
55
|
import { RpcRequest, RpcResponse } from "@hazae41/jsonrpc";
|
|
56
56
|
import { Mutex } from "@hazae41/mutex";
|
|
57
57
|
import { connect } from "@tursodatabase/database";
|
|
@@ -92,7 +92,7 @@ export async function serve(config) {
|
|
|
92
92
|
|
|
93
93
|
module TEXT NOT NULL,
|
|
94
94
|
|
|
95
|
-
key
|
|
95
|
+
key BLOB NOT NULL,
|
|
96
96
|
|
|
97
97
|
value BLOB NOT NULL
|
|
98
98
|
);`);
|
|
@@ -117,12 +117,12 @@ export async function serve(config) {
|
|
|
117
117
|
if (match = new URLPattern("/api/create", request.url).exec(request.url)) {
|
|
118
118
|
if (request.method === "POST") {
|
|
119
119
|
const form = await request.formData();
|
|
120
|
-
const
|
|
121
|
-
if (
|
|
120
|
+
const codeAsEntry = form.get("code");
|
|
121
|
+
if (codeAsEntry == null)
|
|
122
122
|
return Response.json(null, { status: 400 });
|
|
123
|
-
if (typeof
|
|
123
|
+
if (typeof codeAsEntry === "string")
|
|
124
124
|
return Response.json(null, { status: 400 });
|
|
125
|
-
const
|
|
125
|
+
const codeAsBytes = await codeAsEntry.bytes();
|
|
126
126
|
const saltAsEntry = form.get("salt");
|
|
127
127
|
if (saltAsEntry == null)
|
|
128
128
|
return Response.json(null, { status: 400 });
|
|
@@ -142,17 +142,18 @@ export async function serve(config) {
|
|
|
142
142
|
return Response.json(null, { status: 402 });
|
|
143
143
|
setOfEffortsAsHex.add(effortAsHex);
|
|
144
144
|
const sparksAsBigInt = (2n ** 256n) / BigInt("0x" + new Uint8Array(await crypto.subtle.digest("SHA-256", effortAsBytes)).toHex());
|
|
145
|
-
if (sparksAsBigInt < (
|
|
145
|
+
if (sparksAsBigInt < (codeAsBytes.length + saltAsBytes.length))
|
|
146
146
|
return Response.json(null, { status: 402 });
|
|
147
|
-
const
|
|
148
|
-
const
|
|
147
|
+
const saltAsValue = Readable.readFromBytesOrThrow(Packed, saltAsBytes);
|
|
148
|
+
const packAsBytes = Writable.writeToBytesOrThrow(new Packed([codeAsBytes, saltAsValue]));
|
|
149
|
+
const digestOfCodeAsBytes = new Uint8Array(await crypto.subtle.digest("SHA-256", codeAsBytes));
|
|
149
150
|
const digestOfPackAsBytes = new Uint8Array(await crypto.subtle.digest("SHA-256", packAsBytes));
|
|
150
|
-
const
|
|
151
|
+
const digestOfCodeAsHex = digestOfCodeAsBytes.toHex();
|
|
151
152
|
const digestOfPackAsHex = digestOfPackAsBytes.toHex();
|
|
152
|
-
if (!existsSync(`${config.scripts.path}/${
|
|
153
|
-
writeFileSync(`${config.scripts.path}/${
|
|
153
|
+
if (!existsSync(`${config.scripts.path}/${digestOfCodeAsHex}.wasm`))
|
|
154
|
+
writeFileSync(`${config.scripts.path}/${digestOfCodeAsHex}.wasm`, codeAsBytes);
|
|
154
155
|
if (!existsSync(`${config.scripts.path}/${digestOfPackAsHex}.wasm`))
|
|
155
|
-
symlinkSync(`./${
|
|
156
|
+
symlinkSync(`./${digestOfCodeAsHex}.wasm`, `${config.scripts.path}/${digestOfPackAsHex}.wasm`);
|
|
156
157
|
return Response.json(digestOfPackAsHex);
|
|
157
158
|
}
|
|
158
159
|
return Response.json(null, { status: 405, headers: { "Allow": "POST" } });
|
package/out/mods/worker/bin.js
CHANGED
|
@@ -69,7 +69,7 @@ function run(module, method, params, mode, maxsparks) {
|
|
|
69
69
|
throw new Error("Aborted");
|
|
70
70
|
},
|
|
71
71
|
uuid: () => {
|
|
72
|
-
return
|
|
72
|
+
return "17fa1cb5-c5af-4cfd-9bea-1a36590b890d";
|
|
73
73
|
}
|
|
74
74
|
};
|
|
75
75
|
imports["sparks"] = {
|
|
@@ -225,6 +225,9 @@ function run(module, method, params, mode, maxsparks) {
|
|
|
225
225
|
dec: (value) => {
|
|
226
226
|
return value - 1n;
|
|
227
227
|
},
|
|
228
|
+
neg: (value) => {
|
|
229
|
+
return -value;
|
|
230
|
+
},
|
|
228
231
|
add: (left, right) => {
|
|
229
232
|
return left + right;
|
|
230
233
|
},
|
|
@@ -240,6 +243,27 @@ function run(module, method, params, mode, maxsparks) {
|
|
|
240
243
|
pow: (left, right) => {
|
|
241
244
|
return left ** right;
|
|
242
245
|
},
|
|
246
|
+
mod: (left, right) => {
|
|
247
|
+
return left % right;
|
|
248
|
+
},
|
|
249
|
+
lt: (left, right) => {
|
|
250
|
+
return left < right;
|
|
251
|
+
},
|
|
252
|
+
lte: (left, right) => {
|
|
253
|
+
return left <= right;
|
|
254
|
+
},
|
|
255
|
+
gt: (left, right) => {
|
|
256
|
+
return left > right;
|
|
257
|
+
},
|
|
258
|
+
gte: (left, right) => {
|
|
259
|
+
return left >= right;
|
|
260
|
+
},
|
|
261
|
+
eq: (left, right) => {
|
|
262
|
+
return left === right;
|
|
263
|
+
},
|
|
264
|
+
neq: (left, right) => {
|
|
265
|
+
return left !== right;
|
|
266
|
+
},
|
|
243
267
|
from_base16: (text) => {
|
|
244
268
|
return BigInt("0x" + text);
|
|
245
269
|
},
|
|
@@ -254,60 +278,60 @@ function run(module, method, params, mode, maxsparks) {
|
|
|
254
278
|
}
|
|
255
279
|
};
|
|
256
280
|
imports["modules"] = {
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
const digestOfWasmAsBytes = sha256_digest(wasmAsBytes);
|
|
260
|
-
const digestOfPackAsBytes = sha256_digest(packAsBytes);
|
|
261
|
-
const digestOfWasmAsHex = digestOfWasmAsBytes.toHex();
|
|
262
|
-
const digestOfPackAsHex = digestOfPackAsBytes.toHex();
|
|
263
|
-
if (!existsSync(`${config.scripts.path}/${digestOfWasmAsHex}.wasm`))
|
|
264
|
-
writeFileSync(`${config.scripts.path}/${digestOfWasmAsHex}.wasm`, wasmAsBytes);
|
|
265
|
-
if (!existsSync(`${config.scripts.path}/${digestOfPackAsHex}.wasm`))
|
|
266
|
-
symlinkSync(`./${digestOfWasmAsHex}.wasm`, `${config.scripts.path}/${digestOfPackAsHex}.wasm`, "file");
|
|
267
|
-
return digestOfPackAsBytes;
|
|
268
|
-
},
|
|
269
|
-
call: (moduleAsBytes, methodAsBytes, paramsAsPack) => {
|
|
270
|
-
const moduleAsString = moduleAsBytes.toHex();
|
|
271
|
-
const methodAsString = new TextDecoder().decode(methodAsBytes);
|
|
272
|
-
if (exports[moduleAsString] == null)
|
|
273
|
-
load(moduleAsString);
|
|
274
|
-
if (typeof exports[moduleAsString][methodAsString] !== "function")
|
|
275
|
-
throw new Error("Not found");
|
|
276
|
-
return exports[moduleAsString][methodAsString](...paramsAsPack);
|
|
281
|
+
self: () => {
|
|
282
|
+
return module;
|
|
277
283
|
},
|
|
278
|
-
load: (
|
|
279
|
-
return readFileSync(`${config.scripts.path}/${
|
|
284
|
+
load: (module) => {
|
|
285
|
+
return readFileSync(`${config.scripts.path}/${module}.wasm`);
|
|
280
286
|
},
|
|
281
|
-
|
|
282
|
-
|
|
287
|
+
call: (module, method, params) => {
|
|
288
|
+
if (exports[module] == null)
|
|
289
|
+
load(module);
|
|
290
|
+
if (typeof exports[module][method] !== "function")
|
|
291
|
+
throw new Error("Not found");
|
|
292
|
+
return [exports[module][method](...params)];
|
|
293
|
+
},
|
|
294
|
+
create: (code, salt) => {
|
|
295
|
+
const pack = pack_encode([code, salt]);
|
|
296
|
+
const digestOfCodeAsBytes = sha256_digest(code);
|
|
297
|
+
const digestOfPackAsBytes = sha256_digest(pack);
|
|
298
|
+
const digestOfCodeAsHex = digestOfCodeAsBytes.toHex();
|
|
299
|
+
const digestOfPackAsHex = digestOfPackAsBytes.toHex();
|
|
300
|
+
if (!existsSync(`${config.scripts.path}/${digestOfCodeAsHex}.wasm`))
|
|
301
|
+
writeFileSync(`${config.scripts.path}/${digestOfCodeAsHex}.wasm`, code);
|
|
302
|
+
if (!existsSync(`${config.scripts.path}/${digestOfPackAsHex}.wasm`))
|
|
303
|
+
symlinkSync(`./${digestOfCodeAsHex}.wasm`, `${config.scripts.path}/${digestOfPackAsHex}.wasm`, "file");
|
|
304
|
+
return digestOfPackAsHex;
|
|
283
305
|
}
|
|
284
306
|
};
|
|
285
307
|
imports["storage"] = {
|
|
286
308
|
set: (key, fresh) => {
|
|
287
309
|
const cache = caches.get(module);
|
|
288
310
|
cache.set(key, fresh);
|
|
289
|
-
const
|
|
290
|
-
|
|
311
|
+
const keyAsBytes = pack_encode(key);
|
|
312
|
+
const valueAsBytes = pack_encode(fresh);
|
|
313
|
+
writes.push([module, keyAsBytes, valueAsBytes]);
|
|
291
314
|
return;
|
|
292
315
|
},
|
|
293
316
|
get: (key) => {
|
|
294
317
|
const cache = caches.get(module);
|
|
295
318
|
const stale = cache.get(key);
|
|
296
319
|
if (stale != null)
|
|
297
|
-
return stale;
|
|
320
|
+
return [stale];
|
|
321
|
+
const keyAsBytes = pack_encode(key);
|
|
298
322
|
const result = new Int32Array(new SharedArrayBuffer(4 + 4 + 4, { maxByteLength: ((4 + 4 + 4) + (1024 * 1024)) }));
|
|
299
|
-
helper.postMessage({ method: "storage_get", params: [module,
|
|
323
|
+
helper.postMessage({ method: "storage_get", params: [module, keyAsBytes], result });
|
|
300
324
|
if (Atomics.wait(result, 0, 0) !== "ok")
|
|
301
325
|
throw new Error("Failed to wait");
|
|
302
326
|
if (result[0] === 2)
|
|
303
327
|
throw new Error("Internal error");
|
|
304
328
|
if (result[1] === 2)
|
|
305
329
|
return null;
|
|
306
|
-
const
|
|
307
|
-
|
|
330
|
+
const valueAsBytes = new Uint8Array(result.buffer, 4 + 4 + 4, result[2]).slice();
|
|
331
|
+
reads.push([module, keyAsBytes, valueAsBytes]);
|
|
332
|
+
const fresh = pack_decode(valueAsBytes);
|
|
308
333
|
cache.set(key, fresh);
|
|
309
|
-
|
|
310
|
-
return fresh;
|
|
334
|
+
return [fresh];
|
|
311
335
|
}
|
|
312
336
|
};
|
|
313
337
|
imports["symbols"] = {
|
|
@@ -346,19 +370,19 @@ function run(module, method, params, mode, maxsparks) {
|
|
|
346
370
|
return ed25519_sign(payload);
|
|
347
371
|
}
|
|
348
372
|
};
|
|
349
|
-
let
|
|
373
|
+
let meteredCodeAsBytes;
|
|
350
374
|
if (!existsSync(`${config.scripts.path}/${module}.metered.wasm`)) {
|
|
351
|
-
const
|
|
352
|
-
const
|
|
353
|
-
meter(
|
|
354
|
-
|
|
355
|
-
writeFileSync(`${config.scripts.path}/${module}.metered.wasm`,
|
|
375
|
+
const codeAsBytes = readFileSync(`${config.scripts.path}/${module}.wasm`);
|
|
376
|
+
const codeAsWasm = Readable.readFromBytesOrThrow(Wasm.Module, codeAsBytes);
|
|
377
|
+
meter(codeAsWasm, "sparks", "consume");
|
|
378
|
+
meteredCodeAsBytes = Writable.writeToBytesOrThrow(codeAsWasm);
|
|
379
|
+
writeFileSync(`${config.scripts.path}/${module}.metered.wasm`, meteredCodeAsBytes);
|
|
356
380
|
}
|
|
357
381
|
else {
|
|
358
|
-
|
|
382
|
+
meteredCodeAsBytes = readFileSync(`${config.scripts.path}/${module}.metered.wasm`);
|
|
359
383
|
}
|
|
360
|
-
const
|
|
361
|
-
for (const descriptor of WebAssembly.Module.imports(
|
|
384
|
+
const meteredCodeAsModule = new WebAssembly.Module(meteredCodeAsBytes);
|
|
385
|
+
for (const descriptor of WebAssembly.Module.imports(meteredCodeAsModule)) {
|
|
362
386
|
if (imports[descriptor.module] != null) {
|
|
363
387
|
// NOOP
|
|
364
388
|
continue;
|
|
@@ -371,10 +395,10 @@ function run(module, method, params, mode, maxsparks) {
|
|
|
371
395
|
imports[descriptor.module] = instance.exports;
|
|
372
396
|
continue;
|
|
373
397
|
}
|
|
374
|
-
const
|
|
375
|
-
current.instance =
|
|
376
|
-
current.module =
|
|
377
|
-
exports[module] =
|
|
398
|
+
const meteredCodeAsInstance = new WebAssembly.Instance(meteredCodeAsModule, imports);
|
|
399
|
+
current.instance = meteredCodeAsInstance;
|
|
400
|
+
current.module = meteredCodeAsModule;
|
|
401
|
+
exports[module] = meteredCodeAsInstance.exports;
|
|
378
402
|
return current;
|
|
379
403
|
};
|
|
380
404
|
const { instance } = load(module);
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@hazae41/bobine",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.19",
|
|
5
5
|
"description": "A blockchain in your garage",
|
|
6
6
|
"repository": "github:hazae41/bobine",
|
|
7
7
|
"author": "hazae41",
|
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
"scripts": {
|
|
10
10
|
"examine": "deno lint ./src && deno check ./src && deno test -R ./src",
|
|
11
11
|
"prepack": "rm -rf ./out && tsc && tscousin",
|
|
12
|
-
"produce": "deno run -A ./src/mod.ts serve --env=./.env.local",
|
|
13
|
-
"develop": "deno run -A ./src/mod.ts serve --env=./.env.local --dev"
|
|
12
|
+
"produce": "deno run -A --sloppy-imports ./src/mod.ts serve --env=./.env.local",
|
|
13
|
+
"develop": "deno run -A --sloppy-imports ./src/mod.ts serve --env=./.env.local --dev"
|
|
14
14
|
},
|
|
15
15
|
"files": [
|
|
16
16
|
"./out"
|