From: Chris Duncan Date: Mon, 25 May 2026 08:43:10 +0000 (-0700) Subject: Deprecate bigint conversion function. X-Git-Url: https://git.codecow.com/?a=commitdiff_plain;h=c0f318f07c93b228d8804c04b7877c8a40d7b6a4;p=nano-pow.git Deprecate bigint conversion function. --- diff --git a/src/lib/config/index.ts b/src/lib/config/index.ts index 0c1ccc6..e1bdd29 100644 --- a/src/lib/config/index.ts +++ b/src/lib/config/index.ts @@ -1,7 +1,7 @@ //! SPDX-FileCopyrightText: 2025 Chris Duncan //! 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): 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 } diff --git a/src/lib/index.ts b/src/lib/index.ts index 31eb811..480900d 100644 --- a/src/lib/index.ts +++ b/src/lib/index.ts @@ -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 { + 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 => { 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)) diff --git a/src/utils/bigint.ts b/src/utils/bigint.ts index 962afd3..8d12f49 100644 --- a/src/utils/bigint.ts +++ b/src/utils/bigint.ts @@ -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') diff --git a/src/utils/bytes.ts b/src/utils/bytes.ts index 504df38..f5b6766 100644 --- a/src/utils/bytes.ts +++ b/src/utils/bytes.ts @@ -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()) } /** diff --git a/src/utils/cache.ts b/src/utils/cache.ts index f40ddb9..a4a7952 100644 --- a/src/utils/cache.ts +++ b/src/utils/cache.ts @@ -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) } }