verify-wasm-host.mjs raw
1 // verify-wasm-host.mjs — Worker bootstrap for verify.wasm.
2 //
3 // Pure compute worker: receives ["V_CHECK", reqID, evJSON], runs BIP-340
4 // Schnorr verification natively in WASM, returns ["V_RESULT", reqID, 1|0].
5 //
6 // No IDB, no WebSocket, no storage access. Bridge surface: verify_worker_* only.
7
8 import {
9 makeCoreHelpers, makeWasi, makeEnv, makeCommonBridge,
10 computeBuildHash,
11 } from './bridge-common.mjs';
12
13 let mem, xp;
14 const _sabTable = new Map();
15 const _sabSeqRef = { value: 0 };
16 const _spawnedWorkerChans = new Map();
17 const _wasmUrlRef = { value: null };
18 const _buildHashRef = { value: null };
19
20 const h = makeCoreHelpers(() => mem, () => xp);
21 const { readStr, readBytes, writeStr, writeI32, writeBytes, cb0, cbs, cbb, cbdata } = h;
22
23 let _workerMsgCBID = 0;
24
25 function jsonEsc(s) {
26 return String(s).replace(/\\/g, '\\\\').replace(/"/g, '\\"')
27 .replace(/\n/g, '\\n').replace(/\r/g, '\\r').replace(/\t/g, '\\t');
28 }
29
30 const bridge = {
31 verify_worker_on_message(cbID) { _workerMsgCBID = cbID; },
32 verify_worker_post(ptr, len) { self.postMessage(readStr(ptr, len)); },
33 verify_worker_set_timeout(ms, cbID) { return setTimeout(() => cb0(cbID), ms); },
34 verify_worker_clear_timeout(handle) { clearTimeout(handle); },
35
36 ...makeCommonBridge(h, _sabTable, _sabSeqRef, _wasmUrlRef, _buildHashRef, _spawnedWorkerChans),
37 };
38
39 const wasi = makeWasi(() => mem);
40 const env = makeEnv(() => mem);
41
42 self.addEventListener('unhandledrejection', function(ev) {
43 self.postMessage('["__ERROR","unhandledrejection: ' + jsonEsc(String(ev.reason)) + '"]');
44 });
45
46 self.onmessage = async function(e) {
47 const d = e.data;
48
49 if (d && d.type === 'init' && d.mode === 'root') {
50 try {
51 const wasmBytes = await fetch(d.wasmUrl, { cache: 'no-store' }).then(r => r.arrayBuffer());
52 const buildHash = await computeBuildHash(wasmBytes);
53 _wasmUrlRef.value = d.wasmUrl;
54 _buildHashRef.value = buildHash;
55
56 const { instance } = await WebAssembly.instantiate(wasmBytes,
57 { bridge, env, wasi_snapshot_preview1: wasi });
58 mem = instance.exports.memory;
59 xp = instance.exports;
60 xp._start();
61 } catch (err) {
62 self.postMessage('["__ERROR","boot: ' + jsonEsc(String(err)) + '"]');
63 }
64 return;
65 }
66
67 if (typeof d === 'string' && _workerMsgCBID) {
68 cbs(_workerMsgCBID, d);
69 }
70 };
71