nano-pow 3.1.4 → 3.2.1

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,30 +1,26 @@
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
-
5
- import * as fs from 'node:fs/promises'
6
- import * as readline from 'node:readline/promises'
7
- import * as puppeteer from 'puppeteer'
8
-
9
- const hashes = []
10
-
11
- const stdinErrors = []
4
+ import * as fs from "node:fs/promises";
5
+ import * as readline from "node:readline/promises";
6
+ import * as puppeteer from "puppeteer";
7
+ const hashes = [];
8
+ const stdinErrors = [];
12
9
  if (!process.stdin.isTTY) {
13
- const stdin = readline.createInterface({
14
- input: process.stdin
15
- })
16
- for await (const line of stdin) {
17
- if (/^[0-9A-Fa-f]{64}$/.test(line)) {
18
- hashes.push(line)
19
- } else {
20
- stdinErrors.push(`Skipping invalid stdin input: ${line}`)
21
- }
22
- }
10
+ const stdin = readline.createInterface({
11
+ input: process.stdin
12
+ });
13
+ for await (const line of stdin) {
14
+ if (/^[0-9A-Fa-f]{64}$/.test(line)) {
15
+ hashes.push(line);
16
+ } else {
17
+ stdinErrors.push(`Skipping invalid stdin input: ${line}`);
18
+ }
19
+ }
23
20
  }
24
-
25
- const args = process.argv.slice(2)
26
- if ((hashes.length === 0 && args.length === 0) || (args.some(v => v === '--help' || v === '-h'))) {
27
- console.log(`Usage: nano-pow [OPTION]... BLOCKHASH...
21
+ const args = process.argv.slice(2);
22
+ if (hashes.length === 0 && args.length === 0 || args.some((v) => v === "--help" || v === "-h")) {
23
+ console.log(`Usage: nano-pow [OPTION]... BLOCKHASH...
28
24
  Generate work for BLOCKHASH, or multiple work values for BLOCKHASH(es)
29
25
  BLOCKHASH is a 64-character hexadecimal string. Multiple blockhashes must be separated by whitespace or line breaks.
30
26
  Prints a 16-character hexadecimal work value to standard output. If using --validate, prints 'true' or 'false' to standard output instead.
@@ -42,144 +38,139 @@ Threshold must be a hexadecimal string between 0-FFFFFFFF.
42
38
 
43
39
  Report bugs: <bug-nano-pow@zoso.dev>
44
40
  Full documentation: <https://www.npmjs.com/package/nano-pow>
45
- `)
46
- process.exit()
41
+ `);
42
+ process.exit();
47
43
  }
48
-
49
- const inArgs = []
50
- while (/^[0-9A-Fa-f]{64}$/.test(args[args.length - 1] ?? '')) {
51
- inArgs.unshift(args.pop())
44
+ const inArgs = [];
45
+ while (/^[0-9A-Fa-f]{64}$/.test(args[args.length - 1] ?? "")) {
46
+ inArgs.unshift(args.pop());
52
47
  }
53
- hashes.push(...inArgs)
54
-
55
- let fn = 'search'
56
- let work = ''
57
- let isJson = false
58
- const options = {}
59
-
48
+ hashes.push(...inArgs);
49
+ let fn = "work_generate";
50
+ let work = "";
51
+ let isJson = false;
52
+ const options = {};
60
53
  for (let i = 0; i < args.length; i++) {
61
- switch (args[i]) {
62
- case ('--validate'):
63
- case ('-v'): {
64
- if (args[i + 1] == null) throw new Error('Missing argument for work validation')
65
- if (!/^[0-9A-Fa-f]{16}$/.test(args[i + 1])) throw new Error('Invalid work to validate')
66
- fn = 'validate'
67
- work = `'${args[i + 1]}', `
68
- break
69
- }
70
- case ('--threshold'):
71
- case ('-t'): {
72
- if (args[i + 1] == null) throw new Error('Missing argument for threshold')
73
- if (!/^[0-9A-Fa-f]{0,8}$/.test(args[i + 1])) throw new Error('Invalid threshold')
74
- options['threshold'] = parseInt(args[i + 1], 16)
75
- break
76
- }
77
- case ('--effort'):
78
- case ('-e'): {
79
- if (args[i + 1] == null) throw new Error('Missing argument for effort')
80
- if (!/^[0-9]{0,2}$/.test(args[i + 1])) throw new Error('Invalid effort')
81
- options['effort'] = parseInt(args[i + 1], 10)
82
- break
83
- }
84
- case ('--debug'):
85
- case ('-d'): {
86
- options['debug'] = true
87
- break
88
- }
89
- case ('--json'):
90
- case ('-j'): {
91
- isJson = true
92
- break
93
- }
94
- }
54
+ switch (args[i]) {
55
+ case "--validate":
56
+ case "-v": {
57
+ if (args[i + 1] == null) throw new Error("Missing argument for work validation");
58
+ if (!/^[0-9A-Fa-f]{16}$/.test(args[i + 1])) throw new Error("Invalid work to validate");
59
+ fn = "work_validate";
60
+ work = `'${args[i + 1]}', `;
61
+ break;
62
+ }
63
+ case "--threshold":
64
+ case "-t": {
65
+ if (args[i + 1] == null) throw new Error("Missing argument for threshold");
66
+ if (!/^[0-9A-Fa-f]{0,8}$/.test(args[i + 1])) throw new Error("Invalid threshold");
67
+ options["threshold"] = parseInt(args[i + 1], 16);
68
+ break;
69
+ }
70
+ case "--effort":
71
+ case "-e": {
72
+ if (args[i + 1] == null) throw new Error("Missing argument for effort");
73
+ if (!/^[0-9]{0,2}$/.test(args[i + 1])) throw new Error("Invalid effort");
74
+ options["effort"] = parseInt(args[i + 1], 10);
75
+ break;
76
+ }
77
+ case "--debug":
78
+ case "-d": {
79
+ options["debug"] = true;
80
+ break;
81
+ }
82
+ case "--json":
83
+ case "-j": {
84
+ isJson = true;
85
+ break;
86
+ }
87
+ }
95
88
  }
96
-
97
- if (options['debug']) {
98
- console.log(`NanoPowCli.${fn}()`)
99
- console.log(`${fn} options`, JSON.stringify(options))
100
- for (const stdinErr of stdinErrors) {
101
- console.warn(stdinErr)
102
- }
89
+ if (options["debug"]) {
90
+ console.log(`NanoPowCli.${fn}()`);
91
+ console.log(`${fn} options`, JSON.stringify(options));
92
+ for (const stdinErr of stdinErrors) {
93
+ console.warn(stdinErr);
94
+ }
103
95
  }
104
-
105
96
  if (hashes.length === 0) {
106
- console.error('Invalid block hash input')
107
- process.exit(1)
97
+ console.error("Invalid block hash input");
98
+ process.exit(1);
108
99
  }
109
-
110
- /**
111
- * Main
112
- */
113
100
  (async () => {
114
- const NanoPow = await fs.readFile(new URL('../main.min.js', import.meta.url), 'utf-8')
115
- const browser = await puppeteer.launch({
116
- headless: true,
117
- args: [
118
- '--no-sandbox',
119
- '--headless=new',
120
- '--use-angle=vulkan',
121
- '--enable-features=Vulkan',
122
- '--disable-vulkan-surface',
123
- '--enable-unsafe-webgpu',
124
- '--enable-vulkan'
125
- ]
126
- })
127
- const page = await browser.newPage()
128
- await page.setBypassCSP(true)
129
- await page.goto('chrome://terms')
130
-
131
- let start = performance.now()
132
- page.on('console', async (msg) => {
133
- const output = msg.text().split(' ')
134
- if (output[0] === 'cli') {
135
- if (output[1] === 'exit') {
136
- if (isJson) {
137
- const results = await page.evaluate(() => {
138
- return window.results
139
- })
140
- for (let i = 0; i < results.length; i++) {
141
- results[i] = {
142
- blockhash: hashes[i],
143
- work: results[i]
144
- }
145
- }
146
- console.log(JSON.stringify(results, null, 4))
147
- }
148
- const end = performance.now()
149
- if (options['debug']) console.log(end - start, 'ms total |', (end - start) / hashes.length, 'ms avg')
150
- await browser.close()
151
- } else if (!isJson) {
152
- console.log(output[1])
101
+ const NanoPow = await fs.readFile(new URL("../main.min.js", import.meta.url), "utf-8");
102
+ const browser = await puppeteer.launch({
103
+ headless: true,
104
+ args: [
105
+ "--headless=new",
106
+ "--use-angle=vulkan",
107
+ "--enable-features=Vulkan",
108
+ "--disable-vulkan-surface",
109
+ "--enable-unsafe-webgpu"
110
+ ]
111
+ });
112
+ const page = await browser.newPage();
113
+ const cliPage = `${import.meta.dirname}/cli.html`;
114
+ await fs.writeFile(cliPage, "");
115
+ await page.goto(import.meta.resolve("./cli.html"));
116
+ await page.waitForFunction(async () => {
117
+ return await navigator.gpu.requestAdapter();
118
+ });
119
+ const inject = `
120
+ ${NanoPow}
121
+ window.results = []
122
+ const hashes = ["${hashes.join('","')}"]
123
+ for (const hash of hashes) {
124
+ 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)}\`)
128
+ } catch (err) {
129
+ console.error(\`cli \${err}\`)
153
130
  }
154
- } else if (options['debug']) {
155
- console.log(msg.text())
156
131
  }
157
- })
158
- await page.waitForFunction(async () => {
159
- return await navigator.gpu.requestAdapter()
160
- })
161
- start = performance.now()
162
- await page.addScriptTag({
163
- type: 'module',
164
- content: `
165
- window.trustedTypes?.createPolicy?.('default', {
166
- createHTML: string => string,
167
- createScriptURL: string => string,
168
- createScript: string => string,
169
- })
170
- ${NanoPow}
171
- window.results = []
172
- const hashes = ["${hashes.join('","')}"]
173
- for (const hash of hashes) {
174
- try {
175
- const work = await NanoPow.${fn}(${work}hash, ${JSON.stringify(options)})
176
- window.results.push(work)
177
- console.log(\`cli \${work}\`)
178
- } catch (err) {
179
- console.error(\`cli \${err}\`)
180
- }
181
- }
182
- console.log('cli exit')
183
- `
184
- })
185
- })()
132
+ console.log('cli exit')
133
+ `;
134
+ const hash = await crypto.subtle.digest("SHA-256", Buffer.from(inject, "utf-8"));
135
+ const src = `sha256-${Buffer.from(hash).toString("base64")}`;
136
+ let start = performance.now();
137
+ page.on("console", async (msg) => {
138
+ const output = msg.text().split(/^cli /);
139
+ if (output[0] === "") {
140
+ if (output[1] === "exit") {
141
+ if (isJson) {
142
+ const results = await page.evaluate(() => {
143
+ return window.results;
144
+ });
145
+ console.log(JSON.stringify(results, null, 4));
146
+ }
147
+ const end = performance.now();
148
+ if (options["debug"]) console.log(end - start, "ms total |", (end - start) / hashes.length, "ms avg");
149
+ await browser.close();
150
+ } else if (!isJson) {
151
+ try {
152
+ console.log(JSON.parse(output[1]));
153
+ } catch (err) {
154
+ console.log(output[1]);
155
+ }
156
+ }
157
+ } else if (options["debug"]) {
158
+ try {
159
+ console.log(JSON.parse(msg.text()));
160
+ } catch (err) {
161
+ console.log(msg.text());
162
+ }
163
+ }
164
+ });
165
+ start = performance.now();
166
+ await page.setContent(`
167
+ <!DOCTYPE html>
168
+ <head>
169
+ <meta http-equiv="Content-Security-Policy" content="default-src 'none'; base-uri 'none'; form-action 'none'; script-src '${src}';">
170
+ <script type="module">${inject}</script>
171
+ </head>
172
+ </html>
173
+ `);
174
+ await fs.unlink(cliPage);
175
+ if (options["debug"]) console.log("Puppeteer initialized");
176
+ })();