]> git.codecow.com Git - nano-pow.git/commitdiff
Limit message handling in WASM host and worker to known worker URL. Fix bigint serial...
authorChris Duncan <chris@codecow.com>
Fri, 10 Jul 2026 05:55:45 +0000 (22:55 -0700)
committerChris Duncan <chris@codecow.com>
Fri, 10 Jul 2026 05:55:45 +0000 (22:55 -0700)
src/lib/generate/wasm/index.ts
src/lib/generate/wasm/worker.ts

index d0e07b9f3943503ad4f69c3d789ee2e2e74318f6..6817bb5009af25fce8653c36c49ab014970d1b29 100644 (file)
@@ -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<string, bigint> = {}
+let data: Record<string, string> = {}
 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<void> {
-       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<bigint> {
-       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<boolean> {
                                        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 => {
index f41a1780cdab1a9a268c828ead1853cf445d343e..9b07a0d0ff61f2c1365e55929739568440615e6b 100644 (file)
@@ -33,19 +33,20 @@ const worker = async (compute: number[]): Promise<void> => {
        }
 
        async function handleMessage (msg: any): Promise<void> {
+               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<void> => {
                                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<string, unknown>
+                               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)
                }
        }