nano-pow 3.1.2 → 3.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/README.md +2 -1
- package/dist/cli.js +58 -13
- package/dist/main.min.js +62 -32
- package/dist/nano-pow.1 +6 -2
- package/package.json +9 -7
package/README.md
CHANGED
|
@@ -143,7 +143,8 @@ Email: <bug-nano-pow@zoso.dev>
|
|
|
143
143
|
implementation
|
|
144
144
|
|
|
145
145
|
## Licenses
|
|
146
|
-
|
|
146
|
+
GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>
|
|
147
|
+
Portions of this code are also provided under the MIT License: <https://spdx.org/licenses/MIT.html>
|
|
147
148
|
|
|
148
149
|
## Donations
|
|
149
150
|
If you find this package helpful, please consider tipping the developer.
|
package/dist/cli.js
CHANGED
|
@@ -2,11 +2,28 @@
|
|
|
2
2
|
//! SPDX-FileCopyrightText: 2025 Chris Duncan <chris@zoso.dev>
|
|
3
3
|
//! SPDX-License-Identifier: GPL-3.0-or-later
|
|
4
4
|
|
|
5
|
-
import * as puppeteer from 'puppeteer'
|
|
6
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 = []
|
|
12
|
+
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
|
+
}
|
|
23
|
+
}
|
|
7
24
|
|
|
8
25
|
const args = process.argv.slice(2)
|
|
9
|
-
if (args.length === 0 || args.some(v => v === '--help' || v === '-h')) {
|
|
26
|
+
if ((hashes.length === 0 && args.length === 0) || (args.some(v => v === '--help' || v === '-h'))) {
|
|
10
27
|
console.log(`Usage: nano-pow [OPTION]... BLOCKHASH...
|
|
11
28
|
Generate work for BLOCKHASH, or multiple work values for BLOCKHASH(es)
|
|
12
29
|
BLOCKHASH is a 64-character hexadecimal string. Multiple blockhashes must be separated by whitespace or line breaks.
|
|
@@ -14,6 +31,7 @@ Prints a 16-character hexadecimal work value to standard output. If using --vali
|
|
|
14
31
|
|
|
15
32
|
-h, --help show this dialog
|
|
16
33
|
-d, --debug enable additional logging output
|
|
34
|
+
-j, --json format output as JSON
|
|
17
35
|
-e, --effort=<value> increase demand on GPU processing
|
|
18
36
|
-t, --threshold=<value> override the minimum threshold value
|
|
19
37
|
-v, --validate=<value> check an existing work value instead of searching for one
|
|
@@ -28,18 +46,17 @@ Full documentation: <https://www.npmjs.com/package/nano-pow>
|
|
|
28
46
|
process.exit()
|
|
29
47
|
}
|
|
30
48
|
|
|
31
|
-
const
|
|
49
|
+
const inArgs = []
|
|
32
50
|
while (/^[0-9A-Fa-f]{64}$/.test(args[args.length - 1] ?? '')) {
|
|
33
|
-
|
|
34
|
-
}
|
|
35
|
-
if (hashes.length === 0) {
|
|
36
|
-
console.error('Invalid block hash input')
|
|
37
|
-
process.exit(1)
|
|
51
|
+
inArgs.unshift(args.pop())
|
|
38
52
|
}
|
|
53
|
+
hashes.push(...inArgs)
|
|
39
54
|
|
|
40
55
|
let fn = 'search'
|
|
41
56
|
let work = ''
|
|
57
|
+
let isJson = false
|
|
42
58
|
const options = {}
|
|
59
|
+
|
|
43
60
|
for (let i = 0; i < args.length; i++) {
|
|
44
61
|
switch (args[i]) {
|
|
45
62
|
case ('--validate'):
|
|
@@ -69,13 +86,27 @@ for (let i = 0; i < args.length; i++) {
|
|
|
69
86
|
options['debug'] = true
|
|
70
87
|
break
|
|
71
88
|
}
|
|
89
|
+
case ('--json'):
|
|
90
|
+
case ('-j'): {
|
|
91
|
+
isJson = true
|
|
92
|
+
break
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
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)
|
|
72
102
|
}
|
|
73
103
|
}
|
|
74
104
|
|
|
75
|
-
if (
|
|
76
|
-
|
|
105
|
+
if (hashes.length === 0) {
|
|
106
|
+
console.error('Invalid block hash input')
|
|
107
|
+
process.exit(1)
|
|
108
|
+
}
|
|
77
109
|
|
|
78
|
-
;
|
|
79
110
|
/**
|
|
80
111
|
* Main
|
|
81
112
|
*/
|
|
@@ -102,10 +133,22 @@ if (options['debug']) console.log(`${fn} options`, JSON.stringify(options))
|
|
|
102
133
|
const output = msg.text().split(' ')
|
|
103
134
|
if (output[0] === 'cli') {
|
|
104
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
|
+
}
|
|
105
148
|
const end = performance.now()
|
|
106
149
|
if (options['debug']) console.log(end - start, 'ms total |', (end - start) / hashes.length, 'ms avg')
|
|
107
|
-
|
|
108
|
-
} else {
|
|
150
|
+
await browser.close()
|
|
151
|
+
} else if (!isJson) {
|
|
109
152
|
console.log(output[1])
|
|
110
153
|
}
|
|
111
154
|
} else if (options['debug']) {
|
|
@@ -125,10 +168,12 @@ if (options['debug']) console.log(`${fn} options`, JSON.stringify(options))
|
|
|
125
168
|
createScript: string => string,
|
|
126
169
|
})
|
|
127
170
|
${NanoPow}
|
|
171
|
+
window.results = []
|
|
128
172
|
const hashes = ["${hashes.join('","')}"]
|
|
129
173
|
for (const hash of hashes) {
|
|
130
174
|
try {
|
|
131
175
|
const work = await NanoPow.${fn}(${work}hash, ${JSON.stringify(options)})
|
|
176
|
+
window.results.push(work)
|
|
132
177
|
console.log(\`cli \${work}\`)
|
|
133
178
|
} catch (err) {
|
|
134
179
|
console.error(\`cli \${err}\`)
|
package/dist/main.min.js
CHANGED
|
@@ -68,6 +68,66 @@ layout(std140) uniform WORK {
|
|
|
68
68
|
uvec2 seed;
|
|
69
69
|
};
|
|
70
70
|
|
|
71
|
+
/**
|
|
72
|
+
* Initialization vector defined by BLAKE2. Each vec2<u32> represents two halves
|
|
73
|
+
* of the original u64 value from the reference implementation. They appear
|
|
74
|
+
* reversed pairwise as defined below, but this is an illusion due to endianness:
|
|
75
|
+
* the \`x\` component of the vector is the low bits and the \`y\` component is the
|
|
76
|
+
* high bits, and if you laid the bits out individually, they would match the
|
|
77
|
+
* little-endian 64-bit representation.
|
|
78
|
+
*/
|
|
79
|
+
const uvec2 BLAKE2B_IV[8] = uvec2[8](
|
|
80
|
+
uvec2(0xF3BCC908u, 0x6A09E667u),
|
|
81
|
+
uvec2(0x84CAA73Bu, 0xBB67AE85u),
|
|
82
|
+
uvec2(0xFE94F82Bu, 0x3C6EF372u),
|
|
83
|
+
uvec2(0x5F1D36F1u, 0xA54FF53Au),
|
|
84
|
+
uvec2(0xADE682D1u, 0x510E527Fu),
|
|
85
|
+
uvec2(0x2B3E6C1Fu, 0x9B05688Cu),
|
|
86
|
+
uvec2(0xFB41BD6Bu, 0x1F83D9ABu),
|
|
87
|
+
uvec2(0x137E2179u, 0x5BE0CD19u)
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Parameter block as defined in BLAKE2 section 2.8 and configured as follows:
|
|
92
|
+
* maximal depth = 1, fanout = 1, digest byte length = 8
|
|
93
|
+
*/
|
|
94
|
+
const uvec2 BLAKE2B_PARAM = uvec2(0x01010008u, 0u);
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Message input length which is always 40 for Nano.
|
|
98
|
+
* 8 nonce bytes + 32 block hash bytes
|
|
99
|
+
*/
|
|
100
|
+
const uvec2 BLAKE2B_INLEN = uvec2(0x00000028u, 0u);
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Finalization flag as defined in BLAKE2 section 2.4 and set to ~0 since this is
|
|
104
|
+
* the final (and only) message block being hashed.
|
|
105
|
+
*/
|
|
106
|
+
const uvec2 BLAKE2B_FINAL = uvec2(0xFFFFFFFFu, 0xFFFFFFFFu);
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Fully initialized state array that is locally copied at each thread start.
|
|
110
|
+
* Application of each XOR is defined by BLAKE2 section 2.4 compression function.
|
|
111
|
+
*/
|
|
112
|
+
const uvec2 BLAKE2B_INIT[16] = uvec2[16](
|
|
113
|
+
BLAKE2B_IV[0u] ^ BLAKE2B_PARAM,
|
|
114
|
+
BLAKE2B_IV[1u],
|
|
115
|
+
BLAKE2B_IV[2u],
|
|
116
|
+
BLAKE2B_IV[3u],
|
|
117
|
+
BLAKE2B_IV[4u],
|
|
118
|
+
BLAKE2B_IV[5u],
|
|
119
|
+
BLAKE2B_IV[6u],
|
|
120
|
+
BLAKE2B_IV[7u],
|
|
121
|
+
BLAKE2B_IV[0u],
|
|
122
|
+
BLAKE2B_IV[1u],
|
|
123
|
+
BLAKE2B_IV[2u],
|
|
124
|
+
BLAKE2B_IV[3u],
|
|
125
|
+
BLAKE2B_IV[4u] ^ BLAKE2B_INLEN,
|
|
126
|
+
BLAKE2B_IV[5u],
|
|
127
|
+
BLAKE2B_IV[6u] ^ BLAKE2B_FINAL,
|
|
128
|
+
BLAKE2B_IV[7u]
|
|
129
|
+
);
|
|
130
|
+
|
|
71
131
|
// Defined separately from uint v[0].y below as the original value is required
|
|
72
132
|
// to calculate the second uint32 of the digest for threshold comparison
|
|
73
133
|
const uint BLAKE2B_IV32_1 = 0x6A09E667u;
|
|
@@ -79,36 +139,6 @@ const uvec4 ROTATE_16 = uvec4(16u);
|
|
|
79
139
|
const uvec4 ROTATE_24 = uvec4(24u);
|
|
80
140
|
const uvec4 ROTATE_31 = uvec4(31u);
|
|
81
141
|
|
|
82
|
-
// Both buffers represent 16 uint64s as 32 uint32s
|
|
83
|
-
// because that's what GLSL offers, just like Javascript
|
|
84
|
-
|
|
85
|
-
// Compression buffer, intialized to 2 instances of the initialization vector
|
|
86
|
-
// The following values have been modified from the BLAKE2B_IV:
|
|
87
|
-
// OUTLEN is constant 8 bytes
|
|
88
|
-
// v[0] ^= 0x01010000u ^ uint(OUTLEN);
|
|
89
|
-
// INLEN is constant 40 bytes: work value (8) + block hash (32)
|
|
90
|
-
// v[12] ^= uint(INLEN);
|
|
91
|
-
// It's always the "last" compression at this INLEN
|
|
92
|
-
// v[14] = ~v[14];
|
|
93
|
-
const uvec2 blake2b_iv[16] = uvec2[16](
|
|
94
|
-
uvec2(0xF2BDC900u, 0x6A09E667u),
|
|
95
|
-
uvec2(0x84CAA73Bu, 0xBB67AE85u),
|
|
96
|
-
uvec2(0xFE94F82Bu, 0x3C6EF372u),
|
|
97
|
-
uvec2(0x5F1D36F1u, 0xA54FF53Au),
|
|
98
|
-
uvec2(0xADE682D1u, 0x510E527Fu),
|
|
99
|
-
uvec2(0x2B3E6C1Fu, 0x9B05688Cu),
|
|
100
|
-
uvec2(0xFB41BD6Bu, 0x1F83D9ABu),
|
|
101
|
-
uvec2(0x137E2179u, 0x5BE0CD19u),
|
|
102
|
-
uvec2(0xF3BCC908u, 0x6A09E667u),
|
|
103
|
-
uvec2(0x84CAA73Bu, 0xBB67AE85u),
|
|
104
|
-
uvec2(0xFE94F82Bu, 0x3C6EF372u),
|
|
105
|
-
uvec2(0x5F1D36F1u, 0xA54FF53Au),
|
|
106
|
-
uvec2(0xADE682F9u, 0x510E527Fu),
|
|
107
|
-
uvec2(0x2B3E6C1Fu, 0x9B05688Cu),
|
|
108
|
-
uvec2(0x04BE4294u, 0xE07C2654u),
|
|
109
|
-
uvec2(0x137E2179u, 0x5BE0CD19u)
|
|
110
|
-
);
|
|
111
|
-
|
|
112
142
|
// Iterated initialization vector
|
|
113
143
|
uvec2 v[16];
|
|
114
144
|
|
|
@@ -162,7 +192,7 @@ void main() {
|
|
|
162
192
|
m[4u] = uvec2(blockhash[6u], blockhash[7u]);
|
|
163
193
|
|
|
164
194
|
// Reset v
|
|
165
|
-
v =
|
|
195
|
+
v = BLAKE2B_INIT;
|
|
166
196
|
|
|
167
197
|
// Twelve rounds of G mixing
|
|
168
198
|
|
|
@@ -240,7 +270,7 @@ void main() {
|
|
|
240
270
|
|
|
241
271
|
// Pixel data set from work seed values
|
|
242
272
|
// Finalize digest from high bits, low bits can be safely ignored
|
|
243
|
-
if ((
|
|
273
|
+
if ((BLAKE2B_INIT[0u].y ^ v[0u].y ^ v[8u].y) >= threshold && (search || uvec2(gl_FragCoord) == uvec2(0u))) {
|
|
244
274
|
nonce = uvec4(1u, m[0u].y, m[0u].x, (uint(gl_FragCoord.x) << 16u) | uint(gl_FragCoord.y));
|
|
245
275
|
}
|
|
246
276
|
|
package/dist/nano-pow.1
CHANGED
|
@@ -24,6 +24,9 @@ Show this help dialog and exit.
|
|
|
24
24
|
\fB\-d\fR, \fB\-\-debug\fR
|
|
25
25
|
Enable additional logging output.
|
|
26
26
|
.TP
|
|
27
|
+
\fB\-j\fR, \fB\-\-json\fR
|
|
28
|
+
Format output as JSON.
|
|
29
|
+
.TP
|
|
27
30
|
\fB\-e\fR, \fB\-\-effort\fR=\fIEFFORT\fR
|
|
28
31
|
Increase demand on GPU processing. Must be between 1 and 32 inclusive.
|
|
29
32
|
.TP
|
|
@@ -47,9 +50,9 @@ $ nano-pow \fB\-t fffffe00 \-e 32 0123456789abcdef0123456789abcdef0123456789abcd
|
|
|
47
50
|
.EE
|
|
48
51
|
|
|
49
52
|
.PP
|
|
50
|
-
|
|
53
|
+
Read one or more lines of blockhashes from a file and output to another file:
|
|
51
54
|
.EX
|
|
52
|
-
$
|
|
55
|
+
$ cat /path/to/file.txt | nano-pow --json > work.json
|
|
53
56
|
.EE
|
|
54
57
|
|
|
55
58
|
.PP
|
|
@@ -70,4 +73,5 @@ Email <bug-nano-pow@zoso.dev>.
|
|
|
70
73
|
Copyright \(co 2025 Chris Duncan <chris@zoso.dev>
|
|
71
74
|
Nano PoW documentation: <https://docs.nano.org/integration-guides/work-generation/#work-calculation-details>
|
|
72
75
|
License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>
|
|
76
|
+
Portions of this code are also provided under the MIT License: <https://spdx.org/licenses/MIT.html>
|
|
73
77
|
.EE
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nano-pow",
|
|
3
|
-
"version": "3.1.
|
|
3
|
+
"version": "3.1.3",
|
|
4
4
|
"description": "Proof-of-work generation and validation with WebGPU/WebGL for Nano cryptocurrency.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"nemo",
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
"cash",
|
|
9
9
|
"crypto",
|
|
10
10
|
"currency",
|
|
11
|
+
"cryptocurrency",
|
|
11
12
|
"coin",
|
|
12
13
|
"nonce",
|
|
13
14
|
"pow",
|
|
@@ -32,8 +33,7 @@
|
|
|
32
33
|
],
|
|
33
34
|
"main": "dist/main.min.js",
|
|
34
35
|
"browser": {
|
|
35
|
-
"dist/main.min.js": true
|
|
36
|
-
"node:worker_threads": false
|
|
36
|
+
"./dist/main.min.js": true
|
|
37
37
|
},
|
|
38
38
|
"bin": "./dist/cli.js",
|
|
39
39
|
"man": "./dist/nano-pow.1",
|
|
@@ -53,10 +53,12 @@
|
|
|
53
53
|
"typescript": "^5.8.2"
|
|
54
54
|
},
|
|
55
55
|
"type": "module",
|
|
56
|
-
"exports":
|
|
57
|
-
"
|
|
58
|
-
|
|
59
|
-
|
|
56
|
+
"exports": {
|
|
57
|
+
".": {
|
|
58
|
+
"types": "./dist/types.d.ts",
|
|
59
|
+
"default": "./dist/main.min.js"
|
|
60
|
+
}
|
|
61
|
+
},
|
|
60
62
|
"types": "./dist/types.d.ts",
|
|
61
63
|
"unpkg": "./dist/main.min.js",
|
|
62
64
|
"optionalDependencies": {
|