Switch to using WASM solver
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"lockfileVersion": 1,
|
||||
"workspaces": {
|
||||
"": {
|
||||
"name": "@cap.js/solver",
|
||||
"dependencies": {
|
||||
"@cap.js/wasm": "^0.0.3",
|
||||
},
|
||||
},
|
||||
},
|
||||
"packages": {
|
||||
"@cap.js/wasm": ["@cap.js/wasm@0.0.3", "", {}, "sha512-1HqjjRjHSD+2pnNj5yziCb9LfrVDsPWGV+Mr6epRag0o3nAhgEGC+AopQV01BV61BVjEQbhgyjNJBV+1Gc/SGw=="],
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -18,7 +18,7 @@ const CHALLENGES = [
|
||||
["308758072931bb3b254a7b1ed351d04a", "3e49"],
|
||||
["724f89bb167db4b881e1dc7b0949ac8f", "b82e"],
|
||||
["8b79506e4630de15be225c18623eff65", "f0e5"],
|
||||
["0c21ade6e63a4e37b13cb8b087f31863", "65c9e"],
|
||||
["0c21ade6e63a4e37b13cb8b087f31863", "65c9"],
|
||||
];
|
||||
|
||||
const timeStart = new Date().getTime();
|
||||
|
||||
+61
-39
@@ -1,61 +1,58 @@
|
||||
import { Worker } from "worker_threads";
|
||||
import os from "os";
|
||||
import { performance } from "perf_hooks";
|
||||
|
||||
const workerBlob = new Blob(
|
||||
[
|
||||
`
|
||||
import crypto from "crypto";
|
||||
import { parentPort, workerData } from "worker_threads";
|
||||
import { solve_pow } from "@cap.js/wasm";
|
||||
|
||||
const { salt, target } = workerData;
|
||||
const { salt, target, challengeIndex } = 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++;
|
||||
}`,
|
||||
try {
|
||||
const startTime = performance.now();
|
||||
const nonce = solve_pow(salt, target);
|
||||
const endTime = performance.now();
|
||||
const duration = (endTime - startTime) / 1000; // seconds
|
||||
|
||||
parentPort.postMessage({
|
||||
nonce,
|
||||
salt,
|
||||
target,
|
||||
challengeIndex,
|
||||
duration
|
||||
});
|
||||
} catch (error) {
|
||||
parentPort.postMessage({
|
||||
error: error.message,
|
||||
salt,
|
||||
target,
|
||||
challengeIndex
|
||||
});
|
||||
}
|
||||
`,
|
||||
],
|
||||
{
|
||||
type: "application/typescript",
|
||||
}
|
||||
);
|
||||
|
||||
const workerUrl = URL.createObjectURL(workerBlob);
|
||||
|
||||
export default function solver(challenges, config) {
|
||||
export default function wasmSolver(challenges, config = {}) {
|
||||
const totalChallenges = challenges.length;
|
||||
const numWorkers =
|
||||
config?.workerCount || Math.min(totalChallenges, 14, os.cpus().length);
|
||||
config?.workerCount || Math.min(totalChallenges, os.cpus().length);
|
||||
|
||||
let challengesProcessed = 0;
|
||||
let nextChallengeIndex = 0;
|
||||
let activeWorkers = 0;
|
||||
const results = [];
|
||||
const results = new Array(totalChallenges);
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const startTime = performance.now();
|
||||
|
||||
return new Promise((resolve) => {
|
||||
function startWorker() {
|
||||
if (nextChallengeIndex < totalChallenges && activeWorkers < numWorkers) {
|
||||
const currentChallengeIndex = nextChallengeIndex;
|
||||
@@ -68,25 +65,50 @@ export default function solver(challenges, config) {
|
||||
});
|
||||
|
||||
worker.on("message", (result) => {
|
||||
results.push([result.salt, result.target, result.nonce]);
|
||||
challengesProcessed++;
|
||||
worker.terminate();
|
||||
activeWorkers--;
|
||||
|
||||
if (result.error) {
|
||||
console.error(
|
||||
`Error in worker for challenge ${currentChallengeIndex}:`,
|
||||
result.error
|
||||
);
|
||||
reject(new Error(`Worker error: ${result.error}`));
|
||||
return;
|
||||
}
|
||||
|
||||
results[result.challengeIndex] = [
|
||||
result.salt,
|
||||
result.target,
|
||||
result.nonce,
|
||||
];
|
||||
challengesProcessed++;
|
||||
|
||||
if (config?.onProgress) {
|
||||
config.onProgress({
|
||||
progress: Math.floor((challengesProcessed / totalChallenges) * 100),
|
||||
progress: Math.floor(
|
||||
(challengesProcessed / totalChallenges) * 100
|
||||
),
|
||||
currentChallenge: currentChallengeIndex,
|
||||
challengesProcessed,
|
||||
totalChallenges,
|
||||
result,
|
||||
});
|
||||
}
|
||||
|
||||
if (challengesProcessed === totalChallenges) {
|
||||
resolve(results);
|
||||
resolve(results.filter(Boolean));
|
||||
} else {
|
||||
startWorker();
|
||||
}
|
||||
});
|
||||
|
||||
worker.on("error", (err) => {
|
||||
console.error(`Worker error:`, err);
|
||||
worker.terminate();
|
||||
activeWorkers--;
|
||||
reject(err);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+4
-1
@@ -226,5 +226,8 @@
|
||||
"bugs": {
|
||||
"url": "https://github.com/tiagorangel1/cap/issues"
|
||||
},
|
||||
"homepage": "https://github.com/tiagorangel1/cap#readme"
|
||||
"homepage": "https://github.com/tiagorangel1/cap#readme",
|
||||
"dependencies": {
|
||||
"@cap.js/wasm": "^0.0.3"
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user