From: Chris Duncan Date: Mon, 25 May 2026 21:00:37 +0000 (-0700) Subject: Add global alias for byte arrays. Reorganize imports. Replace keyed object types... X-Git-Url: https://git.codecow.com/?a=commitdiff_plain;h=d70946822d17d0e8e879ffe277fc88339505192c;p=nano-pow.git Add global alias for byte arrays. Reorganize imports. Replace keyed object types with flexible Record type. Replace bigint RNG with inline crypto calls to reduce number of calls. --- diff --git a/src/bin/cli.ts b/src/bin/cli.ts index 138b7ca..f6e81f1 100755 --- a/src/bin/cli.ts +++ b/src/bin/cli.ts @@ -3,7 +3,7 @@ //! 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' @@ -77,7 +77,7 @@ hashes.push(...inArgs) let isBatch = false let isBenchmark = false let runs = 1 -const body: { [key: string]: any } = { +const body: Record = { action: 'work_generate' } @@ -254,7 +254,7 @@ function generateHashes (count: number) { } } -async function request (body: { [key: string]: any }): Promise { +async function request (body: Record): Promise { return new Promise((resolve, reject): void => { const listener = async (msg: Serializable): Promise => { if (typeof msg === 'object' && msg != null diff --git a/src/bin/server.ts b/src/bin/server.ts index a8a3c0e..f91774e 100755 --- a/src/bin/server.ts +++ b/src/bin/server.ts @@ -3,7 +3,7 @@ //! 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' @@ -159,7 +159,7 @@ async function work (data: unknown): Promise { LOG: logger.log('Data corrupted.') throw new Error(resBody) } - const dataParsed = data as { [key: string]: unknown } + const dataParsed = data as Record let { action, hash, work, difficulty } = dataParsed if (action !== 'work_generate' && action !== 'work_validate') { diff --git a/src/index.ts b/src/index.ts index 1ea806c..9a9e8cd 100644 --- a/src/index.ts +++ b/src/index.ts @@ -8,6 +8,7 @@ declare global { interface Window { NanoPow: typeof NanoPow } + type Bytes = Uint8Array } /** diff --git a/src/lib/generate/cpu/index.ts b/src/lib/generate/cpu/index.ts index 211e4eb..8d22251 100644 --- a/src/lib/generate/cpu/index.ts +++ b/src/lib/generate/cpu/index.ts @@ -1,9 +1,9 @@ //! SPDX-FileCopyrightText: 2025 Chris Duncan //! 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() @@ -13,11 +13,12 @@ export async function generate (hash: bigint, difficulty: bigint, debug: boolean 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') diff --git a/src/lib/generate/wasm/index.ts b/src/lib/generate/wasm/index.ts index 8ec7344..f1c56c7 100644 --- a/src/lib/generate/wasm/index.ts +++ b/src/lib/generate/wasm/index.ts @@ -1,16 +1,16 @@ //! SPDX-FileCopyrightText: 2025 Chris Duncan //! 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 = {} 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 { - 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' })) @@ -72,9 +72,10 @@ async function workersStarted () { async function dispatch (): Promise { 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 diff --git a/src/lib/generate/wasm/worker.ts b/src/lib/generate/wasm/worker.ts index 945dd20..f41a178 100644 --- a/src/lib/generate/wasm/worker.ts +++ b/src/lib/generate/wasm/worker.ts @@ -3,7 +3,7 @@ //@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 => { let isReady = false diff --git a/src/lib/generate/webgl/index.ts b/src/lib/generate/webgl/index.ts index ab7cbbf..9b22bd2 100644 --- a/src/lib/generate/webgl/index.ts +++ b/src/lib/generate/webgl/index.ts @@ -417,8 +417,9 @@ export async function generate (hash: bigint, difficulty: bigint, effort: number 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 = {} let isFirstRetry = false try { do { @@ -427,13 +428,15 @@ export async function generate (hash: bigint, difficulty: bigint, effort: number 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) diff --git a/src/lib/generate/webgpu/index.ts b/src/lib/generate/webgpu/index.ts index fbd2a79..5cbd0a9 100644 --- a/src/lib/generate/webgpu/index.ts +++ b/src/lib/generate/webgpu/index.ts @@ -280,8 +280,9 @@ export async function generate (hash: bigint, difficulty: bigint, effort: number }, 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 = {} let isFirstRetry = false try { do { @@ -295,11 +296,12 @@ export async function generate (hash: bigint, difficulty: bigint, effort: number } 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) diff --git a/src/lib/validate/index.ts b/src/lib/validate/index.ts index 285b193..f0d42dc 100644 --- a/src/lib/validate/index.ts +++ b/src/lib/validate/index.ts @@ -35,8 +35,8 @@ const blake2b_sigma: readonly (readonly number[])[] = Object.freeze([ const blake2b_param = 0x01010008n // Initialize CPU -const v: BigUint64Array = new BigUint64Array(16) -const m: BigUint64Array = new BigUint64Array(16) +const v: BigUint64Array = new BigUint64Array(16) +const m: BigUint64Array = new BigUint64Array(16) const mView: DataView = new DataView(m.buffer) let result: bigint = 0n diff --git a/src/utils/cache.ts b/src/utils/cache.ts index 6e86a3f..f40ddb9 100644 --- a/src/utils/cache.ts +++ b/src/utils/cache.ts @@ -28,11 +28,11 @@ function setItem (key: string, item: string): void { 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) @@ -40,7 +40,7 @@ export function get (hash: bigint, difficulty: bigint): WorkGenerateResponse | n 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[] @@ -52,7 +52,7 @@ export function remove (hash: bigint): void { 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() diff --git a/src/utils/logger.ts b/src/utils/logger.ts index 566f5fa..0e89283 100644 --- a/src/utils/logger.ts +++ b/src/utils/logger.ts @@ -7,7 +7,7 @@ */ export class Logger { isEnabled: boolean = false - groups: { [key: string]: boolean } = {} + groups: Record = {} groupStart (name: string): void { if (this.isEnabled) { diff --git a/test/index.html b/test/index.html index 92d400d..4913c1c 100644 --- a/test/index.html +++ b/test/index.html @@ -72,7 +72,7 @@ SPDX-License-Identifier: GPL-3.0-or-later 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) {