Files
cap/solver/index.js
T
2025-04-12 14:33:36 +01:00

93 lines
2.1 KiB
JavaScript

import { Worker } from "worker_threads";
import os from "os";
const workerBlob = new Blob(
[
`
import crypto from "crypto";
import { parentPort, workerData } from "worker_threads";
const { salt, target } = workerData;
const saltBuffer = Buffer.from(salt);
const targetLen = target.length;
const targetBytes = Math.ceil(targetLen / 2);
let nonce = 0;
while (true) {
const nonceStr = nonce.toString();
const hash = crypto.createHash("sha256");
hash.update(saltBuffer);
hash.update(nonceStr);
const hashBuffer = hash.digest();
const hashPrefixHex = hashBuffer.toString("hex", 0, targetBytes);
if (hashPrefixHex.startsWith(target)) {
parentPort.postMessage({
nonce: Number(nonce),
salt,
target,
});
break;
}
nonce++;
}`,
],
{
type: "application/typescript",
}
);
const workerUrl = URL.createObjectURL(workerBlob);
export default function solver(challenges, config) {
const totalChallenges = challenges.length;
const numWorkers =
config?.workerCount || Math.min(totalChallenges, 14, os.cpus().length);
let challengesProcessed = 0;
let nextChallengeIndex = 0;
let activeWorkers = 0;
const results = [];
return new Promise((resolve) => {
function startWorker() {
if (nextChallengeIndex < totalChallenges && activeWorkers < numWorkers) {
const currentChallengeIndex = nextChallengeIndex;
const [salt, target] = challenges[currentChallengeIndex];
nextChallengeIndex++;
activeWorkers++;
const worker = new Worker(workerUrl, {
workerData: { salt, target, challengeIndex: currentChallengeIndex },
});
worker.on("message", (result) => {
results.push([result.salt, result.target, result.nonce]);
challengesProcessed++;
activeWorkers--;
if (challengesProcessed === totalChallenges) {
resolve(results);
} else {
startWorker();
}
});
}
}
for (let i = 0; i < numWorkers; i++) {
startWorker();
}
if (totalChallenges === 0) {
resolve([]);
}
});
}