From eeaed6a317d27ce7de82774291cc87bef66e6244 Mon Sep 17 00:00:00 2001 From: Donatas Date: Thu, 20 Mar 2025 22:20:53 +0200 Subject: [PATCH] fix: no duplicate work when exceeding hardcoded int (#36) * fix: no duplicate work when exceeding that 1xxx number * run go generate and update CHANGELOG Signed-off-by: Xe Iaso --------- Signed-off-by: Xe Iaso Co-authored-by: Xe Iaso --- cmd/anubis/js/proof-of-work.mjs | 12 +++++++----- cmd/anubis/static/js/main.mjs | 2 +- cmd/anubis/static/js/main.mjs.br | Bin 993 -> 992 bytes cmd/anubis/static/js/main.mjs.gz | Bin 1193 -> 1194 bytes cmd/anubis/static/js/main.mjs.map | 4 ++-- cmd/anubis/static/js/main.mjs.zst | Bin 1191 -> 1190 bytes docs/docs/CHANGELOG.md | 1 + 7 files changed, 11 insertions(+), 8 deletions(-) diff --git a/cmd/anubis/js/proof-of-work.mjs b/cmd/anubis/js/proof-of-work.mjs index bd69c71..5a5f9f9 100644 --- a/cmd/anubis/js/proof-of-work.mjs +++ b/cmd/anubis/js/proof-of-work.mjs @@ -25,7 +25,8 @@ export function process(data, difficulty = 5, threads = navigator.hardwareConcur worker.postMessage({ data, difficulty, - nonce: 1000000 * i, + nonce: i, + threads, }); workers.push(worker); @@ -52,10 +53,11 @@ function processTask() { let data = event.data.data; let difficulty = event.data.difficulty; let hash; - let nonce = event.data.nonce || 0; + let nonce = event.data.nonce; + let threads = event.data.threads; while (true) { - const currentHash = await sha256(data + nonce++); + const currentHash = await sha256(data + nonce); const thisHash = new Uint8Array(currentHash); let valid = true; @@ -76,9 +78,9 @@ function processTask() { console.log(hash); break; } - } - nonce -= 1; // last nonce was post-incremented + nonce += threads; + } postMessage({ hash, diff --git a/cmd/anubis/static/js/main.mjs b/cmd/anubis/static/js/main.mjs index 3d9e2d0..ffa524b 100644 --- a/cmd/anubis/static/js/main.mjs +++ b/cmd/anubis/static/js/main.mjs @@ -1,2 +1,2 @@ -(()=>{function m(n,i=5,e=navigator.hardwareConcurrency){return new Promise((t,d)=>{let s=URL.createObjectURL(new Blob(["(",p(),")()"],{type:"application/javascript"})),a=[];for(let u=0;u{a.forEach(c=>c.terminate()),o.terminate(),t(r.data)},o.onerror=r=>{o.terminate(),d()},o.postMessage({data:n,difficulty:i,nonce:1e6*u}),a.push(o)}URL.revokeObjectURL(s)})}function p(){return function(){let n=e=>{let t=new TextEncoder().encode(e);return crypto.subtle.digest("SHA-256",t.buffer)};function i(e){return Array.from(e).map(t=>t.toString(16).padStart(2,"0")).join("")}addEventListener("message",async e=>{let t=e.data.data,d=e.data.difficulty,s,a=e.data.nonce||0;for(;;){let u=await n(t+a++),o=new Uint8Array(u),r=!0;for(let c=0;c>(f===0?4:0)&15)!==0){r=!1;break}}if(r){s=i(o),console.log(s);break}}a-=1,postMessage({hash:s,data:t,difficulty:d,nonce:a})})}.toString()}var w=(n="",i={})=>{let e=new URL(n,window.location.href);return Object.entries(i).forEach(t=>{let[d,s]=t;e.searchParams.set(d,s)}),e.toString()},h=(n,i)=>w(`/.within.website/x/cmd/anubis/static/img/${n}.webp`,{cacheBuster:i});(async()=>{let n=document.getElementById("status"),i=document.getElementById("image"),e=document.getElementById("title"),t=document.getElementById("spinner"),d=JSON.parse(document.getElementById("anubis_version").textContent);n.innerHTML="Calculating...";let{challenge:s,difficulty:a}=await fetch("/.within.website/x/cmd/anubis/api/make-challenge",{method:"POST"}).then(l=>{if(!l.ok)throw new Error("Failed to fetch config");return l.json()}).catch(l=>{throw e.innerHTML="Oh no!",n.innerHTML=`Failed to fetch config: ${l.message}`,i.src=h("sad"),t.innerHTML="",t.style.display="none",l});n.innerHTML=`Calculating...
Difficulty: ${a}`;let u=Date.now(),{hash:o,nonce:r}=await m(s,a),c=Date.now();console.log({hash:o,nonce:r}),e.innerHTML="Success!",n.innerHTML=`Done! Took ${c-u}ms, ${r} iterations`,i.src=h("happy",d),t.innerHTML="",t.style.display="none",setTimeout(()=>{let l=window.location.href;window.location.href=w("/.within.website/x/cmd/anubis/api/pass-challenge",{response:o,nonce:r,redir:l,elapsedTime:c-u})},250)})();})(); +(()=>{function m(n,s=5,e=navigator.hardwareConcurrency){return new Promise((t,l)=>{let a=URL.createObjectURL(new Blob(["(",g(),")()"],{type:"application/javascript"})),r=[];for(let d=0;d{r.forEach(u=>u.terminate()),i.terminate(),t(c.data)},i.onerror=c=>{i.terminate(),l()},i.postMessage({data:n,difficulty:s,nonce:d,threads:e}),r.push(i)}URL.revokeObjectURL(a)})}function g(){return function(){let n=e=>{let t=new TextEncoder().encode(e);return crypto.subtle.digest("SHA-256",t.buffer)};function s(e){return Array.from(e).map(t=>t.toString(16).padStart(2,"0")).join("")}addEventListener("message",async e=>{let t=e.data.data,l=e.data.difficulty,a,r=e.data.nonce,d=e.data.threads;for(;;){let i=await n(t+r),c=new Uint8Array(i),u=!0;for(let o=0;o>(p===0?4:0)&15)!==0){u=!1;break}}if(u){a=s(c),console.log(a);break}r+=d}postMessage({hash:a,data:t,difficulty:l,nonce:r})})}.toString()}var w=(n="",s={})=>{let e=new URL(n,window.location.href);return Object.entries(s).forEach(t=>{let[l,a]=t;e.searchParams.set(l,a)}),e.toString()},h=(n,s)=>w(`/.within.website/x/cmd/anubis/static/img/${n}.webp`,{cacheBuster:s});(async()=>{let n=document.getElementById("status"),s=document.getElementById("image"),e=document.getElementById("title"),t=document.getElementById("spinner"),l=JSON.parse(document.getElementById("anubis_version").textContent);n.innerHTML="Calculating...";let{challenge:a,difficulty:r}=await fetch("/.within.website/x/cmd/anubis/api/make-challenge",{method:"POST"}).then(o=>{if(!o.ok)throw new Error("Failed to fetch config");return o.json()}).catch(o=>{throw e.innerHTML="Oh no!",n.innerHTML=`Failed to fetch config: ${o.message}`,s.src=h("sad"),t.innerHTML="",t.style.display="none",o});n.innerHTML=`Calculating...
Difficulty: ${r}`;let d=Date.now(),{hash:i,nonce:c}=await m(a,r),u=Date.now();console.log({hash:i,nonce:c}),e.innerHTML="Success!",n.innerHTML=`Done! Took ${u-d}ms, ${c} iterations`,s.src=h("happy",l),t.innerHTML="",t.style.display="none",setTimeout(()=>{let o=window.location.href;window.location.href=w("/.within.website/x/cmd/anubis/api/pass-challenge",{response:i,nonce:c,redir:o,elapsedTime:u-d})},250)})();})(); //# sourceMappingURL=main.mjs.map diff --git a/cmd/anubis/static/js/main.mjs.br b/cmd/anubis/static/js/main.mjs.br index 56b664638301a24f1977a8405d30958ce3469a62..a7b35e9e4029a4a8d08823b08bae3630b1ad9aa1 100644 GIT binary patch literal 992 zcmV<610Vds*hT-Pz11L>HA%V^R zy+8h=ERc>TzC^MF@7;fnasO+KNm<7yk4=F^iMB@P?4HU8n>7I-?@v(w*n+3TA4oV3 zmY={$@C9SK*6-zEc8@avnOuC&ILR~1|9*ef*&(@yUuht~5070~!?^-Q8$ePBs4i)m z|C)6wk3t6PR6(RT=Kzr|L`dMtmY1g86Vomhn4+cU8|u921&LtM^g8%bmUF}VQ`Di6 zTjUBO?~l5F6n7Rlt?R$ZP=-ch$BgASsseE=5|CC0FbMIK&nz&7JX3pO$w-~Zlh{|c zByqK=mVy)+&(mW;)50kC;jU=0U?GWf1K1YT1S+-Pvz)cL{HWtD%bBNZHUet--~{2& zKWyUDkb_R+Iy=#Azmb$d{c*Ij`tVUv*6XqBBw{hi2NTE^d&Lj2)~g_>w|0Qc``K$C z)w>^254M%N4p@;|Dn!3^T&olo7PNz+k5!Rj7D}TP0^nCCxi2_YRrJGn#OQTU`whi1 z<`ai8tf8@%zRN>iM5N}L{nz{axlBXQBaJ*?@|G-2g*|7&-j2oZcS5y78aTXOnZ5&P z&b!O~eHfT|dGNko;+x$MIR9LY)5!B(BirUupkEkqvYennQiJu{g$-DQx)~ST7H&c_ zR%ErrRMYa9v&6zF0tqZw)YhvH44##u#8VMQtrQyz;HD(|oJj~5(todqGoje%a%}zQ zj_f68Bh@VAf8JM?B!i>dIV8!GnQjl@01vqbxT*96ZBo7TP4!qc+qSZPT=%Kcf5_Hk zs#lXQaM9t0CYAf-@tCs2Iu$g)FB5=A@@yi>#LZn1DV?y|gqu0aWbU(@V|J!t+JZ9* z$+6YKZZ%n25K?IUwT`wZoF)sZ<&$W<_EeDQkHfIm%IuBPyd15woMDfJ*Kebf+}wh~ zc*G8UWj>5M5&9HO#>HAI+iof7?h;MVeNT5V4?5gozK!8Q>0{6G8C7?>BxTYAol!BB zCU`Byiv=ef1jk4sS|??FZZ*4EK#D@rWGEZ>4}iTide0{MeNYPDq~ag z{jvFh?dA_QC011=+I(s162E|jRv(sF5T^ItS5+^2Y@~zNjQ;!m Ol`Ez_+yBW*X+4leXWz_AGpY+?7dP>C^jBF6*0h2~3B(Ul4 zRnEeI2PYr=rUxHCJaS-}MI=4z0P%H*5W|xL&(yGM)G(P~l=i?6*nQIrCPG3LWboOn<;Z(Q zOYhJwa^;ryTG>O&W!V5Cg`e`2AxiStu>MJ8APR=XsiOl&kn#j*b|_wtEj?i}zO>}$ z@n(2#KE53)lE$1rV5N|1GW-aLBW{8gkZQcU|^VU!;WyD9twy z7;ye!8z1`|WExi48QIwzlQM`u4yTI`9|dK(8rEwQv8wnZ7R(+Q#1EqCRWK;Gx`)hr z*|6QsgF>+|P~Ou&E?c|3y>rxmxmoocr`=CdI;)5c*9jlmn^`61A5M;Sj<};X#BZga(cwGYxj6JfndU!0di7^K^ zde%|8;H*qF3SO@JV##FqcLpnxNtBH?C*}lB#e2AJZRDcp8;J!SoL_9Hb=R~p>BqqU5K_kjGI|Z{R_0tlZ z7f2mzDP%^I`T4=QHeJbNzd$L3iB!*^^3pOvwEYcZQVMmnlzBH=k)Ywy74NsPHo4t^ zAbDK(wow7A8Q0$6cEK~Ru5q!lK!kNnt-d>9L&z&b|IvK+lEPKu30y(U{B!#o}lNp}J%pH2~! zr+oKUp-Vi;{w*J~wKpiK>%e7FZBPBjItG{<6ia0`hvQtNz$;(b=H z%x0P(WN3V>N7wd(IX=noMz(R P@2_0(?BD)Rx=FtS;wRhc diff --git a/cmd/anubis/static/js/main.mjs.gz b/cmd/anubis/static/js/main.mjs.gz index f4665eedfeaa9e2e48d7601f8549893588b60044..2bd25c4c0cd1978426c12d007f5f28bfaafe004a 100644 GIT binary patch literal 1194 zcmV;b1XcSViwFoYc-&_I18rexZZ2(Va{!H1U2ohr5PZ+CklC~#VTN*yIw($|izIfD z7Iq!f4*FmiHIG`IXiKC(Qa&FJ`tM!pK70<6ATI||x7wYZogGrjRTW%T~gg>o_)l1&{I6YF8oyOu+a= zffehowO@46iO^4D1EMrD2$7P@kMCX`9=#zvifLa};Mq`YYX|&%Q~aIxY9T6|G`S&b5QABqcy|FX;`VAAEDlen*ksfk#Ko}Eu&R9wa8&p}IK7fs9CPY9^DOnGPa1|C- zXHTub$o}}lo9$^!DOae3_1lqKUT%(Sibs(Y#YPuut_+ez6#adL2!w8ojGTuq|^I>5sO7(Shb9_uYDdoZMzfKO=FRzc- z9v;{dlfEvdi06J7Ftle&B?Hxnz}et%0F9d^ovuRszAT4lQmR#`CyI}Xio1$x){62& zlF1YQYN#y6pBr1cITl~-m_Wv=twL53MCD*c2sE(m&cs!! z>xQcv84C~rl-Knqf;i^%HWzafYh%S6rolwWA9LN7xw8G# zggivVqjS^F@|R0Hq@eDWFEtj2_dROHPr|?oI*NsEI_x z683>GWa67KrcDAw(BBS;2A2gx;&&=_#-gGzsF8nNUi^();L!`e8NcfIzX$LECqNjw z%40-l#l48Euwu;i@#_3ck`JoEp(8VPCWIgb_Po@!Y8tRJNa}c!g&)>JuOQ;U$oJ`1 zoyl8u53jb_2w%1kYgbOlr;E!gbX;5~u+$~vtLUB+?w;X-x%ue$r^yv5`9qlo$}GB7 z*$l;9nHkwC%89#>{0g(7;1E|zx5@&$jb7B5b$f*Gc7OZz(uuWu47VKR=e5L+ zgDTUYcGD(T3vn^pUFaIMkOY?pdv(Kerf;7!{dVf}1+Uds88Xs%NsJky+q&>?PkVuO1q zjh{FUjp_oF3DhLDi+*x=bbwMqHpibAdHz!tT<I@@Oe18rexZZ2(Va{!H1?{C{S5dGf2LgBiBTp7vR! z8IxkA)^M&&8)>++p4^}VP%0q0uO)M;ukKWZL0Hu-VeX5A`60#Qu$&G7jSKN?tV37*wW;N~DGH<8DlVsnTjUI;2k`RO zwnGr2X+udJ>w0!P+`GFSb^_~Ix19vCvmtr&j*eihgf+`?fPD#{)YBdo9IMnXR!j2n>mC?$;F4)`-ev_36Emd76o|LW!u^YuWyRK_FgSTfiuRJqE-!! z@;Hj06|;Ez1*8@ zWu#F?`c?co8L zl6wc)47GmObr|Z|DoBG<=Gxidko3yUdsVJO)V@66kCaoYP)-9M1Qd4#l&=M(x?UR( zq_gf``D7ufm4x8JuDZ?Q!3ervHoh=6cMGgOu9PS}6kA!0xUsKnWxGD8x#25~#o{&jKwH%i~5^?fsbMEu`9_<$223{B*7 zL?gvzh%B>W$oAp#>{ODss=}coGj=Y7AQ@s_=~7h{*g5p-c#wta)>M9Wh%&%=*F@M zs=F|AvQ<mpSxIBop>K-$F^O)&ZGoK#6dmtA}s_rHmE#)2BJ=)CzEq~ln zx86v<89`0am~hp1LbKhy|N2_LHalHkv|1y)ujzP)o$n==&fQ@l}9IDDlg=B>4ILK}v9mFHH@ujdZ(Tm3+!CvZr3k#gAyNQ6W6ioQKe0-|)Z&_mCSu ztvFPw36S?qO?$ZLCx=H9loGNz{5(t3pOWBOui*^A;^@%hWUa7)`Zo06rDy*GjcZ0a H%Lo7fl_X%F diff --git a/cmd/anubis/static/js/main.mjs.map b/cmd/anubis/static/js/main.mjs.map index 577503b..3a0d564 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, 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...
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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", + "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: i,\n threads,\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;\n let threads = event.data.threads;\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 nonce += threads;\n }\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...
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"] } diff --git a/cmd/anubis/static/js/main.mjs.zst b/cmd/anubis/static/js/main.mjs.zst index 1b713784b8bf098a36a3b6bd82fb5ba450ed7d69..8903e1eca6c4fe6649031990c1963872a9eca254 100644 GIT binary patch literal 1190 zcmV;X1X=qiwJ-f-+y})Z04hp64JF{%<^d3ftLaQ-^(Xy1ZOcm2aoTm}vSy1CS4Qu%ROQ3nFH z-Mkt)y`E^DG`beILhdwcBY9mb+@A6zbXq`TNGNCsnS}@h2w}Al5GGMc+>PX;KtN&T zngWKdQ#wUYdgg!;eWnLW5dxs)np}sUawNLu2EX(2k~jQ3kaNdwa(#)DQ`s@L-m|~T zji1e80YQ8<#&$}o@>*jE%qi?Ue+b0YYYhpjnbJRm{(A`cTQT)oFGW3i9CnxJt^;vR~(N|>+RRp8=`Sqd`pXb!?~-u+6rZ95Ai#? zoHMPNJxwgd&iC}N_nv0T=gEo_Q!u!}A%gMd(|-0(O7SiIudzvG^=3KQuFlo#@Cea> zllPpmsz1H_c8!wNHC8RQPzGnBCyQ^*``MHgDFkQRecDws-e0YWmLkWFL#eLW8Ng^L ziHY+0E2hd6Ycd9+BBlk?FKbF~-jveI&BLJVrn zy0xYM>=(65k4|qxp(!`6uMVt^F*p})F3v1hyL@`b8L6^#LD0Zk02NcOs!(rAreIYu zM@P44y$E1108iU?H3S9)ceM=Ewc@EA&A5cxUDrvg+FmPH8~8xFZ_%ct$akF_<5U$( z)%)e;imp-@bYQJeDsl@BWXo`Xw zA&DqVTu>6z#u(=Wz?WI!Q+Xm_Fk9H7geat=n;J&aha}_% zLLt@`#*}M8g1UX$?Xo2#z8EoY@{Hz$Ds0 z0*)YF1;y#sQeW!FPc|aOQtoedeq0Uw8MUXbwl%enrm*v#OH2+zb@7>ndM@p_7>Cg? zKqI(N8Op%ARs_)6q3%uE4LP9%s?XXOn85wM8lT3XU{zodoKaCFXq-G~n)EO<7T|&h zdN3|DQs>)3stpfO;9#kgz{2)(QzVV6H?iW zuQXcd)VNFZQ9J941^-=U!`GY$ceo;mdD@aF_uP_a2?NV%Q#MG*djZoQO|8++Mqo3Pf zqi_L(tIM~9?036Hh`NPk(sP+EeS2k5-fVa2P3oYXC(!w6PM;<5gQsgo;Ub$0EtAH7 zQ*tU5ZtVtjB~-SSv`+fiq8nYUEMF&1lLxm)8i~q!SQHWjRs`h0f(YlFvlSH@Y# zRAx%8_w28c!q5J&fRLx9)Xqpd+FB|?v59@>&ww1Yg+O8@Gx}%HZ(relBZk`Qg{V7? z!tM-uV>2yp$B`oKnLh~lqVz1`M&L;9x0b7+lkH+Q3H zO{)g`yl-dX3Teq~DfxMoZ`r8UnqKwHS7#R~B^qw5nzilQ!e?ancx$okTX*J**jn`xRnm3(s@z+PZnC zp)$DfD{k%RKf5{YPouI;D4cP^daAg{lyY<3WO4qO*2M5xg*=rXCgC7>1pp$3TJ3<^ zj10Lb;){MR(Ygd+7y!-MHLVDW2{tVV>>9CbCLtbSJL@`WRNHIiXyO_t_a)j;)cCHD zDM}RaQ@uYfld}p<62$YMRAYJQNgveO?@1YKHIFT3bs?v0?S#(O&kq`oi62xj9#OzC zNv3+zsT_r6R4HE-k*TSkVU z)~UP2g!=Q#gEslFPLwp0WzUf zO>!I|i6~55P!iL|80Q4wTUk+4`6pmDDUsf}HFwxC6cQb;E??TzFC zNrW4SL8$xKFYmgO4W+DdAyWT&D{`_803%f&SKDwsC+TD+ngXn`stxf&P!s`lX5%<< zld3>K91UJ&%jxTdyrgm~N2FfL<@P%YSA%&*uBm@w&FrImGw(MsbL9EP2Q1WD>Dn@^ z#QOoh286+d$50G@)gWNij=Uyq-$MrthPDb2t_6Jl#kU@Kvi;D+TZV#&RMUg1X~M&3 zSbz`W>M$iQA}tR?6F3}SgJ24KvM_>N32F#p3Xx+k@H%4*X(A2)ar!+S^kr>TKZ~^B zz;o`XfQI76dYWs5P(`b46&{IiRjk2k#5y5k_^-8q!jnyIv~b63AS8Z-S^YqDV+OCv FIXQSIK0N>c diff --git a/docs/docs/CHANGELOG.md b/docs/docs/CHANGELOG.md index 0ceaec7..5847c6e 100644 --- a/docs/docs/CHANGELOG.md +++ b/docs/docs/CHANGELOG.md @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +- Don't duplicate work across multiple threads [#36](https://github.com/TecharoHQ/anubis/pull/36) - Documentation has been moved to https://anubis.techaro.lol/ with sources in docs/ - Removed several visible AI artifacts (e.g., 6 fingers) [#37](https://github.com/TecharoHQ/anubis/pull/37)