nano-pow 3.2.1 → 3.2.2

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/dist/bin/cli.js CHANGED
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  //! SPDX-FileCopyrightText: 2025 Chris Duncan <chris@zoso.dev>
3
3
  //! SPDX-License-Identifier: GPL-3.0-or-later
4
+ import * as crypto from "node:crypto";
4
5
  import * as fs from "node:fs/promises";
5
6
  import * as readline from "node:readline/promises";
6
7
  import * as puppeteer from "puppeteer";
@@ -46,7 +47,7 @@ while (/^[0-9A-Fa-f]{64}$/.test(args[args.length - 1] ?? "")) {
46
47
  inArgs.unshift(args.pop());
47
48
  }
48
49
  hashes.push(...inArgs);
49
- let fn = "work_generate";
50
+ let fn = "search";
50
51
  let work = "";
51
52
  let isJson = false;
52
53
  const options = {};
@@ -56,7 +57,7 @@ for (let i = 0; i < args.length; i++) {
56
57
  case "-v": {
57
58
  if (args[i + 1] == null) throw new Error("Missing argument for work validation");
58
59
  if (!/^[0-9A-Fa-f]{16}$/.test(args[i + 1])) throw new Error("Invalid work to validate");
59
- fn = "work_validate";
60
+ fn = "validate";
60
61
  work = `'${args[i + 1]}', `;
61
62
  break;
62
63
  }
@@ -110,8 +111,9 @@ if (hashes.length === 0) {
110
111
  ]
111
112
  });
112
113
  const page = await browser.newPage();
113
- const cliPage = `${import.meta.dirname}/cli.html`;
114
- await fs.writeFile(cliPage, "");
114
+ const path = new URL(import.meta.url).pathname;
115
+ const dir = path.slice(0, path.lastIndexOf("/"));
116
+ await fs.writeFile(`${dir}/cli.html`, "");
115
117
  await page.goto(import.meta.resolve("./cli.html"));
116
118
  await page.waitForFunction(async () => {
117
119
  return await navigator.gpu.requestAdapter();
@@ -122,9 +124,9 @@ if (hashes.length === 0) {
122
124
  const hashes = ["${hashes.join('","')}"]
123
125
  for (const hash of hashes) {
124
126
  try {
125
- const result = await NanoPow.${fn}(${work}hash, ${JSON.stringify(options)})
126
- window.results.push(result)
127
- console.log(\`cli \${JSON.stringify(result, null, 4)}\`)
127
+ const work = await NanoPow.${fn}(${work}hash, ${JSON.stringify(options)})
128
+ window.results.push(work)
129
+ console.log(\`cli \${work}\`)
128
130
  } catch (err) {
129
131
  console.error(\`cli \${err}\`)
130
132
  }
@@ -135,13 +137,19 @@ if (hashes.length === 0) {
135
137
  const src = `sha256-${Buffer.from(hash).toString("base64")}`;
136
138
  let start = performance.now();
137
139
  page.on("console", async (msg) => {
138
- const output = msg.text().split(/^cli /);
140
+ const output = msg.text().split("/^cli /");
139
141
  if (output[0] === "") {
140
142
  if (output[1] === "exit") {
141
143
  if (isJson) {
142
144
  const results = await page.evaluate(() => {
143
145
  return window.results;
144
146
  });
147
+ for (let i = 0; i < results.length; i++) {
148
+ results[i] = {
149
+ blockhash: hashes[i],
150
+ work: results[i]
151
+ };
152
+ }
145
153
  console.log(JSON.stringify(results, null, 4));
146
154
  }
147
155
  const end = performance.now();
@@ -171,6 +179,6 @@ if (hashes.length === 0) {
171
179
  </head>
172
180
  </html>
173
181
  `);
174
- await fs.unlink(cliPage);
182
+ await fs.unlink(`${dir}/cli.html`);
175
183
  if (options["debug"]) console.log("Puppeteer initialized");
176
184
  })();
package/dist/main.min.js CHANGED
@@ -43,6 +43,7 @@ layout(location=0)in vec4 position;void main(){gl_Position=position;}`;
43
43
  var NanoPowGl = class _NanoPowGl {
44
44
  static #SEND = 0xfffffff800000000n;
45
45
  static #RECEIVE = 0xfffffe0000000000n;
46
+ static #isInitialized = false;
46
47
  static #busy = false;
47
48
  static #debug = false;
48
49
  static #raf = 0;
@@ -187,12 +188,13 @@ var NanoPowGl = class _NanoPowGl {
187
188
  this.#gl.bindBuffer(this.#gl.UNIFORM_BUFFER, null);
188
189
  this.#query = this.#gl.createQuery();
189
190
  this.#pixels = new Uint32Array(this.size * 4);
190
- console.log(`NanoPow WebGL initialized at ${this.#gl.drawingBufferWidth}x${this.#gl.drawingBufferHeight}. Maximum nonces checked per frame: ${this.size}`);
191
191
  } catch (err) {
192
192
  throw new Error("WebGL initialization failed.", { cause: err });
193
193
  } finally {
194
194
  this.#busy = false;
195
195
  }
196
+ this.#isInitialized = true;
197
+ console.log(`NanoPow WebGL initialized at ${this.#gl.drawingBufferWidth}x${this.#gl.drawingBufferHeight}. Maximum nonces checked per frame: ${this.size}`);
196
198
  }
197
199
  /**
198
200
  * On WebGL context loss, attempts to clear all program variables and then
@@ -361,6 +363,7 @@ var NanoPowGl = class _NanoPowGl {
361
363
  * @param {NanoPowOptions} options - Options used to configure search execution
362
364
  */
363
365
  static async work_generate(hash, options) {
366
+ if (!/^[A-Fa-f0-9]{64}$/.test(hash)) throw new Error(`Invalid hash ${hash}`);
364
367
  if (this.#busy) {
365
368
  console.log("NanoPowGl is busy. Retrying search...");
366
369
  return new Promise((resolve) => {
@@ -370,8 +373,8 @@ var NanoPowGl = class _NanoPowGl {
370
373
  }, 100);
371
374
  });
372
375
  }
376
+ if (this.#isInitialized === false) this.init();
373
377
  this.#busy = true;
374
- if (!/^[A-Fa-f0-9]{64}$/.test(hash)) throw new Error(`Invalid hash ${hash}`);
375
378
  const threshold = typeof options?.threshold !== "bigint" || options.threshold < 1n || options.threshold > 0xffffffffffffffffn ? 0xfffffff800000000n : options.threshold;
376
379
  const effort = typeof options?.effort !== "number" || options.effort < 1 || options.effort > 32 ? this.#cores : options.effort;
377
380
  this.#debug = !!options?.debug;
@@ -451,6 +454,8 @@ var NanoPowGl = class _NanoPowGl {
451
454
  * @param {NanoPowOptions} options - Options used to configure search execution
452
455
  */
453
456
  static async work_validate(work, hash, options) {
457
+ if (!/^[A-Fa-f0-9]{16}$/.test(work)) throw new Error(`Invalid work ${work}`);
458
+ if (!/^[A-Fa-f0-9]{64}$/.test(hash)) throw new Error(`Invalid hash ${hash}`);
454
459
  if (this.#busy) {
455
460
  console.log("NanoPowGl is busy. Retrying validate...");
456
461
  return new Promise((resolve) => {
@@ -460,9 +465,8 @@ var NanoPowGl = class _NanoPowGl {
460
465
  }, 100);
461
466
  });
462
467
  }
468
+ if (this.#isInitialized === false) this.init();
463
469
  this.#busy = true;
464
- if (!/^[A-Fa-f0-9]{16}$/.test(work)) throw new Error(`Invalid work ${work}`);
465
- if (!/^[A-Fa-f0-9]{64}$/.test(hash)) throw new Error(`Invalid hash ${hash}`);
466
470
  const threshold = typeof options?.threshold !== "bigint" || options.threshold < 1n || options.threshold > 0xffffffffffffffffn ? 0xfffffff800000000n : options.threshold;
467
471
  this.#debug = !!options?.debug;
468
472
  if (this.#debug) console.log("NanoPowGl.validate()");
@@ -527,6 +531,7 @@ var NanoPowGpu = class _NanoPowGpu {
527
531
  static #SEND = 0xfffffff800000000n;
528
532
  static #RECEIVE = 0xfffffe0000000000n;
529
533
  // Initialize WebGPU
534
+ static #isInitialized = false;
530
535
  static #busy = false;
531
536
  static #debug = false;
532
537
  static #device = null;
@@ -556,6 +561,7 @@ var NanoPowGpu = class _NanoPowGpu {
556
561
  } finally {
557
562
  this.#busy = false;
558
563
  }
564
+ this.#isInitialized = true;
559
565
  }
560
566
  static setup() {
561
567
  if (this.#device == null) throw new Error(`WebGPU device failed to load.`);
@@ -730,6 +736,7 @@ var NanoPowGpu = class _NanoPowGpu {
730
736
  }, 100);
731
737
  });
732
738
  }
739
+ if (this.#isInitialized === false) this.init();
733
740
  this.#busy = true;
734
741
  const threshold = typeof options?.threshold !== "bigint" || options.threshold < 1n || options.threshold > 0xffffffffffffffffn ? 0xfffffff800000000n : options.threshold;
735
742
  const effort = typeof options?.effort !== "number" || options.effort < 1 || options.effort > 32 ? 2048 : options.effort * 256;
@@ -806,6 +813,7 @@ var NanoPowGpu = class _NanoPowGpu {
806
813
  }, 100);
807
814
  });
808
815
  }
816
+ if (this.#isInitialized === false) this.init();
809
817
  this.#busy = true;
810
818
  const threshold = typeof options?.threshold !== "bigint" || options.threshold < 1n || options.threshold > 0xffffffffffffffffn ? 0xfffffff800000000n : options.threshold;
811
819
  this.#debug = !!options?.debug;
@@ -850,15 +858,15 @@ var NanoPowGpu = class _NanoPowGpu {
850
858
  var isGlSupported;
851
859
  var isGpuSupported = false;
852
860
  try {
853
- await NanoPowGpu.init();
854
- isGpuSupported = true;
861
+ const adapter = await navigator?.gpu?.requestAdapter?.();
862
+ isGpuSupported = adapter instanceof GPUAdapter;
855
863
  } catch (err) {
856
864
  console.warn("WebGPU is not supported in this environment.\n", err);
857
865
  isGpuSupported = false;
858
866
  }
859
867
  try {
860
- await NanoPowGl.init();
861
- isGlSupported = true;
868
+ const gl = new OffscreenCanvas(0, 0)?.getContext?.("webgl2");
869
+ isGlSupported = gl instanceof WebGL2RenderingContext;
862
870
  } catch (err) {
863
871
  console.warn("WebGL is not supported in this environment.\n", err);
864
872
  isGlSupported = false;
package/dist/types.d.ts CHANGED
@@ -105,7 +105,7 @@ export type NanoPowOptions = {
105
105
  export declare class NanoPowGl {
106
106
  #private
107
107
  /** Drawing buffer width in pixels. */
108
- static get size (): number | undefined
108
+ static get size (): number
109
109
  /**
110
110
  * Constructs canvas, gets WebGL context, initializes buffers, and compiles
111
111
  * shaders.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nano-pow",
3
- "version": "3.2.1",
3
+ "version": "3.2.2",
4
4
  "description": "Proof-of-work generation and validation with WebGPU/WebGL for Nano cryptocurrency.",
5
5
  "keywords": [
6
6
  "nemo",