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 +7 -3
- package/dist/bin/cli.js +12 -0
- package/dist/bin/server.js +12 -0
- package/dist/main.min.js +148 -128
- package/package.json +5 -5
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
|
|
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
|
|
75
|
-
|
|
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");
|
package/dist/bin/server.js
CHANGED
|
@@ -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 =
|
|
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 =
|
|
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
|
|
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
|
-
|
|
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.
|
|
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.
|
|
57
|
-
"@webgpu/types": "^0.1.
|
|
58
|
-
"assemblyscript": "^0.28.
|
|
59
|
-
"esbuild": "^0.
|
|
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
|
},
|