diff options
Diffstat (limited to 'web/js/proof-of-work.mjs')
| -rw-r--r-- | web/js/proof-of-work.mjs | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/web/js/proof-of-work.mjs b/web/js/proof-of-work.mjs new file mode 100644 index 0000000..b4f9c53 --- /dev/null +++ b/web/js/proof-of-work.mjs @@ -0,0 +1,93 @@ +export default function process(data, difficulty = 5, threads = (navigator.hardwareConcurrency || 1)) { + console.debug("fast algo"); + return new Promise((resolve, reject) => { + let webWorkerURL = URL.createObjectURL(new Blob([ + '(', processTask(), ')()' + ], { type: 'application/javascript' })); + + const workers = []; + + for (let i = 0; i < threads; i++) { + let worker = new Worker(webWorkerURL); + + worker.onmessage = (event) => { + workers.forEach(worker => worker.terminate()); + worker.terminate(); + resolve(event.data); + }; + + worker.onerror = (event) => { + worker.terminate(); + reject(); + }; + + worker.postMessage({ + data, + difficulty, + nonce: i, + threads, + }); + + workers.push(worker); + } + + URL.revokeObjectURL(webWorkerURL); + }); +} + +function processTask() { + return function () { + const sha256 = (text) => { + const encoded = new TextEncoder().encode(text); + 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 = event.data.nonce; + let threads = event.data.threads; + + 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 += threads; + } + + postMessage({ + hash, + data, + difficulty, + nonce, + }); + }); + }.toString(); +} + |
