//! 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'
// 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[] = []
}
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' }))
await workersStarted()
LOG: logger.log('Workers ready')
} catch (err: any) {
- LOG: logger.log(err.message)
throw new Error('Error loading workers')
}
}
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)
}
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))
})
}
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 => {
}
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) {
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)
}
}