//! SPDX-License-Identifier: GPL-3.0-or-later
import { WorkErrorResponse, WorkGenerateResponse, WorkValidateResponse } from 'nano-pow'
-import { isHex32, isHex8, Logger, stats } from 'nano-pow/utils'
+import { Logger, isHex32, isHex8, stats } from 'nano-pow/utils'
import { Serializable, spawn } from 'node:child_process'
import { getRandomValues } from 'node:crypto'
import { createInterface } from 'node:readline/promises'
let isBatch = false
let isBenchmark = false
let runs = 1
-const body: { [key: string]: any } = {
+const body: Record<string, any> = {
action: 'work_generate'
}
}
}
-async function request (body: { [key: string]: any }): Promise<WorkGenerateResponse | WorkValidateResponse | WorkErrorResponse> {
+async function request (body: Record<string, any>): Promise<WorkGenerateResponse | WorkValidateResponse | WorkErrorResponse> {
return new Promise((resolve, reject): void => {
const listener = async (msg: Serializable): Promise<void> => {
if (typeof msg === 'object' && msg != null
//! SPDX-License-Identifier: GPL-3.0-or-later
import { WorkErrorResponse, WorkGenerateResponse, WorkValidateResponse } from 'nano-pow'
-import { isHex32, isHex8, Logger } from 'nano-pow/utils'
+import { Logger, isHex32, isHex8 } from 'nano-pow/utils'
import { Serializable } from 'node:child_process'
import { hash } from 'node:crypto'
import { readFile, writeFile } from 'node:fs/promises'
LOG: logger.log('Data corrupted.')
throw new Error(resBody)
}
- const dataParsed = data as { [key: string]: unknown }
+ const dataParsed = data as Record<string, unknown>
let { action, hash, work, difficulty } = dataParsed
if (action !== 'work_generate' && action !== 'work_validate') {
interface Window {
NanoPow: typeof NanoPow
}
+ type Bytes = Uint8Array<ArrayBuffer>
}
/**
//! SPDX-FileCopyrightText: 2025 Chris Duncan <chris@codecow.com>
//! SPDX-License-Identifier: GPL-3.0-or-later
-import { WorkGenerateResponse } from 'nano-pow'
import { NanoPowValidate } from '#lib/validate'
-import { bigintRandom, Logger } from '#utils'
+import { Logger } from '#utils'
+import { WorkGenerateResponse } from 'nano-pow'
const logger = new Logger()
return new Promise((resolve, reject) => {
const check = () => {
try {
+ const seed = new BigUint64Array(1)
LOG: logger.log('check 0x8000 nonces')
- let result = NanoPowValidate(bigintRandom(), hash, difficulty, false)
+ let result = NanoPowValidate(crypto.getRandomValues(seed)[0], hash, difficulty, false)
for (let i = 0; i < 0x8000; i++) {
- result = NanoPowValidate(bigintRandom(), hash, difficulty, false)
if (result.valid === '1') break
+ result = NanoPowValidate(crypto.getRandomValues(seed)[0], hash, difficulty, false)
}
if (result.valid === '1') {
LOG: logger.groupEnd('NanoPow CPU work_generate')
//! SPDX-FileCopyrightText: 2025 Chris Duncan <chris@codecow.com>
//! SPDX-License-Identifier: GPL-3.0-or-later
-import { WorkGenerateResponse } from 'nano-pow'
import { NanoPowValidate } from '#lib/validate'
-import { bigintRandom, bigintToHex, Logger } from '#utils'
+import { bigintToHex, Logger } from '#utils'
+import { WorkGenerateResponse } from 'nano-pow'
import { NanoPowWasmWorker } from './worker.js'
const logger = new Logger()
// Initialize CPU
let isReady: boolean = false
-let data: { [key: string]: string } = {}
+let data: Record<string, bigint> = {}
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 = bigintToHex(hash, 64)
- data.difficulty = bigintToHex(difficulty, 16)
+ data.hash = hash
+ data.difficulty = difficulty
for (let i = workers.length; i < effort; i++) {
workers.push(new Worker(url, { type: 'module' }))
async function dispatch (): Promise<bigint> {
return new Promise(resolve => {
+ const seed = crypto.getRandomValues(new BigUint64Array(workers.length))
const attempts = []
for (let i = 0; i < workers.length; i++) {
- data.seed = bigintToHex((bigintRandom() & ~((1n << 24n) - 1n)), 16)
+ data.seed = seed[i]
attempts.push(new Promise((found, err) => {
const w = workers[i]
w.onerror = err
//@ts-expect-error
import compute from './asm/build/compute.wasm'
-type Main = (w: bigint, h0: bigint, h1: bigint, h2: bigint, h3: bigint, d: bigint) => any
+type Main = (w: bigint, h0: bigint, h1: bigint, h2: bigint, h3: bigint, d: bigint) => bigint
const worker = async (compute: number[]): Promise<void> => {
let isReady = false
LOG: logger.log(`generate('${hash.toString(16)}', '${difficulty.toString(16)}', ${effort}, ${debug})`)
// Start drawing to calculate one nonce per pixel
+ const seed = new BigUint64Array(4)
let found = false
- let result: { [key: string]: bigint } = {}
+ let result: Record<string, bigint> = {}
let isFirstRetry = false
try {
do {
setup(effort)
}
init(bigintAsUintNArray(hash, 32, 8), 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)
}, 60_000)
LOG: logger.groupStart('NanoPow WebGPU work_generate')
LOG: logger.log('generating')
+ const seed = new BigUint64Array(2)
let found = false
- let result: { [key: string]: bigint } = {}
+ let result: Record<string, bigint> = {}
let isFirstRetry = false
try {
do {
}
await q.add(init, bigintAsUintNArray(hash, 64, 4), 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)
const blake2b_param = 0x01010008n
// Initialize CPU
-const v: BigUint64Array = new BigUint64Array(16)
-const m: BigUint64Array = new BigUint64Array(16)
+const v: BigUint64Array<ArrayBuffer> = new BigUint64Array(16)
+const m: BigUint64Array<ArrayBuffer> = new BigUint64Array(16)
const mView: DataView = new DataView(m.buffer)
let result: bigint = 0n
storage[key] = item
}
-export function clear (): void {
+function clear (): void {
removeItem(STORAGE_KEY)
}
-export function get (hash: bigint, difficulty: bigint): WorkGenerateResponse | null {
+function get (hash: bigint, difficulty: bigint): WorkGenerateResponse | null {
const item = getItem(STORAGE_KEY)
if (item == null) return null
const cache: WorkGenerateResponse[] = JSON.parse(item)
return match ?? null
}
-export function remove (hash: bigint): void {
+function remove (hash: bigint): void {
const item = getItem(STORAGE_KEY)
if (item == null) return
const cache = JSON.parse(item) as WorkGenerateResponse[]
setItem(STORAGE_KEY, JSON.stringify(cache))
}
-export function set (result: WorkGenerateResponse): WorkGenerateResponse {
+function set (result: WorkGenerateResponse): WorkGenerateResponse {
const item = getItem(STORAGE_KEY) ?? '[]'
const cache: WorkGenerateResponse[] = JSON.parse(item)
if (cache.push(result) > 1000) cache.shift()
*/
export class Logger {
isEnabled: boolean = false
- groups: { [key: string]: boolean } = {}
+ groups: Record<string, boolean> = {}
groupStart (name: string): void {
if (this.isEnabled) {
async function run (size, difficulty, effort, api, isOutputShown, isDebug, isSelfCheck) {
// Generate once on load to compile shaders and initialize buffers
- await NanoPow.work_generate(random(), { api, difficulty: 0 })
+ await NanoPow.work_generate(random(), { api, difficulty: '0' })
const type = api
api = type.toLowerCase()
if (isSelfCheck) {