]> git.codecow.com Git - nano-pow.git/commitdiff
Validate payload to WASM worker and use UUID to ensure only relevant results are... next/optimizations
authorChris Duncan <chris@codecow.com>
Sun, 2 Aug 2026 07:09:45 +0000 (00:09 -0700)
committerChris Duncan <chris@codecow.com>
Sun, 2 Aug 2026 07:09:45 +0000 (00:09 -0700)
src/lib/generate/wasm/index.ts
src/lib/generate/wasm/worker.ts

index a71e82ca4c4e23044c46e7a5f58f2dc5d16a4da6..a1e788a0d58690891a1da25797841027fbd69737 100644 (file)
@@ -57,17 +57,18 @@ async function init (hash: bigint, difficulty: bigint, effort: number): Promise<
 
 async function workersStarted () {
        return new Promise(async (ready, fail): Promise<void> => {
+               const id = crypto.randomUUID()
                const resolutions = []
                for (const w of workers) {
                        resolutions.push(new Promise((resolve, reject): void => {
                                w.onerror = reject
                                w.onmessage = (msg) => {
                                        const { data } = msg
-                                       if (data.url === url) {
+                                       if (data.url === url && data.id === id) {
                                                data.result === 'started' ? resolve(data) : reject(data)
                                        }
                                }
-                               w.postMessage({ start: true, url })
+                               w.postMessage({ url, id, start: true })
                        }))
                }
                Promise.all(resolutions).then(ready).catch(fail)
@@ -76,6 +77,7 @@ async function workersStarted () {
 
 async function dispatch (): Promise<bigint> {
        return new Promise((resolve, reject) => {
+               const id = crypto.randomUUID()
                const seed = crypto.getRandomValues(new BigUint64Array(workers.length))
                const attempts = []
                for (let i = 0; i < workers.length; i++) {
@@ -85,13 +87,13 @@ async function dispatch (): Promise<bigint> {
                                w.onerror = err
                                w.onmessage = (msg) => {
                                        const { data } = msg
-                                       if (data.url === url) {
+                                       if (data.url === url && data.id === id) {
                                                logger.log(`received result ${typeof data.result} "${data.result}" from worker ${i}`)
                                                found(data.result)
                                        }
                                }
-                               logger.log(`sending data to worker ${i}`, { ...data, url })
-                               w.postMessage({ ...data, url })
+                               logger.log(`sending data to worker ${i}`, { url, id, ...data })
+                               w.postMessage({ url, id, ...data })
                        }))
                }
                Promise.all(attempts)
@@ -105,6 +107,7 @@ async function dispatch (): Promise<bigint> {
 
 async function workersStopped (): Promise<boolean> {
        return new Promise(stopped => {
+               const id = crypto.randomUUID()
                try {
                        const attempts = []
                        for (let i = 0; i < workers.length; i++) {
@@ -113,11 +116,11 @@ async function workersStopped (): Promise<boolean> {
                                        w.onerror = reject
                                        w.onmessage = (msg) => {
                                                const { data } = msg
-                                               if (data.url === url) {
+                                               if (data.url === url && data.id === id) {
                                                        data.result === 'stopped' ? resolve(true) : reject(i)
                                                }
                                        }
-                                       w.postMessage({ stop: true, url })
+                                       w.postMessage({ url, id, stop: true })
                                }))
                        }
                        Promise.allSettled(attempts).then(results => {
index 17bd5b37b2d76e94406469ba85a769834e90b616..aaf1e10f98f55033f17aaf4af88d78a5274ecad4 100644 (file)
@@ -32,21 +32,41 @@ 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
+       async function handleMessage (msg: unknown): Promise<void> {
+               if (msg == null
+                       || typeof msg !== 'object'
+                       || !('data' in msg)
+                       || msg.data == null
+                       || typeof msg.data !== 'object'
+                       || !('url' in msg.data)
+                       || typeof msg.data.url !== 'string'
+                       || !('id' in msg.data)
+                       || typeof msg.data.id !== 'string'
+               ) return
+
+               const data = msg.data
+               const { url, id } = data
+               if (url !== self.location.href) return
+
+               let result: undefined | string
+
                try {
-                       const { data } = msg
                        if (!isReady) await setup()
                        const hashArray = new BigUint64Array(4)
                        const hashView = new DataView(hashArray.buffer)
 
-                       if (data.start) {
+                       if ('start' in data && data.start) {
                                result = 'started'
-                       } else if (data.stop) {
+                       } else if ('stop' in data && data.stop) {
                                removeEventListener('message', handleMessage)
                                result = 'stopped'
-                       } else {
+                       } else if ('seed' in data
+                               && typeof data.seed === 'string'
+                               && 'difficulty' in data
+                               && typeof data.difficulty === 'string'
+                               && 'hash' in data
+                               && typeof data.hash === 'string'
+                       ) {
                                const seed = BigInt(`0x${data.seed}`)
                                const difficulty = BigInt(`0x${data.difficulty}`)
                                for (let i = 0; i < data.hash.length; i += 16) {
@@ -62,20 +82,15 @@ const worker = async (compute: number[]): Promise<void> => {
                                workView.setBigUint64(0, work, true)
                                result = workArray[0].toString(16).padStart(16, '0')
                        }
-               } catch (err: unknown) {
-                       if (typeof err === 'object' && err != null) {
-                               const e = err as Record<string, unknown>
-                               if (typeof e.message === 'string' && e.message.includes('divide by zero')) {
-                                       result = ''
-                               } else {
-                                       result = e.message
-                               }
+               } catch (e: unknown) {
+                       if (e != null && typeof e === 'object' && 'message' in e && typeof e.message === 'string') {
+                               result = e.message.includes('divide by zero') ? '' : e.message
                        } else {
-                               result = JSON.stringify(err)
+                               result = JSON.stringify(e)
                        }
                } finally {
-                       if (result != null) {
-                               postMessage({ result, url: self.location.href })
+                       if (result !== undefined) {
+                               postMessage({ url, id, result })
                        }
                        addEventListener('message', handleMessage)
                }