UNPKG

@reclaimprotocol/zk-symmetric-crypto

Version:
89 lines (88 loc) 3.09 kB
import { isMainThread, parentPort, Worker, workerData } from 'worker_threads'; import init, { prove } from './wasm-binding.js'; const BYTES_PER_PAGE = 65536; const logger = console; async function main() { const { module, initialisationMemory } = workerData; const wasm = await init({ 'module_or_path': module }); const growthRequired = (initialisationMemory.byteLength - wasm.memory.buffer.byteLength) / BYTES_PER_PAGE; if (growthRequired > 0) { wasm.memory.grow(growthRequired); logger.debug({ growthRequired }, 'memory grown'); } // copy initialisation memory const memory = new Uint8Array(wasm.memory.buffer); memory.set(initialisationMemory); logger.debug('worker initialised w memory'); parentPort.on('message', async (msg) => { const [type, input] = msg; if (type === 'prove') { try { const result = await prove(...input.args); sendOutputRpcBack({ id: input.id, result }); logger.debug({ id: input.id }, 'prove done'); } catch (err) { logger.error({ err }, 'prove error'); sendOutputRpcBack({ id: input.id, type: 'error', message: err.message, stack: err.stack }); } return; } throw new Error(`Unknown message type: ${type}`); }); parentPort.postMessage({ type: 'online' }); function sendOutputRpcBack(output) { parentPort.postMessage(['reply', output]); } } export async function initWorker(workerData) { const __filename = import.meta.url.replace('file://', ''); const worker = new Worker(__filename, { workerData }); await new Promise((resolve, reject) => { worker.once('message', resolve); worker.once('error', reject); }); const channel = { rpc(type, input) { input.id ||= createRpcId(); const wait = waitForRpcReply(input.id); worker.postMessage([type, input]); return wait; }, close() { return worker.terminate(); } }; return channel; async function waitForRpcReply(id) { return new Promise((resolve, reject) => { worker.on('message', listener); worker.once('error', reject); async function listener([type, output]) { if (type !== 'reply' || output.id !== id) { return; } worker.off('message', listener); worker.off('error', reject); if ('type' in output && output.type === 'error') { const err = new Error(output.message); err.stack = output.stack; reject(err); return; } resolve(output); } }); } } function createRpcId() { return Math.random().toString(36).slice(2); } if (!isMainThread) { main(); }