diff options
Diffstat (limited to 'cmd/anubis/js/proof-of-work.mjs')
| -rw-r--r-- | cmd/anubis/js/proof-of-work.mjs | 78 |
1 files changed, 54 insertions, 24 deletions
diff --git a/cmd/anubis/js/proof-of-work.mjs b/cmd/anubis/js/proof-of-work.mjs index d71d2db..bd69c71 100644 --- a/cmd/anubis/js/proof-of-work.mjs +++ b/cmd/anubis/js/proof-of-work.mjs @@ -1,27 +1,35 @@ // https://dev.to/ratmd/simple-proof-of-work-in-javascript-3kgm -export function process(data, difficulty = 5) { +export function process(data, difficulty = 5, threads = navigator.hardwareConcurrency) { return new Promise((resolve, reject) => { let webWorkerURL = URL.createObjectURL(new Blob([ '(', processTask(), ')()' ], { type: 'application/javascript' })); - let worker = new Worker(webWorkerURL); + const workers = []; - worker.onmessage = (event) => { - worker.terminate(); - resolve(event.data); - }; + for (let i = 0; i < threads; i++) { + let worker = new Worker(webWorkerURL); - worker.onerror = (event) => { - worker.terminate(); - reject(); - }; + worker.onmessage = (event) => { + workers.forEach(worker => worker.terminate()); + worker.terminate(); + resolve(event.data); + }; - worker.postMessage({ - data, - difficulty - }); + worker.onerror = (event) => { + worker.terminate(); + reject(); + }; + + worker.postMessage({ + data, + difficulty, + nonce: 1000000 * i, + }); + + workers.push(worker); + } URL.revokeObjectURL(webWorkerURL); }); @@ -31,22 +39,44 @@ function processTask() { return function () { const sha256 = (text) => { const encoded = new TextEncoder().encode(text); - return crypto.subtle.digest("SHA-256", encoded.buffer).then((result) => - Array.from(new Uint8Array(result)) - .map((c) => c.toString(16).padStart(2, "0")) - .join(""), - ); + return crypto.subtle.digest("SHA-256", encoded.buffer); }; + function uint8ArrayToHexString(arr) { + return Array.from(arr) + .map((c) => c.toString(16).padStart(2, "0")) + .join(""); + } + addEventListener('message', async (event) => { let data = event.data.data; let difficulty = event.data.difficulty; - let hash; - let nonce = 0; - do { - hash = await sha256(data + nonce++); - } while (hash.substring(0, difficulty) !== Array(difficulty + 1).join('0')); + let nonce = event.data.nonce || 0; + + while (true) { + const currentHash = await sha256(data + nonce++); + const thisHash = new Uint8Array(currentHash); + let valid = true; + + for (let j = 0; j < difficulty; j++) { + const byteIndex = Math.floor(j / 2); // which byte we are looking at + const nibbleIndex = j % 2; // which nibble in the byte we are looking at (0 is high, 1 is low) + + let nibble = (thisHash[byteIndex] >> (nibbleIndex === 0 ? 4 : 0)) & 0x0F; // Get the nibble + + if (nibble !== 0) { + valid = false; + break; + } + } + + if (valid) { + hash = uint8ArrayToHexString(thisHash); + console.log(hash); + break; + } + } nonce -= 1; // last nonce was post-incremented |
