From d95c08ec8ac8089b0feb7fa2ebd36f87ea50c576 Mon Sep 17 00:00:00 2001 From: Chris Duncan Date: Thu, 9 Jul 2026 22:55:45 -0700 Subject: [PATCH] Limit message handling in WASM host and worker to known worker URL. Fix bigint serialization. --- src/lib/generate/wasm/index.ts | 56 ++++++++++++++++++--------------- src/lib/generate/wasm/worker.ts | 19 ++++++----- 2 files changed, 43 insertions(+), 32 deletions(-) diff --git a/src/lib/generate/wasm/index.ts b/src/lib/generate/wasm/index.ts index d0e07b9..6817bb5 100644 --- a/src/lib/generate/wasm/index.ts +++ b/src/lib/generate/wasm/index.ts @@ -2,7 +2,7 @@ //! SPDX-License-Identifier: GPL-3.0-or-later import { NanoPowValidate } from '#lib/validate' -import { bigHex, Logger } from '#utils' +import { Logger, big, bigHex } from '#utils' import { WorkGenerateResponse } from 'nano-pow' import { NanoPowWasmWorker } from './worker.js' @@ -10,7 +10,7 @@ const logger = new Logger() // Initialize CPU let isReady: boolean = false -let data: Record = {} +let data: Record = {} let v: BigUint64Array = new BigUint64Array(16) let m: BigUint64Array = new BigUint64Array(16) let workers: Worker[] = [] @@ -38,8 +38,8 @@ function reset (): void { } async function init (hash: bigint, difficulty: bigint, effort: number): Promise { - data.hash = hash - data.difficulty = difficulty + data.hash = bigHex(hash) + data.difficulty = bigHex(difficulty) for (let i = workers.length; i < effort; i++) { workers.push(new Worker(url, { type: 'module' })) @@ -51,7 +51,6 @@ async function init (hash: bigint, difficulty: bigint, effort: number): Promise< await workersStarted() LOG: logger.log('Workers ready') } catch (err: any) { - LOG: logger.log(err.message) throw new Error('Error loading workers') } } @@ -61,9 +60,14 @@ async function workersStarted () { const resolutions = [] for (const w of workers) { resolutions.push(new Promise((resolve, reject): void => { - w.onmessage = msg => msg.data === 'started' ? resolve(msg.data) : reject(msg.data) - w.onerror = err => reject(err.message) - w.postMessage('start') + w.onerror = reject + w.onmessage = (msg) => { + const { data } = msg + if (data.url === url) { + data.result === 'started' ? resolve(data) : reject(data) + } + } + w.postMessage({ start: true, url }) })) } Promise.all(resolutions).then(ready).catch(fail) @@ -71,27 +75,31 @@ async function workersStarted () { } async function dispatch (): Promise { - return new Promise(resolve => { + return new Promise((resolve, reject) => { const seed = crypto.getRandomValues(new BigUint64Array(workers.length)) const attempts = [] for (let i = 0; i < workers.length; i++) { - data.seed = seed[i] + data.seed = bigHex(seed[i]) attempts.push(new Promise((found, err) => { const w = workers[i] w.onerror = err w.onmessage = (msg) => { - const result = msg.data - LOG: logger.log(`received result from worker ${i}`) - found(result) + const { data } = msg + if (data.url === url) { + LOG: logger.log(`received result ${data.result} from worker ${i}`) + found(data.result) + } } - LOG: logger.log(`sending data to worker ${i}`) - w.postMessage(JSON.stringify(data)) + LOG: logger.log(`sending data to worker ${i}`, { ...data, url }) + w.postMessage({ ...data, url }) })) } - Promise.all(attempts).then(results => { - const result = results.find(r => typeof r === 'bigint') - result ? resolve(result) : resolve(dispatch()) - }) + Promise.all(attempts) + .then(results => { + const result = results.find(r => typeof r === 'string' && r !== '') + resolve(result ? big(result) : dispatch()) + }) + .catch(err => reject(err)) }) } @@ -104,14 +112,12 @@ async function workersStopped (): Promise { const w = workers[i] w.onerror = reject w.onmessage = (msg) => { - const result = msg.data - if (result === 'stopped') { - resolve(result) - } else { - reject(i) + const { data } = msg + if (data.url === url) { + data.result === 'stopped' ? resolve(true) : reject(i) } } - w.postMessage('stop') + w.postMessage({ stop: true, url }) })) } Promise.allSettled(attempts).then(results => { diff --git a/src/lib/generate/wasm/worker.ts b/src/lib/generate/wasm/worker.ts index f41a178..9b07a0d 100644 --- a/src/lib/generate/wasm/worker.ts +++ b/src/lib/generate/wasm/worker.ts @@ -33,19 +33,20 @@ const worker = async (compute: number[]): Promise => { } async function handleMessage (msg: any): Promise { + if (msg?.data?.url !== self.location.href) return let result: any = null try { + const { data } = msg if (!isReady) await setup() const hashArray = new BigUint64Array(4) const hashView = new DataView(hashArray.buffer) - if (msg.data === 'start') { + if (data.start) { result = 'started' - } else if (msg.data === 'stop') { + } else if (data.stop) { removeEventListener('message', handleMessage) result = 'stopped' } else { - const data = JSON.parse(msg.data) const seed = BigInt(`0x${data.seed}`) const difficulty = BigInt(`0x${data.difficulty}`) for (let i = 0; i < data.hash.length; i += 16) { @@ -59,19 +60,23 @@ const worker = async (compute: number[]): Promise => { const workArray = new BigUint64Array(1) const workView = new DataView(workArray.buffer) workView.setBigUint64(0, work, true) - result = workArray[0] + result = workArray[0].toString(16).padStart(16, '0') } } catch (err: unknown) { if (typeof err === 'object' && err != null) { - const e = err as { [k: string]: unknown } - if (e.message !== 'divide by zero') { + const e = err as Record + if (e.message === 'integer divide by zero') { + result = '' + } else { result = e.message } } else { result = JSON.stringify(err) } } finally { - postMessage(result) + if (result != null) { + postMessage({ result, url: self.location.href }) + } addEventListener('message', handleMessage) } } -- 2.52.0