@hazae41/bobine 0.0.18 → 0.0.20

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
@@ -3,7 +3,7 @@
3
3
  A blockchain in your garage
4
4
 
5
5
  ```bash
6
- npm install -g @hazae41/bobine
6
+ deno install -gf -A npm:@hazae41/bobine
7
7
  ```
8
8
 
9
9
  [**🌐 Website**](https://bobine.tech/) • [**📦 NPM**](https://www.npmjs.com/package/@hazae41/bobine)
@@ -23,6 +23,12 @@ npm install -g @hazae41/bobine
23
23
 
24
24
  ### Running the server
25
25
 
26
+ Install Deno
27
+
28
+ ```bash
29
+ npm install -g deno
30
+ ```
31
+
26
32
  Install the binary with Deno
27
33
 
28
34
  ```bash
@@ -1,57 +1,157 @@
1
+ // deno-lint-ignore-file prefer-const
1
2
  import * as Wasm from "@hazae41/wasm";
2
3
  export function meter(module, from, name) {
3
4
  let wtype = module.body.sections.find(section => section.kind === Wasm.TypeSection.kind);
5
+ let wimport = module.body.sections.find(section => section.kind === Wasm.ImportSection.kind);
6
+ let wexport = module.body.sections.find(section => section.kind === Wasm.ExportSection.kind);
7
+ let wcode = module.body.sections.find(section => section.kind === Wasm.CodeSection.kind);
8
+ let welem = module.body.sections.find(section => section.kind === Wasm.ElementSection.kind);
9
+ let wstart = module.body.sections.find(section => section.kind === Wasm.StartSection.kind);
4
10
  if (wtype == null) {
5
11
  wtype = new Wasm.TypeSection([]);
6
12
  module.body.sections.unshift(wtype);
7
13
  }
8
- let wimport = module.body.sections.find(section => section.kind === Wasm.ImportSection.kind);
9
14
  if (wimport == null) {
10
15
  wimport = new Wasm.ImportSection([]);
11
16
  const before = module.body.sections.findLastIndex(section => section.kind < Wasm.ImportSection.kind);
12
17
  module.body.sections.splice(before + 1, 0, wimport);
13
18
  }
14
- let wexport = module.body.sections.find(section => section.kind === Wasm.ExportSection.kind);
15
- if (wexport == null) {
16
- wexport = new Wasm.ExportSection([]);
17
- const before = module.body.sections.findLastIndex(section => section.kind < Wasm.ExportSection.kind);
18
- module.body.sections.splice(before + 1, 0, wexport);
19
- }
20
- let wcode = module.body.sections.find(section => section.kind === Wasm.CodeSection.kind);
21
- if (wcode == null) {
22
- wcode = new Wasm.CodeSection([]);
23
- const before = module.body.sections.findLastIndex(section => section.kind < Wasm.CodeSection.kind);
24
- module.body.sections.splice(before + 1, 0, wcode);
25
- }
26
- const wstart = module.body.sections.find(section => section.kind === Wasm.StartSection.kind);
27
19
  wtype.descriptors.push({ prefix: Wasm.TypeSection.FuncType.kind, subtypes: [], body: new Wasm.TypeSection.FuncType([0x7f], []) });
28
20
  wimport.descriptors.unshift({ from: new TextEncoder().encode(from), name: new TextEncoder().encode(name), body: new Wasm.ImportSection.FunctionImport(wtype.descriptors.length - 1) });
29
21
  if (wstart != null)
30
22
  wstart.funcidx++;
31
- for (const body of wcode.bodies) {
32
- const instructions = new Array();
33
- const subinstructions = new Array();
34
- for (const instruction of body.instructions) {
35
- if ([0x10, 0x12, 0xd2].includes(instruction.opcode))
36
- instruction.params[0].value++;
37
- if ([0x03, 0x04, 0x05, 0x0B, 0x0c, 0x0D, 0x0E, 0x0F, 0xd5, 0xd6].includes(instruction.opcode)) {
38
- subinstructions.push(instruction);
39
- instructions.push(new Wasm.Instruction(0x41, [new Wasm.LEB128.I32(subinstructions.length)]));
40
- instructions.push(new Wasm.Instruction(0x10, [new Wasm.LEB128.U32(0)]));
41
- instructions.push(...subinstructions);
42
- subinstructions.length = 0;
23
+ if (welem != null) {
24
+ for (const segment of welem.segments) {
25
+ switch (segment.flag) {
26
+ case 0: {
27
+ for (let i = 0; i < segment.funcidxs.length; i++) {
28
+ segment.funcidxs[i]++;
29
+ continue;
30
+ }
31
+ for (const instruction of segment.instructions) {
32
+ if (![0xd2].includes(instruction.opcode))
33
+ continue;
34
+ instruction.params[0].value++;
35
+ continue;
36
+ }
37
+ break;
38
+ }
39
+ case 1: {
40
+ for (const element of segment.elements) {
41
+ for (const instruction of element) {
42
+ if (![0xd2].includes(instruction.opcode))
43
+ continue;
44
+ instruction.params[0].value++;
45
+ continue;
46
+ }
47
+ continue;
48
+ }
49
+ break;
50
+ }
51
+ case 2: {
52
+ for (const instruction of segment.instructions) {
53
+ if (![0xd2].includes(instruction.opcode))
54
+ continue;
55
+ instruction.params[0].value++;
56
+ continue;
57
+ }
58
+ for (const element of segment.elements) {
59
+ for (const instruction of element) {
60
+ if (![0xd2].includes(instruction.opcode))
61
+ continue;
62
+ instruction.params[0].value++;
63
+ continue;
64
+ }
65
+ continue;
66
+ }
67
+ break;
68
+ }
69
+ case 3: {
70
+ for (const element of segment.elements) {
71
+ for (const instruction of element) {
72
+ if (![0xd2].includes(instruction.opcode))
73
+ continue;
74
+ instruction.params[0].value++;
75
+ continue;
76
+ }
77
+ continue;
78
+ }
79
+ break;
80
+ }
81
+ case 4: {
82
+ for (let i = 0; i < segment.funcidxs.length; i++) {
83
+ segment.funcidxs[i]++;
84
+ continue;
85
+ }
86
+ for (const instruction of segment.instructions) {
87
+ if (![0xd2].includes(instruction.opcode))
88
+ continue;
89
+ instruction.params[0].value++;
90
+ continue;
91
+ }
92
+ break;
93
+ }
94
+ case 5: {
95
+ for (let i = 0; i < segment.funcidxs.length; i++) {
96
+ segment.funcidxs[i]++;
97
+ continue;
98
+ }
99
+ break;
100
+ }
101
+ case 6: {
102
+ for (let i = 0; i < segment.funcidxs.length; i++) {
103
+ segment.funcidxs[i]++;
104
+ continue;
105
+ }
106
+ for (const instruction of segment.instructions) {
107
+ if (![0xd2].includes(instruction.opcode))
108
+ continue;
109
+ instruction.params[0].value++;
110
+ continue;
111
+ }
112
+ break;
113
+ }
114
+ case 7: {
115
+ for (let i = 0; i < segment.funcidxs.length; i++) {
116
+ segment.funcidxs[i]++;
117
+ continue;
118
+ }
119
+ break;
120
+ }
43
121
  }
44
- else {
45
- subinstructions.push(instruction);
122
+ continue;
123
+ }
124
+ }
125
+ if (wcode != null) {
126
+ for (const body of wcode.bodies) {
127
+ const instructions = new Array();
128
+ const subinstructions = new Array();
129
+ for (const instruction of body.instructions) {
130
+ if ([0x10, 0x12, 0xd2].includes(instruction.opcode))
131
+ instruction.params[0].value++;
132
+ if ([0x03, 0x04, 0x05, 0x0B, 0x0c, 0x0D, 0x0E, 0x0F, 0xd5, 0xd6].includes(instruction.opcode)) {
133
+ subinstructions.push(instruction);
134
+ instructions.push(new Wasm.Instruction(0x41, [new Wasm.LEB128.I32(subinstructions.length)]));
135
+ instructions.push(new Wasm.Instruction(0x10, [new Wasm.LEB128.U32(0)]));
136
+ instructions.push(...subinstructions);
137
+ subinstructions.length = 0;
138
+ }
139
+ else {
140
+ subinstructions.push(instruction);
141
+ }
142
+ continue;
46
143
  }
144
+ instructions.push(...subinstructions);
145
+ body.instructions = instructions;
146
+ continue;
47
147
  }
48
- instructions.push(...subinstructions);
49
- body.instructions = instructions;
50
- continue;
51
148
  }
52
- for (const descriptor of wexport.descriptors) {
53
- if (descriptor.kind !== 0x00)
149
+ if (wexport != null) {
150
+ for (const descriptor of wexport.descriptors) {
151
+ if (descriptor.kind !== 0x00)
152
+ continue;
153
+ descriptor.xidx++;
54
154
  continue;
55
- descriptor.xidx++;
155
+ }
56
156
  }
57
157
  }
package/out/mod.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- #!/usr/bin/env deno
1
+ #!/usr/bin/env node
2
2
  export * from "./mods/mod.ts";
3
3
  export declare function main(args: string[]): Promise<void>;
package/out/mod.js CHANGED
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env deno
1
+ #!/usr/bin/env node
2
2
  export * from "./mods/mod.js";
3
3
  import process from "node:process";
4
4
  import * as server from "./mods/server/bin.js";
@@ -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" } });
@@ -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
  },
@@ -265,18 +289,18 @@ function run(module, method, params, mode, maxsparks) {
265
289
  load(module);
266
290
  if (typeof exports[module][method] !== "function")
267
291
  throw new Error("Not found");
268
- return exports[module][method](...params);
292
+ return [exports[module][method](...params)];
269
293
  },
270
- create: (wasmAsBytes, saltAsBytes) => {
271
- const packAsBytes = pack_encode([wasmAsBytes, saltAsBytes]);
272
- const digestOfWasmAsBytes = sha256_digest(wasmAsBytes);
273
- const digestOfPackAsBytes = sha256_digest(packAsBytes);
274
- const digestOfWasmAsHex = digestOfWasmAsBytes.toHex();
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();
275
299
  const digestOfPackAsHex = digestOfPackAsBytes.toHex();
276
- if (!existsSync(`${config.scripts.path}/${digestOfWasmAsHex}.wasm`))
277
- writeFileSync(`${config.scripts.path}/${digestOfWasmAsHex}.wasm`, wasmAsBytes);
300
+ if (!existsSync(`${config.scripts.path}/${digestOfCodeAsHex}.wasm`))
301
+ writeFileSync(`${config.scripts.path}/${digestOfCodeAsHex}.wasm`, code);
278
302
  if (!existsSync(`${config.scripts.path}/${digestOfPackAsHex}.wasm`))
279
- symlinkSync(`./${digestOfWasmAsHex}.wasm`, `${config.scripts.path}/${digestOfPackAsHex}.wasm`, "file");
303
+ symlinkSync(`./${digestOfCodeAsHex}.wasm`, `${config.scripts.path}/${digestOfPackAsHex}.wasm`, "file");
280
304
  return digestOfPackAsHex;
281
305
  }
282
306
  };
@@ -284,28 +308,30 @@ function run(module, method, params, mode, maxsparks) {
284
308
  set: (key, fresh) => {
285
309
  const cache = caches.get(module);
286
310
  cache.set(key, fresh);
287
- const value = pack_encode(fresh);
288
- writes.push([module, key, value]);
311
+ const keyAsBytes = pack_encode(key);
312
+ const valueAsBytes = pack_encode(fresh);
313
+ writes.push([module, keyAsBytes, valueAsBytes]);
289
314
  return;
290
315
  },
291
316
  get: (key) => {
292
317
  const cache = caches.get(module);
293
318
  const stale = cache.get(key);
294
319
  if (stale != null)
295
- return stale;
320
+ return [stale];
321
+ const keyAsBytes = pack_encode(key);
296
322
  const result = new Int32Array(new SharedArrayBuffer(4 + 4 + 4, { maxByteLength: ((4 + 4 + 4) + (1024 * 1024)) }));
297
- helper.postMessage({ method: "storage_get", params: [module, key], result });
323
+ helper.postMessage({ method: "storage_get", params: [module, keyAsBytes], result });
298
324
  if (Atomics.wait(result, 0, 0) !== "ok")
299
325
  throw new Error("Failed to wait");
300
326
  if (result[0] === 2)
301
327
  throw new Error("Internal error");
302
328
  if (result[1] === 2)
303
329
  return null;
304
- const value = new Uint8Array(result.buffer, 4 + 4 + 4, result[2]).slice();
305
- 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);
306
333
  cache.set(key, fresh);
307
- reads.push([module, key, value]);
308
- return fresh;
334
+ return [fresh];
309
335
  }
310
336
  };
311
337
  imports["symbols"] = {
@@ -344,19 +370,19 @@ function run(module, method, params, mode, maxsparks) {
344
370
  return ed25519_sign(payload);
345
371
  }
346
372
  };
347
- let meteredWasmAsBytes;
373
+ let meteredCodeAsBytes;
348
374
  if (!existsSync(`${config.scripts.path}/${module}.metered.wasm`)) {
349
- const wasmAsBytes = readFileSync(`${config.scripts.path}/${module}.wasm`);
350
- const wasmAsParsed = Readable.readFromBytesOrThrow(Wasm.Module, wasmAsBytes);
351
- meter(wasmAsParsed, "sparks", "consume");
352
- meteredWasmAsBytes = Writable.writeToBytesOrThrow(wasmAsParsed);
353
- 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);
354
380
  }
355
381
  else {
356
- meteredWasmAsBytes = readFileSync(`${config.scripts.path}/${module}.metered.wasm`);
382
+ meteredCodeAsBytes = readFileSync(`${config.scripts.path}/${module}.metered.wasm`);
357
383
  }
358
- const meteredWasmAsModule = new WebAssembly.Module(meteredWasmAsBytes);
359
- for (const descriptor of WebAssembly.Module.imports(meteredWasmAsModule)) {
384
+ const meteredCodeAsModule = new WebAssembly.Module(meteredCodeAsBytes);
385
+ for (const descriptor of WebAssembly.Module.imports(meteredCodeAsModule)) {
360
386
  if (imports[descriptor.module] != null) {
361
387
  // NOOP
362
388
  continue;
@@ -369,10 +395,10 @@ function run(module, method, params, mode, maxsparks) {
369
395
  imports[descriptor.module] = instance.exports;
370
396
  continue;
371
397
  }
372
- const meteredWasmAsInstance = new WebAssembly.Instance(meteredWasmAsModule, imports);
373
- current.instance = meteredWasmAsInstance;
374
- current.module = meteredWasmAsModule;
375
- 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;
376
402
  return current;
377
403
  };
378
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.18",
4
+ "version": "0.0.20",
5
5
  "description": "A blockchain in your garage",
6
6
  "repository": "github:hazae41/bobine",
7
7
  "author": "hazae41",