]> git.codecow.com Git - nano-pow.git/commitdiff
Implement bytes across generate APIs. Fix repeated byte conversions. Declare global...
authorChris Duncan <chris@codecow.com>
Sat, 23 May 2026 08:53:22 +0000 (01:53 -0700)
committerChris Duncan <chris@codecow.com>
Sat, 23 May 2026 08:53:22 +0000 (01:53 -0700)
src/index.ts
src/lib/generate/cpu/index.ts
src/lib/generate/wasm/index.ts
src/lib/generate/webgl/index.ts
src/lib/generate/webgpu/index.ts
src/lib/index.ts
src/lib/validate/index.ts
src/utils/bytes.ts
test/index.html

index 1ea806cdce02b6b0e73cae7f1be05d1803ccd06b..9a9e8cd6f5b9082589c9d82f395017fcc4ed526f 100644 (file)
@@ -8,6 +8,7 @@ declare global {
        interface Window {
                NanoPow: typeof NanoPow
        }
+       type Bytes = Uint8Array<ArrayBuffer>
 }
 
 /**
index 7289984ee050c68b9ff9dcea73cd0ab66344de49..eb932305bd506bf8fe0458388b92dbba2e06c2e2 100644 (file)
@@ -2,21 +2,21 @@
 //! SPDX-License-Identifier: GPL-3.0-or-later
 
 import { NanoPowValidate } from '#lib/validate'
-import { Bytes, Logger } from '#utils'
+import { Logger } from '#utils'
 import { WorkGenerateResponse } from 'nano-pow'
 
 const logger = new Logger()
 
-export async function generate (hash: bigint, difficulty: bigint, debug: boolean): Promise<WorkGenerateResponse> {
+export async function generate (hash: Bytes, difficulty: bigint, debug: boolean): Promise<WorkGenerateResponse> {
        logger.isEnabled = debug
        LOG: logger.groupStart('NanoPow CPU work_generate')
        return new Promise((resolve, reject) => {
                const check = () => {
                        try {
                                LOG: logger.log('check 0x8000 nonces')
-                               let result = NanoPowValidate(crypto.getRandomValues(new Uint8Array(8)), Bytes(hash, 32), difficulty, false)
+                               let result = NanoPowValidate(crypto.getRandomValues(new Uint8Array(8)), hash, difficulty, false)
                                for (let i = 0; i < 0x8000; i++) {
-                                       result = NanoPowValidate(crypto.getRandomValues(new Uint8Array(8)), Bytes(hash, 32), difficulty, false)
+                                       result = NanoPowValidate(crypto.getRandomValues(new Uint8Array(8)), hash, difficulty, false)
                                        if (result.valid === '1') break
                                }
                                if (result.valid === '1') {
index 1b5df5ea0fb6acaf3eae8bf2960088df41e94c33..eb4179c57183449ff8327dabc4b365bee764a33e 100644 (file)
@@ -2,7 +2,7 @@
 //! SPDX-License-Identifier: GPL-3.0-or-later
 
 import { NanoPowValidate } from '#lib/validate'
-import { bigintRandom, bigintToHex, Bytes, Logger } from '#utils'
+import { Bytes, BytesToHex, Logger, bigintRandom, bigintToHex } from '#utils'
 import { WorkGenerateResponse } from 'nano-pow'
 import { NanoPowWasmWorker } from './worker.js'
 
@@ -37,8 +37,8 @@ function reset (): void {
        v?.fill(0n)
 }
 
-async function init (hash: bigint, difficulty: bigint, effort: number): Promise<void> {
-       data.hash = bigintToHex(hash, 64)
+async function init (hash: Bytes, difficulty: bigint, effort: number): Promise<void> {
+       data.hash = BytesToHex(hash.buffer, 64)
        data.difficulty = bigintToHex(difficulty, 16)
 
        for (let i = workers.length; i < effort; i++) {
@@ -132,7 +132,7 @@ async function workersStopped (): Promise<boolean> {
 /**
 * Nano proof-of-work using WebAssembly.
 */
-export async function generate (hash: bigint, difficulty: bigint, effort: number, debug: boolean): Promise<WorkGenerateResponse> {
+export async function generate (hash: Bytes, difficulty: bigint, effort: number, debug: boolean): Promise<WorkGenerateResponse> {
        logger.isEnabled = debug
        LOG: logger.groupStart('NanoPow WASM work_generate')
        LOG: logger.log('generating')
@@ -143,7 +143,7 @@ export async function generate (hash: bigint, difficulty: bigint, effort: number
        let result = ''
        try {
                work = await dispatch()
-               result = (await NanoPowValidate(Bytes(work, 8), Bytes(hash, 32), difficulty, debug)).difficulty
+               result = (await NanoPowValidate(Bytes(work, 8), hash, difficulty, debug)).difficulty
        } catch (err) {
                LOG: logger.log(err)
        } finally {
@@ -158,7 +158,7 @@ export async function generate (hash: bigint, difficulty: bigint, effort: number
        }
 
        return {
-               hash: bigintToHex(hash, 64),
+               hash: BytesToHex(hash.buffer, 64),
                work: bigintToHex(work, 16),
                difficulty: result
        }
index 7fa8192662d6df10d870583aa3a463e5c0d8bebe..278a4d1907fff6222fe5ba3427cd838f743583b2 100644 (file)
@@ -2,7 +2,7 @@
 //! SPDX-FileContributor: Ben Green <ben@latenightsketches.com>
 //! SPDX-License-Identifier: GPL-3.0-or-later AND MIT
 
-import { Bytes, Logger, bigintRandom, bigintToHex } from '#utils'
+import { BytesToHex, Logger, bigintRandom, bigintToHex } from '#utils'
 import { WorkGenerateResponse } from 'nano-pow'
 import { downsampleSource, drawSource, quadSource } from './shaders'
 
@@ -405,7 +405,7 @@ function read (drawFbo: FBO): { work: bigint, difficulty: bigint } {
 /**
 * Nano proof-of-work using WebGL 2.0.
 */
-export async function generate (hash: bigint, difficulty: bigint, effort: number, debug: boolean): Promise<WorkGenerateResponse> {
+export async function generate (hash: Bytes, difficulty: bigint, effort: number, debug: boolean): Promise<WorkGenerateResponse> {
        logger.isEnabled = debug
        // Set up 60s timeout to prevent long-running calls
        let timeout = false
@@ -414,7 +414,7 @@ export async function generate (hash: bigint, difficulty: bigint, effort: number
                LOG: logger.log('timed out')
        }, 60_000)
        LOG: logger.groupStart('NanoPow WebGL work_generate')
-       LOG: logger.log(`generate('${hash.toString(16)}', '${difficulty.toString(16)}', ${effort}, ${debug})`)
+       LOG: logger.log(`generate('${BytesToHex(hash.buffer)}', '${difficulty.toString(16)}', ${effort}, ${debug})`)
 
        // Start drawing to calculate one nonce per pixel
        let found = false
@@ -426,7 +426,7 @@ export async function generate (hash: bigint, difficulty: bigint, effort: number
                                if (isReady === false || effort !== drawEffort || isFirstRetry) {
                                        setup(effort)
                                }
-                               init(new Uint32Array(Bytes(hash, 32).buffer), difficulty)
+                               init(new Uint32Array(hash.buffer), difficulty)
                                LOG: logger.log('drawing frame 0')
                                draw(bigintRandom(), drawFbos[0], queries[0])
                                draw(bigintRandom(), drawFbos[1], queries[1])
@@ -457,7 +457,7 @@ export async function generate (hash: bigint, difficulty: bigint, effort: number
        }
 
        return {
-               hash: bigintToHex(hash, 64),
+               hash: BytesToHex(hash.buffer, 64),
                work: bigintToHex(result.work, 16),
                difficulty: bigintToHex(result.difficulty, 16)
        }
index 16b7566b881a9aa32c9fff8910b0b2ceb27ab794..4e87cddf0ac2dd98c33cccc293a7f7de520035d4 100644 (file)
@@ -1,7 +1,7 @@
 //! SPDX-FileCopyrightText: 2025 Chris Duncan <chris@codecow.com>
 //! SPDX-License-Identifier: GPL-3.0-or-later
 
-import { Bytes, Logger, Queue, bigintRandom, bigintToHex } from '#utils'
+import { BytesToHex, Logger, Queue, bigintRandom, bigintToHex } from '#utils'
 import { WorkGenerateResponse } from 'nano-pow'
 import { default as NanoPowGpuComputeShader } from './shaders/compute.wgsl'
 
@@ -177,7 +177,7 @@ async function restore (): Promise<void> {
        }
 }
 
-async function init (hash: Uint8Array<ArrayBuffer>, difficulty: bigint): Promise<void> {
+async function init (hash: Bytes, difficulty: bigint): Promise<void> {
        LOG: logger.log('variables initializing')
        try {
                // Save hash data for normal usage and potential recovery efforts
@@ -270,7 +270,7 @@ function read (dispatchIndex: number): { work: bigint, difficulty: bigint } {
 /**
 * Nano proof-of-work using WebGPU.
 */
-export async function generate (hash: bigint, difficulty: bigint, effort: number, debug: boolean): Promise<WorkGenerateResponse> {
+export async function generate (hash: Bytes, difficulty: bigint, effort: number, debug: boolean): Promise<WorkGenerateResponse> {
        logger.isEnabled = debug
        // Set up 60s timeout to prevent long-running calls
        let timeout = false
@@ -293,7 +293,7 @@ export async function generate (hash: bigint, difficulty: bigint, effort: number
                                                throw new Error('failed to start')
                                        }
                                }
-                               await q.add(init, Bytes(hash, 32), difficulty)
+                               await q.add(init, hash, difficulty)
                                // Dispatch initial workgroups and set index
                                await dispatch(0, bigintRandom(), effort)
                                let dispatchIndex = 1
@@ -326,7 +326,7 @@ export async function generate (hash: bigint, difficulty: bigint, effort: number
        }
 
        return {
-               hash: bigintToHex(hash, 64),
+               hash: BytesToHex(hash.buffer, 64),
                work: bigintToHex(result.work, 16),
                difficulty: bigintToHex(result.difficulty, 16)
        }
index 2ec72c13509e66864c2f0ea395876d5737d6b53f..31eb811a3df38b081b941c36a331a5dc1881f1aa 100644 (file)
@@ -30,18 +30,19 @@ export async function generate (hash: unknown, options?: unknown): Promise<WorkG
                                        }
                                }
                        }
+                       const hashBytes = Bytes(bigintHash, 32)
                        switch (api) {
                                case 'webgpu': {
-                                       return Cache.store(await NanoPowWebgpu(bigintHash, difficulty, effort, debug))
+                                       return Cache.store(await NanoPowWebgpu(hashBytes, difficulty, effort, debug))
                                }
                                case 'webgl': {
-                                       return Cache.store(await NanoPowWebgl(bigintHash, difficulty, effort, debug))
+                                       return Cache.store(await NanoPowWebgl(hashBytes, difficulty, effort, debug))
                                }
                                case 'wasm': {
-                                       return Cache.store(await NanoPowWasm(bigintHash, difficulty, effort, debug))
+                                       return Cache.store(await NanoPowWasm(hashBytes, difficulty, effort, debug))
                                }
                                default: {
-                                       return Cache.store(await NanoPowCpu(bigintHash, difficulty, debug))
+                                       return Cache.store(await NanoPowCpu(hashBytes, difficulty, debug))
                                }
                        }
                } catch (e: any) {
index 198ca6e417c038029eef4239495ac47f531d1a1f..c4b6926504dbb693c465ac0118eaad5fc555f640 100644 (file)
@@ -93,7 +93,7 @@ function blake2b (work: Uint8Array, hash: Uint8Array): void {
        result[0] = (blake2b_IV[0] ^ 0x01010008n ^ v[0] ^ v[8])
 }
 
-function log (work: Uint8Array<ArrayBuffer>, hash: Uint8Array<ArrayBuffer>, difficulty: bigint): void {
+function log (work: Bytes, hash: Bytes, difficulty: bigint): void {
        LOG: logger.groupStart('NanoPow CPU work_validate')
        LOG: logger.log('NanoPow CPU work_validate', 'work', BytesToHex(work.buffer))
        LOG: logger.log('NanoPow CPU work_validate', 'hash', BytesToHex(hash.buffer))
@@ -102,7 +102,7 @@ function log (work: Uint8Array<ArrayBuffer>, hash: Uint8Array<ArrayBuffer>, diff
        LOG: logger.groupEnd('NanoPow CPU work_validate')
 }
 
-function validate (work: Uint8Array<ArrayBuffer>, hash: Uint8Array<ArrayBuffer>, difficulty: bigint, debug: boolean): WorkValidateResponse {
+function validate (work: Bytes, hash: Bytes, difficulty: bigint, debug: boolean): WorkValidateResponse {
        logger.isEnabled = debug
        blake2b(work, hash)
        log(work, hash, difficulty)
index 1d0434045ec665db6f36c09507aa4c4264075f5c..26a08155594fc98883b60640c2348f2052609a1c 100644 (file)
@@ -6,9 +6,9 @@
  *
  * @param {(bigint|number|string)} input
  * @param {number} [minLength=1]
- * @returns {Uint8Array<ArrayBuffer>}
+ * @returns {Bytes}
  */
-export function Bytes (input: unknown, minLength: unknown = 1): Uint8Array<ArrayBuffer> {
+export function Bytes (input: unknown, minLength: unknown = 1): Bytes {
        if (typeof input === 'number') {
                input = BigInt(input | 0)
        }
index 92d400d820b4324e9643612c007ea3bee6dab257..4913c1c09ccbdf980a7cd4b4afdba4a77f16d347 100644 (file)
@@ -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) {