No. 05Mini Miner
A Bitcoin miner in a browser tab
Mini Miner hashes real Bitcoin block headers in WebAssembly. The part worth writing about is what the browser checks before it hashes anything.
Alex Colls Outumuro
Co-founder and CTO · · 3 min read
Mini Miner mines Bitcoin solo, on the live network, from a browser tab. Nobody expects a laptop to find a block, and it does not have to for the engineering to be worth writing down. Mining honestly from a browser took three pieces: a fast hash loop, a relay, and a check that the reward is yours.
The hash loop
A Bitcoin block header is 80 bytes. Mining means hashing it twice with SHA-256, again and again, changing the nonce in its last four bytes until the result falls under a target. In Mini Miner each try rewrites only those four bytes, at offset 76, and hashes the header with the WebAssembly SHA-256 of the hash-wasm library.
The work runs in Web Workers, as many as the effort you choose: ×1, ×2, ×4, or Max. Max is measured, not guessed. It adds one worker at a time, lets it warm up, measures for a second, and stops when one more worker adds less than 5%. Each worker starts from its own extranonce and steps forward by the number of workers once it has tried all 2³² nonces, so no two workers ever hash the same header.
The relay
A browser cannot open a TCP socket, and mining pools speak Stratum over TCP. So the browser talks JSON over a WebSocket to our relay, and the relay speaks Stratum v1 to a solo pool, with one pool connection for each address being mined. The relay forwards jobs. It holds no keys and no funds, and it does not choose the transactions in the block: the pool does.
The relay does not take the browser’s word either. It rebuilds every header the browser submits, hashes it again, and only forwards a hash that is really under the target.
Check the coinbase before you hash
This is the part I care about most. A Stratum job does not hand you a block. It hands you the two halves of the coinbase transaction, the one that pays the reward, and you put your extranonces between them. A pool could fill that transaction with any address, and a miner that hashes without looking would be working for someone else.
So before the first hash, the browser assembles the coinbase and parses it. It requires exactly one input, reads every output and rejects trailing bytes. Then it turns your address into the script it expects to find: Base58Check for P2PKH and P2SH, Bech32 for witness version 0, Bech32m for version 1 and up, which covers P2WPKH, P2WSH and Taproot. It compares that script byte for byte with every output and adds up what pays you.
No match, no mining. The check runs again on every new job, and a tab cannot become the miner until it passes:
const canPlay = bound && payout !== null;In our tests, a real job from the pool pays 98% of the reward to the miner’s address.
The relay checks the browser’s hashes. The browser checks the relay’s coinbase.
What we left out
No wallet is ever created. Mini Miner asks for a receive address and nothing else: no key, no signature. And it is a web app, not a browser extension, because the Chrome Web Store has refused mining extensions since 2018.
Alex

