]> git.ardis.lu - minimal-create2/commitdiff
Use multi-threading
authorArdis Lu <ardisglu@gmail.com>
Sat, 29 Jul 2023 22:12:14 +0000 (15:12 -0700)
committerArdis Lu <ardisglu@gmail.com>
Sat, 29 Jul 2023 22:12:14 +0000 (15:12 -0700)
index.html
worker.js [new file with mode: 0644]

index 77be14b6a5dac13b97800b2425ac490299e55309..ae0b3107a2fc62973c01b948417495786ef29025 100644 (file)
 
     document.querySelector('form').addEventListener('submit', e => {
       e.preventDefault();
-      const { factory, bytecode, requirement: requirementString, salt: saltString } = Object.fromEntries(new FormData(e.target));
+      const { factory: factoryString, bytecode: bytecodeString, requirement: requirementString, salt: saltString } = Object.fromEntries(new FormData(e.target));
 
-      const hashedBytecode = keccak256(strToArr(bytecode)); // Hash it once and save for efficiency
+      const factory = strToArr(factoryString);
+      const hashedBytecode = keccak256(strToArr(bytecodeString)); // Hash it once and save for efficiency
       const requirement = RegExp(requirementString.slice(1, -1));
-      let salt = BigInt(saltString); // Converted to 0n if blank
-
-      while (true) {
-        const paddedSalt = `0x${salt.toString(16).padStart(64, '0')}`;
-        const addrBytes = new Uint8Array([0xff, ...strToArr(factory), ...strToArr(paddedSalt), ...hashedBytecode]);
-        const addr = `0x${arrToStr(keccak256(addrBytes)).substring(26)}`;
-        if (requirement.test(addr)) {
-          document.querySelector('output').innerHTML = `<pre>${JSON.stringify({ factory, paddedSalt, bytecode, addr }, null, 2)}</pre>`;
-          break;
-        }
-        salt++;
+
+      // Use SharedArrayBuffer and Atomics for multi-threading 
+      const saltSab = new SharedArrayBuffer(32);
+
+      // Set initial salt; allows "saving" mining progress by resuming mining from last salt.
+      // Hardcoded to use the last bytes so that the first bytes may be used for vanity function signatures.
+      const saltIndex = 3;
+      new BigUint64Array(saltSab)[saltIndex] = BigInt(saltString);
+
+      const workers = [];
+      for (let i = 0; i < navigator.hardwareConcurrency; i++) {
+        const w = new Worker('/worker.js', { type: 'module' });
+        workers.push(w);
+        w.postMessage({ factory, hashedBytecode, requirement, saltSab });
+        w.addEventListener('message', e => {
+          workers.forEach(w => w.terminate());
+
+          const { newSaltArray, addr } = e.data;
+          const output = {
+            factory: factoryString,
+            bytecode: bytecodeString,
+            salt: arrToStr(newSaltArray),
+            addr
+          }
+          document.querySelector('output').innerHTML = `<pre>${JSON.stringify(output, null, 2)}</pre>`;
+        });
       }
     });
   </script>
diff --git a/worker.js b/worker.js
new file mode 100644 (file)
index 0000000..1ded0b7
--- /dev/null
+++ b/worker.js
@@ -0,0 +1,26 @@
+import { keccak256 } from '/keccak256.js';
+
+function arrToStr(arr) {
+  return [...arr].map(v => v.toString(16).padStart(2, '0')).join('');
+}
+
+addEventListener('message', async e => {
+  const { factory, hashedBytecode, requirement, saltSab } = e.data;
+
+  // Hardcoded to use the last bytes so that the first bytes may be used for vanity function signatures.
+  // BigUint64Array is the largest typed array in JS. Max salt is 2n ** 64n - 1n === 18446744073709551615n.
+  const saltIndex = 3;
+  const saltArray = new BigUint64Array(saltSab); // Shared buffer
+  while (true) {
+    const salt = Atomics.add(saltArray, saltIndex, 1n);
+    const b64 = saltArray.slice(); // Clones into a new, non-shared buffer
+    b64[saltIndex] = salt;
+    const newSaltArray = new Uint8Array(b64.buffer); // Uint8Array required for hashing and presentation
+
+    const addrBytes = new Uint8Array([0xff, ...factory, ...newSaltArray, ...hashedBytecode]);
+    const addr = `0x${arrToStr(keccak256(addrBytes)).substring(24)}`;
+    if (requirement.test(addr)) {
+      postMessage({ newSaltArray, addr });
+    }
+  }
+});
This page took 0.040729 seconds and 4 git commands to generate.