From: Chris Duncan Date: Fri, 22 May 2026 18:08:30 +0000 (-0700) Subject: Merge branch 'main' into next/ergonomics X-Git-Url: https://git.codecow.com/?a=commitdiff_plain;h=e998acc9d67c1510d342dbb189af52813248a169;p=nano-pow.git Merge branch 'main' into next/ergonomics --- e998acc9d67c1510d342dbb189af52813248a169 diff --cc src/lib/generate/webgl/index.ts index 36781ba,df50b8b..ab7cbbf --- a/src/lib/generate/webgl/index.ts +++ b/src/lib/generate/webgl/index.ts @@@ -2,8 -2,8 +2,8 @@@ //! SPDX-FileContributor: Ben Green //! SPDX-License-Identifier: GPL-3.0-or-later AND MIT - import { WorkGenerateResponse } from 'nano-pow' -import { WorkGenerateResponse } from '#types' import { bigintAsUintNArray, bigintRandom, bigintToHex, Logger } from '#utils' ++import { WorkGenerateResponse } from 'nano-pow' import { downsampleSource, drawSource, quadSource } from './shaders' /** diff --cc src/lib/index.ts index 938f8ad,bbc0dd5..e290df6 --- a/src/lib/index.ts +++ b/src/lib/index.ts @@@ -4,8 -4,8 +4,8 @@@ import { NanoPowConfig } from '#lib/config' import { NanoPowCpu, NanoPowWasm, NanoPowWebgl, NanoPowWebgpu } from '#lib/generate' import { NanoPowValidate } from '#lib/validate' -import { WorkErrorResponse, WorkGenerateResponse, WorkValidateResponse } from '#types' import { bigintFrom, Cache, Logger, Queue } from '#utils' ++import { WorkErrorResponse, WorkGenerateResponse, WorkValidateResponse } from 'nano-pow' const logger = new Logger() const q = new Queue() @@@ -15,11 -15,19 +15,20 @@@ export async function generate (hash: u try { const { api, debug, difficulty, effort } = await NanoPowConfig(options) LOG: logger.isEnabled = debug - const cached = Cache.search(hash, difficulty) + const bigintHash = bigintFrom(hash, 'hex') + const cached = Cache.search(bigintHash, difficulty) if (cached) { LOG: logger.log('found work in cache') - return cached + const { valid } = NanoPowValidate(bigintFrom(cached.work, 'hex'), bigintFrom(cached.hash, 'hex'), bigintFrom(cached.difficulty, 'hex'), 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) + } + } } switch (api) { case 'webgpu': { diff --cc src/utils/cache.ts index faa4609,24d0e0e..779a227 --- a/src/utils/cache.ts +++ b/src/utils/cache.ts @@@ -1,50 -1,61 +1,61 @@@ //! SPDX-FileCopyrightText: 2025 Chris Duncan //! SPDX-License-Identifier: GPL-3.0-or-later -import { WorkGenerateResponse } from "#types" -import { bigintFrom } from "#utils" +import { WorkGenerateResponse } from 'nano-pow' -export class Cache { +const STORAGE_KEY = 'NanoPowCache' - static clear (): void { - this.#removeItem('NanoPowCache') - } +let storage: { [key: string]: string } = {} - static delete (hash: unknown): void { - const bigintHash = bigintFrom(hash, 'hex') - const item = this.#getItem('NanoPowCache') - if (item == null) return - const cache = JSON.parse(item) as WorkGenerateResponse[] - for (let i = 0; i < cache.length; i++) { - if (bigintFrom(cache[i].hash, 'hex') === bigintHash) { - cache.splice(i, 1) - } - } - this.#setItem('NanoPowCache', JSON.stringify(cache)) - } +function getItem (key: string): string | null { + if (globalThis?.localStorage) return globalThis.localStorage.getItem(key) + return storage[key] +} - static search (hash: unknown, difficulty: bigint): WorkGenerateResponse | null { - const bigintHash = bigintFrom(hash, 'hex') - const item = this.#getItem('NanoPowCache') - if (item) { - const cache = JSON.parse(item) as WorkGenerateResponse[] - for (const c of cache) { - if (bigintFrom(c.hash, 'hex') === bigintHash && bigintFrom(c.difficulty, 'hex') >= difficulty) { - return c - } - } +function removeItem (key: string): void { + if (globalThis?.localStorage) return globalThis.localStorage.removeItem(key) + storage = {} +} + +function setItem (key: string, item: string): void { + if (globalThis?.localStorage) return globalThis.localStorage.setItem(key, item) + storage[key] = item +} + +export function clear (): void { + removeItem(STORAGE_KEY) +} + - export function search (hash: bigint, difficulty: bigint): WorkGenerateResponse | null { ++export function get (hash: bigint, difficulty: bigint): WorkGenerateResponse | null { + const item = getItem(STORAGE_KEY) - if (item) { - const cache = JSON.parse(item) as WorkGenerateResponse[] - for (const c of cache) { - if (BigInt(`0x${c.hash}`) === hash && BigInt(`0x${c.difficulty}`) >= difficulty) { - return c - } ++ if (item == null) return null ++ const cache: WorkGenerateResponse[] = JSON.parse(item) ++ for (const c of cache) { ++ if (BigInt(`0x${c.hash}`) === hash && BigInt(`0x${c.difficulty}`) >= difficulty) { ++ return c } - return null } + return null +} - export function store (result: WorkGenerateResponse): WorkGenerateResponse { - static store (result: WorkGenerateResponse): WorkGenerateResponse { - const item = this.#getItem('NanoPowCache') - const cache = JSON.parse(item ?? '[]') as WorkGenerateResponse[] - if (cache.push(result) > 1000) cache.shift() - this.#setItem('NanoPowCache', JSON.stringify(cache)) - return result ++export function remove (hash: bigint): void { + const item = getItem(STORAGE_KEY) - const cache = JSON.parse(item ?? '[]') as WorkGenerateResponse[] ++ if (item == null) return ++ const cache = JSON.parse(item) as WorkGenerateResponse[] ++ for (let i = 0; i < cache.length; i++) { ++ if (BigInt(`0x${cache[i].hash}`) === hash) { ++ cache.splice(i, 1) ++ } + } ++ setItem('NanoPowCache', JSON.stringify(cache)) ++} + - static #storage: { [key: string]: string } = {} - static #getItem (key: string): string | null { - if (globalThis?.localStorage) return globalThis.localStorage.getItem(key) - return this.#storage[key] - } - static #removeItem (key: string): void { - if (globalThis?.localStorage) return globalThis.localStorage.removeItem(key) - this.#storage = {} - } - static #setItem (key: string, item: string): void { - if (globalThis?.localStorage) return globalThis.localStorage.setItem(key, item) - this.#storage[key] = item - } ++export function set (result: WorkGenerateResponse): WorkGenerateResponse { ++ const item = getItem(STORAGE_KEY) ?? '[]' ++ const cache: WorkGenerateResponse[] = JSON.parse(item) + if (cache.push(result) > 1000) cache.shift() + setItem(STORAGE_KEY, JSON.stringify(cache)) + return result } + - export const Cache = { clear, search, store } ++export const Cache = { clear, delete: remove, search: get, store: set } diff --cc test/index.html index 882e091,2c90f01..c0a873f --- a/test/index.html +++ b/test/index.html @@@ -44,13 -28,13 +44,13 @@@ SPDX-License-Identifier: GPL-3.0-or-lat const glSize = (canvas => { const gl = canvas.getContext('webgl2') - const MAX_VIEWPORT_DIMS = gl.getParameter(gl.MAX_VIEWPORT_DIMS) - canvas.height = MAX_VIEWPORT_DIMS?.[0] ?? 0x1000 - canvas.width = MAX_VIEWPORT_DIMS?.[1] ?? 0x1000 - return Math.min(gl.drawingBufferHeight, gl.drawingBufferWidth) + const MAX_VIEWPORT_DIMS = gl?.getParameter(gl.MAX_VIEWPORT_DIMS) ?? [0x1000, 0x1000] + const size = Math.min(0x2000, ...MAX_VIEWPORT_DIMS) + canvas.height = canvas.width = size + return gl?.drawingBufferHeight < gl?.drawingBufferWidth ? gl?.drawingBufferHeight : gl?.drawingBufferWidth })(new OffscreenCanvas(0, 0)) - function random(size = 64) { + function random (size = 64) { let hex = '' while (hex.length < size) { hex += crypto.randomUUID().replace(/-.*-/g, '') diff --cc tsconfig.json index caeff0e,120b215..12146e2 --- a/tsconfig.json +++ b/tsconfig.json @@@ -2,12 -2,11 +2,11 @@@ "compilerOptions": { "target": "es2022", "module": "es2022", - "moduleResolution": "Bundler", + "moduleResolution": "bundler", "declaration": true, "emitDeclarationOnly": true, - "declarationDir": "./types", + "declarationDir": "./dist", "alwaysStrict": true, - "downlevelIteration": false, "esModuleInterop": true, "forceConsistentCasingInFileNames": true, "noErrorTruncation": true,