hugin-utils 0.1.0
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 +9 -0
- package/index.js +108 -0
- package/package.json +8 -0
package/README.md
ADDED
package/index.js
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
const DEFAULT_NONCE_OFFSET = 39;
|
|
2
|
+
|
|
3
|
+
function readVarint(buffer, offset) {
|
|
4
|
+
let value = 0;
|
|
5
|
+
let shift = 0;
|
|
6
|
+
let bytes = 0;
|
|
7
|
+
while (offset + bytes < buffer.length) {
|
|
8
|
+
const byte = buffer[offset + bytes];
|
|
9
|
+
value |= (byte & 0x7f) << shift;
|
|
10
|
+
bytes += 1;
|
|
11
|
+
if ((byte & 0x80) === 0) {
|
|
12
|
+
return { value, bytes };
|
|
13
|
+
}
|
|
14
|
+
shift += 7;
|
|
15
|
+
if (shift > 63) return null;
|
|
16
|
+
}
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function getNonceOffsetFromBuffer(blobBuffer) {
|
|
21
|
+
try {
|
|
22
|
+
let offset = 0;
|
|
23
|
+
const major = readVarint(blobBuffer, offset);
|
|
24
|
+
if (!major) return DEFAULT_NONCE_OFFSET;
|
|
25
|
+
offset += major.bytes;
|
|
26
|
+
const minor = readVarint(blobBuffer, offset);
|
|
27
|
+
if (!minor) return DEFAULT_NONCE_OFFSET;
|
|
28
|
+
offset += minor.bytes;
|
|
29
|
+
const timestamp = readVarint(blobBuffer, offset);
|
|
30
|
+
if (!timestamp) return DEFAULT_NONCE_OFFSET;
|
|
31
|
+
offset += timestamp.bytes;
|
|
32
|
+
offset += 32;
|
|
33
|
+
return offset;
|
|
34
|
+
} catch (e) {
|
|
35
|
+
return DEFAULT_NONCE_OFFSET;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function getNonceOffset(blobHex) {
|
|
40
|
+
const blobBuffer = Buffer.from(blobHex, 'hex');
|
|
41
|
+
return getNonceOffsetFromBuffer(blobBuffer);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function insertNonce(blobHex, nonceHex) {
|
|
45
|
+
const blobBuffer = Buffer.from(blobHex, 'hex');
|
|
46
|
+
const nonceBuffer = Buffer.from(nonceHex, 'hex');
|
|
47
|
+
const offset = getNonceOffsetFromBuffer(blobBuffer);
|
|
48
|
+
nonceBuffer.copy(blobBuffer, offset);
|
|
49
|
+
return { blobHex: blobBuffer.toString('hex'), offset };
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function meetsTarget(hashHex, targetHex) {
|
|
53
|
+
if (!targetHex || targetHex.length !== 8) return true;
|
|
54
|
+
const hash = Buffer.from(hashHex, 'hex');
|
|
55
|
+
const targetNum = Buffer.from(targetHex, 'hex').readUInt32BE(0);
|
|
56
|
+
const hashNum = Buffer.from(hash.slice(0, 4)).reverse().readUInt32BE(0);
|
|
57
|
+
return hashNum <= targetNum;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
async function findShare({
|
|
61
|
+
job,
|
|
62
|
+
startNonce,
|
|
63
|
+
hashFn,
|
|
64
|
+
log,
|
|
65
|
+
hashesPerSecond = 500,
|
|
66
|
+
timeBudgetMs = 1000,
|
|
67
|
+
yieldEvery = 200,
|
|
68
|
+
logEvery = 100
|
|
69
|
+
}) {
|
|
70
|
+
const maxAttempts = Math.max(1, Math.floor((hashesPerSecond * timeBudgetMs) / 1000));
|
|
71
|
+
let nonce = startNonce;
|
|
72
|
+
const start = Date.now();
|
|
73
|
+
|
|
74
|
+
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
75
|
+
const nonceHex = (nonce & 0xFFFFFFFF).toString(16).padStart(8, '0');
|
|
76
|
+
const { blobHex, offset } = insertNonce(job.blob, nonceHex);
|
|
77
|
+
if (log) log('nonce_offset', { jobId: job.job_id, offset });
|
|
78
|
+
const result = await hashFn(blobHex);
|
|
79
|
+
|
|
80
|
+
if (meetsTarget(result, job.target)) {
|
|
81
|
+
if (log) log('pow_share_found', { jobId: job.job_id, nonce: nonceHex, attempt });
|
|
82
|
+
return { job_id: job.job_id, nonce: nonceHex, result };
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
nonce++;
|
|
86
|
+
if (attempt > 0 && attempt % logEvery === 0) {
|
|
87
|
+
if (log) log('pow_progress', { jobId: job.job_id, attempt, nonce: nonceHex });
|
|
88
|
+
}
|
|
89
|
+
if (attempt > 0 && attempt % yieldEvery === 0) {
|
|
90
|
+
await new Promise(resolve => setTimeout(resolve, 0));
|
|
91
|
+
}
|
|
92
|
+
if (Date.now() - start >= timeBudgetMs) {
|
|
93
|
+
if (log) log('pow_time_budget', { jobId: job.job_id, attempt, elapsedMs: Date.now() - start });
|
|
94
|
+
break;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (log) log('pow_share_exhausted', { jobId: job.job_id, attempts: maxAttempts });
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
module.exports = {
|
|
103
|
+
readVarint,
|
|
104
|
+
getNonceOffset,
|
|
105
|
+
insertNonce,
|
|
106
|
+
meetsTarget,
|
|
107
|
+
findShare
|
|
108
|
+
};
|