aboutsummaryrefslogtreecommitdiff
path: root/cmd/anubis/js/proof-of-work.mjs
blob: d71d2db201aad79fa7b741247014b4a95eddc985 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
// https://dev.to/ratmd/simple-proof-of-work-in-javascript-3kgm

export function process(data, difficulty = 5) {
  return new Promise((resolve, reject) => {
    let webWorkerURL = URL.createObjectURL(new Blob([
      '(', processTask(), ')()'
    ], { type: 'application/javascript' }));

    let worker = new Worker(webWorkerURL);

    worker.onmessage = (event) => {
      worker.terminate();
      resolve(event.data);
    };

    worker.onerror = (event) => {
      worker.terminate();
      reject();
    };

    worker.postMessage({
      data,
      difficulty
    });

    URL.revokeObjectURL(webWorkerURL);
  });
}

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(""),
      );
    };

    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'));

      nonce -= 1; // last nonce was post-incremented

      postMessage({
        hash,
        data,
        difficulty,
        nonce,
      });
    });
  }.toString();
}