Mining VANTA with a Bitaxe BM1368
Sections
There is a very specific feeling you only get when a small piece of hardware sitting on your desk solves a block on a chain you wrote. The first time it happened on Vanta — somewhere around 4 AM on a Tuesday — I had to stare at the explorer for a minute and confirm I wasn’t hallucinating.
This post is the writeup of the mining stack: a Bitaxe BM1368 talking Stratum to a Python server I wrote against vantad RPC, generating real blocks on a real chain that I am, transparently, the operator of. It’s also a continuation of What running a Bitcoin mine taught me about cloud margins — only this time the unit economics actually work.
The hardware
The Bitaxe BM1368 is the open-hardware ASIC of choice for the solo-mining renaissance. The board is roughly the size of a deck of cards. It pulls about 12 watts at the wall. It hashes at ~350 GH/s — that’s 350 gigahashes per second.
Compare that to my year at Foundry Digital: the Antminer S19 XPs we deployed by the rack pull ~3 kW each and hash at ~140 TH/s. So one XP is worth roughly 400 Bitaxes in hashrate, at 250x the power draw. The Bitaxe wins on watts-per-hash but loses on hash-per-dollar-of-capex by about an order of magnitude.
That trade is exactly why solo mining Bitcoin in 2026 is essentially a lottery. With current Bitcoin difficulty, a single Bitaxe expects to find a block once every several centuries. Most operators run them as conversation pieces, not as economic mining rigs.
On Vanta, the math changes.
Vanta difficulty math
Vanta’s chain parameters are deliberately tuned for small operators:
- 1-minute block time (vs Bitcoin’s 10 minutes)
- Difficulty retarget every 60 blocks (~1 hour, vs Bitcoin’s 2016 blocks / ~2 weeks)
- Total network hashrate, today: low
The tight retarget loop means difficulty tracks live network hashrate within an hour. The low total hashrate means a single Bitaxe is a meaningful fraction of the network. As of writing this post — and this number changes every hour — my Bitaxe is finding ~1-2 blocks per day on Vanta. That’s 100,000-200,000 VANTA per day flowing into a wallet, on a chain whose ZK-privacy properties I designed myself.
I am deeply aware of how this looks. It is the founder of an L1 chain talking about how easy it is to mine the chain he founded. So let me say the loud part: this is the testnet phase. As more miners join, my hashrate becomes a smaller fraction of the network, my expected blocks-per-day drops, the subsidy gets distributed more widely, and that is the point. The Bitaxe-friendly difficulty is a feature for the first generation of miners; it scales out gracefully as the network grows.
The Stratum server
Bitaxes speak Stratum v1 — the JSON-RPC over TCP protocol that’s been around since the early Bitcoin days. They expect a Stratum server (often called a “pool”) to send them work and accept their submitted shares.
I wrote one. It lives in pool/ of the vanta monorepo. It’s Python, not Rust, because Stratum is a 200-line protocol and the Python socketserver library is exactly what you want for “spawn a thread per connected miner, marshal JSON, talk to a local node over RPC.”
The flow is:
Bitaxe pool/server.py vantad RPC
│ │ │
│── mining.subscribe ─────────►│ │
│◄────────── subscribe.result ─│ │
│── mining.authorize ─────────►│ │
│◄───────── authorize.result ──│ │
│ │ │
│ │─── getblocktemplate ────►│
│ │◄────── block template ───│
│ │ │
│◄────── mining.notify (job) ──│ │
│── mining.submit (share) ────►│ │
│ │── submitblock (if win) ─►│
│ │◄──── block accepted ─────│
│◄───────── submit.result ─────│ │
Two things matter for a chain operator that don’t matter for a public pool:
- Solo mining payouts. This isn’t a pool with multiple miners splitting rewards by share contribution. Every share that meets the block difficulty (not just the per-miner pool difficulty) is a block; the entire 100,000 VANTA subsidy goes to the miner’s payout address. The Stratum server doesn’t track shares for accounting — it tracks them for monitoring.
- Block-template freshness. With 1-minute blocks, a stale block template means you’re hashing against a block that’s already mined. The server polls
vantadforlongpollidchanges and pushes a newmining.notifyto all connected miners within ~50 ms of a new block landing. Miss that window and your effective hashrate drops.
The second one is the actual engineering work. Naive implementations push templates every 30 seconds and waste 50% of the miner’s effort on stale work. The longpoll-aware version is in pool/server.py:handle_longpoll() if you want to see it.
Wattage, heat, and noise
People who haven’t lived with mining hardware always ask about the noise.
Stock Bitaxe BM1368: ~50 dB at 12 W. About as loud as a desktop PC under load. Sits on my desk next to the keyboard. Doesn’t bother me.
A rack of 12 Bitaxes (which is roughly equivalent to one S19 XP in hashrate, at less wattage) is louder. ~70 dB. Tolerable in a closet, not in a living room.
A rack of S19 XPs — what I worked with at Foundry — is 90+ dB and audible from the next building. You don’t put those in a home. You put those in a converted natural-gas plant in West Texas with chillers and earplugs.
The Bitaxe-on-the-desk solo-mining experience is fundamentally different from industrial mining. It’s the difference between owning a model train and working at Union Pacific.
What this is for
The chain doesn’t need this hardware to function. The pool/Bitaxe rig is there because:
- Bootstrap difficulty. Without a baseline of hashrate, the chain’s difficulty drops to the floor and you get blocks every few seconds, which is bad for finality. The Bitaxe holds difficulty at a reasonable level.
- Live testnet activity. Every block I mine is a real block with real ZK proof verification, real witness-v2 binding, real SMT root commitment. It exercises the entire stack continuously.
- The story. “We forked Bitcoin and we’re solo-mining it on a Bitaxe” is a sentence that makes other engineers lean in at conferences. The chain is real because it’s physically real on hardware you can buy on Tindie.
When the chain has more participants than my desk, the Bitaxe stays — but it stops being load-bearing. That’s the goal.
What I would do differently
Three things, all small:
- Ship a CPU miner alongside the Stratum server. The Bitaxe is delightful but it’s not a requirement. A CPU miner that does 10 MH/s on a laptop is plenty for testnet. I should have shipped that in week one. It’s a 200-line Rust program; I’ll write it.
- Per-miner difficulty in Stratum. Right now every Bitaxe gets the network difficulty as the share difficulty, which is fine for solo mining but inflates the share-rejection rate. A vardiff implementation would smooth out the metrics. Low priority since the operational consequence is zero.
- Better UI for “blocks I mined.” I currently grep
vantad’s logs. The web wallet should have a “blocks mined” tab that pulls coinbase transactions where the recipient is a wallet-owned address. Two-day project, on the list.
Further reading
Dax911/vanta/pool/— the Stratum server sourceskot/bitaxe— Bitaxe open-hardware referenceDax911/vanta— the chain itself- Vanta: a Bitcoin fork with ZK at consensus — what’s actually in the chain
- L1 nullifier sets: enforcing no-double-spend at consensus — sister post on the proof-binding side
- What running a Bitcoin mine taught me about cloud margins — the Foundry chapter
- Stratum v1 protocol reference at reference.cash