28 lines
1.3 KiB
TypeScript
28 lines
1.3 KiB
TypeScript
/// <reference lib="webworker" />
|
|
import { argon2id } from 'hash-wasm';
|
|
import { POW, proofMessage, type Challenge } from '../shared/protocol.ts';
|
|
|
|
self.onmessage = async (event: MessageEvent<{ challenge: Challenge; owner: string; duty: number }>) => {
|
|
const { challenge, owner, duty } = event.data;
|
|
try {
|
|
const salt = new Uint8Array(challenge.seed.match(/.{2}/g)!.map(x => parseInt(x, 16)));
|
|
let nonce = crypto.getRandomValues(new Uint32Array(1))[0];
|
|
let attempts = 0;
|
|
const start = performance.now();
|
|
for (;;) {
|
|
const tick = performance.now();
|
|
const hash = await argon2id({ ...POW, password: proofMessage(challenge, owner, nonce), salt, outputType: 'hex' });
|
|
attempts++;
|
|
self.postMessage({ type: 'progress', attempts, hash, rate: attempts / ((performance.now() - start) / 1000) });
|
|
if (hash.startsWith('0'.repeat(challenge.difficulty))) {
|
|
self.postMessage({ type: 'found', hash, nonce });
|
|
return;
|
|
}
|
|
nonce++;
|
|
await new Promise(resolve => setTimeout(resolve, Math.max(20, (performance.now() - tick) * (1 / duty - 1))));
|
|
}
|
|
} catch (error) {
|
|
self.postMessage({ type: 'error', message: error instanceof Error ? error.message : 'Mining worker failed' });
|
|
}
|
|
};
|