Top
Best
New

Posted by xena 13 hours ago

It took a year to ship WebAssembly in Anubis(anubis.techaro.lol)
275 points | 135 comments
vintagedave 12 hours ago|
> In my experience the kinds of people who run this exact combination of circumstances also tend to be the kind of people that have a wide variance in the level of kindness they display to the authors of open source programs that happen to be in their way.

Love this. There’s been past discussion on HN re how OSS maintainers are treated, and this is such a wry sentence. I really appreciate the tone / attitude to the problem.

skrebbel 2 hours ago|
Can you translate the American for me? “Wide variance”, does that they’re being assholes?
afavour 2 hours ago||
Well a little translation would be that some are very kind, some are total assholes, and everything in between. But your reading is probably more accurate.
strken 1 hour ago|||
I think the literal interpretation is correct here. It's a way of saying "you, dear reader who runs this combination of things, might be very kind, but some of your compatriots will be unusually unkind and will turn up in my issue tracker and on my socials to complain".
skrebbel 1 hour ago|||
Thanks!
doctor_radium 7 hours ago||
I have every copy of Firefox here configured with webassembly disabled...because I don't tend to do what Webassembly was designed for, i.e. online games, video/audio editing, emulation, etc. [1] and because I dislike things running in the background without my knowledge.

So this is going to be interesting.

My plea (in a small voice) to the OP: just as many sites still do for JavaScript, please add a "This captcha required Webassembly to continue" message to your code when Webassembly is disabled. And, incidentally, for smaller platforms/browsers that don't offer a Webassembly engine at all.

[1] https://webassembly.org/docs/use-cases/

evnp 6 hours ago||
The second half of this post chronicles the author's Herculean efforts to make everything work well in the cases you describe.

> One of the big things that blocked this shipping for so long was not having an escape hatch of some kind to allow clients that disable WebAssembly by policy to get through the gate. [...] This combination of factors means that there would need to be another implementation of the proof of work code in JavaScript that would actually execute the number crunching.

doctor_radium 3 hours ago||
Thanks. You're right; it was a very thorough article and I trailed off about halfway through. I still say there are many improper uses of Webassembly out there, but I credit the developer for a highly thoughtful approach to the project. I really wonder if Cloudflare et al. does as much due diligence?
swiftcoder 1 hour ago|||
> because I dislike things running in the background without my knowledge

Point of order: WASM doesn't let things run in the background. To do that you need WebWorkers (a javascript feature, not WASM-specific).

noduerme 49 minutes ago|||
It's amusing (although disheartening to me as someone who builds online games) that wasm is now being treated like a flash plugin by sysadmins. You're not entirely wrong, but it's just funny to me that we took a full ten years to get back to roughly the same place. Now with Ruffle running Flash in wasm, no less! We build shit that doesn't work in the DOM, search engines hate it, walled gardens try to block it, admins fear it, they shut it down and the whole thing starts over.
xena 5 hours ago|||
I don't mean to be rude, but please search "wasm2js" in the article.
jonkoops 2 hours ago|||
I really don't see why you'd disable WebAssembly and allow JavaScript instead. Expecting developers to make a fallback for a baseline-supported feature for any reason but backwards compatibility with runtimes that do not so support WASM is extremely silly.
well_ackshually 2 hours ago|||
"I disable things and expect others to do things for me, in their own time, without being paid, to bring solutions to my paranoia"

You do see how selfish it is, right? While the author did introduce such a solution, it's such a massive waste of time.

xenafan1 7 hours ago||
[flagged]
gavinsyancey 6 hours ago|||
> You should really be running the most popular browser

This amounts to giving Google effectively complete control over the web. I'm not sure that's a good idea. IMO it's important that Firefox and Safari remain popular enough that webdevs are forced to support them.

I'm somewhat sympathetic to "If you want to 'customize' your web experience, you shouldn't be surprised when things don't work right." in terms of turning off commonly-used features, but the request isn't to make it work right. OP just wants a helpful error message.

adrianN 6 hours ago|||
Customizing the experience is what the web is all about. The browser is a user agent not an advertising platform for the corporate overlords.
kccqzy 11 hours ago||
Hats off to Xe for spending so much time on backwards compatibility, especially the tidbit about targeting Chrome 66.

I have a Mac from 2014 running Yosemite that I occasionally use to test for backwards compatibility in my own frontend code (for fun!). But IMO the best way to ensure compatibility is to use period-correct toolchains or toolchains where the pace of change is slower, like ClojureScript.

nxobject 6 hours ago|
In the non-webdev realm, it's gobsmacking that you can put "FROM debian/eol:buzz" in a Dockerfile, and it will do what it says...
adrian17 1 hour ago||
> something I was doing with my "strict MVP" build of Anubis' WASM wasn't in fact sticking to just the MVP features of WebAssembly

Fun fact, this _used_ to be the case - wasm32-unknown-unknown had extra non-mvp features added later, which in my eyes has been a breaking change on stable. You're not the first person to have been bitten by this, there's [1] and a similar story in Ruffle [2].

Weirdly, the response from the rustc side (IIRC we also talked with one of the devs of wasm component on discord a bit) has contained a lot of (paraphrasing) "in retrospect we think wasm32-unknown-unknown target was designed badly*, so we'd prefer if you either dealt with it or switched to another wasm target <with its different set of downsides> than us fixing it". (*I acknowledge that the way std was implemented on that target was unusual and "not clean", but it works _really well_ for a lot of people.)

> I looked into the process involved for rebuilding the standard library twice: once with only MVP wasm features enabled and once with an "all yes config" like usual. Based on some research I did this seemed like a massive pain.

That's what Ruffle does [3], it's a bit unfortunate but wouldn't call it a massive pain.

[1] https://internals.rust-lang.org/t/can-we-have-either-a-new-t...

[2] https://github.com/ruffle-rs/ruffle/pull/18397

[3] See lines 55 and 117-127 in https://github.com/ruffle-rs/ruffle/blob/6890c618daab3153343...

JoshTriplett 12 minutes ago|
> Weirdly, the response from the rustc side (IIRC we also talked with one of the devs of wasm component on discord a bit) has contained a lot of (paraphrasing) "in retrospect we think wasm32-unknown-unknown target was designed badly, so we'd prefer if you either dealt with it or switched to another wasm target <with its different set of downsides> than us fixing it". (I acknowledge that the way std was implemented on that target was unusual and "not clean", but it works _really well_ for a lot of people.)

That's about right. Specifically, wasm32-unknown-unknown is serving multiple targets, which aren't very compatible, and it implements std by panicking in all the bits that can't work.

One target is "you truly have absolutely nothing, and don't really have much of `std` at all". Another target is "you're in a browser, and can do anything a typical browser can provide" (ideally targeting the future where wasm has full browser APIs without going through javascript). Another target is "hosted environment that isn't a browser, and which capabilities you have depends on the environment". Those are three very different things.

I would argue that we need at least two new targets, possibly three:

- `wasm32-none` or similar (by analogy with `x86_64-unknown-none`), a target where you don't have anything except for what you bring with you. The equivalent of writing kernel code.

- `wasm32-wasi-hosted` (or pick another name), where you the hoster of the wasm can supply whatever capabilities you have available.

- `wasm32-wasi-browser`.

It's possible that `none` could be a special case of `hosted`, where the services you provide are "none".

Aachen 11 hours ago||
Is there a place where I can try out if my browser is compatible? Easier to find out now than when I'm trying to get work done and a million websites now have it deployed

On https://wasm-feature-detect.surma.technology it shows that I don't have 3 of all these features but I'm not sure if Anubis needs any of them to not kick me back to the pure JS solution

Which would apparently be bad because

> The WebAssembly that's shipped with this flow is ridiculously performant. This may mean you need to adjust the difficulty [upward, to avoid that bots solve it trivially when they support wasm, I assume this means]

combined with

> The wasm2js flow doesn't currently have a way to update the progress bar [so you have no clue about remaining time]

(wouldn't be the first time that I gave up on a page because it was stuck on 0 hashes per second)

Georgelemental 7 hours ago||
You can use Rust's `wasm32v1-none` target to get baseline WASM with no extra target features. (This restricts you to `#[no_std]`, however.) https://doc.rust-lang.org/rustc/platform-support/wasm32v1-no...
0x696C6961 13 hours ago||
It would be cool if the POW could be done ahead of time. That way I don't get stuck waiting while I'm working. Some type of credit/tokens that my browser could then spend.
xena 12 hours ago||
I'm working on this with a private prototype. I'm probably going to lean towards using a Service Worker (https://developer.mozilla.org/en-US/docs/Web/API/Service_Wor...) to renew challenges at a reduced difficulty. Stay tuned!
gruez 11 hours ago||
That just creates another problem: if you're taking any measures to reduce tracking (ie. clearing cookies on shutdown or using temporary containers), this won't work. If anubis was being deployed on a site that a user visits often (eg. HN), the user might be convinced to whitelist it, but most anubis deployments are on random blogs or fediverse instances that I might not visit again in months. I'm certainly am not going to whitelist those sites, nor am I going to enable cookies wholesale just to avoid solving challenges.
xena 10 hours ago||
Look, if you're going out of your way to break expected behaviour on websites you shouldn't be surprised when people code to the most common denominator and then you have weird subtle breakage as a result.
kstrauser 8 hours ago|||
Gotta agree. Turning tracking cookies off? Sure! Turning session cookies off and then complaining that the server doesn’t remember you? Uhhh…

And while I’m sympathetic to the idea of not wanting to run JS, to a first approximation modern browsers are JS engines that have graphical displays. How things should be vs how they are is a classic is/ought problem. The world took a vote on what a browser’s meant for and we lost. Fighting it today is rough; tomorrow, futile.

gruez 7 hours ago|||
>Gotta agree. Turning tracking cookies off? Sure! Turning session cookies off and then complaining that the server doesn’t remember you? Uhhh…

No, because there are technologies that don't have this issue, eg. privacy pass.

perching_aix 3 hours ago|||
There's no mechanistic difference between the two types of cookies, let's not pretend this is an actual config choice that people are making.

Whenever I hit Anubis, I simply go "keep your secrets then" and take my leave. The vast majority of the sites posted to HN (that catch my fancy) work fine or fine enough, and are better for it.

If I really, really desperately want to check something out, I can always just turn stuff back on. Turns out, I rarely do.

Shoutout to the particularly dogshit few that don't just require cookies and JS, but even third party JS. For reading a blogpost or a message thread!

gkbrk 1 hour ago||||
Clearing cookies when all you want to do is read static content is not "breaking expected behaviour on websites".
anuthis 8 hours ago|||
[flagged]
lxgr 12 hours ago|||
Or something that shadier websites could calculate ahead of time in your browser, then spend on your behalf.

I feel like Anubis is ironically speedrunning a lot of discoveries the crypto folks have already made several years ago...

Terr_ 3 hours ago||
What if the work output was bound to a particular source IP? That'd stop most "theft" at the expense of discards when your device switches networks.
xena 3 hours ago||
Anubis does this. Happy Eyeballs (https://en.wikipedia.org/wiki/Happy_Eyeballs), IPv6 privacy extensions (https://oneuptime.com/blog/post/2026-01-15-ipv6-privacy-exte...), and devices migrating between home and mobile IP addresses as the person moves have all caused issues with this. Fixing this is hard, but I have been trying.
tomodachi94 10 hours ago|||
Privacy Pass does something similar to what you describe: https://developers.cloudflare.com/waf/tools/privacy-pass/
packetlost 12 hours ago|||
I wonder if you could convince the Anubis author to implement x402 payments to bypass the PoW
JsonCameron 8 hours ago|||
This could be done at the web server level, not requiring changes to Anubis
apoorvkhanna88 1 hour ago|||
[flagged]
dist-epoch 12 hours ago||
Then we could implement an exchange, so that if you generate too much Anubis POW, you could exchange it with others.

We could link it to a site, you generate for HN, I for Reddit, but it so happens that you visited Reddit more and I HN, so we depleted our Anubis POW, so we could exchange some Reddit Anubis with some HN Anubis.

ssl-3 12 hours ago|||
And then, we can inextricably link it to a new cryptocurrency -- let's call it BotCoin -- and make Sam Altman pay for it!
kelvinjps10 12 hours ago|||
Basically reinventing crypto one step at the time.
omoikane 11 hours ago||
> This means that adding one (1) to the difficulty of a challenge makes it 1024 (one thousand twenty-four) times as hard to solve in the worst case.

I don't understand the units here, wouldn't a bit versus nibble difference make the multiplier 16, instead of 1024?

xena 11 hours ago|
Oops, there's your proof I didn't write this with AI! Fixing, sorry.
miraline 11 hours ago||
The interesting part is that bots mitigation is actually an economic problem. You don't need to make scraping impossible, you only need to just make it expensive enough so that abusive traffic stops being worth it.
mitxela 10 hours ago|
Scrapers scrape all sorts of nonsense, notably every possible git diff from git hosts. They clearly aren't concerned with rationality.
XorNot 10 hours ago||
Scrapers scrape every link they can find.

The git host example is probably the one which Anubis is the dumbest defense for: the main reason to have those links is for easy machine interaction. So that's dead when you implement it.

So why even host the links? It's a git repo: send them a local got client and let them clone the repo in browser or something.

mitxela 9 hours ago|||
The main reason to have those links is for people to click on them. No sensibly programmed machine is scraping diffs from a git web front end.
cyphar 8 hours ago||
Not to mention it is the least efficient representation of git commits. It seems a lot of people are unaware that git generates the diff representation you see with "git show" on the fly -- internally, commits are Merkle trees representing a snapshot of the repo file contents.

As you said, if you actually want to interact with a remote git repo you'd do so with packfiles not diffs.

utopiah 3 hours ago|||
> why even host the links? It's a git repo: send them a local got client and let them clone the repo in browser or something.

I document my code, in issue and elsewhere on the Web, by referring to specific commits so having a URL for each is useful to me at least.

dspillett 7 hours ago|
> It also means that the "hey Claude vibeslop me a CUDA Anubis solver" route is on its way to being fundamentally dead.

I assume that the previous challenges will still be available for circumstances where WASM is not available (unless we are just working on the basis that it is available if JS is?) or perhaps as a fallback. TFA explicitly mentions “smart” TVs, and I'm sure there are plenty of those out there that run browsers old enough to not know what WASM is. TBH these would not be a priority for me, but they obviously are for this project given they (well, TVs generally, not specifically elderly ones) get specific mention in this write-up.

If so, what is to stop scrapers from just forcing the fallback POW option instead of trying to run the new memory-hard algorithm at all?

Lyrex 7 hours ago|
the answer to this is in the post: where wasm is not available, he transpiles the wasm binary back to Javascript
dspillett 5 hours ago|||
Ah I must have skipped by that bit. And presumably the memory-hard algorithm is CPU-easy enough that this won't be a problem. That leaves me wondering "why not just use a JS memory-hard routine in the first place, but maybe I've shouted over that too. I'll give TFA a reread later.
trickypr 5 hours ago||
I think it is still compute-heavy if not compute-hard, and stuff like WASM SIMD makes it less compute heavy (not really available in JS). And also, for memory bound problems, you probably don't want the JS GC needing to clean up afterwards when WASM gives you that control.
xena 4 hours ago||
I assume that SIMD acceleration is usable with WebCrypto, but I have no evidence either way. It's also not part of WebAssembly so there's that to consider too lol
tyre 5 hours ago|||
tangential fyi: the author is not a he
More comments...