मुझे compiler पसंद नहीं हैं
(xeiaso.net)- Anubis वेबसाइट सुरक्षा के लिए proof-of-work को SHA-256 से आगे बढ़ाते हुए ऐसा डिज़ाइन कर रहा है जिसमें क्लाइंट और सर्वर एक ही WebAssembly validation logic चलाएँ
- WebAssembly बंद होने वाले environments को बाहर न करने के लिए JavaScript recompilation path तैयार किया गया, लेकिन यह WebAssembly से धीमा है और JIT भी बंद हो जाए तो और धीमा हो सकता है
- Linux distribution का
wasm2jsपुराना निकला और उसका output Homebrew version से अलग था, इसलिए reproducible builds के लिए wasi-sdk से build किया गयाwasm2jsbundle करना पड़ा - C/C++ builds में
__DATE__,__TIME__,$PATHकाwasm-opt, और exception handling code में pointer order की वजह से same input पर भी byte-level output बदल सकता है - अंतिम implementation में
--no-wasm-opt,setarch --addr-no-randomize, x86_64·arm64 के लिए SHA-256 verification, और CI rebuild checks के जरिए architecture के भीतर determinism सुनिश्चित किया गया
Anubis का WebAssembly proof-of-work और JavaScript fallback path
- Anubis admins को SHA-256 के अलावा दूसरे proof-of-work तरीकों को वेबसाइट सुरक्षा में इस्तेमाल करने देने के लिए WebAssembly-based proof-of-work validation जोड़ना चाहता है
- मुख्य लक्ष्य यह है कि validation logic को client और server पर अलग-अलग implement न करना पड़े, बल्कि उसे सिर्फ एक जगह define किया जाए
- client और server दोनों एक ही WebAssembly से जुड़कर validation logic चलाते हैं
- लक्ष्य ऐसी संरचना का है जो यह सुनिश्चित करे कि दोनों lockstep में काम कर रहे हैं
- WebAssembly बंद रखने वाले clients को भी ध्यान में रखा गया है
- उपयोगकर्ताओं को व्यवहारिक रूप से वेबसाइट से बाहर नहीं करना चाहते, यह एक बाधा है
- Anubis को user experience, admin experience, और developer experience के बीच संतुलन बनाना है
- चुना गया workaround WebAssembly को दोबारा JavaScript में compile करने का है
- प्रेरणा The Birth and Death of JavaScript से मिली
- तैयार हुआ JavaScript, समान WebAssembly की तुलना में धीमा है
- WebAssembly disable होने पर कई बार JavaScript JIT भी साथ में बंद हो जाता है, इसलिए यह और धीमा हो सकता है
- low-end hardware पर यह पुराने JavaScript से अधिक efficient है या नहीं, इसके लिए और research चाहिए
wasm2js को bundle करना क्यों ज़रूरी हुआ
- ज़रूरी tool binaryen project का
wasm2jsहै wasm2jsLinux distributions में package के रूप में मौजूद है, लेकिन distribution version पुराना था और development environment के Homebrew version जैसा output नहीं दे रहा था- reproducible builds के लिए output का deterministic होना अनिवार्य है
- Anubis repository में commit किए जाने वाले
wasm2jsbinary पर users और packagers तभी भरोसा कर सकते हैं जब वे उसी version को खुद build करके वही bytes प्राप्त कर सकें - आदर्श रूप से दूसरी मशीनों पर भी वही bytes निकलने चाहिए
- Anubis repository में commit किए जाने वाले
- इसके लिए
wasm2jsकी एक copy शामिल की गई जिसे wasi-sdk से WebAssembly target के अनुसार build किया गया
C/C++ builds में reproducibility आसानी से कहाँ टूटती है
- एक ही source bytes और एक ही input देने पर भी compiler output हमेशा वही bytes नहीं बनाता
- C/C++ में सिर्फ
__DATE__और__TIME__जैसे built-in macros से भी non-deterministic output पैदा हो सकता है- उदाहरण
hello.cppको build time की date और time print करने के लिए लिखा गया था - एक build ने
Jun 18 2026 00:00:59print किया, जबकि दूसरे build नेJun 18 2026 00:01:11print किया - source code के bytes एक जैसे थे, लेकिन compiler output अलग था
- उदाहरण
- छोटे पैमाने के compiler सैद्धांतिक रूप से deterministic हो सकते हैं, लेकिन वास्तविक compilers में कहीं अधिक जटिल variables होते हैं
Clang का $PATH में मौजूद wasm-opt को चुपचाप चलाना
- binaryen में
wasm2jsके अलावाwasm-optभी है, जो WebAssembly compiler output को optimize करता है - Clang build के दौरान
wasm-optको shell out करके चलाता है- सामान्य स्थिति में यह performance सुधारने के लिए उचित व्यवहार है
- लेकिन यहाँ
$PATHमें मौजूदwasm-optके version अंतर ने reproducibility तोड़ दी
- DGX Spark पर
wasm-opt/usr/bin/wasm-optका version 108 था, जबकि workstation का Homebrewwasm-optversion 130 था - wasi-sdk और binaryen, WebAssembly Exceptions extension पर निर्भर करते हैं
- Can I use के अनुसार 93.86% browser users ऐसे browser engine इस्तेमाल करते हैं जो इसे support करते हैं
- C++ में exceptions बहुत उपयोग होती हैं, इसलिए WebAssembly native exception handling boilerplate कम कर सकती है
- wasmtime और wazero में exception support को स्पष्ट रूप से enable करना पड़ता है
- wasmtime में
-W exceptions=yदिया जा सकता है - wazero के लिए custom runner harness चाहिए
- wasmtime में
- arm मशीन के पुराने
wasm-optने exception handling instructions देखते ही exit कर दिया, जिससे build fail हो गई - link step में
--no-wasm-optदेकर इस non-reproducible path को हटा दिया गया
address layout का exception handling code generation पर प्रभाव
- इस्तेमाल किए गए Clang version ने
wasm2jscompile process के exception handling path में address-sensitive code generation दिखाया - raw pointer values ने कुछ
try_tableblocks के output order को प्रभावित किया- हर build में लगभग 29 bytes का अंतर आता था
- गणना लगभग समान रहती थी, लेकिन byte order बदल जाता था और catch references भी बदल जाते थे
- arm64 मशीन पर वही fixed version का
wasm2jsbuild करने पर भी pointer iteration order workstation से अलग था, इसलिए वही समस्या आई - workaround दो थे
setarch --addr-no-randomizeसे उस build के लिए address space randomization बंद की गई- trusted machines पर x86_64 और arm64 के लिए अलग-अलग known-good SHA-256 checksums बनाए गए
- CI
./utils/wasm/wasm2jsमें./build.shचलाने के बाद checksum verify करता हैshasums.x86_64से मेल होने पर x86_64 checksum pass माना जाता हैshasums.arm64से मेल होने पर arm64 checksum pass माना जाता है- दोनों में से किसी से मेल न होने पर
wasm-opt_130.wasmऔरwasm2js_130.wasmके SHA-256 print करके fail कर देता है
- यह CI job x86_64 और arm64 दोनों hosts पर चलती है
- host-से-host reproducibility अभी भी हासिल नहीं हुई है, और यह समस्या upstream LLVM bug बनी हुई है
- फिलहाल कम से कम architecture के भीतर builds deterministic तरीके से काम कर रही हैं
1 टिप्पणियां
Lobste.rs की राय
मुझे अभी पहली बार पता चला कि
clangचुपचाप$PATHमें मौजूदwasm-optचलाता है, और यह सच में बेतुका लगाइस वजह से मैंने यह भी जाँचा कि क्या इसका असर
zig ccपर पड़ता है, लेकिन राहत की बात यह रही कि यह सिर्फ तब चलता है जबclangको linker driver की तरह इस्तेमाल किया जाए, इसलिए वह इससे प्रभावित नहीं थाअगर
clangaddress layout पर निर्भर होकर क्रम तय करता है, तो मैं व्यक्तिगत रूप से इसे bug मानूँगा, और अगर यह latest release में भी दोहराया जा सकता है, तो शायद इसी तरह report करूँगाऐसे मसलों को खत्म करने की कोशिश कई सालों से चल रही है
clang.exeको एक भरोसेमंद cross compiler की तरह इस्तेमाल करने की कोशिश करो, तब और भी ज़्यादा पागलपन लगेगाclang करीब 500 तरह से यह मानकर चलता है कि वह native system के लिए build करेगा
मैं आलोचना नहीं करना चाहता, और इस बात का सम्मान करता हूँ कि यह open source है और OP एक लोकप्रिय service मुफ़्त में दे रहा है
फिर भी, web का इस तरह बदलना मुझे सच में नापसंद है। अब तो लगभग हर बार किसी website पर जाते ही Anubis loading page चमक उठती है; समझ नहीं आता कि क्या हम सच में ऐसा web चाहते हैं जहाँ हर लोकप्रिय website proof-of-work splash screen दिखाए
AI crawler लगातार आते जा रहे हैं, इसलिए विकल्प क्या है यह भी समझ नहीं आता, लेकिन यह भी संदेह है कि क्या proof-of-work सच में AI crawler को रोकता है। इनके पास बहुत बड़ा funding होता है, और page पढ़ने के लिए ये पहले से ही कहीं ज़्यादा computation कर रहे होते हैं, इसलिए proof-of-work solve करने की लागत बहुत छोटी लगती है
Anubis pilot में यह unwanted traffic के खिलाफ़ निश्चित रूप से एक असरदार deterrent था, और लगभग default जैसे नियमों से ही तीन application requests का करीब 90% लगातार block किया गया। DDR में 71.0%, ArcLight में 94.6%, और Catalog में 92.4% था
30 मई को bot traffic अचानक बढ़ गया और 3 जून को Anubis लागू होने तक catalog लगभग unusable हो गया। 1 जून के peak पर 21 लाख unique IP से 34 लाख HTTP requests आए, और page loading समय 70 सेकंड से भी ऊपर चला गया। 4 जून को Anubis लागू होने के बाद यह फिर से users के लिए usable हो गया, application ने कुल 1.25 लाख requests संभाले, और page loading 2.12 सेकंड तक सुधर गई
https://lobste.rs/s/ncyfcp/anubis_pilot_project_report_june_2025
एक दूसरे मामले में भी Anubis deploy होते ही समस्या हल हो गई, monitoring में उसका सही समय साफ़ दिखा, और उसके बाद एक भी alert नहीं आया। हमला जारी था, लेकिन server load सबसे निचले स्तर पर रहा, और इसे देखते हुए Anubis ने सिर्फ AI scraper blocking ही नहीं बल्कि DDoS protection की तरह भी काम किया
https://lobste.rs/s/67ijih/day_anubis_saved_our_websites_from_ddos
https://orib.dev/tmp/bandwidth.png
कुछ लोग तो सिर्फ
meta refreshtag या क्लिक करने वाले button से ही इन्हें रोक लेते हैं। इसलिए Anubis काम करता है, लेकिन असली बात proof-of-work नहीं बल्कि unexpected behavior हैJavaScript बंद वाले browser से web इस्तेमाल करने के दिनों से भी ज़्यादा तकलीफ़देह होता जा रहा है। मैं चाहता हूँ कि web बस documents-केंद्रित रहे, लेकिन अब हर जगह Cloudflare, Anubis, और captcha gates से गुजरना पड़ता है
कि bots हमेशा WAF को bypass करने का रास्ता ढूँढ लेते हैं, और असली users loading screen पर CPU cycles बर्बाद करते रह जाते हैं
अफ़सोस की बात है, लेकिन हैरानी की नहीं। compiler toolchain का एक बहुत लंबा इतिहास रहा है जो इस तरह की बेतुकी implicit dependencies पर टिका रहा है कि “local context बस सही होना चाहिए”
फिर भी LLVM आम तौर पर ऐसी dependencies हटाने में आगे रहा है, इसलिए clang में ऐसा देखना अजीब लगता है। इसी वजह से, उदाहरण के लिए, Rust compiler में अलग से cross compiler की अवधारणा के बिना भी काम हो पाया
अगर आप मौजूदा build tools पर निर्भर हुए बिना किसी OS को bootstrap करने की कोशिश करें, तो यह बात तुरंत साफ़ हो जाती है। kernel बनाना, उस kernel के लिए libc और compiler बनाकर चलाना, और फिर नए OS पर सब कुछ दोबारा build करना—यह पूरी प्रक्रिया implicit assumptions से भरी हुई, बेहिसाब जटिल और बेहद संवेदनशील है
यह एक दुर्लभ समस्या है जो ज़्यादातर सिर्फ OS और compiler developers तक ही सीमित रहती है, इसलिए अच्छे tools या best practices भी लगभग नहीं हैं, और हर compiler+OS combination के लिए शायद दुनिया में मुश्किल से 5 लोग होंगे जो पूरे stack को सच में समझते हों
मुझे लगा था कि Zig toolchain ने भी ऐसी कुछ capabilities LLVM से ली होंगी, और बेशक यह समझता हूँ कि उन्होंने चीज़ों को और साफ़-सुथरा अलग करने के लिए बहुत काम किया होगा। अब यह भी जिज्ञासा है कि क्या वे अब LLVM का इस्तेमाल नहीं करते
लेकिन अगर clang में भी वही समस्या है, तो लगता है LLVM से उतनी साफ़ architecture विरासत में नहीं मिली होगी
मुझे लगा कि आप Nix इस्तेमाल करते हैं, इसलिए यह जानने की उत्सुकता हुई कि environment variability का कुछ हिस्सा कम करने के लिए Nix का ज़िक्र या इस्तेमाल क्यों नहीं किया गया
उदाहरण के लिए,
$PATHवालेwasm-optजैसे मसले को Nix से कम किया जा सकता था। या आपने इस्तेमाल किया था और मैंने ही मिस कर दिया?भोलेपन में मुझे लगा था कि wasm को asm.js में ले जाना “आसान” होगा, लेकिन आज कुछ नया सीखने को मिला
blog का शीर्षक clickbait जैसा है, लेकिन सामग्री अच्छी है
मुझे clickbait से सच में नफ़रत है