sha256-purejs.ts 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. import { Sha256 } from "@aws-crypto/sha256-js";
  2. const calculateSHA256 = (text) => {
  3. const hash = new Sha256();
  4. hash.update(text);
  5. return hash.digest();
  6. };
  7. function toHexString(arr: Uint8Array): string {
  8. return Array.from(arr)
  9. .map((c) => c.toString(16).padStart(2, "0"))
  10. .join("");
  11. }
  12. addEventListener("message", async ({ data: eventData }) => {
  13. const { data, difficulty, threads } = eventData;
  14. let nonce = eventData.nonce;
  15. const isMainThread = nonce === 0;
  16. let iterations = 0;
  17. const requiredZeroBytes = Math.floor(difficulty / 2);
  18. const isDifficultyOdd = difficulty % 2 !== 0;
  19. for (;;) {
  20. const hashBuffer = await calculateSHA256(data + nonce);
  21. const hashArray = new Uint8Array(hashBuffer);
  22. let isValid = true;
  23. for (let i = 0; i < requiredZeroBytes; i++) {
  24. if (hashArray[i] !== 0) {
  25. isValid = false;
  26. break;
  27. }
  28. }
  29. if (isValid && isDifficultyOdd) {
  30. if (hashArray[requiredZeroBytes] >> 4 !== 0) {
  31. isValid = false;
  32. }
  33. }
  34. if (isValid) {
  35. const finalHash = toHexString(hashArray);
  36. postMessage({
  37. hash: finalHash,
  38. data,
  39. difficulty,
  40. nonce,
  41. });
  42. return; // Exit worker
  43. }
  44. nonce += threads;
  45. iterations++;
  46. /* Truncate the decimal portion of the nonce. This is a bit of an evil bit
  47. * hack, but it works reliably enough. The core of why this works is:
  48. *
  49. * > 13.4 % 1 !== 0
  50. * true
  51. * > 13 % 1 !== 0
  52. * false
  53. */
  54. if (nonce % 1 !== 0) {
  55. nonce = Math.trunc(nonce);
  56. }
  57. // Send a progress update from the main thread every 1024 iterations.
  58. if (isMainThread && (iterations & 1023) === 0) {
  59. postMessage(nonce);
  60. }
  61. }
  62. });