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 +144 -153
- package/dist/main.min.js +172 -321
- package/dist/types.d.ts +105 -4
- package/package.json +5 -6
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
|
|
6
|
-
import * as
|
|
7
|
-
|
|
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
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
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
|
-
|
|
26
|
-
|
|
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
|
-
|
|
41
|
+
`);
|
|
42
|
+
process.exit();
|
|
47
43
|
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
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
|
|
56
|
-
let
|
|
57
|
-
|
|
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
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
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
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
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
|
-
|
|
107
|
-
|
|
97
|
+
console.error("Invalid block hash input");
|
|
98
|
+
process.exit(1);
|
|
108
99
|
}
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* Main
|
|
112
|
-
*/
|
|
113
100
|
(async () => {
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
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
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
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
|
+
})();
|