diff --git a/web/js/algorithms/wasm.ts b/web/js/algorithms/wasm.ts index 10c56a5f..1a39dc9c 100644 --- a/web/js/algorithms/wasm.ts +++ b/web/js/algorithms/wasm.ts @@ -13,101 +13,20 @@ interface ProcessOptions { const getHardwareConcurrency = () => navigator.hardwareConcurrency !== undefined ? navigator.hardwareConcurrency : 1; -// // https://stackoverflow.com/questions/47879864/how-can-i-check-if-a-browser-supports-webassembly -// const isWASMSupported = (() => { -// try { -// if (typeof WebAssembly === "object" -// && typeof WebAssembly.instantiate === "function") { -// const module = new WebAssembly.Module(Uint8Array.of(0x0, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00)); -// if (module instanceof WebAssembly.Module) -// return new WebAssembly.Instance(module) instanceof WebAssembly.Instance; -// } -// } catch (e) { -// return false; -// } -// return false; -// })(); - -// const fetchWASMBinary = async (url: string): Promise => { -// const res = await fetch(url); -// if (!res.ok) throw new Error('failed to fetch the wasm binary'); -// const wasmBytes = new Uint8Array(await res.arrayBuffer()); -// return wasmBytes; -// }; - -// const runPureJS = ( -// options: ProcessOptions, -// data: string, -// difficulty: number = 5, -// signal: AbortSignal | null = null, -// progressCallback?: ProgressCallback, -// threads: number = Math.trunc(Math.max(getHardwareConcurrency() / 2, 1)), -// ): Promise => { -// const { basePrefix, version, algorithm } = options; - -// return new Promise(async (resolve, reject) => { -// const module = await fetchWASMBinary(u(`${basePrefix}/.within.website/x/cmd/anubis/static/wasm/baseline/${algorithm}.wasm?cacheBuster=${version}`)); -// const jsCode = compile(module, true); -// progressCallback != undefined && progressCallback("Using pure JS mode, this will be slow"); - -// console.log(jsCode); - -// const webWorkerURL = `${options.basePrefix}/.within.website/x/cmd/anubis/static/js/worker/wasm.mjs?cacheBuster=${version}`; - -// const workers: Worker[] = []; -// let settled = false; - -// const onAbort = () => { -// console.log("PoW aborted"); -// cleanup(); -// reject(new DOMException("Aborted", "AbortError")); -// }; - -// const cleanup = () => { -// if (settled) { -// return; -// } -// settled = true; -// workers.forEach((w) => w.terminate()); -// if (signal != null) { -// signal.removeEventListener("abort", onAbort); -// } -// }; - -// if (signal != null) { -// if (signal.aborted) { -// return onAbort(); -// } -// signal.addEventListener("abort", onAbort, { once: true }); -// } - -// for (let i = 0; i < threads; i++) { -// let worker = new Worker(webWorkerURL); - -// worker.onmessage = (event) => { -// if (typeof event.data === "number") { -// progressCallback?.(event.data); -// } else { -// cleanup(); -// resolve(event.data); -// } -// } - -// worker.onerror = (event) => { -// cleanup(); -// reject(event); -// } - -// worker.postMessage({ -// data, -// difficulty, -// nonce: i, -// threads, -// jsCode, -// }); -// } -// }); -// } +// https://stackoverflow.com/questions/47879864/how-can-i-check-if-a-browser-supports-webassembly +const isWASMSupported = (() => { + try { + if (typeof WebAssembly === "object" + && typeof WebAssembly.instantiate === "function") { + const module = new WebAssembly.Module(Uint8Array.of(0x0, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00)); + if (module instanceof WebAssembly.Module) + return new WebAssembly.Instance(module) instanceof WebAssembly.Instance; + } + } catch (e) { + return false; + } + return false; +})(); export default function process( options: ProcessOptions, @@ -119,16 +38,9 @@ export default function process( ): Promise { const { basePrefix, version, algorithm } = options; - // if (!isWASMSupported) { - // return runPureJS( - // options, - // data, - // difficulty, - // signal, - // progressCallback, - // threads, - // ) - // } + if (!isWASMSupported) { + throw new Error("WebAssembly is not supported on this platform. Please report ALL details about your browser, environment, OS, CPU, device vendor, and other details to https://github.com/TecharoHQ/anubis/issues/1116. Remember: being polite means you get this fixed."); + } return new Promise(async (resolve, reject) => { let wasmFeatures = "baseline"; diff --git a/web/js/worker/wasm2js.ts b/web/js/worker/wasm2js.ts deleted file mode 100644 index 15f84ace..00000000 --- a/web/js/worker/wasm2js.ts +++ /dev/null @@ -1,107 +0,0 @@ -import { instantiate } from '@haribala/wasm2js'; - -export interface Args { - data: string; - difficulty: number; - nonce: number; - threads: number; - jsCode: string; -} - -interface AnubisExports { - anubis_work: (difficulty: number, initialNonce: number, threads: number) => number; - data_ptr: () => number; - result_hash_ptr: () => number; - result_hash_size: () => number; - set_data_length: (len: number) => void; - memory: any; -} - -addEventListener("message", async (event: MessageEvent) => { - const { data, difficulty, threads, jsCode } = event.data; - let { nonce } = event.data; - - const importObject = { - anubis: { - anubis_update_nonce: (nonce: number) => postMessage(nonce), - } - }; - - if (nonce !== 0) { - importObject.anubis.anubis_update_nonce = (_) => { }; - } - - const instance = instantiate(jsCode, importObject); - - const { - anubis_work, - data_ptr, - result_hash_ptr, - result_hash_size, - set_data_length, - memory - } = instance.exports as unknown as AnubisExports; - function uint8ArrayToHex(arr: Uint8Array) { - return Array.from(arr) - .map((c) => c.toString(16).padStart(2, "0")) - .join(""); - } - - function hexToUint8Array(hexString: string): Uint8Array { - // Remove whitespace and optional '0x' prefix - hexString = hexString.replace(/\s+/g, '').replace(/^0x/, ''); - - // Check for valid length - if (hexString.length % 2 !== 0) { - throw new Error('Invalid hex string length'); - } - - // Check for valid characters - if (!/^[0-9a-fA-F]+$/.test(hexString)) { - throw new Error('Invalid hex characters'); - } - - // Convert to Uint8Array - const byteArray = new Uint8Array(hexString.length / 2); - for (let i = 0; i < byteArray.length; i++) { - const byteValue = parseInt(hexString.substr(i * 2, 2), 16); - byteArray[i] = byteValue; - } - - return byteArray; - } - - // Write data to buffer - function writeToBuffer(data: Uint8Array) { - if (data.length > 1024) throw new Error("Data exceeds buffer size"); - - // Get pointer and create view - const offset = data_ptr(); - const buffer = new Uint8Array(memory.buffer, offset, data.length); - - // Copy data - buffer.set(data); - - // Set data length - set_data_length(data.length); - } - - function readFromChallenge() { - const offset = result_hash_ptr(); - const buffer = new Uint8Array(memory.buffer, offset, result_hash_size()); - - return buffer; - } - - writeToBuffer(hexToUint8Array(data)); - - nonce = anubis_work(difficulty, nonce, threads); - const challenge = readFromChallenge(); - const result = uint8ArrayToHex(challenge); - - postMessage({ - hash: result, - difficulty, - nonce, - }); -}); \ No newline at end of file