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, 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  
  41  self.addEventListener('unhandledrejection', function(ev) {
  42    self.postMessage('["__ERROR","unhandledrejection: ' + jsonEsc(String(ev.reason)) + '"]');
  43  });
  44  
  45  self.onmessage = async function(e) {
  46    const d = e.data;
  47  
  48    if (d && d.type === 'init' && d.mode === 'root') {
  49      try {
  50        const wasmBytes = await fetch(d.wasmUrl, { cache: 'no-store' }).then(r => r.arrayBuffer());
  51        const buildHash = await computeBuildHash(wasmBytes);
  52        _wasmUrlRef.value = d.wasmUrl;
  53        _buildHashRef.value = buildHash;
  54  
  55        const { instance } = await WebAssembly.instantiate(wasmBytes,
  56          { bridge, wasi_snapshot_preview1: wasi });
  57        mem = instance.exports.memory;
  58        xp = instance.exports;
  59        xp._start();
  60      } catch (err) {
  61        self.postMessage('["__ERROR","boot: ' + jsonEsc(String(err)) + '"]');
  62      }
  63      return;
  64    }
  65  
  66    if (typeof d === 'string' && _workerMsgCBID) {
  67      cbs(_workerMsgCBID, d);
  68    }
  69  };
  70