nano-pow 5.1.14 → 5.1.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -60,7 +60,9 @@ Use it directly on a webpage with a script module:
60
60
  ```javascript
61
61
  // `hash` is a 64-char hex string
62
62
  const hash = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef";
63
- const { work } = await NanoPow.work_generate(hash);
63
+ const result = await NanoPow.work_generate(hash);
64
+ const { hash, work, difficulty } = result;
65
+ console.log(work);
64
66
  // Result is a 16-char hex string
65
67
  ```
66
68
 
@@ -71,8 +73,10 @@ const { work } = await NanoPow.work_generate(hash);
71
73
  const work = "fedcba0987654321";
72
74
  // `hash` is a 64-char hex string
73
75
  const hash = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef";
74
- const { valid } = await NanoPow.work_validate(work, hash);
75
- // Result is a boolean
76
+ const result = await NanoPow.work_validate(work, hash);
77
+ const { hash, work, difficulty, valid_all, valid_receive, valid } = result;
78
+ console.log(valid);
79
+ // Result is string '0' or '1'
76
80
  ```
77
81
 
78
82
  ### Options
package/dist/bin/cli.js CHANGED
@@ -162,6 +162,18 @@ var Cache = class {
162
162
  static clear() {
163
163
  this.#removeItem("NanoPowCache");
164
164
  }
165
+ static delete(hash) {
166
+ const bigintHash = bigintFrom(hash, "hex");
167
+ const item = this.#getItem("NanoPowCache");
168
+ if (item == null) return;
169
+ const cache = JSON.parse(item);
170
+ for (let i = 0; i < cache.length; i++) {
171
+ if (bigintFrom(cache[i].hash, "hex") === bigintHash) {
172
+ cache.splice(i, 1);
173
+ }
174
+ }
175
+ this.#setItem("NanoPowCache", JSON.stringify(cache));
176
+ }
165
177
  static search(hash, difficulty) {
166
178
  const bigintHash = bigintFrom(hash, "hex");
167
179
  const item = this.#getItem("NanoPowCache");
@@ -165,6 +165,18 @@ var Cache = class {
165
165
  static clear() {
166
166
  this.#removeItem("NanoPowCache");
167
167
  }
168
+ static delete(hash2) {
169
+ const bigintHash = bigintFrom(hash2, "hex");
170
+ const item = this.#getItem("NanoPowCache");
171
+ if (item == null) return;
172
+ const cache = JSON.parse(item);
173
+ for (let i = 0; i < cache.length; i++) {
174
+ if (bigintFrom(cache[i].hash, "hex") === bigintHash) {
175
+ cache.splice(i, 1);
176
+ }
177
+ }
178
+ this.#setItem("NanoPowCache", JSON.stringify(cache));
179
+ }
168
180
  static search(hash2, difficulty) {
169
181
  const bigintHash = bigintFrom(hash2, "hex");
170
182
  const item = this.#getItem("NanoPowCache");
package/dist/main.min.js CHANGED
@@ -231,6 +231,18 @@ var Cache = class {
231
231
  static clear() {
232
232
  this.#removeItem("NanoPowCache");
233
233
  }
234
+ static delete(hash) {
235
+ const bigintHash = bigintFrom(hash, "hex");
236
+ const item = this.#getItem("NanoPowCache");
237
+ if (item == null) return;
238
+ const cache = JSON.parse(item);
239
+ for (let i = 0; i < cache.length; i++) {
240
+ if (bigintFrom(cache[i].hash, "hex") === bigintHash) {
241
+ cache.splice(i, 1);
242
+ }
243
+ }
244
+ this.#setItem("NanoPowCache", JSON.stringify(cache));
245
+ }
234
246
  static search(hash, difficulty) {
235
247
  const bigintHash = bigintFrom(hash, "hex");
236
248
  const item = this.#getItem("NanoPowCache");
@@ -396,6 +408,130 @@ function stats(times) {
396
408
  };
397
409
  }
398
410
 
411
+ // src/lib/config/index.ts
412
+ //! SPDX-FileCopyrightText: 2025 Chris Duncan <chris@codecow.com>
413
+ //! SPDX-License-Identifier: GPL-3.0-or-later
414
+ var NanoPowConfigConstructor = class {
415
+ static #isInternal = false;
416
+ static get isInternal() {
417
+ return this.#isInternal;
418
+ }
419
+ api;
420
+ debug;
421
+ difficulty;
422
+ effort;
423
+ toJSON() {
424
+ return {
425
+ api: this.api,
426
+ debug: this.debug,
427
+ difficulty: bigintToHex(this.difficulty, 16),
428
+ effort: this.effort
429
+ };
430
+ }
431
+ constructor(api, debug, difficulty, effort) {
432
+ if (!this.constructor.isInternal) {
433
+ throw new TypeError(`NanoPowConfig cannot be constructed with 'new'.`);
434
+ }
435
+ this.api = api;
436
+ this.debug = debug;
437
+ this.difficulty = difficulty;
438
+ this.effort = effort;
439
+ }
440
+ static async create(options) {
441
+ const input = options;
442
+ const api = await this.#getValidApi(input);
443
+ const debug = this.#getValidDebug(input);
444
+ const difficulty = this.#getValidDifficulty(input);
445
+ const effort = this.#getValidEffort(input);
446
+ this.#isInternal = true;
447
+ const config = new this(api, debug, difficulty, effort);
448
+ this.#isInternal = false;
449
+ return config;
450
+ }
451
+ // Check platform support for default API setting
452
+ static async #getDefaultApi() {
453
+ if (await ApiSupport.webgpu.isSupported) return "webgpu";
454
+ if (await ApiSupport.webgl.isSupported) return "webgl";
455
+ if (await ApiSupport.wasm.isSupported) return "wasm";
456
+ return "cpu";
457
+ }
458
+ // Assign API if valid value passed
459
+ static async #getValidApi(input) {
460
+ if (input != null && input.api != null) {
461
+ if (typeof input.api === "string") {
462
+ try {
463
+ input.api = input.api.toLowerCase();
464
+ } catch {
465
+ input.api = null;
466
+ }
467
+ }
468
+ if (input.api !== "cpu" && input.api !== "wasm" && input.api !== "webgl" && input.api !== "webgpu") {
469
+ throw new Error(`Invalid API ${input.api}`);
470
+ }
471
+ if (!ApiSupport[input.api].isSupported) {
472
+ throw new Error(`${input.api} is not supported`);
473
+ }
474
+ return input.api;
475
+ }
476
+ return this.#getDefaultApi();
477
+ }
478
+ // Assign debug if valid value passed
479
+ static #getValidDebug(input) {
480
+ if (input != null && input.debug != null) {
481
+ if (typeof input.debug === "bigint" || typeof input.debug === "number") {
482
+ input.debug = input.debug.toString();
483
+ }
484
+ if (typeof input.debug === "string") {
485
+ input.debug = ["1", "true", "y", "yes"].includes(input.debug.toLowerCase());
486
+ }
487
+ if (typeof input.debug !== "boolean") {
488
+ throw new Error(`Invalid debug ${input.debug}`);
489
+ }
490
+ return input.debug;
491
+ }
492
+ return false;
493
+ }
494
+ // Assign difficulty if valid value passed
495
+ static #getValidDifficulty(input) {
496
+ if (input != null && input.difficulty != null) {
497
+ if (typeof input.difficulty === "string") {
498
+ try {
499
+ input.difficulty = bigintFrom(input.difficulty, "hex");
500
+ } catch {
501
+ }
502
+ }
503
+ if (typeof input.difficulty !== "bigint") {
504
+ throw new Error(`Invalid difficulty (${typeof input.difficulty})${input.difficulty}`);
505
+ }
506
+ if (input.difficulty < 0x0n || input.difficulty > SEND) {
507
+ throw new Error(`Invalid difficulty ${bigintToHex(input.difficulty, 16)}`);
508
+ }
509
+ return input.difficulty;
510
+ }
511
+ return SEND;
512
+ }
513
+ // Assign effort if valid value passed
514
+ static #getValidEffort(input) {
515
+ if (input != null && input.effort != null) {
516
+ if (typeof input.effort !== "number") {
517
+ throw new Error(`Invalid effort (${typeof input.effort})${input.effort}`);
518
+ }
519
+ if (input.effort < 1 || input.effort > 32) {
520
+ throw new Error(`Invalid effort ${input.effort}`);
521
+ }
522
+ return input.effort;
523
+ }
524
+ return 4;
525
+ }
526
+ };
527
+ var NanoPowConfig = (options) => {
528
+ try {
529
+ return NanoPowConfigConstructor.create(options);
530
+ } catch (err) {
531
+ throw new Error("Error constructing NanoPowConfig", { cause: err });
532
+ }
533
+ };
534
+
399
535
  // src/lib/validate/index.ts
400
536
  //! SPDX-FileCopyrightText: 2025 Chris Duncan <chris@codecow.com>
401
537
  //! SPDX-License-Identifier: GPL-3.0-or-later
@@ -840,10 +976,10 @@ function createCanvas(size) {
840
976
  gl = context;
841
977
  const MAX_VIEWPORT_DIMS = gl.getParameter(gl.MAX_VIEWPORT_DIMS) ?? [4096, 4096];
842
978
  size = Math.min(size, ...MAX_VIEWPORT_DIMS);
843
- size = Math.floor(size / 256) * 256;
979
+ size = size >>> 8 << 8;
844
980
  canvas.height = canvas.width = size;
845
981
  if (canvas.height !== gl.drawingBufferHeight || canvas.width !== gl.drawingBufferWidth) {
846
- size = Math.floor(Math.min(gl.drawingBufferHeight, gl.drawingBufferWidth) / 256) * 256;
982
+ size = (gl.drawingBufferHeight < gl.drawingBufferWidth ? gl.drawingBufferHeight : gl.drawingBufferWidth) >>> 8 << 8;
847
983
  canvas.height = canvas.width = size;
848
984
  }
849
985
  }
@@ -942,7 +1078,7 @@ function setup2(effort) {
942
1078
  try {
943
1079
  reset2();
944
1080
  drawEffort = effort;
945
- createCanvas(drawEffort * 256);
1081
+ createCanvas(drawEffort << 8);
946
1082
  compile();
947
1083
  } catch (err) {
948
1084
  reset2();
@@ -1385,130 +1521,6 @@ async function generate4(hash, difficulty, effort, debug) {
1385
1521
  //! SPDX-FileCopyrightText: 2025 Chris Duncan <chris@codecow.com>
1386
1522
  //! SPDX-License-Identifier: GPL-3.0-or-later
1387
1523
 
1388
- // src/lib/config/index.ts
1389
- //! SPDX-FileCopyrightText: 2025 Chris Duncan <chris@codecow.com>
1390
- //! SPDX-License-Identifier: GPL-3.0-or-later
1391
- var NanoPowConfigConstructor = class {
1392
- static #isInternal = false;
1393
- static get isInternal() {
1394
- return this.#isInternal;
1395
- }
1396
- api;
1397
- debug;
1398
- difficulty;
1399
- effort;
1400
- toJSON() {
1401
- return {
1402
- api: this.api,
1403
- debug: this.debug,
1404
- difficulty: bigintToHex(this.difficulty, 16),
1405
- effort: this.effort
1406
- };
1407
- }
1408
- constructor(api, debug, difficulty, effort) {
1409
- if (!this.constructor.isInternal) {
1410
- throw new TypeError(`NanoPowConfig cannot be constructed with 'new'.`);
1411
- }
1412
- this.api = api;
1413
- this.debug = debug;
1414
- this.difficulty = difficulty;
1415
- this.effort = effort;
1416
- }
1417
- static async create(options) {
1418
- const input = options;
1419
- const api = await this.#getValidApi(input);
1420
- const debug = this.#getValidDebug(input);
1421
- const difficulty = this.#getValidDifficulty(input);
1422
- const effort = this.#getValidEffort(input);
1423
- this.#isInternal = true;
1424
- const config = new this(api, debug, difficulty, effort);
1425
- this.#isInternal = false;
1426
- return config;
1427
- }
1428
- // Check platform support for default API setting
1429
- static async #getDefaultApi() {
1430
- if (await ApiSupport.webgpu.isSupported) return "webgpu";
1431
- if (await ApiSupport.webgl.isSupported) return "webgl";
1432
- if (await ApiSupport.wasm.isSupported) return "wasm";
1433
- return "cpu";
1434
- }
1435
- // Assign API if valid value passed
1436
- static async #getValidApi(input) {
1437
- if (input != null && input.api != null) {
1438
- if (typeof input.api === "string") {
1439
- try {
1440
- input.api = input.api.toLowerCase();
1441
- } catch {
1442
- input.api = null;
1443
- }
1444
- }
1445
- if (input.api !== "cpu" && input.api !== "wasm" && input.api !== "webgl" && input.api !== "webgpu") {
1446
- throw new Error(`Invalid API ${input.api}`);
1447
- }
1448
- if (!ApiSupport[input.api].isSupported) {
1449
- throw new Error(`${input.api} is not supported`);
1450
- }
1451
- return input.api;
1452
- }
1453
- return this.#getDefaultApi();
1454
- }
1455
- // Assign debug if valid value passed
1456
- static #getValidDebug(input) {
1457
- if (input != null && input.debug != null) {
1458
- if (typeof input.debug === "bigint" || typeof input.debug === "number") {
1459
- input.debug = input.debug.toString();
1460
- }
1461
- if (typeof input.debug === "string") {
1462
- input.debug = ["1", "true", "y", "yes"].includes(input.debug.toLowerCase());
1463
- }
1464
- if (typeof input.debug !== "boolean") {
1465
- throw new Error(`Invalid debug ${input.debug}`);
1466
- }
1467
- return input.debug;
1468
- }
1469
- return false;
1470
- }
1471
- // Assign difficulty if valid value passed
1472
- static #getValidDifficulty(input) {
1473
- if (input != null && input.difficulty != null) {
1474
- if (typeof input.difficulty === "string") {
1475
- try {
1476
- input.difficulty = bigintFrom(input.difficulty, "hex");
1477
- } catch {
1478
- }
1479
- }
1480
- if (typeof input.difficulty !== "bigint") {
1481
- throw new Error(`Invalid difficulty (${typeof input.difficulty})${input.difficulty}`);
1482
- }
1483
- if (input.difficulty < 0x0n || input.difficulty > SEND) {
1484
- throw new Error(`Invalid difficulty ${bigintToHex(input.difficulty, 16)}`);
1485
- }
1486
- return input.difficulty;
1487
- }
1488
- return SEND;
1489
- }
1490
- // Assign effort if valid value passed
1491
- static #getValidEffort(input) {
1492
- if (input != null && input.effort != null) {
1493
- if (typeof input.effort !== "number") {
1494
- throw new Error(`Invalid effort (${typeof input.effort})${input.effort}`);
1495
- }
1496
- if (input.effort < 1 || input.effort > 32) {
1497
- throw new Error(`Invalid effort ${input.effort}`);
1498
- }
1499
- return input.effort;
1500
- }
1501
- return 4;
1502
- }
1503
- };
1504
- var NanoPowConfig = (options) => {
1505
- try {
1506
- return NanoPowConfigConstructor.create(options);
1507
- } catch (err) {
1508
- throw new Error("Error constructing NanoPowConfig", { cause: err });
1509
- }
1510
- };
1511
-
1512
1524
  // src/lib/index.ts
1513
1525
  //! SPDX-FileCopyrightText: 2025 Chris Duncan <chris@codecow.com>
1514
1526
  //! SPDX-License-Identifier: GPL-3.0-or-later
@@ -1520,7 +1532,15 @@ async function work_generate(hash, options) {
1520
1532
  const { api, debug, difficulty, effort } = await NanoPowConfig(options);
1521
1533
  const cached = Cache.search(hash, difficulty);
1522
1534
  if (cached) {
1523
- return cached;
1535
+ const { valid } = validate(bigintFrom(cached.work, "hex"), bigintFrom(cached.hash, "hex"), bigintFrom(cached.difficulty, "hex"), debug);
1536
+ if (valid === "1") {
1537
+ return cached;
1538
+ } else {
1539
+ try {
1540
+ Cache.delete(hash);
1541
+ } catch (err) {
1542
+ }
1543
+ }
1524
1544
  }
1525
1545
  switch (api) {
1526
1546
  case "webgpu": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nano-pow",
3
- "version": "5.1.14",
3
+ "version": "5.1.15",
4
4
  "description": "Proof-of-work generation and validation with WebGPU/WebGL/WASM for Nano cryptocurrency.",
5
5
  "keywords": [
6
6
  "nemo",
@@ -53,10 +53,10 @@
53
53
  "test": "npm run build:dev && ./test/script.sh"
54
54
  },
55
55
  "devDependencies": {
56
- "@types/node": "^25.5.0",
57
- "@webgpu/types": "^0.1.69",
58
- "assemblyscript": "^0.28.12",
59
- "esbuild": "^0.27.4",
56
+ "@types/node": "^25.9.1",
57
+ "@webgpu/types": "^0.1.70",
58
+ "assemblyscript": "^0.28.17",
59
+ "esbuild": "^0.28.0",
60
60
  "esbuild-plugin-glsl": "^1.4.1",
61
61
  "typescript": "^5.9.3"
62
62
  },