]> git.codecow.com Git - nano-pow.git/commitdiff
Add global alias for byte arrays. Reorganize imports. Replace keyed object types...
authorChris Duncan <chris@codecow.com>
Mon, 25 May 2026 21:00:37 +0000 (14:00 -0700)
committerChris Duncan <chris@codecow.com>
Mon, 25 May 2026 21:00:37 +0000 (14:00 -0700)
12 files changed:
src/bin/cli.ts
src/bin/server.ts
src/index.ts
src/lib/generate/cpu/index.ts
src/lib/generate/wasm/index.ts
src/lib/generate/wasm/worker.ts
src/lib/generate/webgl/index.ts
src/lib/generate/webgpu/index.ts
src/lib/validate/index.ts
src/utils/cache.ts
src/utils/logger.ts
test/index.html

index 138b7cabbac7ff4a8d6c37cc77050e30175a4f6e..f6e81f17fa02a5b924a459eaa0cca6a7362a6e7d 100755 (executable)
@@ -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<string, any> = {
        action: 'work_generate'
 }
 
@@ -254,7 +254,7 @@ function generateHashes (count: number) {
        }
 }
 
-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
index a8a3c0ef091943e7d14c22762403a95bde8672c3..f91774e9928a7160627faef375017b8aa0dfeec6 100755 (executable)
@@ -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<string> {
                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') {
index 1ea806cdce02b6b0e73cae7f1be05d1803ccd06b..9a9e8cd6f5b9082589c9d82f395017fcc4ed526f 100644 (file)
@@ -8,6 +8,7 @@ declare global {
        interface Window {
                NanoPow: typeof NanoPow
        }
+       type Bytes = Uint8Array<ArrayBuffer>
 }
 
 /**
index 211e4eb466527ce693236c22e1dcc879eb23ee44..8d2225161a9ef404bfaa57144be1ab9f6b54f502 100644 (file)
@@ -1,9 +1,9 @@
 //! 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()
 
@@ -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')
index 8ec7344b596d3693a681c367caf0f177d861a322..f1c56c7d9938aa7193bc88b7a621766d50d8389c 100644 (file)
@@ -1,16 +1,16 @@
 //! 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[] = []
@@ -38,8 +38,8 @@ function reset (): void {
 }
 
 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' }))
@@ -72,9 +72,10 @@ async function workersStarted () {
 
 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
index 945dd20d9125df387d1ea38ca71896cb7a2503c4..f41a1780cdab1a9a268c828ead1853cf445d343e 100644 (file)
@@ -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<void> => {
        let isReady = false
index ab7cbbfd8711a6642f2d97b9818b5fb58ae69d9d..9b22bd2f8d50c6ad1fe1a0034b3099434a18f034 100644 (file)
@@ -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<string, bigint> = {}
        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)
index fbd2a79388c6c61e360abf2c2329bbd7fadf60dd..5cbd0a99fc76b7d2c9f8a2476b8224e153c1af58 100644 (file)
@@ -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<string, bigint> = {}
        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)
index 285b1930eca738d748812aa1b51073c5e4ea7dc3..f0d42dcaf51e7cc7f9da0462aeee92a5693f38e5 100644 (file)
@@ -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<ArrayBuffer> = new BigUint64Array(16)
+const m: BigUint64Array<ArrayBuffer> = new BigUint64Array(16)
 const mView: DataView = new DataView(m.buffer)
 let result: bigint = 0n
 
index 6e86a3fe3335ee44cf884695e95b24edd0fe9c44..f40ddb9f216c9bec7d5ef623be11788ce4450d50 100644 (file)
@@ -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()
index 566f5faac8f092eb7434c394af817a9b360fb867..0e89283170373b6e3d75304f19c68c9273fa6ba2 100644 (file)
@@ -7,7 +7,7 @@
  */
 export class Logger {
        isEnabled: boolean = false
-       groups: { [key: string]: boolean } = {}
+       groups: Record<string, boolean> = {}
 
        groupStart (name: string): void {
                if (this.isEnabled) {
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) {