//! SPDX-License-Identifier: GPL-3.0-or-later
import { NanoPowValidate } from '#lib/validate'
-import { BytesToHex, Logger, bigintRandom, isBytes } from '#utils'
+import { BytesToHex, Logger, isBytes } from '#utils'
import { WorkGenerateResponse } from 'nano-pow'
import { NanoPowWasmWorker } from './worker.js'
async function dispatch (): Promise<Bytes> {
return new Promise(next => {
const attempts = []
- for (const w of workers) {
- data.seed = bigintRandom() & ~((1n << 24n) - 1n)
+ const seed = crypto.getRandomValues(new BigUint64Array(workers.length))
+ for (let i = 0; i < workers.length; i++) {
+ data.seed = seed[i] & ~((1n << 24n) - 1n)
+ const w = workers[i]
const attempt = new Promise((resolve, reject) => {
w.onerror = reject
w.onmessage = (msg) => resolve(msg.data)
//! SPDX-FileContributor: Ben Green <ben@latenightsketches.com>
//! SPDX-License-Identifier: GPL-3.0-or-later AND MIT
-import { BytesToHex, Logger, bigintRandom, bigintToHex } from '#utils'
+import { BytesToHex, Logger, bigintToHex } from '#utils'
import { WorkGenerateResponse } from 'nano-pow'
import { downsampleSource, drawSource, quadSource } from './shaders'
LOG: logger.log(`generate('${BytesToHex(hash.buffer)}', '${difficulty.toString(16)}', ${effort}, ${debug})`)
// Start drawing to calculate one nonce per pixel
+ const seed = new BigUint64Array(4)
let found = false
let result: Record<string, bigint> = {}
let isFirstRetry = false
setup(effort)
}
init(new Uint32Array(hash.buffer), difficulty)
+ crypto.getRandomValues(seed)
LOG: logger.log('drawing frame 0')
- draw(bigintRandom(), drawFbos[0], queries[0])
- draw(bigintRandom(), drawFbos[1], queries[1])
- draw(bigintRandom(), drawFbos[2], queries[2])
+ draw(seed[0], drawFbos[0], queries[0])
+ draw(seed[1], drawFbos[1], queries[1])
+ draw(seed[2], drawFbos[2], queries[2])
let drawIndex = 3
do {
- draw(bigintRandom(), drawFbos[drawIndex], queries[drawIndex])
+ if (drawIndex === 0) crypto.getRandomValues(seed)
+ draw(seed[drawIndex], drawFbos[drawIndex], queries[drawIndex])
drawIndex = (drawIndex + 1) % 4
found = await check(queries[drawIndex])
} while (!found && !timeout)
//! SPDX-FileCopyrightText: 2025 Chris Duncan <chris@codecow.com>
//! SPDX-License-Identifier: GPL-3.0-or-later
-import { BytesToHex, Logger, Queue, bigintRandom, bigintToHex } from '#utils'
+import { BytesToHex, Logger, Queue, bigintToHex } from '#utils'
import { WorkGenerateResponse } from 'nano-pow'
import { default as NanoPowGpuComputeShader } from './shaders/compute.wgsl'
async function dispatch (dispatchIndex: number, seed: bigint, effort: number): Promise<void> {
LOG: logger.log('dispatching compute pass')
try {
- LOG: logger.log('seed', bigintToHex(seed, 16))
+ LOG: logger.log('seed', seed.toString(16).padStart(16, '0'))
// Copy seed into INPUT buffer
inputDataView.setBigUint64(40, seed, true)
}, 60_000)
LOG: logger.groupStart('NanoPow WebGPU work_generate')
LOG: logger.log('generating')
+ const seed = new BigUint64Array(2)
let found = false
let result: Record<string, bigint> = {}
let isFirstRetry = false
}
await q.add(init, hash, difficulty)
// Dispatch initial workgroups and set index
- await dispatch(0, bigintRandom(), effort)
+ await dispatch(0, crypto.getRandomValues(seed)[0], effort)
let dispatchIndex = 1
// Loop attempts until valid work found
do {
- await dispatch(dispatchIndex, bigintRandom(), effort)
+ if (dispatchIndex === 0) crypto.getRandomValues(seed)
+ await dispatch(dispatchIndex, seed[dispatchIndex], effort)
dispatchIndex ^= 1
found = await check(dispatchIndex)
} while (!found && !timeout)
//! SPDX-FileCopyrightText: 2025 Chris Duncan <chris@codecow.com>
//! SPDX-License-Identifier: GPL-3.0-or-later
-export function bigintBitLength (int: bigint): bigint {
- let bitLength = 1n
- while (int > 1n || int < -1n) {
- bitLength++
- int >>= 1n
- }
- return bitLength
-}
-
-export function bigintByteLength (int: bigint): number {
- let byteLength = 0
- while (int > 0n || int < -1n) {
- byteLength++
- int >>= 8n
- }
- return byteLength
-}
-
-export function bigintRandom (): bigint {
- const mask = 0xFFFFFFFFFFFFFFFFn
- const randomUint8Array = new Uint8Array(8)
- let output = 0n
- do {
- output = 0n
- crypto.getRandomValues(randomUint8Array)
- output = BigInt(randomUint8Array[0])
- for (let i = 1; i < randomUint8Array.length; i++) {
- output <<= 8n
- output += BigInt(randomUint8Array[i])
- }
- output &= mask
- } while (output > mask)
- return output
-}
-
export function bigintToHex (int: bigint, length: unknown = 0): string {
if (typeof length !== 'number') {
throw new TypeError('invalid length')