aboutsummaryrefslogtreecommitdiff
path: root/cmd/anubis/static/js/main.mjs.map
diff options
context:
space:
mode:
authorXe Iaso <me@xeiaso.net>2025-03-20 09:26:39 -0400
committerGitHub <noreply@github.com>2025-03-20 09:26:39 -0400
commit52d7a3cd2b9b551b0e5e8d95a43ee8408484c133 (patch)
tree39e8d59b266c2375fb3f8f3bcd14a6070ad4e310 /cmd/anubis/static/js/main.mjs.map
parentc81e938f63281dbe885f5d3e0ca842e2719de81c (diff)
downloadanubis-52d7a3cd2b9b551b0e5e8d95a43ee8408484c133.tar.xz
anubis-52d7a3cd2b9b551b0e5e8d95a43ee8408484c133.zip
cmd/anubis: drastically optimize proof of work (#19)
* cmd/anubis: drastically optimize proof of work Closes #12 Closes #17 This drastically optimizes the proof of work check by removing the stringify call at every iteration. Additionally, this optimizes the checks by running them in parallel for as many threads as the browser has available (according to navigator.hardwareConcurrency). This also changes the redirect lag to 250 milliseconds instead of 2000 milliseconds in order to be perceptually faster. This is below the reaction time threshold of many people, so this will make the post-check success phase perceptually instant. Testing on an iPhone 7 Plus has shown that this can clear a difficulty 4 check in 3.4 seconds. This actually optimizes the check so much it may be a logistical concern for operators. * cmd/anubis/js: fix happy cachebuster logic Signed-off-by: Xe Iaso <me@xeiaso.net> --------- Signed-off-by: Xe Iaso <me@xeiaso.net>
Diffstat (limited to 'cmd/anubis/static/js/main.mjs.map')
-rw-r--r--cmd/anubis/static/js/main.mjs.map6
1 files changed, 3 insertions, 3 deletions
diff --git a/cmd/anubis/static/js/main.mjs.map b/cmd/anubis/static/js/main.mjs.map
index d5b288f..577503b 100644
--- a/cmd/anubis/static/js/main.mjs.map
+++ b/cmd/anubis/static/js/main.mjs.map
@@ -1,7 +1,7 @@
{
"version": 3,
"sources": ["../../js/proof-of-work.mjs", "../../js/main.mjs"],
- "sourcesContent": ["// https://dev.to/ratmd/simple-proof-of-work-in-javascript-3kgm\n\nexport function process(data, difficulty = 5) {\n return new Promise((resolve, reject) => {\n let webWorkerURL = URL.createObjectURL(new Blob([\n '(', processTask(), ')()'\n ], { type: 'application/javascript' }));\n\n let worker = new Worker(webWorkerURL);\n\n worker.onmessage = (event) => {\n worker.terminate();\n resolve(event.data);\n };\n\n worker.onerror = (event) => {\n worker.terminate();\n reject();\n };\n\n worker.postMessage({\n data,\n difficulty\n });\n\n URL.revokeObjectURL(webWorkerURL);\n });\n}\n\nfunction processTask() {\n return function () {\n const sha256 = (text) => {\n const encoded = new TextEncoder().encode(text);\n return crypto.subtle.digest(\"SHA-256\", encoded.buffer).then((result) =>\n Array.from(new Uint8Array(result))\n .map((c) => c.toString(16).padStart(2, \"0\"))\n .join(\"\"),\n );\n };\n\n addEventListener('message', async (event) => {\n let data = event.data.data;\n let difficulty = event.data.difficulty;\n\n let hash;\n let nonce = 0;\n do {\n hash = await sha256(data + nonce++);\n } while (hash.substring(0, difficulty) !== Array(difficulty + 1).join('0'));\n\n nonce -= 1; // last nonce was post-incremented\n\n postMessage({\n hash,\n data,\n difficulty,\n nonce,\n });\n });\n }.toString();\n}\n\n", "import { process } from './proof-of-work.mjs';\nimport { testVideo } from './video.mjs';\n\n// from Xeact\nconst u = (url = \"\", params = {}) => {\n let result = new URL(url, window.location.href);\n Object.entries(params).forEach((kv) => {\n let [k, v] = kv;\n result.searchParams.set(k, v);\n });\n return result.toString();\n};\n\nconst imageURL = (mood) => {\n return `/.within.website/x/cmd/anubis/static/img/${mood}.webp`;\n};\n\n(async () => {\n const status = document.getElementById('status');\n const image = document.getElementById('image');\n const title = document.getElementById('title');\n const spinner = document.getElementById('spinner');\n // const testarea = document.getElementById('testarea');\n\n // const videoWorks = await testVideo(testarea);\n // console.log(`videoWorks: ${videoWorks}`);\n\n // if (!videoWorks) {\n // title.innerHTML = \"Oh no!\";\n // status.innerHTML = \"Checks failed. Please check your browser's settings and try again.\";\n // image.src = imageURL(\"sad\");\n // spinner.innerHTML = \"\";\n // spinner.style.display = \"none\";\n // return;\n // }\n\n status.innerHTML = 'Calculating...';\n\n const { challenge, difficulty } = await fetch(\"/.within.website/x/cmd/anubis/api/make-challenge\", { method: \"POST\" })\n .then(r => {\n if (!r.ok) {\n throw new Error(\"Failed to fetch config\");\n }\n return r.json();\n })\n .catch(err => {\n title.innerHTML = \"Oh no!\";\n status.innerHTML = `Failed to fetch config: ${err.message}`;\n image.src = imageURL(\"sad\");\n spinner.innerHTML = \"\";\n spinner.style.display = \"none\";\n throw err;\n });\n\n status.innerHTML = `Calculating...<br/>Difficulty: ${difficulty}`;\n\n const t0 = Date.now();\n const { hash, nonce } = await process(challenge, difficulty);\n const t1 = Date.now();\n\n title.innerHTML = \"Success!\";\n status.innerHTML = `Done! Took ${t1 - t0}ms, ${nonce} iterations`;\n image.src = imageURL(\"happy\");\n spinner.innerHTML = \"\";\n spinner.style.display = \"none\";\n\n setTimeout(() => {\n const redir = window.location.href;\n window.location.href = u(\"/.within.website/x/cmd/anubis/api/pass-challenge\", { response: hash, nonce, redir, elapsedTime: t1 - t0 });\n }, 2000);\n})();"],
- "mappings": "MAEO,SAASA,EAAQC,EAAMC,EAAa,EAAG,CAC5C,OAAO,IAAI,QAAQ,CAACC,EAASC,IAAW,CACtC,IAAIC,EAAe,IAAI,gBAAgB,IAAI,KAAK,CAC9C,IAAKC,EAAY,EAAG,KACtB,EAAG,CAAE,KAAM,wBAAyB,CAAC,CAAC,EAElCC,EAAS,IAAI,OAAOF,CAAY,EAEpCE,EAAO,UAAaC,GAAU,CAC5BD,EAAO,UAAU,EACjBJ,EAAQK,EAAM,IAAI,CACpB,EAEAD,EAAO,QAAWC,GAAU,CAC1BD,EAAO,UAAU,EACjBH,EAAO,CACT,EAEAG,EAAO,YAAY,CACjB,KAAAN,EACA,WAAAC,CACF,CAAC,EAED,IAAI,gBAAgBG,CAAY,CAClC,CAAC,CACH,CAEA,SAASC,GAAc,CACrB,OAAO,UAAY,CACjB,IAAMG,EAAUC,GAAS,CACvB,IAAMC,EAAU,IAAI,YAAY,EAAE,OAAOD,CAAI,EAC7C,OAAO,OAAO,OAAO,OAAO,UAAWC,EAAQ,MAAM,EAAE,KAAMC,GAC3D,MAAM,KAAK,IAAI,WAAWA,CAAM,CAAC,EAC9B,IAAKC,GAAMA,EAAE,SAAS,EAAE,EAAE,SAAS,EAAG,GAAG,CAAC,EAC1C,KAAK,EAAE,CACZ,CACF,EAEA,iBAAiB,UAAW,MAAOL,GAAU,CAC3C,IAAIP,EAAOO,EAAM,KAAK,KAClBN,EAAaM,EAAM,KAAK,WAExBM,EACAC,EAAQ,EACZ,GACED,EAAO,MAAML,EAAOR,EAAOc,GAAO,QAC3BD,EAAK,UAAU,EAAGZ,CAAU,IAAM,MAAMA,EAAa,CAAC,EAAE,KAAK,GAAG,GAEzEa,GAAS,EAET,YAAY,CACV,KAAAD,EACA,KAAAb,EACA,WAAAC,EACA,MAAAa,CACF,CAAC,CACH,CAAC,CACH,EAAE,SAAS,CACb,CCxDA,IAAMC,EAAI,CAACC,EAAM,GAAIC,EAAS,CAAC,IAAM,CACnC,IAAIC,EAAS,IAAI,IAAIF,EAAK,OAAO,SAAS,IAAI,EAC9C,cAAO,QAAQC,CAAM,EAAE,QAASE,GAAO,CACrC,GAAI,CAACC,EAAGC,CAAC,EAAIF,EACbD,EAAO,aAAa,IAAIE,EAAGC,CAAC,CAC9B,CAAC,EACMH,EAAO,SAAS,CACzB,EAEMI,EAAYC,GACT,4CAA4CA,CAAI,SAGxD,SAAY,CACX,IAAMC,EAAS,SAAS,eAAe,QAAQ,EACzCC,EAAQ,SAAS,eAAe,OAAO,EACvCC,EAAQ,SAAS,eAAe,OAAO,EACvCC,EAAU,SAAS,eAAe,SAAS,EAejDH,EAAO,UAAY,iBAEnB,GAAM,CAAE,UAAAI,EAAW,WAAAC,CAAW,EAAI,MAAM,MAAM,mDAAoD,CAAE,OAAQ,MAAO,CAAC,EACjH,KAAKC,GAAK,CACT,GAAI,CAACA,EAAE,GACL,MAAM,IAAI,MAAM,wBAAwB,EAE1C,OAAOA,EAAE,KAAK,CAChB,CAAC,EACA,MAAMC,GAAO,CACZ,MAAAL,EAAM,UAAY,SAClBF,EAAO,UAAY,2BAA2BO,EAAI,OAAO,GACzDN,EAAM,IAAMH,EAAS,KAAK,EAC1BK,EAAQ,UAAY,GACpBA,EAAQ,MAAM,QAAU,OAClBI,CACR,CAAC,EAEHP,EAAO,UAAY,kCAAkCK,CAAU,GAE/D,IAAMG,EAAK,KAAK,IAAI,EACd,CAAE,KAAAC,EAAM,MAAAC,CAAM,EAAI,MAAMC,EAAQP,EAAWC,CAAU,EACrDO,EAAK,KAAK,IAAI,EAEpBV,EAAM,UAAY,WAClBF,EAAO,UAAY,cAAcY,EAAKJ,CAAE,OAAOE,CAAK,cACpDT,EAAM,IAAMH,EAAS,OAAO,EAC5BK,EAAQ,UAAY,GACpBA,EAAQ,MAAM,QAAU,OAExB,WAAW,IAAM,CACf,IAAMU,EAAQ,OAAO,SAAS,KAC9B,OAAO,SAAS,KAAOtB,EAAE,mDAAoD,CAAE,SAAUkB,EAAM,MAAAC,EAAO,MAAAG,EAAO,YAAaD,EAAKJ,CAAG,CAAC,CACrI,EAAG,GAAI,CACT,GAAG",
- "names": ["process", "data", "difficulty", "resolve", "reject", "webWorkerURL", "processTask", "worker", "event", "sha256", "text", "encoded", "result", "c", "hash", "nonce", "u", "url", "params", "result", "kv", "k", "v", "imageURL", "mood", "status", "image", "title", "spinner", "challenge", "difficulty", "r", "err", "t0", "hash", "nonce", "process", "t1", "redir"]
+ "sourcesContent": ["// https://dev.to/ratmd/simple-proof-of-work-in-javascript-3kgm\n\nexport function process(data, difficulty = 5, threads = navigator.hardwareConcurrency) {\n return new Promise((resolve, reject) => {\n let webWorkerURL = URL.createObjectURL(new Blob([\n '(', processTask(), ')()'\n ], { type: 'application/javascript' }));\n\n const workers = [];\n\n for (let i = 0; i < threads; i++) {\n let worker = new Worker(webWorkerURL);\n\n worker.onmessage = (event) => {\n workers.forEach(worker => worker.terminate());\n worker.terminate();\n resolve(event.data);\n };\n\n worker.onerror = (event) => {\n worker.terminate();\n reject();\n };\n\n worker.postMessage({\n data,\n difficulty,\n nonce: 1000000 * i,\n });\n\n workers.push(worker);\n }\n\n URL.revokeObjectURL(webWorkerURL);\n });\n}\n\nfunction processTask() {\n return function () {\n const sha256 = (text) => {\n const encoded = new TextEncoder().encode(text);\n return crypto.subtle.digest(\"SHA-256\", encoded.buffer);\n };\n\n function uint8ArrayToHexString(arr) {\n return Array.from(arr)\n .map((c) => c.toString(16).padStart(2, \"0\"))\n .join(\"\");\n }\n\n addEventListener('message', async (event) => {\n let data = event.data.data;\n let difficulty = event.data.difficulty;\n let hash;\n let nonce = event.data.nonce || 0;\n\n while (true) {\n const currentHash = await sha256(data + nonce++);\n const thisHash = new Uint8Array(currentHash);\n let valid = true;\n\n for (let j = 0; j < difficulty; j++) {\n const byteIndex = Math.floor(j / 2); // which byte we are looking at\n const nibbleIndex = j % 2; // which nibble in the byte we are looking at (0 is high, 1 is low)\n\n let nibble = (thisHash[byteIndex] >> (nibbleIndex === 0 ? 4 : 0)) & 0x0F; // Get the nibble\n\n if (nibble !== 0) {\n valid = false;\n break;\n }\n }\n\n if (valid) {\n hash = uint8ArrayToHexString(thisHash);\n console.log(hash);\n break;\n }\n }\n\n nonce -= 1; // last nonce was post-incremented\n\n postMessage({\n hash,\n data,\n difficulty,\n nonce,\n });\n });\n }.toString();\n}\n\n", "import { process } from './proof-of-work.mjs';\nimport { testVideo } from './video.mjs';\n\n// from Xeact\nconst u = (url = \"\", params = {}) => {\n let result = new URL(url, window.location.href);\n Object.entries(params).forEach((kv) => {\n let [k, v] = kv;\n result.searchParams.set(k, v);\n });\n return result.toString();\n};\n\nconst imageURL = (mood, cacheBuster) =>\n u(`/.within.website/x/cmd/anubis/static/img/${mood}.webp`, { cacheBuster });\n\n(async () => {\n const status = document.getElementById('status');\n const image = document.getElementById('image');\n const title = document.getElementById('title');\n const spinner = document.getElementById('spinner');\n const anubisVersion = JSON.parse(document.getElementById('anubis_version').textContent);\n\n // const testarea = document.getElementById('testarea');\n\n // const videoWorks = await testVideo(testarea);\n // console.log(`videoWorks: ${videoWorks}`);\n\n // if (!videoWorks) {\n // title.innerHTML = \"Oh no!\";\n // status.innerHTML = \"Checks failed. Please check your browser's settings and try again.\";\n // image.src = imageURL(\"sad\");\n // spinner.innerHTML = \"\";\n // spinner.style.display = \"none\";\n // return;\n // }\n\n status.innerHTML = 'Calculating...';\n\n const { challenge, difficulty } = await fetch(\"/.within.website/x/cmd/anubis/api/make-challenge\", { method: \"POST\" })\n .then(r => {\n if (!r.ok) {\n throw new Error(\"Failed to fetch config\");\n }\n return r.json();\n })\n .catch(err => {\n title.innerHTML = \"Oh no!\";\n status.innerHTML = `Failed to fetch config: ${err.message}`;\n image.src = imageURL(\"sad\");\n spinner.innerHTML = \"\";\n spinner.style.display = \"none\";\n throw err;\n });\n\n status.innerHTML = `Calculating...<br/>Difficulty: ${difficulty}`;\n\n const t0 = Date.now();\n const { hash, nonce } = await process(challenge, difficulty);\n const t1 = Date.now();\n console.log({ hash, nonce });\n\n title.innerHTML = \"Success!\";\n status.innerHTML = `Done! Took ${t1 - t0}ms, ${nonce} iterations`;\n image.src = imageURL(\"happy\", anubisVersion);\n spinner.innerHTML = \"\";\n spinner.style.display = \"none\";\n\n setTimeout(() => {\n const redir = window.location.href;\n window.location.href = u(\"/.within.website/x/cmd/anubis/api/pass-challenge\", { response: hash, nonce, redir, elapsedTime: t1 - t0 });\n }, 250);\n})();"],
+ "mappings": "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",
+ "names": ["process", "data", "difficulty", "threads", "resolve", "reject", "webWorkerURL", "processTask", "workers", "i", "worker", "event", "sha256", "text", "encoded", "uint8ArrayToHexString", "arr", "c", "hash", "nonce", "currentHash", "thisHash", "valid", "j", "byteIndex", "nibbleIndex", "u", "url", "params", "result", "kv", "k", "v", "imageURL", "mood", "cacheBuster", "status", "image", "title", "spinner", "anubisVersion", "challenge", "difficulty", "r", "err", "t0", "hash", "nonce", "process", "t1", "redir"]
}