aboutsummaryrefslogtreecommitdiff
path: root/web/js/proof-of-work.mjs
diff options
context:
space:
mode:
Diffstat (limited to 'web/js/proof-of-work.mjs')
-rw-r--r--web/js/proof-of-work.mjs93
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();
+}
+