@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 CHANGED
@@ -2,6 +2,10 @@
2
2
 
3
3
  A blockchain in your garage
4
4
 
5
+ ```bash
6
+ npm install -g @hazae41/bobine
7
+ ```
8
+
5
9
  [**🌐 Website**](https://bobine.tech/) • [**📦 NPM**](https://www.npmjs.com/package/@hazae41/bobine)
6
10
 
7
11
  ## Features
@@ -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("raw", pubkeyAsBytes, "Ed25519", true, ["verify"]);
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;
@@ -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 TEXT NOT NULL,
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 wasmAsEntry = form.get("code");
121
- if (wasmAsEntry == null)
120
+ const codeAsEntry = form.get("code");
121
+ if (codeAsEntry == null)
122
122
  return Response.json(null, { status: 400 });
123
- if (typeof wasmAsEntry === "string")
123
+ if (typeof codeAsEntry === "string")
124
124
  return Response.json(null, { status: 400 });
125
- const wasmAsBytes = await wasmAsEntry.bytes();
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 < (wasmAsBytes.length + saltAsBytes.length))
145
+ if (sparksAsBigInt < (codeAsBytes.length + saltAsBytes.length))
146
146
  return Response.json(null, { status: 402 });
147
- const packAsBytes = Writable.writeToBytesOrThrow(new Packed([wasmAsBytes, saltAsBytes]));
148
- const digestOfWasmAsBytes = new Uint8Array(await crypto.subtle.digest("SHA-256", wasmAsBytes));
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 digestOfWasmAsHex = digestOfWasmAsBytes.toHex();
151
+ const digestOfCodeAsHex = digestOfCodeAsBytes.toHex();
151
152
  const digestOfPackAsHex = digestOfPackAsBytes.toHex();
152
- if (!existsSync(`${config.scripts.path}/${digestOfWasmAsHex}.wasm`))
153
- writeFileSync(`${config.scripts.path}/${digestOfWasmAsHex}.wasm`, wasmAsBytes);
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(`./${digestOfWasmAsHex}.wasm`, `${config.scripts.path}/${digestOfPackAsHex}.wasm`);
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" } });
@@ -69,7 +69,7 @@ function run(module, method, params, mode, maxsparks) {
69
69
  throw new Error("Aborted");
70
70
  },
71
71
  uuid: () => {
72
- return Uint8Array.fromHex("8a8f19d1de0e4fcd9ab15cd7ed5de6dd");
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
- create: (wasmAsBytes, saltAsBytes) => {
258
- const packAsBytes = pack_encode([wasmAsBytes, saltAsBytes]);
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: (moduleAsBytes) => {
279
- return readFileSync(`${config.scripts.path}/${moduleAsBytes.toHex()}.wasm`);
284
+ load: (module) => {
285
+ return readFileSync(`${config.scripts.path}/${module}.wasm`);
280
286
  },
281
- self: () => {
282
- return Uint8Array.fromHex(module);
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 value = pack_encode(fresh);
290
- writes.push([module, key, value]);
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, key], result });
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 value = new Uint8Array(result.buffer, 4 + 4 + 4, result[2]).slice();
307
- const fresh = pack_decode(value);
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
- reads.push([module, key, value]);
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 meteredWasmAsBytes;
373
+ let meteredCodeAsBytes;
350
374
  if (!existsSync(`${config.scripts.path}/${module}.metered.wasm`)) {
351
- const wasmAsBytes = readFileSync(`${config.scripts.path}/${module}.wasm`);
352
- const wasmAsParsed = Readable.readFromBytesOrThrow(Wasm.Module, wasmAsBytes);
353
- meter(wasmAsParsed, "sparks", "consume");
354
- meteredWasmAsBytes = Writable.writeToBytesOrThrow(wasmAsParsed);
355
- writeFileSync(`${config.scripts.path}/${module}.metered.wasm`, meteredWasmAsBytes);
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
- meteredWasmAsBytes = readFileSync(`${config.scripts.path}/${module}.metered.wasm`);
382
+ meteredCodeAsBytes = readFileSync(`${config.scripts.path}/${module}.metered.wasm`);
359
383
  }
360
- const meteredWasmAsModule = new WebAssembly.Module(meteredWasmAsBytes);
361
- for (const descriptor of WebAssembly.Module.imports(meteredWasmAsModule)) {
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 meteredWasmAsInstance = new WebAssembly.Instance(meteredWasmAsModule, imports);
375
- current.instance = meteredWasmAsInstance;
376
- current.module = meteredWasmAsModule;
377
- exports[module] = meteredWasmAsInstance.exports;
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.17",
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"