import { NanoPowConfig } from '#lib/config'
import { NanoPowCpu, NanoPowWasm, NanoPowWebgl, NanoPowWebgpu } from '#lib/generate'
import { NanoPowValidate } from '#lib/validate'
-import { big, Cache, Logger, Queue } from '#utils'
+import { big, Cache, Logger, MAX_HASH, 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> {
+export async function generate (blockhash: unknown, options?: unknown): Promise<WorkGenerateResponse | WorkErrorResponse> {
const { api, debug, difficulty, effort } = await NanoPowConfig(options)
+ const hash = big(blockhash)
+ if (hash < 0 || hash > MAX_HASH) throw RangeError('invalid block hash', { cause: blockhash })
LOG: logger.isEnabled = debug
const cached = Cache.search(hash, difficulty)
if (cached) {
try {
switch (api) {
case 'webgpu': {
- return Cache.store(await NanoPowWebgpu(big(hash), difficulty, effort, debug))
+ return Cache.store(await NanoPowWebgpu(hash, difficulty, effort, debug))
}
case 'webgl': {
- return Cache.store(await NanoPowWebgl(big(hash), difficulty, effort, debug))
+ return Cache.store(await NanoPowWebgl(hash, difficulty, effort, debug))
}
case 'wasm': {
- return Cache.store(await NanoPowWasm(big(hash), difficulty, effort, debug))
+ return Cache.store(await NanoPowWasm(hash, difficulty, effort, debug))
}
default: {
- return Cache.store(await NanoPowCpu(big(hash), difficulty, debug))
+ return Cache.store(await NanoPowCpu(hash, difficulty, debug))
}
}
} catch (e: any) {
})
}
-export async function validate (work: unknown, hash: unknown, options?: unknown): Promise<WorkValidateResponse | WorkErrorResponse> {
+export async function validate (work: unknown, blockhash: unknown, options?: unknown): Promise<WorkValidateResponse | WorkErrorResponse> {
try {
+ const hash = big(blockhash)
+ if (hash < 0 || hash > MAX_HASH) throw RangeError('invalid block hash', { cause: blockhash })
const { debug, difficulty } = await NanoPowConfig(options)
- const result = await NanoPowValidate(big(work), big(hash), difficulty, debug)
+ const result = await NanoPowValidate(big(work), hash, difficulty, debug)
return result
} catch (e: any) {
return { error: (typeof e === 'string' ? e : (e?.message ?? '')) }
//! SPDX-FileCopyrightText: 2025 Chris Duncan <chris@codecow.com>
//! SPDX-License-Identifier: GPL-3.0-or-later
+import { isHexN } from '#utils'
+
export function big (value: bigint | boolean | number | string | unknown): bigint {
switch (typeof value) {
case 'bigint':
return BigInt(value)
}
case 'string': {
- const v = value.trim().replace(/^0[Xx]/, '').replace(/n$/, '')
+ const v = value.trim().replace(/^0[Xx]/, '').replace(/[Nn]$/, '')
+ if (!isHexN(v, null)) throw TypeError('invalid hex string', { cause: value })
return BigInt(`0x${v}`)
}
default: {
- throw new TypeError(`can't convert value to BigInt`)
+ throw TypeError(`can't convert value to BigInt`)
}
}
}
export const SEND = 0xfffffff800000000n as const
export const RECEIVE = 0xfffffe0000000000n as const
+export const MAX_HASH = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffn as const
type Averages = {
count: number,
/**
* Checks if value is a string representing an N-byte hexadecimal number.
*
-* @param {unknown} value - Value to check.
+* @param {unknown} value - String to check. Be sure to trim whitespace, hex '0x' prefix, and bigint 'n' suffix.
* @param {(number|null)} byteLength - Number of bytes the string should represent, or 'null' for any number greater than zero.
* @returns True if value is a 2N-character hexadecimal string, else false.
*/
export function isHexN (value: unknown, byteLength: number | null): value is string {
if (typeof value !== 'string') return false
- const v = value.replace(/^0[Xx]/, '')
- const length = byteLength === null ? '+' : `{${2 * byteLength}}`
- const r = new RegExp(`^[A-Fa-f\\d]${length}\$`)
- return r.test(v)
+ const length = byteLength === null ? '+' : `{${byteLength << 1}}`
+ const r = new RegExp(`^[0-9a-f]${length}$`, 'i')
+ return r.test(value)
}
/**