]> git.codecow.com Git - nano-pow.git/commitdiff
Deprecate bigint conversion function.
authorChris Duncan <chris@codecow.com>
Mon, 25 May 2026 08:43:10 +0000 (01:43 -0700)
committerChris Duncan <chris@codecow.com>
Mon, 25 May 2026 08:43:10 +0000 (01:43 -0700)
src/lib/config/index.ts
src/lib/index.ts
src/utils/bigint.ts
src/utils/bytes.ts
src/utils/cache.ts

index 0c1ccc6d7ab5bb0236944414f661a80a67b56dfe..e1bdd2938d611dfb149798a582e2b11269ddc151 100644 (file)
@@ -1,7 +1,7 @@
 //! SPDX-FileCopyrightText: 2025 Chris Duncan <chris@codecow.com>
 //! SPDX-License-Identifier: GPL-3.0-or-later
 
-import { ApiSupport, bigintFrom, bigintToHex, SEND } from '#utils'
+import { ApiSupport, SEND } from '#utils'
 
 type ApiSupportedTypes = keyof typeof ApiSupport
 
@@ -33,7 +33,7 @@ class NanoPowConfigConstructor implements NanoPowOptions {
                return {
                        api: this.api,
                        debug: this.debug,
-                       difficulty: bigintToHex(this.difficulty, 16),
+                       difficulty: this.difficulty.toString(16).padStart(16, '0'),
                        effort: this.effort
                }
        }
@@ -116,15 +116,15 @@ class NanoPowConfigConstructor implements NanoPowOptions {
        static #getValidDifficulty (input: Record<string, unknown>): bigint {
                if (input != null && input.difficulty != null) {
                        if (typeof input.difficulty === 'string') {
-                               try {
-                                       input.difficulty = bigintFrom(input.difficulty, 'hex')
-                               } catch { }
+                               input.difficulty = input.difficulty.trim().toLowerCase().replace(/n$/, '')
+                               input.difficulty = /^0[box]/i.test(input.difficulty as string) ? input.difficulty : `0x${input.difficulty}`
+                               input.difficulty = BigInt(input.difficulty as string)
                        }
                        if (typeof input.difficulty !== 'bigint') {
-                               throw new Error(`Invalid difficulty (${typeof input.difficulty})${input.difficulty}`)
+                               throw new Error(`Invalid difficulty ${input.difficulty}`)
                        }
-                       if (input.difficulty < 0x0n || input.difficulty > SEND) {
-                               throw new Error(`Invalid difficulty ${bigintToHex(input.difficulty, 16)}`)
+                       if (input.difficulty < 0n || input.difficulty > SEND) {
+                               throw new Error(`Invalid difficulty ${input.difficulty.toString(16).padStart(16, '0')}`)
                        }
                        return input.difficulty
                }
index 31eb811a3df38b081b941c36a331a5dc1881f1aa..480900d330eb374a4f1294e9db1236013a2636df 100644 (file)
@@ -4,33 +4,38 @@
 import { NanoPowConfig } from '#lib/config'
 import { NanoPowCpu, NanoPowWasm, NanoPowWebgl, NanoPowWebgpu } from '#lib/generate'
 import { NanoPowValidate } from '#lib/validate'
-import { Bytes, Cache, Logger, Queue, bigintFrom } from '#utils'
+import { Bytes, Cache, Logger, Queue } from '#utils'
 import { WorkErrorResponse, WorkGenerateResponse, WorkValidateResponse } from 'nano-pow'
 
 const logger = new Logger()
 const q = new Queue()
 
 export async function generate (hash: unknown, options?: unknown): Promise<WorkGenerateResponse | WorkErrorResponse> {
+       if (typeof hash === 'bigint') {
+               hash = hash.toString(16).padStart(64, '0')
+       }
+       if (typeof hash !== 'string') {
+               throw new TypeError('invalid hash', { cause: hash })
+       }
+       const hashBytes = Bytes(hash, 32)
+       const { api, debug, difficulty, effort } = await NanoPowConfig(options)
+       LOG: logger.isEnabled = debug
+       const cached = Cache.search(hash, difficulty)
+       if (cached) {
+               LOG: logger.log('found work in cache')
+               const { valid } = NanoPowValidate(Bytes(cached.work, 8), hashBytes, difficulty, debug)
+               if (valid === '1') {
+                       return cached
+               } else {
+                       try {
+                               Cache.delete(hash)
+                       } catch (err) {
+                               LOG: logger.log('error deleting invalid work from cache, continuing with generate', err)
+                       }
+               }
+       }
        return q.add(async (): Promise<WorkGenerateResponse | WorkErrorResponse> => {
                try {
-                       const { api, debug, difficulty, effort } = await NanoPowConfig(options)
-                       LOG: logger.isEnabled = debug
-                       const bigintHash = bigintFrom(hash, 'hex')
-                       const cached = Cache.search(bigintHash, difficulty)
-                       if (cached) {
-                               LOG: logger.log('found work in cache')
-                               const { valid } = NanoPowValidate(Bytes(cached.work, 8), Bytes(cached.hash, 32), bigintFrom(cached.difficulty, 'hex'), debug)
-                               if (valid === '1') {
-                                       return cached
-                               } else {
-                                       try {
-                                               Cache.delete(bigintHash)
-                                       } catch (err) {
-                                               LOG: logger.log('error deleting invalid work from cache, continuing with generate', err)
-                                       }
-                               }
-                       }
-                       const hashBytes = Bytes(bigintHash, 32)
                        switch (api) {
                                case 'webgpu': {
                                        return Cache.store(await NanoPowWebgpu(hashBytes, difficulty, effort, debug))
index 962afd384392f70707fe3711ef2277cc414d094c..8d12f490c3920faf87e2abcd1d3faad7cb1a217a 100644 (file)
@@ -19,32 +19,6 @@ export function bigintByteLength (int: bigint): number {
        return byteLength
 }
 
-export function bigintFrom (value: bigint | boolean | number | string | unknown, type?: 'bin' | 'oct' | 'hex'): bigint {
-       if (typeof value === 'bigint') {
-               return value
-       } else if (typeof value === 'boolean' || typeof value === 'number') {
-               return BigInt(value)
-       } else if (typeof value === 'string') {
-               const v = value.trim().replace(/n$/, '')
-               if (/^0[Bb][01]+$/.test(v)
-                       || /^0[Oo][0-7]+$/.test(v)
-                       || /^0[Xx][A-Fa-f\d]+$/.test(v)
-                       || /^\d+$/.test(v)) {
-                       return BigInt(v)
-               }
-               if (type === 'bin' && /^[01]+$/.test(v)) {
-                       return BigInt(`0b${v}`)
-               }
-               if (type === 'oct' && /^[0-7]+$/.test(v)) {
-                       return BigInt(`0o${v}`)
-               }
-               if (type === 'hex' || /^\d*[A-Fa-f]+\d*$/.test(v)) {
-                       return BigInt(`0x${v}`)
-               }
-       }
-       throw new TypeError(`can't convert string to BigInt`)
-}
-
 export function bigintRandom (max: bigint = 0xFFFFFFFFFFFFFFFFn): bigint {
        if (typeof max !== 'bigint' || max < 1n) {
                throw new TypeError('Invalid max value')
index 504df382194bd0f77a68d24ee9fbbe8cbc11b1f3..f5b67663a8e178d19550478c1ff9cfbe8d3225cd 100644 (file)
@@ -12,21 +12,23 @@ export function Bytes (input: unknown, minLength: unknown = 1): Bytes {
        if (typeof input === 'number') {
                input = BigInt(input | 0)
        }
-       if (typeof input === 'bigint') {
-               input = input.toString(16)
+       if (typeof input === 'string') {
+               input = input.trim().toLowerCase().replace(/n$/, '')
+               input = /^0[box]/i.test(input as string) ? input : `0x${input}`
+               input = BigInt(input as string)
        }
-       if (typeof input === 'string' && input.length & 1) {
-               input = `0${input}`
-       }
-       if (typeof input !== 'string' || !/^([a-f0-9]{2})+$/i.test(input)) {
+       if (typeof input !== 'bigint' || input < 0n) {
                throw new TypeError('invalid Bytes input', { cause: input })
        }
        if (typeof minLength !== 'number' || minLength < 1) {
                throw new TypeError('invalid minLength', { cause: minLength })
        }
-       const bytes = input.match(/.{2}/g)?.map(int => parseInt(int, 16)) ?? []
-       const filler = new Array(minLength > bytes.length ? minLength - bytes.length : 0)
-       return new Uint8Array([...filler, ...bytes])
+       const bytes: number[] = []
+       for (let i = 0; i < minLength || input > 0n; i++) {
+               bytes.push(Number(input & 0xffn))
+               input >>= 8n
+       }
+       return new Uint8Array(bytes.reverse())
 }
 
 /**
index f40ddb9f216c9bec7d5ef623be11788ce4450d50..a4a7952bddc08ef1467b38a670e96682bbd83f44 100644 (file)
@@ -32,20 +32,20 @@ function clear (): void {
        removeItem(STORAGE_KEY)
 }
 
-function get (hash: bigint, difficulty: bigint): WorkGenerateResponse | null {
+function get (hash: string, difficulty: bigint): WorkGenerateResponse | null {
        const item = getItem(STORAGE_KEY)
        if (item == null) return null
        const cache: WorkGenerateResponse[] = JSON.parse(item)
-       const match = cache.find(c => eq(c.hash, hash) && eq(c.difficulty, difficulty))
+       const match = cache.find(c => c.hash === hash && eq(c.difficulty, difficulty))
        return match ?? null
 }
 
-function remove (hash: bigint): void {
+function remove (hash: string): void {
        const item = getItem(STORAGE_KEY)
        if (item == null) return
        const cache = JSON.parse(item) as WorkGenerateResponse[]
        for (let i = 0; i < cache.length; i++) {
-               if (eq(cache[i].hash, hash)) {
+               if (cache[i].hash === hash) {
                        cache.splice(i, 1)
                }
        }