nano-pow 4.1.1 → 4.1.3
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 +27 -11
- package/dist/bin/server.js +53 -17
- package/docs/nano-pow.1 +9 -9
- package/package.json +9 -9
package/dist/bin/cli.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
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 { spawn } from "node:child_process";
|
|
4
5
|
import { getRandomValues } from "node:crypto";
|
|
5
6
|
import { createInterface } from "node:readline/promises";
|
|
6
7
|
process.title = "NanoPow CLI";
|
|
7
|
-
process.env.NANO_POW_DEBUG
|
|
8
|
-
process.env.NANO_POW_EFFORT
|
|
9
|
-
process.env.NANO_POW_PORT
|
|
8
|
+
delete process.env.NANO_POW_DEBUG;
|
|
9
|
+
delete process.env.NANO_POW_EFFORT;
|
|
10
|
+
delete process.env.NANO_POW_PORT;
|
|
10
11
|
function log(...args2) {
|
|
11
12
|
if (process.env.NANO_POW_DEBUG) console.log(new Date(Date.now()).toLocaleString(), "NanoPow", args2);
|
|
12
13
|
}
|
|
@@ -35,16 +36,15 @@ BLOCKHASH is a 64-character hexadecimal string. Multiple blockhashes must be sep
|
|
|
35
36
|
Prints the result as a Javascript object to standard output as soon as it is calculated.
|
|
36
37
|
If using --batch, results are printed only after all BLOCKHASH(es) have be processed.
|
|
37
38
|
If using --validate, results will also include validity properties.
|
|
38
|
-
|
|
39
|
-
-h, --help show this dialog
|
|
40
|
-
--debug enable additional logging output
|
|
41
|
-
--benchmark <value> generate work for specified number of random hashes
|
|
42
|
-
|
|
43
39
|
-b, --batch process all data before returning final results as array
|
|
44
40
|
-d, --difficulty <value> override the minimum difficulty value
|
|
45
41
|
-e, --effort <value> increase demand on GPU processing
|
|
46
42
|
-v, --validate <value> check an existing work value instead of searching for one
|
|
47
43
|
|
|
44
|
+
-h, --help show this dialog
|
|
45
|
+
--debug enable additional logging output
|
|
46
|
+
--benchmark <value> generate work for specified number of random hashes
|
|
47
|
+
|
|
48
48
|
If validating a nonce, it must be a 16-character hexadecimal value.
|
|
49
49
|
Effort must be a decimal number between 1-32.
|
|
50
50
|
Difficulty must be a hexadecimal string between 1-FFFFFFFFFFFFFFFF.
|
|
@@ -121,7 +121,19 @@ for (const stdinErr of stdinErrors) {
|
|
|
121
121
|
log(stdinErr);
|
|
122
122
|
}
|
|
123
123
|
log("Starting NanoPow CLI");
|
|
124
|
-
|
|
124
|
+
const server = spawn(process.execPath, [new URL(import.meta.resolve("./server.js")).pathname], { stdio: ["pipe", "pipe", "pipe", "ipc"] });
|
|
125
|
+
const port = await new Promise((resolve, reject) => {
|
|
126
|
+
server.on("message", (msg) => {
|
|
127
|
+
if (msg.type === "listening") {
|
|
128
|
+
if (msg.port != null) {
|
|
129
|
+
log(`Server listening on port ${msg.port}`);
|
|
130
|
+
resolve(msg.port);
|
|
131
|
+
} else {
|
|
132
|
+
reject("Server failed to provide port");
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
});
|
|
125
137
|
const results = [];
|
|
126
138
|
const aborter = new AbortController();
|
|
127
139
|
if (isBenchmark) console.log("Starting benchmark...");
|
|
@@ -130,7 +142,7 @@ for (const hash of hashes) {
|
|
|
130
142
|
try {
|
|
131
143
|
body.hash = hash;
|
|
132
144
|
const kill = setTimeout(() => aborter.abort(), 6e4);
|
|
133
|
-
const response = await fetch(`http://localhost:${
|
|
145
|
+
const response = await fetch(`http://localhost:${port}`, {
|
|
134
146
|
method: "POST",
|
|
135
147
|
body: JSON.stringify(body),
|
|
136
148
|
signal: aborter.signal
|
|
@@ -151,4 +163,8 @@ if (isBatch && !isBenchmark) console.log(results);
|
|
|
151
163
|
if (process.env.NANO_POW_DEBUG || isBenchmark) {
|
|
152
164
|
console.log(end - start, "ms total |", (end - start) / hashes.length, "ms avg");
|
|
153
165
|
}
|
|
154
|
-
|
|
166
|
+
server.on("close", (code) => {
|
|
167
|
+
log(`Server closed with exit code ${code}`);
|
|
168
|
+
process.exit(code);
|
|
169
|
+
});
|
|
170
|
+
server.kill();
|
package/dist/bin/server.js
CHANGED
|
@@ -3,22 +3,53 @@
|
|
|
3
3
|
//! SPDX-License-Identifier: GPL-3.0-or-later
|
|
4
4
|
import { launch } from "puppeteer";
|
|
5
5
|
import { subtle } from "node:crypto";
|
|
6
|
-
import { lookup } from "node:dns/promises";
|
|
7
6
|
import { readFile, unlink, writeFile } from "node:fs/promises";
|
|
8
7
|
import * as http from "node:http";
|
|
9
|
-
import {
|
|
8
|
+
import { homedir } from "node:os";
|
|
10
9
|
import { join } from "node:path";
|
|
10
|
+
function log(...args) {
|
|
11
|
+
if (CONFIG.DEBUG) console.log(new Date(Date.now()).toLocaleString(), "NanoPow", args);
|
|
12
|
+
}
|
|
11
13
|
process.title = "NanoPow Server";
|
|
12
14
|
const MAX_REQUEST_SIZE = 1024;
|
|
13
15
|
const MAX_BODY_SIZE = 158;
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
function
|
|
20
|
-
|
|
16
|
+
const CONFIG = {
|
|
17
|
+
DEBUG: false,
|
|
18
|
+
EFFORT: 8,
|
|
19
|
+
PORT: 5040
|
|
20
|
+
};
|
|
21
|
+
async function loadConfig() {
|
|
22
|
+
let contents = null;
|
|
23
|
+
try {
|
|
24
|
+
contents = await readFile(join(homedir(), ".nano-pow", "config"), "utf-8");
|
|
25
|
+
} catch (err) {
|
|
26
|
+
log("Config file not found");
|
|
27
|
+
}
|
|
28
|
+
if (typeof contents === "string") {
|
|
29
|
+
for (const line of contents.split("\n")) {
|
|
30
|
+
const debugMatch = line.match(/^[ \t]*debug[ \t]*(true|false)[ \t]*(#.*)?$/i);
|
|
31
|
+
if (Array.isArray(debugMatch)) {
|
|
32
|
+
CONFIG.DEBUG = debugMatch[1] === "true";
|
|
33
|
+
}
|
|
34
|
+
const effortMatch = line.match(/^[ \t]*effort[ \t]*(\d{1,2})[ \t]*(#.*)?$/i);
|
|
35
|
+
if (Array.isArray(effortMatch)) {
|
|
36
|
+
CONFIG.EFFORT = +effortMatch[1];
|
|
37
|
+
}
|
|
38
|
+
const portMatch = line.match(/^[ \t]*port[ \t]*(\d{1,5})[ \t]*(#.*)?$/i);
|
|
39
|
+
if (Array.isArray(portMatch)) {
|
|
40
|
+
CONFIG.PORT = +portMatch[1];
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
CONFIG.DEBUG = !!process.env.NANO_POW_DEBUG || CONFIG.DEBUG;
|
|
45
|
+
CONFIG.EFFORT = +(process.env.NANO_POW_EFFORT ?? "") || CONFIG.EFFORT;
|
|
46
|
+
CONFIG.PORT = process.send ? 0 : +(process.env.NANO_POW_PORT ?? "") || CONFIG.PORT;
|
|
21
47
|
}
|
|
48
|
+
await loadConfig();
|
|
49
|
+
process.on("SIGHUP", async () => {
|
|
50
|
+
log("Reloading configuration");
|
|
51
|
+
await loadConfig();
|
|
52
|
+
});
|
|
22
53
|
async function respond(res, data) {
|
|
23
54
|
let statusCode = 500;
|
|
24
55
|
let headers = { "Content-Type": "application/json" };
|
|
@@ -43,8 +74,8 @@ async function respond(res, data) {
|
|
|
43
74
|
}
|
|
44
75
|
response = `${action} failed`;
|
|
45
76
|
const options = {
|
|
46
|
-
debug: DEBUG,
|
|
47
|
-
effort: EFFORT,
|
|
77
|
+
debug: CONFIG.DEBUG,
|
|
78
|
+
effort: CONFIG.EFFORT,
|
|
48
79
|
difficulty
|
|
49
80
|
};
|
|
50
81
|
const args = [];
|
|
@@ -118,7 +149,8 @@ function shutdown() {
|
|
|
118
149
|
log("Server unresponsive, forcefully stopped");
|
|
119
150
|
process.exit(1);
|
|
120
151
|
}, 1e4);
|
|
121
|
-
server.close(() => {
|
|
152
|
+
server.close(async () => {
|
|
153
|
+
await browser.close();
|
|
122
154
|
clearTimeout(kill);
|
|
123
155
|
log("Server stopped");
|
|
124
156
|
process.exit(0);
|
|
@@ -128,7 +160,10 @@ process.on("SIGINT", shutdown);
|
|
|
128
160
|
process.on("SIGTERM", shutdown);
|
|
129
161
|
log("Starting NanoPow work server");
|
|
130
162
|
const NanoPow = await readFile(new URL("../main.min.js", import.meta.url), "utf-8");
|
|
131
|
-
browser = await launch({
|
|
163
|
+
const browser = await launch({
|
|
164
|
+
handleSIGHUP: false,
|
|
165
|
+
handleSIGINT: false,
|
|
166
|
+
handleSIGTERM: false,
|
|
132
167
|
headless: true,
|
|
133
168
|
args: [
|
|
134
169
|
"--headless=new",
|
|
@@ -138,7 +173,7 @@ browser = await launch({
|
|
|
138
173
|
"--enable-unsafe-webgpu"
|
|
139
174
|
]
|
|
140
175
|
});
|
|
141
|
-
page = await browser.newPage();
|
|
176
|
+
const page = await browser.newPage();
|
|
142
177
|
page.on("console", (msg) => log(msg.text()));
|
|
143
178
|
const path = new URL(import.meta.url).pathname;
|
|
144
179
|
const dir = path.slice(0, path.lastIndexOf("/"));
|
|
@@ -159,7 +194,8 @@ await page.setContent(`
|
|
|
159
194
|
`);
|
|
160
195
|
await unlink(filename);
|
|
161
196
|
log("Puppeteer initialized");
|
|
162
|
-
server.listen(PORT, async () => {
|
|
163
|
-
const
|
|
164
|
-
log(`Server process ${process.pid}
|
|
197
|
+
server.listen(CONFIG.PORT, async () => {
|
|
198
|
+
const { port } = server.address();
|
|
199
|
+
log(`Server process ${process.pid} listening on port ${port}`);
|
|
200
|
+
process.send?.({ type: "listening", port });
|
|
165
201
|
});
|
package/docs/nano-pow.1
CHANGED
|
@@ -25,15 +25,6 @@ If \fB--validate\fR is used, the original work value is returned instead along w
|
|
|
25
25
|
\fB--server\fR
|
|
26
26
|
Start work server (see SERVER below). Must be the first argument in order to be recognized.
|
|
27
27
|
.TP
|
|
28
|
-
\fB\-h\fR, \fB\-\-help\fR
|
|
29
|
-
Show this help dialog and exit.
|
|
30
|
-
.TP
|
|
31
|
-
\fB\-\-debug\fR
|
|
32
|
-
Enable additional logging output.
|
|
33
|
-
.TP
|
|
34
|
-
\fB\-\-benchmark\fR \fICOUNT\fR
|
|
35
|
-
Generate work for the specified number of random hashes.
|
|
36
|
-
.TP
|
|
37
28
|
\fB\-b\fR, \fB\-\-batch\fR
|
|
38
29
|
Format final output of all hashes as a JSON array instead of incrementally returning an object for each result as soon as it is calculated.
|
|
39
30
|
.TP
|
|
@@ -45,6 +36,15 @@ Increase demand on GPU processing. Must be between 1 and 32 inclusive.
|
|
|
45
36
|
.TP
|
|
46
37
|
\fB\-v\fR, \fB\-\-validate\fR \fIWORK\fR
|
|
47
38
|
Check an existing work value instead of searching for one. If you pass multiple blockhashes, the work value will be validated against each one.
|
|
39
|
+
.TP
|
|
40
|
+
\fB\-h\fR, \fB\-\-help\fR
|
|
41
|
+
Show this help dialog and exit.
|
|
42
|
+
.TP
|
|
43
|
+
\fB\-\-debug\fR
|
|
44
|
+
Enable additional logging output.
|
|
45
|
+
.TP
|
|
46
|
+
\fB\-\-benchmark\fR \fICOUNT\fR
|
|
47
|
+
Generate work for the specified number of random hashes.
|
|
48
48
|
|
|
49
49
|
.SH SERVER
|
|
50
50
|
Calling \fBnano-pow\fR with the \fI--server\fR option will start the NanoPow work server in a detached process.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nano-pow",
|
|
3
|
-
"version": "4.1.
|
|
3
|
+
"version": "4.1.3",
|
|
4
4
|
"description": "Proof-of-work generation and validation with WebGPU/WebGL for Nano cryptocurrency.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"nemo",
|
|
@@ -52,11 +52,14 @@
|
|
|
52
52
|
"test": "npm run build && ./test/script.sh"
|
|
53
53
|
},
|
|
54
54
|
"devDependencies": {
|
|
55
|
-
"@types/node": "^22.
|
|
56
|
-
"@webgpu/types": "^0.1.
|
|
57
|
-
"esbuild": "^0.25.
|
|
55
|
+
"@types/node": "^22.14.1",
|
|
56
|
+
"@webgpu/types": "^0.1.60",
|
|
57
|
+
"esbuild": "^0.25.2",
|
|
58
58
|
"esbuild-plugin-glsl": "^1.4.0",
|
|
59
|
-
"typescript": "^5.8.
|
|
59
|
+
"typescript": "^5.8.3"
|
|
60
|
+
},
|
|
61
|
+
"optionalDependencies": {
|
|
62
|
+
"puppeteer": "^24.6.1"
|
|
60
63
|
},
|
|
61
64
|
"type": "module",
|
|
62
65
|
"exports": {
|
|
@@ -66,8 +69,5 @@
|
|
|
66
69
|
}
|
|
67
70
|
},
|
|
68
71
|
"types": "./dist/types.d.ts",
|
|
69
|
-
"unpkg": "./dist/main.min.js"
|
|
70
|
-
"optionalDependencies": {
|
|
71
|
-
"puppeteer": "^24.4.0"
|
|
72
|
-
}
|
|
72
|
+
"unpkg": "./dist/main.min.js"
|
|
73
73
|
}
|